static name *RTMemRef( rt_class rt_index ) /********************************************* create a memory_name to reference the given runtime label. */ { label_handle hdl; hdl = RTLabel( rt_index ); return( AllocMemory( hdl, 0, CG_LBL, WD ) ); }
static void Far16Parms( cn call ) { /*************************************/ instruction *ins; type_length parm_size; pn parm, next; instruction *call_ins; name *eax; name *ecx; name *esi; label_handle lbl; type_length offset; name *parmlist; call_state *state; rt_class rtindex; call_ins = call->ins; parm_size = 0; state = call->state; for( parm = call->parms; parm != NULL; parm = parm->next ) { parm_size += _RoundUp( parm->name->tipe->length, 2 ); } parmlist = SAllocTemp( XX, parm_size ); parmlist->v.usage |= NEEDS_MEMORY | USE_IN_ANOTHER_BLOCK | USE_ADDRESS; offset = 0; for( parm = call->parms; parm != NULL; parm = parm->next ) { parm->name->u.i.ins->result = STempOffset( parmlist, offset, TypeClass( parm->name->tipe ), parm->name->tipe->length ); offset += _RoundUp( parm->name->tipe->length, 2 ); } for( parm = call->parms; parm != NULL; parm = next ) { next = parm->next; parm->name->format = NF_ADDR; /* so instruction doesn't get freed! */ BGDone( parm->name ); CGFree( parm ); } eax = AllocRegName( HW_EAX ); ecx = AllocRegName( HW_ECX ); esi = AllocRegName( HW_ESI ); HW_TurnOn( state->parm.used, eax->r.reg ); HW_TurnOn( state->parm.used, ecx->r.reg ); HW_TurnOn( state->parm.used, esi->r.reg ); ins = MakeMove( AllocS32Const( parm_size ), ecx, WD ); AddIns( ins ); ins = MakeUnary( OP_LA, parmlist, esi, WD ); AddIns( ins ); if( ins->head.opcode == OP_CALL ) { ins = MakeUnary( OP_LA, call->name->u.n.name, eax, WD ); } else { ins = MakeMove( GenIns( call->name ), eax, WD ); call_ins->head.opcode = OP_CALL; } call_ins->num_operands = 2; AddIns( ins ); if( call_ins->type_class == XX ) { if( state->attr & ROUTINE_ALLOCS_RETURN ) { rtindex = RT_Far16Cdecl; } else { rtindex = RT_Far16Pascal; } } else { rtindex = RT_Far16Func; } lbl = RTLabel( rtindex ); call->name->u.n.name = AllocMemory( lbl, 0, CG_LBL, WD ); call_ins->flags.call_flags |= CALL_FAR16 | CALL_POPS_PARMS; call_ins->operands[CALL_OP_USED] = AllocRegName( state->parm.used ); call_ins->operands[CALL_OP_POPS] = AllocS32Const( 0 ); call_ins->zap = &call_ins->operands[CALL_OP_USED]->r; }
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 ); }