mipsproc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 691 行 · 第 1/2 页
C
691 行
index_reg = addressableRegion( saved_regs, &offset );
offset += saved_regs->size;
saveRegSet( index_reg, CurrProc->targ.gpr_mask, offset, FALSE );
offset -= CountBits( CurrProc->targ.gpr_mask ) * REG_SIZE;
saveRegSet( index_reg, CurrProc->targ.fpr_mask, offset, TRUE );
}
static void emitSavedRegsEpilog( stack_record *saved_regs )
/**********************************************************/
{
type_length offset;
uint_32 index_reg;
index_reg = addressableRegion( saved_regs, &offset );
loadRegSet( index_reg, CurrProc->targ.fpr_mask, offset, TRUE );
offset += CountBits( CurrProc->targ.fpr_mask ) * REG_SIZE;
loadRegSet( index_reg, CurrProc->targ.gpr_mask, offset, FALSE );
}
static void initVarargs( stack_record *varargs, type_length *offset )
/********************************************************************/
{
sym_handle sym;
fe_attr attr;
varargs->start = *offset;
varargs->size = 0;
sym = AskForLblSym( CurrProc->label );
attr = FEAttr( sym );
if( attr & FE_VARARGS ) {
varargs->size = 4 * REG_SIZE;
*offset += varargs->size;
}
}
static void emitVarargsProlog( stack_record *varargs )
/*****************************************************/
{
type_length offset;
uint_32 index_reg;
if( varargs->size != 0 ) {
index_reg = addressableRegion( varargs, &offset );
offset += varargs->size;
// four registers starting at $4 (ie. $a0-$a3)
saveRegSet( index_reg, 0x0f << 4, offset, FALSE );
// offset -= 6 * REG_SIZE;
// saveRegSet( index_reg, 0x3f << 16, offset, TRUE );
}
}
static void emitVarargsEpilog( stack_record *varargs )
/*****************************************************/
{
// NB see FrameSaveEpilog below
_unused( varargs );
}
static void initFrameSave( stack_record *fs, type_length *offset )
/*****************************************************************/
{
fs->start = *offset;
fs->size = 0;
if( CurrProc->targ.base_is_fp ) {
fs->size = REG_SIZE;
*offset += fs->size;
}
}
static void emitFrameSaveProlog( stack_record *fs )
/**************************************************/
{
uint_32 index_reg;
type_length offset;
if( fs->size != 0 ) {
index_reg = addressableRegion( fs, &offset );
saveReg( index_reg, MIPS_FRAME_REG, offset, FALSE );
}
}
static void emitFrameSaveEpilog( stack_record *fs )
/**************************************************/
{
uint_32 index_reg;
type_length offset;
// NB This instruction must immediately preceed the
// stack restoration instruction - which means that the
// varargs epilog above must be empty
if( fs->size != 0 ) {
index_reg = addressableRegion( fs, &offset );
loadReg( index_reg, MIPS_FRAME_REG, offset, FALSE );
}
}
static void initSlop( stack_record *slop, type_length *offset )
/*****************************************************************/
{
type_length off;
off = *offset;
slop->start = off;
slop->size = 0;
if( off & (STACK_ALIGNMENT - 1) ) {
slop->size = STACK_ALIGNMENT - ( off & (STACK_ALIGNMENT - 1) );
*offset += slop->size;
}
}
static void emitSlopProlog( stack_record *fs )
/*********************************************/
{
_unused( fs );
}
static void emitSlopEpilog( stack_record *fs )
/*********************************************/
{
_unused( fs );
}
static signed_32 frameSize( stack_map *map )
/*******************************************/
{
signed_32 size;
size = map->slop.size + /*map->varargs.size + */map->frame_save.size + map->saved_regs.size +
map->locals.size + map->parm_cache.size;
assert( ( size & ( STACK_ALIGNMENT - 1 ) ) == 0 );
return( size );
}
static void initStackLayout( stack_map *map )
/********************************************/
{
type_length offset;
offset = 0;
initParmCache( &map->parm_cache, &offset );
initLocals( &map->locals, &offset );
initSavedRegs( &map->saved_regs, &offset );
initFrameSave( &map->frame_save, &offset );
initSlop( &map->slop, &offset );
initVarargs( &map->varargs, &offset );
}
static void SetupVarargsReg( stack_map *map )
/********************************************/
{
if( map->varargs.size != 0 ) {
type_length offset;
offset = map->varargs.start;
// Skip hidden parameter in first register
if( CurrProc->targ.return_points != NULL ) {
offset += REG_SIZE;
}
if( offset > MIPS_MAX_OFFSET ) {
GenLOADS32( offset, VARARGS_PTR );
// 'add va_home,va_home,sp'
GenRType( 0x00, 0x21, MIPS_STACK_REG, VARARGS_PTR, VARARGS_PTR );
} else {
genLoadImm( MIPS_STACK_REG, offset, VARARGS_PTR );
}
}
}
static void emitProlog( stack_map *map )
/***************************************/
{
type_length frame_size;
frame_size = frameSize( map );
if( frame_size != 0 ) {
if( frame_size <= MIPS_MAX_OFFSET ) {
genLoadImm( MIPS_STACK_REG, -frame_size, MIPS_STACK_REG );
} else {
GenLOADS32( frame_size, MIPS_GPR_SCRATCH );
// 'subu sp,sp,at'
GenRType( 0x00, 0x23, MIPS_STACK_REG, MIPS_STACK_REG, MIPS_GPR_SCRATCH );
}
if( frame_size >= PAGE_SIZE ) {
GenCallLabelReg( RTLabel( RT_STK_CRAWL_SIZE ), RT_RET_REG );
// Next instruction will be in delay slot!
if( frame_size <= MIPS_MAX_OFFSET ) {
genLoadImm( MIPS_ZERO_SINK, frame_size, RT_PARM1 );
} else {
genMove( MIPS_GPR_SCRATCH, RT_PARM1 );
}
}
}
if( map->locals.size != 0 || map->parm_cache.size != 0 ) {
if( _IsTargetModel( STACK_INIT ) ) {
type_length size;
size = map->locals.size + map->parm_cache.size;
if( size > MIPS_MAX_OFFSET ) {
GenLOADS32( size, RT_PARM1 );
GenCallLabelReg( RTLabel( RT_STK_STOMP ), RT_RET_REG );
genNOP(); // could split LOADS32 call to fill in delay slot...
} else {
GenCallLabelReg( RTLabel( RT_STK_STOMP ), RT_RET_REG );
// Next instruction will be in delay slot!
genLoadImm( MIPS_ZERO_SINK, map->locals.size + map->parm_cache.size, RT_PARM1 );
}
}
}
emitVarargsProlog( &map->varargs );
emitSlopProlog( &map->slop );
emitFrameSaveProlog( &map->frame_save );
emitSavedRegsProlog( &map->saved_regs );
emitLocalProlog( &map->locals );
emitParmCacheProlog( &map->parm_cache );
if( map->frame_save.size != 0 ) {
genMove( MIPS_STACK_REG, MIPS_FRAME_REG );
}
}
static void emitEpilog( stack_map *map )
/***************************************/
{
type_length frame_size;
if( map->frame_save.size != 0 ) {
// NB should just use MIPS_FRAME_REG instead of MIPS_STACK_REG in restore
// code and not bother emitting this instruction
genMove( MIPS_FRAME_REG, MIPS_STACK_REG );
}
emitParmCacheEpilog( &map->parm_cache );
emitLocalEpilog( &map->locals );
emitSavedRegsEpilog( &map->saved_regs );
emitFrameSaveEpilog( &map->frame_save );
emitSlopEpilog( &map->slop );
emitVarargsEpilog( &map->varargs );
frame_size = frameSize( map );
if( frame_size != 0 ) {
if( frame_size <= MIPS_MAX_OFFSET ) {
genLoadImm( MIPS_STACK_REG, frame_size, MIPS_STACK_REG );
} else {
GenLOADS32( frame_size, MIPS_GPR_SCRATCH );
// 'addu sp,sp,at'
GenRType( 0x00, 0x21, MIPS_STACK_REG, MIPS_STACK_REG, MIPS_GPR_SCRATCH );
}
}
}
extern void GenProlog( void )
/****************************/
{
seg_id old;
label_handle label;
old = SetOP( AskCodeSeg() );
label = CurrProc->label;
if( _IsModel( NUMBERS ) ) {
OutFileStart( HeadBlock->ins.hd.line_num );
}
TellKeepLabel( label );
TellProcLabel( label );
CodeLabelLinenum( label, DepthAlign( PROC_ALIGN ), HeadBlock->ins.hd.line_num );
if( _IsModel( DBG_LOCALS ) ) { // d1+ or d2
// DbgRtnBeg( CurrProc->targ.debug, lc );
EmitRtnBeg( /*label, HeadBlock->ins.hd.line_num*/ );
}
// keep stack aligned
CurrProc->locals.size = _RoundUp( CurrProc->locals.size, REG_SIZE );
CurrProc->parms.base = 0;
CurrProc->parms.size = CurrProc->state.parm.offset;
calcUsedRegs();
initStackLayout( &CurrProc->targ.stack_map );
emitProlog( &CurrProc->targ.stack_map );
EmitProEnd();
SetupVarargsReg( &CurrProc->targ.stack_map );
CurrProc->targ.frame_size = frameSize( &CurrProc->targ.stack_map );
SetOP( old );
}
extern void GenEpilog( void )
/****************************/
{
seg_id old;
old = SetOP( AskCodeSeg() );
EmitEpiBeg();
emitEpilog( &CurrProc->targ.stack_map );
GenRET();
CurrProc->prolog_state |= GENERATED_EPILOG;
EmitRtnEnd();
SetOP( old );
}
extern int AskDisplaySize( int level )
/*************************************/
{
level = level;
return( 0 );
}
extern void InitStackDepth( block *blk )
/***************************************/
{
blk = blk;
}
extern type_length PushSize( type_length len )
/*********************************************/
{
if( len < REG_SIZE ) return( REG_SIZE );
return( len );
}
extern type_length NewBase( name *op )
/*************************************/
{
return( TempLocation( op ) );
}
extern int ParmsAtPrologue( void )
/*********************************/
{
return( 0 );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?