diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -3260,11 +3260,13 @@ // repz repnz ; GAS errors for the use of two similar prefixes // lock addq %rax, %rbx ; Destination operand must be of memory type // xacquire ; xacquire must be accompanied by 'lock' - bool isPrefix = StringSwitch(Name) - .Cases("rex64", "data32", "data16", true) - .Cases("xacquire", "xrelease", true) - .Cases("acquire", "release", isParsingIntelSyntax()) - .Default(false); + bool isPrefix = + StringSwitch(Name) + .Cases("cs", "ds", "es", "fs", "gs", "ss", true) + .Cases("rex64", "data32", "data16", "addr32", "addr16", true) + .Cases("xacquire", "xrelease", true) + .Cases("acquire", "release", isParsingIntelSyntax()) + .Default(false); auto isLockRepeatNtPrefix = [](StringRef N) { return StringSwitch(N) diff --git a/llvm/lib/Target/X86/X86InstrSystem.td b/llvm/lib/Target/X86/X86InstrSystem.td --- a/llvm/lib/Target/X86/X86InstrSystem.td +++ b/llvm/lib/Target/X86/X86InstrSystem.td @@ -171,6 +171,17 @@ def GS_PREFIX : I<0x65, PrefixByte, (outs), (ins), "gs", []>; } // SchedRW +//===----------------------------------------------------------------------===// +// Address-size override prefixes. +// + +let SchedRW = [WriteNop] in { +def ADDR16_PREFIX : I<0x67, PrefixByte, (outs), (ins), "addr16", []>, + Requires<[In32BitMode]>; +def ADDR32_PREFIX : I<0x67, PrefixByte, (outs), (ins), "addr32", []>, + Requires<[In64BitMode]>; +} // SchedRW + //===----------------------------------------------------------------------===// // Moves to and from segment registers. // diff --git a/llvm/test/MC/X86/addr16-32.s b/llvm/test/MC/X86/addr16-32.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/X86/addr16-32.s @@ -0,0 +1,24 @@ +# RUN: llvm-mc %s -triple x86_64-linux-gnu -filetype=obj -o - | llvm-objdump -d - | FileCheck %s + +.text +.global foo +foo: + insl + gs outsl + .code64 + addr32 insl + addr32 gs outsl + .code32 + addr16 insl + addr16 gs outsl + .code64 + retq + +# CHECK: : +# CHECK-NEXT: 6d insl %dx, %es:(%rdi) +# CHECK-NEXT: 65 6f outsl %gs:(%rsi), %dx +# CHECK-NEXT: 67 6d insl %dx, %es:(%edi) +# CHECK-NEXT: 67 65 6f outsl %gs:(%esi), %dx +# CHECK-NEXT: 67 6d insl %dx, %es:(%edi) +# CHECK-NEXT: 67 65 6f outsl %gs:(%esi), %dx +# CHECK-NEXT: c3 retq diff --git a/llvm/test/MC/X86/segment-prefix.s b/llvm/test/MC/X86/segment-prefix.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/X86/segment-prefix.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc %s -triple x86_64-linux-gnu -filetype=obj -o - | llvm-objdump -d - | FileCheck %s + +.text +.global foo +foo: + cs outsl + ds outsl + es outsw + fs outsw + gs outsl + ss outsl + retq + +# CHECK: : +# CHECK-NEXT: 2e 6f outsl %cs:(%rsi), %dx +# CHECK-NEXT: 3e 6f outsl %ds:(%rsi), %dx +# CHECK-NEXT: 26 66 6f outsw %es:(%rsi), %dx +# CHECK-NEXT: 64 66 6f outsw %fs:(%rsi), %dx +# CHECK-NEXT: 65 6f outsl %gs:(%rsi), %dx +# CHECK-NEXT: 36 6f outsl %ss:(%rsi), %dx +# CHECK-NEXT: c3 retq