Ramkumar Ramachandra
2013-Jul-16 11:06 UTC
[LLVMdev] [PATCH 2/2] X86: infer immediate forms of bit-test instructions
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