Hello! ABI specifies that TP is loaded in ptr_mode. Attached patch implements this requirement.
2011-07-29 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.md (*load_tp_x32): New. (*load_tp_x32_zext): Ditto. (*add_tp_x32): Ditto. (*add_tp_x32_zext): Ditto. (*load_tp_<mode>): Disable for !TARGET_X32 targets. (*add_tp_<mode>): Ditto. * config/i386/i386.c (get_thread_pointer): Load thread pointer in ptr_mode and convert to Pmode if needed. Testing on x86_64-pc-linux-gnu in progress. H.J., please test this version on x32. Uros.
Index: i386.md =================================================================== --- i386.md (revision 176915) +++ i386.md (working copy) @@ -12444,10 +12444,32 @@ (define_mode_attr tp_seg [(SI "gs") (DI "fs")]) ;; Load and add the thread base pointer from %<tp_seg>:0. +(define_insn "*load_tp_x32" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(const_int 0)] UNSPEC_TP))] + "TARGET_X32" + "mov{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}" + [(set_attr "type" "imov") + (set_attr "modrm" "0") + (set_attr "length" "7") + (set_attr "memory" "load") + (set_attr "imm_disp" "false")]) + +(define_insn "*load_tp_x32_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (unspec:SI [(const_int 0)] UNSPEC_TP)))] + "TARGET_X32" + "mov{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}" + [(set_attr "type" "imov") + (set_attr "modrm" "0") + (set_attr "length" "7") + (set_attr "memory" "load") + (set_attr "imm_disp" "false")]) + (define_insn "*load_tp_<mode>" [(set (match_operand:P 0 "register_operand" "=r") (unspec:P [(const_int 0)] UNSPEC_TP))] - "" + "!TARGET_X32" "mov{<imodesuffix>}\t{%%<tp_seg>:0, %0|%0, <iptrsize> PTR <tp_seg>:0}" [(set_attr "type" "imov") (set_attr "modrm" "0") @@ -12455,12 +12477,39 @@ (set_attr "memory" "load") (set_attr "imm_disp" "false")]) +(define_insn "*add_tp_x32" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP) + (match_operand:SI 1 "register_operand" "0"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_X32" + "add{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}" + [(set_attr "type" "alu") + (set_attr "modrm" "0") + (set_attr "length" "7") + (set_attr "memory" "load") + (set_attr "imm_disp" "false")]) + +(define_insn "*add_tp_x32_zext" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP) + (match_operand:SI 1 "register_operand" "0")))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_X32" + "add{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}" + [(set_attr "type" "alu") + (set_attr "modrm" "0") + (set_attr "length" "7") + (set_attr "memory" "load") + (set_attr "imm_disp" "false")]) + (define_insn "*add_tp_<mode>" [(set (match_operand:P 0 "register_operand" "=r") (plus:P (unspec:P [(const_int 0)] UNSPEC_TP) (match_operand:P 1 "register_operand" "0"))) (clobber (reg:CC FLAGS_REG))] - "" + "!TARGET_X32" "add{<imodesuffix>}\t{%%<tp_seg>:0, %0|%0, <iptrsize> PTR <tp_seg>:0}" [(set_attr "type" "alu") (set_attr "modrm" "0") Index: i386.c =================================================================== --- i386.c (revision 176915) +++ i386.c (working copy) @@ -12118,17 +12118,15 @@ legitimize_pic_address (rtx orig, rtx re static rtx get_thread_pointer (bool to_reg) { - rtx tp, reg, insn; + rtx tp = gen_rtx_UNSPEC (ptr_mode, gen_rtvec (1, const0_rtx), UNSPEC_TP); - tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP); - if (!to_reg) - return tp; + if (GET_MODE (tp) != Pmode) + tp = convert_to_mode (Pmode, tp, 1); - reg = gen_reg_rtx (Pmode); - insn = gen_rtx_SET (VOIDmode, reg, tp); - insn = emit_insn (insn); + if (to_reg) + tp = copy_addr_to_reg (tp); - return reg; + return tp; } /* Construct the SYMBOL_REF for the tls_get_addr function. */