Skip to content

Commit c4ea6d1

Browse files
committed
Semihosting 2 of 3: Refactor magic sequence detection
Refactor (clean up) the code in riscv_semihosting.c by moving the magic sequence detection to its own function. Change-Id: I3a3ce991336ceeeff023d459d0e28558059554e0 Signed-off-by: Jan Matyas <[email protected]>
1 parent ecb2ad4 commit c4ea6d1

File tree

1 file changed

+55
-24
lines changed

1 file changed

+55
-24
lines changed

src/target/riscv/riscv_semihosting.c

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,51 @@
3737
static int riscv_semihosting_setup(struct target *target, int enable);
3838
static int riscv_semihosting_post_result(struct target *target);
3939

40+
static int riscv_semihosting_detect_magic_sequence(struct target *target,
41+
const target_addr_t pc, bool *sequence_found)
42+
{
43+
assert(sequence_found);
44+
45+
const uint32_t magic[] = {
46+
0x01f01013, /* slli zero,zero,0x1f */
47+
0x00100073, /* ebreak */
48+
0x40705013 /* srai zero,zero,0x7 */
49+
};
50+
51+
LOG_TARGET_DEBUG(target, "Checking for RISC-V semihosting sequence "
52+
"at PC = 0x%" TARGET_PRIxADDR, pc);
53+
54+
/* Read three uncompressed instructions:
55+
* The previous, the current one (pointed to by PC) and the next one. */
56+
for (int i = 0; i < 3; i++) {
57+
uint8_t buf[4];
58+
59+
/* Instruction memories may not support arbitrary read size.
60+
* Use any size that will work. */
61+
const target_addr_t address = (pc - 4) + 4 * i;
62+
int result = riscv_read_by_any_size(target, address, 4, buf);
63+
if (result != ERROR_OK) {
64+
*sequence_found = false;
65+
return result;
66+
}
67+
68+
const uint32_t value = target_buffer_get_u32(target, buf);
69+
70+
LOG_TARGET_DEBUG(target, "compare 0x%08x from 0x%" PRIx64 " against 0x%08x",
71+
value, address, magic[i]);
72+
if (value != magic[i]) {
73+
LOG_TARGET_DEBUG(target, "Not a RISC-V semihosting sequence");
74+
*sequence_found = false;
75+
return ERROR_OK;
76+
}
77+
}
78+
79+
LOG_TARGET_DEBUG(target, "RISC-V semihosting sequence found "
80+
"at PC = 0x%" TARGET_PRIxADDR, pc);
81+
*sequence_found = true;
82+
return ERROR_OK;
83+
}
84+
4085
/**
4186
* Initialize RISC-V semihosting. Use common ARM code.
4287
*/
@@ -69,33 +114,19 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
69114
if (result != ERROR_OK)
70115
return SEMIHOSTING_ERROR;
71116

72-
/*
73-
* The instructions that trigger a semihosting call,
74-
* always uncompressed, should look like:
75-
*/
76-
uint32_t magic[] = {
77-
0x01f01013, /* slli zero,zero,0x1f */
78-
0x00100073, /* ebreak */
79-
0x40705013 /* srai zero,zero,0x7 */
80-
};
117+
bool sequence_found;
118+
*retval = riscv_semihosting_detect_magic_sequence(target, pc, &sequence_found);
119+
if (*retval != ERROR_OK)
120+
return SEMIHOSTING_ERROR;
81121

82-
/* Read three uncompressed instructions: The previous, the current one (pointed to by PC) and the next one */
83-
for (int i = 0; i < 3; i++) {
84-
uint8_t buf[4];
85-
/* Instruction memories may not support arbitrary read size. Use any size that will work. */
86-
target_addr_t address = (pc - 4) + 4 * i;
87-
*retval = riscv_read_by_any_size(target, address, 4, buf);
88-
if (*retval != ERROR_OK)
89-
return SEMIHOSTING_ERROR;
90-
uint32_t value = target_buffer_get_u32(target, buf);
91-
LOG_TARGET_DEBUG(target, "compare 0x%08x from 0x%" PRIx64 " against 0x%08x",
92-
value, address, magic[i]);
93-
if (value != magic[i]) {
94-
LOG_TARGET_DEBUG(target, " -> NONE (no magic)");
95-
return SEMIHOSTING_NONE;
96-
}
122+
if (!sequence_found) {
123+
LOG_TARGET_DEBUG(target, " -> NONE (no magic)");
124+
return SEMIHOSTING_NONE;
97125
}
98126

127+
/* Otherwise we have a semihosting call (and semihosting is enabled).
128+
* Proceed with the semihosting. */
129+
99130
/*
100131
* Perform semihosting call if we are not waiting on a fileio
101132
* operation to complete.

0 commit comments

Comments
 (0)