📄 i960.c
字号:
} 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;}#endif/* Modes for condition codes. */#define C_MODES \ ((1 << (int) CCmode) | (1 << (int) CC_UNSmode) | (1<< (int) CC_CHKmode))/* Modes for single-word (and smaller) quantities. */#define S_MODES \ (~C_MODES \ & ~ ((1 << (int) DImode) | (1 << (int) TImode) \ | (1 << (int) DFmode) | (1 << (int) TFmode)))/* Modes for double-word (and smaller) quantities. */#define D_MODES \ (~C_MODES \ & ~ ((1 << (int) TImode) | (1 << (int) TFmode)))/* Modes for quad-word quantities. */#define T_MODES (~C_MODES)/* Modes for single-float quantities. */#define SF_MODES ((1 << (int) SFmode))/* Modes for double-float quantities. */#define DF_MODES (SF_MODES | (1 << (int) DFmode) | (1 << (int) SCmode))/* Modes for quad-float quantities. */#define TF_MODES (DF_MODES | (1 << (int) TFmode) | (1 << (int) DCmode))unsigned int hard_regno_mode_ok[FIRST_PSEUDO_REGISTER] = { T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, TF_MODES, TF_MODES, TF_MODES, TF_MODES, C_MODES};/* 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: case LSHIFT: 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. */ assert (type != 0 && TYPE_MODE (type) == VOIDmode); size = 1; } else size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; if (type == 0) 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 be aligned appropriately. *//* 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 (named == 0 || size > 4 || cum->ca_nstackparms != 0 || (size + ROUND (cum->ca_nregparms, align)) > NPARM_REGS || MUST_PASS_IN_STACK (mode, type)) cum->ca_nstackparms = ROUND (cum->ca_nstackparms, align) + size; else cum->ca_nregparms = ROUND (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 (named == 0 || size > 4 || cum->ca_nstackparms != 0 || (size + ROUND (cum->ca_nregparms, align)) > NPARM_REGS || MUST_PASS_IN_STACK (mode, type)) { cum->ca_nstackparms = ROUND (cum->ca_nstackparms, align); ret = 0; } else { cum->ca_nregparms = ROUND (cum->ca_nregparms, align); ret = gen_rtx (REG, mode, cum->ca_nregparms); } return ret;}/* Floating-point support. */voidi960_output_double (file, value) FILE *file; double value;{ if (REAL_VALUE_ISINF (value)) { fprintf (file, "\t.word 0\n"); fprintf (file, "\t.word 0x7ff00000 # Infinity\n"); } else fprintf (file, "\t.double 0d%.17e\n", (value));}voidi960_output_float (file, value) FILE *file; double value;{ if (REAL_VALUE_ISINF (value)) fprintf (file, "\t.word 0x7f800000 # Infinity\n"); else fprintf (file, "\t.float 0f%.12e\n", (value));}/* 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 size of an aggregate type TSIZE. */treei960_round_size (tsize) tree tsize;{ int size, byte_size, align; if (TREE_CODE (tsize) != INTEGER_CST) return tsize; size = TREE_INT_CST_LOW (tsize); byte_size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; align = i960_object_bytes_bitalign (byte_size); /* Handle #pragma align. */ if (align > i960_maxbitalignment) align = i960_maxbitalignment; if (size % align) size = ((size / align) + 1) * align; return size_int (size);}/* Compute the alignment for an aggregate type TSIZE. */inti960_round_align (align, tsize) int align; tree tsize;{ int byte_size; if (TREE_CODE (tsize) != INTEGER_CST) return align; byte_size = (TREE_INT_CST_LOW (tsize) + BITS_PER_UNIT - 1) / BITS_PER_UNIT; align = i960_object_bytes_bitalign (byte_size); 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_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl) CUMULATIVE_ARGS *cum; enum machine_mode mode; tree type; int *pretend_size; int no_rtl;{ if (cum->ca_nregparms < NPARM_REGS) { int first_reg_offset = cum->ca_nregparms; if (first_reg_offset > NPARM_REGS) first_reg_offset = NPARM_REGS; if (! (no_rtl) && first_reg_offset != NPARM_REGS) { rtx label = gen_label_rtx (); emit_insn (gen_cmpsi (arg_pointer_rtx, const0_rtx)); emit_jump_insn (gen_bne (label)); emit_insn (gen_rtx (SET, VOIDmode, arg_pointer_rtx, stack_pointer_rtx)); emit_insn (gen_rtx (SET, VOIDmode, stack_pointer_rtx, memory_address (SImode, plus_constant (stack_pointer_rtx, 48)))); emit_label (label); move_block_from_reg (first_reg_offset, gen_rtx (MEM, BLKmode, virtual_incoming_args_rtx), NPARM_REGS - first_reg_offset); } *pretend_size = (NPARM_REGS - first_reg_offset) * UNITS_PER_WORD; }}/* Calculate the final size of the reg parm stack space for the current function, based on how many bytes would be allocated on the stack. */inti960_final_reg_parm_stack_space (const_size, var_size) int const_size; tree var_size;{ if (var_size || const_size > 48) return 48; else return 0;}/* Calculate the size of the reg parm stack space. This is a bit complicated on the i960. */inti960_reg_parm_stack_space (fndecl) tree fndecl;{ /* In this case, we are called from emit_library_call, and we don't need to pretend we have more space for parameters than what's apparent. */ if (fndecl == 0) return 0; /* In this case, we are called from locate_and_pad_parms when we're not IN_REGS, so we have an arg block. */ if (fndecl != current_function_decl) return 48; /* Otherwise, we have an arg block if the current function has more than 48 bytes of parameters. */ if (current_function_args_size != 0) return 48; else return 0;}/* Return the register class of a scratch register needed to copy IN into or out of a register in CLASS in MODE. If it can be done directly, NO_REGS is returned. */enum reg_classsecondary_reload_class (class, mode, in) enum reg_class class; enum machine_mode mode; rtx in;{ int regno = -1; if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG) regno = true_regnum (in); /* We can place anything into LOCAL_OR_GLOBAL_REGS and can put LOCAL_OR_GLOBAL_REGS into anything. */ if (class == LOCAL_OR_GLOBAL_REGS || class == LOCAL_REGS || class == GLOBAL_REGS || (regno >= 0 && regno < 32)) return NO_REGS; /* We can place any hard register, 0.0, and 1.0 into FP_REGS. */ if (class == FP_REGS && ((regno >= 0 && regno <= FIRST_PSEUDO_REGISTER) || in == CONST0_RTX (mode) || in == CONST1_RTX (mode))) return NO_REGS; return LOCAL_OR_GLOBAL_REGS;}/* Look at the opcode P, and set i96_last_insn_type to indicate which function unit it executed on. *//* ??? This would make more sense as an attribute. */voidi960_scan_opcode (p) char *p;{ switch (*p) { case 'a': case 'd': case 'e': case 'm': case 'n': case 'o': case 'r': /* Ret is not actually of type REG, but it won't matter, because no insn will ever follow it. */ case 'u': case 'x': i960_last_insn_type = I_TYPE_REG; break; case 'b': if (p[1] == 'x' || p[3] == 'x') i960_last_insn_type = I_TYPE_MEM; i960_last_insn_type = I_TYPE_CTRL; break; case 'f': case 't': i960_last_insn_type = I_TYPE_CTRL; break; case 'c': if (p[1] == 'a') { if (p[4] == 'x') i960_last_insn_type = I_TYPE_MEM; else i960_last_insn_type = I_TYPE_CTRL; } else if (p[1] == 'm') { if (p[3] == 'd') i960_last_insn_type = I_TYPE_REG; else if (p[4] == 'b' || p[4] == 'j') i960_last_insn_type = I_TYPE_CTRL; else i960_last_insn_type = I_TYPE_REG; } else i960_last_insn_type = I_TYPE_REG; break; case 'l': i960_last_insn_type = I_TYPE_MEM; break; case 's': if (p[1] == 't') i960_last_insn_type = I_TYPE_MEM; else i960_last_insn_type = I_TYPE_REG; break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -