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 |