QuaRchitecture Reference

Instruction Set Architecture

Instruction Encoding

In the physical layer (as encoded in the QR code in alphanumeric mode), two characters are encoded in 11 bits: so 5.5 bits per character. This 31% less space than two characters stored in byte-mode.

Each machine instruction consists of an opcode character, followed by an optional argument. The argument is a 1-3 signed or unsigned number encoded in base 44.

Opcodes

Encoding Opcode Stack Effect Description
Arithmetic
0 inc (n -- n) Increment top of stack
1 dec (n -- n) Decrement top of stack
2 neg (n -- n) Negate top of stack
3 add (n n -- n) Add two numbers
4 sub (n n -- n) Subtract top of stack from next of stack
5 mul (n n -- n) Multiply two number on top of stack
6 div (n n -- n) Divide second on stack by top of stack
7 mod (n n -- n) Push remainder from division of second on stack by top of stack
Bitwise
8 not (n -- n) Complement top of stack
9 shl (n n -- n) Bitwise shift left
A shr (n n -- n) Bitwise shift right
B xor (n n -- n) Exclusive or
C or (n n -- n) Or
D and (n n -- n) Bitwise and
Conditionals
E z ? <op> (cnd -- ) Execute next op if zero, else skip
F nz ? <op> (cnd -- ) Execute next op if not zero, else skip
G m ? <op> (cnd -- ) Execute next op if minus, else skip
H p ? <op> (cnd -- ) Execute next op if positive, else skip
Control Flow
I ret (--)
R(pc -- )
Return from subroutine call. Pop and continue execution from address on return stack
J <s1>
K <u2>
jmp <dst> ( -- ) Jump to dst. Dst is either a signed 1char relative offset, or unsigned absolute address
L <s1>
M <u2>
call <dst> R(-- nxt) Call subroutine at dst, pushing the address of the subsequent instruction to be executed on subroutine return on the return stack. Dst is either a signed 1char relative offset, or unsigned absolute address.
N <s1> loop <dst> i > 0:
R(i -- i-1)
else:
R(i -- )
Decrement top of return stack. If greater than 0, jump to dst. Else, drop top of return stack. Dst is a signed 1char relative offset
Load & Store
O <s1>
P <s2>
Q <s3>
ldi ( -- n ) Load an immediate signed number argument onto the stack
R ld (addr -- n) Load a number from the address specified by top of stack
S st (val addr -- n) Store a value at address specified by top of stack
T <u1> ldz <i> (--) Load from immediate offset in zero-page
U <u1> stz <i> (val --) Store to immediate offset in zero-page
V ldp (offset --) Load* from offset in program memory
W st ( val addr -- ) Store value at given memory address
Stackrobatics
X dup (n -- n n) Duplicate top of stack
Y drop (n --) Drop top of stack
Z over (a b -- a b a) Push second on stack
_ swap (a b -- b a) Swap the top two items on the stack
$ nip ( a b -- b ) Drop second on stack
$ rot (a b c -- b c a) Rotate top 3 elements on stack
% rtop (-- n) Push a copy of the top of the return stack
* tos ( -- n)
R( n -- )
Move the top of the return stack to the data stack
+ tor ( n -- )
R( -- n )
Move top of the data stack to the return stack
rdrop r( n -- ) X Drop top of return stack
Control Flow
nop ( -- ) X No operation
hlt ( -- ) X Halt the system
sys ( ... n -- ... ) X Execute a system call n

System Calls

Name Code Stack Effect Description
INCHAR 0 ( -- c) Input a char from stdin
OUTCHAR 1 (c 1 --) Output a character to stdout
OUTNUM 2 (n --) Output a number to stdout
DRAWDOT 3 (x y 3 --) Draw dot on canvas
RANDINT 4 (max 4 -- n) Generate a random number between 0..max

Assembler

The assembler converts a program text into its encoded form. In listing form, the space " " character may be substituted for an underscore "_" for clarity. This is not substituted in the binary output.

Labels

The assembler supports labels. A label l1 can be defined and referenced in arguments to instructions:

l1:
  jmp l1
        

Labels may be redefined. Forward references are also supported:

  call hop
  ldi 3
hop:
  dup
        

Forward references may be encoded non-optimally (specifically, they will use the 2-character absolute encoding of a branch instruction).

Directives

A number of assembler directives are available:

Directive Description
res n Reserve n bytes, filling with nop
equ <name>, <val> Assign a number to a name, which can be substitued later
equ <name>, <val> Assign a number to a name, which can be substitued later
const n1[, n2, n3, ...] Store constant value(s) at the end of program memory. The address of the value(s) in program memory can be referenced by <name>