📄 fr30.c
字号:
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp)); } } if (current_frame_info.save_fp) emit_insn (gen_movsi_pop (frame_pointer_rtx)); /* Pop all the registers that were pushed. */ if (current_frame_info.save_rp) emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM))); for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++) if (current_frame_info.gmask & (1 << regno)) emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno))); if (current_frame_info.pretend_size) emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size))); /* Reset state info for each function. */ current_frame_info = zero_frame_info; emit_jump_insn (gen_return_from_func ());}/* Do any needed setup for a variadic function. We must create a register parameter block, and then copy any anonymous arguments, plus the last named argument, from registers into memory. * copying actually done in fr30_expand_prologue(). ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument which has type TYPE and mode MODE, and we rely on this fact. */voidfr30_setup_incoming_varargs (arg_regs_used_so_far, int_mode, type, pretend_size) CUMULATIVE_ARGS arg_regs_used_so_far; int int_mode; tree type ATTRIBUTE_UNUSED; int * pretend_size;{ enum machine_mode mode = (enum machine_mode)int_mode; int size; /* All BLKmode values are passed by reference. */ if (mode == BLKmode) abort ();#if STRICT_ARGUMENT_NAMING /* If STRICT_ARGUMENT_NAMING is true then the last named arg must not be treated as an anonymous arg. */ arg_regs_used_so_far += fr30_num_arg_regs (int_mode, type);#endif size = FR30_NUM_ARG_REGS - arg_regs_used_so_far; if (size <= 0) return; * pretend_size = (size * UNITS_PER_WORD);}/*}}}*//*{{{ Printing operands */ /* Print a memory address as an operand to reference that memory location. */voidfr30_print_operand_address (stream, address) FILE * stream; rtx address;{ switch (GET_CODE (address)) { case SYMBOL_REF: output_addr_const (stream, address); break; default: fprintf (stderr, "code = %x\n", GET_CODE (address)); debug_rtx (address); output_operand_lossage ("fr30_print_operand_address: unhandled address"); break; }}/* Print an operand. */voidfr30_print_operand (file, x, code) 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, "%d", 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, "%d", 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: if ((unsigned) REGNO (x0) >= ARRAY_SIZE (reg_names)) abort (); 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, #%d)", 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, #%d)", 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 */ /* 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 (int_mode, type) int int_mode; tree type;{ enum machine_mode mode = (enum machine_mode) int_mode; int size; if (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;}/* Implements the FUNCTION_ARG_PARTIAL_NREGS macro. Returns the number of argument registers required to hold *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 entirly 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. */intfr30_function_arg_partial_nregs (cum, int_mode, type, named) CUMULATIVE_ARGS cum; int int_mode; tree type; int named;{ /* Unnamed arguments, ie 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 (int_mode, type) <= FR30_NUM_ARG_REGS) return 0; /* Otherwise return the number of registers that would be used. */ return FR30_NUM_ARG_REGS - cum;}static rtxfr30_pass_by_reference (valist, type) tree valist; tree type;{ tree type_ptr; tree type_ptr_ptr; tree t; type_ptr = build_pointer_type (type); type_ptr_ptr = build_pointer_type (type_ptr); t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (UNITS_PER_WORD, 0)); TREE_SIDE_EFFECTS (t) = 1; t = build1 (NOP_EXPR, type_ptr_ptr, t); TREE_SIDE_EFFECTS (t) = 1; t = build1 (INDIRECT_REF, type_ptr, t); return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);}static rtxfr30_pass_by_value (valist, type) tree valist; tree type;{ HOST_WIDE_INT size = int_size_in_bytes (type); HOST_WIDE_INT rsize; rtx addr_rtx; tree t;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -