8.3 KiB
UXN
Reformatted from the reference document
UXN is a deterministic, non-interrupting, 8-bit instruction set and word stack machine with a 16bi address space. It interacts with the outside world via port mapped I/O devices, of which 16 are supported.
Memory model
UXN presents a linear uniform main memory with a 16bi address space.
Programs may do I/O across the entire address space using the LDR2
and STR2
instructions.
The UXN address space is divided into chunks called pages, each with 8bi of addressing.
The 0 page (0x00[00-FF]
) is special and, for convenience, can be accessed using the LDZ
and STRZ
instructions.
The UXN stack machine, in keeping with the forth tradition has two stacks.
These are referred to as DATA
(stack 0) and RETURN
(stack 1) by convention.
Instructions may choose to transpose the stacks, allowing for computation on either stack.
See below for more on the return
flag.
The LDR
and STR
instructions are stack relative and allow for computed loads and stores.
Instruction set
UXN instructions are 8-bit values.
k | r | 2 | opcode |
---|---|---|---|
keep | return | short | 0 0 0 0 0 |
The three most significant bits of the instructions are mode flags of which we will say more. The least significant five bits select an instruction.
Effects are written using forth-style notation inputs -- outputs
Opcode | Memonic | Long name | Data stack effect | Control stack effect | PC effect | Memory effect |
---|---|---|---|---|---|---|
0x00 | BRK | Break | -- | -- | ||
0x01 | INC | Increment | a -- a+1 | |||
0x02 | POP | Pop | a -- | |||
0x03 | NIP | Nip | b a -- a | |||
0x04 | SWP | Swap | b a -- a b | |||
0x05 | ROT | Rotate | a b c -- b c a | |||
0x06 | DUP | Duplicate | a -- a a | |||
0x07 | OVR | Over | a b -- a b a | |||
0x08 | EQU | Equal | b a -- (a == b) | |||
0x09 | NEQ | Not equal | b a -- (a != b) | |||
0x0A | GTH | Greater than | b a -- (b > a) | |||
0x0B | LTH | Less than | b a -- (b < a) | |||
0x0C | JMP | Jump | a -- | PC+=a | ||
0x0D | JCN | Conditional jump | b a -- | PC+=(a if b else 1) | ||
0x0E | JSR | Jump stash return (call) | a -- | -- pc | PC+=a | |
0x0F | STH | Stash | a -- | -- a | ||
0x10 | LDZ | Load zero page | a: u8 -- MEM[a] | |||
0x11 | STZ | Store zero page | b a: u8 -- | MEM[a] = b | ||
0x12 | LDR | Load | a: i8 -- MEM[DATA + a] | |||
0x13 | STR | Store | b a: i8 -- | MEM[DATA + a] = b | ||
0x14 | LDA | Load absolute | a: i16 -- MEM[a] | |||
0x15 | STA | Store absolute | b a: i16 -- | MEM[a] = b | ||
0x16 | DEI | Device input | a: u8 -- DEV[a] | |||
0x17 | DEO | Device output | b a: u8 -- | DEV[a] = b | ||
0x18 | ADD | Add | b a -- a + b | |||
0x19 | SUB | Subtract | b a -- a - b | |||
0x1A | MUL | Multiply | b a -- a * b | |||
0x1B | DIV | Divide | b a -- a / b | |||
0x1C | AND | And | b a -- a && b | |||
0x1D | ORA | Or | b a -- a|b | |||
0x1E | EOR | Exclusive or (xor) | b a -- a^b | |||
0x1F | SFT | Shift | b a -- b >> (a & 0x0f) << ((a & 0xf0) >> 4) |
Mode bits
Note that all these instructions are listed with keep=0,return=0,short=0
.
The UXN documentation refers to ADD
with keep=1
as ADDk
.
ADD
with short=1
is ADD2
, and with keep=1
would be ADD2k
.
POP
with return=1
is POPr
.
Conventionally these suffixes are formatted %/2?k?r?/
as required.
Short mode
In When the short
bit is set, the opcode will pop two 8bi quantities from the stack where it would only consume one in byte
mode.
Each b a
pair so popped is considered to be the unsigned 16bi quantity a + b<<8
For instance ADDs
would be a b c d –- (a<<8 + b) + (c<<8+d)
.
Exceptions:
- The load/store operations move two 8bi values not one.
STR
becomesc b a -- MEM[DATA + a] =
Relative address computation is unaffected. - The jump opcodes become absolute rather than computed relative jumps.
Keep mode
When the keep
bit is set, no values are popped from the stack.
For instance ADD2k
would be a b c d -- a b c d e f
.
Return mode
"return mode" flips the stacks.
If STH
pops from data and pushes to return, STHr
pops from return and pushes to data.
Likewise if ADD
pops from data and pushes to data, ADDr
would pop from data and push to data.
JMP2
would load b a
from the data stack and branch absolutely, JMP2r
would do the same from the control stack.
DUP2r
would a b -- a b a b
the return stack.
The bytecode sequence LIT 0x01 STH JSRr BRK
would load 0x1
to the data stack, pop and stash it to the return stack, perform a relative jump by +1
while pushing PC
to the data stack and halt.