[llvm] 43c7dc5 - [X86] .code16: temporarily set Mode32Bit when matching an instruction with the data32 prefix
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 6 08:32:09 PDT 2020
Author: Fangrui Song
Date: 2020-10-06T08:32:03-07:00
New Revision: 43c7dc52f12973b306910a161bcf150d70d33504
URL: https://github.com/llvm/llvm-project/commit/43c7dc52f12973b306910a161bcf150d70d33504
DIFF: https://github.com/llvm/llvm-project/commit/43c7dc52f12973b306910a161bcf150d70d33504.diff
LOG: [X86] .code16: temporarily set Mode32Bit when matching an instruction with the data32 prefix
PR47632
This allows MC to match `data32 ...` as one instruction instead of two (data32 without insn + insn).
The compatibility with GNU as improves: `data32 ljmp` will be matched as ljmpl.
`data32 lgdt 4(%eax)` will be matched as `lgdtl` (prefixes: 0x67 0x66, instead
of 0x66 0x67).
GNU as supports many other `data32 *w` as `*l`. We currently just hard code
`data32 callw` and `data32 ljmpw`. Generalizing the suffix replacement is
tricky and requires a think about the "bwlq" appending suffix rules in MatchAndEmitATTInstruction.
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D88772
Added:
Modified:
llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
llvm/test/MC/X86/data-prefix-fail.s
llvm/test/MC/X86/x86-16.s
Removed:
################################################################################
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 1f594c54c410..8af1148df7a2 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -78,6 +78,7 @@ static const char OpPrecedence[] = {
class X86AsmParser : public MCTargetAsmParser {
ParseInstructionInfo *InstInfo;
bool Code16GCC;
+ unsigned ForcedDataPrefix = 0;
enum VEXEncoding {
VEXEncoding_Default,
@@ -3085,13 +3086,18 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
if (getLexer().isNot(AsmToken::EndOfStatement)) {
StringRef Next = Parser.getTok().getString();
- // Parse data32 call as calll.
- if (Next == "call" || Next == "callw") {
- getLexer().Lex();
- Name = "calll";
- PatchedName = Name;
- isPrefix = false;
- }
+ getLexer().Lex();
+ // data32 effectively changes the instruction suffix.
+ // TODO Generalize.
+ if (Next == "callw")
+ Next = "calll";
+ if (Next == "ljmpw")
+ Next = "ljmpl";
+
+ Name = Next;
+ PatchedName = Name;
+ ForcedDataPrefix = X86::Mode32Bit;
+ isPrefix = false;
}
}
@@ -3779,11 +3785,19 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
if (Prefixes)
Inst.setFlags(Prefixes);
+ // In 16-bit mode, if data32 is specified, temporarily switch to 32-bit mode
+ // when matching the instruction.
+ if (ForcedDataPrefix == X86::Mode32Bit)
+ SwitchMode(X86::Mode32Bit);
// First, try a direct match.
FeatureBitset MissingFeatures;
unsigned OriginalError = MatchInstruction(Operands, Inst, ErrorInfo,
MissingFeatures, MatchingInlineAsm,
isParsingIntelSyntax());
+ if (ForcedDataPrefix == X86::Mode32Bit) {
+ SwitchMode(X86::Mode16Bit);
+ ForcedDataPrefix = 0;
+ }
switch (OriginalError) {
default: llvm_unreachable("Unexpected match result!");
case Match_Success:
diff --git a/llvm/test/MC/X86/data-prefix-fail.s b/llvm/test/MC/X86/data-prefix-fail.s
index 638e972ad478..bd5b62ddc9be 100644
--- a/llvm/test/MC/X86/data-prefix-fail.s
+++ b/llvm/test/MC/X86/data-prefix-fail.s
@@ -7,10 +7,8 @@
// ERR64: error: 'data32' is not supported in 64-bit mode
// ERR32: error: redundant data32 prefix
-// 16: data32
-// 16: encoding: [0x66]
-// 16: lgdtw 0
-// 16: encoding: [0x0f,0x01,0x16,0x00,0x00]
+// 16: lgdtl 0
+// 16-SAME: encoding: [0x66,0x0f,0x01,0x16,0x00,0x00]
data32 lgdt 0
// 64: data16
diff --git a/llvm/test/MC/X86/x86-16.s b/llvm/test/MC/X86/x86-16.s
index 277d8a010358..9f8c639726f9 100644
--- a/llvm/test/MC/X86/x86-16.s
+++ b/llvm/test/MC/X86/x86-16.s
@@ -553,6 +553,11 @@ ljmp $0x7ace,$0x7ace
data32 call a
data32 callw a
+// CHECK: ljmpl $1, $2
+// CHECK-NEXT: ljmpl $1, $2
+data32 ljmp $1, $2
+data32 ljmpw $1, $2
+
// CHECK: incb %al # encoding: [0xfe,0xc0]
incb %al
@@ -972,10 +977,8 @@ lretl
// CHECK: encoding: [0x66]
data32
-// CHECK: data32
-// CHECK: encoding: [0x66]
-// CHECK: lgdtw 4(%eax)
-// CHECK: encoding: [0x67,0x0f,0x01,0x50,0x04]
+// CHECK: lgdtl 4(%eax)
+// CHECK-SAME: encoding: [0x67,0x66,0x0f,0x01,0x50,0x04]
data32 lgdt 4(%eax)
// CHECK: wbnoinvd
More information about the llvm-commits
mailing list