some updates
This commit is contained in:
parent
28f27e7fcf
commit
ebb6889d48
83
uxntal.1
83
uxntal.1
|
@ -29,7 +29,7 @@ There are also 256 bytes of device memory, which are used to interact with the v
|
||||||
|
|
||||||
There are 32 base values for opcodes:
|
There are 32 base values for opcodes:
|
||||||
|
|
||||||
0x00 \fB***\fP 0x08 \fBEQU\fP 0x10 \fBLDZ\fP 0x18 \fBADD\fP
|
0x00 \fBBRK*\fP 0x08 \fBEQU\fP 0x10 \fBLDZ\fP 0x18 \fBADD\fP
|
||||||
0x01 \fBINC\fP 0x09 \fBNEQ\fP 0x11 \fBSTZ\fP 0x19 \fBSUB\fP
|
0x01 \fBINC\fP 0x09 \fBNEQ\fP 0x11 \fBSTZ\fP 0x19 \fBSUB\fP
|
||||||
0x02 \fBPOP\fP 0x0a \fBGTH\fP 0x12 \fBLDR\fP 0x1a \fBMUL\fP
|
0x02 \fBPOP\fP 0x0a \fBGTH\fP 0x12 \fBLDR\fP 0x1a \fBMUL\fP
|
||||||
0x03 \fBNIP\fP 0x0b \fBLTH\fP 0x13 \fBSTR\fP 0x1b \fBDIV\fP
|
0x03 \fBNIP\fP 0x0b \fBLTH\fP 0x13 \fBSTR\fP 0x1b \fBDIV\fP
|
||||||
|
@ -40,9 +40,9 @@ There are 32 base values for opcodes:
|
||||||
|
|
||||||
The "complete" opcode's value can be derived by combining the base value with its flags.
|
The "complete" opcode's value can be derived by combining the base value with its flags.
|
||||||
|
|
||||||
For example, \fBADD2k\fP is \fB(0x18 | 0x20 | 0x80)\fP = \fB0xb8\fP.
|
For example, \fBADD2k\fP is \fB(ADD | 2 | k)\fP = \fB(0x18 | 0x20 | 0x80)\fP = \fB0xb8\fP.
|
||||||
|
|
||||||
Unlike other opcodes, \fB0x00\fP is contextual. Its meaning depends on the \fImode\fP bits provided:
|
Unlike other opcodes, \fB0x00\fP (\fBBRK*\fP) is contextual: its meaning depends on the \fImode\fP bits provided:
|
||||||
|
|
||||||
0x00 \fBBRK\fP 0x80 \fBLIT\fP
|
0x00 \fBBRK\fP 0x80 \fBLIT\fP
|
||||||
0x20 \fBJCI\fP 0xa0 \fBLIT2\fP
|
0x20 \fBJCI\fP 0xa0 \fBLIT2\fP
|
||||||
|
@ -51,6 +51,23 @@ Unlike other opcodes, \fB0x00\fP is contextual. Its meaning depends on the \fImo
|
||||||
|
|
||||||
.SH STACK EFFECTS
|
.SH STACK EFFECTS
|
||||||
|
|
||||||
|
.BR
|
||||||
|
|
||||||
|
.SS NOTATION
|
||||||
|
|
||||||
|
Given a stack effect \fB( a^ b^ c^ -- c^ a^ b^ )\fP here is what each symbol means:
|
||||||
|
|
||||||
|
\fB(\fP and \fB)\fP are comment delimiters
|
||||||
|
\fBa^\fP, \fBb^\fP, and \fBc^\fP are values on the stack
|
||||||
|
\fB^\fP indicates that each value is a \fIbyte\fP (\fB*\fP would indicate \fIshort\fP)
|
||||||
|
\fB--\fP separates the "before" and "after" of the stack effect
|
||||||
|
|
||||||
|
The effect here is to move the top byte of the stack below the next two bytes, which could be achieved with \fBROT ROT\fP.
|
||||||
|
|
||||||
|
By default stack effects describe the effect on \fBwst\fP. When \fBrst\fP is involved we use \fB[]\fP to differentiate the stacks. For example \fB( a* [b*] -- a+1* [b+1*] )\fP will increment the top short of both \fBwst\fP and \fBrst\fP.
|
||||||
|
|
||||||
|
.SS EFFECTS AND MODES
|
||||||
|
|
||||||
Regular instructions have a single stack effect which is modified in a predictable way by any additional modes.
|
Regular instructions have a single stack effect which is modified in a predictable way by any additional modes.
|
||||||
|
|
||||||
For example the generic effect for \fBADD\fP is ( x y -- x+y ). The eight combinations of modes have the following effects:
|
For example the generic effect for \fBADD\fP is ( x y -- x+y ). The eight combinations of modes have the following effects:
|
||||||
|
@ -70,6 +87,10 @@ In \fIreturn\fP mode the stacks are reversed. Effects on \fBwst\fP will instead
|
||||||
|
|
||||||
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\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.
|
||||||
|
|
||||||
|
.SS TERMINOLOGY
|
||||||
|
|
||||||
|
We consider the top of the stack to be the first value of the stack, and count back from there. For example, given the stack effect \fB( a b c -- )\fP we would say that \fBc\fP is the top of the stack, \fBb\fP is the second value (second from the top), and \fBa\fP is the third value (third from the top).
|
||||||
|
|
||||||
.SH REGULAR INSTRUCTIONS
|
.SH REGULAR INSTRUCTIONS
|
||||||
|
|
||||||
.BR
|
.BR
|
||||||
|
@ -77,66 +98,100 @@ In \fIkeep\fP mode all the values on the left-hand side of the stack effect will
|
||||||
.SS INC
|
.SS INC
|
||||||
( x -- x+1 )
|
( x -- x+1 )
|
||||||
|
|
||||||
|
Increment the top value of the stack by 1.
|
||||||
|
|
||||||
Overflow will be truncated, so \fB#ff INC\fP will evaluate to \fB0x00\fP.
|
Overflow will be truncated, so \fB#ff INC\fP will evaluate to \fB0x00\fP.
|
||||||
|
|
||||||
.SS POP
|
.SS POP
|
||||||
( x -- )
|
( x -- )
|
||||||
|
|
||||||
|
Remove the top value of the stack.
|
||||||
|
|
||||||
\fBPOPk\fP is guaranteed to have no effect (it will not change the stack).
|
\fBPOPk\fP is guaranteed to have no effect (it will not change the stack).
|
||||||
|
|
||||||
.SS NIP
|
.SS NIP
|
||||||
( x y -- y )
|
( x y -- y )
|
||||||
|
|
||||||
|
Remove the second value of the stack.
|
||||||
|
|
||||||
.SS SWP
|
.SS SWP
|
||||||
( x y -- y x )
|
( x y -- y x )
|
||||||
|
|
||||||
|
Swap the top two values of the stack.
|
||||||
|
|
||||||
.SS ROT
|
.SS ROT
|
||||||
( x y z -- y z x )
|
( x y z -- y z x )
|
||||||
|
|
||||||
|
Rotate the top three values of the stack. The lowest becomes the top and the others are each shifted down one place.
|
||||||
|
|
||||||
.SS DUP
|
.SS DUP
|
||||||
( x -- x x )
|
( x -- x x )
|
||||||
|
|
||||||
|
Place a copy of the top value of the stack on top of the stack.
|
||||||
|
|
||||||
.SS OVR
|
.SS OVR
|
||||||
( x y -- x y x )
|
( x y -- x y x )
|
||||||
|
|
||||||
|
Place a copy of the second value of the stack on top of the stack.
|
||||||
|
|
||||||
.SS EQU
|
.SS EQU
|
||||||
( x y -- x==y^ )
|
( x y -- x==y^ )
|
||||||
|
|
||||||
|
Test whether the top two values of the stack are equal.
|
||||||
|
|
||||||
Result is guaranteed to be boolean (\fB0x00\fP or \fB0x01\fP).
|
Result is guaranteed to be boolean (\fB0x00\fP or \fB0x01\fP).
|
||||||
|
|
||||||
.SS NEQ
|
.SS NEQ
|
||||||
( x y -- x!=y^ )
|
( x y -- x!=y^ )
|
||||||
|
|
||||||
|
Test whether the top two values of the stack are not equal.
|
||||||
|
|
||||||
Result is guaranteed to be boolean (\fB0x00\fP or \fB0x01\fP).
|
Result is guaranteed to be boolean (\fB0x00\fP or \fB0x01\fP).
|
||||||
|
|
||||||
.SS GTH
|
.SS GTH
|
||||||
( x y -- x>y^ )
|
( x y -- x>y^ )
|
||||||
|
|
||||||
|
Test whether the second value of the stack is greater than the top.
|
||||||
|
|
||||||
Result is guaranteed to be boolean (\fB0x00\fP or \fB0x01\fP).
|
Result is guaranteed to be boolean (\fB0x00\fP or \fB0x01\fP).
|
||||||
|
|
||||||
.SS LTH
|
.SS LTH
|
||||||
( x y -- x<y^ )
|
( x y -- x<y^ )
|
||||||
|
|
||||||
|
Test whether the second value of the stack is less than the top.
|
||||||
|
|
||||||
Result is guaranteed to be boolean (\fB0x00\fP or \fB0x01\fP).
|
Result is guaranteed to be boolean (\fB0x00\fP or \fB0x01\fP).
|
||||||
|
|
||||||
.SS JMP
|
.SS JMP
|
||||||
( x -- ; pc <- x )
|
( x -- ; pc <- x )
|
||||||
|
|
||||||
|
Jump to a location.
|
||||||
|
|
||||||
The program counter (\fIpc\fP) is unconditionally updated. 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 program counter (\fIpc\fP) is unconditionally updated. 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).
|
||||||
|
|
||||||
|
It is common to \fBJMP\fP with boolean bytes (0-1) to handle simple conditionals. For example:
|
||||||
|
|
||||||
|
@max ( x^ y^ -- max^ ) GTHk JMP SWP POP JMP2r
|
||||||
|
|
||||||
.SS JCN
|
.SS JCN
|
||||||
( x bool^ -- ; pc <- x if bool )
|
( x bool^ -- ; pc <- x if bool )
|
||||||
|
|
||||||
|
Jump to a location when a condition is true.
|
||||||
|
|
||||||
The program counter (\fIpc\fP) is updated when \fIbool\fP is non-zero. 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 program counter (\fIpc\fP) is updated when \fIbool\fP is non-zero. 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).
|
||||||
|
|
||||||
.SS JSR
|
.SS JSR
|
||||||
( x -- [pc+1*] )
|
( x -- [pc+1*] )
|
||||||
|
|
||||||
|
Jump to a location, saving a reference to the current program counter.
|
||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
.SS STH
|
.SS STH
|
||||||
( x -- [x] )
|
( x -- [x] )
|
||||||
|
|
||||||
|
Move the top value of the stack to the return stack.
|
||||||
|
|
||||||
.SS LDZ
|
.SS LDZ
|
||||||
( zp^ -- x )
|
( zp^ -- x )
|
||||||
|
|
||||||
|
@ -188,21 +243,29 @@ Writing to some ports may have an effect on the underlying VM; in other cases it
|
||||||
.SS ADD
|
.SS ADD
|
||||||
( x y -- x+y )
|
( x y -- x+y )
|
||||||
|
|
||||||
|
Add the top two values of the stack.
|
||||||
|
|
||||||
Overflow will be truncated, so \fB#ff #03 ADD\fP will evaluate to \fB0x02\fP.
|
Overflow will be truncated, so \fB#ff #03 ADD\fP will evaluate to \fB0x02\fP.
|
||||||
|
|
||||||
.SS SUB
|
.SS SUB
|
||||||
( x y -- x-y )
|
( x y -- x-y )
|
||||||
|
|
||||||
|
Subtract the top of the stack from the second value of the stack.
|
||||||
|
|
||||||
Underflow will be truncated, so \fB#01 #03 SUB\fP will evaluate to \fB0xfe\fP.
|
Underflow will be truncated, so \fB#01 #03 SUB\fP will evaluate to \fB0xfe\fP.
|
||||||
|
|
||||||
.SS MUL
|
.SS MUL
|
||||||
( x y -- xy )
|
( x y -- xy )
|
||||||
|
|
||||||
|
Multiply the top two values of the stack.
|
||||||
|
|
||||||
Overflow will be truncated, so \fB#11 #11 MUL\fP will evaluate to \fB0x21\fP.
|
Overflow will be truncated, so \fB#11 #11 MUL\fP will evaluate to \fB0x21\fP.
|
||||||
|
|
||||||
.SS DIV
|
.SS DIV
|
||||||
( x y -- x/y )
|
( x y -- x/y )
|
||||||
|
|
||||||
|
Divide the second value of the stack by the top of the stack.
|
||||||
|
|
||||||
\fBDIV\fP implements \fIEuclidean division\fP, which is also known as \fIinteger division\fP. It returns whole numbers, so \fB#08 #09 DIV\fP evaluates to \fB0x00\fP.
|
\fBDIV\fP implements \fIEuclidean division\fP, which is also known as \fIinteger division\fP. It returns whole numbers, so \fB#08 #09 DIV\fP evaluates to \fB0x00\fP.
|
||||||
|
|
||||||
Division by zero will return zero (instead of signaling an error).
|
Division by zero will return zero (instead of signaling an error).
|
||||||
|
@ -214,15 +277,23 @@ There is no \fIremainder\fP instruction, but the phrase \fBDIVk MUL SUB\fP can b
|
||||||
.SS AND
|
.SS AND
|
||||||
( x y -- x&y )
|
( x y -- x&y )
|
||||||
|
|
||||||
|
Compute the bitwise union of the top two values of the stack.
|
||||||
|
|
||||||
.SS ORA
|
.SS ORA
|
||||||
( x y -- x|y )
|
( x y -- x|y )
|
||||||
|
|
||||||
|
Compute the bitwise intersection of the top two values of the stack.
|
||||||
|
|
||||||
.SS EOR
|
.SS EOR
|
||||||
( x y -- x^y )
|
( x y -- x^y )
|
||||||
|
|
||||||
|
Compute the bitwise exclusive-or (\fIxor\fP) of the top two values of the stack.
|
||||||
|
|
||||||
.SS SFT
|
.SS SFT
|
||||||
( x rl^ -- (x>>l)<<r )
|
( x rl^ -- (x>>l)<<r )
|
||||||
|
|
||||||
|
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 (\fIh\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.
|
||||||
|
@ -245,8 +316,8 @@ The break instruction is used to end a vector call and return control to the vir
|
||||||
|
|
||||||
The "immediate jump" instructions are produced by the assembler. They interpret the next 2 bytes of the ROM as a relative address (\fIaddr\fP) and have the following effects:
|
The "immediate jump" instructions are produced by the assembler. They interpret the next 2 bytes of the ROM as a relative address (\fIaddr\fP) and have the following effects:
|
||||||
|
|
||||||
\fBJMI\fP ( -- ) jump to \fIaddr\fP unconditionally
|
\fBJMI\fP ( -- ) jump to \fIaddr\fP unconditionally
|
||||||
\fBJCI\fP ( bool^ -- ) jump to \fIaddr\fP if \fIbool\fP is non-zero
|
\fBJCI\fP ( bool^ -- ) jump to \fIaddr\fP if \fIbool\fP is non-zero
|
||||||
\fBJSI\fP ( -- [pc*] ) jump to \fIaddr\fP saving the current address (\fIpc\fP) on the return stack
|
\fBJSI\fP ( -- [pc*] ) jump to \fIaddr\fP saving the current address (\fIpc\fP) on the return stack
|
||||||
|
|
||||||
(The instruction pointer will be moved forward 2 bytes, past the relative address.)
|
(The instruction pointer will be moved forward 2 bytes, past the relative address.)
|
||||||
|
@ -259,6 +330,8 @@ These instructions are created by the assembler from special syntax:
|
||||||
|
|
||||||
.SS LIT, LIT2, LITr, and LIT2r
|
.SS LIT, LIT2, LITr, and LIT2r
|
||||||
|
|
||||||
|
Push a literal value on the stack.
|
||||||
|
|
||||||
The "literal" instructions are used to push new data onto the stacks. They interpret the next 1-2 bytes of the ROM (\fIwx\fP, \fIwxyz\fP) as data and push it onto the corresponding stack:
|
The "literal" instructions are used to push new data onto the stacks. They interpret the next 1-2 bytes of the ROM (\fIwx\fP, \fIwxyz\fP) as data and push it onto the corresponding stack:
|
||||||
|
|
||||||
\fBLIT\fP ( -- wx^ ) push literal byte \fIwx\fP onto the \fBwst\fP
|
\fBLIT\fP ( -- wx^ ) push literal byte \fIwx\fP onto the \fBwst\fP
|
||||||
|
|
Loading…
Reference in New Issue