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 } } } */