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
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include <stdint.h>
00050 #include "elf_stuff.h"
00051 #include "defs.h"
00052 #include "em_elf.h"
00053 #include "erglob.h"
00054 #include "ercg.h"
00055 #include "tracing.h"
00056 #include "config.h"
00057 #include "config_targ_opt.h"
00058 #include "config_debug.h"
00059 #include "xstats.h"
00060 #include "topcode.h"
00061 #include "tn.h"
00062 #include "cg_flags.h"
00063 #include "targ_isa_lits.h"
00064 #include "op.h"
00065 #include "stblock.h"
00066 #include "data_layout.h"
00067 #include "strtab.h"
00068 #include "symtab.h"
00069 #include "cg.h"
00070 #include "cgexp.h"
00071 #include "cgexp_internals.h"
00072 #include "cgemit.h"
00073 #include "cg_flags.h"
00074
00075 static void Exp_Ldst( OPCODE opcode,
00076 TN *tn,
00077 ST *sym,
00078 INT64 ofst,
00079 BOOL indirect_call,
00080 BOOL is_store,
00081 BOOL is_load,
00082 OPS *ops,
00083 VARIANT variant );
00084
00085 void
00086 Expand_Lda (TN *dest, TN *src, OPS *ops)
00087 {
00088 FmtAssert(FALSE, ("NYI: Expand_Lda"));
00089 }
00090
00091 static TOP
00092 Pick_Load_Instruction (TYPE_ID rtype, TYPE_ID desc,
00093 TN* base,
00094 TN* ofst,
00095 ISA_REGISTER_CLASS rclass)
00096 {
00097 const BOOL is_64bit = MTYPE_is_size_double(rtype);
00098 const BOOL is_reloc_x8664_64 = (ofst != NULL &&
00099 TN_is_symbol(ofst) &&
00100 TN_is_reloc_x8664_64(ofst));
00101 const BOOL is_reloc_x8664_tpoff32_seg_reg =
00102 (base == NULL &&
00103 ofst != NULL &&
00104 TN_is_symbol(ofst) &&
00105 TN_is_reloc_x8664_tpoff32_seg_reg(ofst));
00106
00107 if (is_reloc_x8664_64) {
00108 FmtAssert((base == NULL) && (rtype == desc),
00109 ("Pick_Load_Instruction: "
00110 "Illegal load operation when mcmodel is medium"));
00111 }
00112
00113 switch (desc) {
00114 case MTYPE_I1:
00115 if (is_64bit)
00116 return base == NULL ? TOP_ld8_64_off : TOP_ld8_64;
00117 if (base != NULL)
00118 return TOP_ld8_32;
00119 return is_reloc_x8664_64 ? TOP_ld8_abs : TOP_ld8_32_n32;
00120 case MTYPE_U1:
00121 if (is_64bit)
00122 return base == NULL ? TOP_ldu8_64_off : TOP_ldu8_64;
00123 if (base != NULL)
00124 return TOP_ldu8_32;
00125 return is_reloc_x8664_64 ? TOP_ld8_abs : TOP_ldu8_32_n32;
00126 case MTYPE_I2:
00127 if (is_64bit)
00128 return base == NULL ? TOP_ld16_64_off : TOP_ld16_64;
00129 if (base != NULL)
00130 return TOP_ld16_32;
00131 return is_reloc_x8664_64 ? TOP_ld16_abs : TOP_ld16_32_n32;
00132 case MTYPE_U2:
00133 if (is_64bit)
00134 return base == NULL ? TOP_ldu16_64_off : TOP_ldu16_64;
00135 if (base != NULL)
00136 return TOP_ldu16_32;
00137 return is_reloc_x8664_64 ? TOP_ld16_abs : TOP_ldu16_32_n32;
00138 case MTYPE_I4:
00139 if (is_64bit)
00140 return base == NULL ? TOP_ld32_64_off : TOP_ld32_64;
00141 if (base != NULL)
00142 return TOP_ld32;
00143 return is_reloc_x8664_64 ? TOP_ld32_abs : TOP_ld32_n32;
00144 case MTYPE_U4:
00145 if (base != NULL)
00146 return TOP_ld32;
00147 return is_reloc_x8664_64 ? TOP_ld32_abs : TOP_ld32_n32;
00148 case MTYPE_I8:
00149 case MTYPE_U8:
00150 if (rclass == ISA_REGISTER_CLASS_mmx)
00151 return base == NULL ? TOP_ld64_2m_n32 : TOP_ld64_2m;
00152 return base == NULL ? TOP_ld64_off :
00153 is_reloc_x8664_64 ? TOP_ld64_abs : TOP_ld64;
00154 case MTYPE_F4:
00155 if (rclass == ISA_REGISTER_CLASS_float)
00156 return base != NULL ? TOP_ldss : TOP_ldss_n32;
00157 else
00158 return base != NULL ? TOP_flds : TOP_flds_n32;
00159 case MTYPE_F8:
00160 if (rclass == ISA_REGISTER_CLASS_float)
00161 return base != NULL ? TOP_ldsd : TOP_ldsd_n32;
00162 else
00163 return base != NULL ? TOP_fldl : TOP_fldl_n32;
00164 case MTYPE_F16:
00165 return TOP_lddqu;
00166 case MTYPE_FQ:
00167 return base != NULL ? TOP_fldt : TOP_fldt_n32;
00168 case MTYPE_V16F4:
00169 case MTYPE_V16C4:
00170 return base != NULL ? TOP_ldaps : TOP_ldaps_n32;
00171 case MTYPE_V16F8:
00172 case MTYPE_V16C8:
00173 return base != NULL ? TOP_ldapd : TOP_ldapd_n32;
00174 case MTYPE_V16I1:
00175 case MTYPE_V16I2:
00176 case MTYPE_V16I4:
00177 case MTYPE_V16I8:
00178 return base != NULL ? TOP_lddqa : TOP_lddqa_n32;
00179 case MTYPE_V8I1:
00180 case MTYPE_V8I2:
00181 case MTYPE_V8I4:
00182 case MTYPE_V8F4:
00183 case MTYPE_M8I1:
00184 case MTYPE_M8I2:
00185 case MTYPE_M8I4:
00186 case MTYPE_M8F4:
00187 if ( rclass == ISA_REGISTER_CLASS_mmx )
00188 return base != NULL ? TOP_ld64_2m : TOP_ld64_2m_n32;
00189 else if ( rclass == ISA_REGISTER_CLASS_float )
00190 return base != NULL ? TOP_ld64_2sse : TOP_ld64_2sse_n32;
00191 else
00192 return base != NULL ? TOP_ldlps : TOP_ldlps_n32;
00193
00194 case MTYPE_V:
00195 if (rtype != MTYPE_V)
00196
00197 return Pick_Load_Instruction(rtype,rtype,base,ofst,rclass);
00198
00199 default:
00200 FmtAssert(FALSE, ("NYI: Pick_Load_Instruction mtype"));
00201 return TOP_UNDEFINED;
00202 }
00203 }
00204
00205
00206 static void Expand_Split_Load( OPCODE opcode,
00207 TN* result, TN* base, TN* ofst, OPS* ops )
00208 {
00209 const TYPE_ID desc = OPCODE_desc(opcode);
00210 const TYPE_ID rtype = OPCODE_rtype(opcode);
00211 const TYPE_ID new_mtype = (rtype == MTYPE_I8 ? MTYPE_I4 : MTYPE_U4);
00212 const TYPE_ID new_desc = MTYPE_is_size_double(desc) ? new_mtype : desc;
00213 const TOP new_top =
00214 Pick_Load_Instruction( new_mtype, new_desc,
00215 base,
00216 ofst,
00217 TN_register_class(result) );
00218
00219 FmtAssert( MTYPE_is_size_double(rtype), ("NYI") );
00220
00221
00222
00223 if( base == NULL )
00224 Build_OP( new_top, result, ofst, ops );
00225 else
00226 Build_OP( new_top, result, base, ofst, ops );
00227
00228
00229 TN* tn_h = Create_TN_Pair( result, rtype );
00230
00231 if( MTYPE_is_size_double( desc ) ){
00232 TN* ofst_h = TN_is_symbol( ofst )
00233 ? Gen_Symbol_TN( TN_var(ofst), TN_offset(ofst) + 4, TN_relocs(ofst))
00234 : Gen_Literal_TN( TN_value(ofst) + 4, TN_size(ofst) );
00235
00236 if( base == NULL )
00237 Build_OP( new_top, tn_h, ofst_h, ops );
00238 else
00239 Build_OP( new_top, tn_h, base, ofst_h, ops );
00240
00241 Set_OP_memory_hi( OPS_last( ops ) );
00242
00243 } else {
00244
00245
00246 if( MTYPE_is_unsigned( desc ) ){
00247 Build_OP( TOP_ldc32, tn_h, Gen_Literal_TN(0,4), ops );
00248
00249 } else {
00250
00251
00252
00253 TN* tmp = result;
00254
00255 if( TN_is_dedicated(result ) ){
00256 tmp = Build_TN_Like( tn_h );
00257 if( base == NULL )
00258 Build_OP( new_top, tmp, ofst, ops );
00259 else
00260 Build_OP( new_top, tmp, base, ofst, ops );
00261 }
00262
00263 Build_OP( TOP_sari32, tn_h, tmp, Gen_Literal_TN(31,4), ops );
00264 }
00265 }
00266
00267 return;
00268 }
00269
00270
00271 void
00272 Expand_Load (OPCODE opcode, TN *result, TN *base, TN *ofst, OPS *ops)
00273 {
00274 if( OP_NEED_PAIR( OPCODE_rtype(opcode) ) ){
00275 Expand_Split_Load( opcode, result, base, ofst, ops );
00276 return;
00277 }
00278
00279 const TYPE_ID mtype = OPCODE_desc(opcode);
00280 const BOOL is_reloc_x8664_64 = ( ofst != NULL &&
00281 TN_is_symbol( ofst ) &&
00282 TN_is_reloc_x8664_64( ofst ) );
00283 const TYPE_ID rtype = is_reloc_x8664_64 ? mtype : OPCODE_rtype(opcode);
00284
00285 TOP top = Pick_Load_Instruction (rtype, mtype,
00286 base,
00287 ofst,
00288 TN_register_class(result));
00289 Is_True (TN_is_constant(ofst), ("Expand_Load: Illegal offset TN"));
00290
00291 if (top == TOP_lddqu && mtype == MTYPE_F16 &&
00292 (base == SP_TN || base == FP_TN) &&
00293 Stack_Alignment() == 16 ) {
00294 if (TN_has_value(ofst) &&
00295 (TN_value(ofst) % 16 == 0))
00296 top = TOP_lddqa;
00297 else if (TN_is_symbol(ofst)) {
00298 ST* base;
00299 INT64 offset = 0;
00300 Base_Symbol_And_Offset (TN_var(ofst), &base, &offset);
00301 offset += TN_offset(ofst);
00302 if (offset % 16 == 0)
00303 top = TOP_lddqa;
00304 }
00305 }
00306
00307 if( base == NULL ){
00308 if( rtype == OPCODE_rtype(opcode) ){
00309
00310 if( is_reloc_x8664_64 &&
00311 TN_is_dedicated( result ) ){
00312 TN* tmp_result = Build_TN_Like( result );
00313 Build_OP( top, tmp_result, ofst, ops );
00314 Exp_COPY( result, tmp_result, ops );
00315
00316 } else
00317 Build_OP( top, result, ofst, ops );
00318
00319 } else {
00320 TN* tmp_result = Build_TN_Of_Mtype( mtype );
00321 Build_OP( top, tmp_result, ofst, ops );
00322 const TOP old_top = Pick_Load_Instruction( OPCODE_rtype(opcode),
00323 mtype,
00324 base,
00325 NULL,
00326 TN_register_class(result) );
00327
00328 Exp_COPY_Ext( old_top, result, tmp_result, ops );
00329
00330 if( TN_is_gra_homeable(result) ){
00331 Reset_TN_is_gra_homeable( result );
00332 Set_TN_home( result, NULL );
00333 }
00334 }
00335 return;
00336 }
00337
00338
00339
00340
00341 if (TN_is_rematerializable(base)) {
00342 WN *home = TN_home(base);
00343 if (WN_operator(home) == OPR_INTCONST) {
00344 INT64 val = WN_const_val(home);
00345 BOOL is_double = TN_size(base) == 8;
00346 TN *tmp_base = Gen_Literal_TN (val + TN_value(ofst), TN_size(base));
00347 tmp_base = Expand_Immediate_Into_Register(tmp_base, is_double, ops);
00348 Build_OP (top, result, tmp_base, Gen_Literal_TN (0, 2), ops);
00349 return;
00350
00351 } else if( WN_operator(home) == OPR_LDA ){
00352 ST* sym = WN_st( home );
00353 const INT64 offset = WN_lda_offset( home ) + TN_value( ofst );
00354 if( ISA_LC_Value_In_Class(offset, LC_simm32) ){
00355 Exp_Ldst( opcode, result, sym, offset, FALSE, FALSE, TRUE, ops, 0 );
00356 return;
00357 }
00358 }
00359 }
00360
00361 Build_OP (top, result, base, ofst, ops);
00362 }
00363
00364 static TOP
00365 Pick_Store_Instruction( TYPE_ID mtype,
00366 TN* base,
00367 TN* ofst,
00368 ISA_REGISTER_CLASS rclass )
00369 {
00370 const BOOL is_reloc_x8664_64 = (ofst != NULL &&
00371 TN_is_symbol(ofst) &&
00372 TN_is_reloc_x8664_64(ofst));
00373 const BOOL is_reloc_x8664_tpoff32_seg_reg =
00374 (base == NULL &&
00375 ofst != NULL &&
00376 TN_is_symbol(ofst) &&
00377 TN_is_reloc_x8664_tpoff32_seg_reg(ofst));
00378
00379 switch (mtype) {
00380 case MTYPE_I1:
00381 case MTYPE_U1:
00382 if( base != NULL )
00383 return TOP_store8;
00384 return is_reloc_x8664_64 ? TOP_store8_abs : TOP_store8_n32;
00385 case MTYPE_I2:
00386 case MTYPE_U2:
00387 if( base != NULL )
00388 return TOP_store16;
00389 return is_reloc_x8664_64 ? TOP_store16_abs : TOP_store16_n32;
00390 case MTYPE_I4:
00391 case MTYPE_U4:
00392 if( base != NULL )
00393 return TOP_store32;
00394 return is_reloc_x8664_64 ? TOP_store32_abs : TOP_store32_n32;
00395 case MTYPE_I8:
00396 case MTYPE_U8:
00397 if (rclass == ISA_REGISTER_CLASS_mmx)
00398 return base == NULL ? TOP_store64_fm_n32 : TOP_store64_fm;
00399 return is_reloc_x8664_64 ? TOP_store64_abs :
00400 base == NULL ? TOP_store64_off : TOP_store64;
00401 case MTYPE_F4:
00402 if( rclass == ISA_REGISTER_CLASS_float )
00403 return base != NULL ? TOP_stss : TOP_stss_n32;
00404 else
00405 return base != NULL ? TOP_fstps : TOP_fstps_n32;
00406 case MTYPE_F8:
00407 if( rclass == ISA_REGISTER_CLASS_float )
00408 return base != NULL ? TOP_stsd : TOP_stsd_n32;
00409 else
00410 return base != NULL ? TOP_fstpl : TOP_fstpl_n32;
00411 case MTYPE_F16:
00412 return TOP_stdqu;
00413 case MTYPE_FQ:
00414 return base != NULL ? TOP_fstpt : TOP_fstpt_n32;
00415 case MTYPE_V16F4:
00416 case MTYPE_V16C4:
00417 return base != NULL ? TOP_staps : TOP_staps_n32;
00418 case MTYPE_V16F8:
00419 case MTYPE_V16C8:
00420 return base != NULL ? TOP_stapd : TOP_stapd_n32;
00421 case MTYPE_V16I1:
00422 case MTYPE_V16I2:
00423 case MTYPE_V16I4:
00424 case MTYPE_V16I8:
00425 return base != NULL ? TOP_stdqa : TOP_stdqa_n32;
00426 case MTYPE_V8I1:
00427 case MTYPE_V8I2:
00428 case MTYPE_V8I4:
00429 case MTYPE_V8F4:
00430 case MTYPE_M8I1:
00431 case MTYPE_M8I2:
00432 case MTYPE_M8I4:
00433 case MTYPE_M8F4:
00434 if ( rclass == ISA_REGISTER_CLASS_mmx )
00435 return base != NULL ? TOP_store64_fm : TOP_store64_fm_n32;
00436 else if ( rclass == ISA_REGISTER_CLASS_float )
00437 return base != NULL ? TOP_store64_fsse : TOP_store64_fsse_n32;
00438 else
00439 return base != NULL ? TOP_stlps : TOP_stlps_n32;
00440
00441 default: FmtAssert(FALSE, ("NYI: Pick_Store_Instruction mtype"));
00442 return TOP_UNDEFINED;
00443 }
00444 }
00445
00446
00447 static void Expand_Split_Store( TYPE_ID mtype,
00448 TN *src, TN *base, TN *ofst, OPS *ops )
00449 {
00450 const TYPE_ID new_mtype = (mtype == MTYPE_I8 ? MTYPE_I4 : MTYPE_U4);
00451 const TOP new_top =
00452 Pick_Store_Instruction( new_mtype, base, ofst, TN_register_class(src) );
00453 TN* src_h = Get_TN_Pair( src );
00454 TN* ofst_h = TN_is_symbol( ofst )
00455 ? Gen_Symbol_TN( TN_var(ofst), TN_offset(ofst) + 4, TN_relocs(ofst))
00456 : Gen_Literal_TN( TN_value(ofst) + 4, TN_size(ofst) );
00457
00458 if( src_h == NULL ){
00459 src_h = Build_TN_Like( src );
00460 Build_OP( TOP_ldc32, src_h, Gen_Literal_TN( 0, 4 ), ops );
00461 }
00462
00463 if( base != NULL ){
00464 Build_OP( new_top, src, base, ofst, ops );
00465
00466 Build_OP( new_top, src_h, base, ofst_h, ops );
00467 Set_OP_memory_hi( OPS_last( ops ) );
00468
00469 } else {
00470 Build_OP( new_top, src, ofst, ops );
00471
00472 Build_OP( new_top, src_h, ofst_h, ops );
00473 Set_OP_memory_hi( OPS_last( ops ) );
00474 }
00475
00476 return;
00477 }
00478
00479
00480 void
00481 Expand_Store (TYPE_ID mtype, TN *src, TN *base, TN *ofst, OPS *ops)
00482 {
00483 TOP top =
00484 Pick_Store_Instruction( mtype, base, ofst, TN_register_class(src) );
00485 Is_True (TN_is_constant(ofst), ("Expand_Store: Illegal offset TN"));
00486
00487 if (top == TOP_stdqu && mtype == MTYPE_F16 &&
00488 (base == SP_TN || base == FP_TN) &&
00489 Stack_Alignment() == 16 ) {
00490 if (TN_has_value(ofst) &&
00491 (TN_value(ofst) % 16 == 0))
00492 top = TOP_stdqa;
00493 else if (TN_is_symbol(ofst)) {
00494 ST* base;
00495 INT64 offset = 0;
00496 Base_Symbol_And_Offset (TN_var(ofst), &base, &offset);
00497 offset += TN_offset(ofst);
00498 if (offset % 16 == 0)
00499 top = TOP_stdqa;
00500 }
00501 }
00502
00503 if( OP_NEED_PAIR( mtype ) ){
00504 Expand_Split_Store( mtype, src, base, ofst, ops );
00505 return;
00506 }
00507
00508 if (!TN_has_value(ofst) || ISA_LC_Value_In_Class(TN_value(ofst), LC_simm32)){
00509 if( base != NULL )
00510 Build_OP (top, src, base, ofst, ops);
00511 else
00512 Build_OP (top, src, ofst, ops);
00513
00514 } else {
00515 if( base != NULL )
00516 Build_OP(top, src, base, Gen_Literal_TN(TN_value(ofst), 4), ops);
00517 else
00518 Build_OP(top, src, Gen_Literal_TN(TN_value(ofst), 4), ops);
00519 }
00520 }
00521
00522 static OPCODE
00523 OPCODE_make_signed_op(OPERATOR op, TYPE_ID rtype, TYPE_ID desc, BOOL is_signed)
00524 {
00525 if (MTYPE_is_signed(rtype) != is_signed)
00526 rtype = MTYPE_complement(rtype);
00527 if (MTYPE_is_signed(desc) != is_signed)
00528 desc = MTYPE_complement(desc);
00529
00530 return OPCODE_make_op(op, rtype, desc);
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 static void
00547 Adjust_Addr_TNs (
00548 TOP opcode,
00549 TN **base_tn,
00550 TN **disp_tn,
00551 INT16 disp,
00552 OPS *ops)
00553 {
00554
00555 if ( Potential_Immediate_TN_Expr (opcode, *disp_tn, disp) )
00556 {
00557 if ( TN_has_value(*disp_tn) ) {
00558 *disp_tn = Gen_Literal_TN ( TN_value(*disp_tn) + disp, 4 );
00559 } else {
00560 *disp_tn = Gen_Symbol_TN ( TN_var(*disp_tn),
00561 TN_offset(*disp_tn) + disp, 0);
00562 }
00563 } else {
00564 TN *tmp = Build_TN_Of_Mtype (Pointer_Mtype);
00565
00566
00567 Expand_Add (tmp, *disp_tn, *base_tn, Pointer_Mtype, ops);
00568 *base_tn = tmp;
00569 *disp_tn = Gen_Literal_TN (disp, 4);
00570 }
00571 }
00572
00573 static void
00574 Expand_Composed_Load ( OPCODE op, TN *result, TN *base, TN *disp, VARIANT variant, OPS *ops)
00575 {
00576 return Expand_Load( op, result, base, disp, ops );
00577 }
00578
00579 void
00580 Expand_Misaligned_Load ( OPCODE op, TN *result, TN *base, TN *disp, VARIANT variant, OPS *ops)
00581 {
00582 TYPE_ID mtype = OPCODE_rtype(op);
00583
00584 if (mtype == MTYPE_V16I1 || mtype == MTYPE_V16I2 ||
00585 mtype == MTYPE_V16I4 || mtype == MTYPE_V16I8) {
00586 if (base != NULL)
00587 Build_OP (TOP_lddqu, result, base, disp, ops);
00588 else Build_OP (TOP_lddqu_n32, result, disp, ops);
00589 }
00590 else if (mtype == MTYPE_V8I1 || mtype == MTYPE_V8I2 ||
00591 mtype == MTYPE_V8I4) {
00592 if (base != NULL)
00593 Build_OP(!Is_Target_SSE2() ? TOP_ldlps : TOP_ld64_2sse, result, base, disp, ops);
00594 else Build_OP(!Is_Target_SSE2() ? TOP_ldlps_n32 : TOP_ld64_2sse_n32, result, disp, ops);
00595 }
00596 else if (mtype == MTYPE_V16F8 || mtype == MTYPE_V16C8) {
00597 if(Is_Target_Barcelona()){
00598 if(base != NULL)
00599 Build_OP (TOP_ldupd, result, base, disp, ops);
00600 else Build_OP (TOP_ldupd_n32, result, disp, ops);
00601 }else{
00602 TN* ofst = TN_is_symbol( disp )
00603 ? Gen_Symbol_TN( TN_var(disp), TN_offset(disp) + 8, TN_RELOC_NONE )
00604 : Gen_Literal_TN( TN_value(disp) + 8, TN_size(disp) );
00605 if (base != NULL) {
00606 Build_OP (TOP_ldlpd, result, base, disp, ops);
00607 Build_OP (TOP_ldhpd, result, base, ofst, ops);
00608 }
00609 else {
00610 Build_OP (TOP_ldlpd_n32, result, disp, ops);
00611 Build_OP (TOP_ldhpd_n32, result, ofst, ops);
00612 }
00613 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00614 }
00615 }
00616 else if (mtype == MTYPE_V16F4 || mtype == MTYPE_V16C4) {
00617 if(Is_Target_Barcelona()){
00618 if(base != NULL)
00619 Build_OP (TOP_ldups, result, base, disp, ops);
00620 else Build_OP (TOP_ldups_n32, result, disp, ops);
00621 }else{
00622 TN* ofst = TN_is_symbol( disp )
00623 ? Gen_Symbol_TN( TN_var(disp), TN_offset(disp) + 8, TN_RELOC_NONE )
00624 : Gen_Literal_TN( TN_value(disp) + 8, TN_size(disp) );
00625 if (base != NULL) {
00626 Build_OP (TOP_ldlps, result, base, disp, ops);
00627 Build_OP (TOP_ldhps, result, base, ofst, ops);
00628 }
00629 else {
00630 Build_OP (TOP_ldlps_n32, result, disp, ops);
00631 Build_OP (TOP_ldhps_n32, result, ofst, ops);
00632 }
00633 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00634 }
00635 }
00636 else
00637 Expand_Composed_Load ( op, result, base, disp, variant, ops );
00638 }
00639
00640
00641 static void
00642 Expand_Composed_Store (TYPE_ID mtype, TN *obj, TN *base, TN *disp, VARIANT variant, OPS *ops)
00643 {
00644 return Expand_Store( mtype, obj, base, disp, ops );
00645 }
00646
00647 void
00648 Expand_Misaligned_Store (TYPE_ID mtype, TN *obj_tn, TN *base_tn, TN *disp_tn, VARIANT variant, OPS *ops)
00649 {
00650 if (mtype == MTYPE_V16I1 || mtype == MTYPE_V16I2 ||
00651 mtype == MTYPE_V16I4 || mtype == MTYPE_V16I8) {
00652 if (base_tn != NULL)
00653 Build_OP (TOP_stdqu, obj_tn, base_tn, disp_tn, ops);
00654 else Build_OP (TOP_stdqu_n32, obj_tn, disp_tn, ops);
00655 }
00656 else if (mtype == MTYPE_V8I1 || mtype == MTYPE_V8I2 || mtype == MTYPE_V8I4) {
00657 if (base_tn != NULL)
00658 Build_OP(!Is_Target_SSE2() ? TOP_stlps : TOP_store64_fsse, obj_tn, base_tn, disp_tn, ops);
00659 else Build_OP(!Is_Target_SSE2() ? TOP_stlps_n32 : TOP_store64_fsse_n32, obj_tn, disp_tn, ops);
00660 }
00661 else if (mtype == MTYPE_V16F4 || mtype == MTYPE_V16C4) {
00662 TN* ofst = TN_is_symbol( disp_tn )
00663 ? Gen_Symbol_TN( TN_var(disp_tn), TN_offset(disp_tn) + 8, TN_RELOC_NONE )
00664 : Gen_Literal_TN( TN_value(disp_tn) + 8, TN_size(disp_tn) );
00665 if (base_tn != NULL) {
00666 Build_OP (TOP_stlps, obj_tn, base_tn, disp_tn, ops);
00667 Build_OP (TOP_sthps, obj_tn, base_tn, ofst, ops);
00668 }
00669 else {
00670 Build_OP (TOP_stlps_n32, obj_tn, disp_tn, ops);
00671 Build_OP (TOP_sthps_n32, obj_tn, ofst, ops);
00672 }
00673 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00674 }
00675 else if (mtype == MTYPE_V16F8 || mtype == MTYPE_V16C8) {
00676 TN* ofst = TN_is_symbol( disp_tn )
00677 ? Gen_Symbol_TN( TN_var(disp_tn), TN_offset(disp_tn) + 8, TN_RELOC_NONE )
00678 : Gen_Literal_TN( TN_value(disp_tn) + 8, TN_size(disp_tn) );
00679 if (base_tn != NULL) {
00680 Build_OP (TOP_stlpd, obj_tn, base_tn, disp_tn, ops);
00681 Build_OP (TOP_sthpd, obj_tn, base_tn, ofst, ops);
00682 }
00683 else {
00684 Build_OP (TOP_stlpd_n32, obj_tn, disp_tn, ops);
00685 Build_OP (TOP_sthpd_n32, obj_tn, ofst, ops);
00686 }
00687 Set_OP_cond_def_kind(OPS_last(ops), OP_ALWAYS_COND_DEF);
00688 }
00689 else
00690 Expand_Composed_Store (mtype, obj_tn, base_tn, disp_tn, variant, ops);
00691 }
00692
00693 static BOOL is_stack_used = FALSE;
00694
00695 BOOL Is_Stack_Used()
00696 {
00697 const BOOL state = is_stack_used;
00698 is_stack_used = FALSE;
00699 return state;
00700 }
00701
00702 void
00703 CG_Set_Is_Stack_Used()
00704 {
00705 is_stack_used = TRUE;
00706 }
00707
00708 static void
00709 Exp_Ldst (
00710 OPCODE opcode,
00711 TN *tn,
00712 ST *sym,
00713 INT64 ofst,
00714 BOOL indirect_call,
00715 BOOL is_store,
00716 BOOL is_load,
00717 OPS *ops,
00718 VARIANT variant)
00719 {
00720 ST* base_sym = NULL;
00721 INT64 base_ofst = 0;
00722 TN* base_tn = NULL;
00723 TN* ofst_tn = NULL;
00724 const BOOL is_lda = (!is_load && !is_store);
00725 OPS newops = OPS_EMPTY;
00726 OP* op = NULL;
00727 BOOL on_stack = FALSE;
00728
00729 if (Trace_Exp2) {
00730 fprintf(TFile, "exp_ldst %s: ", OPCODE_name(opcode));
00731 if (tn) Print_TN(tn,FALSE);
00732 if (is_store) fprintf(TFile, " -> ");
00733 else fprintf(TFile, " <- ");
00734 if (ST_class(sym) != CLASS_CONST)
00735 fprintf(TFile, "%lld (%s)\n", ofst, ST_name(sym));
00736 else
00737 fprintf(TFile, "%lld ()\n", ofst);
00738 }
00739
00740 Allocate_Object(sym);
00741
00742 Base_Symbol_And_Offset_For_Addressing (sym, ofst, &base_sym, &base_ofst);
00743
00744 if (base_sym == SP_Sym || base_sym == FP_Sym) {
00745 is_stack_used = on_stack = TRUE;
00746
00747 base_tn = (base_sym == SP_Sym) ? SP_TN : FP_TN;
00748 if (sym == base_sym) {
00749
00750
00751 if (ISA_LC_Value_In_Class(base_ofst, LC_simm32))
00752 ofst_tn = Gen_Literal_TN (base_ofst, 4);
00753 else {
00754 FmtAssert( false, ("NYI") );
00755 }
00756
00757 } else {
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 if (ISA_LC_Value_In_Class(base_ofst, LC_simm32))
00768 ofst_tn = Gen_Symbol_TN (sym, ofst, 0);
00769 else if (! is_lda) {
00770 FmtAssert( Is_Target_64bit(), ("NYI: 64-bit offset under -m32"));
00771 TN* tmp_tn = Build_TN_Of_Mtype(Pointer_Mtype);
00772
00773 Build_OP( TOP_ldc64, tmp_tn, Gen_Literal_TN(base_ofst,8), &newops);
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 Build_OP(TOP_leax64, tmp_tn, base_tn, tmp_tn, Gen_Literal_TN(1, 4),
00784 Gen_Literal_TN(0, 4), &newops);
00785 base_tn = tmp_tn;
00786 ofst_tn = Gen_Literal_TN( 0, 4 );
00787 }
00788 }
00789
00790 } else if ((ST_class(base_sym) == CLASS_BLOCK || ST_class(base_sym)==CLASS_VAR)
00791 && ST_gprel(base_sym)) {
00792 FmtAssert( FALSE, ("x86 does not use gp\n") );
00793
00794
00795 } else {
00796 if( !ST_is_export_local(base_sym) &&
00797 !ISA_LC_Value_In_Class(base_ofst, LC_simm32) &&
00798 mcmodel < MEDIUM ){
00799
00800 #if 0 // bug 4622
00801 FmtAssert( FALSE, ("offset cannot be fit into 32-bit") );
00802 #endif
00803 }
00804 }
00805
00806 if (!strncmp (".gnu.linkonce.", ST_name (base_sym), strlen (".gnu.linkonce."))
00807 && (ofst == base_ofst))
00808 base_sym = sym;
00809
00810 if( is_lda ){
00811 if( ofst_tn != NULL && TN_is_symbol( ofst_tn ) ){
00812 Build_OP( Is_Target_64bit() ? TOP_lea64 : TOP_lea32,
00813 tn, base_tn, ofst_tn, &newops );
00814
00815 } else {
00816 if (on_stack) {
00817 if ( ofst_tn != NULL )
00818 Build_OP( Is_Target_64bit() ? TOP_addi64 : TOP_addi32, tn,
00819 base_sym == SP_Sym ? SP_TN : FP_TN, ofst_tn,
00820 &newops );
00821 else {
00822 FmtAssert( Is_Target_64bit(), ("NYI: 64-bit offset under -m32"));
00823 TN *tmp_tn = Build_TN_Of_Mtype(MTYPE_I8);
00824 Build_OP( TOP_ldc64, tmp_tn, Gen_Literal_TN(base_ofst, 8), &newops );
00825 Build_OP( TOP_add64, tn, tmp_tn, base_sym == SP_Sym ? SP_TN : FP_TN,
00826 &newops );
00827 }
00828 }
00829 else if( Is_Target_64bit() ){
00830 if (Gen_PIC_Shared) {
00831 FmtAssert(!ST_is_thread_local(base_sym),
00832 ("Exp_Ldst: thread-local storage NYI under PIC"));
00833 if (! ST_is_export_local(base_sym) ) {
00834 TN *tmp = base_ofst == 0 ? tn : Build_TN_Like(tn);
00835 Build_OP( TOP_ld64, tmp, Rip_TN(),
00836 Gen_Symbol_TN( base_sym, 0, TN_RELOC_X8664_GOTPCREL ),
00837 &newops );
00838
00839 Set_OP_no_alias(OPS_last(&newops));
00840 if (base_ofst != 0)
00841 Build_OP( TOP_addi64, tn, tmp, Gen_Literal_TN(base_ofst, 8),
00842 &newops );
00843 }
00844 else Build_OP( TOP_lea64, tn, Rip_TN(),
00845 Gen_Symbol_TN( base_sym, base_ofst, TN_RELOC_NONE ),
00846 &newops );
00847 } else if (ST_is_thread_local(base_sym)) {
00848
00849
00850
00851
00852 TN *segment_base = Build_TN_Like(tn);
00853 Build_OP(TOP_ld64_fs_seg_off, segment_base, Gen_Literal_TN(0, 4),
00854 &newops);
00855 if (ST_sclass(base_sym) == SCLASS_EXTERN) {
00856 TN *segment_offset = Build_TN_Like(tn);
00857 Build_OP(TOP_ld64, segment_offset, Rip_TN(),
00858 Gen_Symbol_TN(base_sym, 0, TN_RELOC_X8664_GOTTPOFF),
00859 &newops);
00860 Build_OP(TOP_add64, tn, segment_base, segment_offset, &newops);
00861 } else {
00862 TN *segment_offset = Gen_Symbol_TN(base_sym, base_ofst,
00863 TN_RELOC_X8664_TPOFF32);
00864 Build_OP(TOP_addi64, tn, segment_base, segment_offset, &newops);
00865 }
00866 } else if (ISA_LC_Value_In_Class(base_ofst, LC_simm32) &&
00867 mcmodel < MEDIUM ){
00868 Build_OP(TOP_ldc64, tn,
00869 Gen_Symbol_TN( base_sym, base_ofst, TN_RELOC_X8664_PC32 ),
00870 &newops );
00871 } else {
00872 #if 0 // bug 4622
00873 FmtAssert( mcmodel >= MEDIUM, ("code model is not medium or higher") );
00874 #endif
00875 TN* sym_tn = NULL;
00876
00877 if( ISA_LC_Value_In_Class(base_ofst, LC_simm32) ){
00878 Build_OP( TOP_movabsq,
00879 tn, Gen_Symbol_TN( base_sym, base_ofst, TN_RELOC_X8664_64 ),
00880 &newops );
00881
00882 } else {
00883 TN* tmp_tn = Build_TN_Of_Mtype(Pointer_Mtype);
00884 TN* const_tn = Build_TN_Of_Mtype(Pointer_Mtype);
00885
00886 Build_OP( TOP_movabsq,
00887 tmp_tn, Gen_Symbol_TN( base_sym, 0, TN_RELOC_X8664_64 ),
00888 &newops );
00889
00890 Build_OP( TOP_movabsq, const_tn, Gen_Literal_TN(base_ofst,8), &newops );
00891 Build_OP( TOP_add64, tn, tmp_tn, const_tn, &newops );
00892 base_ofst = 0;
00893 }
00894 }
00895
00896 } else {
00897
00898
00899 if (!ISA_LC_Value_In_Class(base_ofst, LC_simm32))
00900 ErrMsg(EC_Misc_User_Abort,
00901 ("Detected 64-bit address offset under -m32. Try -m64 -mcmodel=medium."));
00902
00903 if( Gen_PIC_Shared && (!ST_is_export_local(base_sym) ||
00904
00905 ST_class(base_sym) == CLASS_FUNC ||
00906
00907 (ST_class(base_sym) == CLASS_BLOCK &&
00908 STB_section(base_sym) )) ){
00909 FmtAssert(!ST_is_thread_local(base_sym),
00910 ("Exp_Ldst: thread-local storage NYI under PIC"));
00911 TN* tmp = base_ofst == 0 ? tn : Build_TN_Like(tn);
00912 Build_OP( TOP_ld32, tmp, Ebx_TN(),
00913 Gen_Symbol_TN( base_sym, 0, TN_RELOC_IA32_GOT ),
00914 &newops );
00915
00916 Set_OP_no_alias(OPS_last(&newops));
00917 PU_References_GOT = TRUE;
00918
00919 if( base_ofst != 0 ){
00920 Build_OP( TOP_addi32, tn, tmp, Gen_Literal_TN(base_ofst, 4), &newops );
00921 }
00922 } else if (ST_is_thread_local(base_sym)) {
00923
00924
00925
00926
00927 TN *segment_base = Build_TN_Like(tn);
00928 Build_OP(TOP_ld32_gs_seg_off, segment_base, Gen_Literal_TN(0, 4),
00929 &newops);
00930
00931 TN_RELOCS relocs = (ST_sclass(base_sym) == SCLASS_EXTERN) ?
00932 TN_RELOC_X8664_GOTTPOFF : TN_RELOC_X8664_TPOFF32;
00933 TN *segment_offset = Gen_Symbol_TN(base_sym, base_ofst, relocs);
00934
00935 Build_OP(TOP_addi32, tn, segment_base, segment_offset, &newops);
00936 } else {
00937 Build_OP( TOP_ldc32, tn,
00938 Gen_Symbol_TN( base_sym, base_ofst, TN_RELOC_NONE ),
00939 &newops );
00940 }
00941 }
00942 }
00943
00944 } else {
00945 if( base_tn == NULL ){
00946 Is_True(! on_stack, ("Exp_Ldst: unexpected stack reference"));
00947
00948 if( Is_Target_64bit() ){
00949
00950 if (ST_is_thread_local(sym)) {
00951 FmtAssert(ISA_LC_Value_In_Class(base_ofst, LC_simm32),
00952 ("Exp_Ldst: thread-local storage base offset too large"));
00953 if (ST_sclass(sym) == SCLASS_EXTERN) {
00954 base_tn = Build_TN_Of_Mtype(Pointer_Mtype);
00955 Build_OP(TOP_ld64, base_tn, Rip_TN(),
00956 Gen_Symbol_TN(base_sym, 0,
00957 TN_RELOC_X8664_GOTTPOFF),
00958 &newops);
00959 ofst_tn = Gen_Literal_TN(base_ofst, 4);
00960 base_ofst = 0;
00961 Set_TN_is_thread_seg_ptr(base_tn);
00962 } else {
00963 ofst_tn = Gen_Symbol_TN(base_sym, base_ofst,
00964 TN_RELOC_X8664_TPOFF32_seg_reg);
00965 base_ofst = 0;
00966 }
00967 } else if (mcmodel < MEDIUM &&
00968 ISA_LC_Value_In_Class(base_ofst, LC_simm32)) {
00969 base_tn = Rip_TN();
00970 } else {
00971
00972 if( ISA_LC_Value_In_Class(base_ofst, LC_simm32) ){
00973 ofst_tn = Gen_Symbol_TN( base_sym, base_ofst, TN_RELOC_X8664_64 );
00974 base_ofst = 0;
00975
00976 } else {
00977 ofst_tn = Gen_Symbol_TN( base_sym, 0, TN_RELOC_X8664_64 );
00978 }
00979
00980 if( base_ofst != 0 ){
00981
00982 base_tn = Build_TN_Of_Mtype(Pointer_Mtype);
00983
00984 Build_OP( TOP_movabsq,
00985 base_tn, Gen_Symbol_TN( base_sym, base_ofst, TN_RELOC_X8664_64 ),
00986 &newops );
00987 ofst_tn = Gen_Literal_TN(0, 4);
00988 base_ofst = 0;
00989 }
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999 bool use_iload =
01000 ( ( is_load && !MTYPE_is_integral( OPCODE_rtype(opcode) ) ) ||
01001 ( is_store && !MTYPE_is_integral( OPCODE_desc(opcode) ) ) );
01002
01003 if( !use_iload ){
01004
01005
01006
01007
01008 if( TN_register(tn) != REGISTER_UNDEFINED )
01009 use_iload = (base_sym == SP_Sym || base_sym == FP_Sym);
01010 else {
01011 for( OP* op = OPS_last(ops);
01012 op != NULL;
01013 op = OP_prev(op) ){
01014 if( OP_Defs_Reg( op, ISA_REGISTER_CLASS_integer, RAX ) ){
01015 use_iload = TRUE;
01016 break;
01017 }
01018 }
01019 }
01020 }
01021
01022 if( use_iload && base_tn == NULL){
01023 base_tn = Build_TN_Of_Mtype(Pointer_Mtype);
01024 Build_OP( TOP_movabsq, base_tn, ofst_tn, &newops );
01025 ofst_tn = Gen_Literal_TN( 0, 4 );
01026 }
01027 }
01028 }
01029
01030 if( Gen_PIC_Shared && (!ST_is_export_local(base_sym) ||
01031
01032 (ST_class(base_sym) == CLASS_BLOCK &&
01033 STB_section(base_sym) )) ){
01034 FmtAssert(!ST_is_thread_local(base_sym),
01035 ("Exp_Ldst: thread-local storage NYI under PIC"));
01036 if( Is_Target_64bit() ){
01037 TN *new_base = Build_TN_Of_Mtype(Pointer_Mtype);
01038 Build_OP (TOP_ld64, new_base, base_tn,
01039 Gen_Symbol_TN(base_sym, 0, TN_RELOC_X8664_GOTPCREL),
01040 &newops);
01041
01042 Set_OP_no_alias(OPS_last(&newops));
01043 base_tn = new_base;
01044 ofst_tn = Gen_Literal_TN( base_ofst, 4 );
01045
01046 } else {
01047
01048 TN *new_base = Build_TN_Of_Mtype(Pointer_Mtype);
01049 Build_OP (TOP_ld32, new_base, Ebx_TN(),
01050 Gen_Symbol_TN(base_sym, 0, TN_RELOC_IA32_GOT),
01051 &newops);
01052
01053 Set_OP_no_alias(OPS_last(&newops));
01054 PU_References_GOT = TRUE;
01055 base_tn = new_base;
01056 ofst_tn = Gen_Literal_TN( base_ofst, 4 );
01057 }
01058 }
01059 else if( ofst_tn == NULL ){
01060 if (ST_is_thread_local(base_sym) &&
01061 ST_sclass(sym) == SCLASS_EXTERN) {
01062
01063 FmtAssert(Is_Target_32bit(), ("Exp_Ldst: unexpected 64-bit target"));
01064 base_tn = Build_TN_Of_Mtype(Pointer_Mtype);
01065 Build_OP(TOP_ldc32, base_tn,
01066 Gen_Symbol_TN(base_sym, 0,
01067 TN_RELOC_X8664_GOTTPOFF),
01068 &newops);
01069 ofst_tn = Gen_Literal_TN(base_ofst, 4);
01070 base_ofst = 0;
01071 Set_TN_is_thread_seg_ptr(base_tn);
01072 } else {
01073 ofst_tn = Gen_Symbol_TN(base_sym, base_ofst,
01074 ST_is_thread_local(base_sym) ?
01075 TN_RELOC_X8664_TPOFF32_seg_reg :
01076 TN_RELOC_NONE);
01077 }
01078 }
01079 }
01080
01081 if( is_store ){
01082 if ( opcode == OPC_V16C8STID ||
01083 V_align_all(variant) != 0 )
01084 Expand_Misaligned_Store (OPCODE_desc(opcode), tn, base_tn, ofst_tn,
01085 variant, &newops);
01086 else
01087 Expand_Store (OPCODE_desc(opcode), tn, base_tn, ofst_tn, &newops);
01088
01089 } else if( is_load ){
01090 if ( opcode == OPC_V16C8V16C8LDID ||
01091 V_align_all(variant) != 0 )
01092 Expand_Misaligned_Load ( opcode, tn, base_tn, ofst_tn,
01093 variant, &newops );
01094 else
01095 Expand_Load ( opcode, tn, base_tn, ofst_tn, &newops );
01096 }
01097 }
01098
01099 FOR_ALL_OPS_OPs (&newops, op) {
01100 if (is_load && ST_is_constant(sym) && OP_load(op)) {
01101
01102
01103
01104 Set_OP_no_alias(op);
01105 }
01106 if (Trace_Exp2) {
01107 fprintf(TFile, "exp_ldst into "); Print_OP (op);
01108 }
01109 }
01110
01111 OPS_Append_Ops(ops, &newops);
01112 }
01113
01114 void Exp_Lda (
01115 TYPE_ID mtype,
01116 TN *tgt_tn,
01117 ST *sym,
01118 INT64 ofst,
01119 OPERATOR call_opr,
01120 OPS *ops)
01121 {
01122 OPCODE opcode = OPCODE_make_op(OPR_LDA, mtype, MTYPE_V);
01123 Exp_Ldst (opcode, tgt_tn, sym, ofst,
01124 (call_opr == OPR_ICALL),
01125 FALSE, FALSE, ops, 0);
01126 }
01127
01128 void
01129 Exp_Load (
01130 TYPE_ID rtype,
01131 TYPE_ID desc,
01132 TN *tgt_tn,
01133 ST *sym,
01134 INT64 ofst,
01135 OPS *ops,
01136 VARIANT variant)
01137 {
01138 OPCODE opcode = OPCODE_make_op (OPR_LDID, rtype, desc);
01139 Exp_Ldst (opcode, tgt_tn, sym, ofst, FALSE, FALSE, TRUE, ops, variant);
01140 if (TN_register_class(tgt_tn) == ISA_REGISTER_CLASS_mmx)
01141 Build_OP(TOP_emms, ops);
01142 }
01143
01144 void
01145 Exp_Store (
01146 TYPE_ID mtype,
01147 TN *src_tn,
01148 ST *sym,
01149 INT64 ofst,
01150 OPS *ops,
01151 VARIANT variant)
01152 {
01153 OPCODE opcode = OPCODE_make_op(OPR_STID, MTYPE_V, mtype);
01154 Exp_Ldst (opcode, src_tn, sym, ofst, FALSE, TRUE, FALSE, ops, variant);
01155 if (TN_register_class(src_tn) == ISA_REGISTER_CLASS_mmx)
01156 Build_OP(TOP_emms, ops);
01157 }
01158
01159 static ISA_ENUM_CLASS_VALUE
01160 Pick_Prefetch_Hint (VARIANT variant)
01161 {
01162 UINT32 pf_flags = V_pf_flags(variant);
01163 if (PF_GET_READ(pf_flags)) {
01164 if (PF_GET_STRIDE_1L(pf_flags))
01165 return ECV_pfhint_L1_load;
01166 else return ECV_pfhint_L2_load;
01167 }
01168 else {
01169 if (PF_GET_STRIDE_1L(pf_flags))
01170 return ECV_pfhint_L1_store;
01171 else return ECV_pfhint_L2_store;
01172 }
01173 }
01174
01175 void Exp_Prefetch (TOP opc, TN* src1, TN* src2, VARIANT variant, OPS* ops)
01176 {
01177 FmtAssert(opc == TOP_UNDEFINED,
01178 ("Prefetch opcode should be selected in Exp_Prefetch"));
01179 const UINT32 pf_flags = V_pf_flags(variant);
01180 const ISA_ENUM_CLASS_VALUE pfhint = Pick_Prefetch_Hint(variant);
01181 TOP top;
01182
01183 if( PF_GET_WRITE(pf_flags) ){
01184 if( pfhint != ECV_pfhint_L1_store ){
01185 Build_OP( TOP_noop, ops );
01186 return;
01187 }
01188 if ( !Is_Target_3DNow() )
01189 #ifdef KEY //bug 10953: LNO wants prefetchna for non-temporal prefetch
01190 top = PF_GET_NON_TEMPORAL(pf_flags) ? TOP_prefetchnta : TOP_prefetcht0;
01191 #else
01192 top = TOP_prefetcht0;
01193 #endif
01194 else
01195 top = TOP_prefetchw;
01196
01197 } else {
01198 if( pfhint == ECV_pfhint_L1_load )
01199 {
01200 if ( !Is_Target_3DNow() )
01201 #ifdef KEY //bug 10953: LNO wants prefetchna for non-temporal prefetch
01202 top = PF_GET_NON_TEMPORAL(pf_flags) ? TOP_prefetchnta : TOP_prefetcht0;
01203 #else
01204 top = TOP_prefetcht0;
01205 #endif
01206 else
01207 top = TOP_prefetch;
01208 }
01209 else if( pfhint == ECV_pfhint_L2_load )
01210 top = TOP_prefetcht1;
01211 else
01212 FmtAssert( false, ("NYI") );
01213 }
01214
01215 Build_OP( top, Gen_Enum_TN(pfhint), src1, src2, ops );
01216 }
01217
01218
01219
01220
01221 void Exp_Extract_Bits (TYPE_ID rtype, TYPE_ID desc, UINT bit_offset, UINT bit_size,
01222 TN *tgt_tn, TN *src_tn, OPS *ops)
01223 {
01224 TN *tmp1_tn = Build_TN_Like (tgt_tn);
01225 UINT pos = (Target_Byte_Sex == BIG_ENDIAN || CG_emit_non_gas_syntax)
01226 ? MTYPE_bit_size(desc)-bit_offset-bit_size : bit_offset;
01227 if (pos == 0 && bit_size <= 16 && ! MTYPE_signed(rtype)) {
01228
01229 if( OP_NEED_PAIR(rtype) &&
01230 !OP_NEED_PAIR(desc) ){
01231 TN* tn_hi = Create_TN_Pair( tgt_tn, rtype );
01232 Exp_Immediate( tn_hi, Gen_Literal_TN(0,4), FALSE, ops );
01233 }
01234
01235 Expand_Binary_And( tgt_tn, src_tn, Gen_Literal_TN((1 << bit_size)-1, 4),
01236 desc, ops );
01237 return;
01238 }
01239
01240 INT left_shift_amt = MTYPE_bit_size(rtype) - pos - bit_size;
01241 Expand_Shift( tmp1_tn, src_tn, Gen_Literal_TN(left_shift_amt, 4),
01242 rtype, shift_left, ops );
01243
01244 INT right_shift_amt = MTYPE_bit_size(rtype) - bit_size;
01245 Expand_Shift( tgt_tn, tmp1_tn, Gen_Literal_TN(right_shift_amt, 4),
01246 rtype, MTYPE_is_signed(rtype) ? shift_aright : shift_lright, ops );
01247 }
01248
01249
01250
01251
01252 UINT64 Bitmask_Of_Size(INT bsize)
01253 {
01254 Is_True(bsize != 0, ("Bitmask_Of_Size: bsize cannot be 0"));
01255 if (bsize >= 64)
01256 return UINT64_MAX;
01257 return ((UINT64) 1 << bsize) - 1;
01258 }
01259
01260
01261
01262
01263
01264 void Exp_Set_Bits(TYPE_ID rtype, TYPE_ID desc, UINT bit_offset, UINT bit_size,
01265 TN *tgt_tn, TN *src1_tn, OPS *ops)
01266 {
01267 if (!bit_size) return;
01268
01269 UINT targ_bit_offset = bit_offset;
01270 if (Target_Byte_Sex == BIG_ENDIAN) {
01271 targ_bit_offset = MTYPE_bit_size(desc) - bit_offset - bit_size;
01272 }
01273
01274 UINT64 bitmask = Bitmask_Of_Size(bit_size) << targ_bit_offset;
01275 TN *tmp1_tn;
01276 if (MTYPE_byte_size(rtype) <= 4 ||
01277 ISA_LC_Value_In_Class(bitmask, LC_simm32))
01278 tmp1_tn = Gen_Literal_TN(bitmask, MTYPE_byte_size(rtype));
01279 else {
01280 tmp1_tn = Build_TN_Like(tgt_tn);
01281 if( Is_Target_32bit() &&
01282 MTYPE_is_size_double(rtype) &&
01283 Get_TN_Pair(tmp1_tn) == 0 )
01284 (void *) Create_TN_Pair( tmp1_tn, rtype );
01285 Exp_Immediate(tmp1_tn, Gen_Literal_TN(bitmask, MTYPE_byte_size(rtype)),
01286 FALSE, ops );
01287 }
01288
01289 Expand_Binary_Or( tgt_tn, src1_tn, tmp1_tn, rtype, ops );
01290 }
01291
01292
01293
01294
01295
01296
01297 void Exp_Deposit_Bits2(TYPE_ID rtype, TYPE_ID desc, UINT bit_offset, UINT bit_size,
01298 TN *tgt_tn, TN *src1_tn, TN *src2_tn, OPS *ops)
01299 {
01300 if (!bit_size) return;
01301
01302 UINT targ_bit_offset = bit_offset;
01303 if (Target_Byte_Sex == BIG_ENDIAN) {
01304 targ_bit_offset = MTYPE_bit_size(desc) - bit_offset - bit_size;
01305 }
01306
01307 if( Is_Target_32bit() &&
01308 MTYPE_is_size_double(rtype) &&
01309 Get_TN_Pair(src2_tn) == 0 ){
01310 TN* pair = Create_TN_Pair( src2_tn, rtype );
01311 Exp_Immediate( pair, Gen_Literal_TN(0,4), false, ops );
01312 }
01313
01314
01315 TN *tmp1_tn = Build_TN_Like(tgt_tn);
01316 int shift_amt = MTYPE_bit_size(rtype) - bit_size;
01317 Expand_Shift( tmp1_tn, src2_tn, Gen_Literal_TN(shift_amt, 4),
01318 rtype, shift_left, ops );
01319
01320 shift_amt = MTYPE_bit_size(rtype) - bit_size - targ_bit_offset;
01321 Expand_Shift( tmp1_tn, tmp1_tn, Gen_Literal_TN(shift_amt, 4),
01322 rtype, shift_lright, ops );
01323
01324 UINT64 bitmask = ~(Bitmask_Of_Size(bit_size) << targ_bit_offset);
01325 if (MTYPE_byte_size(rtype) <= 4)
01326 bitmask &= Bitmask_Of_Size(MTYPE_byte_size(rtype) * 8);
01327 TN *tmp2_tn;
01328 if (MTYPE_byte_size(rtype) <= 4 ||
01329 ISA_LC_Value_In_Class(bitmask, LC_simm32))
01330 tmp2_tn = Gen_Literal_TN(bitmask, MTYPE_byte_size(rtype));
01331 else {
01332 tmp2_tn = Build_TN_Like(tgt_tn);
01333 if( Is_Target_32bit() &&
01334 MTYPE_is_size_double(rtype) &&
01335 Get_TN_Pair(tmp2_tn) == 0 )
01336 (void *) Create_TN_Pair( tmp2_tn, rtype );
01337 Exp_Immediate(tmp2_tn, Gen_Literal_TN(bitmask, MTYPE_byte_size(rtype)),
01338 FALSE, ops );
01339 }
01340
01341 Expand_Binary_And( tgt_tn, tmp2_tn, src1_tn, rtype, ops );
01342 Expand_Binary_Or( tgt_tn, tgt_tn, tmp1_tn, rtype, ops );
01343 }
01344
01345
01346
01347
01348
01349 void Exp_Deposit_Bits (TYPE_ID rtype, TYPE_ID desc, UINT bit_offset, UINT bit_size,
01350 TN *tgt_tn, TN *src1_tn, TN *src2_tn, OPS *ops)
01351 {
01352 if (CG_valgrind_friendly) {
01353 Exp_Deposit_Bits2(rtype, desc, bit_offset, bit_size, tgt_tn, src1_tn, src2_tn, ops);
01354 return;
01355 }
01356
01357 if (!bit_size) return;
01358
01359 UINT targ_bit_offset = bit_offset;
01360 if (Target_Byte_Sex == BIG_ENDIAN) {
01361 targ_bit_offset = MTYPE_bit_size(desc) - bit_offset - bit_size;
01362 }
01363 TN *tmp1_tn = Build_TN_Like(tgt_tn);
01364
01365 Expand_Shift( tmp1_tn, src1_tn, Gen_Literal_TN(targ_bit_offset,4),
01366 rtype, shift_lright, ops );
01367
01368 if( Is_Target_32bit() &&
01369 MTYPE_is_size_double(rtype) &&
01370 Get_TN_Pair(src2_tn) == 0 ){
01371 TN* pair = Create_TN_Pair( src2_tn, rtype );
01372 Exp_Immediate( pair, Gen_Literal_TN(0,4), false, ops );
01373 }
01374
01375 Expand_Binary_Xor( tmp1_tn, tmp1_tn, src2_tn, rtype, ops );
01376
01377 int shift_amt = MTYPE_bit_size(rtype) - bit_size;
01378 Expand_Shift( tmp1_tn, tmp1_tn, Gen_Literal_TN(shift_amt, 4),
01379 rtype, shift_left, ops );
01380
01381 shift_amt = MTYPE_bit_size(rtype) - bit_size - targ_bit_offset;
01382 Expand_Shift( tmp1_tn, tmp1_tn, Gen_Literal_TN(shift_amt, 4),
01383 rtype, shift_lright, ops );
01384
01385 Expand_Binary_Xor( tgt_tn, src1_tn, tmp1_tn, rtype, ops );
01386 }
01387
01388 void
01389 Expand_Lda_Label (TN *dest, TN *lab, OPS *ops)
01390 {
01391 Exp_Immediate(dest, lab, FALSE, ops);
01392 #if 0
01393 if (Use_32_Bit_Pointers)
01394 Build_OP(TOP_ld32, dest, rip, lab, ops);
01395 else
01396 Build_OP(TOP_ld64, dest, rip, lab, ops);
01397 #endif
01398 }