summaryrefslogtreecommitdiff
path: root/gcc/config/m32r/m32r.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/m32r/m32r.c')
-rw-r--r--gcc/config/m32r/m32r.c270
1 files changed, 135 insertions, 135 deletions
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);
}