3737static int riscv_semihosting_setup (struct target * target , int enable );
3838static 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+ /* The semihosting "magic" sequence must be the exact three instructions
46+ * listed below. All these instructions, including the ebreak, must be
47+ * uncompressed (4 bytes long). */
48+ const uint32_t magic [] = {
49+ 0x01f01013 , /* slli zero,zero,0x1f */
50+ 0x00100073 , /* ebreak */
51+ 0x40705013 /* srai zero,zero,0x7 */
52+ };
53+
54+ LOG_TARGET_DEBUG (target , "Checking for RISC-V semihosting sequence "
55+ "at PC = 0x%" TARGET_PRIxADDR , pc );
56+
57+ /* Read three uncompressed instructions:
58+ * The previous, the current one (pointed to by PC) and the next one. */
59+ const target_addr_t sequence_start_address = pc - 4 ;
60+ for (int i = 0 ; i < 3 ; i ++ ) {
61+ uint8_t buf [4 ];
62+
63+ /* Instruction memories may not support arbitrary read size.
64+ * Use any size that will work. */
65+ const target_addr_t address = sequence_start_address + (4 * i );
66+ int result = riscv_read_by_any_size (target , address , 4 , buf );
67+ if (result != ERROR_OK ) {
68+ * sequence_found = false;
69+ return result ;
70+ }
71+
72+ /* RISC-V instruction layout in memory is always little endian,
73+ * regardless of the endianness of the whole system. */
74+ const uint32_t value = le_to_h_u32 (buf );
75+
76+ LOG_TARGET_DEBUG (target , "compare 0x%08" PRIx32 " from 0x%" PRIx64 " against 0x%08" PRIx32 ,
77+ value , address , magic [i ]);
78+ if (value != magic [i ]) {
79+ LOG_TARGET_DEBUG (target , "Not a RISC-V semihosting sequence" );
80+ * sequence_found = false;
81+ return ERROR_OK ;
82+ }
83+ }
84+
85+ LOG_TARGET_DEBUG (target , "RISC-V semihosting sequence found "
86+ "at PC = 0x%" TARGET_PRIxADDR , pc );
87+ * sequence_found = true;
88+ return ERROR_OK ;
89+ }
90+
4091/**
4192 * Initialize RISC-V semihosting. Use common ARM code.
4293 */
@@ -60,42 +111,32 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
60111 assert (semihosting );
61112
62113 if (!semihosting -> is_active ) {
63- LOG_TARGET_DEBUG (target , " -> NONE (! semihosting->is_active )" );
114+ LOG_TARGET_DEBUG (target , "Semihosting outcome: NONE (semihosting not enabled )" );
64115 return SEMIHOSTING_NONE ;
65116 }
66117
67118 riscv_reg_t pc ;
68119 int result = riscv_reg_get (target , & pc , GDB_REGNO_PC );
69- if (result != ERROR_OK )
120+ if (result != ERROR_OK ) {
121+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (failed to read PC)" );
70122 return SEMIHOSTING_ERROR ;
123+ }
71124
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- };
125+ bool sequence_found ;
126+ * retval = riscv_semihosting_detect_magic_sequence (target , pc , & sequence_found );
127+ if (* retval != ERROR_OK ) {
128+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (during magic seq. detection)" );
129+ return SEMIHOSTING_ERROR ;
130+ }
81131
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- }
132+ if (!sequence_found ) {
133+ LOG_TARGET_DEBUG (target , "Semihosting outcome: NONE (no magic sequence)" );
134+ return SEMIHOSTING_NONE ;
97135 }
98136
137+ /* Otherwise we have a semihosting call (and semihosting is enabled).
138+ * Proceed with the semihosting. */
139+
99140 /*
100141 * Perform semihosting call if we are not waiting on a fileio
101142 * operation to complete.
@@ -108,12 +149,14 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
108149 result = riscv_reg_get (target , & r0 , GDB_REGNO_A0 );
109150 if (result != ERROR_OK ) {
110151 LOG_TARGET_ERROR (target , "Could not read semihosting operation code (register a0)" );
152+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (failed to read a0)" );
111153 return SEMIHOSTING_ERROR ;
112154 }
113155
114156 result = riscv_reg_get (target , & r1 , GDB_REGNO_A1 );
115157 if (result != ERROR_OK ) {
116158 LOG_TARGET_ERROR (target , "Could not read semihosting operation code (register a1)" );
159+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (failed to read a1)" );
117160 return SEMIHOSTING_ERROR ;
118161 }
119162
@@ -128,11 +171,13 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
128171 * retval = semihosting_common (target );
129172 if (* retval != ERROR_OK ) {
130173 LOG_TARGET_ERROR (target , "Failed semihosting operation (0x%02X)" , semihosting -> op );
174+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (error during semihosting processing)" );
131175 return SEMIHOSTING_ERROR ;
132176 }
133177 } else {
134178 /* Unknown operation number, not a semihosting call. */
135179 LOG_TARGET_ERROR (target , "Unknown semihosting operation requested (op = 0x%x)" , semihosting -> op );
180+ LOG_TARGET_DEBUG (target , "Semihosting outcome: NONE (unknown semihosting opcode)" );
136181 return SEMIHOSTING_NONE ;
137182 }
138183 }
@@ -147,11 +192,11 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
147192 * operation to complete.
148193 */
149194 if (semihosting -> is_resumable && !semihosting -> hit_fileio ) {
150- LOG_TARGET_DEBUG (target , " -> HANDLED" );
195+ LOG_TARGET_DEBUG (target , "Semihosting outcome: HANDLED" );
151196 return SEMIHOSTING_HANDLED ;
152197 }
153198
154- LOG_TARGET_DEBUG (target , " -> WAITING" );
199+ LOG_TARGET_DEBUG (target , "Semihosting outcome: WAITING" );
155200 return SEMIHOSTING_WAITING ;
156201}
157202
0 commit comments