Commit e2265be0 by Kaz Kojima Committed by Nick Clifton

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
parent bfcb9121
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
......
/* 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); ...@@ -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);
......
/* 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.
...@@ -273,7 +273,7 @@ init_reg_tables (void) ...@@ -273,7 +273,7 @@ init_reg_tables (void)
m32r_mode_class[i] = 1 << (int) T_MODE; m32r_mode_class[i] = 1 << (int) T_MODE;
else if (GET_MODE_SIZE (i) == 32) else if (GET_MODE_SIZE (i) == 32)
m32r_mode_class[i] = 1 << (int) O_MODE; m32r_mode_class[i] = 1 << (int) O_MODE;
else else
m32r_mode_class[i] = 0; m32r_mode_class[i] = 0;
break; break;
case MODE_FLOAT: case MODE_FLOAT:
...@@ -286,7 +286,7 @@ init_reg_tables (void) ...@@ -286,7 +286,7 @@ init_reg_tables (void)
m32r_mode_class[i] = 1 << (int) TF_MODE; m32r_mode_class[i] = 1 << (int) TF_MODE;
else if (GET_MODE_SIZE (i) == 32) else if (GET_MODE_SIZE (i) == 32)
m32r_mode_class[i] = 1 << (int) OF_MODE; m32r_mode_class[i] = 1 << (int) OF_MODE;
else else
m32r_mode_class[i] = 0; m32r_mode_class[i] = 0;
break; break;
case MODE_CC: case MODE_CC:
...@@ -695,8 +695,8 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) ...@@ -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. */ && CMP_INT16_P (INTVAL (y)) /* Reg equal to small const. */
&& y != const0_rtx) && 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)))); emit_insn (gen_addsi3 (tmp, x, GEN_INT (-INTVAL (y))));
x = tmp; x = tmp;
y = const0_rtx; y = const0_rtx;
...@@ -711,17 +711,17 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) ...@@ -711,17 +711,17 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare)
|| y == const0_rtx) /* Reg equal to zero. */ || y == const0_rtx) /* Reg equal to zero. */
{ {
emit_insn (gen_cmp_eqsi_insn (x, y)); emit_insn (gen_cmp_eqsi_insn (x, y));
return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx); return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx);
} }
break; break;
case LT: case LT:
if (register_operand (y, SImode) if (register_operand (y, SImode)
|| (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y)))) || (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y))))
{ {
rtx tmp = gen_reg_rtx (SImode); /* Reg compared to reg. */ rtx tmp = gen_reg_rtx (SImode); /* Reg compared to reg. */
switch (code) switch (code)
{ {
case LT: case LT:
...@@ -751,17 +751,17 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) ...@@ -751,17 +751,17 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare)
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx); return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx);
} }
break; break;
case LTU: case LTU:
if (register_operand (y, SImode) if (register_operand (y, SImode)
|| (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y)))) || (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y))))
{ {
rtx tmp = gen_reg_rtx (SImode); /* Reg (unsigned) compared to reg. */ rtx tmp = gen_reg_rtx (SImode); /* Reg (unsigned) compared to reg. */
switch (code) switch (code)
{ {
case LTU: case LTU:
...@@ -791,7 +791,7 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) ...@@ -791,7 +791,7 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare)
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx); return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx);
} }
break; break;
...@@ -806,12 +806,12 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) ...@@ -806,12 +806,12 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare)
if (compare_code == EQ if (compare_code == EQ
&& register_operand (y, SImode)) && register_operand (y, SImode))
return gen_rtx_fmt_ee (code, CCmode, x, y); return gen_rtx_fmt_ee (code, CCmode, x, y);
/* Reg/zero signed comparison. */ /* Reg/zero signed comparison. */
if ((compare_code == EQ || compare_code == LT) if ((compare_code == EQ || compare_code == LT)
&& y == const0_rtx) && y == const0_rtx)
return gen_rtx_fmt_ee (code, CCmode, x, y); return gen_rtx_fmt_ee (code, CCmode, x, y);
/* Reg/smallconst equal comparison. */ /* Reg/smallconst equal comparison. */
if (compare_code == EQ if (compare_code == EQ
&& GET_CODE (y) == CONST_INT && GET_CODE (y) == CONST_INT
...@@ -822,7 +822,7 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) ...@@ -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)))); emit_insn (gen_addsi3 (tmp, x, GEN_INT (-INTVAL (y))));
return gen_rtx_fmt_ee (code, CCmode, tmp, const0_rtx); return gen_rtx_fmt_ee (code, CCmode, tmp, const0_rtx);
} }
/* Reg/const equal comparison. */ /* Reg/const equal comparison. */
if (compare_code == EQ if (compare_code == EQ
&& CONSTANT_P (y)) && CONSTANT_P (y))
...@@ -1045,9 +1045,9 @@ m32r_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, ...@@ -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);
...@@ -1191,30 +1191,30 @@ m32r_compute_function_type (tree decl) ...@@ -1191,30 +1191,30 @@ m32r_compute_function_type (tree decl)
| | | | | | | |
SP+0->+-----------------------+ +-----------------------+ SP+0->+-----------------------+ +-----------------------+
| reg parm save area, | | reg parm save area, |
| only created for | | only created for |
| variable argument | | variable argument |
| functions | | functions |
+-----------------------+ +-----------------------+
| previous frame ptr | | previous frame ptr |
+-----------------------+ +-----------------------+
| | | |
| register save area | | register save area |
| | | |
+-----------------------+ +-----------------------+
| return address | | return address |
+-----------------------+ +-----------------------+
| | | |
| local variables | | local variables |
| | | |
+-----------------------+ +-----------------------+
| | | |
| alloca allocations | | alloca allocations |
| | | |
+-----------------------+ +-----------------------+
| | | |
low | arguments on stack | low | arguments on stack |
memory | | memory | |
SP+0->+-----------------------+ SP+0->+-----------------------+
Notes: Notes:
1) The "reg parm save area" does not exist for non variable argument fns. 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; ...@@ -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;
...@@ -1332,25 +1332,25 @@ m32r_compute_frame_size (int size) /* # of var. bytes allocated. */ ...@@ -1332,25 +1332,25 @@ m32r_compute_frame_size (int size) /* # of var. bytes allocated. */
/* The table we use to reference PIC data. */ /* The table we use to reference PIC data. */
static rtx global_offset_table; static rtx global_offset_table;
static void static void
m32r_reload_lr (rtx sp, int size) 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));
...@@ -1362,7 +1362,7 @@ m32r_load_pic_register (void) ...@@ -1362,7 +1362,7 @@ m32r_load_pic_register (void)
global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table, emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,
GEN_INT (TARGET_MODEL_SMALL))); GEN_INT (TARGET_MODEL_SMALL)));
/* Need to emit this whether or not we obey regdecls, /* Need to emit this whether or not we obey regdecls,
since setjmp/longjmp can cause life info to screw up. */ since setjmp/longjmp can cause life info to screw up. */
emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
...@@ -1442,7 +1442,7 @@ m32r_expand_prologue (void) ...@@ -1442,7 +1442,7 @@ m32r_expand_prologue (void)
/* Push lr for mcount (form_pc, x). */ /* Push lr for mcount (form_pc, x). */
emit_insn (gen_movsi_push (stack_pointer_rtx, emit_insn (gen_movsi_push (stack_pointer_rtx,
gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM))); gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM)));
if (pic_reg_used) if (pic_reg_used)
{ {
m32r_load_pic_register (); m32r_load_pic_register ();
...@@ -1481,19 +1481,27 @@ m32r_output_function_prologue (FILE * file, HOST_WIDE_INT size) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
} }
...@@ -1626,14 +1631,14 @@ m32r_legitimate_pic_operand_p (rtx x) ...@@ -1626,14 +1631,14 @@ m32r_legitimate_pic_operand_p (rtx x)
{ {
if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
return 0; return 0;
if (GET_CODE (x) == CONST if (GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
&& (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
|| GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF) || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
&& (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)) && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
return 0; return 0;
return 1; return 1;
} }
...@@ -1773,7 +1778,7 @@ m32r_print_operand (FILE * file, rtx x, int code) ...@@ -1773,7 +1778,7 @@ m32r_print_operand (FILE * file, rtx x, int code)
else else
output_operand_lossage ("invalid operand to %%s code"); output_operand_lossage ("invalid operand to %%s code");
return; return;
case 'p': case 'p':
if (GET_CODE (x) == REG) if (GET_CODE (x) == REG)
fprintf (file, "@%s+", reg_names [REGNO (x)]); fprintf (file, "@%s+", reg_names [REGNO (x)]);
...@@ -2096,14 +2101,14 @@ emit_cond_move (rtx * operands, rtx insn ATTRIBUTE_UNUSED) ...@@ -2096,14 +2101,14 @@ emit_cond_move (rtx * operands, rtx insn ATTRIBUTE_UNUSED)
{ {
static char buffer [100]; static char buffer [100];
const char * dest = reg_names [REGNO (operands [0])]; const char * dest = reg_names [REGNO (operands [0])];
buffer [0] = 0; buffer [0] = 0;
/* Destination must be a register. */ /* Destination must be a register. */
gcc_assert (GET_CODE (operands [0]) == REG); gcc_assert (GET_CODE (operands [0]) == REG);
gcc_assert (conditional_move_operand (operands [2], SImode)); gcc_assert (conditional_move_operand (operands [2], SImode));
gcc_assert (conditional_move_operand (operands [3], SImode)); gcc_assert (conditional_move_operand (operands [3], SImode));
/* Check to see if the test is reversed. */ /* Check to see if the test is reversed. */
if (GET_CODE (operands [1]) == NE) if (GET_CODE (operands [1]) == NE)
{ {
...@@ -2130,19 +2135,19 @@ m32r_not_same_reg (rtx a, rtx b) ...@@ -2130,19 +2135,19 @@ m32r_not_same_reg (rtx a, rtx b)
{ {
int reg_a = -1; int reg_a = -1;
int reg_b = -2; int reg_b = -2;
while (GET_CODE (a) == SUBREG) while (GET_CODE (a) == SUBREG)
a = SUBREG_REG (a); a = SUBREG_REG (a);
if (GET_CODE (a) == REG) if (GET_CODE (a) == REG)
reg_a = REGNO (a); reg_a = REGNO (a);
while (GET_CODE (b) == SUBREG) while (GET_CODE (b) == SUBREG)
b = SUBREG_REG (b); b = SUBREG_REG (b);
if (GET_CODE (b) == REG) if (GET_CODE (b) == REG)
reg_b = REGNO (b); reg_b = REGNO (b);
return reg_a != reg_b; return reg_a != reg_b;
} }
...@@ -2163,7 +2168,7 @@ m32r_function_symbol (const char *name) ...@@ -2163,7 +2168,7 @@ m32r_function_symbol (const char *name)
else else
gcc_unreachable (); /* Shouldn't happen. */ gcc_unreachable (); /* Shouldn't happen. */
extra_flags |= model << SYMBOL_FLAG_MODEL_SHIFT; extra_flags |= model << SYMBOL_FLAG_MODEL_SHIFT;
if (extra_flags) if (extra_flags)
SYMBOL_REF_FLAGS (sym) |= extra_flags; SYMBOL_REF_FLAGS (sym) |= extra_flags;
...@@ -2232,7 +2237,7 @@ m32r_expand_block_move (rtx operands[]) ...@@ -2232,7 +2237,7 @@ m32r_expand_block_move (rtx operands[])
leftover = bytes % MAX_MOVE_BYTES; leftover = bytes % MAX_MOVE_BYTES;
bytes -= leftover; bytes -= leftover;
/* If necessary, generate a loop to handle the bulk of the copy. */ /* If necessary, generate a loop to handle the bulk of the copy. */
if (bytes) if (bytes)
{ {
...@@ -2272,7 +2277,7 @@ m32r_expand_block_move (rtx operands[]) ...@@ -2272,7 +2277,7 @@ m32r_expand_block_move (rtx operands[])
emit_move_insn (dst_reg, new_dst_reg); emit_move_insn (dst_reg, new_dst_reg);
emit_move_insn (src_reg, new_src_reg); emit_move_insn (src_reg, new_src_reg);
emit_insn (gen_addsi3 (dst_reg, dst_reg, GEN_INT (4))); emit_insn (gen_addsi3 (dst_reg, dst_reg, GEN_INT (4)));
if (bytes > MAX_MOVE_BYTES) if (bytes > MAX_MOVE_BYTES)
{ {
emit_insn (gen_cmpsi (src_reg, final_src)); emit_insn (gen_cmpsi (src_reg, final_src));
...@@ -2288,7 +2293,7 @@ m32r_expand_block_move (rtx operands[]) ...@@ -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[0] is the memory address of the destination.
operands[1] is the memory address of the source. operands[1] is the memory address of the source.
...@@ -2302,17 +2307,17 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[]) ...@@ -2302,17 +2307,17 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
HOST_WIDE_INT bytes = INTVAL (operands[2]); HOST_WIDE_INT bytes = INTVAL (operands[2]);
int first_time; int first_time;
int got_extra = 0; int got_extra = 0;
gcc_assert (bytes >= 1 && bytes <= MAX_MOVE_BYTES); gcc_assert (bytes >= 1 && bytes <= MAX_MOVE_BYTES);
/* We do not have a post-increment store available, so the first set of /* 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 stores are done without any increment, then the remaining ones can use
the pre-increment addressing mode. the pre-increment addressing mode.
Note: expand_block_move() also relies upon this behavior when building Note: expand_block_move() also relies upon this behavior when building
loops to copy large blocks. */ loops to copy large blocks. */
first_time = 1; first_time = 1;
while (bytes > 0) while (bytes > 0)
{ {
if (bytes >= 8) if (bytes >= 8)
...@@ -2338,12 +2343,12 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[]) ...@@ -2338,12 +2343,12 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
{ {
if (bytes > 4) if (bytes > 4)
got_extra = 1; got_extra = 1;
output_asm_insn ("ld\t%5, %p1", operands); output_asm_insn ("ld\t%5, %p1", operands);
if (got_extra) if (got_extra)
output_asm_insn ("ld\t%6, %p1", operands); output_asm_insn ("ld\t%6, %p1", operands);
if (first_time) if (first_time)
output_asm_insn ("st\t%5, @%0", operands); output_asm_insn ("st\t%5, @%0", operands);
else else
...@@ -2351,7 +2356,7 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[]) ...@@ -2351,7 +2356,7 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
bytes -= 4; bytes -= 4;
} }
else else
{ {
/* Get the entire next word, even though we do not want all of it. /* 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 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[]) ...@@ -2381,7 +2386,7 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
my_operands[1] = GEN_INT (dst_offset); my_operands[1] = GEN_INT (dst_offset);
my_operands[2] = operands[0]; my_operands[2] = operands[0];
output_asm_insn ("sth\t%0, @(%1,%2)", my_operands); output_asm_insn ("sth\t%0, @(%1,%2)", my_operands);
/* If there is a byte left to store then increment the /* If there is a byte left to store then increment the
destination address and shift the contents of the source destination address and shift the contents of the source
register down by 8 bits. We could not do the address 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[]) ...@@ -2417,7 +2422,7 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
my_operands[1] = GEN_INT (dst_inc_amount); my_operands[1] = GEN_INT (dst_inc_amount);
output_asm_insn ("addi\t%0, #%1", my_operands); output_asm_insn ("addi\t%0, #%1", my_operands);
} }
/* Update the source pointer if needed. We have to do this /* Update the source pointer if needed. We have to do this
so that the patterns matches what we output in this so that the patterns matches what we output in this
function. */ function. */
...@@ -2428,7 +2433,7 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[]) ...@@ -2428,7 +2433,7 @@ m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
my_operands[1] = GEN_INT (src_inc_amount); my_operands[1] = GEN_INT (src_inc_amount);
output_asm_insn ("addi\t%0, #%1", my_operands); output_asm_insn ("addi\t%0, #%1", my_operands);
} }
bytes = 0; bytes = 0;
} }
...@@ -2447,11 +2452,6 @@ m32r_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED, ...@@ -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;
} }
...@@ -2460,6 +2460,6 @@ m32r_return_addr (int count) ...@@ -2460,6 +2460,6 @@ m32r_return_addr (int count)
{ {
if (count != 0) if (count != 0)
return const0_rtx; return const0_rtx;
return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM);
} }
;; 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.
...@@ -200,7 +200,7 @@ ...@@ -200,7 +200,7 @@
(include "predicates.md") (include "predicates.md")
;; Expand prologue as RTL ;; Expand prologue as RTL
(define_expand "prologue" (define_expand "prologue"
[(const_int 1)] [(const_int 1)]
...@@ -211,6 +211,16 @@ ...@@ -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.
;; ;;
...@@ -1166,7 +1176,7 @@ ...@@ -1166,7 +1176,7 @@
;; Compare instructions. ;; Compare instructions.
;; This controls RTL generation and register allocation. ;; 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 ;; patterns store away the operands. Then the bcc patterns
;; emit RTL for both the compare and the branch. ;; emit RTL for both the compare and the branch.
;; ;;
...@@ -1795,7 +1805,7 @@ ...@@ -1795,7 +1805,7 @@
(set (match_dup 0) (set (match_dup 0)
(ne:SI (reg:CC 17) (const_int 0)))] (ne:SI (reg:CC 17) (const_int 0)))]
"") "")
(define_expand "slt" (define_expand "slt"
[(match_operand:SI 0 "register_operand" "")] [(match_operand:SI 0 "register_operand" "")]
"" ""
...@@ -2270,13 +2280,47 @@ ...@@ -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 "" "")))])]
...@@ -2367,7 +2411,7 @@ ...@@ -2367,7 +2411,7 @@
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(clobber (reg:SI 14))])] (clobber (reg:SI 14))])]
"" ""
" "
{ {
if (flag_pic) if (flag_pic)
current_function_uses_pic_offset_table = 1; current_function_uses_pic_offset_table = 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment