[LLVMdev] [PATCH 2/2] X86: infer immediate forms of bit-test instructions

Ramkumar Ramachandra artagnon at gmail.com
Tue Jul 16 04:06:27 PDT 2013


The instruction mnemonics for the immediate forms of bit-test
instructions including bt, btr and bts, btc do not work.  llvm-mc barfs
with:

  error: ambiguous instructions require an explicit suffix

This is highly user-unfriendly, since we can easily infer what the user
meant by inspecting $imm and translating the instruction appropriately.
Do it exactly as the Intel manual describes.  Note that we are the first
major assembler to do this properly: neither GNU as nor NASM does the
right thing currently.

Cc: Stephen Checkoway <s at pahtak.org>
Cc: Tim Northover <t.p.northover at gmail.com>
Cc: Jim Grosbach <grosbach at apple.com>
Cc: Chris Lattner <sabre at nondot.org>
Signed-off-by: Ramkumar Ramachandra <artagnon at gmail.com>
---
 lib/Target/X86/AsmParser/X86AsmParser.cpp | 30 ++++++++++++++++++++++++++++++
 test/MC/X86/x86-64.s                      |  7 +++++++
 2 files changed, 37 insertions(+)

diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 263eb5e..fba0f3c 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -2124,6 +2124,36 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
     }
   }
 
+  // Infer the immediate form of bit-test instructions without length suffix
+  // correctly.  The register form works fine.
+  // bt{,r,s,..} $n, mem becomes btl $(n % 32), (mem + 4 * (n / 32))
+  if (Name.startswith("bt")
+      && !(Name.endswith("b") || Name.endswith("w") || Name.endswith("l") || Name.endswith("q"))
+      && Operands.size() == 3) {
+    X86Operand &Op1 = *(X86Operand*)Operands.begin()[1];
+    X86Operand &Op2 = *(X86Operand*)Operands.begin()[2];
+
+    if (Op1.isImm() && isa<MCConstantExpr>(Op1.getImm()) &&
+	Op2.isMem() && isa<MCConstantExpr>(Op2.Mem.Disp)) {
+      int64_t Given_imm = cast<MCConstantExpr>(Op1.getImm())->getValue();
+      int64_t Given_mem = cast<MCConstantExpr>(Op2.Mem.Disp)->getValue();
+
+      static_cast<X86Operand*>(Operands[0])->setTokenValue(StringRef(Name.str() + "l"));
+
+      SMLoc Loc = Op1.getEndLoc();
+      const MCExpr *Op1_transformed = MCConstantExpr::Create(Given_imm % 32, getContext());
+      Operands.begin()[1] = X86Operand::CreateImm(Op1_transformed, Loc, Loc);
+
+      Loc = Op2.getEndLoc();
+      const MCExpr *Op2_transformed = MCConstantExpr::Create(Given_mem + 4 * (Given_imm / 32),
+							     getContext());
+      Operands.begin()[2] = X86Operand::CreateMem(Op2_transformed, Loc, Loc);
+
+      delete &Op1;
+      delete &Op2;
+    }
+  }
+
   return false;
 }
 
diff --git a/test/MC/X86/x86-64.s b/test/MC/X86/x86-64.s
index ff60969..e82db1e 100644
--- a/test/MC/X86/x86-64.s
+++ b/test/MC/X86/x86-64.s
@@ -694,6 +694,13 @@ movl	0, %eax   // CHECK: movl 0, %eax # encoding: [0x8b,0x04,0x25,0x00,0x00,0x00
 // CHECK: encoding: [0x75,A]
         jnz 0
 
+// Infer immediate form of bit-test instructions without suffix
+bt   $1, 0 // CHECK: btl $1, 0 # encoding: [0x0f,0xba,0x24,0x25,0x00,0x00,0x00,0x00,0x01]
+btl  $1, 0 // CHECK: btl $1, 0 # encoding: [0x0f,0xba,0x24,0x25,0x00,0x00,0x00,0x00,0x01]
+bt  $63, 0 // CHECK: btl $31, 4 # encoding: [0x0f,0xba,0x24,0x25,0x04,0x00,0x00,0x00,0x1f]
+btr $63, 0 // CHECK: btrl $31, 4 # encoding: [0x0f,0xba,0x34,0x25,0x04,0x00,0x00,0x00,0x1f]
+btq $63, 0 // CHECK: btq $63, 0 # encoding: [0x48,0x0f,0xba,0x24,0x25,0x00,0x00,0x00,0x00,0x3f]
+
 // rdar://8017515
 btq $0x01,%rdx
 // CHECK: btq	$1, %rdx
-- 
1.8.3.2.736.g869de25




More information about the llvm-dev mailing list