Some assemblers do not support MOVS instructions with explicit operands.
Emit instruction with implicit operands, but prefix the instruction with a
segment override prefix if the memory operand refers to ADDR_SPACE_SEG_FS
or ADDR_SPACE_SEG_GS named address space.

    PR target/120019

gcc/ChangeLog:

    * config/i386/i386.cc (ix86_print_operand): Handle 'v' operand
    modifier to emit segment override prefix.
    * config/i386/i386.md (*strmovdi_rex_1): Use %v operand modifier
    to emit segment override prefix.
    (*strmovsi_1): Ditto.
    (*strmovhi_1): Ditto.
    (*strmovqi_1): Ditto.
    (*rep_movdi_rex64): Ditto.
    (*rep_movsi): Ditto.
    (*rep_movqi): Ditto.

gcc/testsuite/ChangeLog:

    * gcc.target/i386/pr111657-1.c (dg-do): Change to "assemble".
    (dg-options): Remove -masm=att and add -save-temps.
    (dg-final): Update scan-assembler and scan-assembler-not strings.

Co-authored-by: Rainer Orth <r...@cebitec.uni-bielefeld.de>

Bootstrapped and regression tested on x86_64-linux-gnu {-m32}. Also
bootstrapped by Rainer on i386-pc-solaris2.11 where the build
previously failed.

Uros.
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 5ad47e19434..df3e3efdfd0 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -13738,10 +13738,11 @@ print_reg (rtx x, int code, FILE *file)
    H -- print a memory address offset by 8; used for sse high-parts
    Y -- print condition for XOP pcom* instruction.
    V -- print naked full integer register name without %.
+   v -- print segment override prefix
    + -- print a branch hint as 'cs' or 'ds' prefix
    ; -- print a semicolon (after prefixes due to bug in older gas).
    ~ -- print "i" if TARGET_AVX2, "f" otherwise.
-   ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
+   ^ -- print addr32 prefix if Pmode != word_mode
    M -- print addr32 prefix for TARGET_X32 with VSIB address.
    ! -- print NOTRACK prefix for jxx/call/ret instructions if required.
    N -- print maskz if it's constant 0 operand.
@@ -14243,6 +14244,28 @@ ix86_print_operand (FILE *file, rtx x, int code)
 
          return;
 
+       case 'v':
+         if (MEM_P (x))
+           {
+             switch (MEM_ADDR_SPACE (x))
+               {
+               case ADDR_SPACE_GENERIC:
+                 break;
+               case ADDR_SPACE_SEG_FS:
+                 fputs ("fs ", file);
+                 break;
+               case ADDR_SPACE_SEG_GS:
+                 fputs ("gs ", file);
+                 break;
+               default:
+                 gcc_unreachable ();
+               }
+           }
+         else
+           output_operand_lossage ("operand is not a memory reference, "
+                                   "invalid operand code 'v'");
+         return;
+
        case '*':
          if (ASSEMBLER_DIALECT == ASM_ATT)
            putc ('*', file);
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index bb02ab0d4e1..80b2023c088 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -58,10 +58,11 @@
 ;; H -- print a memory address offset by 8; used for sse high-parts
 ;; K -- print HLE lock prefix
 ;; Y -- print condition for XOP pcom* instruction.
+;; v -- print segment override prefix
 ;; + -- print a branch hint as 'cs' or 'ds' prefix
 ;; ; -- print a semicolon (after prefixes due to bug in older gas).
 ;; ~ -- print "i" if TARGET_AVX2, "f" otherwise.
-;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
+;; ^ -- print addr32 prefix if Pmode != word_mode
 ;; ! -- print NOTRACK prefix for jxx/call/ret instructions if required.
 
 (define_c_enum "unspec" [
@@ -25643,7 +25644,7 @@ (define_insn "*strmovdi_rex_1"
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "movsq\t{%1, %0|%0, %1}";
+  return "%^%v1movsq";
 }
   [(set_attr "type" "str")
    (set_attr "memory" "both")
@@ -25666,7 +25667,7 @@ (define_insn "*strmovsi_1"
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "movs{l|d}\t{%1, %0|%0, %1}";
+  return "%^%v1movs{l|d}";
 }
   [(set_attr "type" "str")
    (set_attr "memory" "both")
@@ -25689,7 +25690,7 @@ (define_insn "*strmovhi_1"
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "movsw\t{%1, %0|%0, %1}";
+  return "%^%v1movsw";
 }
   [(set_attr "type" "str")
    (set_attr "memory" "both")
@@ -25712,7 +25713,7 @@ (define_insn "*strmovqi_1"
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "movsb\t{%1, %0|%0, %1}";
+  return "%^%v1movsb";
 }
   [(set_attr "type" "str")
    (set_attr "memory" "both")
@@ -25759,7 +25760,7 @@ (define_insn "*rep_movdi_rex64"
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "rep{%;} movsq\t{%1, %0|%0, %1}";
+  return "%^%v1rep{%;} movsq";
 }
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
@@ -25786,7 +25787,7 @@ (define_insn "*rep_movsi"
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "rep{%;} movs{l|d}\t{%1, %0|%0, %1}";
+  return "%^%v1rep{%;} movs{l|d}";
 }
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
@@ -25811,7 +25812,7 @@ (define_insn "*rep_movqi"
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "rep{%;} movsb\t{%1, %0|%0, %1}";
+  return "%^%v1rep{%;} movsb";
 }
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
diff --git a/gcc/testsuite/gcc.target/i386/pr111657-1.c 
b/gcc/testsuite/gcc.target/i386/pr111657-1.c
index 99acd1f6839..a4ba21073f5 100644
--- a/gcc/testsuite/gcc.target/i386/pr111657-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr111657-1.c
@@ -1,5 +1,5 @@
-/* { dg-do compile } */
-/* { dg-options "-O2 -mno-sse -mtune=generic -masm=att" } */
+/* { dg-do assemble } */
+/* { dg-options "-O2 -mno-sse -mtune=generic -save-temps" } */
 
 typedef unsigned long uword __attribute__ ((mode (word)));
 
@@ -8,5 +8,5 @@ struct a { uword arr[30]; };
 __seg_gs struct a m;
 void bar (struct a *dst) { *dst = m; }
 
-/* { dg-final { scan-assembler "rep\[; \t\]+movs(l|q)\[ \t\]+%gs:" { target { 
! x32 } } } } */
-/* { dg-final { scan-assembler-not "rep\[; \t\]+movs(l|q)\[ \t\]+%gs:" { 
target x32 } } } */
+/* { dg-final { scan-assembler "gs\[ \t\]+rep\[; \t\]+movs(l|q)" { target { ! 
x32 } } } } */
+/* { dg-final { scan-assembler-not "gs\[ \t\]+rep\[; \t\]+movs(l|q)" { target 
x32 } } } */

Reply via email to