diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index d7671ed19589b..73487af52cc5d 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -3523,8 +3523,26 @@ bool X86AsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name, PatchedName = Name; // Hacks to handle 'data16' and 'data32' - if (PatchedName == "data16" && is16BitMode()) { - return Error(NameLoc, "redundant data16 prefix"); + if (PatchedName == "data16") { + if (is16BitMode()) + return Error(NameLoc, "redundant data16 prefix"); + if (is64BitMode()) + return Error(NameLoc, "'data16' is not supported in 64-bit mode"); + if (getLexer().isNot(AsmToken::EndOfStatement)) { + StringRef Next = Parser.getTok().getString(); + getLexer().Lex(); + // data16 effectively changes the instruction suffix. + // TODO Generalize. + if (Next == "call") + Next = "callw"; + if (Next == "ljmp") + Next = "ljmpw"; + + Name = Next; + PatchedName = Name; + ForcedDataPrefix = X86::Is16Bit; + IsPrefix = false; + } } if (PatchedName == "data32") { if (is32BitMode()) @@ -4538,14 +4556,26 @@ bool X86AsmParser::matchAndEmitIntelInstruction( if (X86Op->isImm()) { // If it's not a constant fall through and let remainder take care of it. const auto *CE = dyn_cast(X86Op->getImm()); - unsigned Size = getPointerWidth(); + // Determine the size. Prioritize the ForcedDataPrefix flag if it was set + // by a 'data32' prefix. Otherwise, fall back to the pointer width of the + // current mode. + unsigned Size = (ForcedDataPrefix == X86::Is32Bit) ? 32 + : (ForcedDataPrefix == X86::Is16Bit) ? 16 + : getPointerWidth(); + ForcedDataPrefix = 0; if (CE && (isIntN(Size, CE->getValue()) || isUIntN(Size, CE->getValue()))) { SmallString<16> Tmp; Tmp += Base; - Tmp += (is64BitMode()) - ? "q" - : (is32BitMode()) ? "l" : (is16BitMode()) ? "w" : " "; + // Append the suffix corresponding to the determined size. + if (Size == 64) + Tmp += "q"; + else if (Size == 32) + Tmp += "l"; + else if (Size == 16) + Tmp += "w"; + else + Tmp += " "; Op.setTokenValue(Tmp); // Do match in ATT mode to allow explicit suffix usage. Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo, diff --git a/llvm/test/MC/X86/x86-16-intel.s b/llvm/test/MC/X86/x86-16-intel.s new file mode 100644 index 0000000000000..77ae4ae217218 --- /dev/null +++ b/llvm/test/MC/X86/x86-16-intel.s @@ -0,0 +1,13 @@ +// RUN: llvm-mc -triple i386-unknown-unknown-code16 --x86-asm-syntax=intel --show-encoding %s | FileCheck %s + +// CHECK: pushl $8 +// CHECK: encoding: [0x66,0x6a,0x08] + data32 push 8 + +// CHECK: pushw $8 +// CHECK: encoding: [0x6a,0x08] + push 8 + +// CHECK: lretl +// CHECK: encoding: [0x66,0xcb] + data32 retf diff --git a/llvm/test/MC/X86/x86-16.s b/llvm/test/MC/X86/x86-16.s index b0a4bda56fcbf..b4e116ab1a0fb 100644 --- a/llvm/test/MC/X86/x86-16.s +++ b/llvm/test/MC/X86/x86-16.s @@ -1060,3 +1060,15 @@ xresldtrk // CHECK: encoding: [0x66,0x8b,0x1e,A,A] // CHECK: fixup A - offset: 3, value: nearer, kind: FK_Data_2 movl nearer, %ebx + +// CHECK: pushl $8 +// CHECK: encoding: [0x66,0x6a,0x08] +data32 push $8 + +// CHECK: pushl $8 +// CHECK: encoding: [0x66,0x6a,0x08] +pushl $8 + +// CHECK: pushw $8 +// CHECK: encoding: [0x6a,0x08] +push $8 diff --git a/llvm/test/MC/X86/x86-32-intel.s b/llvm/test/MC/X86/x86-32-intel.s new file mode 100644 index 0000000000000..44fc5104653c2 --- /dev/null +++ b/llvm/test/MC/X86/x86-32-intel.s @@ -0,0 +1,28 @@ +// RUN: llvm-mc -triple i386-unknown-unknown --x86-asm-syntax=intel --show-encoding %s | FileCheck %s + +// CHECK: encoding: [0x66,0x6a,0x08] + data16 push 8 + +// CHECK: encoding: [0x6a,0x08] + push 8 + +// CxHECK: encoding: [0x66,0xcb] + // data16 retf + +// CHECK: encoding: [0xcb] + retf + +// CHECK: encoding: [0x66,0x9a,0xcd,0xab,0xce,0x7a] + data16 call 0x7ace, 0xabcd + +// CHECK: encoding: [0x9a,0xcd,0xab,0x00,0x00,0xce,0x7a] + call 0x7ace, 0xabcd + +// CHECK: encoding: [0xe8,A,A,A,A] + call a + +// CxHECK: encoding: [0x66,0xea,0xcd,0xab,0xce,0x7a] + // data16 ljmp 0x7ace, 0xabcd + +// CHECK: encoding: [0xea,0xcd,0xab,0x00,0x00,0xce,0x7a] + ljmp 0x7ace, 0xabcd