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+ const uint32_t value = target_buffer_get_u32 (target , buf );
73+
74+ LOG_TARGET_DEBUG (target , "compare 0x%08" PRIx32 " from 0x%" PRIx64 " against 0x%08" PRIx32 ,
75+ value , address , magic [i ]);
76+ if (value != magic [i ]) {
77+ LOG_TARGET_DEBUG (target , "Not a RISC-V semihosting sequence" );
78+ * sequence_found = false;
79+ return ERROR_OK ;
80+ }
81+ }
82+
83+ LOG_TARGET_DEBUG (target , "RISC-V semihosting sequence found "
84+ "at PC = 0x%" TARGET_PRIxADDR , pc );
85+ * sequence_found = true;
86+ return ERROR_OK ;
87+ }
88+
4089/**
4190 * Initialize RISC-V semihosting. Use common ARM code.
4291 */
@@ -60,42 +109,32 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
60109 assert (semihosting );
61110
62111 if (!semihosting -> is_active ) {
63- LOG_TARGET_DEBUG (target , " -> NONE (! semihosting->is_active )" );
112+ LOG_TARGET_DEBUG (target , "Semihosting outcome: NONE (semihosting not enabled )" );
64113 return SEMIHOSTING_NONE ;
65114 }
66115
67116 riscv_reg_t pc ;
68117 int result = riscv_reg_get (target , & pc , GDB_REGNO_PC );
69- if (result != ERROR_OK )
118+ if (result != ERROR_OK ) {
119+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (failed to read PC)" );
70120 return SEMIHOSTING_ERROR ;
121+ }
71122
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- };
123+ bool sequence_found ;
124+ * retval = riscv_semihosting_detect_magic_sequence (target , pc , & sequence_found );
125+ if (* retval != ERROR_OK ) {
126+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (during magic seq. detection)" );
127+ return SEMIHOSTING_ERROR ;
128+ }
81129
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- }
130+ if (!sequence_found ) {
131+ LOG_TARGET_DEBUG (target , "Semihosting outcome: NONE (no magic sequence)" );
132+ return SEMIHOSTING_NONE ;
97133 }
98134
135+ /* Otherwise we have a semihosting call (and semihosting is enabled).
136+ * Proceed with the semihosting. */
137+
99138 /*
100139 * Perform semihosting call if we are not waiting on a fileio
101140 * operation to complete.
@@ -108,12 +147,14 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
108147 result = riscv_reg_get (target , & r0 , GDB_REGNO_A0 );
109148 if (result != ERROR_OK ) {
110149 LOG_TARGET_ERROR (target , "Could not read semihosting operation code (register a0)" );
150+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (failed to read a0)" );
111151 return SEMIHOSTING_ERROR ;
112152 }
113153
114154 result = riscv_reg_get (target , & r1 , GDB_REGNO_A1 );
115155 if (result != ERROR_OK ) {
116156 LOG_TARGET_ERROR (target , "Could not read semihosting operation code (register a1)" );
157+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (failed to read a1)" );
117158 return SEMIHOSTING_ERROR ;
118159 }
119160
@@ -128,11 +169,13 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
128169 * retval = semihosting_common (target );
129170 if (* retval != ERROR_OK ) {
130171 LOG_TARGET_ERROR (target , "Failed semihosting operation (0x%02X)" , semihosting -> op );
172+ LOG_TARGET_DEBUG (target , "Semihosting outcome: ERROR (error during semihosting processing)" );
131173 return SEMIHOSTING_ERROR ;
132174 }
133175 } else {
134176 /* Unknown operation number, not a semihosting call. */
135177 LOG_TARGET_ERROR (target , "Unknown semihosting operation requested (op = 0x%x)" , semihosting -> op );
178+ LOG_TARGET_DEBUG (target , "Semihosting outcome: NONE (unknown semihosting opcode)" );
136179 return SEMIHOSTING_NONE ;
137180 }
138181 }
@@ -147,11 +190,11 @@ enum semihosting_result riscv_semihosting(struct target *target, int *retval)
147190 * operation to complete.
148191 */
149192 if (semihosting -> is_resumable && !semihosting -> hit_fileio ) {
150- LOG_TARGET_DEBUG (target , " -> HANDLED" );
193+ LOG_TARGET_DEBUG (target , "Semihosting outcome: HANDLED" );
151194 return SEMIHOSTING_HANDLED ;
152195 }
153196
154- LOG_TARGET_DEBUG (target , " -> WAITING" );
197+ LOG_TARGET_DEBUG (target , "Semihosting outcome: WAITING" );
155198 return SEMIHOSTING_WAITING ;
156199}
157200
0 commit comments