mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[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
This commit is contained in:
parent
b959205f6d
commit
4b618b1f5f
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user