On Wed, Jul 27, 2011 at 07:55:08PM -0700, H.J. Lu wrote: > TLS on X32 is almost identical to TLS on x86-64. The only difference is > x32 address space is 32bit. That means TLS symbols can be in either > SImode or DImode with upper 32bit zero. This patch updates > tls_global_dynamic_64 to support x32. OK for trunk? >
Small update to correct *tls_global_dynamic_64 length. H.J. -- 2011-07-27 H.J. Lu <hongjiu...@intel.com> PR target/47715 * config/i386/i386.md (PTR64): New. (*tls_global_dynamic_64): Rename to ... (*tls_global_dynamic_64_<mode>): This. Put PTR64 on operand 1. (tls_global_dynamic_64): Rename to ... (tls_global_dynamic_64_<mode>): This. Put PTR64 on operand 1. * config/i386/i386.c (legitimize_tls_address): Updated. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 8723dc5..31d5b8e 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -12215,9 +12215,22 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) if (TARGET_64BIT) { rtx rax = gen_rtx_REG (Pmode, AX_REG), insns; + rtx (*tls_global_dynamic) (rtx, rtx, rtx); + + switch (GET_MODE (x)) + { + case SImode: + tls_global_dynamic = gen_tls_global_dynamic_64_si; + break; + case DImode: + tls_global_dynamic = gen_tls_global_dynamic_64_di; + break; + default: + gcc_unreachable (); + } start_sequence (); - emit_call_insn (gen_tls_global_dynamic_64 (rax, x, caddr)); + emit_call_insn (tls_global_dynamic (rax, x, caddr)); insns = get_insns (); end_sequence (); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index e91a299..f59e685 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -951,6 +951,9 @@ ;; This mode iterator allows :P to be used for patterns that operate on ;; pointer-sized quantities. Exactly one of the two alternatives will match. (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) + +;; Pointer modes in 64bit. +(define_mode_iterator PTR64 [(SI "TARGET_X32") DI]) ;; Scheduling descriptions @@ -12322,16 +12325,17 @@ (clobber (match_scratch:SI 5 "")) (clobber (reg:CC FLAGS_REG))])]) -(define_insn "*tls_global_dynamic_64" +(define_insn "*tls_global_dynamic_64_<mode>" [(set (match_operand:DI 0 "register_operand" "=a") (call:DI (mem:QI (match_operand:DI 2 "constant_call_address_operand" "z")) (match_operand:DI 3 "" ""))) - (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + (unspec:DI [(match_operand:PTR64 1 "tls_symbolic_operand" "")] UNSPEC_TLS_GD)] "TARGET_64BIT" { - fputs (ASM_BYTE "0x66\n", asm_out_file); + if (!TARGET_X32) + fputs (ASM_BYTE "0x66\n", asm_out_file); output_asm_insn ("lea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}", operands); fputs (ASM_SHORT "0x6666\n", asm_out_file); @@ -12341,15 +12345,16 @@ return "call\t%P2"; } [(set_attr "type" "multi") - (set_attr "length" "16")]) + (set (attr "length") + (symbol_ref "TARGET_X32 ? 15 : 16"))]) -(define_expand "tls_global_dynamic_64" +(define_expand "tls_global_dynamic_64_<mode>" [(parallel [(set (match_operand:DI 0 "register_operand" "") (call:DI (mem:QI (match_operand:DI 2 "constant_call_address_operand" "")) (const_int 0))) - (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + (unspec:DI [(match_operand:PTR64 1 "tls_symbolic_operand" "")] UNSPEC_TLS_GD)])]) (define_insn "*tls_local_dynamic_base_32_gnu"