00001 /* 00002 * Copyright 2003, 2004, 2005, 2006 PathScale, Inc. All Rights Reserved. 00003 */ 00004 00005 /* 00006 00007 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00008 00009 This program is free software; you can redistribute it and/or modify it 00010 under the terms of version 2 of the GNU General Public License as 00011 published by the Free Software Foundation. 00012 00013 This program is distributed in the hope that it would be useful, but 00014 WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00016 00017 Further, this software is distributed without any warranty that it is 00018 free of the rightful claim of any third person regarding infringement 00019 or the like. Any license provided herein, whether implied or 00020 otherwise, applies only to this software file. Patent licenses, if 00021 any, provided herein do not apply to combinations of this program with 00022 other software, or any other product whatsoever. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with this program; if not, write the Free Software Foundation, Inc., 59 00026 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00027 00028 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00029 Mountain View, CA 94043, or: 00030 00031 http://www.sgi.com 00032 00033 For further information regarding this notice, see: 00034 00035 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00036 00037 */ 00038 00039 // 00040 // This file should only be included by <targ>/targ_sim.cxx 00041 // It is for target-independent things that are shared by the targ_sim code. 00042 // 00043 00044 /* 00045 * This defines the ABI subprogram interface, 00046 * and is used to determine how parameters and results are passed. 00047 * We have an array of tables, where each table describes the info 00048 * for one abi. The array is indexed by the TARGET_ABI enumeration. 00049 * The register values are the PREG offsets, so these values can be 00050 * used in WHIRL. 00051 */ 00052 00053 typedef mUINT8 mDED_PREG_NUM; /* physical pregs will be in 0..127 range */ 00054 00055 /* Preg_Range defines a sequence of preg values */ 00056 typedef struct { 00057 mDED_PREG_NUM first_reg; 00058 mDED_PREG_NUM last_reg; 00059 mINT16 skip_value; /* whether to increment by 1 or 2 */ 00060 /* only need 2 bits, but use 16 so no padding & no purify complaint */ 00061 } Preg_Range; 00062 00063 #define PR_first_reg(x) x.first_reg 00064 #define PR_last_reg(x) x.last_reg 00065 #define PR_skip_value(x) x.skip_value 00066 00067 /* Define an interface descriptor: */ 00068 typedef struct subprogram_interface { 00069 00070 mUINT32 flags; /* Flags -- see masks below */ 00071 00072 /* Registers used for parameters and results */ 00073 Preg_Range int_args; 00074 #ifdef TARG_NVISA 00075 Preg_Range int64_args; 00076 #endif 00077 Preg_Range flt_args; 00078 Preg_Range dbl_args; 00079 Preg_Range int_results; 00080 #ifdef TARG_NVISA 00081 Preg_Range int64_results; 00082 #endif 00083 Preg_Range flt_results; 00084 Preg_Range dbl_results; 00085 00086 /* Argument conversion: */ 00087 mTYPE_ID int_type; /* Convert to at least this type */ 00088 #ifdef TARG_NVISA 00089 mTYPE_ID int64_type; /* Convert to at least this type */ 00090 #endif 00091 mTYPE_ID flt_type; /* Convert to at least this type */ 00092 mTYPE_ID dbl_type; /* Convert to at least this type */ 00093 00094 /* Argument save area definition: */ 00095 mINT16 min_save_area_bytes; /* Minimum size to be reserved */ 00096 mINT16 formal_save_area_bytes; /* save area for formals */ 00097 mINT16 varargs_save_offset; /* First argument offset (varargs) */ 00098 00099 /* Miscellaneous: */ 00100 mINT16 max_struct_size; /* Max size of structs in regs */ 00101 /* -1 for no maximum; see IFACE_REG_STRUCTS flag */ 00102 mINT16 max_struct_result; /* Max size of struct result (in bits) */ 00103 00104 mDED_PREG_NUM slink_reg; /* Static link register */ 00105 mDED_PREG_NUM pic_call_reg; /* PIC call address register */ 00106 00107 } SIM; 00108 00109 /* Flag masks */ 00110 #define SIM_EXTRA_FLT_IN_INT 0x0001 /* Use int regs for extra flts? */ 00111 /* After all available floating point argument registers have 00112 * been used, should we use integer registers? 00113 */ 00114 #define SIM_FLT_AFTER_INT 0x0002 /* Use flt regs after int args? */ 00115 /* Can we use floating point argument registers for floating 00116 * point arguments which come after (right of) integer args? 00117 */ 00118 #define SIM_FIXED_REG_BYTES 0x0008 /* Max bytes in registers? */ 00119 /* The MIPS and SPARC ABIs both reserve enough save area space 00120 * for all of the integer argument register contents, but 00121 * considering floating point arguments as well actually could 00122 * allow more register arguments than will fit in the minimum 00123 * space. Can we actually use more registers than the minimum? 00124 */ 00125 #define SIM_COORD_INT_FLT 0x0010 /* Coordinate int/flt regs? */ 00126 /* Does the next available integer register get incremented 00127 * when we assign a float argument, and vice versa? (The MIPS 00128 * conventions say YES.) 00129 */ 00130 #define SIM_COORD_MEM_REG 0x0020 /* Coordinate mem and regs? */ 00131 /* Are the registers a map of memory, i.e. does alignment in 00132 * memory force equivalent alignment in registers? 00133 */ 00134 #define SIM_REG_STRUCTS 0x0040 /* Pass structs in regs? */ 00135 #define SIM_FLT_RTN_COMPLEX 0x0080 /* Return complex in flt regs? */ 00136 #define SIM_CALLER_SAVE_GP 0x0100 /* GP is caller-save? */ 00137 #define SIM_FLT_REG_FIELDS 0x0200 /* Float fields in float regs? */ 00138 #define SIM_DBL_REG_FIELDS 0x0400 /* Double fields in float regs? */ 00139 #define SIM_VARARGS_FLOATS 0x0800 /* Variable float args in fregs? */ 00140 #define SIM_RET_ADDR_VIA_ARGS 0x1000 /* if return large structs via addr 00141 * in implicit arg, do we use normal 00142 * parameter passing conventions for 00143 * that implicit arg. */ 00144 #define SIM_RET_ADDR_VIA_INT_RET 0x2000 /* if return large structs via addr 00145 * in implicit arg, do we use integer 00146 * return register rather than normal 00147 * parameter passing for that 00148 * implicit arg. */ 00149 00150 00151 // gcc and edg have different restrictions on how to do a forward decl 00152 // of an initialized object. 00153 #if (__GNUC__ == 2) 00154 static SIM SIM_Info[]; 00155 #else 00156 extern SIM SIM_Info[]; 00157 #endif 00158 #define SIM_INFO SIM_Info[Target_ABI] 00159 00160 #define SIM_varargs_floats ((SIM_INFO.flags & SIM_VARARGS_FLOATS) != 0) 00161 #define SIM_flt_after_int ((SIM_INFO.flags & SIM_FLT_AFTER_INT) != 0) 00162 #define SIM_caller_save_gp ((SIM_INFO.flags & SIM_CALLER_SAVE_GP) != 0) 00163 #define SIM_dbl_fields_in_reg ((SIM_INFO.flags & SIM_DBL_REG_FIELDS) != 0) 00164 #define SIM_return_addr_via_int_return_reg ((SIM_INFO.flags & SIM_RET_ADDR_VIA_INT_RET) != 0) 00165 00166 /* 00167 * check for array case where fe doesn't fill in right btype 00168 */ 00169 TYPE_ID 00170 Fix_TY_mtype (TY_IDX ty) 00171 { 00172 TYPE_ID type = TY_mtype (ty); 00173 if (type == MTYPE_UNKNOWN && TY_kind (ty) == KIND_ARRAY) 00174 type = Pointer_Mtype; 00175 else if (MTYPE_is_complex(type) && TY_kind (ty) == KIND_STRUCT) 00176 type = MTYPE_M; 00177 00178 return type; 00179 } 00180 00181 static INT Current_Param_Num = -1; 00182 /* number of current logical parameter register, start at 0 */ 00183 static INT Last_Param_Offset = 0; /* stack offset */ 00184 static INT Last_Fixed_Param = INT_MAX; /* # of last fixed param (varargs) */ 00185 00186 00187 static inline PREG_NUM 00188 Get_Current_Preg_Num (Preg_Range pr) 00189 { 00190 PREG_NUM i; 00191 i = PR_first_reg(pr) + (Current_Param_Num * PR_skip_value(pr)); 00192 if (i > PR_last_reg(pr)) 00193 return 0; 00194 else 00195 return i; 00196 } 00197 00198 static PLOC Setup_Parameter_Locations (TY_IDX pu_type); 00199 static PLOC Get_Parameter_Location (TY_IDX ty, BOOL is_output); 00200 00201 extern PLOC 00202 Setup_Input_Parameter_Locations (TY_IDX pu_type) 00203 { 00204 return Setup_Parameter_Locations (pu_type); 00205 } 00206 00207 extern PLOC 00208 Setup_Output_Parameter_Locations (TY_IDX pu_type) 00209 { 00210 return Setup_Parameter_Locations (pu_type); 00211 } 00212 00213 extern PLOC 00214 Get_Input_Parameter_Location (TY_IDX ty) 00215 { 00216 return Get_Parameter_Location (ty, FALSE); 00217 } 00218 00219 extern PLOC 00220 Get_Output_Parameter_Location (TY_IDX ty) 00221 { 00222 return Get_Parameter_Location (ty, TRUE); 00223 } 00224 00225 static PLOC Get_Vararg_Parameter_Location (PLOC prev); 00226 00227 extern PLOC 00228 Get_Vararg_Input_Parameter_Location (PLOC prev) 00229 { 00230 return Get_Vararg_Parameter_Location (prev); 00231 } 00232 00233 extern PLOC 00234 Get_Vararg_Output_Parameter_Location (PLOC prev) 00235 { 00236 return Get_Vararg_Parameter_Location (prev); 00237 } 00238 00239 #define IS_INT_PREG(p) \ 00240 ((PR_first_reg(SIM_INFO.int_args) <= p) \ 00241 && (p <= PR_last_reg(SIM_INFO.int_args))) 00242 00243 #define IS_FLT_PREG(p) \ 00244 ((PR_first_reg(SIM_INFO.flt_args) <= p) \ 00245 && (p <= PR_last_reg(SIM_INFO.flt_args))) 00246 00247 /* return position (0'th parameter...8'th parameter) of preg */ 00248 #define GET_PREG_POSITION(p,range) \ 00249 ((p - PR_first_reg(range)) / PR_skip_value(range)) 00250 00251 00252 extern INT32 00253 Get_Preg_Size (PREG_NUM p) 00254 { 00255 if (IS_FLT_PREG(p)) 00256 return MTYPE_RegisterSize(SIM_INFO.flt_type); 00257 else 00258 return MTYPE_RegisterSize(SIM_INFO.int_type); 00259 } 00260 00261 static void Setup_Struct_Parameter_Locations (TY_IDX struct_ty); 00262 static PLOC Get_Struct_Parameter_Location (PLOC prev); 00263 00264 extern void 00265 Setup_Struct_Input_Parameter_Locations (TY_IDX struct_ty) 00266 { 00267 Setup_Struct_Parameter_Locations (struct_ty); 00268 } 00269 00270 extern void 00271 Setup_Struct_Output_Parameter_Locations (TY_IDX struct_ty) 00272 { 00273 Setup_Struct_Parameter_Locations (struct_ty); 00274 } 00275 00276 extern PLOC 00277 Get_Struct_Input_Parameter_Location (PLOC prev) 00278 { 00279 return Get_Struct_Parameter_Location (prev); 00280 } 00281 00282 extern PLOC 00283 Get_Struct_Output_Parameter_Location (PLOC prev) 00284 { 00285 return Get_Struct_Parameter_Location (prev); 00286 } 00287 00288 00289 static TYPE_ID ploc_parm_mtype; 00290 static INT32 ploc_last_offset; 00291 00292 00293 static PLOC 00294 First_PLOC_Reg (PLOC ploc, TY_IDX parm_ty) 00295 { 00296 ploc_parm_mtype = Fix_TY_mtype (parm_ty); /* Target type */ 00297 PLOC first = ploc; 00298 ploc_last_offset = PLOC_total_size(ploc); 00299 switch (ploc_parm_mtype) { 00300 case MTYPE_F10: 00301 /* 00302 * When FP types wider than a register are passed in integer 00303 * registers or onto the stack, we need multiple of such 00304 * registers or register slots. Treat them as compound types. 00305 */ 00306 if (!PLOC_on_stack(ploc) && IS_FLT_PREG(PLOC_reg(ploc))) 00307 break; 00308 /*FALLTHROUGH*/ 00309 case MTYPE_M: 00310 Setup_Struct_Parameter_Locations (parm_ty); 00311 first = Get_Struct_Parameter_Location (ploc); 00312 break; 00313 case MTYPE_C4: 00314 PLOC_size(first) = MTYPE_RegisterSize(MTYPE_F4); 00315 break; 00316 case MTYPE_C8: 00317 case MTYPE_CQ: 00318 case MTYPE_FQ: 00319 PLOC_size(first) = MTYPE_RegisterSize(MTYPE_F8); 00320 break; 00321 #ifdef TARG_IA64 00322 case MTYPE_C10: 00323 PLOC_size(first) = MTYPE_RegisterSize(MTYPE_F10); 00324 break; 00325 #endif 00326 } 00327 return first; 00328 } 00329 00330 extern PLOC 00331 First_Input_PLOC_Reg (PLOC ploc, TY_IDX parm_ty) 00332 { 00333 return First_PLOC_Reg (ploc, parm_ty); 00334 } 00335 00336 extern PLOC 00337 First_Output_PLOC_Reg (PLOC ploc, TY_IDX parm_ty) 00338 { 00339 return First_PLOC_Reg (ploc, parm_ty); 00340 } 00341 00342 static PLOC 00343 Next_PLOC_Reg (PLOC prev) 00344 { 00345 PLOC next = prev; 00346 switch (ploc_parm_mtype) { 00347 case MTYPE_M: 00348 next = Get_Struct_Parameter_Location (prev); 00349 break; 00350 case MTYPE_C4: 00351 case MTYPE_C8: 00352 case MTYPE_CQ: 00353 case MTYPE_FQ: 00354 if (ploc_parm_mtype == MTYPE_C4) 00355 PLOC_offset(next) += MTYPE_RegisterSize(MTYPE_F4); 00356 else 00357 PLOC_offset(next) += MTYPE_RegisterSize(MTYPE_F8); 00358 if (PLOC_offset(next) == ploc_last_offset) { 00359 // end reached 00360 PLOC_size(next) = 0; 00361 } 00362 PLOC_reg(next) += PR_skip_value(SIM_INFO.flt_args); 00363 if (PLOC_reg(next) > PR_last_reg(SIM_INFO.flt_args)) { 00364 PLOC_reg(next) = 0; 00365 } 00366 break; 00367 #ifdef TARG_IA64 00368 case MTYPE_C10: 00369 PLOC_offset(next) += MTYPE_RegisterSize(MTYPE_F10); 00370 if (PLOC_offset(next) == ploc_last_offset) 00371 PLOC_size(next) = 0; 00372 PLOC_reg(next) += PR_skip_value(SIM_INFO.flt_args); 00373 if (PLOC_reg(next) > PR_last_reg(SIM_INFO.flt_args)) 00374 PLOC_reg(next) = 0; 00375 break; 00376 #endif 00377 case MTYPE_F10: 00378 /* 00379 * When FP types wider than a register are passed in integer 00380 * registers, we need multiple of such registers. Treat them 00381 * as compound types. 00382 */ 00383 if (PLOC_on_stack(prev) || !IS_FLT_PREG(PLOC_reg(prev))) { 00384 next = Get_Struct_Parameter_Location (prev); 00385 break; 00386 } 00387 /*FALLTHROUGH*/ 00388 default: 00389 PLOC_offset(next) = ploc_last_offset; 00390 PLOC_size(next) = 0; 00391 } 00392 return next; 00393 } 00394 00395 extern PLOC 00396 Next_Input_PLOC_Reg (PLOC prev) 00397 { 00398 return Next_PLOC_Reg (prev); 00399 } 00400 00401 extern PLOC 00402 Next_Output_PLOC_Reg (PLOC prev) 00403 { 00404 return Next_PLOC_Reg (prev); 00405 }
1.5.6