diff options
author | Paul Brook <paul@codesourcery.com> | 2008-09-02 01:44:33 +0000 |
---|---|---|
committer | Paul Brook <pbrook@gcc.gnu.org> | 2008-09-02 01:44:33 +0000 |
commit | 571191af2664d15b44e3a9795bc0cba9df44b8a6 (patch) | |
tree | edc8d4f03839a499afaebcfdf54c24f88f391bce /gcc/config | |
parent | 4e2eb53c13c1fc2e3f777fa9cd6827716c6b81e4 (diff) | |
download | gcc-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')
-rw-r--r-- | gcc/config/arm/arm-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 48 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 8 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 30 | ||||
-rw-r--r-- | gcc/config/arm/arm.opt | 4 | ||||
-rw-r--r-- | gcc/config/arm/symbian.h | 2 | ||||
-rw-r--r-- | gcc/config/arm/uclinux-elf.h | 2 | ||||
-rw-r--r-- | gcc/config/arm/vxworks.h | 3 |
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 |