Instruction set

QCPU 2 5-3-2-3-3 reference

QCPU 2 Short Description Representation Notes
00000-DDD-00-SSS-SSS add Addition rd = rs + rs
00000-DDD-01-SSS-SSS addc Addition with carry rd = rs + rs + 1 if carry carry from previous op
00000-DDD-10-SSS-SSS sub Subtraction rd = rs - rs
00000-DDD-11-SSS-SSS subb Subtraction with borrow rd = rs - rs - 1 if not carry carry from previous op
00001-WWW-IIIIIIII addi Addition with sign ext. immediate rd = rd + imm
00010-SSS-IIIIIIII cmpi Comparison with sign ext. immediate, flags only zr = rs - imm
00011-DDD-00-IIIIII csrr Control & Status Register read rd = csr
00011-SSS-01-IIIIII csrw Control & Status Register write csr = rs
00011-DDD-10-SSS-SSS slt Set one if less than register rd = 1 if rs < rs sign bit, greater than or equal to with xori rd, 1
00011-DDD-11-SSS-SSS sltu Set one if less than register unsigned rd = 1 if rs < rs carry bit, greater than or equal to with xori rd, 1
00100-DDD-00-SSS-SSS szr Select register if register is zero rd = rs if rs == 0 leaves rd intact if rs != 0; use clr for zero
00100-DDD-01-SSS-SSS ior Bitwise incl. OR (insert bits) rd = rs | rs
00100-DDD-10-SSS-SSS and Bitwise ADD (mask bits) rd = rs & rs
00100-DDD-11-SSS-SSS xor Bitwise excl. OR (toggle bits) rd = rs ^ rs
00101-WWW-IIIIIIII iori Bitwise incl. OR with sign ext. immediate rd = rd | imm
00110-WWW-IIIIIIII ioriu Bitwise incl. OR with immediate rd = rd | uimm
00111-WWW-IIIIIIII andi Bitwise AND with sign ext. immediate rd = rd & imm
01000-WWW-IIIIIIII andiu Bitwise AND with immediate rd = rd & uimm
01001-SSS-IIIIIIII biti Bitwise AND with immediate, flags only zr = rs & uimm
01010-WWW-IIIIIIII xori Bitwise excl. OR with sign ext. immediate rd = rd ^ imm
01011-WWW-IIIIIIII xoriu Bitwise excl. OR with immediate rd = rd ^ uimm
01100-DDD-0LLLL-SSS bsl Barrel shift left rd = rs << l
01100-DDD-1RRRR-SSS bsr Barrel shift right rd = rs >> r
01101-DDD-0RRRR-SSS bsrs Barrel shift right preserving sign rd = rs >> r preserve sign
01101-DDD-1RRRR-SSS brr Barrel rotate right rd = rs >> r | rs << -r
01110-DDD-00-SSS-SSS bsld Barrel shift left from register rd = rs << rs
01110-DDD-01-SSS-SSS bsrd Barrel shift right from register rd = rs >> rs
01110-DDD-10-SSS-SSS bsrsd Barrel shift right preserving sign from register rd = rs >> rs preserve sign
01110-DDD-11-SSS-SSS brrd Barrel rotate right from register rd = rs >> rs | rs << -rs
01111-DDD-00-SSS-SSS
01111-DDD-01-SSS-SSS
01111-DDD-10-SSS-SSS
01111-DDD-11-SSS-SSS
10000-DDD-IIIIIIII lli Load lower sign ext. immediate rd = imm unsigned with andiu rd, 0xFF
10001-DDD-IIIIIIII lui Load upper immediate rd = uimm << 8 full immediate is lui + ioriu
10010-IIIIIIIIIII jmp Jump ip = imm << 5 32 byte aligned
10011-IIIIIIIIIII jmpl Jump and link ip = imm << 5; rp = ip 32 byte aligned
10100-IIIIIIIIIII jmpr Jump relative ip += imm << 1 range of +- 2 KiB (2 byte aligned)
10101-IIIIIIIIIII jmprl Jump relative and link ip += imm << 1; rp = ip range of +- 2 KiB (2 byte aligned)
10110-SSS-FFFFFFFF jmpd Jump to register ip = rs
10111-SSS-FFFFFFFF jmpdl Jump to register and link ip = rs; rp = ip
11000-CCC-IIIIIIII brh Branch ip += imm << 1 if condition range of +- 256 b (2 byte aligned)
11001-IIIIIIIIIII prfi Prefetch instructions relative poke pc + (imm << 5) full range (32 byte aligned)
11010-DDD-IIIII-SSS mld Memory load with immediate rd = *(rs + uimm) sign ext. rd rd = zr is prefetch, range uimm +32 B, async, cut8
11011-DDD-IIIII-SSS mldw Memory load word with immediate rd = *(rs + (uimm << 1)) rd = zr is prefetch, range uimm +64 B, async, LE
11100-SSS-IIIII-SSS mst Memory store with immediate *(rs + uimm) = rs rs = zr is clear, range uimm +32 B, async
11101-SSS-IIIII-SSS mstw Memory store word with immediate *(rs + (uimm << 1)) = rs rs = zr is clear, range uimm +64 B, async, LE
11110-WWW-IIIII-SSS xch Memory atomic exchange with immediate *(rs + uimm) = rs; rs = *(rs + uimm) sign ext. rs rd = zr is clear, range uimm +32 B, async, cut8
11111-WWW-IIIII-SSS xchw Memory atomic exchange word with immediate *(rs + (uimm << 1)) = rs; rs = *(rs + (uimm << 1)) rd = zr is clear, range uimm +64 B, async, LE
QCPU 2 Short Description Translation Notes
00000-000-00-000-000 bkpt * Breakpoint add 0, 0, 0
00000-DDD-00-SSS-000 mov Move register to register add rd, rs, 0
00000-000-00-SSS-000 test Test register in ALU add 0, rs, 0
00000-DDD-10-000-SSS neg Negation sub rd, 0, rs
00000-000-10-SSS-SSS cmp Comparison sub 0, rs, rs
00001-000-00000000 nop * No operation (disables flags) addi 0, 0
00001-DDD-00000001 inc Increment addi rd, 1
00001-DDD-11111111 dec Decrement addi rd, -1
00001-010-IIIIIIII alloc Allocate (stack) addi sp, x
00011-DDD-00-XXXXXX ip Instruction pointer csrr, rd, ip
00011-000-01-XXXXXX clri Clear interrupt csrw, 0, pen
00011-DDD-10-SSS-000 sneg One if register is negative slt rd, rs, 0
00011-DDD-10-000-SSS spos One if register is positive (non-zero) slt rd, 0, rs
00011-DDD-11-000-SSS snez One if register is not zero sltu rd, 0, rs
01000-000-00001111 cut4 Cut register to 4 bit andiu rd, 0xF
01000-000-11111111 cut8 Cut register to 8 bit andiu rd, 0xFF
01000-000-00000000 clrl Clear lower register andiu rd, 0
01010-WWW-11111111 not Bitwise NOT xori rd, -1
01011-WWW-11111111 not8 Bitwise NOT lower 8 bit xoriu rd, -1
10001-000-00000000 clr Register clear lui rd, 0
10110-000-IIIIIIII sysc * System call jmpd 0, x
10110-001-00000000 ret Return jmpd rp, 0
10111-000-00000001 fence * Fence memory writes and reads jmpdl 0, 1
10111-000-00000010 ftlb * Flush TLB (after next jump) jmpdl 0, 2
10111-000-00000100 rfi * Return from interrupt jmpdl 0, 4
10111-000-00001000 wfi * Sleep until interrupt jmpdl 0, 8
10111-000-00010000 scf * Set carry flag jmpdl 0, 16
10111-000-00100000 rscf * Reset carry flag jmpdl 0, 32
10111-000-01000000 jmpdl 0, 64
10111-000-10000000 jmpdl 0, 128
11011-000-IIIII-SSS prfd Prefetch data mldw 0, rs, x
11100-000-IIIII-SSS mclr Memory clear mst 0, rs, x
11101-000-IIIII-SSS mclrw Memory clear word mstw 0, rs, x

*: special behaviour encoded in control.

QCPU 2 Usage Description Notes
u8 uint u8 255, u8 @var Unsigned byte
u16 uint u16 65535, u16 @var Unsigned word
u24 uint u24 16777215, u24 @var Unsigned 24 bit word
u32 uint u32 4294967295, u32 @var Unsigned 32 bit word
i8 int i8 -128, i8 @var Signed byte
i16 int i16 -32768, i16 @var Signed word
i24 int i24 -8388608, u24 @var Signed 24 bit word
i32 int i32 -2147483648, u32 @var Signed 32 bit word
reserve type[, amt] reserve u8, 256, reserve u8, @len Reserve opaque space must be analysis-known
ascii text[, sen] ascii "Hello word!", ascii "Cstr" 0 ASCII text must be analysis-known
  • S: register source 1 and/or 2
  • D: register destination
  • W: source and writeback register
  • I: immediate
  • C: condition
  • L/R: left/right shift amount
  • F: flags
Set Register Identifier Size
Special Purpose ip (instruction ptr, 2 bytes aligned) 15 bits
Special Purpose fl (flags) 4 bits
r0 zr (zero) 16 bits
General Purpose/Async r1 rp (return ptr) 16 bits
General Purpose/Async r2 sp (stack ptr) 16 bits
General Purpose/Async r3 x1 (argument 1/return) 16 bits
General Purpose/Async r4 x2 (argument 2/return) 16 bits
General Purpose/Async r5 x3 (argument 3/return) 16 bits
General Purpose/Async r6 t1 (temporary) 16 bits
General Purpose/Async r7 t2 (temporary) 16 bits

Special Purpose Registers (SPRs) can be accessed using the CSR (Control & Status Register) interface. Additionally, configuration and read-only registers are accessed using the CSRs, like the interrupt interface and virtual memory configuration.

In the ABI, it’s the callee’s responsibility to save any register it clobbers. This way, subroutine epiloques perform the load from memory as soon as possible to make use of asynchronous memory. GPRs (General Purpose Registers) include an ‘async resolved’ bit. A pipeline bubble is inserted when a sourcing instruction attempts to read from a register where memory hasn’t resolved yet, and a fault interrupt is signalled when a destination instruction attempts to write to such a register.

A rp (return pointer) doesn’t have to be stored to memory when the subroutine layer doesn’t include calls to subroutines itself. Interrupts save the existing rp to memory and the interrupt return address is retrieved from a CSR.

Arithmetic and logical instructions writing to zr are considered a flags-only nop, unless the control unit routes the logic otherwise.

Flags Name Representation
000 c if overflow || underflow
001 s if signed
010 z if acc == 0
011
100 nc if !(overflow || underflow)
101 ns if !signed
110 nz if acc != 0
111
fetch fetch decode execute memory writeback
Fetch 1 Fetch 2 Decode Execute Memory Writeback