summaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386.md
diff options
context:
space:
mode:
authorhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2012-03-10 18:47:52 +0000
committerhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2012-03-10 18:47:52 +0000
commitfe73ce464d6780175d5d8add5fbff7a9e5c639da (patch)
tree509d003bc07727357da8824fb54ec875c92e9a2f /gcc/config/i386/i386.md
parent553877d921e5d7e7d156c95e1214106d2edfa37c (diff)
downloadgcc-fe73ce464d6780175d5d8add5fbff7a9e5c639da.tar.gz
Properly generate x32 TLS IE sequence
2012-03-10 H.J. Lu <hongjiu.lu@intel.com> * config/i386/i386.c (ix86_decompose_address): Disallow fs:(reg) if Pmode != word_mode. (legitimize_tls_address): Call gen_tls_initial_exec_x32 if Pmode == SImode for x32. * config/i386/i386.md (UNSPEC_TLS_IE_X32): New. (tls_initial_exec_x32): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@185179 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r--gcc/config/i386/i386.md23
1 files changed, 23 insertions, 0 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index a4a7d3ab1b8..dcbfab43eee 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -96,6 +96,7 @@
UNSPEC_TLS_LD_BASE
UNSPEC_TLSDESC
UNSPEC_TLS_IE_SUN
+ UNSPEC_TLS_IE_X32
;; Other random patterns
UNSPEC_SCAS
@@ -12777,6 +12778,28 @@
}
[(set_attr "type" "multi")])
+;; When Pmode == SImode, there may be no REX prefix for ADD. Avoid
+;; any instructions between MOV and ADD, which may interfere linker
+;; IE->LE optimization, since the last byte of the previous instruction
+;; before ADD may look like a REX prefix. This also avoids
+;; movl x@gottpoff(%rip), %reg32
+;; movl $fs:(%reg32), %reg32
+;; Since address override works only on the (reg32) part in fs:(reg32),
+;; we can't use it as memory operand.
+(define_insn "tls_initial_exec_x32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI
+ [(match_operand:SI 1 "tls_symbolic_operand" "")]
+ UNSPEC_TLS_IE_X32))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_X32"
+{
+ output_asm_insn
+ ("mov{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}", operands);
+ return "add{l}\t{%a1@gottpoff(%%rip), %0|%0, %a1@gottpoff[rip]}";
+}
+ [(set_attr "type" "multi")])
+
;; GNU2 TLS patterns can be split.
(define_expand "tls_dynamic_gnu2_32"