# SubV This is a wip clone of [SubX][mu] for the RISC-V RV31I base ISA. $ out.elf $ ./qemu.sh out.elf ## Status Features: - ELF output: ✔️ - Free arg order: ❌ - SubX cross-asm: ❌ Instruction Groups: - OP-IMM: ✔️✔️ - OP: ✔️❌ - LUI: ✔️✔️ - AIUPC: ✔️❌ - JAL: ✔️✔️ - JALR: ✔️❌ - BRANCH: ❌❌ - LOAD: ✔️❌ - STORE: ✔️✔️ (✔️❌: implemented but untested) ## Pipeline back to front: - `elf.py`: takes hex bytes and segment headers, outputs an ELF file - `pack.py`: packs bitfields (`3/3 1/1 f/4`) into hex bytes (`fb`) - `format.py`: bit-packs ops into ISA format - `survey.py`: replaces label references by their addresses - `validate.py`: checks op-arguments and puts them into canonical order and now front to back with a little example: $ ./validate.py ex.valid $ ./survey.py ex.survey $ ./format.py ex.format $ ./pack.py ex.pack $ ./elf.py ex.elf $ ./qemu.sh ex.elf `ex.subv`: hand-writable. == code 0x80000000 # repeatedly print "Hi\\n" main: # load 0x10010000 (UART0) into t0 37/lui 5/rd/t0 0x10010/imm20 # store 0x48 (H) in UART0+0 13/opi 0/subop/add 6/rd/t1 0/rs/x0 48/imm12 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 # store 0x69 (i) in UART0+0 13/opi 0/subop/add 6/rd/t1 0/rs/x0 69/imm12 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 # store 0x0a (\n) in UART0+0 13/opi 0/subop/add 6/rd/t1 0/rs/x0 0a/imm12 23/store 2/subop/word 5/rs/t0 6/rs/t1 0/off12 # jump back up to the top 6f/jal 0/rd/x0 main/off21 `ex.format`: mnemonics validated and discarded == code 0x80000000 # repeatedly print "Hi\n" main: # load 0x10010000 (UART0) into t0 37/u 05/rd 10010/imm20 # store 0x48 (H) in UART0+0 13/i 0/subop 6/rd 0/rs 48/imm12 23/s 2/subop 5/rs2 6/rs1 0/off12 # store 0x69 (i) in UART0+0 13/i 0/subop 6/rd 0/rs 69/imm12 23/s 2/subop 5/rs2 6/rs1 0/off12 # store 0x0a (\n) in UART0+0 13/i 0/subop 6/rd 0/rs 0a/imm12 23/s 2/subop 5/rs2 6/rs1 0/off12 # jump back up to the top 6f/j 0/4d main/off21 `ex.survey`: references resolved and labels removed == code 0x80000000 # repeatedly print "Hi\n" # main: # load 0x10010000 (UART0) into t0 37/u 05/rd 10010/imm20 # store 0x48 (H) in UART0+0 13/i 0/subop 6/rd 0/rs 48/imm12 23/s 2/subop 5/rs2 6/rs1 0/off12 # store 0x69 (i) in UART0+0 13/i 0/subop 6/rd 0/rs 69/imm12 23/s 2/subop 5/rs2 6/rs1 0/off12 # store 0x0a (\n) in UART0+0 13/i 0/subop 6/rd 0/rs 0a/imm12 23/s 2/subop 5/rs2 6/rs1 0/off12 # jump back up to the top 6f/j 0/4d fffe4/off21 `ex.format`: arguments sliced and diced and put into the ISA order. == code 0x80000000 # repeatedly print "Hi\n" # main: # load 0x10010000 (UART0) into t0 37/7 05/5 10010/20 # store 0x48 (H) in UART0+0 13/7 06/5 00/3 00/5 48/12 23/7 00/5 02/3 05/5 06/5 00/7 # store 0x69 (i) in UART0+0 13/7 06/5 00/3 00/5 69/12 23/7 00/5 02/3 05/5 06/5 00/7 # store 0x0a (\n) in UART0+0 13/7 06/5 00/3 00/5 0a/12 23/7 00/5 02/3 05/5 06/5 00/7 # jump back up to the top 6f/7 00/5 ff/8 01/1 3f2/10 01/1 `ex.pack`: fully packed, ready to run bare-metal == code 0x80000000 # repeatedly print "Hi\n" # main: # load 0x10010000 (UART0) into t0 b7 02 01 10 # store 0x48 (H) in UART0+0 13 03 80 04 23 a0 62 00 # store 0x69 (i) in UART0+0 13 03 90 06 23 a0 62 00 # store 0x0a (\n) in UART0+0 13 03 a0 00 23 a0 62 00 # jump back up to the top 6f f0 5f fe `ex.elf`: binary file for use with `qemu` (see next section). ## Debugging You can hook gdb into `qemu` using the `-s` flag, and make it halt on start using the `-S` flag. `gdb` can be attached using `target remote localhost:1234`: $ ./qemu.sh out.elf -S -s # in another terminal $ riscv32-elf-gdb -iex "target remote localhost:1234" layout asm # show assembly trace nexti # step forward one instruction c # free-run forward [mu]: https://github.com/akkartik/mu