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

📄 stormy16.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Xstormy16 target functions.   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004   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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, 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;/* Return 1 if this is a LT, GE, LTU, or GEU operator.  */intxstormy16_ineqsi_operator (register rtx op, enum machine_mode mode){  enum rtx_code code = GET_CODE (op);    return ((mode == VOIDmode || GET_MODE (op) == mode)	  && (code == LT || code == GE || code == LTU || code == GEU));}/* Return 1 if this is an EQ or NE operator.  */intequality_operator (register rtx op, enum machine_mode mode){  return ((mode == VOIDmode || GET_MODE (op) == mode)	  && (GET_CODE (op) == EQ || GET_CODE (op) == NE));}/* Return 1 if this is a comparison operator but not an EQ or NE operator.  */intinequality_operator (register rtx op, enum machine_mode mode){  return comparison_operator (op, mode) && ! equality_operator (op, mode);}/* 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);  if (mode != HImode && mode != SImode)    abort ();  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 ();  if (! INSN_P (seq))    abort ();  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:      abort ();    }  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:      abort ();    }  switch (code)    {    case EQ: case NE:      {	int regnum;		if (GET_CODE (XEXP (op, 0)) != REG)	  abort ();      	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:      abort ();    }  if (need_longbranch)    template = "%s | b%s .+6 | jmpf %s";  else    template = "%s | b%s %s";  sprintf (string, template, prevop, ccode, label);    return string;}

⌨️ 快捷键说明

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