From 58f4ce52a1be9bd6554b62589e433797b3120a82 Mon Sep 17 00:00:00 2001 From: nickc Date: Thu, 18 Jan 2007 17:04:21 +0000 Subject: [PATCH] * config/m32r/m32r-protos.h (m32r_expand_epilogue): Declare it. * config/m32r/m32r.c (m32r_setup_incoming_varargs): Use gen_frame_mem. (m32r_compute_frame_size): Use unsigned for regno. (m32r_reload_lr): Use gen_frame_mem. (pop): New. (m32r_output_function_epilogue): Don't output the function epilogue textually here. (m32r_expand_epilogue): New. (direct_return): Return false if the function has the interrupt attribute. (m32r_hard_regno_rename_ok): Remove code for the textual epilogue. * config/m32r/m32r.md (epilogue): New expander. (return_lr, return_rte): New insns. (return): Make it expander. (return_normal): New expander. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120904 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 18 +++ gcc/config/m32r/m32r-protos.h | 3 +- gcc/config/m32r/m32r.c | 270 +++++++++++++++++++++--------------------- gcc/config/m32r/m32r.md | 64 ++++++++-- 4 files changed, 209 insertions(+), 146 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index af089fe9889..c54f4a67cbb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2007-01-18 Kaz Kojima + + * config/m32r/m32r-protos.h (m32r_expand_epilogue): Declare it. + * config/m32r/m32r.c (m32r_setup_incoming_varargs): Use gen_frame_mem. + (m32r_compute_frame_size): Use unsigned for regno. + (m32r_reload_lr): Use gen_frame_mem. + (pop): New. + (m32r_output_function_epilogue): Don't output the function epilogue + textually here. + (m32r_expand_epilogue): New. + (direct_return): Return false if the function has the interrupt + attribute. + (m32r_hard_regno_rename_ok): Remove code for the textual epilogue. + * config/m32r/m32r.md (epilogue): New expander. + (return_lr, return_rte): New insns. + (return): Make it expander. + (return_normal): New expander. + 2007-01-18 Josh Conner PR target/30485 diff --git a/gcc/config/m32r/m32r-protos.h b/gcc/config/m32r/m32r-protos.h index ee03a1e4cd7..f6cd29cf31c 100644 --- a/gcc/config/m32r/m32r-protos.h +++ b/gcc/config/m32r/m32r-protos.h @@ -1,5 +1,5 @@ /* Prototypes for m32r.c functions used in the md file & elsewhere. - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -27,6 +27,7 @@ extern void m32r_init (void); extern void m32r_init_expanders (void); extern unsigned m32r_compute_frame_size (int); extern void m32r_expand_prologue (void); +extern void m32r_expand_epilogue (void); extern int direct_return (void); extern void m32r_load_pic_register (void); diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index a4d20397bc2..9b288f319a1 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -1,6 +1,6 @@ /* Subroutines used for code generation on the Renesas M32R cpu. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005 Free Software Foundation, Inc. + 2005, 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -273,7 +273,7 @@ init_reg_tables (void) m32r_mode_class[i] = 1 << (int) T_MODE; else if (GET_MODE_SIZE (i) == 32) m32r_mode_class[i] = 1 << (int) O_MODE; - else + else m32r_mode_class[i] = 0; break; case MODE_FLOAT: @@ -286,7 +286,7 @@ init_reg_tables (void) m32r_mode_class[i] = 1 << (int) TF_MODE; else if (GET_MODE_SIZE (i) == 32) m32r_mode_class[i] = 1 << (int) OF_MODE; - else + else m32r_mode_class[i] = 0; break; case MODE_CC: @@ -695,8 +695,8 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) && CMP_INT16_P (INTVAL (y)) /* Reg equal to small const. */ && y != const0_rtx) { - rtx tmp = gen_reg_rtx (SImode); - + rtx tmp = gen_reg_rtx (SImode); + emit_insn (gen_addsi3 (tmp, x, GEN_INT (-INTVAL (y)))); x = tmp; y = const0_rtx; @@ -711,17 +711,17 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) || y == const0_rtx) /* Reg equal to zero. */ { emit_insn (gen_cmp_eqsi_insn (x, y)); - + return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx); } break; - + case LT: if (register_operand (y, SImode) || (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y)))) { rtx tmp = gen_reg_rtx (SImode); /* Reg compared to reg. */ - + switch (code) { case LT: @@ -751,17 +751,17 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) default: gcc_unreachable (); } - + return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx); } break; - + case LTU: if (register_operand (y, SImode) || (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y)))) { rtx tmp = gen_reg_rtx (SImode); /* Reg (unsigned) compared to reg. */ - + switch (code) { case LTU: @@ -791,7 +791,7 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) default: gcc_unreachable (); } - + return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx); } break; @@ -806,12 +806,12 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) if (compare_code == EQ && register_operand (y, SImode)) return gen_rtx_fmt_ee (code, CCmode, x, y); - + /* Reg/zero signed comparison. */ if ((compare_code == EQ || compare_code == LT) && y == const0_rtx) return gen_rtx_fmt_ee (code, CCmode, x, y); - + /* Reg/smallconst equal comparison. */ if (compare_code == EQ && GET_CODE (y) == CONST_INT @@ -822,7 +822,7 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) emit_insn (gen_addsi3 (tmp, x, GEN_INT (-INTVAL (y)))); return gen_rtx_fmt_ee (code, CCmode, tmp, const0_rtx); } - + /* Reg/const equal comparison. */ if (compare_code == EQ && CONSTANT_P (y)) @@ -1045,9 +1045,9 @@ m32r_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, int size = M32R_MAX_PARM_REGS - first_reg_offset; rtx regblock; - regblock = gen_rtx_MEM (BLKmode, - plus_constant (arg_pointer_rtx, - FIRST_PARM_OFFSET (0))); + regblock = gen_frame_mem (BLKmode, + plus_constant (arg_pointer_rtx, + FIRST_PARM_OFFSET (0))); set_mem_alias_set (regblock, get_varargs_alias_set ()); move_block_from_reg (first_reg_offset, regblock, size); @@ -1191,30 +1191,30 @@ m32r_compute_function_type (tree decl) | | | | SP+0->+-----------------------+ +-----------------------+ | reg parm save area, | - | only created for | - | variable argument | - | functions | + | only created for | + | variable argument | + | functions | +-----------------------+ | previous frame ptr | - +-----------------------+ - | | - | register save area | - | | + +-----------------------+ + | | + | register save area | + | | +-----------------------+ - | return address | - +-----------------------+ - | | - | local variables | - | | - +-----------------------+ - | | - | alloca allocations | - | | - +-----------------------+ - | | - low | arguments on stack | - memory | | - SP+0->+-----------------------+ + | return address | + +-----------------------+ + | | + | local variables | + | | + +-----------------------+ + | | + | alloca allocations | + | | + +-----------------------+ + | | + low | arguments on stack | + memory | | + SP+0->+-----------------------+ Notes: 1) The "reg parm save area" does not exist for non variable argument fns. @@ -1270,7 +1270,7 @@ static struct m32r_frame_info zero_frame_info; unsigned int m32r_compute_frame_size (int size) /* # of var. bytes allocated. */ { - int regno; + unsigned int regno; unsigned int total_size, var_size, args_size, pretend_size, extra_size; unsigned int reg_size, frame_size; unsigned int gmask; @@ -1332,25 +1332,25 @@ m32r_compute_frame_size (int size) /* # of var. bytes allocated. */ /* The table we use to reference PIC data. */ static rtx global_offset_table; - + static void m32r_reload_lr (rtx sp, int size) { rtx lr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); if (size == 0) - emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode, sp))); + emit_insn (gen_movsi (lr, gen_frame_mem (Pmode, sp))); else if (size < 32768) - emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode, - gen_rtx_PLUS (Pmode, sp, - GEN_INT (size))))); + emit_insn (gen_movsi (lr, gen_frame_mem (Pmode, + gen_rtx_PLUS (Pmode, sp, + GEN_INT (size))))); else - { + { rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM); emit_insn (gen_movsi (tmp, GEN_INT (size))); emit_insn (gen_addsi3 (tmp, tmp, sp)); - emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode, tmp))); + emit_insn (gen_movsi (lr, gen_frame_mem (Pmode, tmp))); } emit_insn (gen_rtx_USE (VOIDmode, lr)); @@ -1362,7 +1362,7 @@ m32r_load_pic_register (void) global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table, GEN_INT (TARGET_MODEL_SMALL))); - + /* Need to emit this whether or not we obey regdecls, since setjmp/longjmp can cause life info to screw up. */ emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); @@ -1442,7 +1442,7 @@ m32r_expand_prologue (void) /* Push lr for mcount (form_pc, x). */ emit_insn (gen_movsi_push (stack_pointer_rtx, gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM))); - + if (pic_reg_used) { m32r_load_pic_register (); @@ -1481,19 +1481,27 @@ m32r_output_function_prologue (FILE * file, HOST_WIDE_INT size) current_frame_info.extra_size); } -/* Do any necessary cleanup after a function to restore stack, frame, - and regs. */ +/* Output RTL to pop register REGNO from the stack. */ static void -m32r_output_function_epilogue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) +pop (int regno) +{ + rtx x; + + x = emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno), + stack_pointer_rtx)); + REG_NOTES (x) + = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, 0); +} + +/* Expand the m32r epilogue as a series of insns. */ + +void +m32r_expand_epilogue (void) { int regno; int noepilogue = FALSE; int total_size; - enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl); - - /* This is only for the human reader. */ - fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START); gcc_assert (current_frame_info.initialized); total_size = current_frame_info.total_size; @@ -1504,7 +1512,7 @@ m32r_output_function_epilogue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) /* If the last insn was a BARRIER, we don't have to write any code because a jump (aka return) was put there. */ - if (GET_CODE (insn) == NOTE) + if (insn && GET_CODE (insn) == NOTE) insn = prev_nonnote_insn (insn); if (insn && GET_CODE (insn) == BARRIER) noepilogue = TRUE; @@ -1516,88 +1524,82 @@ m32r_output_function_epilogue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) unsigned int args_size = current_frame_info.args_size; unsigned int gmask = current_frame_info.gmask; int can_trust_sp_p = !current_function_calls_alloca; - const char * sp_str = reg_names[STACK_POINTER_REGNUM]; - const char * fp_str = reg_names[FRAME_POINTER_REGNUM]; + + if (flag_exceptions) + emit_insn (gen_blockage ()); /* The first thing to do is point the sp at the bottom of the register save area. */ if (can_trust_sp_p) { unsigned int reg_offset = var_size + args_size; + if (reg_offset == 0) ; /* Nothing to do. */ - else if (reg_offset < 128) - fprintf (file, "\taddi %s,%s%d\n", - sp_str, IMMEDIATE_PREFIX, reg_offset); else if (reg_offset < 32768) - fprintf (file, "\tadd3 %s,%s,%s%d\n", - sp_str, sp_str, IMMEDIATE_PREFIX, reg_offset); - else if (reg_offset < (1 << 24)) - fprintf (file, "\tld24 %s,%s%d\n\tadd %s,%s\n", - reg_names[PROLOGUE_TMP_REGNUM], - IMMEDIATE_PREFIX, reg_offset, - sp_str, reg_names[PROLOGUE_TMP_REGNUM]); + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (reg_offset))); else - fprintf (file, "\tseth %s,%s%d\n\tor3 %s,%s,%s%d\n\tadd %s,%s\n", - reg_names[PROLOGUE_TMP_REGNUM], - IMMEDIATE_PREFIX, reg_offset >> 16, - reg_names[PROLOGUE_TMP_REGNUM], - reg_names[PROLOGUE_TMP_REGNUM], - IMMEDIATE_PREFIX, reg_offset & 0xffff, - sp_str, reg_names[PROLOGUE_TMP_REGNUM]); + { + rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM); + + emit_insn (gen_movsi (tmp, GEN_INT (reg_offset))); + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, + tmp)); + } } else if (frame_pointer_needed) { unsigned int reg_offset = var_size + args_size; if (reg_offset == 0) - fprintf (file, "\tmv %s,%s\n", sp_str, fp_str); + emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx)); else if (reg_offset < 32768) - fprintf (file, "\tadd3 %s,%s,%s%d\n", - sp_str, fp_str, IMMEDIATE_PREFIX, reg_offset); - else if (reg_offset < (1 << 24)) - fprintf (file, "\tld24 %s,%s%d\n\tadd %s,%s\n", - reg_names[PROLOGUE_TMP_REGNUM], - IMMEDIATE_PREFIX, reg_offset, - sp_str, reg_names[PROLOGUE_TMP_REGNUM]); + emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx, + GEN_INT (reg_offset))); else - fprintf (file, "\tseth %s,%s%d\n\tor3 %s,%s,%s%d\n\tadd %s,%s\n", - reg_names[PROLOGUE_TMP_REGNUM], - IMMEDIATE_PREFIX, reg_offset >> 16, - reg_names[PROLOGUE_TMP_REGNUM], - reg_names[PROLOGUE_TMP_REGNUM], - IMMEDIATE_PREFIX, reg_offset & 0xffff, - sp_str, reg_names[PROLOGUE_TMP_REGNUM]); + { + rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM); + + emit_insn (gen_movsi (tmp, GEN_INT (reg_offset))); + emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx)); + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, + tmp)); + } } else gcc_unreachable (); if (current_frame_info.save_lr) - fprintf (file, "\tpop %s\n", reg_names[RETURN_ADDR_REGNUM]); + pop (RETURN_ADDR_REGNUM); /* Restore any saved registers, in reverse order of course. */ gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK); for (regno = M32R_MAX_INT_REGS - 1; regno >= 0; --regno) { if ((gmask & (1L << regno)) != 0) - fprintf (file, "\tpop %s\n", reg_names[regno]); + pop (regno); } if (current_frame_info.save_fp) - fprintf (file, "\tpop %s\n", fp_str); + pop (FRAME_POINTER_REGNUM); /* Remove varargs area if present. */ if (current_frame_info.pretend_size != 0) - fprintf (file, "\taddi %s,%s%d\n", - sp_str, IMMEDIATE_PREFIX, current_frame_info.pretend_size); - - /* Emit the return instruction. */ - if (M32R_INTERRUPT_P (fn_type)) - fprintf (file, "\trte\n"); - else - fprintf (file, "\tjmp %s\n", reg_names[RETURN_ADDR_REGNUM]); + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (current_frame_info.pretend_size))); + + emit_insn (gen_blockage ()); } +} + +/* Do any necessary cleanup after a function to restore stack, frame, + and regs. */ +static void +m32r_output_function_epilogue (FILE * file ATTRIBUTE_UNUSED, + HOST_WIDE_INT size ATTRIBUTE_UNUSED) +{ /* Reset state info for each function. */ current_frame_info = zero_frame_info; m32r_compute_function_type (NULL_TREE); @@ -1612,10 +1614,13 @@ direct_return (void) if (!reload_completed) return FALSE; + if (M32R_INTERRUPT_P (m32r_compute_function_type (current_function_decl))) + return FALSE; + if (! current_frame_info.initialized) m32r_compute_frame_size (get_frame_size ()); - return current_frame_info.total_size == 0; + return current_frame_info.total_size == 0; } @@ -1626,14 +1631,14 @@ m32r_legitimate_pic_operand_p (rtx x) { if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) return 0; - + if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF) && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)) return 0; - + return 1; } @@ -1773,7 +1778,7 @@ m32r_print_operand (FILE * file, rtx x, int code) else output_operand_lossage ("invalid operand to %%s code"); return; - + case 'p': if (GET_CODE (x) == REG) fprintf (file, "@%s+", reg_names [REGNO (x)]); @@ -2096,14 +2101,14 @@ emit_cond_move (rtx * operands, rtx insn ATTRIBUTE_UNUSED) { static char buffer [100]; const char * dest = reg_names [REGNO (operands [0])]; - + buffer [0] = 0; - + /* Destination must be a register. */ gcc_assert (GET_CODE (operands [0]) == REG); gcc_assert (conditional_move_operand (operands [2], SImode)); gcc_assert (conditional_move_operand (operands [3], SImode)); - + /* Check to see if the test is reversed. */ if (GET_CODE (operands [1]) == NE) { @@ -2130,19 +2135,19 @@ m32r_not_same_reg (rtx a, rtx b) { int reg_a = -1; int reg_b = -2; - + while (GET_CODE (a) == SUBREG) a = SUBREG_REG (a); - + if (GET_CODE (a) == REG) reg_a = REGNO (a); - + while (GET_CODE (b) == SUBREG) b = SUBREG_REG (b); - + if (GET_CODE (b) == REG) reg_b = REGNO (b); - + return reg_a != reg_b; } @@ -2163,7 +2168,7 @@ m32r_function_symbol (const char *name) else gcc_unreachable (); /* Shouldn't happen. */ extra_flags |= model << SYMBOL_FLAG_MODEL_SHIFT; - + if (extra_flags) SYMBOL_REF_FLAGS (sym) |= extra_flags; @@ -2232,7 +2237,7 @@ m32r_expand_block_move (rtx operands[]) leftover = bytes % MAX_MOVE_BYTES; bytes -= leftover; - + /* If necessary, generate a loop to handle the bulk of the copy. */ if (bytes) { @@ -2272,7 +2277,7 @@ m32r_expand_block_move (rtx operands[]) emit_move_insn (dst_reg, new_dst_reg); emit_move_insn (src_reg, new_src_reg); emit_insn (gen_addsi3 (dst_reg, dst_reg, GEN_INT (4))); - + if (bytes > MAX_MOVE_BYTES) { emit_insn (gen_cmpsi (src_reg, final_src)); @@ -2288,7 +2293,7 @@ m32r_expand_block_move (rtx operands[]) } -/* Emit load/stores for a small constant word aligned block_move. +/* Emit load/stores for a small constant word aligned block_move. operands[0] is the memory address of the destination. operands[1] is the memory address of the source. @@ -2302,17 +2307,17 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[]) HOST_WIDE_INT bytes = INTVAL (operands[2]); int first_time; int got_extra = 0; - + gcc_assert (bytes >= 1 && bytes <= MAX_MOVE_BYTES); - + /* We do not have a post-increment store available, so the first set of stores are done without any increment, then the remaining ones can use the pre-increment addressing mode. - + Note: expand_block_move() also relies upon this behavior when building loops to copy large blocks. */ first_time = 1; - + while (bytes > 0) { if (bytes >= 8) @@ -2338,12 +2343,12 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[]) { if (bytes > 4) got_extra = 1; - + output_asm_insn ("ld\t%5, %p1", operands); - + if (got_extra) output_asm_insn ("ld\t%6, %p1", operands); - + if (first_time) output_asm_insn ("st\t%5, @%0", operands); else @@ -2351,7 +2356,7 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[]) bytes -= 4; } - else + else { /* Get the entire next word, even though we do not want all of it. The saves us from doing several smaller loads, and we assume that @@ -2381,7 +2386,7 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[]) my_operands[1] = GEN_INT (dst_offset); my_operands[2] = operands[0]; output_asm_insn ("sth\t%0, @(%1,%2)", my_operands); - + /* If there is a byte left to store then increment the destination address and shift the contents of the source register down by 8 bits. We could not do the address @@ -2417,7 +2422,7 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[]) my_operands[1] = GEN_INT (dst_inc_amount); output_asm_insn ("addi\t%0, #%1", my_operands); } - + /* Update the source pointer if needed. We have to do this so that the patterns matches what we output in this function. */ @@ -2428,7 +2433,7 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[]) my_operands[1] = GEN_INT (src_inc_amount); output_asm_insn ("addi\t%0, #%1", my_operands); } - + bytes = 0; } @@ -2447,11 +2452,6 @@ m32r_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED, && !regs_ever_live[new_reg]) return 0; - /* We currently emit epilogues as text, not rtl, so the liveness - of the return address register isn't visible. */ - if (current_function_is_leaf && new_reg == RETURN_ADDR_REGNUM) - return 0; - return 1; } @@ -2460,6 +2460,6 @@ m32r_return_addr (int count) { if (count != 0) return const0_rtx; - + return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); } diff --git a/gcc/config/m32r/m32r.md b/gcc/config/m32r/m32r.md index 552dd3f0ef3..2487dd893e8 100644 --- a/gcc/config/m32r/m32r.md +++ b/gcc/config/m32r/m32r.md @@ -1,6 +1,6 @@ ;; Machine description of the Renesas M32R cpu for GNU C compiler -;; Copyright (C) 1996, 1997, 1998, 1999, 2001, 2003, 2004, 2005 -; Free Software Foundation, Inc. +;; Copyright (C) 1996, 1997, 1998, 1999, 2001, 2003, 2004, 2005, +; 2007 Free Software Foundation, Inc. ;; This file is part of GCC. @@ -200,7 +200,7 @@ (include "predicates.md") - + ;; Expand prologue as RTL (define_expand "prologue" [(const_int 1)] @@ -211,6 +211,16 @@ DONE; }") +;; Expand epilogue as RTL +(define_expand "epilogue" + [(return)] + "" + " +{ + m32r_expand_epilogue (); + emit_jump_insn (gen_return_normal ()); + DONE; +}") ;; Move instructions. ;; @@ -1166,7 +1176,7 @@ ;; Compare instructions. ;; This controls RTL generation and register allocation. -;; We generate RTL for comparisons and branches by having the cmpxx +;; We generate RTL for comparisons and branches by having the cmpxx ;; patterns store away the operands. Then the bcc patterns ;; emit RTL for both the compare and the branch. ;; @@ -1795,7 +1805,7 @@ (set (match_dup 0) (ne:SI (reg:CC 17) (const_int 0)))] "") - + (define_expand "slt" [(match_operand:SI 0 "register_operand" "")] "" @@ -2270,13 +2280,47 @@ [(set_attr "type" "uncond_branch") (set_attr "length" "2")]) -(define_insn "return" - [(return)] - "direct_return ()" +(define_insn "return_lr" + [(parallel [(return) (use (reg:SI 14))])] + "" "jmp lr" [(set_attr "type" "uncond_branch") (set_attr "length" "2")]) - + +(define_insn "return_rte" + [(return)] + "" + "rte" + [(set_attr "type" "uncond_branch") + (set_attr "length" "2")]) + +(define_expand "return" + [(return)] + "direct_return ()" + " +{ + emit_jump_insn (gen_return_lr ()); + DONE; +}") + +(define_expand "return_normal" + [(return)] + "!direct_return ()" + " +{ + enum m32r_function_type fn_type; + + fn_type = m32r_compute_function_type (current_function_decl); + if (M32R_INTERRUPT_P (fn_type)) + { + emit_jump_insn (gen_return_rte ()); + DONE; + } + + emit_jump_insn (gen_return_lr ()); + DONE; +}") + (define_expand "tablejump" [(parallel [(set (pc) (match_operand 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))])] @@ -2367,7 +2411,7 @@ (match_operand 2 "" ""))) (clobber (reg:SI 14))])] "" - " + " { if (flag_pic) current_function_uses_pic_offset_table = 1; -- 2.11.0