i386.md (iptrsize): New mode attribute.
authorUros Bizjak <ubizjak@gmail.com>
Mon, 6 Sep 2010 06:43:54 +0000 (08:43 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Mon, 6 Sep 2010 06:43:54 +0000 (08:43 +0200)
* config/i386/i386.md (iptrsize): New mode attribute.
(tp_seg): Ditto.
(*load_tp_<mode>): Macroize insn from *load_tp_{si,di} using P
mode iterator.
(*add_tp_<mode>): Ditto from *add_tp_{si,di}.
(stack_protect_set_<mode>): Ditto from stack_protect_set_{si,di}.
(stack_protect_test_<mode>): Ditto from stack_protect_test_{si,di}.
(stack_tls_protect_set_<mode>): Ditto from
stack_tls_protect_set_{si,di}.  Use %@ to output segment register
of thread base pointer load.
(stack_tls_protect_test_<mode>): Ditto from
stack_tls_protect_test_{si,di}.  Use %@ to output segment register
of thread base pointer load.
(stack_protect_set): Rewrite using indirect functions.
(stack_protect_test): Ditto.
* config/i386/i386.c (ix86_print_operand_punct_valid): Add '@'.
(ix86_print_operand): Handle '@'.

From-SVN: r163900

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.md

index 141063e..1b47551 100644 (file)
@@ -1,3 +1,23 @@
+2010-09-06  Uros Bizjak  <ubizjak@gmail.com>
+
+       * config/i386/i386.md (iptrsize): New mode attribute.
+       (tp_seg): Ditto.
+       (*load_tp_<mode>): Macroize insn from *load_tp_{si,di} using P
+       mode iterator.
+       (*add_tp_<mode>): Ditto from *add_tp_{si,di}.
+       (stack_protect_set_<mode>): Ditto from stack_protect_set_{si,di}.
+       (stack_protect_test_<mode>): Ditto from stack_protect_test_{si,di}.
+       (stack_tls_protect_set_<mode>): Ditto from
+       stack_tls_protect_set_{si,di}.  Use %@ to output segment register
+       of thread base pointer load.
+       (stack_tls_protect_test_<mode>): Ditto from
+       stack_tls_protect_test_{si,di}.  Use %@ to output segment register
+       of thread base pointer load.
+       (stack_protect_set): Rewrite using indirect functions.
+       (stack_protect_test): Ditto.
+       * config/i386/i386.c (ix86_print_operand_punct_valid): Add '@'.
+       (ix86_print_operand): Handle '@'.
+
 2010-09-05  Giuseppe Scrivano  <gscrivano@gnu.org>
 
        * tree-tailcall.c (process_assignment): Handle NEGATE_EXPR and
index 3a8484a..fac660b 100644 (file)
@@ -12404,6 +12404,7 @@ get_some_local_dynamic_name (void)
    Y -- print condition for XOP pcom* instruction.
    + -- print a branch hint as 'cs' or 'ds' prefix
    ; -- print a semicolon (after prefixes due to bug in older gas).
+   @ -- print a segment register of thread base pointer load
  */
 
 void
@@ -12882,6 +12883,19 @@ ix86_print_operand (FILE *file, rtx x, int code)
 #endif
          return;
 
+       case '@':
+         if (ASSEMBLER_DIALECT == ASM_ATT)
+           putc ('%', file);
+
+         /* The kernel uses a different segment register for performance
+            reasons; a system call would not have to trash the userspace
+            segment register, which would be expensive.  */
+         if (TARGET_64BIT && ix86_cmodel != CM_KERNEL)
+           fputs ("fs", file);
+         else
+           fputs ("gs", file);
+         return;
+
        default:
            output_operand_lossage ("invalid operand code '%c'", code);
        }
@@ -13012,7 +13026,8 @@ ix86_print_operand (FILE *file, rtx x, int code)
 static bool
 ix86_print_operand_punct_valid_p (unsigned char code)
 {
-  return (code == '*' || code == '+' || code == '&' || code == ';');
+  return (code == '@' || code == '*' || code == '+'
+         || code == '&' || code == ';');
 }
 \f
 /* Print a memory operand whose address is ADDR.  */
index 726301c..9780eef 100644 (file)
@@ -59,6 +59,7 @@
 ;; Y -- print condition for XOP pcom* instruction.
 ;; + -- print a branch hint as 'cs' or 'ds' prefix
 ;; ; -- print a semicolon (after prefixes due to bug in older gas).
+;; @ -- print a segment register of thread base pointer load
 
 ;; UNSPEC usage:
 
 ;; Instruction suffix for integer modes.
 (define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
 
+;; Pointer size prefix for integer modes (Intel asm dialect)
+(define_mode_attr iptrsize [(QI "BYTE")
+                           (HI "WORD")
+                           (SI "DWORD")
+                           (DI "QWORD")])
+
 ;; Register class for integer modes.
 (define_mode_attr r [(QI "q") (HI "r") (SI "r") (DI "r")])
 
              (clobber (reg:CC FLAGS_REG))])]
   "")
 
-;; Load and add the thread base pointer from %gs:0.
+;; Segment register for the thread base ptr load
+(define_mode_attr tp_seg [(SI "gs") (DI "fs")])
 
-(define_insn "*load_tp_si"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(const_int 0)] UNSPEC_TP))]
-  "!TARGET_64BIT"
-  "mov{l}\t{%%gs:0, %0|%0, DWORD PTR gs:0}"
-  [(set_attr "type" "imov")
-   (set_attr "modrm" "0")
-   (set_attr "length" "7")
-   (set_attr "memory" "load")
-   (set_attr "imm_disp" "false")])
-
-(define_insn "*add_tp_si"
-  [(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_64BIT"
-  "add{l}\t{%%gs:0, %0|%0, DWORD PTR gs:0}"
-  [(set_attr "type" "alu")
-   (set_attr "modrm" "0")
-   (set_attr "length" "7")
-   (set_attr "memory" "load")
-   (set_attr "imm_disp" "false")])
-
-(define_insn "*load_tp_di"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(const_int 0)] UNSPEC_TP))]
-  "TARGET_64BIT"
-  "mov{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}"
+;; Load and add the thread base pointer from %gs:0.
+(define_insn "*load_tp_<mode>"
+  [(set (match_operand:P 0 "register_operand" "=r")
+       (unspec:P [(const_int 0)] UNSPEC_TP))]
+  ""
+  "mov{<imodesuffix>}\t{%%<tp_seg>:0, %0|%0, <iptrsize> PTR <tp_seg>:0}"
   [(set_attr "type" "imov")
    (set_attr "modrm" "0")
    (set_attr "length" "7")
    (set_attr "memory" "load")
    (set_attr "imm_disp" "false")])
 
-(define_insn "*add_tp_di"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (plus:DI (unspec:DI [(const_int 0)] UNSPEC_TP)
-                (match_operand:DI 1 "register_operand" "0")))
+(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_64BIT"
-  "add{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}"
+  ""
+  "add{<imodesuffix>}\t{%%<tp_seg>:0, %0|%0, <iptrsize> PTR <tp_seg>:0}"
   [(set_attr "type" "alu")
    (set_attr "modrm" "0")
    (set_attr "length" "7")
   operands[4] = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : operands[0];
   emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1]));
 })
-
-;;
 \f
 ;; These patterns match the binary 387 instructions for addM3, subM3,
 ;; mulM3 and divM3.  There are three patterns for each of DFmode and
    (match_operand 1 "memory_operand" "")]
   ""
 {
+  rtx (*insn)(rtx, rtx);
+
 #ifdef TARGET_THREAD_SSP_OFFSET
-  if (TARGET_64BIT)
-    emit_insn (gen_stack_tls_protect_set_di (operands[0],
-                                       GEN_INT (TARGET_THREAD_SSP_OFFSET)));
-  else
-    emit_insn (gen_stack_tls_protect_set_si (operands[0],
-                                       GEN_INT (TARGET_THREAD_SSP_OFFSET)));
+  operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET);
+  insn = (TARGET_64BIT
+         ? gen_stack_tls_protect_set_di
+         : gen_stack_tls_protect_set_si);
 #else
-  if (TARGET_64BIT)
-    emit_insn (gen_stack_protect_set_di (operands[0], operands[1]));
-  else
-    emit_insn (gen_stack_protect_set_si (operands[0], operands[1]));
+  insn = (TARGET_64BIT
+         ? gen_stack_protect_set_di
+         : gen_stack_protect_set_si);
 #endif
+
+  emit_insn (insn (operands[0], operands[1]));
   DONE;
 })
 
-(define_insn "stack_protect_set_si"
-  [(set (match_operand:SI 0 "memory_operand" "=m")
-       (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
-   (set (match_scratch:SI 2 "=&r") (const_int 0))
+(define_insn "stack_protect_set_<mode>"
+  [(set (match_operand:P 0 "memory_operand" "=m")
+       (unspec:P [(match_operand:P 1 "memory_operand" "m")] UNSPEC_SP_SET))
+   (set (match_scratch:P 2 "=&r") (const_int 0))
    (clobber (reg:CC FLAGS_REG))]
   ""
-  "mov{l}\t{%1, %2|%2, %1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
-  [(set_attr "type" "multi")])
-
-(define_insn "stack_protect_set_di"
-  [(set (match_operand:DI 0 "memory_operand" "=m")
-       (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
-   (set (match_scratch:DI 2 "=&r") (const_int 0))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "mov{q}\t{%1, %2|%2, %1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
+  "mov{<imodesuffix>}\t{%1, %2|%2, %1}\;mov{<imodesuffix>}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
   [(set_attr "type" "multi")])
 
-(define_insn "stack_tls_protect_set_si"
-  [(set (match_operand:SI 0 "memory_operand" "=m")
-       (unspec:SI [(match_operand:SI 1 "const_int_operand" "i")]
-                  UNSPEC_SP_TLS_SET))
-   (set (match_scratch:SI 2 "=&r") (const_int 0))
+(define_insn "stack_tls_protect_set_<mode>"
+  [(set (match_operand:P 0 "memory_operand" "=m")
+       (unspec:P [(match_operand:P 1 "const_int_operand" "i")]
+                 UNSPEC_SP_TLS_SET))
+   (set (match_scratch:P 2 "=&r") (const_int 0))
    (clobber (reg:CC FLAGS_REG))]
   ""
-  "mov{l}\t{%%gs:%P1, %2|%2, DWORD PTR gs:%P1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
-  [(set_attr "type" "multi")])
-
-(define_insn "stack_tls_protect_set_di"
-  [(set (match_operand:DI 0 "memory_operand" "=m")
-       (unspec:DI [(match_operand:DI 1 "const_int_operand" "i")]
-                  UNSPEC_SP_TLS_SET))
-   (set (match_scratch:DI 2 "=&r") (const_int 0))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  {
-     /* The kernel uses a different segment register for performance reasons; a
-        system call would not have to trash the userspace segment register,
-        which would be expensive */
-     if (ix86_cmodel != CM_KERNEL)
-        return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
-     else
-        return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
-  }
+  "mov{<imodesuffix>}\t{%@:%P1, %2|%2, <iptrsize> PTR %@:%P1}\;mov{<imodesuffix>}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
   [(set_attr "type" "multi")])
 
 (define_expand "stack_protect_test"
 {
   rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG);
 
+  rtx (*insn)(rtx, rtx, rtx);
+
 #ifdef TARGET_THREAD_SSP_OFFSET
-  if (TARGET_64BIT)
-    emit_insn (gen_stack_tls_protect_test_di (flags, operands[0],
-                                       GEN_INT (TARGET_THREAD_SSP_OFFSET)));
-  else
-    emit_insn (gen_stack_tls_protect_test_si (flags, operands[0],
-                                       GEN_INT (TARGET_THREAD_SSP_OFFSET)));
+  operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET);
+  insn = (TARGET_64BIT
+         ? gen_stack_tls_protect_test_di
+         : gen_stack_tls_protect_test_si);
 #else
-  if (TARGET_64BIT)
-    emit_insn (gen_stack_protect_test_di (flags, operands[0], operands[1]));
-  else
-    emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1]));
+  insn = (TARGET_64BIT
+         ? gen_stack_protect_test_di
+         : gen_stack_protect_test_si);
 #endif
 
+  emit_insn (insn (flags, operands[0], operands[1]));
+
   emit_jump_insn (gen_cbranchcc4 (gen_rtx_EQ (VOIDmode, flags, const0_rtx),
                                  flags, const0_rtx, operands[2]));
   DONE;
 })
 
-(define_insn "stack_protect_test_si"
+(define_insn "stack_protect_test_<mode>"
   [(set (match_operand:CCZ 0 "flags_reg_operand" "")
-       (unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
-                    (match_operand:SI 2 "memory_operand" "m")]
+       (unspec:CCZ [(match_operand:P 1 "memory_operand" "m")
+                    (match_operand:P 2 "memory_operand" "m")]
                    UNSPEC_SP_TEST))
-   (clobber (match_scratch:SI 3 "=&r"))]
+   (clobber (match_scratch:P 3 "=&r"))]
   ""
-  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%2, %3|%3, %2}"
-  [(set_attr "type" "multi")])
-
-(define_insn "stack_protect_test_di"
-  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
-       (unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
-                    (match_operand:DI 2 "memory_operand" "m")]
-                   UNSPEC_SP_TEST))
-   (clobber (match_scratch:DI 3 "=&r"))]
-  "TARGET_64BIT"
-  "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%2, %3|%3, %2}"
+  "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;xor{<imodesuffix>}\t{%2, %3|%3, %2}"
   [(set_attr "type" "multi")])
 
-(define_insn "stack_tls_protect_test_si"
+(define_insn "stack_tls_protect_test_<mode>"
   [(set (match_operand:CCZ 0 "flags_reg_operand" "")
-       (unspec:CCZ [(match_operand:SI 1 "memory_operand" "m")
-                    (match_operand:SI 2 "const_int_operand" "i")]
+       (unspec:CCZ [(match_operand:P 1 "memory_operand" "m")
+                    (match_operand:P 2 "const_int_operand" "i")]
                    UNSPEC_SP_TLS_TEST))
-   (clobber (match_scratch:SI 3 "=r"))]
+   (clobber (match_scratch:P 3 "=r"))]
   ""
-  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%%gs:%P2, %3|%3, DWORD PTR gs:%P2}"
-  [(set_attr "type" "multi")])
-
-(define_insn "stack_tls_protect_test_di"
-  [(set (match_operand:CCZ 0 "flags_reg_operand" "")
-       (unspec:CCZ [(match_operand:DI 1 "memory_operand" "m")
-                    (match_operand:DI 2 "const_int_operand" "i")]
-                   UNSPEC_SP_TLS_TEST))
-   (clobber (match_scratch:DI 3 "=r"))]
-  "TARGET_64BIT"
-  {
-     /* The kernel uses a different segment register for performance reasons; a
-        system call would not have to trash the userspace segment register,
-        which would be expensive */
-     if (ix86_cmodel != CM_KERNEL)
-        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR fs:%P2}";
-     else
-        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR gs:%P2}";
-  }
+  "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;xor{<imodesuffix>}\t{%@:%P2, %3|%3, <iptrsize> PTR %@:%P2}"
   [(set_attr "type" "multi")])
 
 (define_insn "sse4_2_crc32<mode>"