📄 i960.c
字号:
if (! (RTX_OK_FOR_INDEX_P (XEXP (XEXP (op0, 0), 0), strict) && SCALE_TERM_P (XEXP (XEXP (op0, 0), 1)))) return 0; if (RTX_OK_FOR_BASE_P (XEXP (op0, 1), strict) && CONSTANT_P (op1)) return 1; else return 0; } else if (RTX_OK_FOR_BASE_P (XEXP (op0, 0), strict)) { if (RTX_OK_FOR_INDEX_P (XEXP (op0, 1), strict) && CONSTANT_P (op1)) return 1; else return 0; } else return 0; } else if (GET_CODE (op0) == MULT) { if (! (RTX_OK_FOR_INDEX_P (XEXP (op0, 0), strict) && SCALE_TERM_P (XEXP (op0, 1)))) return 0; if (RTX_OK_FOR_BASE_P (op1, strict)) return 1; else if (CONSTANT_P (op1)) return 1; else return 0; } else return 0; } else if (GET_CODE (addr) == MULT) { if (! TARGET_COMPLEX_ADDR && ! reload_completed) return 0; return (RTX_OK_FOR_INDEX_P (XEXP (addr, 0), strict) && SCALE_TERM_P (XEXP (addr, 1))); } else return 0;}/* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. This macro is used in only one place: `memory_address' in explow.c. This converts some non-canonical addresses to canonical form so they can be recognized. */rtxlegitimize_address (x, oldx, mode) register rtx x; register rtx oldx; enum machine_mode mode;{ if (GET_CODE (x) == SYMBOL_REF) { abort (); x = copy_to_reg (x); } if (! TARGET_COMPLEX_ADDR && ! reload_completed) return x; /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const))) into (plus (plus (mult (reg) (const)) (reg)) (const)). This can be created by virtual register instantiation, register elimination, and similar optimizations. */ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS) x = gen_rtx (PLUS, Pmode, gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)), XEXP (XEXP (x, 1), 1)); /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const) into (plus (plus (mult (reg) (const)) (reg)) (const)). */ else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS && CONSTANT_P (XEXP (x, 1))) { rtx constant, other; if (GET_CODE (XEXP (x, 1)) == CONST_INT) { constant = XEXP (x, 1); other = XEXP (XEXP (XEXP (x, 0), 1), 1); } else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT) { constant = XEXP (XEXP (XEXP (x, 0), 1), 1); other = XEXP (x, 1); } else constant = 0; if (constant) x = gen_rtx (PLUS, Pmode, gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0), XEXP (XEXP (XEXP (x, 0), 1), 0)), plus_constant (other, INTVAL (constant))); } return x;}#if 0/* Return the most stringent alignment that we are willing to consider objects of size SIZE and known alignment ALIGN as having. */ inti960_alignment (size, align) int size; int align;{ int i; if (! TARGET_STRICT_ALIGN) if (TARGET_IC_COMPAT2_0 || align >= 4) { i = i960_object_bytes_bitalign (size) / BITS_PER_UNIT; if (i > align) align = i; } return align;}#endifinthard_regno_mode_ok (regno, mode) int regno; enum machine_mode mode;{ if (regno < 32) { switch (mode) { case CCmode: case CC_UNSmode: case CC_CHKmode: return 0; case DImode: case DFmode: return (regno & 1) == 0; case TImode: case XFmode: return (regno & 3) == 0; default: return 1; } } else if (regno >= 32 && regno < 36) { switch (mode) { case SFmode: case DFmode: case XFmode: case SCmode: case DCmode: return 1; default: return 0; } } else if (regno == 36) { switch (mode) { case CCmode: case CC_UNSmode: case CC_CHKmode: return 1; default: return 0; } } else if (regno == 37) return 0; abort ();}/* Return the minimum alignment of an expression rtx X in bytes. This takes advantage of machine specific facts, such as knowing that the frame pointer is always 16 byte aligned. */inti960_expr_alignment (x, size) rtx x; int size;{ int align = 1; if (x == 0) return 1; switch (GET_CODE(x)) { case CONST_INT: align = INTVAL(x); if ((align & 0xf) == 0) align = 16; else if ((align & 0x7) == 0) align = 8; else if ((align & 0x3) == 0) align = 4; else if ((align & 0x1) == 0) align = 2; else align = 1; break; case PLUS: align = MIN (i960_expr_alignment (XEXP (x, 0), size), i960_expr_alignment (XEXP (x, 1), size)); break; case SYMBOL_REF: /* If this is a valid program, objects are guaranteed to be correctly aligned for whatever size the reference actually is. */ align = i960_object_bytes_bitalign (size) / BITS_PER_UNIT; break; case REG: if (REGNO (x) == FRAME_POINTER_REGNUM) align = 16; break; case ASHIFT: align = i960_expr_alignment (XEXP (x, 0)); if (GET_CODE (XEXP (x, 1)) == CONST_INT) { align = align << INTVAL (XEXP (x, 1)); align = MIN (align, 16); } break; case MULT: align = (i960_expr_alignment (XEXP (x, 0), size) * i960_expr_alignment (XEXP (x, 1), size)); align = MIN (align, 16); break; } return align;}/* Return true if it is possible to reference both BASE and OFFSET, which have alignment at least as great as 4 byte, as if they had alignment valid for an object of size SIZE. */inti960_improve_align (base, offset, size) rtx base; rtx offset; int size;{ int i, j; /* We have at least a word reference to the object, so we know it has to be aligned at least to 4 bytes. */ i = MIN (i960_expr_alignment (base, 4), i960_expr_alignment (offset, 4)); i = MAX (i, 4); /* We know the size of the request. If strict align is not enabled, we can guess that the alignment is OK for the requested size. */ if (! TARGET_STRICT_ALIGN) if ((j = (i960_object_bytes_bitalign (size) / BITS_PER_UNIT)) > i) i = j; return (i >= size);}/* Return true if it is possible to access BASE and OFFSET, which have 4 byte (SImode) alignment as if they had 16 byte (TImode) alignment. */inti960_si_ti (base, offset) rtx base; rtx offset;{ return i960_improve_align (base, offset, 16);}/* Return true if it is possible to access BASE and OFFSET, which have 4 byte (SImode) alignment as if they had 8 byte (DImode) alignment. */inti960_si_di (base, offset) rtx base; rtx offset;{ return i960_improve_align (base, offset, 8);}/* Return raw values of size and alignment (in words) for the data type being accessed. These values will be rounded by the caller. */static void i960_arg_size_and_align (mode, type, size_out, align_out) enum machine_mode mode; tree type; int *size_out; int *align_out;{ int size, align; /* Use formal alignment requirements of type being passed, except make it at least a word. If we don't have a type, this is a library call, and the parm has to be of scalar type. In this case, consider its formal alignment requirement to be its size in words. */ if (mode == BLKmode) size = (int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; else if (mode == VOIDmode) { /* End of parm list. */ if (type == 0 || TYPE_MODE (type) != VOIDmode) abort (); size = 1; } else size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; if (type == 0) { /* ??? This is a hack to properly correct the alignment of XFmode values without affecting anything else. */ if (size == 3) align = 4; else align = size; } else if (TYPE_ALIGN (type) >= BITS_PER_WORD) align = TYPE_ALIGN (type) / BITS_PER_WORD; else align = 1; *size_out = size; *align_out = align;}/* On the 80960 the first 12 args are in registers and the rest are pushed. Any arg that is bigger than 4 words is placed on the stack and all subsequent arguments are placed on the stack. Additionally, parameters with an alignment requirement stronger than a word must be aligned appropriately. Note that this means that a 64 bit object with a 32 bit alignment is not 64 bit aligned and may be passed in an odd/even register pair. *//* Update CUM to advance past an argument described by MODE and TYPE. */voidi960_function_arg_advance (cum, mode, type, named) CUMULATIVE_ARGS *cum; enum machine_mode mode; tree type; int named;{ int size, align; i960_arg_size_and_align (mode, type, &size, &align); if (size > 4 || cum->ca_nstackparms != 0 || (size + ROUND_PARM (cum->ca_nregparms, align)) > NPARM_REGS || MUST_PASS_IN_STACK (mode, type)) { /* Indicate that all the registers are in use, even if all are not, so va_start will compute the right value. */ cum->ca_nregparms = NPARM_REGS; cum->ca_nstackparms = ROUND_PARM (cum->ca_nstackparms, align) + size; } else cum->ca_nregparms = ROUND_PARM (cum->ca_nregparms, align) + size;}/* Return the register that the argument described by MODE and TYPE is passed in, or else return 0 if it is passed on the stack. */rtxi960_function_arg (cum, mode, type, named) CUMULATIVE_ARGS *cum; enum machine_mode mode; tree type; int named;{ rtx ret; int size, align; i960_arg_size_and_align (mode, type, &size, &align); if (size > 4 || cum->ca_nstackparms != 0 || (size + ROUND_PARM (cum->ca_nregparms, align)) > NPARM_REGS || MUST_PASS_IN_STACK (mode, type)) { cum->ca_nstackparms = ROUND_PARM (cum->ca_nstackparms, align); ret = 0; } else { cum->ca_nregparms = ROUND_PARM (cum->ca_nregparms, align); ret = gen_rtx (REG, mode, cum->ca_nregparms); } return ret;}/* Floating-point support. */voidi960_output_long_double (file, value) FILE *file; REAL_VALUE_TYPE value;{ long value_long[3]; char dstr[30]; REAL_VALUE_TO_TARGET_LONG_DOUBLE (value, value_long); REAL_VALUE_TO_DECIMAL (value, "%.20g", dstr); fprintf (file, "\t.word\t0x%08lx\t\t# %s\n\t.word\t0x%08lx\n\t.word\t0x%08lx\n", value_long[0], dstr, value_long[1], value_long[2]); fprintf (file, "\t.word\t0x0\n");}voidi960_output_double (file, value) FILE *file; REAL_VALUE_TYPE value;{ long value_long[2]; char dstr[30]; REAL_VALUE_TO_TARGET_DOUBLE (value, value_long); REAL_VALUE_TO_DECIMAL (value, "%.20g", dstr); fprintf (file, "\t.word\t0x%08lx\t\t# %s\n\t.word\t0x%08lx\n", value_long[0], dstr, value_long[1]);} voidi960_output_float (file, value) FILE *file; REAL_VALUE_TYPE value;{ long value_long; char dstr[30]; REAL_VALUE_TO_TARGET_SINGLE (value, value_long); REAL_VALUE_TO_DECIMAL (value, "%.12g", dstr); fprintf (file, "\t.word\t0x%08lx\t\t# %s (float)\n", value_long, dstr);}/* Return the number of bits that an object of size N bytes is aligned to. */inti960_object_bytes_bitalign (n) int n;{ if (n > 8) n = 128; else if (n > 4) n = 64; else if (n > 2) n = 32; else if (n > 1) n = 16; else n = 8; return n;}/* Compute the alignment for an aggregate type TSIZE. Alignment is MAX (greatest member alignment, MIN (pragma align, structure size alignment)). */inti960_round_align (align, tsize) int align; tree tsize;{ int new_align; if (TREE_CODE (tsize) != INTEGER_CST) return align; new_align = i960_object_bytes_bitalign (TREE_INT_CST_LOW (tsize) / BITS_PER_UNIT); /* Handle #pragma align. */ if (new_align > i960_maxbitalignment) new_align = i960_maxbitalignment; if (align < new_align) align = new_align; return align;}/* Do any needed setup for a varargs function. For the i960, we must create a register parameter block if one doesn't exist, and then copy all register parameters to memory. */voidi960_s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -