diff --git a/uxntal.1 b/uxntal.1 index 220efcf..eef9be6 100644 --- a/uxntal.1 +++ b/uxntal.1 @@ -14,6 +14,8 @@ Instructions manipulate data using two stacks: a working stack (\fBwst\fP) and a There are also 256 bytes of device memory, which are used to interact with the virtual machine and its devices. +Instructions deal with unsigned 8-bit values (\fIbytes\fP) and unsigned 16-bit values (\fIshorts\fP). There are no other built-in data types. + .SH INSTRUCTION LAYOUT 0x01 ---- @@ -21,9 +23,9 @@ There are also 256 bytes of device memory, which are used to interact with the v 0x04 +- \fIopcode\fP 0x08 / 0x10 ---- - 0x20 ---- 2: \fIshort\fP mode - 0x40 ---- r: \fIreturn\fP mode - 0x80 ---- k: \fIkeep\fP mode + 0x20 ---- 2: \fIshort mode\fP + 0x40 ---- r: \fIreturn mode\fP + 0x80 ---- k: \fIkeep mode\fP .SH OPCODE LAYOUT @@ -81,11 +83,11 @@ For example the generic effect for \fBADD\fP is ( x y -- x+y ). The eight combin \fBADD2k\fP ( x* y* -- x* y* x+y* ) sum two shorts using \fBwst\fP, retain arguments \fBADD2kr\fP ( [x* y*] -- [x* y* x+y*] ) sum two shorts using \fBrst\fP, retain arguments -Thus for regular instructions writing a "generic" effect (leaving sigils off values whose size depends on \fIshort\fP mode) is sufficient to describe its behavior across all eight variations. Note that some instructions always read values of a fixed size. For example the boolean condition read by \fBJCN\fP is always one byte, no matter what modes are used. +Thus for regular instructions writing a "generic" effect (leaving sigils off values whose size depends on \fIshort mode\fP) is sufficient to describe its behavior across all eight variations. Note that some instructions always read values of a fixed size. For example the boolean condition read by \fBJCN\fP is always one byte, no matter what modes are used. -In \fIreturn\fP mode the stacks are reversed. Effects on \fBwst\fP will instead affect \fBrst\fP, and effects on \fBrst\fP will instead affect \fBwst\fP. For example, \fBSTH\fP reads a byte from \fBwst\fP and writes it to \fBrst\fP, but \fBSTHr\fP reads a byte from \fBrst\fP and writes it to \fBwst\fP. +In \fIreturn mode\fP the stacks are reversed. Effects on \fBwst\fP will instead affect \fBrst\fP, and effects on \fBrst\fP will instead affect \fBwst\fP. For example, \fBSTH\fP reads a byte from \fBwst\fP and writes it to \fBrst\fP, but \fBSTHr\fP reads a byte from \fBrst\fP and writes it to \fBwst\fP. -In \fIkeep\fP mode all the values on the left-hand side of the stack effect will also appear on the right-hand side before the outputs. For example, \fBSWP\fP is \fB(x y -- y x)\fP but \fBSWPk\fP is \fB(x y -- x y y x)\fP. +In \fIkeep mode\fP all the values on the left-hand side of the stack effect will also appear on the right-hand side before the outputs. For example, \fBSWP\fP is \fB(x y -- y x)\fP but \fBSWPk\fP is \fB(x y -- x y y x)\fP. .SS TERMINOLOGY @@ -114,6 +116,8 @@ Remove the top value of the stack. Remove the second value of the stack. +\fBNIPk\fP is guaranteed to have no effect (it will not change the stack). + .SS SWP ( x y -- y x ) @@ -183,9 +187,11 @@ The program counter (\fIpc\fP) is updated when \fIbool\fP is non-zero. When \fIx .SS JSR ( x -- [pc+1*] ) -Jump to a location, saving a reference to the current program counter. +Jump to a location, saving a reference to return to. -Store the next address to execute before unconditionally updating the program counter (\fIpc\fP). This instruction is usually used to invoke subroutines, which use the \fBJMP2r\fP to return. When \fIx\fP is a byte, it is treated as relative (\fBpc += x\fP) and when \fIx\fP is a short it is treated as absolute (\fBpc = x\fP). +Stores the next address to execute before unconditionally updating the program counter (\fIpc\fP). This instruction is usually used to invoke subroutines, which use the \fBJMP2r\fP to return. When \fIx\fP is a byte, it is treated as relative (\fBpc += x\fP) and when \fIx\fP is a short it is treated as absolute (\fBpc = x\fP). + +The saved address will always be a short regardless of \fIshort mode\fP. .SS STH ( x -- [x] ) @@ -294,11 +300,11 @@ Compute the bitwise exclusive-or (\fIxor\fP) of the top two values of the stack. Compute a bit shift of the second value of the stack; the directions and distances are determined by the top value of the stack. -Given a byte \fIrl\fP consisting of a low nibble (\fIl\fP) and a high nibble (\fIh\fP), this instruction shifts \fIx\fP left by \fIl\fP and then right by \fIr\fP. +Given a byte \fIrl\fP consisting of a low nibble (\fIl\fP) and a high nibble (\fIr\fP), this instruction shifts \fIx\fP left by \fIl\fP and then right by \fIr\fP. -Right shifts are unsigned (they introduce zero bits); there are no signed shifts. +Right shifts are unsigned (they introduce zero bits). There are no signed shifts. -Since the largest values (\fIshort\fP) are 16-bit, one nibble (\fB0x0 - 0xf\fP) is sufficient to express all useful left or right shifts. +For 16-bit (and 8-bit) values, one nibble (\fB0x0 - 0xf\fP) is sufficient to express all useful left or right shifts. Right: \fB#ff #03 SFT\fP evaluates to \fB0x1f\fP Left: \fB#ff #20 SFT\fP evaluates to \fB0xfc\fP @@ -341,7 +347,7 @@ The "literal" instructions are used to push new data onto the stacks. They inter (The instruction pointer will be moved forward 1-2 bytes, past the literal data.) -Literal values can be updated dynamically using store: +Literal values can be updated dynamically using store instructions: #abcd ;x STA2 ( later on... )