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

📄 convex.c

📁 早期freebsd实现
💻 C
字号:
/* Subroutines for insn-output.c for Convex.   Copyright (C) 1989,1991 Free Software Foundation, Inc.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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */#include "config.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"/* Boolean to keep track of whether the current section is .text or not.   Used by .align handler in convex.h. */int current_section_is_text;/* set_cmp saves the operands of a "cmp" insn, along with the type character * to be used in the compare instruction. * * gen_cmp finds out what comparison is to be performed and outputs the * necessary instructions, e.g. *    "eq.w a1,a2\;jbra.t L5" * for (cmpsi a1 a2) (beq L5)  */ static rtx xop0, xop1;static char typech, regch;char *set_cmp (op0, op1, typechr)     rtx op0, op1;     char typechr;{  xop0 = op0;  xop1 = op1;  typech = typechr;  if (GET_CODE (op0) == REG)    regch = A_REGNO_P (REGNO (op0)) ? 'a' : 's';  else if (GET_CODE (op1) == REG)    regch = A_REGNO_P (REGNO (op1)) ? 'a' : 's';  else abort ();  return "";}char *gen_cmp (label, cmpop, tf)     rtx label;     char *cmpop;     char tf;{  char buf[80];  char revop[4];  rtx ops[3];  ops[2] = label;  /* Constant must be first; swap operands if necessary.     If lt, le, ltu, leu are swapped, change to le, lt, leu, ltu     and reverse the sense of the jump. */  if (CONSTANT_P (xop1))    {      ops[0] = xop1;      ops[1] = xop0;      if (cmpop[0] == 'l')	{	  bcopy (cmpop, revop, sizeof revop);	  revop[1] ^= 'e' ^ 't';	  tf ^= 't' ^ 'f';	  cmpop = revop;	}    }  else    {      ops[0] = xop0;      ops[1] = xop1;    }  sprintf (buf, "%s.%c %%0,%%1\n\tjbr%c.%c %%l2", cmpop, typech, regch, tf);  output_asm_insn (buf, ops);  return "";}/* Routines to separate CONST_DOUBLEs into component parts. */intconst_double_high_int (x)     rtx x;{  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)    return CONST_DOUBLE_LOW (x);  else    return CONST_DOUBLE_HIGH (x);}intconst_double_low_int (x)     rtx x;{  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)    return CONST_DOUBLE_HIGH (x);  else    return CONST_DOUBLE_LOW (x);}/* Return the number of args in the call insn X. */static intcall_num_args (x)     rtx x;{  if (GET_CODE (x) == CALL)    return INTVAL (x->fld[1].rtx);  if (GET_CODE (x) == SET)    return call_num_args (SET_SRC (x));  abort ();}/* Scan forward from a call to decide whether we need to reload AP   from 12(FP) after it.  We need to if there can be a reference to   arg_pointer_rtx before the next call, which will clobber AP.   Look forward in the instruction list until encountering a call   (don't need the load), or a reference to AP (do need it), or   a jump (don't know, do the load).  */static intap_reload_needed (insn)     rtx insn;{  for (;;)    {      insn = NEXT_INSN (insn);      switch (GET_CODE (insn))	{	case JUMP_INSN:	  /* Basic block ends.  If return, no AP needed, else assume it is. */	  return GET_CODE (PATTERN (insn)) != RETURN;	case CALL_INSN:	  /* A subsequent call.  AP isn't needed unless the call itself	     requires it.  But zero-arg calls don't clobber AP, so	     don't terminate the search in that case. */	  if (reg_mentioned_p (arg_pointer_rtx, PATTERN (insn)))	    return 1;	  if (! TARGET_ARGCOUNT && call_num_args (PATTERN (insn)) == 0)	    break;	  return 0;	case BARRIER:	  /* Barrier, don't need AP. */	  return 0;	case INSN:	  /* Other insn may need AP; if not, keep looking. */	  if (reg_mentioned_p (arg_pointer_rtx, PATTERN (insn)))	    return 1;	}    }}/* Output the insns needed to do a call. */char *output_call (insn, address, argcount)    rtx insn, address, argcount;{  int set_ap = TARGET_ARGCOUNT || argcount != const0_rtx;  /* If AP is used by the call address, evaluate the address into a temp. */  if (reg_mentioned_p (arg_pointer_rtx, address))    if (set_ap)      {	address = XEXP (address, 0);	output_asm_insn ("ld.w %0,a1", &address);	address = gen_rtx (MEM, QImode, gen_rtx (REG, Pmode, 9));      }  /* If there are args, point AP to them. */  if (set_ap)    output_asm_insn ("mov sp,ap");  /* If we are passing an arg count, convert it to words and push it. */  if (TARGET_ARGCOUNT)    {      argcount = gen_rtx (CONST_INT, VOIDmode, (INTVAL (argcount) + 3) / 4);      output_asm_insn ("pshea %a0", &argcount);    }  /* The call. */  output_asm_insn ("calls %0", &address);  /* If we clobbered AP, reload it if it is live. */  if (set_ap)    if (ap_reload_needed (insn))      output_asm_insn ("ld.w 12(fp),ap");  /* If we pushed an arg count, pop it and the args. */  if (TARGET_ARGCOUNT)    {      argcount = gen_rtx (CONST_INT, VOIDmode, INTVAL (argcount) * 4 + 4);      output_asm_insn ("add.w %0,sp", &argcount);    }    return "";}

⌨️ 快捷键说明

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