uxn/doc/uxn.md

101 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.