+2008-11-03 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/arm/arm.md (UNSPEC_PIC_BASE): Update documentation.
+ (UNSPEC_GOTSYM_OFF): New unspec.
+ (pic_add_dot_plus_four): Simplify the UNSPEC_PIC_BASE operands.
+ (pic_add_dot_plus_eight): Likewise.
+ (tls_load_dot_plus_eight): Likewise. Update peephole2.
+ * config/arm/thumb2.md (pic_load_dot_plus_four): Simplify the
+ UNSPEC_PIC_BASE operands.
+ * config/arm/arm.c (arm_load_pic_register): Use UNSPEC_GOTSYM_OFF.
+ (arm_output_addr_const_extra): Handle it.
+
2008-11-03 Eric Botcazou <ebotcazou@adacore.com>
* config/i386/i386.c (classify_argument) <ARRAY_TYPE>: Promote partial
void
arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
{
- rtx l1, labelno, pic_tmp, pic_tmp2, pic_rtx, pic_reg;
- rtx global_offset_table;
+ rtx l1, labelno, pic_tmp, pic_rtx, pic_reg;
if (crtl->uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
return;
l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
l1 = gen_rtx_CONST (VOIDmode, l1);
- global_offset_table
- = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
/* On the ARM the PC register contains 'dot + 8' at the time of the
addition, on the Thumb it is 'dot + 4'. */
- pic_tmp = plus_constant (l1, TARGET_ARM ? 8 : 4);
- if (GOT_PCREL)
- {
- pic_tmp2 = gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx);
- pic_tmp2 = gen_rtx_CONST (VOIDmode, pic_tmp2);
- }
- else
- pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
-
- pic_rtx = gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp);
+ pic_rtx = plus_constant (l1, TARGET_ARM ? 8 : 4);
+ pic_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, pic_rtx),
+ UNSPEC_GOTSYM_OFF);
pic_rtx = gen_rtx_CONST (Pmode, pic_rtx);
if (TARGET_ARM)
return TRUE;
}
+ else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_GOTSYM_OFF)
+ {
+ assemble_name (fp, "_GLOBAL_OFFSET_TABLE_");
+ if (GOT_PCREL)
+ fputs ("+.", fp);
+ fputs ("-(", fp);
+ output_addr_const (fp, XVECEXP (x, 0, 0));
+ fputc (')', fp);
+ return TRUE;
+ }
else if (GET_CODE (x) == CONST_VECTOR)
return arm_emit_vector_const (fp, x);
(UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
; usage, that is, we will add the pic_register
; value to it before trying to dereference it.
- (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
- ; GLOBAL_OFFSET_TABLE. The operation is fully
- ; described by the RTL but must be wrapped to
- ; prevent combine from trying to rip it apart.
+ (UNSPEC_PIC_BASE 4) ; Add PC and all but the last operand together,
+ ; The last operand is the number of a PIC_LABEL
+ ; that points at the containing instruction.
(UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
; being scheduled before the stack adjustment insn.
(UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
; generate correct unwind information.
(UNSPEC_PIC_OFFSET 23) ; A symbolic 12-bit OFFSET that has been treated
; correctly for PIC usage.
+ (UNSPEC_GOTSYM_OFF 24) ; The offset of the start of the the GOT from a
+ ; a given symbolic address.
]
)
(define_insn "pic_add_dot_plus_four"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
- (const (plus:SI (pc) (const_int 4))))
+ (unspec:SI [(match_operand:SI 1 "register_operand" "0")
+ (const_int 4)
(match_operand 2 "" "")]
UNSPEC_PIC_BASE))]
"TARGET_THUMB1"
(define_insn "pic_add_dot_plus_eight"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
- (const (plus:SI (pc) (const_int 8))))
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+ (const_int 8)
(match_operand 2 "" "")]
UNSPEC_PIC_BASE))]
"TARGET_ARM"
(define_insn "tls_load_dot_plus_eight"
[(set (match_operand:SI 0 "register_operand" "+r")
- (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
- (const (plus:SI (pc) (const_int 8))))
+ (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+ (const_int 8)
(match_operand 2 "" "")]
UNSPEC_PIC_BASE)))]
"TARGET_ARM"
;; tls_load_dot_plus_eight by a peephole.
(define_peephole2
- [(parallel [(set (match_operand:SI 0 "register_operand" "")
- (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
- (const (plus:SI (pc) (const_int 8))))]
- UNSPEC_PIC_BASE))
- (use (label_ref (match_operand 1 "" "")))])
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(match_operand:SI 3 "register_operand" "")
+ (const_int 8)
+ (match_operand 1 "" "")]
+ UNSPEC_PIC_BASE))
(set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
"TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
- [(parallel [(set (match_dup 2)
- (mem:SI (unspec:SI [(plus:SI (match_dup 3)
- (const (plus:SI (pc) (const_int 8))))]
- UNSPEC_PIC_BASE)))
- (use (label_ref (match_dup 1)))])]
+ [(set (match_dup 2)
+ (mem:SI (unspec:SI [(match_dup 3)
+ (const_int 8)
+ (match_dup 1)]
+ UNSPEC_PIC_BASE)))]
""
)
;; word aligned.
(define_insn "pic_load_dot_plus_four"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(const (plus:SI (pc) (const_int 4)))
- (use (match_operand 1 "" ""))]
+ (unspec:SI [(const_int 4)
+ (match_operand 1 "" "")]
UNSPEC_PIC_BASE))]
"TARGET_THUMB2"
"*