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

📄 stormy16.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Xstormy16 target functions.   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005   Free Software Foundation, Inc.   Contributed by Red Hat, Inc.This file is part of GCC.GCC 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.GCC 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 GCC; see the file COPYING.  If not, write tothe Free Software Foundation, 51 Franklin Street, Fifth Floor,Boston, MA 02110-1301, USA.  */#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-flags.h"#include "output.h"#include "insn-attr.h"#include "flags.h"#include "recog.h"#include "toplev.h"#include "obstack.h"#include "tree.h"#include "expr.h"#include "optabs.h"#include "except.h"#include "function.h"#include "target.h"#include "target-def.h"#include "tm_p.h"#include "langhooks.h"#include "tree-gimple.h"static rtx emit_addhi3_postreload (rtx, rtx, rtx);static void xstormy16_asm_out_constructor (rtx, int);static void xstormy16_asm_out_destructor (rtx, int);static void xstormy16_asm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,					   HOST_WIDE_INT, tree);static void xstormy16_init_builtins (void);static rtx xstormy16_expand_builtin (tree, rtx, rtx, enum machine_mode, int);static bool xstormy16_rtx_costs (rtx, int, int, int *);static int xstormy16_address_cost (rtx);static bool xstormy16_return_in_memory (tree, tree);/* Define the information needed to generate branch and scc insns.  This is   stored from the compare operation.  */struct rtx_def * xstormy16_compare_op0;struct rtx_def * xstormy16_compare_op1;/* Compute a (partial) cost for rtx X.  Return true if the complete   cost has been computed, and false if subexpressions should be   scanned.  In either case, *TOTAL contains the cost result.  */static boolxstormy16_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,		     int *total){  switch (code)    {    case CONST_INT:      if (INTVAL (x) < 16 && INTVAL (x) >= 0)        *total = COSTS_N_INSNS (1) / 2;      else if (INTVAL (x) < 256 && INTVAL (x) >= 0)	*total = COSTS_N_INSNS (1);      else	*total = COSTS_N_INSNS (2);      return true;    case CONST_DOUBLE:    case CONST:    case SYMBOL_REF:    case LABEL_REF:      *total = COSTS_N_INSNS(2);      return true;    case MULT:      *total = COSTS_N_INSNS (35 + 6);      return true;    case DIV:      *total = COSTS_N_INSNS (51 - 6);      return true;    default:      return false;    }}static intxstormy16_address_cost (rtx x){  return (GET_CODE (x) == CONST_INT ? 2	  : GET_CODE (x) == PLUS ? 7	  : 5);}/* Branches are handled as follows:   1. HImode compare-and-branches.  The machine supports these      natively, so the appropriate pattern is emitted directly.   2. SImode EQ and NE.  These are emitted as pairs of HImode      compare-and-branches.         3. SImode LT, GE, LTU and GEU.  These are emitted as a sequence      of a SImode subtract followed by a branch (not a compare-and-branch),      like this:      sub      sbc      blt   4. SImode GT, LE, GTU, LEU.  These are emitted as a sequence like:      sub      sbc      blt      or      bne*//* Emit a branch of kind CODE to location LOC.  */voidxstormy16_emit_cbranch (enum rtx_code code, rtx loc){  rtx op0 = xstormy16_compare_op0;  rtx op1 = xstormy16_compare_op1;  rtx condition_rtx, loc_ref, branch, cy_clobber;  rtvec vec;  enum machine_mode mode;    mode = GET_MODE (op0);  gcc_assert (mode == HImode || mode == SImode);  if (mode == SImode      && (code == GT || code == LE || code == GTU || code == LEU))    {      int unsigned_p = (code == GTU || code == LEU);      int gt_p = (code == GT || code == GTU);      rtx lab = NULL_RTX;            if (gt_p)	lab = gen_label_rtx ();      xstormy16_emit_cbranch (unsigned_p ? LTU : LT, gt_p ? lab : loc);      /* This should be generated as a comparison against the temporary	 created by the previous insn, but reload can't handle that.  */      xstormy16_emit_cbranch (gt_p ? NE : EQ, loc);      if (gt_p)	emit_label (lab);      return;    }  else if (mode == SImode 	   && (code == NE || code == EQ)	   && op1 != const0_rtx)    {      rtx lab = NULL_RTX;      int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;      int i;            if (code == EQ)	lab = gen_label_rtx ();            for (i = 0; i < num_words - 1; i++)	{	  xstormy16_compare_op0 = simplify_gen_subreg (word_mode, op0, mode, 						      i * UNITS_PER_WORD);	  xstormy16_compare_op1 = simplify_gen_subreg (word_mode, op1, mode, 						      i * UNITS_PER_WORD);	  xstormy16_emit_cbranch (NE, code == EQ ? lab : loc);	}      xstormy16_compare_op0 = simplify_gen_subreg (word_mode, op0, mode, 						  i * UNITS_PER_WORD);      xstormy16_compare_op1 = simplify_gen_subreg (word_mode, op1, mode, 						  i * UNITS_PER_WORD);      xstormy16_emit_cbranch (code, loc);      if (code == EQ)	emit_label (lab);      return;    }  /* We can't allow reload to try to generate any reload after a branch,     so when some register must match we must make the temporary ourselves.  */  if (mode != HImode)    {      rtx tmp;      tmp = gen_reg_rtx (mode);      emit_move_insn (tmp, op0);      op0 = tmp;    }  condition_rtx = gen_rtx_fmt_ee (code, mode, op0, op1);  loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);  branch = gen_rtx_SET (VOIDmode, pc_rtx,			gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,					      loc_ref, pc_rtx));  cy_clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (BImode));  if (mode == HImode)    vec = gen_rtvec (2, branch, cy_clobber);  else if (code == NE || code == EQ)    vec = gen_rtvec (2, branch, gen_rtx_CLOBBER (VOIDmode, op0));  else    {      rtx sub;#if 0      sub = gen_rtx_SET (VOIDmode, op0, gen_rtx_MINUS (SImode, op0, op1));#else      sub = gen_rtx_CLOBBER (SImode, op0);#endif      vec = gen_rtvec (3, branch, sub, cy_clobber);    }  emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec));}/* Take a SImode conditional branch, one of GT/LE/GTU/LEU, and split   the arithmetic operation.  Most of the work is done by   xstormy16_expand_arith.  */voidxstormy16_split_cbranch (enum machine_mode mode, rtx label, rtx comparison,			 rtx dest, rtx carry){  rtx op0 = XEXP (comparison, 0);  rtx op1 = XEXP (comparison, 1);  rtx seq, last_insn;  rtx compare;    start_sequence ();  xstormy16_expand_arith (mode, COMPARE, dest, op0, op1, carry);  seq = get_insns ();  end_sequence ();  gcc_assert (INSN_P (seq));  last_insn = seq;  while (NEXT_INSN (last_insn) != NULL_RTX)    last_insn = NEXT_INSN (last_insn);  compare = SET_SRC (XVECEXP (PATTERN (last_insn), 0, 0));  PUT_CODE (XEXP (compare, 0), GET_CODE (comparison));  XEXP (compare, 1) = gen_rtx_LABEL_REF (VOIDmode, label);  emit_insn (seq);}/* Return the string to output a conditional branch to LABEL, which is   the operand number of the label.   OP is the conditional expression, or NULL for branch-always.   REVERSED is nonzero if we should reverse the sense of the comparison.   INSN is the insn.  */char *xstormy16_output_cbranch_hi (rtx op, const char *label, int reversed, rtx insn){  static char string[64];  int need_longbranch = (op != NULL_RTX			 ? get_attr_length (insn) == 8			 : get_attr_length (insn) == 4);  int really_reversed = reversed ^ need_longbranch;  const char *ccode;  const char *template;  const char *operands;  enum rtx_code code;    if (! op)    {      if (need_longbranch)	ccode = "jmpf";      else	ccode = "br";      sprintf (string, "%s %s", ccode, label);      return string;    }  code = GET_CODE (op);  if (GET_CODE (XEXP (op, 0)) != REG)    {      code = swap_condition (code);      operands = "%3,%2";    }  else      operands = "%2,%3";  /* Work out which way this really branches.  */  if (really_reversed)    code = reverse_condition (code);  switch (code)    {    case EQ:   ccode = "z";   break;    case NE:   ccode = "nz";  break;    case GE:   ccode = "ge";  break;    case LT:   ccode = "lt";  break;    case GT:   ccode = "gt";  break;    case LE:   ccode = "le";  break;    case GEU:  ccode = "nc";  break;    case LTU:  ccode = "c";   break;    case GTU:  ccode = "hi";  break;    case LEU:  ccode = "ls";  break;          default:      gcc_unreachable ();    }  if (need_longbranch)    template = "b%s %s,.+8 | jmpf %s";  else    template = "b%s %s,%s";  sprintf (string, template, ccode, operands, label);    return string;}/* Return the string to output a conditional branch to LABEL, which is   the operand number of the label, but suitable for the tail of a   SImode branch.   OP is the conditional expression (OP is never NULL_RTX).   REVERSED is nonzero if we should reverse the sense of the comparison.   INSN is the insn.  */char *xstormy16_output_cbranch_si (rtx op, const char *label, int reversed, rtx insn){  static char string[64];  int need_longbranch = get_attr_length (insn) >= 8;  int really_reversed = reversed ^ need_longbranch;  const char *ccode;  const char *template;  char prevop[16];  enum rtx_code code;    code = GET_CODE (op);  /* Work out which way this really branches.  */  if (really_reversed)    code = reverse_condition (code);  switch (code)    {    case EQ:   ccode = "z";   break;    case NE:   ccode = "nz";  break;    case GE:   ccode = "ge";  break;    case LT:   ccode = "lt";  break;    case GEU:  ccode = "nc";  break;    case LTU:  ccode = "c";   break;      /* The missing codes above should never be generated.  */    default:      gcc_unreachable ();    }  switch (code)    {    case EQ: case NE:      {	int regnum;		gcc_assert (GET_CODE (XEXP (op, 0)) == REG);      	regnum = REGNO (XEXP (op, 0));	sprintf (prevop, "or %s,%s", reg_names[regnum], reg_names[regnum+1]);      }      break;    case GE: case LT: case GEU: case LTU:      strcpy (prevop, "sbc %2,%3");      break;    default:      gcc_unreachable ();    }  if (need_longbranch)    template = "%s | b%s .+6 | jmpf %s";  else    template = "%s | b%s %s";  sprintf (string, template, prevop, ccode, label);    return string;}/* Many machines have some registers that cannot be copied directly to or from   memory or even from other types of registers.  An example is the `MQ'   register, which on most machines, can only be copied to or from general   registers, but not memory.  Some machines allow copying all registers to and   from memory, but require a scratch register for stores to some memory   locations (e.g., those with symbolic address on the RT, and those with   certain symbolic address on the SPARC when compiling PIC).  In some cases,   both an intermediate and a scratch register are required.   You should define these macros to indicate to the reload phase that it may   need to allocate at least one register for a reload in addition to the   register to contain the data.  Specifically, if copying X to a register   CLASS in MODE requires an intermediate register, you should define   `SECONDARY_INPUT_RELOAD_CLASS' to return the largest register class all of   whose registers can be used as intermediate registers or scratch registers.   If copying a register CLASS in MODE to X requires an intermediate or scratch   register, `SECONDARY_OUTPUT_RELOAD_CLASS' should be defined to return the   largest register class required.  If the requirements for input and output   reloads are the same, the macro `SECONDARY_RELOAD_CLASS' should be used   instead of defining both macros identically.   The values returned by these macros are often `GENERAL_REGS'.  Return   `NO_REGS' if no spare register is needed; i.e., if X can be directly copied   to or from a register of CLASS in MODE without requiring a scratch register.   Do not define this macro if it would always return `NO_REGS'.   If a scratch register is required (either with or without an intermediate

⌨️ 快捷键说明

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