aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2025-05-05 13:59:43 +0200
committerUros Bizjak <ubizjak@gmail.com>2025-05-05 20:36:29 +0200
commitc182f4d14d65b3e012ad65b5014d86352fabc86f (patch)
tree56f5a01a496de636be4cb3397d1bc76c3ddb7566
parentbb83283e5c5c55eab7493a58c5e415aa56f5940c (diff)
downloadgcc-c182f4d14d65b3e012ad65b5014d86352fabc86f.zip
gcc-c182f4d14d65b3e012ad65b5014d86352fabc86f.tar.gz
gcc-c182f4d14d65b3e012ad65b5014d86352fabc86f.tar.bz2
i386: Do not use explicit operands for MOVS instructions [PR120019]
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 <ro@CeBiTec.Uni-Bielefeld.DE>
-rw-r--r--gcc/config/i386/i386.cc25
-rw-r--r--gcc/config/i386/i386.md17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr111657-1.c8
3 files changed, 37 insertions, 13 deletions
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 5ad47e1..df3e3ef 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 bb02ab0..80b2023 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 99acd1f..a4ba210 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 } } } */