hw_reg_set FixedRegs( void ) /***********************************/ /* MJC do you really want to fix them */ { hw_reg_set fixed; HW_CAsgn( fixed, HW_R30 ); HW_CTurnOn( fixed, HW_R31 ); HW_CTurnOn( fixed, HW_R15 ); HW_CTurnOn( fixed, HW_F30 ); // Used to generate problematic converts (I8->FD and such) return( fixed ); }
static void CopyAuxInfo( void ) /*****************************/ { hw_reg_set default_flt_n_seg; hw_reg_set flt_n_seg; if( CurrEntry == NULL ) { // Redefining a built-in calling convention } else { CurrInfo = (struct aux_info *)CMemAlloc( sizeof( struct aux_info ) ); *CurrInfo = *CurrAlias; } if( AuxInfo.code != NULL ) { CurrInfo->code = AuxInfo.code; } if( AuxInfoFlg.f_near ) { CurrInfo->cclass &= ~FAR; } if( AuxInfoFlg.f_routine_pops ) { CurrInfo->cclass &= ~CALLER_POPS; } if( AuxInfoFlg.f_caller_return ) { CurrInfo->cclass &= ~ROUTINE_RETURN; } if( AuxInfoFlg.f_8087_returns ) { CurrInfo->cclass &= ~NO_8087_RETURNS; } CurrInfo->cclass |= AuxInfo.cclass; CurrInfo->flags |= AuxInfo.flags; if( AuxInfo.objname != NULL ) CurrInfo->objname = AuxInfo.objname; if( AuxInfo.cclass & SPECIAL_RETURN ) CurrInfo->returns = AuxInfo.returns; if( AuxInfo.cclass & SPECIAL_STRUCT_RETURN ) CurrInfo->streturn = AuxInfo.streturn; if( AuxInfo.parms != NULL ) CurrInfo->parms = AuxInfo.parms; if( !HW_CEqual( AuxInfo.save, HW_EMPTY ) ) { HW_CTurnOn( CurrInfo->save, HW_FULL ); if( !( AuxInfo.cclass & MODIFY_EXACT ) && !CompFlags.save_restore_segregs ) { HW_Asgn( default_flt_n_seg, WatcallInfo.save ); HW_CAsgn( flt_n_seg, HW_FLTS ); HW_CTurnOn( flt_n_seg, HW_SEGS ); HW_TurnOff( CurrInfo->save, flt_n_seg ); HW_OnlyOn( default_flt_n_seg, flt_n_seg ); HW_TurnOn( CurrInfo->save, default_flt_n_seg ); } HW_TurnOff( CurrInfo->save, AuxInfo.save ); } }
static void GetSaveInfo( void ) { hw_reg_set modlist; hw_reg_set default_flt_n_seg; hw_reg_set flt_n_seg; struct { unsigned f_exact : 1; unsigned f_nomemory : 1; unsigned f_list : 1; } have; have.f_exact = 0; have.f_nomemory = 0; have.f_list = 0; for( ;; ) { if( !have.f_exact && PragRecog( "exact" ) ) { CurrInfo->cclass |= MODIFY_EXACT; have.f_exact = 1; } else if( !have.f_nomemory && PragRecog( "nomemory" ) ) { CurrInfo->cclass |= NO_MEMORY_CHANGED; have.f_nomemory = 1; } else if( !have.f_list && IS_REGSET( CurToken ) ) { modlist = PragRegList(); have.f_list = 1; } else { break; } } if( have.f_list ) { HW_Asgn( default_flt_n_seg, DefaultInfo.save ); HW_CTurnOn( CurrInfo->save, HW_FULL ); if( !have.f_exact && !CompFlags.save_restore_segregs ) { HW_CAsgn( flt_n_seg, HW_FLTS ); HW_CTurnOn( flt_n_seg, HW_SEGS ); HW_TurnOff( CurrInfo->save, flt_n_seg ); HW_OnlyOn( default_flt_n_seg, flt_n_seg ); HW_TurnOn( CurrInfo->save, default_flt_n_seg ); } HW_TurnOff( CurrInfo->save, modlist ); } }
an BGCall( cn call, bool use_return, bool in_line ) /******************************************************/ { instruction *call_ins; call_state *state; name *ret_ptr = NULL; name *result; name *temp; name *reg_name; instruction *ret_ins = NULL; hw_reg_set return_reg; hw_reg_set zap_reg; if( call->name->tipe == TypeProcParm ) { SaveDisplay( OP_PUSH ); } state = call->state; result = BGNewTemp( call->tipe ); call_ins = call->ins; /* If we have a return value that won't fit in a register*/ /* pass a pointer to result as the first parm*/ if( call_ins->type_class == XX ) { if( _RoutineIsFar16( state->attr ) ) { if( state->attr & ROUTINE_ALLOCS_RETURN ) { HW_CAsgn( state->return_reg, HW_EAX ); } else { HW_CAsgn( state->return_reg, HW_EBX ); } } if( ( state->attr & ROUTINE_ALLOCS_RETURN ) == 0 ) { if( HW_CEqual( state->return_reg, HW_EMPTY ) ) { ret_ptr = AllocTemp( WD ); } else { ret_ptr = AllocRegName( state->return_reg ); } ret_ins = MakeUnary( OP_LA, result, ret_ptr, WD ); HW_TurnOn( state->parm.used, state->return_reg ); call_ins->flags.call_flags |= CALL_RETURNS_STRUCT; } } if( _IsTargetModel(FLOATING_DS) && (state->attr&ROUTINE_NEEDS_DS_LOADED) ) { HW_CTurnOn( state->parm.used, HW_DS ); } if( _RoutineIsFar16( state->attr ) ) { #if _TARGET & _TARG_80386 Far16Parms( call ); #endif } else { if( AssgnParms( call, in_line ) ) { if( state->attr & ROUTINE_REMOVES_PARMS ) { call_ins->flags.call_flags |= CALL_POPS_PARMS; } } } if( state->attr & (ROUTINE_MODIFIES_NO_MEMORY | ROUTINE_NEVER_RETURNS) ) { /* a routine that never returns can not write any memory as far as this routine is concerned */ call_ins->flags.call_flags |= CALL_WRITES_NO_MEMORY; } if( state->attr & ROUTINE_READS_NO_MEMORY ) { call_ins->flags.call_flags |= CALL_READS_NO_MEMORY; } if( state->attr & ROUTINE_NEVER_RETURNS ) { call_ins->flags.call_flags |= CALL_ABORTS; } if( _RoutineIsInterrupt( state->attr ) ) { call_ins->flags.call_flags |= CALL_INTERRUPT | CALL_POPS_PARMS; } if( !use_return ) { call_ins->flags.call_flags |= CALL_IGNORES_RETURN; } if( call_ins->type_class == XX ) { reg_name = AllocRegName( state->return_reg ); if( state->attr & ROUTINE_ALLOCS_RETURN ) { call_ins->result = reg_name; AddCall( call_ins, call ); if( use_return ) { temp = AllocTemp( WD ); /* assume near pointer*/ AddIns( MakeMove( reg_name, temp, WD ) ); temp = SAllocIndex( temp, NULL, 0, result->n.type_class, call->tipe->length ); AddIns( MakeMove( temp, result, result->n.type_class ) ); } } else { call_ins->result = result; AddIns( ret_ins ); if( HW_CEqual( state->return_reg, HW_EMPTY ) ) { AddIns( MakeUnary( OP_PUSH, ret_ptr, NULL, WD ) ); state->parm.offset += TypeClassSize[WD]; call_ins->operands[CALL_OP_POPS] = AllocS32Const( call_ins->operands[CALL_OP_POPS]->c.lo.int_value + TypeClassSize[WD] ); if( state->attr & ROUTINE_REMOVES_PARMS ) { call_ins->flags.call_flags |= CALL_POPS_PARMS; } } AddCall( call_ins, call ); } } else { return_reg = state->return_reg; zap_reg = call_ins->zap->reg; HW_CTurnOn( zap_reg, HW_FLTS ); HW_OnlyOn( return_reg, zap_reg ); call_ins->result = AllocRegName( return_reg ); reg_name = AllocRegName( state->return_reg ); AddCall( call_ins, call ); if( use_return ) { ret_ins = MakeMove( reg_name, result, result->n.type_class ); if( HW_COvlap( reg_name->r.reg, HW_FLTS ) ) { ret_ins->stk_entry = 1; ret_ins->stk_exit = 0; } AddIns( ret_ins ); } } if( state->parm.offset != 0 && ( state->attr & ROUTINE_REMOVES_PARMS ) == 0 ) { reg_name = AllocRegName( HW_SP ); AddIns( MakeBinary( OP_ADD, reg_name, AllocS32Const( state->parm.offset ), reg_name, WD ) ); } return( MakeTempAddr( result ) ); }
/* // This section is for // 8086 // 386 // // pass auxiliary information to back end */ CGPOINTER FEAuxInfo( CGPOINTER req_handle, int request ) { aux_info *inf; auto SYM_ENTRY sym; static hw_reg_set save_set; switch( request ) { case SOURCE_LANGUAGE: return( (CGPOINTER)"C" ); case STACK_SIZE_8087: return( (CGPOINTER)(pointer_int)Stack87 ); case CODE_GROUP: return( (CGPOINTER)GenCodeGroup ); case DATA_GROUP: return( (CGPOINTER)DataSegName ); case OBJECT_FILE_NAME: return( (CGPOINTER)ObjFileName() ); case REVISION_NUMBER: return( (CGPOINTER)(pointer_int)II_REVISION ); case AUX_LOOKUP: return( req_handle ); case PROEPI_DATA_SIZE: return( (CGPOINTER)(pointer_int)ProEpiDataSize ); case DBG_PREDEF_SYM: return( (CGPOINTER)SymDFAbbr ); case P5_CHIP_BUG_SYM: return( (CGPOINTER)SymChipBug ); case CODE_LABEL_ALIGNMENT: { static unsigned char Alignment[] = { 2, 1, 1 }; if( OptSize == 0 ) Alignment[1] = TARGET_INT; return( (CGPOINTER)Alignment ); } case CLASS_NAME: return( (CGPOINTER)SegClassName( (segment_id)(pointer_int)req_handle ) ); case USED_8087: CompFlags.pgm_used_8087 = 1; return( NULL ); #if _CPU == 386 case P5_PROF_DATA: return( (CGPOINTER)FunctionProfileBlock ); case P5_PROF_SEG: return( (CGPOINTER)(pointer_int)FunctionProfileSegment ); #endif case SOURCE_NAME: if( SrcFName == ModuleName ) { return( (CGPOINTER)FNameFullPath( FNames ) ); } else { return( (CGPOINTER)ModuleName ); } case CALL_CLASS: { static call_class cclass; cclass = GetCallClass( req_handle ); return( (CGPOINTER)&cclass ); } case FREE_SEGMENT: return( NULL ); case NEXT_LIBRARY: case LIBRARY_NAME: return( NextLibrary( (int)(pointer_int)req_handle, request ) ); case NEXT_IMPORT: case IMPORT_NAME: return( NextImport( (int)(pointer_int)req_handle, request ) ); case NEXT_IMPORT_S: case IMPORT_NAME_S: return( NextImportS( (int)(pointer_int)req_handle, request ) ); case NEXT_ALIAS: case ALIAS_NAME: case ALIAS_SYMBOL: case ALIAS_SUBST_NAME: case ALIAS_SUBST_SYMBOL: return( NextAlias( (int)(pointer_int)req_handle, request ) ); case TEMP_LOC_NAME: return( (CGPOINTER)(pointer_int)TEMP_LOC_QUIT ); case TEMP_LOC_TELL: return( NULL ); case NEXT_DEPENDENCY: if( CompFlags.emit_dependencies ) return( (CGPOINTER)NextDependency( (FNAMEPTR)req_handle ) ); return( NULL ); case DEPENDENCY_TIMESTAMP: return( (CGPOINTER)getFileDepTimeStamp( (FNAMEPTR)req_handle ) ); case DEPENDENCY_NAME: return( (CGPOINTER)FNameFullPath( (FNAMEPTR)req_handle ) ); case PEGGED_REGISTER: return( (CGPOINTER)SegPeggedReg( (segment_id)(pointer_int)req_handle ) ); default: break; } inf = FindInfo( &sym, req_handle ); switch( request ) { case SAVE_REGS: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } else { sym.mods = 0; } save_set = inf->save; if( sym.mods & FLAG_SAVEREGS ) { HW_CTurnOn( save_set, HW_SEGS ); } #ifdef __SEH__ if( (SYM_HANDLE)req_handle == SymTryInit ) { HW_CTurnOff( save_set, HW_SP ); } #endif return( (CGPOINTER)&save_set ); case RETURN_REG: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } return( (CGPOINTER)&inf->returns ); case CALL_BYTES: return( (CGPOINTER)inf->code ); case PARM_REGS: #ifdef __SEH__ if(( (SYM_HANDLE)req_handle == SymTryInit ) || ( (SYM_HANDLE)req_handle == SymTryFini ) || ( (SYM_HANDLE)req_handle == SymTryUnwind ) || ( (SYM_HANDLE)req_handle == SymExcept )) { return( (CGPOINTER)TryParms ); } #endif if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); if( inf->code == NULL && VarFunc( &sym ) ) { return( (CGPOINTER)DefaultVarParms ); } } return( (CGPOINTER)inf->parms ); case STRETURN_REG: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } return( (CGPOINTER)&inf->streturn ); default: break; } return( NULL ); }
extern hw_reg_set SavedRegs( void ) /*********************************/ { hw_reg_set saved; HW_CAsgn( saved, HW_EMPTY ); HW_CTurnOn( saved, HW_R16 ); HW_CTurnOn( saved, HW_R17 ); HW_CTurnOn( saved, HW_R18 ); HW_CTurnOn( saved, HW_R19 ); HW_CTurnOn( saved, HW_R20 ); HW_CTurnOn( saved, HW_R21 ); HW_CTurnOn( saved, HW_R22 ); HW_CTurnOn( saved, HW_R23 ); HW_CTurnOn( saved, HW_R30 ); HW_CTurnOn( saved, HW_R31 ); HW_CTurnOn( saved, HW_F20 ); HW_CTurnOn( saved, HW_F21 ); HW_CTurnOn( saved, HW_F22 ); HW_CTurnOn( saved, HW_F23 ); HW_CTurnOn( saved, HW_F24 ); HW_CTurnOn( saved, HW_F25 ); HW_CTurnOn( saved, HW_F26 ); HW_CTurnOn( saved, HW_F27 ); HW_CTurnOn( saved, HW_F28 ); HW_CTurnOn( saved, HW_F29 ); HW_CTurnOn( saved, HW_F30 ); return( saved ); }
void PragAux( void ) /******************/ { struct { unsigned f_call : 1; unsigned f_loadds : 1; unsigned f_rdosdev: 1; unsigned f_export : 1; unsigned f_parm : 1; unsigned f_value : 1; unsigned f_modify : 1; unsigned f_frame : 1; unsigned uses_auto: 1; } have; InitAuxInfo(); if( !GetAliasInfo() ) return; if( CurToken != T_ID ) return; SetCurrInfo( Buffer ); NextToken(); PragObjNameInfo( &AuxInfo.objname ); have.f_call = 0; have.f_loadds = 0; have.f_rdosdev = 0; have.f_export = 0; have.f_parm = 0; have.f_value = 0; have.f_modify = 0; have.f_frame = 0; have.uses_auto = 0; /* BBB - Jan 26, 1994 */ for( ;; ) { if( !have.f_call && CurToken == T_EQUAL ) { have.uses_auto = GetByteSeq( &AuxInfo.code ); have.f_call = 1; } else if( !have.f_call && PragRecog( "far" ) ) { AuxInfo.cclass |= FAR; have.f_call = 1; } else if( !have.f_call && PragRecog( "near" ) ) { AuxInfo.cclass &= ~FAR; AuxInfoFlg.f_near = 1; have.f_call = 1; } else if( !have.f_loadds && PragRecog( "loadds" ) ) { AuxInfo.cclass |= LOAD_DS_ON_ENTRY; have.f_loadds = 1; } else if( !have.f_rdosdev && PragRecog( "rdosdev" ) ) { AuxInfo.cclass |= LOAD_RDOSDEV_ON_ENTRY; have.f_rdosdev = 1; } else if( !have.f_export && PragRecog( "export" ) ) { AuxInfo.cclass |= DLL_EXPORT; have.f_export = 1; } else if( !have.f_parm && PragRecog( "parm" ) ) { GetParmInfo(); have.f_parm = 1; } else if( !have.f_value && PragRecog( "value" ) ) { GetRetInfo(); have.f_value = 1; } else if( !have.f_value && PragRecog( "aborts" ) ) { AuxInfo.cclass |= SUICIDAL; have.f_value = 1; } else if( !have.f_modify && PragRecog( "modify" ) ) { GetSaveInfo(); have.f_modify = 1; } else if( !have.f_frame && PragRecog( "frame" ) ) { AuxInfo.cclass |= GENERATE_STACK_FRAME; have.f_frame = 1; } else { break; } } if( have.uses_auto ) { /* We want to force the calling routine to set up a [E]BP frame for the use of this pragma. This is done by saying the pragma modifies the [E]SP register. A kludge, but it works. */ HW_CTurnOn( AuxInfo.save, HW_SP ); } CopyAuxInfo(); PragEnding(); }
hw_reg_set ParmRegConflicts( hw_reg_set regs ) /*************************************************/ { hw_reg_set conflicts; conflicts = regs; if( HW_COvlap( regs, HW_R16 ) ) { HW_CTurnOn( conflicts, HW_F16 ); HW_CTurnOn( conflicts, HW_R16 ); } if( HW_COvlap( regs, HW_R17 ) ) { HW_CTurnOn( conflicts, HW_F17 ); HW_CTurnOn( conflicts, HW_R17 ); } if( HW_COvlap( regs, HW_R18 ) ) { HW_CTurnOn( conflicts, HW_F18 ); HW_CTurnOn( conflicts, HW_R18 ); } if( HW_COvlap( regs, HW_R19 ) ) { HW_CTurnOn( conflicts, HW_F19 ); HW_CTurnOn( conflicts, HW_R19 ); } if( HW_COvlap( regs, HW_R20 ) ) { HW_CTurnOn( conflicts, HW_F20 ); HW_CTurnOn( conflicts, HW_R20 ); } if( HW_COvlap( regs, HW_R21 ) ) { HW_CTurnOn( conflicts, HW_F21 ); HW_CTurnOn( conflicts, HW_R21 ); } if( HW_COvlap( regs, HW_F16 ) ) { HW_CTurnOn( conflicts, HW_R16 ); HW_CTurnOn( conflicts, HW_F16 ); } if( HW_COvlap( regs, HW_F17 ) ) { HW_CTurnOn( conflicts, HW_R17 ); HW_CTurnOn( conflicts, HW_F17 ); } if( HW_COvlap( regs, HW_F18 ) ) { HW_CTurnOn( conflicts, HW_R18 ); HW_CTurnOn( conflicts, HW_F18 ); } if( HW_COvlap( regs, HW_F19 ) ) { HW_CTurnOn( conflicts, HW_R19 ); HW_CTurnOn( conflicts, HW_F19 ); } if( HW_COvlap( regs, HW_F20 ) ) { HW_CTurnOn( conflicts, HW_R20 ); HW_CTurnOn( conflicts, HW_F20 ); } if( HW_COvlap( regs, HW_F21 ) ) { HW_CTurnOn( conflicts, HW_R21 ); HW_CTurnOn( conflicts, HW_F21 ); } return( conflicts ); }
instruction *rMAKECALL( instruction *ins ) /********************************************* Using the table RTInfo[], do all the necessary stuff to turn instruction "ins" into a call to a runtime support routine. Move the parms into registers, and move the return register of the runtime routine into the result. Used for 386 and 370 versions */ { rtn_info *info; label_handle lbl; instruction *left_ins; instruction *new_ins; instruction *last_ins; name *reg_name; hw_reg_set regs; hw_reg_set all_regs; hw_reg_set tmp; rt_class rtindex; if( !_IsConvert( ins ) ) { rtindex = LookupRoutine( ins ); } else { /* look it up again in case we ran out of memory during expansion*/ rtindex = LookupConvertRoutine( ins ); } info = &RTInfo[rtindex]; regs = _ParmReg( info->left ); all_regs = regs; left_ins = MakeMove( ins->operands[0], AllocRegName( regs ), info->operand_class ); ins->operands[0] = left_ins->result; MoveSegOp( ins, left_ins, 0 ); PrefixIns( ins, left_ins ); regs = _ParmReg( info->right ); if( !HW_CEqual( regs, HW_EMPTY ) ) { new_ins = MakeMove( ins->operands[1], AllocRegName( regs ), info->operand_class ); ins->operands[1] = new_ins->result; MoveSegOp( ins, new_ins, 0 ); HW_TurnOn( all_regs, regs ); PrefixIns( ins, new_ins ); } #if _TARGET & _TARG_370 tmp = RAReg(); HW_TurnOn( all_regs, tmp ); tmp = LNReg(); HW_TurnOn( all_regs, tmp ); #elif _TARGET & _TARG_80386 { tmp = ReturnReg( WD, false ); HW_TurnOn( all_regs, tmp ); } #endif reg_name = AllocRegName( all_regs ); lbl = RTLabel( rtindex ); new_ins = NewIns( 3 ); new_ins->head.opcode = OP_CALL; new_ins->type_class = ins->type_class; new_ins->operands[CALL_OP_USED] = reg_name; new_ins->operands[CALL_OP_USED2] = reg_name; new_ins->operands[CALL_OP_ADDR] = AllocMemory( lbl, 0, CG_LBL, ins->type_class ); new_ins->result = NULL; new_ins->num_operands = 2; /* special case for OP_CALL*/ #if _TARGET & _TARG_AXP { HW_CTurnOn( all_regs, HW_FULL ); HW_TurnOff( all_regs, SavedRegs() ); HW_CTurnOff( all_regs, HW_UNUSED ); HW_TurnOn( all_regs, ReturnAddrReg() ); } #endif new_ins->zap = (register_name *)AllocRegName( all_regs ); /* all parm regs could be zapped*/ last_ins = new_ins; if( ins->result == NULL || _OpIsCondition( ins->head.opcode ) ) { /* comparison, still need conditional jumps*/ ins->operands[0] = AllocIntConst( 0 ); ins->operands[1] = AllocIntConst( 1 ); DelSeg( ins ); DoNothing( ins ); /* just conditional jumps for ins*/ PrefixIns( ins, new_ins ); new_ins->ins_flags |= INS_CC_USED; last_ins = ins; } else { regs = _ParmReg( info->result ); tmp = regs; HW_TurnOn( tmp, new_ins->zap->reg ); new_ins->zap = (register_name *)AllocRegName( tmp ); reg_name = AllocRegName( regs ); new_ins->result = reg_name; last_ins = MakeMove( reg_name, ins->result, ins->type_class ); ins->result = last_ins->operands[0]; MoveSegRes( ins, last_ins ); SuffixIns( ins, last_ins ); ReplIns( ins, new_ins ); } FixCallIns( new_ins ); UpdateLive( left_ins, last_ins ); return( left_ins ); }