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 // This file should only be included by <targ>/targ_sim.cxx 00037 // It is for target-independent things that are shared by the targ_sim code. 00038 // 00039 00040 /* 00041 * This defines the ABI subprogram interface, 00042 * and is used to determine how parameters and results are passed. 00043 * We have an array of tables, where each table describes the info 00044 * for one abi. The array is indexed by the TARGET_ABI enumeration. 00045 * The register values are the PREG offsets, so these values can be 00046 * used in WHIRL. 00047 */ 00048 00049 typedef mUINT8 mDED_PREG_NUM; /* physical pregs will be in 0..127 range */ 00050 00051 /* Preg_Range defines a sequence of preg values */ 00052 typedef struct { 00053 mDED_PREG_NUM first_reg; 00054 mDED_PREG_NUM last_reg; 00055 mINT16 skip_value; /* whether to increment by 1 or 2 */ 00056 /* only need 2 bits, but use 16 so no padding & no purify complaint */ 00057 } Preg_Range; 00058 00059 #define PR_first_reg(x) x.first_reg 00060 #define PR_last_reg(x) x.last_reg 00061 #define PR_skip_value(x) x.skip_value 00062 00063 /* Define an interface descriptor: */ 00064 typedef struct subprogram_interface { 00065 00066 mUINT32 flags; /* Flags -- see masks below */ 00067 00068 /* Registers used for parameters and results */ 00069 Preg_Range int_args; 00070 Preg_Range flt_args; 00071 Preg_Range dbl_args; 00072 Preg_Range int_results; 00073 Preg_Range flt_results; 00074 Preg_Range dbl_results; 00075 00076 /* Argument conversion: */ 00077 mTYPE_ID int_type; /* Convert to at least this type */ 00078 mTYPE_ID flt_type; /* Convert to at least this type */ 00079 mTYPE_ID dbl_type; /* Convert to at least this type */ 00080 00081 /* Argument save area definition: */ 00082 mINT16 min_save_area_bytes; /* Minimum size to be reserved */ 00083 mINT16 formal_save_area_bytes; /* save area for formals */ 00084 mINT16 varargs_save_offset; /* First argument offset (varargs) */ 00085 00086 /* Miscellaneous: */ 00087 mINT16 max_struct_size; /* Max size of structs in regs */ 00088 /* -1 for no maximum; see IFACE_REG_STRUCTS flag */ 00089 mINT16 max_struct_result; /* Max size of struct result (in bits) */ 00090 00091 mDED_PREG_NUM slink_reg; /* Static link register */ 00092 mDED_PREG_NUM pic_call_reg; /* PIC call address register */ 00093 00094 } SIM; 00095 00096 /* Flag masks */ 00097 #define SIM_EXTRA_FLT_IN_INT 0x0001 /* Use int regs for extra flts? */ 00098 /* After all available floating point argument registers have 00099 * been used, should we use integer registers? 00100 */ 00101 #define SIM_FLT_AFTER_INT 0x0002 /* Use flt regs after int args? */ 00102 /* Can we use floating point argument registers for floating 00103 * point arguments which come after (right of) integer args? 00104 */ 00105 #define SIM_FIXED_REG_BYTES 0x0008 /* Max bytes in registers? */ 00106 /* The MIPS and SPARC ABIs both reserve enough save area space 00107 * for all of the integer argument register contents, but 00108 * considering floating point arguments as well actually could 00109 * allow more register arguments than will fit in the minimum 00110 * space. Can we actually use more registers than the minimum? 00111 */ 00112 #define SIM_COORD_INT_FLT 0x0010 /* Coordinate int/flt regs? */ 00113 /* Does the next available integer register get incremented 00114 * when we assign a float argument, and vice versa? (The MIPS 00115 * conventions say YES.) 00116 */ 00117 #define SIM_COORD_MEM_REG 0x0020 /* Coordinate mem and regs? */ 00118 /* Are the registers a map of memory, i.e. does alignment in 00119 * memory force equivalent alignment in registers? 00120 */ 00121 #define SIM_REG_STRUCTS 0x0040 /* Pass structs in regs? */ 00122 #define SIM_FLT_RTN_COMPLEX 0x0080 /* Return complex in flt regs? */ 00123 #define SIM_CALLER_SAVE_GP 0x0100 /* GP is caller-save? */ 00124 #define SIM_FLT_REG_FIELDS 0x0200 /* Float fields in float regs? */ 00125 #define SIM_DBL_REG_FIELDS 0x0400 /* Double fields in float regs? */ 00126 #define SIM_VARARGS_FLOATS 0x0800 /* Variable float args in fregs? */ 00127 #define SIM_RET_ADDR_VIA_ARGS 0x1000 /* if return large structs via addr 00128 * in implicit arg, do we use normal 00129 * parameter passing conventions for 00130 * that implicit arg. */ 00131 #define SIM_RET_ADDR_VIA_INT_RET 0x2000 /* if return large structs via addr 00132 * in implicit arg, do we use integer 00133 * return register rather than normal 00134 * parameter passing for that 00135 * implicit arg. */ 00136 00137 extern SIM SIM_Info[]; 00138 #define SIM_INFO SIM_Info[Target_ABI] 00139 00140 #define SIM_varargs_floats ((SIM_INFO.flags & SIM_VARARGS_FLOATS) != 0) 00141 #define SIM_flt_after_int ((SIM_INFO.flags & SIM_FLT_AFTER_INT) != 0) 00142 #define SIM_caller_save_gp ((SIM_INFO.flags & SIM_CALLER_SAVE_GP) != 0) 00143 #define SIM_dbl_fields_in_reg ((SIM_INFO.flags & SIM_DBL_REG_FIELDS) != 0) 00144 #define SIM_return_addr_via_int_return_reg ((SIM_INFO.flags & SIM_RET_ADDR_VIA_INT_RET) != 0) 00145 00146 /* 00147 * check for array case where fe doesn't fill in right btype 00148 */ 00149 TYPE_ID 00150 Fix_TY_mtype (TY_IDX ty) 00151 { 00152 TYPE_ID type = TY_mtype (ty); 00153 if (type == MTYPE_UNKNOWN && TY_kind (ty) == KIND_ARRAY) 00154 type = Pointer_Mtype; 00155 else if (MTYPE_is_complex(type) && TY_kind (ty) == KIND_STRUCT) 00156 type = MTYPE_M; 00157 00158 return type; 00159 } 00160 00161 static INT Current_Param_Num = -1; 00162 /* number of current logical parameter register, start at 0 */ 00163 static INT Last_Param_Offset = 0; /* stack offset */ 00164 static INT Last_Fixed_Param = INT_MAX; /* # of last fixed param (varargs) */ 00165 00166 00167 static inline PREG_NUM 00168 Get_Current_Preg_Num (Preg_Range pr) 00169 { 00170 PREG_NUM i; 00171 i = PR_first_reg(pr) + (Current_Param_Num * PR_skip_value(pr)); 00172 if (i > PR_last_reg(pr)) 00173 return 0; 00174 else 00175 return i; 00176 } 00177 00178 static PLOC Setup_Parameter_Locations (TY_IDX pu_type); 00179 static PLOC Get_Parameter_Location (TY_IDX ty, BOOL is_output); 00180 00181 extern PLOC 00182 Setup_Input_Parameter_Locations (TY_IDX pu_type) 00183 { 00184 return Setup_Parameter_Locations (pu_type); 00185 } 00186 00187 extern PLOC 00188 Setup_Output_Parameter_Locations (TY_IDX pu_type) 00189 { 00190 return Setup_Parameter_Locations (pu_type); 00191 } 00192 00193 extern PLOC 00194 Get_Input_Parameter_Location (TY_IDX ty) 00195 { 00196 return Get_Parameter_Location (ty, FALSE); 00197 } 00198 00199 extern PLOC 00200 Get_Output_Parameter_Location (TY_IDX ty) 00201 { 00202 return Get_Parameter_Location (ty, TRUE); 00203 } 00204 00205 static PLOC Get_Vararg_Parameter_Location (PLOC prev); 00206 00207 extern PLOC 00208 Get_Vararg_Input_Parameter_Location (PLOC prev) 00209 { 00210 return Get_Vararg_Parameter_Location (prev); 00211 } 00212 00213 extern PLOC 00214 Get_Vararg_Output_Parameter_Location (PLOC prev) 00215 { 00216 return Get_Vararg_Parameter_Location (prev); 00217 } 00218 00219 #define IS_INT_PREG(p) \ 00220 ((PR_first_reg(SIM_INFO.int_args) <= p) \ 00221 && (p <= PR_last_reg(SIM_INFO.int_args))) 00222 00223 #define IS_FLT_PREG(p) \ 00224 ((PR_first_reg(SIM_INFO.flt_args) <= p) \ 00225 && (p <= PR_last_reg(SIM_INFO.flt_args))) 00226 00227 /* return position (0'th parameter...8'th parameter) of preg */ 00228 #define GET_PREG_POSITION(p,range) \ 00229 ((p - PR_first_reg(range)) / PR_skip_value(range)) 00230 00231 00232 extern INT32 00233 Get_Preg_Size (PREG_NUM p) 00234 { 00235 if (IS_FLT_PREG(p)) 00236 return MTYPE_RegisterSize(SIM_INFO.flt_type); 00237 else 00238 return MTYPE_RegisterSize(SIM_INFO.int_type); 00239 } 00240 00241 static void Setup_Struct_Parameter_Locations (TY_IDX struct_ty); 00242 static PLOC Get_Struct_Parameter_Location (PLOC prev); 00243 00244 extern void 00245 Setup_Struct_Input_Parameter_Locations (TY_IDX struct_ty) 00246 { 00247 Setup_Struct_Parameter_Locations (struct_ty); 00248 } 00249 00250 extern void 00251 Setup_Struct_Output_Parameter_Locations (TY_IDX struct_ty) 00252 { 00253 Setup_Struct_Parameter_Locations (struct_ty); 00254 } 00255 00256 extern PLOC 00257 Get_Struct_Input_Parameter_Location (PLOC prev) 00258 { 00259 return Get_Struct_Parameter_Location (prev); 00260 } 00261 00262 extern PLOC 00263 Get_Struct_Output_Parameter_Location (PLOC prev) 00264 { 00265 return Get_Struct_Parameter_Location (prev); 00266 } 00267 00268 00269 static TYPE_ID ploc_parm_mtype; 00270 static INT32 ploc_last_offset; 00271 00272 00273 static PLOC 00274 First_PLOC_Reg (PLOC ploc, TY_IDX parm_ty) 00275 { 00276 ploc_parm_mtype = Fix_TY_mtype (parm_ty); /* Target type */ 00277 PLOC first = ploc; 00278 ploc_last_offset = PLOC_total_size(ploc); 00279 switch (ploc_parm_mtype) { 00280 case MTYPE_M: 00281 Setup_Struct_Parameter_Locations (parm_ty); 00282 first = Get_Struct_Parameter_Location (ploc); 00283 break; 00284 case MTYPE_C4: 00285 PLOC_size(first) = MTYPE_RegisterSize(MTYPE_F4); 00286 break; 00287 case MTYPE_C8: 00288 case MTYPE_CQ: 00289 case MTYPE_FQ: 00290 PLOC_size(first) = MTYPE_RegisterSize(MTYPE_F8); 00291 break; 00292 } 00293 return first; 00294 } 00295 00296 extern PLOC 00297 First_Input_PLOC_Reg (PLOC ploc, TY_IDX parm_ty) 00298 { 00299 return First_PLOC_Reg (ploc, parm_ty); 00300 } 00301 00302 extern PLOC 00303 First_Output_PLOC_Reg (PLOC ploc, TY_IDX parm_ty) 00304 { 00305 return First_PLOC_Reg (ploc, parm_ty); 00306 } 00307 00308 static PLOC 00309 Next_PLOC_Reg (PLOC prev) 00310 { 00311 PLOC next = prev; 00312 switch (ploc_parm_mtype) { 00313 case MTYPE_M: 00314 next = Get_Struct_Parameter_Location (prev); 00315 break; 00316 case MTYPE_C4: 00317 case MTYPE_C8: 00318 case MTYPE_CQ: 00319 case MTYPE_FQ: 00320 if (ploc_parm_mtype == MTYPE_C4) 00321 PLOC_offset(next) += MTYPE_RegisterSize(MTYPE_F4); 00322 else 00323 PLOC_offset(next) += MTYPE_RegisterSize(MTYPE_F8); 00324 if (PLOC_offset(next) == ploc_last_offset) { 00325 // end reached 00326 PLOC_size(next) = 0; 00327 } 00328 PLOC_reg(next) += PR_skip_value(SIM_INFO.flt_args); 00329 if (PLOC_reg(next) > PR_last_reg(SIM_INFO.flt_args)) { 00330 PLOC_reg(next) = 0; 00331 } 00332 break; 00333 default: 00334 PLOC_offset(next) = ploc_last_offset; 00335 PLOC_size(next) = 0; 00336 } 00337 return next; 00338 } 00339 00340 extern PLOC 00341 Next_Input_PLOC_Reg (PLOC prev) 00342 { 00343 return Next_PLOC_Reg (prev); 00344 } 00345 00346 extern PLOC 00347 Next_Output_PLOC_Reg (PLOC prev) 00348 { 00349 return Next_PLOC_Reg (prev); 00350 }