Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
54 changes: 46 additions & 8 deletions llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3563,8 +3563,34 @@ 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.
Next = "lgdtq16";
} else {
Next = "lgdtw";
}
}

Name = Next;
PatchedName = Name;
ForcedDataPrefix = X86::Is16Bit;
IsPrefix = false;
}
}
if (PatchedName == "data32") {
if (is32BitMode())
Expand All @@ -3579,9 +3605,9 @@ bool X86AsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
getLexer().Lex();
// data32 effectively changes the instruction suffix.
// TODO Generalize.
if (Next == "callw")
if (Next == "call")
Next = "calll";
if (Next == "ljmpw")
if (Next == "ljmp")
Next = "ljmpl";

Name = Next;
Expand Down Expand Up @@ -4585,14 +4611,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
16 changes: 16 additions & 0 deletions llvm/lib/Target/X86/X86InstrAsmAlias.td
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,12 @@ defm : CMPCCXADD_Aliases<"g", 15>;
def : MnemonicAlias<"call", "callw", "att">, Requires<[In16BitMode]>;
def : MnemonicAlias<"call", "calll", "att">, Requires<[In32BitMode]>;
def : MnemonicAlias<"call", "callq", "att">, Requires<[In64BitMode]>;
def : MnemonicAlias<"call", "callw", "intel">, Requires<[In16BitMode]>;
def : MnemonicAlias<"call", "calll", "intel">, Requires<[In32BitMode]>;
def : MnemonicAlias<"call", "callq", "intel">, Requires<[In64BitMode]>;

def : MnemonicAlias<"ljmp", "ljmpw", "intel">, Requires<[In16BitMode]>;
def : MnemonicAlias<"ljmp", "ljmpl", "intel">, Requires<[In32BitMode]>;

def : MnemonicAlias<"cbw", "cbtw", "att">;
def : MnemonicAlias<"cwde", "cwtl", "att">;
Expand All @@ -260,6 +266,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 @@ -665,6 +674,11 @@ def : InstAlias<"jmpw\t$seg, $off", (FARJMP16i i16imm:$off, i16imm:$seg)>, Req
def : InstAlias<"calll\t$seg, $off", (FARCALL32i i32imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>;
def : InstAlias<"jmpl\t$seg, $off", (FARJMP32i i32imm:$off, i16imm:$seg)>, Requires<[Not64BitMode]>;

// Near call aliases for data16/data32 prefix support
def : InstAlias<"callw\t$dst", (CALLpcrel16 i16imm_brtarget:$dst)>;
def : InstAlias<"calll\t$dst", (CALLpcrel32 i32imm_brtarget:$dst)>, Requires<[Not64BitMode]>;
def : InstAlias<"callq\t$dst", (CALL64pcrel32 i64i32imm_brtarget:$dst)>, Requires<[In64BitMode]>;

// Match 'movq <largeimm>, <reg>' as an alias for movabsq.
def : InstAlias<"mov{q}\t{$imm, $reg|$reg, $imm}", (MOV64ri GR64:$reg, i64imm:$imm), 0>;

Expand Down Expand Up @@ -723,6 +737,8 @@ 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<"ljmpl\t$seg, $off", (FARJMP32i i32imm:$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
14 changes: 7 additions & 7 deletions llvm/lib/Target/X86/X86InstrControl.td
Original file line number Diff line number Diff line change
Expand Up @@ -166,16 +166,16 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
Requires<[In64BitMode]>, Sched<[WriteJumpLd]>, NOTRACK;
}

let Predicates = [Not64BitMode], AsmVariantName = "att" in {
let Predicates = [Not64BitMode], AsmVariantName = "att" in
def FARJMP32i : Iseg32<0xEA, RawFrmImm16, (outs),
(ins i32imm:$off, i16imm:$seg),
"ljmp{l}\t$seg, $off", []>,
OpSize32, Sched<[WriteJump]>;
let AsmVariantName = "att" in
def FARJMP16i : Iseg16<0xEA, RawFrmImm16, (outs),
(ins i16imm:$off, i16imm:$seg),
"ljmp{w}\t$seg, $off", []>,
OpSize16, Sched<[WriteJump]>;
}
let mayLoad = 1 in {
def FARJMP64m : RI<0xFF, MRM5m, (outs), (ins opaquemem:$dst),
"ljmp{q}\t{*}$dst", []>, Sched<[WriteJump]>, Requires<[In64BitMode]>;
Expand Down Expand Up @@ -214,11 +214,6 @@ let isCall = 1 in
(outs), (ins i32imm_brtarget:$dst),
"call{l}\t$dst", []>, OpSize32,
Requires<[Not64BitMode]>, Sched<[WriteJump]>;
let hasSideEffects = 0 in
def CALLpcrel16 : Ii16PCRel<0xE8, RawFrm,
(outs), (ins i16imm_brtarget:$dst),
"call{w}\t$dst", []>, OpSize16,
Requires<[Not64BitMode]>, Sched<[WriteJump]>;
def CALL16r : I<0xFF, MRM2r, (outs), (ins GR16:$dst),
"call{w}\t{*}$dst", [(X86call GR16:$dst)]>,
OpSize16, Requires<[Not64BitMode]>, Sched<[WriteJump]>;
Expand Down Expand Up @@ -329,6 +324,11 @@ let isCall = 1, Uses = [RSP, SSP], SchedRW = [WriteJump] in {
(outs), (ins i64i32imm_brtarget:$dst),
"call{q}\t$dst", []>, OpSize32,
Requires<[In64BitMode]>;
let hasSideEffects = 0 in
def CALLpcrel16 : Ii16PCRel<0xE8, RawFrm,
(outs), (ins i16imm_brtarget:$dst),
"call{w}\t$dst", []>, OpSize16,
Sched<[WriteJump]>;
def CALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst),
"call{q}\t{*}$dst", [(X86call GR64:$dst)]>,
Requires<[In64BitMode,NotUseIndirectThunkCalls,ImportCallOptimizationDisabled]>;
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
16 changes: 4 additions & 12 deletions llvm/test/MC/X86/data-prefix-fail.s
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,12 @@
// X86-16-SAME: encoding: [0x66,0x0f,0x01,0x16,0x00,0x00]
data32 lgdt 0

// X86-64: data16
// X86-64: encoding: [0x66]
// X86-64: lgdtq 0
// X86-64: encoding: [0x0f,0x01,0x14,0x25,0x00,0x00,0x00,0x00]
// X86-32: data16
// X86-32: encoding: [0x66]
// X86-32: lgdtl 0
// X86-32: encoding: [0x0f,0x01,0x15,0x00,0x00,0x00,0x00]
// X86-64: encoding: [0x66,0x0f,0x01,0x14,0x25,0x00,0x00,0x00,0x00]
// X86-32: encoding: [0x66,0x0f,0x01,0x15,0x00,0x00,0x00,0x00]
// ERR16: error: redundant data16 prefix
data16 lgdt 0

// X86-64: data16 # encoding: [0x66]
// X86-64-NEXT: callq 0 # encoding: [0xe8,A,A,A,A]
// X86-32: data16 # encoding: [0x66]
// X86-32-NEXT: calll 0 # encoding: [0xe8,A,A,A,A]
// X86-64: callw 0 # encoding: [0x66,0xe8,A,A]
// X86-32: callw 0 # encoding: [0x66,0xe8,A,A]
// ERR16: {{.*}}.s:[[#@LINE+1]]:1: error: redundant data16 prefix
data16 call 0
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
// 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
5 changes: 1 addition & 4 deletions llvm/test/MC/X86/x86-32.s
Original file line number Diff line number Diff line change
Expand Up @@ -1101,10 +1101,7 @@ lretw
// CHECK: encoding: [0x66]
data16

// CHECK: data16
// CHECK: encoding: [0x66]
// CHECK: lgdtl 4(%eax)
// CHECK: encoding: [0x0f,0x01,0x50,0x04]
// CHECK: encoding: [0x66,0x0f,0x01,0x50,0x04]
data16 lgdt 4(%eax)

// CHECK: rdpid %eax
Expand Down
5 changes: 1 addition & 4 deletions llvm/test/MC/X86/x86-64.s
Original file line number Diff line number Diff line change
Expand Up @@ -1081,10 +1081,7 @@ movq %mm5, %rbx // CHECK: movq %mm5, %rbx # encoding: [0x48,0x0f,0x7e,0xeb]
rex64 // CHECK: rex64 # encoding: [0x48]
data16 // CHECK: data16 # encoding: [0x66]

// CHECK: data16
// CHECK: encoding: [0x66]
// CHECK: lgdtq 4(%rax)
// CHECK: encoding: [0x0f,0x01,0x50,0x04]
// CHECK: encoding: [0x66,0x0f,0x01,0x50,0x04]
data16 lgdt 4(%rax)

// PR8855
Expand Down
Loading