|
37 | 37 | #include "gdb_reg.h" |
38 | 38 | #include "riscv_debug.h" |
39 | 39 | #include "buffer_utils.h" |
| 40 | +#include "semihosting.h" |
40 | 41 |
|
41 | 42 | #include <assert.h> |
42 | 43 |
|
@@ -864,6 +865,31 @@ bool riscv_csr_write(riscv_hart_s *const hart, const uint16_t reg, const void *c |
864 | 865 | return true; |
865 | 866 | } |
866 | 867 |
|
| 868 | +static target_addr_t riscv_pc_read(riscv_hart_s *const hart) |
| 869 | +{ |
| 870 | + target_addr_t data = 0; |
| 871 | + riscv_csr_read(hart, RV_DPC, &data); |
| 872 | + //riscv32_reg_read(target, 32, &data, sizeof(data)); |
| 873 | + return data; |
| 874 | +} |
| 875 | + |
| 876 | +static bool riscv_hostio_request(target_s *const target) |
| 877 | +{ |
| 878 | + /* Read out syscall number from a0/x10 and first argument from a1/x11 */ |
| 879 | + uint32_t syscall = 0U; |
| 880 | + target_reg_read(target, 10, &syscall, sizeof(syscall)); |
| 881 | + uint32_t a1 = 0U; |
| 882 | + target_reg_read(target, 11, &a1, sizeof(a1)); |
| 883 | + |
| 884 | + /* Hand off to the main semihosting implementation */ |
| 885 | + const int32_t result = semihosting_request(target, syscall, a1); |
| 886 | + |
| 887 | + /* Write the result back to the target */ |
| 888 | + target_reg_write(target, 10, &result, sizeof(result)); |
| 889 | + /* Return if the request was in any way interrupted */ |
| 890 | + return target->tc->interrupted; |
| 891 | +} |
| 892 | + |
867 | 893 | uint8_t riscv_mem_access_width(const riscv_hart_s *const hart, const target_addr_t address, const size_t length) |
868 | 894 | { |
869 | 895 | /* Grab the Hart's most maxmimally aligned possible write width */ |
@@ -1103,6 +1129,21 @@ static target_halt_reason_e riscv_halt_poll(target_s *const target, target_addr6 |
1103 | 1129 | status &= RV_DCSR_CAUSE_MASK; |
1104 | 1130 | /* Dispatch on the cause code */ |
1105 | 1131 | switch (status) { |
| 1132 | + case RV_HALT_CAUSE_EBREAK: { |
| 1133 | + /* If we've hit a programmed breakpoint, check for semihosting call. */ |
| 1134 | + const target_addr_t program_counter = riscv_pc_read(hart); |
| 1135 | + uint32_t instructions[3] = {0}; |
| 1136 | + target_mem32_read(target, &instructions, program_counter - 4U, 12); |
| 1137 | + /* A semihosting call is three consecutive uncompressed instructions: slli zero, zero 0x1f; ebreak, srai zero, zero, 7. */ |
| 1138 | + if (instructions[0] == 0x01f01013 && instructions[1] == RV_EBREAK && instructions[2] == 0x40705013) { |
| 1139 | + if (riscv_hostio_request(target)) |
| 1140 | + return TARGET_HALT_REQUEST; |
| 1141 | + |
| 1142 | + riscv_halt_resume(target, false); |
| 1143 | + return TARGET_HALT_RUNNING; |
| 1144 | + } |
| 1145 | + return TARGET_HALT_BREAKPOINT; |
| 1146 | + } |
1106 | 1147 | case RV_HALT_CAUSE_TRIGGER: |
1107 | 1148 | /* XXX: Need to read out the triggers to find the one causing this, and grab the watch value */ |
1108 | 1149 | return TARGET_HALT_BREAKPOINT; |
|
0 commit comments