⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s390.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on IBM S/390 and zSeries   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.   Contributed by Hartmut Penner (hpenner@de.ibm.com) and                  Ulrich Weigand (uweigand@de.ibm.com).This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "config.h"#include "system.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"static bool s390_assemble_integer PARAMS ((rtx, unsigned int, int));static int s390_adjust_cost PARAMS ((rtx, rtx, rtx, int));static int s390_adjust_priority PARAMS ((rtx, int));static void s390_select_rtx_section PARAMS ((enum machine_mode, rtx, 					     unsigned HOST_WIDE_INT));static void s390_encode_section_info PARAMS ((tree, int));static const char *s390_strip_name_encoding PARAMS ((const char *));static bool s390_cannot_force_const_mem PARAMS ((rtx));static void s390_init_builtins PARAMS ((void));static rtx s390_expand_builtin PARAMS ((tree, rtx, rtx, 					enum machine_mode, int));static void s390_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,					  HOST_WIDE_INT, tree));#undef  TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"#undef  TARGET_ASM_ALIGNED_DI_OP#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"#undef  TARGET_ASM_INTEGER#define TARGET_ASM_INTEGER s390_assemble_integer#undef  TARGET_ASM_OPEN_PAREN#define TARGET_ASM_OPEN_PAREN ""#undef  TARGET_ASM_CLOSE_PAREN#define TARGET_ASM_CLOSE_PAREN ""#undef	TARGET_ASM_SELECT_RTX_SECTION#define	TARGET_ASM_SELECT_RTX_SECTION  s390_select_rtx_section#undef  TARGET_SCHED_ADJUST_COST#define TARGET_SCHED_ADJUST_COST s390_adjust_cost#undef  TARGET_SCHED_ADJUST_PRIORITY#define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority#undef	TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO s390_encode_section_info#undef  TARGET_STRIP_NAME_ENCODING#define TARGET_STRIP_NAME_ENCODING s390_strip_name_encoding#ifdef HAVE_AS_TLS#undef TARGET_HAVE_TLS#define TARGET_HAVE_TLS true#endif#undef TARGET_CANNOT_FORCE_CONST_MEM#define TARGET_CANNOT_FORCE_CONST_MEM s390_cannot_force_const_mem#undef  TARGET_INIT_BUILTINS#define TARGET_INIT_BUILTINS s390_init_builtins#undef  TARGET_EXPAND_BUILTIN#define TARGET_EXPAND_BUILTIN s390_expand_builtin#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_truestruct gcc_target targetm = TARGET_INITIALIZER;extern int reload_completed;/* The alias set for prologue/epilogue register save/restore.  */static int s390_sr_alias_set = 0;/* Save information from a "cmpxx" operation until the branch or scc is   emitted.  */rtx s390_compare_op0, s390_compare_op1;/* The encoding characters for the four TLS models present in ELF.  */static char const tls_model_chars[] = " GLil";/* 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;  int pointer;};/* Define the structure for the machine field in struct function.  */struct machine_function GTY(()){  /* Label of start of initial literal pool.  */  rtx literal_pool_label;  /* Set, if some of the fprs 8-15 need to be saved (64 bit abi).  */  int save_fprs_p;  /* Number of first and last gpr to be saved, restored.  */  int first_save_gpr;  int first_restore_gpr;  int last_save_gpr;  /* Size of stack frame.  */  HOST_WIDE_INT frame_size;  /* Some local-dynamic TLS symbol name.  */  const char *some_ld_name;};static int s390_match_ccmode_set PARAMS ((rtx, enum machine_mode));static int s390_branch_condition_mask PARAMS ((rtx));static const char *s390_branch_condition_mnemonic PARAMS ((rtx, int));static int check_mode PARAMS ((rtx, enum machine_mode *));static int general_s_operand PARAMS ((rtx, enum machine_mode, int));static int s390_decompose_address PARAMS ((rtx, struct s390_address *));static rtx get_thread_pointer PARAMS ((void));static rtx legitimize_tls_address PARAMS ((rtx, rtx));static const char *get_some_local_dynamic_name PARAMS ((void));static int get_some_local_dynamic_name_1 PARAMS ((rtx *, void *));static int reg_used_in_mem_p PARAMS ((int, rtx));static int addr_generation_dependency_p PARAMS ((rtx, rtx));static int s390_split_branches PARAMS ((rtx, bool *));static void find_constant_pool_ref PARAMS ((rtx, rtx *));static void replace_constant_pool_ref PARAMS ((rtx *, rtx, rtx));static int find_base_register_in_addr PARAMS ((struct s390_address *));static bool find_base_register_ref PARAMS ((rtx));static void replace_base_register_ref PARAMS ((rtx *, rtx));static void s390_optimize_prolog PARAMS ((int));static bool s390_fixup_clobbered_return_reg PARAMS ((rtx));static int find_unused_clobbered_reg PARAMS ((void));static void s390_frame_info PARAMS ((void));static rtx save_fpr PARAMS ((rtx, int, int));static rtx restore_fpr PARAMS ((rtx, int, int));static rtx save_gprs PARAMS ((rtx, int, int, int));static rtx restore_gprs PARAMS ((rtx, int, int, int));static int s390_function_arg_size PARAMS ((enum machine_mode, tree));static struct machine_function * s390_init_machine_status PARAMS ((void)); /* 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 ints390_match_ccmode_set (set, req_mode)     rtx set;     enum machine_mode req_mode;{  enum machine_mode set_mode;  if (GET_CODE (set) != SET)    abort ();  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 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:      abort ();    }   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.  */ ints390_match_ccmode (insn, req_mode)     rtx insn;     enum machine_mode req_mode;{  int i;  /* s390_tm_ccmode returns VOIDmode to indicate failure.  */  if (req_mode == VOIDmode)    return 0;  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 0;        }  return 1;}/* 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 (op1, op2, mixed)     rtx op1;     rtx op2;     int 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.  */  if (INTVAL (op2) == 0)    return CCTmode;  /* Selected bits all one: CC3.  */  if (INTVAL (op2) == INTVAL (op1))    return CCT3mode;  /* Exactly two bits selected, mixed zeroes and ones: CC1 or CC2.  */  if (mixed)    {      bit1 = exact_log2 (INTVAL (op2));      bit0 = exact_log2 (INTVAL (op1) ^ INTVAL (op2));      if (bit0 != -1 && bit1 != -1)        return bit0 > bit1 ? CCT1mode : CCT2mode;    }  return VOIDmode;}/* Given a comparison code OP (EQ, NE, etc.) and the operands    OP0 and OP1 of a COMPARE, return the mode to be used for the    comparison.  */enum machine_modes390_select_ccmode (code, op0, op1)      enum rtx_code code;     rtx op0;     rtx op1;{  switch (code)    {      case EQ:      case NE:	if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT	    && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op0, 1)), 'K')) 	  return CCAPmode;	if (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS	    || GET_CODE (op1) == NEG)	  return CCLmode;	if (GET_CODE (op0) == AND)	  {	    /* Check whether we can potentially do it via TM.  */	    enum machine_mode ccmode;	    ccmode = s390_tm_ccmode (XEXP (op0, 1), op1, 1);	    if (ccmode != VOIDmode)	      {		/* Relax CCTmode to CCZmode to allow fall-back to AND		   if that turns out to be beneficial.  */	        return ccmode == CCTmode ? CCZmode : ccmode;	      }	  }	if (register_operand (op0, HImode) 	    && GET_CODE (op1) == CONST_INT	    && (INTVAL (op1) == -1 || INTVAL (op1) == 65535))	  return CCT3mode;	if (register_operand (op0, QImode) 	    && GET_CODE (op1) == CONST_INT	    && (INTVAL (op1) == -1 || INTVAL (op1) == 255))	  return CCT3mode;	return CCZmode;      case LE:      case LT:      case GE:      case GT:	  if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT	      && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op0, 1)), 'K'))             {	      if (INTVAL (XEXP((op0), 1)) < 0)	        return CCANmode;              else	        return CCAPmode;	    }      case UNORDERED:      case ORDERED:      case UNEQ:      case UNLE:      case UNLT:      case UNGE:      case UNGT:      case LTGT:	if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)	    && GET_CODE (op1) != CONST_INT)	  return CCSRmode;	return CCSmode;      case LTU:      case GEU:	if (GET_CODE (op0) == PLUS)	  return CCL1mode;	if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)	    && GET_CODE (op1) != CONST_INT)	  return CCURmode;	return CCUmode;      case LEU:      case GTU:	if (GET_CODE (op0) == MINUS)	  return CCL2mode;	if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)	    && GET_CODE (op1) != CONST_INT)	  return CCURmode;	return CCUmode;      default:	abort ();    }}/* Return branch condition mask to implement a branch    specified by CODE.  */static ints390_branch_condition_mask (code)    rtx code;{   const int CC0 = 1 << 3;  const int CC1 = 1 << 2;  const int CC2 = 1 << 1;  const int CC3 = 1 << 0;  if (GET_CODE (XEXP (code, 0)) != REG      || REGNO (XEXP (code, 0)) != CC_REGNUM      || XEXP (code, 1) != const0_rtx)    abort ();  switch (GET_MODE (XEXP (code, 0)))    {    case CCZmode:      switch (GET_CODE (code))        {        case EQ:	return CC0;	case NE:	return CC1 | CC2 | CC3;	default:	  abort ();        }      break;    case CCT1mode:      switch (GET_CODE (code))        {        case EQ:	return CC1;	case NE:	return CC0 | CC2 | CC3;	default:	  abort ();        }      break;    case CCT2mode:      switch (GET_CODE (code))        {        case EQ:	return CC2;	case NE:	return CC0 | CC1 | CC3;	default:	  abort ();        }      break;    case CCT3mode:      switch (GET_CODE (code))        {        case EQ:	return CC3;	case NE:	return CC0 | CC1 | CC2;	default:	  abort ();        }      break;    case CCLmode:      switch (GET_CODE (code))        {        case EQ:	return CC0 | CC2;	case NE:	return CC1 | CC3;	default:	  abort ();        }      break;    case CCL1mode:      switch (GET_CODE (code))        {	case LTU:	return CC2 | CC3;  /* carry */	case GEU:	return CC0 | CC1;  /* no carry */	default:	  abort ();        }      break;    case CCL2mode:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -