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

📄 stormy16.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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   register), you should define patterns for `reload_inM' or `reload_outM', as   required..  These patterns, which will normally be implemented with a   `define_expand', should be similar to the `movM' patterns, except that   operand 2 is the scratch register.   Define constraints for the reload register and scratch register that contain   a single register class.  If the original reload register (whose class is   CLASS) can meet the constraint given in the pattern, the value returned by   these macros is used for the class of the scratch register.  Otherwise, two   additional reload registers are required.  Their classes are obtained from   the constraints in the insn pattern.   X might be a pseudo-register or a `subreg' of a pseudo-register, which could   either be in a hard register or in memory.  Use `true_regnum' to find out;   it will return -1 if the pseudo is in memory and the hard register number if   it is in a register.   These macros should not be used in the case where a particular class of   registers can only be copied to memory and not to another class of   registers.  In that case, secondary reload registers are not needed and   would not be helpful.  Instead, a stack location must be used to perform the   copy and the `movM' pattern should use memory as an intermediate storage.   This case often occurs between floating-point and general registers.  */enum reg_classxstormy16_secondary_reload_class (enum reg_class class,				  enum machine_mode mode,				  rtx x){  /* This chip has the interesting property that only the first eight     registers can be moved to/from memory.  */  if ((GET_CODE (x) == MEM       || ((GET_CODE (x) == SUBREG || GET_CODE (x) == REG)	   && (true_regnum (x) == -1	       || true_regnum (x) >= FIRST_PSEUDO_REGISTER)))      && ! reg_class_subset_p (class, EIGHT_REGS))    return EIGHT_REGS;  /* When reloading a PLUS, the carry register will be required     unless the inc or dec instructions can be used.  */  if (xstormy16_carry_plus_operand (x, mode))    return CARRY_REGS;  return NO_REGS;}/* Recognize a PLUS that needs the carry register.  */intxstormy16_carry_plus_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  return (GET_CODE (x) == PLUS	  && GET_CODE (XEXP (x, 1)) == CONST_INT	  && (INTVAL (XEXP (x, 1)) < -4 || INTVAL (XEXP (x, 1)) > 4));}/* Detect and error out on out-of-range constants for movhi.  */intxs_hi_general_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  if ((GET_CODE (x) == CONST_INT)    && ((INTVAL (x) >= 32768) || (INTVAL (x) < -32768)))    error ("Constant halfword load operand out of range.");  return general_operand (x, mode);}/* Detect and error out on out-of-range constants for addhi and subhi.  */intxs_hi_nonmemory_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  if ((GET_CODE (x) == CONST_INT)    && ((INTVAL (x) >= 32768) || (INTVAL (x) < -32768)))    error ("Constant arithmetic operand out of range.");  return nonmemory_operand (x, mode);}enum reg_classxstormy16_preferred_reload_class (rtx x, enum reg_class class){  if (class == GENERAL_REGS      && GET_CODE (x) == MEM)    return EIGHT_REGS;  return class;}/* Predicate for symbols and addresses that reflect special 8-bit   addressing.  */intxstormy16_below100_symbol (rtx x,			   enum machine_mode mode ATTRIBUTE_UNUSED){  if (GET_CODE (x) == CONST)    x = XEXP (x, 0);  if (GET_CODE (x) == PLUS      && GET_CODE (XEXP (x, 1)) == CONST_INT)    x = XEXP (x, 0);  if (GET_CODE (x) == SYMBOL_REF)    {      const char *n = XSTR (x, 0);      if (n[0] == '@' && n[1] == 'b' && n[2] == '.')	return 1;    }  if (GET_CODE (x) == CONST_INT)    {      HOST_WIDE_INT i = INTVAL (x);      if ((i >= 0x0000 && i <= 0x00ff)	  || (i >= 0x7f00 && i <= 0x7fff))	return 1;    }  return 0;}/* Predicate for MEMs that can use special 8-bit addressing.  */intxstormy16_below100_operand (rtx x, enum machine_mode mode){  if (GET_MODE (x) != mode)    return 0;  if (GET_CODE (x) == MEM)    x = XEXP (x, 0);  else if (GET_CODE (x) == SUBREG	   && GET_CODE (XEXP (x, 0)) == MEM	   && !MEM_VOLATILE_P (XEXP (x, 0)))    x = XEXP (XEXP (x, 0), 0);  else    return 0;  if (GET_CODE (x) == CONST_INT)    {      HOST_WIDE_INT i = INTVAL (x);      return (i >= 0x7f00 && i < 0x7fff);    }  return xstormy16_below100_symbol (x, HImode);}/* Likewise, but only for non-volatile MEMs, for patterns where the   MEM will get split into smaller sized accesses.  */intxstormy16_splittable_below100_operand (rtx x, enum machine_mode mode){  if (GET_CODE (x) == MEM && MEM_VOLATILE_P (x))    return 0;  return xstormy16_below100_operand (x, mode);}intxstormy16_below100_or_register (rtx x, enum machine_mode mode){  return (xstormy16_below100_operand (x, mode)	  || register_operand (x, mode));}intxstormy16_splittable_below100_or_register (rtx x, enum machine_mode mode){  if (GET_CODE (x) == MEM && MEM_VOLATILE_P (x))    return 0;  return (xstormy16_below100_operand (x, mode)	  || register_operand (x, mode));}/* Predicate for constants with exactly one bit set.  */intxstormy16_onebit_set_operand (rtx x, enum machine_mode mode){  HOST_WIDE_INT i;  if (GET_CODE (x) != CONST_INT)    return 0;  i = INTVAL (x);  if (mode == QImode)    i &= 0xff;  if (mode == HImode)    i &= 0xffff;  return exact_log2 (i) != -1;}/* Predicate for constants with exactly one bit not set.  */intxstormy16_onebit_clr_operand (rtx x, enum machine_mode mode){  HOST_WIDE_INT i;  if (GET_CODE (x) != CONST_INT)    return 0;  i = ~ INTVAL (x);  if (mode == QImode)    i &= 0xff;  if (mode == HImode)    i &= 0xffff;  return exact_log2 (i) != -1;}/* Expand an 8-bit IOR.  This either detects the one case we can   actually do, or uses a 16-bit IOR.  */voidxstormy16_expand_iorqi3 (rtx *operands){  rtx in, out, outsub, val;  out = operands[0];  in = operands[1];  val = operands[2];  if (xstormy16_onebit_set_operand (val, QImode))    {      if (!xstormy16_below100_or_register (in, QImode))	in = copy_to_mode_reg (QImode, in);      if (!xstormy16_below100_or_register (out, QImode))	out = gen_reg_rtx (QImode);      emit_insn (gen_iorqi3_internal (out, in, val));      if (out != operands[0])	emit_move_insn (operands[0], out);      return;    }  if (GET_CODE (in) != REG)    in = copy_to_mode_reg (QImode, in);  if (GET_CODE (val) != REG      && GET_CODE (val) != CONST_INT)    val = copy_to_mode_reg (QImode, val);  if (GET_CODE (out) != REG)    out = gen_reg_rtx (QImode);  in = simplify_gen_subreg (HImode, in, QImode, 0);  outsub = simplify_gen_subreg (HImode, out, QImode, 0);  if (GET_CODE (val) != CONST_INT)    val = simplify_gen_subreg (HImode, val, QImode, 0);  emit_insn (gen_iorhi3 (outsub, in, val));  if (out != operands[0])    emit_move_insn (operands[0], out);}/* Likewise, for AND.  */voidxstormy16_expand_andqi3 (rtx *operands){  rtx in, out, outsub, val;  out = operands[0];  in = operands[1];  val = operands[2];  if (xstormy16_onebit_clr_operand (val, QImode))    {      if (!xstormy16_below100_or_register (in, QImode))	in = copy_to_mode_reg (QImode, in);      if (!xstormy16_below100_or_register (out, QImode))	out = gen_reg_rtx (QImode);      emit_insn (gen_andqi3_internal (out, in, val));      if (out != operands[0])	emit_move_insn (operands[0], out);      return;    }  if (GET_CODE (in) != REG)    in = copy_to_mode_reg (QImode, in);  if (GET_CODE (val) != REG      && GET_CODE (val) != CONST_INT)    val = copy_to_mode_reg (QImode, val);  if (GET_CODE (out) != REG)    out = gen_reg_rtx (QImode);  in = simplify_gen_subreg (HImode, in, QImode, 0);  outsub = simplify_gen_subreg (HImode, out, QImode, 0);  if (GET_CODE (val) != CONST_INT)    val = simplify_gen_subreg (HImode, val, QImode, 0);  emit_insn (gen_andhi3 (outsub, in, val));  if (out != operands[0])    emit_move_insn (operands[0], out);}#define LEGITIMATE_ADDRESS_INTEGER_P(X, OFFSET)				\ (GET_CODE (X) == CONST_INT						\  && (unsigned HOST_WIDE_INT) (INTVAL (X) + (OFFSET) + 2048) < 4096)#define LEGITIMATE_ADDRESS_CONST_INT_P(X, OFFSET)			 \ (GET_CODE (X) == CONST_INT						 \  && INTVAL (X) + (OFFSET) >= 0						 \  && INTVAL (X) + (OFFSET) < 0x8000					 \  && (INTVAL (X) + (OFFSET) < 0x100 || INTVAL (X) + (OFFSET) >= 0x7F00))intxstormy16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,				rtx x, int strict){  if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0))    return 1;  if (GET_CODE (x) == PLUS      && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (x, 1), 0))    x = XEXP (x, 0);    if ((GET_CODE (x) == PRE_MODIFY       && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT)      || GET_CODE (x) == POST_INC      || GET_CODE (x) == PRE_DEC)    x = XEXP (x, 0);    if (GET_CODE (x) == REG && REGNO_OK_FOR_BASE_P (REGNO (x))      && (! strict || REGNO (x) < FIRST_PSEUDO_REGISTER))    return 1;  if (xstormy16_below100_symbol(x, mode))    return 1;    return 0;}/* Return nonzero if memory address X (an RTX) can have different   meanings depending on the machine mode of the memory reference it   is used for or if the address is valid for some modes but not   others.   Autoincrement and autodecrement addresses typically have mode-dependent   effects because the amount of the increment or decrement is the size of the   operand being addressed.  Some machines have other mode-dependent addresses.   Many RISC machines have no mode-dependent addresses.   You may assume that ADDR is a valid address for the machine.        On this chip, this is true if the address is valid with an offset   of 0 but not of 6, because in that case it cannot be used as an   address for DImode or DFmode, or if the address is a post-increment   or pre-decrement address.  */intxstormy16_mode_dependent_address_p (rtx x){  if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0)      && ! LEGITIMATE_ADDRESS_CONST_INT_P (x, 6))    return 1;    if (GET_CODE (x) == PLUS      && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (x, 1), 0)      && ! LEGITIMATE_ADDRESS_INTEGER_P (XEXP (x, 1), 6))    return 1;  if (GET_CODE (x) == PLUS)    x = XEXP (x, 0);  if (GET_CODE (x) == POST_INC      || GET_CODE (x) == PRE_DEC)    return 1;  return 0;}/* A C expression that defines the optional machine-dependent constraint   letters (`Q', `R', `S', `T', `U') that can be used to segregate specific   types of operands, usually memory references, for the target machine.   Normally this macro will not be defined.  If it is required for a particular   target machine, it should return 1 if VALUE corresponds to the operand type   represented by the constraint letter C.  If C is not defined as an extra   constraint, the value returned should be 0 regardless of VALUE.  */intxstormy16_extra_constraint_p (rtx x, int c){  switch (c)    {      /* 'Q' is for pushes.  */    case 'Q':      return (GET_CODE (x) == MEM	      && GET_CODE (XEXP (x, 0)) == POST_INC	      && XEXP (XEXP (x, 0), 0) == stack_pointer_rtx);      /* 'R' is for pops.  */    case 'R':      return (GET_CODE (x) == MEM	      && GET_CODE (XEXP (x, 0)) == PRE_DEC	      && XEXP (XEXP (x, 0), 0) == stack_pointer_rtx);      /* 'S' is for immediate memory addresses.  */    case 'S':      return (GET_CODE (x) == MEM	      && GET_CODE (XEXP (x, 0)) == CONST_INT	      && xstormy16_legitimate_address_p (VOIDmode, XEXP (x, 0), 0));      /* 'T' is for Rx.  */    case 'T':      /* Not implemented yet.  */      return 0;      /* 'U' is for CONST_INT values not between 2 and 15 inclusive,	 for allocating a scratch register for 32-bit shifts.  */    case 'U':      return (GET_CODE (x) == CONST_INT	      && (INTVAL (x) < 2 || INTVAL (x) > 15));      /* 'Z' is for CONST_INT value zero.  This is for adding zero to	 a register in addhi3, which would otherwise require a carry.  */    case 'Z':      return (GET_CODE (x) == CONST_INT	      && (INTVAL (x) == 0));    case 'W':      return xstormy16_below100_operand(x, GET_MODE(x));    default:      return 0;    }}intshort_memory_operand (rtx x, enum machine_mode mode){  if (! memory_operand (x, mode))    return 0;  return (GET_CODE (XEXP (x, 0)) != PLUS);}

⌨️ 快捷键说明

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