HAL opcode structure (close to RISC-V structure)
b0     +)
b1     m)
b2     8b) => 8-bit if set
b3     dir)
b4     &)
b5     i)
b6     16b) => 32-bit if set, 16-bit if unset
b11:7  rd (destination register)
b14:12 Zeroes (funct 3)
b19:15 rs1 (source register)
b24:20 rs2 (no meaning in HAL, but can temporarily hold a value)
b25    signed)
b27:26 Zeroes
b31:28 hbank index

See [hw/riscv] for general register assignment. There, it says that x10-x12 are
for temporary HAL variables. To avoid stepping on each other toes, here are
the policies for those registers:

x10: immediate loading, either from i) m) or +)
x11: source value "staging" register
x12: other uses that dont fit x10 or x11.

=) <>) <) >=) etc..
  b2:0 correspond to funct3, but b3 is special and handled by "brc," before
  orring the condition in. This bit indicates that we should swap rs1 and rs2.

rs1@ ( instr -- r )
rs2@ ( instr -- r )
  Get the specified fields in "instr".

rs1! ( instr r -- instr )
rs2! ( instr r -- instr )
funct3! ( instr n -- instr )
  Set the specified fields in "instr".

rs1<>rs2 ( instr -- instr )
  Swap RS1 and RS2 fields.

Bimm! ( instr n -- instr )
  Encode n immediate so that it corresponds to the B-type encoding.
  Because it's supposed to encode a multiple of 2, "n" is divided by 2 before
  being encoded.

Iimm! ( instr n -- instr )
Simm! ( instr n -- instr )
  You get the idea...

dropf, ( -- )
  0001a203 lw) xTOS rd) xPSP base)
  00418193 addi) xPSP rd) xPSP rs1) 4 imm)

dropcmp, ( -- )
  Move W to xAcmp for brz, and brnz, then drop W.

  00020e13 mv) xAcmp rd) xTOS rs1)

brci, ( a cond -- )
  Jump to absolute "a" if "cond" is met. Cannot be used with the "inverted"
  conditions (greater than 7).

op, ( instr op -- )
  merge operand with instr and write

imm, ( reg n -- )
  Write instructions setting register "reg" to number "n".

?inv ( instr op -- instr op )
  If HALINV is set, swap RD and RS2 and make load instr into a store.

sz! ( instr op -- instr op )
  Given a load/store instruction "instr", set its size according to "op".

loadstore, ( instr off op -- )
  Assuming that "off" fits in 12-bit, write the load/store instruction based on
  base instruction "instr" and depending on whether "op" has HALINV (load if no,
  store if yes).

@, ( op -- )
  One of the complexities here is the "big offset" case, a fetch with HALOFF not
  fitting in 12-bit. In that case, we load the offset in x11, add the source
  register to it, then use x11 as a base register for the load/store.

  00000003 lb) xZERO rd) xZERO base) 0 imm)

swp, ( op -- )
  Write an eor between operand's src and dereferenced dst.

  00004033 xor) xZERO rd) xZERO rs1) xZERO rs2)

@!, ( op -- )
  00058013 mv) xZERO rd) x11 rs1)

addn, ( reg n -- )
  Compile a add) of immediate "n" with target register
  Uses x10 as a staging register

  00000013 addi) xZERO rd) xZERO rs1) 0 imm)
  00a00033 add) xZERO rd) xZERO rs1) x10 rs2)

addrr, ( rd rs2 -- )
  Compile a add) of register Rs2 with target register

  00000033 add) xZERO rd) xZERO rs1) xZERO rs2)

?imm, ( op -- op )
  Checks if operand is i) or m). If it is, compile a write of this value to x10
  and modify operand in consequence

mvreg, ( rd rs1 -- )
  Write a mv) from operand's src to operand *dereferenced* dst. If operand has
  an offset, a add) is written after the mov).

  00000013 mv) xZERO rd) xZERO rs1)

zop, ( instr -- )
  Write "instr" followed by a mv) of its "rd" field to xAcmp, and 0 to xBcmp
  thus "setting" the Z flag.

shift, ( op instr -- )
  Write shift instruction with base opcode "instr" with HAL operand "op".

ariZ, ( op instr -- )
  Write arithmetic instruction then "update Z flag"
  if b31 is set on x10, invert RS1 and RS2

  mul and /mod doesn't update flags
  special case for div, it also has to generate a mod

  00000e13 mv) xAcmp rd) xZERO rs1)
  00000e93 mv) xBcmp rd) xZERO rs1)

ari, ( op instr -- )
  Write arithmetic operation, that is:
  1. Load operand's src in x11
  2. Apply instr with operand's dst as Rd and Rs1 and x11 as Rs2.

  Write inverted arithmetic operation, that is:
  1. Load operand's src in x11
  2. Apply instr with x11 as Rd and Rs1 and operand's dst as Rs2.
  3. Store x11 in operand's src

  TODO: avoid step by encoding imm) directly when possible

swap-, ( op -- )
  the setting of b31 is *not* part of RISC-V. It's an internal flag we set for
  swapping rs1 and rs2 later on.

compare, ( op -- )
  Write compare operation, that is:
  1. Load operand's src in x11
  2. Apply instr with operand's dst as Rd and x11 as Rs1.

  same opcodes as ariZ,

+n, ( n operand -- )
  use x11 as a temp register to store value to add

  same opcodes as ariZ,

brr, ( op -- )
  000580e7 jalr) xRA rd) x11 rs1) 0 imm)

TODO: &) combined with +) are broken
br, ( op -- )
  00058067 jalr) xZERO rd) x11 rs1) 0 imm)

brc, ( op cond -- )
  we're going to write a branch instruction using the negation of the given cond
  this branch will jump over two instructions allowing to make the jump to the
  given address so if the cond is true, we wont jump over the jump instructions,
  and so we'll do the jump adding the conditional branch before the
  2-instructions jump, also force us to adjust by four the address

  01de0663 beq) xAcmp rs1) xBcmp rs2) 12 imm) \ jump over two instructions

br! ( br tgt -- )
  Need to read the targetted instructions to know which kind of jump/branch it
  is in order to be able to write the immediate correctly

C>W, ( cond -- )
  00000213 xW 0 li,
  01de0463 beq) xAcmp rs1) xBcmp rs2) \ jump over following instr
  00120213 addi) xW rd) xW rs1) 1 imm)

?rs1>x10, ( op -- op )
  Maybe move rs1 to x10 in the context of a le@, or be@, op.

  If op's rs1 is the same as rd or if HALOFF is set, compile a move of that
  register to x10 and set rs1 to x10.

le!, be!,
  _srl8, ( op -- ) shift dst right by 8

le@, be@,
  _x11+@, ( op off -- )
  _orr ( reg shift -- ) or left-shifted x11 in reg
  _16 ( op -- op )

## Range words

pre,
  00030e63 beq) xS rs1) xZERO rs2) 28 imm)

post,
  fff30313 subi) xS rd) xS rs1) 1 imm)
  fe0316e3 bne) xS rs1) xZERO rs2) -20 imm)

move,
  00022983 lw) x19 rd) xTOS base)
  0132a023 sw) x19 src) xA base)
  00420213 addi) xTOS rd) xTOS rs1) 4 imm)
  00428293 addi) xA rd) xA rs1) 4 imm)

wmove,
  00025983 lhu) x19 rd) xTOS base)
  01329023 sh) x19 src) xA base)
  00220213 addi) xTOS rd) xTOS rs1) 2 imm)
  00228293 addi) xA rd) xA rs1) 2 imm)

cmove,
  00024983 lbu) x19 rd) xTOS base)
  01328023 sb) x19 src) xA base)
  00120213 addi) xTOS rd) xTOS rs1) 1 imm)
  00128293 addi) xA rd) xA rs1) 1 imm)

pre,
  00000e13 xAcmp 0 li,
  00000e93 xBcmp 0 li,
  02030063 beq) xS rs1) xZERO rs2) 32 imm)

post,
  fff30313 subi) xS rd) xS rs1) 1 imm)
  01de1463 bne) xAcmp rs1) xBcmp rs2) 8 imm)
  fe0314e3 bne) xS rs1) xZERO rs2) -24 imm)

[]=,
  00022e03 lw) xAcmp rd) xTOS base)
  0002ae83 lw) xBcmp rd) xA base)
  00420213 addi) xTOS rd) xTOS rs1) 4 imm)
  00428293 addi) xA rd) xA rs1) 4 imm)

w[]=,
  00025e03 lhu) xAcmp rd) xTOS base)
  0002de83 lhu) xBcmp rd) xA base)
  00220213 addi) xTOS rd) xTOS rs1) 2 imm)
  00228293 addi) xA rd) xA rs1) 2 imm)

c[]=,
  00024e03 lbu) xAcmp rd) xTOS base)
  0002ce83 lbu) xBcmp rd) xA base)
  00120213 addi) xTOS rd) xTOS rs1) 1 imm)
  00128293 addi) xA rd) xA rs1) 1 imm)

pre,
  00020e13 mv) xAcmp rd) xTOS rs1)
  001e0e93 addi) xBcmp rd) xAcmp rs1) 1 imm)
  02030063 beq) xS rs1) xZERO rs2) 32 imm)
  00030993 mv) x19 rd) xS rs1)

post,
  01de0663 beq) xAcmp rs1) xBcmp rs2) 12 imm)
  fff98993 subi) x19 rd) x19 rs1) 1 imm)
  fe0998e3 bne) x19 rs1) xZERO rs2) -16 imm)
  41330333 sub) xS rd) xS rs1) x19 rs2)

idx,
  0002ae83 lw) xBcmp rd) xA base)
  00428293 addi) xA rd) xA rs1) 4 imm)

widx,
  0002de83 lhu) xBcmp rd) xA base)
  00228293 addi) xA rd) xA rs1) 2 imm)

cidx,
  0002ce83 lbu) xBcmp rd) xA base)
  00128293 addi) xA rd) xA rs1) 1 imm)

pre,
  00030a63 beq) xS rs1) xZERO rs2) 20 imm)

post,
  fff30313 subi) xS rd) xS rs1) 1 imm)
  fe031ae3 bne) xS rs1) xZERO rs2) -12 imm)

fill,
  0042a023 sw) xTOS src) xA base)
  00428293 addi) xA rd) xA rs1) 4 imm)

wfill,
  00429023 sh) xTOS src) xA base)
  00228293 addi) xA rd) xA rs1) 2 imm)

cfill,
  00428023 sb) xTOS src) xA base)
  00128293 addi) xA rd) xA rs1) 1 imm)
