1212#include "esp_cpu.h"
1313#include "esp_ipc_isr.h"
1414#include "esp_private/crosscore_int.h"
15+ #include <xtensa_context.h>
1516
1617#if !XCHAL_HAVE_WINDOWED
1718#warning "gdbstub_xtensa: revisit the implementation for Call0 ABI"
@@ -38,13 +39,54 @@ static void update_regfile_common(esp_gdbstub_gdb_regfile_t *dst)
3839 RSR (CONFIGID1 , dst -> configid1 );
3940}
4041
42+ #if XCHAL_HAVE_FP
43+ /** @brief Read FPU registers to memory
44+ */
45+ static void gdbstub_read_fpu_regs (void * data )
46+ {
47+ float * ptr0 ;
48+ void * ptr1 ;
49+
50+ asm volatile ("mov %0, %1" : "=a" (ptr0 ) : "a" (data ));
51+
52+ asm volatile ("rur.FCR %0" : "=a" (ptr1 ));
53+ asm volatile ("s32i %0, %1, 64" : "=a" (ptr1 ) : "a" (ptr0 ));
54+ asm volatile ("rur.FSR %0" : "=a" (ptr1 ));
55+ asm volatile ("s32i %0, %1, 68" : "=a" (ptr1 ) : "a" (ptr0 ));
56+
57+ asm volatile ("ssi f0, %0, 0" :: "a" (ptr0 )); //*(ptr0 + 0) = f0;
58+ asm volatile ("ssi f1, %0, 4" :: "a" (ptr0 )); //*(ptr0 + 4) = f1;
59+ asm volatile ("ssi f2, %0, 8" :: "a" (ptr0 )); //...
60+ asm volatile ("ssi f3, %0, 12" :: "a" (ptr0 ));
61+ asm volatile ("ssi f4, %0, 16" :: "a" (ptr0 ));
62+ asm volatile ("ssi f5, %0, 20" :: "a" (ptr0 ));
63+ asm volatile ("ssi f6, %0, 24" :: "a" (ptr0 ));
64+ asm volatile ("ssi f7, %0, 28" :: "a" (ptr0 ));
65+ asm volatile ("ssi f8, %0, 32" :: "a" (ptr0 ));
66+ asm volatile ("ssi f9, %0, 36" :: "a" (ptr0 ));
67+ asm volatile ("ssi f10, %0, 40" :: "a" (ptr0 ));
68+ asm volatile ("ssi f11, %0, 44" :: "a" (ptr0 ));
69+ asm volatile ("ssi f12, %0, 48" :: "a" (ptr0 ));
70+ asm volatile ("ssi f13, %0, 52" :: "a" (ptr0 ));
71+ asm volatile ("ssi f14, %0, 56" :: "a" (ptr0 ));
72+ asm volatile ("ssi f15, %0, 60" :: "a" (ptr0 ));
73+
74+ }
75+ #endif // XCHAL_HAVE_FP
76+
77+
78+ extern const uint32_t offset_pxEndOfStack ;
79+ extern const uint32_t offset_cpsa ; /* Offset to start of the CPSA area on the stack. See uxInitialiseStackCPSA(). */
80+ extern uint32_t _xt_coproc_owner_sa [2 ];
81+
4182void esp_gdbstub_frame_to_regfile (const esp_gdbstub_frame_t * frame , esp_gdbstub_gdb_regfile_t * dst )
4283{
4384 init_regfile (dst );
4485 const uint32_t * a_regs = (const uint32_t * ) & frame -> a0 ;
86+
4587 if (!(esp_ptr_executable (esp_cpu_pc_to_addr (frame -> pc )) && (frame -> pc & 0xC0000000U ))) {
4688 /* Xtensa ABI sets the 2 MSBs of the PC according to the windowed call size
47- * Incase the PC is invalid, GDB will fail to translate addresses to function names
89+ * In case the PC is invalid, GDB will fail to translate addresses to function names
4890 * Hence replacing the PC to a placeholder address in case of invalid PC
4991 */
5092 dst -> pc = (uint32_t )& _invalid_pc_placeholder ;
@@ -59,6 +101,36 @@ void esp_gdbstub_frame_to_regfile(const esp_gdbstub_frame_t *frame, esp_gdbstub_
59101 dst -> a [i ] = 0xDEADBEEF ;
60102 }
61103
104+ #if XCHAL_HAVE_FP
105+
106+ extern void * pxCurrentTCBs [2 ];
107+ void * current_tcb_ptr = pxCurrentTCBs [0 ];
108+ uint32_t * current_fpu_ptr = NULL ;
109+
110+ #if !CONFIG_FREERTOS_UNICORE
111+ current_tcb_ptr = pxCurrentTCBs [esp_cpu_get_core_id ()];
112+ #endif
113+ uint32_t cp_enabled ;
114+ RSR (CPENABLE , cp_enabled );
115+
116+ // Check if the co-processor is enabled
117+ if (cp_enabled ) {
118+ gdbstub_read_fpu_regs (dst -> f );
119+ } else {
120+ current_tcb_ptr += offset_pxEndOfStack ;
121+ current_tcb_ptr = * (void * * )current_tcb_ptr ;
122+ current_tcb_ptr -= offset_cpsa ;
123+ // Operation (&~0xf) required in .macro get_cpsa_from_tcb reg_A reg_B
124+ current_tcb_ptr = (void * )((uint32_t )current_tcb_ptr & ~0xf );
125+ current_fpu_ptr = * (uint32_t * * )(current_tcb_ptr + XT_CP_ASA );
126+
127+ dst -> fcr = current_fpu_ptr [0 ];
128+ dst -> fsr = current_fpu_ptr [1 ];
129+ for (int i = 0 ; i < 16 ; i ++ ) {
130+ dst -> f [i ] = current_fpu_ptr [i + 2 ];
131+ }
132+ }
133+ #endif //XCHAL_HAVE_FP
62134#if XCHAL_HAVE_LOOPS
63135 dst -> lbeg = frame -> lbeg ;
64136 dst -> lend = frame -> lend ;
@@ -72,6 +144,84 @@ void esp_gdbstub_frame_to_regfile(const esp_gdbstub_frame_t *frame, esp_gdbstub_
72144
73145#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
74146
147+ /* Represents FreeRTOS TCB structure */
148+ typedef struct {
149+ uint8_t * top_of_stack ;
150+ /* Other members aren't needed */
151+ } dummy_tcb_t ;
152+
153+ void esp_gdbstub_tcb_frame_to_regfile (dummy_tcb_t * tcb , esp_gdbstub_gdb_regfile_t * dst )
154+ {
155+ const XtExcFrame * frame = (XtExcFrame * ) tcb -> top_of_stack ;
156+
157+ init_regfile (dst );
158+ const uint32_t * a_regs = (const uint32_t * ) & frame -> a0 ;
159+
160+ if (!(esp_ptr_executable (esp_cpu_pc_to_addr (frame -> pc )) && (frame -> pc & 0xC0000000U ))) {
161+ /* Xtensa ABI sets the 2 MSBs of the PC according to the windowed call size
162+ * In case the PC is invalid, GDB will fail to translate addresses to function names
163+ * Hence replacing the PC to a placeholder address in case of invalid PC
164+ */
165+ dst -> pc = (uint32_t )& _invalid_pc_placeholder ;
166+ } else {
167+ dst -> pc = (uint32_t )esp_cpu_pc_to_addr (frame -> pc );
168+ }
169+
170+ for (int i = 0 ; i < 16 ; i ++ ) {
171+ dst -> a [i ] = a_regs [i ];
172+ }
173+ for (int i = 16 ; i < 64 ; i ++ ) {
174+ dst -> a [i ] = 0xDEADBEEF ;
175+ }
176+
177+ #if XCHAL_HAVE_FP
178+ uint32_t * current_xt_coproc_owner_sa = (uint32_t * )_xt_coproc_owner_sa [0 ];
179+
180+ #if !CONFIG_FREERTOS_UNICORE
181+ current_xt_coproc_owner_sa = (uint32_t * )_xt_coproc_owner_sa [esp_cpu_get_core_id ()];
182+ #endif
183+
184+ uint32_t cp_enabled ;
185+ RSR (CPENABLE , cp_enabled );
186+
187+ void * current_tcb_ptr = tcb ;
188+ uint32_t * current_fpu_ptr = NULL ;
189+ {
190+ current_tcb_ptr += offset_pxEndOfStack ;
191+ current_tcb_ptr = * (void * * )current_tcb_ptr ;
192+ current_tcb_ptr -= offset_cpsa ;
193+ // Operation (&~0xf) required in .macro get_cpsa_from_tcb reg_A reg_B
194+ current_tcb_ptr = (void * )((uint32_t )current_tcb_ptr & ~0xf );
195+ current_fpu_ptr = * (uint32_t * * )(current_tcb_ptr + XT_CP_ASA );
196+
197+ bool use_fpu_regs = ((false == cp_enabled ) && (current_xt_coproc_owner_sa [0 ] == 1 ) && (current_fpu_ptr == (uint32_t * )current_xt_coproc_owner_sa [2 ]));
198+
199+ dst -> fcr = current_fpu_ptr [0 ];
200+ dst -> fsr = current_fpu_ptr [1 ];
201+ for (int i = 0 ; i < 16 ; i ++ ) {
202+ dst -> f [i ] = current_fpu_ptr [i + 2 ];
203+ }
204+
205+ /* We have situation when FPU is in use, but the context not stored
206+ to the memory, and we have to read from CPU registers.
207+ */
208+ if (use_fpu_regs ) {
209+ gdbstub_read_fpu_regs (dst -> f );
210+ }
211+ }
212+ #endif // XCHAL_HAVE_FP
213+
214+ #if XCHAL_HAVE_LOOPS
215+ dst -> lbeg = frame -> lbeg ;
216+ dst -> lend = frame -> lend ;
217+ dst -> lcount = frame -> lcount ;
218+ #endif
219+
220+ dst -> ps = (frame -> ps & PS_UM ) ? (frame -> ps & ~PS_EXCM ) : frame -> ps ;
221+ dst -> sar = frame -> sar ;
222+ update_regfile_common (dst );
223+ }
224+
75225static void solicited_frame_to_regfile (const XtSolFrame * frame , esp_gdbstub_gdb_regfile_t * dst )
76226{
77227 init_regfile (dst );
@@ -94,20 +244,12 @@ static void solicited_frame_to_regfile(const XtSolFrame *frame, esp_gdbstub_gdb_
94244 update_regfile_common (dst );
95245}
96246
97- /* Represents FreeRTOS TCB structure */
98- typedef struct {
99- uint8_t * top_of_stack ;
100- /* Other members aren't needed */
101- } dummy_tcb_t ;
102-
103-
104247void esp_gdbstub_tcb_to_regfile (TaskHandle_t tcb , esp_gdbstub_gdb_regfile_t * dst )
105248{
106- const dummy_tcb_t * dummy_tcb = (const dummy_tcb_t * ) tcb ;
107-
249+ dummy_tcb_t * dummy_tcb = (dummy_tcb_t * ) tcb ;
108250 const XtExcFrame * frame = (XtExcFrame * ) dummy_tcb -> top_of_stack ;
109251 if (frame -> exit != 0 ) {
110- esp_gdbstub_frame_to_regfile ( frame , dst );
252+ esp_gdbstub_tcb_frame_to_regfile ( dummy_tcb , dst );
111253 } else {
112254 const XtSolFrame * taskFrame = (const XtSolFrame * ) dummy_tcb -> top_of_stack ;
113255 solicited_frame_to_regfile (taskFrame , dst );
@@ -206,14 +348,80 @@ void esp_gdbstub_trigger_cpu(void)
206348 * Set register in frame with address to value
207349 *
208350 * */
351+
209352void esp_gdbstub_set_register (esp_gdbstub_frame_t * frame , uint32_t reg_index , uint32_t value )
210353{
211- switch (reg_index ) {
212- case 0 :
354+ uint32_t temp_fpu_value = value ;
355+ float * ptr0 ;
356+
357+ asm volatile ("mov %0, %1" : "=a" (ptr0 ) : "a" (& temp_fpu_value ));
358+
359+ if (reg_index == 0 ) {
213360 frame -> pc = value ;
214- break ;
215- default :
361+ } else if (reg_index > 0 && (reg_index <= 27 )) {
216362 (& frame -> a0 )[reg_index - 1 ] = value ;
217- break ;
218363 }
364+ #if XCHAL_HAVE_FP
365+ void * ptr1 ;
366+ uint32_t cp_enabled ;
367+ RSR (CPENABLE , cp_enabled );
368+ if (cp_enabled != 0 ) {
369+ if (reg_index == 87 ) {
370+ asm volatile ("lsi f0, %0, 0" :: "a" (ptr0 ));
371+ }
372+ if (reg_index == 88 ) {
373+ asm volatile ("lsi f1, %0, 0" :: "a" (ptr0 ));
374+ }
375+ if (reg_index == 89 ) {
376+ asm volatile ("lsi f2, %0, 0" :: "a" (ptr0 ));
377+ }
378+ if (reg_index == 90 ) {
379+ asm volatile ("lsi f3, %0, 0" :: "a" (ptr0 ));
380+ }
381+ if (reg_index == 91 ) {
382+ asm volatile ("lsi f4, %0, 0" :: "a" (ptr0 ));
383+ }
384+ if (reg_index == 92 ) {
385+ asm volatile ("lsi f5, %0, 0" :: "a" (ptr0 ));
386+ }
387+ if (reg_index == 93 ) {
388+ asm volatile ("lsi f6, %0, 0" :: "a" (ptr0 ));
389+ }
390+ if (reg_index == 94 ) {
391+ asm volatile ("lsi f7, %0, 0" :: "a" (ptr0 ));
392+ }
393+ if (reg_index == 95 ) {
394+ asm volatile ("lsi f8, %0, 0" :: "a" (ptr0 ));
395+ }
396+ if (reg_index == 96 ) {
397+ asm volatile ("lsi f9, %0, 0" :: "a" (ptr0 ));
398+ }
399+ if (reg_index == 97 ) {
400+ asm volatile ("lsi f10, %0, 0" :: "a" (ptr0 ));
401+ }
402+ if (reg_index == 98 ) {
403+ asm volatile ("lsi f11, %0, 0" :: "a" (ptr0 ));
404+ }
405+ if (reg_index == 99 ) {
406+ asm volatile ("lsi f12, %0, 0" :: "a" (ptr0 ));
407+ }
408+ if (reg_index == 100 ) {
409+ asm volatile ("lsi f13, %0, 0" :: "a" (ptr0 ));
410+ }
411+ if (reg_index == 101 ) {
412+ asm volatile ("lsi f14, %0, 0" :: "a" (ptr0 ));
413+ }
414+ if (reg_index == 102 ) {
415+ asm volatile ("lsi f15, %0, 0" :: "a" (ptr0 ));
416+ }
417+ if (reg_index == 103 ) {
418+ asm volatile ("l32i %0, %1, 0" : "=a" (ptr1 ) : "a" (ptr0 ));
419+ asm volatile ("wur.FCR %0" : "=a" (ptr1 ));
420+ }
421+ if (reg_index == 104 ) {
422+ asm volatile ("l32i %0, %1, 0" : "=a" (ptr1 ) : "a" (ptr0 ));
423+ asm volatile ("wur.FSR %0" : "=a" (ptr1 ));
424+ }
425+ }
426+ #endif // XCHAL_HAVE_FP
219427}
0 commit comments