/* Output routines for GCC for Renesas / SuperH SH.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com).
Improved by Jim Wilson (wilson@cygnus.com).
#include "insn-attr.h"
#include "toplev.h"
#include "recog.h"
-#include "c-pragma.h"
#include "integrate.h"
#include "dwarf2.h"
#include "tm_p.h"
#include "intl.h"
#include "sched-int.h"
#include "ggc.h"
-#include "tree-gimple.h"
+#include "gimple.h"
#include "cfgloop.h"
#include "alloc-pool.h"
#include "tm-constrs.h"
static bool sh_function_ok_for_sibcall (tree, tree);
static bool sh_cannot_modify_jumps_p (void);
-static int sh_target_reg_class (void);
+static enum reg_class sh_target_reg_class (void);
static bool sh_optimize_target_register_callee_saved (bool);
static bool sh_ms_bitfield_layout_p (const_tree);
static int multcosts (rtx);
static bool unspec_caller_rtx_p (rtx);
static bool sh_cannot_copy_insn_p (rtx);
-static bool sh_rtx_costs (rtx, int, int, int *);
-static int sh_address_cost (rtx);
+static bool sh_rtx_costs (rtx, int, int, int *, bool);
+static int sh_address_cost (rtx, bool);
static int sh_pr_n_sets (void);
static rtx sh_allocate_initial_value (rtx);
+static rtx sh_legitimize_address (rtx, rtx, enum machine_mode);
static int shmedia_target_regs_stack_space (HARD_REG_SET *);
static int shmedia_reserve_space_for_target_registers_p (int, HARD_REG_SET *);
static int shmedia_target_regs_stack_adjust (HARD_REG_SET *);
static bool sh_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *);
static tree sh_build_builtin_va_list (void);
static void sh_va_start (tree, rtx);
-static tree sh_gimplify_va_arg_expr (tree, tree, tree *, tree *);
+static tree sh_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
static bool sh_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
const_tree, bool);
static bool sh_callee_copies (CUMULATIVE_ARGS *, enum machine_mode,
#undef TARGET_SCHED_INIT
#define TARGET_SCHED_INIT sh_md_init
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS sh_legitimize_address
+
#undef TARGET_CANNOT_MODIFY_JUMPS_P
#define TARGET_CANNOT_MODIFY_JUMPS_P sh_cannot_modify_jumps_p
#undef TARGET_BRANCH_TARGET_REGISTER_CLASS
#undef TARGET_MACHINE_DEPENDENT_REORG
#define TARGET_MACHINE_DEPENDENT_REORG sh_reorg
+#undef TARGET_DWARF_REGISTER_SPAN
+#define TARGET_DWARF_REGISTER_SPAN sh_dwarf_register_span
+
#ifdef HAVE_AS_TLS
#undef TARGET_HAVE_TLS
#define TARGET_HAVE_TLS true
output_address (XEXP (x, 0));
break;
- case CONST:
- if (TARGET_SHMEDIA
- && (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
- || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND)
- && (GET_MODE (XEXP (x, 0)) == DImode
- || GET_MODE (XEXP (x, 0)) == SImode)
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == TRUNCATE
- && GET_MODE (XEXP (XEXP (x, 0), 0)) == HImode)
- {
- rtx val = XEXP (XEXP (XEXP (x, 0), 0), 0);
- rtx val2 = val;
- bool nested_expr = false;
-
- fputc ('(', stream);
- if (GET_CODE (val) == ASHIFTRT)
- {
- fputc ('(', stream);
- val2 = XEXP (val, 0);
- }
- if (GET_CODE (val2) == CONST
- || GET_RTX_CLASS (GET_CODE (val2)) != RTX_OBJ)
- {
- fputc ('(', stream);
- nested_expr = true;
- }
- output_addr_const (stream, val2);
- if (nested_expr)
- fputc (')', stream);
- if (GET_CODE (val) == ASHIFTRT)
- {
- fputs (" >> ", stream);
- output_addr_const (stream, XEXP (val, 1));
- fputc (')', stream);
- }
- fputs (" & 65535)", stream);
- break;
- }
-
- /* Fall through. */
default:
if (TARGET_SH1)
fputc ('#', stream);
if ((mode == SImode || mode == DImode)
&& flag_pic
&& ! ((mode == Pmode || mode == ptr_mode)
- && tls_symbolic_operand (operands[1], Pmode) != 0))
+ && tls_symbolic_operand (operands[1], Pmode) != TLS_MODEL_NONE))
{
rtx temp;
if (SYMBOLIC_CONST_P (operands[1]))
{
/* This is like change_address_1 (operands[0], mode, 0, 1) ,
except that we can't use that function because it is static. */
- rtx new = change_address (operands[0], mode, 0);
- MEM_COPY_ATTRIBUTES (new, operands[0]);
- operands[0] = new;
+ rtx new_rtx = change_address (operands[0], mode, 0);
+ MEM_COPY_ATTRIBUTES (new_rtx, operands[0]);
+ operands[0] = new_rtx;
}
/* This case can happen while generating code to move the result
op1 = operands[1];
if (GET_CODE (op1) == CONST
&& GET_CODE (XEXP (op1, 0)) == PLUS
- && tls_symbolic_operand (XEXP (XEXP (op1, 0), 0), Pmode))
+ && (tls_symbolic_operand (XEXP (XEXP (op1, 0), 0), Pmode)
+ != TLS_MODEL_NONE))
{
opc = XEXP (XEXP (op1, 0), 1);
op1 = XEXP (XEXP (op1, 0), 0);
else
opc = NULL_RTX;
- if ((tls_kind = tls_symbolic_operand (op1, Pmode)))
+ if ((tls_kind = tls_symbolic_operand (op1, Pmode)) != TLS_MODEL_NONE)
{
rtx tga_op1, tga_ret, tmp, tmp2;
rtx op1;
rtx scratch = NULL_RTX;
- if (comparison == CODE_FOR_nothing)
+ if (comparison == LAST_AND_UNUSED_RTX_CODE)
comparison = GET_CODE (operands[0]);
else
scratch = operands[4];
operands[1], operands[2])));
jump = emit_jump_insn (branch_expander (operands[3]));
if (probability >= 0)
- REG_NOTES (jump)
- = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (probability),
- REG_NOTES (jump));
+ add_reg_note (jump, REG_BR_PROB, GEN_INT (probability));
}
op2h = gen_highpart_mode (SImode, DImode, operands[2]);
op1l = gen_lowpart (SImode, operands[1]);
op2l = gen_lowpart (SImode, operands[2]);
- msw_taken = msw_skip = lsw_taken = CODE_FOR_nothing;
+ msw_taken = msw_skip = lsw_taken = LAST_AND_UNUSED_RTX_CODE;
prob = split_branch_probability;
rev_prob = REG_BR_PROB_BASE - prob;
switch (comparison)
break;
default: return false;
}
- num_branches = ((msw_taken != CODE_FOR_nothing)
- + (msw_skip != CODE_FOR_nothing)
- + (lsw_taken != CODE_FOR_nothing));
+ num_branches = ((msw_taken != LAST_AND_UNUSED_RTX_CODE)
+ + (msw_skip != LAST_AND_UNUSED_RTX_CODE)
+ + (lsw_taken != LAST_AND_UNUSED_RTX_CODE));
if (comparison != EQ && comparison != NE && num_branches > 1)
{
if (!CONSTANT_P (operands[2])
operands[4] = NULL_RTX;
if (reload_completed
&& ! arith_reg_or_0_operand (op2h, SImode) && true_regnum (op1h)
- && (msw_taken != CODE_FOR_nothing || msw_skip != CODE_FOR_nothing))
+ && (msw_taken != LAST_AND_UNUSED_RTX_CODE
+ || msw_skip != LAST_AND_UNUSED_RTX_CODE))
{
emit_move_insn (scratch, operands[2]);
operands[2] = scratch;
}
- if (msw_taken != CODE_FOR_nothing)
+ if (msw_taken != LAST_AND_UNUSED_RTX_CODE)
expand_cbranchsi4 (operands, msw_taken, msw_taken_prob);
- if (msw_skip != CODE_FOR_nothing)
+ if (msw_skip != LAST_AND_UNUSED_RTX_CODE)
{
rtx taken_label = operands[3];
/* Operands were possibly modified, but msw_skip doesn't expect this.
Always use the original ones. */
- if (msw_taken != CODE_FOR_nothing)
+ if (msw_taken != LAST_AND_UNUSED_RTX_CODE)
{
operands[1] = op1h;
operands[2] = op2h;
}
operands[1] = op1l;
operands[2] = op2l;
- if (lsw_taken != CODE_FOR_nothing)
+ if (lsw_taken != LAST_AND_UNUSED_RTX_CODE)
{
if (reload_completed
&& ! arith_reg_or_0_operand (op2l, SImode) && true_regnum (op1l))
operands[4] = scratch;
expand_cbranchsi4 (operands, lsw_taken, lsw_taken_prob);
}
- if (msw_skip != CODE_FOR_nothing)
+ if (msw_skip != LAST_AND_UNUSED_RTX_CODE)
emit_label (skip_label);
return true;
}
else
insn = gen_rtx_SET (VOIDmode,
gen_rtx_REG (SImode, T_REG),
- gen_rtx_fmt_ee (code, SImode,
+ gen_rtx_fmt_ee ((enum rtx_code) code, SImode,
sh_compare_op0, sh_compare_op1));
if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT)
{
const char *
output_far_jump (rtx insn, rtx op)
{
- struct { rtx lab, reg, op; } this;
+ struct { rtx lab, reg, op; } this_jmp;
rtx braf_base_lab = NULL_RTX;
const char *jump;
int far;
int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
rtx prev;
- this.lab = gen_label_rtx ();
+ this_jmp.lab = gen_label_rtx ();
if (TARGET_SH2
&& offset >= -32764
if (GET_CODE ((prev = prev_nonnote_insn (insn))) == INSN
&& INSN_CODE (prev) == CODE_FOR_indirect_jump_scratch)
{
- this.reg = SET_DEST (XVECEXP (PATTERN (prev), 0, 0));
- if (REGNO (this.reg) == R0_REG && flag_pic && ! TARGET_SH2)
+ this_jmp.reg = SET_DEST (XVECEXP (PATTERN (prev), 0, 0));
+ if (REGNO (this_jmp.reg) == R0_REG && flag_pic && ! TARGET_SH2)
jump = "mov.l r1,@-r15; mova %O0,r0; mov.l @r0,r1; add r1,r0; mov.l @r15+,r1; jmp @%1";
- output_asm_insn (jump, &this.lab);
+ output_asm_insn (jump, &this_jmp.lab);
if (dbr_sequence_length ())
print_slot (final_sequence);
else
if (dbr_sequence_length ())
print_slot (final_sequence);
- this.reg = gen_rtx_REG (SImode, 13);
+ this_jmp.reg = gen_rtx_REG (SImode, 13);
/* We must keep the stack aligned to 8-byte boundaries on SH5.
Fortunately, MACL is fixed and call-clobbered, and we never
need its value across jumps, so save r13 in it instead of in
output_asm_insn ("lds r13, macl", 0);
else
output_asm_insn ("mov.l r13,@-r15", 0);
- output_asm_insn (jump, &this.lab);
+ output_asm_insn (jump, &this_jmp.lab);
if (TARGET_SH5)
output_asm_insn ("sts macl, r13", 0);
else
}
if (far)
output_asm_insn (".align 2", 0);
- (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (this.lab));
- this.op = op;
+ (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (this_jmp.lab));
+ this_jmp.op = op;
if (far && flag_pic)
{
if (TARGET_SH2)
- this.lab = braf_base_lab;
- output_asm_insn (".long %O2-%O0", &this.lab);
+ this_jmp.lab = braf_base_lab;
+ output_asm_insn (".long %O2-%O0", &this_jmp.lab);
}
else
- output_asm_insn (far ? ".long %O2" : ".word %O2-%O0", &this.lab);
+ output_asm_insn (far ? ".long %O2" : ".word %O2-%O0", &this_jmp.lab);
return "";
}
}
}
-/* Output a code sequence for INSN using TEMPLATE with OPERANDS; but before,
+/* Output a code sequence for INSN using TEMPL with OPERANDS; but before,
fill in operands 9 as a label to the successor insn.
We try to use jump threading where possible.
IF CODE matches the comparison in the IF_THEN_ELSE of a following jump,
we assume the jump is taken. I.e. EQ means follow jmp and bf, NE means
follow jmp and bt, if the address is in range. */
const char *
-output_branchy_insn (enum rtx_code code, const char *template,
+output_branchy_insn (enum rtx_code code, const char *templ,
rtx insn, rtx *operands)
{
rtx next_insn = NEXT_INSN (insn);
INSN_ADDRESSES_NEW (operands[9],
INSN_ADDRESSES (INSN_UID (next_insn))
+ get_attr_length (next_insn));
- return template;
+ return templ;
}
else
{
/* branch_true */
src = XEXP (src, 1);
operands[9] = src;
- return template;
+ return templ;
}
}
}
INSN_ADDRESSES_NEW (operands[9],
INSN_ADDRESSES (INSN_UID (insn))
+ get_attr_length (insn));
- return template;
+ return templ;
}
const char *
static bool
unspec_caller_rtx_p (rtx pat)
{
- switch (GET_CODE (pat))
+ rtx base, offset;
+ int i;
+
+ split_const (pat, &base, &offset);
+ if (GET_CODE (base) == UNSPEC)
{
- case CONST:
- return unspec_caller_rtx_p (XEXP (pat, 0));
- case PLUS:
- case MINUS:
- if (unspec_caller_rtx_p (XEXP (pat, 0)))
- return true;
- return unspec_caller_rtx_p (XEXP (pat, 1));
- case UNSPEC:
- if (XINT (pat, 1) == UNSPEC_CALLER)
+ if (XINT (base, 1) == UNSPEC_CALLER)
return true;
- default:
- break;
+ for (i = 0; i < XVECLEN (base, 0); i++)
+ if (unspec_caller_rtx_p (XVECEXP (base, 0, i)))
+ return true;
}
-
return false;
}
shift_insns_rtx (rtx insn)
{
rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
- int shift_count = INTVAL (XEXP (set_src, 1));
+ int shift_count = INTVAL (XEXP (set_src, 1)) & 31;
enum rtx_code shift_code = GET_CODE (set_src);
switch (shift_code)
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
return SH_DYNAMIC_SHIFT_COST;
- value = INTVAL (XEXP (x, 1));
+ /* Otherwise, return the true cost in instructions. Cope with out of range
+ shift counts more or less arbitrarily. */
+ value = INTVAL (XEXP (x, 1)) & 31;
- /* Otherwise, return the true cost in instructions. */
if (GET_CODE (x) == ASHIFTRT)
{
int cost = ashiftrt_insns[value];
|| satisfies_constraint_J16 (XEXP (x, 1)))
return 1;
else
- return 1 + rtx_cost (XEXP (x, 1), AND);
+ return 1 + rtx_cost (XEXP (x, 1), AND, !optimize_size);
}
/* These constants are single cycle extu.[bw] instructions. */
scanned. In either case, *TOTAL contains the cost result. */
static bool
-sh_rtx_costs (rtx x, int code, int outer_code, int *total)
+sh_rtx_costs (rtx x, int code, int outer_code, int *total,
+ bool speed ATTRIBUTE_UNUSED)
{
switch (code)
{
since it increases pressure on r0. */
static int
-sh_address_cost (rtx X)
+sh_address_cost (rtx X,
+ bool speed ATTRIBUTE_UNUSED)
{
return (GET_CODE (X) == PLUS
&& ! CONSTANT_P (XEXP (X, 1))
int max, i;
/* Truncate the shift count in case it is out of bounds. */
- value = value & 0x1f;
+ value = value & 31;
if (value == 31)
{
int
sh_dynamicalize_shift_p (rtx count)
{
- return shift_insns[INTVAL (count)] > 1 + SH_DYNAMIC_SHIFT_COST;
+ return shift_insns[INTVAL (count) & 31] > 1 + SH_DYNAMIC_SHIFT_COST;
}
/* Try to find a good way to implement the combiner pattern
shl_and_scr_length (rtx insn)
{
rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
- int len = shift_insns[INTVAL (XEXP (set_src, 1))];
+ int len = shift_insns[INTVAL (XEXP (set_src, 1)) & 31];
rtx op = XEXP (set_src, 0);
- len += shift_insns[INTVAL (XEXP (op, 1))] + 1;
+ len += shift_insns[INTVAL (XEXP (op, 1)) & 31] + 1;
op = XEXP (XEXP (op, 0), 0);
- return len + shift_insns[INTVAL (XEXP (op, 1))];
+ return len + shift_insns[INTVAL (XEXP (op, 1)) & 31];
}
/* Generate rtl for instructions for which shl_and_kind advised a particular
add_constant (rtx x, enum machine_mode mode, rtx last_value)
{
int i;
- rtx lab, new;
+ rtx lab, new_rtx;
label_ref_list_t ref, newref;
/* First see if we've already got it. */
}
if (rtx_equal_p (x, pool_vector[i].value))
{
- lab = new = 0;
+ lab = new_rtx = 0;
if (! last_value
|| ! i
|| ! rtx_equal_p (last_value, pool_vector[i-1].value))
{
- new = gen_label_rtx ();
- LABEL_REFS (new) = pool_vector[i].label;
- pool_vector[i].label = lab = new;
+ new_rtx = gen_label_rtx ();
+ LABEL_REFS (new_rtx) = pool_vector[i].label;
+ pool_vector[i].label = lab = new_rtx;
}
if (lab && pool_window_label)
{
newref->next = ref;
pool_vector[pool_window_last].wend = newref;
}
- if (new)
- pool_window_label = new;
+ if (new_rtx)
+ pool_window_label = new_rtx;
pool_window_last = i;
return lab;
}
{
rtx worker = mova;
rtx lab = gen_label_rtx ();
- rtx wpat, wpat0, wpat1, wsrc, diff;
+ rtx wpat, wpat0, wpat1, wsrc, target, base, diff;
do
{
XEXP (XVECEXP (wsrc, 0, 2), 0), lab,
XEXP (wpat1, 0)));
INSN_CODE (worker) = -1;
- diff = gen_rtx_MINUS (Pmode, XVECEXP (SET_SRC (PATTERN (mova)), 0, 0),
- gen_rtx_LABEL_REF (Pmode, lab));
- diff = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, diff), UNSPEC_PIC);
+ target = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
+ base = gen_rtx_LABEL_REF (Pmode, lab);
+ diff = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, target, base), UNSPEC_SYMOFF);
SET_SRC (PATTERN (mova)) = gen_rtx_CONST (Pmode, diff);
INSN_CODE (mova) = -1;
}
if (optimize)
{
+ /* If NEW_MOVA has no address yet, it will be handled later. */
+ if (INSN_ADDRESSES_SIZE() <= (unsigned) INSN_UID (new_mova))
+ return -1;
+
n_addr = INSN_ADDRESSES (INSN_UID (new_mova));
n_target = INSN_ADDRESSES (INSN_UID (XEXP (MOVA_LABELREF (new_mova), 0)));
if (n_addr > n_target || n_addr + 1022 < n_target)
rtx scan;
/* Don't look for the stack pointer as a scratch register,
it would cause trouble if an interrupt occurred. */
- unsigned try = 0x7fff, used;
+ unsigned attempt = 0x7fff, used;
int jump_left = flag_expensive_optimizations + 1;
/* It is likely that the most recent eligible instruction is wanted for
&& GET_CODE (PATTERN (scan)) != CLOBBER
&& get_attr_in_delay_slot (scan) == IN_DELAY_SLOT_YES)
{
- try &= ~regs_used (PATTERN (scan), 0);
+ attempt &= ~regs_used (PATTERN (scan), 0);
break;
}
}
if (code == CALL_INSN)
used |= regs_used (CALL_INSN_FUNCTION_USAGE (scan), 0);
dead |= (used >> 16) & ~used;
- if (dead & try)
+ if (dead & attempt)
{
- dead &= try;
+ dead &= attempt;
break;
}
if (code == JUMP_INSN)
/* If we are not optimizing, then there may not be
a note. */
if (note)
- PUT_MODE (note, REG_INC);
+ PUT_REG_NOTE_KIND (note, REG_INC);
*last_float_addr = r0_inc_rtx;
}
insn = emit_fn (GEN_ADD3 (reg, reg, const_reg));
}
if (! epilogue_p)
- REG_NOTES (insn)
- = (gen_rtx_EXPR_LIST
- (REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode, reg,
- gen_rtx_PLUS (SImode, reg, GEN_INT (size))),
- REG_NOTES (insn)));
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (VOIDmode, reg,
+ gen_rtx_PLUS (SImode, reg,
+ GEN_INT (size))));
}
}
}
x = gen_push (gen_rtx_REG (SImode, rn));
x = frame_insn (x);
- REG_NOTES (x)
- = gen_rtx_EXPR_LIST (REG_INC,
- gen_rtx_REG (SImode, STACK_POINTER_REGNUM), 0);
+ add_reg_note (x, REG_INC, gen_rtx_REG (SImode, STACK_POINTER_REGNUM));
return x;
}
x = gen_pop (gen_rtx_REG (SImode, rn));
x = emit_insn (x);
- REG_NOTES (x)
- = gen_rtx_EXPR_LIST (REG_INC,
- gen_rtx_REG (SImode, STACK_POINTER_REGNUM), 0);
+ add_reg_note (x, REG_INC, gen_rtx_REG (SImode, STACK_POINTER_REGNUM));
}
/* Generate code to push the regs specified in the mask. */
&& crtl->args.info.call_cookie
&& reg == PIC_OFFSET_TABLE_REGNUM)
|| (df_regs_ever_live_p (reg)
- && (!call_really_used_regs[reg]
+ && ((!call_really_used_regs[reg]
+ && !(reg != PIC_OFFSET_TABLE_REGNUM
+ && fixed_regs[reg] && call_used_regs[reg]))
|| (trapa_handler && reg == FPSCR_REG && TARGET_FPU_ANY)))
|| (crtl->calls_eh_return
&& (reg == EH_RETURN_DATA_REGNO (0)
tmp_pnt = schedule.temps;
for (entry = &schedule.entries[1]; entry->mode != VOIDmode; entry++)
{
- enum machine_mode mode = entry->mode;
+ enum machine_mode mode = (enum machine_mode) entry->mode;
unsigned int reg = entry->reg;
rtx reg_rtx, mem_rtx, pre_dec = NULL_RTX;
rtx orig_reg_rtx;
stack_pointer_rtx,
GEN_INT (offset)));
- GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_pre_dec);
-
- gcc_assert (r0);
- mem_rtx = NULL_RTX;
-
- try_pre_dec:
- do
- if (HAVE_PRE_DECREMENT
- && (offset_in_r0 - offset == GET_MODE_SIZE (mode)
- || mem_rtx == NULL_RTX
- || reg == PR_REG || SPECIAL_REGISTER_P (reg)))
- {
- pre_dec = gen_frame_mem (mode, gen_rtx_PRE_DEC (Pmode, r0));
+ if (!memory_address_p (mode, XEXP (mem_rtx, 0)))
+ {
+ gcc_assert (r0);
+ mem_rtx = NULL_RTX;
+ }
- GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (pre_dec, 0),
- pre_dec_ok);
+ if (HAVE_PRE_DECREMENT
+ && (offset_in_r0 - offset == GET_MODE_SIZE (mode)
+ || mem_rtx == NULL_RTX
+ || reg == PR_REG || SPECIAL_REGISTER_P (reg)))
+ {
+ pre_dec = gen_frame_mem (mode, gen_rtx_PRE_DEC (Pmode, r0));
+ if (!memory_address_p (mode, XEXP (pre_dec, 0)))
pre_dec = NULL_RTX;
-
- break;
-
- pre_dec_ok:
- mem_rtx = NULL_RTX;
- offset += GET_MODE_SIZE (mode);
- }
- while (0);
+ else
+ {
+ mem_rtx = NULL_RTX;
+ offset += GET_MODE_SIZE (mode);
+ }
+ }
if (mem_rtx != NULL_RTX)
goto addr_ok;
a direct save from the to-be-saved register. */
if (REGNO (reg_rtx) != reg)
{
- rtx set, note_rtx;
+ rtx set;
set = gen_rtx_SET (VOIDmode, mem_rtx, orig_reg_rtx);
- note_rtx = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, set,
- REG_NOTES (insn));
- REG_NOTES (insn) = note_rtx;
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, set);
}
if (TARGET_SHCOMPACT && (offset_in_r0 != -1))
{
rtx reg_rtx = gen_rtx_REG (mode, reg);
- rtx set, note_rtx;
+ rtx set;
rtx mem_rtx = gen_frame_mem (mode,
gen_rtx_PLUS (Pmode,
stack_pointer_rtx,
GEN_INT (offset)));
set = gen_rtx_SET (VOIDmode, mem_rtx, reg_rtx);
- note_rtx = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, set,
- REG_NOTES (insn));
- REG_NOTES (insn) = note_rtx;
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, set);
}
}
}
tmp_pnt = schedule.temps;
for (; entry->mode != VOIDmode; entry--)
{
- enum machine_mode mode = entry->mode;
+ enum machine_mode mode = (enum machine_mode) entry->mode;
int reg = entry->reg;
rtx reg_rtx, mem_rtx, post_inc = NULL_RTX, insn;
stack_pointer_rtx,
GEN_INT (offset)));
- GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_post_inc);
-
- mem_rtx = NULL_RTX;
+ if (!memory_address_p (mode, XEXP (mem_rtx, 0)))
+ mem_rtx = NULL_RTX;
- try_post_inc:
- do
- if (HAVE_POST_INCREMENT
- && (offset == offset_in_r0
- || (offset + GET_MODE_SIZE (mode) != d + d_rounding
- && mem_rtx == NULL_RTX)
- || reg == PR_REG || SPECIAL_REGISTER_P (reg)))
- {
- post_inc = gen_frame_mem (mode, gen_rtx_POST_INC (Pmode, r0));
-
- GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (post_inc, 0),
- post_inc_ok);
+ if (HAVE_POST_INCREMENT
+ && (offset == offset_in_r0
+ || (offset + GET_MODE_SIZE (mode) != d + d_rounding
+ && mem_rtx == NULL_RTX)
+ || reg == PR_REG || SPECIAL_REGISTER_P (reg)))
+ {
+ post_inc = gen_frame_mem (mode, gen_rtx_POST_INC (Pmode, r0));
+ if (!memory_address_p (mode, XEXP (post_inc, 0)))
post_inc = NULL_RTX;
-
- break;
-
- post_inc_ok:
+ else
mem_rtx = NULL_RTX;
- }
- while (0);
+ }
if (mem_rtx != NULL_RTX)
goto addr_ok;
/* Call __builtin_saveregs. */
u = make_tree (sizetype, expand_builtin_saveregs ());
u = fold_convert (ptr_type_node, u);
- t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_fp, u);
+ t = build2 (MODIFY_EXPR, ptr_type_node, next_fp, u);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
nfp = 0;
u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u,
size_int (UNITS_PER_WORD * nfp));
- t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_fp_limit, u);
+ t = build2 (MODIFY_EXPR, ptr_type_node, next_fp_limit, u);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_o, u);
+ t = build2 (MODIFY_EXPR, ptr_type_node, next_o, u);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
nint = 0;
u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u,
size_int (UNITS_PER_WORD * nint));
- t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_o_limit, u);
+ t = build2 (MODIFY_EXPR, ptr_type_node, next_o_limit, u);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
u = make_tree (ptr_type_node, nextarg);
- t = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_stack, u);
+ t = build2 (MODIFY_EXPR, ptr_type_node, next_stack, u);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
/* Implement `va_arg'. */
static tree
-sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
- tree *post_p ATTRIBUTE_UNUSED)
+sh_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
+ gimple_seq *post_p ATTRIBUTE_UNUSED)
{
HOST_WIDE_INT size, rsize;
tree tmp, pptr_type_node;
tree cmp;
bool is_double = size == 8 && TREE_CODE (eff_type) == REAL_TYPE;
- tmp = build1 (ADDR_EXPR, pptr_type_node, next_fp);
- tmp = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, tmp);
- gimplify_and_add (tmp, pre_p);
+ tmp = build1 (ADDR_EXPR, pptr_type_node, unshare_expr (next_fp));
+ gimplify_assign (unshare_expr (addr), tmp, pre_p);
- tmp = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_fp_tmp, valist);
- gimplify_and_add (tmp, pre_p);
+ gimplify_assign (unshare_expr (next_fp_tmp), valist, pre_p);
tmp = next_fp_limit;
if (size > 4 && !is_double)
- tmp = build2 (POINTER_PLUS_EXPR, TREE_TYPE (tmp), tmp,
- size_int (4 - size));
- tmp = build2 (GE_EXPR, boolean_type_node, next_fp_tmp, tmp);
+ tmp = build2 (POINTER_PLUS_EXPR, TREE_TYPE (tmp),
+ unshare_expr (tmp), size_int (4 - size));
+ tmp = build2 (GE_EXPR, boolean_type_node,
+ unshare_expr (next_fp_tmp), unshare_expr (tmp));
cmp = build3 (COND_EXPR, void_type_node, tmp,
- build1 (GOTO_EXPR, void_type_node, lab_false),
- NULL_TREE);
+ build1 (GOTO_EXPR, void_type_node,
+ unshare_expr (lab_false)), NULL_TREE);
if (!is_double)
gimplify_and_add (cmp, pre_p);
tmp = build2 (BIT_AND_EXPR, sizetype, tmp,
size_int (UNITS_PER_WORD));
tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
- next_fp_tmp, tmp);
- tmp = build2 (GIMPLE_MODIFY_STMT, ptr_type_node,
- next_fp_tmp, tmp);
- gimplify_and_add (tmp, pre_p);
+ unshare_expr (next_fp_tmp), tmp);
+ gimplify_assign (unshare_expr (next_fp_tmp), tmp, pre_p);
}
if (is_double)
gimplify_and_add (cmp, pre_p);
= std_gimplify_va_arg_expr (next_fp_tmp, subtype, pre_p, NULL);
real = get_initialized_tmp_var (real, pre_p, NULL);
- result = build2 (COMPLEX_EXPR, type, real, imag);
+ result = build2 (COMPLEX_EXPR, eff_type, real, imag);
+ if (type != eff_type)
+ result = build1 (VIEW_CONVERT_EXPR, type, result);
result = get_initialized_tmp_var (result, pre_p, NULL);
}
#endif /* FUNCTION_ARG_SCmode_WART */
- tmp = build1 (GOTO_EXPR, void_type_node, lab_over);
+ tmp = build1 (GOTO_EXPR, void_type_node, unshare_expr (lab_over));
gimplify_and_add (tmp, pre_p);
- tmp = build1 (LABEL_EXPR, void_type_node, lab_false);
+ tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (lab_false));
gimplify_and_add (tmp, pre_p);
- tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack);
- tmp = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, tmp);
- gimplify_and_add (tmp, pre_p);
- tmp = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, next_fp_tmp, valist);
- gimplify_and_add (tmp, pre_p);
+ tmp = build1 (ADDR_EXPR, pptr_type_node, unshare_expr (next_stack));
+ gimplify_assign (unshare_expr (addr), tmp, pre_p);
+ gimplify_assign (unshare_expr (next_fp_tmp),
+ unshare_expr (valist), pre_p);
- tmp = build2 (GIMPLE_MODIFY_STMT, ptr_type_node, valist, next_fp_tmp);
- gimplify_and_add (tmp, post_p);
+ gimplify_assign (unshare_expr (valist),
+ unshare_expr (next_fp_tmp), post_p);
valist = next_fp_tmp;
}
else
{
- tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, next_o,
- size_int (rsize));
- tmp = build2 (GT_EXPR, boolean_type_node, tmp, next_o_limit);
+ tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
+ unshare_expr (next_o), size_int (rsize));
+ tmp = build2 (GT_EXPR, boolean_type_node, tmp,
+ unshare_expr (next_o_limit));
tmp = build3 (COND_EXPR, void_type_node, tmp,
- build1 (GOTO_EXPR, void_type_node, lab_false),
- NULL_TREE);
+ build1 (GOTO_EXPR, void_type_node,
+ unshare_expr (lab_false)),
+ NULL_TREE);
gimplify_and_add (tmp, pre_p);
- tmp = build1 (ADDR_EXPR, pptr_type_node, next_o);
- tmp = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, tmp);
- gimplify_and_add (tmp, pre_p);
+ tmp = build1 (ADDR_EXPR, pptr_type_node, unshare_expr (next_o));
+ gimplify_assign (unshare_expr (addr), tmp, pre_p);
- tmp = build1 (GOTO_EXPR, void_type_node, lab_over);
+ tmp = build1 (GOTO_EXPR, void_type_node, unshare_expr (lab_over));
gimplify_and_add (tmp, pre_p);
- tmp = build1 (LABEL_EXPR, void_type_node, lab_false);
+ tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (lab_false));
gimplify_and_add (tmp, pre_p);
if (size > 4 && ! (TARGET_SH4 || TARGET_SH2A))
- {
- tmp = build2 (GIMPLE_MODIFY_STMT, ptr_type_node,
- next_o, next_o_limit);
- gimplify_and_add (tmp, pre_p);
- }
+ gimplify_assign (unshare_expr (next_o),
+ unshare_expr (next_o_limit), pre_p);
- tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack);
- tmp = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, tmp);
- gimplify_and_add (tmp, pre_p);
+ tmp = build1 (ADDR_EXPR, pptr_type_node, unshare_expr (next_stack));
+ gimplify_assign (unshare_expr (addr), tmp, pre_p);
}
if (!result)
{
- tmp = build1 (LABEL_EXPR, void_type_node, lab_over);
+ tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (lab_over));
gimplify_and_add (tmp, pre_p);
}
}
tmp = std_gimplify_va_arg_expr (valist, type, pre_p, NULL);
if (result)
{
- tmp = build2 (GIMPLE_MODIFY_STMT, void_type_node, result, tmp);
- gimplify_and_add (tmp, pre_p);
+ gimplify_assign (result, tmp, pre_p);
- tmp = build1 (LABEL_EXPR, void_type_node, lab_over);
+ tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (lab_over));
gimplify_and_add (tmp, pre_p);
}
else
return result;
}
+/* 64 bit floating points memory transfers are paired single precision loads
+ or store. So DWARF information needs fixing in little endian (unless
+ PR=SZ=1 in FPSCR). */
+rtx
+sh_dwarf_register_span (rtx reg)
+{
+ unsigned regno = REGNO (reg);
+
+ if (WORDS_BIG_ENDIAN || GET_MODE (reg) != DFmode)
+ return NULL_RTX;
+
+ return
+ gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2,
+ gen_rtx_REG (SFmode,
+ DBX_REGISTER_NUMBER (regno+1)),
+ gen_rtx_REG (SFmode,
+ DBX_REGISTER_NUMBER (regno))));
+}
+
bool
sh_promote_prototypes (const_tree type)
{
}
/* Return the TLS type for TLS symbols, 0 for otherwise. */
-int
+enum tls_model
tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != SYMBOL_REF)
- return 0;
+ return TLS_MODEL_NONE;
return SYMBOL_REF_TLS_MODEL (op);
}
\f
void
fpscr_set_from_mem (int mode, HARD_REG_SET regs_live)
{
- enum attr_fp_mode fp_mode = mode;
+ enum attr_fp_mode fp_mode = (enum attr_fp_mode) mode;
enum attr_fp_mode norm_mode = ACTUAL_NORMAL_MODE (FP_MODE);
rtx addr_reg;
/* SH2e has a bug that prevents the use of annulled branches, so if
the delay slot is not filled, we'll have to put a NOP in it. */
- if (sh_cpu == CPU_SH2E
+ if (sh_cpu_attr == CPU_SH2E
&& GET_CODE (insn) == JUMP_INSN
&& GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
&& GET_CODE (PATTERN (insn)) != ADDR_VEC
{
int sum = 0;
rtx body = PATTERN (insn);
- const char *template;
+ const char *templ;
char c;
int maybe_label = 1;
if (GET_CODE (body) == ASM_INPUT)
- template = XSTR (body, 0);
+ templ = XSTR (body, 0);
else if (asm_noperands (body) >= 0)
- template
+ templ
= decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL);
else
return 0;
int ppi_adjust = 0;
do
- c = *template++;
+ c = *templ++;
while (c == ' ' || c == '\t');
/* all sh-dsp parallel-processing insns start with p.
The only non-ppi sh insn starting with p is pref.
The only ppi starting with pr is prnd. */
- if ((c == 'p' || c == 'P') && strncasecmp ("re", template, 2))
+ if ((c == 'p' || c == 'P') && strncasecmp ("re", templ, 2))
ppi_adjust = 2;
/* The repeat pseudo-insn expands two three insns, a total of
six bytes in size. */
else if ((c == 'r' || c == 'R')
- && ! strncasecmp ("epeat", template, 5))
+ && ! strncasecmp ("epeat", templ, 5))
ppi_adjust = 4;
while (c && c != '\n'
- && ! IS_ASM_LOGICAL_LINE_SEPARATOR (c, template))
+ && ! IS_ASM_LOGICAL_LINE_SEPARATOR (c, templ))
{
/* If this is a label, it is obviously not a ppi insn. */
if (c == ':' && maybe_label)
}
else if (c == '\'' || c == '"')
maybe_label = 0;
- c = *template++;
+ c = *templ++;
}
sum += ppi_adjust;
maybe_label = c != ':';
|| XINT (x, 1) == UNSPEC_GOTPLT
|| XINT (x, 1) == UNSPEC_GOTTPOFF
|| XINT (x, 1) == UNSPEC_DTPOFF
- || XINT (x, 1) == UNSPEC_PLT))
+ || XINT (x, 1) == UNSPEC_PLT
+ || XINT (x, 1) == UNSPEC_SYMOFF
+ || XINT (x, 1) == UNSPEC_PCREL_SYMOFF))
return 0;
fmt = GET_RTX_FORMAT (GET_CODE (x));
legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
rtx reg)
{
- if (tls_symbolic_operand (orig, Pmode))
+ if (tls_symbolic_operand (orig, Pmode) != TLS_MODEL_NONE)
return orig;
if (GET_CODE (orig) == LABEL_REF
return orig;
}
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ Otherwise, return X.
+
+ For the SH, if X is almost suitable for indexing, but the offset is
+ out of range, convert it into a normal form so that CSE has a chance
+ of reducing the number of address registers used. */
+
+static rtx
+sh_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
+{
+ if (flag_pic)
+ x = legitimize_pic_address (oldx, mode, NULL_RTX);
+
+ if (GET_CODE (x) == PLUS
+ && (GET_MODE_SIZE (mode) == 4
+ || GET_MODE_SIZE (mode) == 8)
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && BASE_REGISTER_RTX_P (XEXP (x, 0))
+ && ! TARGET_SHMEDIA
+ && ! ((TARGET_SH4 || TARGET_SH2A_DOUBLE) && mode == DFmode)
+ && ! (TARGET_SH2E && mode == SFmode))
+ {
+ rtx index_rtx = XEXP (x, 1);
+ HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;
+ rtx sum;
+
+ /* On rare occasions, we might get an unaligned pointer
+ that is indexed in a way to give an aligned address.
+ Therefore, keep the lower two bits in offset_base. */
+ /* Instead of offset_base 128..131 use 124..127, so that
+ simple add suffices. */
+ if (offset > 127)
+ offset_base = ((offset + 4) & ~60) - 4;
+ else
+ offset_base = offset & ~60;
+
+ /* Sometimes the normal form does not suit DImode. We
+ could avoid that by using smaller ranges, but that
+ would give less optimized code when SImode is
+ prevalent. */
+ if (GET_MODE_SIZE (mode) + offset - offset_base <= 64)
+ {
+ sum = expand_binop (Pmode, add_optab, XEXP (x, 0),
+ GEN_INT (offset_base), NULL_RTX, 0,
+ OPTAB_LIB_WIDEN);
+
+ return gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base));
+ }
+ }
+
+ return x;
+}
+
/* Mark the use of a constant in the literal table. If the constant
has multiple labels, make it unique. */
static rtx
return (TARGET_SHMEDIA && (reload_in_progress || reload_completed));
}
-static int
+static enum reg_class
sh_target_reg_class (void)
{
return TARGET_SHMEDIA ? TARGET_REGS : NO_REGS;
|| (!(TARGET_SH4A_ARCH || TARGET_SH4_300) && TARGET_USERMODE))
emit_library_call (function_symbol (NULL, "__ic_invalidate",
FUNCTION_ORDINARY),
- 0, VOIDmode, 1, tramp, SImode);
+ LCT_NORMAL, VOIDmode, 1, tramp, SImode);
else
emit_insn (gen_ic_invalidate_line (tramp));
}
argmode = TYPE_MODE (TREE_TYPE (arg));
if (argmode != opmode)
arg = build1 (NOP_EXPR, optype, arg);
- op[nop] = expand_expr (arg, NULL_RTX, opmode, 0);
+ op[nop] = expand_expr (arg, NULL_RTX, opmode, EXPAND_NORMAL);
if (! (*insn_data[icode].operand[nop].predicate) (op[nop], opmode))
op[nop] = copy_to_mode_reg (opmode, op[nop]);
}
emit_insn (gen_binary_sf_op1 (op0, op1, op2, op));
}
+/* Return true if hard register REGNO can hold a value of machine-mode MODE.
+ We can allow any mode in any general register. The special registers
+ only allow SImode. Don't allow any mode in the PR.
+
+ We cannot hold DCmode values in the XD registers because alter_reg
+ handles subregs of them incorrectly. We could work around this by
+ spacing the XD registers like the DR registers, but this would require
+ additional memory in every compilation to hold larger register vectors.
+ We could hold SFmode / SCmode values in XD registers, but that
+ would require a tertiary reload when reloading from / to memory,
+ and a secondary reload to reload from / to general regs; that
+ seems to be a loosing proposition.
+
+ We want to allow TImode FP regs so that when V4SFmode is loaded as TImode,
+ it won't be ferried through GP registers first. */
+
+bool
+sh_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
+{
+ if (SPECIAL_REGISTER_P (regno))
+ return mode == SImode;
+
+ if (regno == FPUL_REG)
+ return (mode == SImode || mode == SFmode);
+
+ if (FP_REGISTER_P (regno) && mode == SFmode)
+ return true;
+
+ if (mode == V2SFmode)
+ {
+ if (((FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 2 == 0)
+ || GENERAL_REGISTER_P (regno)))
+ return true;
+ else
+ return false;
+ }
+
+ if (mode == V4SFmode)
+ {
+ if ((FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 4 == 0)
+ || GENERAL_REGISTER_P (regno))
+ return true;
+ else
+ return false;
+ }
+
+ if (mode == V16SFmode)
+ {
+ if (TARGET_SHMEDIA)
+ {
+ if (FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 16 == 0)
+ return true;
+ else
+ return false;
+ }
+ else
+ return regno == FIRST_XD_REG;
+ }
+
+ if (FP_REGISTER_P (regno))
+ {
+ if (mode == SFmode
+ || mode == SImode
+ || ((TARGET_SH2E || TARGET_SHMEDIA) && mode == SCmode)
+ || ((((TARGET_SH4 || TARGET_SH2A_DOUBLE) && mode == DFmode)
+ || mode == DCmode
+ || (TARGET_SHMEDIA
+ && (mode == DFmode || mode == DImode
+ || mode == V2SFmode || mode == TImode)))
+ && ((regno - FIRST_FP_REG) & 1) == 0)
+ || ((TARGET_SH4 || TARGET_SHMEDIA) && mode == TImode
+ && ((regno - FIRST_FP_REG) & 3) == 0))
+ return true;
+ else
+ return false;
+ }
+
+ if (XD_REGISTER_P (regno))
+ return mode == DFmode;
+
+ if (TARGET_REGISTER_P (regno))
+ return (mode == DImode || mode == SImode || mode == PDImode);
+
+ if (regno == PR_REG)
+ return mode == SImode;
+
+ if (regno == FPSCR_REG)
+ return mode == PSImode;
+
+ /* FIXME. This works around PR target/37633 for -O0. */
+ if (!optimize && TARGET_SHMEDIA32 && GET_MODE_SIZE (mode) > 4)
+ {
+ unsigned int n = GET_MODE_SIZE (mode) / 8;
+
+ if (regno >= FIRST_GENERAL_REG + 10 - n + 1
+ && regno <= FIRST_GENERAL_REG + 14)
+ return false;
+ }
+
+ return true;
+}
+
/* Return the class of registers for which a mode change from FROM to TO
is invalid. */
bool
sh_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
- enum reg_class class)
+ enum reg_class rclass)
{
/* We want to enable the use of SUBREGs as a means to
VEC_SELECT a single element of a vector. */
if (to == SFmode && VECTOR_MODE_P (from) && GET_MODE_INNER (from) == SFmode)
- return (reg_classes_intersect_p (GENERAL_REGS, class));
+ return (reg_classes_intersect_p (GENERAL_REGS, rclass));
if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
{
if (TARGET_LITTLE_ENDIAN)
{
if (GET_MODE_SIZE (to) < 8 || GET_MODE_SIZE (from) < 8)
- return reg_classes_intersect_p (DF_REGS, class);
+ return reg_classes_intersect_p (DF_REGS, rclass);
}
else
{
if (GET_MODE_SIZE (from) < 8)
- return reg_classes_intersect_p (DF_HI_REGS, class);
+ return reg_classes_intersect_p (DF_HI_REGS, rclass);
}
}
return 0;
{
CUMULATIVE_ARGS cum;
int structure_value_byref = 0;
- rtx this, this_value, sibcall, insns, funexp;
+ rtx this_rtx, this_value, sibcall, insns, funexp;
tree funtype = TREE_TYPE (function);
int simple_add = CONST_OK_FOR_ADD (delta);
int did_load = 0;
FUNCTION_ARG_ADVANCE (cum, Pmode, ptype, 1);
}
- this = FUNCTION_ARG (cum, Pmode, ptr_type_node, 1);
+ this_rtx = FUNCTION_ARG (cum, Pmode, ptr_type_node, 1);
/* For SHcompact, we only have r0 for a scratch register: r1 is the
static chain pointer (even if you can't have nested virtual functions
error ("Need a call-clobbered target register");
}
- this_value = plus_constant (this, delta);
+ this_value = plus_constant (this_rtx, delta);
if (vcall_offset
&& (simple_add || scratch0 != scratch1)
&& strict_memory_address_p (ptr_mode, this_value))
if (!delta)
; /* Do nothing. */
else if (simple_add)
- emit_move_insn (this, this_value);
+ emit_move_insn (this_rtx, this_value);
else
{
emit_move_insn (scratch1, GEN_INT (delta));
- emit_insn (gen_add2_insn (this, scratch1));
+ emit_insn (gen_add2_insn (this_rtx, scratch1));
}
if (vcall_offset)
rtx offset_addr;
if (!did_load)
- emit_load_ptr (scratch0, this);
+ emit_load_ptr (scratch0, this_rtx);
offset_addr = plus_constant (scratch0, vcall_offset);
if (strict_memory_address_p (ptr_mode, offset_addr))
/* scratch0 != scratch1, and we have indexed loads. Get better
schedule by loading the offset into r1 and using an indexed
load - then the load of r1 can issue before the load from
- (this + delta) finishes. */
+ (this_rtx + delta) finishes. */
emit_move_insn (scratch1, GEN_INT (vcall_offset));
offset_addr = gen_rtx_PLUS (Pmode, scratch0, scratch1);
}
if (Pmode != ptr_mode)
scratch0 = gen_rtx_TRUNCATE (ptr_mode, scratch0);
- emit_insn (gen_add2_insn (this, scratch0));
+ emit_insn (gen_add2_insn (this_rtx, scratch0));
}
/* Generate a tail call to the target function. */
}
sibcall = emit_call_insn (sibcall);
SIBLING_CALL_P (sibcall) = 1;
- use_reg (&CALL_INSN_FUNCTION_USAGE (sibcall), this);
+ use_reg (&CALL_INSN_FUNCTION_USAGE (sibcall), this_rtx);
emit_barrier ();
/* Run just enough of rest_of_compilation to do scheduling and get
insn_locators_alloc ();
insns = get_insns ();
-#if 0
- if (optimize > 0)
- {
- /* Initialize the bitmap obstacks. */
- bitmap_obstack_initialize (NULL);
- bitmap_obstack_initialize (®_obstack);
- if (! cfun->cfg)
- init_flow ();
- rtl_register_cfg_hooks ();
- init_rtl_bb_info (ENTRY_BLOCK_PTR);
- init_rtl_bb_info (EXIT_BLOCK_PTR);
- ENTRY_BLOCK_PTR->flags |= BB_RTL;
- EXIT_BLOCK_PTR->flags |= BB_RTL;
- find_basic_blocks (insns);
-
- if (flag_schedule_insns_after_reload)
- {
- life_analysis (PROP_FINAL);
-
- split_all_insns (1);
-
- schedule_insns ();
- }
- /* We must split jmp insn in PIC case. */
- else if (flag_pic)
- split_all_insns_noflow ();
- }
-#else
if (optimize > 0)
{
if (! cfun->cfg)
init_flow (cfun);
split_all_insns_noflow ();
}
-#endif
sh_reorg ();
if (GET_CODE (x) == SUBREG)
{
- rtx new = replace_n_hard_rtx (SUBREG_REG (x), replacements,
+ rtx new_rtx = replace_n_hard_rtx (SUBREG_REG (x), replacements,
n_replacements, modify);
- if (GET_CODE (new) == CONST_INT)
+ if (GET_CODE (new_rtx) == CONST_INT)
{
- x = simplify_subreg (GET_MODE (x), new,
+ x = simplify_subreg (GET_MODE (x), new_rtx,
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
if (! x)
abort ();
}
else if (modify)
- SUBREG_REG (x) = new;
+ SUBREG_REG (x) = new_rtx;
return x;
}
}
else if (GET_CODE (x) == ZERO_EXTEND)
{
- rtx new = replace_n_hard_rtx (XEXP (x, 0), replacements,
+ rtx new_rtx = replace_n_hard_rtx (XEXP (x, 0), replacements,
n_replacements, modify);
- if (GET_CODE (new) == CONST_INT)
+ if (GET_CODE (new_rtx) == CONST_INT)
{
x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
- new, GET_MODE (XEXP (x, 0)));
+ new_rtx, GET_MODE (XEXP (x, 0)));
if (! x)
abort ();
}
else if (modify)
- XEXP (x, 0) = new;
+ XEXP (x, 0) = new_rtx;
return x;
}
fmt = GET_RTX_FORMAT (GET_CODE (x));
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
{
- rtx new;
+ rtx new_rtx;
if (fmt[i] == 'e')
{
- new = replace_n_hard_rtx (XEXP (x, i), replacements,
+ new_rtx = replace_n_hard_rtx (XEXP (x, i), replacements,
n_replacements, modify);
- if (!new)
+ if (!new_rtx)
return NULL_RTX;
if (modify)
- XEXP (x, i) = new;
+ XEXP (x, i) = new_rtx;
}
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
{
- new = replace_n_hard_rtx (XVECEXP (x, i, j), replacements,
+ new_rtx = replace_n_hard_rtx (XVECEXP (x, i, j), replacements,
n_replacements, modify);
- if (!new)
+ if (!new_rtx)
return NULL_RTX;
if (modify)
- XVECEXP (x, i, j) = new;
+ XVECEXP (x, i, j) = new_rtx;
}
}
}
enum reg_class
-sh_secondary_reload (bool in_p, rtx x, enum reg_class class,
+sh_secondary_reload (bool in_p, rtx x, enum reg_class rclass,
enum machine_mode mode, secondary_reload_info *sri)
{
if (in_p)
{
- if (REGCLASS_HAS_FP_REG (class)
+ if (REGCLASS_HAS_FP_REG (rclass)
&& ! TARGET_SHMEDIA
&& immediate_operand ((x), mode)
&& ! ((fp_zero_operand (x) || fp_one_operand (x))
default:
abort ();
}
- if (class == FPUL_REGS
+ if (rclass == FPUL_REGS
&& ((GET_CODE (x) == REG
&& (REGNO (x) == MACL_REG || REGNO (x) == MACH_REG
|| REGNO (x) == T_REG))
|| GET_CODE (x) == PLUS))
return GENERAL_REGS;
- if (class == FPUL_REGS && immediate_operand (x, mode))
+ if (rclass == FPUL_REGS && immediate_operand (x, mode))
{
if (satisfies_constraint_I08 (x) || fp_zero_operand (x))
return GENERAL_REGS;
sri->icode = CODE_FOR_reload_insi__i_fpul;
return NO_REGS;
}
- if (class == FPSCR_REGS
+ if (rclass == FPSCR_REGS
&& ((GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
|| (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PLUS)))
return GENERAL_REGS;
- if (REGCLASS_HAS_FP_REG (class)
+ if (REGCLASS_HAS_FP_REG (rclass)
&& TARGET_SHMEDIA
&& immediate_operand (x, mode)
&& x != CONST0_RTX (GET_MODE (x))
? CODE_FOR_reload_inqi : CODE_FOR_reload_inhi);
return NO_REGS;
}
- if (TARGET_SHMEDIA && class == GENERAL_REGS
- && (GET_CODE (x) == LABEL_REF || PIC_DIRECT_ADDR_P (x)))
+ if (TARGET_SHMEDIA && rclass == GENERAL_REGS
+ && (GET_CODE (x) == LABEL_REF || PIC_ADDR_P (x)))
return TARGET_REGS;
} /* end of input-only processing. */
- if (((REGCLASS_HAS_FP_REG (class)
+ if (((REGCLASS_HAS_FP_REG (rclass)
&& (GET_CODE (x) == REG
&& (GENERAL_OR_AP_REGISTER_P (REGNO (x))
|| (FP_REGISTER_P (REGNO (x)) && mode == SImode
&& TARGET_FMOVD))))
- || (REGCLASS_HAS_GENERAL_REG (class)
+ || (REGCLASS_HAS_GENERAL_REG (rclass)
&& GET_CODE (x) == REG
&& FP_REGISTER_P (REGNO (x))))
&& ! TARGET_SHMEDIA
&& (mode == SFmode || mode == SImode))
return FPUL_REGS;
- if ((class == FPUL_REGS
- || (REGCLASS_HAS_FP_REG (class)
+ if ((rclass == FPUL_REGS
+ || (REGCLASS_HAS_FP_REG (rclass)
&& ! TARGET_SHMEDIA && mode == SImode))
&& (GET_CODE (x) == MEM
|| (GET_CODE (x) == REG
|| REGNO (x) == T_REG
|| system_reg_operand (x, VOIDmode)))))
{
- if (class == FPUL_REGS)
+ if (rclass == FPUL_REGS)
return GENERAL_REGS;
return FPUL_REGS;
}
- if ((class == TARGET_REGS
- || (TARGET_SHMEDIA && class == SIBCALL_REGS))
+ if ((rclass == TARGET_REGS
+ || (TARGET_SHMEDIA && rclass == SIBCALL_REGS))
&& !satisfies_constraint_Csy (x)
&& (GET_CODE (x) != REG || ! GENERAL_REGISTER_P (REGNO (x))))
return GENERAL_REGS;
- if ((class == MAC_REGS || class == PR_REGS)
+ if ((rclass == MAC_REGS || rclass == PR_REGS)
&& GET_CODE (x) == REG && ! GENERAL_REGISTER_P (REGNO (x))
- && class != REGNO_REG_CLASS (REGNO (x)))
+ && rclass != REGNO_REG_CLASS (REGNO (x)))
return GENERAL_REGS;
- if (class != GENERAL_REGS && GET_CODE (x) == REG
+ if (rclass != GENERAL_REGS && GET_CODE (x) == REG
&& TARGET_REGISTER_P (REGNO (x)))
return GENERAL_REGS;
return NO_REGS;