📄 icontext.c
字号:
// around in the stack to find out some truth...
sptrap = (cyg_uint32 *)eCos_regset; // point to the IL save area for
sptrap -= 24; // the trap handler, for PC, NPC
trapli = (HAL_SavedWindow *)sptrap; // Get at those regs
ctxli = (HAL_SavedWindow *)(trapli->i[6]); // (the frame pointer)
// and get at the interruptee's regs
// Pick up interruptee's registers from all over the stack:
for ( reg = 0; reg < 8 ; reg++ ) {
gdb[ G0 + reg ] = eCos_regset->g[reg];
gdb[ O0 + reg ] = trapli->i[reg];
gdb[ L0 + reg ] = ctxli->l[reg];
gdb[ I0 + reg ] = ctxli->i[reg];
}
// Clear out G0 which is always 0 (but abused in eCos_regset)
// and the FP regs which we do not have:
gdb[ G0 ] = 0;
for ( reg = F0; reg <= F31; reg++ )
gdb[ reg ] = 0;
// In the save context _of the trap handler_ registers are as follows:
// %l0 = psr (with this CWP/window-level in it)
// %l1 = pc
// %l2 = npc
// %l3 = vector number (1-15 for interrupts)
// %l4 = Y register preserved
gdb[ Y ] = trapli->l[4];
scratch = trapli->l[0]; // the PSR in the trap handler
#if 8 == __WINSIZE
scratch++; // back to interupted thread's window
scratch &=~ 0x38; // clear ET and any __WINSIZE overflow
gdb[ PSR ] = scratch;
gdb[ WIM ] = 1 << ((__WINBITS & (1 + scratch)));
#else // 6 or 7 windows only
reg = (int)(scratch & __WINBITS);
scratch &=~ (__WINBITS_MAXIMAL | 0x20); // clear ET and CWP
if ( __WINSIZE <= ++reg ) reg = 0; // back to intr'd window
gdb[ PSR ] = scratch | reg;
if ( __WINSIZE <= ++reg ) reg = 0; // good index for WIM
gdb[ WIM ] = 1 << reg;
#endif // __WINSIZE
// Read _a_ TBR value and ignore the current trap details:
asm volatile ( "rd %%tbr, %0" : "=r"(scratch) : );
gdb[ TBR ] = (scratch &~ 0xfff);
gdb[ PC ] = trapli->l[1];
gdb[ NPC ] = trapli->l[2];
gdb[ FPSR ] = 0;
gdb[ CPSR ] = 0;
#ifdef THREAD_DEBUG_SERIAL_VERBOSE
newline();
swrites( "-----------------------------------------------------" ); newline();
swrites( "-------------- INTERRUPT STACK GET ------------------" ); newline();
swrites( "eCos regset at " ); swritex( eCos_regset ); newline();
swrites( " trapli " ); swritex( trapli ); newline();
swrites( " ctxli " ); swritex( ctxli ); newline();
x8( "global ", &(gdb[G0]) );
x8( " in ", &(gdb[I0]) );
x8( " local ", &(gdb[L0]) );
x8( " out ", &(gdb[O0]) );
swrites( "gdb PC = " ); swritex( gdb[ PC ] ); newline();
swrites( "gdb NPC = " ); swritex( gdb[ NPC ] ); newline();
swrites( "gdb PSR = " ); swritex( gdb[ PSR ] ); newline();
#endif
}
else {
// It's a synchronous context switch that led to this object.
// Pick up interruptee's registers from the saved context:
for ( reg = 0; reg < 8 ; reg++ ) {
#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
gdb[ G0 + reg ] = 0;
gdb[ O0 + reg ] = 0;
#else
gdb[ G0 + reg ] = eCos_regset->g[reg];
gdb[ O0 + reg ] = eCos_regset->o[reg];
#endif
gdb[ L0 + reg ] = eCos_regset->li.l[reg];
gdb[ I0 + reg ] = eCos_regset->li.i[reg];
}
#ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
// Set up the stack pointer by arithmetic and the return address
gdb[ SP ] = ((cyg_uint32)(eCos_regset));
gdb[ O7 ] = eCos_regset->o[ 7 ];
#else
// Clear out G0 which is always 0 (but abused in eCos_regset)
gdb[ G0 ] = 0;
#endif
// and clear the FP regs which we do not have:
for ( reg = F0; reg <= F31; reg++ )
gdb[ reg ] = 0;
gdb[ Y ] = 0; // it's not preserved.
scratch = eCos_regset->g[ 0 ]; // the PSR in the saved context
gdb[ PSR ] = scratch; // return it verbatim.
#if 8 == __WINSIZE
gdb[ WIM ] = 1 << ((__WINBITS & (1 + scratch)));
#else // 6 or 7 windows only
reg = (int)(scratch & __WINBITS);
if ( __WINSIZE <= ++reg ) reg = 0; // good index for WIM
gdb[ WIM ] = 1 << reg;
#endif // __WINSIZE
// Read _a_ TBR value and ignore the current trap details:
asm volatile ( "rd %%tbr, %0" : "=r"(scratch) : );
gdb[ TBR ] = (scratch &~ 0xfff);
gdb[ PC ] = eCos_regset->o[ 7 ]; // the return address
gdb[ NPC ] = 4 + gdb[ PC ];
gdb[ FPSR ] = 0;
gdb[ CPSR ] = 0;
#ifdef THREAD_DEBUG_SERIAL_VERBOSE
newline();
swrites( "-----------------------------------------------------" ); newline();
swrites( "-------------- SYNCHRONOUS SWITCH GET----------------" ); newline();
swrites( "eCos regset at " ); swritex( eCos_regset ); newline();
x8( "global ", &(gdb[G0]) );
x8( " in ", &(gdb[I0]) );
x8( " local ", &(gdb[L0]) );
x8( " out ", &(gdb[O0]) );
swrites( "gdb PC = " ); swritex( gdb[ PC ] ); newline();
swrites( "gdb NPC = " ); swritex( gdb[ NPC ] ); newline();
swrites( "gdb PSR = " ); swritex( gdb[ PSR ] ); newline();
#endif
}
}
// ---------------------------------------------------------------------------
void
cyg_hal_sparc_set_gdb_regs( HAL_SavedRegisters *eCos_regset,
void *gdb_regset )
{
target_register_t *gdb = (target_register_t *)gdb_regset;
int reg;
cyg_uint32 scratch = 0;
cyg_uint32 *sptrap;
HAL_SavedWindow *trapli, *ctxli;
// Guess where the eCos register set really is:
if ( 0 == eCos_regset->g[0] ||
0xc0 == (0xe0 & eCos_regset->g[0]) ) {
// Then it's an interrupt stack saved state:
// (either minimal, or a saved PSR with traps disabled)
// The saved register set is pretty minimal, so we have to grub
// around in the stack to find out some truth...
sptrap = (cyg_uint32 *)eCos_regset; // point to the IL save area for
sptrap -= 24; // the trap handler, for PC, NPC
trapli = (HAL_SavedWindow *)sptrap; // Get at those regs
ctxli = (HAL_SavedWindow *)(trapli->i[6]); // (the frame pointer)
// and get at the interruptee's regs
scratch = eCos_regset->g[0];
// Put back interruptee's registers all over the stack:
for ( reg = 0; reg < 8 ; reg++ ) {
eCos_regset->g[reg] = gdb[ G0 + reg ] ;
trapli->i[reg] = gdb[ O0 + reg ] ;
ctxli->l[reg] = gdb[ L0 + reg ] ;
ctxli->i[reg] = gdb[ I0 + reg ] ;
}
// Put back the eCos G0 which is always 0 (but abused in eCos_regset)
eCos_regset->g[0] = scratch;
// In the save context _of the trap handler_ registers are as follows:
// %l0 = psr (with this CWP/window-level in it)
// %l1 = pc
// %l2 = npc
// %l3 = vector number (1-15 for interrupts)
// %l4 = Y register preserved
trapli->l[4] = gdb[ Y ];
// I am *not* interfering with the saved PSR, nor the TBR nor WIM.
// put back return PC and NPC
trapli->l[1] = gdb[ PC ] ;
trapli->l[2] = gdb[ NPC ];
#ifdef THREAD_DEBUG_SERIAL_VERBOSE
newline();
swrites( "-----------------------------------------------------" ); newline();
swrites( "-------------- INTERRUPT STACK SET ------------------" ); newline();
swrites( "eCos regset at " ); swritex( eCos_regset ); newline();
swrites( " trapli " ); swritex( trapli ); newline();
swrites( " ctxli " ); swritex( ctxli ); newline();
x8( "global ", &(gdb[G0]) );
x8( " in ", &(gdb[I0]) );
x8( " local ", &(gdb[L0]) );
x8( " out ", &(gdb[O0]) );
swrites( "gdb PC = " ); swritex( gdb[ PC ] ); newline();
swrites( "gdb NPC = " ); swritex( gdb[ NPC ] ); newline();
swrites( "gdb PSR = " ); swritex( gdb[ PSR ] ); newline();
#endif
}
else {
// It's a synchronous context switch that led to this object.
// Pick up interruptee's registers from the saved context:
scratch = eCos_regset->g[0];
for ( reg = 0; reg < 8 ; reg++ ) {
eCos_regset->g[reg] = gdb[ G0 + reg ];
eCos_regset->o[reg] = gdb[ O0 + reg ];
eCos_regset->li.l[reg] = gdb[ L0 + reg ];
eCos_regset->li.i[reg] = gdb[ I0 + reg ];
}
// Put back the eCos G0 which is always 0 (but abused in eCos_regset)
eCos_regset->g[0] = scratch;
// I am *not* interfering with the saved PSR, nor the TBR nor WIM.
// The PC is in o7, altering it via GDB's PC is not on.
// Setting the NPC in a voluntary context is meaningless.
#ifdef THREAD_DEBUG_SERIAL_VERBOSE
newline();
swrites( "-----------------------------------------------------" ); newline();
swrites( "-------------- SYNCHRONOUS SWITCH SET ---------------" ); newline();
swrites( "eCos regset at " ); swritex( eCos_regset ); newline();
x8( "global ", &(gdb[G0]) );
x8( " in ", &(gdb[I0]) );
x8( " local ", &(gdb[L0]) );
x8( " out ", &(gdb[O0]) );
swrites( "gdb PC = " ); swritex( gdb[ PC ] ); newline();
swrites( "gdb NPC = " ); swritex( gdb[ NPC ] ); newline();
swrites( "gdb PSR = " ); swritex( gdb[ PSR ] ); newline();
#endif
}
}
/*---------------------------------------------------------------------------*/
// EOF icontext.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -