aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2008-09-02 01:44:33 +0000
committerPaul Brook <pbrook@gcc.gnu.org>2008-09-02 01:44:33 +0000
commit571191af2664d15b44e3a9795bc0cba9df44b8a6 (patch)
treeedc8d4f03839a499afaebcfdf54c24f88f391bce /gcc/config/arm
parent4e2eb53c13c1fc2e3f777fa9cd6827716c6b81e4 (diff)
downloadgcc-571191af2664d15b44e3a9795bc0cba9df44b8a6.zip
gcc-571191af2664d15b44e3a9795bc0cba9df44b8a6.tar.gz
gcc-571191af2664d15b44e3a9795bc0cba9df44b8a6.tar.bz2
invoke.texi: Document -mword-relocations.
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. From-SVN: r139881
Diffstat (limited to 'gcc/config/arm')
-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
8 files changed, 93 insertions, 5 deletions
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