| Module | Ruva::VM::Opcodes |
| In: |
lib/ruva/opcodes.rb
|
Provides the standard opcode implementations. The VM will use the standard opcodes by default. If you want to pass custom opcodes, you can base your modifications off the hash in Opcodes::OPCODES
| __any_cmpg | -> | __any_cmpl |
| NaN treated the same right now | ||
| __any_aload | -> | op50 |
| AALOAD (0x32) () …, arrayref, idx => …, value | ||
| __any_astore | -> | op83 |
| AASTORE (0x53) () …, arrayref, idx, value => … | ||
| __any_load | -> | op25 |
| ALOAD (0x19) (idx) …, => …, objectref | ||
| __any_return | -> | op176 |
| ARETURN (0xB0) () …, value => (^) objectref | ||
| __any_store | -> | op58 |
ASTORE (0x3A)(idx) ..., objectref => ... |
||
| __any_aload | -> | op51 |
| BALOAD (0x33) () …, arrayref, idx => …, value | ||
| __any_aload | -> | op52 |
| CALOAD (0x34) () …, arrayref, idx => …, value | ||
| __any_aload | -> | op49 |
| DALOAD (0x31) () …, arrayref, idx => …, value | ||
| __any_load | -> | op24 |
| DLOAD (0x18) (idx) …, => …, value | ||
| __any_aload | -> | op48 |
| FALOAD (0x30) () …, arrayref, idx => …, value | ||
| __any_load | -> | op23 |
| FLOAD (0x17) (idx) …, => …, value | ||
| __any_aload | -> | op46 |
| IALOAD (0x2E) () …, arrayref, idx => …, value | ||
| __any_load | -> | op21 |
| ILOAD (0x15) (idx) …, => …, value | ||
| __any_aload | -> | op47 |
| LALOAD (0x2f) () …, arrayref, idx => …, value | ||
| op19 | -> | op20 |
| LDC2W (0x14) (idx1, idx2) … => …, value | ||
| __any_load | -> | op22 |
| LLOAD (0x16) (idx) …, => …, value | ||
| __any_aload | -> | op53 |
| SALOAD (0x35) () …, arrayref, idx => …, value | ||
# File lib/ruva/opcodes.rb, line 150
150: def __any_add(vm)
151: v2 = vm.stack.pop
152: v1 = vm.stack.pop
153: vm.stack.push(v1 + v2)
154: end
IMPLEMENTATION OPCODES () …, arrayref, idx => …, value
# File lib/ruva/opcodes.rb, line 127
127: def __any_aload(vm)
128: idx = vm.stack.pop
129: arr = vm.stack.pop
130: vm.stack.push(arr[idx])
131: end
() …, arrayref, idx, value => …
# File lib/ruva/opcodes.rb, line 135
135: def __any_astore(vm)
136: value = vm.stack.pop
137: idx = vm.stack.pop
138: arr = vm.stack.pop
139: arr[idx] = value
140: end
# File lib/ruva/opcodes.rb, line 156
156: def __any_cmpg(vm)
157: v2 = vm.stack.pop
158: v1 = vm.stack.pop
159: vm.stack.push(v1 <=> v2)
160: end
# File lib/ruva/opcodes.rb, line 165
165: def __any_div(vm)
166: v2 = vm.stack.pop
167: v1 = vm.stack.pop
168: vm.stack.push(v1 / v2)
169: end
# File lib/ruva/opcodes.rb, line 142
142: def __any_load(vm, idx)
143: vm.stack.push(vm.locals[idx])
144: end
# File lib/ruva/opcodes.rb, line 171
171: def __any_mul(vm)
172: v2 = vm.stack.pop
173: v1 = vm.stack.pop
174: vm.stack.push(v1 * v2)
175: end
# File lib/ruva/opcodes.rb, line 183
183: def __any_neg(vm)
184: vm.stack.push(-vm.stack.pop)
185: end
# File lib/ruva/opcodes.rb, line 187
187: def __any_rem(vm)
188: v2 = vm.stack.pop
189: v1 = vm.stack.pop
190: vm.stack.push(v1 % v2)
191: end
# File lib/ruva/opcodes.rb, line 193
193: def __any_return(vm)
194: r = vm.stack.pop
195: vm.pop_frame
196: vm.stack.push(r)
197: end
# File lib/ruva/opcodes.rb, line 146
146: def __any_store(vm, idx)
147: vm.locals[idx] = vm.stack.pop
148: end
# File lib/ruva/opcodes.rb, line 177
177: def __any_sub(vm)
178: v2 = vm.stack.pop
179: v1 = vm.stack.pop
180: vm.stack.push(v1 - v2)
181: end
Check a ruby Integer is in byte range. Do this before pushing it.
# File lib/ruva/opcodes.rb, line 20
20: def check_byte(b)
21: raise IllegalArgumentError, "Invalid byte #{b.inspect}" unless b && b.is_a?(Integer) && (-128..127).member?(b)
22: b.is_a?(VM::Types::Cat2Value) ? b.__value : b
23: end
Check a ruby Integer is in char range. Do this before pushing it.
# File lib/ruva/opcodes.rb, line 26
26: def check_char(c)
27: raise IllegalArgumentError, "Invalid char #{c.inspect}" unless c && c.is_a?(Integer) && (0..65535).member?(c)
28: c.is_a?(VM::Types::Cat2Value) ? c.__value : c
29: end
Check a ruby Float as a double and wrap it in a VM::Types::Cat2Value Do this before pushing it.
# File lib/ruva/opcodes.rb, line 52
52: def check_double(d)
53: raise IllegalArgumentError, "Invalid double #{d.inspect}" unless d && d.is_a?(Float)
54: d.is_a?(VM::Types::Cat2Value) ? d : VM::Types::Cat2Value.new(d)
55: end
Check a ruby Float as a float. Do this before pushing it.
# File lib/ruva/opcodes.rb, line 58
58: def check_float(f)
59: raise IllegalArgumentError, "Invalid float #{f.inspect}" unless f && f.is_a?(Float)
60: f.is_a?(VM::Types::Cat2Value) ? f.__value : f
61: end
Check a ruby Integer is in int range. Do this before pushing it.
# File lib/ruva/opcodes.rb, line 38
38: def check_int(i)
39: raise IllegalArgumentError, "Invalid int #{i.inspect}" unless i.is_a?(Integer)
40: i.is_a?(VM::Types::Cat2Value) ? i.__value : i
41: end
Check a ruby Integer is in long range and wrap it in a VM::Types::Cat2Value. Do this before pushing it.
# File lib/ruva/opcodes.rb, line 45
45: def check_long(i)
46: raise IllegalArgumentError, "Invalid long #{i.inspect}" unless i.is_a?(Integer)
47: i.is_a?(VM::Types::Cat2Value) ? i : VM::Types::Cat2Value.new(i)
48: end
Check a ruby Integer is in short range. Do this before pushing it.
# File lib/ruva/opcodes.rb, line 32
32: def check_short(s)
33: raise IllegalArgumentError, "Invalid short #{s.inspect}" unless s && s.is_a?(Integer) && (-32768..32767).member?(s)
34: s.is_a?(VM::Types::Cat2Value) ? s.__value : s
35: end
Encode the supplied (char-range) operands as a long (32-bit) jump target instruction offset. This is calculated as the operands value as a short, minus five (to account for the fact that pc will already point to the next instruction).
# File lib/ruva/opcodes.rb, line 118
118: def long_jump(b1, b2, b3, b4)
119: signed_long(operands_long(b1, b2, b3, b4)) - 5
120: end
Decode the supplied long (32-bit) operands to a quad of char-range operands.
# File lib/ruva/opcodes.rb, line 81
81: def long_operands(long)
82: # TODO reverse for little-endian plaf?
83: # How does JVM behave?
84: [(long & 0xFF000000) >> 24,
85: (long & 0x00FF0000) >> 16,
86: (long & 0x0000FF00) >> 8,
87: long & 0x000000FF]
88: end
# File lib/ruva/opcodes.rb, line 15
15: def not_yet
16: raise Ruva::VM::VMError, "Unimplemented Opcode (defined: #{caller[-1]})"
17: end
NOP (0x00) () …
# File lib/ruva/opcodes.rb, line 1908
1908: def op0(vm, *operands)
1909: # nop
1910: end
ACONSTNULL (0x01) () …, => …, null
# File lib/ruva/opcodes.rb, line 217
217: def op1(vm)
218: vm.stack.push nil
219: end
LCONST_1 (0x0a) () … => …, const
# File lib/ruva/opcodes.rb, line 1660
1660: def op10(vm)
1661: vm.stack.push(check_long(1))
1662: end
ISUB (0x64) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1552
1552: def op100(vm)
1553: b, a = vm.stack.pop, vm.stack.pop
1554: check_int(a) and check_int(b)
1555: vm.stack.push(a) and vm.stack.push(b)
1556: __any_sub(vm)
1557: end
LSUB (0x65) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1838
1838: def op101(vm)
1839: b, a = vm.stack.pop, vm.stack.pop
1840: vm.stack.push(check_long(a - b))
1841: end
FSUB (0x66) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 815
815: def op102(vm)
816: b, a = vm.stack.pop, vm.stack.pop
817: check_float(a) and check_float(b)
818: vm.stack.push(a) and vm.stack.push(b)
819: __any_sub(vm)
820: end
DSUB (0x67) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 544
544: def op103(vm)
545: b, a = vm.stack.pop, vm.stack.pop
546: vm.stack.push(check_double(a - b))
547: end
IMUL (0x68) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1226
1226: def op104(vm)
1227: b, a = vm.stack.pop, vm.stack.pop
1228: check_int(a) and check_int(b)
1229: vm.stack.push(a) and vm.stack.push(b)
1230: __any_mul(vm)
1231: end
LMUL (0x69) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1737
1737: def op105(vm)
1738: b, a = vm.stack.pop, vm.stack.pop
1739: vm.stack.push(check_long(a * b))
1740: end
FMUL (0x6A) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 743
743: def op106(vm)
744: b, a = vm.stack.pop, vm.stack.pop
745: check_float(a) and check_float(b)
746: vm.stack.push(a) and vm.stack.push(b)
747: __any_mul(vm)
748: end
DMUL (0x6B) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 476
476: def op107(vm)
477: b, a = vm.stack.pop, vm.stack.pop
478: vm.stack.push(check_double(a * b))
479: end
IDIV (0x6C) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1045
1045: def op108(vm)
1046: b, a = vm.stack.pop, vm.stack.pop
1047: check_int(a) and check_int(b)
1048: vm.stack.push(a) and vm.stack.push(b)
1049: __any_div(vm)
1050: end
LDIV (0x6d) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1696
1696: def op109(vm)
1697: b, a = vm.stack.pop, vm.stack.pop
1698: vm.stack.push(check_long(a / b))
1699: end
FCONST_0 (0x0B) () … => …, const
# File lib/ruva/opcodes.rb, line 679
679: def op11(vm)
680: vm.stack.push(0.0)
681: end
FDIV (0x6E) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 700
700: def op110(vm)
701: b, a = vm.stack.pop, vm.stack.pop
702: check_float(a) and check_float(b)
703: vm.stack.push(a) and vm.stack.push(b)
704: __any_div(vm)
705: end
DDIV (0x6F) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 435
435: def op111(vm)
436: b, a = vm.stack.pop, vm.stack.pop
437: vm.stack.push(check_double(a / b))
438: end
IREM (0x70) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1480
1480: def op112(vm)
1481: b, a = vm.stack.pop, vm.stack.pop
1482: check_int(a) and check_int(b)
1483: vm.stack.push(a) and vm.stack.push(b)
1484: __any_rem(vm)
1485: end
LREM (0x71) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1767
1767: def op113(vm)
1768: b, a = vm.stack.pop, vm.stack.pop
1769: vm.stack.push(check_long(a % b))
1770: end
FREM (0x72) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 761
761: def op114(vm)
762: b, a = vm.stack.pop, vm.stack.pop
763: check_float(a) and check_float(b)
764: vm.stack.push(a) and vm.stack.push(b)
765: __any_rem(vm)
766: end
DREM (0x73) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 492
492: def op115(vm)
493: b, a = vm.stack.pop, vm.stack.pop
494: vm.stack.push(check_double(a % b))
495: end
INEG (0x74) () …, value => …, result
# File lib/ruva/opcodes.rb, line 1236
1236: def op116(vm)
1237: vm.stack.push(check_int(vm.stack.pop))
1238: __any_neg(vm)
1239: end
LNEG (0x75) () …, value => …, result
# File lib/ruva/opcodes.rb, line 1745
1745: def op117(vm)
1746: vm.stack.push(check_long(-vm.stack.pop))
1747: end
FNEG (0x76) () …, value => …, result
# File lib/ruva/opcodes.rb, line 753
753: def op118(vm)
754: vm.stack.push(check_float(vm.stack.pop))
755: __any_neg(vm)
756: end
DNEG (0x77) () …, value => …, result
# File lib/ruva/opcodes.rb, line 484
484: def op119(vm)
485: a = vm.stack.pop
486: vm.stack.push(check_double(-a))
487: end
FCONST_1 (0x0C) () … => …, const
# File lib/ruva/opcodes.rb, line 686
686: def op12(vm)
687: vm.stack.push(1.0)
688: end
ISHL (0x78) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1498
1498: def op120(vm)
1499: b, a = check_int(vm.stack.pop), check_int(vm.stack.pop)
1500: vm.stack.push(a << b)
1501: end
LSHL (0x79) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1784
1784: def op121(vm)
1785: v2 = vm.stack.pop
1786: v1 = vm.stack.pop
1787: vm.stack.push(check_long(v1 << v2))
1788: end
ISHR (0x7A) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1506
1506: def op122(vm)
1507: v2 = vm.stack.pop
1508: v1 = vm.stack.pop
1509: check_int(v1) and check_int(v2)
1510: vm.stack.push(v1 >> v2)
1511: end
LSHR (0x7B) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1793
1793: def op123(vm)
1794: v2 = vm.stack.pop
1795: v1 = vm.stack.pop
1796: vm.stack.push(check_long(v1 >> v2))
1797: end
IUSHR (0x7C) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1562
1562: def op124(vm)
1563: b, a = check_int(vm.stack.pop), check_int(vm.stack.pop)
1564: vm.stack.push([a].pack('l').unpack('L').first >> b)
1565: end
LUSHR (0x7D) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1846
1846: def op125(vm)
1847: not_yet
1848: end
IAND (0x7E) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 980
980: def op126(vm)
981: b, a = check_int(vm.stack.pop), check_int(vm.stack.pop)
982: vm.stack.push(a & b)
983: end
LAND (0x7f) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1630
1630: def op127(vm)
1631: b,a = vm.stack.pop, vm.stack.pop
1632: vm.stack.push(check_long(a & b))
1633: end
INT ##################
IOR (0x80) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1471
1471: def op128(vm)
1472: v2 = vm.stack.pop
1473: v1 = vm.stack.pop
1474: vm.stack.push(v1 | v2)
1475: end
LOR (0x81) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1759
1759: def op129(vm)
1760: b,a = vm.stack.pop, vm.stack.pop
1761: vm.stack.push(check_long(b | a))
1762: end
FCONST_2 (0x0D) () … => …, const
# File lib/ruva/opcodes.rb, line 693
693: def op13(vm)
694: vm.stack.push(2.0)
695: end
IXOR (0x82) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1570
1570: def op130(vm)
1571: v2 = vm.stack.pop
1572: v1 = vm.stack.pop
1573: vm.stack.push(v1 ^ v2)
1574: end
LXOR (0x83) () …, value1, value2 => …, result
# File lib/ruva/opcodes.rb, line 1853
1853: def op131(vm)
1854: b,a = vm.stack.pop, vm.stack.pop
1855: vm.stack.push(check_long(b ^ a))
1856: end
IINC (0x84) (idx, const) …, => …
# File lib/ruva/opcodes.rb, line 1185
1185: def op132(vm, idx, const)
1186: locals = vm.locals
1187: locals[idx] = check_int(locals[idx]) + check_byte(signed_byte(const))
1188: end
I2L (0x85) () …, value => …, long
# File lib/ruva/opcodes.rb, line 951
951: def op133(vm)
952: vm.stack.push(check_long(Integer(vm.stack.pop)))
953: end
I2F (0x86) () …, value => …, float
# File lib/ruva/opcodes.rb, line 944
944: def op134(vm)
945: vm.stack.push(check_float(Float(vm.stack.pop)))
946: end
I2D (0x87) …, value => …, double
# File lib/ruva/opcodes.rb, line 937
937: def op135(vm)
938: vm.stack.push(check_double(Float(vm.stack.pop)))
939: end
L2I (0x88) () …, value => …, int
# File lib/ruva/opcodes.rb, line 1610
1610: def op136(vm)
1611: vm.stack.push(check_int([vm.stack.pop & 0xFFFFFFFF].pack('Q').unpack('q').first))
1612: end
L2F (0x89) () …, value => …, long
# File lib/ruva/opcodes.rb, line 1603
1603: def op137(vm)
1604: vm.stack.push(check_float(Float(vm.stack.pop.__value)))
1605: end
LONG ################
L2D (0x8a) () …, value => …, double
# File lib/ruva/opcodes.rb, line 1596
1596: def op138(vm)
1597: vm.stack.push(check_double(Float(vm.stack.pop.__value)))
1598: end
F2I (0x8B) () …, value => …, int
# File lib/ruva/opcodes.rb, line 622
622: def op139(vm)
623: vm.stack.push(Integer(vm.stack.pop))
624: end
DCONST_0 (0x0E) () … => …, const
# File lib/ruva/opcodes.rb, line 421
421: def op14(vm)
422: vm.stack.push(check_double(0.0))
423: end