📄 s390.c
字号:
/* Subroutines used for code generation on IBM S/390 and zSeries Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Hartmut Penner (hpenner@de.ibm.com) and Ulrich Weigand (uweigand@de.ibm.com).This file is part of GCC.GCC is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.GCC is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public Licensealong with GCC; see the file COPYING. If not, write to the FreeSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA02110-1301, USA. */#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "rtl.h"#include "tree.h"#include "tm_p.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "output.h"#include "insn-attr.h"#include "flags.h"#include "except.h"#include "function.h"#include "recog.h"#include "expr.h"#include "reload.h"#include "toplev.h"#include "basic-block.h"#include "integrate.h"#include "ggc.h"#include "target.h"#include "target-def.h"#include "debug.h"#include "langhooks.h"#include "optabs.h"#include "tree-gimple.h"/* Define the specific costs for a given cpu. */struct processor_costs { /* multiplication */ const int m; /* cost of an M instruction. */ const int mghi; /* cost of an MGHI instruction. */ const int mh; /* cost of an MH instruction. */ const int mhi; /* cost of an MHI instruction. */ const int ml; /* cost of an ML instruction. */ const int mr; /* cost of an MR instruction. */ const int ms; /* cost of an MS instruction. */ const int msg; /* cost of an MSG instruction. */ const int msgf; /* cost of an MSGF instruction. */ const int msgfr; /* cost of an MSGFR instruction. */ const int msgr; /* cost of an MSGR instruction. */ const int msr; /* cost of an MSR instruction. */ const int mult_df; /* cost of multiplication in DFmode. */ const int mxbr; /* square root */ const int sqxbr; /* cost of square root in TFmode. */ const int sqdbr; /* cost of square root in DFmode. */ const int sqebr; /* cost of square root in SFmode. */ /* multiply and add */ const int madbr; /* cost of multiply and add in DFmode. */ const int maebr; /* cost of multiply and add in SFmode. */ /* division */ const int dxbr; const int dxr; const int ddbr; const int ddr; const int debr; const int der; const int dlgr; const int dlr; const int dr; const int dsgfr; const int dsgr;};const struct processor_costs *s390_cost;static conststruct processor_costs z900_cost = { COSTS_N_INSNS (5), /* M */ COSTS_N_INSNS (10), /* MGHI */ COSTS_N_INSNS (5), /* MH */ COSTS_N_INSNS (4), /* MHI */ COSTS_N_INSNS (5), /* ML */ COSTS_N_INSNS (5), /* MR */ COSTS_N_INSNS (4), /* MS */ COSTS_N_INSNS (15), /* MSG */ COSTS_N_INSNS (7), /* MSGF */ COSTS_N_INSNS (7), /* MSGFR */ COSTS_N_INSNS (10), /* MSGR */ COSTS_N_INSNS (4), /* MSR */ COSTS_N_INSNS (7), /* multiplication in DFmode */ COSTS_N_INSNS (13), /* MXBR */ COSTS_N_INSNS (136), /* SQXBR */ COSTS_N_INSNS (44), /* SQDBR */ COSTS_N_INSNS (35), /* SQEBR */ COSTS_N_INSNS (18), /* MADBR */ COSTS_N_INSNS (13), /* MAEBR */ COSTS_N_INSNS (134), /* DXBR */ COSTS_N_INSNS (135), /* DXR */ COSTS_N_INSNS (30), /* DDBR */ COSTS_N_INSNS (30), /* DDR */ COSTS_N_INSNS (27), /* DEBR */ COSTS_N_INSNS (26), /* DER */ COSTS_N_INSNS (220), /* DLGR */ COSTS_N_INSNS (34), /* DLR */ COSTS_N_INSNS (34), /* DR */ COSTS_N_INSNS (32), /* DSGFR */ COSTS_N_INSNS (32), /* DSGR */};static conststruct processor_costs z990_cost = { COSTS_N_INSNS (4), /* M */ COSTS_N_INSNS (2), /* MGHI */ COSTS_N_INSNS (2), /* MH */ COSTS_N_INSNS (2), /* MHI */ COSTS_N_INSNS (4), /* ML */ COSTS_N_INSNS (4), /* MR */ COSTS_N_INSNS (5), /* MS */ COSTS_N_INSNS (6), /* MSG */ COSTS_N_INSNS (4), /* MSGF */ COSTS_N_INSNS (4), /* MSGFR */ COSTS_N_INSNS (4), /* MSGR */ COSTS_N_INSNS (4), /* MSR */ COSTS_N_INSNS (1), /* multiplication in DFmode */ COSTS_N_INSNS (28), /* MXBR */ COSTS_N_INSNS (130), /* SQXBR */ COSTS_N_INSNS (66), /* SQDBR */ COSTS_N_INSNS (38), /* SQEBR */ COSTS_N_INSNS (1), /* MADBR */ COSTS_N_INSNS (1), /* MAEBR */ COSTS_N_INSNS (60), /* DXBR */ COSTS_N_INSNS (72), /* DXR */ COSTS_N_INSNS (40), /* DDBR */ COSTS_N_INSNS (44), /* DDR */ COSTS_N_INSNS (26), /* DDBR */ COSTS_N_INSNS (28), /* DER */ COSTS_N_INSNS (176), /* DLGR */ COSTS_N_INSNS (31), /* DLR */ COSTS_N_INSNS (31), /* DR */ COSTS_N_INSNS (31), /* DSGFR */ COSTS_N_INSNS (31), /* DSGR */};static conststruct processor_costs z9_109_cost = { COSTS_N_INSNS (4), /* M */ COSTS_N_INSNS (2), /* MGHI */ COSTS_N_INSNS (2), /* MH */ COSTS_N_INSNS (2), /* MHI */ COSTS_N_INSNS (4), /* ML */ COSTS_N_INSNS (4), /* MR */ COSTS_N_INSNS (5), /* MS */ COSTS_N_INSNS (6), /* MSG */ COSTS_N_INSNS (4), /* MSGF */ COSTS_N_INSNS (4), /* MSGFR */ COSTS_N_INSNS (4), /* MSGR */ COSTS_N_INSNS (4), /* MSR */ COSTS_N_INSNS (1), /* multiplication in DFmode */ COSTS_N_INSNS (28), /* MXBR */ COSTS_N_INSNS (130), /* SQXBR */ COSTS_N_INSNS (66), /* SQDBR */ COSTS_N_INSNS (38), /* SQEBR */ COSTS_N_INSNS (1), /* MADBR */ COSTS_N_INSNS (1), /* MAEBR */ COSTS_N_INSNS (60), /* DXBR */ COSTS_N_INSNS (72), /* DXR */ COSTS_N_INSNS (40), /* DDBR */ COSTS_N_INSNS (37), /* DDR */ COSTS_N_INSNS (26), /* DDBR */ COSTS_N_INSNS (28), /* DER */ COSTS_N_INSNS (30), /* DLGR */ COSTS_N_INSNS (23), /* DLR */ COSTS_N_INSNS (23), /* DR */ COSTS_N_INSNS (24), /* DSGFR */ COSTS_N_INSNS (24), /* DSGR */};extern int reload_completed;/* Save information from a "cmpxx" operation until the branch or scc is emitted. */rtx s390_compare_op0, s390_compare_op1;/* Save the result of a compare_and_swap until the branch or scc is emitted. */rtx s390_compare_emitted = NULL_RTX;/* Structure used to hold the components of a S/390 memory address. A legitimate address on S/390 is of the general form base + index + displacement where any of the components is optional. base and index are registers of the class ADDR_REGS, displacement is an unsigned 12-bit immediate constant. */struct s390_address{ rtx base; rtx indx; rtx disp; bool pointer; bool literal_pool;};/* Which cpu are we tuning for. */enum processor_type s390_tune = PROCESSOR_max;enum processor_flags s390_tune_flags;/* Which instruction set architecture to use. */enum processor_type s390_arch;enum processor_flags s390_arch_flags;HOST_WIDE_INT s390_warn_framesize = 0;HOST_WIDE_INT s390_stack_size = 0;HOST_WIDE_INT s390_stack_guard = 0;/* The following structure is embedded in the machine specific part of struct function. */struct s390_frame_layout GTY (()){ /* Offset within stack frame. */ HOST_WIDE_INT gprs_offset; HOST_WIDE_INT f0_offset; HOST_WIDE_INT f4_offset; HOST_WIDE_INT f8_offset; HOST_WIDE_INT backchain_offset; /* Number of first and last gpr where slots in the register save area are reserved for. */ int first_save_gpr_slot; int last_save_gpr_slot; /* Number of first and last gpr to be saved, restored. */ int first_save_gpr; int first_restore_gpr; int last_save_gpr; int last_restore_gpr; /* Bits standing for floating point registers. Set, if the respective register has to be saved. Starting with reg 16 (f0) at the rightmost bit. Bit 15 - 8 7 6 5 4 3 2 1 0 fpr 15 - 8 7 5 3 1 6 4 2 0 reg 31 - 24 23 22 21 20 19 18 17 16 */ unsigned int fpr_bitmap; /* Number of floating point registers f8-f15 which must be saved. */ int high_fprs; /* Set if return address needs to be saved. This flag is set by s390_return_addr_rtx if it could not use the initial value of r14 and therefore depends on r14 saved to the stack. */ bool save_return_addr_p; /* Size of stack frame. */ HOST_WIDE_INT frame_size;};/* Define the structure for the machine field in struct function. */struct machine_function GTY(()){ struct s390_frame_layout frame_layout; /* Literal pool base register. */ rtx base_reg; /* True if we may need to perform branch splitting. */ bool split_branches_pending_p; /* True during final stage of literal pool processing. */ bool decomposed_literal_pool_addresses_ok_p; /* Some local-dynamic TLS symbol name. */ const char *some_ld_name; bool has_landing_pad_p;};/* Few accessor macros for struct cfun->machine->s390_frame_layout. */#define cfun_frame_layout (cfun->machine->frame_layout)#define cfun_save_high_fprs_p (!!cfun_frame_layout.high_fprs)#define cfun_gprs_save_area_size ((cfun_frame_layout.last_save_gpr_slot - \ cfun_frame_layout.first_save_gpr_slot + 1) * UNITS_PER_WORD)#define cfun_set_fpr_bit(BITNUM) (cfun->machine->frame_layout.fpr_bitmap |= \ (1 << (BITNUM)))#define cfun_fpr_bit_p(BITNUM) (!!(cfun->machine->frame_layout.fpr_bitmap & \ (1 << (BITNUM))))/* Number of GPRs and FPRs used for argument passing. */#define GP_ARG_NUM_REG 5#define FP_ARG_NUM_REG (TARGET_64BIT? 4 : 2)/* A couple of shortcuts. */#define CONST_OK_FOR_J(x) \ CONST_OK_FOR_CONSTRAINT_P((x), 'J', "J")#define CONST_OK_FOR_K(x) \ CONST_OK_FOR_CONSTRAINT_P((x), 'K', "K")#define CONST_OK_FOR_Os(x) \ CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Os")#define CONST_OK_FOR_Op(x) \ CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Op")#define CONST_OK_FOR_On(x) \ CONST_OK_FOR_CONSTRAINT_P((x), 'O', "On")/* Set the has_landing_pad_p flag in struct machine_function to VALUE. */voids390_set_has_landing_pad_p (bool value){ cfun->machine->has_landing_pad_p = value;}/* If two condition code modes are compatible, return a condition code mode which is compatible with both. Otherwise, return VOIDmode. */static enum machine_modes390_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2){ if (m1 == m2) return m1; switch (m1) { case CCZmode: if (m2 == CCUmode || m2 == CCTmode || m2 == CCZ1mode || m2 == CCSmode || m2 == CCSRmode || m2 == CCURmode) return m2; return VOIDmode; case CCSmode: case CCUmode: case CCTmode: case CCSRmode: case CCURmode: case CCZ1mode: if (m2 == CCZmode) return m1; return VOIDmode; default: return VOIDmode; } return VOIDmode;}/* Return true if SET either doesn't set the CC register, or else the source and destination have matching CC modes and that CC mode is at least as constrained as REQ_MODE. */static bools390_match_ccmode_set (rtx set, enum machine_mode req_mode){ enum machine_mode set_mode; gcc_assert (GET_CODE (set) == SET); if (GET_CODE (SET_DEST (set)) != REG || !CC_REGNO_P (REGNO (SET_DEST (set)))) return 1; set_mode = GET_MODE (SET_DEST (set)); switch (set_mode) { case CCSmode: case CCSRmode: case CCUmode: case CCURmode: case CCLmode: case CCL1mode: case CCL2mode: case CCL3mode: case CCT1mode: case CCT2mode: case CCT3mode: if (req_mode != set_mode) return 0; break; case CCZmode: if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode && req_mode != CCSRmode && req_mode != CCURmode) return 0; break; case CCAPmode: case CCANmode: if (req_mode != CCAmode) return 0; break; default: gcc_unreachable (); } return (GET_MODE (SET_SRC (set)) == set_mode);}/* Return true if every SET in INSN that sets the CC register has source and destination with matching CC modes and that CC mode is at least as constrained as REQ_MODE. If REQ_MODE is VOIDmode, always return false. */bools390_match_ccmode (rtx insn, enum machine_mode req_mode){ int i; /* s390_tm_ccmode returns VOIDmode to indicate failure. */ if (req_mode == VOIDmode) return false; if (GET_CODE (PATTERN (insn)) == SET) return s390_match_ccmode_set (PATTERN (insn), req_mode); if (GET_CODE (PATTERN (insn)) == PARALLEL) for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) { rtx set = XVECEXP (PATTERN (insn), 0, i); if (GET_CODE (set) == SET) if (!s390_match_ccmode_set (set, req_mode)) return false; } return true;}/* If a test-under-mask instruction can be used to implement (compare (and ... OP1) OP2), return the CC mode required to do that. Otherwise, return VOIDmode. MIXED is true if the instruction can distinguish between CC1 and CC2 for mixed selected bits (TMxx), it is false if the instruction cannot (TM). */enum machine_modes390_tm_ccmode (rtx op1, rtx op2, bool mixed){ int bit0, bit1; /* ??? Fixme: should work on CONST_DOUBLE as well. */ if (GET_CODE (op1) != CONST_INT || GET_CODE (op2) != CONST_INT) return VOIDmode; /* Selected bits all zero: CC0. e.g.: int a; if ((a & (16 + 128)) == 0) */ if (INTVAL (op2) == 0) return CCTmode; /* Selected bits all one: CC3. e.g.: int a; if ((a & (16 + 128)) == 16 + 128) */ if (INTVAL (op2) == INTVAL (op1)) return CCT3mode; /* Exactly two bits selected, mixed zeroes and ones: CC1 or CC2. e.g.: int a; if ((a & (16 + 128)) == 16) -> CCT1 if ((a & (16 + 128)) == 128) -> CCT2 */ if (mixed) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -