00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "rtl.h"
00029 #include "tree.h"
00030 #include "tm_p.h"
00031 #include "regs.h"
00032 #include "hard-reg-set.h"
00033 #include "real.h"
00034 #include "insn-config.h"
00035 #include "conditions.h"
00036 #include "output.h"
00037 #include "insn-attr.h"
00038 #include "flags.h"
00039 #include "except.h"
00040 #include "function.h"
00041 #include "recog.h"
00042 #include "expr.h"
00043 #include "reload.h"
00044 #include "toplev.h"
00045 #include "basic-block.h"
00046 #include "integrate.h"
00047 #include "ggc.h"
00048 #include "target.h"
00049 #include "target-def.h"
00050 #include "debug.h"
00051 #include "langhooks.h"
00052 #include "optabs.h"
00053 #include "tree-gimple.h"
00054
00055
00056
00057
00058 struct processor_costs
00059 {
00060
00061 const int m;
00062 const int mghi;
00063 const int mh;
00064 const int mhi;
00065 const int ml;
00066 const int mr;
00067 const int ms;
00068 const int msg;
00069 const int msgf;
00070 const int msgfr;
00071 const int msgr;
00072 const int msr;
00073 const int mult_df;
00074 const int mxbr;
00075
00076 const int sqxbr;
00077 const int sqdbr;
00078 const int sqebr;
00079
00080 const int madbr;
00081 const int maebr;
00082
00083 const int dxbr;
00084 const int dxr;
00085 const int ddbr;
00086 const int ddr;
00087 const int debr;
00088 const int der;
00089 const int dlgr;
00090 const int dlr;
00091 const int dr;
00092 const int dsgfr;
00093 const int dsgr;
00094 };
00095
00096 const struct processor_costs *s390_cost;
00097
00098 static const
00099 struct processor_costs z900_cost =
00100 {
00101 COSTS_N_INSNS (5),
00102 COSTS_N_INSNS (10),
00103 COSTS_N_INSNS (5),
00104 COSTS_N_INSNS (4),
00105 COSTS_N_INSNS (5),
00106 COSTS_N_INSNS (5),
00107 COSTS_N_INSNS (4),
00108 COSTS_N_INSNS (15),
00109 COSTS_N_INSNS (7),
00110 COSTS_N_INSNS (7),
00111 COSTS_N_INSNS (10),
00112 COSTS_N_INSNS (4),
00113 COSTS_N_INSNS (7),
00114 COSTS_N_INSNS (13),
00115 COSTS_N_INSNS (136),
00116 COSTS_N_INSNS (44),
00117 COSTS_N_INSNS (35),
00118 COSTS_N_INSNS (18),
00119 COSTS_N_INSNS (13),
00120 COSTS_N_INSNS (134),
00121 COSTS_N_INSNS (135),
00122 COSTS_N_INSNS (30),
00123 COSTS_N_INSNS (30),
00124 COSTS_N_INSNS (27),
00125 COSTS_N_INSNS (26),
00126 COSTS_N_INSNS (220),
00127 COSTS_N_INSNS (34),
00128 COSTS_N_INSNS (34),
00129 COSTS_N_INSNS (32),
00130 COSTS_N_INSNS (32),
00131 };
00132
00133 static const
00134 struct processor_costs z990_cost =
00135 {
00136 COSTS_N_INSNS (4),
00137 COSTS_N_INSNS (2),
00138 COSTS_N_INSNS (2),
00139 COSTS_N_INSNS (2),
00140 COSTS_N_INSNS (4),
00141 COSTS_N_INSNS (4),
00142 COSTS_N_INSNS (5),
00143 COSTS_N_INSNS (6),
00144 COSTS_N_INSNS (4),
00145 COSTS_N_INSNS (4),
00146 COSTS_N_INSNS (4),
00147 COSTS_N_INSNS (4),
00148 COSTS_N_INSNS (1),
00149 COSTS_N_INSNS (28),
00150 COSTS_N_INSNS (130),
00151 COSTS_N_INSNS (66),
00152 COSTS_N_INSNS (38),
00153 COSTS_N_INSNS (1),
00154 COSTS_N_INSNS (1),
00155 COSTS_N_INSNS (60),
00156 COSTS_N_INSNS (72),
00157 COSTS_N_INSNS (40),
00158 COSTS_N_INSNS (44),
00159 COSTS_N_INSNS (26),
00160 COSTS_N_INSNS (28),
00161 COSTS_N_INSNS (176),
00162 COSTS_N_INSNS (31),
00163 COSTS_N_INSNS (31),
00164 COSTS_N_INSNS (31),
00165 COSTS_N_INSNS (31),
00166 };
00167
00168 static const
00169 struct processor_costs z9_109_cost =
00170 {
00171 COSTS_N_INSNS (4),
00172 COSTS_N_INSNS (2),
00173 COSTS_N_INSNS (2),
00174 COSTS_N_INSNS (2),
00175 COSTS_N_INSNS (4),
00176 COSTS_N_INSNS (4),
00177 COSTS_N_INSNS (5),
00178 COSTS_N_INSNS (6),
00179 COSTS_N_INSNS (4),
00180 COSTS_N_INSNS (4),
00181 COSTS_N_INSNS (4),
00182 COSTS_N_INSNS (4),
00183 COSTS_N_INSNS (1),
00184 COSTS_N_INSNS (28),
00185 COSTS_N_INSNS (130),
00186 COSTS_N_INSNS (66),
00187 COSTS_N_INSNS (38),
00188 COSTS_N_INSNS (1),
00189 COSTS_N_INSNS (1),
00190 COSTS_N_INSNS (60),
00191 COSTS_N_INSNS (72),
00192 COSTS_N_INSNS (40),
00193 COSTS_N_INSNS (37),
00194 COSTS_N_INSNS (26),
00195 COSTS_N_INSNS (28),
00196 COSTS_N_INSNS (30),
00197 COSTS_N_INSNS (23),
00198 COSTS_N_INSNS (23),
00199 COSTS_N_INSNS (24),
00200 COSTS_N_INSNS (24),
00201 };
00202
00203 extern int reload_completed;
00204
00205
00206
00207 rtx s390_compare_op0, s390_compare_op1;
00208
00209
00210
00211 rtx s390_compare_emitted = NULL_RTX;
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 struct s390_address
00223 {
00224 rtx base;
00225 rtx indx;
00226 rtx disp;
00227 bool pointer;
00228 bool literal_pool;
00229 };
00230
00231
00232 enum processor_type s390_tune = PROCESSOR_max;
00233 enum processor_flags s390_tune_flags;
00234
00235 enum processor_type s390_arch;
00236 enum processor_flags s390_arch_flags;
00237
00238 HOST_WIDE_INT s390_warn_framesize = 0;
00239 HOST_WIDE_INT s390_stack_size = 0;
00240 HOST_WIDE_INT s390_stack_guard = 0;
00241
00242
00243
00244
00245 struct s390_frame_layout GTY (())
00246 {
00247
00248 HOST_WIDE_INT gprs_offset;
00249 HOST_WIDE_INT f0_offset;
00250 HOST_WIDE_INT f4_offset;
00251 HOST_WIDE_INT f8_offset;
00252 HOST_WIDE_INT backchain_offset;
00253
00254
00255
00256 int first_save_gpr_slot;
00257 int last_save_gpr_slot;
00258
00259
00260 int first_save_gpr;
00261 int first_restore_gpr;
00262 int last_save_gpr;
00263 int last_restore_gpr;
00264
00265
00266
00267
00268
00269
00270
00271 unsigned int fpr_bitmap;
00272
00273
00274 int high_fprs;
00275
00276
00277
00278
00279
00280 bool save_return_addr_p;
00281
00282
00283 HOST_WIDE_INT frame_size;
00284 };
00285
00286
00287
00288 struct machine_function GTY(())
00289 {
00290 struct s390_frame_layout frame_layout;
00291
00292
00293 rtx base_reg;
00294
00295
00296 bool split_branches_pending_p;
00297
00298
00299 bool decomposed_literal_pool_addresses_ok_p;
00300
00301
00302 const char *some_ld_name;
00303
00304 bool has_landing_pad_p;
00305 };
00306
00307
00308
00309 #define cfun_frame_layout (cfun->machine->frame_layout)
00310 #define cfun_save_high_fprs_p (!!cfun_frame_layout.high_fprs)
00311 #define cfun_gprs_save_area_size ((cfun_frame_layout.last_save_gpr_slot - \
00312 cfun_frame_layout.first_save_gpr_slot + 1) * UNITS_PER_WORD)
00313 #define cfun_set_fpr_bit(BITNUM) (cfun->machine->frame_layout.fpr_bitmap |= \
00314 (1 << (BITNUM)))
00315 #define cfun_fpr_bit_p(BITNUM) (!!(cfun->machine->frame_layout.fpr_bitmap & \
00316 (1 << (BITNUM))))
00317
00318
00319 #define GP_ARG_NUM_REG 5
00320 #define FP_ARG_NUM_REG (TARGET_64BIT? 4 : 2)
00321
00322
00323 #define CONST_OK_FOR_J(x) \
00324 CONST_OK_FOR_CONSTRAINT_P((x), 'J', "J")
00325 #define CONST_OK_FOR_K(x) \
00326 CONST_OK_FOR_CONSTRAINT_P((x), 'K', "K")
00327 #define CONST_OK_FOR_Os(x) \
00328 CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Os")
00329 #define CONST_OK_FOR_Op(x) \
00330 CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Op")
00331 #define CONST_OK_FOR_On(x) \
00332 CONST_OK_FOR_CONSTRAINT_P((x), 'O', "On")
00333
00334 #define REGNO_PAIR_OK(REGNO, MODE) \
00335 (HARD_REGNO_NREGS ((REGNO), (MODE)) == 1 || !((REGNO) & 1))
00336
00337
00338 static bool
00339 s390_scalar_mode_supported_p (enum machine_mode mode)
00340 {
00341 if (DECIMAL_FLOAT_MODE_P (mode))
00342 return true;
00343 else
00344 return default_scalar_mode_supported_p (mode);
00345 }
00346
00347
00348
00349 void
00350 s390_set_has_landing_pad_p (bool value)
00351 {
00352 cfun->machine->has_landing_pad_p = value;
00353 }
00354
00355
00356
00357
00358
00359 static enum machine_mode
00360 s390_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
00361 {
00362 if (m1 == m2)
00363 return m1;
00364
00365 switch (m1)
00366 {
00367 case CCZmode:
00368 if (m2 == CCUmode || m2 == CCTmode || m2 == CCZ1mode
00369 || m2 == CCSmode || m2 == CCSRmode || m2 == CCURmode)
00370 return m2;
00371 return VOIDmode;
00372
00373 case CCSmode:
00374 case CCUmode:
00375 case CCTmode:
00376 case CCSRmode:
00377 case CCURmode:
00378 case CCZ1mode:
00379 if (m2 == CCZmode)
00380 return m1;
00381
00382 return VOIDmode;
00383
00384 default:
00385 return VOIDmode;
00386 }
00387 return VOIDmode;
00388 }
00389
00390
00391
00392
00393
00394 static bool
00395 s390_match_ccmode_set (rtx set, enum machine_mode req_mode)
00396 {
00397 enum machine_mode set_mode;
00398
00399 gcc_assert (GET_CODE (set) == SET);
00400
00401 if (GET_CODE (SET_DEST (set)) != REG || !CC_REGNO_P (REGNO (SET_DEST (set))))
00402 return 1;
00403
00404 set_mode = GET_MODE (SET_DEST (set));
00405 switch (set_mode)
00406 {
00407 case CCSmode:
00408 case CCSRmode:
00409 case CCUmode:
00410 case CCURmode:
00411 case CCLmode:
00412 case CCL1mode:
00413 case CCL2mode:
00414 case CCL3mode:
00415 case CCT1mode:
00416 case CCT2mode:
00417 case CCT3mode:
00418 if (req_mode != set_mode)
00419 return 0;
00420 break;
00421
00422 case CCZmode:
00423 if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode
00424 && req_mode != CCSRmode && req_mode != CCURmode)
00425 return 0;
00426 break;
00427
00428 case CCAPmode:
00429 case CCANmode:
00430 if (req_mode != CCAmode)
00431 return 0;
00432 break;
00433
00434 default:
00435 gcc_unreachable ();
00436 }
00437
00438 return (GET_MODE (SET_SRC (set)) == set_mode);
00439 }
00440
00441
00442
00443
00444
00445
00446 bool
00447 s390_match_ccmode (rtx insn, enum machine_mode req_mode)
00448 {
00449 int i;
00450
00451
00452 if (req_mode == VOIDmode)
00453 return false;
00454
00455 if (GET_CODE (PATTERN (insn)) == SET)
00456 return s390_match_ccmode_set (PATTERN (insn), req_mode);
00457
00458 if (GET_CODE (PATTERN (insn)) == PARALLEL)
00459 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
00460 {
00461 rtx set = XVECEXP (PATTERN (insn), 0, i);
00462 if (GET_CODE (set) == SET)
00463 if (!s390_match_ccmode_set (set, req_mode))
00464 return false;
00465 }
00466
00467 return true;
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477 enum machine_mode
00478 s390_tm_ccmode (rtx op1, rtx op2, bool mixed)
00479 {
00480 int bit0, bit1;
00481
00482
00483 if (GET_CODE (op1) != CONST_INT || GET_CODE (op2) != CONST_INT)
00484 return VOIDmode;
00485
00486
00487
00488 if (INTVAL (op2) == 0)
00489 return CCTmode;
00490
00491
00492
00493 if (INTVAL (op2) == INTVAL (op1))
00494 return CCT3mode;
00495
00496
00497
00498
00499
00500 if (mixed)
00501 {
00502 bit1 = exact_log2 (INTVAL (op2));
00503 bit0 = exact_log2 (INTVAL (op1) ^ INTVAL (op2));
00504 if (bit0 != -1 && bit1 != -1)
00505 return bit0 > bit1 ? CCT1mode : CCT2mode;
00506 }
00507
00508 return VOIDmode;
00509 }
00510
00511
00512
00513
00514
00515 enum machine_mode
00516 s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
00517 {
00518 switch (code)
00519 {
00520 case EQ:
00521 case NE:
00522 if ((GET_CODE (op0) == NEG || GET_CODE (op0) == ABS)
00523 && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
00524 return CCAPmode;
00525 if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
00526 && CONST_OK_FOR_K (INTVAL (XEXP (op0, 1))))
00527 return CCAPmode;
00528 if ((GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
00529 || GET_CODE (op1) == NEG)
00530 && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
00531 return CCLmode;
00532
00533 if (GET_CODE (op0) == AND)
00534 {
00535
00536 enum machine_mode ccmode;
00537 ccmode = s390_tm_ccmode (XEXP (op0, 1), op1, 1);
00538 if (ccmode != VOIDmode)
00539 {
00540
00541
00542 return ccmode == CCTmode ? CCZmode : ccmode;
00543 }
00544 }
00545
00546 if (register_operand (op0, HImode)
00547 && GET_CODE (op1) == CONST_INT
00548 && (INTVAL (op1) == -1 || INTVAL (op1) == 65535))
00549 return CCT3mode;
00550 if (register_operand (op0, QImode)
00551 && GET_CODE (op1) == CONST_INT
00552 && (INTVAL (op1) == -1 || INTVAL (op1) == 255))
00553 return CCT3mode;
00554
00555 return CCZmode;
00556
00557 case LE:
00558 case LT:
00559 case GE:
00560 case GT:
00561
00562
00563
00564
00565 if ((GET_CODE (op0) == NEG || GET_CODE (op0) == ABS)
00566 && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
00567 return CCAPmode;
00568
00569
00570
00571
00572
00573
00574 if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
00575 && CONST_OK_FOR_K (INTVAL (XEXP (op0, 1))))
00576 {
00577 if (INTVAL (XEXP((op0), 1)) < 0)
00578 return CCANmode;
00579 else
00580 return CCAPmode;
00581 }
00582
00583 case UNORDERED:
00584 case ORDERED:
00585 case UNEQ:
00586 case UNLE:
00587 case UNLT:
00588 case UNGE:
00589 case UNGT:
00590 case LTGT:
00591 if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
00592 && GET_CODE (op1) != CONST_INT)
00593 return CCSRmode;
00594 return CCSmode;
00595
00596 case LTU:
00597 case GEU:
00598 if (GET_CODE (op0) == PLUS
00599 && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
00600 return CCL1mode;
00601
00602 if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
00603 && GET_CODE (op1) != CONST_INT)
00604 return CCURmode;
00605 return CCUmode;
00606
00607 case LEU:
00608 case GTU:
00609 if (GET_CODE (op0) == MINUS
00610 && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
00611 return CCL2mode;
00612
00613 if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
00614 && GET_CODE (op1) != CONST_INT)
00615 return CCURmode;
00616 return CCUmode;
00617
00618 default:
00619 gcc_unreachable ();
00620 }
00621 }
00622
00623
00624
00625
00626 void
00627 s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
00628 {
00629
00630 if ((*code == EQ || *code == NE)
00631 && *op1 == const0_rtx
00632 && GET_CODE (*op0) == ZERO_EXTRACT
00633 && GET_CODE (XEXP (*op0, 1)) == CONST_INT
00634 && GET_CODE (XEXP (*op0, 2)) == CONST_INT
00635 && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0))))
00636 {
00637 rtx inner = XEXP (*op0, 0);
00638 HOST_WIDE_INT modesize = GET_MODE_BITSIZE (GET_MODE (inner));
00639 HOST_WIDE_INT len = INTVAL (XEXP (*op0, 1));
00640 HOST_WIDE_INT pos = INTVAL (XEXP (*op0, 2));
00641
00642 if (len > 0 && len < modesize
00643 && pos >= 0 && pos + len <= modesize
00644 && modesize <= HOST_BITS_PER_WIDE_INT)
00645 {
00646 unsigned HOST_WIDE_INT block;
00647 block = ((unsigned HOST_WIDE_INT) 1 << len) - 1;
00648 block <<= modesize - pos - len;
00649
00650 *op0 = gen_rtx_AND (GET_MODE (inner), inner,
00651 gen_int_mode (block, GET_MODE (inner)));
00652 }
00653 }
00654
00655
00656 if ((*code == EQ || *code == NE)
00657 && *op1 == const0_rtx
00658 && GET_CODE (*op0) == AND
00659 && GET_CODE (XEXP (*op0, 1)) == CONST_INT
00660 && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0))))
00661 {
00662 rtx inner = XEXP (*op0, 0);
00663 rtx mask = XEXP (*op0, 1);
00664
00665
00666 if (GET_CODE (inner) == SUBREG
00667 && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (inner)))
00668 && (GET_MODE_SIZE (GET_MODE (inner))
00669 >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner))))
00670 && ((INTVAL (mask)
00671 & GET_MODE_MASK (GET_MODE (inner))
00672 & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (inner))))
00673 == 0))
00674 inner = SUBREG_REG (inner);
00675
00676
00677 if (MEM_P (inner) && !MEM_VOLATILE_P (inner))
00678 {
00679 int part = s390_single_part (XEXP (*op0, 1),
00680 GET_MODE (inner), QImode, 0);
00681 if (part >= 0)
00682 {
00683 mask = gen_int_mode (s390_extract_part (mask, QImode, 0), QImode);
00684 inner = adjust_address_nv (inner, QImode, part);
00685 *op0 = gen_rtx_AND (QImode, inner, mask);
00686 }
00687 }
00688 }
00689
00690
00691 if ((*code == EQ || *code == NE)
00692 && GET_CODE (*op1) == CONST_INT
00693 && INTVAL (*op1) == 0xffff
00694 && SCALAR_INT_MODE_P (GET_MODE (*op0))
00695 && (nonzero_bits (*op0, GET_MODE (*op0))
00696 & ~(unsigned HOST_WIDE_INT) 0xffff) == 0)
00697 {
00698 *op0 = gen_lowpart (HImode, *op0);
00699 *op1 = constm1_rtx;
00700 }
00701
00702
00703
00704 if (GET_CODE (*op0) == UNSPEC
00705 && XINT (*op0, 1) == UNSPEC_CMPINT
00706 && XVECLEN (*op0, 0) == 1
00707 && GET_MODE (XVECEXP (*op0, 0, 0)) == CCUmode
00708 && GET_CODE (XVECEXP (*op0, 0, 0)) == REG
00709 && REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM
00710 && *op1 == const0_rtx)
00711 {
00712 enum rtx_code new_code = UNKNOWN;
00713 switch (*code)
00714 {
00715 case EQ: new_code = EQ; break;
00716 case NE: new_code = NE; break;
00717 case LT: new_code = GTU; break;
00718 case GT: new_code = LTU; break;
00719 case LE: new_code = GEU; break;
00720 case GE: new_code = LEU; break;
00721 default: break;
00722 }
00723
00724 if (new_code != UNKNOWN)
00725 {
00726 *op0 = XVECEXP (*op0, 0, 0);
00727 *code = new_code;
00728 }
00729 }
00730
00731
00732 if ((*code == NE || *code == EQ)
00733 && (GET_CODE (*op0) == EQ || GET_CODE (*op0) == NE)
00734 && GET_MODE (*op0) == SImode
00735 && GET_MODE (XEXP (*op0, 0)) == CCZ1mode
00736 && REG_P (XEXP (*op0, 0))
00737 && XEXP (*op0, 1) == const0_rtx
00738 && *op1 == const0_rtx)
00739 {
00740 if ((*code == EQ && GET_CODE (*op0) == NE)
00741 || (*code == NE && GET_CODE (*op0) == EQ))
00742 *code = EQ;
00743 else
00744 *code = NE;
00745 *op0 = XEXP (*op0, 0);
00746 }
00747
00748
00749 if (MEM_P (*op0) && REG_P (*op1))
00750 {
00751 rtx tem = *op0; *op0 = *op1; *op1 = tem;
00752 *code = swap_condition (*code);
00753 }
00754 }
00755
00756
00757
00758
00759
00760 rtx
00761 s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
00762 {
00763 enum machine_mode mode = s390_select_ccmode (code, op0, op1);
00764 rtx ret = NULL_RTX;
00765
00766
00767
00768 if (s390_compare_emitted
00769 && (s390_cc_modes_compatible (GET_MODE (s390_compare_emitted), mode)
00770 == GET_MODE (s390_compare_emitted)))
00771 ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx);
00772 else
00773 {
00774 rtx cc = gen_rtx_REG (mode, CC_REGNUM);
00775
00776 emit_insn (gen_rtx_SET (VOIDmode, cc, gen_rtx_COMPARE (mode, op0, op1)));
00777 ret = gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx);
00778 }
00779 s390_compare_emitted = NULL_RTX;
00780 return ret;
00781 }
00782
00783
00784
00785
00786
00787
00788 static rtx
00789 s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem, rtx cmp, rtx new)
00790 {
00791 rtx ret;
00792
00793 emit_insn (gen_sync_compare_and_swap_ccsi (old, mem, cmp, new));
00794 ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx);
00795
00796 s390_compare_emitted = NULL_RTX;
00797
00798 return ret;
00799 }
00800
00801
00802
00803
00804 void
00805 s390_emit_jump (rtx target, rtx cond)
00806 {
00807 rtx insn;
00808
00809 target = gen_rtx_LABEL_REF (VOIDmode, target);
00810 if (cond)
00811 target = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, target, pc_rtx);
00812
00813 insn = gen_rtx_SET (VOIDmode, pc_rtx, target);
00814 emit_jump_insn (insn);
00815 }
00816
00817
00818
00819
00820 int
00821 s390_branch_condition_mask (rtx code)
00822 {
00823 const int CC0 = 1 << 3;
00824 const int CC1 = 1 << 2;
00825 const int CC2 = 1 << 1;
00826 const int CC3 = 1 << 0;
00827
00828 gcc_assert (GET_CODE (XEXP (code, 0)) == REG);
00829 gcc_assert (REGNO (XEXP (code, 0)) == CC_REGNUM);
00830 gcc_assert (XEXP (code, 1) == const0_rtx);
00831
00832 switch (GET_MODE (XEXP (code, 0)))
00833 {
00834 case CCZmode:
00835 case CCZ1mode:
00836 switch (GET_CODE (code))
00837 {
00838 case EQ: return CC0;
00839 case NE: return CC1 | CC2 | CC3;
00840 default: return -1;
00841 }
00842 break;
00843
00844 case CCT1mode:
00845 switch (GET_CODE (code))
00846 {
00847 case EQ: return CC1;
00848 case NE: return CC0 | CC2 | CC3;
00849 default: return -1;
00850 }
00851 break;
00852
00853 case CCT2mode:
00854 switch (GET_CODE (code))
00855 {
00856 case EQ: return CC2;
00857 case NE: return CC0 | CC1 | CC3;
00858 default: return -1;
00859 }
00860 break;
00861
00862 case CCT3mode:
00863 switch (GET_CODE (code))
00864 {
00865 case EQ: return CC3;
00866 case NE: return CC0 | CC1 | CC2;
00867 default: return -1;
00868 }
00869 break;
00870
00871 case CCLmode:
00872 switch (GET_CODE (code))
00873 {
00874 case EQ: return CC0 | CC2;
00875 case NE: return CC1 | CC3;
00876 default: return -1;
00877 }
00878 break;
00879
00880 case CCL1mode:
00881 switch (GET_CODE (code))
00882 {
00883 case LTU: return CC2 | CC3;
00884 case GEU: return CC0 | CC1;
00885 default: return -1;
00886 }
00887 break;
00888
00889 case CCL2mode:
00890 switch (GET_CODE (code))
00891 {
00892 case GTU: return CC0 | CC1;
00893 case LEU: return CC2 | CC3;
00894 default: return -1;
00895 }
00896 break;
00897
00898 case CCL3mode:
00899 switch (GET_CODE (code))
00900 {
00901 case EQ: return CC0 | CC2;
00902 case NE: return CC1 | CC3;
00903 case LTU: return CC1;
00904 case GTU: return CC3;
00905 case LEU: return CC1 | CC2;
00906 case GEU: return CC2 | CC3;
00907 default: return -1;
00908 }
00909
00910 case CCUmode:
00911 switch (GET_CODE (code))
00912 {
00913 case EQ: return CC0;
00914 case NE: return CC1 | CC2 | CC3;
00915 case LTU: return CC1;
00916 case GTU: return CC2;
00917 case LEU: return CC0 | CC1;
00918 case GEU: return CC0 | CC2;
00919 default: return -1;
00920 }
00921 break;
00922
00923 case CCURmode:
00924 switch (GET_CODE (code))
00925 {
00926 case EQ: return CC0;
00927 case NE: return CC2 | CC1 | CC3;
00928 case LTU: return CC2;
00929 case GTU: return CC1;
00930 case LEU: return CC0 | CC2;
00931 case GEU: return CC0 | CC1;
00932 default: return -1;
00933 }
00934 break;
00935
00936 case CCAPmode:
00937 switch (GET_CODE (code))
00938 {
00939 case EQ: return CC0;
00940 case NE: return CC1 | CC2 | CC3;
00941 case LT: return CC1 | CC3;
00942 case GT: return CC2;
00943 case LE: return CC0 | CC1 | CC3;
00944 case GE: return CC0 | CC2;
00945 default: return -1;
00946 }
00947 break;
00948
00949 case CCANmode:
00950 switch (GET_CODE (code))
00951 {
00952 case EQ: return CC0;
00953 case NE: return CC1 | CC2 | CC3;
00954 case LT: return CC1;
00955 case GT: return CC2 | CC3;
00956 case LE: return CC0 | CC1;
00957 case GE: return CC0 | CC2 | CC3;
00958 default: return -1;
00959 }
00960 break;
00961
00962 case CCSmode:
00963 switch (GET_CODE (code))
00964 {
00965 case EQ: return CC0;
00966 case NE: return CC1 | CC2 | CC3;
00967 case LT: return CC1;
00968 case GT: return CC2;
00969 case LE: return CC0 | CC1;
00970 case GE: return CC0 | CC2;
00971 case UNORDERED: return CC3;
00972 case ORDERED: return CC0 | CC1 | CC2;
00973 case UNEQ: return CC0 | CC3;
00974 case UNLT: return CC1 | CC3;
00975 case UNGT: return CC2 | CC3;
00976 case UNLE: return CC0 | CC1 | CC3;
00977 case UNGE: return CC0 | CC2 | CC3;
00978 case LTGT: return CC1 | CC2;
00979 default: return -1;
00980 }
00981 break;
00982
00983 case CCSRmode:
00984 switch (GET_CODE (code))
00985 {
00986 case EQ: return CC0;
00987 case NE: return CC2 | CC1 | CC3;
00988 case LT: return CC2;
00989 case GT: return CC1;
00990 case LE: return CC0 | CC2;
00991 case GE: return CC0 | CC1;
00992 case UNORDERED: return CC3;
00993 case ORDERED: return CC0 | CC2 | CC1;
00994 case UNEQ: return CC0 | CC3;
00995 case UNLT: return CC2 | CC3;
00996 case UNGT: return CC1 | CC3;
00997 case UNLE: return CC0 | CC2 | CC3;
00998 case UNGE: return CC0 | CC1 | CC3;
00999 case LTGT: return CC2 | CC1;
01000 default: return -1;
01001 }
01002 break;
01003
01004 default:
01005 return -1;
01006 }
01007 }
01008
01009
01010
01011
01012
01013 static const char *
01014 s390_branch_condition_mnemonic (rtx code, int inv)
01015 {
01016 static const char *const mnemonic[16] =
01017 {
01018 NULL, "o", "h", "nle",
01019 "l", "nhe", "lh", "ne",
01020 "e", "nlh", "he", "nl",
01021 "le", "nh", "no", NULL
01022 };
01023
01024 int mask = s390_branch_condition_mask (code);
01025 gcc_assert (mask >= 0);
01026
01027 if (inv)
01028 mask ^= 15;
01029
01030 gcc_assert (mask >= 1 && mask <= 14);
01031
01032 return mnemonic[mask];
01033 }
01034
01035
01036
01037
01038
01039
01040 unsigned HOST_WIDE_INT
01041 s390_extract_part (rtx op, enum machine_mode mode, int def)
01042 {
01043 unsigned HOST_WIDE_INT value = 0;
01044 int max_parts = HOST_BITS_PER_WIDE_INT / GET_MODE_BITSIZE (mode);
01045 int part_bits = GET_MODE_BITSIZE (mode);
01046 unsigned HOST_WIDE_INT part_mask
01047 = ((unsigned HOST_WIDE_INT)1 << part_bits) - 1;
01048 int i;
01049
01050 for (i = 0; i < max_parts; i++)
01051 {
01052 if (i == 0)
01053 value = (unsigned HOST_WIDE_INT) INTVAL (op);
01054 else
01055 value >>= part_bits;
01056
01057 if ((value & part_mask) != (def & part_mask))
01058 return value & part_mask;
01059 }
01060
01061 gcc_unreachable ();
01062 }
01063
01064
01065
01066
01067
01068 int
01069 s390_single_part (rtx op,
01070 enum machine_mode mode,
01071 enum machine_mode part_mode,
01072 int def)
01073 {
01074 unsigned HOST_WIDE_INT value = 0;
01075 int n_parts = GET_MODE_SIZE (mode) / GET_MODE_SIZE (part_mode);
01076 unsigned HOST_WIDE_INT part_mask
01077 = ((unsigned HOST_WIDE_INT)1 << GET_MODE_BITSIZE (part_mode)) - 1;
01078 int i, part = -1;
01079
01080 if (GET_CODE (op) != CONST_INT)
01081 return -1;
01082
01083 for (i = 0; i < n_parts; i++)
01084 {
01085 if (i == 0)
01086 value = (unsigned HOST_WIDE_INT) INTVAL (op);
01087 else
01088 value >>= GET_MODE_BITSIZE (part_mode);
01089
01090 if ((value & part_mask) != (def & part_mask))
01091 {
01092 if (part != -1)
01093 return -1;
01094 else
01095 part = i;
01096 }
01097 }
01098 return part == -1 ? -1 : n_parts - 1 - part;
01099 }
01100
01101
01102
01103
01104
01105 bool
01106 s390_split_ok_p (rtx dst, rtx src, enum machine_mode mode, int first_subword)
01107 {
01108
01109 if (FP_REG_P (src) || FP_REG_P (dst))
01110 return false;
01111
01112
01113 if (s_operand (src, mode) || s_operand (dst, mode))
01114 return false;
01115
01116
01117 if ((GET_CODE (src) == MEM && !offsettable_memref_p (src))
01118 || (GET_CODE (dst) == MEM && !offsettable_memref_p (dst)))
01119 return false;
01120
01121
01122
01123 if (register_operand (dst, mode))
01124 {
01125 rtx subreg = operand_subword (dst, first_subword, 0, mode);
01126 if (reg_overlap_mentioned_p (subreg, src))
01127 return false;
01128 }
01129
01130 return true;
01131 }
01132
01133
01134
01135
01136
01137 bool
01138 s390_overlap_p (rtx mem1, rtx mem2, HOST_WIDE_INT size)
01139 {
01140 rtx addr1, addr2, addr_delta;
01141 HOST_WIDE_INT delta;
01142
01143 if (GET_CODE (mem1) != MEM || GET_CODE (mem2) != MEM)
01144 return true;
01145
01146 if (size == 0)
01147 return false;
01148
01149 addr1 = XEXP (mem1, 0);
01150 addr2 = XEXP (mem2, 0);
01151
01152 addr_delta = simplify_binary_operation (MINUS, Pmode, addr2, addr1);
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162 if (!addr_delta || GET_CODE (addr_delta) != CONST_INT)
01163 return false;
01164
01165 delta = INTVAL (addr_delta);
01166
01167 if (delta == 0
01168 || (delta > 0 && delta < size)
01169 || (delta < 0 && -delta < size))
01170 return true;
01171
01172 return false;
01173 }
01174
01175
01176
01177
01178
01179 bool
01180 s390_offset_p (rtx mem1, rtx mem2, rtx delta)
01181 {
01182 rtx addr1, addr2, addr_delta;
01183
01184 if (GET_CODE (mem1) != MEM || GET_CODE (mem2) != MEM)
01185 return false;
01186
01187 addr1 = XEXP (mem1, 0);
01188 addr2 = XEXP (mem2, 0);
01189
01190 addr_delta = simplify_binary_operation (MINUS, Pmode, addr2, addr1);
01191 if (!addr_delta || !rtx_equal_p (addr_delta, delta))
01192 return false;
01193
01194 return true;
01195 }
01196
01197
01198
01199 void
01200 s390_expand_logical_operator (enum rtx_code code, enum machine_mode mode,
01201 rtx *operands)
01202 {
01203 enum machine_mode wmode = mode;
01204 rtx dst = operands[0];
01205 rtx src1 = operands[1];
01206 rtx src2 = operands[2];
01207 rtx op, clob, tem;
01208
01209
01210 if (!s390_logical_operator_ok_p (operands))
01211 dst = gen_reg_rtx (mode);
01212
01213
01214
01215 if ((mode == QImode || mode == HImode) && GET_CODE (dst) != MEM)
01216 wmode = SImode;
01217
01218
01219 if (mode != wmode)
01220 {
01221 if (GET_CODE (dst) == SUBREG
01222 && (tem = simplify_subreg (wmode, dst, mode, 0)) != 0)
01223 dst = tem;
01224 else if (REG_P (dst))
01225 dst = gen_rtx_SUBREG (wmode, dst, 0);
01226 else
01227 dst = gen_reg_rtx (wmode);
01228
01229 if (GET_CODE (src1) == SUBREG
01230 && (tem = simplify_subreg (wmode, src1, mode, 0)) != 0)
01231 src1 = tem;
01232 else if (GET_MODE (src1) != VOIDmode)
01233 src1 = gen_rtx_SUBREG (wmode, force_reg (mode, src1), 0);
01234
01235 if (GET_CODE (src2) == SUBREG
01236 && (tem = simplify_subreg (wmode, src2, mode, 0)) != 0)
01237 src2 = tem;
01238 else if (GET_MODE (src2) != VOIDmode)
01239 src2 = gen_rtx_SUBREG (wmode, force_reg (mode, src2), 0);
01240 }
01241
01242
01243 op = gen_rtx_SET (VOIDmode, dst, gen_rtx_fmt_ee (code, wmode, src1, src2));
01244 clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
01245 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
01246
01247
01248 if (dst != operands[0])
01249 emit_move_insn (operands[0], gen_lowpart (mode, dst));
01250 }
01251
01252
01253
01254 bool
01255 s390_logical_operator_ok_p (rtx *operands)
01256 {
01257
01258
01259
01260 if (GET_CODE (operands[0]) == MEM)
01261 return rtx_equal_p (operands[0], operands[1])
01262 || (!reload_completed && rtx_equal_p (operands[0], operands[2]));
01263
01264 return true;
01265 }
01266
01267
01268
01269
01270 void
01271 s390_narrow_logical_operator (enum rtx_code code, rtx *memop, rtx *immop)
01272 {
01273 int def = code == AND ? -1 : 0;
01274 HOST_WIDE_INT mask;
01275 int part;
01276
01277 gcc_assert (GET_CODE (*memop) == MEM);
01278 gcc_assert (!MEM_VOLATILE_P (*memop));
01279
01280 mask = s390_extract_part (*immop, QImode, def);
01281 part = s390_single_part (*immop, GET_MODE (*memop), QImode, def);
01282 gcc_assert (part >= 0);
01283
01284 *memop = adjust_address (*memop, QImode, part);
01285 *immop = gen_int_mode (mask, QImode);
01286 }
01287
01288
01289
01290
01291 static struct machine_function *
01292 s390_init_machine_status (void)
01293 {
01294 return ggc_alloc_cleared (sizeof (struct machine_function));
01295 }
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305 void
01306 optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
01307 {
01308
01309 flag_caller_saves = 0;
01310
01311
01312
01313 flag_asynchronous_unwind_tables = 1;
01314
01315
01316 if (size != 0)
01317 target_flags |= MASK_MVCLE;
01318 }
01319
01320
01321
01322
01323 static bool
01324 s390_handle_arch_option (const char *arg,
01325 enum processor_type *type,
01326 enum processor_flags *flags)
01327 {
01328 static struct pta
01329 {
01330 const char *const name;
01331 const enum processor_type processor;
01332 const enum processor_flags flags;
01333 }
01334 const processor_alias_table[] =
01335 {
01336 {"g5", PROCESSOR_9672_G5, PF_IEEE_FLOAT},
01337 {"g6", PROCESSOR_9672_G6, PF_IEEE_FLOAT},
01338 {"z900", PROCESSOR_2064_Z900, PF_IEEE_FLOAT | PF_ZARCH},
01339 {"z990", PROCESSOR_2084_Z990, PF_IEEE_FLOAT | PF_ZARCH
01340 | PF_LONG_DISPLACEMENT},
01341 {"z9-109", PROCESSOR_2094_Z9_109, PF_IEEE_FLOAT | PF_ZARCH
01342 | PF_LONG_DISPLACEMENT | PF_EXTIMM},
01343 };
01344 size_t i;
01345
01346 for (i = 0; i < ARRAY_SIZE (processor_alias_table); i++)
01347 if (strcmp (arg, processor_alias_table[i].name) == 0)
01348 {
01349 *type = processor_alias_table[i].processor;
01350 *flags = processor_alias_table[i].flags;
01351 return true;
01352 }
01353 return false;
01354 }
01355
01356
01357
01358 static bool
01359 s390_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
01360 {
01361 switch (code)
01362 {
01363 case OPT_march_:
01364 return s390_handle_arch_option (arg, &s390_arch, &s390_arch_flags);
01365
01366 case OPT_mstack_guard_:
01367 if (sscanf (arg, HOST_WIDE_INT_PRINT_DEC, &s390_stack_guard) != 1)
01368 return false;
01369 if (exact_log2 (s390_stack_guard) == -1)
01370 error ("stack guard value must be an exact power of 2");
01371 return true;
01372
01373 case OPT_mstack_size_:
01374 if (sscanf (arg, HOST_WIDE_INT_PRINT_DEC, &s390_stack_size) != 1)
01375 return false;
01376 if (exact_log2 (s390_stack_size) == -1)
01377 error ("stack size must be an exact power of 2");
01378 return true;
01379
01380 case OPT_mtune_:
01381 return s390_handle_arch_option (arg, &s390_tune, &s390_tune_flags);
01382
01383 case OPT_mwarn_framesize_:
01384 return sscanf (arg, HOST_WIDE_INT_PRINT_DEC, &s390_warn_framesize) == 1;
01385
01386 default:
01387 return true;
01388 }
01389 }
01390
01391 void
01392 override_options (void)
01393 {
01394
01395 init_machine_status = s390_init_machine_status;
01396
01397
01398 if (!(target_flags_explicit & MASK_ZARCH))
01399 {
01400 if (TARGET_64BIT)
01401 target_flags |= MASK_ZARCH;
01402 else
01403 target_flags &= ~MASK_ZARCH;
01404 }
01405
01406
01407 if (!s390_arch_string)
01408 {
01409 s390_arch_string = TARGET_ZARCH? "z900" : "g5";
01410 s390_handle_arch_option (s390_arch_string, &s390_arch, &s390_arch_flags);
01411 }
01412
01413
01414 if (s390_tune == PROCESSOR_max)
01415 {
01416 s390_tune = s390_arch;
01417 s390_tune_flags = s390_arch_flags;
01418 }
01419
01420
01421 if (TARGET_ZARCH && !(s390_arch_flags & PF_ZARCH))
01422 error ("z/Architecture mode not supported on %s", s390_arch_string);
01423 if (TARGET_64BIT && !TARGET_ZARCH)
01424 error ("64-bit ABI not supported in ESA/390 mode");
01425
01426
01427 if (s390_tune == PROCESSOR_2094_Z9_109)
01428 s390_cost = &z9_109_cost;
01429 else if (s390_tune == PROCESSOR_2084_Z990)
01430 s390_cost = &z990_cost;
01431 else
01432 s390_cost = &z900_cost;
01433
01434 if (TARGET_BACKCHAIN && TARGET_PACKED_STACK && TARGET_HARD_FLOAT)
01435 error ("-mbackchain -mpacked-stack -mhard-float are not supported "
01436 "in combination");
01437
01438 if (s390_stack_size)
01439 {
01440 if (!s390_stack_guard)
01441 error ("-mstack-size implies use of -mstack-guard");
01442 else if (s390_stack_guard >= s390_stack_size)
01443 error ("stack size must be greater than the stack guard value");
01444 else if (s390_stack_size > 1 << 16)
01445 error ("stack size must not be greater than 64k");
01446 }
01447 else if (s390_stack_guard)
01448 error ("-mstack-guard implies use of -mstack-size");
01449
01450 #ifdef TARGET_DEFAULT_LONG_DOUBLE_128
01451 if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
01452 target_flags |= MASK_LONG_DOUBLE_128;
01453 #endif
01454 }
01455
01456
01457
01458 const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
01459 { GENERAL_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
01460 ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
01461 ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
01462 ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
01463 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
01464 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
01465 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
01466 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
01467 ADDR_REGS, CC_REGS, ADDR_REGS, ADDR_REGS,
01468 ACCESS_REGS, ACCESS_REGS
01469 };
01470
01471
01472
01473 static enum attr_type
01474 s390_safe_attr_type (rtx insn)
01475 {
01476 if (recog_memoized (insn) >= 0)
01477 return get_attr_type (insn);
01478 else
01479 return TYPE_NONE;
01480 }
01481
01482
01483
01484 static bool
01485 s390_short_displacement (rtx disp)
01486 {
01487
01488 if (!disp)
01489 return true;
01490
01491
01492 if (GET_CODE (disp) == CONST_INT)
01493 return INTVAL (disp) >= 0 && INTVAL (disp) < 4096;
01494
01495
01496 if (GET_CODE (disp) == CONST
01497 && GET_CODE (XEXP (disp, 0)) == UNSPEC
01498 && (XINT (XEXP (disp, 0), 1) == UNSPEC_GOT
01499 || XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF))
01500 return false;
01501
01502
01503
01504 if (GET_CODE (disp) == CONST)
01505 return true;
01506
01507 return false;
01508 }
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521 static int
01522 s390_decompose_address (rtx addr, struct s390_address *out)
01523 {
01524 HOST_WIDE_INT offset = 0;
01525 rtx base = NULL_RTX;
01526 rtx indx = NULL_RTX;
01527 rtx disp = NULL_RTX;
01528 rtx orig_disp;
01529 bool pointer = false;
01530 bool base_ptr = false;
01531 bool indx_ptr = false;
01532 bool literal_pool = false;
01533
01534
01535
01536
01537
01538
01539 rtx fake_pool_base = gen_rtx_REG (Pmode, ARG_POINTER_REGNUM);
01540
01541
01542
01543 if (GET_CODE (addr) == REG || GET_CODE (addr) == UNSPEC)
01544 base = addr;
01545
01546 else if (GET_CODE (addr) == PLUS)
01547 {
01548 rtx op0 = XEXP (addr, 0);
01549 rtx op1 = XEXP (addr, 1);
01550 enum rtx_code code0 = GET_CODE (op0);
01551 enum rtx_code code1 = GET_CODE (op1);
01552
01553 if (code0 == REG || code0 == UNSPEC)
01554 {
01555 if (code1 == REG || code1 == UNSPEC)
01556 {
01557 indx = op0;
01558 base = op1;
01559 }
01560
01561 else
01562 {
01563 base = op0;
01564 disp = op1;
01565 }
01566 }
01567
01568 else if (code0 == PLUS)
01569 {
01570 indx = XEXP (op0, 0);
01571 base = XEXP (op0, 1);
01572 disp = op1;
01573 }
01574
01575 else
01576 {
01577 return false;
01578 }
01579 }
01580
01581 else
01582 disp = addr;
01583
01584
01585 orig_disp = disp;
01586 if (disp)
01587 {
01588 if (GET_CODE (disp) == CONST_INT)
01589 {
01590 offset = INTVAL (disp);
01591 disp = NULL_RTX;
01592 }
01593 else if (GET_CODE (disp) == CONST
01594 && GET_CODE (XEXP (disp, 0)) == PLUS
01595 && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
01596 {
01597 offset = INTVAL (XEXP (XEXP (disp, 0), 1));
01598 disp = XEXP (XEXP (disp, 0), 0);
01599 }
01600 }
01601
01602
01603 if (disp && GET_CODE (disp) == CONST)
01604 disp = XEXP (disp, 0);
01605
01606
01607
01608 if (disp && GET_CODE (disp) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (disp))
01609 {
01610
01611 if (!base)
01612 base = fake_pool_base, literal_pool = true;
01613 else if (!indx)
01614 indx = fake_pool_base, literal_pool = true;
01615 else
01616 return false;
01617
01618
01619 disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp),
01620 UNSPEC_LTREL_OFFSET);
01621 }
01622
01623
01624 if (base)
01625 {
01626 if (GET_CODE (base) == UNSPEC)
01627 switch (XINT (base, 1))
01628 {
01629 case UNSPEC_LTREF:
01630 if (!disp)
01631 disp = gen_rtx_UNSPEC (Pmode,
01632 gen_rtvec (1, XVECEXP (base, 0, 0)),
01633 UNSPEC_LTREL_OFFSET);
01634 else
01635 return false;
01636
01637 base = XVECEXP (base, 0, 1);
01638 break;
01639
01640 case UNSPEC_LTREL_BASE:
01641 if (XVECLEN (base, 0) == 1)
01642 base = fake_pool_base, literal_pool = true;
01643 else
01644 base = XVECEXP (base, 0, 1);
01645 break;
01646
01647 default:
01648 return false;
01649 }
01650
01651 if (!REG_P (base)
01652 || (GET_MODE (base) != SImode
01653 && GET_MODE (base) != Pmode))
01654 return false;
01655
01656 if (REGNO (base) == STACK_POINTER_REGNUM
01657 || REGNO (base) == FRAME_POINTER_REGNUM
01658 || ((reload_completed || reload_in_progress)
01659 && frame_pointer_needed
01660 && REGNO (base) == HARD_FRAME_POINTER_REGNUM)
01661 || REGNO (base) == ARG_POINTER_REGNUM
01662 || (flag_pic
01663 && REGNO (base) == PIC_OFFSET_TABLE_REGNUM))
01664 pointer = base_ptr = true;
01665
01666 if ((reload_completed || reload_in_progress)
01667 && base == cfun->machine->base_reg)
01668 pointer = base_ptr = literal_pool = true;
01669 }
01670
01671
01672 if (indx)
01673 {
01674 if (GET_CODE (indx) == UNSPEC)
01675 switch (XINT (indx, 1))
01676 {
01677 case UNSPEC_LTREF:
01678 if (!disp)
01679 disp = gen_rtx_UNSPEC (Pmode,
01680 gen_rtvec (1, XVECEXP (indx, 0, 0)),
01681 UNSPEC_LTREL_OFFSET);
01682 else
01683 return false;
01684
01685 indx = XVECEXP (indx, 0, 1);
01686 break;
01687
01688 case UNSPEC_LTREL_BASE:
01689 if (XVECLEN (indx, 0) == 1)
01690 indx = fake_pool_base, literal_pool = true;
01691 else
01692 indx = XVECEXP (indx, 0, 1);
01693 break;
01694
01695 default:
01696 return false;
01697 }
01698
01699 if (!REG_P (indx)
01700 || (GET_MODE (indx) != SImode
01701 && GET_MODE (indx) != Pmode))
01702 return false;
01703
01704 if (REGNO (indx) == STACK_POINTER_REGNUM
01705 || REGNO (indx) == FRAME_POINTER_REGNUM
01706 || ((reload_completed || reload_in_progress)
01707 && frame_pointer_needed
01708 && REGNO (indx) == HARD_FRAME_POINTER_REGNUM)
01709 || REGNO (indx) == ARG_POINTER_REGNUM
01710 || (flag_pic
01711 && REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))
01712 pointer = indx_ptr = true;
01713
01714 if ((reload_completed || reload_in_progress)
01715 && indx == cfun->machine->base_reg)
01716 pointer = indx_ptr = literal_pool = true;
01717 }
01718
01719
01720 if (base && indx && !base_ptr
01721 && (indx_ptr || (!REG_POINTER (base) && REG_POINTER (indx))))
01722 {
01723 rtx tmp = base;
01724 base = indx;
01725 indx = tmp;
01726 }
01727
01728
01729 if (!disp)
01730 {
01731
01732
01733
01734
01735
01736
01737
01738
01739 if (base != arg_pointer_rtx
01740 && indx != arg_pointer_rtx
01741 && base != return_address_pointer_rtx
01742 && indx != return_address_pointer_rtx
01743 && base != frame_pointer_rtx
01744 && indx != frame_pointer_rtx
01745 && base != virtual_stack_vars_rtx
01746 && indx != virtual_stack_vars_rtx)
01747 if (!DISP_IN_RANGE (offset))
01748 return false;
01749 }
01750 else
01751 {
01752
01753 pointer = true;
01754
01755
01756
01757 if (GET_CODE (disp) == UNSPEC
01758 && (XINT (disp, 1) == UNSPEC_GOT
01759 || XINT (disp, 1) == UNSPEC_GOTNTPOFF)
01760 && flag_pic == 1)
01761 {
01762 ;
01763 }
01764
01765
01766 else if (cfun && cfun->machine
01767 && cfun->machine->decomposed_literal_pool_addresses_ok_p
01768 && GET_CODE (disp) == MINUS
01769 && GET_CODE (XEXP (disp, 0)) == LABEL_REF
01770 && GET_CODE (XEXP (disp, 1)) == LABEL_REF)
01771 {
01772 ;
01773 }
01774
01775
01776 else if (GET_CODE (disp) == UNSPEC
01777 && XINT (disp, 1) == UNSPEC_LTREL_OFFSET)
01778 {
01779 orig_disp = gen_rtx_CONST (Pmode, disp);
01780 if (offset)
01781 {
01782
01783
01784 rtx sym = XVECEXP (disp, 0, 0);
01785 if (offset >= GET_MODE_SIZE (get_pool_mode (sym)))
01786 return false;
01787
01788 orig_disp = plus_constant (orig_disp, offset);
01789 }
01790 }
01791
01792 else
01793 return false;
01794 }
01795
01796 if (!base && !indx)
01797 pointer = true;
01798
01799 if (out)
01800 {
01801 out->base = base;
01802 out->indx = indx;
01803 out->disp = orig_disp;
01804 out->pointer = pointer;
01805 out->literal_pool = literal_pool;
01806 }
01807
01808 return true;
01809 }
01810
01811
01812
01813
01814
01815
01816 bool
01817 s390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset)
01818 {
01819 HOST_WIDE_INT off = 0;
01820
01821
01822
01823 if (GET_CODE (op) == CONST_INT)
01824 {
01825 off = INTVAL (op);
01826 op = NULL_RTX;
01827 }
01828 if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
01829 {
01830 off = INTVAL (XEXP (op, 1));
01831 op = XEXP (op, 0);
01832 }
01833 while (op && GET_CODE (op) == SUBREG)
01834 op = SUBREG_REG (op);
01835
01836 if (op && GET_CODE (op) != REG)
01837 return false;
01838
01839 if (offset)
01840 *offset = off;
01841 if (base)
01842 *base = op;
01843
01844 return true;
01845 }
01846
01847
01848
01849
01850 bool
01851 s390_legitimate_address_without_index_p (rtx op)
01852 {
01853 struct s390_address addr;
01854
01855 if (!s390_decompose_address (XEXP (op, 0), &addr))
01856 return false;
01857 if (addr.indx)
01858 return false;
01859
01860 return true;
01861 }
01862
01863
01864
01865
01866
01867
01868 int
01869 s390_mem_constraint (const char *str, rtx op)
01870 {
01871 struct s390_address addr;
01872 char c = str[0];
01873
01874
01875 if (c == 'A')
01876 {
01877
01878 if (!MEM_P (op) || MEM_VOLATILE_P (op))
01879 return 0;
01880
01881 if ((reload_completed || reload_in_progress)
01882 ? !offsettable_memref_p (op) : !offsettable_nonstrict_memref_p (op))
01883 return 0;
01884
01885 c = str[1];
01886 }
01887
01888
01889 else if (c == 'B')
01890 {
01891 if (GET_CODE (op) != MEM)
01892 return 0;
01893 if (!s390_decompose_address (XEXP (op, 0), &addr))
01894 return 0;
01895 if (addr.literal_pool)
01896 return 0;
01897
01898 c = str[1];
01899 }
01900
01901 switch (c)
01902 {
01903 case 'Q':
01904 if (GET_CODE (op) != MEM)
01905 return 0;
01906 if (!s390_decompose_address (XEXP (op, 0), &addr))
01907 return 0;
01908 if (addr.indx)
01909 return 0;
01910
01911 if (TARGET_LONG_DISPLACEMENT)
01912 {
01913 if (!s390_short_displacement (addr.disp))
01914 return 0;
01915 }
01916 break;
01917
01918 case 'R':
01919 if (GET_CODE (op) != MEM)
01920 return 0;
01921
01922 if (TARGET_LONG_DISPLACEMENT)
01923 {
01924 if (!s390_decompose_address (XEXP (op, 0), &addr))
01925 return 0;
01926 if (!s390_short_displacement (addr.disp))
01927 return 0;
01928 }
01929 break;
01930
01931 case 'S':
01932 if (!TARGET_LONG_DISPLACEMENT)
01933 return 0;
01934 if (GET_CODE (op) != MEM)
01935 return 0;
01936 if (!s390_decompose_address (XEXP (op, 0), &addr))
01937 return 0;
01938 if (addr.indx)
01939 return 0;
01940 if (s390_short_displacement (addr.disp))
01941 return 0;
01942 break;
01943
01944 case 'T':
01945 if (!TARGET_LONG_DISPLACEMENT)
01946 return 0;
01947 if (GET_CODE (op) != MEM)
01948 return 0;
01949
01950
01951 if (s390_decompose_address (XEXP (op, 0), &addr)
01952 && s390_short_displacement (addr.disp))
01953 return 0;
01954 break;
01955
01956 case 'U':
01957 if (TARGET_LONG_DISPLACEMENT)
01958 {
01959 if (!s390_decompose_address (op, &addr))
01960 return 0;
01961 if (!s390_short_displacement (addr.disp))
01962 return 0;
01963 }
01964 break;
01965
01966 case 'W':
01967 if (!TARGET_LONG_DISPLACEMENT)
01968 return 0;
01969
01970
01971 if (s390_decompose_address (op, &addr)
01972 && s390_short_displacement (addr.disp))
01973 return 0;
01974 break;
01975
01976 case 'Y':
01977
01978
01979 if (!s390_decompose_shift_count (op, NULL, NULL))
01980 return 0;
01981 break;
01982
01983 default:
01984 return 0;
01985 }
01986
01987 return 1;
01988 }
01989
01990
01991
01992
01993
01994
01995
01996
01997 int
01998 s390_O_constraint_str (const char c, HOST_WIDE_INT value)
01999 {
02000 if (!TARGET_EXTIMM)
02001 return 0;
02002
02003 switch (c)
02004 {
02005 case 's':
02006 return trunc_int_for_mode (value, SImode) == value;
02007
02008 case 'p':
02009 return value == 0
02010 || s390_single_part (GEN_INT (value), DImode, SImode, 0) == 1;
02011
02012 case 'n':
02013 return value == -1
02014 || s390_single_part (GEN_INT (value), DImode, SImode, -1) == 1;
02015
02016 default:
02017 gcc_unreachable ();
02018 }
02019 }
02020
02021
02022
02023
02024
02025
02026 int
02027 s390_N_constraint_str (const char *str, HOST_WIDE_INT value)
02028 {
02029 enum machine_mode mode, part_mode;
02030 int def;
02031 int part, part_goal;
02032
02033
02034 if (str[0] == 'x')
02035 part_goal = -1;
02036 else
02037 part_goal = str[0] - '0';
02038
02039 switch (str[1])
02040 {
02041 case 'Q':
02042 part_mode = QImode;
02043 break;
02044 case 'H':
02045 part_mode = HImode;
02046 break;
02047 case 'S':
02048 part_mode = SImode;
02049 break;
02050 default:
02051 return 0;
02052 }
02053
02054 switch (str[2])
02055 {
02056 case 'H':
02057 mode = HImode;
02058 break;
02059 case 'S':
02060 mode = SImode;
02061 break;
02062 case 'D':
02063 mode = DImode;
02064 break;
02065 default:
02066 return 0;
02067 }
02068
02069 switch (str[3])
02070 {
02071 case '0':
02072 def = 0;
02073 break;
02074 case 'F':
02075 def = -1;
02076 break;
02077 default:
02078 return 0;
02079 }
02080
02081 if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (part_mode))
02082 return 0;
02083
02084 part = s390_single_part (GEN_INT (value), mode, part_mode, def);
02085 if (part < 0)
02086 return 0;
02087 if (part_goal != -1 && part_goal != part)
02088 return 0;
02089
02090 return 1;
02091 }
02092
02093
02094
02095
02096 int
02097 s390_float_const_zero_p (rtx value)
02098 {
02099 return (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT
02100 && value == CONST0_RTX (GET_MODE (value)));
02101 }
02102
02103
02104
02105
02106
02107
02108
02109
02110 static bool
02111 s390_rtx_costs (rtx x, int code, int outer_code, int *total)
02112 {
02113 switch (code)
02114 {
02115 case CONST:
02116 case CONST_INT:
02117 case LABEL_REF:
02118 case SYMBOL_REF:
02119 case CONST_DOUBLE:
02120 case MEM:
02121 *total = 0;
02122 return true;
02123
02124 case ASHIFT:
02125 case ASHIFTRT:
02126 case LSHIFTRT:
02127 case ROTATE:
02128 case ROTATERT:
02129 case AND:
02130 case IOR:
02131 case XOR:
02132 case NEG:
02133 case NOT:
02134 *total = COSTS_N_INSNS (1);
02135 return false;
02136
02137 case PLUS:
02138 case MINUS:
02139
02140 if ((GET_MODE (x) == DFmode || GET_MODE (x) == SFmode)
02141 && GET_CODE (XEXP (x, 0)) == MULT
02142 && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT && TARGET_FUSED_MADD)
02143 {
02144
02145 if (GET_MODE (x) == DFmode)
02146 *total = s390_cost->madbr;
02147 else
02148 *total = s390_cost->maebr;
02149 *total += rtx_cost (XEXP (XEXP (x, 0), 0), MULT)
02150 + rtx_cost (XEXP (XEXP (x, 0), 1), MULT)
02151 + rtx_cost (XEXP (x, 1), code);
02152 return true;
02153 }
02154 *total = COSTS_N_INSNS (1);
02155 return false;
02156
02157 case MULT:
02158 switch (GET_MODE (x))
02159 {
02160 case SImode:
02161 {
02162 rtx left = XEXP (x, 0);
02163 rtx right = XEXP (x, 1);
02164 if (GET_CODE (right) == CONST_INT
02165 && CONST_OK_FOR_K (INTVAL (right)))
02166 *total = s390_cost->mhi;
02167 else if (GET_CODE (left) == SIGN_EXTEND)
02168 *total = s390_cost->mh;
02169 else
02170 *total = s390_cost->ms;
02171 break;
02172 }
02173 case DImode:
02174 {
02175 rtx left = XEXP (x, 0);
02176 rtx right = XEXP (x, 1);
02177 if (TARGET_64BIT)
02178 {
02179 if (GET_CODE (right) == CONST_INT
02180 && CONST_OK_FOR_K (INTVAL (right)))
02181 *total = s390_cost->mghi;
02182 else if (GET_CODE (left) == SIGN_EXTEND)
02183 *total = s390_cost->msgf;
02184 else
02185 *total = s390_cost->msg;
02186 }
02187 else
02188 {
02189 if (GET_CODE (left) == SIGN_EXTEND
02190 && GET_CODE (right) == SIGN_EXTEND)
02191
02192 *total = s390_cost->m;
02193 else if (GET_CODE (left) == ZERO_EXTEND
02194 && GET_CODE (right) == ZERO_EXTEND
02195 && TARGET_CPU_ZARCH)
02196
02197 *total = s390_cost->ml;
02198 else
02199
02200 *total = COSTS_N_INSNS (40);
02201 }
02202 break;
02203 }
02204 case SFmode:
02205 case DFmode:
02206 *total = s390_cost->mult_df;
02207 break;
02208 case TFmode:
02209 *total = s390_cost->mxbr;
02210 break;
02211 default:
02212 return false;
02213 }
02214 return false;
02215
02216 case UDIV:
02217 case UMOD:
02218 if (GET_MODE (x) == TImode)
02219 *total = s390_cost->dlgr;
02220 else if (GET_MODE (x) == DImode)
02221 {
02222 rtx right = XEXP (x, 1);
02223 if (GET_CODE (right) == ZERO_EXTEND)
02224 *total = s390_cost->dlr;
02225 else
02226 *total = s390_cost->dlgr;
02227 }
02228 else if (GET_MODE (x) == SImode)
02229 *total = s390_cost->dlr;
02230 return false;
02231
02232 case DIV:
02233 case MOD:
02234 if (GET_MODE (x) == DImode)
02235 {
02236 rtx right = XEXP (x, 1);
02237 if (GET_CODE (right) == ZERO_EXTEND)
02238 if (TARGET_64BIT)
02239 *total = s390_cost->dsgfr;
02240 else
02241 *total = s390_cost->dr;
02242 else
02243 *total = s390_cost->dsgr;
02244 }
02245 else if (GET_MODE (x) == SImode)
02246 *total = s390_cost->dlr;
02247 else if (GET_MODE (x) == SFmode)
02248 {
02249 if (TARGET_IEEE_FLOAT)
02250 *total = s390_cost->debr;
02251 else
02252 *total = s390_cost->der;
02253 }
02254 else if (GET_MODE (x) == DFmode)
02255 {
02256 if (TARGET_IEEE_FLOAT)
02257 *total = s390_cost->ddbr;
02258 else
02259 *total = s390_cost->ddr;
02260 }
02261 else if (GET_MODE (x) == TFmode)
02262 {
02263 if (TARGET_IEEE_FLOAT)
02264 *total = s390_cost->dxbr;
02265 else
02266 *total = s390_cost->dxr;
02267 }
02268 return false;
02269
02270 case SQRT:
02271 if (GET_MODE (x) == SFmode)
02272 *total = s390_cost->sqebr;
02273 else if (GET_MODE (x) == DFmode)
02274 *total = s390_cost->sqdbr;
02275 else
02276 *total = s390_cost->sqxbr;
02277 return false;
02278
02279 case SIGN_EXTEND:
02280 case ZERO_EXTEND:
02281 if (outer_code == MULT || outer_code == DIV || outer_code == MOD
02282 || outer_code == PLUS || outer_code == MINUS
02283 || outer_code == COMPARE)
02284 *total = 0;
02285 return false;
02286
02287 case COMPARE:
02288 *total = COSTS_N_INSNS (1);
02289 if (GET_CODE (XEXP (x, 0)) == AND
02290 && GET_CODE (XEXP (x, 1)) == CONST_INT
02291 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
02292 {
02293 rtx op0 = XEXP (XEXP (x, 0), 0);
02294 rtx op1 = XEXP (XEXP (x, 0), 1);
02295 rtx op2 = XEXP (x, 1);
02296
02297 if (memory_operand (op0, GET_MODE (op0))
02298 && s390_tm_ccmode (op1, op2, 0) != VOIDmode)
02299 return true;
02300 if (register_operand (op0, GET_MODE (op0))
02301 && s390_tm_ccmode (op1, op2, 1) != VOIDmode)
02302 return true;
02303 }
02304 return false;
02305
02306 default:
02307 return false;
02308 }
02309 }
02310
02311
02312
02313 static int
02314 s390_address_cost (rtx addr)
02315 {
02316 struct s390_address ad;
02317 if (!s390_decompose_address (addr, &ad))
02318 return 1000;
02319
02320 return ad.indx? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (1);
02321 }
02322
02323
02324
02325
02326 int
02327 tls_symbolic_operand (rtx op)
02328 {
02329 if (GET_CODE (op) != SYMBOL_REF)
02330 return 0;
02331 return SYMBOL_REF_TLS_MODEL (op);
02332 }
02333
02334
02335
02336
02337
02338
02339 void
02340 s390_split_access_reg (rtx reg, rtx *lo, rtx *hi)
02341 {
02342 gcc_assert (TARGET_64BIT);
02343 gcc_assert (ACCESS_REG_P (reg));
02344 gcc_assert (GET_MODE (reg) == DImode);
02345 gcc_assert (!(REGNO (reg) & 1));
02346
02347 *lo = gen_rtx_REG (SImode, REGNO (reg) + 1);
02348 *hi = gen_rtx_REG (SImode, REGNO (reg));
02349 }
02350
02351
02352
02353 bool
02354 symbolic_reference_mentioned_p (rtx op)
02355 {
02356 const char *fmt;
02357 int i;
02358
02359 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
02360 return 1;
02361
02362 fmt = GET_RTX_FORMAT (GET_CODE (op));
02363 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
02364 {
02365 if (fmt[i] == 'E')
02366 {
02367 int j;
02368
02369 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
02370 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
02371 return 1;
02372 }
02373
02374 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
02375 return 1;
02376 }
02377
02378 return 0;
02379 }
02380
02381
02382
02383 bool
02384 tls_symbolic_reference_mentioned_p (rtx op)
02385 {
02386 const char *fmt;
02387 int i;
02388
02389 if (GET_CODE (op) == SYMBOL_REF)
02390 return tls_symbolic_operand (op);
02391
02392 fmt = GET_RTX_FORMAT (GET_CODE (op));
02393 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
02394 {
02395 if (fmt[i] == 'E')
02396 {
02397 int j;
02398
02399 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
02400 if (tls_symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
02401 return true;
02402 }
02403
02404 else if (fmt[i] == 'e' && tls_symbolic_reference_mentioned_p (XEXP (op, i)))
02405 return true;
02406 }
02407
02408 return false;
02409 }
02410
02411
02412
02413
02414
02415
02416 int
02417 legitimate_pic_operand_p (rtx op)
02418 {
02419
02420 if (!SYMBOLIC_CONST (op))
02421 return 1;
02422
02423
02424
02425 return 0;
02426 }
02427
02428
02429
02430
02431 int
02432 legitimate_constant_p (rtx op)
02433 {
02434
02435 if (!SYMBOLIC_CONST (op))
02436 return 1;
02437
02438
02439 if (TARGET_CPU_ZARCH && larl_operand (op, VOIDmode))
02440 return 1;
02441
02442
02443
02444
02445 if (TLS_SYMBOLIC_CONST (op))
02446 return 0;
02447
02448
02449
02450
02451 if (flag_pic)
02452 return 1;
02453
02454
02455
02456 return 0;
02457 }
02458
02459
02460
02461
02462
02463 static bool
02464 s390_cannot_force_const_mem (rtx x)
02465 {
02466 switch (GET_CODE (x))
02467 {
02468 case CONST_INT:
02469 case CONST_DOUBLE:
02470
02471 return false;
02472
02473 case LABEL_REF:
02474
02475 return flag_pic != 0;
02476
02477 case SYMBOL_REF:
02478
02479
02480 if (tls_symbolic_operand (x))
02481 return true;
02482 else
02483 return flag_pic != 0;
02484
02485 case CONST:
02486 return s390_cannot_force_const_mem (XEXP (x, 0));
02487 case PLUS:
02488 case MINUS:
02489 return s390_cannot_force_const_mem (XEXP (x, 0))
02490 || s390_cannot_force_const_mem (XEXP (x, 1));
02491
02492 case UNSPEC:
02493 switch (XINT (x, 1))
02494 {
02495
02496 case UNSPEC_LTREL_OFFSET:
02497 case UNSPEC_GOT:
02498 case UNSPEC_GOTOFF:
02499 case UNSPEC_PLTOFF:
02500 case UNSPEC_TLSGD:
02501 case UNSPEC_TLSLDM:
02502 case UNSPEC_NTPOFF:
02503 case UNSPEC_DTPOFF:
02504 case UNSPEC_GOTNTPOFF:
02505 case UNSPEC_INDNTPOFF:
02506 return false;
02507
02508
02509
02510 case UNSPEC_INSN:
02511 return TARGET_CPU_ZARCH;
02512
02513 default:
02514 return true;
02515 }
02516 break;
02517
02518 default:
02519 gcc_unreachable ();
02520 }
02521 }
02522
02523
02524
02525
02526
02527
02528
02529 bool
02530 legitimate_reload_constant_p (rtx op)
02531 {
02532
02533 if (GET_CODE (op) == CONST_INT
02534 && DISP_IN_RANGE (INTVAL (op)))
02535 return true;
02536
02537
02538 if (GET_CODE (op) == CONST_INT
02539 && (CONST_OK_FOR_K (INTVAL (op)) || CONST_OK_FOR_Os (INTVAL (op))))
02540 return true;
02541
02542
02543 if (TARGET_ZARCH
02544 && GET_CODE (op) == CONST_INT
02545 && trunc_int_for_mode (INTVAL (op), word_mode) == INTVAL (op)
02546 && s390_single_part (op, word_mode, HImode, 0) >= 0)
02547 return true;
02548
02549 if (TARGET_EXTIMM
02550 && GET_CODE (op) == CONST_INT
02551 && trunc_int_for_mode (INTVAL (op), word_mode) == INTVAL (op)
02552 && s390_single_part (op, word_mode, SImode, 0) >= 0)
02553 return true;
02554
02555
02556 if (TARGET_CPU_ZARCH
02557 && larl_operand (op, VOIDmode))
02558 return true;
02559
02560
02561 if (GET_CODE (op) == CONST_DOUBLE
02562 && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'G', "G"))
02563 return true;
02564
02565
02566 if (GET_CODE (op) == CONST_INT
02567 && trunc_int_for_mode (INTVAL (op), word_mode) != INTVAL (op))
02568 {
02569 enum machine_mode dword_mode = word_mode == SImode ? DImode : TImode;
02570 rtx hi = operand_subword (op, 0, 0, dword_mode);
02571 rtx lo = operand_subword (op, 1, 0, dword_mode);
02572 return legitimate_reload_constant_p (hi)
02573 && legitimate_reload_constant_p (lo);
02574 }
02575
02576
02577 return false;
02578 }
02579
02580
02581
02582
02583 enum reg_class
02584 s390_preferred_reload_class (rtx op, enum reg_class class)
02585 {
02586 switch (GET_CODE (op))
02587 {
02588
02589
02590
02591 case CONST_DOUBLE:
02592 case CONST_INT:
02593 if (legitimate_reload_constant_p (op))
02594 return class;
02595 else
02596 return NO_REGS;
02597
02598
02599
02600
02601
02602 case PLUS:
02603 case LABEL_REF:
02604 case SYMBOL_REF:
02605 case CONST:
02606 if (reg_class_subset_p (ADDR_REGS, class))
02607 return ADDR_REGS;
02608 else
02609 return NO_REGS;
02610
02611 default:
02612 break;
02613 }
02614
02615 return class;
02616 }
02617
02618
02619
02620
02621
02622
02623
02624 enum reg_class
02625 s390_secondary_input_reload_class (enum reg_class class,
02626 enum machine_mode mode, rtx in)
02627 {
02628 if (s390_plus_operand (in, mode))
02629 return ADDR_REGS;
02630
02631 if (reg_classes_intersect_p (FP_REGS, class)
02632 && mode == TFmode
02633 && GET_CODE (in) == MEM
02634 && GET_CODE (XEXP (in, 0)) == PLUS
02635 && GET_CODE (XEXP (XEXP (in, 0), 1)) == CONST_INT
02636 && !DISP_IN_RANGE (INTVAL (XEXP (XEXP (in, 0), 1))
02637 + GET_MODE_SIZE (mode) - 1))
02638 return ADDR_REGS;
02639
02640 if (reg_classes_intersect_p (CC_REGS, class))
02641 return GENERAL_REGS;
02642
02643 return NO_REGS;
02644 }
02645
02646
02647
02648
02649
02650
02651
02652 enum reg_class
02653 s390_secondary_output_reload_class (enum reg_class class,
02654 enum machine_mode mode, rtx out)
02655 {
02656 if ((TARGET_64BIT ? (mode == TImode || mode == TFmode)
02657 : (mode == DImode || mode == DFmode))
02658 && reg_classes_intersect_p (GENERAL_REGS, class)
02659 && GET_CODE (out) == MEM
02660 && GET_CODE (XEXP (out, 0)) == PLUS
02661 && GET_CODE (XEXP (XEXP (out, 0), 0)) == PLUS
02662 && GET_CODE (XEXP (XEXP (out, 0), 1)) == CONST_INT
02663 && !DISP_IN_RANGE (INTVAL (XEXP (XEXP (out, 0), 1))
02664 + GET_MODE_SIZE (mode) - 1))
02665 return ADDR_REGS;
02666
02667 if (reg_classes_intersect_p (FP_REGS, class)
02668 && mode == TFmode
02669 && GET_CODE (out) == MEM
02670 && GET_CODE (XEXP (out, 0)) == PLUS
02671 && GET_CODE (XEXP (XEXP (out, 0), 1)) == CONST_INT
02672 && !DISP_IN_RANGE (INTVAL (XEXP (XEXP (out, 0), 1))
02673 + GET_MODE_SIZE (mode) - 1))
02674 return ADDR_REGS;
02675
02676 if (reg_classes_intersect_p (CC_REGS, class))
02677 return GENERAL_REGS;
02678
02679 return NO_REGS;
02680 }
02681
02682
02683
02684
02685
02686 void
02687 s390_expand_plus_operand (rtx target, rtx src,
02688 rtx scratch)
02689 {
02690 rtx sum1, sum2;
02691 struct s390_address ad;
02692
02693
02694 gcc_assert (GET_CODE (src) == PLUS);
02695 gcc_assert (GET_MODE (src) == Pmode);
02696
02697
02698
02699
02700 sum1 = find_replacement (&XEXP (src, 0));
02701 sum2 = find_replacement (&XEXP (src, 1));
02702 src = gen_rtx_PLUS (Pmode, sum1, sum2);
02703
02704
02705 if (!s390_decompose_address (src, &ad)
02706 || (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
02707 || (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx))))
02708 {
02709
02710
02711 if (true_regnum (sum1) < 1 || true_regnum (sum1) > 15)
02712 {
02713 emit_move_insn (scratch, sum1);
02714 sum1 = scratch;
02715 }
02716 if (true_regnum (sum2) < 1 || true_regnum (sum2) > 15)
02717 {
02718 emit_move_insn (scratch, sum2);
02719 sum2 = scratch;
02720 }
02721
02722
02723
02724
02725
02726 if (sum1 == scratch && sum2 == scratch)
02727 {
02728 debug_rtx (src);
02729 gcc_unreachable ();
02730 }
02731
02732 src = gen_rtx_PLUS (Pmode, sum1, sum2);
02733 }
02734
02735
02736
02737
02738 s390_load_address (target, src);
02739 }
02740
02741
02742
02743
02744
02745 bool
02746 legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
02747 rtx addr, int strict)
02748 {
02749 struct s390_address ad;
02750 if (!s390_decompose_address (addr, &ad))
02751 return false;
02752
02753 if (strict)
02754 {
02755 if (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
02756 return false;
02757
02758 if (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx)))
02759 return false;
02760 }
02761 else
02762 {
02763 if (ad.base
02764 && !(REGNO (ad.base) >= FIRST_PSEUDO_REGISTER
02765 || REGNO_REG_CLASS (REGNO (ad.base)) == ADDR_REGS))
02766 return false;
02767
02768 if (ad.indx
02769 && !(REGNO (ad.indx) >= FIRST_PSEUDO_REGISTER
02770 || REGNO_REG_CLASS (REGNO (ad.indx)) == ADDR_REGS))
02771 return false;
02772 }
02773 return true;
02774 }
02775
02776
02777
02778
02779
02780 bool
02781 legitimate_la_operand_p (rtx op)
02782 {
02783 struct s390_address addr;
02784 if (!s390_decompose_address (op, &addr))
02785 return false;
02786
02787 return (TARGET_64BIT || addr.pointer);
02788 }
02789
02790
02791
02792
02793 bool
02794 preferred_la_operand_p (rtx op1, rtx op2)
02795 {
02796 struct s390_address addr;
02797
02798 if (op2 != const0_rtx)
02799 op1 = gen_rtx_PLUS (Pmode, op1, op2);
02800
02801 if (!s390_decompose_address (op1, &addr))
02802 return false;
02803 if (addr.base && !REGNO_OK_FOR_BASE_P (REGNO (addr.base)))
02804 return false;
02805 if (addr.indx && !REGNO_OK_FOR_INDEX_P (REGNO (addr.indx)))
02806 return false;
02807
02808 if (!TARGET_64BIT && !addr.pointer)
02809 return false;
02810
02811 if (addr.pointer)
02812 return true;
02813
02814 if ((addr.base && REG_P (addr.base) && REG_POINTER (addr.base))
02815 || (addr.indx && REG_P (addr.indx) && REG_POINTER (addr.indx)))
02816 return true;
02817
02818 return false;
02819 }
02820
02821
02822
02823
02824
02825 void
02826 s390_load_address (rtx dst, rtx src)
02827 {
02828 if (TARGET_64BIT)
02829 emit_move_insn (dst, src);
02830 else
02831 emit_insn (gen_force_la_31 (dst, src));
02832 }
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852 rtx
02853 legitimize_pic_address (rtx orig, rtx reg)
02854 {
02855 rtx addr = orig;
02856 rtx new = orig;
02857 rtx base;
02858
02859 gcc_assert (!TLS_SYMBOLIC_CONST (addr));
02860
02861 if (GET_CODE (addr) == LABEL_REF
02862 || (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (addr)))
02863 {
02864
02865 if (TARGET_CPU_ZARCH && larl_operand (addr, VOIDmode))
02866 {
02867
02868
02869
02870 }
02871 else
02872 {
02873
02874
02875 rtx temp = reg? reg : gen_reg_rtx (Pmode);
02876
02877 if (reload_in_progress || reload_completed)
02878 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
02879
02880 addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
02881 addr = gen_rtx_CONST (Pmode, addr);
02882 addr = force_const_mem (Pmode, addr);
02883 emit_move_insn (temp, addr);
02884
02885 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
02886 if (reg != 0)
02887 {
02888 s390_load_address (reg, new);
02889 new = reg;
02890 }
02891 }
02892 }
02893 else if (GET_CODE (addr) == SYMBOL_REF)
02894 {
02895 if (reg == 0)
02896 reg = gen_reg_rtx (Pmode);
02897
02898 if (flag_pic == 1)
02899 {
02900
02901
02902
02903 if (reload_in_progress || reload_completed)
02904 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
02905
02906 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
02907 new = gen_rtx_CONST (Pmode, new);
02908 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
02909 new = gen_const_mem (Pmode, new);
02910 emit_move_insn (reg, new);
02911 new = reg;
02912 }
02913 else if (TARGET_CPU_ZARCH)
02914 {
02915
02916
02917
02918 rtx temp = gen_reg_rtx (Pmode);
02919
02920 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTENT);
02921 new = gen_rtx_CONST (Pmode, new);
02922 emit_move_insn (temp, new);
02923
02924 new = gen_const_mem (Pmode, temp);
02925 emit_move_insn (reg, new);
02926 new = reg;
02927 }
02928 else
02929 {
02930
02931
02932
02933 rtx temp = gen_reg_rtx (Pmode);
02934
02935 if (reload_in_progress || reload_completed)
02936 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
02937
02938 addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
02939 addr = gen_rtx_CONST (Pmode, addr);
02940 addr = force_const_mem (Pmode, addr);
02941 emit_move_insn (temp, addr);
02942
02943 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
02944 new = gen_const_mem (Pmode, new);
02945 emit_move_insn (reg, new);
02946 new = reg;
02947 }
02948 }
02949 else
02950 {
02951 if (GET_CODE (addr) == CONST)
02952 {
02953 addr = XEXP (addr, 0);
02954 if (GET_CODE (addr) == UNSPEC)
02955 {
02956 gcc_assert (XVECLEN (addr, 0) == 1);
02957 switch (XINT (addr, 1))
02958 {
02959
02960
02961 case UNSPEC_GOTOFF:
02962 case UNSPEC_PLTOFF:
02963 new = force_const_mem (Pmode, orig);
02964 break;
02965
02966
02967 case UNSPEC_GOT:
02968 if (flag_pic == 2)
02969 new = force_const_mem (Pmode, orig);
02970 break;
02971
02972
02973 case UNSPEC_GOTENT:
02974 break;
02975
02976
02977
02978 case UNSPEC_PLT:
02979 if (!TARGET_CPU_ZARCH)
02980 {
02981 rtx temp = reg? reg : gen_reg_rtx (Pmode);
02982
02983 if (reload_in_progress || reload_completed)
02984 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
02985
02986 addr = XVECEXP (addr, 0, 0);
02987 addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
02988 UNSPEC_PLTOFF);
02989 addr = gen_rtx_CONST (Pmode, addr);
02990 addr = force_const_mem (Pmode, addr);
02991 emit_move_insn (temp, addr);
02992
02993 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
02994 if (reg != 0)
02995 {
02996 s390_load_address (reg, new);
02997 new = reg;
02998 }
02999 }
03000 break;
03001
03002
03003 default:
03004 gcc_unreachable ();
03005 }
03006 }
03007 else
03008 gcc_assert (GET_CODE (addr) == PLUS);
03009 }
03010 if (GET_CODE (addr) == PLUS)
03011 {
03012 rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
03013
03014 gcc_assert (!TLS_SYMBOLIC_CONST (op0));
03015 gcc_assert (!TLS_SYMBOLIC_CONST (op1));
03016
03017
03018
03019 if ((GET_CODE (op0) == LABEL_REF
03020 || (GET_CODE (op0) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op0)))
03021 && GET_CODE (op1) == CONST_INT)
03022 {
03023 if (TARGET_CPU_ZARCH
03024 && larl_operand (op0, VOIDmode)
03025 && INTVAL (op1) < (HOST_WIDE_INT)1 << 31
03026 && INTVAL (op1) >= -((HOST_WIDE_INT)1 << 31))
03027 {
03028 if (INTVAL (op1) & 1)
03029 {
03030
03031
03032 rtx temp = reg? reg : gen_reg_rtx (Pmode);
03033
03034 if (!DISP_IN_RANGE (INTVAL (op1)))
03035 {
03036 HOST_WIDE_INT even = INTVAL (op1) - 1;
03037 op0 = gen_rtx_PLUS (Pmode, op0, GEN_INT (even));
03038 op0 = gen_rtx_CONST (Pmode, op0);
03039 op1 = const1_rtx;
03040 }
03041
03042 emit_move_insn (temp, op0);
03043 new = gen_rtx_PLUS (Pmode, temp, op1);
03044
03045 if (reg != 0)
03046 {
03047 s390_load_address (reg, new);
03048 new = reg;
03049 }
03050 }
03051 else
03052 {
03053
03054
03055 }
03056 }
03057 else
03058 {
03059
03060
03061 rtx temp = reg? reg : gen_reg_rtx (Pmode);
03062
03063 if (reload_in_progress || reload_completed)
03064 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
03065
03066 addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0),
03067 UNSPEC_GOTOFF);
03068 addr = gen_rtx_PLUS (Pmode, addr, op1);
03069 addr = gen_rtx_CONST (Pmode, addr);
03070 addr = force_const_mem (Pmode, addr);
03071 emit_move_insn (temp, addr);
03072
03073 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
03074 if (reg != 0)
03075 {
03076 s390_load_address (reg, new);
03077 new = reg;
03078 }
03079 }
03080 }
03081
03082
03083
03084
03085 else if (GET_CODE (op0) == UNSPEC
03086 && GET_CODE (op1) == CONST_INT
03087 && XINT (op0, 1) == UNSPEC_GOTOFF)
03088 {
03089 gcc_assert (XVECLEN (op0, 0) == 1);
03090
03091 new = force_const_mem (Pmode, orig);
03092 }
03093
03094
03095 else
03096 {
03097 base = legitimize_pic_address (XEXP (addr, 0), reg);
03098 new = legitimize_pic_address (XEXP (addr, 1),
03099 base == reg ? NULL_RTX : reg);
03100 if (GET_CODE (new) == CONST_INT)
03101 new = plus_constant (base, INTVAL (new));
03102 else
03103 {
03104 if (GET_CODE (new) == PLUS && CONSTANT_P (XEXP (new, 1)))
03105 {
03106 base = gen_rtx_PLUS (Pmode, base, XEXP (new, 0));
03107 new = XEXP (new, 1);
03108 }
03109 new = gen_rtx_PLUS (Pmode, base, new);
03110 }
03111
03112 if (GET_CODE (new) == CONST)
03113 new = XEXP (new, 0);
03114 new = force_operand (new, 0);
03115 }
03116 }
03117 }
03118 return new;
03119 }
03120
03121
03122
03123 rtx
03124 s390_get_thread_pointer (void)
03125 {
03126 rtx tp = gen_reg_rtx (Pmode);
03127
03128 emit_move_insn (tp, gen_rtx_REG (Pmode, TP_REGNUM));
03129 mark_reg_pointer (tp, BITS_PER_WORD);
03130
03131 return tp;
03132 }
03133
03134
03135
03136
03137
03138
03139 static GTY(()) rtx s390_tls_symbol;
03140
03141 static void
03142 s390_emit_tls_call_insn (rtx result_reg, rtx tls_call)
03143 {
03144 rtx insn;
03145
03146 gcc_assert (flag_pic);
03147
03148 if (!s390_tls_symbol)
03149 s390_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_offset");
03150
03151 insn = s390_emit_call (s390_tls_symbol, tls_call, result_reg,
03152 gen_rtx_REG (Pmode, RETURN_REGNUM));
03153
03154 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), result_reg);
03155 CONST_OR_PURE_CALL_P (insn) = 1;
03156 }
03157
03158
03159
03160
03161 static rtx
03162 legitimize_tls_address (rtx addr, rtx reg)
03163 {
03164 rtx new, tls_call, temp, base, r2, insn;
03165
03166 if (GET_CODE (addr) == SYMBOL_REF)
03167 switch (tls_symbolic_operand (addr))
03168 {
03169 case TLS_MODEL_GLOBAL_DYNAMIC:
03170 start_sequence ();
03171 r2 = gen_rtx_REG (Pmode, 2);
03172 tls_call = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_TLSGD);
03173 new = gen_rtx_CONST (Pmode, tls_call);
03174 new = force_const_mem (Pmode, new);
03175 emit_move_insn (r2, new);
03176 s390_emit_tls_call_insn (r2, tls_call);
03177 insn = get_insns ();
03178 end_sequence ();
03179
03180 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_NTPOFF);
03181 temp = gen_reg_rtx (Pmode);
03182 emit_libcall_block (insn, temp, r2, new);
03183
03184 new = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
03185 if (reg != 0)
03186 {
03187 s390_load_address (reg, new);
03188 new = reg;
03189 }
03190 break;
03191
03192 case TLS_MODEL_LOCAL_DYNAMIC:
03193 start_sequence ();
03194 r2 = gen_rtx_REG (Pmode, 2);
03195 tls_call = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TLSLDM);
03196 new = gen_rtx_CONST (Pmode, tls_call);
03197 new = force_const_mem (Pmode, new);
03198 emit_move_insn (r2, new);
03199 s390_emit_tls_call_insn (r2, tls_call);
03200 insn = get_insns ();
03201 end_sequence ();
03202
03203 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TLSLDM_NTPOFF);
03204 temp = gen_reg_rtx (Pmode);
03205 emit_libcall_block (insn, temp, r2, new);
03206
03207 new = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
03208 base = gen_reg_rtx (Pmode);
03209 s390_load_address (base, new);
03210
03211 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_DTPOFF);
03212 new = gen_rtx_CONST (Pmode, new);
03213 new = force_const_mem (Pmode, new);
03214 temp = gen_reg_rtx (Pmode);
03215 emit_move_insn (temp, new);
03216
03217 new = gen_rtx_PLUS (Pmode, base, temp);
03218 if (reg != 0)
03219 {
03220 s390_load_address (reg, new);
03221 new = reg;
03222 }
03223 break;
03224
03225 case TLS_MODEL_INITIAL_EXEC:
03226 if (flag_pic == 1)
03227 {
03228
03229
03230
03231 if (reload_in_progress || reload_completed)
03232 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
03233
03234 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF);
03235 new = gen_rtx_CONST (Pmode, new);
03236 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
03237 new = gen_const_mem (Pmode, new);
03238 temp = gen_reg_rtx (Pmode);
03239 emit_move_insn (temp, new);
03240 }
03241 else if (TARGET_CPU_ZARCH)
03242 {
03243
03244
03245
03246 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_INDNTPOFF);
03247 new = gen_rtx_CONST (Pmode, new);
03248 temp = gen_reg_rtx (Pmode);
03249 emit_move_insn (temp, new);
03250
03251 new = gen_const_mem (Pmode, temp);
03252 temp = gen_reg_rtx (Pmode);
03253 emit_move_insn (temp, new);
03254 }
03255 else if (flag_pic)
03256 {
03257
03258
03259
03260 if (reload_in_progress || reload_completed)
03261 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
03262
03263 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF);
03264 new = gen_rtx_CONST (Pmode, new);
03265 new = force_const_mem (Pmode, new);
03266 temp = gen_reg_rtx (Pmode);
03267 emit_move_insn (temp, new);
03268
03269 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
03270 new = gen_const_mem (Pmode, new);
03271
03272 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new, addr), UNSPEC_TLS_LOAD);
03273 temp = gen_reg_rtx (Pmode);
03274 emit_insn (gen_rtx_SET (Pmode, temp, new));
03275 }
03276 else
03277 {
03278
03279
03280
03281 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_INDNTPOFF);
03282 new = gen_rtx_CONST (Pmode, new);
03283 new = force_const_mem (Pmode, new);
03284 temp = gen_reg_rtx (Pmode);
03285 emit_move_insn (temp, new);
03286
03287 new = temp;
03288 new = gen_const_mem (Pmode, new);
03289 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new, addr), UNSPEC_TLS_LOAD);
03290 temp = gen_reg_rtx (Pmode);
03291 emit_insn (gen_rtx_SET (Pmode, temp, new));
03292 }
03293
03294 new = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
03295 if (reg != 0)
03296 {
03297 s390_load_address (reg, new);
03298 new = reg;
03299 }
03300 break;
03301
03302 case TLS_MODEL_LOCAL_EXEC:
03303 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_NTPOFF);
03304 new = gen_rtx_CONST (Pmode, new);
03305 new = force_const_mem (Pmode, new);
03306 temp = gen_reg_rtx (Pmode);
03307 emit_move_insn (temp, new);
03308
03309 new = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
03310 if (reg != 0)
03311 {
03312 s390_load_address (reg, new);
03313 new = reg;
03314 }
03315 break;
03316
03317 default:
03318 gcc_unreachable ();
03319 }
03320
03321 else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == UNSPEC)
03322 {
03323 switch (XINT (XEXP (addr, 0), 1))
03324 {
03325 case UNSPEC_INDNTPOFF:
03326 gcc_assert (TARGET_CPU_ZARCH);
03327 new = addr;
03328 break;
03329
03330 default:
03331 gcc_unreachable ();
03332 }
03333 }
03334
03335 else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == PLUS
03336 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
03337 {
03338 new = XEXP (XEXP (addr, 0), 0);
03339 if (GET_CODE (new) != SYMBOL_REF)
03340 new = gen_rtx_CONST (Pmode, new);
03341
03342 new = legitimize_tls_address (new, reg);
03343 new = plus_constant (new, INTVAL (XEXP (XEXP (addr, 0), 1)));
03344 new = force_operand (new, 0);
03345 }
03346
03347 else
03348 gcc_unreachable ();
03349
03350 return new;
03351 }
03352
03353
03354
03355 void
03356 emit_symbolic_move (rtx *operands)
03357 {
03358 rtx temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
03359
03360 if (GET_CODE (operands[0]) == MEM)
03361 operands[1] = force_reg (Pmode, operands[1]);
03362 else if (TLS_SYMBOLIC_CONST (operands[1]))
03363 operands[1] = legitimize_tls_address (operands[1], temp);
03364 else if (flag_pic)
03365 operands[1] = legitimize_pic_address (operands[1], temp);
03366 }
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379 rtx
03380 legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
03381 enum machine_mode mode ATTRIBUTE_UNUSED)
03382 {
03383 rtx constant_term = const0_rtx;
03384
03385 if (TLS_SYMBOLIC_CONST (x))
03386 {
03387 x = legitimize_tls_address (x, 0);
03388
03389 if (legitimate_address_p (mode, x, FALSE))
03390 return x;
03391 }
03392 else if (GET_CODE (x) == PLUS
03393 && (TLS_SYMBOLIC_CONST (XEXP (x, 0))
03394 || TLS_SYMBOLIC_CONST (XEXP (x, 1))))
03395 {
03396 return x;
03397 }
03398 else if (flag_pic)
03399 {
03400 if (SYMBOLIC_CONST (x)
03401 || (GET_CODE (x) == PLUS
03402 && (SYMBOLIC_CONST (XEXP (x, 0))
03403 || SYMBOLIC_CONST (XEXP (x, 1)))))
03404 x = legitimize_pic_address (x, 0);
03405
03406 if (legitimate_address_p (mode, x, FALSE))
03407 return x;
03408 }
03409
03410 x = eliminate_constant_term (x, &constant_term);
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420 if (GET_CODE (constant_term) == CONST_INT
03421 && !TARGET_LONG_DISPLACEMENT
03422 && !DISP_IN_RANGE (INTVAL (constant_term))
03423 && !(REG_P (x) && REGNO_PTR_FRAME_P (REGNO (x))))
03424 {
03425 HOST_WIDE_INT lower = INTVAL (constant_term) & 0xfff;
03426 HOST_WIDE_INT upper = INTVAL (constant_term) ^ lower;
03427
03428 rtx temp = gen_reg_rtx (Pmode);
03429 rtx val = force_operand (GEN_INT (upper), temp);
03430 if (val != temp)
03431 emit_move_insn (temp, val);
03432
03433 x = gen_rtx_PLUS (Pmode, x, temp);
03434 constant_term = GEN_INT (lower);
03435 }
03436
03437 if (GET_CODE (x) == PLUS)
03438 {
03439 if (GET_CODE (XEXP (x, 0)) == REG)
03440 {
03441 rtx temp = gen_reg_rtx (Pmode);
03442 rtx val = force_operand (XEXP (x, 1), temp);
03443 if (val != temp)
03444 emit_move_insn (temp, val);
03445
03446 x = gen_rtx_PLUS (Pmode, XEXP (x, 0), temp);
03447 }
03448
03449 else if (GET_CODE (XEXP (x, 1)) == REG)
03450 {
03451 rtx temp = gen_reg_rtx (Pmode);
03452 rtx val = force_operand (XEXP (x, 0), temp);
03453 if (val != temp)
03454 emit_move_insn (temp, val);
03455
03456 x = gen_rtx_PLUS (Pmode, temp, XEXP (x, 1));
03457 }
03458 }
03459
03460 if (constant_term != const0_rtx)
03461 x = gen_rtx_PLUS (Pmode, x, constant_term);
03462
03463 return x;
03464 }
03465
03466
03467
03468
03469
03470
03471
03472 rtx
03473 legitimize_reload_address (rtx ad, enum machine_mode mode ATTRIBUTE_UNUSED,
03474 int opnum, int type)
03475 {
03476 if (!optimize || TARGET_LONG_DISPLACEMENT)
03477 return NULL_RTX;
03478
03479 if (GET_CODE (ad) == PLUS)
03480 {
03481 rtx tem = simplify_binary_operation (PLUS, Pmode,
03482 XEXP (ad, 0), XEXP (ad, 1));
03483 if (tem)
03484 ad = tem;
03485 }
03486
03487 if (GET_CODE (ad) == PLUS
03488 && GET_CODE (XEXP (ad, 0)) == REG
03489 && GET_CODE (XEXP (ad, 1)) == CONST_INT
03490 && !DISP_IN_RANGE (INTVAL (XEXP (ad, 1))))
03491 {
03492 HOST_WIDE_INT lower = INTVAL (XEXP (ad, 1)) & 0xfff;
03493 HOST_WIDE_INT upper = INTVAL (XEXP (ad, 1)) ^ lower;
03494 rtx cst, tem, new;
03495
03496 cst = GEN_INT (upper);
03497 if (!legitimate_reload_constant_p (cst))
03498 cst = force_const_mem (Pmode, cst);
03499
03500 tem = gen_rtx_PLUS (Pmode, XEXP (ad, 0), cst);
03501 new = gen_rtx_PLUS (Pmode, tem, GEN_INT (lower));
03502
03503 push_reload (XEXP (tem, 1), 0, &XEXP (tem, 1), 0,
03504 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
03505 opnum, (enum reload_type) type);
03506 return new;
03507 }
03508
03509 return NULL_RTX;
03510 }
03511
03512
03513
03514 void
03515 s390_expand_movmem (rtx dst, rtx src, rtx len)
03516 {
03517 if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
03518 {
03519 if (INTVAL (len) > 0)
03520 emit_insn (gen_movmem_short (dst, src, GEN_INT (INTVAL (len) - 1)));
03521 }
03522
03523 else if (TARGET_MVCLE)
03524 {
03525 emit_insn (gen_movmem_long (dst, src, convert_to_mode (Pmode, len, 1)));
03526 }
03527
03528 else
03529 {
03530 rtx dst_addr, src_addr, count, blocks, temp;
03531 rtx loop_start_label = gen_label_rtx ();
03532 rtx loop_end_label = gen_label_rtx ();
03533 rtx end_label = gen_label_rtx ();
03534 enum machine_mode mode;
03535
03536 mode = GET_MODE (len);
03537 if (mode == VOIDmode)
03538 mode = Pmode;
03539
03540 dst_addr = gen_reg_rtx (Pmode);
03541 src_addr = gen_reg_rtx (Pmode);
03542 count = gen_reg_rtx (mode);
03543 blocks = gen_reg_rtx (mode);
03544
03545 convert_move (count, len, 1);
03546 emit_cmp_and_jump_insns (count, const0_rtx,
03547 EQ, NULL_RTX, mode, 1, end_label);
03548
03549 emit_move_insn (dst_addr, force_operand (XEXP (dst, 0), NULL_RTX));
03550 emit_move_insn (src_addr, force_operand (XEXP (src, 0), NULL_RTX));
03551 dst = change_address (dst, VOIDmode, dst_addr);
03552 src = change_address (src, VOIDmode, src_addr);
03553
03554 temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0);
03555 if (temp != count)
03556 emit_move_insn (count, temp);
03557
03558 temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1, 0);
03559 if (temp != blocks)
03560 emit_move_insn (blocks, temp);
03561
03562 emit_cmp_and_jump_insns (blocks, const0_rtx,
03563 EQ, NULL_RTX, mode, 1, loop_end_label);
03564
03565 emit_label (loop_start_label);
03566
03567 emit_insn (gen_movmem_short (dst, src, GEN_INT (255)));
03568 s390_load_address (dst_addr,
03569 gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
03570 s390_load_address (src_addr,
03571 gen_rtx_PLUS (Pmode, src_addr, GEN_INT (256)));
03572
03573 temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1, 0);
03574 if (temp != blocks)
03575 emit_move_insn (blocks, temp);
03576
03577 emit_cmp_and_jump_insns (blocks, const0_rtx,
03578 EQ, NULL_RTX, mode, 1, loop_end_label);
03579
03580 emit_jump (loop_start_label);
03581 emit_label (loop_end_label);
03582
03583 emit_insn (gen_movmem_short (dst, src,
03584 convert_to_mode (Pmode, count, 1)));
03585 emit_label (end_label);
03586 }
03587 }
03588
03589
03590
03591
03592 void
03593 s390_expand_setmem (rtx dst, rtx len, rtx val)
03594 {
03595 if (GET_CODE (len) == CONST_INT && INTVAL (len) == 0)
03596 return;
03597
03598 gcc_assert (GET_CODE (val) == CONST_INT || GET_MODE (val) == QImode);
03599
03600 if (GET_CODE (len) == CONST_INT && INTVAL (len) > 0 && INTVAL (len) <= 257)
03601 {
03602 if (val == const0_rtx && INTVAL (len) <= 256)
03603 emit_insn (gen_clrmem_short (dst, GEN_INT (INTVAL (len) - 1)));
03604 else
03605 {
03606
03607 emit_move_insn (adjust_address (dst, QImode, 0), val);
03608
03609 if (INTVAL (len) > 1)
03610 {
03611
03612
03613
03614
03615
03616 rtx dstp1 = adjust_address (dst, VOIDmode, 1);
03617 set_mem_size (dst, const1_rtx);
03618
03619 emit_insn (gen_movmem_short (dstp1, dst,
03620 GEN_INT (INTVAL (len) - 2)));
03621 }
03622 }
03623 }
03624
03625 else if (TARGET_MVCLE)
03626 {
03627 val = force_not_mem (convert_modes (Pmode, QImode, val, 1));
03628 emit_insn (gen_setmem_long (dst, convert_to_mode (Pmode, len, 1), val));
03629 }
03630
03631 else
03632 {
03633 rtx dst_addr, src_addr, count, blocks, temp, dstp1 = NULL_RTX;
03634 rtx loop_start_label = gen_label_rtx ();
03635 rtx loop_end_label = gen_label_rtx ();
03636 rtx end_label = gen_label_rtx ();
03637 enum machine_mode mode;
03638
03639 mode = GET_MODE (len);
03640 if (mode == VOIDmode)
03641 mode = Pmode;
03642
03643 dst_addr = gen_reg_rtx (Pmode);
03644 src_addr = gen_reg_rtx (Pmode);
03645 count = gen_reg_rtx (mode);
03646 blocks = gen_reg_rtx (mode);
03647
03648 convert_move (count, len, 1);
03649 emit_cmp_and_jump_insns (count, const0_rtx,
03650 EQ, NULL_RTX, mode, 1, end_label);
03651
03652 emit_move_insn (dst_addr, force_operand (XEXP (dst, 0), NULL_RTX));
03653 dst = change_address (dst, VOIDmode, dst_addr);
03654
03655 if (val == const0_rtx)
03656 temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0);
03657 else
03658 {
03659 dstp1 = adjust_address (dst, VOIDmode, 1);
03660 set_mem_size (dst, const1_rtx);
03661
03662
03663 emit_move_insn (adjust_address (dst, QImode, 0), val);
03664
03665
03666 emit_cmp_and_jump_insns (count, const1_rtx,
03667 EQ, NULL_RTX, mode, 1, end_label);
03668
03669 temp = expand_binop (mode, add_optab, count, GEN_INT (-2), count, 1, 0);
03670 }
03671 if (temp != count)
03672 emit_move_insn (count, temp);
03673
03674 temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1, 0);
03675 if (temp != blocks)
03676 emit_move_insn (blocks, temp);
03677
03678 emit_cmp_and_jump_insns (blocks, const0_rtx,
03679 EQ, NULL_RTX, mode, 1, loop_end_label);
03680
03681 emit_label (loop_start_label);
03682
03683 if (val == const0_rtx)
03684 emit_insn (gen_clrmem_short (dst, GEN_INT (255)));
03685 else
03686 emit_insn (gen_movmem_short (dstp1, dst, GEN_INT (255)));
03687 s390_load_address (dst_addr,
03688 gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
03689
03690 temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1, 0);
03691 if (temp != blocks)
03692 emit_move_insn (blocks, temp);
03693
03694 emit_cmp_and_jump_insns (blocks, const0_rtx,
03695 EQ, NULL_RTX, mode, 1, loop_end_label);
03696
03697 emit_jump (loop_start_label);
03698 emit_label (loop_end_label);
03699
03700 if (val == const0_rtx)
03701 emit_insn (gen_clrmem_short (dst, convert_to_mode (Pmode, count, 1)));
03702 else
03703 emit_insn (gen_movmem_short (dstp1, dst, convert_to_mode (Pmode, count, 1)));
03704 emit_label (end_label);
03705 }
03706 }
03707
03708
03709
03710
03711 void
03712 s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
03713 {
03714 rtx ccreg = gen_rtx_REG (CCUmode, CC_REGNUM);
03715 rtx tmp;
03716
03717
03718
03719 tmp = op0; op0 = op1; op1 = tmp;
03720
03721 if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
03722 {
03723 if (INTVAL (len) > 0)
03724 {
03725 emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (INTVAL (len) - 1)));
03726 emit_insn (gen_cmpint (target, ccreg));
03727 }
03728 else
03729 emit_move_insn (target, const0_rtx);
03730 }
03731 else if (TARGET_MVCLE)
03732 {
03733 emit_insn (gen_cmpmem_long (op0, op1, convert_to_mode (Pmode, len, 1)));
03734 emit_insn (gen_cmpint (target, ccreg));
03735 }
03736 else
03737 {
03738 rtx addr0, addr1, count, blocks, temp;
03739 rtx loop_start_label = gen_label_rtx ();
03740 rtx loop_end_label = gen_label_rtx ();
03741 rtx end_label = gen_label_rtx ();
03742 enum machine_mode mode;
03743
03744 mode = GET_MODE (len);
03745 if (mode == VOIDmode)
03746 mode = Pmode;
03747
03748 addr0 = gen_reg_rtx (Pmode);
03749 addr1 = gen_reg_rtx (Pmode);
03750 count = gen_reg_rtx (mode);
03751 blocks = gen_reg_rtx (mode);
03752
03753 convert_move (count, len, 1);
03754 emit_cmp_and_jump_insns (count, const0_rtx,
03755 EQ, NULL_RTX, mode, 1, end_label);
03756
03757 emit_move_insn (addr0, force_operand (XEXP (op0, 0), NULL_RTX));
03758 emit_move_insn (addr1, force_operand (XEXP (op1, 0), NULL_RTX));
03759 op0 = change_address (op0, VOIDmode, addr0);
03760 op1 = change_address (op1, VOIDmode, addr1);
03761
03762 temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0);
03763 if (temp != count)
03764 emit_move_insn (count, temp);
03765
03766 temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1, 0);
03767 if (temp != blocks)
03768 emit_move_insn (blocks, temp);
03769
03770 emit_cmp_and_jump_insns (blocks, const0_rtx,
03771 EQ, NULL_RTX, mode, 1, loop_end_label);
03772
03773 emit_label (loop_start_label);
03774
03775 emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (255)));
03776 temp = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
03777 temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
03778 gen_rtx_LABEL_REF (VOIDmode, end_label), pc_rtx);
03779 temp = gen_rtx_SET (VOIDmode, pc_rtx, temp);
03780 emit_jump_insn (temp);
03781
03782 s390_load_address (addr0,
03783 gen_rtx_PLUS (Pmode, addr0, GEN_INT (256)));
03784 s390_load_address (addr1,
03785 gen_rtx_PLUS (Pmode, addr1, GEN_INT (256)));
03786
03787 temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1, 0);
03788 if (temp != blocks)
03789 emit_move_insn (blocks, temp);
03790
03791 emit_cmp_and_jump_insns (blocks, const0_rtx,
03792 EQ, NULL_RTX, mode, 1, loop_end_label);
03793
03794 emit_jump (loop_start_label);
03795 emit_label (loop_end_label);
03796
03797 emit_insn (gen_cmpmem_short (op0, op1,
03798 convert_to_mode (Pmode, count, 1)));
03799 emit_label (end_label);
03800
03801 emit_insn (gen_cmpint (target, ccreg));
03802 }
03803 }
03804
03805
03806
03807
03808
03809
03810
03811
03812
03813
03814
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825 bool
03826 s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
03827 rtx dst, rtx src, rtx increment)
03828 {
03829 enum machine_mode cmp_mode;
03830 enum machine_mode cc_mode;
03831 rtx op_res;
03832 rtx insn;
03833 rtvec p;
03834 int ret;
03835
03836 if ((GET_MODE (cmp_op0) == SImode || GET_MODE (cmp_op0) == VOIDmode)
03837 && (GET_MODE (cmp_op1) == SImode || GET_MODE (cmp_op1) == VOIDmode))
03838 cmp_mode = SImode;
03839 else if ((GET_MODE (cmp_op0) == DImode || GET_MODE (cmp_op0) == VOIDmode)
03840 && (GET_MODE (cmp_op1) == DImode || GET_MODE (cmp_op1) == VOIDmode))
03841 cmp_mode = DImode;
03842 else
03843 return false;
03844
03845
03846 if (increment == const1_rtx)
03847 {
03848
03849 if (cmp_code == EQ || cmp_code == NE)
03850 {
03851 if (cmp_op1 != const0_rtx)
03852 {
03853 cmp_op0 = expand_simple_binop (cmp_mode, XOR, cmp_op0, cmp_op1,
03854 NULL_RTX, 0, OPTAB_WIDEN);
03855 cmp_op1 = const0_rtx;
03856 }
03857
03858 cmp_code = cmp_code == EQ ? LEU : GTU;
03859 }
03860
03861 if (cmp_code == LTU || cmp_code == LEU)
03862 {
03863 rtx tem = cmp_op0;
03864 cmp_op0 = cmp_op1;
03865 cmp_op1 = tem;
03866 cmp_code = swap_condition (cmp_code);
03867 }
03868
03869 switch (cmp_code)
03870 {
03871 case GTU:
03872 cc_mode = CCUmode;
03873 break;
03874
03875 case GEU:
03876 cc_mode = CCL3mode;
03877 break;
03878
03879 default:
03880 return false;
03881 }
03882
03883
03884 if (!register_operand (cmp_op0, cmp_mode))
03885 cmp_op0 = force_reg (cmp_mode, cmp_op0);
03886
03887 insn = gen_rtx_SET (VOIDmode, gen_rtx_REG (cc_mode, CC_REGNUM),
03888 gen_rtx_COMPARE (cc_mode, cmp_op0, cmp_op1));
03889
03890 ret = insn_invalid_p (emit_insn (insn));
03891 gcc_assert (!ret);
03892
03893
03894 op_res = gen_rtx_fmt_ee (cmp_code, GET_MODE (dst),
03895 gen_rtx_REG (cc_mode, CC_REGNUM),
03896 const0_rtx);
03897
03898 if (src != const0_rtx)
03899 {
03900 if (!register_operand (src, GET_MODE (dst)))
03901 src = force_reg (GET_MODE (dst), src);
03902
03903 src = gen_rtx_PLUS (GET_MODE (dst), src, const0_rtx);
03904 op_res = gen_rtx_PLUS (GET_MODE (dst), src, op_res);
03905 }
03906
03907 p = rtvec_alloc (2);
03908 RTVEC_ELT (p, 0) =
03909 gen_rtx_SET (VOIDmode, dst, op_res);
03910 RTVEC_ELT (p, 1) =
03911 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
03912 emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
03913
03914 return true;
03915 }
03916
03917
03918 if (increment == constm1_rtx)
03919 {
03920
03921 if (cmp_code == EQ || cmp_code == NE)
03922 {
03923 if (cmp_op1 != const0_rtx)
03924 {
03925 cmp_op0 = expand_simple_binop (cmp_mode, XOR, cmp_op0, cmp_op1,
03926 NULL_RTX, 0, OPTAB_WIDEN);
03927 cmp_op1 = const0_rtx;
03928 }
03929
03930 cmp_code = cmp_code == EQ ? LEU : GTU;
03931 }
03932
03933 if (cmp_code == GTU || cmp_code == GEU)
03934 {
03935 rtx tem = cmp_op0;
03936 cmp_op0 = cmp_op1;
03937 cmp_op1 = tem;
03938 cmp_code = swap_condition (cmp_code);
03939 }
03940
03941 switch (cmp_code)
03942 {
03943 case LEU:
03944 cc_mode = CCUmode;
03945 break;
03946
03947 case LTU:
03948 cc_mode = CCL3mode;
03949 break;
03950
03951 default:
03952 return false;
03953 }
03954
03955
03956 if (!register_operand (cmp_op0, cmp_mode))
03957 cmp_op0 = force_reg (cmp_mode, cmp_op0);
03958
03959 insn = gen_rtx_SET (VOIDmode, gen_rtx_REG (cc_mode, CC_REGNUM),
03960 gen_rtx_COMPARE (cc_mode, cmp_op0, cmp_op1));
03961
03962 ret = insn_invalid_p (emit_insn (insn));
03963 gcc_assert (!ret);
03964
03965
03966 if (!register_operand (src, GET_MODE (dst)))
03967 src = force_reg (GET_MODE (dst), src);
03968
03969 op_res = gen_rtx_MINUS (GET_MODE (dst),
03970 gen_rtx_MINUS (GET_MODE (dst), src, const0_rtx),
03971 gen_rtx_fmt_ee (cmp_code, GET_MODE (dst),
03972 gen_rtx_REG (cc_mode, CC_REGNUM),
03973 const0_rtx));
03974 p = rtvec_alloc (2);
03975 RTVEC_ELT (p, 0) =
03976 gen_rtx_SET (VOIDmode, dst, op_res);
03977 RTVEC_ELT (p, 1) =
03978 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
03979 emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
03980
03981 return true;
03982 }
03983
03984 return false;
03985 }
03986
03987
03988
03989 bool
03990 s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
03991 {
03992 int bitsize = INTVAL (op1);
03993 int bitpos = INTVAL (op2);
03994
03995
03996 if (bitsize % BITS_PER_UNIT)
03997 return false;
03998
03999 if (bitpos == 0
04000 && memory_operand (dest, VOIDmode)
04001 && (register_operand (src, word_mode)
04002 || const_int_operand (src, VOIDmode)))
04003 {
04004
04005 enum machine_mode mode = smallest_mode_for_size (bitsize, MODE_INT);
04006 if (GET_MODE_BITSIZE (mode) == bitsize)
04007 emit_move_insn (adjust_address (dest, mode, 0), gen_lowpart (mode, src));
04008
04009
04010 else if (const_int_operand (src, VOIDmode))
04011 {
04012 int size = bitsize / BITS_PER_UNIT;
04013 rtx src_mem = adjust_address (force_const_mem (word_mode, src), BLKmode,
04014 GET_MODE_SIZE (word_mode) - size);
04015
04016 dest = adjust_address (dest, BLKmode, 0);
04017 set_mem_size (dest, GEN_INT (size));
04018 s390_expand_movmem (dest, src_mem, GEN_INT (size));
04019 }
04020
04021
04022 else if (register_operand (src, word_mode))
04023 {
04024 if (bitsize <= GET_MODE_BITSIZE (SImode))
04025 emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, op1,
04026 const0_rtx), src);
04027 else
04028 {
04029
04030 int stcmh_width = bitsize - GET_MODE_BITSIZE (SImode);
04031 int size = stcmh_width / BITS_PER_UNIT;
04032
04033 emit_move_insn (adjust_address (dest, SImode, size),
04034 gen_lowpart (SImode, src));
04035 set_mem_size (dest, GEN_INT (size));
04036 emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, GEN_INT
04037 (stcmh_width), const0_rtx),
04038 gen_rtx_LSHIFTRT (word_mode, src, GEN_INT
04039 (GET_MODE_BITSIZE (SImode))));
04040 }
04041 }
04042 else
04043 return false;
04044
04045 return true;
04046 }
04047
04048
04049 if (TARGET_ZARCH
04050 && register_operand (dest, word_mode)
04051 && (bitpos % 16) == 0
04052 && (bitsize % 16) == 0
04053 && const_int_operand (src, VOIDmode))
04054 {
04055 HOST_WIDE_INT val = INTVAL (src);
04056 int regpos = bitpos + bitsize;
04057
04058 while (regpos > bitpos)
04059 {
04060 enum machine_mode putmode;
04061 int putsize;
04062
04063 if (TARGET_EXTIMM && (regpos % 32 == 0) && (regpos >= bitpos + 32))
04064 putmode = SImode;
04065 else
04066 putmode = HImode;
04067
04068 putsize = GET_MODE_BITSIZE (putmode);
04069 regpos -= putsize;
04070 emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest,
04071 GEN_INT (putsize),
04072 GEN_INT (regpos)),
04073 gen_int_mode (val, putmode));
04074 val >>= putsize;
04075 }
04076 gcc_assert (regpos == bitpos);
04077 return true;
04078 }
04079
04080 return false;
04081 }
04082
04083
04084
04085
04086 static inline rtx
04087 s390_expand_mask_and_shift (rtx val, enum machine_mode mode, rtx count)
04088 {
04089 val = expand_simple_binop (SImode, AND, val, GEN_INT (GET_MODE_MASK (mode)),
04090 NULL_RTX, 1, OPTAB_DIRECT);
04091 return expand_simple_binop (SImode, ASHIFT, val, count,
04092 NULL_RTX, 1, OPTAB_DIRECT);
04093 }
04094
04095
04096
04097
04098 struct alignment_context
04099 {
04100 rtx memsi;
04101 rtx shift;
04102 rtx modemask;
04103 rtx modemaski;
04104 bool aligned;
04105 };
04106
04107
04108
04109
04110
04111
04112 static void
04113 init_alignment_context (struct alignment_context *ac, rtx mem,
04114 enum machine_mode mode)
04115 {
04116 ac->shift = GEN_INT (GET_MODE_SIZE (SImode) - GET_MODE_SIZE (mode));
04117 ac->aligned = (MEM_ALIGN (mem) >= GET_MODE_BITSIZE (SImode));
04118
04119 if (ac->aligned)
04120 ac->memsi = adjust_address (mem, SImode, 0);
04121 else
04122 {
04123
04124 rtx byteoffset, addr, align;
04125
04126
04127 addr = force_reg (Pmode, XEXP (mem, 0));
04128
04129
04130 align = expand_simple_binop (Pmode, AND, addr,
04131 GEN_INT (-GET_MODE_SIZE (SImode)),
04132 NULL_RTX, 1, OPTAB_DIRECT);
04133
04134 ac->memsi = gen_rtx_MEM (SImode, align);
04135 MEM_VOLATILE_P (ac->memsi) = MEM_VOLATILE_P (mem);
04136 set_mem_alias_set (ac->memsi, ALIAS_SET_MEMORY_BARRIER);
04137 set_mem_align (ac->memsi, GET_MODE_BITSIZE (SImode));
04138
04139
04140 byteoffset = expand_simple_binop (Pmode, AND, addr,
04141 GEN_INT (GET_MODE_SIZE (SImode) - 1),
04142 NULL_RTX, 1, OPTAB_DIRECT);
04143
04144 ac->shift = expand_simple_binop (SImode, MINUS, ac->shift, byteoffset,
04145 NULL_RTX, 1, OPTAB_DIRECT);
04146
04147 }
04148
04149 ac->shift = expand_simple_binop (SImode, MULT, ac->shift, GEN_INT (BITS_PER_UNIT),
04150 NULL_RTX, 1, OPTAB_DIRECT);
04151
04152 ac->modemask = expand_simple_binop (SImode, ASHIFT,
04153 GEN_INT (GET_MODE_MASK (mode)), ac->shift,
04154 NULL_RTX, 1, OPTAB_DIRECT);
04155 ac->modemaski = expand_simple_unop (SImode, NOT, ac->modemask, NULL_RTX, 1);
04156 }
04157
04158
04159
04160
04161
04162
04163
04164 void
04165 s390_expand_cs_hqi (enum machine_mode mode, rtx target, rtx mem, rtx cmp, rtx new)
04166 {
04167 struct alignment_context ac;
04168 rtx cmpv, newv, val, resv, cc;
04169 rtx res = gen_reg_rtx (SImode);
04170 rtx csloop = gen_label_rtx ();
04171 rtx csend = gen_label_rtx ();
04172
04173 gcc_assert (register_operand (target, VOIDmode));
04174 gcc_assert (MEM_P (mem));
04175
04176 init_alignment_context (&ac, mem, mode);
04177
04178
04179 if (!(ac.aligned && MEM_P (cmp)))
04180 cmp = s390_expand_mask_and_shift (cmp, mode, ac.shift);
04181 if (!(ac.aligned && MEM_P (new)))
04182 new = s390_expand_mask_and_shift (new, mode, ac.shift);
04183
04184
04185 val = expand_simple_binop (SImode, AND, ac.memsi, ac.modemaski,
04186 NULL_RTX, 1, OPTAB_DIRECT);
04187
04188
04189 emit_label (csloop);
04190
04191
04192
04193
04194
04195
04196 if (ac.aligned && MEM_P (cmp))
04197 {
04198 cmpv = force_reg (SImode, val);
04199 store_bit_field (cmpv, GET_MODE_BITSIZE (mode), 0, SImode, cmp);
04200 }
04201 else
04202 cmpv = force_reg (SImode, expand_simple_binop (SImode, IOR, cmp, val,
04203 NULL_RTX, 1, OPTAB_DIRECT));
04204 if (ac.aligned && MEM_P (new))
04205 {
04206 newv = force_reg (SImode, val);
04207 store_bit_field (newv, GET_MODE_BITSIZE (mode), 0, SImode, new);
04208 }
04209 else
04210 newv = force_reg (SImode, expand_simple_binop (SImode, IOR, new, val,
04211 NULL_RTX, 1, OPTAB_DIRECT));
04212
04213
04214 s390_emit_jump (csend, s390_emit_compare_and_swap (EQ, res, ac.memsi,
04215 cmpv, newv));
04216
04217
04218 resv = expand_simple_binop (SImode, AND, res, ac.modemaski,
04219 NULL_RTX, 1, OPTAB_DIRECT);
04220 cc = s390_emit_compare (NE, resv, val);
04221 emit_move_insn (val, resv);
04222
04223 s390_emit_jump (csloop, cc);
04224
04225 emit_label (csend);
04226
04227
04228 convert_move (target, expand_simple_binop (SImode, LSHIFTRT, res, ac.shift,
04229 NULL_RTX, 1, OPTAB_DIRECT), 1);
04230 }
04231
04232
04233
04234
04235
04236
04237
04238 void
04239 s390_expand_atomic (enum machine_mode mode, enum rtx_code code,
04240 rtx target, rtx mem, rtx val, bool after)
04241 {
04242 struct alignment_context ac;
04243 rtx cmp;
04244 rtx new = gen_reg_rtx (SImode);
04245 rtx orig = gen_reg_rtx (SImode);
04246 rtx csloop = gen_label_rtx ();
04247
04248 gcc_assert (!target || register_operand (target, VOIDmode));
04249 gcc_assert (MEM_P (mem));
04250
04251 init_alignment_context (&ac, mem, mode);
04252
04253
04254
04255 if (!(ac.aligned && code == SET && MEM_P (val)))
04256 val = s390_expand_mask_and_shift (val, mode, ac.shift);
04257
04258
04259 if (code == PLUS || code == MINUS)
04260 emit_move_insn (orig, val);
04261 else if (code == MULT || code == AND)
04262 val = expand_simple_binop (SImode, XOR, val, ac.modemaski,
04263 NULL_RTX, 1, OPTAB_DIRECT);
04264
04265
04266 cmp = force_reg (SImode, ac.memsi);
04267
04268
04269 emit_label (csloop);
04270 emit_move_insn (new, cmp);
04271
04272
04273 switch (code)
04274 {
04275 case PLUS:
04276 case MINUS:
04277 val = expand_simple_binop (SImode, code, new, orig,
04278 NULL_RTX, 1, OPTAB_DIRECT);
04279 val = expand_simple_binop (SImode, AND, val, ac.modemask,
04280 NULL_RTX, 1, OPTAB_DIRECT);
04281
04282 case SET:
04283 if (ac.aligned && MEM_P (val))
04284 store_bit_field (new, GET_MODE_BITSIZE (mode), 0, SImode, val);
04285 else
04286 {
04287 new = expand_simple_binop (SImode, AND, new, ac.modemaski,
04288 NULL_RTX, 1, OPTAB_DIRECT);
04289 new = expand_simple_binop (SImode, IOR, new, val,
04290 NULL_RTX, 1, OPTAB_DIRECT);
04291 }
04292 break;
04293 case AND:
04294 case IOR:
04295 case XOR:
04296 new = expand_simple_binop (SImode, code, new, val,
04297 NULL_RTX, 1, OPTAB_DIRECT);
04298 break;
04299 case MULT:
04300 new = expand_simple_binop (SImode, XOR, new, ac.modemask,
04301 NULL_RTX, 1, OPTAB_DIRECT);
04302 new = expand_simple_binop (SImode, AND, new, val,
04303 NULL_RTX, 1, OPTAB_DIRECT);
04304 break;
04305 default:
04306 gcc_unreachable ();
04307 }
04308
04309 s390_emit_jump (csloop, s390_emit_compare_and_swap (NE, cmp,
04310 ac.memsi, cmp, new));
04311
04312
04313 if (target)
04314 convert_move (target, expand_simple_binop (SImode, LSHIFTRT,
04315 after ? new : cmp, ac.shift,
04316 NULL_RTX, 1, OPTAB_DIRECT), 1);
04317 }
04318
04319
04320
04321
04322 static void s390_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
04323
04324 static void
04325 s390_output_dwarf_dtprel (FILE *file, int size, rtx x)
04326 {
04327 switch (size)
04328 {
04329 case 4:
04330 fputs ("\t.long\t", file);
04331 break;
04332 case 8:
04333 fputs ("\t.quad\t", file);
04334 break;
04335 default:
04336 gcc_unreachable ();
04337 }
04338 output_addr_const (file, x);
04339 fputs ("@DTPOFF", file);
04340 }
04341
04342 #ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
04343
04344
04345 static const char *
04346 s390_mangle_fundamental_type (tree type)
04347 {
04348 if (TYPE_MAIN_VARIANT (type) == long_double_type_node
04349 && TARGET_LONG_DOUBLE_128)
04350 return "g";
04351
04352
04353 return NULL;
04354 }
04355 #endif
04356
04357
04358
04359
04360
04361 static rtx
04362 s390_delegitimize_address (rtx orig_x)
04363 {
04364 rtx x = orig_x, y;
04365
04366 if (GET_CODE (x) != MEM)
04367 return orig_x;
04368
04369 x = XEXP (x, 0);
04370 if (GET_CODE (x) == PLUS
04371 && GET_CODE (XEXP (x, 1)) == CONST
04372 && GET_CODE (XEXP (x, 0)) == REG
04373 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
04374 {
04375 y = XEXP (XEXP (x, 1), 0);
04376 if (GET_CODE (y) == UNSPEC
04377 && XINT (y, 1) == UNSPEC_GOT)
04378 return XVECEXP (y, 0, 0);
04379 return orig_x;
04380 }
04381
04382 if (GET_CODE (x) == CONST)
04383 {
04384 y = XEXP (x, 0);
04385 if (GET_CODE (y) == UNSPEC
04386 && XINT (y, 1) == UNSPEC_GOTENT)
04387 return XVECEXP (y, 0, 0);
04388 return orig_x;
04389 }
04390
04391 return orig_x;
04392 }
04393
04394
04395
04396
04397
04398 static void
04399 print_shift_count_operand (FILE *file, rtx op)
04400 {
04401 HOST_WIDE_INT offset;
04402 rtx base;
04403
04404
04405 if (!s390_decompose_shift_count (op, &base, &offset))
04406 gcc_unreachable ();
04407
04408
04409 if (base)
04410 {
04411 gcc_assert (GET_CODE (base) == REG);
04412 gcc_assert (REGNO (base) < FIRST_PSEUDO_REGISTER);
04413 gcc_assert (REGNO_REG_CLASS (REGNO (base)) == ADDR_REGS);
04414 }
04415
04416
04417 fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset & ((1 << 12) - 1));
04418 if (base)
04419 fprintf (file, "(%s)", reg_names[REGNO (base)]);
04420 }
04421
04422
04423
04424 static int
04425 get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
04426 {
04427 rtx x = *px;
04428
04429 if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
04430 {
04431 x = get_pool_constant (x);
04432 return for_each_rtx (&x, get_some_local_dynamic_name_1, 0);
04433 }
04434
04435 if (GET_CODE (x) == SYMBOL_REF
04436 && tls_symbolic_operand (x) == TLS_MODEL_LOCAL_DYNAMIC)
04437 {
04438 cfun->machine->some_ld_name = XSTR (x, 0);
04439 return 1;
04440 }
04441
04442 return 0;
04443 }
04444
04445
04446
04447
04448 static const char *
04449 get_some_local_dynamic_name (void)
04450 {
04451 rtx insn;
04452
04453 if (cfun->machine->some_ld_name)
04454 return cfun->machine->some_ld_name;
04455
04456 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
04457 if (INSN_P (insn)
04458 && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
04459 return cfun->machine->some_ld_name;
04460
04461 gcc_unreachable ();
04462 }
04463
04464
04465
04466
04467
04468 bool
04469 s390_output_addr_const_extra (FILE *file, rtx x)
04470 {
04471 if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 1)
04472 switch (XINT (x, 1))
04473 {
04474 case UNSPEC_GOTENT:
04475 output_addr_const (file, XVECEXP (x, 0, 0));
04476 fprintf (file, "@GOTENT");
04477 return true;
04478 case UNSPEC_GOT:
04479 output_addr_const (file, XVECEXP (x, 0, 0));
04480 fprintf (file, "@GOT");
04481 return true;
04482 case UNSPEC_GOTOFF:
04483 output_addr_const (file, XVECEXP (x, 0, 0));
04484 fprintf (file, "@GOTOFF");
04485 return true;
04486 case UNSPEC_PLT:
04487 output_addr_const (file, XVECEXP (x, 0, 0));
04488 fprintf (file, "@PLT");
04489 return true;
04490 case UNSPEC_PLTOFF:
04491 output_addr_const (file, XVECEXP (x, 0, 0));
04492 fprintf (file, "@PLTOFF");
04493 return true;
04494 case UNSPEC_TLSGD:
04495 output_addr_const (file, XVECEXP (x, 0, 0));
04496 fprintf (file, "@TLSGD");
04497 return true;
04498 case UNSPEC_TLSLDM:
04499 assemble_name (file, get_some_local_dynamic_name ());
04500 fprintf (file, "@TLSLDM");
04501 return true;
04502 case UNSPEC_DTPOFF:
04503 output_addr_const (file, XVECEXP (x, 0, 0));
04504 fprintf (file, "@DTPOFF");
04505 return true;
04506 case UNSPEC_NTPOFF:
04507 output_addr_const (file, XVECEXP (x, 0, 0));
04508 fprintf (file, "@NTPOFF");
04509 return true;
04510 case UNSPEC_GOTNTPOFF:
04511 output_addr_const (file, XVECEXP (x, 0, 0));
04512 fprintf (file, "@GOTNTPOFF");
04513 return true;
04514 case UNSPEC_INDNTPOFF:
04515 output_addr_const (file, XVECEXP (x, 0, 0));
04516 fprintf (file, "@INDNTPOFF");
04517 return true;
04518 }
04519
04520 return false;
04521 }
04522
04523
04524
04525
04526 void
04527 print_operand_address (FILE *file, rtx addr)
04528 {
04529 struct s390_address ad;
04530
04531 if (!s390_decompose_address (addr, &ad)
04532 || (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
04533 || (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx))))
04534 output_operand_lossage ("cannot decompose address");
04535
04536 if (ad.disp)
04537 output_addr_const (file, ad.disp);
04538 else
04539 fprintf (file, "0");
04540
04541 if (ad.base && ad.indx)
04542 fprintf (file, "(%s,%s)", reg_names[REGNO (ad.indx)],
04543 reg_names[REGNO (ad.base)]);
04544 else if (ad.base)
04545 fprintf (file, "(%s)", reg_names[REGNO (ad.base)]);
04546 }
04547
04548
04549
04550
04551
04552
04553
04554
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572 void
04573 print_operand (FILE *file, rtx x, int code)
04574 {
04575 switch (code)
04576 {
04577 case 'C':
04578 fprintf (file, s390_branch_condition_mnemonic (x, FALSE));
04579 return;
04580
04581 case 'D':
04582 fprintf (file, s390_branch_condition_mnemonic (x, TRUE));
04583 return;
04584
04585 case 'J':
04586 if (GET_CODE (x) == SYMBOL_REF)
04587 {
04588 fprintf (file, "%s", ":tls_load:");
04589 output_addr_const (file, x);
04590 }
04591 else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD)
04592 {
04593 fprintf (file, "%s", ":tls_gdcall:");
04594 output_addr_const (file, XVECEXP (x, 0, 0));
04595 }
04596 else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM)
04597 {
04598 fprintf (file, "%s", ":tls_ldcall:");
04599 assemble_name (file, get_some_local_dynamic_name ());
04600 }
04601 else
04602 gcc_unreachable ();
04603 return;
04604
04605 case 'G':
04606 fprintf (file, "%u", GET_MODE_SIZE (GET_MODE (x)));
04607 return;
04608
04609 case 'O':
04610 {
04611 struct s390_address ad;
04612 int ret;
04613
04614 gcc_assert (GET_CODE (x) == MEM);
04615 ret = s390_decompose_address (XEXP (x, 0), &ad);
04616 gcc_assert (ret);
04617 gcc_assert (!ad.base || REGNO_OK_FOR_BASE_P (REGNO (ad.base)));
04618 gcc_assert (!ad.indx);
04619
04620 if (ad.disp)
04621 output_addr_const (file, ad.disp);
04622 else
04623 fprintf (file, "0");
04624 }
04625 return;
04626
04627 case 'R':
04628 {
04629 struct s390_address ad;
04630 int ret;
04631
04632 gcc_assert (GET_CODE (x) == MEM);
04633 ret = s390_decompose_address (XEXP (x, 0), &ad);
04634 gcc_assert (ret);
04635 gcc_assert (!ad.base || REGNO_OK_FOR_BASE_P (REGNO (ad.base)));
04636 gcc_assert (!ad.indx);
04637
04638 if (ad.base)
04639 fprintf (file, "%s", reg_names[REGNO (ad.base)]);
04640 else
04641 fprintf (file, "0");
04642 }
04643 return;
04644
04645 case 'S':
04646 {
04647 struct s390_address ad;
04648 int ret;
04649
04650 gcc_assert (GET_CODE (x) == MEM);
04651 ret = s390_decompose_address (XEXP (x, 0), &ad);
04652 gcc_assert (ret);
04653 gcc_assert (!ad.base || REGNO_OK_FOR_BASE_P (REGNO (ad.base)));
04654 gcc_assert (!ad.indx);
04655
04656 if (ad.disp)
04657 output_addr_const (file, ad.disp);
04658 else
04659 fprintf (file, "0");
04660
04661 if (ad.base)
04662 fprintf (file, "(%s)", reg_names[REGNO (ad.base)]);
04663 }
04664 return;
04665
04666 case 'N':
04667 if (GET_CODE (x) == REG)
04668 x = gen_rtx_REG (GET_MODE (x), REGNO (x) + 1);
04669 else if (GET_CODE (x) == MEM)
04670 x = change_address (x, VOIDmode, plus_constant (XEXP (x, 0), 4));
04671 else
04672 gcc_unreachable ();
04673 break;
04674
04675 case 'M':
04676 if (GET_CODE (x) == REG)
04677 x = gen_rtx_REG (GET_MODE (x), REGNO (x) + 1);
04678 else if (GET_CODE (x) == MEM)
04679 x = change_address (x, VOIDmode, plus_constant (XEXP (x, 0), 8));
04680 else
04681 gcc_unreachable ();
04682 break;
04683
04684 case 'Y':
04685 print_shift_count_operand (file, x);
04686 return;
04687 }
04688
04689 switch (GET_CODE (x))
04690 {
04691 case REG:
04692 fprintf (file, "%s", reg_names[REGNO (x)]);
04693 break;
04694
04695 case MEM:
04696 output_address (XEXP (x, 0));
04697 break;
04698
04699 case CONST:
04700 case CODE_LABEL:
04701 case LABEL_REF:
04702 case SYMBOL_REF:
04703 output_addr_const (file, x);
04704 break;
04705
04706 case CONST_INT:
04707 if (code == 'b')
04708 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xff);
04709 else if (code == 'x')
04710 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffff);
04711 else if (code == 'h')
04712 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xffff) ^ 0x8000) - 0x8000);
04713 else if (code == 'i')
04714 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
04715 s390_extract_part (x, HImode, 0));
04716 else if (code == 'j')
04717 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
04718 s390_extract_part (x, HImode, -1));
04719 else if (code == 'k')
04720 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
04721 s390_extract_part (x, SImode, 0));
04722 else if (code == 'm')
04723 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
04724 s390_extract_part (x, SImode, -1));
04725 else if (code == 'o')
04726 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffffffff);
04727 else
04728 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
04729 break;
04730
04731 case CONST_DOUBLE:
04732 gcc_assert (GET_MODE (x) == VOIDmode);
04733 if (code == 'b')
04734 fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x) & 0xff);
04735 else if (code == 'x')
04736 fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x) & 0xffff);
04737 else if (code == 'h')
04738 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((CONST_DOUBLE_LOW (x) & 0xffff) ^ 0x8000) - 0x8000);
04739 else
04740 gcc_unreachable ();
04741 break;
04742
04743 default:
04744 fatal_insn ("UNKNOWN in print_operand !?", x);
04745 break;
04746 }
04747 }
04748
04749
04750
04751
04752
04753 static bool
04754 s390_assemble_integer (rtx x, unsigned int size, int aligned_p)
04755 {
04756 if (size == 8 && aligned_p
04757 && GET_CODE (x) == CONST_INT && INTVAL (x) < INT_MIN)
04758 {
04759 fprintf (asm_out_file, "\t.quad\t" HOST_WIDE_INT_PRINT_HEX "\n",
04760 INTVAL (x));
04761 return true;
04762 }
04763 return default_assemble_integer (x, size, aligned_p);
04764 }
04765
04766
04767
04768
04769 static bool
04770 reg_used_in_mem_p (int regno, rtx x)
04771 {
04772 enum rtx_code code = GET_CODE (x);
04773 int i, j;
04774 const char *fmt;
04775
04776 if (code == MEM)
04777 {
04778 if (refers_to_regno_p (regno, regno+1,
04779 XEXP (x, 0), 0))
04780 return true;
04781 }
04782 else if (code == SET
04783 && GET_CODE (SET_DEST (x)) == PC)
04784 {
04785 if (refers_to_regno_p (regno, regno+1,
04786 SET_SRC (x), 0))
04787 return true;
04788 }
04789
04790 fmt = GET_RTX_FORMAT (code);
04791 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
04792 {
04793 if (fmt[i] == 'e'
04794 && reg_used_in_mem_p (regno, XEXP (x, i)))
04795 return true;
04796
04797 else if (fmt[i] == 'E')
04798 for (j = 0; j < XVECLEN (x, i); j++)
04799 if (reg_used_in_mem_p (regno, XVECEXP (x, i, j)))
04800 return true;
04801 }
04802 return false;
04803 }
04804
04805
04806
04807
04808 static bool
04809 addr_generation_dependency_p (rtx dep_rtx, rtx insn)
04810 {
04811 rtx target, pat;
04812
04813 if (GET_CODE (dep_rtx) == INSN)
04814 dep_rtx = PATTERN (dep_rtx);
04815
04816 if (GET_CODE (dep_rtx) == SET)
04817 {
04818 target = SET_DEST (dep_rtx);
04819 if (GET_CODE (target) == STRICT_LOW_PART)
04820 target = XEXP (target, 0);
04821 while (GET_CODE (target) == SUBREG)
04822 target = SUBREG_REG (target);
04823
04824 if (GET_CODE (target) == REG)
04825 {
04826 int regno = REGNO (target);
04827
04828 if (s390_safe_attr_type (insn) == TYPE_LA)
04829 {
04830 pat = PATTERN (insn);
04831 if (GET_CODE (pat) == PARALLEL)
04832 {
04833 gcc_assert (XVECLEN (pat, 0) == 2);
04834 pat = XVECEXP (pat, 0, 0);
04835 }
04836 gcc_assert (GET_CODE (pat) == SET);
04837 return refers_to_regno_p (regno, regno+1, SET_SRC (pat), 0);
04838 }
04839 else if (get_attr_atype (insn) == ATYPE_AGEN)
04840 return reg_used_in_mem_p (regno, PATTERN (insn));
04841 }
04842 }
04843 return false;
04844 }
04845
04846
04847
04848 int
04849 s390_agen_dep_p (rtx dep_insn, rtx insn)
04850 {
04851 rtx dep_rtx = PATTERN (dep_insn);
04852 int i;
04853
04854 if (GET_CODE (dep_rtx) == SET
04855 && addr_generation_dependency_p (dep_rtx, insn))
04856 return 1;
04857 else if (GET_CODE (dep_rtx) == PARALLEL)
04858 {
04859 for (i = 0; i < XVECLEN (dep_rtx, 0); i++)
04860 {
04861 if (addr_generation_dependency_p (XVECEXP (dep_rtx, 0, i), insn))
04862 return 1;
04863 }
04864 }
04865 return 0;
04866 }
04867
04868
04869
04870
04871
04872
04873
04874
04875
04876 static int
04877 s390_adjust_priority (rtx insn ATTRIBUTE_UNUSED, int priority)
04878 {
04879 if (! INSN_P (insn))
04880 return priority;
04881
04882 if (s390_tune != PROCESSOR_2084_Z990
04883 && s390_tune != PROCESSOR_2094_Z9_109)
04884 return priority;
04885
04886 switch (s390_safe_attr_type (insn))
04887 {
04888 case TYPE_FSTOREDF:
04889 case TYPE_FSTORESF:
04890 priority = priority << 3;
04891 break;
04892 case TYPE_STORE:
04893 case TYPE_STM:
04894 priority = priority << 1;
04895 break;
04896 default:
04897 break;
04898 }
04899 return priority;
04900 }
04901
04902
04903
04904 static int
04905 s390_issue_rate (void)
04906 {
04907 if (s390_tune == PROCESSOR_2084_Z990
04908 || s390_tune == PROCESSOR_2094_Z9_109)
04909 return 3;
04910 return 1;
04911 }
04912
04913 static int
04914 s390_first_cycle_multipass_dfa_lookahead (void)
04915 {
04916 return 4;
04917 }
04918
04919
04920
04921
04922
04923 static void
04924 annotate_constant_pool_refs (rtx *x)
04925 {
04926 int i, j;
04927 const char *fmt;
04928
04929 gcc_assert (GET_CODE (*x) != SYMBOL_REF
04930 || !CONSTANT_POOL_ADDRESS_P (*x));
04931
04932
04933 if (GET_CODE (*x) == MEM)
04934 {
04935 rtx memref = XEXP (*x, 0);
04936
04937 if (GET_CODE (memref) == SYMBOL_REF
04938 && CONSTANT_POOL_ADDRESS_P (memref))
04939 {
04940 rtx base = cfun->machine->base_reg;
04941 rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, memref, base),
04942 UNSPEC_LTREF);
04943
04944 *x = replace_equiv_address (*x, addr);
04945 return;
04946 }
04947
04948 if (GET_CODE (memref) == CONST
04949 && GET_CODE (XEXP (memref, 0)) == PLUS
04950 && GET_CODE (XEXP (XEXP (memref, 0), 1)) == CONST_INT
04951 && GET_CODE (XEXP (XEXP (memref, 0), 0)) == SYMBOL_REF
04952 && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (memref, 0), 0)))
04953 {
04954 HOST_WIDE_INT off = INTVAL (XEXP (XEXP (memref, 0), 1));
04955 rtx sym = XEXP (XEXP (memref, 0), 0);
04956 rtx base = cfun->machine->base_reg;
04957 rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
04958 UNSPEC_LTREF);
04959
04960 *x = replace_equiv_address (*x, plus_constant (addr, off));
04961 return;
04962 }
04963 }
04964
04965
04966 if (GET_CODE (*x) == SET)
04967 {
04968 rtx addrref = SET_SRC (*x);
04969
04970 if (GET_CODE (addrref) == SYMBOL_REF
04971 && CONSTANT_POOL_ADDRESS_P (addrref))
04972 {
04973 rtx base = cfun->machine->base_reg;
04974 rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, addrref, base),
04975 UNSPEC_LTREF);
04976
04977 SET_SRC (*x) = addr;
04978 return;
04979 }
04980
04981 if (GET_CODE (addrref) == CONST
04982 && GET_CODE (XEXP (addrref, 0)) == PLUS
04983 && GET_CODE (XEXP (XEXP (addrref, 0), 1)) == CONST_INT
04984 && GET_CODE (XEXP (XEXP (addrref, 0), 0)) == SYMBOL_REF
04985 && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (addrref, 0), 0)))
04986 {
04987 HOST_WIDE_INT off = INTVAL (XEXP (XEXP (addrref, 0), 1));
04988 rtx sym = XEXP (XEXP (addrref, 0), 0);
04989 rtx base = cfun->machine->base_reg;
04990 rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
04991 UNSPEC_LTREF);
04992
04993 SET_SRC (*x) = plus_constant (addr, off);
04994 return;
04995 }
04996 }
04997
04998
04999 if (GET_CODE (*x) == UNSPEC
05000 && XINT (*x, 1) == UNSPEC_LTREL_BASE)
05001 {
05002 rtx base = cfun->machine->base_reg;
05003 *x = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XVECEXP (*x, 0, 0), base),
05004 UNSPEC_LTREL_BASE);
05005 return;
05006 }
05007
05008 fmt = GET_RTX_FORMAT (GET_CODE (*x));
05009 for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
05010 {
05011 if (fmt[i] == 'e')
05012 {
05013 annotate_constant_pool_refs (&XEXP (*x, i));
05014 }
05015 else if (fmt[i] == 'E')
05016 {
05017 for (j = 0; j < XVECLEN (*x, i); j++)
05018 annotate_constant_pool_refs (&XVECEXP (*x, i, j));
05019 }
05020 }
05021 }
05022
05023
05024
05025
05026 static int
05027 s390_split_branches (void)
05028 {
05029 rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
05030 int new_literal = 0, ret;
05031 rtx insn, pat, tmp, target;
05032 rtx *label;
05033
05034
05035
05036 shorten_branches (get_insns ());
05037
05038
05039
05040 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
05041 {
05042 if (GET_CODE (insn) != JUMP_INSN)
05043 continue;
05044
05045 pat = PATTERN (insn);
05046 if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
05047 pat = XVECEXP (pat, 0, 0);
05048 if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
05049 continue;
05050
05051 if (GET_CODE (SET_SRC (pat)) == LABEL_REF)
05052 {
05053 label = &SET_SRC (pat);
05054 }
05055 else if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
05056 {
05057 if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF)
05058 label = &XEXP (SET_SRC (pat), 1);
05059 else if (GET_CODE (XEXP (SET_SRC (pat), 2)) == LABEL_REF)
05060 label = &XEXP (SET_SRC (pat), 2);
05061 else
05062 continue;
05063 }
05064 else
05065 continue;
05066
05067 if (get_attr_length (insn) <= 4)
05068 continue;
05069
05070
05071
05072 cfun_frame_layout.save_return_addr_p = 1;
05073
05074 if (!flag_pic)
05075 {
05076 new_literal = 1;
05077 tmp = force_const_mem (Pmode, *label);
05078 tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn);
05079 INSN_ADDRESSES_NEW (tmp, -1);
05080 annotate_constant_pool_refs (&PATTERN (tmp));
05081
05082 target = temp_reg;
05083 }
05084 else
05085 {
05086 new_literal = 1;
05087 target = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, *label),
05088 UNSPEC_LTREL_OFFSET);
05089 target = gen_rtx_CONST (Pmode, target);
05090 target = force_const_mem (Pmode, target);
05091 tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, target), insn);
05092 INSN_ADDRESSES_NEW (tmp, -1);
05093 annotate_constant_pool_refs (&PATTERN (tmp));
05094
05095 target = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XEXP (target, 0),
05096 cfun->machine->base_reg),
05097 UNSPEC_LTREL_BASE);
05098 target = gen_rtx_PLUS (Pmode, temp_reg, target);
05099 }
05100
05101 ret = validate_change (insn, label, target, 0);
05102 gcc_assert (ret);
05103 }
05104
05105 return new_literal;
05106 }
05107
05108
05109
05110
05111
05112
05113
05114
05115
05116
05117 static void
05118 find_constant_pool_ref (rtx x, rtx *ref)
05119 {
05120 int i, j;
05121 const char *fmt;
05122
05123
05124 if (GET_CODE (x) == UNSPEC
05125 && XINT (x, 1) == UNSPEC_LTREL_BASE)
05126 return;
05127
05128 if (GET_CODE (x) == UNSPEC_VOLATILE
05129 && XINT (x, 1) == UNSPECV_POOL_ENTRY)
05130 return;
05131
05132 gcc_assert (GET_CODE (x) != SYMBOL_REF
05133 || !CONSTANT_POOL_ADDRESS_P (x));
05134
05135 if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_LTREF)
05136 {
05137 rtx sym = XVECEXP (x, 0, 0);
05138 gcc_assert (GET_CODE (sym) == SYMBOL_REF
05139 && CONSTANT_POOL_ADDRESS_P (sym));
05140
05141 if (*ref == NULL_RTX)
05142 *ref = sym;
05143 else
05144 gcc_assert (*ref == sym);
05145
05146 return;
05147 }
05148
05149 fmt = GET_RTX_FORMAT (GET_CODE (x));
05150 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
05151 {
05152 if (fmt[i] == 'e')
05153 {
05154 find_constant_pool_ref (XEXP (x, i), ref);
05155 }
05156 else if (fmt[i] == 'E')
05157 {
05158 for (j = 0; j < XVECLEN (x, i); j++)
05159 find_constant_pool_ref (XVECEXP (x, i, j), ref);
05160 }
05161 }
05162 }
05163
05164
05165
05166
05167 static void
05168 replace_constant_pool_ref (rtx *x, rtx ref, rtx offset)
05169 {
05170 int i, j;
05171 const char *fmt;
05172
05173 gcc_assert (*x != ref);
05174
05175 if (GET_CODE (*x) == UNSPEC
05176 && XINT (*x, 1) == UNSPEC_LTREF
05177 && XVECEXP (*x, 0, 0) == ref)
05178 {
05179 *x = gen_rtx_PLUS (Pmode, XVECEXP (*x, 0, 1), offset);
05180 return;
05181 }
05182
05183 if (GET_CODE (*x) == PLUS
05184 && GET_CODE (XEXP (*x, 1)) == CONST_INT
05185 && GET_CODE (XEXP (*x, 0)) == UNSPEC
05186 && XINT (XEXP (*x, 0), 1) == UNSPEC_LTREF
05187 && XVECEXP (XEXP (*x, 0), 0, 0) == ref)
05188 {
05189 rtx addr = gen_rtx_PLUS (Pmode, XVECEXP (XEXP (*x, 0), 0, 1), offset);
05190 *x = plus_constant (addr, INTVAL (XEXP (*x, 1)));
05191 return;
05192 }
05193
05194 fmt = GET_RTX_FORMAT (GET_CODE (*x));
05195 for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
05196 {
05197 if (fmt[i] == 'e')
05198 {
05199 replace_constant_pool_ref (&XEXP (*x, i), ref, offset);
05200 }
05201 else if (fmt[i] == 'E')
05202 {
05203 for (j = 0; j < XVECLEN (*x, i); j++)
05204 replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, offset);
05205 }
05206 }
05207 }
05208
05209
05210
05211
05212 static rtx
05213 find_ltrel_base (rtx x)
05214 {
05215 int i, j;
05216 const char *fmt;
05217
05218 if (GET_CODE (x) == UNSPEC
05219 && XINT (x, 1) == UNSPEC_LTREL_BASE)
05220 return XVECEXP (x, 0, 0);
05221
05222 fmt = GET_RTX_FORMAT (GET_CODE (x));
05223 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
05224 {
05225 if (fmt[i] == 'e')
05226 {
05227 rtx fnd = find_ltrel_base (XEXP (x, i));
05228 if (fnd)
05229 return fnd;
05230 }
05231 else if (fmt[i] == 'E')
05232 {
05233 for (j = 0; j < XVECLEN (x, i); j++)
05234 {
05235 rtx fnd = find_ltrel_base (XVECEXP (x, i, j));
05236 if (fnd)
05237 return fnd;
05238 }
05239 }
05240 }
05241
05242 return NULL_RTX;
05243 }
05244
05245
05246
05247 static void
05248 replace_ltrel_base (rtx *x)
05249 {
05250 int i, j;
05251 const char *fmt;
05252
05253 if (GET_CODE (*x) == UNSPEC
05254 && XINT (*x, 1) == UNSPEC_LTREL_BASE)
05255 {
05256 *x = XVECEXP (*x, 0, 1);
05257 return;
05258 }
05259
05260 fmt = GET_RTX_FORMAT (GET_CODE (*x));
05261 for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
05262 {
05263 if (fmt[i] == 'e')
05264 {
05265 replace_ltrel_base (&XEXP (*x, i));
05266 }
05267 else if (fmt[i] == 'E')
05268 {
05269 for (j = 0; j < XVECLEN (*x, i); j++)
05270 replace_ltrel_base (&XVECEXP (*x, i, j));
05271 }
05272 }
05273 }
05274
05275
05276
05277
05278
05279 #define NR_C_MODES 11
05280 enum machine_mode constant_modes[NR_C_MODES] =
05281 {
05282 TFmode, TImode, TDmode,
05283 DFmode, DImode, DDmode,
05284 SFmode, SImode, SDmode,
05285 HImode,
05286 QImode
05287 };
05288
05289 struct constant
05290 {
05291 struct constant *next;
05292 rtx value;
05293 rtx label;
05294 };
05295
05296 struct constant_pool
05297 {
05298 struct constant_pool *next;
05299 rtx first_insn;
05300 rtx pool_insn;
05301 bitmap insns;
05302
05303 struct constant *constants[NR_C_MODES];
05304 struct constant *execute;
05305 rtx label;
05306 int size;
05307 };
05308
05309
05310
05311 static struct constant_pool *
05312 s390_alloc_pool (void)
05313 {
05314 struct constant_pool *pool;
05315 int i;
05316
05317 pool = (struct constant_pool *) xmalloc (sizeof *pool);
05318 pool->next = NULL;
05319 for (i = 0; i < NR_C_MODES; i++)
05320 pool->constants[i] = NULL;
05321
05322 pool->execute = NULL;
05323 pool->label = gen_label_rtx ();
05324 pool->first_insn = NULL_RTX;
05325 pool->pool_insn = NULL_RTX;
05326 pool->insns = BITMAP_ALLOC (NULL);
05327 pool->size = 0;
05328
05329 return pool;
05330 }
05331
05332
05333
05334
05335 static struct constant_pool *
05336 s390_start_pool (struct constant_pool **pool_list, rtx insn)
05337 {
05338 struct constant_pool *pool, **prev;
05339
05340 pool = s390_alloc_pool ();
05341 pool->first_insn = insn;
05342
05343 for (prev = pool_list; *prev; prev = &(*prev)->next)
05344 ;
05345 *prev = pool;
05346
05347 return pool;
05348 }
05349
05350
05351
05352
05353 static void
05354 s390_end_pool (struct constant_pool *pool, rtx insn)
05355 {
05356 rtx pool_size = GEN_INT (pool->size + 8 );
05357
05358 if (!insn)
05359 insn = get_last_insn ();
05360
05361 pool->pool_insn = emit_insn_after (gen_pool (pool_size), insn);
05362 INSN_ADDRESSES_NEW (pool->pool_insn, -1);
05363 }
05364
05365
05366
05367 static void
05368 s390_add_pool_insn (struct constant_pool *pool, rtx insn)
05369 {
05370 bitmap_set_bit (pool->insns, INSN_UID (insn));
05371 }
05372
05373
05374
05375 static struct constant_pool *
05376 s390_find_pool (struct constant_pool *pool_list, rtx insn)
05377 {
05378 struct constant_pool *pool;
05379
05380 for (pool = pool_list; pool; pool = pool->next)
05381 if (bitmap_bit_p (pool->insns, INSN_UID (insn)))
05382 break;
05383
05384 return pool;
05385 }
05386
05387
05388
05389 static void
05390 s390_add_constant (struct constant_pool *pool, rtx val, enum machine_mode mode)
05391 {
05392 struct constant *c;
05393 int i;
05394
05395 for (i = 0; i < NR_C_MODES; i++)
05396 if (constant_modes[i] == mode)
05397 break;
05398 gcc_assert (i != NR_C_MODES);
05399
05400 for (c = pool->constants[i]; c != NULL; c = c->next)
05401 if (rtx_equal_p (val, c->value))
05402 break;
05403
05404 if (c == NULL)
05405 {
05406 c = (struct constant *) xmalloc (sizeof *c);
05407 c->value = val;
05408 c->label = gen_label_rtx ();
05409 c->next = pool->constants[i];
05410 pool->constants[i] = c;
05411 pool->size += GET_MODE_SIZE (mode);
05412 }
05413 }
05414
05415
05416
05417
05418
05419 static rtx
05420 s390_find_constant (struct constant_pool *pool, rtx val,
05421 enum machine_mode mode)
05422 {
05423 struct constant *c;
05424 rtx offset;
05425 int i;
05426
05427 for (i = 0; i < NR_C_MODES; i++)
05428 if (constant_modes[i] == mode)
05429 break;
05430 gcc_assert (i != NR_C_MODES);
05431
05432 for (c = pool->constants[i]; c != NULL; c = c->next)
05433 if (rtx_equal_p (val, c->value))
05434 break;
05435
05436 gcc_assert (c);
05437
05438 offset = gen_rtx_MINUS (Pmode, gen_rtx_LABEL_REF (Pmode, c->label),
05439 gen_rtx_LABEL_REF (Pmode, pool->label));
05440 offset = gen_rtx_CONST (Pmode, offset);
05441 return offset;
05442 }
05443
05444
05445
05446
05447 static rtx
05448 s390_execute_label (rtx insn)
05449 {
05450 if (GET_CODE (insn) == INSN
05451 && GET_CODE (PATTERN (insn)) == PARALLEL
05452 && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == UNSPEC
05453 && XINT (XVECEXP (PATTERN (insn), 0, 0), 1) == UNSPEC_EXECUTE)
05454 return XVECEXP (XVECEXP (PATTERN (insn), 0, 0), 0, 2);
05455
05456 return NULL_RTX;
05457 }
05458
05459
05460
05461 static void
05462 s390_add_execute (struct constant_pool *pool, rtx insn)
05463 {
05464 struct constant *c;
05465
05466 for (c = pool->execute; c != NULL; c = c->next)
05467 if (INSN_UID (insn) == INSN_UID (c->value))
05468 break;
05469
05470 if (c == NULL)
05471 {
05472 c = (struct constant *) xmalloc (sizeof *c);
05473 c->value = insn;
05474 c->label = gen_label_rtx ();
05475 c->next = pool->execute;
05476 pool->execute = c;
05477 pool->size += 6;
05478 }
05479 }
05480
05481
05482
05483
05484
05485 static rtx
05486 s390_find_execute (struct constant_pool *pool, rtx insn)
05487 {
05488 struct constant *c;
05489 rtx offset;
05490
05491 for (c = pool->execute; c != NULL; c = c->next)
05492 if (INSN_UID (insn) == INSN_UID (c->value))
05493 break;
05494
05495 gcc_assert (c);
05496
05497 offset = gen_rtx_MINUS (Pmode, gen_rtx_LABEL_REF (Pmode, c->label),
05498 gen_rtx_LABEL_REF (Pmode, pool->label));
05499 offset = gen_rtx_CONST (Pmode, offset);
05500 return offset;
05501 }
05502
05503
05504
05505 static rtx
05506 s390_execute_target (rtx insn)
05507 {
05508 rtx pattern = PATTERN (insn);
05509 gcc_assert (s390_execute_label (insn));
05510
05511 if (XVECLEN (pattern, 0) == 2)
05512 {
05513 pattern = copy_rtx (XVECEXP (pattern, 0, 1));
05514 }
05515 else
05516 {
05517 rtvec vec = rtvec_alloc (XVECLEN (pattern, 0) - 1);
05518 int i;
05519
05520 for (i = 0; i < XVECLEN (pattern, 0) - 1; i++)
05521 RTVEC_ELT (vec, i) = copy_rtx (XVECEXP (pattern, 0, i + 1));
05522
05523 pattern = gen_rtx_PARALLEL (VOIDmode, vec);
05524 }
05525
05526 return pattern;
05527 }
05528
05529
05530
05531
05532 static bool
05533 s390_cannot_copy_insn_p (rtx insn)
05534 {
05535 rtx label = s390_execute_label (insn);
05536 return label && label != const0_rtx;
05537 }
05538
05539
05540
05541
05542 static void
05543 s390_dump_pool (struct constant_pool *pool, bool remote_label)
05544 {
05545 struct constant *c;
05546 rtx insn = pool->pool_insn;
05547 int i;
05548
05549
05550 if (TARGET_CPU_ZARCH)
05551 {
05552 insn = emit_insn_after (gen_pool_section_start (), insn);
05553 INSN_ADDRESSES_NEW (insn, -1);
05554 }
05555
05556
05557 if (TARGET_CPU_ZARCH)
05558 insn = emit_insn_after (gen_pool_align (GEN_INT (8)), insn);
05559 else
05560 insn = emit_insn_after (gen_pool_align (GEN_INT (4)), insn);
05561 INSN_ADDRESSES_NEW (insn, -1);
05562
05563
05564 if (!remote_label)
05565 {
05566 insn = emit_label_after (pool->label, insn);
05567 INSN_ADDRESSES_NEW (insn, -1);
05568 }
05569
05570
05571
05572 for (i = 0; i < NR_C_MODES; i++)
05573 for (c = pool->constants[i]; c; c = c->next)
05574 {
05575
05576 rtx value = c->value;
05577 if (GET_CODE (value) == CONST
05578 && GET_CODE (XEXP (value, 0)) == UNSPEC
05579 && XINT (XEXP (value, 0), 1) == UNSPEC_LTREL_OFFSET
05580 && XVECLEN (XEXP (value, 0), 0) == 1)
05581 {
05582 value = gen_rtx_MINUS (Pmode, XVECEXP (XEXP (value, 0), 0, 0),
05583 gen_rtx_LABEL_REF (VOIDmode, pool->label));
05584 value = gen_rtx_CONST (VOIDmode, value);
05585 }
05586
05587 insn = emit_label_after (c->label, insn);
05588 INSN_ADDRESSES_NEW (insn, -1);
05589
05590 value = gen_rtx_UNSPEC_VOLATILE (constant_modes[i],
05591 gen_rtvec (1, value),
05592 UNSPECV_POOL_ENTRY);
05593 insn = emit_insn_after (value, insn);
05594 INSN_ADDRESSES_NEW (insn, -1);
05595 }
05596
05597
05598 insn = emit_insn_after (gen_pool_align (GEN_INT (2)), insn);
05599 INSN_ADDRESSES_NEW (insn, -1);
05600
05601
05602 for (c = pool->execute; c; c = c->next)
05603 {
05604 insn = emit_label_after (c->label, insn);
05605 INSN_ADDRESSES_NEW (insn, -1);
05606
05607 insn = emit_insn_after (s390_execute_target (c->value), insn);
05608 INSN_ADDRESSES_NEW (insn, -1);
05609 }
05610
05611
05612 if (TARGET_CPU_ZARCH)
05613 {
05614 insn = emit_insn_after (gen_pool_section_end (), insn);
05615 INSN_ADDRESSES_NEW (insn, -1);
05616 }
05617
05618 insn = emit_barrier_after (insn);
05619 INSN_ADDRESSES_NEW (insn, -1);
05620
05621
05622 remove_insn (pool->pool_insn);
05623 }
05624
05625
05626
05627 static void
05628 s390_free_pool (struct constant_pool *pool)
05629 {
05630 struct constant *c, *next;
05631 int i;
05632
05633 for (i = 0; i < NR_C_MODES; i++)
05634 for (c = pool->constants[i]; c; c = next)
05635 {
05636 next = c->next;
05637 free (c);
05638 }
05639
05640 for (c = pool->execute; c; c = next)
05641 {
05642 next = c->next;
05643 free (c);
05644 }
05645
05646 BITMAP_FREE (pool->insns);
05647 free (pool);
05648 }
05649
05650
05651
05652
05653 static struct constant_pool *
05654 s390_mainpool_start (void)
05655 {
05656 struct constant_pool *pool;
05657 rtx insn;
05658
05659 pool = s390_alloc_pool ();
05660
05661 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
05662 {
05663 if (GET_CODE (insn) == INSN
05664 && GET_CODE (PATTERN (insn)) == SET
05665 && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC_VOLATILE
05666 && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPECV_MAIN_POOL)
05667 {
05668 gcc_assert (!pool->pool_insn);
05669 pool->pool_insn = insn;
05670 }
05671
05672 if (!TARGET_CPU_ZARCH && s390_execute_label (insn))
05673 {
05674 s390_add_execute (pool, insn);
05675 }
05676 else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
05677 {
05678 rtx pool_ref = NULL_RTX;
05679 find_constant_pool_ref (PATTERN (insn), &pool_ref);
05680 if (pool_ref)
05681 {
05682 rtx constant = get_pool_constant (pool_ref);
05683 enum machine_mode mode = get_pool_mode (pool_ref);
05684 s390_add_constant (pool, constant, mode);
05685 }
05686 }
05687 }
05688
05689 gcc_assert (pool->pool_insn || pool->size == 0);
05690
05691 if (pool->size >= 4096)
05692 {
05693
05694
05695 remove_insn (pool->pool_insn);
05696
05697 s390_free_pool (pool);
05698 pool = NULL;
05699 }
05700
05701 return pool;
05702 }
05703
05704
05705
05706
05707
05708 static void
05709 s390_mainpool_finish (struct constant_pool *pool)
05710 {
05711 rtx base_reg = cfun->machine->base_reg;
05712 rtx insn;
05713
05714
05715 if (pool->size == 0)
05716 {
05717
05718 cfun->machine->base_reg = NULL_RTX;
05719
05720 if (pool->pool_insn)
05721 remove_insn (pool->pool_insn);
05722 s390_free_pool (pool);
05723 return;
05724 }
05725
05726
05727 shorten_branches (get_insns ());
05728
05729
05730
05731 if (TARGET_CPU_ZARCH)
05732 {
05733 insn = gen_main_base_64 (base_reg, pool->label);
05734 insn = emit_insn_after (insn, pool->pool_insn);
05735 INSN_ADDRESSES_NEW (insn, -1);
05736 remove_insn (pool->pool_insn);
05737
05738 insn = get_last_insn ();
05739 pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
05740 INSN_ADDRESSES_NEW (pool->pool_insn, -1);
05741
05742 s390_dump_pool (pool, 0);
05743 }
05744
05745
05746
05747
05748 else if (INSN_ADDRESSES (INSN_UID (get_last_insn ()))
05749 + pool->size + 8 < 4096)
05750 {
05751 insn = gen_main_base_31_small (base_reg, pool->label);
05752 insn = emit_insn_after (insn, pool->pool_insn);
05753 INSN_ADDRESSES_NEW (insn, -1);
05754 remove_insn (pool->pool_insn);
05755
05756 insn = emit_label_after (pool->label, insn);
05757 INSN_ADDRESSES_NEW (insn, -1);
05758
05759 insn = get_last_insn ();
05760 pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
05761 INSN_ADDRESSES_NEW (pool->pool_insn, -1);
05762
05763 s390_dump_pool (pool, 1);
05764 }
05765
05766
05767
05768 else
05769 {
05770 rtx pool_end = gen_label_rtx ();
05771
05772 insn = gen_main_base_31_large (base_reg, pool->label, pool_end);
05773 insn = emit_insn_after (insn, pool->pool_insn);
05774 INSN_ADDRESSES_NEW (insn, -1);
05775 remove_insn (pool->pool_insn);
05776
05777 insn = emit_label_after (pool->label, insn);
05778 INSN_ADDRESSES_NEW (insn, -1);
05779
05780 pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
05781 INSN_ADDRESSES_NEW (pool->pool_insn, -1);
05782
05783 insn = emit_label_after (pool_end, pool->pool_insn);
05784 INSN_ADDRESSES_NEW (insn, -1);
05785
05786 s390_dump_pool (pool, 1);
05787 }
05788
05789
05790
05791
05792 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
05793 {
05794 if (INSN_P (insn))
05795 replace_ltrel_base (&PATTERN (insn));
05796
05797 if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
05798 {
05799 rtx addr, pool_ref = NULL_RTX;
05800 find_constant_pool_ref (PATTERN (insn), &pool_ref);
05801 if (pool_ref)
05802 {
05803 if (s390_execute_label (insn))
05804 addr = s390_find_execute (pool, insn);
05805 else
05806 addr = s390_find_constant (pool, get_pool_constant (pool_ref),
05807 get_pool_mode (pool_ref));
05808
05809 replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
05810 INSN_CODE (insn) = -1;
05811 }
05812 }
05813 }
05814
05815
05816
05817 s390_free_pool (pool);
05818 }
05819
05820
05821
05822
05823 static void
05824 s390_mainpool_cancel (struct constant_pool *pool)
05825 {
05826
05827
05828 s390_free_pool (pool);
05829 }
05830
05831
05832
05833
05834 #define S390_POOL_CHUNK_MIN 0xc00
05835 #define S390_POOL_CHUNK_MAX 0xe00
05836
05837 static struct constant_pool *
05838 s390_chunkify_start (void)
05839 {
05840 struct constant_pool *curr_pool = NULL, *pool_list = NULL;
05841 int extra_size = 0;
05842 bitmap far_labels;
05843 rtx pending_ltrel = NULL_RTX;
05844 rtx insn;
05845
05846 rtx (*gen_reload_base) (rtx, rtx) =
05847 TARGET_CPU_ZARCH? gen_reload_base_64 : gen_reload_base_31;
05848
05849
05850
05851
05852 shorten_branches (get_insns ());
05853
05854
05855
05856 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
05857 {
05858
05859 if (INSN_P (insn))
05860 {
05861 rtx ltrel_base = find_ltrel_base (PATTERN (insn));
05862 if (ltrel_base)
05863 {
05864 gcc_assert (ltrel_base == pending_ltrel);
05865 pending_ltrel = NULL_RTX;
05866 }
05867 }
05868
05869 if (!TARGET_CPU_ZARCH && s390_execute_label (insn))
05870 {
05871 if (!curr_pool)
05872 curr_pool = s390_start_pool (&pool_list, insn);
05873
05874 s390_add_execute (curr_pool, insn);
05875 s390_add_pool_insn (curr_pool, insn);
05876 }
05877 else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
05878 {
05879 rtx pool_ref = NULL_RTX;
05880 find_constant_pool_ref (PATTERN (insn), &pool_ref);
05881 if (pool_ref)
05882 {
05883 rtx constant = get_pool_constant (pool_ref);
05884 enum machine_mode mode = get_pool_mode (pool_ref);
05885
05886 if (!curr_pool)
05887 curr_pool = s390_start_pool (&pool_list, insn);
05888
05889 s390_add_constant (curr_pool, constant, mode);
05890 s390_add_pool_insn (curr_pool, insn);
05891
05892
05893
05894 if (GET_CODE (constant) == CONST
05895 && GET_CODE (XEXP (constant, 0)) == UNSPEC
05896 && XINT (XEXP (constant, 0), 1) == UNSPEC_LTREL_OFFSET)
05897 {
05898 gcc_assert (!pending_ltrel);
05899 pending_ltrel = pool_ref;
05900 }
05901 }
05902 }
05903
05904 if (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CODE_LABEL)
05905 {
05906 if (curr_pool)
05907 s390_add_pool_insn (curr_pool, insn);
05908
05909 gcc_assert (!pending_ltrel);
05910 }
05911
05912 if (!curr_pool
05913 || INSN_ADDRESSES_SIZE () <= (size_t) INSN_UID (insn)
05914 || INSN_ADDRESSES (INSN_UID (insn)) == -1)
05915 continue;
05916
05917 if (TARGET_CPU_ZARCH)
05918 {
05919 if (curr_pool->size < S390_POOL_CHUNK_MAX)
05920 continue;
05921
05922 s390_end_pool (curr_pool, NULL_RTX);
05923 curr_pool = NULL;
05924 }
05925 else
05926 {
05927 int chunk_size = INSN_ADDRESSES (INSN_UID (insn))
05928 - INSN_ADDRESSES (INSN_UID (curr_pool->first_insn))
05929 + extra_size;
05930
05931
05932
05933
05934
05935 if (GET_CODE (insn) == CODE_LABEL)
05936 extra_size += 6;
05937
05938 if (chunk_size < S390_POOL_CHUNK_MIN
05939 && curr_pool->size < S390_POOL_CHUNK_MIN)
05940 continue;
05941
05942
05943 if (GET_CODE (insn) == BARRIER)
05944 {
05945 s390_end_pool (curr_pool, insn);
05946 curr_pool = NULL;
05947 extra_size = 0;
05948 }
05949
05950
05951 else if ((chunk_size > S390_POOL_CHUNK_MAX
05952 || curr_pool->size > S390_POOL_CHUNK_MAX))
05953 {
05954 rtx label, jump, barrier;
05955
05956
05957 if (GET_CODE (insn) != INSN && GET_CODE (insn) != CALL_INSN)
05958 continue;
05959 if (get_attr_length (insn) == 0)
05960 continue;
05961
05962
05963
05964 if (pending_ltrel)
05965 continue;
05966
05967 label = gen_label_rtx ();
05968 jump = emit_jump_insn_after (gen_jump (label), insn);
05969 barrier = emit_barrier_after (jump);
05970 insn = emit_label_after (label, barrier);
05971 JUMP_LABEL (jump) = label;
05972 LABEL_NUSES (label) = 1;
05973
05974 INSN_ADDRESSES_NEW (jump, -1);
05975 INSN_ADDRESSES_NEW (barrier, -1);
05976 INSN_ADDRESSES_NEW (insn, -1);
05977
05978 s390_end_pool (curr_pool, barrier);
05979 curr_pool = NULL;
05980 extra_size = 0;
05981 }
05982 }
05983 }
05984
05985 if (curr_pool)
05986 s390_end_pool (curr_pool, NULL_RTX);
05987 gcc_assert (!pending_ltrel);
05988
05989
05990
05991
05992 far_labels = BITMAP_ALLOC (NULL);
05993
05994 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
05995 {
05996
05997
05998
05999
06000
06001
06002
06003 if (GET_CODE (insn) == CODE_LABEL
06004 && (LABEL_PRESERVE_P (insn) || LABEL_NAME (insn)))
06005 {
06006 rtx vec_insn = next_real_insn (insn);
06007 rtx vec_pat = vec_insn && GET_CODE (vec_insn) == JUMP_INSN ?
06008 PATTERN (vec_insn) : NULL_RTX;
06009 if (!vec_pat
06010 || !(GET_CODE (vec_pat) == ADDR_VEC
06011 || GET_CODE (vec_pat) == ADDR_DIFF_VEC))
06012 bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (insn));
06013 }
06014
06015
06016
06017 else if (GET_CODE (insn) == JUMP_INSN)
06018 {
06019 rtx pat = PATTERN (insn);
06020 if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
06021 pat = XVECEXP (pat, 0, 0);
06022
06023 if (GET_CODE (pat) == SET)
06024 {
06025 rtx label = JUMP_LABEL (insn);
06026 if (label)
06027 {
06028 if (s390_find_pool (pool_list, label)
06029 != s390_find_pool (pool_list, insn))
06030 bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (label));
06031 }
06032 }
06033 else if (GET_CODE (pat) == PARALLEL
06034 && XVECLEN (pat, 0) == 2
06035 && GET_CODE (XVECEXP (pat, 0, 0)) == SET
06036 && GET_CODE (XVECEXP (pat, 0, 1)) == USE
06037 && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == LABEL_REF)
06038 {
06039
06040 rtx vec_label = XEXP (XEXP (XVECEXP (pat, 0, 1), 0), 0);
06041 rtx vec_insn = next_real_insn (vec_label);
06042 rtx vec_pat = vec_insn && GET_CODE (vec_insn) == JUMP_INSN ?
06043 PATTERN (vec_insn) : NULL_RTX;
06044 if (vec_pat
06045 && (GET_CODE (vec_pat) == ADDR_VEC
06046 || GET_CODE (vec_pat) == ADDR_DIFF_VEC))
06047 {
06048 int i, diff_p = GET_CODE (vec_pat) == ADDR_DIFF_VEC;
06049
06050 for (i = 0; i < XVECLEN (vec_pat, diff_p); i++)
06051 {
06052 rtx label = XEXP (XVECEXP (vec_pat, diff_p, i), 0);
06053
06054 if (s390_find_pool (pool_list, label)
06055 != s390_find_pool (pool_list, insn))
06056 bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (label));
06057 }
06058 }
06059 }
06060 }
06061 }
06062
06063
06064
06065 for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
06066 {
06067 rtx new_insn = gen_reload_base (cfun->machine->base_reg,
06068 curr_pool->label);
06069 rtx insn = curr_pool->first_insn;
06070 INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
06071 }
06072
06073
06074
06075 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
06076 if (GET_CODE (insn) == CODE_LABEL
06077 && bitmap_bit_p (far_labels, CODE_LABEL_NUMBER (insn)))
06078 {
06079 struct constant_pool *pool = s390_find_pool (pool_list, insn);
06080 if (pool)
06081 {
06082 rtx new_insn = gen_reload_base (cfun->machine->base_reg,
06083 pool->label);
06084 INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
06085 }
06086 }
06087
06088
06089 BITMAP_FREE (far_labels);
06090
06091
06092
06093
06094 init_insn_lengths ();
06095 shorten_branches (get_insns ());
06096
06097 return pool_list;
06098 }
06099
06100
06101
06102
06103
06104 static void
06105 s390_chunkify_finish (struct constant_pool *pool_list)
06106 {
06107 struct constant_pool *curr_pool = NULL;
06108 rtx insn;
06109
06110
06111
06112
06113 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
06114 {
06115 if (INSN_P (insn))
06116 replace_ltrel_base (&PATTERN (insn));
06117
06118 curr_pool = s390_find_pool (pool_list, insn);
06119 if (!curr_pool)
06120 continue;
06121
06122 if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
06123 {
06124 rtx addr, pool_ref = NULL_RTX;
06125 find_constant_pool_ref (PATTERN (insn), &pool_ref);
06126 if (pool_ref)
06127 {
06128 if (s390_execute_label (insn))
06129 addr = s390_find_execute (curr_pool, insn);
06130 else
06131 addr = s390_find_constant (curr_pool,
06132 get_pool_constant (pool_ref),
06133 get_pool_mode (pool_ref));
06134
06135 replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
06136 INSN_CODE (insn) = -1;
06137 }
06138 }
06139 }
06140
06141
06142
06143 for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
06144 s390_dump_pool (curr_pool, 0);
06145
06146
06147
06148 while (pool_list)
06149 {
06150 struct constant_pool *next = pool_list->next;
06151 s390_free_pool (pool_list);
06152 pool_list = next;
06153 }
06154 }
06155
06156
06157
06158
06159
06160 static void
06161 s390_chunkify_cancel (struct constant_pool *pool_list)
06162 {
06163 struct constant_pool *curr_pool = NULL;
06164 rtx insn;
06165
06166
06167
06168 for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
06169 {
06170
06171 rtx barrier = PREV_INSN (curr_pool->pool_insn);
06172 rtx jump = barrier? PREV_INSN (barrier) : NULL_RTX;
06173 rtx label = NEXT_INSN (curr_pool->pool_insn);
06174
06175 if (jump && GET_CODE (jump) == JUMP_INSN
06176 && barrier && GET_CODE (barrier) == BARRIER
06177 && label && GET_CODE (label) == CODE_LABEL
06178 && GET_CODE (PATTERN (jump)) == SET
06179 && SET_DEST (PATTERN (jump)) == pc_rtx
06180 && GET_CODE (SET_SRC (PATTERN (jump))) == LABEL_REF
06181 && XEXP (SET_SRC (PATTERN (jump)), 0) == label)
06182 {
06183 remove_insn (jump);
06184 remove_insn (barrier);
06185 remove_insn (label);
06186 }
06187
06188 remove_insn (curr_pool->pool_insn);
06189 }
06190
06191
06192
06193 for (insn = get_insns (); insn; )
06194 {
06195 rtx next_insn = NEXT_INSN (insn);
06196
06197 if (GET_CODE (insn) == INSN
06198 && GET_CODE (PATTERN (insn)) == SET
06199 && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC
06200 && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPEC_RELOAD_BASE)
06201 remove_insn (insn);
06202
06203 insn = next_insn;
06204 }
06205
06206
06207
06208 while (pool_list)
06209 {
06210 struct constant_pool *next = pool_list->next;
06211 s390_free_pool (pool_list);
06212 pool_list = next;
06213 }
06214 }
06215
06216
06217
06218
06219 void
06220 s390_output_pool_entry (rtx exp, enum machine_mode mode, unsigned int align)
06221 {
06222 REAL_VALUE_TYPE r;
06223
06224 switch (GET_MODE_CLASS (mode))
06225 {
06226 case MODE_FLOAT:
06227 case MODE_DECIMAL_FLOAT:
06228 gcc_assert (GET_CODE (exp) == CONST_DOUBLE);
06229
06230 REAL_VALUE_FROM_CONST_DOUBLE (r, exp);
06231 assemble_real (r, mode, align);
06232 break;
06233
06234 case MODE_INT:
06235 assemble_integer (exp, GET_MODE_SIZE (mode), align, 1);
06236 break;
06237
06238 default:
06239 gcc_unreachable ();
06240 }
06241 }
06242
06243
06244
06245
06246
06247
06248 rtx
06249 s390_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
06250 {
06251 int offset;
06252 rtx addr;
06253
06254
06255
06256 if (!TARGET_BACKCHAIN && count > 0)
06257 return NULL_RTX;
06258
06259
06260
06261
06262 if (count == 0)
06263 {
06264
06265 if (TARGET_CPU_ZARCH)
06266 return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
06267 else
06268 {
06269 cfun_frame_layout.save_return_addr_p = true;
06270 return gen_rtx_MEM (Pmode, return_address_pointer_rtx);
06271 }
06272 }
06273
06274 if (TARGET_PACKED_STACK)
06275 offset = -2 * UNITS_PER_WORD;
06276 else
06277 offset = RETURN_REGNUM * UNITS_PER_WORD;
06278
06279 addr = plus_constant (frame, offset);
06280 addr = memory_address (Pmode, addr);
06281 return gen_rtx_MEM (Pmode, addr);
06282 }
06283
06284
06285
06286
06287 rtx
06288 s390_back_chain_rtx (void)
06289 {
06290 rtx chain;
06291
06292 gcc_assert (TARGET_BACKCHAIN);
06293
06294 if (TARGET_PACKED_STACK)
06295 chain = plus_constant (stack_pointer_rtx,
06296 STACK_POINTER_OFFSET - UNITS_PER_WORD);
06297 else
06298 chain = stack_pointer_rtx;
06299
06300 chain = gen_rtx_MEM (Pmode, chain);
06301 return chain;
06302 }
06303
06304
06305
06306
06307
06308 static int
06309 find_unused_clobbered_reg (void)
06310 {
06311 int i;
06312 for (i = 0; i < 6; i++)
06313 if (!regs_ever_live[i])
06314 return i;
06315 return 0;
06316 }
06317
06318
06319
06320
06321
06322 static void
06323 s390_reg_clobbered_rtx (rtx setreg, rtx set_insn ATTRIBUTE_UNUSED, void *data)
06324 {
06325 int *regs_ever_clobbered = (int *)data;
06326 unsigned int i, regno;
06327 enum machine_mode mode = GET_MODE (setreg);
06328
06329 if (GET_CODE (setreg) == SUBREG)
06330 {
06331 rtx inner = SUBREG_REG (setreg);
06332 if (!GENERAL_REG_P (inner))
06333 return;
06334 regno = subreg_regno (setreg);
06335 }
06336 else if (GENERAL_REG_P (setreg))
06337 regno = REGNO (setreg);
06338 else
06339 return;
06340
06341 for (i = regno;
06342 i < regno + HARD_REGNO_NREGS (regno, mode);
06343 i++)
06344 regs_ever_clobbered[i] = 1;
06345 }
06346
06347
06348
06349
06350
06351
06352 static void
06353 s390_regs_ever_clobbered (int *regs_ever_clobbered)
06354 {
06355 basic_block cur_bb;
06356 rtx cur_insn;
06357 unsigned int i;
06358
06359 memset (regs_ever_clobbered, 0, 16 * sizeof (int));
06360
06361
06362
06363 if (!current_function_is_leaf)
06364 {
06365 for (i = 0; i < 16; i++)
06366 regs_ever_clobbered[i] = call_really_used_regs[i];
06367 }
06368
06369
06370
06371
06372
06373
06374
06375 if (current_function_calls_eh_return || cfun->machine->has_landing_pad_p)
06376 for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM ; i++)
06377 if (current_function_calls_eh_return
06378 || (cfun->machine->has_landing_pad_p
06379 && regs_ever_live [EH_RETURN_DATA_REGNO (i)]))
06380 regs_ever_clobbered[EH_RETURN_DATA_REGNO (i)] = 1;
06381
06382
06383
06384
06385
06386 if (current_function_has_nonlocal_label)
06387 for (i = 0; i < 16; i++)
06388 if (!call_really_used_regs[i])
06389 regs_ever_clobbered[i] = 1;
06390
06391 FOR_EACH_BB (cur_bb)
06392 {
06393 FOR_BB_INSNS (cur_bb, cur_insn)
06394 {
06395 if (INSN_P (cur_insn))
06396 note_stores (PATTERN (cur_insn),
06397 s390_reg_clobbered_rtx,
06398 regs_ever_clobbered);
06399 }
06400 }
06401 }
06402
06403
06404
06405
06406
06407
06408
06409 static void
06410 s390_frame_area (int *area_bottom, int *area_top)
06411 {
06412 int b, t;
06413 int i;
06414
06415 b = INT_MAX;
06416 t = INT_MIN;
06417
06418 if (cfun_frame_layout.first_restore_gpr != -1)
06419 {
06420 b = (cfun_frame_layout.gprs_offset
06421 + cfun_frame_layout.first_restore_gpr * UNITS_PER_WORD);
06422 t = b + (cfun_frame_layout.last_restore_gpr
06423 - cfun_frame_layout.first_restore_gpr + 1) * UNITS_PER_WORD;
06424 }
06425
06426 if (TARGET_64BIT && cfun_save_high_fprs_p)
06427 {
06428 b = MIN (b, cfun_frame_layout.f8_offset);
06429 t = MAX (t, (cfun_frame_layout.f8_offset
06430 + cfun_frame_layout.high_fprs * 8));
06431 }
06432
06433 if (!TARGET_64BIT)
06434 for (i = 2; i < 4; i++)
06435 if (cfun_fpr_bit_p (i))
06436 {
06437 b = MIN (b, cfun_frame_layout.f4_offset + (i - 2) * 8);
06438 t = MAX (t, cfun_frame_layout.f4_offset + (i - 1) * 8);
06439 }
06440
06441 *area_bottom = b;
06442 *area_top = t;
06443 }
06444
06445
06446
06447
06448 static void
06449 s390_register_info (int clobbered_regs[])
06450 {
06451 int i, j;
06452
06453
06454 cfun_frame_layout.fpr_bitmap = 0;
06455 cfun_frame_layout.high_fprs = 0;
06456 if (TARGET_64BIT)
06457 for (i = 24; i < 32; i++)
06458 if (regs_ever_live[i] && !global_regs[i])
06459 {
06460 cfun_set_fpr_bit (i - 16);
06461 cfun_frame_layout.high_fprs++;
06462 }
06463
06464
06465
06466
06467
06468
06469
06470 s390_regs_ever_clobbered (clobbered_regs);
06471
06472 for (i = 0; i < 16; i++)
06473 clobbered_regs[i] = clobbered_regs[i] && !global_regs[i] && !fixed_regs[i];
06474
06475 if (frame_pointer_needed)
06476 clobbered_regs[HARD_FRAME_POINTER_REGNUM] = 1;
06477
06478 if (flag_pic)
06479 clobbered_regs[PIC_OFFSET_TABLE_REGNUM]
06480 |= regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
06481
06482 clobbered_regs[BASE_REGNUM]
06483 |= (cfun->machine->base_reg
06484 && REGNO (cfun->machine->base_reg) == BASE_REGNUM);
06485
06486 clobbered_regs[RETURN_REGNUM]
06487 |= (!current_function_is_leaf
06488 || TARGET_TPF_PROFILING
06489 || cfun->machine->split_branches_pending_p
06490 || cfun_frame_layout.save_return_addr_p
06491 || current_function_calls_eh_return
06492 || current_function_stdarg);
06493
06494 clobbered_regs[STACK_POINTER_REGNUM]
06495 |= (!current_function_is_leaf
06496 || TARGET_TPF_PROFILING
06497 || cfun_save_high_fprs_p
06498 || get_frame_size () > 0
06499 || current_function_calls_alloca
06500 || current_function_stdarg);
06501
06502 for (i = 6; i < 16; i++)
06503 if (regs_ever_live[i] || clobbered_regs[i])
06504 break;
06505 for (j = 15; j > i; j--)
06506 if (regs_ever_live[j] || clobbered_regs[j])
06507 break;
06508
06509 if (i == 16)
06510 {
06511
06512 cfun_frame_layout.first_save_gpr_slot = -1;
06513 cfun_frame_layout.last_save_gpr_slot = -1;
06514 cfun_frame_layout.first_save_gpr = -1;
06515 cfun_frame_layout.first_restore_gpr = -1;
06516 cfun_frame_layout.last_save_gpr = -1;
06517 cfun_frame_layout.last_restore_gpr = -1;
06518 }
06519 else
06520 {
06521
06522 cfun_frame_layout.first_save_gpr_slot = i;
06523 cfun_frame_layout.last_save_gpr_slot = j;
06524
06525 for (i = cfun_frame_layout.first_save_gpr_slot;
06526 i < cfun_frame_layout.last_save_gpr_slot + 1;
06527 i++)
06528 if (clobbered_regs[i])
06529 break;
06530
06531 for (j = cfun_frame_layout.last_save_gpr_slot; j > i; j--)
06532 if (clobbered_regs[j])
06533 break;
06534
06535 if (i == cfun_frame_layout.last_save_gpr_slot + 1)
06536 {
06537
06538 cfun_frame_layout.first_save_gpr = -1;
06539 cfun_frame_layout.first_restore_gpr = -1;
06540 cfun_frame_layout.last_save_gpr = -1;
06541 cfun_frame_layout.last_restore_gpr = -1;
06542 }
06543 else
06544 {
06545
06546 cfun_frame_layout.first_save_gpr = i;
06547 cfun_frame_layout.first_restore_gpr = i;
06548 cfun_frame_layout.last_save_gpr = j;
06549 cfun_frame_layout.last_restore_gpr = j;
06550 }
06551 }
06552
06553 if (current_function_stdarg)
06554 {
06555
06556 if (cfun->va_list_gpr_size
06557 && current_function_args_info.gprs < GP_ARG_NUM_REG)
06558 {
06559 int min_gpr = current_function_args_info.gprs;
06560 int max_gpr = min_gpr + cfun->va_list_gpr_size;
06561 if (max_gpr > GP_ARG_NUM_REG)
06562 max_gpr = GP_ARG_NUM_REG;
06563
06564 if (cfun_frame_layout.first_save_gpr == -1
06565 || cfun_frame_layout.first_save_gpr > 2 + min_gpr)
06566 {
06567 cfun_frame_layout.first_save_gpr = 2 + min_gpr;
06568 cfun_frame_layout.first_save_gpr_slot = 2 + min_gpr;
06569 }
06570
06571 if (cfun_frame_layout.last_save_gpr == -1
06572 || cfun_frame_layout.last_save_gpr < 2 + max_gpr - 1)
06573 {
06574 cfun_frame_layout.last_save_gpr = 2 + max_gpr - 1;
06575 cfun_frame_layout.last_save_gpr_slot = 2 + max_gpr - 1;
06576 }
06577 }
06578
06579
06580 if (TARGET_HARD_FLOAT && cfun->va_list_fpr_size
06581 && current_function_args_info.fprs < FP_ARG_NUM_REG)
06582 {
06583 int min_fpr = current_function_args_info.fprs;
06584 int max_fpr = min_fpr + cfun->va_list_fpr_size;
06585 if (max_fpr > FP_ARG_NUM_REG)
06586 max_fpr = FP_ARG_NUM_REG;
06587
06588
06589
06590 if (TARGET_PACKED_STACK)
06591 min_fpr = 0;
06592
06593 for (i = min_fpr; i < max_fpr; i++)
06594 cfun_set_fpr_bit (i);
06595 }
06596 }
06597
06598 if (!TARGET_64BIT)
06599 for (i = 2; i < 4; i++)
06600 if (regs_ever_live[i + 16] && !global_regs[i + 16])
06601 cfun_set_fpr_bit (i);
06602 }
06603
06604
06605
06606 static void
06607 s390_frame_info (void)
06608 {
06609 int i;
06610
06611 cfun_frame_layout.frame_size = get_frame_size ();
06612 if (!TARGET_64BIT && cfun_frame_layout.frame_size > 0x7fff0000)
06613 fatal_error ("total size of local variables exceeds architecture limit");
06614
06615 if (!TARGET_PACKED_STACK)
06616 {
06617 cfun_frame_layout.backchain_offset = 0;
06618 cfun_frame_layout.f0_offset = 16 * UNITS_PER_WORD;
06619 cfun_frame_layout.f4_offset = cfun_frame_layout.f0_offset + 2 * 8;
06620 cfun_frame_layout.f8_offset = -cfun_frame_layout.high_fprs * 8;
06621 cfun_frame_layout.gprs_offset = (cfun_frame_layout.first_save_gpr_slot
06622 * UNITS_PER_WORD);
06623 }
06624 else if (TARGET_BACKCHAIN)
06625 {
06626 cfun_frame_layout.backchain_offset = (STACK_POINTER_OFFSET
06627 - UNITS_PER_WORD);
06628 cfun_frame_layout.gprs_offset
06629 = (cfun_frame_layout.backchain_offset
06630 - (STACK_POINTER_REGNUM - cfun_frame_layout.first_save_gpr_slot + 1)
06631 * UNITS_PER_WORD);
06632
06633 if (TARGET_64BIT)
06634 {
06635 cfun_frame_layout.f4_offset
06636 = (cfun_frame_layout.gprs_offset
06637 - 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
06638
06639 cfun_frame_layout.f0_offset
06640 = (cfun_frame_layout.f4_offset
06641 - 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
06642 }
06643 else
06644 {
06645
06646
06647 cfun_frame_layout.f0_offset
06648 = ((cfun_frame_layout.gprs_offset
06649 & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1))
06650 - 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
06651
06652 cfun_frame_layout.f4_offset
06653 = (cfun_frame_layout.f0_offset
06654 - 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
06655 }
06656 }
06657 else
06658 {
06659 cfun_frame_layout.f4_offset
06660 = (STACK_POINTER_OFFSET
06661 - 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
06662
06663 cfun_frame_layout.f0_offset
06664 = (cfun_frame_layout.f4_offset
06665 - 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
06666
06667 cfun_frame_layout.gprs_offset
06668 = cfun_frame_layout.f0_offset - cfun_gprs_save_area_size;
06669 }
06670
06671 if (current_function_is_leaf
06672 && !TARGET_TPF_PROFILING
06673 && cfun_frame_layout.frame_size == 0
06674 && !cfun_save_high_fprs_p
06675 && !current_function_calls_alloca
06676 && !current_function_stdarg)
06677 return;
06678
06679 if (!TARGET_PACKED_STACK)
06680 cfun_frame_layout.frame_size += (STACK_POINTER_OFFSET
06681 + current_function_outgoing_args_size
06682 + cfun_frame_layout.high_fprs * 8);
06683 else
06684 {
06685 if (TARGET_BACKCHAIN)
06686 cfun_frame_layout.frame_size += UNITS_PER_WORD;
06687
06688
06689
06690 cfun_frame_layout.f8_offset = (MIN (MIN (cfun_frame_layout.f0_offset,
06691 cfun_frame_layout.f4_offset),
06692 cfun_frame_layout.gprs_offset)
06693 - cfun_frame_layout.high_fprs * 8);
06694
06695 cfun_frame_layout.frame_size += cfun_frame_layout.high_fprs * 8;
06696
06697 for (i = 0; i < 8; i++)
06698 if (cfun_fpr_bit_p (i))
06699 cfun_frame_layout.frame_size += 8;
06700
06701 cfun_frame_layout.frame_size += cfun_gprs_save_area_size;
06702
06703
06704
06705 cfun_frame_layout.frame_size = ((cfun_frame_layout.frame_size +
06706 STACK_BOUNDARY / BITS_PER_UNIT - 1)
06707 & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1));
06708
06709 cfun_frame_layout.frame_size += current_function_outgoing_args_size;
06710 }
06711 }
06712
06713
06714
06715
06716
06717 static void
06718 s390_init_frame_layout (void)
06719 {
06720 HOST_WIDE_INT frame_size;
06721 int base_used;
06722 int clobbered_regs[16];
06723
06724
06725
06726
06727
06728 if (!TARGET_CPU_ZARCH)
06729 cfun->machine->split_branches_pending_p = true;
06730
06731 do
06732 {
06733 frame_size = cfun_frame_layout.frame_size;
06734
06735
06736 base_used = cfun->machine->split_branches_pending_p
06737 || current_function_uses_const_pool
06738 || (!DISP_IN_RANGE (frame_size)
06739 && !CONST_OK_FOR_K (frame_size));
06740
06741
06742
06743
06744 if (!base_used)
06745 cfun->machine->base_reg = NULL_RTX;
06746 else if (current_function_is_leaf && !regs_ever_live[5])
06747 cfun->machine->base_reg = gen_rtx_REG (Pmode, 5);
06748 else
06749 cfun->machine->base_reg = gen_rtx_REG (Pmode, BASE_REGNUM);
06750
06751 s390_register_info (clobbered_regs);
06752 s390_frame_info ();
06753 }
06754 while (frame_size != cfun_frame_layout.frame_size);
06755 }
06756
06757
06758
06759
06760
06761
06762 static void
06763 s390_update_frame_layout (void)
06764 {
06765 int clobbered_regs[16];
06766
06767 s390_register_info (clobbered_regs);
06768
06769 regs_ever_live[BASE_REGNUM] = clobbered_regs[BASE_REGNUM];
06770 regs_ever_live[RETURN_REGNUM] = clobbered_regs[RETURN_REGNUM];
06771 regs_ever_live[STACK_POINTER_REGNUM] = clobbered_regs[STACK_POINTER_REGNUM];
06772
06773 if (cfun->machine->base_reg)
06774 regs_ever_live[REGNO (cfun->machine->base_reg)] = 1;
06775 }
06776
06777
06778
06779 bool
06780 s390_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
06781 {
06782 switch (REGNO_REG_CLASS (regno))
06783 {
06784 case FP_REGS:
06785 if (REGNO_PAIR_OK (regno, mode))
06786 {
06787 if (mode == SImode || mode == DImode)
06788 return true;
06789
06790 if (FLOAT_MODE_P (mode) && GET_MODE_CLASS (mode) != MODE_VECTOR_FLOAT)
06791 return true;
06792 }
06793 break;
06794 case ADDR_REGS:
06795 if (FRAME_REGNO_P (regno) && mode == Pmode)
06796 return true;
06797
06798
06799 case GENERAL_REGS:
06800 if (REGNO_PAIR_OK (regno, mode))
06801 {
06802 if (TARGET_64BIT
06803 || (mode != TFmode && mode != TCmode && mode != TDmode))
06804 return true;
06805 }
06806 break;
06807 case CC_REGS:
06808 if (GET_MODE_CLASS (mode) == MODE_CC)
06809 return true;
06810 break;
06811 case ACCESS_REGS:
06812 if (REGNO_PAIR_OK (regno, mode))
06813 {
06814 if (mode == SImode || mode == Pmode)
06815 return true;
06816 }
06817 break;
06818 default:
06819 return false;
06820 }
06821
06822 return false;
06823 }
06824
06825
06826
06827 bool
06828 s390_hard_regno_rename_ok (unsigned int old_reg, unsigned int new_reg)
06829 {
06830
06831
06832 if (cfun->machine->base_reg)
06833 if (REGNO (cfun->machine->base_reg) == old_reg
06834 || REGNO (cfun->machine->base_reg) == new_reg)
06835 return false;
06836
06837 return true;
06838 }
06839
06840
06841
06842
06843 bool
06844 s390_class_max_nregs (enum reg_class class, enum machine_mode mode)
06845 {
06846 switch (class)
06847 {
06848 case FP_REGS:
06849 if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
06850 return 2 * ((GET_MODE_SIZE (mode) / 2 + 8 - 1) / 8);
06851 else
06852 return (GET_MODE_SIZE (mode) + 8 - 1) / 8;
06853 case ACCESS_REGS:
06854 return (GET_MODE_SIZE (mode) + 4 - 1) / 4;
06855 default:
06856 break;
06857 }
06858 return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
06859 }
06860
06861
06862
06863 bool
06864 s390_can_eliminate (int from, int to)
06865 {
06866
06867
06868
06869
06870
06871
06872
06873
06874 if (from == BASE_REGNUM && to == BASE_REGNUM)
06875 {
06876 if (TARGET_CPU_ZARCH)
06877 {
06878 s390_init_frame_layout ();
06879 return cfun->machine->base_reg == NULL_RTX;
06880 }
06881
06882 return false;
06883 }
06884
06885
06886 gcc_assert (to == STACK_POINTER_REGNUM
06887 || to == HARD_FRAME_POINTER_REGNUM);
06888
06889 gcc_assert (from == FRAME_POINTER_REGNUM
06890 || from == ARG_POINTER_REGNUM
06891 || from == RETURN_ADDRESS_POINTER_REGNUM);
06892
06893
06894 if (from == RETURN_ADDRESS_POINTER_REGNUM)
06895 if (!current_function_calls_eh_return
06896 && !current_function_stdarg
06897 && !cfun_frame_layout.save_return_addr_p)
06898 return false;
06899
06900 return true;
06901 }
06902
06903
06904
06905 HOST_WIDE_INT
06906 s390_initial_elimination_offset (int from, int to)
06907 {
06908 HOST_WIDE_INT offset;
06909 int index;
06910
06911
06912 if (!s390_can_eliminate (from, to))
06913 return 0;
06914
06915 switch (from)
06916 {
06917 case FRAME_POINTER_REGNUM:
06918 offset = (get_frame_size()
06919 + STACK_POINTER_OFFSET
06920 + current_function_outgoing_args_size);
06921 break;
06922
06923 case ARG_POINTER_REGNUM:
06924 s390_init_frame_layout ();
06925 offset = cfun_frame_layout.frame_size + STACK_POINTER_OFFSET;
06926 break;
06927
06928 case RETURN_ADDRESS_POINTER_REGNUM:
06929 s390_init_frame_layout ();
06930 index = RETURN_REGNUM - cfun_frame_layout.first_save_gpr_slot;
06931 gcc_assert (index >= 0);
06932 offset = cfun_frame_layout.frame_size + cfun_frame_layout.gprs_offset;
06933 offset += index * UNITS_PER_WORD;
06934 break;
06935
06936 case BASE_REGNUM:
06937 offset = 0;
06938 break;
06939
06940 default:
06941 gcc_unreachable ();
06942 }
06943
06944 return offset;
06945 }
06946
06947
06948
06949
06950 static rtx
06951 save_fpr (rtx base, int offset, int regnum)
06952 {
06953 rtx addr;
06954 addr = gen_rtx_MEM (DFmode, plus_constant (base, offset));
06955
06956 if (regnum >= 16 && regnum <= (16 + FP_ARG_NUM_REG))
06957 set_mem_alias_set (addr, get_varargs_alias_set ());
06958 else
06959 set_mem_alias_set (addr, get_frame_alias_set ());
06960
06961 return emit_move_insn (addr, gen_rtx_REG (DFmode, regnum));
06962 }
06963
06964
06965
06966
06967 static rtx
06968 restore_fpr (rtx base, int offset, int regnum)
06969 {
06970 rtx addr;
06971 addr = gen_rtx_MEM (DFmode, plus_constant (base, offset));
06972 set_mem_alias_set (addr, get_frame_alias_set ());
06973
06974 return emit_move_insn (gen_rtx_REG (DFmode, regnum), addr);
06975 }
06976
06977
06978
06979
06980
06981 static rtx
06982 save_gprs (rtx base, int offset, int first, int last)
06983 {
06984 rtx addr, insn, note;
06985 int i;
06986
06987 addr = plus_constant (base, offset);
06988 addr = gen_rtx_MEM (Pmode, addr);
06989
06990 set_mem_alias_set (addr, get_frame_alias_set ());
06991
06992
06993 if (first == last)
06994 {
06995 if (TARGET_64BIT)
06996 insn = gen_movdi (addr, gen_rtx_REG (Pmode, first));
06997 else
06998 insn = gen_movsi (addr, gen_rtx_REG (Pmode, first));
06999
07000 RTX_FRAME_RELATED_P (insn) = 1;
07001 return insn;
07002 }
07003
07004
07005 insn = gen_store_multiple (addr,
07006 gen_rtx_REG (Pmode, first),
07007 GEN_INT (last - first + 1));
07008
07009 if (first <= 6 && current_function_stdarg)
07010 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
07011 {
07012 rtx mem = XEXP (XVECEXP (PATTERN (insn), 0, i), 0);
07013
07014 if (first + i <= 6)
07015 set_mem_alias_set (mem, get_varargs_alias_set ());
07016 }
07017
07018
07019
07020
07021
07022
07023
07024
07025
07026
07027
07028
07029
07030 if (first >= 6)
07031 {
07032 rtx pat = PATTERN (insn);
07033
07034 for (i = 0; i < XVECLEN (pat, 0); i++)
07035 if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
07036 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1;
07037
07038 RTX_FRAME_RELATED_P (insn) = 1;
07039 }
07040 else if (last >= 6)
07041 {
07042 addr = plus_constant (base, offset + (6 - first) * UNITS_PER_WORD);
07043 note = gen_store_multiple (gen_rtx_MEM (Pmode, addr),
07044 gen_rtx_REG (Pmode, 6),
07045 GEN_INT (last - 6 + 1));
07046 note = PATTERN (note);
07047
07048 REG_NOTES (insn) =
07049 gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
07050 note, REG_NOTES (insn));
07051
07052 for (i = 0; i < XVECLEN (note, 0); i++)
07053 if (GET_CODE (XVECEXP (note, 0, i)) == SET)
07054 RTX_FRAME_RELATED_P (XVECEXP (note, 0, i)) = 1;
07055
07056 RTX_FRAME_RELATED_P (insn) = 1;
07057 }
07058
07059 return insn;
07060 }
07061
07062
07063
07064
07065
07066 static rtx
07067 restore_gprs (rtx base, int offset, int first, int last)
07068 {
07069 rtx addr, insn;
07070
07071 addr = plus_constant (base, offset);
07072 addr = gen_rtx_MEM (Pmode, addr);
07073 set_mem_alias_set (addr, get_frame_alias_set ());
07074
07075
07076 if (first == last)
07077 {
07078 if (TARGET_64BIT)
07079 insn = gen_movdi (gen_rtx_REG (Pmode, first), addr);
07080 else
07081 insn = gen_movsi (gen_rtx_REG (Pmode, first), addr);
07082
07083 return insn;
07084 }
07085
07086 insn = gen_load_multiple (gen_rtx_REG (Pmode, first),
07087 addr,
07088 GEN_INT (last - first + 1));
07089 return insn;
07090 }
07091
07092
07093
07094 static GTY(()) rtx got_symbol;
07095 rtx
07096 s390_load_got (void)
07097 {
07098 rtx insns;
07099
07100 if (!got_symbol)
07101 {
07102 got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
07103 SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL;
07104 }
07105
07106 start_sequence ();
07107
07108 if (TARGET_CPU_ZARCH)
07109 {
07110 emit_move_insn (pic_offset_table_rtx, got_symbol);
07111 }
07112 else
07113 {
07114 rtx offset;
07115
07116 offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol),
07117 UNSPEC_LTREL_OFFSET);
07118 offset = gen_rtx_CONST (Pmode, offset);
07119 offset = force_const_mem (Pmode, offset);
07120
07121 emit_move_insn (pic_offset_table_rtx, offset);
07122
07123 offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (offset, 0)),
07124 UNSPEC_LTREL_BASE);
07125 offset = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
07126
07127 emit_move_insn (pic_offset_table_rtx, offset);
07128 }
07129
07130 insns = get_insns ();
07131 end_sequence ();
07132 return insns;
07133 }
07134
07135
07136
07137 void
07138 s390_emit_prologue (void)
07139 {
07140 rtx insn, addr;
07141 rtx temp_reg;
07142 int i;
07143 int offset;
07144 int next_fpr = 0;
07145
07146
07147
07148 s390_update_frame_layout ();
07149
07150
07151
07152
07153 push_topmost_sequence ();
07154
07155 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
07156 if (INSN_P (insn))
07157 annotate_constant_pool_refs (&PATTERN (insn));
07158
07159 pop_topmost_sequence ();
07160
07161
07162
07163
07164 if (!has_hard_reg_initial_val (Pmode, RETURN_REGNUM)
07165 && !current_function_is_leaf
07166 && !TARGET_TPF_PROFILING)
07167 temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
07168 else
07169 temp_reg = gen_rtx_REG (Pmode, 1);
07170
07171
07172 if (cfun_frame_layout.first_save_gpr != -1)
07173 {
07174 insn = save_gprs (stack_pointer_rtx,
07175 cfun_frame_layout.gprs_offset +
07176 UNITS_PER_WORD * (cfun_frame_layout.first_save_gpr
07177 - cfun_frame_layout.first_save_gpr_slot),
07178 cfun_frame_layout.first_save_gpr,
07179 cfun_frame_layout.last_save_gpr);
07180 emit_insn (insn);
07181 }
07182
07183
07184
07185 if (cfun->machine->base_reg)
07186 emit_insn (gen_main_pool (cfun->machine->base_reg));
07187
07188 offset = cfun_frame_layout.f0_offset;
07189
07190
07191 for (i = 0; i < 2; i++)
07192 {
07193 if (cfun_fpr_bit_p (i))
07194 {
07195 save_fpr (stack_pointer_rtx, offset, i + 16);
07196 offset += 8;
07197 }
07198 else if (!TARGET_PACKED_STACK)
07199 offset += 8;
07200 }
07201
07202
07203 offset = cfun_frame_layout.f4_offset;
07204 for (i = 2; i < 4; i++)
07205 {
07206 if (cfun_fpr_bit_p (i))
07207 {
07208 insn = save_fpr (stack_pointer_rtx, offset, i + 16);
07209 offset += 8;
07210
07211
07212
07213 if (!call_really_used_regs[i + 16])
07214 RTX_FRAME_RELATED_P (insn) = 1;
07215 }
07216 else if (!TARGET_PACKED_STACK)
07217 offset += 8;
07218 }
07219
07220 if (TARGET_PACKED_STACK
07221 && cfun_save_high_fprs_p
07222 && cfun_frame_layout.f8_offset + cfun_frame_layout.high_fprs * 8 > 0)
07223 {
07224 offset = (cfun_frame_layout.f8_offset
07225 + (cfun_frame_layout.high_fprs - 1) * 8);
07226
07227 for (i = 15; i > 7 && offset >= 0; i--)
07228 if (cfun_fpr_bit_p (i))
07229 {
07230 insn = save_fpr (stack_pointer_rtx, offset, i + 16);
07231
07232 RTX_FRAME_RELATED_P (insn) = 1;
07233 offset -= 8;
07234 }
07235 if (offset >= cfun_frame_layout.f8_offset)
07236 next_fpr = i + 16;
07237 }
07238
07239 if (!TARGET_PACKED_STACK)
07240 next_fpr = cfun_save_high_fprs_p ? 31 : 0;
07241
07242
07243
07244 if (cfun_frame_layout.frame_size > 0)
07245 {
07246 rtx frame_off = GEN_INT (-cfun_frame_layout.frame_size);
07247
07248 if (s390_stack_size)
07249 {
07250 HOST_WIDE_INT stack_check_mask = ((s390_stack_size - 1)
07251 & ~(s390_stack_guard - 1));
07252 rtx t = gen_rtx_AND (Pmode, stack_pointer_rtx,
07253 GEN_INT (stack_check_mask));
07254
07255 if (TARGET_64BIT)
07256 gen_cmpdi (t, const0_rtx);
07257 else
07258 gen_cmpsi (t, const0_rtx);
07259
07260 emit_insn (gen_conditional_trap (gen_rtx_EQ (CCmode,
07261 gen_rtx_REG (CCmode,
07262 CC_REGNUM),
07263 const0_rtx),
07264 const0_rtx));
07265 }
07266
07267 if (s390_warn_framesize > 0
07268 && cfun_frame_layout.frame_size >= s390_warn_framesize)
07269 warning (0, "frame size of %qs is " HOST_WIDE_INT_PRINT_DEC " bytes",
07270 current_function_name (), cfun_frame_layout.frame_size);
07271
07272 if (s390_warn_dynamicstack_p && cfun->calls_alloca)
07273 warning (0, "%qs uses dynamic stack allocation", current_function_name ());
07274
07275
07276 if (TARGET_BACKCHAIN || next_fpr)
07277 insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
07278
07279
07280
07281 if (DISP_IN_RANGE (INTVAL (frame_off)))
07282 {
07283 insn = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
07284 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
07285 frame_off));
07286 insn = emit_insn (insn);
07287 }
07288 else
07289 {
07290 if (!CONST_OK_FOR_K (INTVAL (frame_off)))
07291 frame_off = force_const_mem (Pmode, frame_off);
07292
07293 insn = emit_insn (gen_add2_insn (stack_pointer_rtx, frame_off));
07294 annotate_constant_pool_refs (&PATTERN (insn));
07295 }
07296
07297 RTX_FRAME_RELATED_P (insn) = 1;
07298 REG_NOTES (insn) =
07299 gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
07300 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
07301 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
07302 GEN_INT (-cfun_frame_layout.frame_size))),
07303 REG_NOTES (insn));
07304
07305
07306
07307 if (TARGET_BACKCHAIN)
07308 {
07309 if (cfun_frame_layout.backchain_offset)
07310 addr = gen_rtx_MEM (Pmode,
07311 plus_constant (stack_pointer_rtx,
07312 cfun_frame_layout.backchain_offset));
07313 else
07314 addr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
07315 set_mem_alias_set (addr, get_frame_alias_set ());
07316 insn = emit_insn (gen_move_insn (addr, temp_reg));
07317 }
07318
07319
07320
07321
07322
07323 if (TARGET_BACKCHAIN && flag_non_call_exceptions)
07324 {
07325 addr = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode));
07326 emit_insn (gen_rtx_CLOBBER (VOIDmode, addr));
07327 }
07328 }
07329
07330
07331
07332 if (cfun_save_high_fprs_p && next_fpr)
07333 {
07334 insn = emit_insn (gen_add2_insn (temp_reg,
07335 GEN_INT (cfun_frame_layout.f8_offset)));
07336
07337 offset = 0;
07338
07339 for (i = 24; i <= next_fpr; i++)
07340 if (cfun_fpr_bit_p (i - 16))
07341 {
07342 rtx addr = plus_constant (stack_pointer_rtx,
07343 cfun_frame_layout.frame_size
07344 + cfun_frame_layout.f8_offset
07345 + offset);
07346
07347 insn = save_fpr (temp_reg, offset, i);
07348 offset += 8;
07349 RTX_FRAME_RELATED_P (insn) = 1;
07350 REG_NOTES (insn) =
07351 gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
07352 gen_rtx_SET (VOIDmode,
07353 gen_rtx_MEM (DFmode, addr),
07354 gen_rtx_REG (DFmode, i)),
07355 REG_NOTES (insn));
07356 }
07357 }
07358
07359
07360
07361 if (frame_pointer_needed)
07362 {
07363 insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
07364 RTX_FRAME_RELATED_P (insn) = 1;
07365 }
07366
07367
07368
07369 if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
07370 {
07371 rtx insns = s390_load_got ();
07372
07373 for (insn = insns; insn; insn = NEXT_INSN (insn))
07374 {
07375 annotate_constant_pool_refs (&PATTERN (insn));
07376
07377 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
07378 REG_NOTES (insn));
07379 }
07380
07381 emit_insn (insns);
07382 }
07383
07384 if (TARGET_TPF_PROFILING)
07385 {
07386
07387
07388
07389 emit_insn (gen_prologue_tpf ());
07390
07391
07392
07393 emit_insn (gen_blockage ());
07394 }
07395 }
07396
07397
07398
07399 void
07400 s390_emit_epilogue (bool sibcall)
07401 {
07402 rtx frame_pointer, return_reg;
07403 int area_bottom, area_top, offset = 0;
07404 int next_offset;
07405 rtvec p;
07406 int i;
07407
07408 if (TARGET_TPF_PROFILING)
07409 {
07410
07411
07412
07413
07414
07415
07416
07417 emit_insn (gen_blockage ());
07418
07419 emit_insn (gen_epilogue_tpf ());
07420 }
07421
07422
07423
07424 frame_pointer = (frame_pointer_needed
07425 ? hard_frame_pointer_rtx : stack_pointer_rtx);
07426
07427 s390_frame_area (&area_bottom, &area_top);
07428
07429
07430
07431
07432 if (area_top <= area_bottom)
07433 {
07434
07435 }
07436 else if (DISP_IN_RANGE (cfun_frame_layout.frame_size + area_bottom)
07437 && DISP_IN_RANGE (cfun_frame_layout.frame_size + area_top - 1))
07438 {
07439
07440 offset = cfun_frame_layout.frame_size;
07441 }
07442 else
07443 {
07444 rtx insn, frame_off;
07445
07446 offset = area_bottom < 0 ? -area_bottom : 0;
07447 frame_off = GEN_INT (cfun_frame_layout.frame_size - offset);
07448
07449 if (DISP_IN_RANGE (INTVAL (frame_off)))
07450 {
07451 insn = gen_rtx_SET (VOIDmode, frame_pointer,
07452 gen_rtx_PLUS (Pmode, frame_pointer, frame_off));
07453 insn = emit_insn (insn);
07454 }
07455 else
07456 {
07457 if (!CONST_OK_FOR_K (INTVAL (frame_off)))
07458 frame_off = force_const_mem (Pmode, frame_off);
07459
07460 insn = emit_insn (gen_add2_insn (frame_pointer, frame_off));
07461 annotate_constant_pool_refs (&PATTERN (insn));
07462 }
07463 }
07464
07465
07466
07467 if (TARGET_64BIT)
07468 {
07469 if (cfun_save_high_fprs_p)
07470 {
07471 next_offset = cfun_frame_layout.f8_offset;
07472 for (i = 24; i < 32; i++)
07473 {
07474 if (cfun_fpr_bit_p (i - 16))
07475 {
07476 restore_fpr (frame_pointer,
07477 offset + next_offset, i);
07478 next_offset += 8;
07479 }
07480 }
07481 }
07482
07483 }
07484 else
07485 {
07486 next_offset = cfun_frame_layout.f4_offset;
07487 for (i = 18; i < 20; i++)
07488 {
07489 if (cfun_fpr_bit_p (i - 16))
07490 {
07491 restore_fpr (frame_pointer,
07492 offset + next_offset, i);
07493 next_offset += 8;
07494 }
07495 else if (!TARGET_PACKED_STACK)
07496 next_offset += 8;
07497 }
07498
07499 }
07500
07501
07502
07503 return_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
07504
07505
07506
07507 if (cfun_frame_layout.first_restore_gpr != -1)
07508 {
07509 rtx insn, addr;
07510 int i;
07511
07512
07513
07514
07515 for (i = cfun_frame_layout.first_restore_gpr;
07516 i <= cfun_frame_layout.last_restore_gpr;
07517 i++)
07518 {
07519
07520
07521 if (i == STACK_POINTER_REGNUM
07522 || i == RETURN_REGNUM
07523 || i == BASE_REGNUM
07524 || (flag_pic && i == (int)PIC_OFFSET_TABLE_REGNUM))
07525 continue;
07526
07527 if (global_regs[i])
07528 {
07529 addr = plus_constant (frame_pointer,
07530 offset + cfun_frame_layout.gprs_offset
07531 + (i - cfun_frame_layout.first_save_gpr_slot)
07532 * UNITS_PER_WORD);
07533 addr = gen_rtx_MEM (Pmode, addr);
07534 set_mem_alias_set (addr, get_frame_alias_set ());
07535 emit_move_insn (addr, gen_rtx_REG (Pmode, i));
07536 }
07537 }
07538
07539 if (! sibcall)
07540 {
07541
07542
07543
07544 if (cfun_frame_layout.save_return_addr_p
07545 || (cfun_frame_layout.first_restore_gpr < BASE_REGNUM
07546 && cfun_frame_layout.last_restore_gpr > RETURN_REGNUM))
07547 {
07548 int return_regnum = find_unused_clobbered_reg();
07549 if (!return_regnum)
07550 return_regnum = 4;
07551 return_reg = gen_rtx_REG (Pmode, return_regnum);
07552
07553 addr = plus_constant (frame_pointer,
07554 offset + cfun_frame_layout.gprs_offset
07555 + (RETURN_REGNUM
07556 - cfun_frame_layout.first_save_gpr_slot)
07557 * UNITS_PER_WORD);
07558 addr = gen_rtx_MEM (Pmode, addr);
07559 set_mem_alias_set (addr, get_frame_alias_set ());
07560 emit_move_insn (return_reg, addr);
07561 }
07562 }
07563
07564 insn = restore_gprs (frame_pointer,
07565 offset + cfun_frame_layout.gprs_offset
07566 + (cfun_frame_layout.first_restore_gpr
07567 - cfun_frame_layout.first_save_gpr_slot)
07568 * UNITS_PER_WORD,
07569 cfun_frame_layout.first_restore_gpr,
07570 cfun_frame_layout.last_restore_gpr);
07571 emit_insn (insn);
07572 }
07573
07574 if (! sibcall)
07575 {
07576
07577
07578
07579 p = rtvec_alloc (2);
07580
07581 RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
07582 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
07583 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
07584 }
07585 }
07586
07587
07588
07589
07590
07591
07592 static int
07593 s390_function_arg_size (enum machine_mode mode, tree type)
07594 {
07595 if (type)
07596 return int_size_in_bytes (type);
07597
07598
07599 if (mode != BLKmode)
07600 return GET_MODE_SIZE (mode);
07601
07602
07603 gcc_unreachable ();
07604 }
07605
07606
07607
07608
07609 static bool
07610 s390_function_arg_float (enum machine_mode mode, tree type)
07611 {
07612 int size = s390_function_arg_size (mode, type);
07613 if (size > 8)
07614 return false;
07615
07616
07617 if (TARGET_SOFT_FLOAT)
07618 return false;
07619
07620
07621 if (!type)
07622 return mode == SFmode || mode == DFmode || mode == SDmode || mode == DDmode;
07623
07624
07625
07626 while (TREE_CODE (type) == RECORD_TYPE)
07627 {
07628 tree field, single = NULL_TREE;
07629
07630 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
07631 {
07632 if (TREE_CODE (field) != FIELD_DECL)
07633 continue;
07634
07635 if (single == NULL_TREE)
07636 single = TREE_TYPE (field);
07637 else
07638 return false;
07639 }
07640
07641 if (single == NULL_TREE)
07642 return false;
07643 else
07644 type = single;
07645 }
07646
07647 return TREE_CODE (type) == REAL_TYPE;
07648 }
07649
07650
07651
07652
07653
07654 static bool
07655 s390_function_arg_integer (enum machine_mode mode, tree type)
07656 {
07657 int size = s390_function_arg_size (mode, type);
07658 if (size > 8)
07659 return false;
07660
07661
07662 if (!type)
07663 return GET_MODE_CLASS (mode) == MODE_INT
07664 || (TARGET_SOFT_FLOAT && SCALAR_FLOAT_MODE_P (mode));
07665
07666
07667 if (INTEGRAL_TYPE_P (type)
07668 || POINTER_TYPE_P (type)
07669 || TREE_CODE (type) == OFFSET_TYPE
07670 || (TARGET_SOFT_FLOAT && TREE_CODE (type) == REAL_TYPE))
07671 return true;
07672
07673
07674
07675 if (AGGREGATE_TYPE_P (type)
07676 && exact_log2 (size) >= 0
07677 && !s390_function_arg_float (mode, type))
07678 return true;
07679
07680 return false;
07681 }
07682
07683
07684
07685
07686
07687
07688
07689 static bool
07690 s390_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
07691 enum machine_mode mode, tree type,
07692 bool named ATTRIBUTE_UNUSED)
07693 {
07694 int size = s390_function_arg_size (mode, type);
07695 if (size > 8)
07696 return true;
07697
07698 if (type)
07699 {
07700 if (AGGREGATE_TYPE_P (type) && exact_log2 (size) < 0)
07701 return 1;
07702
07703 if (TREE_CODE (type) == COMPLEX_TYPE
07704 || TREE_CODE (type) == VECTOR_TYPE)
07705 return 1;
07706 }
07707
07708 return 0;
07709 }
07710
07711
07712
07713
07714
07715
07716
07717 void
07718 s390_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
07719 tree type, int named ATTRIBUTE_UNUSED)
07720 {
07721 if (s390_function_arg_float (mode, type))
07722 {
07723 cum->fprs += 1;
07724 }
07725 else if (s390_function_arg_integer (mode, type))
07726 {
07727 int size = s390_function_arg_size (mode, type);
07728 cum->gprs += ((size + UNITS_PER_WORD-1) / UNITS_PER_WORD);
07729 }
07730 else
07731 gcc_unreachable ();
07732 }
07733
07734
07735
07736
07737
07738
07739
07740
07741
07742
07743
07744
07745
07746
07747
07748
07749
07750
07751
07752
07753 rtx
07754 s390_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
07755 int named ATTRIBUTE_UNUSED)
07756 {
07757 if (s390_function_arg_float (mode, type))
07758 {
07759 if (cum->fprs + 1 > FP_ARG_NUM_REG)
07760 return 0;
07761 else
07762 return gen_rtx_REG (mode, cum->fprs + 16);
07763 }
07764 else if (s390_function_arg_integer (mode, type))
07765 {
07766 int size = s390_function_arg_size (mode, type);
07767 int n_gprs = (size + UNITS_PER_WORD-1) / UNITS_PER_WORD;
07768
07769 if (cum->gprs + n_gprs > GP_ARG_NUM_REG)
07770 return 0;
07771 else
07772 return gen_rtx_REG (mode, cum->gprs + 2);
07773 }
07774
07775
07776
07777
07778
07779
07780 else if (type == void_type_node)
07781 return const0_rtx;
07782
07783 gcc_unreachable ();
07784 }
07785
07786
07787
07788
07789
07790 static bool
07791 s390_return_in_memory (tree type, tree fundecl ATTRIBUTE_UNUSED)
07792 {
07793
07794 if (INTEGRAL_TYPE_P (type)
07795 || POINTER_TYPE_P (type)
07796 || TREE_CODE (type) == OFFSET_TYPE
07797 || TREE_CODE (type) == REAL_TYPE)
07798 return int_size_in_bytes (type) > 8;
07799
07800
07801
07802 if (AGGREGATE_TYPE_P (type)
07803 || TREE_CODE (type) == COMPLEX_TYPE
07804 || TREE_CODE (type) == VECTOR_TYPE)
07805 return true;
07806
07807
07808
07809
07810 return true;
07811 }
07812
07813
07814
07815
07816
07817 rtx
07818 s390_function_value (tree type, enum machine_mode mode)
07819 {
07820 if (type)
07821 {
07822 int unsignedp = TYPE_UNSIGNED (type);
07823 mode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1);
07824 }
07825
07826 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT || SCALAR_FLOAT_MODE_P (mode));
07827 gcc_assert (GET_MODE_SIZE (mode) <= 8);
07828
07829 if (TARGET_HARD_FLOAT && SCALAR_FLOAT_MODE_P (mode))
07830 return gen_rtx_REG (mode, 16);
07831 else
07832 return gen_rtx_REG (mode, 2);
07833 }
07834
07835
07836
07837
07838
07839
07840
07841
07842
07843
07844
07845
07846
07847
07848
07849
07850
07851
07852
07853
07854
07855
07856
07857 static tree
07858 s390_build_builtin_va_list (void)
07859 {
07860 tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl;
07861
07862 record = lang_hooks.types.make_type (RECORD_TYPE);
07863
07864 type_decl =
07865 build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
07866
07867 f_gpr = build_decl (FIELD_DECL, get_identifier ("__gpr"),
07868 long_integer_type_node);
07869 f_fpr = build_decl (FIELD_DECL, get_identifier ("__fpr"),
07870 long_integer_type_node);
07871 f_ovf = build_decl (FIELD_DECL, get_identifier ("__overflow_arg_area"),
07872 ptr_type_node);
07873 f_sav = build_decl (FIELD_DECL, get_identifier ("__reg_save_area"),
07874 ptr_type_node);
07875
07876 va_list_gpr_counter_field = f_gpr;
07877 va_list_fpr_counter_field = f_fpr;
07878
07879 DECL_FIELD_CONTEXT (f_gpr) = record;
07880 DECL_FIELD_CONTEXT (f_fpr) = record;
07881 DECL_FIELD_CONTEXT (f_ovf) = record;
07882 DECL_FIELD_CONTEXT (f_sav) = record;
07883
07884 TREE_CHAIN (record) = type_decl;
07885 TYPE_NAME (record) = type_decl;
07886 TYPE_FIELDS (record) = f_gpr;
07887 TREE_CHAIN (f_gpr) = f_fpr;
07888 TREE_CHAIN (f_fpr) = f_ovf;
07889 TREE_CHAIN (f_ovf) = f_sav;
07890
07891 layout_type (record);
07892
07893
07894 return build_array_type (record, build_index_type (size_zero_node));
07895 }
07896
07897
07898
07899
07900
07901
07902
07903
07904
07905
07906
07907
07908
07909
07910 void
07911 s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
07912 {
07913 HOST_WIDE_INT n_gpr, n_fpr;
07914 int off;
07915 tree f_gpr, f_fpr, f_ovf, f_sav;
07916 tree gpr, fpr, ovf, sav, t;
07917
07918 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
07919 f_fpr = TREE_CHAIN (f_gpr);
07920 f_ovf = TREE_CHAIN (f_fpr);
07921 f_sav = TREE_CHAIN (f_ovf);
07922
07923 valist = build_va_arg_indirect_ref (valist);
07924 gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
07925 fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
07926 ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
07927 sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
07928
07929
07930
07931 n_gpr = current_function_args_info.gprs;
07932 n_fpr = current_function_args_info.fprs;
07933
07934 if (cfun->va_list_gpr_size)
07935 {
07936 t = build2 (MODIFY_EXPR, TREE_TYPE (gpr), gpr,
07937 build_int_cst (NULL_TREE, n_gpr));
07938 TREE_SIDE_EFFECTS (t) = 1;
07939 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
07940 }
07941
07942 if (cfun->va_list_fpr_size)
07943 {
07944 t = build2 (MODIFY_EXPR, TREE_TYPE (fpr), fpr,
07945 build_int_cst (NULL_TREE, n_fpr));
07946 TREE_SIDE_EFFECTS (t) = 1;
07947 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
07948 }
07949
07950
07951 if (n_gpr + cfun->va_list_gpr_size > GP_ARG_NUM_REG
07952 || n_fpr + cfun->va_list_fpr_size > FP_ARG_NUM_REG)
07953 {
07954 t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
07955
07956 off = INTVAL (current_function_arg_offset_rtx);
07957 off = off < 0 ? 0 : off;
07958 if (TARGET_DEBUG_ARG)
07959 fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
07960 (int)n_gpr, (int)n_fpr, off);
07961
07962 t = build2 (PLUS_EXPR, TREE_TYPE (ovf), t, build_int_cst (NULL_TREE, off));
07963
07964 t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
07965 TREE_SIDE_EFFECTS (t) = 1;
07966 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
07967 }
07968
07969
07970 if ((cfun->va_list_gpr_size && n_gpr < GP_ARG_NUM_REG)
07971 || (cfun->va_list_fpr_size && n_fpr < FP_ARG_NUM_REG))
07972 {
07973 t = make_tree (TREE_TYPE (sav), return_address_pointer_rtx);
07974 t = build2 (PLUS_EXPR, TREE_TYPE (sav), t,
07975 build_int_cst (NULL_TREE, -RETURN_REGNUM * UNITS_PER_WORD));
07976
07977 t = build2 (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
07978 TREE_SIDE_EFFECTS (t) = 1;
07979 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
07980 }
07981 }
07982
07983
07984
07985
07986
07987
07988
07989
07990
07991
07992
07993
07994
07995
07996
07997
07998
07999
08000
08001
08002
08003
08004
08005
08006
08007 static tree
08008 s390_gimplify_va_arg (tree valist, tree type, tree *pre_p,
08009 tree *post_p ATTRIBUTE_UNUSED)
08010 {
08011 tree f_gpr, f_fpr, f_ovf, f_sav;
08012 tree gpr, fpr, ovf, sav, reg, t, u;
08013 int indirect_p, size, n_reg, sav_ofs, sav_scale, max_reg;
08014 tree lab_false, lab_over, addr;
08015
08016 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
08017 f_fpr = TREE_CHAIN (f_gpr);
08018 f_ovf = TREE_CHAIN (f_fpr);
08019 f_sav = TREE_CHAIN (f_ovf);
08020
08021 valist = build_va_arg_indirect_ref (valist);
08022 gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
08023 fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
08024 ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
08025 sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
08026
08027 size = int_size_in_bytes (type);
08028
08029 if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
08030 {
08031 if (TARGET_DEBUG_ARG)
08032 {
08033 fprintf (stderr, "va_arg: aggregate type");
08034 debug_tree (type);
08035 }
08036
08037
08038 indirect_p = 1;
08039 reg = gpr;
08040 n_reg = 1;
08041
08042
08043
08044
08045 sav_ofs = 2 * UNITS_PER_WORD;
08046 sav_scale = UNITS_PER_WORD;
08047 size = UNITS_PER_WORD;
08048 max_reg = GP_ARG_NUM_REG - n_reg;
08049 }
08050 else if (s390_function_arg_float (TYPE_MODE (type), type))
08051 {
08052 if (TARGET_DEBUG_ARG)
08053 {
08054 fprintf (stderr, "va_arg: float type");
08055 debug_tree (type);
08056 }
08057
08058
08059 indirect_p = 0;
08060 reg = fpr;
08061 n_reg = 1;
08062 sav_ofs = 16 * UNITS_PER_WORD;
08063 sav_scale = 8;
08064 max_reg = FP_ARG_NUM_REG - n_reg;
08065 }
08066 else
08067 {
08068 if (TARGET_DEBUG_ARG)
08069 {
08070 fprintf (stderr, "va_arg: other type");
08071 debug_tree (type);
08072 }
08073
08074
08075 indirect_p = 0;
08076 reg = gpr;
08077 n_reg = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
08078
08079
08080
08081
08082 sav_ofs = 2 * UNITS_PER_WORD;
08083
08084 if (size < UNITS_PER_WORD)
08085 sav_ofs += UNITS_PER_WORD - size;
08086
08087 sav_scale = UNITS_PER_WORD;
08088 max_reg = GP_ARG_NUM_REG - n_reg;
08089 }
08090
08091
08092
08093 lab_false = create_artificial_label ();
08094 lab_over = create_artificial_label ();
08095 addr = create_tmp_var (ptr_type_node, "addr");
08096 DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
08097
08098 t = fold_convert (TREE_TYPE (reg), size_int (max_reg));
08099 t = build2 (GT_EXPR, boolean_type_node, reg, t);
08100 u = build1 (GOTO_EXPR, void_type_node, lab_false);
08101 t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
08102 gimplify_and_add (t, pre_p);
08103
08104 t = build2 (PLUS_EXPR, ptr_type_node, sav,
08105 fold_convert (ptr_type_node, size_int (sav_ofs)));
08106 u = build2 (MULT_EXPR, TREE_TYPE (reg), reg,
08107 fold_convert (TREE_TYPE (reg), size_int (sav_scale)));
08108 t = build2 (PLUS_EXPR, ptr_type_node, t, fold_convert (ptr_type_node, u));
08109
08110 t = build2 (MODIFY_EXPR, void_type_node, addr, t);
08111 gimplify_and_add (t, pre_p);
08112
08113 t = build1 (GOTO_EXPR, void_type_node, lab_over);
08114 gimplify_and_add (t, pre_p);
08115
08116 t = build1 (LABEL_EXPR, void_type_node, lab_false);
08117 append_to_statement_list (t, pre_p);
08118
08119
08120
08121
08122 t = ovf;
08123 if (size < UNITS_PER_WORD)
08124 t = build2 (PLUS_EXPR, ptr_type_node, t,
08125 fold_convert (ptr_type_node, size_int (UNITS_PER_WORD - size)));
08126
08127 gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
08128
08129 u = build2 (MODIFY_EXPR, void_type_node, addr, t);
08130 gimplify_and_add (u, pre_p);
08131
08132 t = build2 (PLUS_EXPR, ptr_type_node, t,
08133 fold_convert (ptr_type_node, size_int (size)));
08134 t = build2 (MODIFY_EXPR, ptr_type_node, ovf, t);
08135 gimplify_and_add (t, pre_p);
08136
08137 t = build1 (LABEL_EXPR, void_type_node, lab_over);
08138 append_to_statement_list (t, pre_p);
08139
08140
08141
08142
08143 u = build2 (PREINCREMENT_EXPR, TREE_TYPE (reg), reg,
08144 fold_convert (TREE_TYPE (reg), size_int (n_reg)));
08145 gimplify_and_add (u, pre_p);
08146
08147 if (indirect_p)
08148 {
08149 t = build_pointer_type (build_pointer_type (type));
08150 addr = fold_convert (t, addr);
08151 addr = build_va_arg_indirect_ref (addr);
08152 }
08153 else
08154 {
08155 t = build_pointer_type (type);
08156 addr = fold_convert (t, addr);
08157 }
08158
08159 return build_va_arg_indirect_ref (addr);
08160 }
08161
08162
08163
08164
08165 enum s390_builtin
08166 {
08167 S390_BUILTIN_THREAD_POINTER,
08168 S390_BUILTIN_SET_THREAD_POINTER,
08169
08170 S390_BUILTIN_max
08171 };
08172
08173 static unsigned int const code_for_builtin_64[S390_BUILTIN_max] = {
08174 CODE_FOR_get_tp_64,
08175 CODE_FOR_set_tp_64
08176 };
08177
08178 static unsigned int const code_for_builtin_31[S390_BUILTIN_max] = {
08179 CODE_FOR_get_tp_31,
08180 CODE_FOR_set_tp_31
08181 };
08182
08183 static void
08184 s390_init_builtins (void)
08185 {
08186 tree ftype;
08187
08188 ftype = build_function_type (ptr_type_node, void_list_node);
08189 lang_hooks.builtin_function ("__builtin_thread_pointer", ftype,
08190 S390_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
08191 NULL, NULL_TREE);
08192
08193 ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
08194 lang_hooks.builtin_function ("__builtin_set_thread_pointer", ftype,
08195 S390_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
08196 NULL, NULL_TREE);
08197 }
08198
08199
08200
08201
08202
08203
08204
08205 static rtx
08206 s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
08207 enum machine_mode mode ATTRIBUTE_UNUSED,
08208 int ignore ATTRIBUTE_UNUSED)
08209 {
08210 #define MAX_ARGS 2
08211
08212 unsigned int const *code_for_builtin =
08213 TARGET_64BIT ? code_for_builtin_64 : code_for_builtin_31;
08214
08215 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
08216 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
08217 tree arglist = TREE_OPERAND (exp, 1);
08218 enum insn_code icode;
08219 rtx op[MAX_ARGS], pat;
08220 int arity;
08221 bool nonvoid;
08222
08223 if (fcode >= S390_BUILTIN_max)
08224 internal_error ("bad builtin fcode");
08225 icode = code_for_builtin[fcode];
08226 if (icode == 0)
08227 internal_error ("bad builtin fcode");
08228
08229 nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
08230
08231 for (arglist = TREE_OPERAND (exp, 1), arity = 0;
08232 arglist;
08233 arglist = TREE_CHAIN (arglist), arity++)
08234 {
08235 const struct insn_operand_data *insn_op;
08236
08237 tree arg = TREE_VALUE (arglist);
08238 if (arg == error_mark_node)
08239 return NULL_RTX;
08240 if (arity > MAX_ARGS)
08241 return NULL_RTX;
08242
08243 insn_op = &insn_data[icode].operand[arity + nonvoid];
08244
08245 op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, 0);
08246
08247 if (!(*insn_op->predicate) (op[arity], insn_op->mode))
08248 op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]);
08249 }
08250
08251 if (nonvoid)
08252 {
08253 enum machine_mode tmode = insn_data[icode].operand[0].mode;
08254 if (!target
08255 || GET_MODE (target) != tmode
08256 || !(*insn_data[icode].operand[0].predicate) (target, tmode))
08257 target = gen_reg_rtx (tmode);
08258 }
08259
08260 switch (arity)
08261 {
08262 case 0:
08263 pat = GEN_FCN (icode) (target);
08264 break;
08265 case 1:
08266 if (nonvoid)
08267 pat = GEN_FCN (icode) (target, op[0]);
08268 else
08269 pat = GEN_FCN (icode) (op[0]);
08270 break;
08271 case 2:
08272 pat = GEN_FCN (icode) (target, op[0], op[1]);
08273 break;
08274 default:
08275 gcc_unreachable ();
08276 }
08277 if (!pat)
08278 return NULL_RTX;
08279 emit_insn (pat);
08280
08281 if (nonvoid)
08282 return target;
08283 else
08284 return const0_rtx;
08285 }
08286
08287
08288
08289
08290
08291
08292
08293
08294 void
08295 s390_trampoline_template (FILE *file)
08296 {
08297 rtx op[2];
08298 op[0] = gen_rtx_REG (Pmode, 0);
08299 op[1] = gen_rtx_REG (Pmode, 1);
08300
08301 if (TARGET_64BIT)
08302 {
08303 output_asm_insn ("basr\t%1,0", op);
08304 output_asm_insn ("lmg\t%0,%1,14(%1)", op);
08305 output_asm_insn ("br\t%1", op);
08306 ASM_OUTPUT_SKIP (file, (HOST_WIDE_INT)(TRAMPOLINE_SIZE - 10));
08307 }
08308 else
08309 {
08310 output_asm_insn ("basr\t%1,0", op);
08311 output_asm_insn ("lm\t%0,%1,6(%1)", op);
08312 output_asm_insn ("br\t%1", op);
08313 ASM_OUTPUT_SKIP (file, (HOST_WIDE_INT)(TRAMPOLINE_SIZE - 8));
08314 }
08315 }
08316
08317
08318
08319
08320
08321 void
08322 s390_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt)
08323 {
08324 emit_move_insn (gen_rtx_MEM (Pmode,
08325 memory_address (Pmode,
08326 plus_constant (addr, (TARGET_64BIT ? 16 : 8)))), cxt);
08327 emit_move_insn (gen_rtx_MEM (Pmode,
08328 memory_address (Pmode,
08329 plus_constant (addr, (TARGET_64BIT ? 24 : 12)))), fnaddr);
08330 }
08331
08332
08333
08334
08335 rtx
08336 s390_gen_rtx_const_DI (int high, int low)
08337 {
08338 #if HOST_BITS_PER_WIDE_INT >= 64
08339 HOST_WIDE_INT val;
08340 val = (HOST_WIDE_INT)high;
08341 val <<= 32;
08342 val |= (HOST_WIDE_INT)low;
08343
08344 return GEN_INT (val);
08345 #else
08346 #if HOST_BITS_PER_WIDE_INT >= 32
08347 return immed_double_const ((HOST_WIDE_INT)low, (HOST_WIDE_INT)high, DImode);
08348 #else
08349 gcc_unreachable ();
08350 #endif
08351 #endif
08352 }
08353
08354
08355
08356
08357 void
08358 s390_function_profiler (FILE *file, int labelno)
08359 {
08360 rtx op[7];
08361
08362 char label[128];
08363 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
08364
08365 fprintf (file, "# function profiler \n");
08366
08367 op[0] = gen_rtx_REG (Pmode, RETURN_REGNUM);
08368 op[1] = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
08369 op[1] = gen_rtx_MEM (Pmode, plus_constant (op[1], UNITS_PER_WORD));
08370
08371 op[2] = gen_rtx_REG (Pmode, 1);
08372 op[3] = gen_rtx_SYMBOL_REF (Pmode, label);
08373 SYMBOL_REF_FLAGS (op[3]) = SYMBOL_FLAG_LOCAL;
08374
08375 op[4] = gen_rtx_SYMBOL_REF (Pmode, "_mcount");
08376 if (flag_pic)
08377 {
08378 op[4] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[4]), UNSPEC_PLT);
08379 op[4] = gen_rtx_CONST (Pmode, op[4]);
08380 }
08381
08382 if (TARGET_64BIT)
08383 {
08384 output_asm_insn ("stg\t%0,%1", op);
08385 output_asm_insn ("larl\t%2,%3", op);
08386 output_asm_insn ("brasl\t%0,%4", op);
08387 output_asm_insn ("lg\t%0,%1", op);
08388 }
08389 else if (!flag_pic)
08390 {
08391 op[6] = gen_label_rtx ();
08392
08393 output_asm_insn ("st\t%0,%1", op);
08394 output_asm_insn ("bras\t%2,%l6", op);
08395 output_asm_insn (".long\t%4", op);
08396 output_asm_insn (".long\t%3", op);
08397 targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (op[6]));
08398 output_asm_insn ("l\t%0,0(%2)", op);
08399 output_asm_insn ("l\t%2,4(%2)", op);
08400 output_asm_insn ("basr\t%0,%0", op);
08401 output_asm_insn ("l\t%0,%1", op);
08402 }
08403 else
08404 {
08405 op[5] = gen_label_rtx ();
08406 op[6] = gen_label_rtx ();
08407
08408 output_asm_insn ("st\t%0,%1", op);
08409 output_asm_insn ("bras\t%2,%l6", op);
08410 targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (op[5]));
08411 output_asm_insn (".long\t%4-%l5", op);
08412 output_asm_insn (".long\t%3-%l5", op);
08413 targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (op[6]));
08414 output_asm_insn ("lr\t%0,%2", op);
08415 output_asm_insn ("a\t%0,0(%2)", op);
08416 output_asm_insn ("a\t%2,4(%2)", op);
08417 output_asm_insn ("basr\t%0,%0", op);
08418 output_asm_insn ("l\t%0,%1", op);
08419 }
08420 }
08421
08422
08423
08424
08425 static void
08426 s390_encode_section_info (tree decl, rtx rtl, int first)
08427 {
08428 default_encode_section_info (decl, rtl, first);
08429
08430
08431
08432 if (TREE_CODE (decl) == VAR_DECL
08433 && DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 16)
08434 SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1;
08435 }
08436
08437
08438
08439
08440
08441
08442
08443 static void
08444 s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
08445 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
08446 tree function)
08447 {
08448 rtx op[10];
08449 int nonlocal = 0;
08450
08451
08452 op[0] = XEXP (DECL_RTL (function), 0);
08453 if (flag_pic && !SYMBOL_REF_LOCAL_P (op[0]))
08454 {
08455 nonlocal = 1;
08456 op[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[0]),
08457 TARGET_64BIT ? UNSPEC_PLT : UNSPEC_GOT);
08458 op[0] = gen_rtx_CONST (Pmode, op[0]);
08459 }
08460
08461
08462 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
08463 op[1] = gen_rtx_REG (Pmode, 3);
08464 else
08465 op[1] = gen_rtx_REG (Pmode, 2);
08466
08467
08468 op[2] = GEN_INT (delta);
08469
08470
08471 op[3] = GEN_INT (vcall_offset);
08472
08473
08474 op[4] = gen_rtx_REG (Pmode, 1);
08475
08476
08477 op[5] = NULL_RTX;
08478 op[6] = NULL_RTX;
08479 op[7] = NULL_RTX;
08480 op[8] = NULL_RTX;
08481
08482
08483 op[9] = NULL_RTX;
08484
08485
08486 if (TARGET_64BIT)
08487 {
08488
08489 if ((!DISP_IN_RANGE (delta)
08490 && !CONST_OK_FOR_K (delta)
08491 && !CONST_OK_FOR_Os (delta))
08492 || (!DISP_IN_RANGE (vcall_offset)
08493 && !CONST_OK_FOR_K (vcall_offset)
08494 && !CONST_OK_FOR_Os (vcall_offset)))
08495 {
08496 op[5] = gen_label_rtx ();
08497 output_asm_insn ("larl\t%4,%5", op);
08498 }
08499
08500
08501 if (delta)
08502 {
08503 if (CONST_OK_FOR_J (delta))
08504 output_asm_insn ("la\t%1,%2(%1)", op);
08505 else if (DISP_IN_RANGE (delta))
08506 output_asm_insn ("lay\t%1,%2(%1)", op);
08507 else if (CONST_OK_FOR_K (delta))
08508 output_asm_insn ("aghi\t%1,%2", op);
08509 else if (CONST_OK_FOR_Os (delta))
08510 output_asm_insn ("agfi\t%1,%2", op);
08511 else
08512 {
08513 op[6] = gen_label_rtx ();
08514 output_asm_insn ("agf\t%1,%6-%5(%4)", op);
08515 }
08516 }
08517
08518
08519 if (vcall_offset)
08520 {
08521 if (DISP_IN_RANGE (vcall_offset))
08522 {
08523 output_asm_insn ("lg\t%4,0(%1)", op);
08524 output_asm_insn ("ag\t%1,%3(%4)", op);
08525 }
08526 else if (CONST_OK_FOR_K (vcall_offset))
08527 {
08528 output_asm_insn ("lghi\t%4,%3", op);
08529 output_asm_insn ("ag\t%4,0(%1)", op);
08530 output_asm_insn ("ag\t%1,0(%4)", op);
08531 }
08532 else if (CONST_OK_FOR_Os (vcall_offset))
08533 {
08534 output_asm_insn ("lgfi\t%4,%3", op);
08535 output_asm_insn ("ag\t%4,0(%1)", op);
08536 output_asm_insn ("ag\t%1,0(%4)", op);
08537 }
08538 else
08539 {
08540 op[7] = gen_label_rtx ();
08541 output_asm_insn ("llgf\t%4,%7-%5(%4)", op);
08542 output_asm_insn ("ag\t%4,0(%1)", op);
08543 output_asm_insn ("ag\t%1,0(%4)", op);
08544 }
08545 }
08546
08547
08548 output_asm_insn ("jg\t%0", op);
08549
08550
08551 if (op[5])
08552 {
08553 output_asm_insn (".align\t4", op);
08554 targetm.asm_out.internal_label (file, "L",
08555 CODE_LABEL_NUMBER (op[5]));
08556 }
08557 if (op[6])
08558 {
08559 targetm.asm_out.internal_label (file, "L",
08560 CODE_LABEL_NUMBER (op[6]));
08561 output_asm_insn (".long\t%2", op);
08562 }
08563 if (op[7])
08564 {
08565 targetm.asm_out.internal_label (file, "L",
08566 CODE_LABEL_NUMBER (op[7]));
08567 output_asm_insn (".long\t%3", op);
08568 }
08569 }
08570 else
08571 {
08572
08573 if (!vcall_offset
08574 || (!DISP_IN_RANGE (delta)
08575 && !CONST_OK_FOR_K (delta)
08576 && !CONST_OK_FOR_Os (delta))
08577 || (!DISP_IN_RANGE (delta)
08578 && !CONST_OK_FOR_K (vcall_offset)
08579 && !CONST_OK_FOR_Os (vcall_offset)))
08580 {
08581 op[5] = gen_label_rtx ();
08582 output_asm_insn ("basr\t%4,0", op);
08583 targetm.asm_out.internal_label (file, "L",
08584 CODE_LABEL_NUMBER (op[5]));
08585 }
08586
08587
08588 if (delta)
08589 {
08590 if (CONST_OK_FOR_J (delta))
08591 output_asm_insn ("la\t%1,%2(%1)", op);
08592 else if (DISP_IN_RANGE (delta))
08593 output_asm_insn ("lay\t%1,%2(%1)", op);
08594 else if (CONST_OK_FOR_K (delta))
08595 output_asm_insn ("ahi\t%1,%2", op);
08596 else if (CONST_OK_FOR_Os (delta))
08597 output_asm_insn ("afi\t%1,%2", op);
08598 else
08599 {
08600 op[6] = gen_label_rtx ();
08601 output_asm_insn ("a\t%1,%6-%5(%4)", op);
08602 }
08603 }
08604
08605
08606 if (vcall_offset)
08607 {
08608 if (CONST_OK_FOR_J (vcall_offset))
08609 {
08610 output_asm_insn ("l\t%4,0(%1)", op);
08611 output_asm_insn ("a\t%1,%3(%4)", op);
08612 }
08613 else if (DISP_IN_RANGE (vcall_offset))
08614 {
08615 output_asm_insn ("l\t%4,0(%1)", op);
08616 output_asm_insn ("ay\t%1,%3(%4)", op);
08617 }
08618 else if (CONST_OK_FOR_K (vcall_offset))
08619 {
08620 output_asm_insn ("lhi\t%4,%3", op);
08621 output_asm_insn ("a\t%4,0(%1)", op);
08622 output_asm_insn ("a\t%1,0(%4)", op);
08623 }
08624 else if (CONST_OK_FOR_Os (vcall_offset))
08625 {
08626 output_asm_insn ("iilf\t%4,%3", op);
08627 output_asm_insn ("a\t%4,0(%1)", op);
08628 output_asm_insn ("a\t%1,0(%4)", op);
08629 }
08630 else
08631 {
08632 op[7] = gen_label_rtx ();
08633 output_asm_insn ("l\t%4,%7-%5(%4)", op);
08634 output_asm_insn ("a\t%4,0(%1)", op);
08635 output_asm_insn ("a\t%1,0(%4)", op);
08636 }
08637
08638
08639
08640 op[5] = gen_label_rtx ();
08641 output_asm_insn ("basr\t%4,0", op);
08642 targetm.asm_out.internal_label (file, "L",
08643 CODE_LABEL_NUMBER (op[5]));
08644 }
08645
08646
08647 op[8] = gen_label_rtx ();
08648
08649 if (!flag_pic)
08650 output_asm_insn ("l\t%4,%8-%5(%4)", op);
08651 else if (!nonlocal)
08652 output_asm_insn ("a\t%4,%8-%5(%4)", op);
08653
08654 else if (flag_pic == 1)
08655 {
08656 output_asm_insn ("a\t%4,%8-%5(%4)", op);
08657 output_asm_insn ("l\t%4,%0(%4)", op);
08658 }
08659 else if (flag_pic == 2)
08660 {
08661 op[9] = gen_rtx_REG (Pmode, 0);
08662 output_asm_insn ("l\t%9,%8-4-%5(%4)", op);
08663 output_asm_insn ("a\t%4,%8-%5(%4)", op);
08664 output_asm_insn ("ar\t%4,%9", op);
08665 output_asm_insn ("l\t%4,0(%4)", op);
08666 }
08667
08668 output_asm_insn ("br\t%4", op);
08669
08670
08671 output_asm_insn (".align\t4", op);
08672
08673 if (nonlocal && flag_pic == 2)
08674 output_asm_insn (".long\t%0", op);
08675 if (nonlocal)
08676 {
08677 op[0] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
08678 SYMBOL_REF_FLAGS (op[0]) = SYMBOL_FLAG_LOCAL;
08679 }
08680
08681 targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (op[8]));
08682 if (!flag_pic)
08683 output_asm_insn (".long\t%0", op);
08684 else
08685 output_asm_insn (".long\t%0-%5", op);
08686
08687 if (op[6])
08688 {
08689 targetm.asm_out.internal_label (file, "L",
08690 CODE_LABEL_NUMBER (op[6]));
08691 output_asm_insn (".long\t%2", op);
08692 }
08693 if (op[7])
08694 {
08695 targetm.asm_out.internal_label (file, "L",
08696 CODE_LABEL_NUMBER (op[7]));
08697 output_asm_insn (".long\t%3", op);
08698 }
08699 }
08700 }
08701
08702 static bool
08703 s390_valid_pointer_mode (enum machine_mode mode)
08704 {
08705 return (mode == SImode || (TARGET_64BIT && mode == DImode));
08706 }
08707
08708
08709
08710
08711
08712
08713 static bool
08714 s390_call_saved_register_used (tree argument_list)
08715 {
08716 CUMULATIVE_ARGS cum;
08717 tree parameter;
08718 enum machine_mode mode;
08719 tree type;
08720 rtx parm_rtx;
08721 int reg;
08722
08723 INIT_CUMULATIVE_ARGS (cum, NULL, NULL, 0, 0);
08724
08725 while (argument_list)
08726 {
08727 parameter = TREE_VALUE (argument_list);
08728 argument_list = TREE_CHAIN (argument_list);
08729
08730 gcc_assert (parameter);
08731
08732
08733
08734 if (TREE_CODE (parameter) == ERROR_MARK)
08735 return true;
08736
08737 type = TREE_TYPE (parameter);
08738 gcc_assert (type);
08739
08740 mode = TYPE_MODE (type);
08741 gcc_assert (mode);
08742
08743 if (pass_by_reference (&cum, mode, type, true))
08744 {
08745 mode = Pmode;
08746 type = build_pointer_type (type);
08747 }
08748
08749 parm_rtx = s390_function_arg (&cum, mode, type, 0);
08750
08751 s390_function_arg_advance (&cum, mode, type, 0);
08752
08753 if (parm_rtx && REG_P (parm_rtx))
08754 {
08755 for (reg = 0;
08756 reg < HARD_REGNO_NREGS (REGNO (parm_rtx), GET_MODE (parm_rtx));
08757 reg++)
08758 if (! call_used_regs[reg + REGNO (parm_rtx)])
08759 return true;
08760 }
08761 }
08762 return false;
08763 }
08764
08765
08766
08767
08768
08769
08770 static bool
08771 s390_function_ok_for_sibcall (tree decl, tree exp)
08772 {
08773
08774 if (TARGET_TPF_PROFILING)
08775 return false;
08776
08777
08778
08779 if (!TARGET_64BIT && flag_pic && decl && !targetm.binds_local_p (decl))
08780 return false;
08781
08782
08783
08784
08785 if (TREE_OPERAND (exp, 1)
08786 && s390_call_saved_register_used (TREE_OPERAND (exp, 1)))
08787 return false;
08788
08789 return true;
08790 }
08791
08792
08793
08794 static bool
08795 s390_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
08796 {
08797 *p1 = CC_REGNUM;
08798 *p2 = INVALID_REGNUM;
08799
08800 return true;
08801 }
08802
08803
08804
08805
08806
08807
08808
08809
08810
08811
08812
08813 rtx
08814 s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg,
08815 rtx retaddr_reg)
08816 {
08817 bool plt_call = false;
08818 rtx insn;
08819 rtx call;
08820 rtx clobber;
08821 rtvec vec;
08822
08823
08824 if (GET_CODE (addr_location) == SYMBOL_REF)
08825 {
08826
08827
08828 if (flag_pic && !SYMBOL_REF_LOCAL_P (addr_location))
08829 {
08830 addr_location = gen_rtx_UNSPEC (Pmode,
08831 gen_rtvec (1, addr_location),
08832 UNSPEC_PLT);
08833 addr_location = gen_rtx_CONST (Pmode, addr_location);
08834 plt_call = true;
08835 }
08836
08837
08838
08839 if (!TARGET_SMALL_EXEC && !TARGET_CPU_ZARCH)
08840 {
08841 if (flag_pic)
08842 addr_location = legitimize_pic_address (addr_location, 0);
08843 else
08844 addr_location = force_reg (Pmode, addr_location);
08845 }
08846 }
08847
08848
08849
08850
08851 if (retaddr_reg == NULL_RTX
08852 && GET_CODE (addr_location) != SYMBOL_REF
08853 && !plt_call)
08854 {
08855 emit_move_insn (gen_rtx_REG (Pmode, SIBCALL_REGNUM), addr_location);
08856 addr_location = gen_rtx_REG (Pmode, SIBCALL_REGNUM);
08857 }
08858
08859 addr_location = gen_rtx_MEM (QImode, addr_location);
08860 call = gen_rtx_CALL (VOIDmode, addr_location, const0_rtx);
08861
08862 if (result_reg != NULL_RTX)
08863 call = gen_rtx_SET (VOIDmode, result_reg, call);
08864
08865 if (retaddr_reg != NULL_RTX)
08866 {
08867 clobber = gen_rtx_CLOBBER (VOIDmode, retaddr_reg);
08868
08869 if (tls_call != NULL_RTX)
08870 vec = gen_rtvec (3, call, clobber,
08871 gen_rtx_USE (VOIDmode, tls_call));
08872 else
08873 vec = gen_rtvec (2, call, clobber);
08874
08875 call = gen_rtx_PARALLEL (VOIDmode, vec);
08876 }
08877
08878 insn = emit_call_insn (call);
08879
08880
08881 if ((!TARGET_64BIT && plt_call) || tls_call != NULL_RTX)
08882 {
08883
08884
08885 gcc_assert (retaddr_reg != NULL_RTX);
08886
08887 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
08888 }
08889 return insn;
08890 }
08891
08892
08893
08894 void
08895 s390_conditional_register_usage (void)
08896 {
08897 int i;
08898
08899 if (flag_pic)
08900 {
08901 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
08902 call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
08903 }
08904 if (TARGET_CPU_ZARCH)
08905 {
08906 fixed_regs[BASE_REGNUM] = 0;
08907 call_used_regs[BASE_REGNUM] = 0;
08908 fixed_regs[RETURN_REGNUM] = 0;
08909 call_used_regs[RETURN_REGNUM] = 0;
08910 }
08911 if (TARGET_64BIT)
08912 {
08913 for (i = 24; i < 32; i++)
08914 call_used_regs[i] = call_really_used_regs[i] = 0;
08915 }
08916 else
08917 {
08918 for (i = 18; i < 20; i++)
08919 call_used_regs[i] = call_really_used_regs[i] = 0;
08920 }
08921
08922 if (TARGET_SOFT_FLOAT)
08923 {
08924 for (i = 16; i < 32; i++)
08925 call_used_regs[i] = fixed_regs[i] = 1;
08926 }
08927 }
08928
08929
08930
08931 static GTY(()) rtx s390_tpf_eh_return_symbol;
08932 void
08933 s390_emit_tpf_eh_return (rtx target)
08934 {
08935 rtx insn, reg;
08936
08937 if (!s390_tpf_eh_return_symbol)
08938 s390_tpf_eh_return_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tpf_eh_return");
08939
08940 reg = gen_rtx_REG (Pmode, 2);
08941
08942 emit_move_insn (reg, target);
08943 insn = s390_emit_call (s390_tpf_eh_return_symbol, NULL_RTX, reg,
08944 gen_rtx_REG (Pmode, RETURN_REGNUM));
08945 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
08946
08947 emit_move_insn (EH_RETURN_HANDLER_RTX, reg);
08948 }
08949
08950
08951
08952
08953 static void
08954 s390_optimize_prologue (void)
08955 {
08956 rtx insn, new_insn, next_insn;
08957
08958
08959
08960 s390_update_frame_layout ();
08961
08962
08963
08964
08965 if (cfun_frame_layout.first_save_gpr <= BASE_REGNUM
08966 && cfun_frame_layout.last_save_gpr >= BASE_REGNUM
08967 && (TARGET_CPU_ZARCH
08968 || (cfun_frame_layout.first_save_gpr <= RETURN_REGNUM
08969 && cfun_frame_layout.last_save_gpr >= RETURN_REGNUM)))
08970 return;
08971
08972
08973
08974 for (insn = get_insns (); insn; insn = next_insn)
08975 {
08976 int first, last, off;
08977 rtx set, base, offset;
08978
08979 next_insn = NEXT_INSN (insn);
08980
08981 if (GET_CODE (insn) != INSN)
08982 continue;
08983
08984 if (GET_CODE (PATTERN (insn)) == PARALLEL
08985 && store_multiple_operation (PATTERN (insn), VOIDmode))
08986 {
08987 set = XVECEXP (PATTERN (insn), 0, 0);
08988 first = REGNO (SET_SRC (set));
08989 last = first + XVECLEN (PATTERN (insn), 0) - 1;
08990 offset = const0_rtx;
08991 base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
08992 off = INTVAL (offset);
08993
08994 if (GET_CODE (base) != REG || off < 0)
08995 continue;
08996 if (cfun_frame_layout.first_save_gpr != -1
08997 && (cfun_frame_layout.first_save_gpr < first
08998 || cfun_frame_layout.last_save_gpr > last))
08999 continue;
09000 if (REGNO (base) != STACK_POINTER_REGNUM
09001 && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
09002 continue;
09003 if (first > BASE_REGNUM || last < BASE_REGNUM)
09004 continue;
09005
09006 if (cfun_frame_layout.first_save_gpr != -1)
09007 {
09008 new_insn = save_gprs (base,
09009 off + (cfun_frame_layout.first_save_gpr
09010 - first) * UNITS_PER_WORD,
09011 cfun_frame_layout.first_save_gpr,
09012 cfun_frame_layout.last_save_gpr);
09013 new_insn = emit_insn_before (new_insn, insn);
09014 INSN_ADDRESSES_NEW (new_insn, -1);
09015 }
09016
09017 remove_insn (insn);
09018 continue;
09019 }
09020
09021 if (cfun_frame_layout.first_save_gpr == -1
09022 && GET_CODE (PATTERN (insn)) == SET
09023 && GET_CODE (SET_SRC (PATTERN (insn))) == REG
09024 && (REGNO (SET_SRC (PATTERN (insn))) == BASE_REGNUM
09025 || (!TARGET_CPU_ZARCH
09026 && REGNO (SET_SRC (PATTERN (insn))) == RETURN_REGNUM))
09027 && GET_CODE (SET_DEST (PATTERN (insn))) == MEM)
09028 {
09029 set = PATTERN (insn);
09030 first = REGNO (SET_SRC (set));
09031 offset = const0_rtx;
09032 base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
09033 off = INTVAL (offset);
09034
09035 if (GET_CODE (base) != REG || off < 0)
09036 continue;
09037 if (REGNO (base) != STACK_POINTER_REGNUM
09038 && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
09039 continue;
09040
09041 remove_insn (insn);
09042 continue;
09043 }
09044
09045 if (GET_CODE (PATTERN (insn)) == PARALLEL
09046 && load_multiple_operation (PATTERN (insn), VOIDmode))
09047 {
09048 set = XVECEXP (PATTERN (insn), 0, 0);
09049 first = REGNO (SET_DEST (set));
09050 last = first + XVECLEN (PATTERN (insn), 0) - 1;
09051 offset = const0_rtx;
09052 base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
09053 off = INTVAL (offset);
09054
09055 if (GET_CODE (base) != REG || off < 0)
09056 continue;
09057 if (cfun_frame_layout.first_restore_gpr != -1
09058 && (cfun_frame_layout.first_restore_gpr < first
09059 || cfun_frame_layout.last_restore_gpr > last))
09060 continue;
09061 if (REGNO (base) != STACK_POINTER_REGNUM
09062 && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
09063 continue;
09064 if (first > BASE_REGNUM || last < BASE_REGNUM)
09065 continue;
09066
09067 if (cfun_frame_layout.first_restore_gpr != -1)
09068 {
09069 new_insn = restore_gprs (base,
09070 off + (cfun_frame_layout.first_restore_gpr
09071 - first) * UNITS_PER_WORD,
09072 cfun_frame_layout.first_restore_gpr,
09073 cfun_frame_layout.last_restore_gpr);
09074 new_insn = emit_insn_before (new_insn, insn);
09075 INSN_ADDRESSES_NEW (new_insn, -1);
09076 }
09077
09078 remove_insn (insn);
09079 continue;
09080 }
09081
09082 if (cfun_frame_layout.first_restore_gpr == -1
09083 && GET_CODE (PATTERN (insn)) == SET
09084 && GET_CODE (SET_DEST (PATTERN (insn))) == REG
09085 && (REGNO (SET_DEST (PATTERN (insn))) == BASE_REGNUM
09086 || (!TARGET_CPU_ZARCH
09087 && REGNO (SET_DEST (PATTERN (insn))) == RETURN_REGNUM))
09088 && GET_CODE (SET_SRC (PATTERN (insn))) == MEM)
09089 {
09090 set = PATTERN (insn);
09091 first = REGNO (SET_DEST (set));
09092 offset = const0_rtx;
09093 base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
09094 off = INTVAL (offset);
09095
09096 if (GET_CODE (base) != REG || off < 0)
09097 continue;
09098 if (REGNO (base) != STACK_POINTER_REGNUM
09099 && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
09100 continue;
09101
09102 remove_insn (insn);
09103 continue;
09104 }
09105 }
09106 }
09107
09108
09109
09110 static void
09111 s390_reorg (void)
09112 {
09113 bool pool_overflow = false;
09114
09115
09116
09117 split_all_insns_noflow ();
09118
09119
09120 cfun->machine->decomposed_literal_pool_addresses_ok_p = true;
09121
09122
09123
09124
09125
09126
09127
09128
09129
09130
09131
09132
09133
09134
09135
09136
09137
09138
09139
09140
09141
09142
09143
09144
09145
09146
09147
09148
09149
09150
09151
09152
09153
09154
09155 for (;;)
09156 {
09157 struct constant_pool *pool = NULL;
09158
09159
09160 if (!pool_overflow)
09161 {
09162 pool = s390_mainpool_start ();
09163 if (!pool)
09164 pool_overflow = true;
09165 }
09166
09167
09168 if (pool_overflow)
09169 pool = s390_chunkify_start ();
09170
09171
09172
09173
09174
09175 if (!TARGET_CPU_ZARCH && s390_split_branches ())
09176 {
09177 if (pool_overflow)
09178 s390_chunkify_cancel (pool);
09179 else
09180 s390_mainpool_cancel (pool);
09181
09182 continue;
09183 }
09184
09185
09186
09187 if (pool_overflow)
09188 s390_chunkify_finish (pool);
09189 else
09190 s390_mainpool_finish (pool);
09191
09192
09193 cfun->machine->split_branches_pending_p = false;
09194 break;
09195 }
09196
09197
09198 if (TARGET_CPU_ZARCH)
09199 {
09200 rtx insn, label, target;
09201
09202 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
09203 {
09204 label = s390_execute_label (insn);
09205 if (!label)
09206 continue;
09207
09208 gcc_assert (label != const0_rtx);
09209
09210 target = emit_label (XEXP (label, 0));
09211 INSN_ADDRESSES_NEW (target, -1);
09212
09213 target = emit_insn (s390_execute_target (insn));
09214 INSN_ADDRESSES_NEW (target, -1);
09215 }
09216 }
09217
09218
09219 s390_optimize_prologue ();
09220 }
09221
09222
09223
09224
09225 #undef TARGET_ASM_ALIGNED_HI_OP
09226 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
09227 #undef TARGET_ASM_ALIGNED_DI_OP
09228 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
09229 #undef TARGET_ASM_INTEGER
09230 #define TARGET_ASM_INTEGER s390_assemble_integer
09231
09232 #undef TARGET_ASM_OPEN_PAREN
09233 #define TARGET_ASM_OPEN_PAREN ""
09234
09235 #undef TARGET_ASM_CLOSE_PAREN
09236 #define TARGET_ASM_CLOSE_PAREN ""
09237
09238 #undef TARGET_DEFAULT_TARGET_FLAGS
09239 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_FUSED_MADD)
09240 #undef TARGET_HANDLE_OPTION
09241 #define TARGET_HANDLE_OPTION s390_handle_option
09242
09243 #undef TARGET_ENCODE_SECTION_INFO
09244 #define TARGET_ENCODE_SECTION_INFO s390_encode_section_info
09245
09246 #ifdef HAVE_AS_TLS
09247 #undef TARGET_HAVE_TLS
09248 #define TARGET_HAVE_TLS true
09249 #endif
09250 #undef TARGET_CANNOT_FORCE_CONST_MEM
09251 #define TARGET_CANNOT_FORCE_CONST_MEM s390_cannot_force_const_mem
09252
09253 #undef TARGET_DELEGITIMIZE_ADDRESS
09254 #define TARGET_DELEGITIMIZE_ADDRESS s390_delegitimize_address
09255
09256 #undef TARGET_RETURN_IN_MEMORY
09257 #define TARGET_RETURN_IN_MEMORY s390_return_in_memory
09258
09259 #undef TARGET_INIT_BUILTINS
09260 #define TARGET_INIT_BUILTINS s390_init_builtins
09261 #undef TARGET_EXPAND_BUILTIN
09262 #define TARGET_EXPAND_BUILTIN s390_expand_builtin
09263
09264 #undef TARGET_ASM_OUTPUT_MI_THUNK
09265 #define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk
09266 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
09267 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
09268
09269 #undef TARGET_SCHED_ADJUST_PRIORITY
09270 #define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority
09271 #undef TARGET_SCHED_ISSUE_RATE
09272 #define TARGET_SCHED_ISSUE_RATE s390_issue_rate
09273 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
09274 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD s390_first_cycle_multipass_dfa_lookahead
09275
09276 #undef TARGET_CANNOT_COPY_INSN_P
09277 #define TARGET_CANNOT_COPY_INSN_P s390_cannot_copy_insn_p
09278 #undef TARGET_RTX_COSTS
09279 #define TARGET_RTX_COSTS s390_rtx_costs
09280 #undef TARGET_ADDRESS_COST
09281 #define TARGET_ADDRESS_COST s390_address_cost
09282
09283 #undef TARGET_MACHINE_DEPENDENT_REORG
09284 #define TARGET_MACHINE_DEPENDENT_REORG s390_reorg
09285
09286 #undef TARGET_VALID_POINTER_MODE
09287 #define TARGET_VALID_POINTER_MODE s390_valid_pointer_mode
09288
09289 #undef TARGET_BUILD_BUILTIN_VA_LIST
09290 #define TARGET_BUILD_BUILTIN_VA_LIST s390_build_builtin_va_list
09291 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
09292 #define TARGET_GIMPLIFY_VA_ARG_EXPR s390_gimplify_va_arg
09293
09294 #undef TARGET_PROMOTE_FUNCTION_ARGS
09295 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
09296 #undef TARGET_PROMOTE_FUNCTION_RETURN
09297 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
09298 #undef TARGET_PASS_BY_REFERENCE
09299 #define TARGET_PASS_BY_REFERENCE s390_pass_by_reference
09300
09301 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
09302 #define TARGET_FUNCTION_OK_FOR_SIBCALL s390_function_ok_for_sibcall
09303
09304 #undef TARGET_FIXED_CONDITION_CODE_REGS
09305 #define TARGET_FIXED_CONDITION_CODE_REGS s390_fixed_condition_code_regs
09306
09307 #undef TARGET_CC_MODES_COMPATIBLE
09308 #define TARGET_CC_MODES_COMPATIBLE s390_cc_modes_compatible
09309
09310 #undef TARGET_INVALID_WITHIN_DOLOOP
09311 #define TARGET_INVALID_WITHIN_DOLOOP hook_constcharptr_rtx_null
09312
09313 #ifdef HAVE_AS_TLS
09314 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
09315 #define TARGET_ASM_OUTPUT_DWARF_DTPREL s390_output_dwarf_dtprel
09316 #endif
09317
09318 #ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
09319 #undef TARGET_MANGLE_FUNDAMENTAL_TYPE
09320 #define TARGET_MANGLE_FUNDAMENTAL_TYPE s390_mangle_fundamental_type
09321 #endif
09322
09323 #undef TARGET_SCALAR_MODE_SUPPORTED_P
09324 #define TARGET_SCALAR_MODE_SUPPORTED_P s390_scalar_mode_supported_p
09325
09326 struct gcc_target targetm = TARGET_INITIALIZER;
09327
09328 #include "gt-s390.h"