Down one more level
Real emulators are written close to the metal. Write the toy CPU's decoder in RISC-V: the same shifts and masks you used in JavaScript, now as srli and andi — and a branch to classify jump instructions.
Shift, then mask
# The toy ISA: op (bits 15-12) | r (11-10) | s (9-8) | n (7-0) # op_of(a0 = word) -> a0 = the operation number op_of: srli a0, a0, 12 ret # reg_of(a0 = word) -> a0 = the register field r reg_of: srli a0, a0, 10 andi a0, a0, 3 ret # imm_of(a0 = word) -> a0 = the 8-bit number n imm_of: andi a0, a0, 255 ret # is_jump(a0 = word) -> 1 for JMP, JZ or JNZ (ops 4, 5, 6), else 0 is_jump: srli t0, a0, 12 li a0, 0 li t1, 4 blt t0, t1, not_jump li t1, 6 bgt t0, t1, not_jump li a0, 1 not_jump: ret