Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 45 additions & 6 deletions llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3563,8 +3563,35 @@ 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 (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";
if (Next == "retf")
Next = "retfw";
if (Next == "lgdt") {
if (is64BitMode()) {
// Use the special lgdtq variant with OpSize16 flag.
// I think the CPU ignores the prefix anyway--but hey.
Next = "lgdtq16";
} else {
Next = "lgdtw";
}
}

Name = Next;
PatchedName = Name;
ForcedDataPrefix = X86::Is16Bit;
IsPrefix = false;
}
}
if (PatchedName == "data32") {
if (is32BitMode())
Expand Down Expand Up @@ -4585,14 +4612,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<MCConstantExpr>(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,
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/X86/X86InstrAsmAlias.td
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ def : MnemonicAlias<"cqo", "cqto", "att">;
// In 64-bit mode lret maps to lretl; it is not ambiguous with lretq.
def : MnemonicAlias<"lret", "lretw", "att">, Requires<[In16BitMode]>;
def : MnemonicAlias<"lret", "lretl", "att">, Requires<[Not16BitMode]>;
def : InstAlias<"lgdtw\t$src", (LGDT16m opaquemem:$src), 0>, Requires<[Not64BitMode]>;
def : InstAlias<"lgdtq16\t$src", (LGDT64m_16 opaquemem:$src), 0>, Requires<[In64BitMode]>;
def : InstAlias<"retfw", (LRET16), 0>;

def : MnemonicAlias<"leavel", "leave", "att">, Requires<[Not64BitMode]>;
def : MnemonicAlias<"leaveq", "leave", "att">, Requires<[In64BitMode]>;
Expand Down Expand Up @@ -723,6 +726,7 @@ def : InstAlias<"shrd{l}\t{$reg, $mem|$mem, $reg}", (SHRD32mrCL i32mem:$mem, GR3
def : InstAlias<"shrd{q}\t{$reg, $mem|$mem, $reg}", (SHRD64mrCL i64mem:$mem, GR64:$reg), 0>;

// test: We accept "testX <reg>, <mem>" and "testX <mem>, <reg>" as synonyms.
def : InstAlias<"ljmpw\t$seg, $off", (FARJMP16i i16imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>;
def : InstAlias<"test{b}\t{$mem, $val|$val, $mem}",
(TEST8mr i8mem :$mem, GR8 :$val), 0>;
def : InstAlias<"test{w}\t{$mem, $val|$val, $mem}",
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/X86/X86InstrSystem.td
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,9 @@ def LGDT32m : I<0x01, MRM2m, (outs), (ins opaquemem:$src),
"lgdt{l|d}\t$src", []>, OpSize32, TB, Requires<[Not64BitMode]>;
def LGDT64m : I<0x01, MRM2m, (outs), (ins opaquemem:$src),
"lgdt{q}\t$src", []>, TB, Requires<[In64BitMode]>;
// Special variant with data16 prefix (OpSize16) for 64-bit mode
def LGDT64m_16 : I<0x01, MRM2m, (outs), (ins opaquemem:$src),
"lgdt{q}\t$src", []>, TB, OpSize16, Requires<[In64BitMode]>;
def LIDT16m : I<0x01, MRM3m, (outs), (ins opaquemem:$src),
"lidtw\t$src", []>, TB, OpSize16, Requires<[Not64BitMode]>;
def LIDT32m : I<0x01, MRM3m, (outs), (ins opaquemem:$src),
Expand Down
31 changes: 30 additions & 1 deletion llvm/test/MC/X86/intel-syntax-32.s
Original file line number Diff line number Diff line change
@@ -1,6 +1,35 @@
// RUN: llvm-mc -triple i686-unknown-unknown -x86-asm-syntax=intel %s | FileCheck %s
// RUN: llvm-mc -triple i686-unknown-unknown -x86-asm-syntax=intel --show-encoding %s | FileCheck %s

// CHECK: leaw (%bp,%si), %ax
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please can add encoding checks to the old LEA tests as well

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

// CHECK: encoding: [0x67,0x66,0x8d,0x02]
lea ax, [bp+si]
// CHECK: leaw (%bp,%si), %ax
// CHECK: encoding: [0x67,0x66,0x8d,0x02]
lea ax, [si+bp]

// CHECK: encoding: [0x66,0x6a,0x08]
data16 push 8

// CHECK: encoding: [0x6a,0x08]
push 8

// CHECK: 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

// CHECK: encoding: [0x66,0xea,0xcd,0xab,0xce,0x7a]
data16 ljmp 0x7ace, 0xabcd

// CHECK: encoding: [0xea,0xcd,0xab,0x00,0x00,0xce,0x7a]
ljmp 0x7ace, 0xabcd
13 changes: 13 additions & 0 deletions llvm/test/MC/X86/x86-16-intel.s
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions llvm/test/MC/X86/x86-16.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading