⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icontext.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
        // 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 + -