00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #define TRACE_ENTRY(x)
00047 #define TRACE_EXIT(x)
00048 #define TRACE_EXIT_i(x,i)
00049
00050 #include <limits.h>
00051 #include "defs.h"
00052 #include "mtypes.h"
00053 #include "errors.h"
00054 #include "erglob.h"
00055 #include "stab.h"
00056 #include "config_targ.h"
00057 #include "targ_sim.h"
00058
00059 #include "targ_sim_body.h"
00060
00061
00062 #define I0 (Int_Preg_Min_Offset - 1)
00063 #define F0 Float_Preg_Min_Offset
00064
00065 #if (__GNUC__ == 2)
00066 static
00067 #endif
00068 SIM SIM_Info[] = {
00069
00070
00071
00072
00073
00074
00075 {
00076 0,
00077 {0,0,0}, {0,0,0}, {0,0,0},
00078 {0,0,0}, {0,0,0}, {0,0,0},
00079 0, 0, 0,
00080 0, 0, 0,
00081 0, 0, 0, 0
00082 },
00083 {
00084 SIM_FLT_AFTER_INT | SIM_COORD_MEM_REG | SIM_COORD_INT_FLT
00085 | SIM_REG_STRUCTS | SIM_FLT_RTN_COMPLEX | SIM_DBL_REG_FIELDS ,
00086 #if defined(TARG_SL)
00087 {I0+4,I0+11,1}, {F0+6,F0+9,1}, {F0+6,F0+9,1},
00088 #else
00089 {I0+4,I0+11,1}, {F0+12,F0+19,1}, {F0+12,F0+19,1},
00090 #endif
00091 {I0+2,I0+3,1}, {F0,F0+1,2}, {F0,F0+1,2},
00092 MTYPE_I8, MTYPE_F8, MTYPE_F8,
00093 0, 64, -64,
00094 -1, 128, I0+2, I0+25
00095 },
00096 {
00097 SIM_FLT_AFTER_INT | SIM_COORD_MEM_REG | SIM_COORD_INT_FLT
00098 | SIM_REG_STRUCTS | SIM_FLT_RTN_COMPLEX | SIM_DBL_REG_FIELDS ,
00099 #if defined(TARG_SL)
00100 {I0+4,I0+11,1}, {F0+6,F0+9,1}, {F0+6,F0+9,1},
00101 #else
00102 {I0+4,I0+11,1}, {F0+12,F0+19,1}, {F0+12,F0+19,1},
00103 #endif
00104 {I0+2,I0+3,1}, {F0,F0+2,2}, {F0,F0+2,2},
00105 MTYPE_I8, MTYPE_F8, MTYPE_F8,
00106 0, 64, -64,
00107 -1, 128, I0+2, I0+25
00108 }
00109 };
00110
00111
00112 extern BOOL
00113 Is_Return_Preg (PREG_NUM preg)
00114 {
00115 return (preg >= First_Int_Preg_Return_Offset
00116 && preg <= Last_Int_Preg_Return_Offset)
00117 || (preg >= First_Float_Preg_Return_Offset
00118 && preg <= Last_Float_Preg_Return_Offset);
00119 }
00120
00121
00122 extern BOOL
00123 Is_Int_Output_Preg (PREG_NUM preg)
00124 {
00125 Fail_FmtAssertion (
00126 ("Is_Int_Output_Preg not applicable to MIPS targets"));
00127 }
00128
00129
00130 extern BOOL
00131 Is_Formal_Preg (PREG_NUM preg)
00132 {
00133 return (preg >= First_Int_Preg_Param_Offset
00134 && preg <= (First_Int_Preg_Param_Offset
00135 + MAX_NUMBER_OF_REGISTER_PARAMETERS) )
00136 || (preg >= First_Float_Preg_Param_Offset
00137 && preg <= (First_Float_Preg_Param_Offset
00138 + MAX_NUMBER_OF_REGISTER_PARAMETERS) );
00139 }
00140
00141
00142 static BOOL
00143 Struct_Has_One_Float (const TY_IDX ty, TYPE_ID &ftype)
00144 {
00145 if (TY_is_union (ty))
00146 return FALSE;
00147
00148 if (TY_fld (ty).Is_Null ())
00149 return FALSE;
00150
00151 FLD_HANDLE fld = TY_fld (ty);
00152
00153 if (FLD_last_field (fld) && FLD_type (fld) != 0 &&
00154 TY_kind (FLD_type (fld)) == KIND_SCALAR) {
00155 ftype = TY_mtype (FLD_type (fld));
00156 if (MTYPE_float (ftype))
00157 return TRUE;
00158 }
00159 ftype = MTYPE_V;
00160 return FALSE;
00161 }
00162
00163
00164
00165 static BOOL
00166 no_overlap (const FLD_HANDLE fld1, const FLD_HANDLE fld2)
00167 {
00168 if (FLD_ofst (fld1) <= FLD_ofst (fld2))
00169 return FLD_ofst(fld1) + TY_size (FLD_type (fld1)) <= FLD_ofst (fld2);
00170 else
00171 return FLD_ofst(fld2) + TY_size (FLD_type (fld2)) <= FLD_ofst (fld1);
00172 }
00173
00174 static BOOL
00175 Struct_Has_Two_Floats (const TY_IDX ty, TYPE_ID& ftype1, TYPE_ID& ftype2)
00176 {
00177 if (TY_is_union (ty))
00178 return FALSE;
00179
00180 if (TY_fld (ty).Is_Null ())
00181 return FALSE;
00182
00183 FLD_HANDLE fld1 = TY_fld (ty);
00184
00185 if (FLD_last_field (fld1))
00186 return FALSE;
00187
00188 FLD_HANDLE fld2 (FLD_next (fld1));
00189
00190 if (FLD_last_field (fld2) &&
00191 FLD_type (fld1) != 0 && TY_kind (FLD_type (fld1)) == KIND_SCALAR &&
00192 FLD_type (fld2) != 0 && TY_kind (FLD_type (fld2)) == KIND_SCALAR &&
00193 no_overlap (fld1, fld2)) {
00194 ftype1 = TY_mtype (FLD_type(fld1));
00195 ftype2 = TY_mtype (FLD_type(fld2));
00196 if (MTYPE_float (ftype1) && MTYPE_float (ftype2))
00197 return TRUE;
00198 }
00199 ftype1 = ftype2 = MTYPE_V;
00200 return FALSE;
00201
00202 }
00203
00204 static BOOL
00205 Is_Simulated_Type (TYPE_ID mtype)
00206 {
00207 switch (mtype) {
00208 case MTYPE_FQ: return TRUE;
00209 case MTYPE_C4: return TRUE;
00210 case MTYPE_C8: return TRUE;
00211 case MTYPE_CQ: return TRUE;
00212 default: return FALSE;
00213 }
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 extern void
00225 Get_Return_Mtypes (
00226 TY_IDX rtype,
00227 Mtype_Return_Level level,
00228 TYPE_ID *mreg1,
00229 TYPE_ID *mreg2)
00230 {
00231 Fail_FmtAssertion (
00232 ("Get_Return_Mtypes should not be invoked; invoke Get_Return_Info instead"));
00233 }
00234
00235
00236
00237
00238
00239
00240
00241 extern void
00242 Get_Return_Pregs (
00243 TYPE_ID mreg1,
00244 TYPE_ID mreg2,
00245 PREG_NUM *rreg1,
00246 PREG_NUM *rreg2)
00247 {
00248 Fail_FmtAssertion (
00249 ("Get_Return_Pregs should not be invoked; invoke Get_Return_Info instead"));
00250 }
00251
00252 RETURN_INFO
00253 Get_Return_Info (TY_IDX rtype, Mtype_Return_Level level)
00254 {
00255 TYPE_ID mtype = TY_mtype (rtype);
00256 RETURN_INFO info;
00257 INT32 i;
00258
00259
00260 info.return_via_first_arg = FALSE;
00261
00262 switch (mtype) {
00263
00264 case MTYPE_UNKNOWN:
00265
00266
00267 info.count = 0;
00268
00269
00270 break;
00271
00272 case MTYPE_V:
00273
00274 info.count = 0;
00275 break;
00276
00277 case MTYPE_I1:
00278 case MTYPE_I2:
00279 case MTYPE_I4:
00280 case MTYPE_I8:
00281 case MTYPE_U1:
00282 case MTYPE_U2:
00283 case MTYPE_U4:
00284 case MTYPE_U8:
00285 case MTYPE_A4:
00286 case MTYPE_A8:
00287
00288 info.count = 1;
00289 info.mtype [0] = mtype;
00290 info.preg [0] = PR_first_reg(SIM_INFO.int_results);
00291 break;
00292
00293 case MTYPE_F4:
00294 case MTYPE_F8:
00295
00296 info.count = 1;
00297 info.mtype [0] = mtype;
00298 info.preg [0] = PR_first_reg(SIM_INFO.flt_results);
00299 break;
00300
00301 case MTYPE_FQ:
00302
00303 if (level == No_Simulated) {
00304
00305 info.count = 2;
00306 info.mtype [0] = MTYPE_F8;
00307 info.mtype [1] = MTYPE_F8;
00308 info.preg [0] = PR_first_reg(SIM_INFO.flt_results);
00309 info.preg [1] = PR_first_reg(SIM_INFO.flt_results)
00310 + PR_skip_value(SIM_INFO.flt_results);
00311 }
00312
00313 else {
00314
00315 info.count = 1;
00316 info.mtype [0] = mtype;
00317 info.preg [0] = PR_first_reg(SIM_INFO.flt_results);
00318 }
00319 break;
00320
00321 case MTYPE_C4:
00322 case MTYPE_C8:
00323
00324 if (level == Use_Simulated) {
00325
00326 info.count = 1;
00327 info.mtype [0] = mtype;
00328 info.preg [0] = PR_first_reg(SIM_INFO.flt_results);
00329 }
00330
00331 else {
00332
00333 info.count = 2;
00334 info.mtype [0] = Mtype_complex_to_real(mtype);
00335 info.mtype [1] = Mtype_complex_to_real(mtype);
00336 info.preg [0] = PR_first_reg(SIM_INFO.flt_results);
00337 info.preg [1] = PR_first_reg(SIM_INFO.flt_results)
00338 + PR_skip_value(SIM_INFO.flt_results);
00339 }
00340 break;
00341
00342 case MTYPE_CQ:
00343
00344 info.count = 4;
00345 for (INT32 i = 0; i < 4; i++) {
00346
00347 info.mtype [i] = Mtype_complex_to_real(mtype);
00348 info.preg [i] = PR_first_reg(SIM_INFO.flt_results)
00349 + i * PR_skip_value(SIM_INFO.flt_results);
00350 }
00351 break;
00352
00353 case MTYPE_M:
00354
00355 info.count = 0;
00356 info.return_via_first_arg = TRUE;
00357
00358 if (SIM_INFO.max_struct_result != 0) {
00359
00360 UINT64 size = TY_size(Ty_Table[rtype]);
00361
00362 if (size > 0 && 8 * size <= SIM_INFO.max_struct_result) {
00363
00364 int n = (size + MTYPE_RegisterSize(SIM_INFO.int_type) - 1)
00365 / MTYPE_RegisterSize(SIM_INFO.int_type);
00366 PREG_NUM reg = PR_first_reg(SIM_INFO.int_results);
00367
00368 info.return_via_first_arg = FALSE;
00369 info.count = n;
00370 for (int i = 0; i < n; i++) {
00371
00372 info.mtype [i] = SIM_INFO.int_type;
00373 info.preg [i] = reg++;
00374 }
00375 }
00376 }
00377 break;
00378
00379 default:
00380
00381 info.count = 0;
00382 Fail_FmtAssertion ("Invalid return mtype %s encountered",
00383 (MTYPE_name(mtype)));
00384 break;
00385 }
00386
00387 for (i = info.count; i < MAX_NUMBER_OF_REGISTERS_FOR_RETURN; i++) {
00388
00389 info.mtype [i] = MTYPE_V;
00390 info.preg [i] = 0;
00391 }
00392
00393 return info;
00394 }
00395
00396 static BOOL First_Param_In_Return_Reg = FALSE;
00397
00398 static PLOC
00399 Setup_Parameter_Locations (TY_IDX pu_type)
00400 {
00401 static PLOC plocNULL;
00402
00403 TY_IDX ret_type = (TY_kind(pu_type) == KIND_FUNCTION ? TY_ret_type(pu_type)
00404 : pu_type);
00405 RETURN_INFO info = Get_Return_Info (ret_type, No_Simulated);
00406 First_Param_In_Return_Reg = (RETURN_INFO_return_via_first_arg(info)
00407 & SIM_return_addr_via_int_return_reg);
00408 if (TY_is_varargs (pu_type)) {
00409
00410 TYLIST_IDX idx = TY_tylist (pu_type);
00411 Last_Fixed_Param = -1;
00412 for (++idx; Tylist_Table[idx] != 0; ++idx)
00413 ++Last_Fixed_Param;
00414
00415 if ( ! TY_has_prototype(pu_type))
00416 --Last_Fixed_Param;
00417
00418 if (TY_return_to_param (pu_type))
00419 ++Last_Fixed_Param;
00420 } else
00421 Last_Fixed_Param = INT_MAX;
00422
00423 Current_Param_Num = -1;
00424 Last_Param_Offset = 0;
00425 return plocNULL;
00426 }
00427
00428
00429
00430 static inline PREG_NUM
00431 Get_Current_Float_Preg_Num (Preg_Range pr)
00432 {
00433 PREG_NUM i;
00434 TRACE_ENTRY("Get_Current_Float_Preg_Num");
00435 i = PR_first_reg(pr) + (Current_Param_Num * PR_skip_value(pr));
00436 if (i > PR_last_reg(pr)) {
00437 TRACE_EXIT_i("Get_Current_Float_Preg_Num", 0);
00438 return 0;
00439 }
00440 else {
00441 i = PR_first_reg(pr) + (Current_Param_Num * PR_skip_value(pr));
00442 TRACE_EXIT_i("Get_Current_Float_Preg_Num", i);
00443 return i;
00444 }
00445 }
00446
00447
00448 static PLOC
00449 Get_Parameter_Location (TY_IDX ty, BOOL is_output)
00450 {
00451 PLOC ploc;
00452
00453 ploc.reg = 0;
00454 ploc.start_offset = Last_Param_Offset;
00455 ploc.size = 0;
00456 ploc.vararg_reg = 0;
00457 if (TY_kind (ty) == KIND_VOID) {
00458 return ploc;
00459 }
00460
00461
00462 TYPE_ID pmtype = Fix_TY_mtype (ty);
00463 ploc.size = MTYPE_RegisterSize(pmtype);
00464
00465 if (First_Param_In_Return_Reg) {
00466 First_Param_In_Return_Reg = FALSE;
00467 ploc.reg = PR_first_reg(SIM_INFO.int_results);
00468 return ploc;
00469 }
00470 ++Current_Param_Num;
00471 if (TY_align_exp (ty) == 4 && (Current_Param_Num % 2) == 1) {
00472
00473 ++Current_Param_Num;
00474
00475 if (Last_Fixed_Param < INT_MAX)
00476 ++Last_Fixed_Param;
00477 ploc.start_offset += MTYPE_RegisterSize(SIM_INFO.flt_type);
00478 }
00479
00480 INT rpad = 0;
00481
00482 switch (pmtype) {
00483
00484 case MTYPE_I1:
00485 case MTYPE_U1:
00486 case MTYPE_I2:
00487 case MTYPE_U2:
00488 case MTYPE_I4:
00489 case MTYPE_U4:
00490 case MTYPE_A4:
00491 if (Target_Byte_Sex == BIG_ENDIAN) {
00492
00493 ploc.start_offset += (MTYPE_RegisterSize(SIM_INFO.int_type) -
00494 ploc.size);
00495 }
00496 else {
00497
00498 rpad = (MTYPE_RegisterSize(SIM_INFO.int_type) - ploc.size);
00499 }
00500 ploc.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00501 break;
00502
00503 case MTYPE_I8:
00504 case MTYPE_U8:
00505 case MTYPE_A8:
00506 ploc.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00507 if (MTYPE_size_reg(SIM_INFO.int_type) < MTYPE_size_reg(pmtype)) {
00508 Current_Param_Num++;
00509
00510 if (Last_Fixed_Param < INT_MAX)
00511 ++Last_Fixed_Param;
00512 }
00513 break;
00514
00515 case MTYPE_F4:
00516 case MTYPE_F8:
00517
00518 rpad = MTYPE_RegisterSize(SIM_INFO.flt_type) - ploc.size;
00519 if (Current_Param_Num > Last_Fixed_Param && !SIM_varargs_floats) {
00520
00521 ploc.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00522 } else {
00523 ploc.reg = Get_Current_Float_Preg_Num (SIM_INFO.flt_args);
00524 ploc.vararg_reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00525 }
00526 break;
00527
00528 case MTYPE_FQ:
00529 if (Current_Param_Num > Last_Fixed_Param && !SIM_varargs_floats) {
00530
00531 ploc.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00532 } else {
00533 ploc.reg = Get_Current_Float_Preg_Num (SIM_INFO.flt_args);
00534 ploc.vararg_reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00535 }
00536 Current_Param_Num++;
00537
00538 if (Last_Fixed_Param < INT_MAX)
00539 ++Last_Fixed_Param;
00540 break;
00541
00542 case MTYPE_C4:
00543 case MTYPE_C8:
00544 case MTYPE_CQ:
00545 ploc.reg = Get_Current_Float_Preg_Num (SIM_INFO.flt_args);
00546 Current_Param_Num++;
00547
00548 if (Last_Fixed_Param < INT_MAX)
00549 ++Last_Fixed_Param;
00550 break;
00551
00552 case MTYPE_M:
00553 {
00554 ploc.size = TY_size (ty);
00555 INT psize = TY_size (ty) / MTYPE_RegisterSize(SIM_INFO.int_type);
00556
00557 if ((TY_size (ty) % MTYPE_RegisterSize(SIM_INFO.int_type)) != 0)
00558 psize++;
00559
00560 rpad = (psize * MTYPE_RegisterSize(SIM_INFO.int_type)) - ploc.size;
00561 RETURN_INFO info = Get_Return_Info (ty, No_Simulated);
00562 if (RETURN_INFO_count(info) &&
00563 MTYPE_float (RETURN_INFO_mtype (info, 0)) &&
00564 !(Current_Param_Num > Last_Fixed_Param && !SIM_varargs_floats)) {
00565 ploc.reg = Get_Current_Float_Preg_Num (SIM_INFO.flt_args);
00566 ploc.vararg_reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00567 Current_Param_Num += RETURN_INFO_count (info) - 1;
00568
00569 if (Last_Fixed_Param < INT_MAX)
00570 Last_Fixed_Param += RETURN_INFO_count(info) - 1;
00571 } else {
00572 ploc.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00573 Current_Param_Num += psize - 1;
00574
00575 if (Last_Fixed_Param < INT_MAX)
00576 Last_Fixed_Param += psize - 1;
00577 }
00578 }
00579 break;
00580
00581 default:
00582 FmtAssert (FALSE, ("Get_Parameter_Location: mtype %s",
00583 MTYPE_name(pmtype)));
00584 }
00585 Last_Param_Offset = ploc.start_offset + ploc.size + rpad;
00586 return ploc;
00587 }
00588
00589
00590
00591 struct PSTRUCT {
00592 BOOL is_struct;
00593 BOOL first_call;
00594 BOOL is_hfa;
00595 TYPE_ID hfa_mtype;
00596 INT64 offset;
00597 INT64 size;
00598
00599 PSTRUCT () : is_struct (FALSE), first_call (TRUE),
00600 is_hfa (FALSE), hfa_mtype (MTYPE_V),
00601 offset (0), size (0) {}
00602 };
00603
00604 static PSTRUCT pstruct;
00605
00606 #define PSTRUCT_struct pstruct.is_struct
00607 #define PSTRUCT_first_call pstruct.first_call
00608 #define PSTRUCT_hfa pstruct.is_hfa
00609 #define PSTRUCT_hfa_mtype pstruct.hfa_mtype
00610 #define PSTRUCT_offset pstruct.offset
00611 #define PSTRUCT_size pstruct.size
00612
00613 static void
00614 Setup_Struct_Parameter_Locations (TY_IDX struct_ty)
00615 {
00616 PSTRUCT_struct = ! TY_is_union (struct_ty);
00617 PSTRUCT_first_call = TRUE;
00618 PSTRUCT_hfa = FALSE;
00619 PSTRUCT_offset = 0;
00620 PSTRUCT_size = TY_size (struct_ty);
00621 }
00622
00623 static PLOC
00624 Get_Struct_Parameter_Location (PLOC prev)
00625 {
00626 TYPE_ID pmtype;
00627 PLOC next;
00628 INT ireg_size = MTYPE_RegisterSize(SIM_INFO.int_type);
00629 BOOL onStack = (prev.reg == 0);
00630
00631 if (PSTRUCT_first_call)
00632 PLOC_offset(next) = PLOC_offset(prev);
00633 else
00634 PLOC_offset(next) = PLOC_offset(prev) + PLOC_size(prev);
00635
00636 if (PSTRUCT_offset >= PSTRUCT_size) {
00637 PLOC_size(next) = 0;
00638 return next;
00639 }
00640
00641 PLOC_size(next) = ireg_size;
00642 PSTRUCT_offset += ireg_size;
00643
00644 if (onStack) {
00645 PLOC_reg(next) = 0;
00646 PSTRUCT_first_call = FALSE;
00647 } else if (PSTRUCT_first_call) {
00648 PSTRUCT_first_call = FALSE;
00649 PLOC_reg(next) = PLOC_reg(prev);
00650 } else if (IS_INT_PREG(PLOC_reg(prev))) {
00651 PLOC_reg(next) = PLOC_reg(prev) + PR_skip_value(SIM_INFO.int_args);
00652 if (!IS_INT_PREG(PLOC_reg(next)))
00653 PLOC_reg(next) = 0;
00654 }
00655
00656 return next;
00657 }
00658
00659
00660
00661 static PLOC
00662 Get_Vararg_Parameter_Location (PLOC prev)
00663 {
00664 PLOC next;
00665 Current_Param_Num++;
00666 next.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00667
00668 if (next.reg > PR_last_reg(SIM_INFO.int_args))
00669 {
00670 next.reg = 0;
00671 next.size = 0;
00672 }
00673 else
00674 {
00675 next.size = MTYPE_RegisterSize(SIM_INFO.int_type);
00676 }
00677
00678 next.start_offset = Last_Param_Offset;
00679 Last_Param_Offset = next.start_offset + next.size;
00680 return next;
00681 }
00682
00683 BOOL Is_Caller_Save_GP;
00684
00685 #if defined(TARG_SL)
00686 INT Formal_Save_Area_Size = 32;
00687 #else
00688 INT Formal_Save_Area_Size = 64;
00689 #endif
00690 INT Stack_Offset_Adjustment = 0;
00691
00692 extern void
00693 Init_Targ_Sim (void)
00694 {
00695 Is_Caller_Save_GP = SIM_caller_save_gp;
00696 }
00697