*** empty log message ***

This commit is contained in:
hyung-hwan 2005-07-10 09:21:46 +00:00
parent d8b4f8b710
commit b795ce8408
5 changed files with 169 additions and 329 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $Id: bytecode.c,v 1.4 2005-07-08 11:32:50 bacon Exp $ * $Id: bytecode.c,v 1.5 2005-07-10 09:21:46 bacon Exp $
*/ */
#include <xp/stx/bytecode.h> #include <xp/stx/bytecode.h>
#include <xp/stx/class.h> #include <xp/stx/class.h>
@ -33,33 +33,21 @@ static void __decode1 (xp_stx_t* stx, xp_word_t idx, void* data)
__decode2 (stx, data, method_obj); __decode2 (stx, data, method_obj);
} }
static const xp_char_t* opcode_names[] =
{
XP_TEXT("PUSH_VARIABLE"),
XP_TEXT("PUSH_TEMPORARY"),
XP_TEXT("PUSH_LITERAL_CONSTANT"),
XP_TEXT("PUSH_LITERAL_VARIABLE"),
XP_TEXT("STORE_VARIABLE"),
XP_TEXT("STORE_TEMPORARY"),
XP_TEXT("SEND"),
XP_TEXT("JUMP"),
XP_TEXT("DO_SPECIAL"),
XP_TEXT("DO_PRIMITIVE"),
XP_TEXT("PUSH_VARIABLE_EXTENDED"),
XP_TEXT("PUSH_TEMPORARY_EXTENDED"),
XP_TEXT("STORE_VARIABLE_EXTENDED"),
XP_TEXT("STORE_TEMPORARY_EXTENDED"),
XP_TEXT("DO_SPECIAL_EXTENDED"),
XP_TEXT("DO_PRIMITIVE_EXTENDED")
};
static int __decode2 (xp_stx_t* stx, static int __decode2 (xp_stx_t* stx,
xp_stx_class_t* class_obj, xp_stx_method_t* method_obj) xp_stx_class_t* class_obj, xp_stx_method_t* method_obj)
{ {
xp_stx_byte_object_t* bytecodes; xp_stx_byte_object_t* bytecodes;
xp_word_t bytecode_size, pc = 0; xp_word_t bytecode_size, pc = 0;
xp_byte_t code; int code, next;
int opcode, operand;
static const xp_char_t* stack_opcode_names[] = {
XP_TEXT("push_receiver_variable"),
XP_TEXT("push_temporary_location"),
XP_TEXT("push_literal_constant"),
XP_TEXT("push_literal_variable"),
XP_TEXT("store_receiver_variable"),
XP_TEXT("store_temporary_location")
};
bytecodes = XP_STX_BYTE_OBJECT(stx, method_obj->bytecodes); bytecodes = XP_STX_BYTE_OBJECT(stx, method_obj->bytecodes);
bytecode_size = XP_STX_SIZE(stx, method_obj->bytecodes); bytecode_size = XP_STX_SIZE(stx, method_obj->bytecodes);
@ -67,23 +55,36 @@ static int __decode2 (xp_stx_t* stx,
while (pc < bytecode_size) { while (pc < bytecode_size) {
code = bytecodes->data[pc++]; code = bytecodes->data[pc++];
opcode = (code & 0xF0) >> 4; if (code >= 0x00 && code <= 0x5F) {
operand = code & 0x0F; /* stack */
if (opcode > 0x9) { xp_printf (XP_TEXT("%s %d\n"),
if (pc >= bytecode_size) { stack_opcode_names[code >> 4], code & 0x0F);
/* TODO: */ }
xp_printf (XP_TEXT("error in bytecodes\n")); else if (code >= 0x60 && code <= 0x65) {
return -1; /* stack extended */
} next = bytecodes->data[pc++];
code = bytecodes->data[pc++]; xp_printf (XP_TEXT("%s %d\n"),
operand |= (code << 4); stack_opcode_names[code & 0x0F], next);
}
else if (code >= 0x70 && code <= 0x73 ) {
/* send */
}
else if (code >= 0x78 && code <= 0x7D) {
// return
}
else if (code >= 0x80 && code <= 0x8F) {
// jump
}
else if (code >= 0xF0 && code <= 0xFF) {
// primitive
next = bytecodes->data[pc++];
xp_printf (XP_TEXT("do_primitive %d\n"), ((code & 0x0F) << 8) | next);
}
else {
xp_printf (XP_TEXT("unknown byte code 0x%x\n"), code);
} }
xp_printf (XP_TEXT("%s(0x%x), operand = %d\n"),
opcode_names[opcode], opcode, operand);
} }
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: bytecode.h,v 1.6 2005-07-10 03:16:40 bacon Exp $ * $Id: bytecode.h,v 1.7 2005-07-10 09:21:46 bacon Exp $
*/ */
#ifndef _XP_STX_BYTECODE_H_ #ifndef _XP_STX_BYTECODE_H_
@ -24,10 +24,10 @@
#define DUPLICATE_POP_STACK_TOP 0x69 #define DUPLICATE_POP_STACK_TOP 0x69
#define PUSH_ACTIVE_CONTEXT 0x6A #define PUSH_ACTIVE_CONTEXT 0x6A
#define SEND_SELECTOR_TO_SELF 0x70 #define SEND_TO_SELF 0x70
#define SEND_SELECTOR_TO_SUPER 0x71 #define SEND_TO_SUPER 0x71
#define SEND_SELECTOR_TO_SELF_EXTENDED 0x72 #define SEND_TO_SELF_EXTENDED 0x72
#define SEND_SELECTOR_TO_SUPER_EXTENDED 0x73 #define SEND_TO_SUPER_EXTENDED 0x73
#define RETURN_RECEIVER 0x78 #define RETURN_RECEIVER 0x78
#define RETURN_TRUE 0x79 #define RETURN_TRUE 0x79
@ -36,29 +36,7 @@
#define RETURN_FROM_MESSAGE 0x7C #define RETURN_FROM_MESSAGE 0x7C
#define RETURN_FROM_BLOCK 0x7D #define RETURN_FROM_BLOCK 0x7D
#define PUSH_VARIABLE 0x0 #define DO_PRIMITIVE 0xF0
#define PUSH_TEMPORARY 0x1
#define PUSH_LITERAL_CONSTANT 0x2
#define PUSH_LITERAL_VARIABLE 0x3
#define STORE_VARIABLE 0x4
#define STORE_TEMPORARY 0x5
#define SEND 0x6
#define JUMP 0x7
#define DO_SPECIAL 0x8
#define DO_PRIMITIVE 0x9
#define PUSH_VARIABLE_EXTENDED 0xA
#define PUSH_TEMPORARY_EXTENDED 0xB
#define STORE_TEMPORARY_EXTENDED 0xC
#define STORE_VARIABLE_EXTENDED 0xD
#define DO_SPECIAL_EXTENDED 0xE
#define DO_PRIMITIVE_EXTENDED 0xF
#define RETURN_RECEIVER 1
#define RETURN_NIL 2
#define RETURN_TRUE 3
#define RETURN_FALSE 4
#define RETURN_FROM_MESSAGE 5
#define RETURN_FROM_BLOCK 6
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -1,5 +1,5 @@
/* /*
* $Id: parser.c,v 1.60 2005-07-10 03:16:40 bacon Exp $ * $Id: parser.c,v 1.61 2005-07-10 09:21:46 bacon Exp $
*/ */
#include <xp/stx/parser.h> #include <xp/stx/parser.h>
@ -115,12 +115,6 @@ void xp_stx_parser_close (xp_stx_parser_t* parser)
if (parser->__malloced) xp_free (parser); if (parser->__malloced) xp_free (parser);
} }
#define EMIT_CODE_TEST(parser,high,low) \
do { if (__emit_code_test(parser,high,low) == -1) return -1; } while (0)
#define EMIT_CODE(parser,code) \
do { if (__emit_code(parser,code) == -1) return -1; } while(0)
#define GET_CHAR(parser) \ #define GET_CHAR(parser) \
do { if (__get_char(parser) == -1) return -1; } while (0) do { if (__get_char(parser) == -1) return -1; } while (0)
#define UNGET_CHAR(parser,c) \ #define UNGET_CHAR(parser,c) \
@ -241,6 +235,69 @@ static INLINE xp_bool_t __is_closing_char (xp_cint_t c)
c == XP_CHAR('\"') || c == XP_CHAR('\''); c == XP_CHAR('\"') || c == XP_CHAR('\'');
} }
#define EMIT_CODE_TEST(parser,high,low) \
do { if (__emit_code_test(parser,high,low) == -1) return -1; } while (0)
#define EMIT_CODE(parser,code) \
do { if (__emit_code(parser,code) == -1) return -1; } while(0)
#define EMIT_PUSH_RECEIVER_VARIABLE(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, PUSH_RECEIVER_VARIABLE, pos) == -1) return -1; \
} while (0)
#define EMIT_PUSH_TEMPORARY_LOCATION(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, PUSH_TEMPORARY_LOCATION, pos) == -1) return -1; \
} while (0)
#define EMIT_PUSH_LITERAL_CONSTANT(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, PUSH_LITERAL_CONSTANT, pos) == -1) return -1; \
} while (0)
#define EMIT_PUSH_LITERAL_VARIABLE(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, PUSH_LITERAL_VARIABLE, pos) == -1) return -1; \
} while (0)
#define EMIT_STORE_RECEIVER_VARIABLE(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, STORE_RECEIVER_VARIABLE, pos) == -1) return -1; \
} while (0)
#define EMIT_STORE_TEMPORARY_LOCATION(parser,pos) \
do { \
if (__emit_stack_positional ( \
parser, STORE_TEMPORARY_LOCATION, pos) == -1) return -1; \
} while (0)
#define EMIT_POP_STACK_TOP(parser) EMIT_CODE(parser, POP_STACK_TOP)
#define EMIT_DUPLICATE_STACK_TOP(parser) EMIT_CODE(parser, DUPLICATE_STACK_TOP)
#define EMIT_PUSH_ACTIVE_CONTEXT(parser) EMIT_CODE(parser, PUSH_ACTIVE_CONTEXT)
#define EMIT_RETURN_FROM_MESSAGE(parser) EMIT_CODE(parser, RETURN_FROM_MESSAGE)
#define EMIT_RETURN_FROM_BLOCK(parser) EMIT_CODE(parser, RETURN_FROM_BLOCK)
#define EMIT_SEND_TO_SELF(parser,selector,nargs) \
do { \
if (__emit_send_to_self(parser,selector,nargs) == -1) return -1; \
} while (0)
#define EMIT_SEND_TO_SUPER(parser,selector,nargs) \
do { \
if (__emit_send_to_super(parser,selector,nargs) == -1) return -1; \
} while (0)
#define EMIT_DO_PRIMITIVE(parser,no) \
do { if (__emit_do_primitive(parser,no) == -1) return -1; } while(0)
static INLINE int __emit_code_test ( static INLINE int __emit_code_test (
xp_stx_parser_t* parser, const xp_char_t* high, const xp_char_t* low) xp_stx_parser_t* parser, const xp_char_t* high, const xp_char_t* low)
{ {
@ -258,73 +315,44 @@ static INLINE int __emit_code (xp_stx_parser_t* parser, xp_byte_t code)
return 0; return 0;
} }
static INLINE int __emit_stack_code_positional ( static INLINE int __emit_stack_positional (
xp_stx_parser_t* parser, int opcode, int pos) xp_stx_parser_t* parser, int opcode, int pos)
{ {
static int mapping[] = { xp_assert (pos < 0xFF);
PUSH_RECEIVER_VARIABLE_EXTENDED,
PUSH_TEMPORARY_LOCATION_EXTENDED,
PUSH_LITERAL_CONSTANT_EXTENDED,
PUSH_LITERAL_VARIABLE_EXTENDED,
STORE_RECEIVER_VARIABLE,
STORE_TEMPORARY_VARIABLE
};
}
static INLINE int __emit_push_receiver_variable (xp_stx_parser_t* parser, int pos) if (pos <= 0x0F) {
{ EMIT_CODE (parser, (opcode & 0xF0) | (pos & 0x0F));
if (pos > 0x0F) {
EMIT_CODE (parser, PUSH_RECEIVER_VARIABLE | (pos & 0x0F));
} }
else { else {
EMIT_CODE (parser, PUSH_RECEIVER_VARIABLE_EXTENDED); EMIT_CODE (parser, (opcode >> 4) & 0x6F);
EMIT_CODE (parser, pos & 0xFF) EMIT_CODE (parser, pos & 0xFF);
} }
return 0; return 0;
} }
static INLINE int __emit_push_temporary_location (xp_stx_parser_t* parser, int pos) static INLINE int __emit_send_to_self (
xp_stx_parser_t* parser, int selector, int nargs)
{ {
if (pos > 0x0F) { xp_assert (selector >= 0x00 && selector <= 0xFF);
EMIT_CODE (parser, PUSH_TEMPORARY_LOCATION | (pos & 0x0F)); xp_assert (nargs >= 0x00 nargs <= 0xFF);
} }
else {
EMIT_CODE (parser, PUSH_RECEIVER_VARIABLE_EXTENDED); static INLINE int __emit_send_to_super (
EMIT_CODE (parser, pos & 0xFF) xp_stx_parser_t* parser, int selector, int nargs)
} {
}
static INLINE int __emit_do_primitive (xp_stx_parser_t* parser, int no)
{
xp_assert (no >= 0x0 && no <= 0xFFF);
EMIT_CODE (parser, DO_PRIMITIVE & ((no >> 8) & 0x0F));
EMIT_CODE (parser, no & 0xFF);
return 0; return 0;
} }
/*
push_receiver_variable,
push_temporary_location,
push_literal_constant,
push_literal_variable,
store_receiver_variable,
store_temporary_location,
push_receiver,
push_true,
push_false,
push_nil,
push_minus_one,
push_zero,
push_one,
push_two,
return_receiver,
return_true,
return_false,
return_nil,
return_from_message,
return_from_block,
XP_NULL,
push_receiver_variable,
push_temporary_location,
push_literal_constant,
push_literal_variable,
*/
int xp_stx_parser_parse_method ( int xp_stx_parser_parse_method (
xp_stx_parser_t* parser, xp_word_t method_class, void* input) xp_stx_parser_t* parser, xp_word_t method_class, void* input)
{ {
@ -615,20 +643,12 @@ static int __parse_primitive (xp_stx_parser_t* parser)
} }
XP_STRTOI (prim_no, parser->token.name.buffer, XP_NULL, 10); XP_STRTOI (prim_no, parser->token.name.buffer, XP_NULL, 10);
if (prim_no < 0 || prim_no > 0x0FFF) { if (prim_no < 0 || prim_no > 0xFF) {
parser->error_code = XP_STX_PARSER_ERROR_PRIMITIVE_NUMBER_RANGE; parser->error_code = XP_STX_PARSER_ERROR_PRIMITIVE_NUMBER_RANGE;
return -1; return -1;
} }
if (prim_no <= 0x0F) { EMIT_DO_PRIMITIVE (parser, prim_no);
EMIT_CODE_TEST (parser, XP_TEXT("DO_PRIMITIVE"), parser->token.name.buffer);
EMIT_CODE (parser, (DO_PRIMITIVE << 4) | prim_no);
}
else {
EMIT_CODE_TEST (parser, XP_TEXT("DO_PRIMITIVE_EXTENDED"), parser->token.name.buffer);
EMIT_CODE (parser, (DO_PRIMITIVE_EXTENDED << 4) | (prim_no & 0x0F));
EMIT_CODE (parser, prim_no >> 4);
}
GET_TOKEN (parser); GET_TOKEN (parser);
if (!__is_primitive_closer(&parser->token)) { if (!__is_primitive_closer(&parser->token)) {
@ -691,17 +711,7 @@ static int __parse_statement (xp_stx_parser_t* parser)
if (parser->token.type == XP_STX_TOKEN_RETURN) { if (parser->token.type == XP_STX_TOKEN_RETURN) {
GET_TOKEN (parser); GET_TOKEN (parser);
if (__parse_expression(parser) == -1) return -1; if (__parse_expression(parser) == -1) return -1;
EMIT_RETURN_FROM_MESSAGE (parser);
/* TODO */
if (RETURN_FROM_MESSAGE <= 0x0F) {
EMIT_CODE_TEST (parser, XP_TEXT("DO_SPECIAL"), XP_TEXT("RETURN_FROM_MESSAGE"));
EMIT_CODE (parser, (DO_SPECIAL << 4) | RETURN_FROM_MESSAGE);
}
else {
EMIT_CODE_TEST (parser, XP_TEXT("DO_SPECIAL_EXTENDED"), XP_TEXT("RETURN_FROM_MESSAGE"));
EMIT_CODE (parser, (DO_SPECIAL_EXTENDED << 4) | (RETURN_FROM_MESSAGE & 0x0F));
EMIT_CODE (parser, RETURN_FROM_MESSAGE >> 4);
}
} }
else { else {
if (__parse_expression(parser) == -1) return -1; if (__parse_expression(parser) == -1) return -1;
@ -779,40 +789,16 @@ static int __parse_assignment (
for (i = parser->argument_count; i < parser->temporary_count; i++) { for (i = parser->argument_count; i < parser->temporary_count; i++) {
if (xp_strcmp (target, parser->temporaries[i]) == 0) { if (xp_strcmp (target, parser->temporaries[i]) == 0) {
xp_char_t buf[100];
if (__parse_expression(parser) == -1) return -1; if (__parse_expression(parser) == -1) return -1;
xp_sprintf (buf, xp_countof(buf), XP_TEXT("%d"), i); EMIT_STORE_TEMPORARY_LOCATION (parser, i);
if (i <= 0x0F) {
EMIT_CODE_TEST (parser, XP_TEXT("STORE_TEMPORARY"), buf);
EMIT_CODE (parser, (STORE_TEMPORARY << 4) | i);
}
else {
EMIT_CODE_TEST (parser, XP_TEXT("STORE_TEMPORARY_EXTENDED"), buf);
EMIT_CODE (parser, (STORE_TEMPORARY_EXTENDED << 4) | (i & 0x0F));
EMIT_CODE (parser, i >> 4);
}
return 0; return 0;
} }
} }
if (xp_stx_get_instance_variable_index ( if (xp_stx_get_instance_variable_index (
stx, parser->method_class, target, &i) == 0) { stx, parser->method_class, target, &i) == 0) {
xp_char_t buf[100];
if (__parse_expression(parser) == -1) return -1; if (__parse_expression(parser) == -1) return -1;
xp_sprintf (buf, xp_countof(buf), XP_TEXT("%d"), i); EMIT_STORE_RECEIVER_VARIABLE (parser, i);
/* TODO */
if (i <= 0x0F) {
EMIT_CODE_TEST (parser, XP_TEXT("STORE_VARIABLE"), buf);
EMIT_CODE (parser, (STORE_VARIABLE << 4) | i);
}
else {
EMIT_CODE_TEST (parser, XP_TEXT("STORE_VARIABLE_EXTENDED"), buf);
EMIT_CODE (parser, (STORE_VARIABLE_EXTENDED << 4) | (i & 0x0F));
EMIT_CODE (parser, i >> 4);
}
return 0; return 0;
} }
@ -822,6 +808,7 @@ xp_sprintf (buf, xp_countof(buf), XP_TEXT("%d"), i);
/* TODO */ /* TODO */
EMIT_CODE_TEST (parser, XP_TEXT("ASSIGN_CLASSVAR #"), target); EMIT_CODE_TEST (parser, XP_TEXT("ASSIGN_CLASSVAR #"), target);
//EMIT_STORE_CLASS_VARIABLE (parser, target);
return 0; return 0;
} }
@ -843,7 +830,7 @@ static int __parse_primary (xp_stx_parser_t* parser, const xp_char_t* ident)
if (ident == XP_NULL) { if (ident == XP_NULL) {
if (parser->token.type == XP_STX_TOKEN_IDENT) { if (parser->token.type == XP_STX_TOKEN_IDENT) {
if (__parse_primary_ident (parser, parser->token.buffer) == -1) return -1; if (__parse_primary_ident(parser, parser->token.name.buffer) == -1) return -1;
GET_TOKEN (parser); GET_TOKEN (parser);
} }
else if (parser->token.type == XP_STX_TOKEN_CHARLIT) { else if (parser->token.type == XP_STX_TOKEN_CHARLIT) {
@ -884,7 +871,7 @@ static int __parse_primary (xp_stx_parser_t* parser, const xp_char_t* ident)
} }
} }
else { else {
if (__parse_primary_ident (parser, parser->token.buffer) == -1) return -1; if (__parse_primary_ident(parser, parser->token.name.buffer) == -1) return -1;
} }
return 0; return 0;
@ -893,27 +880,34 @@ static int __parse_primary (xp_stx_parser_t* parser, const xp_char_t* ident)
static int __parse_primary_ident (xp_stx_parser_t* parser, const xp_char_t* ident) static int __parse_primary_ident (xp_stx_parser_t* parser, const xp_char_t* ident)
{ {
xp_word_t i; xp_word_t i;
xp_stx_t* stx = parser->stx;
/* Refer to __parse_assignment for identifier lookup */ /* Refer to __parse_assignment for identifier lookup */
for (i = 0; i < parser->temporary_count; i++) { for (i = 0; i < parser->temporary_count; i++) {
if (xp_strcmp (target, parser->temporaries[i]) == 0) { if (xp_strcmp(ident, parser->temporaries[i]) == 0) {
EMIT_CODE_1 (parser, PUSH_TEMPORARY_VARIABLE, i); EMIT_PUSH_TEMPORARY_LOCATION (parser, i);
return 0; return 0;
} }
} }
if (xp_stx_get_instance_variable_index ( if (xp_stx_get_instance_variable_index (
stx, parser->method_class, target, &i) == 0) { stx, parser->method_class, ident, &i) == 0) {
EMIT_CODE_1 (parser, PUSH_RECEIVER_VARIABLE, i); EMIT_PUSH_RECEIVER_VARIABLE (parser, i);
return 0; return 0;
} }
/* TODO: what is the best way to look up a class variable? */
/* 1. Use the class containing it and using its position */
/* 2. Use a primitive method after pushing the name as a symbol */
/* 3. Implement a vm instruction to do it */
/*
if (xp_stx_lookup_class_variable ( if (xp_stx_lookup_class_variable (
stx, parser->method_class, target) != stx->nil) { stx, parser->method_class, ident) != stx->nil) {
//PUSH_CLASS_VARIABLE //EMIT_LOOKUP_CLASS_VARIABLE (parser, ident);
return 0; return 0;
} }
*/
/* TODO: IMPLEMENT POOL DICTIONARIES */ /* TODO: IMPLEMENT POOL DICTIONARIES */

View File

@ -36,141 +36,6 @@ SEE ALSO
xpkit(7) xpkit(7)
-------------------
/*
&unsupportedByte, //--- 00
&bytePushInstance, //--- 01
&bytePushArgument, //--- 02
&bytePushTemporary, //--- 03
&bytePushLiteral, //--- 04
&bytePushConstant, //--- 05
&byteAssignInstance, //--- 06
&byteAssignTemporary, //--- 07
&byteMarkArguments, //--- 08
&byteSendMessage, //--- 09
&byteSendUnary, //--- 10
&byteSendBinary, //--- 11
&unsupportedByte, //--- 12
&byteDoPrimitive, //--- 13
&unsupportedByte, //--- 14
&byteDoSpecial //--- 15
* Directly access by byte codes
> the receiver and arguments of the invoking message
> the values of the receiver's instance variables
> the values of any temporary variables required by the method
> seven special constants (true, false, nil, -1, 0, 1, and 2)
> 32 special message selectors
* contained in literal frame.
> shared variables (global, class, and pool)
> most literal constants (numbers, characters, strings, arrays, and symbols)
> most message selectors (those that are not special)
PushInstance
PushArgument -> normal arguments plus self/super(0)
PushTemporary
PushConstant -> nil, true, false, etc....
PushLiteral -> global variables, literal constants... -> access literal frame
AssignInstance
AssignTemporary
*/
Pocket Smalltalk
0x push instance variable x
1x store instance variable x
2x push local x
3x store local x
40..43 xx jump forward by xxx
44..47 xx jump backward by xxx
48..4F xx (reserved)
50..53 xx jump forward if true by xxx
54..57 xx jump backward if true by xxx
58..5B xx jump forward if false by xxx
5C..5F xx jump backward if false by xxx
60 xx fetch inst var xx of stack top
61 xx store stack top inst var xx of stack level 2
62..6F (reserved)
7x yyyy send self yyyy, x args
8x yyyy send yyyy, x args
9x yyyy send super yyyy, x args
Ax yy send self yy, x args
B0 xx push object xx
B1 xxxx push object xxxx
B2 xx get instvar xx of next outer receiver
B3 xx store instvar xx of next outer receiver
B4 xx get next outer local x
B5 xx store next outer local
B6 xx yy get (y th) outer local
B7 xx yy store (y th) outer local
B8 nonlocal block return, next outer context
B9 xx make full block
BA xx make hybrid block
BB xx yy get instvar xx of yyth outer receiver
BC xx yy store instvar xx of yyth outer receiver
BD xx nonlocal block return, distance xx
BE push next outer receiver
BF xx push xxth outer receiver
Cx send special selector:
0: <=
1: >=
2: <
3: >
4: ==
5: ~~
6: not
7: +
8: -
9: basicAt:
A: basicAt:put:
B: isNil
C: notNil
D: (reserved)
E: (reserved)
F: (reserved)
Dx yy send yy to stack top, xx args
E0 pop stack
E1 duplicate stacktop
E2 duplicate level 2
E3 return stack top
E4 return true
E5 return false
E6 return nil
E7 return self
E8 push false
E9 push true
EA push nil
EB push self
EC xx push negative integer
ED xx push positive integer
EE xxxx push negative integer
EF xxxx push positive integer
F0 xx push instvar xx
F1 xx store instvar xx
F2 xx push local xx
F3 xx store local xx
F4 xx push global xx
F5 xx store global xx
F6 xx push Character xx
F7 add 1
F8 subtract 1
F9 push thisContext
FA (reserved)
FB
FC
FD
FE xx primitive xx
FF extended op
-- stack bytecodes -- -- stack bytecodes --
0 0000 XXXX push_receiver_variable 0 0000 XXXX push_receiver_variable
1 0001 XXXX push_temporary_location 1 0001 XXXX push_temporary_location
@ -184,22 +49,22 @@ FF extended op
0110 0011 XXXXXXXX push_literal_variable_extended 0110 0011 XXXXXXXX push_literal_variable_extended
0110 0100 XXXXXXXX store_receiver_variable_extended 0110 0100 XXXXXXXX store_receiver_variable_extended
0110 0101 XXXXXXXX store_temporary_location_extended 0110 0101 XXXXXXXX store_temporary_location_extended
0110 0110 XXXXXXXX unused 0110 0110 unused
0110 0111 XXXXXXXX unused 0110 0111 unused
0110 1000 pop_stack_top 0110 1000 pop_stack_top
0110 1001 duplicate_stack_top 0110 1001 duplicate_stack_top
0110 1010 push_active_context 0110 1010 push_active_context
0110 1011 XXXXXXXX unused 0110 1011 unused
0110 1100 XXXXXXXX unused 0110 1100 unused
0110 1101 XXXXXXXX unused 0110 1101 unused
0110 1110 XXXXXXXX unused 0110 1110 unused
0110 1111 XXXXXXXX unused 0110 1111 unused
-- send bytecodes -- -- send bytecodes --
7 0111 0000 JJJKKKKK send_selector_to_self 7 0111 0000 JJJKKKKK send_to_self
0111 0001 JJJKKKKK send_selector_to_super 0111 0001 JJJKKKKK send_to_super
0111 0010 JJJJJJJJ KKKKKKKK send_selector_to_self_extended 0111 0010 JJJJJJJJ KKKKKKKK send_to_self_extended
0111 0011 JJJJJJJJ KKKKKKKK send_selector_to_super_extended 0111 0011 JJJJJJJJ KKKKKKKK send_to_super_extended
0111 0100 XXXXXXXX 0111 0100 XXXXXXXX
0111 0101 XXXXXXXX 0111 0101 XXXXXXXX
@ -221,3 +86,5 @@ FF extended op
8 1000 0XXX jump_forward 8 1000 0XXX jump_forward
1000 1XXX XXXXXXXX jump_forward 1000 1XXX XXXXXXXX jump_forward
-- primitive --
F 1111 XXXX XXXXXXXX do_primitive

View File

@ -10,9 +10,9 @@ perform: method with: x with: y with: z with: a1 with: b2 with: c2
" "
b := -30 xxx nil this. b := -30 xxx nil this.
"instanceClass := 10." "instanceClass := 10."
selector := 20.
"Win32Errors := 10."
selector := 20.
"
(jjj xxx: 10 xy) zzz: (10 fuck: 20 you: 40) yyy: kkk. (jjj xxx: 10 xy) zzz: (10 fuck: 20 you: 40) yyy: kkk.
[ spec plus: 20]. [ spec plus: 20].
^10. ^10."