static bool okHwChange( // TEST IF OK TO CHANGE HARDWARE DEFINITION hw_reg_set oldr, // - reg. set, old hw_reg_set newr, // - reg. set, new hw_reg_set defr ) // - reg. set, default { return HW_Equal( oldr, newr ) || HW_Equal( oldr, defr ); }
void UpdateReturn( call_state *state, type_def *tipe, type_class_def type_class, aux_handle aux ) /**************************************************************************************************/ { hw_reg_set normal; if( _FPULevel( FPU_87 ) && _NPX( state->attr ) && (tipe->attr & TYPE_FLOAT) ) { HW_COnlyOn( state->return_reg, HW_ST0 ); } else { HW_CTurnOff( state->return_reg, HW_FLTS ); } if( tipe == TypeNone ) { if( HW_CEqual( state->return_reg, HW_EMPTY ) ) return; FEMessage( MSG_BAD_RETURN_REGISTER, aux ); HW_CAsgn( state->return_reg, HW_EMPTY ); state->attr &= ~ROUTINE_HAS_SPECIAL_RETURN; } else if( type_class == XX ) { normal = ReturnReg( WD, _NPX( state->attr ) ); if( HW_Equal( state->return_reg, normal ) ) return; if( HW_CEqual( state->return_reg, HW_EMPTY ) ) return; // if( !HW_Ovlap( state->return_reg, state->unalterable ) && // IsRegClass( state->return_reg, WD ) ) // return; if( IsRegClass( state->return_reg, WD ) ) return; FEMessage( MSG_BAD_RETURN_REGISTER, aux ); state->return_reg = normal; state->attr &= ~ROUTINE_HAS_SPECIAL_RETURN; } else { normal = ReturnReg( type_class, _NPX( state->attr ) ); if( HW_Equal( state->return_reg, normal ) ) return; // if( !HW_Ovlap( state->return_reg, state->unalterable ) && // IsRegClass( state->return_reg, type_class ) ) // return; if( IsRegClass( state->return_reg, type_class ) ) return; FEMessage( MSG_BAD_RETURN_REGISTER, aux ); state->return_reg = normal; state->attr &= ~ROUTINE_HAS_SPECIAL_RETURN; } }
bool ScAddOk( hw_reg_set reg1, hw_reg_set reg2 ) /********************************************************** Is it ok to say that "reg1" = "reg2"? This is not ok for unalterable registers since there may be hidden modifications of these registers. */ { if( HW_Ovlap( reg1, CurrProc->state.unalterable ) ) { if( !HW_CEqual( reg1, HW_DS ) && !HW_CEqual( reg1, HW_SS ) ) { return( false ); } } if( HW_Ovlap( reg2, CurrProc->state.unalterable ) ) { if( !HW_Equal( reg2, HW_DS ) && !HW_Equal( reg2, HW_SS ) ) { return( false ); } } return( true ); }
bool IsRegClass( hw_reg_set regs, type_class_def type_class ) /**************************************************************/ { hw_reg_set *list; for( list = RegSets[IsSets[type_class]]; !HW_CEqual( *list, HW_EMPTY ); ++list ) { if( HW_Equal( *list, regs ) ) { return( true ); } } return( false ); }
bool PragmasTypeEquivalent( // TEST IF TWO PRAGMAS ARE TYPE-EQUIVALENT AUX_INFO *inf1, // - pragma [1] AUX_INFO *inf2 ) // - pragma [2] { if( inf1 == NULL ) { inf1 = &DefaultInfo; } if( inf2 == NULL ) { inf2 = &DefaultInfo; } if( inf1 == inf2 ) { return TRUE; } return ( ( inf1->cclass & ~CALL_CLASS_IGNORE ) == ( inf2->cclass & ~CALL_CLASS_IGNORE ) ) && parmSetsIdentical( inf1->parms, inf2->parms ) && HW_Equal( inf1->returns, inf2->returns ) && HW_Equal( inf1->streturn, inf2->streturn ) && HW_Equal( inf1->save, inf2->save ) && ( inf1->flags == inf2->flags ); }
bool IsIndexReg( hw_reg_set reg, type_class_def type_class, bool is_temp_index ) /*********************************************************************************/ { hw_reg_set *dregs; /* unused parameters */ (void)type_class; (void)is_temp_index; for( dregs = &DWordRegs[0]; !HW_CEqual( *dregs, HW_EMPTY ); ++dregs ) { if( HW_Equal( *dregs, reg ) ) { return( true ); } } return( false ); }
bool PragmaOKForVariables( // TEST IF PRAGMA IS SUITABLE FOR A VARIABLE AUX_INFO *datap ) // - pragma { AUX_INFO *def_info; // only the obj_name can be set for variables everything else is // specific to functions except for "__cdecl" and "__syscall" if( datap == &CdeclInfo ) { return( TRUE ); } if( datap == &SyscallInfo ) { return( TRUE ); } def_info = &DefaultInfo; if( datap->cclass != def_info->cclass ) { return( FALSE ); } if( datap->code != def_info->code ) { return( FALSE ); } if( ! parmSetsIdentical( datap->parms, def_info->parms ) ) { return( FALSE ); } if( ! HW_Equal( datap->returns, def_info->returns ) ) { return( FALSE ); } if( ! HW_Equal( datap->streturn, def_info->streturn ) ) { return( FALSE ); } if( ! HW_Equal( datap->save, def_info->save ) ) { return( FALSE ); } if( datap->flags != def_info->flags ) { return( FALSE ); } return( TRUE ); }
static byte DoIndex( hw_reg_set regs ) /****************************************/ { byte i; for( i = 0; i < INDICES; ++i ) { if( HW_Equal( regs, IndexTab[i] ) ) { break; } } if( i >= INDICES ) { _Zoiks( ZOIKS_033 ); } i <<= S_RMR_RM; return( i ); }
static bool parmSetsIdentical( hw_reg_set *parms1, hw_reg_set *parms2 ) { if( parms1 == parms2 ) { return( TRUE ); } if( parms1 != NULL && parms2 != NULL ) { for(;;) { if( HW_Equal( *parms1, *parms2 ) ) { if( HW_CEqual( *parms1, HW_EMPTY ) ) { return( TRUE ); } ++parms1; ++parms2; } else { break; } } } return( FALSE ); }
axp_regn RegTransN( name *reg_name ) /***** Translate reg name to enum name ****/ { hw_reg_set reg; int i; reg = reg_name->r.reg; for( i = 0; i < sizeof( QWordRegs ) / sizeof( QWordRegs[0] ); i++ ) { if( HW_Subset( QWordRegs[i], reg ) ) { return( i+AXP_REGN_r0 ); } } for( i = 0; i < sizeof( FloatRegs ) / sizeof( FloatRegs[0] ); i++ ) { if( HW_Equal( reg, FloatRegs[i] ) ) { return( i+AXP_REGN_f0 ); } } _Zoiks( ZOIKS_031 ); return( AXP_REGN_END ); }
byte RegTrans( hw_reg_set reg ) /****************************************/ { int i; /* * This should be cached in the reg name and used instead of a stupid lookup */ for( i = 0; i < sizeof( QWordRegs ) / sizeof( QWordRegs[0] ); i++ ) { if( HW_Subset( QWordRegs[i], reg ) ) { return( i ); } } for( i = 0; i < sizeof( FloatRegs ) / sizeof( FloatRegs[0] ); i++ ) { if( HW_Equal( reg, FloatRegs[i] ) ) { return( i ); } } return( 0 ); }
static bool PartIntersect( reg_tree *part, reg_tree *whole, hw_reg_set (*rtn)( hw_reg_set ) ) /****************************************************************/ { bool change; int i; int j; hw_reg_set *src; hw_reg_set *dst; hw_reg_set curr; hw_reg_set tmp; change = false; if( whole->idx != RL_NUMBER_OF_SETS ) { if( part->idx == RL_NUMBER_OF_SETS ) { /* build a register for part consisting of the Hi/Lo parts of whole*/ part->regs = AllocRegSet(); part->idx = RL_; src = whole->regs; dst = part->regs; for( i = REG_COUNT; i > 0; --i ) { *dst++ = rtn( *src++ ); } } /* check that all Hi/Lo parts of whole are contained in part*/ src = whole->regs; for( i = REG_COUNT; i > 0; --i ) { if( !HW_CEqual( *src, HW_EMPTY ) ) { curr = rtn( *src ); if( !HW_CEqual( curr, HW_EMPTY ) ) { dst = part->regs; for( j = REG_COUNT; j > 0; --j ) { if( HW_Equal( *dst, curr ) ) { break; } ++dst; } if( j == 0 ) { HW_CAsgn( *src, HW_EMPTY ); change = true; } } else { HW_CAsgn( *src, HW_EMPTY ); change = true; } } ++src; } /* check that each reg in part is a Hi/Lo part in whole*/ src = part->regs; for( i = REG_COUNT; i > 0; --i ) { curr = *src; if( !HW_CEqual( curr, HW_EMPTY ) ) { dst = whole->regs; for( j = REG_COUNT; j > 0; --j ) { if( !HW_CEqual( *dst, HW_EMPTY ) ) { tmp = rtn( *dst ); if( HW_Equal( curr, tmp ) ) { break; } } ++dst; } if( j == 0 ) { HW_CAsgn( *src, HW_EMPTY ); change = true; } } ++src; } } return( change ); }
extern bool DoVerify( vertype kind, instruction *ins ) { /**********************************************************/ name *op1; name *op2; name *result; hw_reg_set tmp; result = ins->result; if( ins->num_operands != 0 ) { op1 = ins->operands[ 0 ]; if( ins->num_operands != 1 ) { op2 = ins->operands[ 1 ]; } } switch( kind ) { case V_OP2I2: /* * U2 is OK too. A U2 operand wouldn't be present in the instruction * unless the tree code decided it was ok for a halfword instruction * Kludgey? Maybe just a little. */ if( op2->n.name_class == U2 ) return( TRUE ); if( op2->n.name_class == I2 ) return( TRUE ); return( FALSE ); case V_OP1SMALL: if( op1->c.const_type != CONS_ABSOLUTE ) return( FALSE ); if( op1->c.int_value < 0 ) return( FALSE ); if( op1->c.int_value > 4095 ) return( FALSE ); return( TRUE ); case V_OP1TEMP: if( op1->n.class == N_TEMP ) return( TRUE ); return( FALSE ); case V_OP1ADDR: case V_OP1LOC: if( op1->n.class == N_MEMORY ) return( TRUE ); return( FALSE ); case V_OP2I2CON: if( op2->c.const_type == CONS_ABSOLUTE && CFIsI16( op2->c.value ) ) return( TRUE ); return( FALSE ); case V_LA2: if( HW_CEqual( op1->r.reg, HW_G0 ) ) return( FALSE ); /* fall through ! */ case V_OP2SMALL: if( op2->c.const_type != CONS_ABSOLUTE ) return( FALSE ); if( op2->c.int_value < 0 ) return( FALSE ); if( op2->c.int_value > 4095 ) return( FALSE ); return( TRUE ); case V_MULPAIR: if( !IsRegPair( result->r.reg ) ) return( FALSE ); tmp = LowReg( result->r.reg ); if( !HW_Equal( tmp, op1->r.reg ) ) return( FALSE ); return( TRUE ); case V_CONVPAIR: if( !IsRegPair( result->r.reg ) ) return( FALSE ); tmp = HighReg( result->r.reg ); if( !HW_Equal( tmp, op1->r.reg ) ) return( FALSE ); return( TRUE ); case V_SIZE_SMALL: if( op1->n.size > 256 ) return( FALSE ); return( TRUE ); case V_OP2BYTE4CONS: if( !CFIsI32( op2->c.value ) ) return( FALSE ); if( ( op2->c.int_value & 0xFFFFFF00 ) == 0 ) return( TRUE ); if( ( op2->c.int_value & 0xFFFF00FF ) == 0 ) return( TRUE ); if( ( op2->c.int_value & 0xFF00FFFF ) == 0 ) return( TRUE ); if( ( op2->c.int_value & 0x00FFFFFF ) == 0 ) return( TRUE ); return( FALSE ); case V_OP2BYTE2CONS: if( !CFIsI16( op2->c.value ) ) return( FALSE ); if( ( op2->c.int_value & 0xFFFFFF00 ) == 0 ) return( TRUE ); if( ( op2->c.int_value & 0xFFFF00FF ) == 0 ) return( TRUE ); return( FALSE ); case V_CMPEQ_OP2ZERO: if( !OtherVerify( V_CMPEQ, ins, op1, op2, result ) ) return( FALSE ); if( !OtherVerify( V_OP2ZERO, ins, op1, op2, result ) ) return( FALSE ); return( TRUE ); default: return( OtherVerify( kind, ins, op1, op2, result ) ); } return( FALSE ); }