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 #include <map>
00031 #include "elf_stuff.h"
00032 #include "defs.h"
00033 #include "em_elf.h"
00034 #include "erglob.h"
00035 #include "erbe.h"
00036 #include "tracing.h"
00037 #include "config.h"
00038 #include "config_debug.h"
00039 #include "xstats.h"
00040 #include "topcode.h"
00041 #include "tn.h"
00042 #include "cg_flags.h"
00043 #include "targ_isa_enums.h"
00044 #include "targ_isa_lits.h"
00045 #include "op.h"
00046 #include "stblock.h"
00047 #include "data_layout.h"
00048 #include "strtab.h"
00049 #include "symtab.h"
00050 #include "cg.h"
00051 #include "cgexp.h"
00052 #include "cgexp_internals.h"
00053 #include "cgemit.h"
00054 #include "be_symtab.h"
00055 #include "whirl2ops.h"
00056
00057 std::map<pair<UINT,INT64>, TN*> st_to_tn_map;
00058
00059 void Exp_Ldst_Init (void)
00060 {
00061 st_to_tn_map.clear();
00062 }
00063
00064 static const TOP load_top[11] = {
00065 TOP_ld_qualifier_space_s8, TOP_ld_qualifier_space_s16,
00066 TOP_ld_qualifier_space_s32, TOP_ld_qualifier_space_s64,
00067 TOP_ld_qualifier_space_u8, TOP_ld_qualifier_space_u16,
00068 TOP_ld_qualifier_space_u32, TOP_ld_qualifier_space_u64,
00069 TOP_ld_qualifier_space_f32, TOP_ld_qualifier_space_f64
00070 };
00071 static const TOP loado_top[11] = {
00072 TOP_ld_qualifier_space_s8_o, TOP_ld_qualifier_space_s16_o,
00073 TOP_ld_qualifier_space_s32_o, TOP_ld_qualifier_space_s64_o,
00074 TOP_ld_qualifier_space_u8_o, TOP_ld_qualifier_space_u16_o,
00075 TOP_ld_qualifier_space_u32_o, TOP_ld_qualifier_space_u64_o,
00076 TOP_ld_qualifier_space_f32_o, TOP_ld_qualifier_space_f64_o
00077 };
00078 static const TOP loadr_top[11] = {
00079 TOP_ld_qualifier_space_s8_r, TOP_ld_qualifier_space_s16_r,
00080 TOP_ld_qualifier_space_s32_r, TOP_ld_qualifier_space_s64_r,
00081 TOP_ld_qualifier_space_u8_r, TOP_ld_qualifier_space_u16_r,
00082 TOP_ld_qualifier_space_u32_r, TOP_ld_qualifier_space_u64_r,
00083 TOP_ld_qualifier_space_f32_r, TOP_ld_qualifier_space_f64_r
00084 };
00085 static const TOP load32_top[11] = {
00086 TOP_ld_qualifier_space_s8_b32, TOP_ld_qualifier_space_s16_b32,
00087 TOP_UNDEFINED, TOP_UNDEFINED,
00088 TOP_ld_qualifier_space_u8_b32, TOP_ld_qualifier_space_u16_b32,
00089 TOP_UNDEFINED, TOP_UNDEFINED,
00090 TOP_UNDEFINED, TOP_UNDEFINED
00091 };
00092 static const TOP load32o_top[11] = {
00093 TOP_ld_qualifier_space_s8_b32_o, TOP_ld_qualifier_space_s16_b32_o,
00094 TOP_UNDEFINED, TOP_UNDEFINED,
00095 TOP_ld_qualifier_space_u8_b32_o, TOP_ld_qualifier_space_u16_b32_o,
00096 TOP_UNDEFINED, TOP_UNDEFINED,
00097 TOP_UNDEFINED, TOP_UNDEFINED
00098 };
00099 static const TOP load32r_top[11] = {
00100 TOP_ld_qualifier_space_s8_b32_r, TOP_ld_qualifier_space_s16_b32_r,
00101 TOP_UNDEFINED, TOP_UNDEFINED,
00102 TOP_ld_qualifier_space_u8_b32_r, TOP_ld_qualifier_space_u16_b32_r,
00103 TOP_UNDEFINED, TOP_UNDEFINED,
00104 TOP_UNDEFINED, TOP_UNDEFINED
00105 };
00106 static const TOP loade_top[11] = {
00107 TOP_ld_qualifier_space_s8_a64, TOP_ld_qualifier_space_s16_a64,
00108 TOP_ld_qualifier_space_s32_a64, TOP_ld_qualifier_space_s64_a64,
00109 TOP_ld_qualifier_space_u8_a64, TOP_ld_qualifier_space_u16_a64,
00110 TOP_ld_qualifier_space_u32_a64, TOP_ld_qualifier_space_u64_a64,
00111 TOP_ld_qualifier_space_f32_a64, TOP_ld_qualifier_space_f64_a64
00112 };
00113 static const TOP loadeo_top[11] = {
00114 TOP_ld_qualifier_space_s8_a64_o, TOP_ld_qualifier_space_s16_a64_o,
00115 TOP_ld_qualifier_space_s32_a64_o, TOP_ld_qualifier_space_s64_a64_o,
00116 TOP_ld_qualifier_space_u8_a64_o, TOP_ld_qualifier_space_u16_a64_o,
00117 TOP_ld_qualifier_space_u32_a64_o, TOP_ld_qualifier_space_u64_a64_o,
00118 TOP_ld_qualifier_space_f32_a64_o, TOP_ld_qualifier_space_f64_a64_o
00119 };
00120 static const TOP loader_top[11] = {
00121 TOP_ld_qualifier_space_s8_a64_r, TOP_ld_qualifier_space_s16_a64_r,
00122 TOP_ld_qualifier_space_s32_a64_r, TOP_ld_qualifier_space_s64_a64_r,
00123 TOP_ld_qualifier_space_u8_a64_r, TOP_ld_qualifier_space_u16_a64_r,
00124 TOP_ld_qualifier_space_u32_a64_r, TOP_ld_qualifier_space_u64_a64_r,
00125 TOP_ld_qualifier_space_f32_a64_r, TOP_ld_qualifier_space_f64_a64_r
00126 };
00127 static const TOP loade32_top[11] = {
00128 TOP_ld_qualifier_space_s8_b32_a64, TOP_ld_qualifier_space_s16_b32_a64,
00129 TOP_UNDEFINED, TOP_UNDEFINED,
00130 TOP_ld_qualifier_space_u8_b32_a64, TOP_ld_qualifier_space_u16_b32_a64,
00131 TOP_UNDEFINED, TOP_UNDEFINED,
00132 TOP_UNDEFINED, TOP_UNDEFINED
00133 };
00134 static const TOP loade32o_top[11] = {
00135 TOP_ld_qualifier_space_s8_b32_a64_o, TOP_ld_qualifier_space_s16_b32_a64_o,
00136 TOP_UNDEFINED, TOP_UNDEFINED,
00137 TOP_ld_qualifier_space_u8_b32_a64_o, TOP_ld_qualifier_space_u16_b32_a64_o,
00138 TOP_UNDEFINED, TOP_UNDEFINED,
00139 TOP_UNDEFINED, TOP_UNDEFINED
00140 };
00141 static const TOP loade32r_top[11] = {
00142 TOP_ld_qualifier_space_s8_b32_a64_r, TOP_ld_qualifier_space_s16_b32_a64_r,
00143 TOP_UNDEFINED, TOP_UNDEFINED,
00144 TOP_ld_qualifier_space_u8_b32_a64_r, TOP_ld_qualifier_space_u16_b32_a64_r,
00145 TOP_UNDEFINED, TOP_UNDEFINED,
00146 TOP_UNDEFINED, TOP_UNDEFINED
00147 };
00148
00149 static const TOP store_top[11] = {
00150 TOP_st_qualifier_space_s8, TOP_st_qualifier_space_s16,
00151 TOP_st_qualifier_space_s32, TOP_st_qualifier_space_s64,
00152 TOP_st_qualifier_space_u8, TOP_st_qualifier_space_u16,
00153 TOP_st_qualifier_space_u32, TOP_st_qualifier_space_u64,
00154 TOP_st_qualifier_space_f32, TOP_st_qualifier_space_f64
00155 };
00156 static const TOP storeo_top[11] = {
00157 TOP_st_qualifier_space_s8_o, TOP_st_qualifier_space_s16_o,
00158 TOP_st_qualifier_space_s32_o, TOP_st_qualifier_space_s64_o,
00159 TOP_st_qualifier_space_u8_o, TOP_st_qualifier_space_u16_o,
00160 TOP_st_qualifier_space_u32_o, TOP_st_qualifier_space_u64_o,
00161 TOP_st_qualifier_space_f32_o, TOP_st_qualifier_space_f64_o
00162 };
00163 static const TOP storer_top[11] = {
00164 TOP_st_qualifier_space_s8_r, TOP_st_qualifier_space_s16_r,
00165 TOP_st_qualifier_space_s32_r, TOP_st_qualifier_space_s64_r,
00166 TOP_st_qualifier_space_u8_r, TOP_st_qualifier_space_u16_r,
00167 TOP_st_qualifier_space_u32_r, TOP_st_qualifier_space_u64_r,
00168 TOP_st_qualifier_space_f32_r, TOP_st_qualifier_space_f64_r
00169 };
00170 static const TOP store32_top[11] = {
00171 TOP_st_qualifier_space_s8_b32, TOP_st_qualifier_space_s16_b32,
00172 TOP_UNDEFINED, TOP_UNDEFINED,
00173 TOP_st_qualifier_space_u8_b32, TOP_st_qualifier_space_u16_b32,
00174 TOP_UNDEFINED, TOP_UNDEFINED,
00175 TOP_UNDEFINED, TOP_UNDEFINED
00176 };
00177 static const TOP store32o_top[11] = {
00178 TOP_st_qualifier_space_s8_b32_o, TOP_st_qualifier_space_s16_b32_o,
00179 TOP_UNDEFINED, TOP_UNDEFINED,
00180 TOP_st_qualifier_space_u8_b32_o, TOP_st_qualifier_space_u16_b32_o,
00181 TOP_UNDEFINED, TOP_UNDEFINED,
00182 TOP_UNDEFINED, TOP_UNDEFINED
00183 };
00184 static const TOP store32r_top[11] = {
00185 TOP_st_qualifier_space_s8_b32_r, TOP_st_qualifier_space_s16_b32_r,
00186 TOP_UNDEFINED, TOP_UNDEFINED,
00187 TOP_st_qualifier_space_u8_b32_r, TOP_st_qualifier_space_u16_b32_r,
00188 TOP_UNDEFINED, TOP_UNDEFINED,
00189 TOP_UNDEFINED, TOP_UNDEFINED
00190 };
00191 static const TOP storee_top[11] = {
00192 TOP_st_qualifier_space_s8_a64, TOP_st_qualifier_space_s16_a64,
00193 TOP_st_qualifier_space_s32_a64, TOP_st_qualifier_space_s64_a64,
00194 TOP_st_qualifier_space_u8_a64, TOP_st_qualifier_space_u16_a64,
00195 TOP_st_qualifier_space_u32_a64, TOP_st_qualifier_space_u64_a64,
00196 TOP_st_qualifier_space_f32_a64, TOP_st_qualifier_space_f64_a64
00197 };
00198 static const TOP storeeo_top[11] = {
00199 TOP_st_qualifier_space_s8_a64_o, TOP_st_qualifier_space_s16_a64_o,
00200 TOP_st_qualifier_space_s32_a64_o, TOP_st_qualifier_space_s64_a64_o,
00201 TOP_st_qualifier_space_u8_a64_o, TOP_st_qualifier_space_u16_a64_o,
00202 TOP_st_qualifier_space_u32_a64_o, TOP_st_qualifier_space_u64_a64_o,
00203 TOP_st_qualifier_space_f32_a64_o, TOP_st_qualifier_space_f64_a64_o
00204 };
00205 static const TOP storeer_top[11] = {
00206 TOP_st_qualifier_space_s8_a64_r, TOP_st_qualifier_space_s16_a64_r,
00207 TOP_st_qualifier_space_s32_a64_r, TOP_st_qualifier_space_s64_a64_r,
00208 TOP_st_qualifier_space_u8_a64_r, TOP_st_qualifier_space_u16_a64_r,
00209 TOP_st_qualifier_space_u32_a64_r, TOP_st_qualifier_space_u64_a64_r,
00210 TOP_st_qualifier_space_f32_a64_r, TOP_st_qualifier_space_f64_a64_r
00211 };
00212 static const TOP storee32_top[11] = {
00213 TOP_st_qualifier_space_s8_b32_a64, TOP_st_qualifier_space_s16_b32_a64,
00214 TOP_UNDEFINED, TOP_UNDEFINED,
00215 TOP_st_qualifier_space_u8_b32_a64, TOP_st_qualifier_space_u16_b32_a64,
00216 TOP_UNDEFINED, TOP_UNDEFINED,
00217 TOP_UNDEFINED, TOP_UNDEFINED
00218 };
00219 static const TOP storee32o_top[11] = {
00220 TOP_st_qualifier_space_s8_b32_a64_o, TOP_st_qualifier_space_s16_b32_a64_o,
00221 TOP_UNDEFINED, TOP_UNDEFINED,
00222 TOP_st_qualifier_space_u8_b32_a64_o, TOP_st_qualifier_space_u16_b32_a64_o,
00223 TOP_UNDEFINED, TOP_UNDEFINED,
00224 TOP_UNDEFINED, TOP_UNDEFINED
00225 };
00226 static const TOP storee32r_top[11] = {
00227 TOP_st_qualifier_space_s8_b32_a64_r, TOP_st_qualifier_space_s16_b32_a64_r,
00228 TOP_UNDEFINED, TOP_UNDEFINED,
00229 TOP_st_qualifier_space_u8_b32_a64_r, TOP_st_qualifier_space_u16_b32_a64_r,
00230 TOP_UNDEFINED, TOP_UNDEFINED,
00231 TOP_UNDEFINED, TOP_UNDEFINED
00232 };
00233
00234 static ISA_ENUM_CLASS_VALUE
00235 Space_Enum (VARIANT v, TN *tn)
00236 {
00237 #ifdef Is_True_On
00238
00239 UINT t = V_memory_space(v);
00240 UINT n = 0;
00241 while (t != 0) {
00242 if ((t & 1) == 1)
00243 ++n;
00244 t = t >> 1;
00245 }
00246 if (n > 1)
00247 DevWarn("multiple memory spaces set");
00248 #endif
00249 if (V_global_mem(v)) return ECV_space_global;
00250 else if (V_shared_mem(v)) return ECV_space_shared;
00251 else if (V_local_mem(v)) return ECV_space_local;
00252 else if (V_const_mem(v)) return ECV_space_const;
00253 else if (V_param_mem(v)) return ECV_space_param;
00254 else if (TN_has_memory_space(tn)) {
00255 if (TN_in_global_mem(tn)) return ECV_space_global;
00256 else if (TN_in_shared_mem(tn)) return ECV_space_shared;
00257 else if (TN_in_local_mem(tn)) return ECV_space_local;
00258 else if (TN_in_const_mem(tn)) return ECV_space_const;
00259 else if (TN_in_param_mem(tn)) return ECV_space_param;
00260 else FmtAssert(FALSE, ("unknown memory space"));
00261 }
00262 else return ECV_UNDEFINED;
00263 }
00264
00265 static inline TOP
00266 Pick_Load_Instruction (TYPE_ID mtype, BOOL val_is32, BOOL addr_is64,
00267 BOOL use_reg, BOOL has_offset)
00268 {
00269 if (addr_is64) {
00270 if (val_is32) {
00271 if (use_reg)
00272 return loade32r_top[Mtype_Index(mtype)];
00273 else if (has_offset)
00274 return loade32o_top[Mtype_Index(mtype)];
00275 else
00276 return loade32_top[Mtype_Index(mtype)];
00277 }
00278 else {
00279 if (use_reg)
00280 return loader_top[Mtype_Index(mtype)];
00281 else if (has_offset)
00282 return loadeo_top[Mtype_Index(mtype)];
00283 else
00284 return loade_top[Mtype_Index(mtype)];
00285 }
00286 }
00287 else {
00288 if (val_is32) {
00289 if (use_reg)
00290 return load32r_top[Mtype_Index(mtype)];
00291 else if (has_offset)
00292 return load32o_top[Mtype_Index(mtype)];
00293 else
00294 return load32_top[Mtype_Index(mtype)];
00295 }
00296 else {
00297 if (use_reg)
00298 return loadr_top[Mtype_Index(mtype)];
00299 else if (has_offset)
00300 return loado_top[Mtype_Index(mtype)];
00301 else
00302 return load_top[Mtype_Index(mtype)];
00303 }
00304 }
00305 }
00306
00307 static inline TOP
00308 Pick_Store_Instruction (TYPE_ID mtype, BOOL val_is32, BOOL addr_is64,
00309 BOOL use_reg, BOOL has_offset)
00310 {
00311 if (addr_is64) {
00312 if (val_is32) {
00313 if (use_reg)
00314 return storee32r_top[Mtype_Index(mtype)];
00315 else if (has_offset)
00316 return storee32o_top[Mtype_Index(mtype)];
00317 else
00318 return storee32_top[Mtype_Index(mtype)];
00319 }
00320 else {
00321 if (use_reg)
00322 return storeer_top[Mtype_Index(mtype)];
00323 else if (has_offset)
00324 return storeeo_top[Mtype_Index(mtype)];
00325 else
00326 return storee_top[Mtype_Index(mtype)];
00327 }
00328 }
00329 else {
00330 if (val_is32) {
00331 if (use_reg)
00332 return store32r_top[Mtype_Index(mtype)];
00333 else if (has_offset)
00334 return store32o_top[Mtype_Index(mtype)];
00335 else
00336 return store32_top[Mtype_Index(mtype)];
00337 }
00338 else {
00339 if (use_reg)
00340 return storer_top[Mtype_Index(mtype)];
00341 else if (has_offset)
00342 return storeo_top[Mtype_Index(mtype)];
00343 else
00344 return store_top[Mtype_Index(mtype)];
00345 }
00346 }
00347 }
00348
00349 static void
00350 Set_TN_Memory_Space_From_Variant (TN *tn, VARIANT v, TN *base)
00351 {
00352
00353
00354 if (V_global_mem(v)) {
00355 Set_TN_in_global_mem(tn);
00356 }
00357 else if (V_shared_mem(v)) {
00358 Set_TN_in_shared_mem(tn);
00359 }
00360 else if (V_param_mem(v)) {
00361 Set_TN_in_param_mem(tn);
00362 }
00363 else if (V_local_mem(v)) {
00364 Set_TN_in_local_mem(tn);
00365 }
00366 else if (V_const_mem(v)) {
00367 Set_TN_in_const_mem(tn);
00368 }
00369 else if (TN_has_memory_space(base)) {
00370 Set_TN_memory_space(tn, TN_memory_space(base));
00371 }
00372 else FmtAssert(FALSE, ("NYI: tn memory type"));
00373 }
00374
00375 void
00376 Expand_Load (OPCODE opcode, TN *result, TN *base, TN *ofst, VARIANT v, OPS *ops)
00377 {
00378 TOP top;
00379 const TYPE_ID dtype = OPCODE_desc(opcode);
00380 const TYPE_ID rtype = OPCODE_rtype(opcode);
00381 TN *dresult = result;
00382 BOOL need_convert = FALSE;
00383 BOOL val_is32 = FALSE;
00384 BOOL addr_is64;
00385 BOOL use_reg;
00386 BOOL has_offset;
00387 TN *space_tn = Gen_Enum_TN(Space_Enum(v,base));
00388 TN *qualifier_tn;
00389
00390 switch (Space_Enum(v,base)) {
00391 case ECV_space_global:
00392 case ECV_space_shared:
00393 break;
00394 default:
00395
00396 Reset_V_volatile(v);
00397 }
00398 if (V_volatile(v))
00399 qualifier_tn = Gen_Enum_TN(ECV_qualifier_volatile);
00400 else
00401 qualifier_tn = Gen_Enum_TN(ECV_qualifier_none);
00402
00403 Is_True(TN_size(result) >= MTYPE_byte_size(rtype), ("load won't fit in result"));
00404
00405 if (dtype != rtype && MTYPE_is_integral(rtype)) {
00406 if ((rtype == MTYPE_U4 || rtype == MTYPE_I4)
00407 && MTYPE_byte_size(dtype) < MTYPE_byte_size(rtype))
00408 {
00409
00410
00411 val_is32 = TRUE;
00412 } else {
00413
00414 dresult = Build_TN_Of_Mtype (dtype);
00415 need_convert = TRUE;
00416 }
00417 }
00418 Is_True (TN_is_constant(ofst), ("Expand_Load: Illegal offset TN"));
00419 if (TN_is_symbol(base)) {
00420 use_reg = FALSE;
00421 addr_is64 = (MTYPE_RegisterSize(ST_mtype(TN_var(base))) == 8);
00422 if (TN_has_value(ofst) && TN_value(ofst) == 0
00423 && TN_is_symbol(base) && Is_Simple_Type(ST_type(TN_var(base))))
00424 {
00425
00426 has_offset = FALSE;
00427 } else {
00428
00429 has_offset = TRUE;
00430 }
00431 }
00432 else {
00433
00434 use_reg = TRUE;
00435 has_offset = TRUE;
00436 addr_is64 = (TN_register_class(base) == ISA_REGISTER_CLASS_integer64);
00437 }
00438 top = Pick_Load_Instruction (dtype, val_is32, addr_is64, use_reg, has_offset);
00439 FmtAssert(top != TOP_UNDEFINED, ("no topcode"));
00440 if (has_offset)
00441 Build_OP (top, dresult, qualifier_tn, space_tn, base, ofst, ops);
00442 else
00443 Build_OP (top, dresult, qualifier_tn, space_tn, base, ops);
00444
00445 if (TN_enum(space_tn) == ECV_space_shared) {
00446
00447
00448 Set_TN_from_shared_load(dresult);
00449 }
00450 if (need_convert) {
00451 Expand_Convert (result, rtype, dresult, dtype, ops);
00452 }
00453
00454 if (rtype == Pointer_Mtype) {
00455 Set_TN_Memory_Space_From_Variant (result, v, base);
00456 }
00457 }
00458
00459
00460 void
00461 Expand_Store (TYPE_ID mtype, TN *src, TN *base, TN *ofst, VARIANT v, OPS *ops)
00462 {
00463 TOP top;
00464 BOOL val_is32 = FALSE;
00465 BOOL addr_is64;
00466 BOOL use_reg;
00467 BOOL has_offset;
00468 TN *space_tn = Gen_Enum_TN(Space_Enum(v,base));
00469 TN *qualifier_tn;
00470
00471 switch (Space_Enum(v,base)) {
00472 case ECV_space_global:
00473 case ECV_space_shared:
00474 break;
00475 default:
00476
00477 Reset_V_volatile(v);
00478 }
00479 if (V_volatile(v))
00480 qualifier_tn = Gen_Enum_TN(ECV_qualifier_volatile);
00481 else
00482 qualifier_tn = Gen_Enum_TN(ECV_qualifier_none);
00483
00484
00485 if (TN_size(src) != MTYPE_byte_size(mtype)) {
00486 const TYPE_ID regtype = Mtype_Of_TN(src);
00487 if ((regtype == MTYPE_U4 || regtype == MTYPE_I4)
00488 && MTYPE_byte_size(mtype) < MTYPE_byte_size(regtype))
00489 {
00490
00491
00492 val_is32 = TRUE;
00493 }
00494 else {
00495
00496 TN *tmp = Build_TN_Of_Mtype (mtype);
00497 Expand_Convert (tmp, mtype, src, Mtype_Of_TN(src), ops);
00498 src = tmp;
00499 }
00500 }
00501 Is_True (TN_is_constant(ofst), ("Expand_Store: Illegal offset TN"));
00502 if (TN_is_symbol(base)) {
00503 use_reg = FALSE;
00504 addr_is64 = (MTYPE_RegisterSize(ST_mtype(TN_var(base))) == 8);
00505 if (TN_has_value(ofst) && TN_value(ofst) == 0
00506 && TN_is_symbol(base) && Is_Simple_Type(ST_type(TN_var(base))))
00507 {
00508
00509 has_offset = FALSE;
00510 } else {
00511
00512 has_offset = TRUE;
00513 }
00514 }
00515 else {
00516
00517 use_reg = TRUE;
00518 has_offset = TRUE;
00519 addr_is64 = (TN_register_class(base) == ISA_REGISTER_CLASS_integer64);
00520 }
00521 top = Pick_Store_Instruction (mtype, val_is32, addr_is64, use_reg, has_offset);
00522 FmtAssert(top != TOP_UNDEFINED, ("no topcode"));
00523 if (has_offset)
00524 Build_OP (top, qualifier_tn, space_tn, base, ofst, src, ops);
00525 else
00526 Build_OP (top, qualifier_tn, space_tn, base, src, ops);
00527 }
00528
00529 void
00530 Expand_Lda (TN *dest, TN *src, OPS *ops)
00531 {
00532 FmtAssert(FALSE, ("NYI"));
00533 }
00534
00535 static void
00536 Expand_Lda (TYPE_ID mtype, TN *dest, TN *base, TN *ofst, VARIANT v, OPS *ops)
00537 {
00538
00539
00540
00541
00542 FmtAssert(mtype == Pointer_Mtype, ("unexpected mtype"));
00543 Is_True (TN_is_constant(ofst), ("Expand_Load: Illegal offset TN"));
00544
00545 ST *sym = TN_var(base);
00546 if (ST_sclass(sym) == SCLASS_PSTATIC) {
00547
00548
00549 char buf[80];
00550 char *p = ST_name(sym);
00551 sprintf(buf, "%d", (INT) ST_ofst(sym));
00552 p += strlen(p) - strlen(buf);
00553 if (strncmp(ST_name(sym), "__cuda_", 7) == 0
00554 && strcmp(p, buf) == 0)
00555 ;
00556 else
00557 Set_ST_name(sym, Save_Str2i ("__cuda_", ST_name(sym), (INT) ST_ofst(sym)));
00558 }
00559 if (TN_has_value(ofst) && TN_value(ofst) == 0)
00560 Build_OP (Is_Target_64bit() ? TOP_mov_u64_a : TOP_mov_u32_a,
00561 dest, base, ops);
00562 else
00563 Build_OP (Is_Target_64bit() ? TOP_mov_u64_ao : TOP_mov_u32_ao,
00564 dest, base, ofst, ops);
00565
00566 Set_TN_Memory_Space_From_Variant (dest, v, base);
00567 }
00568
00569 static OPCODE
00570 OPCODE_make_signed_op(OPERATOR op, TYPE_ID rtype, TYPE_ID desc, BOOL is_signed)
00571 {
00572 if (MTYPE_is_signed(rtype) != is_signed)
00573 rtype = MTYPE_complement(rtype);
00574 if (MTYPE_is_signed(desc) != is_signed)
00575 desc = MTYPE_complement(desc);
00576
00577 return OPCODE_make_op(op, rtype, desc);
00578 }
00579
00580 static void
00581 Expand_Composed_Load ( OPCODE op, TN *result, TN *base, TN *disp, VARIANT variant, OPS *ops)
00582 {
00583 return Expand_Load( op, result, base, disp, variant, ops );
00584 }
00585
00586 void
00587 Expand_Misaligned_Load ( OPCODE op, TN *result, TN *base, TN *disp, VARIANT variant, OPS *ops)
00588 {
00589 ErrMsgSrcpos(EC_Unaligned_Memory, current_srcpos);
00590 }
00591
00592
00593 static void
00594 Expand_Composed_Store (TYPE_ID mtype, TN *obj, TN *base, TN *disp, VARIANT variant, OPS *ops)
00595 {
00596 return Expand_Store( mtype, obj, base, disp, variant, ops );
00597 }
00598
00599 void
00600 Expand_Misaligned_Store (TYPE_ID mtype, TN *obj_tn, TN *base_tn, TN *disp_tn, VARIANT variant, OPS *ops)
00601 {
00602 ErrMsgSrcpos(EC_Unaligned_Memory, current_srcpos);
00603 }
00604
00605
00606 static TN*
00607 Get_TN_For_Predefined_Symbol (ST *sym, INT64 ofst)
00608 {
00609 INT index = 0;
00610 if (ofst == 0)
00611 index += 0;
00612 else if (ofst == 4)
00613 index += 1;
00614 else if (ofst == 8)
00615 index += 2;
00616 else
00617 FmtAssert(FALSE, ("unexpected offset %lld with symbol %s",
00618 ofst, ST_name(sym) ));
00619
00620 if (strcmp(ST_name(sym), "threadIdx") == 0) {
00621 return Tid_TN(index);
00622 }
00623 else if (strcmp(ST_name(sym), "blockDim") == 0) {
00624 return Ntid_TN(index);
00625 }
00626 else if (strcmp(ST_name(sym), "blockIdx") == 0) {
00627 return Ctaid_TN(index);
00628 }
00629 else if (strcmp(ST_name(sym), "gridDim") == 0) {
00630 return Nctaid_TN(index);
00631 }
00632 else if (strcmp(ST_name(sym), "warpSize") == 0) {
00633
00634 Set_ST_name(sym, Save_Str("WARP_SZ"));
00635 return Gen_Symbol_TN(sym, 0, 0);
00636 }
00637 else if (strcmp(ST_name(sym), "WARP_SZ") == 0) {
00638 return Gen_Symbol_TN(sym, 0, 0);
00639 }
00640 else {
00641 return NULL;
00642 }
00643 }
00644
00645 static void
00646 Exp_Ldst (
00647 OPCODE opcode,
00648 TN *tn,
00649 ST *sym,
00650 INT64 ofst,
00651 BOOL indirect_call,
00652 BOOL is_store,
00653 BOOL is_load,
00654 OPS *ops,
00655 VARIANT variant)
00656 {
00657 ST* base_sym = NULL;
00658 INT64 base_ofst = 0;
00659 TN* base_tn = NULL;
00660 TN* ofst_tn = NULL;
00661 TN* tmp_tn = NULL;
00662 const BOOL is_lda = (!is_load && !is_store);
00663 OPS newops = OPS_EMPTY;
00664 OP* op = NULL;
00665
00666 if (Trace_Exp2) {
00667 fprintf(TFile, "exp_ldst %s: ", OPCODE_name(opcode));
00668 if (tn) Print_TN(tn,FALSE);
00669 if (is_store) fprintf(TFile, " -> ");
00670 else fprintf(TFile, " <- ");
00671 if (ST_class(sym) != CLASS_CONST)
00672 fprintf(TFile, "%lld (%s)\n", ofst, ST_name(sym));
00673 else
00674 fprintf(TFile, "%lld ()\n", ofst);
00675 }
00676
00677 if (TY_is_volatile(ST_type(sym)) && ! V_volatile(variant))
00678 DevWarn("not marked volatile?");
00679
00680 Allocate_Object(sym);
00681 Set_BE_ST_referenced(sym);
00682
00683 Base_Symbol_And_Offset_For_Addressing (sym, ofst, &base_sym, &base_ofst);
00684
00685 if (base_sym == SP_Sym || base_sym == FP_Sym) {
00686
00687 base_tn = (base_sym == SP_Sym) ? SP_TN : FP_TN;
00688 if (sym == base_sym) {
00689
00690
00691 FmtAssert( false, ("stack pointer nyi: probably an unexpected call or intrinsic") );
00692
00693 } else {
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 if (CG_opt_level > 0
00707 && !ST_addr_saved(sym)
00708
00709
00710
00711
00712
00713 && !TY_has_union(ST_type(sym)) )
00714 {
00715
00716
00717 std::map<pair<UINT,INT64>,TN*>::iterator it;
00718
00719 TYPE_ID sym_mtype = Mtype_For_Type_Offset(ST_type(sym),ofst);
00720
00721
00722 TYPE_ID tn_mtype = Mtype_TransferSign(sym_mtype, Mtype_Of_TN(tn));
00723 TN *symtn;
00724 FmtAssert(!is_lda, ("lda but not addr used?"));
00725 it = st_to_tn_map.find(
00726 pair<UINT,INT64>(ST_index(sym), ofst) );
00727 if (it == st_to_tn_map.end()) {
00728
00729 symtn = Build_TN_Of_Mtype(sym_mtype);
00730 st_to_tn_map.insert(
00731 pair<pair<UINT,INT64>,TN*>(
00732 pair<UINT,INT64>(ST_index(sym), ofst),
00733 symtn) );
00734 DevWarn("map local %d,%d to tn%d", ST_index(sym), (INT)ofst, TN_number(symtn));
00735 }
00736 else {
00737 symtn = it->second;
00738 }
00739
00740
00741 if (is_store) {
00742
00743
00744
00745 if (TN_size(symtn) != TN_size(tn)) {
00746
00747 Expand_Convert (symtn, sym_mtype, tn, tn_mtype, &newops);
00748 } else {
00749 Exp_COPY (symtn, tn, &newops);
00750 }
00751 is_store = FALSE;
00752 }
00753 else if (is_load) {
00754
00755
00756
00757 if (TN_size(symtn) != TN_size(tn)) {
00758
00759 Expand_Convert (tn, tn_mtype, symtn, sym_mtype, &newops);
00760 } else {
00761 Exp_COPY (tn, symtn, &newops);
00762 }
00763 is_load = FALSE;
00764 }
00765 }
00766 else if (CGEXP_auto_as_static) {
00767
00768
00769
00770
00771
00772
00773
00774 DevWarn("convert stack variable %s to static local", ST_name(sym));
00775 Set_ST_sclass(sym, SCLASS_PSTATIC);
00776 if (ST_is_value_parm(sym)) Clear_ST_is_value_parm(sym);
00777 Set_ST_in_local_mem(sym);
00778 Set_V_local_mem(variant);
00779 Set_ST_name(sym, Save_Str2i ("__cuda_", ST_name(sym), (INT) ST_ofst(sym)));
00780 Set_ST_base(sym, sym);
00781 Set_ST_ofst(sym, 0);
00782
00783
00784
00785 Allocate_Object(sym);
00786
00787 base_tn = Gen_Symbol_TN (sym, 0, 0);
00788 ofst_tn = Gen_Literal_TN (ofst, 4);
00789 } else {
00790 FmtAssert(FALSE, ("stack variables not supported"));
00791 }
00792 }
00793
00794 } else if (ST_sclass(sym) == SCLASS_COMMON
00795 || ST_sclass(sym) == SCLASS_FSTATIC
00796 || ST_sclass(sym) == SCLASS_PSTATIC
00797 || ST_sclass(sym) == SCLASS_UGLOBAL
00798 || ST_sclass(sym) == SCLASS_DGLOBAL)
00799 {
00800 ofst_tn = Gen_Literal_TN (ofst, 4);
00801 base_tn = Gen_Symbol_TN (sym, 0, 0);
00802 if (V_memory_space(variant)) {
00803
00804 } else if (ST_in_global_mem(sym)) {
00805 Set_V_global_mem(variant);
00806 } else if (ST_in_shared_mem(sym)) {
00807 Set_V_shared_mem(variant);
00808 } else if (ST_in_local_mem(sym)) {
00809 Set_V_local_mem(variant);
00810 } else if (ST_in_constant_mem(sym)) {
00811 Set_V_const_mem(variant);
00812 } else if (ST_in_texture_mem(sym)) {
00813 if (tn != NULL) {
00814 if (Trace_Exp2) fprintf(TFile,"replace tn home with texture ldid\n");
00815
00816
00817 Set_TN_home (tn,
00818 WN_CreateLdid (opcode,ofst,sym,ST_type(sym)));
00819 Set_TN_in_texture_mem(tn);
00820 return;
00821 }
00822 else
00823 FmtAssert(FALSE, ("texture variable NYI"));
00824 }
00825 else if (ST_is_initialized(sym)
00826 && (ST_sclass(sym) == SCLASS_PSTATIC)
00827 || (ST_sclass(sym) == SCLASS_FSTATIC))
00828 {
00829
00830
00831 Set_ST_in_constant_mem(sym);
00832 Set_V_const_mem(variant);
00833 }
00834 else FmtAssert(FALSE, ("variable not in memory space"));
00835
00836 } else if (ST_sclass(sym) == SCLASS_FORMAL) {
00837
00838 ofst_tn = Gen_Literal_TN (ofst, 4);
00839 base_tn = Gen_Symbol_TN (sym, 0, 0);
00840 Set_V_param_mem(variant);
00841 } else if (ST_sclass(sym) == SCLASS_EXTERN) {
00842 base_tn = Get_TN_For_Predefined_Symbol(sym, ofst);
00843 FmtAssert (base_tn != NULL, ("unrecognized extern symbol: %s", ST_name(sym)));
00844 if (is_load) {
00845 if (TN_is_symbol(base_tn)) {
00846
00847 Expand_Mtype_Immediate (tn, base_tn, OPCODE_rtype(opcode), &newops);
00848 } else {
00849
00850
00851
00852
00853 Expand_Convert (tn, OPCODE_rtype(opcode),
00854 base_tn, MTYPE_U2, &newops);
00855 }
00856 is_load = FALSE;
00857 }
00858 else
00859 FmtAssert(FALSE, ("NYI"));
00860
00861 } else {
00862 FmtAssert(FALSE, ("NYI"));
00863 }
00864
00865 if (is_store) {
00866 if (V_align_all(variant) == 0)
00867 Expand_Store (OPCODE_desc(opcode), tn, base_tn, ofst_tn,
00868 variant, &newops);
00869 else
00870 Expand_Misaligned_Store (OPCODE_desc(opcode), tn,
00871 base_tn, ofst_tn, variant, &newops);
00872 }
00873 else if (is_load) {
00874 if (V_align_all(variant) == 0)
00875 Expand_Load (opcode, tn, base_tn, ofst_tn, variant, &newops);
00876 else
00877 Expand_Misaligned_Load (opcode, tn,
00878 base_tn, ofst_tn, variant, &newops);
00879 }
00880 else if (is_lda) {
00881 Expand_Lda (OPCODE_rtype(opcode), tn, base_tn, ofst_tn, variant, &newops);
00882
00883 }
00884
00885 FOR_ALL_OPS_OPs (&newops, op) {
00886 if (is_load && ST_is_constant(sym) && OP_load(op)) {
00887
00888
00889
00890 Set_OP_no_alias(op);
00891 }
00892 if (Trace_Exp2) {
00893 fprintf(TFile, "exp_ldst into "); Print_OP (op);
00894 }
00895 }
00896
00897 OPS_Append_Ops(ops, &newops);
00898 }
00899
00900 void Exp_Lda (
00901 TYPE_ID mtype,
00902 TN *tgt_tn,
00903 ST *sym,
00904 INT64 ofst,
00905 OPERATOR call_opr,
00906 OPS *ops)
00907 {
00908 OPCODE opcode = OPCODE_make_op(OPR_LDA, mtype, MTYPE_V);
00909 Exp_Ldst (opcode, tgt_tn, sym, ofst,
00910 (call_opr == OPR_ICALL),
00911 FALSE, FALSE, ops, V_NONE);
00912 }
00913
00914 void
00915 Exp_Load (
00916 TYPE_ID rtype,
00917 TYPE_ID desc,
00918 TN *tgt_tn,
00919 ST *sym,
00920 INT64 ofst,
00921 OPS *ops,
00922 VARIANT variant)
00923 {
00924 OPCODE opcode = OPCODE_make_op (OPR_LDID, rtype, desc);
00925 Exp_Ldst (opcode, tgt_tn, sym, ofst, FALSE, FALSE, TRUE, ops, variant);
00926 }
00927
00928 void
00929 Exp_Store (
00930 TYPE_ID mtype,
00931 TN *src_tn,
00932 ST *sym,
00933 INT64 ofst,
00934 OPS *ops,
00935 VARIANT variant)
00936 {
00937 OPCODE opcode = OPCODE_make_op(OPR_STID, MTYPE_V, mtype);
00938 Exp_Ldst (opcode, src_tn, sym, ofst, FALSE, TRUE, FALSE, ops, variant);
00939 }
00940
00941 static ISA_ENUM_CLASS_VALUE
00942 Pick_Prefetch_Hint (VARIANT variant)
00943 {
00944 UINT32 pf_flags = V_pf_flags(variant);
00945 FmtAssert(FALSE, ("NYI"));
00946 }
00947
00948 void Exp_Prefetch (TOP opc, TN* src1, TN* src2, VARIANT variant, OPS* ops)
00949 {
00950 FmtAssert(opc == TOP_UNDEFINED,
00951 ("Prefetch opcode should be selected in Exp_Prefetch"));
00952 const UINT32 pf_flags = V_pf_flags(variant);
00953 const ISA_ENUM_CLASS_VALUE pfhint = Pick_Prefetch_Hint(variant);
00954 TOP top;
00955
00956 FmtAssert(FALSE, ("NYI"));
00957 }
00958
00959
00960
00961
00962 void Exp_Extract_Bits (TYPE_ID rtype, TYPE_ID desc, UINT bit_offset, UINT bit_size,
00963 TN *tgt_tn, TN *src_tn, OPS *ops)
00964 {
00965 INT64 src_val;
00966 BOOL is_double = MTYPE_is_size_double (rtype);
00967
00968
00969
00970
00971
00972
00973 if (TN_Can_Use_Constant_Value (src_tn, desc, &src_val)
00974 && (!is_double))
00975 {
00976 if (MTYPE_is_signed (rtype))
00977 {
00978
00979
00980
00981 INT32 val = ((INT32) src_val) << (MTYPE_bit_size (rtype) - bit_offset - bit_size);
00982 val = val >> (MTYPE_bit_size (rtype) - bit_size);
00983
00984 Expand_Mtype_Immediate (tgt_tn, Gen_Literal_TN(val,4), rtype, ops);
00985 }
00986 else
00987 {
00988 UINT32 bit_mask = ((-1U) >> (MTYPE_bit_size(desc) - bit_size)) << bit_offset;
00989 UINT32 val = src_val & bit_mask;
00990
00991 val = val >> bit_offset;
00992 Expand_Mtype_Immediate (tgt_tn, Gen_Literal_TN(val,4), rtype, ops);
00993 }
00994 }
00995 else
00996 {
00997
00998 TN *tmp1_tn = Build_TN_Like (tgt_tn);
00999
01000 INT32 left_shift_amt = MTYPE_bit_size (rtype) - bit_offset - bit_size;
01001 Expand_Shift ( tmp1_tn, src_tn, Gen_Literal_TN(left_shift_amt, 4),
01002 rtype, shift_left, ops );
01003
01004 INT32 right_shift_amt = MTYPE_bit_size(rtype) - bit_size;
01005 Expand_Shift ( tgt_tn, tmp1_tn, Gen_Literal_TN(right_shift_amt, 4),
01006 rtype, MTYPE_is_signed(rtype) ? shift_aright : shift_lright, ops );
01007 }
01008 }
01009
01010
01011
01012
01013
01014 void Exp_Deposit_Bits (TYPE_ID rtype, TYPE_ID desc, UINT bit_offset, UINT bit_size,
01015 TN *tgt_tn, TN *src1_tn, TN *src2_tn, OPS *ops)
01016 {
01017
01018 FmtAssert( bit_size != 0, ("size of bit field cannot be 0"));
01019 FmtAssert( MTYPE_bit_size(desc) == 32, ("NYI: deposit_bits for non-word size"));
01020
01021 TN *tmp1_tn = Build_TN_Like(tgt_tn);
01022 TN *tmp2_tn = Build_TN_Like(tgt_tn);
01023 UINT src2_mask = (1 << bit_size) - 1;
01024 UINT src1_mask = ~(src2_mask << bit_offset);
01025 INT64 src1_val;
01026 INT64 src2_val;
01027 UINT val;
01028 if (TN_Can_Use_Constant_Value (src1_tn, desc, &src1_val)) {
01029 val = src1_val;
01030 val = val & src1_mask;
01031 tmp1_tn = Gen_Literal_TN (val, 4);
01032 }
01033 else {
01034 Expand_Binary_And( tmp1_tn, src1_tn, Gen_Literal_TN(src1_mask,4),
01035 rtype, ops);
01036 }
01037 if (TN_Can_Use_Constant_Value (src2_tn, desc, &src2_val)) {
01038 val = src2_val;
01039 val = val & src2_mask;
01040 val = val << bit_offset;
01041 tmp2_tn = Gen_Literal_TN (val, 4);
01042 }
01043 else {
01044 Expand_Binary_And( tmp2_tn, src2_tn, Gen_Literal_TN(src2_mask,4),
01045 rtype, ops);
01046 Expand_Shift( tmp2_tn, tmp2_tn, Gen_Literal_TN(bit_offset, 4),
01047 rtype, shift_left, ops);
01048 }
01049 if (TN_is_constant(tmp1_tn) && TN_has_value(tmp1_tn)
01050 && TN_is_constant(tmp2_tn) && TN_has_value(tmp2_tn))
01051 {
01052
01053 src1_val = TN_value(tmp1_tn);
01054 src2_val = TN_value(tmp2_tn);
01055 src1_val = src1_val | src2_val;
01056 val = src1_val;
01057 Expand_Mtype_Immediate (tgt_tn, Gen_Literal_TN(val,4), rtype, ops);
01058 }
01059 else {
01060 Expand_Binary_Or( tgt_tn, tmp1_tn, tmp2_tn, rtype, ops);
01061 }
01062 }
01063
01064 void
01065 Expand_Lda_Label (TN *dest, TN *lab, OPS *ops)
01066 {
01067 Expand_Mtype_Immediate(dest, lab, Mtype_Of_TN(dest), ops);
01068 }