## Architecture
32 bit instruction width/word size

## Instruction Types:

Type Sizes: 
  - u16: [16 bits]
  - u6: [6 bits]
  - Reg: [5 bits]
  - Opcode: [6 bits]
  
Instruction Types:
  - R: [Opcode] [Reg] [Reg] [Reg] [Reg] [u6]
  - I: [Opcode] [Reg] [Reg] [u16           ]

## Instruction Set

// move
mov  <src: Reg> <dst: Reg> [ unused ]
cmov <src: Reg> <dst: Reg> <cmp: Reg>

// load
ldb  <src: Reg> <dst: Reg> <offset: u16>
ldbs <src: Reg> <dst: Reg> <offset: u16>
ldh  <src: Reg> <dst: Reg> <offset: u16>
ldhs <src: Reg> <dst: Reg> <offset: u16>
ldw  <src: Reg> <dst: Reg> <offset: u16>

// store
stb <src: Reg> <dst: Reg> <offset: u16>
sth <src: Reg> <dst: Reg> <offset: u16>
stw <src: Reg> <dst: Reg> <offset: u16>

// immediate
lli <dst: Reg> [unused] <imm: u16>
lui <dst: Reg> [unused] <imm: u16>  

// comparison
ieq <sr1: Reg> <sr2: Reg> <dst: Reg> [unused]
ine <sr1: Reg> <sr2: Reg> <dst: Reg> [unused]
igt <sr1: Reg> <sr2: Reg> <dst: Reg> [unused]
ige <sr1: Reg> <sr2: Reg> <dst: Reg> [unused]
ilt <sr1: Reg> <sr2: Reg> <dst: Reg> [unused]
ile <sr1: Reg> <sr2: Reg> <dst: Reg> [unused]

// Jump
jmp [ unused ] <addr: Reg> <offset: u16> // unconditional

jez <cmp: Reg> <addr: Reg> <offset: u16> // conditional on cmp == 0
jnz <cmp: Reg> <addr: Reg> <offset: u16>

jic [ unused ] <addr: Reg> <offset: u16> // conditional on carry
jnc [ unused ] <addr: Reg> <offset: u16>

// Bitwise
and <sr1: Reg> <sr2: Reg> <dst: Reg> [unused] // and
nnd <sr1: Reg> <sr2: Reg> <dst: Reg> [unused] // nand
or  <sr1: Reg> <sr2: Reg> <dst: Reg> [unused] // or
nor <sr1: Reg> <sr2: Reg> <dst: Reg> [unused] // nor
xor <sr1: Reg> <sr2: Reg> <dst: Reg> [unused] // xor
xnr <sr1: Reg> <sr2: Reg> <dst: Reg> [unused] // xnor
not <src: Reg> [ unused ] <dst: Reg> [unused] // not

// Arithmetic
add <sr1: Reg> <sr2: Reg> <dst: Reg>
sub <sr1: Reg> <sr2: Reg> <dst: Reg>
shl <src: Reg> <rshamt: Reg> <dst: Reg> <ishamt: u6> // left shift of rshamt+ishamt
shr <src: Reg> <rshamt: Reg> <dst: Reg> <ishamt: u6> // right shift

// Immediate Arithmetic
addi <sr1: Reg> <dst: Reg> <imm: u16>
subi <sr1: Reg> <dst: Reg> <imm: u16>

// Misc
nop (zero/do nothing)
int <imm16: u16>
irt
hlt

// Atomic

// Atomic Compare and Swap - compares src and dst, if src
acs <src: Reg> <cmp: Reg> <dst: Reg> <res: Reg>

## Assembler Pseudoinstructions
Definitions:
  Label - named address, a function or global

```
lwi <src: Label|Imm> <dest: Reg> // loads the literal value of Label|Imm into dest
  // if src is a Label, take literal value of Label
  => lli $src, $dest  
  => lui $src, $dest
lli <src: Label> <dest: Reg> // loads the lower 16 bits of the literal value of Label into dest
... -> similarly defined for lui

ldw <src: Label> <dest: Reg>     // loads the word at the address of Label into dest
... => similarly defined for ldb, ldbs, ldh, ldhs
  // load the label value of src into dest with lui/lli 
  => lli $src, $dest
  => lui $src, $dest
  => ldw $dest, $dest
  
stw <src: Reg> <dest: Label>     // stores the word in src using the address/label that is dest.
  // load the literal value of dest into the accumulator with lui/lli
  => lli $dest, acc
  => lui $dest, acc
  => stw $src, acc

jmp <dest: Label> 
  CASE dest > u16::MAX:
    => lli $dest, acc
    => lui $dest, acc
    => jmp $dest, 0
  CASE dest < u16::MAX:
    // assembler inserts the literal value of dest
    => jmp $dest, 0
    
jmp <lbl: Label> <dest: Reg>
  CASE lbl > u16::MAX:
    AssemblerError!
  CASE lbl < u16::MAX:
    => jmp $dest, lbl
    
call <addr: Label>
  => subi spr, 4, spr
  => stw pcx, spr, 0
  => jmp $addr
  
func
  // push bpr
  => subi spr, 4, spr
  => stw bpr, spr, 0
  // replace bpr with spr
  => mov spr, bpr
  
return
  => mov bpr, spr
  // pop bpr
  => addi spr, 4, spr
  => ldw spr, bpr, 0
  // load return addr
  => ldw spr, ret, 0
  => addi, spr, 4, spr
  => jmp ret, 4
  
```
