736 lines
33 KiB
Markdown
736 lines
33 KiB
Markdown
---
|
|
Title: ARCTIC Documentation
|
|
Author: Louis A. Burke
|
|
Language: en
|
|
CSS: doc/documentation.css
|
|
LaTeX Leader: arctic-leader.tex
|
|
LaTeX Begin: arctic-begin.tex
|
|
LaTeX Footer: arctic-footer.tex
|
|
LaTeX Header Level: 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
|
|
|
|
```{=todo}
|
|
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?
|
|
I prefer sections, start with just implementations/documentation/specification
|
|
of code/data. For JIT code is obvious, data is variables loaded with appropriate
|
|
data and "passed through" to JIT.
|
|
Ideally keep immediate instructions consistent in each section (easier
|
|
parsing/highlighting/etc)?
|
|
```
|
|
|
|
## 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
|
|
|
|
```{=todo}
|
|
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]
|