3 We will reimplement VM to use 8bit instruction code. By
4 bytecode, we mean real byte code. The whole purpose is
5 reducing the memory consumption of mruby VM.
9 Instructions are bytes. There can be 256 instructions. Currently we
10 have 94 instructions. Instructions can take 0 to 3 operands.
14 The size of operands can be either 8bits, 16bits or 24bits.
15 In the table.1 below, the second field describes the size (and
24 First two byte operands may be extended to 16bit. When those byte
25 operands are bigger than 256, the instruction will be prefixed by
26 `OP_EXT1` (means 1st operand is 16bit) or `OP_EXT2` (means 2nd operand
27 is 16bit) or `OP_EXT3` (means 1st and 2nd operands are 16bit).
29 For instructions marked by `'`, `OP_EXT1` can be prefixed. For those
30 with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
32 ## table.1 Instruction Table
34 |Instruction Name |Operand type |Semantics
35 |-----------------|-------------|-----------------
37 |OP_MOVE" |BB |R(a) = R(b)
38 |OP_LOADL" |BB |R(a) = Pool(b)
39 |OP_LOADI" |BsB |R(a) = mrb_int(b)
40 |OP_LOADI_0' |B |R(a) = 0
41 |OP_LOADI_1' |B |R(a) = 1
42 |OP_LOADI_2' |B |R(a) = 2
43 |OP_LOADI_3' |B |R(a) = 3
44 |OP_LOADSYM" |BB |R(a) = Syms(b)
45 |OP_LOADNIL' |B |R(a) = nil
46 |OP_LOADSELF' |B |R(a) = self
47 |OP_LOADT' |B |R(a) = true
48 |OP_LOADF' |B |R(a) = false
49 |OP_GETGV" |BB |R(a) = getglobal(Syms(b))
50 |OP_SETGV" |BB |setglobal(Syms(b), R(a))
51 |OP_GETSV" |BB |R(a) = Special[b]
52 |OP_SETSV" |BB |Special[b] = R(a)
53 |OP_GETIV" |BB |R(a) = ivget(Syms(b))
54 |OP_SETIV" |BB |ivset(Syms(b),R(a))
55 |OP_GETCV" |BB |R(a) = cvget(Syms(b))
56 |OP_SETCV" |BB |cvset(Syms(b),R(a))
57 |OP_GETCONST" |BB |R(a) = constget(Syms(b))
58 |OP_SETCONST" |BB |constset(Syms(b),R(a))
59 |OP_GETMCNST" |BB |R(a) = R(a)::Syms(b)
60 |OP_SETMCNST" |BB |R(a+1)::Syms(b) = R(a)
61 |OP_GETUPVAR' |BBB |R(a) = uvget(b,c)
62 |OP_SETUPVAR' |BBB |uvset(b,c,R(a))
64 |OP_JMPIF' |SB |if R(b) pc+=a
65 |OP_JMPNOT' |SB |if !R(b) pc+=a
66 |OP_ONERR |sS |rescue_push(pc+a)
67 |OP_EXCEPT' |B |R(a) = exc
68 |OP_RESCUE" |BB |R(b) = R(a).isa?(R(b))
69 |OP_POPERR |B |a.times{rescue_pop()}
70 |OP_RAISE' |B |raise(R(a))
71 |OP_EPUSH' |B |ensure_push(SEQ[a])
72 |OP_EPOP |B |A.times{ensure_pop().call}
73 |OP_SENDV" |BB |R(a) = call(R(a),Syms(b),*R(a+1))
74 |OP_SENDVB" |BB |R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
75 |OP_SEND" |BBB |R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
76 |OP_SENDB" |BBB |R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
77 |OP_CALL' |B |R(a) = self.call(frame.argc, frame.argv)
78 |OP_SUPER' |BB |R(a) = super(R(a+1),... ,R(a+b+1))
79 |OP_ARGARY' |BS |R(a) = argument array (16=5:1:5:1:4)
80 |OP_ENTER |W |arg setup according to flags (23=5:5:1:5:5:1:1)
81 |OP_KARG" |BB |R(a) = kdict[Syms(Bx)] # todo
82 |OP_KARG2" |BB |R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
83 |OP_RETURN' |B |return R(a) (normal)
84 |OP_RETURN_BLK' |B |return R(a) (in-block return)
85 |OP_BREAK' |B |break R(a)
86 |OP_BLKPUSH' |BS |R(a) = block (16=5:1:5:1:4)
87 |OP_ADD" |BB |R(a) = R(a)+R(a+1)
88 |OP_ADDI" |BBB |R(a) = R(a)+mrb_int(c)
89 |OP_SUB" |BB |R(a) = R(a)-R(a+1)
90 |OP_SUBI" |BB |R(a) = R(a)-C
91 |OP_MUL" |BB |R(a) = R(a)*R(a+1)
92 |OP_DIV" |BB |R(a) = R(a)/R(a+1)
93 |OP_EQ" |BB |R(a) = R(a)==R(a+1)
94 |OP_LT" |BB |R(a) = R(a)<R(a+1)
95 |OP_LE" |BB |R(a) = R(a)<=R(a+1)
96 |OP_GT" |BB |R(a) = R(a)>R(a+1)
97 |OP_GE" |BB |R(a) = R(a)>=R(a+1)
98 |OP_ARRAY' |BB |R(a) = ary_new(R(a),R(a+1)..R(a+b))
99 |OP_ARRAY2" |BB |R(a) = ary_new(R(b),R(b+1)..R(b+c))
100 |OP_ARYCAT' |B |ary_cat(R(a),R(a+1))
101 |OP_ARYPUSH' |B |ary_push(R(a),R(a+1))
102 |OP_AREF' |BB |R(a) = R(a)[b]
103 |OP_ASET' |BB |R(a)[b] = R(a+1)
104 |OP_APOST' |BB |*R(a),R(A+1)..R(A+C) = R(a)[B..]
105 |OP_STRING" |BB |R(a) = str_dup(Lit(b))
106 |OP_STRCAT' |B |str_cat(R(a),R(a+1))
107 |OP_HASH' |BB |R(a) = hash_new(R(a),R(a+1)..R(a+b))
108 |OP_HASHADD' |BB |R(a) = hash_push(R(a),R(a+1)..R(a+b))
109 |OP_LAMBDA" |BB |R(a) = lambda(SEQ[b],OP_L_LAMBDA)
110 |OP_BLOCK" |BB |R(a) = lambda(SEQ[b],OP_L_BLOCK)
111 |OP_METHOD" |BB |R(a) = lambda(SEQ[b],OP_L_METHOD)
112 |OP_RANGE_INC' |B |R(a) = range_new(R(a),R(a+1),FALSE)
113 |OP_RANGE_EXC' |B |R(a) = range_new(R(a),R(a+1),TRUE)
114 |OP_OCLASS' |B |R(a) = ::Object
115 |OP_CLASS" |BB |R(a) = newclass(R(a),Syms(b),R(a+1))
116 |OP_MODULE" |BB |R(a) = newmodule(R(a),Syms(b))
117 |OP_EXEC" |BB |R(a) = blockexec(R(a),SEQ[b])
118 |OP_DEF" |BB |R(a).newmethod(Syms(b),R(a+1))
119 |OP_ALIAS' |B |alias_method(R(a),R(a+1),R(a+2))
120 |OP_UNDEF" |BB |undef_method(R(a),Syms(b))
121 |OP_SCLASS' |B |R(a) = R(a).singleton_class
122 |OP_TCLASS' |B |R(a) = target_class
123 |OP_ERR' |B |raise(RuntimeError, Lit(Bx))
124 |OP_EXT1 |- |make 1st operand 16bit
125 |OP_EXT2 |- |make 2nd operand 16bit
126 |OP_EXT3 |- |make 1st and 2nd operands 16bit