aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/config/arm/arm-protos.h1
-rw-r--r--gcc/config/arm/arm.c48
-rw-r--r--gcc/config/arm/arm.h8
-rw-r--r--gcc/config/arm/arm.md30
-rw-r--r--gcc/config/arm/arm.opt4
-rw-r--r--gcc/config/arm/symbian.h2
-rw-r--r--gcc/config/arm/uclinux-elf.h2
-rw-r--r--gcc/config/arm/vxworks.h3
-rw-r--r--gcc/doc/invoke.texi10
10 files changed, 119 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d92bff6..7c4df92d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,22 @@
2008-09-01 Paul Brook <paul@codesourcery.com>
+ * doc/invoke.texi: Document -mword-relocations.
+ * config/arm/uclinux-elf.h (TARGET_DEFAULT_WORD_RELOCATIONS): Define.
+ * config/arm/symbian.h (TARGET_DEFAULT_WORD_RELOCATIONS): Define.
+ * config/arm/vxworks.h (TARGET_DEFAULT_WORD_RELOCATIONS): Define.
+ * config/arm/arm.c (arm_split_constant): Use arm_emit_movpair.
+ (arm_rtx_costs_1, arm_size_rtx_costs): Handle HIGH and LO_SUM.
+ (arm_emit_movpair): New function.
+ (arm_print_operand <c>): Handle sybolic addresses.
+ * config/arm/arm.h (TARGET_USE_MOVT): Define.
+ (TARGET_DEFAULT_WORD_RELOCATIONS): Define.
+ * config/arm/arm-protos.h (arm_emit_movpair): Add prototype.
+ * config/arm/arm.opt: Add -mword-relocations.
+ * config/arm/arm.md (movsi): Use arm_emit_movpair.
+ (arm_movt, arm_movw): New.
+
+2008-09-01 Paul Brook <paul@codesourcery.com>
+
* config/arm/arm.c (arm_override_options): Set arm_abi earlier.
Allow Interworking on ARMv4 EABI based targets.
* config/arm/bpabi.h (TARGET_FIX_V4BX_SPEC): Define.
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index d0e408c..ab08ef4 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -123,6 +123,7 @@ extern const char *fp_immediate_constant (rtx);
extern void arm_emit_call_insn (rtx, rtx);
extern const char *output_call (rtx *);
extern const char *output_call_mem (rtx *);
+void arm_emit_movpair (rtx, rtx);
extern const char *output_mov_long_double_fpa_from_arm (rtx *);
extern const char *output_mov_long_double_arm_from_fpa (rtx *);
extern const char *output_mov_long_double_arm_from_arm (rtx *);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index c6128ac..724f1ac 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1926,14 +1926,22 @@ arm_split_constant (enum rtx_code code, enum machine_mode mode, rtx insn,
{
/* Currently SET is the only monadic value for CODE, all
the rest are diadic. */
- emit_set_insn (target, GEN_INT (val));
+ if (TARGET_USE_MOVT)
+ arm_emit_movpair (target, GEN_INT (val));
+ else
+ emit_set_insn (target, GEN_INT (val));
+
return 1;
}
else
{
rtx temp = subtargets ? gen_reg_rtx (mode) : target;
- emit_set_insn (temp, GEN_INT (val));
+ if (TARGET_USE_MOVT)
+ arm_emit_movpair (temp, GEN_INT (val));
+ else
+ emit_set_insn (temp, GEN_INT (val));
+
/* For MINUS, the value is subtracted from, since we never
have subtraction of a constant. */
if (code == MINUS)
@@ -5117,6 +5125,10 @@ arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
case SYMBOL_REF:
return 6;
+ case HIGH:
+ case LO_SUM:
+ return (outer == SET) ? 1 : -1;
+
case CONST_DOUBLE:
if (arm_const_double_rtx (x) || vfp3_const_double_rtx (x))
return outer == SET ? 2 : -1;
@@ -5343,6 +5355,13 @@ arm_size_rtx_costs (rtx x, int code, int outer_code, int *total)
*total = COSTS_N_INSNS (4);
return true;
+ case HIGH:
+ case LO_SUM:
+ /* We prefer constant pool entries to MOVW/MOVT pairs, so bump the
+ cost of these slightly. */
+ *total = COSTS_N_INSNS (1) + 1;
+ return true;
+
default:
if (mode != VOIDmode)
*total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
@@ -9891,6 +9910,14 @@ output_mov_long_double_arm_from_arm (rtx *operands)
}
+/* Emit a MOVW/MOVT pair. */
+void arm_emit_movpair (rtx dest, rtx src)
+{
+ emit_set_insn (dest, gen_rtx_HIGH (SImode, src));
+ emit_set_insn (dest, gen_rtx_LO_SUM (SImode, dest, src));
+}
+
+
/* Output a move from arm registers to an fpa registers.
OPERANDS[0] is an fpa register.
OPERANDS[1] is the first registers of an arm register pair. */
@@ -12906,10 +12933,21 @@ arm_print_operand (FILE *stream, rtx x, int code)
}
return;
- /* An integer without a preceding # sign. */
+ /* An integer or symbol address without a preceding # sign. */
case 'c':
- gcc_assert (GET_CODE (x) == CONST_INT);
- fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+ fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ break;
+
+ case SYMBOL_REF:
+ output_addr_const (stream, x);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
return;
case 'B':
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index a8820cb..e12c3f9 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -241,6 +241,9 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
#define TARGET_INT_SIMD \
(TARGET_32BIT && arm_arch6 && arm_arch_notm)
+/* Should MOVW/MOVT be used in preference to a constant pool. */
+#define TARGET_USE_MOVT (arm_arch_thumb2 && !optimize_size)
+
/* We could use unified syntax for arm mode, but for now we just use it
for Thumb-2. */
#define TARGET_UNIFIED_ASM TARGET_THUMB2
@@ -1962,6 +1965,11 @@ typedef struct
SYMBOL's section. */
#define ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 0
+/* Nonzero if all target requires all absolute relocations be R_ARM_ABS32. */
+#ifndef TARGET_DEFAULT_WORD_RELOCATIONS
+#define TARGET_DEFAULT_WORD_RELOCATIONS 0
+#endif
+
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 204f8a4..c5708d6 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -4823,6 +4823,14 @@
optimize && can_create_pseudo_p ());
DONE;
}
+
+ if (TARGET_USE_MOVT && !target_word_relocations
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && !flag_pic && !arm_tls_referenced_p (operands[1]))
+ {
+ arm_emit_movpair (operands[0], operands[1]);
+ DONE;
+ }
}
else /* TARGET_THUMB1... */
{
@@ -4883,6 +4891,28 @@
"
)
+;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
+;; LO_SUM adds in the high bits. Fortunately these are opaque operations
+;; so this does not matter.
+(define_insn "*arm_movt"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:SI 2 "general_operand" "i")))]
+ "TARGET_32BIT"
+ "movt%?\t%0, #:upper16:%c2"
+ [(set_attr "predicable" "yes")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*arm_movw"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
+ (high:SI (match_operand:SI 1 "general_operand" "i")))]
+ "TARGET_32BIT"
+ "movw%?\t%0, #:lower16:%c1"
+ [(set_attr "predicable" "yes")
+ (set_attr "length" "4")]
+)
+
(define_insn "*arm_movsi_insn"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
(match_operand:SI 1 "general_operand" "rk, I,K,N,mi,rk"))]
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index 2b005e4..c8bdcf8 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -156,3 +156,7 @@ Assume big endian bytes, little endian words
mvectorize-with-neon-quad
Target Report Mask(NEON_VECTORIZE_QUAD)
Use Neon quad-word (rather than double-word) registers for vectorization
+
+mword-relocations
+Target Report Var(target_word_relocations) Init(TARGET_DEFAULT_WORD_RELOCATIONS)
++Only generate absolute relocations on word sized values.
diff --git a/gcc/config/arm/symbian.h b/gcc/config/arm/symbian.h
index 3e583b3..af92c72 100644
--- a/gcc/config/arm/symbian.h
+++ b/gcc/config/arm/symbian.h
@@ -101,3 +101,5 @@
/* SymbianOS cannot merge entities with vague linkage at runtime. */
#define TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P false
+
+#define TARGET_DEFAULT_WORD_RELOCATIONS 1
diff --git a/gcc/config/arm/uclinux-elf.h b/gcc/config/arm/uclinux-elf.h
index 98a7850..89b96f2 100644
--- a/gcc/config/arm/uclinux-elf.h
+++ b/gcc/config/arm/uclinux-elf.h
@@ -83,3 +83,5 @@
"%{pthread:-lpthread} \
%{shared:-lc} \
%{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+
+#define TARGET_DEFAULT_WORD_RELOCATIONS 1
diff --git a/gcc/config/arm/vxworks.h b/gcc/config/arm/vxworks.h
index 4416557..a7610ac 100644
--- a/gcc/config/arm/vxworks.h
+++ b/gcc/config/arm/vxworks.h
@@ -113,3 +113,6 @@ along with GCC; see the file COPYING3. If not see
cannot allow arbitrary offsets for shared libraries either. */
#undef ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P
#define ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 1
+
+#undef TARGET_DEFAULT_WORD_RELOCATIONS
+#define TARGET_DEFAULT_WORD_RELOCATIONS 1
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 33070a09..aa73f82 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -448,7 +448,8 @@ Objective-C and Objective-C++ Dialects}.
-mthumb -marm @gol
-mtpcs-frame -mtpcs-leaf-frame @gol
-mcaller-super-interworking -mcallee-super-interworking @gol
--mtp=@var{name}}
+-mtp=@var{name}
+-mword-relocations}
@emph{AVR Options}
@gccoptlist{-mmcu=@var{mcu} -msize -minit-stack=@var{n} -mno-interrupts @gol
@@ -8910,6 +8911,13 @@ models are @option{soft}, which generates calls to @code{__aeabi_read_tp},
best available method for the selected processor. The default setting is
@option{auto}.
+@item -mword-relocations
+@opindex mword-relocations
+Only generate absolute relocations on word sized values (i.e. R_ARM_ABS32).
+This is enabled by default on targets (uClinux, SymbianOS) where the runtime
+loader imposes this restriction, and when @option{-fpic} or @option{-fPIC}
+is speficied.
+
@end table
@node AVR Options