m32r-protos.h (m32r_expand_epilogue): Declare it.

* 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.

From-SVN: r120904
This commit is contained in:
Kaz Kojima 2007-01-19 02:04:21 +09:00 committed by Nick Clifton
parent bfcb912149
commit e2265be077
4 changed files with 210 additions and 147 deletions

View File

@ -1,3 +1,21 @@
2007-01-18 Kaz Kojima <kkojima@rr.iij4u.or.jp>
* 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 <jconner@apple.com> 2007-01-18 Josh Conner <jconner@apple.com>
PR target/30485 PR target/30485

View File

@ -1,5 +1,5 @@
/* Prototypes for m32r.c functions used in the md file & elsewhere. /* 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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
@ -27,6 +27,7 @@ extern void m32r_init (void);
extern void m32r_init_expanders (void); extern void m32r_init_expanders (void);
extern unsigned m32r_compute_frame_size (int); extern unsigned m32r_compute_frame_size (int);
extern void m32r_expand_prologue (void); extern void m32r_expand_prologue (void);
extern void m32r_expand_epilogue (void);
extern int direct_return (void); extern int direct_return (void);
extern void m32r_load_pic_register (void); extern void m32r_load_pic_register (void);

View File

@ -1,6 +1,6 @@
/* Subroutines used for code generation on the Renesas M32R cpu. /* Subroutines used for code generation on the Renesas M32R cpu.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 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. This file is part of GCC.
@ -1045,9 +1045,9 @@ m32r_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
int size = M32R_MAX_PARM_REGS - first_reg_offset; int size = M32R_MAX_PARM_REGS - first_reg_offset;
rtx regblock; rtx regblock;
regblock = gen_rtx_MEM (BLKmode, regblock = gen_frame_mem (BLKmode,
plus_constant (arg_pointer_rtx, plus_constant (arg_pointer_rtx,
FIRST_PARM_OFFSET (0))); FIRST_PARM_OFFSET (0)));
set_mem_alias_set (regblock, get_varargs_alias_set ()); set_mem_alias_set (regblock, get_varargs_alias_set ());
move_block_from_reg (first_reg_offset, regblock, size); move_block_from_reg (first_reg_offset, regblock, size);
@ -1270,7 +1270,7 @@ static struct m32r_frame_info zero_frame_info;
unsigned int unsigned int
m32r_compute_frame_size (int size) /* # of var. bytes allocated. */ 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 total_size, var_size, args_size, pretend_size, extra_size;
unsigned int reg_size, frame_size; unsigned int reg_size, frame_size;
unsigned int gmask; unsigned int gmask;
@ -1339,18 +1339,18 @@ m32r_reload_lr (rtx sp, int size)
rtx lr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); rtx lr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
if (size == 0) 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) else if (size < 32768)
emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode, emit_insn (gen_movsi (lr, gen_frame_mem (Pmode,
gen_rtx_PLUS (Pmode, sp, gen_rtx_PLUS (Pmode, sp,
GEN_INT (size))))); GEN_INT (size)))));
else else
{ {
rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM); rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
emit_insn (gen_movsi (tmp, GEN_INT (size))); emit_insn (gen_movsi (tmp, GEN_INT (size)));
emit_insn (gen_addsi3 (tmp, tmp, sp)); 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)); emit_insn (gen_rtx_USE (VOIDmode, lr));
@ -1481,19 +1481,27 @@ m32r_output_function_prologue (FILE * file, HOST_WIDE_INT size)
current_frame_info.extra_size); current_frame_info.extra_size);
} }
/* Do any necessary cleanup after a function to restore stack, frame, /* Output RTL to pop register REGNO from the stack. */
and regs. */
static void 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 regno;
int noepilogue = FALSE; int noepilogue = FALSE;
int total_size; 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); gcc_assert (current_frame_info.initialized);
total_size = current_frame_info.total_size; 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 /* If the last insn was a BARRIER, we don't have to write any code
because a jump (aka return) was put there. */ because a jump (aka return) was put there. */
if (GET_CODE (insn) == NOTE) if (insn && GET_CODE (insn) == NOTE)
insn = prev_nonnote_insn (insn); insn = prev_nonnote_insn (insn);
if (insn && GET_CODE (insn) == BARRIER) if (insn && GET_CODE (insn) == BARRIER)
noepilogue = TRUE; 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 args_size = current_frame_info.args_size;
unsigned int gmask = current_frame_info.gmask; unsigned int gmask = current_frame_info.gmask;
int can_trust_sp_p = !current_function_calls_alloca; 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 /* The first thing to do is point the sp at the bottom of the register
save area. */ save area. */
if (can_trust_sp_p) if (can_trust_sp_p)
{ {
unsigned int reg_offset = var_size + args_size; unsigned int reg_offset = var_size + args_size;
if (reg_offset == 0) if (reg_offset == 0)
; /* Nothing to do. */ ; /* 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) else if (reg_offset < 32768)
fprintf (file, "\tadd3 %s,%s,%s%d\n", emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
sp_str, sp_str, IMMEDIATE_PREFIX, reg_offset); GEN_INT (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]);
else else
fprintf (file, "\tseth %s,%s%d\n\tor3 %s,%s,%s%d\n\tadd %s,%s\n", {
reg_names[PROLOGUE_TMP_REGNUM], rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
IMMEDIATE_PREFIX, reg_offset >> 16,
reg_names[PROLOGUE_TMP_REGNUM], emit_insn (gen_movsi (tmp, GEN_INT (reg_offset)));
reg_names[PROLOGUE_TMP_REGNUM], emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
IMMEDIATE_PREFIX, reg_offset & 0xffff, tmp));
sp_str, reg_names[PROLOGUE_TMP_REGNUM]); }
} }
else if (frame_pointer_needed) else if (frame_pointer_needed)
{ {
unsigned int reg_offset = var_size + args_size; unsigned int reg_offset = var_size + args_size;
if (reg_offset == 0) 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) else if (reg_offset < 32768)
fprintf (file, "\tadd3 %s,%s,%s%d\n", emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx,
sp_str, fp_str, IMMEDIATE_PREFIX, reg_offset); GEN_INT (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]);
else else
fprintf (file, "\tseth %s,%s%d\n\tor3 %s,%s,%s%d\n\tadd %s,%s\n", {
reg_names[PROLOGUE_TMP_REGNUM], rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
IMMEDIATE_PREFIX, reg_offset >> 16,
reg_names[PROLOGUE_TMP_REGNUM], emit_insn (gen_movsi (tmp, GEN_INT (reg_offset)));
reg_names[PROLOGUE_TMP_REGNUM], emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
IMMEDIATE_PREFIX, reg_offset & 0xffff, emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
sp_str, reg_names[PROLOGUE_TMP_REGNUM]); tmp));
}
} }
else else
gcc_unreachable (); gcc_unreachable ();
if (current_frame_info.save_lr) 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. */ /* Restore any saved registers, in reverse order of course. */
gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK); gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK);
for (regno = M32R_MAX_INT_REGS - 1; regno >= 0; --regno) for (regno = M32R_MAX_INT_REGS - 1; regno >= 0; --regno)
{ {
if ((gmask & (1L << regno)) != 0) if ((gmask & (1L << regno)) != 0)
fprintf (file, "\tpop %s\n", reg_names[regno]); pop (regno);
} }
if (current_frame_info.save_fp) if (current_frame_info.save_fp)
fprintf (file, "\tpop %s\n", fp_str); pop (FRAME_POINTER_REGNUM);
/* Remove varargs area if present. */ /* Remove varargs area if present. */
if (current_frame_info.pretend_size != 0) if (current_frame_info.pretend_size != 0)
fprintf (file, "\taddi %s,%s%d\n", emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
sp_str, IMMEDIATE_PREFIX, current_frame_info.pretend_size); GEN_INT (current_frame_info.pretend_size)));
/* Emit the return instruction. */ emit_insn (gen_blockage ());
if (M32R_INTERRUPT_P (fn_type))
fprintf (file, "\trte\n");
else
fprintf (file, "\tjmp %s\n", reg_names[RETURN_ADDR_REGNUM]);
} }
}
/* 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. */ /* Reset state info for each function. */
current_frame_info = zero_frame_info; current_frame_info = zero_frame_info;
m32r_compute_function_type (NULL_TREE); m32r_compute_function_type (NULL_TREE);
@ -1612,10 +1614,13 @@ direct_return (void)
if (!reload_completed) if (!reload_completed)
return FALSE; return FALSE;
if (M32R_INTERRUPT_P (m32r_compute_function_type (current_function_decl)))
return FALSE;
if (! current_frame_info.initialized) if (! current_frame_info.initialized)
m32r_compute_frame_size (get_frame_size ()); m32r_compute_frame_size (get_frame_size ());
return current_frame_info.total_size == 0; return current_frame_info.total_size == 0;
} }
@ -2447,11 +2452,6 @@ m32r_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
&& !regs_ever_live[new_reg]) && !regs_ever_live[new_reg])
return 0; 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; return 1;
} }

View File

@ -1,6 +1,6 @@
;; Machine description of the Renesas M32R cpu for GNU C compiler ;; Machine description of the Renesas M32R cpu for GNU C compiler
;; Copyright (C) 1996, 1997, 1998, 1999, 2001, 2003, 2004, 2005 ;; Copyright (C) 1996, 1997, 1998, 1999, 2001, 2003, 2004, 2005,
; Free Software Foundation, Inc. ; 2007 Free Software Foundation, Inc.
;; This file is part of GCC. ;; This file is part of GCC.
@ -211,6 +211,16 @@
DONE; DONE;
}") }")
;; Expand epilogue as RTL
(define_expand "epilogue"
[(return)]
""
"
{
m32r_expand_epilogue ();
emit_jump_insn (gen_return_normal ());
DONE;
}")
;; Move instructions. ;; Move instructions.
;; ;;
@ -2270,13 +2280,47 @@
[(set_attr "type" "uncond_branch") [(set_attr "type" "uncond_branch")
(set_attr "length" "2")]) (set_attr "length" "2")])
(define_insn "return" (define_insn "return_lr"
[(return)] [(parallel [(return) (use (reg:SI 14))])]
"direct_return ()" ""
"jmp lr" "jmp lr"
[(set_attr "type" "uncond_branch") [(set_attr "type" "uncond_branch")
(set_attr "length" "2")]) (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" (define_expand "tablejump"
[(parallel [(set (pc) (match_operand 0 "register_operand" "r")) [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))])] (use (label_ref (match_operand 1 "" "")))])]