1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +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:
Fangrui Song 2020-10-06 08:26:12 -07:00
parent b959205f6d
commit 4b618b1f5f
3 changed files with 30 additions and 15 deletions

View File

@ -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:

View File

@ -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

View File

@ -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