📄 mt.c
字号:
if (fntype) { tree ret_type = TREE_TYPE (fntype); fprintf (stderr, " return = %s,", tree_code_name[ (int)TREE_CODE (ret_type) ]); } if (libname && GET_CODE (libname) == SYMBOL_REF) fprintf (stderr, " libname = %s", XSTR (libname, 0)); if (cfun->returns_struct) fprintf (stderr, " return-struct"); putc ('\n', stderr); }}/* Compute the slot number to pass an argument in. Returns the slot number or -1 if passing on the stack. CUM is a variable of type CUMULATIVE_ARGS which gives info about the preceding args and about the function being called. MODE is the argument's machine mode. TYPE is the data type of the argument (as a tree). This is null for libcalls where that information may not be available. NAMED is nonzero if this argument is a named parameter (otherwise it is an extra parameter matching an ellipsis). INCOMING_P is zero for FUNCTION_ARG, nonzero for FUNCTION_INCOMING_ARG. *PREGNO records the register number to use if scalar type. */static intmt_function_arg_slotno (const CUMULATIVE_ARGS * cum, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED, int incoming_p ATTRIBUTE_UNUSED, int * pregno){ int regbase = FIRST_ARG_REGNUM; int slotno = * cum; if (mode == VOIDmode || targetm.calls.must_pass_in_stack (mode, type)) return -1; if (slotno >= MT_NUM_ARG_REGS) return -1; * pregno = regbase + slotno; return slotno;}/* Implement FUNCTION_ARG. */rtxmt_function_arg (const CUMULATIVE_ARGS * cum, enum machine_mode mode, tree type, int named, int incoming_p){ int slotno, regno; rtx reg; slotno = mt_function_arg_slotno (cum, mode, type, named, incoming_p, ®no); if (slotno == -1) reg = NULL_RTX; else reg = gen_rtx_REG (mode, regno); return reg;}/* Implement FUNCTION_ARG_ADVANCE. */voidmt_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode, tree type ATTRIBUTE_UNUSED, int named){ int slotno, regno; /* We pass 0 for incoming_p here, it doesn't matter. */ slotno = mt_function_arg_slotno (cum, mode, type, named, 0, ®no); * cum += (mode != BLKmode ? ROUND_ADVANCE (GET_MODE_SIZE (mode)) : ROUND_ADVANCE (int_size_in_bytes (type))); if (TARGET_DEBUG_ARG) fprintf (stderr, "mt_function_arg_advance: words = %2d, mode = %4s, named = %d, size = %3d\n", *cum, GET_MODE_NAME (mode), named, (*cum) * UNITS_PER_WORD);}/* Implement hook TARGET_ARG_PARTIAL_BYTES. Returns the number of bytes at the beginning of an argument that must be put in registers. The value must be zero for arguments that are passed entirely in registers or that are entirely pushed on the stack. */static intmt_arg_partial_bytes (CUMULATIVE_ARGS * pcum, enum machine_mode mode, tree type, bool named ATTRIBUTE_UNUSED){ int cum = * pcum; int words; if (mode == BLKmode) words = ((int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD); else words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; if (! targetm.calls.pass_by_reference (&cum, mode, type, named) && cum < MT_NUM_ARG_REGS && (cum + words) > MT_NUM_ARG_REGS) { int bytes = (MT_NUM_ARG_REGS - cum) * UNITS_PER_WORD; if (TARGET_DEBUG) fprintf (stderr, "function_arg_partial_nregs = %d\n", bytes); return bytes; } return 0;}/* Implement TARGET_PASS_BY_REFERENCE hook. */static boolmt_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, tree type, bool named ATTRIBUTE_UNUSED){ return (type && int_size_in_bytes (type) > 4 * UNITS_PER_WORD);}/* Implement FUNCTION_ARG_BOUNDARY. */intmt_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED){ return BITS_PER_WORD;}/* Implement REG_OK_FOR_BASE_P. */intmt_reg_ok_for_base_p (rtx x, int strict){ if (strict) return (((unsigned) REGNO (x)) < FIRST_PSEUDO_REGISTER); return 1;}/* Helper function of mt_legitimate_address_p. Return true if XINSN is a simple address, otherwise false. */static boolmt_legitimate_simple_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx xinsn, int strict){ if (TARGET_DEBUG) { fprintf (stderr, "\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n", strict ? "" : "not "); debug_rtx (xinsn); } if (GET_CODE (xinsn) == REG && mt_reg_ok_for_base_p (xinsn, strict)) return true; if (GET_CODE (xinsn) == PLUS && GET_CODE (XEXP (xinsn, 0)) == REG && mt_reg_ok_for_base_p (XEXP (xinsn, 0), strict) && GET_CODE (XEXP (xinsn, 1)) == CONST_INT && SMALL_INT (XEXP (xinsn, 1))) return true; return false;}/* Helper function of GO_IF_LEGITIMATE_ADDRESS. Return non-zero if XINSN is a legitimate address on MT. */intmt_legitimate_address_p (enum machine_mode mode, rtx xinsn, int strict){ if (mt_legitimate_simple_address_p (mode, xinsn, strict)) return 1; if ((mode) == SImode && GET_CODE (xinsn) == AND && GET_CODE (XEXP (xinsn, 1)) == CONST_INT && INTVAL (XEXP (xinsn, 1)) == -3) return mt_legitimate_simple_address_p (mode, XEXP (xinsn, 0), strict); else return 0;}/* Return truth value of whether OP can be used as an operands where a register or 16 bit unsigned integer is needed. */intuns_arith_operand (rtx op, enum machine_mode mode){ if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op)) return 1; return register_operand (op, mode);}/* Return truth value of whether OP can be used as an operands where a 16 bit integer is needed. */intarith_operand (rtx op, enum machine_mode mode){ if (GET_CODE (op) == CONST_INT && SMALL_INT (op)) return 1; return register_operand (op, mode);}/* Return truth value of whether OP is a register or the constant 0. */intreg_or_0_operand (rtx op, enum machine_mode mode){ switch (GET_CODE (op)) { case CONST_INT: return INTVAL (op) == 0; case REG: case SUBREG: return register_operand (op, mode); default: break; } return 0;}/* Return truth value of whether OP is a constant that requires two loads to put in a register. */intbig_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_LETTER_P (INTVAL (op), 'M')) return 1; return 0;}/* Return truth value of whether OP is a constant that require only one load to put in a register. */intsingle_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ if (big_const_operand (op, mode) || GET_CODE (op) == CONST || GET_CODE (op) == LABEL_REF || GET_CODE (op) == SYMBOL_REF) return 0; return 1;}/* True if the current function is an interrupt handler (either via #pragma or an attribute specification). */int interrupt_handler;enum processor_type mt_cpu;static struct machine_function *mt_init_machine_status (void){ struct machine_function *f; f = ggc_alloc_cleared (sizeof (struct machine_function)); return f;}/* Implement OVERRIDE_OPTIONS. */voidmt_override_options (void){ if (mt_cpu_string != NULL) { if (!strcmp (mt_cpu_string, "ms1-64-001")) mt_cpu = PROCESSOR_MS1_64_001; else if (!strcmp (mt_cpu_string, "ms1-16-002")) mt_cpu = PROCESSOR_MS1_16_002; else if (!strcmp (mt_cpu_string, "ms1-16-003")) mt_cpu = PROCESSOR_MS1_16_003; else if (!strcmp (mt_cpu_string, "ms2")) mt_cpu = PROCESSOR_MS2; else error ("bad value (%s) for -march= switch", mt_cpu_string); } else mt_cpu = PROCESSOR_MS1_64_001; if (flag_exceptions) { flag_omit_frame_pointer = 0; flag_gcse = 0; } /* We do delayed branch filling in machine dependent reorg */ mt_flag_delayed_branch = flag_delayed_branch; flag_delayed_branch = 0; init_machine_status = mt_init_machine_status;}/* Do what is necessary for `va_start'. We look at the current function to determine if stdarg or varargs is used and return the address of the first unnamed parameter. */static voidmt_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, int *pretend_size, int no_rtl){ int regno; int regs = MT_NUM_ARG_REGS - *cum; *pretend_size = regs < 0 ? 0 : GET_MODE_SIZE (SImode) * regs; if (no_rtl) return; for (regno = *cum; regno < MT_NUM_ARG_REGS; regno++) { rtx reg = gen_rtx_REG (SImode, FIRST_ARG_REGNUM + regno); rtx slot = gen_rtx_PLUS (Pmode, gen_rtx_REG (SImode, ARG_POINTER_REGNUM), GEN_INT (UNITS_PER_WORD * regno)); emit_move_insn (gen_rtx_MEM (SImode, slot), reg); }}/* Returns the number of bytes offset between the frame pointer and the stack pointer for the current function. SIZE is the number of bytes of space needed for local variables. */unsigned intmt_compute_frame_size (int size){ int regno; unsigned int total_size; unsigned int var_size; unsigned int args_size; unsigned int pretend_size; unsigned int extra_size; unsigned int reg_size; unsigned int frame_size; unsigned int reg_mask; var_size = size; args_size = current_function_outgoing_args_size; pretend_size = current_function_pretend_args_size; extra_size = FIRST_PARM_OFFSET (0); total_size = extra_size + pretend_size + args_size + var_size; reg_size = 0; reg_mask = 0; /* Calculate space needed for registers. */ for (regno = GPR_R0; regno <= GPR_LAST; regno++) { if (MUST_SAVE_REGISTER (regno)) { reg_size += UNITS_PER_WORD; reg_mask |= 1 << regno; } } current_frame_info.save_fp = (regs_ever_live [GPR_FP] || frame_pointer_needed || interrupt_handler); current_frame_info.save_lr = (regs_ever_live [GPR_LINK] || profile_flag || interrupt_handler); reg_size += (current_frame_info.save_fp + current_frame_info.save_lr) * UNITS_PER_WORD; total_size += reg_size; total_size = ((total_size + 3) & ~3); frame_size = total_size; /* Save computed information. */ current_frame_info.pretend_size = pretend_size; current_frame_info.var_size = var_size; current_frame_info.args_size = args_size; current_frame_info.reg_size = reg_size; current_frame_info.frame_size = args_size + var_size; current_frame_info.total_size = total_size; current_frame_info.extra_size = extra_size; current_frame_info.reg_mask = reg_mask; current_frame_info.initialized = reload_completed; return total_size;}/* Emit code to save REG in stack offset pointed to by MEM. STACK_OFFSET is the offset from the SP where the save will happen. This function sets the REG_FRAME_RELATED_EXPR note accordingly. */static voidmt_emit_save_restore (enum save_direction direction, rtx reg, rtx mem, int stack_offset){ if (direction == FROM_PROCESSOR_TO_MEM) { rtx insn; insn = emit_move_insn (mem, reg); RTX_FRAME_RELATED_P (insn) = 1; REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, gen_rtx_SET (VOIDmode, gen_rtx_MEM (SImode, gen_rtx_PLUS (SImode, stack_pointer_rtx, GEN_INT (stack_offset))), reg), REG_NOTES (insn)); } else emit_move_insn (reg, mem);}/* Emit code to save the frame pointer in the prologue and restore frame pointer in epilogue. */static voidmt_emit_save_fp (enum save_direction direction, struct mt_frame_info info){ rtx base_reg; int reg_mask = info.reg_mask & ~(FP_MASK | LINK_MASK); int offset = info.total_size; int stack_offset = info.total_size; /* If there is nothing to save, get out now. */ if (! info.save_fp && ! info.save_lr && ! reg_mask) return; /* If offset doesn't fit in a 15-bit signed integer, uses a scratch registers to get a smaller offset. */ if (CONST_OK_FOR_LETTER_P(offset, 'O')) base_reg = stack_pointer_rtx; else { /* Use the scratch register R9 that holds old stack pointer. */ base_reg = gen_rtx_REG (SImode, GPR_R9); offset = 0; } if (info.save_fp) { offset -= UNITS_PER_WORD; stack_offset -= UNITS_PER_WORD; mt_emit_save_restore (direction, gen_rtx_REG (SImode, GPR_FP), gen_rtx_MEM (SImode, gen_rtx_PLUS (SImode, base_reg, GEN_INT (offset))), stack_offset); }}/* Emit code to save registers in the prologue and restore register in epilogue. */static voidmt_emit_save_regs (enum save_direction direction, struct mt_frame_info info){ rtx base_reg; int regno; int reg_mask = info.reg_mask & ~(FP_MASK | LINK_MASK); int offset = info.total_size; int stack_offset = info.total_size;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -