• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2021-2025 Huawei Device Co., Ltd.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14---
15
16chapters:
17  - name: General Design
18    text: >
19      VM is register-based with a dedicated accumulator register that serves as an implicit operand to instructions.
20
21  - name: Registers
22    text: >
23      Registers are wide enough to hold a single reference when working with objects.
24      When used for primitive types, register width is considered to be 64 bits.
25      When used for object types, registers must be considered wide enough to hold a reference to an object.
26      The scope of a register is a *function frame* (also known as *activation record*). If an instruction defines not all 64
27      bits of a register, then the undefined bits are not accessed in a verified code.
28      Register field width in instruction encoding can be 4 (16 addressable registers), 8 (256 registers) or
29      16 (65536 registers) bits.
30
31  - name: Accumulator
32    text: >
33      *Accumulator* is a special register which is used implicitly by instructions as a source and/or destination operand.
34      The main goal of using accumulator is to improve encoding density without losing much in performance. Therefore,
35      the general intuition regarding accumulator usage is to utilize accumulator as much as possible by taking it as
36      a source from a previous instruction result and passing it to the next instruction in its destination operand.
37      Moreover, when an instruction has more than one source operand, the shorter-living value must be passed
38      through accumulator. However, instruction variations that do not write into accumulator are also introduced
39      if it gives advantage. For example, arguments for the`call.range` instruction can be moved register-to-register.
40
41  - name: Calling Sequence
42    text: >
43      A new function frame is created upon the execution of call bytecode. All necessary arguments are copied from the
44      caller frame to the top of the callee frame. E.g., the last argument is placed in the register with the largest
45      index, and the first argument is placed in the register with the index that equals the size of the frame subtracted
46      by the number of arguments. The accumulator value is considered *undefined*; it is not read in the verified bytecode.
47      Upon return, the callee frame is destroyed. If a function return value is non-void, then it is passed to the caller
48      via accumulator. Otherwise, the accumulator content in the caller frame is considered *undefined*; it is not
49      read in the verified bytecode.
50
51  - name: Supported Primitive Types
52    text: |
53      VM supports operations on registers with i32 and i64 integral values. However, 8-bit and 16-bit integral values
54      can be loaded/stored into records and arrays with corresponding bytecodes. In that case, VM extends/truncates the
55      value to match storage size with i32. Similarly, passing an 8-bit or 16-bit value to a function can be emulated by
56      passing a value, which is zero or sign-extended to i32.
57      VM supports operations on registers with f32 and f64 values, which correspond to the IEEE-754 single and double precision
58      floating-point representations.
59      Primitive data type of a register is not tracked by VM and is interpreted by separate bytecodes.
60      Integral values are not inherently signed or unsigned. Their signedness is interpreted by bytecodes as well.
61      If bytecode treats a register value as a signed integer, then it uses two's complement representation.
62      If bytecode treats a register value as an unsigned integer, then the bytecode is denoted by using the u32/u64 notation.
63      It is not always possible to denote the type of result for moves, loads and stores, because it depends on the type of the
64      source object. If it is not possible to denote the type of result, then bNN notation is used, where NN is the bit size of
65      the result. Therefore, for example, b64 is a union of f64 and i64.
66
67      ### Floating-point literals
68
69      Decimal floating-point literals can have the following parts:
70
71      - Sign ('``+``' or '``-`'`),
72      - Whole number part,
73      - Decimal point,
74      - Fractional part,
75      - Exponent indicator ('``e``'),
76      - Exponent sign,
77      - Exponent.
78
79      Decimal floating-point literals must have at least one digit, plus either a decimal point or an exponent part.
80
81      Special values:
82
83      - Positive zero (+0.0, hexadecimal representation is `0x0000000000000000`),
84      - Negative zero (-0.0, hexadecimal representation is `0x8000000000000000`),
85      - Minimal positive value (4.9E-324, hexadecimal representation is `0x0000000000000001`),
86      - Maximal negative value (-4.9E-324, hexadecimal representation is `0x8000000000000001`),
87      - Maximal positive value (1.7976931348623157e308, hexadecimal representation is `0x7fefffffffffffff`),
88      - Minimal negative value (-1.7976931348623157e308, hexadecimal representation is `0xffefffffffffffff`),
89      - Positive infinity (hexadecimal representation is `0x7ff0000000000000`),
90      - Negative infinity (hexadecimal representation is `0xfff0000000000000`),
91      - Not a number - set of all NaN values (one of hexadecimal representations is `0x7ff8000000000000`).
92
93  - name: Language-Dependent Types
94    text: >
95      Panda VM supports type hierarchies according to the language it executes. Therefore, creation (or loading
96      from a constant pool) of strings, arrays, and exception objects produces objects of types native to the
97      language, including inheritance relations.
98
99  - name: Dynamically-Typed Languages Support
100    text: >
101      Panda VM supports dynamically-typed languages. It represents a dynamic value through a special 'any' value. 'Any' values
102      wrap each value itself (both primitive value and object) with its corresponding type info. VM tracks types of registers
103      that hold 'any' values, whether primitive or not. Virtual registers and accumulator are wide enough to hold an 'any'
104      value. Regular static instructions can also be used when the VM executes a code inside a dynamically-typed language context.
105
106# File format and ISA versioning
107min_version: 0.0.0.5
108version: 0.0.0.5
109
110properties:
111  - tag: type_id
112    description: Use an id which resolves into a type constant.
113  - tag: method_id
114    description: Use an id which resolves into a method constant.
115  - tag: static_method_id
116    description: Use an id which resolves into a static method constant.
117  - tag: string_id
118    description: Use an id which resolves into a string constant.
119  - tag: literalarray_id
120    description: Use an id which resolves into a constant literalarray.
121  - tag: field_id
122    description: Use an id which resolves into an instance field reference.
123  - tag: static_field_id
124    description: Use an id which resolves into a static field reference.
125  - tag: short_long_range
126    description: Instruction is used to pass arguments, exists in short, long and range forms.
127  - tag: call
128    description: Pass control to the callee method.
129  - tag: call_virt
130    description: Pass control to the callee method via virtual call.
131  - tag: return
132    description: Pass control to the caller method.
133  - tag: suspend
134    description: Suspend current method and pass control to the caller one.
135  - tag: jump
136    description: Pass control to another bytecode in a current method.
137  - tag: conditional
138    description: Operate based on computed condition, otherwise is no operation.
139  - tag: float
140    description: Perform floating point operation.
141  - tag: dynamic
142    description: Operates on 'any' values.
143  - tag: maybe_dynamic
144    description: May operate on 'any' values depending on language context.
145  - tag: language_type
146    description: Creates objects of type depending on language context.
147  - tag: initialize_type
148    description: May initialize type instance during execution.
149  - tag: init_obj
150    description: Calls the object initialization function.
151exceptions:
152  - tag: x_none
153    description: Bytecode doesn't throw exceptions.
154  - tag: x_null
155    description: Bytecode throws NullPointerException in case of null reference as a source.
156  - tag: x_bounds
157    description: Bytecode throws ArrayIndexOutOfBoundsException if index is out of bounds of an array.
158  - tag: x_negsize
159    description: Bytecode throws NegativeArraySizeException if index is less than zero.
160  - tag: x_store
161    description: Bytecode throws ArrayStoreException if element isn't instance of array's element type.
162  - tag: x_abstract
163    description: Bytecode throws AbstractMethodError if resolved method has no implementation.
164  - tag: x_arith
165    description: Bytecode throws ArithmeticException if the divisor is 0.
166  - tag: x_cast
167    description: Bytecode throws ClassCastException if type cast failed.
168  - tag: x_classdef
169    description: Bytecode throws NoClassDefFoundError if type cast failed.
170  - tag: x_oom
171    description: Bytecode throws OutOfMemoryError if failed to allocate object.
172  - tag: x_init
173    description: Bytecode throws ExceptionInInitializerError if unexpected exception occurred in a static initializer.
174  - tag: x_call
175    description: Bytecode may throw an error if an exception occurs in the called bytecode.
176  - tag: x_throw
177    description: Bytecode's primary role is to throw provided exception object.
178  - tag: x_link
179    description: Bytecode may throw NoClassDefFoundError if failed to resolve id.
180verification:
181  - tag: none
182    description: Instruction is always valid.
183  - tag: v1_array
184    description: First operand contains a reference to an array.
185  - tag: v1_object
186    description: First operand contains a reference to an object (other than array).
187  - tag: v1_array_type
188    # TODO: specify
189    description: First operand contains a reference to an array of elements of type corresponding to bytecode.
190  - tag: v1_i32
191    description: First operand contains a value of i32 type.
192  - tag: v1_type
193    description: First operand contains a value of type corresponding to bytecode.
194  - tag: v1_obj_or_null
195    description: First operand contains a reference to an object or null.
196  - tag: v2_i32
197    description: Second operand contains a value of i32 type.
198  - tag: v2_object
199    description: Second operand contains a reference to an object (other than array).
200  - tag: v2_type
201    description: Second operand contains a value of type corresponding to bytecode.
202  - tag: acc_i32
203    description: Accumulator contains a value of i32 type.
204  - tag: acc_type
205    description: Accumulator contains a value of type corresponding to bytecode.  # TODO: specify
206  - tag: acc_return_type
207    # TODO: specify, including assignment compatibility (see Java 'areturn')
208    description: Accumulator type is compatible with method return type.
209  - tag: v1_throw_type
210    description: First operand contains a reference to an instance of class Throwable or of a subclass of Throwable.
211  - tag: acc_obj_or_null
212    description: Accumulator contains a reference to an object or null.
213  - tag: type_id_array
214    description: Type_id operand must correspond to an array type.
215  - tag: type_id_object
216    description: Type_id operand must correspond to an object type (other than array).
217  - tag: type_id_any_object
218    description: Type_id operand must correspond to any object type.
219  - tag: type_id_class
220    description: Type_id operand must correspond to a Class type.
221  - tag: method_id_static
222    description: Method_id must resolve to a static method or into initializer for a type other than one-dimensional array.
223  - tag: method_id_non_static
224    description: Method_id must resolve to a non-static method.
225  - tag: method_id_non_abstract
226    description: Method_id must resolve to a method that has implementation.
227  - tag: method_id_accessible
228    description: Method_id must resolve to a method which is accessible.
229  - tag: constant_string_id
230    description: Id must resolve into a constant-pool string.
231  - tag: constant_literalarray_id
232    description: Id must resolve into a constant literalarray.
233  - tag: compatible_arguments
234    description: Arguments provided to a method must be of compatible types.  # TODO: specify compatibility
235  - tag: method_init_obj
236    description: Method_id must resolve into initializer for a type other than one-dimensional array.
237  - tag: branch_target
238    description: Branch target should point to a beginning of an instruction of the same method.
239  - tag: field_id_non_static
240    description: Field_id must resolve to a non-static object field.
241  - tag: field_id_static
242    description: Field_id must resolve to a static field.
243  - tag: field_id_size
244    description: Field_id must resolve to a field of size corresponding to bytecode.
245  - tag: valid_in_dynamic_context
246    description: Instruction valid only for dynamically-typed language context.
247
248prefixes:
249  - name: bit
250    description: Bit operations.
251    opcode_idx: 0xef
252  - name: unsigned
253    description: Unsigned operations.
254    opcode_idx: 0xee
255  - name: cast
256    description: Cast operations.
257    opcode_idx: 0xed
258  - name: f32
259    description: IEEE-754 single precision floating-point operations.
260    opcode_idx: 0xec
261
262# Define elements allowed to be used in a profile description.
263profiles_schema: {}
264
265# Profiles should be specified in an ISA description for a specific language.
266profiles: []
267
268namespaces:
269  - namespace: core
270    used_instructions: []
271
272groups:
273  - title: No operation
274    description: Perform an operation without behavior.
275    exceptions:
276      - x_none
277    verification:
278      - none
279    pseudo: |
280      skip
281    instructions:
282      - sig: nop
283        acc: none
284        format: [op_none]
285        opcode_idx: [0x0]
286
287  - title: Move register-to-register
288    description: Move values between registers.
289    exceptions:
290      - x_none
291    verification:
292      - v2_type
293    pseudo: |
294      vd = vs
295    instructions:
296      - sig: mov v1:out:b32, v2:in:b32
297        acc: none
298        format: [op_v1_4_v2_4, op_v1_8_v2_8, op_v1_16_v2_16]
299        opcode_idx: [0x1, 0x2, 0x3]
300      - sig: mov.64 v1:out:b64, v2:in:b64
301        acc: none
302        format: [op_v1_4_v2_4, op_v1_16_v2_16]
303        opcode_idx: [0x4, 0x5]
304      - sig: mov.obj v1:out:ref, v2:in:ref
305        acc: none
306        format: [op_v1_4_v2_4, op_v1_8_v2_8, op_v1_16_v2_16]
307        opcode_idx: [0x6, 0x7, 0x8]
308
309  - title: Move immediate-to-register
310    description: >
311      Move integer immediate into a register. For short formats immediate is sign-extended to operand size.
312    exceptions:
313      - x_none
314    verification:
315      - none
316    pseudo: >
317      vd = imm
318    instructions:
319      - sig: movi v:out:i32, imm:i32
320        acc: none
321        format: [op_v_4_imm_4, op_v_8_imm_8, op_v_8_imm_16, op_v_8_imm_32]
322        opcode_idx: [0x9, 0xa, 0xb, 0xc]
323      - sig: movi.64 v:out:i64, imm:i64
324        acc: none
325        format: [op_v_8_imm_64]
326        opcode_idx: [0xd]
327      - sig: fmovi v:out:f32, imm:f32
328        acc: none
329        prefix: f32
330        format: [pref_op_v_8_imm_32]
331        opcode_idx: [0x0]
332        properties: [float]
333      - sig: fmovi.64 v:out:f64, imm:f64
334        acc: none
335        format: [op_v_8_imm_64]
336        opcode_idx: [0xe]
337        properties: [float]
338
339  - title: Move null reference into the register
340    description: Move null reference into the register.
341    exceptions:
342      - x_none
343    verification:
344      - none
345    pseudo: >
346      vd = null
347    instructions:
348      - sig: mov.null v:out:ref
349        acc: none
350        format: [op_v_8]
351        opcode_idx: [0xf]
352
353  - title: Load accumulator from the register
354    description: Moves register content into accumulator.
355    exceptions:
356      - x_none
357    verification:
358      - v1_type
359    pseudo: |
360      acc = vs
361    instructions:
362      - sig: lda v:in:b32
363        acc: out:b32
364        format: [op_v_8]
365        opcode_idx: [0x10]
366      - sig: lda.64 v:in:b64
367        acc: out:b64
368        format: [op_v_8]
369        opcode_idx: [0x11]
370      - sig: lda.obj v:in:ref
371        acc: out:ref
372        format: [op_v_8]
373        opcode_idx: [0x12]
374
375  - title: Load accumulator from immediate
376    description: >
377      Load immediate into accumulator. For short formats immediate is sign-extended to operand size.
378    exceptions:
379      - x_none
380    verification:
381      - none
382    pseudo: |
383      acc = imm
384    instructions:
385      - sig: ldai imm:i32
386        acc: out:i32
387        format: [op_imm_8, op_imm_16, op_imm_32]
388        opcode_idx: [0x13, 0x14, 0x15]
389      - sig: ldai.64 imm:i64
390        acc: out:i64
391        format: [op_imm_64]
392        opcode_idx: [0x16]
393      - sig: fldai imm:f32
394        acc: out:f32
395        prefix: f32
396        format: [pref_op_imm_32]
397        opcode_idx: [0x1]
398        properties: [float]
399      - sig: fldai.64 imm:f64
400        acc: out:f64
401        format: [op_imm_64]
402        opcode_idx: [0x17]
403        properties: [float]
404
405  - title: Load accumulator from string constant pool
406    description: >
407      Load string specified by id into accumulator. In dynamically-typed language context
408      load string as 'any' value.
409    properties:
410      - string_id
411      - language_type
412      - maybe_dynamic
413    exceptions:
414      - x_oom
415    verification:
416      - constant_string_id
417    pseudo: |
418      acc = load(id)
419    instructions:
420      - sig: lda.str string_id
421        acc: out:ref
422        format: [op_id_32]
423        opcode_idx: [0x18]
424
425  - title: Create and initialize new constant array
426    description: >
427      Create a new single-dimensional constant literal array and put a reference to it into register.
428    properties:
429      - literalarray_id
430    exceptions:
431      - x_oom
432    verification:
433      - constant_literalarray_id
434    pseudo: |
435      arr = load(id)
436      if arr == nullptr then
437        throw OutOfMemoryError
438      end
439      v = arr
440    instructions:
441      - sig: lda.const v:out:ref, literalarray_id
442        acc: none
443        format: [op_v_8_id_16]
444        opcode_idx: [0x19]
445
446  - title: Load accumulator from type constant pool
447    description: Load type specified by id into accumulator.
448    properties:
449      - type_id
450      - language_type
451    exceptions:
452      - x_link
453    verification:
454      - type_id_class
455    pseudo: |
456      type = load(id)
457      if type == nullptr then
458        throw NoClassDefFoundError
459      end
460      acc = type
461    instructions:
462      - sig: lda.type type_id
463        acc: out:ref
464        format: [op_id_16]
465        opcode_idx: [0x1a]
466
467  - title: Load null reference into accumulator
468    description: Load null reference into accumulator.
469    exceptions:
470      - x_none
471    verification:
472      - none
473    pseudo: |
474      acc = null
475    instructions:
476      - sig: lda.null
477        acc: out:ref
478        format: [op_none]
479        opcode_idx: [0x1b]
480
481  - title: Store accumulator
482    description: Moves accumulator content into a register.
483    exceptions:
484      - x_none
485    verification:
486      - acc_type
487    pseudo: |
488      vd = acc
489    instructions:
490      - sig: sta v:out:b32
491        acc: in:b32
492        format: [op_v_8]
493        opcode_idx: [0x1c]
494      - sig: sta.64 v:out:b64
495        acc: in:b64
496        format: [op_v_8]
497        opcode_idx: [0x1d]
498      - sig: sta.obj v:out:ref
499        acc: in:ref
500        format: [op_v_8]
501        opcode_idx: [0x1e]
502
503  - title: Integer comparison
504    description: Perform specified signed or unsigned integer comparison between register and accumulator.
505    exceptions:
506      - x_none
507    verification:
508      - acc_type
509      - v1_type
510    pseudo: |
511        if acc < vs then
512          acc = -1
513        else if acc == vs then
514          acc = 0
515        else
516          acc = 1
517        end
518    instructions:
519      - sig: cmp.64 v:in:i64
520        acc: inout:i64->i32
521        format: [op_v_8]
522        opcode_idx: [0x1f]
523      - sig: ucmp v:in:u32
524        acc: inout:u32->i32
525        prefix: unsigned
526        format: [pref_op_v_8]
527        opcode_idx: [0x0]
528      - sig: ucmp.64 v:in:u64
529        acc: inout:u64->i32
530        prefix: unsigned
531        format: [pref_op_v_8]
532        opcode_idx: [0x1]
533
534  - title: Floating-point comparison
535    description: Perform specified floating-point comparison between register and accumulator.
536    properties:
537      - float
538    exceptions:
539      - x_none
540    verification:
541      - acc_type
542      - v1_type
543    pseudo: |
544      if isnan(acc) or isnan(vs) then
545        switch (op)
546        case fcmpg:
547        case fcmpg.64:
548          acc = 1
549        case fcmpl:
550        case fcmpl.64:
551          acc = -1
552      else
553        if acc < vs then
554          acc = -1
555        else if acc == vs then
556          acc = 0
557        else
558          acc = 1
559        end
560      end
561    instructions:
562      - sig: fcmpl v:in:f32
563        acc: inout:f32->i32
564        prefix: f32
565        format: [pref_op_v_8]
566        opcode_idx: [0x2]
567      - sig: fcmpl.64 v:in:f64
568        acc: inout:f64->i32
569        format: [op_v_8]
570        opcode_idx: [0x20]
571      - sig: fcmpg v:in:f32
572        acc: inout:f32->i32
573        prefix: f32
574        format: [pref_op_v_8]
575        opcode_idx: [0x3]
576      - sig: fcmpg.64 v:in:f64
577        acc: inout:f64->i32
578        format: [op_v_8]
579        opcode_idx: [0x21]
580
581  - title: Unconditional jump
582    description: >
583      Unconditionally transfer execution to an instruction at offset bytes from the beginning of the current
584      instruction. Offset is sign-extended to the size of instruction address.
585    properties:
586      - jump
587    exceptions:
588      - x_none
589    verification:
590      - branch_target
591    pseudo: |
592      pc += imm
593    instructions:
594      - sig: jmp imm:i32
595        acc: none
596        format: [op_imm_8, op_imm_16, op_imm_32]
597        opcode_idx: [0x22, 0x23, 0x24]
598
599  - title: Conditional object comparison jump
600    description: >
601      Transfer execution to an instruction at offset bytes from the beginning of the current instruction if
602      object references in accumulator and source register compare as specified. Offset is sign-extended to the size of
603      instruction address.
604    properties:
605      - jump
606      - conditional
607    exceptions:
608      - x_none
609    verification:
610      - branch_target
611      - acc_obj_or_null
612      - v1_obj_or_null
613    pseudo: |
614      switch (cc)
615      case eq:
616        if acc == vs then
617          pc += imm
618        end
619      case ne:
620        if acc != vs then
621          pc += imm
622      end
623    instructions:
624      - sig: jeq.obj v:in:ref, imm:i32
625        acc: in:ref
626        format: [op_v_8_imm_8, op_v_8_imm_16]
627        opcode_idx: [0x25, 0x26]
628      - sig: jne.obj v:in:ref, imm:i32
629        acc: in:ref
630        format: [op_v_8_imm_8, op_v_8_imm_16]
631        opcode_idx: [0x27, 0x28]
632
633  - title: Conditional compared to null jump
634    description: >
635      Transfer execution to an instruction at offset bytes from the beginning of the current instruction if
636      object reference in accumulator compares with null as specified. Offset is sign-extended to the size of
637      instruction address.
638    properties:
639      - jump
640      - conditional
641    exceptions:
642      - x_none
643    verification:
644      - branch_target
645      - acc_obj_or_null
646    pseudo: |
647      switch (cc)
648      case eq:
649        if acc == null then
650          pc += imm
651        end
652      case ne:
653        if acc != null then
654          pc += imm
655      end
656    instructions:
657      - sig: jeqz.obj imm:i32
658        acc: in:ref
659        format: [op_imm_8, op_imm_16]
660        opcode_idx: [0x29, 0x2a]
661      - sig: jnez.obj imm:i32
662        acc: in:ref
663        format: [op_imm_8, op_imm_16]
664        opcode_idx: [0x2b, 0x2c]
665
666  - title: Conditional compared to zero jump
667    description: >
668      Transfer execution to an instruction at offset bytes from the beginning of the current instruction if
669      signed 32-bit integer in accumulator compares with 0 as specified. Offset is sign-extended to the size
670      of instruction address.
671    properties:
672      - jump
673      - conditional
674    exceptions:
675      - x_none
676    verification:
677      - branch_target
678      - acc_type
679    pseudo: |
680      switch (cc)
681      case eq:
682        if acc == 0 then
683          pc += imm
684        end
685      case ne:
686        if acc != 0 then
687          pc += imm
688        end
689      case lt:
690        if acc < 0 then
691          pc += imm
692        end
693      case gt:
694        if acc > 0 then
695          pc += imm
696        end
697      case le:
698        if acc <= 0 then
699          pc += imm
700        end
701      case ge:
702        if acc >= 0 then
703          pc += imm
704        end
705    instructions:
706      - sig: jeqz imm:i32
707        acc: in:i32
708        format: [op_imm_8, op_imm_16]
709        opcode_idx: [0x2d, 0x2e]
710      - sig: jnez imm:i32
711        acc: in:i32
712        format: [op_imm_8, op_imm_16]
713        opcode_idx: [0x2f, 0x30]
714      - sig: jltz imm:i32
715        acc: in:i32
716        format: [op_imm_8, op_imm_16]
717        opcode_idx: [0x31, 0x32]
718      - sig: jgtz imm:i32
719        acc: in:i32
720        format: [op_imm_8, op_imm_16]
721        opcode_idx: [0x33, 0x34]
722      - sig: jlez imm:i32
723        acc: in:i32
724        format: [op_imm_8, op_imm_16]
725        opcode_idx: [0x35, 0x36]
726      - sig: jgez imm:i32
727        acc: in:i32
728        format: [op_imm_8, op_imm_16]
729        opcode_idx: [0x37, 0x38]
730
731  - title: Conditional compared to register jump
732    description: >
733      Transfer execution to an instruction at offset bytes from the beginning of the current instruction if signed
734      32-bit integers in accumulator and register compare as specified. Offset is sign-extended to the size of
735      instruction address.
736    properties:
737      - jump
738      - conditional
739    exceptions:
740      - x_none
741    verification:
742      - branch_target
743      - acc_type
744      - v1_type
745    pseudo: |
746      diff = signed_cmp(acc, vs)
747      switch (cc)
748      case eq:
749        if diff == 0 then
750          pc += imm
751        end
752      case ne:
753        if diff != 0 then
754          pc += imm
755        end
756      case lt:
757        if diff < 0 then
758          pc += imm
759        end
760      case gt:
761        if diff > 0 then
762          pc += imm
763        end
764      case le:
765        if diff <= 0 then
766          pc += imm
767        end
768      case ge:
769        if diff >= 0 then
770          pc += imm
771        end
772    instructions:
773      - sig: jeq v:in:i32, imm:i32
774        acc: in:i32
775        format: [op_v_8_imm_8, op_v_8_imm_16]
776        opcode_idx: [0x39, 0x3a]
777      - sig: jne v:in:i32, imm:i32
778        acc: in:i32
779        format: [op_v_8_imm_8, op_v_8_imm_16]
780        opcode_idx: [0x3b, 0x3c]
781      - sig: jlt v:in:i32, imm:i32
782        acc: in:i32
783        format: [op_v_8_imm_8, op_v_8_imm_16]
784        opcode_idx: [0x3d, 0x3e]
785      - sig: jgt v:in:i32, imm:i32
786        acc: in:i32
787        format: [op_v_8_imm_8, op_v_8_imm_16]
788        opcode_idx: [0x3f, 0x40]
789      - sig: jle v:in:i32, imm:i32
790        acc: in:i32
791        format: [op_v_8_imm_8, op_v_8_imm_16]
792        opcode_idx: [0x41, 0x42]
793      - sig: jge v:in:i32, imm:i32
794        acc: in:i32
795        format: [op_v_8_imm_8, op_v_8_imm_16]
796        opcode_idx: [0x43, 0x44]
797
798  - title: Floating-point unary
799    description: Perform specified floating-point operation on accumulator.
800    properties:
801      - float
802    exceptions:
803      - x_none
804    verification:
805      - acc_type
806    pseudo: |
807      switch (op)
808      case fneg:
809      case fneg.64:
810        acc = -acc
811    instructions:
812      - sig: fneg
813        acc: inout:f32
814        prefix: f32
815        format: [pref_op_none]
816        opcode_idx: [0x4]
817      - sig: fneg.64
818        acc: inout:f64
819        format: [op_none]
820        opcode_idx: [0x45]
821
822  - title: Unary
823    description: Perform specified operation on accumulator.
824    exceptions:
825      - x_none
826    verification:
827      - acc_type
828    pseudo: |
829      switch (op)
830      case neg:
831      case neg.64:
832        acc = -acc
833      case not:
834      case not.64:
835        acc = ~acc
836    instructions:
837      - sig: neg
838        acc: inout:i32
839        format: [op_none]
840        opcode_idx: [0x46]
841      - sig: neg.64
842        acc: inout:i64
843        format: [op_none]
844        opcode_idx: [0x47]
845      - sig: not
846        acc: inout:i32
847        prefix: bit
848        format: [pref_op_none]
849        opcode_idx: [0x0]
850      - sig: not.64
851        acc: inout:i64
852        prefix: bit
853        format: [pref_op_none]
854        opcode_idx: [0x1]
855
856  - title: Two address binary operation on accumulator
857    description: Perform specified binary operation on accumulator and register, and store the result into accumulator.
858    exceptions:
859      - x_none
860    verification:
861      - acc_type
862      - v1_type
863    pseudo: |
864      switch (op)
865      case add2:
866        acc = (acc + vs) % 2^32
867      case add2.64:
868        acc = (acc + vs) % 2^64
869      case sub2:
870        acc = (acc - vs) % 2^32
871      case sub2.64:
872        acc = (acc - vs) % 2^64
873      case mul2:
874        acc = (acc * vs) % 2^32
875      case mul2.64:
876        acc = (acc * vs) % 2^64
877      case and2:
878        acc = acc & vs
879      case and2.64:
880        acc = acc & vs
881      case or2:
882        acc = acc | vs
883      case or2.64:
884        acc = acc | vs
885      case xor2:
886        acc = acc ^ vs
887      case xor2.64:
888        acc = acc ^ vs
889      case shl2:
890        acc = (acc << (vs & 0x1f)) % 2^32
891      case shl2.64:
892        acc = (acc << (vs & 0x3f)) % 2^64
893      case shr2:
894        acc = acc >> (vs & 0x1f)
895      case shr2.64:
896        acc = acc >> (vs & 0x3f)
897      case ashr2:
898        acc = (acc < 0) ? ~(~acc >> vs & 0x1f) : acc >> vs & 0x1f
899      case ashr2.64:
900        acc = (acc < 0) ? ~(~acc >> vs & 0x3f) : acc >> vs & 0x3f
901    instructions:
902      - sig: add2 v:in:i32
903        acc: inout:i32
904        format: [op_v_8]
905        opcode_idx: [0x48]
906      - sig: add2.64 v:in:i64
907        acc: inout:i64
908        format: [op_v_8]
909        opcode_idx: [0x49]
910      - sig: sub2 v:in:i32
911        acc: inout:i32
912        format: [op_v_8]
913        opcode_idx: [0x4a]
914      - sig: sub2.64 v:in:i64
915        acc: inout:i64
916        format: [op_v_8]
917        opcode_idx: [0x4b]
918      - sig: mul2 v:in:i32
919        acc: inout:i32
920        format: [op_v_8]
921        opcode_idx: [0x4c]
922      - sig: mul2.64 v:in:i64
923        acc: inout:i64
924        format: [op_v_8]
925        opcode_idx: [0x4d]
926      - sig: and2 v:in:i32
927        acc: inout:i32
928        prefix: bit
929        format: [pref_op_v_8]
930        opcode_idx: [0x2]
931      - sig: and2.64 v:in:i64
932        acc: inout:i64
933        prefix: bit
934        format: [pref_op_v_8]
935        opcode_idx: [0x3]
936      - sig: or2 v:in:i32
937        acc: inout:i32
938        prefix: bit
939        format: [pref_op_v_8]
940        opcode_idx: [0x4]
941      - sig: or2.64 v:in:i64
942        acc: inout:i64
943        prefix: bit
944        format: [pref_op_v_8]
945        opcode_idx: [0x5]
946      - sig: xor2 v:in:i32
947        acc: inout:i32
948        prefix: bit
949        format: [pref_op_v_8]
950        opcode_idx: [0x6]
951      - sig: xor2.64 v:in:i64
952        acc: inout:i64
953        prefix: bit
954        format: [pref_op_v_8]
955        opcode_idx: [0x7]
956      - sig: shl2 v:in:i32
957        acc: inout:i32
958        prefix: bit
959        format: [pref_op_v_8]
960        opcode_idx: [0x8]
961      - sig: shl2.64 v:in:i64
962        acc: inout:i64
963        prefix: bit
964        format: [pref_op_v_8]
965        opcode_idx: [0x9]
966      - sig: shr2 v:in:i32
967        acc: inout:i32
968        prefix: bit
969        format: [pref_op_v_8]
970        opcode_idx: [0xa]
971      - sig: shr2.64 v:in:i64
972        acc: inout:i64
973        prefix: bit
974        format: [pref_op_v_8]
975        opcode_idx: [0xb]
976      - sig: ashr2 v:in:i32
977        acc: inout:i32
978        prefix: bit
979        format: [pref_op_v_8]
980        opcode_idx: [0xc]
981      - sig: ashr2.64 v:in:i64
982        acc: inout:i64
983        prefix: bit
984        format: [pref_op_v_8]
985        opcode_idx: [0xd]
986
987  - title: Two address binary operations on accumulator with results in the register
988    description: Perform specified binary operation on accumulator and register, and store the result into the register.
989    exceptions:
990      - x_none
991    verification:
992      - acc_type
993      - v1_type
994    pseudo: |
995      switch (op)
996      case add2:
997        vd = (acc + vs) % 2^32
998      case add2.64:
999        vd = (acc + vs) % 2^64
1000      case sub2:
1001        vd = (acc - vs) % 2^32
1002      case sub2.64:
1003        vd = (acc - vs) % 2^64
1004      case mul2:
1005        vd = (acc * vs) % 2^32
1006      case mul2.64:
1007        acc = (acc * vs) % 2^64
1008      case and2:
1009        vd = acc & vs
1010      case and2.64:
1011        vd = acc & vs
1012      case or2:
1013        vd = acc | vs
1014      case or2.64:
1015        vd = acc | vs
1016      case xor2:
1017        vd = acc ^ vs
1018      case xor2.64:
1019        vd = acc ^ vs
1020      case shl2:
1021        vd = (acc << (vs & 0x1f)) % 2^32
1022      case shl2.64:
1023        vd = (acc << (vs & 0x3f)) % 2^64
1024      case shr2:
1025        vd = acc >> (vs & 0x1f)
1026      case shr2.64:
1027        vd = acc >> (vs & 0x3f)
1028      case ashr2:
1029        vd = (acc < 0) ? ~(~acc >> vs & 0x1f) : acc >> vs & 0x1f
1030      case ashr2.64:
1031        vd = (acc < 0) ? ~(~acc >> vs & 0x3f) : acc >> vs & 0x3f
1032    instructions:
1033      - sig: add2v v1:out:i32, v2:in:i32
1034        acc: in:i32
1035        format: [op_v1_8_v2_8]
1036      - sig: add2v.64 v1:out:i64, v2:in:i64
1037        acc: in:i64
1038        format: [op_v1_8_v2_8]
1039      - sig: sub2v v1:out:i32, v2:in:i32
1040        acc: in:i32
1041        format: [op_v1_8_v2_8]
1042      - sig: sub2v.64 v1:out:i64, v2:in:i64
1043        acc: in:i64
1044        format: [op_v1_8_v2_8]
1045      - sig: mul2v v1:out:i32, v2:in:i32
1046        acc: in:i32
1047        format: [op_v1_8_v2_8]
1048      - sig: mul2v.64 v1:out:i64, v2:in:i64
1049        acc: in:i64
1050        format: [op_v1_8_v2_8]
1051      - sig: and2v v1:out:i32, v2:in:i32
1052        acc: in:i32
1053        prefix: bit
1054        format: [pref_op_v1_8_v2_8]
1055      - sig: and2v.64 v1:out:i64, v2:in:i64
1056        acc: in:i64
1057        prefix: bit
1058        format: [pref_op_v1_8_v2_8]
1059      - sig: or2v v1:out:i32, v2:in:i32
1060        acc: in:i32
1061        prefix: bit
1062        format: [pref_op_v1_8_v2_8]
1063      - sig: or2v.64 v1:out:i64, v2:in:i64
1064        acc: in:i64
1065        prefix: bit
1066        format: [pref_op_v1_8_v2_8]
1067      - sig: xor2v v1:out:i32, v2:in:i32
1068        acc: in:i32
1069        prefix: bit
1070        format: [pref_op_v1_8_v2_8]
1071      - sig: xor2v.64 v1:out:i64, v2:in:i64
1072        acc: in:i64
1073        prefix: bit
1074        format: [pref_op_v1_8_v2_8]
1075      - sig: shl2v v1:out:i32, v2:in:i32
1076        acc: in:i32
1077        prefix: bit
1078        format: [pref_op_v1_8_v2_8]
1079      - sig: shl2v.64 v1:out:i64, v2:in:i64
1080        acc: in:i64
1081        prefix: bit
1082        format: [pref_op_v1_8_v2_8]
1083      - sig: shr2v v1:out:i32, v2:in:i32
1084        acc: in:i32
1085        prefix: bit
1086        format: [pref_op_v1_8_v2_8]
1087      - sig: shr2v.64 v1:out:i64, v2:in:i64
1088        acc: in:i64
1089        prefix: bit
1090        format: [pref_op_v1_8_v2_8]
1091      - sig: ashr2v v1:out:i32, v2:in:i32
1092        acc: in:i32
1093        prefix: bit
1094        format: [pref_op_v1_8_v2_8]
1095      - sig: ashr2v.64 v1:out:i64, v2:in:i64
1096        acc: in:i64
1097        prefix: bit
1098        format: [pref_op_v1_8_v2_8]
1099
1100  - title: Two address floating-point binary operation on accumulator
1101    description: |
1102      Perform specified floating-point binary operation on accumulator and register, and store the result into accumulator.
1103      The results of instructions correspond to the IEEE-754 arithmetic rules.
1104
1105      - Any operation with NaN results in the NaN value.
1106      - The sum of opposite infinities or the difference of the same-sign infinities is NaN.
1107      - Division is NaN if Infinity is divided by Infinity.
1108      - Division is NaN if zero is divided by zero.
1109      - Multiplication is NaN if zero is multiplied by infinity.
1110      - The sign of division or multiplication result is positive if both values have the same sign, or negative if the values have different signs.
1111      - Division is infinity if any nonzero value is divided by zero.
1112      - Multiplication is infinity if any nonzero value is multiplied by infinity.
1113      - The sum of two infinities of the same sign or the difference of two infinities of opposite signs is infinity. The sign of the result matches
1114        the sign of the accumulator value.
1115      - The sum or the difference of infinity and any finite value is infinity. The sign of the result matches the sign of infinity.
1116      - The sum or the difference of zeros is zero. Exceptions are the sum of two negative zeros and the difference of negative and positive zeros - the result is negative zero.
1117
1118    properties:
1119      - float
1120    exceptions:
1121      - x_none
1122    verification:
1123      - acc_type
1124      - v1_type
1125    pseudo: |
1126      switch (op)
1127      case fadd2:
1128      case fadd2.64:
1129        acc = acc + vs
1130      case fsub2:
1131      case fsub2.64:
1132        acc = acc - vs
1133      case fmul2:
1134      case fmul2.64:
1135        acc = acc * vs
1136      case fdiv2:
1137      case fdiv2.64:
1138        acc = acc / vs
1139      case fmod2:
1140      case fmod2.64:
1141        acc = acc % vs
1142    instructions:
1143      - sig: fadd2 v:in:f32
1144        acc: inout:f32
1145        prefix: f32
1146        format: [pref_op_v_8]
1147        opcode_idx: [0x5]
1148      - sig: fadd2.64 v:in:f64
1149        acc: inout:f64
1150        format: [op_v_8]
1151        opcode_idx: [0x4e]
1152      - sig: fsub2 v:in:f32
1153        acc: inout:f32
1154        prefix: f32
1155        format: [pref_op_v_8]
1156        opcode_idx: [0x6]
1157      - sig: fsub2.64 v:in:f64
1158        acc: inout:f64
1159        format: [op_v_8]
1160        opcode_idx: [0x4f]
1161      - sig: fmul2 v:in:f32
1162        acc: inout:f32
1163        prefix: f32
1164        format: [pref_op_v_8]
1165        opcode_idx: [0x7]
1166      - sig: fmul2.64 v:in:f64
1167        acc: inout:f64
1168        format: [op_v_8]
1169        opcode_idx: [0x50]
1170      - sig: fdiv2 v:in:f32
1171        acc: inout:f32
1172        prefix: f32
1173        format: [pref_op_v_8]
1174        opcode_idx: [0x8]
1175      - sig: fdiv2.64 v:in:f64
1176        acc: inout:f64
1177        format: [op_v_8]
1178        opcode_idx: [0x51]
1179      - sig: fmod2 v:in:f32
1180        acc: inout:f32
1181        prefix: f32
1182        format: [pref_op_v_8]
1183        opcode_idx: [0x9]
1184      - sig: fmod2.64 v:in:f64
1185        acc: inout:f64
1186        format: [op_v_8]
1187        opcode_idx: [0x52]
1188
1189  - title: Two address floating-point binary operations on accumulator with the results in the register.
1190    description: |
1191      Perform specified floating-point binary operation on accumulator and register, and store the result into the register.
1192      The results of instructions correspond to the IEEE-754 arithmetic rules.
1193
1194      - Any operation with NaN results in NaN value.
1195      - The sum of opposite infinities or the difference of the same-sign infinities is NaN.
1196      - Division is NaN if Infinity is divided by Infinity.
1197      - Division is NaN if zero is divided by zero.
1198      - Multiplication is NaN if zero is multiplied by infinity.
1199      - The sign of division or multiplication result is positive if both values have the same sign, negative if the values have different sign.
1200      - Division is infinity if any nonzero value is divided by zero.
1201      - Multiplication is infinity if any nonzero value is multiplied by infinity.
1202      - The sum of two infinities of the same sign or the difference of two infinities of opposite sign is infinity.
1203        The sign of result matches the sign of the accumulator value.
1204      - The sum or the difference of infinity and any finite value is infinity. The sign of result matches the sign of infinity.
1205      - The sum or the difference of zeros is zero. Exceptions are the sum of two negative zeros and the difference of negative and positive zeros - the result is negative zero.
1206
1207    properties:
1208      - float
1209    exceptions:
1210      - x_none
1211    verification:
1212      - acc_type
1213      - v1_type
1214    pseudo: |
1215      switch (op)
1216      case fadd2:
1217      case fadd2.64:
1218        vd = acc + vs
1219      case fsub2:
1220      case fsub2.64:
1221        vd = acc - vs
1222      case fmul2:
1223      case fmul2.64:
1224        vd = acc * vs
1225      case fdiv2:
1226      case fdiv2.64:
1227        vd = acc / vs
1228      case fmod2:
1229      case fmod2.64:
1230        vd = acc % vs
1231    instructions:
1232      - sig: fadd2v v1:out:f32, v2:in:f32
1233        acc: in:f32
1234        prefix: f32
1235        format: [pref_op_v1_8_v2_8]
1236      - sig: fadd2v.64 v1:out:f64, v2:in:f64
1237        acc: in:f64
1238        format: [op_v1_8_v2_8]
1239      - sig: fsub2v v1:out:f32, v2:in:f32
1240        acc: in:f32
1241        prefix: f32
1242        format: [pref_op_v1_8_v2_8]
1243      - sig: fsub2v.64 v1:out:f64, v2:in:f64
1244        acc: in:f64
1245        format: [op_v1_8_v2_8]
1246      - sig: fmul2v v1:out:f32, v2:in:f32
1247        acc: in:f32
1248        prefix: f32
1249        format: [pref_op_v1_8_v2_8]
1250      - sig: fmul2v.64 v1:out:f64, v2:in:f64
1251        acc: in:f64
1252        format: [op_v1_8_v2_8]
1253      - sig: fdiv2v v1:out:f32, v2:in:f32
1254        acc: in:f32
1255        prefix: f32
1256        format: [pref_op_v1_8_v2_8]
1257      - sig: fdiv2v.64 v1:out:f64, v2:in:f64
1258        acc: in:f64
1259        format: [op_v1_8_v2_8]
1260      - sig: fmod2v v1:out:f32, v2:in:f32
1261        acc: in:f32
1262        prefix: f32
1263        format: [pref_op_v1_8_v2_8]
1264      - sig: fmod2v.64 v1:out:f64, v2:in:f64
1265        acc: in:f64
1266        format: [op_v1_8_v2_8]
1267
1268  - title: Two address integer division and modulo on accumulator
1269    description: Perform integer division or modulo on accumulator and register, and store the result into accumulator.
1270    exceptions:
1271      - x_arith
1272    verification:
1273      - acc_type
1274      - v1_type
1275    pseudo: |
1276      if vs == 0 then
1277        throw ArithmeticException
1278      end
1279      switch (op)
1280      case div:
1281        if acc == INT32_MIN and vs == -1 then
1282          acc = INT32_MIN
1283        else
1284          acc = acc / vs
1285        end
1286      case div.64:
1287        if acc == INT64_MIN and vs == -1 then
1288          acc = INT64_MIN
1289        else
1290          acc = acc / vs
1291        end
1292      case divu:
1293      case divu.64:
1294        acc = acc / vs
1295      case mod:
1296        if acc == INT32_MIN and vs == -1 then
1297          acc = 0
1298        else
1299          acc = acc % vs
1300        end
1301      case mod.64:
1302        if acc == INT64_MIN and vs == -1 then
1303          acc = 0
1304        else
1305          acc = acc % vs
1306        end
1307      case modu:
1308      case modu.64:
1309        acc = acc % vs
1310    instructions:
1311      - sig: div2 v:in:i32
1312        acc: inout:i32
1313        format: [op_v_8]
1314        opcode_idx: [0x53]
1315      - sig: div2.64 v:in:i64
1316        acc: inout:i64
1317        format: [op_v_8]
1318        opcode_idx: [0x54]
1319      - sig: mod2 v:in:i32
1320        acc: inout:i32
1321        format: [op_v_8]
1322        opcode_idx: [0x55]
1323      - sig: mod2.64 v:in:i64
1324        acc: inout:i64
1325        format: [op_v_8]
1326        opcode_idx: [0x56]
1327      - sig: divu2 v:in:u32
1328        acc: inout:u32
1329        prefix: unsigned
1330        format: [pref_op_v_8]
1331        opcode_idx: [0x2]
1332      - sig: divu2.64 v:in:u64
1333        acc: inout:u64
1334        prefix: unsigned
1335        format: [pref_op_v_8]
1336        opcode_idx: [0x3]
1337      - sig: modu2 v:in:u32
1338        acc: inout:u32
1339        prefix: unsigned
1340        format: [pref_op_v_8]
1341        opcode_idx: [0x4]
1342      - sig: modu2.64 v:in:u64
1343        acc: inout:u64
1344        prefix: unsigned
1345        format: [pref_op_v_8]
1346        opcode_idx: [0x5]
1347
1348  - title: Two address integer division and modulo on accumulator with the result in the register
1349    description: Perform integer division or modulo on accumulator and register, and store the result into the register.
1350    exceptions:
1351      - x_arith
1352    verification:
1353      - acc_type
1354      - v1_type
1355    pseudo: |
1356      if vs == 0 then
1357        throw ArithmeticException
1358      end
1359      switch (op)
1360      case div:
1361        if acc == INT32_MIN and vs == -1 then
1362          vd = INT32_MIN
1363        else
1364          vd = acc / vs
1365        end
1366      case div.64:
1367        if acc == INT64_MIN and vs == -1 then
1368          vd = INT64_MIN
1369        else
1370          vd = acc / vs
1371        end
1372      case divu:
1373      case divu.64:
1374        vd = acc / vs
1375      case mod:
1376        if acc == INT32_MIN and vs == -1 then
1377          vd = 0
1378        else
1379          vd = acc % vs
1380        end
1381      case mod.64:
1382        if acc == INT64_MIN and vs == -1 then
1383          vd = 0
1384        else
1385          vd = acc % vs
1386        end
1387      case modu:
1388      case modu.64:
1389        vd = acc % vs
1390    instructions:
1391      - sig: div2v v1:out:i32, v2:in:i32
1392        acc: in:i32
1393        format: [op_v1_8_v2_8]
1394      - sig: div2v.64 v1:out:i64, v2:in:i64
1395        acc: in:i64
1396        format: [op_v1_8_v2_8]
1397      - sig: mod2v v1:out:i32, v2:in:i32
1398        acc: in:i32
1399        format: [op_v1_8_v2_8]
1400      - sig: mod2v.64 v1:out:i64, v2:in:i64
1401        acc: in:i64
1402        format: [op_v1_8_v2_8]
1403      - sig: divu2v v1:out:u32, v2:in:u32
1404        acc: in:u32
1405        prefix: unsigned
1406        format: [pref_op_v1_8_v2_8]
1407      - sig: divu2v.64 v1:out:u64, v2:in:u64
1408        acc: in:u64
1409        prefix: unsigned
1410        format: [pref_op_v1_8_v2_8]
1411      - sig: modu2v v1:out:u32, v2:in:u32
1412        acc: in:u32
1413        prefix: unsigned
1414        format: [pref_op_v1_8_v2_8]
1415      - sig: modu2v.64 v1:out:u64, v2:in:u64
1416        acc: in:u64
1417        prefix: unsigned
1418        format: [pref_op_v1_8_v2_8]
1419
1420  - title: Two address binary operation with immediate on accumulator
1421    description: >
1422      Perform specified binary operation on accumulator and immediate, and store the result into accumulator.
1423      Immediate is sign-extended to operand size.
1424    exceptions:
1425      - x_none
1426    verification:
1427      - acc_type
1428    pseudo: |
1429      switch (op)
1430      case addi:
1431        acc = (acc + imm) % 2^32
1432      case subi:
1433        acc = (acc - imm) % 2^32
1434      case muli:
1435        acc = (acc * imm) % 2^32
1436      case andi:
1437        acc = acc & imm
1438      case ori:
1439        acc = acc | imm
1440      case xori:
1441        acc = acc ^ imm
1442      case shli:
1443        acc = (acc << (imm & 0x1f)) % 2^32
1444      case shri:
1445        acc = acc >> (imm & 0x1f)
1446      case ashri:
1447        acc = (acc < 0) ? ~(~acc >> imm & 0x1f) : acc >> imm & 0x1f
1448    instructions:
1449      - sig: addi imm:i32
1450        acc: inout:i32
1451        format: [op_imm_8]
1452        opcode_idx: [0x57]
1453      - sig: subi imm:i32
1454        acc: inout:i32
1455        format: [op_imm_8]
1456        opcode_idx: [0x58]
1457      - sig: muli imm:i32
1458        acc: inout:i32
1459        format: [op_imm_8]
1460        opcode_idx: [0x59]
1461      - sig: andi imm:i32
1462        acc: inout:i32
1463        format: [op_imm_32]
1464        opcode_idx: [0x5a]
1465      - sig: ori imm:i32
1466        acc: inout:i32
1467        format: [op_imm_32]
1468        opcode_idx: [0x5b]
1469      - sig: xori imm:i32
1470        acc: inout:i32
1471        prefix: bit
1472        format: [pref_op_imm_32]
1473        opcode_idx: [0xe]
1474      - sig: shli imm:i32
1475        acc: inout:i32
1476        format: [op_imm_8]
1477        opcode_idx: [0x5c]
1478      - sig: shri imm:i32
1479        acc: inout:i32
1480        format: [op_imm_8]
1481        opcode_idx: [0x5d]
1482      - sig: ashri imm:i32
1483        acc: inout:i32
1484        format: [op_imm_8]
1485        opcode_idx: [0x5e]
1486
1487  - title: Two address binary operation with immediate
1488    description: >
1489      Perform specified binary operation and immediate, and store the result into the register.
1490      Immediate is sign-extended to operand size.
1491    exceptions:
1492      - x_none
1493    verification:
1494      - v1_type
1495      - v2_type
1496    pseudo: |
1497      switch (op)
1498      case addi:
1499        v1 = (v2 + imm) % 2^32
1500      case subi:
1501        v1 = (v2 - imm) % 2^32
1502      case muli:
1503        v1 = (v2 * imm) % 2^32
1504      case andi:
1505        v1 = v2 & imm
1506      case ori:
1507        v1 = v2 | imm
1508      case xori:
1509        v1 = v2 ^ imm
1510      case shli:
1511        v1 = (v2 << (imm & 0x1f)) % 2^32
1512      case shri:
1513        v1 = v2 >> (imm & 0x1f)
1514      case ashri:
1515        v1 = (v2 < 0) ? ~(~v2 >> imm & 0x1f) : v2 >> imm & 0x1f
1516    instructions:
1517      - sig: addiv v1:out:i32, v2:in:i32, imm:i32
1518        acc: none
1519        format: [op_v1_4_v2_4_imm_8]
1520      - sig: subiv v1:out:i32, v2:in:i32, imm:i32
1521        acc: none
1522        format: [op_v1_4_v2_4_imm_8]
1523      - sig: muliv v1:out:i32, v2:in:i32, imm:i32
1524        acc: none
1525        format: [op_v1_4_v2_4_imm_8]
1526      - sig: andiv v1:out:i32, v2:in:i32, imm:i32
1527        acc: none
1528        format: [op_v1_4_v2_4_imm_32]
1529      - sig: oriv v1:out:i32, v2:in:i32, imm:i32
1530        acc: none
1531        format: [op_v1_4_v2_4_imm_32]
1532      - sig: xoriv v1:out:i32, v2:in:i32, imm:i32
1533        acc: none
1534        prefix: bit
1535        format: [pref_op_v1_4_v2_4_imm_32]
1536      - sig: shliv v1:out:i32, v2:in:i32, imm:i32
1537        acc: none
1538        format: [op_v1_4_v2_4_imm_8]
1539      - sig: shriv v1:out:i32, v2:in:i32, imm:i32
1540        acc: none
1541        format: [op_v1_4_v2_4_imm_8]
1542      - sig: ashriv v1:out:i32, v2:in:i32, imm:i32
1543        acc: none
1544        format: [op_v1_4_v2_4_imm_8]
1545
1546  - title: Two address integer division or modulo with immediate on accumulator
1547    description: >
1548      Perform two address integer division or modulo on accumulator and immediate, and store the result into accumulator.
1549      Immediate is sign-extended to operand size.
1550    exceptions:
1551      - x_arith
1552    verification:
1553      - acc_type
1554    pseudo: |
1555      if imm == 0 then
1556        throw ArithmeticException
1557      end
1558      switch(op)
1559      case divi:
1560        if acc == INT32_MIN and imm == -1 then
1561          acc = INT32_MIN
1562        else
1563          acc = acc / imm
1564        end
1565      case modi:
1566        if acc == INT32_MIN and imm == -1 then
1567          acc = 0
1568        else
1569          acc = acc % imm
1570        end
1571    instructions:
1572      - sig: divi imm:i32
1573        acc: inout:i32
1574        format: [op_imm_8]
1575        opcode_idx: [0x5f]
1576      - sig: modi imm:i32
1577        acc: inout:i32
1578        format: [op_imm_8]
1579        opcode_idx: [0x60]
1580
1581  - title: Two address integer division or modulo with immediate
1582    description: >
1583      Perform two address integer division or modulo and immediate, and store the result into the register.
1584      Immediate is sign-extended to operand size.
1585    exceptions:
1586      - x_arith
1587    verification:
1588      - v1_type
1589      - v2_type
1590    pseudo: |
1591      if imm == 0 then
1592        throw ArithmeticException
1593      end
1594      switch(op)
1595      case divi:
1596        if v1 == INT32_MIN and imm == -1 then
1597          v1 = INT32_MIN
1598        else
1599          v1 = v2 / imm
1600        end
1601      case modi:
1602        if v1 == INT32_MIN and imm == -1 then
1603          v1 = 0
1604        else
1605          v1 = v2 % imm
1606        end
1607    instructions:
1608      - sig: diviv v1:out:i32, v2:in:i32, imm:i32
1609        acc: none
1610        format: [op_v1_4_v2_4_imm_8]
1611      - sig: modiv v1:out:i32, v2:in:i32, imm:i32
1612        acc: none
1613        format: [op_v1_4_v2_4_imm_8]
1614
1615  - title: Three address binary operation
1616    description: Perform specified binary operation on two registers, and store the result into accumulator.
1617    exceptions:
1618      - x_none
1619    verification:
1620      - v1_type
1621      - v2_type
1622    pseudo: |
1623      switch (op)
1624      case add:
1625        acc = (vs1 + vs2) % 2^32
1626      case sub:
1627        acc = (vs1 - vs2) % 2^32
1628      case mul:
1629        acc = (vs1 * vs2) % 2^32
1630      case and:
1631        acc = vs1 & vs2
1632      case or:
1633        acc = vs1 | vs2
1634      case xor:
1635        acc = vs1 ^ vs2
1636      case shl:
1637        acc = (vs1 << (vs2 & 0x1f)) % 2^32
1638      case shr:
1639        acc = vs1 >> (vs2 & 0x1f)
1640      case ashr:
1641        acc = (vs1 < 0) ? ~(~vs1 >> vs2 & 0x1f) : vs1 >> vs2 & 0x1f
1642    instructions:
1643      - sig: add v1:in:i32, v2:in:i32
1644        acc: out:i32
1645        format: [op_v1_4_v2_4]
1646        opcode_idx: [0x61]
1647      - sig: sub v1:in:i32, v2:in:i32
1648        acc: out:i32
1649        format: [op_v1_4_v2_4]
1650        opcode_idx: [0x62]
1651      - sig: mul v1:in:i32, v2:in:i32
1652        acc: out:i32
1653        format: [op_v1_4_v2_4]
1654        opcode_idx: [0x63]
1655      - sig: and v1:in:i32, v2:in:i32
1656        acc: out:i32
1657        prefix: bit
1658        format: [pref_op_v1_4_v2_4]
1659        opcode_idx: [0xf]
1660      - sig: or v1:in:i32, v2:in:i32
1661        acc: out:i32
1662        prefix: bit
1663        format: [pref_op_v1_4_v2_4]
1664        opcode_idx: [0x10]
1665      - sig: xor v1:in:i32, v2:in:i32
1666        acc: out:i32
1667        prefix: bit
1668        format: [pref_op_v1_4_v2_4]
1669        opcode_idx: [0x11]
1670      - sig: shl v1:in:i32, v2:in:i32
1671        acc: out:i32
1672        prefix: bit
1673        format: [pref_op_v1_4_v2_4]
1674        opcode_idx: [0x12]
1675      - sig: shr v1:in:i32, v2:in:i32
1676        acc: out:i32
1677        prefix: bit
1678        format: [pref_op_v1_4_v2_4]
1679        opcode_idx: [0x13]
1680      - sig: ashr v1:in:i32, v2:in:i32
1681        acc: out:i32
1682        prefix: bit
1683        format: [pref_op_v1_4_v2_4]
1684        opcode_idx: [0x14]
1685
1686  - title: Three address binary operation with the result in the register
1687    description: Perform specified binary operation on two registers, and store the result into the register.
1688    exceptions:
1689      - x_none
1690    verification:
1691      - v1_type
1692      - v2_type
1693    pseudo: |
1694      switch (op)
1695      case add:
1696        v1 = (v1 + v2) % 2^32
1697      case sub:
1698        v1 = (v1 - v2) % 2^32
1699      case mul:
1700        v1 = (v1 * v2) % 2^32
1701      case and:
1702        v1 = v1 & v2
1703      case or:
1704        v1 = v1 | v2
1705      case xor:
1706        v1 = v1 ^ v2
1707      case shl:
1708        v1 = (v1 << (v2 & 0x1f)) % 2^32
1709      case shr:
1710        v1 = v1 >> (v2 & 0x1f)
1711      case ashr:
1712        v1 = (v1 < 0) ? ~(~v1 >> v2 & 0x1f) : v1 >> v2 & 0x1f
1713    instructions:
1714      - sig: addv v1:inout:i32, v2:in:i32
1715        acc: none
1716        format: [op_v1_4_v2_4]
1717      - sig: subv v1:inout:i32, v2:in:i32
1718        acc: none
1719        format: [op_v1_4_v2_4]
1720      - sig: mulv v1:inout:i32, v2:in:i32
1721        acc: none
1722        format: [op_v1_4_v2_4]
1723      - sig: andv v1:inout:i32, v2:in:i32
1724        acc: none
1725        prefix: bit
1726        format: [pref_op_v1_4_v2_4]
1727      - sig: orv v1:inout:i32, v2:in:i32
1728        acc: none
1729        prefix: bit
1730        format: [pref_op_v1_4_v2_4]
1731      - sig: xorv v1:inout:i32, v2:in:i32
1732        acc: none
1733        prefix: bit
1734        format: [pref_op_v1_4_v2_4]
1735      - sig: shlv v1:inout:i32, v2:in:i32
1736        acc: none
1737        prefix: bit
1738        format: [pref_op_v1_4_v2_4]
1739      - sig: shrv v1:inout:i32, v2:in:i32
1740        acc: none
1741        prefix: bit
1742        format: [pref_op_v1_4_v2_4]
1743      - sig: ashrv v1:inout:i32, v2:in:i32
1744        acc: none
1745        prefix: bit
1746        format: [pref_op_v1_4_v2_4]
1747
1748  - title: Three address integer division or modulo
1749    description: Perform integer division or modulo on two registers, and store the result into accumulator.
1750    exceptions:
1751      - x_arith
1752    verification:
1753      - v1_type
1754      - v2_type
1755    pseudo: |
1756      if vs2 == 0 then
1757        throw ArithmeticException
1758      end
1759      switch(op)
1760      case div:
1761        if vs1 == INT32_MIN and vs2 == -1 then
1762          acc = INT32_MIN
1763        else
1764          acc = vs1 / vs2
1765        end
1766      case mod:
1767        if vs1 == INT32_MIN and vs2 == -1 then
1768          acc = 0
1769        else
1770          acc = vs1 % vs2
1771        end
1772    instructions:
1773      - sig: div v1:in:i32, v2:in:i32
1774        acc: out:i32
1775        format: [op_v1_4_v2_4]
1776        opcode_idx: [0x64]
1777      - sig: mod v1:in:i32, v2:in:i32
1778        acc: out:i32
1779        format: [op_v1_4_v2_4]
1780        opcode_idx: [0x65]
1781
1782  - title: Three address integer division or modulo with the result in the register
1783    description: Perform integer division or modulo on two registers, and store the result into accumulator.
1784    exceptions:
1785      - x_arith
1786    verification:
1787      - v1_type
1788      - v2_type
1789    pseudo: |
1790      if v2 == 0 then
1791        throw ArithmeticException
1792      end
1793      switch(op)
1794      case div:
1795        if v1 == INT32_MIN and v2 == -1 then
1796          v1 = INT32_MIN
1797        else
1798          v1 = v1 / v2
1799        end
1800      case mod:
1801        if v1 == INT32_MIN and v2 == -1 then
1802          v1 = 0
1803        else
1804          v1 = v1 % v2
1805        end
1806    instructions:
1807      - sig: divv v1:inout:i32, v2:in:i32
1808        acc: none
1809        format: [op_v1_4_v2_4]
1810      - sig: modv v1:inout:i32, v2:in:i32
1811        acc: none
1812        format: [op_v1_4_v2_4]
1813
1814  - title: Increment register with immediate
1815    description: >
1816      Increment virtual register by specified immediate. Immediate is sign-extended to operand size.
1817    exceptions:
1818      - x_none
1819    verification:
1820      - v1_i32
1821    pseudo: |
1822      vx = (vx + imm) % 2^32
1823    instructions:
1824      - sig: inci v:inout:i32, imm:i32
1825        acc: none
1826        format: [op_v_4_imm_4]
1827        opcode_idx: [0x66]
1828
1829  - title: Conversions between integer and floating-point types
1830    description: |
1831      Perform specified primitive type conversion of accumulator.
1832      Conversion from floating-point types to integer type is performed by the following rules:
1833
1834      - It is rounding toward zero.
1835      - If converted value is less than minimal value for destination type, then the result is the minimum value for that type.
1836      - If source is negative infinity, then the result is the minimum value for the destination type.
1837      - If converted value is greater than the maximum value for the destination type, then the result is the maximum value for that type.
1838      - If source is positive infinity, then the result is the maximum value for the destination type.
1839      - If source is NaN, then the result is equal to 0.
1840
1841    properties:
1842      - float
1843    exceptions:
1844      - x_none
1845    verification:
1846      - acc_type
1847    pseudo: |
1848      (dest_type) acc = (src_type) acc
1849    instructions:
1850      - sig: i32tof32
1851        acc: inout:i32->f32
1852        prefix: f32
1853        format: [pref_op_none]
1854        opcode_idx: [0xa]
1855      - sig: i32tof64
1856        acc: inout:i32->f64
1857        prefix: cast
1858        format: [pref_op_none]
1859        opcode_idx: [0x0]
1860      - sig: u32tof32
1861        acc: inout:u32->f32
1862        prefix: f32
1863        format: [pref_op_none]
1864        opcode_idx: [0xb]
1865      - sig: u32tof64
1866        acc: inout:u32->f64
1867        prefix: cast
1868        format: [pref_op_none]
1869        opcode_idx: [0x1]
1870      - sig: i64tof32
1871        acc: inout:i64->f32
1872        prefix: f32
1873        format: [pref_op_none]
1874        opcode_idx: [0xc]
1875      - sig: i64tof64
1876        acc: inout:i64->f64
1877        prefix: cast
1878        format: [pref_op_none]
1879        opcode_idx: [0x2]
1880      - sig: u64tof32
1881        acc: inout:u64->f32
1882        prefix: f32
1883        format: [pref_op_none]
1884        opcode_idx: [0xd]
1885      - sig: u64tof64
1886        acc: inout:u64->f64
1887        prefix: cast
1888        format: [pref_op_none]
1889        opcode_idx: [0x3]
1890      - sig: f32tof64
1891        acc: inout:f32->f64
1892        prefix: f32
1893        format: [pref_op_none]
1894        opcode_idx: [0xe]
1895      - sig: f32toi32
1896        acc: inout:f32->i32
1897        prefix: f32
1898        format: [pref_op_none]
1899        opcode_idx: [0xf]
1900      - sig: f32toi64
1901        acc: inout:f32->i64
1902        prefix: f32
1903        format: [pref_op_none]
1904        opcode_idx: [0x10]
1905      - sig: f32tou32
1906        acc: inout:f32->u32
1907        prefix: f32
1908        format: [pref_op_none]
1909        opcode_idx: [0x11]
1910      - sig: f32tou64
1911        acc: inout:f32->u64
1912        prefix: f32
1913        format: [pref_op_none]
1914        opcode_idx: [0x12]
1915      - sig: f64toi32
1916        acc: inout:f64->i32
1917        prefix: cast
1918        format: [pref_op_none]
1919        opcode_idx: [0x4]
1920      - sig: f64toi64
1921        acc: inout:f64->i64
1922        prefix: cast
1923        format: [pref_op_none]
1924        opcode_idx: [0x5]
1925      - sig: f64tou32
1926        acc: inout:f64->u32
1927        prefix: cast
1928        format: [pref_op_none]
1929        opcode_idx: [0x6]
1930      - sig: f64tou64
1931        acc: inout:f64->u64
1932        prefix: cast
1933        format: [pref_op_none]
1934        opcode_idx: [0x7]
1935      - sig: f64tof32
1936        acc: inout:f64->f32
1937        prefix: f32
1938        format: [pref_op_none]
1939        opcode_idx: [0x13]
1940
1941  - title: Conversions from integer types to u1
1942    description: |
1943      Conversion from integer types to u1 is performed by the following rules:
1944
1945      - If converted integer is not equal to zero, then the result is 1.
1946      - Otherwise, the result is 0.
1947
1948    exceptions:
1949      - x_none
1950    verification:
1951      - acc_type
1952    pseudo: |
1953      (dest_type) acc = (src_type) acc
1954    instructions:
1955      - sig: i32tou1
1956        acc: inout:i32->u1
1957        prefix: cast
1958        format: [pref_op_none]
1959        opcode_idx: [0x8]
1960      - sig: i64tou1
1961        acc: inout:i64->u1
1962        prefix: cast
1963        format: [pref_op_none]
1964        opcode_idx: [0x9]
1965      - sig: u32tou1
1966        acc: inout:u32->u1
1967        prefix: cast
1968        format: [pref_op_none]
1969        opcode_idx: [0xa]
1970      - sig: u64tou1
1971        acc: inout:u64->u1
1972        prefix: cast
1973        format: [pref_op_none]
1974        opcode_idx: [0xb]
1975
1976  - title: Integer truncations and extensions
1977    description: >
1978      Perform specified integer extension or truncations of accumulator.
1979      Truncations discard all but N lowest-order bits, where N is the bit size of the destination type.
1980      If extension bytecode treats its source as signed integer, then the value is sign-extended to destination type.
1981      If extension bytecode treats its source as unsigned integer, then the value is zero-extended to destination type.
1982    exceptions:
1983      - x_none
1984    verification:
1985      - acc_type
1986    pseudo: |
1987      (dest_type) acc = (src_type) acc
1988    instructions:
1989      - sig: i32toi64
1990        acc: inout:i32->i64
1991        prefix: cast
1992        format: [pref_op_none]
1993        opcode_idx: [0xc]
1994      - sig: i32toi16
1995        acc: inout:i32->i16
1996        prefix: cast
1997        format: [pref_op_none]
1998        opcode_idx: [0xd]
1999      - sig: i32tou16
2000        acc: inout:i32->u16
2001        prefix: cast
2002        format: [pref_op_none]
2003        opcode_idx: [0xe]
2004      - sig: i32toi8
2005        acc: inout:i32->i8
2006        prefix: cast
2007        format: [pref_op_none]
2008        opcode_idx: [0xf]
2009      - sig: i32tou8
2010        acc: inout:i32->u8
2011        prefix: cast
2012        format: [pref_op_none]
2013        opcode_idx: [0x10]
2014      - sig: i64toi32
2015        acc: inout:i64->i32
2016        prefix: cast
2017        format: [pref_op_none]
2018        opcode_idx: [0x11]
2019      - sig: u32toi64
2020        acc: inout:u32->i64
2021        prefix: cast
2022        format: [pref_op_none]
2023        opcode_idx: [0x12]
2024      - sig: u32toi16
2025        acc: inout:u32->i16
2026        prefix: cast
2027        format: [pref_op_none]
2028        opcode_idx: [0x13]
2029      - sig: u32tou16
2030        acc: inout:u32->u16
2031        prefix: cast
2032        format: [pref_op_none]
2033        opcode_idx: [0x14]
2034      - sig: u32toi8
2035        acc: inout:u32->i8
2036        prefix: cast
2037        format: [pref_op_none]
2038        opcode_idx: [0x15]
2039      - sig: u32tou8
2040        acc: inout:u32->u8
2041        prefix: cast
2042        format: [pref_op_none]
2043        opcode_idx: [0x16]
2044      - sig: u64toi32
2045        acc: inout:u64->i32
2046        prefix: cast
2047        format: [pref_op_none]
2048        opcode_idx: [0x17]
2049      - sig: u64tou32
2050        acc: inout:u64->u32
2051        prefix: cast
2052        format: [pref_op_none]
2053        opcode_idx: [0x18]
2054
2055  - title: Load from array
2056    description: >
2057      Load an element from array using accumulator as an index and put it into accumulator.
2058      If the size of an element is smaller then 32 bits, then it is zero or
2059      sign-extended (depending on bytecode) to i32.
2060    verification:
2061      - v1_array_type
2062      - acc_i32
2063    exceptions:
2064      - x_null
2065      - x_bounds
2066    pseudo: |
2067      if vs == null then
2068        throw NullPointerException
2069      end
2070      if acc < 0 || acc >= len(vs) then
2071        throw ArrayIndexOutOfBoundsException
2072      end
2073      if op == ldarr.8 then
2074        acc = i8toi32(vs[acc])
2075      else if op == ldarru.8 then
2076        acc = u8toi32(vs[acc])
2077      else if op == ldarr.16 then
2078        acc = i16toi32(vs[acc])
2079      else if op == ldarru.16 then
2080        acc = u16toi32(vs[acc])
2081      else
2082        acc = vs[acc]
2083      end
2084    instructions:
2085      - sig: ldarr.8 v:in:i8[]
2086        acc: inout:i32
2087        format: [op_v_8]
2088        opcode_idx: [0x67]
2089      - sig: ldarru.8 v:in:u8[]
2090        acc: inout:i32
2091        format: [op_v_8]
2092        opcode_idx: [0x68]
2093      - sig: ldarr.16 v:in:i16[]
2094        acc: inout:i32
2095        format: [op_v_8]
2096        opcode_idx: [0x69]
2097      - sig: ldarru.16 v:in:u16[]
2098        acc: inout:i32
2099        format: [op_v_8]
2100        opcode_idx: [0x6a]
2101      - sig: ldarr v:in:i32[]
2102        acc: inout:i32
2103        format: [op_v_8]
2104        opcode_idx: [0x6b]
2105      - sig: ldarr.64 v:in:i64[]
2106        acc: inout:i32->i64
2107        format: [op_v_8]
2108        opcode_idx: [0x6c]
2109      - sig: fldarr.32 v:in:f32[]
2110        acc: inout:i32->f32
2111        format: [op_v_8]
2112        opcode_idx: [0x6d]
2113        properties: [float]
2114      - sig: fldarr.64 v:in:f64[]
2115        acc: inout:i32->f64
2116        format: [op_v_8]
2117        opcode_idx: [0x6e]
2118        properties: [float]
2119      - sig: ldarr.obj v:in:ref[]
2120        acc: inout:i32->ref
2121        format: [op_v_8]
2122        opcode_idx: [0x6f]
2123
2124  - title: Store to array
2125    description: >
2126      Store the accumulator content into the array slot pointed by index.
2127      If the size of an element to store is less than 32, then the accumulator
2128      content is truncated to storage size before storing.
2129    verification:
2130      - v1_array_type
2131      - v2_i32
2132      - acc_type
2133    exceptions:
2134      - x_null
2135      - x_bounds
2136      - x_store
2137    pseudo: |
2138      if vs1 == null then
2139        throw NullPointerException
2140      end
2141      if vs2 < 0 || vs2 >= len(vs1) then
2142        throw ArrayIndexOutOfBoundsException
2143      end
2144      if op == starr.obj && !has_type(acc, component_type(vs1))
2145        throw ArrayStoreException
2146      end
2147      if op == starr.8 then
2148        vs1[vs2] = truncateto8(acc)
2149      else if op == starr.16 then
2150        vs1[vs2] = truncateto16(acc)
2151      else
2152        vs1[vs2] = acc
2153      end
2154    instructions:
2155      - sig: starr.8 v1:in:i8[], v2:in:i32
2156        acc: in:i8
2157        format: [op_v1_4_v2_4]
2158        opcode_idx: [0x70]
2159      - sig: starr.16 v1:in:i16[], v2:in:i32
2160        acc: in:i16
2161        format: [op_v1_4_v2_4]
2162        opcode_idx: [0x71]
2163      - sig: starr v1:in:i32[], v2:in:i32
2164        acc: in:i32
2165        format: [op_v1_4_v2_4]
2166        opcode_idx: [0x72]
2167      - sig: starr.64 v1:in:i64[], v2:in:i32
2168        acc: in:i64
2169        format: [op_v1_4_v2_4]
2170        opcode_idx: [0x73]
2171      - sig: fstarr.32 v1:in:f32[], v2:in:i32
2172        acc: in:f32
2173        format: [op_v1_4_v2_4]
2174        opcode_idx: [0x74]
2175        properties: [float]
2176      - sig: fstarr.64 v1:in:f64[], v2:in:i32
2177        acc: in:f64
2178        format: [op_v1_4_v2_4]
2179        opcode_idx: [0x75]
2180        properties: [float]
2181      - sig: starr.obj v1:in:ref[], v2:in:i32
2182        acc: in:ref
2183        format: [op_v1_4_v2_4]
2184        opcode_idx: [0x76]
2185
2186  - title: Array length
2187    description: Get length of an array and put it into accumulator.
2188    verification:
2189      - v1_array
2190    exceptions:
2191      - x_null
2192    pseudo: |
2193      if x == null then
2194        throw NullPointerException
2195      end
2196      acc = len(vs)
2197    instructions:
2198      - sig: lenarr v:in:top[]
2199        acc: out:i32
2200        format: [op_v_8]
2201        opcode_idx: [0x77]
2202
2203  - title: Create new array
2204    description: >
2205      Create a new single-dimensional array of given type and size and put a reference to it into register.
2206      Elements of array are initialized to a default value, i.e., 0 for primitive types and null for objects.
2207    verification:
2208      - type_id_array
2209      - v2_i32
2210    exceptions:
2211      - x_negsize
2212      - x_oom
2213    properties:
2214      - type_id
2215      - language_type
2216      - initialize_type
2217    pseudo: |
2218      if v2 < 0 then
2219        throw NegativeArraySizeException
2220      end
2221      type = resolve(type_id)
2222      v1 = new_array(v2, type)
2223      if not initialized(type)
2224        initialize(type)
2225      end
2226      if v1 == null then
2227        throw OutOfMemoryError
2228      end
2229    instructions:
2230      - sig: newarr v1:out:ref, v2:in:i32, type_id
2231        acc: none
2232        format: [op_v1_4_v2_4_id_16]
2233        opcode_idx: [0x78]
2234
2235  - title: Create new object
2236    description: |
2237      Resolve class type from type_id, allocate memory for an object,
2238      initialize its fields with their default values (i.e., 0 for primitives
2239      and null for objects), and put a reference to the newly created object
2240      into the register. The object must be initialized by calling the
2241      initialization method before further usage.
2242    verification:
2243      - type_id_object
2244    exceptions:
2245      - x_oom
2246    properties:
2247      - type_id
2248      - initialize_type
2249    pseudo: |
2250      type = resolve(type_id)
2251      if not initialized(type)
2252        initialize(type)
2253      end
2254      v = new_instance(type)
2255      if v == null then
2256        throw OutOfMemoryError
2257      end
2258    instructions:
2259      - sig: newobj v:out:ref, type_id
2260        acc: none
2261        format: [op_v_8_id_16]
2262        opcode_idx: [0x79]
2263
2264  - title: Create new object and call initializer
2265    description: >
2266      Resolve class type from initializer method_id, allocate memory for an
2267      object, initialize its fields with their default values (i.e., 0 for
2268      primitives and null for objects), call specified initializer, and put
2269      a reference to the newly created object into accumulator.
2270      method_id must resolve to an initializer. Non-range instructions can be
2271      used to pass up to 4 arguments. Unused register slot values are to be
2272      discarded, and corresponding registers are not to be passed to initializer).
2273      Range kinds of instruction is to be used for methods with more arguments.
2274      Such instructions take the required number of arguments starting from
2275      'vs' register.
2276    verification:
2277      - method_id_non_static
2278      - method_id_accessible
2279      - method_init_obj
2280      - compatible_arguments
2281    exceptions:
2282      - x_abstract
2283      - x_oom
2284      - x_call
2285    properties:
2286      - method_id
2287      - call
2288      - initialize_type
2289      - init_obj
2290      - short_long_range
2291    pseudo: |
2292      init, type = resolve(method_id)
2293      if not initialized(type)
2294        initialize(type)
2295      end
2296      acc = new_instance(type)
2297      if acc == null then
2298        throw OutOfMemoryError
2299      end
2300      init(acc, args)
2301    instructions:
2302      - sig: initobj.short method_id, v1:in:none, v2:in:none
2303        acc: out:ref
2304        format: [op_v1_4_v2_4_id_16]
2305        opcode_idx: [0x7a]
2306      - sig: initobj method_id, v1:in:none, v2:in:none, v3:in:none, v4:in:none
2307        acc: out:ref
2308        format: [op_v1_4_v2_4_v3_4_v4_4_id_16]
2309        opcode_idx: [0x7b]
2310      - sig: initobj.range method_id, v:in:none
2311        acc: out:ref
2312        format: [op_v_8_id_16]
2313        opcode_idx: [0x7c]
2314
2315  - title: Get field from object to accumulator
2316    description: >
2317      Get field value from an object by field id and put it into accumulator.
2318      For a non-object variant, the size of the field is determined by the
2319      field_id. The most significant bits are sign- or unsigned-extended
2320      based on the field type to fit accumulator size. If field type size is
2321      less than 32, then the loaded value is sign- or zero-extended to i32
2322      depending on field type.
2323    verification:
2324      - v1_object
2325      - field_id_non_static
2326      - field_id_size
2327    properties:
2328      - field_id
2329    exceptions:
2330      - x_null
2331    pseudo: |
2332      if vs == null then
2333        throw NullPointerException
2334      end
2335      field = resolve(field_id)
2336      if op == ldobj and size(field) < 32 then
2337        acc = extendto32(vs.get(field))
2338      else
2339        acc = vs.get(field)
2340      end
2341    instructions:
2342      - sig: ldobj v:in:ref, field_id
2343        acc: out:b32
2344        format: [op_v_8_id_16]
2345        opcode_idx: [0x7d]
2346      - sig: ldobj.64 v:in:ref, field_id
2347        acc: out:b64
2348        format: [op_v_8_id_16]
2349        opcode_idx: [0x7e]
2350      - sig: ldobj.obj v:in:ref, field_id
2351        acc: out:ref
2352        format: [op_v_8_id_16]
2353        opcode_idx: [0x7f]
2354
2355  - title: Store accumulator content into object field
2356    description: >
2357      Store the accumulator content into object field by field_id. For
2358      a non-object variant, the size of the actually stored value is determined
2359      by field_id, while other accumulator bits are discarded.
2360      If field type size is less than 32, then the accumulator content is
2361      truncated to storage size before storing.
2362    verification:
2363      - v1_object
2364      - field_id_non_static
2365      - field_id_size
2366      - acc_type
2367    properties:
2368      - field_id
2369    exceptions:
2370      - x_null
2371    pseudo: |
2372      if vs == null then
2373        throw NullPointerException
2374      end
2375      field = resolve(field_id)
2376      if op == stobj and size(field) < 32 then
2377        vs.set(field, truncate(field, acc))
2378      else
2379        vs.set(field, acc)
2380      end
2381    instructions:
2382      - sig: stobj v:in:ref, field_id
2383        acc: in:b32
2384        format: [op_v_8_id_16]
2385        opcode_idx: [0x80]
2386      - sig: stobj.64 v:in:ref, field_id
2387        acc: in:b64
2388        format: [op_v_8_id_16]
2389        opcode_idx: [0x81]
2390      - sig: stobj.obj v:in:ref, field_id
2391        acc: in:ref
2392        format: [op_v_8_id_16]
2393        opcode_idx: [0x82]
2394
2395  - title: Get field from object to register
2396    description: >
2397      Get field value from an object by field id and put it into register.
2398      For a non-object variant, the size of the field is determined by the
2399      field_id, and the most significant bits are sign- or unsigned-extended
2400      based on the field type to fit register size. If field type size is less
2401      than 32, then the loaded value is sign- or zero-extended to i32
2402      depending on field type.
2403    verification:
2404      - v2_object
2405      - field_id_non_static
2406      - field_id_size
2407    properties:
2408      - field_id
2409    exceptions:
2410      - x_null
2411    pseudo: |
2412      if v2 == null then
2413        throw NullPointerException
2414      end
2415      field = resolve(field_id)
2416      if op == ldobj and size(field) < 32 then
2417        v1 = extendto32(v2.get(field))
2418      else
2419        v1 = v2.get(field)
2420      end
2421    instructions:
2422      - sig: ldobj.v v1:out:b32, v2:in:ref, field_id
2423        acc: none
2424        format: [op_v1_4_v2_4_id_16]
2425        opcode_idx: [0x83]
2426      - sig: ldobj.v.64 v1:out:b64, v2:in:ref, field_id
2427        acc: none
2428        format: [op_v1_4_v2_4_id_16]
2429        opcode_idx: [0x84]
2430      - sig: ldobj.v.obj v1:out:ref, v2:in:ref, field_id
2431        acc: none
2432        format: [op_v1_4_v2_4_id_16]
2433        opcode_idx: [0x85]
2434
2435  - title: Store register content into object field
2436    description: >
2437      Store register content into object field by field_id. For a non-object
2438      variant the size of the actually stored value is determined by field_id,
2439      while other register bits are discarded.
2440      If field type size is less than 32, then the register content is truncated
2441      to storage size before storing.
2442    verification:
2443      - v1_type
2444      - v2_object
2445      - field_id_non_static
2446      - field_id_size
2447    properties:
2448      - field_id
2449    exceptions:
2450      - x_null
2451    pseudo: |
2452      if v2 == null then
2453        throw NullPointerException
2454      end
2455      field = resolve(field_id)
2456      if op == stobj and size(field) < 32 then
2457        v2.set(field, truncate(field, v1))
2458      else
2459        v2.set(field, v1)
2460      end
2461    instructions:
2462      - sig: stobj.v v1:in:b32, v2:in:ref, field_id
2463        acc: none
2464        format: [op_v1_4_v2_4_id_16]
2465        opcode_idx: [0x86]
2466      - sig: stobj.v.64 v1:in:b64, v2:in:ref, field_id
2467        acc: none
2468        format: [op_v1_4_v2_4_id_16]
2469        opcode_idx: [0x87]
2470      - sig: stobj.v.obj v1:in:ref, v2:in:ref, field_id
2471        acc: none
2472        format: [op_v1_4_v2_4_id_16]
2473        opcode_idx: [0x88]
2474
2475  - title: Get static field
2476    description: >
2477      Get static field value by field_id and put it into accumulator. For a
2478      non-object variant, the size of the field is determined by field_id, the
2479      most significant bits are sign- or unsigned-extended based on field type
2480      to fit accumulator size.
2481      If field size is less then 32, then the result is sign- or
2482      unsigned-extended to i32 depending on field type.
2483    verification:
2484      - field_id_static
2485      - field_id_size
2486    properties:
2487      - static_field_id
2488      - initialize_type
2489    exceptions:
2490      - x_init
2491    pseudo: |
2492      field, type = resolve(field_id)
2493      if not initialized(type)
2494        initialize(type)
2495      end
2496      if op == ldstatic and size(field) < 32 then
2497        acc = extendto32(get_static(field))
2498      else
2499        acc = get_static(field)
2500      end
2501    instructions:
2502      - sig: ldstatic field_id
2503        acc: out:b32
2504        format: [op_id_16]
2505        opcode_idx: [0x89]
2506      - sig: ldstatic.64 field_id
2507        acc: out:b64
2508        format: [op_id_16]
2509        opcode_idx: [0x8a]
2510      - sig: ldstatic.obj field_id
2511        acc: out:ref
2512        format: [op_id_16]
2513        opcode_idx: [0x8b]
2514
2515  - title: Store to static field
2516    description: >
2517      Store accumulator content into static field by field_id. For a non-object
2518      variant the size of the actually stored value is determined by field_id, other
2519      accumulator bits are discarded. If field type size is less than 32, then
2520      accumulator content is truncated to field size before storing.
2521    verification:
2522      - field_id_static
2523      - field_id_size
2524      - acc_type
2525    properties:
2526      - static_field_id
2527      - initialize_type
2528    exceptions:
2529      - x_init
2530    pseudo: |
2531      field, type = resolve(field_id)
2532      if not initialized(type)
2533        initialize(type)
2534      end
2535      if op == ststatic and size(field) < 32 then
2536        set_static(field, truncate(field, acc))
2537      else
2538        set_static(field, acc)
2539      end
2540    instructions:
2541      - sig: ststatic field_id
2542        acc: in:b32
2543        format: [op_id_16]
2544        opcode_idx: [0x8c]
2545      - sig: ststatic.64 field_id
2546        acc: in:b64
2547        format: [op_id_16]
2548        opcode_idx: [0x8d]
2549      - sig: ststatic.obj field_id
2550        acc: in:ref
2551        format: [op_id_16]
2552        opcode_idx: [0x8e]
2553
2554  - title: Return value from method
2555    description: >
2556      Return from the current method, i.e., restore the frame of method invoker
2557      and return control to the invoker. Return value must be in accumulator.
2558    verification:
2559      - acc_return_type
2560    exceptions:
2561      - x_none
2562    properties:
2563      - return
2564    pseudo: |
2565      return acc
2566    instructions:
2567      - sig: return
2568        acc: in:b32
2569        format: [op_none]
2570        opcode_idx: [0x8f]
2571      - sig: return.64
2572        acc: in:b64
2573        format: [op_none]
2574        opcode_idx: [0x90]
2575      - sig: return.obj
2576        acc: in:ref
2577        format: [op_none]
2578        opcode_idx: [0x91]
2579
2580  - title: Return from a void method
2581    description: >
2582      Return from the current method, i.e., restore the frame of method invoker
2583      and return control to the invoker. Caller must treat accumulator value as
2584      undefined, and cannot use it until accumulator in the caller frame is
2585      defined.
2586    verification:
2587      - none
2588    exceptions:
2589      - x_none
2590    properties:
2591      - return
2592    pseudo: |
2593      return
2594    instructions:
2595      - sig: return.void
2596        acc: none
2597        format: [op_none]
2598        opcode_idx: [0x92]
2599
2600  - title: Throw exception
2601    description: >
2602      Throw an exception located in register. The current method is searched
2603      for the first exception handler that matches the class of exception. If
2604      exception handler is found, then control is passed to the exception
2605      handler. If no exception handler is found, then the frame of invoker is
2606      restored. If such frame exists, then the exception is re-thrown.
2607      If no such frame exists, then the current VM thread exits.
2608    verification:
2609      - v1_throw_type
2610    exceptions:
2611      - x_null
2612      - x_throw
2613    pseudo: |
2614      if vs == null then
2615        throw NullPointerException
2616      end
2617      throw vs
2618    instructions:
2619      - sig: throw v:in:ref
2620        acc: none
2621        format: [op_v_8]
2622        opcode_idx: [0x93]
2623
2624  - title: Check cast
2625    description: >
2626      Resolve object type by specified id; if an object in accumulator can be
2627      cast to the resolved type, then the accumulator content remains unchanged.
2628      Otherwise, ClassCastException is thrown.
2629      Object of type O can be cast to type T if O is the same as T or is a
2630      subtype of T. For arrays, O can be cast to T if T is a root type in type
2631      hierarchy, or array elements of T and O are the same, or O is a subtype
2632      of a T array element.
2633      'null' object reference can be cast to every type.
2634    verification:
2635      - type_id_any_object
2636      - acc_obj_or_null
2637    exceptions:
2638      - x_cast
2639    properties:
2640      - type_id
2641    pseudo: |
2642      type = resolve(type_id)
2643      if acc != null and !has_type(acc, type) then
2644        throw ClassCastException
2645      end
2646    instructions:
2647      - sig: checkcast type_id
2648        acc: in:ref
2649        format: [op_id_16]
2650        opcode_idx: [0x94]
2651
2652  - title: Is instance
2653    description: >
2654      Resolve object type by specified id, and if an object in accumulator is
2655      an instance of the resolved type, then put 1 into accumulator. Otherwise,
2656      put 0.
2657      Object of type O is instance of type T if O is the same as T, or is a
2658      subtype of T. For arrays, T must be a root type in type hierarchy, or
2659      array elements of T and O are the same, or O is a subtype of a T
2660      array element.
2661      'null' object is not an instance of any class.
2662    verification:
2663      - type_id_any_object
2664      - acc_obj_or_null
2665    exceptions:
2666      - x_classdef
2667    properties:
2668      - type_id
2669    pseudo: |
2670      type = resolve(type_id)
2671      if acc == null or !has_type(acc, type) then
2672        acc = 0
2673      else
2674        acc = 1
2675      end
2676    instructions:
2677      - sig: isinstance type_id
2678        acc: inout:ref->i32
2679        format: [op_id_16]
2680        opcode_idx: [0x95]
2681
2682  - title: Static call
2683    description: >
2684      Call the indicated static method, i.e., create new frame, pass values of
2685      arguments, and continue the execution from the first instruction of a
2686      method.
2687      Callee must treat the accumulator value as undefined, and cannot use it
2688      until accumulator in the new frame is defined.
2689      Result (if any) is returned in accumulator (see 'Calling sequence'
2690      for more details).
2691      Method, its class, and the number of arguments is resolved by a given
2692      method_id in runtime constant-pool.
2693      Arguments are passed in source registers in the same order as in the
2694      method signature.
2695      Non-range instructions can be used to pass up to 4 arguments (unused
2696      register slot values are discarded, and corresponding registers are not
2697      passed to the callee).
2698      Range kind of instructions are to be used for methods with more arguments
2699      Such instructions take the required number of arguments starting from
2700      'vs' register.
2701    verification:
2702      - method_id_static
2703      - method_id_non_abstract
2704      - compatible_arguments
2705    properties:
2706      - static_method_id
2707      - call
2708      - initialize_type
2709      - short_long_range
2710    exceptions:
2711      - x_call
2712    pseudo: |
2713      if not initialized(type)
2714        initialize(type)
2715      end
2716      acc = call(method, args)
2717    instructions:
2718      - sig: call.short method_id, v1:in:top, v2:in:top
2719        acc: out:top
2720        format: [op_v1_4_v2_4_id_16]
2721        opcode_idx: [0x96]
2722      - sig: call method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top
2723        acc: out:top
2724        format: [op_v1_4_v2_4_v3_4_v4_4_id_16]
2725        opcode_idx: [0x97]
2726      - sig: call.range method_id, v:in:top
2727        acc: out:top
2728        format: [op_v_8_id_16]
2729        opcode_idx: [0x98]
2730
2731  - title: Static call with accumulator as input
2732    description: >
2733      Call the indicated static method, i.e., create a new frame, pass values
2734      of arguments, and continue the execution from the first instruction of a
2735      method.
2736      Callee must treat the accumulator value as undefined, and cannot use it
2737      until accumulator in the new frame is defined.
2738      Result (if any) is returned in accumulator (see 'Calling sequence' for
2739      more details).
2740      Method, its class, and the number of arguments is resolved by a given
2741      method_id in runtime constant-pool.
2742      Arguments are passed in source registers in the same order as in the
2743      method signature.
2744      Non-range instructions can be used to pass up to 4 arguments (unused
2745      register slot values are discarded, and corresponding registers are not
2746      passed to the callee).
2747      Immediate operand encodes a position starting from 0 on which accumulator
2748      is passed.
2749    verification:
2750      - method_id_static
2751      - method_id_non_abstract
2752      - compatible_arguments
2753    properties:
2754      - static_method_id
2755      - call
2756      - short_long_range
2757    exceptions:
2758      - x_call
2759    pseudo: |
2760      args = []
2761      for (i = 0; i < 4; ++i)
2762        if (i < imm) then
2763          args[i] = regs[i]
2764        else if (i == imm) then
2765          args[i] = acc
2766        else
2767          args[i] = regs[i - 1]
2768        end
2769      end
2770      method = resolve(method_id)
2771      acc = call(method, args)
2772    instructions:
2773      - sig: call.acc.short method_id, v:in:top, imm:u1
2774        acc: inout:top
2775        format: [op_v_4_imm_4_id_16]
2776        opcode_idx: [0x99]
2777      - sig: call.acc method_id, v1:in:top, v2:in:top, v3:in:top, imm:u2
2778        acc: inout:top
2779        format: [op_v1_4_v2_4_v3_4_imm_4_id_16]
2780        opcode_idx: [0x9a]
2781
2782  - title: Virtual calls
2783    description: >
2784      Call the indicated virtual method, i.e., create a new frame, pass values
2785      of arguments, and continue the execution from the first instruction of a
2786      method.
2787      Callee must treat the accumulator value as undefined, and cannot use it
2788      until accumulator in the new frame is defined.
2789      Result (if any) is returned in accumulator (see 'Calling sequence' for
2790      more details).
2791      Method, its class, and the number of arguments is resolved by a given
2792      method_id in runtime constant-pool based on object reference using
2793      language-specific semantics (currently only Java virtual methods are
2794      supported, further extensions are TBD).
2795      Object reference is passed in the first source register, arguments are
2796      passed starting from the second source register in the same order as in
2797      the method signature.
2798      Non-range instructions can be used to pass up to 4 arguments (including
2799      object reference).
2800      Unused register slot values are discarded, and corresponding registers
2801      are not passed to the callee).
2802      For methods with more arguments, range kinds of instruction are to be used.
2803      The instructions take the required number of arguments starting from
2804      'vs' register (including object reference).
2805    verification:
2806      - compatible_arguments
2807      - method_id_accessible
2808    exceptions:
2809      - x_null
2810      - x_abstract
2811      - x_call
2812    properties:
2813      - method_id
2814      - call
2815      - call_virt
2816      - short_long_range
2817    pseudo: |
2818      if args[0] == null then
2819        throw NullPointerException
2820      end
2821      method = resolve(method_id)
2822      if is_abstract(method) then
2823        throw AbstractMethodError
2824      end
2825      acc = call(method, args)
2826    instructions:
2827      - sig: call.virt.short method_id, v1:in:top, v2:in:top
2828        acc: out:top
2829        format: [op_v1_4_v2_4_id_16]
2830        opcode_idx: [0x9b]
2831      - sig: call.virt method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top
2832        acc: out:top
2833        format: [op_v1_4_v2_4_v3_4_v4_4_id_16]
2834        opcode_idx: [0x9c]
2835      - sig: call.virt.range method_id, v:in:top
2836        acc: out:top
2837        format: [op_v_8_id_16]
2838        opcode_idx: [0x9d]
2839
2840  - title: Virtual calls with accumulator as input
2841    description: >
2842      Call the indicated virtual method, i.e., create a new frame, pass values
2843      of arguments, and continue the execution from the first instruction of a
2844      method.
2845      Callee must treat the accumulator value as undefined, and cannot use it
2846      until accumulator in the new frame is defined.
2847      Result (if any) is returned in accumulator (see 'Calling sequence' for
2848      more details).
2849      Method, its class, and the number of arguments is resolved by a given
2850      method_id in runtime constant-pool based on object reference using
2851      language-specific semantics (currently only Java virtual methods are
2852      supported, further extensions are TBD).
2853      Object reference is passed in the first source register, arguments are
2854      passed starting from the second source register in the same order as
2855      in the method signature.
2856      Non-range instructions can be used to pass up to 4 arguments (including
2857      object reference). Unused register slot values are discarded, and
2858      corresponding registers are not passed to the callee).
2859      Immediate operand encodes a position starting from 0 on which accumulator
2860      is passed.
2861    verification:
2862      - compatible_arguments
2863      - method_id_accessible
2864    exceptions:
2865      - x_null
2866      - x_abstract
2867      - x_call
2868    properties:
2869      - method_id
2870      - call
2871      - call_virt
2872      - short_long_range
2873    pseudo: |
2874      args = []
2875      for (i = 0; i < 4; ++i)
2876        if (i < imm) then
2877          args[i] = regs[i]
2878        else if (i == imm) then
2879          args[i] = acc
2880        else
2881          args[i] = regs[i - 1]
2882        end
2883      end
2884      if args[0] == null then
2885        throw NullPointerException
2886      end
2887      method = resolve(method_id)
2888      if is_abstract(method) then
2889        throw AbstractMethodError
2890      end
2891      acc = call(method, args)
2892    instructions:
2893      - sig: call.virt.acc.short method_id, v:in:top, imm:u1
2894        acc: inout:top
2895        format: [op_v_4_imm_4_id_16]
2896        opcode_idx: [0x9e]
2897      - sig: call.virt.acc method_id, v1:in:top, v2:in:top, v3:in:top, imm:u2
2898        acc: inout:top
2899        format: [op_v1_4_v2_4_v3_4_imm_4_id_16]
2900        opcode_idx: [0x9f]
2901
2902  - title: Dynamic move register-to-register
2903    description: >
2904      Move 'any' values between registers
2905    verification:
2906      - valid_in_dynamic_context
2907    exceptions:
2908      - x_none
2909    properties:
2910      - dynamic
2911    pseudo: |
2912      vd = vs
2913    instructions:
2914      - sig: mov.dyn v1:out:any, v2:in:any
2915        acc: none
2916        format: [op_v1_8_v2_8, op_v1_16_v2_16]
2917        opcode_idx: [0xa0, 0xa1]
2918
2919  - title: Dynamic load accumulator from register
2920    description: >
2921      Move 'any' value from register to accumulator
2922    verification:
2923      - valid_in_dynamic_context
2924    exceptions:
2925      - x_none
2926    properties:
2927      - dynamic
2928    pseudo: |
2929      acc = v
2930    instructions:
2931      - sig: lda.dyn v:in:any
2932        acc: out:any
2933        format: [op_v_8]
2934        opcode_idx: [0xa2]
2935
2936  - title: Dynamic store accumulator
2937    description: >
2938      Move 'any' value from accumulator to register
2939    verification:
2940      - valid_in_dynamic_context
2941    exceptions:
2942      - x_none
2943    properties:
2944      - dynamic
2945    pseudo: |
2946      v = acc
2947    instructions:
2948      - sig: sta.dyn v:out:any
2949        acc: in:any
2950        format: [op_v_8]
2951        opcode_idx: [0xa3]
2952
2953  - title: Dynamic load accumulator from immediate
2954    description: >
2955      Move immediate as 'any' value to accumulator
2956    verification:
2957      - valid_in_dynamic_context
2958    exceptions:
2959      - x_none
2960    properties:
2961      - dynamic
2962    pseudo: |
2963      acc = imm
2964    instructions:
2965      - sig: ldai.dyn imm:i32
2966        acc: out:any
2967        format: [op_imm_32]
2968        opcode_idx: [0xa4]
2969      - sig: fldai.dyn imm:f64
2970        acc: out:any
2971        format: [op_imm_64]
2972        opcode_idx: [0xa5]
2973        properties: [float, dynamic]
2974