Detailed description
- This is enough code for a new feature.
- The existing problem is RISC-V semihosting calls not supported by BMD -- target gets stuck on any ebreak, does not step over (unless you manually set $pc=$pc+4).
- Ths PR solves it by cloning
cortexm_hostio_request() into riscv_debug.c and hooking it to riscv_halt_poll() in much the same fashion. Entire semihosting.c can be reused because https://github.com/riscv-non-isa/riscv-semihosting follows https://github.com/ARM-software/abi-aa/blob/main/semihosting/semihosting.rst w.r.t. syscall numbers and calling convention. Thanks to maintainers for refactoring and splitting out the common code of BMD implementation.
Additional code for stepping over XLEN-wide EBREAK helps me avoid doing $pc manipulation from gdb console, although I'm not sure how correct is it to do so.
Tested on Pico 2 board running basically https://github.com/raspberrypi/pico-examples/blob/master/hello_world/serial/hello_serial.c on the first Hazard3/RISC-V core, but using PICO_STDIO_SEMIHOSTING not PICO_STDIO_UART. Debugger is blackpill-f411ce, running BMF v2.0 with full newlib (not nano because of rvhuimac bug) and/or BMDA. Not tested on RV64. There were 2-byte compressed instructions in disassembly AFAICS, like 0x9002 short ebreak elsewhere, but BMD memory access layer works regardless.
Disassembly snippet of semihosting trampoline
static void stdio_semihosting_out_chars(const char *buf, int length) {
100011a4: 1141 addi sp,sp,-16
size_t fd;
const char *buf;
size_t len;
} args;
args.fd = 2; // 2 = stdout
100011a6: 4789 li a5,2
100011a8: c23e sw a5,4(sp)
args.buf = buf;
100011aa: c42a sw a0,8(sp)
args.len = length;
100011ac: c62e sw a1,12(sp)
pico_default_asm (
100011ae: 005c addi a5,sp,4
100011b0: 4515 li a0,5
100011b2: 85be mv a1,a5
100011b4: 01f01013 slli zero,zero,0x1f
100011b8: 00100073 ebreak
100011bc: 40705013 srai zero,zero,0x7
:
: [args] "r" (&args)
: "r0", "r1", "cc", "memory"
#endif
);
}
100011c0: 0141 addi sp,sp,16
100011c2: 8082 ret
The same helloworld runs on Cortex-M33 (ARM Secure) when recompiled to, and both arches exhibit a bug where the emit Fwrite packets to file descriptor 0 (subtracted 1 from callsite https://github.com/raspberrypi/pico-sdk/blob/2.1.1/src/rp2_common/pico_stdio_semihosting/stdio_semihosting.c#L24), and I'm not sure whose bug this is. Previously Cortex-M semihosting worked from --rdimon.specs as well as fw-test (on random cortexm targets I mean), so I think Pico C SDK should be fixed, which is what I did locally. Porting blackmagic-test-fw-archive to RISC-V could help test the other calls, I only checked 0x5 SYS_WRITE to fd 2 (stdout) which works, without fd=Fopen(":tt"), both in GDB and in BMF redirect_stdout, as well as DEBUG_INFO("syscall ") diagnostic logs.
This branch is based on #2113 but I could rebase it away because Hazard3/ice40 is not strictly required, it's just another target applicable to testing.
Some refactoring may be needed, like extracting macros for preamble/postamble slli/srai instructions, and that's for review process to deal with.
Scope of support (and possible testing) is obviously RP2350, ESP32-C3/C6 (with manual assembly, no ESP-IDF), GD32VF103 (with -lrdimon etc.), maybe CH32V205/V307 once RVSWD transport is merged, maybe Milk-V Duo and other chips with no flash driver support merged.
Your checklist for this pull request
Closing issues
## Detailed description
* This is enough code for a new feature.
* The existing problem is RISC-V semihosting calls not supported by BMD -- target gets stuck on any ebreak, does not step over (unless you manually set $pc=$pc+4).
* Ths PR solves it by cloning `cortexm_hostio_request()` into riscv_debug.c and hooking it to `riscv_halt_poll()` in much the same fashion. Entire semihosting.c can be reused because https://github.com/riscv-non-isa/riscv-semihosting follows https://github.com/ARM-software/abi-aa/blob/main/semihosting/semihosting.rst w.r.t. syscall numbers and calling convention. Thanks to maintainers for refactoring and splitting out the common code of BMD implementation.
Additional code for stepping over XLEN-wide EBREAK helps me avoid doing $pc manipulation from gdb console, although I'm not sure how correct is it to do so.
Tested on Pico 2 board running basically https://github.com/raspberrypi/pico-examples/blob/master/hello_world/serial/hello_serial.c on the first Hazard3/RISC-V core, but using `PICO_STDIO_SEMIHOSTING` not `PICO_STDIO_UART`. Debugger is `blackpill-f411ce`, running BMF v2.0 with full newlib (not nano because of rv`hu`imac bug) and/or BMDA. Not tested on RV64. There were 2-byte compressed instructions in disassembly AFAICS, like 0x9002 short ebreak elsewhere, but BMD memory access layer works regardless.
<details>
<summary> Disassembly snippet of semihosting trampoline </summary>
```asm
static void stdio_semihosting_out_chars(const char *buf, int length) {
100011a4: 1141 addi sp,sp,-16
size_t fd;
const char *buf;
size_t len;
} args;
args.fd = 2; // 2 = stdout
100011a6: 4789 li a5,2
100011a8: c23e sw a5,4(sp)
args.buf = buf;
100011aa: c42a sw a0,8(sp)
args.len = length;
100011ac: c62e sw a1,12(sp)
pico_default_asm (
100011ae: 005c addi a5,sp,4
100011b0: 4515 li a0,5
100011b2: 85be mv a1,a5
100011b4: 01f01013 slli zero,zero,0x1f
100011b8: 00100073 ebreak
100011bc: 40705013 srai zero,zero,0x7
:
: [args] "r" (&args)
: "r0", "r1", "cc", "memory"
#endif
);
}
100011c0: 0141 addi sp,sp,16
100011c2: 8082 ret
```
</details>
The same helloworld runs on Cortex-M33 (ARM Secure) when recompiled to, and both arches exhibit a bug where the emit Fwrite packets to file descriptor 0 (subtracted 1 from callsite https://github.com/raspberrypi/pico-sdk/blob/2.1.1/src/rp2_common/pico_stdio_semihosting/stdio_semihosting.c#L24), and I'm not sure whose bug this is. Previously Cortex-M semihosting worked from --rdimon.specs as well as fw-test (on random cortexm targets I mean), so I think Pico C SDK should be fixed, which is what I did locally. Porting blackmagic-test-fw-archive to RISC-V could help test the other calls, I only checked 0x5 SYS_WRITE to fd 2 (stdout) which works, without fd=Fopen(":tt"), both in GDB and in BMF redirect_stdout, as well as `DEBUG_INFO("syscall ")` diagnostic logs.
This branch is based on #2113 but I could rebase it away because Hazard3/ice40 is not strictly required, it's just another target applicable to testing.
Some refactoring may be needed, like extracting macros for preamble/postamble slli/srai instructions, and that's for review process to deal with.
Scope of support (and possible testing) is obviously RP2350, ESP32-C3/C6 (with manual assembly, no ESP-IDF), GD32VF103 (with -lrdimon etc.), maybe CH32V205/V307 once RVSWD transport is merged, maybe Milk-V Duo and other chips with no flash driver support merged.
## Your checklist for this pull request
* [x] I've read the [Code of Conduct](https://github.com/blackmagic-debug/blackmagic/blob/main/CODE_OF_CONDUCT.md)
* [x] I've read the [guidelines for contributing](https://github.com/blackmagic-debug/blackmagic/blob/main/CONTRIBUTING.md) to this repository
* [x] It builds for hardware native (see [Building the firmware](https://github.com/blackmagic-debug/blackmagic?tab=readme-ov-file#building-black-magic-debug-firmware))
* [x] It builds as BMDA (see [Building the BMDA](https://github.com/blackmagic-debug/blackmagic?tab=readme-ov-file#building-black-magic-debug-app))
* [x] I've tested it to the best of my ability
* [x] My commit messages provide a useful short description of what the commits do
## Closing issues