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.
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue