RSM offers 30 general-purpose 64-bit integer registers and 30 64-bit floating-point registers. Instructions are 32 bits wide, fixed size. PC and jump- & branch destinations are expressed in #instructions rather than bytes.
Most instructions accept register number or immediate value as their last argument. See Instruction Encoding for more details.
| Name | Inputs | Output | Semantics | 
|---|---|---|---|
| copy | ABu | reg | RA = Bu -- aka "move" | 
| copyv | ABv | reg | RA = instr[...]; PC+=Bu | 
| load | ABCs | reg | RA = mem[RB + Cs : 8] | 
| load4u | ABCs | reg | RA = mem[RB + Cs : 4] -- zero-extend i32 to i64 | 
| load4s | ABCs | reg | RA = mem[RB + Cs : 4] -- sign-extend i32 to i64 | 
| load2u | ABCs | reg | RA = mem[RB + Cs : 2] -- zero-extend i16 to i64 | 
| load2s | ABCs | reg | RA = mem[RB + Cs : 2] -- sign-extend i16 to i64 | 
| load1u | ABCs | reg | RA = mem[RB + Cs : 1] -- zero-extend i8 to i64 | 
| load1s | ABCs | reg | RA = mem[RB + Cs : 1] -- sign-extend i8 to i64 | 
| store | ABCs | mem | mem[RB + Cs : 8] = RA | 
| store4 | ABCs | mem | mem[RB + Cs : 4] = RA -- wrap i64 to i32 | 
| store2 | ABCs | mem | mem[RB + Cs : 2] = RA -- wrap i64 to i16 | 
| store1 | ABCs | mem | mem[RB + Cs : 1] = RA -- wrap i64 to i8 | 
| add | ABCu | reg | RA = RB + Cu -- wrap on overflow | 
| sub | ABCu | reg | RA = RB - Cu -- wrap on overflow | 
| mul | ABCu | reg | RA = RB * Cu -- wrap on overflow | 
| adds | ABCs | reg | RA = RB + Cs -- panic on overflow | 
| subs | ABCs | reg | RA = RB - Cs -- panic on overflow | 
| muls | ABCs | reg | RA = RB * Cs -- panic on overflow | 
| div | ABCu | reg | RA = RB / Cu | 
| mod | ABCu | reg | RA = RB % Cu | 
| and | ABCu | reg | RA = RB & Cu | 
| or | ABCu | reg | RA = RB | Cu | 
| xor | ABCu | reg | RA = RB ^ Cu | 
| shl | ABCu | reg | RA = RB << Cu | 
| shrs | ABCu | reg | RA = RB >> Cu -- sign-replicating (arithmetic) | 
| shru | ABCu | reg | RA = RB >> Cu -- zero-replicating (logical) | 
| binv | ABu | reg | RA = ~Bu -- bitwise complement, invert bits | 
| not | ABu | reg | RA = !Bu -- boolean negation | 
| eq | ABCu | reg | RA = RB == Cu | 
| neq | ABCu | reg | RA = RB != Cu | 
| ltu | ABCu | reg | RA = RB < Cu | 
| lts | ABCs | reg | RA = RB < Cs | 
| lteu | ABCu | reg | RA = RB <= Cu | 
| ltes | ABCs | reg | RA = RB <= Cs | 
| gtu | ABCu | reg | RA = RB > Cu | 
| gts | ABCs | reg | RA = RB > Cs | 
| gteu | ABCu | reg | RA = RB >= Cu | 
| gtes | ABCs | reg | RA = RB >= Cs | 
| if | ABs | – | if RA!=0 PC += Bs | 
| ifz | ABs | – | if RA==0 PC += Bs | 
| call | Au | – | R0...R7 = push(PC); PC=Au | 
| jump | Au | – | PC = Au | 
| ret | _ | – | PC = pop() | 
| tspawn | Au | – | R0 = spawn_task(pc=Au, args=R0...R7) | 
| syscall | Au | – | R0...R7 = syscall(code=Au, args=R0...R18) | 
| write | ABCDs | reg | RA = write dstaddr=RB size=RC fd=Ds | 
| read | ABCDu | reg | RA = read srcaddr=RB size=RC fd=Du | 
| mcopy | ABCu | mem | mem[RA:Cu] = mem[RB:Cu] | 
| mcmp | ABCDu | reg | RA = mem[RB:Du] <> mem[RC:Du] | 
| stkmem | As | – | SP = maybe_split_or_join_stack(); SP += As | 
Instructions are fixed-size, 32 bits wide, little endian.
PC and jump- & branch destinations are expressed in #instructions rather than bytes.
There is room for 256 operations and 32+32 (int+fp) registers (8 bit OP, 5 bit reg)
Most instructions accept reg or immediate (i bit is set) as last argument.
      ┌───────────────┬─────────┬─────────┬─────────┬─┬───────────────┐
bit   │3 3 2 2 2 2 2 2│2 2 2 2 1│1 1 1 1 1│1 1 1 1  │ │               │
      │1 0 9 8 7 6 5 4│3 2 1 0 9│8 7 6 5 4│3 2 1 0 9│8│7 6 5 4 3 2 1 0│
      ├───────────────┼─────────┼─────────┼─────────┼─┼───────────────┤
ABCD  │         D (8) │  C (5)  │  B (5)  │  A (5)  │i│     OP (8)    │
      ├───────────────┴─────────┼─────────┼─────────┼─┼───────────────┤
ABCw  │                  C (13) │  B (5)  │  A (5)  │i│     OP (8)    │
      ├─────────────────────────┴─────────┼─────────┼─┼───────────────┤
ABw   │                            B (18) │  A (5)  │i│     OP (8)    │
      ├───────────────────────────────────┴─────────┼─┼───────────────┤
Aw    │                                      A (23) │i│     OP (8)    │
      └─────────────────────────────────────────────┴─┴───────────────┘
           Min         Max                  Min         Max
Au           0   8,388,607       As  -4,194,304   4,194,303
Bu           0     262,143       Bs    -131,072     131,071
Cu           0       8,191       Cs      -4,096       4,095
Du           0         255       Ds        -128         127
| Encoding | Arguments | 
|---|---|
| _ | (none) | 
| A | R(A) | 
| Au | R(A) or immediate unsigned value | 
| As | R(A) or immediate signed value | 
| ABv | R(A), with Bu immediate trailing u32 values | 
| AB | R(A), R(B) | 
| ABu | R(A), R(B) or immediate unsigned value | 
| ABs | R(A), R(B) or immediate signed value | 
| ABC | R(A), R(B), R(C) | 
| ABCu | R(A), R(B), R(C) or immediate unsigned value | 
| ABCs | R(A), R(B), R(C) or immediate signed value | 
| ABCD | R(A), R(B), R(C), R(D) | 
| ABCDu | R(A), R(B), R(C), R(D) or immediate unsigned value | 
| ABCDs | R(A), R(B), R(C), R(D) or immediate signed value | 
Callee-owned (caller-saved, temporary) registers. Caller needs to save these before a call (if caller uses them.) Callee can freely use these registers.
R0…R7   1st…8th integer argument/return value
F0…F7   1st…8th floating-point argument/return value
R8…R18  General purpose
F8…F18  General purpose
Caller-owned (callee-saved, long-lived) registers. Caller does not need to save these registers. Callee using these must save and later restore their values before returning.
R19…R29   General purpose
F19…F29   General purpose
SP (R31)  Stack pointer
CTX  (R30)  Context (like AAPCS platform reg and Go's G)
SP   (R31)  Stack pointer
-    (F30)  Reserved (unused)
FPSR (F31)  Floating-point status