Skip to content

List of Majiro IL instructions

Robert Jordan edited this page May 11, 2021 · 12 revisions

List of Majiro IL instructions

Shorthand name is MjIL (Majiro Intermediate Language).

Important: As of 2021-05-11, breaking changes have been made to instruction names: bge.v, bgt.v, ble.v, blt.v (all comparison types were mislabeled). Additionally, since then, b_.case is now the primary name for these instructions, while b_.v remains only as an alias.

External links

Operand definitions

Operand Types
field <uint16 (flags), uint32 (hash), int16 (offs)>
method <uint32 (hash)>

Type codes

The postfix .r stands for real, which follows CIL instruction naming conventions.

Type Code Postfix
int 0 .i
float 1 .r
string 2 .s
int[] 3 .iarr
float[] 4 .rarr
string[] 5 .sarr

Opcode definitions

Operator and assignment opcodes (0x100~0x320) all follow a pattern for their code number. Each base operator code is a multiple of 8, and the supported type is a number (0~5) added to that value (i.e. 0x118 : add.i, 0x119 : add.r, 0x11A : add.s).

All remaining opcodes (0x800~0x850) serve various purposes, from stack management and branching, to more specific VN-related commands.

Opcode aliasing

All opcode names are chosen to best match conventions used by CIL instructions. However many opcodes have no counterpart, or have a hugely different scope (e.g. ld for all variables in MjIL / and ldloc, ldarg, ldfld, etc. in CIL).

MjIL text parsers should support the op.%03x alias for all opcodes (e.g. 0x845 : op.845).

The name nop.%03x is used for all nop -no operation- opcodes (e.g. 0x191 : nop.191). These opcodes must still be defined, as many may have an effect on the stack, or may originally have had a function. [citation needed]

All operators that only implement int types will not include the .i postfix in the name. There still must be an alias that includes the postfix (e.g. xor / xor.i). This rule extends to operators that implement other types that are nop's (e.g. notl / notl.i, and notl.r : aka nop.191).

Opcode definitions table

Opcode Instruction Description
0x100 mul.i Multiply integer values.
0x101 mul.r Multiply floating-point values. (accepts int)
0x108 div.i Divide two values to return an integer quotient.
0x109 div.r Divide two values to return a floating-point result. (accepts int)
0x110 rem Remainder when dividing one value by another. (can return negative results, signed modulus)
0x110 rem.i (alias for rem)
0x118 add.i Add two integer values, returning a new value.
0x119 add.r Add two floating-point values, returning a new value. (accepts int)
0x11A add.s Concatenate two string values, returning a new value.
0x120 sub.i Subtract integer value2 from integer value1, returning a new value.
0x121 sub.r Subtract floating-point value2 from value1, returning a new value. (allows integers)
0x128 shr Shift an integer right (shift in zero), return an integer.
0x128 shr.i (alias for shr)
0x130 shl Shift an integer left (shifting in zeros), return an integer.
0x130 shl.i (alias for shl)
0x138 cle.i Push 1 (of type int) if integer value1 lower or equals value2, else push 0.
0x139 cle.r Push 1 (of type int) if floating-point value1 lower or equals value2, else push 0. (accepts int)
0x13A cle.s Push 1 (of type int) if string value1 lower or equals value2, else push 0. (case insensitive)
0x140 clt.i Push 1 (of type int) if integer value1 lower than value2, else push 0.
0x141 clt.r Push 1 (of type int) if floating-point value1 lower than value2, else push 0.
0x142 clt.s Push 1 (of type int) if string value1 lower than value2, else push 0. (case insensitive)
0x148 cge.i Push 1 (of type int) if integer value1 greater or equals value2, else push 0.
0x149 cge.r Push 1 (of type int) if floating-point value1 greater or equals value2, else push 0. (accepts int)
0x14A cge.s Push 1 (of type int) if string value1 greater or equals value2, else push 0. (case insensitive)
0x150 cgt.i Push 1 (of type int) if integer value1 greater than value2, else push 0.
0x151 cgt.r Push 1 (of type int) if floating-point value1 greater than value2, else push 0. (accepts int)
0x152 cgt.s Push 1 (of type int) if string value1 greater than value2, else push 0. (case insensitive)
0x158 ceq.i Push 1 (of type int) if integer value1 equals value2, else push 0.
0x159 ceq.r Push 1 (of type int) if floating-point value1 equals value2, else push 0. (accepts int)
0x15A ceq.s Push 1 (of type int) if string value1 equals value2, else push 0. (case insensitive)
0x15B ceq.iarr Push 1 (of type int) if integer array1 equals array2, else push 0.
0x15C ceq.rarr Push 1 (of type int) if floating-point array1 equals array2, else push 0. (accepts int)
0x15D ceq.sarr Push 1 (of type int) if string array1 equals array2, else push 0. (case insensitive)
0x160 cne.i Push 1 (of type int) if integer value1 not equals value2, else push 0.
0x161 cne.r Push 1 (of type int) if floating-point value1 not equals value2, else push 0. (accepts int)
0x162 cne.s Push 1 (of type int) if string value1 not equals value2, else push 0. (case insensitive)
0x163 cne.iarr Push 1 (of type int) if integer array1 not equals array2, else push 0.
0x164 cne.rarr Push 1 (of type int) if floating-point array1 not equals array2, else push 0. (accepts int)
0x165 cne.sarr Push 1 (of type int) if string array1 not equals array2, else push 0. (case insensitive)
0x168 xor Bitwise XOR of integer values, returns an integer.
0x168 xor.i (alias for xor)
0x170 andl Push 1 (of type int) if both of two integer values are non-zero, else push 0.
0x170 andl.i (alias for andl)
0x178 orl Push 1 (of type int) if either of two integer values are non-zero, else push 0.
0x178 orl.i (alias for orl)
0x180 and Bitwise AND of two integral values, returns an integral value.
0x180 and.i (alias for and)
0x188 or Bitwise OR of two integer values, returns an integer.
0x188 or.i (alias for or)
0x190 notl Push 1 (of type int) if integer value is zero, else push 0 (comparison not !).
0x190 notl.i (alias for notl)
0x191 nop.191 (this is a nop) Push 1 (of type int) if floating-point value is zero, else push 0.
0x191 notl.r (this is a nop) Push 1 (of type int) if floating-point value is zero, else push 0.
0x198 not Bitwise complement (logical not ~).
0x198 not.i (alias for not)
0x1A0 neg.i Negate integer value.
0x1A1 neg.r Negate floating-point value.
0x1A8 nop.1a8 (this is a nop) Positive integer value.
0x1A8 pos.i (alias for nop.1a8) Positive integer value.
0x1A9 nop.1a9 (this is a nop) Positive floating-point value.
0x1A9 pos.r (alias for nop.1a9) Positive floating-point value.
0x1B0 st.i <field> Store value of type int into variable.
0x1B1 st.f <field> Store value of type float into variable.
0x1B2 st.s <field> Store value of type string into variable.
0x1B3 st.iarr <field> Store value of type int[] into variable.
0x1B4 st.rarr <field> Store value of type float[] into variable.
0x1B5 st.sarr <field> Store value of type string[] into variable.
0x1B8 st.mul.i <field> Compound multiply, then store value of type int into variable.
0x1B9 st.mul.r <field> Compound multiply, then store value of type float into variable. (accepts int)
0x1C0 st.div.i <field> Compound divide, then store value of type int into variable.
0x1C1 st.div.r <field> Compound divide, then store value of type float into variable. (accepts int)
0x1C8 st.rem <field> Compound remainder, then store value of type int into variable.
0x1C8 st.rem.i <field> (alias for st.rem)
0x1D0 st.add.i <field> Compound add, then store value of type int into variable.
0x1D1 st.add.r <field> Compound add, then store value of type float into variable. (accepts int)
0x1D2 st.add.s <field> Compound concatenate, then store value of type string into variable.
0x1D8 st.sub.i <field> Compound subtract, then store value of type int into variable.
0x1D9 st.sub.r <field> Compound subtract, then store value of type float into variable. (accepts int)
0x1E0 st.shl <field> Compound shift left, then store value of type int into variable.
0x1E0 st.shl.i <field> (alias for st.shl)
0x1E8 st.shr <field> Compound shift right, then store value of type int into variable.
0x1E8 st.shr.i <field> (alias for st.shr)
0x1F0 st.and <field> Compound bitwise AND, then store value of type int into variable.
0x1F0 st.and.i <field> (alias for st.and)
0x1F8 st.xor <field> Compound bitwise XOR, then store value of type int into variable.
0x1F8 st.xor.i <field> (alias for st.xor)
0x200 st.or <field> Compound bitwise OR, then store value of type int into variable.
0x200 st.or.i <field> (alias for st.or)
0x210 stp.i <field> Pop a value of type int into variable.
0x211 stp.f <field> Pop a value of type float into variable.
0x212 stp.s <field> Pop a value of type string into variable.
0x213 stp.iarr <field> Pop a value of type int[] into variable.
0x214 stp.rarr <field> Pop a value of type float[] into variable.
0x215 stp.sarr <field> Pop a value of type string[] into variable.
0x218 stp.mul.i <field> Compound multiply, then pop value of type int into variable.
0x219 stp.mul.r <field> Compound multiply, then pop value of type float into variable. (accepts int)
0x220 stp.div.i <field> Compound divide, then pop value of type int into variable.
0x221 stp.div.r <field> Compound divide, then pop value of type float into variable. (accepts int)
0x228 stp.rem <field> Compound remainder, then pop value of type int into variable.
0x228 stp.rem.i <field> (alias for stp.rem)
0x230 stp.add.i <field> Compound add, then pop value of type int into variable.
0x231 stp.add.r <field> Compound add, then pop value of type float into variable. (accepts int)
0x232 stp.add.s <field> Compound concatenate, then pop value of type string into variable.
0x238 stp.sub.i <field> Compound subtract, then pop value of type int into variable.
0x239 stp.sub.r <field> Compound subtract, then pop value of type float into variable. (accepts int)
0x240 stp.shl <field> Compound shift left, then pop value of type int into variable.
0x240 stp.shl.i <field> (alias for stp.shl)
0x248 stp.shr <field> Compound shift right, then pop value of type int into variable.
0x248 stp.shr.i <field> (alias for stp.shr)
0x250 stp.and <field> Compound bitwise AND, then pop value of type int into variable.
0x250 stp.and.i <field> (alias for stp.and)
0x258 stp.xor <field> Compound bitwise XOR, then pop value of type int into variable.
0x258 stp.xor.i <field> (alias for stp.xor)
0x260 stp.or <field> Compound bitwise OR, then pop value of type int into variable.
0x260 stp.or.i <field> (alias for stp.or)
0x270 stelem.i <field> Store value of type int into array element at indices.
0x271 stelem.f <field> Store value of type float into array element at indices.
0x272 stelem.s <field> Store value of type string into array element at indices.
0x278 stelem.mul.i <field> Compound multiply, then store value of type int into array element at indices.
0x279 stelem.mul.r <field> Compound multiply, then store value of type float into array element at indices. (accepts int)
0x280 stelem.div.i <field> Compound divide, then store value of type int into array element at indices.
0x281 stelem.div.r <field> Compound divide, then store value of type float into array element at indices. (accepts int)
0x288 stelem.rem <field> Compound remainder, then store value of type int into array element at indices.
0x288 stelem.rem.i <field> (alias for stelem.rem)
0x290 stelem.add.i <field> Compound add, then store value of type int into array element at indices.
0x291 stelem.add.r <field> Compound add, then store value of type float into array element at indices. (accepts int)
0x292 stelem.add.s <field> Compound concatenate, then store value of type string into array element at indices.
0x298 stelem.sub.i <field> Compound subtract, then store value of type int into array element at indices.
0x299 stelem.sub.r <field> Compound subtract, then store value of type float into array element at indices. (accepts int)
0x2A0 stelem.shl <field> Compound shift left, then store value of type int into array element at indices.
0x2A0 stelem.shl.i <field> (alias for stelem.shl)
0x2A8 stelem.shr <field> Compound shift right, then store value of type int into array element at indices.
0x2A8 stelem.shr.i <field> (alias for stelem.shr)
0x2B0 stelem.and <field> Compound bitwise AND, then store value of type int into array element at indices.
0x2B0 stelem.and.i <field> (alias for stelem.and)
0x2B8 stelem.xor <field> Compound bitwise XOR, then store value of type int into array element at indices.
0x2B8 stelem.xor.i <field> (alias for stelem.xor)
0x2C0 stelem.or <field> Compound bitwise OR, then store value of type int into array element at indices.
0x2C0 stelem.or.i <field> (alias for stelem.or)
0x2D0 stelemp.i <field> Pop a value of type int into array element at indices.
0x2D1 stelemp.f <field> Pop a value of type float into array element at indices.
0x2D2 stelemp.s <field> Pop a value of type string into array element at indices.
0x2D8 stelemp.mul.i <field> Compound multiply, then pop value of type int into array element at indices.
0x2D9 stelemp.mul.r <field> Compound multiply, then pop value of type float into array element at indices. (accepts int)
0x2E0 stelemp.div.i <field> Compound divide, then pop value of type int into array element at indices.
0x2E1 stelemp.div.r <field> Compound divide, then pop value of type float into array element at indices. (accepts int)
0x2E8 stelemp.rem <field> Compound remainder, then pop value of type int into array element at indices.
0x2E8 stelemp.rem.i <field> (alias for stelemp.rem)
0x2F0 stelemp.add.i <field> Compound add, then pop value of type int into array element at indices.
0x2F1 stelemp.add.r <field> Compound add, then pop value of type float into array element at indices. (accepts int)
0x2F2 stelemp.add.s <field> Compound concatenate, then pop value of type string into array element at indices.
0x2F8 stelemp.sub.i <field> Compound subtract, then pop value of type int into array element at indices.
0x2F9 stelemp.sub.r <field> Compound subtract, then pop value of type float into array element at indices. (accepts int)
0x300 stelemp.shl <field> Compound shift left, then pop value of type int into array element at indices.
0x300 stelemp.shl.i <field> (alias for stelemp.shl)
0x308 stelemp.shr <field> Compound shift right, then pop value of type int into array element at indices.
0x308 stelemp.shr.i <field> (alias for stelemp.shr)
0x310 stelemp.and <field> Compound bitwise AND, then pop value of type int into array element at indices.
0x310 stelemp.and.i <field> (alias for stelemp.and)
0x318 stelemp.xor <field> Compound bitwise XOR, then pop value of type int into array element at indices.
0x318 stelemp.xor.i <field> (alias for stelemp.xor)
0x320 stelemp.or <field> Compound bitwise OR, then pop value of type int into array element at indices.
0x320 stelemp.or.i <field> (alias for stelemp.or)
0x800 ldc.i <int32 (num)> Push num of type int onto the stack.
0x801 ldstr <string> Push a string object for the literal string onto the stack.
0x802 ld <field> Push the value of the variable on the stack.
0x803 ldc.r <float32 (num)> Push num of type float onto the stack.
0x80F call <method, int32 (0), uint16 (argC)> Call user-defined function with argC arguments from the stack.
0x810 callp <method, int32 (0), uint16 (argC)> Call (void return) user-defined function with argC arguments from the stack.
0x829 alloca <uint16 (N), uint8 (t1..tN)> Allocate n local variables of type t.
0x82B ret Return from method, with value on the stack (pops depending on call type).
0x82C br <int32 (target)> Branch to target (unconditional).
0x82D brtrue <int32 (target)> Branch to target if value is non-zero (true).
0x82E brfalse <int32 (target)> Branch to target if value is zero (false).
0x82F pop Pop value from the stack.
0x830 br.case <int32 (target)> Branch to target and store value as case condition in thread-local var $11F91FD3 %Op_internalCase~@MAJIRO_INTER.
Start of switch statement.
0x830 br.v <int32 (target)> (old alias for br.case)
0x831 bne.case <int32 (target)> Branch to target if br.case condition not equals value.
0x831 bne.v <int32 (target)> (old alias for bne.case)
0x832 bge.case <int32 (target)> Branch to target if br.case condition greater or equals value.
0x832 bge.v <int32 (target)> (old alias for bge.case)
0x833 ble.case <int32 (target)> Branch to target if br.case condition lower or equals value.
0x833 ble.v <int32 (target)> (old alias for ble.case)
0x834 syscall <method, uint16 (argC)> Call system function with argC arguments from the stack.
0x835 syscallp <method, uint16 (argC)> Call (void return) system function with argC arguments from the stack.
0x836 argcheck <uint16 (N), uint8 (t1..tN)> Confirms n arguments on stack match t types (func sig check).
0x837 ldelem <field> Load the array element at indices onto the top of the stack.
0x838 blt.case <int32 (target)> Branch to target if br.case condition lower than value.
0x838 blt.v <int32 (target)> (old alias for blt.case)
0x839 bgt.case <int32 (target)> Branch to target if br.case condition greater than value.
0x839 bgt.v <int32 (target)> (old alias for bgt.case)
0x83A line <uint16 (num)> Inform a debugger of the script source line number.
Used to mark read lines in scenarios.
0x83B bsel.1 <int32 (target)> (unk) Set branch target AIP:1 (lclick).
0x83C bsel.3 <int32 (target)> (unk) Set branch target AIP:3 (mclick).
0x83D bsel.2 <int32 (target)> (unk) Set branch target AIP:2 (rclick).
0x83E conv.i Convert float to int, pushing int on stack.
0x83F conv.r Convert int to float, pushing float on stack.
0x840 text <string> (VN) Append to text/message buffer.
0x841 proc (unk, VN) Process text buffer created by text.
Listed as marker in mjdisasm.ml, and as ProcessString in MjoParser.py.
In asm, opcode has int param. 2 passed in bytecode, 8 passed in syscall $wait ($59180bbb).
0x842 ctrl <string> (VN) Process escape sequences based on the defined string character.
"p" : pause, "w" : cls
0x843 bsel.x <int32 (target)> (unk) Set branch targets AIP:1, AIP:2, AIP:3 (lclick, rclick, mclick).
0x844 bsel.clr (unk) Clear branch targets set by bsel.# instructions. MjoParser.py : ClearJumpTbl.
0x845 bsel.4 <int32 (target)> (unk) Set branch target AIP:4. MjoParser.py : SetJmpAddr3.
0x846 bsel.jmp.4 (unk) Jump to branch target AIP:4 (set by bsel.4, op.845).
0x847 bsel.5 <int32 (target)> Set branch target AIP:5 (destructor). MjoParser.py : SetJmpAddr4.
0x850 switch <uint16 (N), int32 (t1..tN)> Jump to one of n targets t.
(Note: target offsets are relative to the end of operand, not end of instruction)