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

📄 fr30.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Print an operand.  */voidfr30_print_operand (FILE *file, rtx x, int code){  rtx x0;    switch (code)    {    case '#':      /* Output a :D if this instruction is delayed.  */      if (dbr_sequence_length () != 0)	fputs (":D", file);      return;          case 'p':      /* Compute the register name of the second register in a hi/lo	 register pair.  */      if (GET_CODE (x) != REG)	output_operand_lossage ("fr30_print_operand: unrecognized %%p code");      else	fprintf (file, "r%d", REGNO (x) + 1);      return;          case 'b':      /* Convert GCC's comparison operators into FR30 comparison codes.  */      switch (GET_CODE (x))	{	case EQ:  fprintf (file, "eq"); break;	case NE:  fprintf (file, "ne"); break;	case LT:  fprintf (file, "lt"); break;	case LE:  fprintf (file, "le"); break;	case GT:  fprintf (file, "gt"); break;	case GE:  fprintf (file, "ge"); break;	case LTU: fprintf (file, "c"); break;	case LEU: fprintf (file, "ls"); break;	case GTU: fprintf (file, "hi"); break;	case GEU: fprintf (file, "nc");  break;	default:	  output_operand_lossage ("fr30_print_operand: unrecognized %%b code");	  break;	}      return;          case 'B':      /* Convert GCC's comparison operators into the complimentary FR30	 comparison codes.  */      switch (GET_CODE (x))	{	case EQ:  fprintf (file, "ne"); break;	case NE:  fprintf (file, "eq"); break;	case LT:  fprintf (file, "ge"); break;	case LE:  fprintf (file, "gt"); break;	case GT:  fprintf (file, "le"); break;	case GE:  fprintf (file, "lt"); break;	case LTU: fprintf (file, "nc"); break;	case LEU: fprintf (file, "hi"); break;	case GTU: fprintf (file, "ls"); break;	case GEU: fprintf (file, "c"); break;	default:	  output_operand_lossage ("fr30_print_operand: unrecognized %%B code");	  break;	}      return;    case 'A':      /* Print a signed byte value as an unsigned value.  */      if (GET_CODE (x) != CONST_INT)	output_operand_lossage ("fr30_print_operand: invalid operand to %%A code");      else	{	  HOST_WIDE_INT val;	  	  val = INTVAL (x);	  val &= 0xff;	  fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);	}      return;          case 'x':      if (GET_CODE (x) != CONST_INT	  || INTVAL (x) < 16	  || INTVAL (x) > 32)	output_operand_lossage ("fr30_print_operand: invalid %%x code");      else	fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) - 16);      return;    case 'F':      if (GET_CODE (x) != CONST_DOUBLE)	output_operand_lossage ("fr30_print_operand: invalid %%F code");      else	{	  char str[30];	  real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x),			   sizeof (str), 0, 1);	  fputs (str, file);	}      return;          case 0:      /* Handled below.  */      break;          default:      fprintf (stderr, "unknown code = %x\n", code);      output_operand_lossage ("fr30_print_operand: unknown code");      return;    }  switch (GET_CODE (x))    {    case REG:      fputs (reg_names [REGNO (x)], file);      break;    case MEM:      x0 = XEXP (x,0);            switch (GET_CODE (x0))	{	case REG:	  gcc_assert ((unsigned) REGNO (x0) < ARRAY_SIZE (reg_names));	  fprintf (file, "@%s", reg_names [REGNO (x0)]);	  break;	case PLUS:	  if (GET_CODE (XEXP (x0, 0)) != REG	      || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM	      || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM	      || GET_CODE (XEXP (x0, 1)) != CONST_INT)	    {	      fprintf (stderr, "bad INDEXed address:");	      debug_rtx (x);	      output_operand_lossage ("fr30_print_operand: unhandled MEM");	    }	  else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)	    {	      HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));	      if (val < -(1 << 9) || val > ((1 << 9) - 4))		{		  fprintf (stderr, "frame INDEX out of range:");		  debug_rtx (x);		  output_operand_lossage ("fr30_print_operand: unhandled MEM");		}	      fprintf (file, "@(r14, #" HOST_WIDE_INT_PRINT_DEC ")", val);	    }	  else	    {	      HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));	      if (val < 0 || val > ((1 << 6) - 4))		{		  fprintf (stderr, "stack INDEX out of range:");		  debug_rtx (x);		  output_operand_lossage ("fr30_print_operand: unhandled MEM");		}	      fprintf (file, "@(r15, #" HOST_WIDE_INT_PRINT_DEC ")", val);	    }	  break;	  	case SYMBOL_REF:	  output_address (x0);	  break;	  	default:	  fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));	  debug_rtx (x);	  output_operand_lossage ("fr30_print_operand: unhandled MEM");	  break;	}      break;          case CONST_DOUBLE :      /* We handle SFmode constants here as output_addr_const doesn't.  */      if (GET_MODE (x) == SFmode)	{	  REAL_VALUE_TYPE d;	  long l;	  REAL_VALUE_FROM_CONST_DOUBLE (d, x);	  REAL_VALUE_TO_TARGET_SINGLE (d, l);	  fprintf (file, "0x%08lx", l);	  break;	}      /* Fall through.  Let output_addr_const deal with it.  */    default:      output_addr_const (file, x);      break;    }  return;}/*}}}*//*{{{  Function arguments */ /* Return true if we should pass an argument on the stack rather than   in registers.  */static boolfr30_must_pass_in_stack (enum machine_mode mode, tree type){  if (mode == BLKmode)    return true;  if (type == NULL)    return false;  return AGGREGATE_TYPE_P (type);}/* Compute the number of word sized registers needed to hold a   function argument of mode INT_MODE and tree type TYPE.  */intfr30_num_arg_regs (enum machine_mode mode, tree type){  int size;  if (targetm.calls.must_pass_in_stack (mode, type))    return 0;  if (type && mode == BLKmode)    size = int_size_in_bytes (type);  else    size = GET_MODE_SIZE (mode);  return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;}/* Returns the number of bytes in which *part* of a parameter of machine   mode MODE and tree type TYPE (which may be NULL if the type is not known).   If the argument fits entirely in the argument registers, or entirely on   the stack, then 0 is returned.   CUM is the number of argument registers already used by earlier   parameters to the function.  */static intfr30_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,			tree type, bool named){  /* Unnamed arguments, i.e. those that are prototyped as ...     are always passed on the stack.     Also check here to see if all the argument registers are full.  */  if (named == 0 || *cum >= FR30_NUM_ARG_REGS)    return 0;  /* Work out how many argument registers would be needed if this     parameter were to be passed entirely in registers.  If there     are sufficient argument registers available (or if no registers     are needed because the parameter must be passed on the stack)     then return zero, as this parameter does not require partial     register, partial stack stack space.  */  if (*cum + fr30_num_arg_regs (mode, type) <= FR30_NUM_ARG_REGS)    return 0;    return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD;}/*}}}*//*{{{  Operand predicates */ #ifndef Mmode#define Mmode enum machine_mode#endif/* Returns true iff all the registers in the operands array   are in descending or ascending order.  */intfr30_check_multiple_regs (rtx *operands, int num_operands, int descending){  if (descending)    {      unsigned int prev_regno = 0;            while (num_operands --)	{	  if (GET_CODE (operands [num_operands]) != REG)	    return 0;	  	  if (REGNO (operands [num_operands]) < prev_regno)	    return 0;	  	  prev_regno = REGNO (operands [num_operands]);	}    }  else    {      unsigned int prev_regno = CONDITION_CODE_REGNUM;            while (num_operands --)	{	  if (GET_CODE (operands [num_operands]) != REG)	    return 0;	  	  if (REGNO (operands [num_operands]) > prev_regno)	    return 0;	  	  prev_regno = REGNO (operands [num_operands]);	}    }  return 1;}intfr30_const_double_is_zero (rtx operand){  REAL_VALUE_TYPE d;  if (operand == NULL || GET_CODE (operand) != CONST_DOUBLE)    return 0;  REAL_VALUE_FROM_CONST_DOUBLE (d, operand);  return REAL_VALUES_EQUAL (d, dconst0);}/*}}}*//*{{{  Instruction Output Routines  *//* Output a double word move.   It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.   On the FR30 we are constrained by the fact that it does not   support offsetable addresses, and so we have to load the   address of the secnd word into the second destination register   before we can use it.  */rtxfr30_move_double (rtx * operands){  rtx src  = operands[1];  rtx dest = operands[0];  enum rtx_code src_code = GET_CODE (src);  enum rtx_code dest_code = GET_CODE (dest);  enum machine_mode mode = GET_MODE (dest);  rtx val;  start_sequence ();  if (dest_code == REG)    {      if (src_code == REG)	{	  int reverse = (REGNO (dest) == REGNO (src) + 1);	  	  /* We normally copy the low-numbered register first.  However, if	     the first register of operand 0 is the same as the second register	     of operand 1, we must copy in the opposite order.  */	  emit_insn (gen_rtx_SET (VOIDmode,				  operand_subword (dest, reverse, TRUE, mode),				  operand_subword (src,  reverse, TRUE, mode)));	  	  emit_insn (gen_rtx_SET (VOIDmode,			      operand_subword (dest, !reverse, TRUE, mode),			      operand_subword (src,  !reverse, TRUE, mode)));	}      else if (src_code == MEM)	{	  rtx addr = XEXP (src, 0);	  int dregno = REGNO (dest);	  rtx dest0;	  rtx dest1;	  rtx new_mem;	  	  /* If the high-address word is used in the address, we	     must load it last.  Otherwise, load it first.  */	  int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);	  gcc_assert (GET_CODE (addr) == REG);	  	  dest0 = operand_subword (dest, reverse, TRUE, mode);	  dest1 = operand_subword (dest, !reverse, TRUE, mode);	  if (reverse)	    {	      emit_insn (gen_rtx_SET (VOIDmode, dest1,				      adjust_address (src, SImode, 0)));	      emit_insn (gen_rtx_SET (SImode, dest0,				      gen_rtx_REG (SImode, REGNO (addr))));	      emit_insn (gen_rtx_SET (SImode, dest0,				      plus_constant (dest0, UNITS_PER_WORD)));	      new_mem = gen_rtx_MEM (SImode, dest0);	      MEM_COPY_ATTRIBUTES (new_mem, src);	      	      emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));	    }	  else	    {	      emit_insn (gen_rtx_SET (VOIDmode, dest0,				      adjust_address (src, SImode, 0)));	      emit_insn (gen_rtx_SET (SImode, dest1,				      gen_rtx_REG (SImode, REGNO (addr))));	      emit_insn (gen_rtx_SET (SImode, dest1,				      plus_constant (dest1, UNITS_PER_WORD)));	      new_mem = gen_rtx_MEM (SImode, dest1);	      MEM_COPY_ATTRIBUTES (new_mem, src);	      	      emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));	    }	}      else if (src_code == CONST_INT || src_code == CONST_DOUBLE)	{	  rtx words[2];	  split_double (src, &words[0], &words[1]);	  emit_insn (gen_rtx_SET (VOIDmode,				  operand_subword (dest, 0, TRUE, mode),				  words[0]));      	  emit_insn (gen_rtx_SET (VOIDmode,				  operand_subword (dest, 1, TRUE, mode),				  words[1]));	}    }  else if (src_code == REG && dest_code == MEM)    {      rtx addr = XEXP (dest, 0);      rtx src0;      rtx src1;      gcc_assert (GET_CODE (addr) == REG);            src0 = operand_subword (src, 0, TRUE, mode);      src1 = operand_subword (src, 1, TRUE, mode);            emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0),			      src0));      if (REGNO (addr) == STACK_POINTER_REGNUM	  || REGNO (addr) == FRAME_POINTER_REGNUM)	emit_insn (gen_rtx_SET (VOIDmode,				adjust_address (dest, SImode, UNITS_PER_WORD),				src1));      else	{	  rtx new_mem;	  	  /* We need a scratch register to hold the value of 'address + 4'.	     We ought to allow gcc to find one for us, but for now, just	     push one of the source registers.  */	  emit_insn (gen_movsi_push (src0));	  emit_insn (gen_movsi_internal (src0, addr));	  emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD)));	  	  new_mem = gen_rtx_MEM (SImode, src0);	  MEM_COPY_ATTRIBUTES (new_mem, dest);	  	  emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1));	  emit_insn (gen_movsi_pop (src0));	}    }  else    /* This should have been prevented by the constraints on movdi_insn.  */    gcc_unreachable ();    val = get_insns ();  end_sequence ();  return val;}/*}}}*//* Local Variables: *//* folded-file: t   *//* End:		    */

⌨️ 快捷键说明

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