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
00031
00032
00033
00034
00035
00036
00037 #include <elf_stuff.h>
00038 #include <vector>
00039 #include "defs.h"
00040 #include "em_elf.h"
00041 #include "erglob.h"
00042 #include "ercg.h"
00043 #include "tracing.h"
00044 #include "config.h"
00045 #include "config_targ_opt.h"
00046 #include "config_debug.h"
00047 #include "xstats.h"
00048 #include "topcode.h"
00049 #include "tn.h"
00050 #include "cg_flags.h"
00051 #include "targ_isa_lits.h"
00052 #include "op.h"
00053 #include "stblock.h"
00054 #include "data_layout.h"
00055 #include "strtab.h"
00056 #include "symtab.h"
00057 #include "cg.h"
00058 #include "cgexp.h"
00059 #include "cgexp_internals.h"
00060 #include "whirl2ops.h"
00061 #include "tls.h"
00062 #include "targ_sim_core.h"
00063
00064 void
00065 Expand_Lda (TN *dest, TN *src, OPS *ops)
00066 {
00067 FmtAssert(FALSE, ("NYI: Expand_Lda"));
00068 }
00069
00070 static ISA_ENUM_CLASS_VALUE
00071 Get_ldhint (const char *s, ISA_ENUM_CLASS_VALUE default_val)
00072 {
00073 ISA_ENUM_CLASS_VALUE ldhint = default_val;
00074 if (s) {
00075 if (strcmp(s, "nt1") == 0) {
00076 ldhint = ECV_ldhint_nt1;
00077 } else if (strcmp(s, "nta") == 0) {
00078 ldhint = ECV_ldhint_nta;
00079 } else if (strcmp(s, "none") == 0) {
00080 ldhint = ECV_ldhint;
00081 } else {
00082 fprintf(stderr, "bad ldhint specification: '%s';"
00083 "must be 'nt1', 'nta' or 'none'\n",
00084 s);
00085 }
00086 }
00087 return ldhint;
00088 }
00089
00090 static ISA_ENUM_CLASS_VALUE
00091 Pick_Load_Hint (VARIANT variant)
00092 {
00093 UINT32 pf_flags = V_pf_flags(variant);
00094 static ISA_ENUM_CLASS_VALUE ldhint_L1;
00095 static ISA_ENUM_CLASS_VALUE ldhint_L2;
00096 static BOOL hints_inited = FALSE;
00097 if (!hints_inited) {
00098 ldhint_L1 = Get_ldhint(CGEXP_ldhint_L1, ECV_ldhint);
00099 ldhint_L2 = Get_ldhint(CGEXP_ldhint_L2, ECV_ldhint);
00100 hints_inited = TRUE;
00101 }
00102
00103 ISA_ENUM_CLASS_VALUE ldhint;
00104 if (PF_GET_STRIDE_1L(pf_flags)) {
00105 ldhint = ldhint_L1;
00106 } else if (PF_GET_STRIDE_2L(pf_flags)) {
00107 ldhint = ldhint_L2;
00108 } else {
00109 ldhint = ECV_ldhint;
00110 }
00111
00112 return ldhint;
00113 }
00114
00115 static ISA_ENUM_CLASS_VALUE
00116 Pick_Load_Type (VARIANT variant, TYPE_ID mtype)
00117 {
00118 if (MTYPE_is_float(mtype)) {
00119 return ECV_fldtype;
00120 } else if (V_volatile(variant)) {
00121 return ECV_ldtype_acq;
00122 } else {
00123 return ECV_ldtype;
00124 }
00125 }
00126
00127 static TOP
00128 Pick_Load_Instruction (TYPE_ID rtype, TYPE_ID desc)
00129 {
00130 switch (desc) {
00131 case MTYPE_I1: case MTYPE_U1: return TOP_ld1;
00132 case MTYPE_I2: case MTYPE_U2: return TOP_ld2;
00133 case MTYPE_I4: case MTYPE_U4: return TOP_ld4;
00134 case MTYPE_I8: case MTYPE_U8: return TOP_ld8;
00135 case MTYPE_F4: return TOP_ldfs;
00136 case MTYPE_F8: return TOP_ldfd;
00137 case MTYPE_F10: return TOP_ldfe;
00138 case MTYPE_F16: return TOP_ldf_fill;
00139
00140 case MTYPE_V:
00141 if (rtype != MTYPE_V) {
00142
00143 return Pick_Load_Instruction(rtype,rtype);
00144 }
00145
00146
00147 default:
00148 FmtAssert(FALSE, ("NYI: Pick_Load_Instruction mtype"));
00149
00150 }
00151 }
00152
00153 void
00154 Expand_Load (OPCODE opcode, TN *result, TN *base, TN *ofst,
00155 VARIANT variant, OPS *ops)
00156 {
00157 TYPE_ID mtype = OPCODE_desc(opcode);
00158 TOP top = Pick_Load_Instruction (OPCODE_rtype(opcode), mtype);
00159 ISA_ENUM_CLASS_VALUE ldhint = Pick_Load_Hint (variant);
00160 Is_True (TN_is_constant(ofst), ("Illegal load offset TN"));
00161
00162 if (!TN_has_value(ofst) || (TN_value(ofst) != 0)) {
00163
00164 TN *tmp = Build_TN_Like (base);
00165 Expand_Add (tmp, ofst, base, Pointer_Mtype, ops);
00166 base = tmp;
00167 }
00168 if (top == TOP_ldf_fill) {
00169 Build_OP (top, result, True_TN, Gen_Enum_TN(ldhint), base, ops);
00170 } else {
00171 ISA_ENUM_CLASS_VALUE ldtype = Pick_Load_Type (variant, mtype);
00172 Build_OP (top, result, True_TN,
00173 Gen_Enum_TN(ldtype), Gen_Enum_TN(ldhint),
00174 base, ops);
00175 }
00176 }
00177
00178 static ISA_ENUM_CLASS_VALUE
00179 Get_sthint (const char *s, ISA_ENUM_CLASS_VALUE default_val)
00180 {
00181 ISA_ENUM_CLASS_VALUE sthint = default_val;
00182 if (s) {
00183 if (strcmp(s, "nta") == 0) {
00184 sthint = ECV_sthint_nta;
00185 } else if (strcmp(s, "none") == 0) {
00186 sthint = ECV_sthint;
00187 } else {
00188 fprintf(stderr, "bad sthint specification: '%s';"
00189 "must be 'nta' or 'none'\n",
00190 s);
00191 }
00192 }
00193 return sthint;
00194 }
00195
00196 static ISA_ENUM_CLASS_VALUE
00197 Pick_Store_Hint (VARIANT variant)
00198 {
00199 UINT32 pf_flags = V_pf_flags(variant);
00200 static ISA_ENUM_CLASS_VALUE sthint_L1;
00201 static ISA_ENUM_CLASS_VALUE sthint_L2;
00202 static BOOL hints_inited = FALSE;
00203 if (!hints_inited) {
00204 sthint_L1 = Get_sthint(CGEXP_sthint_L1, ECV_sthint);
00205 sthint_L2 = Get_sthint(CGEXP_sthint_L2, ECV_sthint);
00206 hints_inited = TRUE;
00207 }
00208
00209 ISA_ENUM_CLASS_VALUE sthint;
00210 if (PF_GET_STRIDE_1L(pf_flags)) {
00211 sthint = sthint_L1;
00212 } else if (PF_GET_STRIDE_2L(pf_flags)) {
00213 sthint = sthint_L2;
00214 } else {
00215 sthint = ECV_sthint;
00216 }
00217
00218 return sthint;
00219 }
00220
00221 static ISA_ENUM_CLASS_VALUE
00222 Pick_Store_Type (VARIANT variant)
00223 {
00224 return V_volatile(variant) ? ECV_sttype_rel : ECV_sttype;
00225 }
00226
00227 static TOP
00228 Pick_Store_Instruction (TYPE_ID mtype)
00229 {
00230 switch (mtype) {
00231 case MTYPE_I1: case MTYPE_U1: return TOP_st1;
00232 case MTYPE_I2: case MTYPE_U2: return TOP_st2;
00233 case MTYPE_I4: case MTYPE_U4: return TOP_st4;
00234 case MTYPE_I8: case MTYPE_U8: return TOP_st8;
00235 case MTYPE_F4: return TOP_stfs;
00236 case MTYPE_F8: return TOP_stfd;
00237 case MTYPE_F10: return TOP_stfe;
00238 case MTYPE_F16: return TOP_stf_spill;
00239 default:
00240 FmtAssert(FALSE, ("NYI: Pick_Store_Instruction mtype"));
00241
00242 }
00243 }
00244
00245 void
00246 Expand_Store (TYPE_ID mtype, TN *src, TN *base, TN *ofst,
00247 VARIANT variant, OPS *ops)
00248 {
00249 TOP top = Pick_Store_Instruction (mtype);
00250 ISA_ENUM_CLASS_VALUE sthint = Pick_Store_Hint (variant);
00251 Is_True (TN_is_constant(ofst), ("Illegal load offset TN"));
00252
00253 if (!TN_has_value(ofst) || (TN_value(ofst) != 0)) {
00254
00255 TN *tmp = Build_TN_Like (base);
00256 Expand_Add (tmp, ofst, base, Pointer_Mtype, ops);
00257 base = tmp;
00258 }
00259 if (MTYPE_is_float(mtype)) {
00260 Build_OP (top, True_TN, Gen_Enum_TN(sthint), base, src, ops);
00261 } else {
00262 ISA_ENUM_CLASS_VALUE sttype = Pick_Store_Type (variant);
00263 Build_OP (top, True_TN, Gen_Enum_TN(sttype), Gen_Enum_TN(sthint),
00264 base, src, ops);
00265 }
00266 }
00267
00268 static TYPE_ID
00269 Composed_Align_Type(TYPE_ID mtype, VARIANT variant, INT32 *alignment, INT32 *partials)
00270 {
00271 *alignment = MIN(MTYPE_alignment(mtype), 1U << V_alignment(variant));
00272 *partials = MTYPE_alignment(mtype) / *alignment;
00273 return Mtype_AlignmentClass( *alignment, MTYPE_CLASS_UNSIGNED_INTEGER);
00274 }
00275
00276 static OPCODE
00277 OPCODE_make_signed_op(OPERATOR op, TYPE_ID rtype, TYPE_ID desc, BOOL is_signed)
00278 {
00279 if (MTYPE_is_signed(rtype) != is_signed)
00280 rtype = MTYPE_complement(rtype);
00281 if (MTYPE_is_signed(desc) != is_signed)
00282 desc = MTYPE_complement(desc);
00283
00284 return OPCODE_make_op(op, rtype, desc);
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 static void
00301 Adjust_Addr_TNs (
00302 TOP opcode,
00303 TN **base_tn,
00304 TN **disp_tn,
00305 INT16 disp,
00306 OPS *ops)
00307 {
00308
00309 if ( Potential_Immediate_TN_Expr (opcode, *disp_tn, disp) )
00310 {
00311 if ( TN_has_value(*disp_tn) ) {
00312 *disp_tn = Gen_Literal_TN ( TN_value(*disp_tn) + disp, 4 );
00313 } else {
00314 *disp_tn = Gen_Symbol_TN ( TN_var(*disp_tn),
00315 TN_offset(*disp_tn) + disp, 0);
00316 }
00317 } else {
00318 TN *tmp = Build_TN_Of_Mtype (Pointer_Mtype);
00319
00320
00321 Expand_Add (tmp, *disp_tn, *base_tn, Pointer_Mtype, ops);
00322 *base_tn = tmp;
00323 *disp_tn = Gen_Literal_TN (disp, 4);
00324 }
00325 }
00326
00327 static void
00328 Expand_Composed_Load ( OPCODE op, TN *result, TN *base, TN *disp, VARIANT variant, OPS *ops)
00329 {
00330 TYPE_ID rtype;
00331 TYPE_ID desc, new_desc;
00332 TOP top;
00333 INT32 alignment, nLoads, i;
00334 OPCODE new_opcode;
00335 TN *tmpV[8];
00336
00337 rtype = OPCODE_rtype(op);
00338 desc = OPCODE_desc(op);
00339 new_desc = Composed_Align_Type(desc, variant, &alignment, &nLoads);
00340
00341 if (nLoads == 1) {
00342 Expand_Load(op, result, base, disp, variant, ops);
00343 return;
00344 }
00345
00346 new_opcode = OPCODE_make_signed_op(OPR_LDID, rtype, new_desc, FALSE);
00347 top = Pick_Load_Instruction (rtype, new_desc);
00348
00349
00350
00351
00352
00353 INT endian_xor = (Target_Byte_Sex == BIG_ENDIAN) ? (nLoads-1) : 0;
00354 for (i=0; i < nLoads; i++)
00355 {
00356 INT idx = i ^ endian_xor;
00357 tmpV[idx] = Build_TN_Of_Mtype(rtype);
00358 Expand_Load ( new_opcode, tmpV[idx], base, disp, variant, ops);
00359 if (i < nLoads-1) Adjust_Addr_TNs ( top, &base, &disp, alignment, ops);
00360 }
00361
00362
00363
00364
00365
00366
00367
00368 INT nLoadBits = alignment * 8;
00369 if (nLoadBits <= 16) {
00370 TN *tmp0 = tmpV[0];
00371 for (i=1; i < (nLoads-1); i++)
00372 {
00373 TN *tmp= Build_TN_Of_Mtype(rtype);
00374 Build_OP(TOP_dep, tmp, True_TN, tmpV[i], tmp0,
00375 Gen_Literal_TN(i*nLoadBits, 4), Gen_Literal_TN(nLoadBits, 4), ops);
00376 tmp0 = tmp;
00377 }
00378 Build_OP(TOP_dep, result, True_TN, tmpV[i], tmp0,
00379 Gen_Literal_TN(i*nLoadBits, 4), Gen_Literal_TN(nLoadBits, 4), ops);
00380 } else {
00381 FmtAssert(nLoadBits == 32 && nLoads == 2,
00382 ("%s: unexpected composition", __func__));
00383 Build_OP(TOP_mix4_r, result, True_TN, tmpV[1], tmpV[0], ops);
00384 }
00385 }
00386
00387 void
00388 Expand_Misaligned_Load ( OPCODE op, TN *result, TN *base, TN *disp, VARIANT variant, OPS *ops)
00389 {
00390 TYPE_ID rtype = OPCODE_rtype(op);
00391
00392 Is_True(TN_is_constant(disp), ("%s() called with variable disp", __func__));
00393
00394 if (MTYPE_is_float(rtype))
00395 {
00396 switch (rtype) {
00397 case MTYPE_F4:
00398 {
00399 TN *tmp = Build_TN_Of_Mtype(MTYPE_I4);
00400 Expand_Composed_Load(OPC_I4I4LDID, tmp, base, disp, variant, ops);
00401 Build_OP(TOP_setf_s, result, True_TN, tmp, ops);
00402 break;
00403 }
00404 case MTYPE_F8:
00405 {
00406 TN *tmp = Build_TN_Of_Mtype(MTYPE_I8);
00407 Expand_Composed_Load(OPC_I8I8LDID, tmp, base, disp, variant, ops);
00408 Build_OP(TOP_setf_d, result, True_TN, tmp, ops);
00409 break;
00410 }
00411 case MTYPE_F10:
00412 {
00413 TN *TRs = Build_TN_Of_Mtype(MTYPE_U8);
00414 TN *TRx = Build_TN_Of_Mtype(MTYPE_U8);
00415
00416 TN *TRd = Gen_Adjusted_TN (disp, 8);
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 if (Target_Byte_Sex == BIG_ENDIAN) {
00441 TN *TR1 = Build_TN_Of_Mtype(MTYPE_U8);
00442 TN *TR2 = Build_TN_Of_Mtype(MTYPE_U8);
00443 TN *TR3 = Build_TN_Of_Mtype(MTYPE_U8);
00444 TN *TR4 = Build_TN_Of_Mtype(MTYPE_U8);
00445 TN *TR5 = Build_TN_Of_Mtype(MTYPE_U8);
00446
00447 Expand_Composed_Load (OPC_U8U8LDID, TR1, base, disp, variant, ops);
00448 Expand_Composed_Load (OPC_U8U2LDID, TR2, base, TRd, variant, ops);
00449 Build_OP(TOP_dep_z, TR3, True_TN, TR1, Gen_Literal_TN(16, 1),
00450 Gen_Literal_TN(48, 1), ops);
00451 Build_OP(TOP_dep, TRs, True_TN, TR2, TR3, Gen_Literal_TN(0, 1),
00452 Gen_Literal_TN(16, 1), ops);
00453 Build_OP(TOP_extr_u, TR4, True_TN, TR1, Gen_Literal_TN(62, 1),
00454 Gen_Literal_TN(2, 1), ops);
00455 Build_OP(TOP_extr_u, TR5, True_TN, TR1, Gen_Literal_TN(48, 1),
00456 Gen_Literal_TN(14, 1), ops);
00457 Build_OP(TOP_dep, TRx, True_TN, TR4, TR5, Gen_Literal_TN(16, 1),
00458 Gen_Literal_TN(2, 1), ops);
00459 } else {
00460 TN *TR1 = Build_TN_Of_Mtype(MTYPE_U8);
00461 TN *TR2 = Build_TN_Of_Mtype(MTYPE_U8);
00462 TN *TR3 = Build_TN_Of_Mtype(MTYPE_U8);
00463
00464 Expand_Composed_Load (OPC_U8U8LDID, TRs, base, disp, variant, ops);
00465 Expand_Composed_Load (OPC_U8U2LDID, TR1, base, TRd, variant, ops);
00466 Build_OP(TOP_extr_u, TR2, True_TN, TR1, Gen_Literal_TN(14, 1),
00467 Gen_Literal_TN(2, 1), ops);
00468 Build_OP(TOP_dep_z, TR3, True_TN, TR1, Gen_Literal_TN(0, 1),
00469 Gen_Literal_TN(14, 1), ops);
00470 Build_OP(TOP_dep, TRx, True_TN, TR2, TR3, Gen_Literal_TN(16, 1),
00471 Gen_Literal_TN(2, 1), ops);
00472 }
00473
00474 TN *TRa = Build_TN_Of_Mtype(MTYPE_U8);
00475 TN *TRb = Build_TN_Of_Mtype(MTYPE_U8);
00476 TN *TFs = Build_TN_Of_Mtype(MTYPE_F10);
00477 TN *TFx = Build_TN_Of_Mtype(MTYPE_F10);
00478
00479 Build_OP(TOP_adds, TRa, True_TN, Gen_Literal_TN(3, 1), Zero_TN, ops);
00480 Build_OP(TOP_dep, TRb, True_TN, TRa, TRx, Gen_Literal_TN(14, 1),
00481 Gen_Literal_TN(2, 1), ops);
00482 Build_OP(TOP_setf_sig, TFs, True_TN, TRs, ops);
00483 Build_OP(TOP_setf_exp, TFx, True_TN, TRb, ops);
00484 Build_OP(TOP_fmerge_se, result, True_TN, TFx, TFs, ops);
00485 break;
00486 }
00487 default:
00488 FmtAssert(FALSE, ("%s() doesn't handle %s", __func__,
00489 MTYPE_name(rtype)));
00490
00491 }
00492 Reset_TN_is_fpu_int(result);
00493 }
00494 else
00495 Expand_Composed_Load(op, result, base, disp, variant, ops);
00496 }
00497
00498
00499 static void
00500 Expand_Composed_Store (TYPE_ID mtype, TN *obj, TN *base, TN *disp, VARIANT variant, OPS *ops)
00501 {
00502 TOP top;
00503 INT32 alignment, nStores;
00504 TYPE_ID new_desc;
00505
00506 new_desc = Composed_Align_Type(mtype, variant, &alignment, &nStores);
00507 top = Pick_Store_Instruction (new_desc);
00508
00509 if (nStores == 1) {
00510 Expand_Store(mtype, obj, base, disp, variant, ops);
00511 return;
00512 }
00513
00514 if (Target_Byte_Sex == BIG_ENDIAN)
00515 Adjust_Addr_TNs ( top, &base, &disp, MTYPE_alignment(mtype)-alignment, ops);
00516 Expand_Store ( new_desc, obj, base, disp, variant, ops);
00517
00518 while(--nStores >0)
00519 {
00520 TN *tmp = Build_TN_Of_Mtype(mtype);
00521 Expand_Shift( tmp, obj, Gen_Literal_TN(alignment*8, 4), mtype, shift_lright, ops);
00522 obj = tmp;
00523
00524 if (Target_Byte_Sex == BIG_ENDIAN)
00525 Adjust_Addr_TNs ( top, &base, &disp, -alignment, ops);
00526 else Adjust_Addr_TNs ( top, &base, &disp, alignment, ops);
00527
00528 Expand_Store ( new_desc, obj, base, disp, variant, ops);
00529 }
00530 }
00531
00532 void
00533 Expand_Misaligned_Store (TYPE_ID mtype, TN *obj, TN *base, TN *disp, VARIANT variant, OPS *ops)
00534 {
00535
00536 Is_True(TN_is_constant(disp), ("%s() called with variable disp", __func__));
00537
00538 if (MTYPE_is_float(mtype)) {
00539 switch (mtype) {
00540 case MTYPE_F4:
00541 {
00542 TN *tmp = Build_TN_Of_Mtype(MTYPE_U4);
00543 Build_OP(TOP_getf_s, tmp, True_TN, obj, ops);
00544 Expand_Composed_Store(MTYPE_U4, tmp, base, disp, variant, ops);
00545 break;
00546 }
00547 case MTYPE_F8:
00548 {
00549 TN *tmp = Build_TN_Of_Mtype(MTYPE_U8);
00550 Build_OP(TOP_getf_d, tmp, True_TN, obj, ops);
00551 Expand_Composed_Store(MTYPE_U8, tmp, base, disp, variant, ops);
00552 break;
00553 }
00554 case MTYPE_F10:
00555 {
00556 TN *TRs = Build_TN_Of_Mtype(MTYPE_U8);
00557 TN *TRx = Build_TN_Of_Mtype(MTYPE_U8);
00558 TN *TRy = Build_TN_Of_Mtype(MTYPE_U8);
00559 TN *TRd = Gen_Literal_TN(8 + TN_value(disp), 8);
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 Build_OP(TOP_getf_sig, TRs, True_TN, obj, ops);
00578 Build_OP(TOP_getf_exp, TRx, True_TN, obj, ops);
00579 Build_OP(TOP_extr_u, TRy, True_TN, TRx, Gen_Literal_TN(16, 1),
00580 Gen_Literal_TN(2, 1), ops);
00581
00582 if (Target_Byte_Sex == BIG_ENDIAN) {
00583 TN *TR1 = Build_TN_Of_Mtype(MTYPE_U8);
00584 TN *TR2 = Build_TN_Of_Mtype(MTYPE_U8);
00585 TN *TR3 = Build_TN_Of_Mtype(MTYPE_U8);
00586
00587 Expand_Composed_Store(MTYPE_U2, TRs, base, TRd, variant, ops);
00588 Build_OP(TOP_extr_u, TR1, True_TN, TRs, Gen_Literal_TN(16, 1),
00589 Gen_Literal_TN(48, 1), ops);
00590 Build_OP(TOP_dep, TR2, True_TN, TRx, TR1, Gen_Literal_TN(48, 1),
00591 Gen_Literal_TN(14, 1), ops);
00592 Build_OP(TOP_dep, TR3, True_TN, TRy, TR2, Gen_Literal_TN(62, 1),
00593 Gen_Literal_TN(2, 1), ops);
00594 Expand_Composed_Store(MTYPE_U8, TR3, base, disp, variant, ops);
00595 } else {
00596 TN *TR1 = Build_TN_Of_Mtype(MTYPE_U8);
00597
00598 Expand_Composed_Store(MTYPE_U8, TRs, base, disp, variant, ops);
00599 Build_OP(TOP_dep, TR1, True_TN, TRy, TRx, Gen_Literal_TN(14, 1),
00600 Gen_Literal_TN(2, 1), ops);
00601 Expand_Composed_Store(MTYPE_U2, TR1, base, TRd, variant, ops);
00602 }
00603 break;
00604 }
00605 default:
00606 FmtAssert(FALSE, ("%s() doesn't handle %s", __func__,
00607 MTYPE_name(mtype)));
00608
00609 }
00610 }
00611 else
00612 Expand_Composed_Store(mtype, obj, base, disp, variant, ops);
00613 }
00614
00615 static void
00616 Exp_Ldst (
00617 OPCODE opcode,
00618 TN *tn,
00619 ST *sym,
00620 INT64 ofst,
00621 BOOL indirect_call,
00622 BOOL is_store,
00623 BOOL is_load,
00624 OPS *ops,
00625 VARIANT variant)
00626 {
00627 ST *base_sym;
00628 INT64 base_ofst;
00629 TN *base_tn;
00630 TN *ofst_tn;
00631 BOOL is_lda = (!is_load && !is_store);
00632 OPS newops;
00633 OP *op;
00634 OPS_Init(&newops);
00635
00636 if (Trace_Exp2) {
00637 fprintf(TFile, "exp_ldst %s: ", OPCODE_name(opcode));
00638 if (tn) Print_TN(tn,FALSE);
00639 if (is_store) fprintf(TFile, " -> ");
00640 else fprintf(TFile, " <- ");
00641 fprintf(TFile, "%lld (%s)\n", ofst, ST_name(sym));
00642 }
00643
00644 Allocate_Object(sym);
00645
00646 Base_Symbol_And_Offset_For_Addressing (sym, ofst, &base_sym, &base_ofst);
00647
00648 if (ST_on_stack(sym)) {
00649
00650
00651
00652 base_tn = (base_sym == FP_Sym) ? FP_TN : SP_TN;
00653 if (sym == base_sym) {
00654
00655
00656 ofst_tn = Gen_Literal_TN (base_ofst, Pointer_Size);
00657 }
00658 else {
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 ofst_tn = Gen_Symbol_TN (sym, ofst, 0);
00669 }
00670 }
00671 else if ((ST_class(base_sym) == CLASS_BLOCK || ST_class(base_sym)==CLASS_VAR)
00672 && ST_gprel(base_sym))
00673 {
00674
00675 PU_References_GP = TRUE;
00676 if (ISA_LC_Value_In_Class(base_ofst, LC_i22)) {
00677 base_tn = GP_TN;
00678 ofst_tn = Gen_Symbol_TN (sym, ofst, TN_RELOC_IA_GPREL22);
00679 }
00680 else {
00681 FmtAssert(FALSE, ("gp-relative offset doesn't fit in 22 bits"));
00682 }
00683 }
00684 else if (ST_is_tls(sym))
00685 {
00686
00687 TN *tmp1, *tmp2;
00688
00689 TN *out0, *out1, *ret0, *tgt_tn;
00690 CALLINFO *call_info;
00691 RETURN_INFO return_info;
00692 WN* call_wn;
00693
00694 PLOC ploc;
00695
00696 TLS_init();
00697 switch( TLS_model) {
00698 case TLS_MODEL_GLOBAL_DYNAMIC:
00699
00700
00701
00702
00703
00704
00705
00706
00707 case TLS_MODEL_LOCAL_DYNAMIC:
00708
00709
00710
00711
00712
00713
00714 Allocate_Object( TLS_get_addr_st );
00715 Is_True( (TLS_get_addr_ty_idx != 0 && TLS_get_addr_st != NULL),
00716 ("TY or ST for __tls_get_addr is NULL."));
00717
00718 ploc = Setup_Output_Parameter_Locations( ST_pu_type(TLS_get_addr_st) );
00719 ploc = Get_Output_Parameter_Location( MTYPE_To_TY(Pointer_Mtype) );
00720 out0 = PREG_To_TN (MTYPE_To_PREG(Pointer_Mtype), PLOC_reg(ploc));
00721 ploc = Get_Output_Parameter_Location( MTYPE_To_TY(Pointer_Mtype) );
00722 out1 = PREG_To_TN (MTYPE_To_PREG(Pointer_Mtype), PLOC_reg(ploc));
00723 return_info = Get_Return_Info(Be_Type_Tbl(Pointer_Mtype), Use_Simulated);
00724 ret0 = PREG_To_TN (MTYPE_To_PREG(Pointer_Mtype), RETURN_INFO_preg(return_info, 0));
00725
00726 tmp1 = Build_TN_Of_Mtype(Pointer_Mtype);
00727 Expand_Add(tmp1,
00728 Gen_Symbol_TN(sym, 0, TN_RELOC_IA_LTOFF_DTPMOD22),
00729 GP_TN, Pointer_Mtype, &newops);
00730 if ( TLS_model == TLS_MODEL_GLOBAL_DYNAMIC ) {
00731 tmp2 = Build_TN_Of_Mtype(Pointer_Mtype);
00732 Expand_Add(tmp2,
00733 Gen_Symbol_TN(sym, 0, TN_RELOC_IA_LTOFF_DTPREL22),
00734 GP_TN, Pointer_Mtype, &newops);
00735 Expand_Load(OPCODE_make_signed_op(OPR_LDID,
00736 Pointer_Mtype, Pointer_Mtype, FALSE),
00737 out1, tmp2, Gen_Literal_TN(0, 4), variant, &newops);
00738 Set_OP_no_alias(OPS_last(&newops));
00739 }
00740 else {
00741 Expand_Add(out1,
00742 Gen_Symbol_TN(sym, 0, TN_RELOC_IA_DTPREL22),
00743 Zero_TN, Pointer_Mtype, &newops);
00744 }
00745 Expand_Load(OPCODE_make_signed_op(OPR_LDID,
00746 Pointer_Mtype, Pointer_Mtype, FALSE),
00747 out0, tmp1, Gen_Literal_TN(0, 4), variant, &newops);
00748 Set_OP_no_alias(OPS_last(&newops));
00749
00750 call_wn = WN_Create(OPR_CALL, Pointer_Mtype, MTYPE_V, 0);
00751 WN_st_idx(call_wn) = ST_st_idx(TLS_get_addr_st);
00752 Expand_New_Call_To_OPs(call_wn, OPR_CALL, &newops);
00753
00754 base_tn = Build_TN_Of_Mtype(Pointer_Mtype);
00755 Exp_COPY(base_tn, ret0, &newops);
00756 ofst_tn = Gen_Literal_TN(ofst, 4);
00757 break;
00758 case TLS_MODEL_INITIAL_EXEC:
00759
00760
00761
00762 tmp1 = Build_TN_Of_Mtype(Pointer_Mtype);
00763 Expand_Add(tmp1,
00764 Gen_Symbol_TN(sym, 0, TN_RELOC_IA_LTOFF_TPREL22),
00765 GP_TN, Pointer_Mtype, &newops);
00766 tmp2 = Build_TN_Of_Mtype(Pointer_Mtype);
00767 Expand_Load(OPCODE_make_signed_op(OPR_LDID,
00768 Pointer_Mtype, Pointer_Mtype, FALSE),
00769 tmp2, tmp1, Gen_Literal_TN(0, 4), variant, &newops);
00770 Set_OP_no_alias(OPS_last(&newops));
00771 base_tn = Build_TN_Of_Mtype(Pointer_Mtype);
00772 Expand_Add(base_tn,
00773 tmp2, TP_TN, Pointer_Mtype, &newops);
00774 ofst_tn = Gen_Literal_TN(ofst, 4);
00775 break;
00776 case TLS_MODEL_LOCAL_EXEC:
00777 base_tn = TP_TN;
00778 ofst_tn = Gen_Symbol_TN(sym, ofst, TN_RELOC_IA_TPREL22);
00779 break;
00780 default:
00781 FmtAssert(FALSE, ("Wrong TLS_MODEL"));
00782 }
00783 }
00784 else if (Guaranteed_Small_GOT) {
00785
00786 TN *tmp1 = Build_TN_Of_Mtype (Pointer_Mtype);
00787 TN *tmp2 = Build_TN_Of_Mtype (Pointer_Mtype);
00788 base_tn = GP_TN;
00789
00790 if (ST_class(sym) == CLASS_FUNC && ! Get_Trace (TP_CGEXP, 256) ) {
00791 Expand_Add (tmp1,
00792 Gen_Symbol_TN (base_sym, 0, TN_RELOC_IA_LTOFF_FPTR),
00793 base_tn, Pointer_Mtype, &newops);
00794 }
00795 else {
00796 Expand_Add (tmp1,
00797 Gen_Symbol_TN (base_sym, 0,
00798 CG_Enable_Ldxmov_Support ?
00799 TN_RELOC_IA_LTOFF22X : TN_RELOC_IA_LTOFF22X),
00800 base_tn, Pointer_Mtype, &newops);
00801 }
00802
00803 if (is_lda && base_ofst == 0) {
00804
00805
00806 tmp2 = tn;
00807 is_lda = FALSE;
00808 }
00809
00810 Expand_Load (OPCODE_make_signed_op(OPR_LDID,
00811 Pointer_Mtype, Pointer_Mtype, FALSE),
00812 tmp2, tmp1, Gen_Literal_TN (0, 4), variant, &newops);
00813
00814
00815 if (ST_class(sym) != CLASS_FUNC && CG_Enable_Ldxmov_Support) {
00816 OP_MAP_Set (OP_Ld_GOT_2_Sym_Map, OPS_last(&newops), base_sym);
00817 Set_OP_load_GOT_entry (OPS_last(&newops));
00818 }
00819 Set_OP_no_alias(OPS_last(&newops));
00820 base_tn = tmp2;
00821
00822 ofst_tn = Gen_Literal_TN_Ex(base_ofst);
00823 }
00824 else {
00825 FmtAssert(FALSE, ("NYI: Exp_Ldst"));
00826 }
00827
00828 if (is_store) {
00829 if (V_align_all(variant) == 0)
00830 Expand_Store (OPCODE_desc(opcode), tn, base_tn, ofst_tn,
00831 variant, &newops);
00832 else
00833 Expand_Misaligned_Store (OPCODE_desc(opcode), tn,
00834 base_tn, ofst_tn, variant, &newops);
00835 }
00836 else if (is_load) {
00837 if (V_align_all(variant) == 0)
00838 Expand_Load (opcode, tn, base_tn, ofst_tn, variant, &newops);
00839 else
00840 Expand_Misaligned_Load (opcode, tn,
00841 base_tn, ofst_tn, variant, &newops);
00842 }
00843 else if (is_lda) {
00844 Expand_Add (tn, ofst_tn, base_tn, OPCODE_rtype(opcode), &newops);
00845 }
00846
00847 FOR_ALL_OPS_OPs (&newops, op) {
00848
00849 if (OP_load(op)){
00850 Set_OP_safe_load(op);
00851 }
00852
00853 if (is_load && OP_load(op)) {
00854
00855
00856
00857 if (ST_is_constant(sym))
00858 Set_OP_no_alias(op);
00859
00860 }
00861 if (Trace_Exp2) {
00862 fprintf(TFile, "exp_ldst into "); Print_OP (op);
00863 }
00864 }
00865
00866 OPS_Append_Ops(ops, &newops);
00867 }
00868
00869 void Exp_Lda (
00870 TYPE_ID mtype,
00871 TN *tgt_tn,
00872 ST *sym,
00873 INT64 ofst,
00874 OPERATOR call_opr,
00875 OPS *ops)
00876 {
00877 OPCODE opcode = OPCODE_make_op(OPR_LDA, mtype, MTYPE_V);
00878 Exp_Ldst (opcode, tgt_tn, sym, ofst,
00879 (call_opr == OPR_ICALL),
00880 FALSE, FALSE, ops, V_NONE);
00881 }
00882
00883 void
00884 Exp_Load (
00885 TYPE_ID rtype,
00886 TYPE_ID desc,
00887 TN *tgt_tn,
00888 ST *sym,
00889 INT64 ofst,
00890 OPS *ops,
00891 VARIANT variant)
00892 {
00893 OPCODE opcode = OPCODE_make_op (OPR_LDID, rtype, desc);
00894 Exp_Ldst (opcode, tgt_tn, sym, ofst, FALSE, FALSE, TRUE, ops, variant);
00895 }
00896
00897 void
00898 Exp_Store (
00899 TYPE_ID mtype,
00900 TN *src_tn,
00901 ST *sym,
00902 INT64 ofst,
00903 OPS *ops,
00904 VARIANT variant)
00905 {
00906 OPCODE opcode = OPCODE_make_op(OPR_STID, MTYPE_V, mtype);
00907 Exp_Ldst (opcode, src_tn, sym, ofst, FALSE, TRUE, FALSE, ops, variant);
00908 }
00909
00910 static ISA_ENUM_CLASS_VALUE
00911 Get_lfhint (const char *s, ISA_ENUM_CLASS_VALUE default_val)
00912 {
00913 ISA_ENUM_CLASS_VALUE lfhint = default_val;
00914 if (s) {
00915 if (strcmp(s, "nt1") == 0) {
00916 lfhint = ECV_lfhint_nt1;
00917 } else if (strcmp(s, "nt2") == 0) {
00918 lfhint = ECV_lfhint_nt2;
00919 } else if (strcmp(s, "nta") == 0) {
00920 lfhint = ECV_lfhint_nta;
00921 } else if (strcmp(s, "none") == 0) {
00922 lfhint = ECV_lfhint;
00923 } else {
00924 fprintf(stderr, "bad lfhint specification: '%s';"
00925 "must be 'nt1', 'nt2', 'nta' or 'none'\n",
00926 s);
00927 }
00928 }
00929 return lfhint;
00930 }
00931
00932 static ISA_ENUM_CLASS_VALUE
00933 Pick_Prefetch_Hint (VARIANT variant)
00934 {
00935 UINT32 pf_flags = V_pf_flags(variant);
00936 static ISA_ENUM_CLASS_VALUE lfhint_L1;
00937 static ISA_ENUM_CLASS_VALUE lfhint_L2;
00938 static BOOL inited = FALSE;
00939 if (!inited) {
00940 lfhint_L1 = Get_lfhint(CGEXP_lfhint_L1, ECV_lfhint);
00941 lfhint_L2 = Get_lfhint(CGEXP_lfhint_L2, ECV_lfhint_nt1);
00942 inited = TRUE;
00943 }
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956 ISA_ENUM_CLASS_VALUE lfhint;
00957 if (PF_GET_STRIDE_1L(pf_flags)) {
00958 lfhint = lfhint_L1;
00959 } else if (PF_GET_STRIDE_2L(pf_flags)) {
00960 lfhint = lfhint_L2;
00961 } else {
00962 lfhint = ECV_lfhint;
00963 }
00964
00965 return lfhint;
00966 }
00967
00968 void Exp_Prefetch (TOP opc, TN* src1, TN* src2, VARIANT variant, OPS* ops)
00969 {
00970 ISA_ENUM_CLASS_VALUE lfhint;
00971 UINT32 pf_flags = V_pf_flags(variant);
00972 FmtAssert(opc == TOP_UNDEFINED,
00973 ("Prefetch opcode should be selected in Exp_Prefetch"));
00974 opc = (PF_GET_WRITE(pf_flags) && CG_exclusive_prefetch)
00975 ? TOP_lfetch_excl : TOP_lfetch;
00976 lfhint = Pick_Prefetch_Hint(variant);
00977
00978
00979 if (!TN_is_zero(src2)) {
00980 TN* tmp = Build_TN_Like(src1);
00981 Expand_Add (tmp, src1, src2, Pointer_Mtype, ops);
00982 src1 = tmp;
00983 }
00984
00985 Build_OP(opc, True_TN, Gen_Enum_TN(lfhint), src1, ops);
00986 }
00987
00988
00989
00990
00991 void
00992 Exp_Extract_Bits (TYPE_ID rtype, TYPE_ID desc, UINT bit_offset, UINT bit_size,
00993 TN *tgt_tn, TN *src_tn, OPS *ops)
00994 {
00995 TOP extr_op = MTYPE_signed(rtype) ? TOP_extr : TOP_extr_u;
00996 UINT pos = Target_Byte_Sex == BIG_ENDIAN
00997 ? MTYPE_bit_size(desc)-bit_offset-bit_size : bit_offset;
00998 Build_OP(extr_op, tgt_tn, True_TN, src_tn,
00999 Gen_Literal_TN(pos, 4), Gen_Literal_TN(bit_size, 4), ops);
01000 }
01001
01002
01003
01004
01005
01006 void
01007 Exp_Deposit_Bits (TYPE_ID rtype, TYPE_ID desc, UINT bit_offset, UINT bit_size,
01008 TN *tgt_tn, TN *src1_tn, TN *src2_tn, OPS *ops)
01009 {
01010 FmtAssert(bit_size != 0, ("size of bit field cannot be 0"));
01011
01012 UINT targ_bit_offset = bit_offset;
01013 if (Target_Byte_Sex == BIG_ENDIAN) {
01014 targ_bit_offset = MTYPE_bit_size(desc) - bit_offset - bit_size;
01015 }
01016
01017 if (bit_size <= 16) {
01018 Build_OP(TOP_dep, tgt_tn, True_TN, src2_tn, src1_tn,
01019 Gen_Literal_TN(targ_bit_offset, 4), Gen_Literal_TN(bit_size, 4), ops);
01020 return;
01021 }
01022
01023
01024 TN *tmp1_tn = Build_TN_Like (src1_tn);
01025 TN *tmp2_tn = Build_TN_Like (src1_tn);
01026 Build_OP(TOP_dep_i, tmp1_tn, True_TN, Gen_Literal_TN(0, 4), src1_tn,
01027 Gen_Literal_TN(targ_bit_offset, 4), Gen_Literal_TN(bit_size, 4), ops);
01028 Build_OP(TOP_dep_z, tmp2_tn, True_TN, src2_tn,
01029 Gen_Literal_TN(targ_bit_offset, 4), Gen_Literal_TN(bit_size, 4), ops);
01030 Build_OP(TOP_or, tgt_tn, True_TN, tmp1_tn, tmp2_tn, ops);
01031 }
01032
01033 void
01034 Expand_Lda_Label (TN *dest, TN *lab, OPS *ops)
01035 {
01036 TN *tmp1 = Build_TN_Of_Mtype (Pointer_Mtype);
01037 Set_TN_is_reloc_ia_ltoff22(lab);
01038
01039 Expand_Add (tmp1, lab, GP_TN, Pointer_Mtype, ops);
01040
01041 Expand_Load (
01042
01043 OPCODE_make_op(OPR_LDID, Pointer_Mtype, Pointer_Mtype),
01044 dest, tmp1, Gen_Literal_TN (0, 4), V_NONE, ops);
01045 }