📄 icontext.c
字号:
/*=============================================================================
//
// icontext.c
//
// SPARC HAL context init function
//
//=============================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): hmt
// Contributors: hmt
// Date: 1998-12-14
// Purpose: HAL context initialization function
// Description: Initialize a HAL context for SPARC; this is in C and out
// of line because there is too much of it for a simple macro.
//
//####DESCRIPTIONEND####
//
//===========================================================================*/
#include <pkgconf/hal.h>
#include <cyg/hal/hal_arch.h> // HAL header
#include <cyg/infra/cyg_type.h>
#include <cyg/hal/vectors.h> // SAVE_REGS_SIZE, __WINSIZE, ...
/*---------------------------------------------------------------------------*/
/* We lay out the stack in the manner that the PCS demands:
* frame pointer -----> [top of stack]
* Argument spill area (6 words)
* Return Arg pointer
* Initial saved register window (i[8], l[8])
* for use by program when it starts
* [rest of] saved register object (various)
* stack pointer -----> saved register window (i[8], l[8])
* to allow us to be interrupted.
*
* ie. frame pointer ->
* struct HAL_FrameStructure
* stack pointer -> struct HAL_SavedRegisters
*
* and when the context "resumes" sp is incremented by 40 * 4, the size of
* a _struct HAL_SavedRegisters_ which points it at the extant but unused
* _struct HAL_FrameStructure_ as the PCS requires. The frame pointer is
* left pointing off the top of stack.
*
*
* Thus the stack is the same if created from an already executing context:
*
* frame pointer ----->
* [temporaries and locals]
* [more arguments]
* Argument spill area (6 words)
* Return Arg pointer
* [sp at entry]------> Previous saved register window (i[8], l[8])
* for use by program when it starts
* [rest of] saved register object (various)
* stack pointer -----> saved register window (i[8], l[8])
* to allow us to be interrupted.
*/
CYG_ADDRESS
hal_thread_init_context( CYG_WORD sparg,
CYG_WORD thread,
CYG_WORD entry,
CYG_WORD id )
{
register CYG_WORD fp = sparg;
register CYG_WORD sp = 0;
register HAL_SavedRegisters *regs;
register HAL_FrameStructure *frame;
int i;
if ( 0 == (id & 0xffff0000) )
id <<= 16;
fp &= ~15; // round down to double alignment
frame = (HAL_FrameStructure *)(
fp - sizeof( HAL_FrameStructure ) );
regs = (HAL_SavedRegisters *)(
((CYG_WORD)frame) - sizeof(HAL_SavedRegisters) );
sp = (CYG_WORD)regs;
for ( i = 0; i < 6; i++ ) {
frame->spill_args[i] = id | 0xa0 | i;
}
frame->composite_return_ptr = 0;
for ( i = 0; i < 8; i++ ) {
frame->li.i[i] = id | ( 56 + i );
frame->li.l[i] = id | ( 48 + i );
regs ->li.i[i] = id | ( 24 + i );
regs ->li.l[i] = id | ( 16 + i );
regs ->o[i] = id | ( 8 + i );
regs ->g[i] = id | ( i );
}
// first terminate the linked list on the stack in the initial
// (already saved) register window:
frame->li.i[6] = regs->li.i[6] = (cyg_uint32)fp; // frame pointer
frame->li.i[7] = regs->li.i[7] = (cyg_uint32)0; // no ret addr here
// and set up other saved regs as if called from just before
// the entry point:
regs->o[7] = (entry - 8);
regs->o[6] = sp;
// this is the argument that the entry point is called with
regs->o[0] = thread;
// this is the initial CWP and interrupt state; CWP is quite arbitrary
// really, the WIM is set up accordingly in hal_thread_load_context().
regs->g[0] = 0x0e0 + __WIN_INIT; // PIL zero, ET, S, PS and CWP set.
return (CYG_ADDRESS)sp;
}
// ---------------------------------------------------------------------------
//#define THREAD_DEBUG_SERIAL_VERBOSE
#ifdef THREAD_DEBUG_SERIAL_VERBOSE // NOT INCLUDED
// This is unpleasant to try to debug, because these routines are called
// WHEN THE PROGRAM IS NOT RUNNING from the CygMon's GDB stubs - so you
// can't use any normal output: these little routines use the serial
// line directly, so are best used when debugging via Ethernet, so you
// just have a separate output stream to read. Nasty...
#include <cyg/hal/hal_diag.h>
#undef HAL_DIAG_WRITE_CHAR
#define HAL_DIAG_WRITE_CHAR(_c_) CYG_MACRO_START \
SLEB_LED = (_c_); \
HAL_DIAG_WRITE_CHAR_DIRECT( _c_ ); \
CYG_MACRO_END
static void swritec( char c )
{
HAL_DIAG_WRITE_CHAR( c );
}
static void swrites( char *s )
{
char c;
while ( 0 != (c = *s++) )
HAL_DIAG_WRITE_CHAR( c );
}
static void swritex( cyg_uint32 x )
{
int i;
swrites( "0x" );
for ( i = 28; i >= 0; i-= 4 ) {
char c = "0123456789abcdef"[ 0xf & (x >> i) ];
HAL_DIAG_WRITE_CHAR( c );
}
}
#define newline() swrites( "\n\r" )
static void x8( char *s, unsigned long *xp )
{
int i;
for ( i = 0; i < 8; i++ ) {
swrites( s );
swritec( '0' + i );
swrites( " = " );
swritex( xp[i] );
if ( 3 == (i & 3) )
newline();
else
swrites( " " );
}
}
#endif // THREAD_DEBUG_SERIAL_VERBOSE ... NOT INCLUDED
// ---------------------------------------------------------------------------
// Routines in icontext.c used here because they're quite large for
// the SPARC (note param order); these are used in talking to GDB.
enum regnames {G0 = 0, G1, G2, G3, G4, G5, G6, G7,
O0, O1, O2, O3, O4, O5, SP, O7,
L0, L1, L2, L3, L4, L5, L6, L7,
I0, I1, I2, I3, I4, I5, FP, I7,
F0, F1, F2, F3, F4, F5, F6, F7,
F8, F9, F10, F11, F12, F13, F14, F15,
F16, F17, F18, F19, F20, F21, F22, F23,
F24, F25, F26, F27, F28, F29, F30, F31,
Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR};
typedef unsigned long target_register_t;
void
cyg_hal_sparc_get_gdb_regs( void *gdb_regset,
HAL_SavedRegisters *eCos_regset )
{
target_register_t *gdb = (target_register_t *)gdb_regset;
int reg;
cyg_uint32 scratch = 0;
cyg_uint32 *sptrap;
HAL_SavedWindow *trapli, *ctxli;
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -