33 KiB
Title | Author | Language | CSS | LaTeX Leader | LaTeX Begin | LaTeX Footer | LaTeX Header Level |
---|---|---|---|---|---|---|---|
ARCTIC Documentation | Louis A. Burke | en | doc/documentation.css | arctic-leader.tex | arctic-begin.tex | arctic-footer.tex | 3 |
ARCTIC Code
ASCII Rendered, Cross-Target Invocation Character Codes
Like the JVM, but the "binaries" consist of printable ASCII characters and the result can be more easily precompiled for native execution. Also far less safety and verification, feel free to shoot yourself in the foot.
Behaviour
The behaviour of ARCTIC code is described by how a theoretical virtual machine would interpret it. Any compiler or interpreter that produces the same series of exernal syscalls with the same values and returns the same result as the theoretical virtual machine is considered a compliant ARCTIC implementation.
This documentation describes the input as a "file", but it actually may consist of multiple files or may be processed from standard input. How an ARCTIC implementation consumes its input is up to each specific implementation, but should be well documented.
Structure
ARCTIC code is divided into sections. In each section, each character represents a different operation.
Data Types
The Stack
Memory
Sections
code is LE \ w.r.t
CODE is BE / LDAx
Specifically:
.* is shared file load (" libc.so")
A.* is BE atomic data
a.* is LE atomic data
[bB].* is BSS data (uninitialized, but allocated)
C.* is BE code
c.* is LE code
D.* is BE data
d.* is LE data
E.* is BE externals
e.* is LE externals
[fF].* is embedded file ("file X")
[gG].* is embedded resource ("get X")
[hH].* is embedded resource ("http...")
[iI].* is embedded code ("include X")
[jJ].* is embedded java ("jvm X")
[kK].* is ???
[lL].* is embedded arctic file ("load X")
M.* is BE macros
m.* is LE macros
[nN].* is ???
O.* is BE register-based code ("OPTIMIZED")
o.* is LE register-based code ("optimized")
P.* is BE per-thread data (POOL)
p.* is LE per-thread data (pool)
Q.* is BE quantum code ("QUANTUM")
q.* is LE quantum code ("quantum")
R.* is BE read-only data
r.* is LE read-only data
[sS].* is ???
[tT].* is ???
[uU].* is ???
[vV].* is ???
[wW].* is load module ("with X")
[xX].* is ???
[yY].* is ???
[zZ].* is ???
Need better description of data '' format. See QBE's data for inspiration?
Consider having each op-code mean something different in different sections?
Only consistency would be labels... those could be more universally parsed?
Alternatively remove sections altogether and use only dynamic memory?
File Format
Loading, Compiling, and Running
Instructions
This section describes the various instructions that are defined for an ARCTIC system. When stack manipulation is shown, the following conventions apply.
Stack direction: The stack is shown from left to right where the top of the
stack is on the right. For example 1 2 3
shows a stack with 3 on top of 2 on
top of 1.
Ellipses: When only the top of the stack is relevant, the rest may be
abbreviated with …
. For example … 10
shows a stack with a value of 10 at the
top and unknown data possibly below it.
Production: To indicate the change in a stack, an arrow is used. For example
1 2 3 → 3 1 2
shows a stack containing 1, 2, 3 becoming a stack containing 3,
1, 2. Similarly, if the arrow is doubled, it indicates an immediate value is
also consumed. For example 1 2 ⇒ 3
shows a stack containing 1 and 2 becoming
a stack containing 3 after consuming an immediate value.
Variables/Values: Variables and values are presented as space-separated c expressions. These are interpreted as if declared as follows:
int64_t x, y, z;
double a, b, c;
void *p, *q; // data pointers
void *f; // function pointer
Notate that immediates can be: …###, …###.###, …$name, or …v (for abcinxyz)
for most operations that take immediates.
Sections, a la ELF. Probably want:
- code
- macros (ephemeral "code")
- constants (ephemeral "data")
- data (read-only memory)
- state (initialized memory)
- memory (uninitialized memory)
The ops below are probably code exclusive. The remaining " and ' can switch
modes? Maybe just "section" to start a section? Leaving ' as the only impl-def?
Memory
The following table summarizes the memory operations that are described below.
⋄ | Code | … | Stack | … | Description |
---|---|---|---|---|---|
1 | LDAB | … p | → | … x | load byte x from p |
2 | LDAS | … p | → | … x | load short x from p |
3 | LDAI | … p | → | … x | load int x from p |
4 | LDAW | … p | → | … x | load word x from p |
o | LDOB | … p | ⇒ | … x | load byte at p plus immediate offset in x |
H | LDOS | … p | ⇒ | … x | load short at p plus immediate offset in x |
G | LDOI | … p | ⇒ | … x | load int at p plus immediate offset in x |
Q | LDOW | … p | ⇒ | … x | load word at p plus immediate offset in x |
5 | STAB | … p x | → | … | store byte x to p |
6 | STAS | … p x | → | … | store short x to p |
7 | STAI | … p x | → | … | store int x to p |
8 | STAW | … p x | → | … | store word x to p |
D† | MCLR | … p x | → | … | memclear x bytes from p |
d† | MSET | … p x | ⇒ | … | set x bytes of memory to immediate value at p |
K† | MCPY | … p q x | → | … | copy x bytes of memory from p to q |
J | MOFF | … p x | → | … q | set q to memory pointer p shifted by x bytes |
M† | MALL | … p | ⇒ | … p | (re)allocate/free memory for immediate bytes at p |
R† | REAL | … p x | → | … p | (re)allocate/free memory for x bytes at p |
9 | CASS | … p x y | → | … z | compare and swap x and y at p, return success |
LDAx
The LDAx instructions take a pointer on the top of the stack and replace it with the value of 1, 2, 4, or 8 bytes loaded from its address as 2's compliment. The endianness is determined by the endianness of the code section under execution.
- LDAB:
… p → … (int64)*(int8*)p
- LDAS:
… p → … (int64)*(int16*)p
- LDAI:
… p → … (int64)*(int32*)p
- LDAW:
… p → … *(int64*)p
LDOx
The LDOx instructions take an immediate offset following the instruction code and a pointer on top of the stack and act like their LDAx counterparts, but operating on the memory address specified by adding the immediate value to the pointer.
- LDOB(i):
… p ⇒ … (int64)((int8*)p)[i]
- LDOS(i):
… p ⇒ … (int64)((int16*)p)[i]
- LDOI(i):
… p ⇒ … (int64)((int32*)p)[i]
- LDOW(i):
… p ⇒ … ((int64*)p)[i]
STAx
The STAx instructions take a value on top of the stack and a pointer underneath it and write the least significant 1, 2, 4, or 8 bytes of the value to the address of the pointer, removing both from the stack.
- STAB:
… p x → … (void)(*(int8*)p=x&0xFF)
- STAS:
… p x → … (void)(*(int16*)p=x&0xFFFF)
- STAI:
… p x → … (void)(*(int32*)p=x&0xFFFFFFFF)
- STAW:
… p x → … (void)(*p=x)
MOFF
The MOFF instruction takes an integer on top of the stack and a memory address underneath it and shifts the memory address by the integer, removing the integer in the process.
- MOFF:
… p x → … ((int8*p)+x)
MCLR
The MCLR instruction takes an integer value on top of the stack and a pointer underneath it. It then clears as many bytes of memory in order as indicated by the integer value starting from the pointer address. Both the value and pointer are removed from the stack.
- MCLR:
… p x → … (void)memset(p,x,0)
MSET
The MSET instruction takes an immediate byte value following the instruction code, as well as an integer value on top of the stack and a pointer underneath it. It then sets as many bytes of memory in order as indicated by the integer value starting from the pointer address to the immediate value. Both the value and pointer are removed from the stack.
- MSET(i):
… p x ⇒ … (void)memset(p,x,i)
MCPY
The MCPY instruction takes an integer value on top of the stack and a pair of pointers underneath it. It then copies as many bytes of memory in order as indicated by the integer value starting from the bottom pointer into memory starting from the top pointer. All three arguments are removed from the stack.
- MCPY:
… p q x → … (void)memmove(q, p, x)
MALL
The MALL instruction takes an immediate offset following the instruction code and a pointer on top of the stack and allocates or reallocates memory of that many bytes, replacing the pointer with the new pointer on the stack.
If the size is zero, this frees the memory and pushes a null pointer.
- MALL(i):
… p ⇒ … realloc(p, i)
REAL
The REAL instruction takes an offset value on top of the stack and a pointer underneath it and allocates or reallocates memory of that many bytes, replacing the pointer with the new pointer on the stack.
If the size is zero, this frees the memory and pushes a null pointer.
- REAL:
… p x → … realloc(p, x)
CASS
The CASS instruction takes a new value on top of the stack, an expected old value underneath it, and a pointer underneath that. It atomically compares the 8 bytes of memory referenced by the pointer with the expected old value; if they match, the memory content is updated to the new value and all three arguments are replaced with the number 1 as a 64-bit integer; if they do not match, no memory is updated and all three arguments are replaced with the number 0.
- CASS:
… p x y → … atomic_compare_exchange_strong(p,&x,y)
Math
⋄ | Code | … | Stack | … | Description |
---|---|---|---|---|---|
+ | IADD | … x y | → | … z | set z to the sum of x and y |
- | ISUB | … x y | → | … z | set z to the difference between x and y (x - y) |
* | IMUL | … x y | → | … z | set z to the product of x and y |
/ | IDIV | … x y | → | … z | set z to the quotient of x by y |
% | IMOD | … x y | → | … z | set z to the modulo of x by y |
\|IREM | … x y | → | … z | set z to the remainder of x by y | |
_ | INEG | … x | → | … x | negate x |
| | IABS | … x | → | … x | take the absolute value of x |
s | FADD | … a b | → | … c | set c to the sum of a and b |
m | FSUB | … a b | → | … c | set c to the difference between a and b (a - b) |
p | FMUL | … a b | → | … c | set c to the product of a and b |
q | FDIV | … a b | → | … c | set c to the quotient of a by b |
f | FMOD | … a b | → | … c | set c to the modulo of a by b |
r | FREM | … a b | → | … c | set c to the remainder of a by b |
j | FNEG | … a | → | … a | negate a |
v | FABS | … a | → | … a | take the absolute value of a |
V | BIOR | … x y | → | … z | bitwise OR x and y and store in z |
& | BAND | … x y | → | … z | set z to the bitwise and of x and y |
^ | BXOR | … x y | → | … z | set z to the bitwise xor of x and y |
l | BITC | … x y | → | … z | bit clear y from x to z (z = x and not y) |
! | BNOT | … x | → | … y | set y to the bitwise not of x |
u | USHR | … x | ⇒ | … x | logical shift x by immediate bits right |
[ | ROTR | … x | ⇒ | … x | rotate x by immediate bits |
] | BSHR | … x | ⇒ | … x | arithmetic right shift x by immediate bits |
? | CMPI | … x y | → | … z | compare x to y and set z such that x o y is z o 0 |
~ | CMPF | … a b | ⇒ | … c | compare a to b and set c such that a o b is z o c within immediate ULPs |
U | CMPU | … x y | → | … z | compare x to y unsigned and set z such that x o y is z o 0 |
F | BMIS | … x | ⇒ | … x | bit manipulation instructions |
xADD/xSUB/xMUL/xDIV/xMOD/xREM
The xADD/xSUB/xMUL/xDIV/xMOD/xREM instructions take two values on top of the stack (either two integers or two floating point numbers) and perform the specified mathematical operation, replacing the values with the result of the operation.
The difference between MOD and REM is that MOD is floored while REM is truncated.
- IADD:
… x y → (x+y)
- FADD:
… a b → (a+b)
- ISUB:
… x y → (x-y)
- FSUB:
… a b → (a-b)
- IMUL:
… x y → (x*y)
- FMUL:
… a b → (a*b)
- IDIV:
… x y → (x/y)
- FDIV:
… a b → (a/b)
- IMOD:
… x y → (y>0?abs(x%y):-abs(x%y))
- FMOD:
… a b → (b>0?fabs(fmod(x,y)):-fabs(fmod(x,y)))
- IREM:
… x y → x%y
- FREM:
… a b → fmod(x,y)
xNEG/xABS
The xNEG/xABS instructions take a value on top of the stack (either an integer or a floating point number) and replaces it with either its negated value or its absolute value.
- INEG:
… x → -x
- FNEG:
… a → -a
- IABS:
… x → abs(x)
- FABS:
… a → fabs(a)
BIOR/BAND/BXOR/BITC
The BIOR/BAND/BXOR/BITC instructions take two values on top of the stack and perform the specified bitwise operation, replacing the values with the result of the operation.
BITC is a single instruction that performs A AND NOT B between its arguments.
- BIOR:
… x y → x|y
- BAND:
… x y → x&y
- BXOR:
… x y → x^y
- BITC:
… x y → x&~y
USHR/BSHR/ROTR
The USHR/BSHR instructions take a value on top of the stack and an immediate offset and shift the value on top of the stack that number of bits in the given direction.
USHR and BSHR differ in that BSHR performs an arithmetic shift, duplicating the highest order bit instead of shifting in a 0.
ROTR performs a rightward rotation, however with a negative shift amount, it performs a leftward rotation.
- USHR(i):
… x ⇒ ((uint64_t)x)>>i
- BSHR(i):
… x ⇒ x>>i
- ROTR(i):
… x ⇒ (x>>shift)|(value<<(64-shift))
CMPx
The CMPx instructions perform comparisons between two values on top of the stack and replace them with either 1, 0, or -1 if the top value is less than, equal to, or greater than the second value respectively. In the case of CMPF, a floating point precision is specified by an immediate value, with equality spanning all values within the given precision of each other.
- CMPI:
… x y → ((x-y)>0)-((x-y)<0)
- CMPF(i):
… a b ⇒ fabs(a-b)<i?0:((a-b)>0)-((a-b)<0)
- CMPU:
… x y → (((uint64_t)x-(uint64_t)y)>0)-(((uint64_t)x-(uint64_t)y)<0)
BMIS
The BMIS instruction bundles many unary bitwise operators into a single instruction, indexed by an immediate integer based on the following table:
Immediate | Operation |
---|---|
0 | ??? |
Type Conversions
⋄ | Code | … | Stack | … | Description |
---|---|---|---|---|---|
E | FTOI | … a | ⇒ | … x | round a to integer and store in x |
O | ITOC | … x | → | … x | truncate x to 8 bits, then sign extend |
S | ITOS | … x | → | … x | truncate x to 16 bits, then sign extend |
W | ITOW | … x | → | … x | truncate x to 32 bits, then sign extend |
. | ITOF | … x | → | … a | convert x to a floating point number |
FTOI
The FTOI instruction takes a floating point value on top of the stack and replaces it with an integer by rounding. The direction of rounding is determined by the immediate integer value:
Value | Rounding Mode |
---|---|
1 | Round towards infinity. "Round up" |
-1 | Round towards negative infinity. "Round down" |
0 | Round towards 0. "Truncate" |
others | Round to even. "Unbiased" |
- FTOI(1):
… a ⇒ fesetround(FE_UPWARD),(int64_t)a
- FTOI(-1):
… a ⇒ fesetround(FE_DOWNWARD),(int64_t)a
- FTOI(0):
… a ⇒ fesetround(FE_TOWARDZERO),(int64_t)a
- FTOI(i):
… a ⇒ fesetround(FE_TONEAREST),(int64_t)a
ITOC/ITOS/ITOW
The ITOC/ITOS/ITOW instructions take a 64-bit integer on top of the stack and replace it with a truncated and sign extended smaller integer.
- ITOC:
… x → (int64_t)*(int8_t*)&x
- ITOS:
… x → (int64_t)*(int16_t*)&x
- ITOW:
… x → (int64_t)*(int32_t*)&x
ITOF
The ITOF instruction takes a 64-bit integer on top of the stack and replaces it with the closest 64-bit floating point approximation.
- ITOF:
… x → (double)x
Stack Management
⋄ | Code | … | Stack | … | Description |
---|---|---|---|---|---|
w | SDUP | … x | → | … x x | stack duplicate |
k | SPOP | … x | → | … | stack pop |
t | SWAP | … x y | → | … y x | stack swap |
h | OVER | … x y | → | … x y x | stack over |
e | SROT | … x y z | → | … y z x | rotate stack |
P | PICK | … x ‥ z | ⇒ | … x ‥ z x | pick stack element at immediate place |
L | ROLL | … x y ‥ z | ⇒ | … y ‥ z x | roll stack by immediate places |
T | PUSH | … x ‥ y z | ⇒ | … y x ‥ z | push top of stack down by immediate places (opposite of ROLL) |
( | DPTH | … | → | … x | set x to depth of stack (before x) |
) | PACK | … p x | → | … p | pack x elements of stack (before p) into array p |
SDUP
The SDUP instruction takes a value on top of the stack and pushes a copy of it to the top of the stack.
- SDUP:
… x → x x
SPOP
The SPOP instruction removes the value on top of the stack.
- SPOP:
… x →
SWAP/OVER/SROT
The SWAP/OVER/SROT instructions manipulate the values near the top of the stack.
- SWAP:
… x y → … y x
- OVER:
… x y → … x y x
- SROT:
… x y z → … y z x
PICK
The PICK instruction acts like an OVER command with an arbitrary depth, copying an
element indicated by the immediate value to the top of the stack. OVER can be
defined in terms of PICK as P1
while SDUP is equivalent to P0
.
- PICK(i):
… x …i… y ⇒ … x …i… y x
ROLL/PUSH
The ROLL and PUSH instructions act like SROT with an arbitrary depth, allowing
a value from any depth in the stack to be rotated to the top or pushed back down
to depth. SROT can be defined in terms of ROLL as L1
while SWAP is equivalent
to L0
or T0
.
- ROLL(i):
… x y …i… z ⇒ … y …i… z x
- PUSH(i):
… x …i… y z ⇒ … z x …i… y
DPTH/PACK
The DPTH instruction pushes the total depth of the stack on top of the stack. The PACK instruction takes an integer on top of a pointer and saves the top elements of the stack beneath the pointer to the memory pointed to by it.
These can be combined to store the entire stack in a new array via: (w$0 Rt)
- DPTH:
…x… → …x… x
- PACK:
… p x → p
Control Flow
⋄ | Code | … | Stack | … | Description |
---|---|---|---|---|---|
= | BEQZ | … x | ⇒ | … | branch to immediate if x is zero |
0 | BNEZ | … x | ⇒ | … | branch to immediate if x not zero |
< | BLTZ | … x | ⇒ | … | branch to immediate if x less than zero |
> | BGTZ | … x | ⇒ | … | branch to immediate if x is greater than zero |
{ | BLEZ | … x | ⇒ | … | branch to immediate if x is less than or equal to zero |
} | BGEZ | … x | ⇒ | … | branch to immediate if x is greater or equal to zero |
g | FINV | … f | → | f … | invoke f, saving return address on stack |
@ | CALL | … | ⇒ | f … | call immediate name |
, | JUMP | … | ⇒ | … | jump to immediate without pushing return address |
; | RETN | … f | → | … | return from subroutine (jump but for stack) |
: | LABL | … | ↔ | … | label code location |
BEQZ/BNEZ/BLTZ/BGTZ/BLEZ/BGEZ
The BEQZ/BNEZ/BLTZ/BGTZ/BLEZ/BGEZ instructions are the basic branching instructions. They take an immediate offset and, if their condition is met, jump that many beats (lines) forward or backward.
- BEQZ(i):
… x ⇒ …
- BNEZ(i):
… x ⇒ …
- BLTZ(i):
… x ⇒ …
- BGTZ(i):
… x ⇒ …
- BLEZ(i):
… x ⇒ …
- BGEZ(i):
… x ⇒ …
FINV/CALL
The FINV/CALL instructions invoke functions by jumping to their first instruction after pushing the address of the next instruction on the stack.
- FINV:
… f → g …
- CALL(f):
… → g …
JUMP/RETN
The JUMP/RETN instructions are the complement to the FINV/CALL instructions. They jump to the first instruction of the given function, but do not push a return address on the stack.
- JUMP(f):
… ⇒ …
- RETN:
… f ⇒ …
LABL
The LABL instruction takes an immediate name and marks the next current beat in memory as having that name for future or past references.
- LABL:
… ↔ …
Variables
⋄ | Code | … | Stack | … | Description |
---|---|---|---|---|---|
A | PUTA | … x | → | … | store x in rA |
B | PUTB | … x | → | … | store x in rB |
C | PUTC | … x | → | … | store x in rC |
I | PUTI | … x | → | … | store x in rI |
N | PUTN | … x | → | … | store x in rN |
X | PUTX | … x | → | … | store x in rX |
Y | PUTY | … x | → | … | store x in rY |
Z | PUTZ | … x | → | … | store x in rZ |
a | GETA | … | → | … x | load x from rA |
b | GETB | … | → | … x | load x from rB |
c | GETC | … | → | … x | load x from rC |
i | GETI | … | → | … x | load x from rI |
n | GETN | … | → | … x | load x from rN |
x | GETX | … | → | … x | load x from rX |
y | GETY | … | → | … x | load x from rY |
z | GETZ | … | → | … x | load x from rZ |
PUTA/PUTB/PUTC/PUTI/PUTN/PUTX/PUTY/PUTZ
The PUTA/PUTB/PUTC/PUTI/PUTN/PUTX/PUTY/PUTZ instructions take a value on top of the stack and store it in a register for later recall.
- PUTA:
… x → …
- PUTB:
… x → …
- PUTC:
… x → …
- PUTI:
… x → …
- PUTN:
… x → …
- PUTX:
… x → …
- PUTY:
… x → …
- PUTZ:
… x → …
GETA/GETB/GETC/GETI/GETN/GETX/GETY/GETZ
The GETA/GETB/GETC/GETI/GETN/GETX/GETY/GETZ instructions push the previously saved value in a register onto the stack.
- GETA:
… → … x
- GETB:
… → … x
- GETC:
… → … x
- GETI:
… → … x
- GETN:
… → … x
- GETX:
… → … x
- GETY:
… → … x
- GETZ:
… → … x
Miscellaneous
⋄ | Code | … | Stack | … | Description |
---|---|---|---|---|---|
$ | VALU | … | ⇒ | … * | load constant value |
' | DATA | Embed data | |||
" | SECT | Change section | |||
` | BIFC | … ? | ↔ | … ? | call builtin with given name/value |
␣ | NOOP | … | ↔ | … | do nothing, maybe end identifier definition |
¶ | BEAT | … | ↔ | … | mark a beat for relative branching |
Summary
. | -0 | -1 | -2 | -3 | -4 | -5 | -6 | -7 |
---|---|---|---|---|---|---|---|---|
000- | 0 BNEZ |
1 LDAB |
2 LDAS |
3 LDAI |
4 LDAW |
5 STAB |
6 STAS |
7 STAI |
001- | 8 STAW |
9 CASS |
A PUTA |
B PUTB |
C PUTC |
D MCLR |
E FTOI |
F BMIS |
010- | G LDOI |
H LDOS |
I PUTI |
J MOFF |
K MCPY |
L ROLL |
M MALL |
N PUTN |
011- | O ITOC |
P PICK |
Q LDOW |
R REAL |
S ITOS |
T PUSH |
U CMPU |
V BIOR |
100- | W ITOW |
X PUTX |
Y PUTY |
Z PUTZ |
a GETA |
b GETB |
c GETC |
d MSET |
101- | e SROT |
f FMOD |
g FINV |
h OVER |
i GETI |
j FNEG |
k SPOP |
l BITC |
110- | m FSUB |
n GETN |
o LDOB |
p FMUL |
q FDIV |
r FREM |
s FADD |
t SWAP |
111- | u USHR |
v FABS |
w SDUP |
x GETX |
y GETY |
z GETZ |
_ INEG |
. ITOF |
200- | + IADD |
- ISUB |
* IMUL |
/ IDIV |
% IMOD |
\ IREM |
| IABS |
$ VALU |
201- | @ CALL |
< BLTZ |
{ BLEZ |
= BEQZ |
} BGEZ |
> BGTZ |
, JUMP |
; RTRN |
210- | & BAND |
^ BXOR |
! BNOT |
[ ROTR |
] BSHR |
? CMPI |
~ CMPF |
: LABL |
211- | ( DPTH |
) PACK |
' DATA |
" SECT |
\ BIFC` |
␣ NOP |
# COMM |
¶ BEAT |
[Operations by code][ops-by-code] |
In this table x, y, and z are integers; a, b, and c are floating point numbers; p and q are memory pointers; and f is a function pointer. Additionally, → indicates a basic operation, while ⇒ indicates an operation using an immediate value, and ↔ indicates a meta operation.
⋄ | Code | … | Stack | … | Description |
---|---|---|---|---|---|
0 | BNEZ | … x | ⇒ | … | branch to immediate if x not zero |
1 | LDAB | … p | → | … x | load byte x from p |
2 | LDAS | … p | → | … x | load short x from p |
3 | LDAI | … p | → | … x | load int x from p |
4 | LDAW | … p | → | … x | load word x from p |
5 | STAB | … p x | → | … | store byte x to p |
6 | STAS | … p x | → | … | store short x to p |
7 | STAI | … p x | → | … | store int x to p |
8 | STAW | … p x | → | … | store word x to p |
9 | CASS | … p x y | → | … z | compare and swap x and y at p, return success |
A | PUTA | … x | → | … | store x in rA |
B | PUTB | … x | → | … | store x in rB |
C | PUTC | … x | → | … | store x in rC |
D | MCLR | … p x | → | … | memclear x bytes from p |
E | FTOI | … a | ⇒ | … x | round a to integer and store in x |
F | BMIS | … x | ⇒ | … x | bit manipulation instructions |
G | LDOI | … p | ⇒ | … x | load int at p plus immediate offset in x |
H | LDOS | … p | ⇒ | … x | load short at p plus immediate offset in x |
I | PUTI | … x | → | … | store x in rI |
J | MOFF | … p x | → | … q | set q to memory pointer p shifted by x bytes |
K | MCPY | … p q x | → | … | copy x bytes of memory from p to q |
L | ROLL | … x y ‥ z | ⇒ | … y ‥ z x | roll stack by immediate places |
M | MALL | … p | ⇒ | … p | (re)allocate/free memory for immediate bytes at p |
N | PUTN | … x | → | … | store x in rN |
O | ITOC | … x | → | … x | truncate x to 8 bits, then sign extend |
P | PICK | … x ‥ z | ⇒ | … x ‥ z x | pick stack element at immediate place |
Q | LDOW | … p | ⇒ | … x | load word at p plus immediate offset in x |
R | REAL | … p x | → | … p | (re)allocate/free memory for x bytes at p |
S | ITOS | … x | → | … x | truncate x to 16 bits, then sign extend |
T | PUSH | … x ‥ y z | ⇒ | … y x ‥ z | push top of stack down by immediate places (opposite of ROLL) |
U | CMPU | … x y | → | … z | compare x to y unsigned and set z such that x o y is z o 0 |
V | BIOR | … x y | → | … z | bitwise OR x and y and store in z |
W | ITOW | … x | → | … x | truncate x to 32 bits, then sign extend |
X | PUTX | … x | → | … | store x in rX |
Y | PUTY | … x | → | … | store x in rY |
Z | PUTZ | … x | → | … | store x in rZ |
a | GETA | … | → | … x | load x from rA |
b | GETB | … | → | … x | load x from rB |
c | GETC | … | → | … x | load x from rC |
d | MSET | … p x | ⇒ | … | set x bytes of memory to immediate value at p |
e | SROT | … x y z | → | … y z x | rotate stack |
f | FMOD | … a b | → | … c | set c to the modulo of a by b |
g | FINV | … f | → | f … | invoke f, saving return address on stack |
h | OVER | … x y | → | … x y x | stack over |
i | GETI | … | → | … x | load x from rI |
j | FNEG | … a | → | … a | negate a |
k | SPOP | … x | → | … | stack pop |
l | BITC | … x y | → | … z | bit clear y from x to z (z = x and not y) |
m | FSUB | … a b | → | … c | set c to the difference between a and b (a - b) |
n | GETN | … | → | … x | load x from rN |
o | LDOB | … p | ⇒ | … x | load byte at p plus immediate offset in x |
p | FMUL | … a b | → | … c | set c to the product of a and b |
q | FDIV | … a b | → | … c | set c to the quotient of a by b |
r | FREM | … a b | → | … c | set c to the remainder of a by b |
s | FADD | … a b | → | … c | set c to the sum of a and b |
t | SWAP | … x y | → | … y x | stack swap |
u | USHR | … x | ⇒ | … x | logical shift x by immediate bits right |
v | FABS | … a | → | … a | take the absolute value of a |
w | SDUP | … x | → | … x x | stack duplicate |
x | GETX | … | → | … x | load x from rX |
y | GETY | … | → | … x | load x from rY |
z | GETZ | … | → | … x | load x from rZ |
_ | INEG | … x | → | … x | negate x |
. | ITOF | … x | → | … a | convert x to a floating point number |
+ | IADD | … x y | → | … z | set z to the sum of x and y |
- | ISUB | … x y | → | … z | set z to the difference between x and y (x - y) |
* | IMUL | … x y | → | … z | set z to the product of x and y |
/ | IDIV | … x y | → | … z | set z to the quotient of x by y |
% | IMOD | … x y | → | … z | set z to the modulo of x by y |
\|IREM | … x y | → | … z | set z to the remainder of x by y | |
| | IABS | … x | → | … x | take the absolute value of x |
$ | VALU | … | ⇒ | … * | load constant value |
@ | CALL | … | → | f … | call immediate name |
< | BLTZ | … x | ⇒ | … | branch to immediate if x less than zero |
{ | BLEZ | … x | ⇒ | … | branch to immediate if x is less than or equal to zero |
= | BEQZ | … x | ⇒ | … | branch to immediate if x is zero |
} | BGEZ | … x | ⇒ | … | branch to immediate if x is greater or equal to zero |
> | BGTZ | … x | ⇒ | … | branch to immediate if x is greater than zero |
, | JUMP | … | ⇒ | … | jump to immediate without pushing return address |
; | RETN | … f | ⇒ | … | return from subroutine (jump but for stack) |
& | BAND | … x y | → | … z | set z to the bitwise and of x and y |
^ | BXOR | … x y | → | … z | set z to the bitwise xor of x and y |
! | BNOT | … x | → | y | set y to the bitwise not of x |
[ | ROTR | … x | ⇒ | … x | rotate x by immediate bits |
] | BSHR | … x | ⇒ | … x | arithmetic right shift x by immediate bits |
? | CMPI | … x y | → | … z | compare x to y and set z such that x o y is z o 0 |
~ | CMPF | … a b | ⇒ | … c | compare a to b and set c such that a o b is z o c within an immediate error |
: | LABL | … | ↔ | … | label code location |
( | DPTH | … | → | … x | set x to depth of stack (before x) |
) | PACK | … p x | → | … p | pack x elements of stack (before p) into array p |
' | DATA | Embed data | |||
" | SECT | Change section | |||
` | BIFC | … ? | ↔ | … ? | call builtin with given name/value |
␣ | NOOP | … | ↔ | … | do nothing, maybe end identifier definition |
¶ | BEAT | … | ↔ | … | mark a beat for relative branching |
[Operations in order][ops-in-order] |