aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2008-10-06 19:07:13 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2008-10-06 19:07:13 +0000
commit2e4316da802a3049f67686001f9dbca5711dcace (patch)
treeccf0ce9fa3c9617218e9f154f6b176a7969628ca /gcc/config/rs6000
parent3517d3a0870e7081d4ded0fa4cc590c602713a8c (diff)
downloadgcc-2e4316da802a3049f67686001f9dbca5711dcace.zip
gcc-2e4316da802a3049f67686001f9dbca5711dcace.tar.gz
gcc-2e4316da802a3049f67686001f9dbca5711dcace.tar.bz2
rs6000-protos.h (rs6000_output_addr_const_extra): Declare.
gcc/ * config/rs6000/rs6000-protos.h (rs6000_output_addr_const_extra): Declare. * config/rs6000/rs6000.h (OUTPUT_ADDR_CONST_EXTRA): New macro. * config/rs6000/rs6000.md (UNSPEC_TOCREL): New constant. * config/rs6000/rs6000.c (constant_pool_expr_1): Delete. (constant_pool_expr_p): Use split_const and check the base. (toc_relative_expr_p): Likewise, checking for an UNSPEC_TOCREL instead of a MINUS. (legitimate_constant_pool_address_p): Check toc_relative_p instead of constant_pool_expr_p. (print_operand_address): Always use output_addr_const for constant pool addresses. (rs6000_output_addr_const_extra): New function. (create_TOC_reference): Create an UNSPEC_TOCREL instead of a MINUS. From-SVN: r140910
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.c122
-rw-r--r--gcc/config/rs6000/rs6000.h6
-rw-r--r--gcc/config/rs6000/rs6000.md1
4 files changed, 49 insertions, 81 deletions
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index a9fb2ab..42e939b 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -77,6 +77,7 @@ extern int extract_ME (rtx);
extern void rs6000_output_function_entry (FILE *, const char *);
extern void print_operand (FILE *, rtx, int);
extern void print_operand_address (FILE *, rtx);
+extern bool rs6000_output_addr_const_extra (FILE *, rtx);
extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
enum rtx_code);
extern void rs6000_emit_sCOND (enum rtx_code, rtx);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index d230dfd..e6844dd 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -765,7 +765,6 @@ static void rs6000_emit_allocate_stack (HOST_WIDE_INT, int, int);
static unsigned rs6000_hash_constant (rtx);
static unsigned toc_hash_function (const void *);
static int toc_hash_eq (const void *, const void *);
-static int constant_pool_expr_1 (rtx, int *, int *);
static bool constant_pool_expr_p (rtx);
static bool legitimate_small_data_p (enum machine_mode, rtx);
static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int);
@@ -3505,58 +3504,28 @@ gpr_or_gpr_p (rtx op0, rtx op1)
/* Subroutines of rs6000_legitimize_address and rs6000_legitimate_address. */
-static int
-constant_pool_expr_1 (rtx op, int *have_sym, int *have_toc)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- if (RS6000_SYMBOL_REF_TLS_P (op))
- return 0;
- else if (CONSTANT_POOL_ADDRESS_P (op))
- {
- if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op), Pmode))
- {
- *have_sym = 1;
- return 1;
- }
- else
- return 0;
- }
- else if (! strcmp (XSTR (op, 0), toc_label_name))
- {
- *have_toc = 1;
- return 1;
- }
- else
- return 0;
- case PLUS:
- case MINUS:
- return (constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc)
- && constant_pool_expr_1 (XEXP (op, 1), have_sym, have_toc));
- case CONST:
- return constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc);
- case CONST_INT:
- return 1;
- default:
- return 0;
- }
-}
-
static bool
constant_pool_expr_p (rtx op)
{
- int have_sym = 0;
- int have_toc = 0;
- return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_sym;
+ rtx base, offset;
+
+ split_const (op, &base, &offset);
+ return (GET_CODE (base) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (base)
+ && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (base), Pmode));
}
bool
toc_relative_expr_p (rtx op)
{
- int have_sym = 0;
- int have_toc = 0;
- return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_toc;
+ rtx base, offset;
+
+ if (GET_CODE (op) != CONST)
+ return false;
+
+ split_const (op, &base, &offset);
+ return (GET_CODE (base) == UNSPEC
+ && XINT (base, 1) == UNSPEC_TOCREL);
}
bool
@@ -3566,7 +3535,7 @@ legitimate_constant_pool_address_p (rtx x)
&& GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == REG
&& (TARGET_MINIMAL_TOC || REGNO (XEXP (x, 0)) == TOC_REGISTER)
- && constant_pool_expr_p (XEXP (x, 1)));
+ && toc_relative_expr_p (XEXP (x, 1)));
}
static bool
@@ -12572,45 +12541,37 @@ print_operand_address (FILE *file, rtx x)
#endif
else if (legitimate_constant_pool_address_p (x))
{
- if (TARGET_AIX && (!TARGET_ELF || !TARGET_MINIMAL_TOC))
- {
- rtx contains_minus = XEXP (x, 1);
- rtx minus, symref;
- const char *name;
-
- /* Find the (minus (sym) (toc)) buried in X, and temporarily
- turn it into (sym) for output_addr_const. */
- while (GET_CODE (XEXP (contains_minus, 0)) != MINUS)
- contains_minus = XEXP (contains_minus, 0);
-
- minus = XEXP (contains_minus, 0);
- symref = XEXP (minus, 0);
- gcc_assert (GET_CODE (XEXP (minus, 1)) == SYMBOL_REF);
- XEXP (contains_minus, 0) = symref;
- if (TARGET_ELF)
- {
- char *newname;
-
- name = XSTR (symref, 0);
- newname = XALLOCAVEC (char, strlen (name) + sizeof ("@toc"));
- strcpy (newname, name);
- strcat (newname, "@toc");
- XSTR (symref, 0) = newname;
- }
- output_addr_const (file, XEXP (x, 1));
- if (TARGET_ELF)
- XSTR (symref, 0) = name;
- XEXP (contains_minus, 0) = minus;
- }
- else
- output_addr_const (file, XEXP (x, 1));
-
+ output_addr_const (file, XEXP (x, 1));
fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]);
}
else
gcc_unreachable ();
}
+/* Implement OUTPUT_ADDR_CONST_EXTRA for address X. */
+
+bool
+rs6000_output_addr_const_extra (FILE *file, rtx x)
+{
+ if (GET_CODE (x) == UNSPEC)
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_TOCREL:
+ x = XVECEXP (x, 0, 0);
+ gcc_assert (GET_CODE (x) == SYMBOL_REF);
+ output_addr_const (file, x);
+ if (!TARGET_AIX || (TARGET_ELF && TARGET_MINIMAL_TOC))
+ {
+ putc ('-', file);
+ assemble_name (file, toc_label_name);
+ }
+ else if (TARGET_ELF)
+ fputs ("@toc", file);
+ return true;
+ }
+ return false;
+}
+
/* Target hook for assembling integer objects. The PowerPC version has
to handle fixup entries for relocatable code if RELOCATABLE_NEEDS_FIXUP
is defined. It also needs to handle DI-mode objects on 64-bit
@@ -15431,8 +15392,7 @@ create_TOC_reference (rtx symbol)
return gen_rtx_PLUS (Pmode,
gen_rtx_REG (Pmode, TOC_REGISTER),
gen_rtx_CONST (Pmode,
- gen_rtx_MINUS (Pmode, symbol,
- gen_rtx_SYMBOL_REF (Pmode, toc_label_name))));
+ gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_TOCREL)));
}
/* If _Unwind_* has been called from within the same module,
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index e1023da..79250c8 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -2352,6 +2352,12 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
+ do \
+ if (!rs6000_output_addr_const_extra (STREAM, X)) \
+ goto FAIL; \
+ while (0)
+
/* uncomment for disabling the corresponding default options */
/* #define MACHINE_no_sched_interblock */
/* #define MACHINE_no_sched_speculative */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 71a73ad..4146c4f 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -99,6 +99,7 @@
(UNSPEC_DLMZB_CR 46)
(UNSPEC_DLMZB_STRLEN 47)
(UNSPEC_RSQRT 48)
+ (UNSPEC_TOCREL 49)
])
;;