summaryrefslogtreecommitdiffhomepage
path: root/doc/opcode.md
blob: 21dc2ef9da543391bff9e328be6044ebae42092b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# The new bytecode

We will reimplement the VM to use 8bit instruction code. By
bytecode, we mean real byte code. The whole purpose is
reducing the memory consumption of mruby VM.

# Instructions

Instructions are bytes. There can be 256 instructions. Currently, we
have 94 instructions. Instructions can take 0 to 3 operands.

## operands

The size of operands can be either 8bits, 16bits or 24bits.
In the table.1 below, the second field describes the size (and
sign) of operands.

* B: 8bit
* S: 16bit
* sS: signed 16bit
* W: 24bit

## table.1 Instruction Table

| Instruction Name | Operand type | Semantics                                              |
|------------------|--------------|--------------------------------------------------------|
| `OP_NOP`         | `-`          | `no operation`                                         |
| `OP_MOVE`        | `BB`         | `R(a) = R(b)`                                          |
| `OP_LOADL`       | `BB`         | `R(a) = Pool(b)`                                       |
| `OP_LOADI`       | `BB`         | `R(a) = mrb_int(b)`                                    |
| `OP_LOADINEG`    | `BB`         | `R(a) = mrb_int(-b)`                                   |
| `OP_LOADI__1`    | `B`          | `R(a) = mrb_int(-1)`                                   |
| `OP_LOADI_0`     | `B`          | `R(a) = mrb_int(0)`                                    |
| `OP_LOADI_1`     | `B`          | `R(a) = mrb_int(1)`                                    |
| `OP_LOADI_2`     | `B`          | `R(a) = mrb_int(2)`                                    |
| `OP_LOADI_3`     | `B`          | `R(a) = mrb_int(3)`                                    |
| `OP_LOADI_4`     | `B`          | `R(a) = mrb_int(4)`                                    |
| `OP_LOADI_5`     | `B`          | `R(a) = mrb_int(5)`                                    |
| `OP_LOADI_6`     | `B`          | `R(a) = mrb_int(6)`                                    |
| `OP_LOADI_7`     | `B`          | `R(a) = mrb_int(7)`                                    |
| `OP_LOADI16`     | `BS`         | `R(a) = mrb_int(b)`                                    |
| `OP_LOADI32`     | `BSS`        | `R(a) = mrb_int((b<<16)+c)`                            |
| `OP_LOADSYM`     | `BB`         | `R(a) = Syms(b)`                                       |
| `OP_LOADNIL`     | `B`          | `R(a) = nil`                                           |
| `OP_LOADSELF`    | `B`          | `R(a) = self`                                          |
| `OP_LOADT`       | `B`          | `R(a) = true`                                          |
| `OP_LOADF`       | `B`          | `R(a) = false`                                         |
| `OP_GETGV`       | `BB`         | `R(a) = getglobal(Syms(b))`                            |
| `OP_SETGV`       | `BB`         | `setglobal(Syms(b), R(a))`                             |
| `OP_GETSV`       | `BB`         | `R(a) = Special[Syms(b)]`                              |
| `OP_SETSV`       | `BB`         | `Special[Syms(b)] = R(a)`                              |
| `OP_GETIV`       | `BB`         | `R(a) = ivget(Syms(b))`                                |
| `OP_SETIV`       | `BB`         | `ivset(Syms(b),R(a))`                                  |
| `OP_GETCV`       | `BB`         | `R(a) = cvget(Syms(b))`                                |
| `OP_SETCV`       | `BB`         | `cvset(Syms(b),R(a))`                                  |
| `OP_GETCONST`    | `BB`         | `R(a) = constget(Syms(b))`                             |
| `OP_SETCONST`    | `BB`         | `constset(Syms(b),R(a))`                               |
| `OP_GETMCNST`    | `BB`         | `R(a) = R(a)::Syms(b)`                                 |
| `OP_SETMCNST`    | `BB`         | `R(a+1)::Syms(b) = R(a)`                               |
| `OP_GETUPVAR`    | `BBB`        | `R(a) = uvget(b,c)`                                    |
| `OP_SETUPVAR`    | `BBB`        | `uvset(b,c,R(a))`                                      |
| `OP_JMP`         | `S`          | `pc+=a`                                                |
| `OP_JMPIF`       | `BS`         | `if R(a) pc+=b`                                        |
| `OP_JMPNOT`      | `BS`         | `if !R(a) pc+=b`                                       |
| `OP_JMPNIL`      | `BS`         | `if R(a)==nil pc+=b`                                   |
| `OP_JMPUW`       | `S`          | `unwind_and_jump_to(a)`                                |
| `OP_EXCEPT`      | `B`          | `R(a) = exc`                                           |
| `OP_RESCUE`      | `BB`         | `R(b) = R(a).isa?(R(b))`                               |
| `OP_RAISEIF`     | `B`          | `raise(R(a)) if R(a)`                                  |
| `OP_SENDV`       | `BB`         | `R(a) = call(R(a),Syms(b),*R(a+1))`                    |
| `OP_SENDVB`      | `BB`         | `R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))`            |
| `OP_SEND`        | `BBB`        | `R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))`          |
| `OP_SENDB`       | `BBB`        | `R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c),&R(a+c+1))` |
| `OP_SENDVK`      | `BB`         | `R(a) = call(R(a),Syms(b),*R(a+1),**(a+2),&R(a+3))`    |
| `OP_CALL`        | `-`          | `R(0) = self.call(frame.argc, frame.argv)`             |
| `OP_SUPER`       | `BB`         | `R(a) = super(R(a+1),... ,R(a+b+1))`                   |
| `OP_ARGARY`      | `BS`         | `R(a) = argument array (16=m5:r1:m5:d1:lv4)`           |
| `OP_ENTER`       | `W`          | `arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1)` |
| `OP_KEY_P`       | `BB`         | `R(a) = kdict.key?(Syms(b))`                           |
| `OP_KEYEND`      | `-`          | `raise unless kdict.empty?`                            |
| `OP_KARG`        | `BB`         | `R(a) = kdict[Syms(b)]; kdict.delete(Syms(b))`         |
| `OP_RETURN`      | `B`          | `return R(a) (normal)`                                 |
| `OP_RETURN_BLK`  | `B`          | `return R(a) (in-block return)`                        |
| `OP_BREAK`       | `B`          | `break R(a)`                                           |
| `OP_BLKPUSH`     | `BS`         | `R(a) = block (16=m5:r1:m5:d1:lv4)`                    |
| `OP_ADD`         | `B`          | `R(a) = R(a)+R(a+1)`                                   |
| `OP_ADDI`        | `BB`         | `R(a) = R(a)+mrb_int(b)`                               |
| `OP_SUB`         | `B`          | `R(a) = R(a)-R(a+1)`                                   |
| `OP_SUBI`        | `BB`         | `R(a) = R(a)-mrb_int(b)`                               |
| `OP_MUL`         | `B`          | `R(a) = R(a)*R(a+1)`                                   |
| `OP_DIV`         | `B`          | `R(a) = R(a)/R(a+1)`                                   |
| `OP_EQ`          | `B`          | `R(a) = R(a)==R(a+1)`                                  |
| `OP_LT`          | `B`          | `R(a) = R(a)<R(a+1)`                                   |
| `OP_LE`          | `B`          | `R(a) = R(a)<=R(a+1)`                                  |
| `OP_GT`          | `B`          | `R(a) = R(a)>R(a+1)`                                   |
| `OP_GE`          | `B`          | `R(a) = R(a)>=R(a+1)`                                  |
| `OP_ARRAY`       | `BB`         | `R(a) = ary_new(R(a),R(a+1)..R(a+b))`                  |
| `OP_ARRAY2`      | `BBB`        | `R(a) = ary_new(R(b),R(b+1)..R(b+c))`                  |
| `OP_ARYCAT`      | `B`          | `ary_cat(R(a),R(a+1))`                                 |
| `OP_ARYPUSH`     | `B`          | `ary_push(R(a),R(a+1))`                                |
| `OP_ARYDUP`      | `B`          | `R(a) = ary_dup(R(a))`                                 |
| `OP_AREF`        | `BBB`        | `R(a) = R(b)[c]`                                       |
| `OP_ASET`        | `BBB`        | `R(a)[c] = R(b)`                                       |
| `OP_APOST`       | `BBB`        | `*R(a),R(a+1)..R(a+c) = R(a)[b..]`                     |
| `OP_INTERN`      | `B`          | `R(a) = intern(R(a))`                                  |
| `OP_STRING`      | `BB`         | `R(a) = str_dup(Lit(b))`                               |
| `OP_STRCAT`      | `B`          | `str_cat(R(a),R(a+1))`                                 |
| `OP_HASH`        | `BB`         | `R(a) = hash_new(R(a),R(a+1)..R(a+b*2-1))`             |
| `OP_HASHADD`     | `BB`         | `R(a) = hash_push(R(a),R(a+1)..R(a+b*2))`              |
| `OP_HASHCAT`     | `B`          | `R(a) = hash_cat(R(a),R(a+1))`                         |
| `OP_LAMBDA`      | `BB`         | `R(a) = lambda(SEQ[b],OP_L_LAMBDA)`                    |
| `OP_BLOCK`       | `BB`         | `R(a) = lambda(SEQ[b],OP_L_BLOCK)`                     |
| `OP_METHOD`      | `BB`         | `R(a) = lambda(SEQ[b],OP_L_METHOD)`                    |
| `OP_RANGE_INC`   | `B`          | `R(a) = range_new(R(a),R(a+1),FALSE)`                  |
| `OP_RANGE_EXC`   | `B`          | `R(a) = range_new(R(a),R(a+1),TRUE)`                   |
| `OP_OCLASS`      | `B`          | `R(a) = ::Object`                                      |
| `OP_CLASS`       | `BB`         | `R(a) = newclass(R(a),Syms(b),R(a+1))`                 |
| `OP_MODULE`      | `BB`         | `R(a) = newmodule(R(a),Syms(b))`                       |
| `OP_EXEC`        | `BB`         | `R(a) = blockexec(R(a),SEQ[b])`                        |
| `OP_DEF`         | `BB`         | `R(a).newmethod(Syms(b),R(a+1))`                       |
| `OP_ALIAS`       | `BB`         | `alias_method(target_class,Syms(a),Syms(b))`           |
| `OP_UNDEF`       | `B`          | `undef_method(target_class,Syms(a))`                   |
| `OP_SCLASS`      | `B`          | `R(a) = R(a).singleton_class`                          |
| `OP_TCLASS`      | `B`          | `R(a) = target_class`                                  |
| `OP_DEBUG`       | `BBB`        | `print a,b,c`                                          |
| `OP_ERR`         | `B`          | `raise(LocalJumpError, Lit(a))`                        |
| `OP_EXT1`        | `-`          | `make 1st operand 16bit`                               |
| `OP_EXT2`        | `-`          | `make 2nd operand 16bit`                               |
| `OP_EXT3`        | `-`          | `make 1st and 2nd operands 16bit`                      |
| `OP_STOP`        | `-`          | `stop VM`                                              |
|------------------|--------------|--------------------------------------------------------|