Home/Docs/MVIS Opcodes

MVIS — Minimum Viable Instruction Set

The Minimum Viable Instruction Set (MVIS) is the core of the UA language. These 37 instructions are fully portable — they work identically on every supported architecture. The compiler translates each MVIS opcode into the equivalent native machine instructions for the target CPU.

MVIS Doctrine: Whether targeting a 64-bit desktop processor, an ARM mobile chip, or a tiny 8-bit 8051 microcontroller, the core logic remains identical. The compiler handles the architectural polyfills behind the scenes, keeping the language pure and unified.


Table of Contents

  1. Instruction Summary
  2. Data Movement
  3. Arithmetic
  4. Bitwise Logic
  5. Shift Operations
  6. Comparison
  7. Control Flow
  8. Stack Operations
  9. System & Control
  10. Variables & Memory
  11. Operand Shape Reference

Instruction Summary

#MnemonicCategoryOperandsDescription
1MOVData MovementRd, RsCopy register to register
2LDIData MovementRd, #immLoad immediate value into register
3LOADData MovementRd, RsLoad word from memory address in Rs
4STOREData MovementRs, RdStore word to memory address in Rd
5LDSData MovementRd, "str"Load address of string literal
6LOADBData MovementRd, RsLoad byte from memory, zero-extend
7STOREBData MovementRs, RdStore low byte to memory
8ADDArithmeticRd, Rs/immRd = Rd + Rs or Rd + imm
9SUBArithmeticRd, Rs/immRd = Rd - Rs or Rd - imm
10MULArithmeticRd, Rs/immRd = Rd * Rs or Rd * imm
11DIVArithmeticRd, Rs/immRd = Rd / Rs or Rd / imm
12INCArithmeticRdRd = Rd + 1
13DECArithmeticRdRd = Rd - 1
14ANDBitwiseRd, Rs/immRd = Rd & Rs or Rd & imm
15ORBitwiseRd, Rs/immRd = Rd | Rs or Rd | imm
16XORBitwiseRd, Rs/immRd = Rd ^ Rs or Rd ^ imm
17NOTBitwiseRdRd = ~Rd
18SHLShiftRd, Rs/immShift Rd left by Rs/imm bits
19SHRShiftRd, Rs/immShift Rd right by Rs/imm bits
20CMPComparisonRa, Rb/immCompare (sets flags for jumps)
21JMPControl FlowlabelUnconditional jump
22JZControl FlowlabelJump if equal (zero flag)
23JNZControl FlowlabelJump if not equal
24JLControl FlowlabelJump if less (signed)
25JGControl FlowlabelJump if greater (signed)
26CALLControl FlowlabelCall subroutine
27RETControl Flow(none)Return from subroutine
28PUSHStackRsPush register onto stack
29POPStackRdPop stack into register
30INTSystem#immSoftware interrupt
31SYSSystem(none)OS system call
32NOPSystem(none)No operation
33HLTSystem(none)Halt execution
34VARVariablesname [, imm]Declare named variable
35SETVariablesname, Rs/immStore to variable
36GETVariablesRd, nameLoad from variable
37BUFFERMemoryname, sizeAllocate byte buffer

Data Movement

MOV — Register Copy

MOV  Rd, Rs

Copies the value of register Rs into register Rd. The original value in Rs is unchanged.

FieldValue
Operands2 registers
Flags affectedNone
ArchitecturesAll
    LDI  R0, 42
    MOV  R1, R0     ; R1 = 42, R0 still = 42

Backend translations:

ArchitectureNative Instruction
x86-64MOV r64, r64 (REX.W 89 ModRM)
x86-32MOV r32, r32 (89 ModRM)
ARMMOV Rd, Rs (data processing)
ARM64MOV Xd, Xn (ORR Xd, XZR, Xn)
RISC-VMV rd, rs (ADDI rd, rs, 0)
8051MOV A, Rs; MOV Rd, A (via accumulator)

LDI — Load Immediate

LDI  Rd, #imm

Loads a constant numeric value into register Rd.

FieldValue
Operands1 register, 1 immediate
Flags affectedNone
ArchitecturesAll
    LDI  R0, 42          ; decimal
    LDI  R1, 0xFF        ; hexadecimal
    LDI  R2, 0b1010      ; binary
    LDI  R3, -1           ; negative

Immediate ranges:

ArchitectureRangeNotes
x86-64±2 billion (32-bit, sign-extended to 64)MOV r64, imm32
x86-32±2 billion (32-bit native)MOV r32, imm32
ARMFull 32-bitMOVW (+ MOVT if > 16 bits)
ARM64Full 32-bitMOVZ (+ MOVK if > 16 bits)
RISC-VFull 32-bitLUI + ADDI
80510–255 (8-bit)MOV Rn, #imm8

LOAD — Memory Read

LOAD  Rd, Rs

Reads a word from the memory address stored in Rs and places it in Rd.

FieldValue
Operands2 registers
Flags affectedNone
ArchitecturesAll
    LOAD  R1, R0     ; R1 = memory[R0]

8051 restriction: The pointer register (Rs) must be R0 or R1 due to indirect addressing limitations (@R0/@R1 only).


STORE — Memory Write

STORE  Rs, Rd

Writes the value of Rs to the memory address stored in Rd.

FieldValue
Operands2 registers
Flags affectedNone
ArchitecturesAll
    STORE  R1, R0    ; memory[R0] = R1

8051 restriction: Same as LOAD — the destination address register must be R0 or R1.


LDS — Load String Address

LDS  Rd, "string literal"

Loads the memory address of a null-terminated string literal into Rd. The string data is stored in a string table appended to the output binary.

FieldValue
Operands1 register, 1 string literal
Flags affectedNone
ArchitecturesAll
    LDS  R0, "Hello, World!\n"   ; R0 = pointer to "Hello, World!\n"

Supported escape sequences: \n, \t, \r, \0, \\, \"

Duplicate string literals are automatically de-duplicated — identical strings share storage.


LOADB — Load Byte

LOADB  Rd, Rs

Reads a single byte from the address in Rs, zero-extends it to the register width, and stores it in Rd. Essential for traversing strings character by character.

FieldValue
Operands2 registers
Flags affectedNone
ArchitecturesAll
    LOADB  R1, R0    ; R1 = zero_extend(byte at address R0)

Backend translations:

ArchitectureNative Instruction
x86-64MOVZX r64, byte [r64]
x86-32MOVZX r32, byte [r32]
ARMLDRB Rd, [Rs]
ARM64LDRB Wd, [Xn]
RISC-VLBU rd, 0(rs)
8051MOV A, @Ri (Rs must be R0 or R1)

STOREB — Store Byte

STOREB  Rs, Rd

Writes the low byte of Rs to the memory address in Rd.

FieldValue
Operands2 registers
Flags affectedNone
ArchitecturesAll
    STOREB  R1, R0   ; byte at address R0 = low byte of R1

Arithmetic

ADD — Addition

ADD  Rd, Rs       ; Rd = Rd + Rs
ADD  Rd, #imm     ; Rd = Rd + imm
FieldValue
Operands1 register + 1 register or immediate
Flags affectedZero, carry, overflow
ArchitecturesAll
    LDI  R0, 10
    ADD  R0, 5       ; R0 = 15
    ADD  R0, R1      ; R0 = R0 + R1

SUB — Subtraction

SUB  Rd, Rs       ; Rd = Rd - Rs
SUB  Rd, #imm     ; Rd = Rd - imm
FieldValue
Operands1 register + 1 register or immediate
Flags affectedZero, carry, overflow
ArchitecturesAll
    LDI  R0, 20
    SUB  R0, 8       ; R0 = 12

MUL — Multiplication

MUL  Rd, Rs       ; Rd = Rd * Rs
MUL  Rd, #imm     ; Rd = Rd * imm
FieldValue
Operands1 register + 1 register or immediate
Flags affectedVaries by architecture
ArchitecturesAll
    LDI  R0, 6
    MUL  R0, 7       ; R0 = 42

8051 Note: Uses MUL AB — result limited to 16 bits (high byte in B, low byte in A).


DIV — Division

DIV  Rd, Rs       ; Rd = Rd / Rs
DIV  Rd, #imm     ; Rd = Rd / imm
FieldValue
Operands1 register + 1 register or immediate
Flags affectedVaries by architecture
ArchitecturesAll
    LDI  R0, 42
    DIV  R0, 6       ; R0 = 7

x86 Note: Uses signed division (IDIV). The backend saves/restores RDX (clobbered by IDIV).

8051 Note: Uses DIV AB — 8-bit unsigned division.


INC — Increment

INC  Rd           ; Rd = Rd + 1
FieldValue
Operands1 register
Flags affectedZero, overflow
ArchitecturesAll

DEC — Decrement

DEC  Rd           ; Rd = Rd - 1
FieldValue
Operands1 register
Flags affectedZero, overflow
ArchitecturesAll

Bitwise Logic

AND — Bitwise AND

AND  Rd, Rs       ; Rd = Rd & Rs
AND  Rd, #imm     ; Rd = Rd & imm

Commonly used for masking bits:

    LDI  R0, 0xFF
    AND  R0, 0x0F    ; R0 = 0x0F (keep low nibble only)

OR — Bitwise OR

OR  Rd, Rs        ; Rd = Rd | Rs
OR  Rd, #imm      ; Rd = Rd | imm

Commonly used for setting bits:

    OR   R0, 0x80    ; set bit 7

XOR — Bitwise XOR

XOR  Rd, Rs       ; Rd = Rd ^ Rs
XOR  Rd, #imm     ; Rd = Rd ^ imm

Commonly used for toggling bits or clearing a register:

    XOR  R0, R0      ; R0 = 0 (common zeroing idiom)

NOT — Bitwise Complement

NOT  Rd           ; Rd = ~Rd

Flips all bits in Rd.


Shift Operations

SHL — Shift Left

SHL  Rd, Rs       ; Rd = Rd << Rs
SHL  Rd, #imm     ; Rd = Rd << imm

Shifts Rd left by the specified number of bits. Vacated bits are filled with zeros. Equivalent to multiplying by powers of 2.

    LDI  R0, 1
    SHL  R0, 4       ; R0 = 16  (1 << 4)

8051 Note: Implemented using rotate instructions (RL A). Bits wrap around instead of being discarded.


SHR — Shift Right

SHR  Rd, Rs       ; Rd = Rd >> Rs
SHR  Rd, #imm     ; Rd = Rd >> imm

Shifts Rd right by the specified number of bits. This is a logical shift (zero-fill).

    LDI  R0, 16
    SHR  R0, 2       ; R0 = 4  (16 >> 2)

Comparison

CMP — Compare

CMP  Ra, Rb       ; compare Ra with Rb
CMP  Ra, #imm     ; compare Ra with immediate

Performs a subtraction (Ra - Rb) without storing the result. Only the CPU flags are updated. Use conditional jumps immediately after CMP:

    CMP  R0, R1
    JZ   equal       ; jump if R0 == R1
    JNZ  not_equal   ; jump if R0 != R1
    JL   less        ; jump if R0 < R1 (signed)
    JG   greater     ; jump if R0 > R1 (signed)

8051 Note: Register comparison uses CLR C; SUBB A, Rn. Immediate comparison uses CJNE A, #imm, $+3.


Control Flow

JMP — Unconditional Jump

JMP  label

Jumps to the specified label unconditionally. Forward references are supported.


JZ — Jump if Zero

JZ  label

Jumps to label if the zero flag is set (typically after CMP Ra, Rb where Ra == Rb).


JNZ — Jump if Not Zero

JNZ  label

Jumps to label if the zero flag is clear (Ra != Rb after CMP).


JL — Jump if Less

JL  label

Jumps to label if the previous comparison showed Ra < Rb (signed).

ArchitectureNative Encoding
x86-64/32JL rel32 (0F 8C)
ARMBLT (condition 0xB)
ARM64B.LT (condition 0xB)
RISC-VBLT t0, x0, offset
8051JC rel8 (carry = less-than after SUBB)

JG — Jump if Greater

JG  label

Jumps to label if the previous comparison showed Ra > Rb (signed).

8051 Note: Implemented as a 6-byte polyfill: JC $+4; JZ $+2; SJMP target (skip if less-or-equal, then jump).


CALL — Call Subroutine

CALL  label

Pushes the return address onto the stack (or link register on ARM/RISC-V) and jumps to the label. Use RET to return.


RET — Return

RET

Returns from a subroutine by popping the return address and jumping to it.

ArchitectureNative Instruction
x86-64/32RET (0xC3)
ARMBX LR
ARM64RET (BR X30)
RISC-VJALR x0, ra, 0
8051RET (0x22)

Stack Operations

PUSH — Push Register

PUSH  Rs

Pushes the value of Rs onto the stack. The stack pointer is decremented.

    PUSH R0          ; save R0

POP — Pop Register

POP  Rd

Pops the top value from the stack into Rd. The stack pointer is incremented.

    POP  R0          ; restore R0

Important: Stack operations are LIFO — pop in the reverse order of push.


System & Control

INT — Software Interrupt

INT  #imm

Triggers a software interrupt with the given vector number.

ArchitectureNative Instruction
x86-64/32INT n (0xCD, n)
ARMSVC #n
ARM64SVC #n
RISC-VECALL
8051LCALL (n*8)+3 (interrupt vector polyfill)

SYS — System Call

SYS

Invokes the operating system's system call mechanism. Register conventions vary by architecture and OS — refer to the standard library sources for details.

Architecture + SystemNative Instruction
x86-64 LinuxSYSCALL (0F 05)
x86-64 Win32CALL write_dispatcher
x86-32 LinuxINT 0x80 (CD 80)
ARM LinuxSVC #0
ARM64SVC #0
RISC-VECALL
8051Not supported (no OS)

NOP — No Operation

NOP

Does nothing. Useful for alignment or as a placeholder during development.


HLT — Halt

HLT

Stops program execution.

ArchitectureNative Instruction
x86-64/32RET (returns to OS/JIT runner)
ARMBX LR
ARM64RET
RISC-VJALR x0, ra, 0
8051SJMP $ (infinite self-loop)

Variables & Memory

VAR — Declare Variable

VAR  name              ; declare with default value 0
VAR  name, #imm        ; declare with initial value

Declares a named storage location. Variables persist across function calls and are accessible from anywhere.

    VAR  counter, 0
    VAR  result
ArchitectureStorageSize
x86-64Data section8 bytes
x86-32Data section4 bytes
ARM/ARM64Data section4/8 bytes
RISC-VData section8 bytes
8051Internal RAM1 byte

SET — Store to Variable

SET  name, Rs         ; variable = register value
SET  name, #imm       ; variable = immediate value

GET — Load from Variable

GET  Rd, name         ; register = variable value

BUFFER — Allocate Byte Buffer

BUFFER  name, size

Allocates a contiguous block of zero-initialized bytes. Access the buffer's base address with GET, then use LOADB/STOREB for byte-level access.

    BUFFER  data, 64         ; allocate 64 bytes
    GET     R0, data         ; R0 = base address
    LDI     R1, 0x41         ; 'A'
    STOREB  R1, R0           ; data[0] = 'A'

Operand Shape Reference

Every instruction has a fixed operand shape enforced at compile time:

ShapeMeaningExample Instructions
(none)No operandsNOP, HLT, RET, SYS
regOne registerNOT, INC, DEC, PUSH, POP
reg, regTwo registersMOV, LOAD, STORE, LOADB, STOREB
reg, reg/immRegister + register or immediateADD, SUB, MUL, DIV, AND, OR, XOR, SHL, SHR, CMP
reg, immRegister + immediateLDI
reg, stringRegister + string literalLDS
labelLabel referenceJMP, JZ, JNZ, JL, JG, CALL
immImmediate onlyINT
name [, imm]Variable name (optional init)VAR
name, reg/immVariable name + register/immediateSET
reg, nameRegister + variable nameGET
name, sizeBuffer name + size immediateBUFFER

Incorrect operand shapes produce a compile-time error:

  parser: line 12: shape mismatch for ADD — expected register, got label