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) @@ -3333,7 +3335,7 @@ Name = Next; PatchedName = Name; ForcedDataPrefix = X86::Mode32Bit; - isPrefix = false; + IsPrefix = false; } } @@ -3350,7 +3352,7 @@ // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we // just want to parse the "lock" as the first instruction and the "incl" as // the next one. - if (getLexer().isNot(AsmToken::EndOfStatement) && !isPrefix) { + if (getLexer().isNot(AsmToken::EndOfStatement) && !IsPrefix) { // Parse '*' modifier. if (getLexer().is(AsmToken::Star)) Operands.push_back(X86Operand::CreateToken("*", consumeToken())); @@ -3387,7 +3389,7 @@ // Consume the EndOfStatement or the prefix separator Slash if (getLexer().is(AsmToken::EndOfStatement) || - (isPrefix && getLexer().is(AsmToken::Slash))) + (IsPrefix && getLexer().is(AsmToken::Slash))) Parser.Lex(); else if (CurlyAsEndOfStatement) // Add an actual EndOfStatement before the curly brace 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,23 @@ +# 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 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,20 @@ +# 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