101 lines
8.3 KiB
Markdown
101 lines
8.3 KiB
Markdown
# UXN
|
||
|
||
Reformatted from [the reference document](https://wiki.xxiivv.com/site/uxntal_reference.html)
|
||
|
||
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](http://www.forth.org/svfig/Len/softstak.htm) 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` becomes `c 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.
|