Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
targ_sim.cxx
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines