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:
parent
bfcb912149
commit
e2265be077
|
@ -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>
|
||||
|
||||
PR target/30485
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
@ -1045,7 +1045,7 @@ 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,
|
||||
regblock = gen_frame_mem (BLKmode,
|
||||
plus_constant (arg_pointer_rtx,
|
||||
FIRST_PARM_OFFSET (0)));
|
||||
set_mem_alias_set (regblock, get_varargs_alias_set ());
|
||||
|
@ -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;
|
||||
|
@ -1339,9 +1339,9 @@ 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,
|
||||
emit_insn (gen_movsi (lr, gen_frame_mem (Pmode,
|
||||
gen_rtx_PLUS (Pmode, sp,
|
||||
GEN_INT (size)))));
|
||||
else
|
||||
|
@ -1350,7 +1350,7 @@ m32r_reload_lr (rtx sp, int size)
|
|||
|
||||
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));
|
||||
|
@ -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_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (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_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,6 +1614,9 @@ 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 ());
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
;;
|
||||
|
@ -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 "" "")))])]
|
||||
|
|
Loading…
Reference in New Issue