The Þog of 2023-03-07 — Another Fantasy ISA

This is another yet-unnamed fantasy CPU instruction set inspired by RISC-V, MIPS, and Professor Bruce Jacob's RiSC-16. It has fixed-length 16 bit instructions, 7 general purpose registers, and a zero register.

Instruction Encoding

The eight registers directly available contain 16 bit, two's-compliment integers. The zero register always returns 0, and all writes to it are ignored. Whether an instruction's immediate value is interpreted as signed or unsigned depends on the opcode.

A fault will be triggered if the program counter or a SW/LW is not word-aligned.

F   E   D   C   B   A   9   8   7   6   5   4   3   2   1   0  Bit
├───┼───────────┼───────────┼───────────┼───────────────────┤
│ 0 │    rs2    │    rs1    │    rd     │      opcode       │  RRR Type
└───┴───────────┴───────────┴───────────┴───────────────────┘
F   E   D   C   B   A   9   8   7   6   5   4   3   2   1   0  Bit
├───────────────┼───────────┼───────────┼───────────────────┤
│     imm5      │    rs1    │    rd     │      opcode       │  RRI Type
└───────────────┴───────────┴───────────┴───────────────────┘
F   E   D   C   B   A   9   8   7   6   5   4   3   2   1   0  Bit
├───────────────────────────┼───────────┼───────────────────┤
│           imm8            │    rd     │      opcode       │  RI Type
└───────────────────────────┴───────────┴───────────────────┘

Opcodes

┌─────┬──┬───┬─────┐
│00000│00│RRR│  ADD│ rd := rs1 + rs2
├─────┼──┼───┼─────┤
│00001│01│RRR│  SUB│ rd := rs1 - rs2
├─────┼──┼───┼─────┤
│00010│02│RRR│  SLL│ rd := rs1 << rs2
├─────┼──┼───┼─────┤
│00011│03│RRR│  SRL│ rd := rs1 >>> rs2
├─────┼──┼───┼─────┤
│00100│04│RRR│  SRA│ rd := rs1 >> rs2
├─────┼──┼───┼─────┤
│00101│05│RRI│ ADDI│ rd := rs1 + (signed)imm5
├─────┼──┼───┼─────┤
│00110│06│RI │  LUI│ rd := imm8 << 8
├─────┼──┼───┼─────┤
│00111│07│RI │  LLI│ rd := (rd & 0xFF00) | imm8
└─────┴──┴───┴─────┘
┌─────┬──┬───┬─────┐
│01000│08│RRI│   SW│ *(u16)(rd + imm5) := rs1
├─────┼──┼───┼─────┤
│01001│09│RRI│   LW│ rd := *(u16)(rs1 + imm5)
├─────┼──┼───┼─────┤
│01010│0A│RRI│   SB│ *(u8)(rd + imm5) := rs1 & 0xFF
├─────┼──┼───┼─────┤
│01011│0B│RRI│   LB│ rd := *(u8)(rs1 + imm5)
├─────┼──┼───┼─────┤
│01100│0C│RRI│  LBU│ rd := *(i8)(rs1 + imm5)
├─────┼──┼───┼─────┤
│01101│0D│   │     │
│01110│0E│   │     │ Reserved
│01111│0F│   │     │
└─────┴──┴───┴─────┘
┌─────┬──┬───┬─────┐
│10000│10│RRR│  AND│ rd := rs1 & rs2
├─────┼──┼───┼─────┤
│10001│11│RRR│   OR│ rd := rs1 | rs2
├─────┼──┼───┼─────┤
│10010│12│RRR│  XOR│ rd := rs1 ^ rs2
└─────┴──┴───┴─────┘
┌─────┬──┬───┬─────┐
│10011│13│RRR│   EQ│ rd := rs1 == rs2
├─────┼──┼───┼─────┤
│10100│14│RRR│   GT│ rd := (signed)rs1 > (signed)rs2
├─────┼──┼───┼─────┤
│10101│15│RRR│   GE│ rd := (signed)rs1 >= (signed)rs2
├─────┼──┼───┼─────┤
│10110│16│RRR│  GTU│ rd := (unsigned)rs1 > (unsigned)rs2
├─────┼──┼───┼─────┤
│10111│17│RRR│  GEU│ rd := (unsigned)rs1 >= (unsigned)rs2
└─────┴──┴───┴─────┘
┌─────┬──┬───┬─────┐
│11000│18│RRR│  JLR│ rd := pc + 2; pc := rs1 + (signed)rs2
├─────┼──┼───┼─────┤
│11001│19│RI │  BNS│ if rd == 0 then pc := pc + (signed)(imm8 * 2)
├─────┼──┼───┼─────┤
│11010│1A│RI │   BS│ if rd != 0 then pc := pc + (signed)(imm8 * 2)
├─────┼──┼───┼─────┤
│11011│1B│   │     │ Reserved
└─────┴──┴───┴─────┘
┌─────┬──┬───┬─────┐
│11100│1C│RI │   SF│ csr[imm8] := rd
├─────┼──┼───┼─────┤
│11101│1D│RI │   LF│ rd := csr[imm8]
├─────┼──┼───┼─────┤
│11110│1E│RI │  SYC│ System call
├─────┼──┼───┼─────┤
│11111│1F│RI │  BRK│ Break to debugger/environment
└─────┴──┴───┴─────┘

Assembler Syntax

# routine that prints 'hello, world\n' to an imaginary uart
.org $0100
Start:
	li   r1, Hello
	addi r2, r0, 13
	addi r3, r0, 4  # the imaginary uart's address

@Loop:
	lbu  r4, r1, 0
	sb   r1, r4, 0
	addi r1, r1, 1
	addi r2, r2, -1
	eq   r4, r2, r0
	bns  r4, @Loop

	brk  $00


.org $0200
Hello:
	.ascii "hello, world"
	.byte $0a
┌───┬────────────────────────────────────────┐
│nop│                          add r0, r0, r0│
├───┼────────────────────────────────────────┤
│not│                            sub A, B, r0│
├───┼────────────────────────────────────────┤
│li │lui A, IMM & 0xFF00; lli A, IMM & 0x00FF│
└───┴────────────────────────────────────────┘

A reference assembler written in Lua will be available soon.