Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* 00037 * This defines the ABI subprogram interface, 00038 * and is used to determine how parameters and results are passed. 00039 * We have an array of tables, where each table describes the info 00040 * for one abi. The array is indexed by the TARGET_ABI enumeration. 00041 * The register values are the PREG offsets, so these values can be 00042 * used in WHIRL. 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 /* flags */ 00070 /* int args, flt args, dbl args */ 00071 /* int res , flt res, dbl res */ 00072 /* int type, flt type, dbl type */ 00073 /* save area, formal-area, var ofst */ 00074 /* struct arg, struct res, slink, pic */ 00075 {/* ABI_UNDEF */ 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 { /* ABI_I32 */ 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 { /* ABI_I64 */ 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 /* return whether preg is a return preg */ 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 /* return whether preg is an output preg */ 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 /* return whether preg is an input preg */ 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 } /* Array_Is_HFA */ 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 } /* Struct_Is_HFA */ 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 } // Struct_Has_One_Float 00298 00299 00300 // check if two fields in a struct overlaps 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 } // no_overlap 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 } // Struct_Has_Two_Floats 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 /* This routine figures out the mtypes of the return registers that are 00353 * used for returning an object of the given type. 00354 * This returns the mtypes to use for the CALL opcode in high-level whirl. 00355 * This means that returns of simulated objects, like FQ, are just shown 00356 * as returning FQ, which will later be split into F8F8. 00357 * However, structures that return in registers are specified explicitly. 00358 */ 00359 /*ARGSUSED*/ 00360 extern void 00361 Get_Return_Mtypes ( 00362 TY_IDX rtype, /* The result type */ 00363 Mtype_Return_Level level, /* whether to lower the mtypes */ 00364 TYPE_ID *mreg1, /* out: mtype for result register 1 */ 00365 TYPE_ID *mreg2) /* out: mtype for result register 2 */ 00366 { 00367 Fail_FmtAssertion ( 00368 ("Get_Return_Mtypes should not be invoked; invoke Get_Return_Info instead")); 00369 } 00370 00371 /* This routine figures out which return registers are to be used 00372 * for returning an object with the given mtypes. 00373 * It is assumed that the mtypes will be determined by calling 00374 * Get_Return_Mtypes. 00375 */ 00376 /*ARGSUSED*/ 00377 extern void 00378 Get_Return_Pregs ( 00379 TYPE_ID mreg1, /* in: mtype for result register 1 */ 00380 TYPE_ID mreg2, /* in: mtype for result register 2 */ 00381 PREG_NUM *rreg1, /* out: result register 1 */ 00382 PREG_NUM *rreg2) /* out: result register 2 */ 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 // FORTRAN character array 00403 info.count = 0; 00404 // f90 already has made visible the arg for arrays 00405 // info.return_via_first_arg = TRUE; 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 /* if (size > 0 && 8 * size <= 2 * SIM_INFO.max_struct_result) */ 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 } /* switch (mtype) */ 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 } /* Get_Return_Info */ 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 // find last fixed parameter 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 // old style varargs is counting va_alist and should not 00625 if ( ! TY_has_prototype(pu_type)) 00626 --Last_Fixed_Param; 00627 // account for functions returning to first parameter 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 } // Setup_Parameter_Locations 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; // return location 00663 00664 ploc.reg = 0; 00665 ploc.start_offset = Last_Param_Offset; 00666 ploc.size = 0; 00667 ploc.vararg_reg = 0; // to silence purify 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 /* check for array case where fe doesn't fill in right btype */ 00677 TYPE_ID pmtype = Fix_TY_mtype (ty); /* Target type */ 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 /* skip a parameter slot so quad-aligned */ 00692 ++Current_Param_Num; 00693 /* adjust Last_Fixed_Param in varargs case */ 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; /* padding to right of object */ 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 /* want to right-justify the object */ 00712 ploc.start_offset += (MTYPE_RegisterSize(SIM_INFO.int_type) - 00713 ploc.size); 00714 } 00715 else { 00716 /* Pad to doubleword; leave address alone */ 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 /* adjust Last_Fixed_Param in varargs case */ 00729 if (Last_Fixed_Param < INT_MAX) 00730 ++Last_Fixed_Param; 00731 } 00732 break; 00733 00734 case MTYPE_F4: 00735 case MTYPE_F8: 00736 /* want to left-justify the object */ 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 /* varargs causes float args to be int regs */ 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 /* varargs causes float args to be int regs */ 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 /* adjust Last_Fixed_Param in varargs case */ 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 /* adjust Last_Fixed_Param in varargs case */ 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 /* round up */ 00781 if ((TY_size (ty) % MTYPE_RegisterSize(SIM_INFO.int_type)) != 0) 00782 psize++; 00783 /* structures are left-justified, so may be padding at end */ 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 /* adjust Last_Fixed_Param in varargs case */ 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 /* adjust Last_Fixed_Param in varargs case */ 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 } // Get_Parameter_Location 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; // offset from beginning of struct 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 } // Get_Struct_Parameter_Location 00932 00933 00934 /* Iterate over vararg non-fixed parameters */ 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 /* use Last_Param_Offset in case last fixed arg had padding */ 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; /* whether GP is caller-save */ 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