[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