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 #define TRACE_ENTRY(x)
00046 #define TRACE_EXIT(x)
00047 #define TRACE_EXIT_i(x,i)
00048
00049 #include <limits.h>
00050 #include "defs.h"
00051 #include "mtypes.h"
00052 #include "errors.h"
00053 #include "erglob.h"
00054 #include "stab.h"
00055 #include "config_targ.h"
00056 #include "targ_sim.h"
00057
00058 #include "targ_sim_body.h"
00059
00060
00061 static mDED_PREG_NUM Input_Base_Preg = 32;
00062 static mDED_PREG_NUM Output_Base_Preg = 127;
00063
00064 #define I0 (Int_Preg_Min_Offset - 1)
00065 #define F0 Float_Preg_Min_Offset
00066
00067
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 | SIM_CALLER_SAVE_GP | SIM_RET_ADDR_VIA_INT_RET,
00087 {I0+32,I0+39,1}, {F0+8,F0+15,1}, {F0+8,F0+15,1},
00088 {I0+8,I0+11,1}, {F0+8,F0+15,1}, {F0+8,F0+15,1},
00089 MTYPE_I8, MTYPE_F8, MTYPE_F8,
00090 0, 64, -64,
00091 -1, 256, I0+2, I0+25
00092 },
00093 {
00094 SIM_FLT_AFTER_INT | SIM_COORD_MEM_REG | SIM_COORD_INT_FLT
00095 | SIM_REG_STRUCTS | SIM_FLT_RTN_COMPLEX | SIM_DBL_REG_FIELDS
00096 | SIM_CALLER_SAVE_GP | SIM_RET_ADDR_VIA_INT_RET,
00097 {I0+32,I0+39,1}, {F0+8,F0+15,1}, {F0+8,F0+15,1},
00098 {I0+8,I0+11,1}, {F0+8,F0+15,1}, {F0+8,F0+15,1},
00099 MTYPE_I8, MTYPE_F8, MTYPE_F8,
00100 0, 64, -64,
00101 -1, 256, I0+2, I0+25
00102 }
00103 };
00104
00105 static BOOL Struct_Is_HFA (const TY_IDX, Mtype_Return_Level, TYPE_ID&);
00106
00107
00108 extern BOOL
00109 Is_Return_Preg (PREG_NUM preg)
00110 {
00111 return (preg >= First_Int_Preg_Return_Offset
00112 && preg <= Last_Int_Preg_Return_Offset)
00113 || (preg >= First_Float_Preg_Return_Offset
00114 && preg <= Last_Float_Preg_Return_Offset);
00115 }
00116
00117
00118 extern BOOL
00119 Is_Int_Output_Preg (PREG_NUM preg)
00120 {
00121 return (preg <= Output_Base_Preg
00122 && preg > (Output_Base_Preg - MAX_NUMBER_OF_REGISTER_PARAMETERS));
00123 }
00124
00125
00126 extern BOOL
00127 Is_Formal_Preg (PREG_NUM preg)
00128 {
00129 return (preg >= First_Int_Preg_Param_Offset
00130 && preg <= (First_Int_Preg_Param_Offset
00131 + MAX_NUMBER_OF_REGISTER_PARAMETERS) )
00132 || (preg >= First_Float_Preg_Param_Offset
00133 && preg <= (First_Float_Preg_Param_Offset
00134 + MAX_NUMBER_OF_REGISTER_PARAMETERS) );
00135 }
00136
00137 static BOOL
00138 Array_Is_HFA (
00139 const TY_IDX ty,
00140 Mtype_Return_Level level,
00141 TYPE_ID& hfa_mtype
00142 )
00143 {
00144 const TY_IDX ety = TY_etype (ty);
00145
00146 if (TY_kind (ety) == KIND_SCALAR) {
00147
00148 TYPE_ID mtype = TY_mtype (ety);
00149
00150 switch (mtype) {
00151
00152 case MTYPE_F4:
00153 case MTYPE_F8:
00154 case MTYPE_FQ:
00155 case MTYPE_F10:
00156 case MTYPE_F16:
00157 case MTYPE_C4:
00158 case MTYPE_C8:
00159 case MTYPE_CQ:
00160 case MTYPE_C10:
00161 case MTYPE_C16:
00162
00163 if (hfa_mtype == MTYPE_V)
00164 hfa_mtype = mtype;
00165
00166 else
00167 if (hfa_mtype != mtype)
00168 return FALSE;
00169
00170 break;
00171
00172 default:
00173
00174 return FALSE;
00175 }
00176 }
00177
00178 else
00179 if (TY_kind (ety) == KIND_ARRAY) {
00180
00181 if (!Array_Is_HFA (ety, level, hfa_mtype))
00182 return FALSE;
00183 }
00184
00185 else
00186 if (TY_kind (ety) == KIND_STRUCT) {
00187
00188 if (!Struct_Is_HFA (ety, level, hfa_mtype))
00189 return FALSE;
00190 }
00191
00192 else
00193 return FALSE;
00194
00195 return TRUE;
00196 }
00197
00198 static BOOL
00199 Struct_Is_HFA (
00200 const TY_IDX ty,
00201 Mtype_Return_Level level,
00202 TYPE_ID& hfa_mtype
00203 )
00204 {
00205 mUINT64 offset = 0;
00206
00207 if (TY_is_union (ty))
00208 return FALSE;
00209
00210 if (TY_fld (ty).Is_Null ())
00211 return FALSE;
00212
00213 FLD_HANDLE fld = TY_fld (ty);
00214
00215 do {
00216
00217 if (FLD_ofst (fld) != offset)
00218 return FALSE;
00219
00220 TY_IDX fty = FLD_type (fld);
00221
00222 if (TY_kind (fty) == KIND_SCALAR) {
00223
00224 TYPE_ID mtype = TY_mtype (fty);
00225
00226 switch (mtype) {
00227
00228 case MTYPE_F4:
00229 case MTYPE_F8:
00230 case MTYPE_FQ:
00231 case MTYPE_F10:
00232 case MTYPE_F16:
00233 case MTYPE_C4:
00234 case MTYPE_C8:
00235 case MTYPE_CQ:
00236 case MTYPE_C10:
00237 case MTYPE_C16:
00238
00239 if (hfa_mtype == MTYPE_V)
00240 hfa_mtype = mtype;
00241
00242 else
00243 if (hfa_mtype != mtype)
00244 return FALSE;
00245
00246 break;
00247
00248 default:
00249
00250 return FALSE;
00251 }
00252 }
00253
00254 else
00255 if (TY_kind (fty) == KIND_ARRAY) {
00256
00257 if (!Array_Is_HFA (fty, level, hfa_mtype))
00258 return FALSE;
00259 }
00260
00261 else
00262 if (TY_kind (fty) == KIND_STRUCT) {
00263
00264 if (!Struct_Is_HFA (fty, level, hfa_mtype))
00265 return FALSE;
00266 }
00267
00268 else
00269 return FALSE;
00270
00271 offset += TY_size (fty);
00272 fld = FLD_next (fld);
00273 } while (!fld.Is_Null ());
00274
00275 return TRUE;
00276 }
00277
00278 static BOOL
00279 Struct_Has_One_Float (const TY_IDX ty, TYPE_ID &ftype)
00280 {
00281 if (TY_is_union (ty))
00282 return FALSE;
00283
00284 if (TY_fld (ty).Is_Null ())
00285 return FALSE;
00286
00287 FLD_HANDLE fld = TY_fld (ty);
00288
00289 if (FLD_last_field (fld) && FLD_type (fld) != 0 &&
00290 TY_kind (FLD_type (fld)) == KIND_SCALAR) {
00291 ftype = TY_mtype (FLD_type (fld));
00292 if (MTYPE_float (ftype))
00293 return TRUE;
00294 }
00295 ftype = MTYPE_V;
00296 return FALSE;
00297 }
00298
00299
00300
00301 static BOOL
00302 no_overlap (const FLD_HANDLE fld1, const FLD_HANDLE fld2)
00303 {
00304 if (FLD_ofst (fld1) <= FLD_ofst (fld2))
00305 return FLD_ofst(fld1) + TY_size (FLD_type (fld1)) <= FLD_ofst (fld2);
00306 else
00307 return FLD_ofst(fld2) + TY_size (FLD_type (fld2)) <= FLD_ofst (fld1);
00308 }
00309
00310 static BOOL
00311 Struct_Has_Two_Floats (const TY_IDX ty, TYPE_ID& ftype1, TYPE_ID& ftype2)
00312 {
00313 if (TY_is_union (ty))
00314 return FALSE;
00315
00316 if (TY_fld (ty).Is_Null ())
00317 return FALSE;
00318
00319 FLD_HANDLE fld1 = TY_fld (ty);
00320
00321 if (FLD_last_field (fld1))
00322 return FALSE;
00323
00324 FLD_HANDLE fld2 (FLD_next (fld1));
00325
00326 if (FLD_last_field (fld2) &&
00327 FLD_type (fld1) != 0 && TY_kind (FLD_type (fld1)) == KIND_SCALAR &&
00328 FLD_type (fld2) != 0 && TY_kind (FLD_type (fld2)) == KIND_SCALAR &&
00329 no_overlap (fld1, fld2)) {
00330 ftype1 = TY_mtype (FLD_type(fld1));
00331 ftype2 = TY_mtype (FLD_type(fld2));
00332 if (MTYPE_float (ftype1) && MTYPE_float (ftype2))
00333 return TRUE;
00334 }
00335 ftype1 = ftype2 = MTYPE_V;
00336 return FALSE;
00337
00338 }
00339
00340 static BOOL
00341 Is_Simulated_Type (TYPE_ID mtype)
00342 {
00343 switch (mtype) {
00344 case MTYPE_FQ: return TRUE;
00345 case MTYPE_C4: return TRUE;
00346 case MTYPE_C8: return TRUE;
00347 case MTYPE_CQ: return TRUE;
00348 default: return FALSE;
00349 }
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 extern void
00361 Get_Return_Mtypes (
00362 TY_IDX rtype,
00363 Mtype_Return_Level level,
00364 TYPE_ID *mreg1,
00365 TYPE_ID *mreg2)
00366 {
00367 Fail_FmtAssertion (
00368 ("Get_Return_Mtypes should not be invoked; invoke Get_Return_Info instead"));
00369 }
00370
00371
00372
00373
00374
00375
00376
00377 extern void
00378 Get_Return_Pregs (
00379 TYPE_ID mreg1,
00380 TYPE_ID mreg2,
00381 PREG_NUM *rreg1,
00382 PREG_NUM *rreg2)
00383 {
00384 Fail_FmtAssertion (
00385 ("Get_Return_Pregs should not be invoked; invoke Get_Return_Info instead"));
00386 }
00387
00388 RETURN_INFO
00389 Get_Return_Info (TY_IDX rtype, Mtype_Return_Level level)
00390 {
00391 TYPE_ID mtype = TY_mtype (rtype);
00392 RETURN_INFO info;
00393 INT32 i;
00394
00395
00396 info.return_via_first_arg = FALSE;
00397
00398 switch (mtype) {
00399
00400 case MTYPE_UNKNOWN:
00401
00402
00403 info.count = 0;
00404
00405
00406 break;
00407
00408 case MTYPE_V:
00409
00410 info.count = 0;
00411 break;
00412
00413 case MTYPE_I1:
00414 case MTYPE_I2:
00415 case MTYPE_I4:
00416 case MTYPE_I8:
00417 case MTYPE_U1:
00418 case MTYPE_U2:
00419 case MTYPE_U4:
00420 case MTYPE_U8:
00421 case MTYPE_A4:
00422 case MTYPE_A8:
00423
00424 info.count = 1;
00425 info.mtype [0] = mtype;
00426 info.preg [0] = PR_first_reg(SIM_INFO.int_results);
00427 break;
00428
00429 case MTYPE_F4:
00430 case MTYPE_F8:
00431
00432 info.count = 1;
00433 info.mtype [0] = mtype;
00434 info.preg [0] = PR_first_reg(SIM_INFO.flt_results);
00435 break;
00436
00437 case MTYPE_FQ:
00438
00439 if (level == No_Simulated) {
00440
00441 info.count = 2;
00442 info.mtype [0] = MTYPE_F8;
00443 info.mtype [1] = MTYPE_F8;
00444 info.preg [0] = PR_first_reg(SIM_INFO.flt_results);
00445 info.preg [1] = PR_first_reg(SIM_INFO.flt_results)
00446 + PR_skip_value(SIM_INFO.flt_results);
00447 }
00448
00449 else {
00450
00451 info.count = 1;
00452 info.mtype [0] = mtype;
00453 info.preg [0] = PR_first_reg(SIM_INFO.flt_results);
00454 }
00455 break;
00456
00457 case MTYPE_C4:
00458 case MTYPE_C8:
00459
00460 if (level == Use_Simulated) {
00461
00462 info.count = 1;
00463 info.mtype [0] = mtype;
00464 info.preg [0] = PR_first_reg(SIM_INFO.flt_results);
00465 }
00466
00467 else {
00468
00469 info.count = 2;
00470 info.mtype [0] = Mtype_complex_to_real(mtype);
00471 info.mtype [1] = Mtype_complex_to_real(mtype);
00472 info.preg [0] = PR_first_reg(SIM_INFO.flt_results);
00473 info.preg [1] = PR_first_reg(SIM_INFO.flt_results)
00474 + PR_skip_value(SIM_INFO.flt_results);
00475 }
00476 break;
00477
00478 case MTYPE_CQ:
00479
00480 info.count = 4;
00481 for (INT32 i = 0; i < 4; i++) {
00482
00483 info.mtype [i] = Mtype_complex_to_real(mtype);
00484 info.preg [i] = PR_first_reg(SIM_INFO.flt_results)
00485 + i * PR_skip_value(SIM_INFO.flt_results);
00486 }
00487 break;
00488
00489 case MTYPE_M:
00490
00491 info.count = 0;
00492 info.return_via_first_arg = TRUE;
00493
00494 if (SIM_INFO.max_struct_result != 0) {
00495 UINT64 size = TY_size(Ty_Table[rtype]);
00496
00497 if (size > 0 && 8 * size <= 2 * SIM_INFO.max_struct_result && 0)
00498 {
00499 TYPE_ID hfa_mtype = MTYPE_V;
00500
00501 if (Struct_Is_HFA (rtype, level, hfa_mtype) &&
00502 hfa_mtype != MTYPE_V &&
00503 ((hfa_mtype != MTYPE_F4 && hfa_mtype != MTYPE_C4) ||
00504 ((hfa_mtype == MTYPE_F4 || hfa_mtype == MTYPE_C4) &&
00505 8 * size <= SIM_INFO.max_struct_result))) {
00506
00507 PREG_NUM reg = PR_first_reg(SIM_INFO.flt_results);
00508 INT32 n;
00509 INT32 i;
00510 INT32 step;
00511
00512 info.return_via_first_arg = FALSE;
00513
00514 switch (hfa_mtype) {
00515
00516 case MTYPE_F4:
00517 case MTYPE_F8:
00518 case MTYPE_F10:
00519
00520 break;
00521
00522 case MTYPE_C4:
00523 case MTYPE_C8:
00524 case MTYPE_C10:
00525
00526 if (level != Use_Simulated)
00527 hfa_mtype = Mtype_complex_to_real(hfa_mtype);
00528 break;
00529 }
00530
00531 switch (hfa_mtype) {
00532
00533 case MTYPE_F4:
00534 case MTYPE_C4:
00535
00536 n = TY_size (rtype) / TY_size (Be_Type_Tbl (MTYPE_F4));
00537 info.count = n;
00538
00539 for (i = 0; i < n; i++) {
00540
00541 info.mtype [i] = hfa_mtype;
00542 info.preg [i] = reg;
00543 reg += PR_skip_value(SIM_INFO.flt_results);
00544 }
00545 break;
00546
00547 case MTYPE_F8:
00548 case MTYPE_F10:
00549 case MTYPE_C8:
00550 case MTYPE_C10:
00551
00552 n = TY_size (rtype) / TY_size (Be_Type_Tbl (hfa_mtype));
00553 step = TY_size (Be_Type_Tbl (hfa_mtype)) /
00554 TY_size (Be_Type_Tbl (MTYPE_F8));
00555 info.count = n;
00556
00557 for (i = 0; i < n; i++) {
00558
00559 info.mtype [i] = hfa_mtype;
00560 info.preg [i] = reg;
00561 reg += step * PR_skip_value(SIM_INFO.flt_results);
00562 }
00563 break;
00564 }
00565 }
00566
00567 else
00568 if (8 * size <= SIM_INFO.max_struct_result) {
00569
00570 int n = (size + MTYPE_RegisterSize(SIM_INFO.int_type) - 1)
00571 / MTYPE_RegisterSize(SIM_INFO.int_type);
00572 PREG_NUM reg = PR_first_reg(SIM_INFO.int_results);
00573
00574 info.return_via_first_arg = FALSE;
00575 info.count = n;
00576 for (int i = 0; i < n; i++) {
00577
00578 info.mtype [i] = SIM_INFO.int_type;
00579 info.preg [i] = reg++;
00580 }
00581
00582 break;
00583 }
00584 }
00585 }
00586 break;
00587
00588 default:
00589
00590 info.count = 0;
00591 Fail_FmtAssertion ("Invalid return mtype %s encountered",
00592 (MTYPE_name(mtype)));
00593 break;
00594 }
00595
00596 for (i = info.count; i < MAX_NUMBER_OF_REGISTERS_FOR_RETURN; i++) {
00597
00598 info.mtype [i] = MTYPE_V;
00599 info.preg [i] = 0;
00600 }
00601
00602 return info;
00603 }
00604
00605 static INT Current_Float_Param_Num = -1;
00606 static BOOL First_Param_In_Return_Reg = FALSE;
00607
00608 static PLOC
00609 Setup_Parameter_Locations (TY_IDX pu_type)
00610 {
00611 static PLOC plocNULL;
00612
00613 TY_IDX ret_type = (TY_kind(pu_type) == KIND_FUNCTION ? TY_ret_type(pu_type)
00614 : pu_type);
00615 RETURN_INFO info = Get_Return_Info (ret_type, No_Simulated);
00616 First_Param_In_Return_Reg = (RETURN_INFO_return_via_first_arg(info)
00617 & SIM_return_addr_via_int_return_reg);
00618 if (TY_is_varargs (pu_type)) {
00619
00620 TYLIST_IDX idx = TY_tylist (pu_type);
00621 Last_Fixed_Param = -1;
00622 for (++idx; Tylist_Table[idx] != 0; ++idx)
00623 ++Last_Fixed_Param;
00624
00625 if ( ! TY_has_prototype(pu_type))
00626 --Last_Fixed_Param;
00627
00628 if (TY_return_to_param (pu_type))
00629 ++Last_Fixed_Param;
00630 } else
00631 Last_Fixed_Param = INT_MAX;
00632
00633 Current_Param_Num = -1;
00634 Current_Float_Param_Num = -1;
00635 Last_Param_Offset = 0;
00636 return plocNULL;
00637 }
00638
00639
00640
00641 static inline PREG_NUM
00642 Get_Current_Float_Preg_Num (Preg_Range pr)
00643 {
00644 PREG_NUM i;
00645 TRACE_ENTRY("Get_Current_Float_Preg_Num");
00646 i = PR_first_reg(pr) + (Current_Param_Num * PR_skip_value(pr));
00647 if (i > PR_last_reg(pr)) {
00648 TRACE_EXIT_i("Get_Current_Float_Preg_Num", 0);
00649 return 0;
00650 }
00651 else {
00652 i = PR_first_reg(pr) + (Current_Float_Param_Num * PR_skip_value(pr));
00653 TRACE_EXIT_i("Get_Current_Float_Preg_Num", i);
00654 return i;
00655 }
00656 }
00657
00658
00659 static PLOC
00660 Get_Parameter_Location (TY_IDX ty, BOOL is_output)
00661 {
00662 PLOC ploc;
00663
00664 ploc.reg = 0;
00665 ploc.start_offset = Last_Param_Offset;
00666 ploc.size = 0;
00667 ploc.vararg_reg = 0;
00668 if (TY_kind (ty) == KIND_VOID) {
00669 if (is_output && IS_INT_PREG(PLOC_reg(ploc)))
00670 PLOC_reg(ploc) = Output_Base_Preg - PLOC_reg(ploc) + 32;
00671 else if ( ! is_output && IS_INT_PREG(PLOC_reg(ploc)))
00672 PLOC_reg(ploc) = Input_Base_Preg + PLOC_reg(ploc) - 32;
00673 return ploc;
00674 }
00675
00676
00677 TYPE_ID pmtype = Fix_TY_mtype (ty);
00678 ploc.size = MTYPE_RegisterSize(pmtype);
00679
00680 if (First_Param_In_Return_Reg) {
00681 First_Param_In_Return_Reg = FALSE;
00682 ploc.reg = PR_first_reg(SIM_INFO.int_results);
00683 if (is_output && IS_INT_PREG(PLOC_reg(ploc)))
00684 PLOC_reg(ploc) = Output_Base_Preg - PLOC_reg(ploc) + 32;
00685 else if ( ! is_output && IS_INT_PREG(PLOC_reg(ploc)))
00686 PLOC_reg(ploc) = Input_Base_Preg + PLOC_reg(ploc) - 32;
00687 return ploc;
00688 }
00689 ++Current_Param_Num;
00690 if (TY_align_exp (ty) == 4 && (Current_Param_Num % 2) == 1) {
00691
00692 ++Current_Param_Num;
00693
00694 if (Last_Fixed_Param < INT_MAX)
00695 ++Last_Fixed_Param;
00696 ploc.start_offset += MTYPE_RegisterSize(SIM_INFO.flt_type);
00697 }
00698
00699 INT rpad = 0;
00700
00701 switch (pmtype) {
00702
00703 case MTYPE_I1:
00704 case MTYPE_U1:
00705 case MTYPE_I2:
00706 case MTYPE_U2:
00707 case MTYPE_I4:
00708 case MTYPE_U4:
00709 case MTYPE_A4:
00710 if (Target_Byte_Sex == BIG_ENDIAN) {
00711
00712 ploc.start_offset += (MTYPE_RegisterSize(SIM_INFO.int_type) -
00713 ploc.size);
00714 }
00715 else {
00716
00717 rpad = (MTYPE_RegisterSize(SIM_INFO.int_type) - ploc.size);
00718 }
00719 ploc.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00720 break;
00721
00722 case MTYPE_I8:
00723 case MTYPE_U8:
00724 case MTYPE_A8:
00725 ploc.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00726 if (MTYPE_size_reg(SIM_INFO.int_type) < MTYPE_size_reg(pmtype)) {
00727 Current_Param_Num++;
00728
00729 if (Last_Fixed_Param < INT_MAX)
00730 ++Last_Fixed_Param;
00731 }
00732 break;
00733
00734 case MTYPE_F4:
00735 case MTYPE_F8:
00736
00737 ++Current_Float_Param_Num;
00738 rpad = MTYPE_RegisterSize(SIM_INFO.flt_type) - ploc.size;
00739 if (Current_Param_Num > Last_Fixed_Param && !SIM_varargs_floats) {
00740
00741 ploc.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00742 } else {
00743 ploc.reg = Get_Current_Float_Preg_Num (SIM_INFO.flt_args);
00744 ploc.vararg_reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00745 }
00746 break;
00747
00748 case MTYPE_FQ:
00749 ++Current_Float_Param_Num;
00750 if (Current_Param_Num > Last_Fixed_Param && !SIM_varargs_floats) {
00751
00752 ploc.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00753 } else {
00754 ploc.reg = Get_Current_Float_Preg_Num (SIM_INFO.flt_args);
00755 ploc.vararg_reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00756 }
00757 Current_Param_Num++;
00758
00759 if (Last_Fixed_Param < INT_MAX)
00760 ++Last_Fixed_Param;
00761 Current_Float_Param_Num++;
00762 break;
00763
00764 case MTYPE_C4:
00765 case MTYPE_C8:
00766 case MTYPE_CQ:
00767 ++Current_Float_Param_Num;
00768 ploc.reg = Get_Current_Float_Preg_Num (SIM_INFO.flt_args);
00769 Current_Param_Num++;
00770
00771 if (Last_Fixed_Param < INT_MAX)
00772 ++Last_Fixed_Param;
00773 Current_Float_Param_Num++;
00774 break;
00775
00776 case MTYPE_M:
00777 {
00778 ploc.size = TY_size (ty);
00779 INT psize = TY_size (ty) / MTYPE_RegisterSize(SIM_INFO.int_type);
00780
00781 if ((TY_size (ty) % MTYPE_RegisterSize(SIM_INFO.int_type)) != 0)
00782 psize++;
00783
00784 rpad = (psize * MTYPE_RegisterSize(SIM_INFO.int_type)) - ploc.size;
00785 RETURN_INFO info = Get_Return_Info (ty, No_Simulated);
00786 if (RETURN_INFO_count(info) &&
00787 MTYPE_float (RETURN_INFO_mtype (info, 0)) &&
00788 !(Current_Param_Num > Last_Fixed_Param && !SIM_varargs_floats)) {
00789 ++Current_Float_Param_Num;
00790 ploc.reg = Get_Current_Float_Preg_Num (SIM_INFO.flt_args);
00791 ploc.vararg_reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00792 Current_Param_Num += RETURN_INFO_count (info) - 1;
00793
00794 if (Last_Fixed_Param < INT_MAX)
00795 Last_Fixed_Param += RETURN_INFO_count(info) - 1;
00796 Current_Float_Param_Num += RETURN_INFO_count (info) - 1;
00797 } else {
00798 ploc.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00799 Current_Param_Num += psize - 1;
00800
00801 if (Last_Fixed_Param < INT_MAX)
00802 Last_Fixed_Param += psize - 1;
00803 }
00804 }
00805 break;
00806
00807 default:
00808 FmtAssert (FALSE, ("Get_Parameter_Location: mtype %s",
00809 MTYPE_name(pmtype)));
00810 }
00811 Last_Param_Offset = ploc.start_offset + ploc.size + rpad;
00812 if (is_output && IS_INT_PREG(PLOC_reg(ploc)))
00813 PLOC_reg(ploc) = Output_Base_Preg - PLOC_reg(ploc) + 32;
00814 else if ( ! is_output && IS_INT_PREG(PLOC_reg(ploc)))
00815 PLOC_reg(ploc) = Input_Base_Preg + PLOC_reg(ploc) - 32;
00816 return ploc;
00817 }
00818
00819
00820
00821 struct PSTRUCT {
00822 BOOL is_struct;
00823 BOOL first_call;
00824 BOOL is_hfa;
00825 TYPE_ID hfa_mtype;
00826 INT64 offset;
00827 INT64 size;
00828
00829 PSTRUCT () : is_struct (FALSE), first_call (TRUE),
00830 is_hfa (FALSE), hfa_mtype (MTYPE_V),
00831 offset (0), size (0) {}
00832 };
00833
00834 static PSTRUCT pstruct;
00835
00836 #define PSTRUCT_struct pstruct.is_struct
00837 #define PSTRUCT_first_call pstruct.first_call
00838 #define PSTRUCT_hfa pstruct.is_hfa
00839 #define PSTRUCT_hfa_mtype pstruct.hfa_mtype
00840 #define PSTRUCT_offset pstruct.offset
00841 #define PSTRUCT_size pstruct.size
00842
00843 static void
00844 Setup_Struct_Parameter_Locations (TY_IDX struct_ty)
00845 {
00846 PSTRUCT_struct = ! TY_is_union (struct_ty);
00847 PSTRUCT_first_call = TRUE;
00848 PSTRUCT_hfa = Struct_Is_HFA (struct_ty, No_Simulated, PSTRUCT_hfa_mtype);
00849 PSTRUCT_offset = 0;
00850 PSTRUCT_size = TY_size (struct_ty);
00851 }
00852
00853 static PLOC
00854 Get_Struct_Parameter_Location (PLOC prev)
00855 {
00856 TYPE_ID pmtype;
00857 PLOC next;
00858 INT ireg_size = MTYPE_RegisterSize(SIM_INFO.int_type);
00859 BOOL onStack = (prev.reg == 0);
00860
00861 if (PSTRUCT_first_call)
00862 PLOC_offset(next) = PLOC_offset(prev);
00863 else
00864 PLOC_offset(next) = PLOC_offset(prev) + PLOC_size(prev);
00865
00866 if (PSTRUCT_offset >= PSTRUCT_size) {
00867 PLOC_size(next) = 0;
00868 return next;
00869 }
00870
00871 if (PSTRUCT_struct && PSTRUCT_hfa &&
00872 !(Current_Param_Num > Last_Fixed_Param && !SIM_varargs_floats)) {
00873 if (PSTRUCT_hfa_mtype == MTYPE_F4 || PSTRUCT_hfa_mtype == MTYPE_C4) {
00874 PLOC_size(next) = TY_size (Be_Type_Tbl (MTYPE_F4));
00875 PSTRUCT_offset += TY_size (Be_Type_Tbl (MTYPE_F4));
00876 } else {
00877 PLOC_size(next) = TY_size (Be_Type_Tbl (MTYPE_F8));
00878 PSTRUCT_offset += TY_size (Be_Type_Tbl (MTYPE_F8));
00879 }
00880 if (onStack) {
00881 PLOC_reg(next) = 0;
00882 PSTRUCT_first_call = FALSE;
00883 } else if (PSTRUCT_first_call) {
00884 PSTRUCT_first_call = FALSE;
00885 PLOC_reg(next) = PLOC_reg(prev);
00886 if (!IS_FLT_PREG(PLOC_reg(next)))
00887 PLOC_reg(next) = 0;
00888 } else if (IS_FLT_PREG(PLOC_reg(prev))) {
00889 PLOC_reg(next) = PLOC_reg(prev) + PR_skip_value(SIM_INFO.flt_args);
00890 if (PLOC_reg(next) > PR_last_reg(SIM_INFO.flt_args)) {
00891 if (PSTRUCT_hfa_mtype == MTYPE_F4 || PSTRUCT_hfa_mtype == MTYPE_C4)
00892 PLOC_reg(next) = Get_Current_Preg_Num (SIM_INFO.int_args);
00893 else
00894 PLOC_reg(next) = 0;
00895 }
00896 } else if (Is_Int_Output_Preg(PLOC_reg(prev))) {
00897 PLOC_reg(next) = PLOC_reg(prev) - PR_skip_value(SIM_INFO.int_args);
00898 if (!Is_Int_Output_Preg(PLOC_reg(next)))
00899 PLOC_reg(next) = 0;
00900 } else if (IS_INT_PREG(PLOC_reg(prev))) {
00901 PLOC_reg(next) = PLOC_reg(prev) + PR_skip_value(SIM_INFO.int_args);
00902 if (!IS_INT_PREG(PLOC_reg(next)))
00903 PLOC_reg(next) = 0;
00904 }
00905
00906 return next;
00907 }
00908
00909 PLOC_size(next) = ireg_size;
00910 PSTRUCT_offset += ireg_size;
00911
00912 if (onStack) {
00913 PLOC_reg(next) = 0;
00914 PSTRUCT_first_call = FALSE;
00915 } else if (PSTRUCT_first_call) {
00916 PSTRUCT_first_call = FALSE;
00917 PLOC_reg(next) = PLOC_reg(prev);
00918 if (!(Is_Int_Output_Preg(PLOC_reg(next)) || IS_INT_PREG(PLOC_reg(next))))
00919 PLOC_reg(next) = 0;
00920 } else if (Is_Int_Output_Preg(PLOC_reg(prev))) {
00921 PLOC_reg(next) = PLOC_reg(prev) - PR_skip_value(SIM_INFO.int_args);
00922 if (!Is_Int_Output_Preg(PLOC_reg(next)))
00923 PLOC_reg(next) = 0;
00924 } else if (IS_INT_PREG(PLOC_reg(prev))) {
00925 PLOC_reg(next) = PLOC_reg(prev) + PR_skip_value(SIM_INFO.int_args);
00926 if (!IS_INT_PREG(PLOC_reg(next)))
00927 PLOC_reg(next) = 0;
00928 }
00929
00930 return next;
00931 }
00932
00933
00934
00935 static PLOC
00936 Get_Vararg_Parameter_Location (PLOC prev)
00937 {
00938 PLOC next;
00939 Current_Param_Num++;
00940 next.reg = Get_Current_Preg_Num (SIM_INFO.int_args);
00941
00942 if (next.reg > PR_last_reg(SIM_INFO.int_args))
00943 {
00944 next.reg = 0;
00945 next.size = 0;
00946 }
00947 else
00948 {
00949 next.size = MTYPE_RegisterSize(SIM_INFO.int_type);
00950 }
00951
00952 next.start_offset = Last_Param_Offset;
00953 Last_Param_Offset = next.start_offset + next.size;
00954 return next;
00955 }
00956
00957 BOOL Is_Caller_Save_GP;
00958
00959 INT Formal_Save_Area_Size = 64;
00960 INT Stack_Offset_Adjustment = 16;
00961
00962 extern void
00963 Init_Targ_Sim (void)
00964 {
00965 Is_Caller_Save_GP = SIM_caller_save_gp;
00966 }
00967