Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Unified Diff: gcc/gcc/config/frv/frv.c

Issue 3050029: [gcc] GCC 4.5.0=>4.5.1 (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/nacl-toolchain.git
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gcc/gcc/config/fr30/t-fr30 ('k') | gcc/gcc/config/frv/frv-protos.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gcc/gcc/config/frv/frv.c
diff --git a/gcc/gcc/config/frv/frv.c b/gcc/gcc/config/frv/frv.c
index 7dde7e4464badf32e8c5d4bf15a258b455110603..a757472f37bf76979ce37f60f48e32e6fe455945 100644
--- a/gcc/gcc/config/frv/frv.c
+++ b/gcc/gcc/config/frv/frv.c
@@ -1,5 +1,5 @@
/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007,
- 2008 Free Software Foundation, Inc.
+ 2008, 2009 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of GCC.
@@ -139,7 +139,7 @@ struct frv_io {
REG++)
/* This structure contains machine specific function data. */
-struct machine_function GTY(())
+struct GTY(()) machine_function
{
/* True if we have created an rtx that relies on the stack frame. */
int frame_needed;
@@ -193,11 +193,6 @@ typedef struct
int base_offset;
} frv_frame_accessor_t;
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. */
-rtx frv_compare_op0;
-rtx frv_compare_op1;
-
/* Conditional execution support gathered together in one structure. */
typedef struct
{
@@ -269,6 +264,7 @@ frv_cpu_t frv_cpu_type = CPU_TYPE; /* value of -mcpu= */
/* Forward references */
static bool frv_handle_option (size_t, const char *, int);
+static bool frv_legitimate_address_p (enum machine_mode, rtx, bool);
static int frv_default_flags_for_cpu (void);
static int frv_string_begins_with (const_tree, const char *);
static FRV_INLINE bool frv_small_data_reloc_p (rtx, int);
@@ -277,6 +273,10 @@ static void frv_print_operand_memory_reference_reg
static void frv_print_operand_memory_reference (FILE *, rtx, int);
static int frv_print_operand_jump_hint (rtx);
static const char *comparison_string (enum rtx_code, rtx);
+static rtx frv_function_value (const_tree, const_tree,
+ bool);
+static rtx frv_libcall_value (enum machine_mode,
+ const_rtx);
static FRV_INLINE int frv_regno_ok_for_base_p (int, int);
static rtx single_set_pattern (rtx);
static int frv_function_contains_far_jump (void);
@@ -303,6 +303,7 @@ static int frv_check_constant_argument (enum insn_code, int, rtx);
static rtx frv_legitimize_target (enum insn_code, rtx);
static rtx frv_legitimize_argument (enum insn_code, int, rtx);
static rtx frv_legitimize_tls_address (rtx, enum tls_model);
+static rtx frv_legitimize_address (rtx, rtx, enum machine_mode);
static rtx frv_expand_set_builtin (enum insn_code, tree, rtx);
static rtx frv_expand_unop_builtin (enum insn_code, tree, rtx);
static rtx frv_expand_binop_builtin (enum insn_code, tree, rtx);
@@ -384,6 +385,9 @@ static void frv_output_dwarf_dtprel (FILE *, int, rtx)
static bool frv_secondary_reload (bool, rtx, enum reg_class,
enum machine_mode,
secondary_reload_info *);
+static bool frv_frame_pointer_required (void);
+static bool frv_can_eliminate (const int, const int);
+static void frv_trampoline_init (rtx, tree, rtx);
/* Allow us to easily change the default for -malloc-cc. */
#ifndef DEFAULT_NO_ALLOC_CC
@@ -433,6 +437,9 @@ static bool frv_secondary_reload (bool, rtx, enum reg_class,
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE frv_issue_rate
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS frv_legitimize_address
+
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL frv_function_ok_for_sibcall
#undef TARGET_CANNOT_FORCE_CONST_MEM
@@ -468,6 +475,23 @@ static bool frv_secondary_reload (bool, rtx, enum reg_class,
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD frv_secondary_reload
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P frv_legitimate_address_p
+
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED frv_frame_pointer_required
+
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE frv_can_eliminate
+
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT frv_trampoline_init
+
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE frv_function_value
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE frv_libcall_value
+
struct gcc_target targetm = TARGET_INITIALIZER;
#define FRV_SYMBOL_REF_TLS_P(RTX) \
@@ -1687,7 +1711,21 @@ frv_frame_access (frv_frame_accessor_t *accessor, rtx reg, int stack_offset)
emit_insn (gen_rtx_SET (VOIDmode, reg, temp));
}
else
- emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
+ {
+ /* We cannot use reg+reg addressing for DImode access. */
+ if (mode == DImode
+ && GET_CODE (XEXP (mem, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (mem, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (mem, 0), 1)) == REG)
+ {
+ rtx temp = gen_rtx_REG (SImode, TEMP_REGNO);
+ rtx insn = emit_move_insn (temp,
+ gen_rtx_PLUS (SImode, XEXP (XEXP (mem, 0), 0),
+ XEXP (XEXP (mem, 0), 1)));
+ mem = gen_rtx_MEM (DImode, temp);
+ }
+ emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
+ }
emit_use (reg);
}
else
@@ -1699,7 +1737,7 @@ frv_frame_access (frv_frame_accessor_t *accessor, rtx reg, int stack_offset)
frv_frame_insn (gen_rtx_SET (Pmode, mem, temp),
frv_dwarf_store (reg, stack_offset));
}
- else if (GET_MODE (reg) == DImode)
+ else if (mode == DImode)
{
/* For DImode saves, the dwarf2 version needs to be a SEQUENCE
with a separate save for each register. */
@@ -1707,6 +1745,19 @@ frv_frame_access (frv_frame_accessor_t *accessor, rtx reg, int stack_offset)
rtx reg2 = gen_rtx_REG (SImode, REGNO (reg) + 1);
rtx set1 = frv_dwarf_store (reg1, stack_offset);
rtx set2 = frv_dwarf_store (reg2, stack_offset + 4);
+
+ /* Also we cannot use reg+reg addressing. */
+ if (GET_CODE (XEXP (mem, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (mem, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (mem, 0), 1)) == REG)
+ {
+ rtx temp = gen_rtx_REG (SImode, TEMP_REGNO);
+ rtx insn = emit_move_insn (temp,
+ gen_rtx_PLUS (SImode, XEXP (XEXP (mem, 0), 0),
+ XEXP (XEXP (mem, 0), 1)));
+ mem = gen_rtx_MEM (DImode, temp);
+ }
+
frv_frame_insn (gen_rtx_SET (Pmode, mem, reg),
gen_rtx_PARALLEL (VOIDmode,
gen_rtvec (2, set1, set2)));
@@ -2075,28 +2126,10 @@ frv_asm_output_mi_thunk (FILE *file,
}
-/* A C expression which is nonzero if a function must have and use a frame
- pointer. This expression is evaluated in the reload pass. If its value is
- nonzero the function will have a frame pointer.
-
- The expression can in principle examine the current function and decide
- according to the facts, but on most machines the constant 0 or the constant
- 1 suffices. Use 0 when the machine allows code to be generated with no
- frame pointer, and doing so saves some time or space. Use 1 when there is
- no possible advantage to avoiding a frame pointer.
-
- In certain cases, the compiler does not know how to produce valid code
- without a frame pointer. The compiler recognizes those cases and
- automatically gives the function a frame pointer regardless of what
- `FRAME_POINTER_REQUIRED' says. You don't need to worry about them.
-
- In a function that does not require a frame pointer, the frame pointer
- register can be allocated for ordinary usage, unless you mark it as a fixed
- register. See `FIXED_REGISTERS' for more information. */
/* On frv, create a frame whenever we need to create stack. */
-int
+static bool
frv_frame_pointer_required (void)
{
/* If we forgoing the usual linkage requirements, we only need
@@ -2105,30 +2138,40 @@ frv_frame_pointer_required (void)
return !current_function_sp_is_unchanging;
if (! current_function_is_leaf)
- return TRUE;
+ return true;
if (get_frame_size () != 0)
- return TRUE;
+ return true;
if (cfun->stdarg)
- return TRUE;
+ return true;
if (!current_function_sp_is_unchanging)
- return TRUE;
+ return true;
if (!TARGET_FDPIC && flag_pic && crtl->uses_pic_offset_table)
- return TRUE;
+ return true;
if (profile_flag)
- return TRUE;
+ return true;
if (cfun->machine->frame_needed)
- return TRUE;
+ return true;
- return FALSE;
+ return false;
}
+/* Worker function for TARGET_CAN_ELIMINATE. */
+
+bool
+frv_can_eliminate (const int from, const int to)
+{
+ return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
+ ? ! frame_pointer_needed
+ : true);
+}
+
/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the
initial difference between the specified pair of registers. This macro must
be defined if `ELIMINABLE_REGS' is defined. */
@@ -2506,7 +2549,7 @@ frv_return_addr_rtx (int count, rtx frame)
MEMREF has already happened.
MEMREF must be a legitimate operand for modes larger than SImode.
- GO_IF_LEGITIMATE_ADDRESS forbids register+register addresses, which
+ frv_legitimate_address_p forbids register+register addresses, which
this function cannot handle. */
rtx
frv_index_memory (rtx memref, enum machine_mode mode, int index)
@@ -2545,6 +2588,12 @@ frv_print_operand_address (FILE * stream, rtx x)
output_addr_const (stream, x);
return;
+ case PLUS:
+ /* Poorly constructed asm statements can trigger this alternative.
+ See gcc/testsuite/gcc.dg/asm-4.c for an example. */
+ frv_print_operand_memory_reference (stream, x, 0);
+ return;
+
default:
break;
}
@@ -3251,6 +3300,35 @@ frv_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
+/* Implements TARGET_FUNCTION_VALUE. */
+
+static rtx
+frv_function_value (const_tree valtype,
+ const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+ bool outgoing ATTRIBUTE_UNUSED)
+{
+ return gen_rtx_REG (TYPE_MODE (valtype), RETURN_VALUE_REGNUM);
+}
+
+
+/* Implements TARGET_LIBCALL_VALUE. */
+
+static rtx
+frv_libcall_value (enum machine_mode mode,
+ const_rtx fun ATTRIBUTE_UNUSED)
+{
+ return gen_rtx_REG (mode, RETURN_VALUE_REGNUM);
+}
+
+
+/* Implements FUNCTION_VALUE_REGNO_P. */
+
+bool
+frv_function_value_regno_p (const unsigned int regno)
+{
+ return (regno == RETURN_VALUE_REGNUM);
+}
+
/* Return true if a register is ok to use as a base or index register. */
static FRV_INLINE int
@@ -3291,12 +3369,6 @@ frv_regno_ok_for_base_p (int regno, int strict_p)
conditional to define the strict variant in that case and the non-strict
variant otherwise.
- Subroutines to check for acceptable registers for various purposes (one for
- base registers, one for index registers, and so on) are typically among the
- subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'. Then only these
- subroutine macros need have two variants; the higher levels of macros may be
- the same whether strict or not.
-
Normally, constant addresses which are the sum of a `symbol_ref' and an
integer are stored inside a `const' RTX to mark them as constant.
Therefore, there is no need to recognize such sums specifically as
@@ -3307,30 +3379,14 @@ frv_regno_ok_for_base_p (int regno, int strict_p)
are not marked with `const'. It assumes that a naked `plus' indicates
indexing. If so, then you *must* reject such naked constant sums as
illegitimate addresses, so that none of them will be given to
- `PRINT_OPERAND_ADDRESS'.
-
- On some machines, whether a symbolic address is legitimate depends on the
- section that the address refers to. On these machines, define the macro
- `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and
- then check for it here. When you see a `const', you will have to look
- inside it to find the `symbol_ref' in order to determine the section.
-
- The best way to modify the name string is by adding text to the beginning,
- with suitable punctuation to prevent any ambiguity. Allocate the new name
- in `saveable_obstack'. You will have to modify `ASM_OUTPUT_LABELREF' to
- remove and decode the added text and output the name accordingly, and define
- `(* targetm.strip_name_encoding)' to access the original name string.
-
- You can check the information stored here into the `symbol_ref' in the
- definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and
`PRINT_OPERAND_ADDRESS'. */
int
-frv_legitimate_address_p (enum machine_mode mode,
- rtx x,
- int strict_p,
- int condexec_p,
- int allow_double_reg_p)
+frv_legitimate_address_p_1 (enum machine_mode mode,
+ rtx x,
+ int strict_p,
+ int condexec_p,
+ int allow_double_reg_p)
{
rtx x0, x1;
int ret = 0;
@@ -3448,7 +3504,7 @@ frv_legitimate_address_p (enum machine_mode mode,
if (TARGET_DEBUG_ADDR)
{
- fprintf (stderr, "\n========== GO_IF_LEGITIMATE_ADDRESS, mode = %s, result = %d, addresses are %sstrict%s\n",
+ fprintf (stderr, "\n========== legitimate_address_p, mode = %s, result = %d, addresses are %sstrict%s\n",
GET_MODE_NAME (mode), ret, (strict_p) ? "" : "not ",
(condexec_p) ? ", inside conditional code" : "");
debug_rtx (x);
@@ -3457,6 +3513,12 @@ frv_legitimate_address_p (enum machine_mode mode,
return ret;
}
+bool
+frv_legitimate_address_p (enum machine_mode mode, rtx x, bool strict_p)
+{
+ return frv_legitimate_address_p_1 (mode, x, strict_p, FALSE, FALSE);
+}
+
/* Given an ADDR, generate code to inline the PLT. */
static rtx
gen_inlined_tls_plt (rtx addr)
@@ -3628,7 +3690,7 @@ frv_legitimize_address (rtx x,
return frv_legitimize_tls_address (x, model);
}
- return NULL_RTX;
+ return x;
}
/* Test whether a local function descriptor is canonical, i.e.,
@@ -3751,8 +3813,8 @@ frv_legitimate_memory_operand (rtx op, enum machine_mode mode, int condexec_p)
{
return ((GET_MODE (op) == mode || mode == VOIDmode)
&& GET_CODE (op) == MEM
- && frv_legitimate_address_p (mode, XEXP (op, 0),
- reload_completed, condexec_p, FALSE));
+ && frv_legitimate_address_p_1 (mode, XEXP (op, 0),
+ reload_completed, condexec_p, FALSE));
}
void
@@ -3912,7 +3974,7 @@ condexec_memory_operand (rtx op, enum machine_mode mode)
return FALSE;
addr = XEXP (op, 0);
- return frv_legitimate_address_p (mode, addr, reload_completed, TRUE, FALSE);
+ return frv_legitimate_address_p_1 (mode, addr, reload_completed, TRUE, FALSE);
}
/* Return true if the bare return instruction can be used outside of the
@@ -4731,19 +4793,18 @@ frv_emit_comparison (enum rtx_code test, rtx op0, rtx op1)
}
-/* Emit code for a conditional branch. The comparison operands were previously
- stored in frv_compare_op0 and frv_compare_op1.
-
+/* Emit code for a conditional branch.
XXX: I originally wanted to add a clobber of a CCR register to use in
conditional execution, but that confuses the rest of the compiler. */
int
-frv_emit_cond_branch (enum rtx_code test, rtx label)
+frv_emit_cond_branch (rtx operands[])
{
rtx test_rtx;
rtx label_ref;
rtx if_else;
- rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
+ enum rtx_code test = GET_CODE (operands[0]);
+ rtx cc_reg = frv_emit_comparison (test, operands[1], operands[2]);
enum machine_mode cc_mode = GET_MODE (cc_reg);
/* Branches generate:
@@ -4751,7 +4812,7 @@ frv_emit_cond_branch (enum rtx_code test, rtx label)
(if_then_else (<test>, <cc_reg>, (const_int 0))
(label_ref <branch_label>)
(pc))) */
- label_ref = gen_rtx_LABEL_REF (VOIDmode, label);
+ label_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
test_rtx = gen_rtx_fmt_ee (test, cc_mode, cc_reg, const0_rtx);
if_else = gen_rtx_IF_THEN_ELSE (cc_mode, test_rtx, label_ref, pc_rtx);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_else));
@@ -4759,23 +4820,23 @@ frv_emit_cond_branch (enum rtx_code test, rtx label)
}
-/* Emit code to set a gpr to 1/0 based on a comparison. The comparison
- operands were previously stored in frv_compare_op0 and frv_compare_op1. */
+/* Emit code to set a gpr to 1/0 based on a comparison. */
int
-frv_emit_scc (enum rtx_code test, rtx target)
+frv_emit_scc (rtx operands[])
{
rtx set;
rtx test_rtx;
rtx clobber;
rtx cr_reg;
- rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
+ enum rtx_code test = GET_CODE (operands[1]);
+ rtx cc_reg = frv_emit_comparison (test, operands[2], operands[3]);
/* SCC instructions generate:
(parallel [(set <target> (<test>, <cc_reg>, (const_int 0))
(clobber (<ccr_reg>))]) */
test_rtx = gen_rtx_fmt_ee (test, SImode, cc_reg, const0_rtx);
- set = gen_rtx_SET (VOIDmode, target, test_rtx);
+ set = gen_rtx_SET (VOIDmode, operands[0], test_rtx);
cr_reg = ((TARGET_ALLOC_CC)
? gen_reg_rtx (CC_CCRmode)
@@ -4837,7 +4898,8 @@ frv_emit_cond_move (rtx dest, rtx test_rtx, rtx src1, rtx src2)
rtx cr_reg;
rtx if_rtx;
enum rtx_code test = GET_CODE (test_rtx);
- rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
+ rtx cc_reg = frv_emit_comparison (test,
+ XEXP (test_rtx, 0), XEXP (test_rtx, 1));
enum machine_mode cc_mode = GET_MODE (cc_reg);
/* Conditional move instructions generate:
@@ -5814,7 +5876,7 @@ frv_ifcvt_rewrite_mem (rtx mem, enum machine_mode mode, rtx insn)
{
rtx addr = XEXP (mem, 0);
- if (!frv_legitimate_address_p (mode, addr, reload_completed, TRUE, FALSE))
+ if (!frv_legitimate_address_p_1 (mode, addr, reload_completed, TRUE, FALSE))
{
if (GET_CODE (addr) == PLUS)
{
@@ -6280,9 +6342,11 @@ frv_trampoline_size (void)
sethi #0, <static_chain>
jmpl @(gr0,<jmp_reg>) */
-void
-frv_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
+static void
+frv_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
{
+ rtx addr = XEXP (m_tramp, 0);
+ rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
rtx sc_reg = force_reg (Pmode, static_chain);
emit_library_call (gen_rtx_SYMBOL_REF (SImode, "__trampoline_setup"),
« no previous file with comments | « gcc/gcc/config/fr30/t-fr30 ('k') | gcc/gcc/config/frv/frv-protos.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698