[llvm-commits] [llvm] r137144 - in /llvm/trunk: lib/Target/ARM/ lib/Target/ARM/Disassembler/ test/MC/Disassembler/ARM/ utils/TableGen/
Evan Cheng
evan.cheng at apple.com
Tue Aug 9 17:45:36 PDT 2011
Awesome. Thanks for doing this!
Evan
On Aug 10, 2011, at 4:55 AM, Owen Anderson <resistor at mac.com> wrote:
> Author: resistor
> Date: Tue Aug 9 15:55:18 2011
> New Revision: 137144
>
> URL: http://llvm.org/viewvc/llvm-project?rev=137144&view=rev
> Log:
> Replace the existing ARM disassembler with a new one based on the FixedLenDecoderEmitter.
> This new disassembler can correctly decode all the testcases that the old one did, though
> some "expected failure" testcases are XFAIL'd for now because it is not (yet) as strict in
> operand checking as the old one was.
>
> Removed:
> llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
> llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h
> llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
> Modified:
> llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
> llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
> llvm/trunk/lib/Target/ARM/ARMInstrNEON.td
> llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
> llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
> llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
> llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h
> llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt
> llvm/trunk/lib/Target/ARM/Makefile
> llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt
> llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt
> llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp
>
> Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original)
> +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Tue Aug 9 15:55:18 2011
> @@ -152,6 +152,7 @@
> (ops (i32 14), (i32 zero_reg))> {
> let PrintMethod = "printPredicateOperand";
> let ParserMatchClass = CondCodeOperand;
> + let DecoderMethod = "DecodePredicateOperand";
> }
>
> // Conditional code result for instructions whose 's' bit is set, e.g. subs.
> @@ -160,6 +161,7 @@
> let EncoderMethod = "getCCOutOpValue";
> let PrintMethod = "printSBitModifierOperand";
> let ParserMatchClass = CCOutOperand;
> + let DecoderMethod = "DecodeCCOutOperand";
> }
>
> // Same as cc_out except it defaults to setting CPSR.
> @@ -167,6 +169,7 @@
> let EncoderMethod = "getCCOutOpValue";
> let PrintMethod = "printSBitModifierOperand";
> let ParserMatchClass = CCOutOperand;
> + let DecoderMethod = "DecodeCCOutOperand";
> }
>
> // ARM special operands for disassembly only.
> @@ -199,15 +202,19 @@
> // 64 64 - <imm> is encoded in imm6<5:0>
> def shr_imm8 : Operand<i32> {
> let EncoderMethod = "getShiftRight8Imm";
> + let DecoderMethod = "DecodeShiftRight8Imm";
> }
> def shr_imm16 : Operand<i32> {
> let EncoderMethod = "getShiftRight16Imm";
> + let DecoderMethod = "DecodeShiftRight16Imm";
> }
> def shr_imm32 : Operand<i32> {
> let EncoderMethod = "getShiftRight32Imm";
> + let DecoderMethod = "DecodeShiftRight32Imm";
> }
> def shr_imm64 : Operand<i32> {
> let EncoderMethod = "getShiftRight64Imm";
> + let DecoderMethod = "DecodeShiftRight64Imm";
> }
>
> //===----------------------------------------------------------------------===//
> @@ -579,6 +586,8 @@
> let Inst{11-8} = addr{7-4}; // imm7_4/zero
> let Inst{7-4} = op;
> let Inst{3-0} = addr{3-0}; // imm3_0/Rm
> +
> + let DecoderMethod = "DecodeAddrMode3Instruction";
> }
>
> class AI3ldstidx<bits<4> op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
> @@ -1265,6 +1274,7 @@
> let AsmString = !strconcat(opc, "${p}", asm);
> let Pattern = pattern;
> let PostEncoderMethod = "VFPThumb2PostEncoder";
> + let DecoderNamespace = "VFP";
> list<Predicate> Predicates = [HasVFP2];
> }
>
> @@ -1280,6 +1290,7 @@
> let AsmString = asm;
> let Pattern = pattern;
> let PostEncoderMethod = "VFPThumb2PostEncoder";
> + let DecoderNamespace = "VFP";
> list<Predicate> Predicates = [HasVFP2];
> }
>
> @@ -1597,6 +1608,7 @@
> let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
> let Pattern = pattern;
> list<Predicate> Predicates = [HasNEON];
> + let DecoderNamespace = "NEON";
> }
>
> // Same as NeonI except it does not have a "data type" specifier.
> @@ -1609,6 +1621,7 @@
> let AsmString = !strconcat(opc, "${p}", "\t", asm);
> let Pattern = pattern;
> list<Predicate> Predicates = [HasNEON];
> + let DecoderNamespace = "NEON";
> }
>
> class NLdSt<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
> @@ -1700,6 +1713,7 @@
> let Inst{24} = SIMM{7};
> let Inst{18-16} = SIMM{6-4};
> let Inst{3-0} = SIMM{3-0};
> + let DecoderMethod = "DecodeNEONModImmInstruction";
> }
>
> // NEON 2 vector register format.
>
> Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
> +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Aug 9 15:55:18 2011
> @@ -315,6 +315,7 @@
> def brtarget : Operand<OtherVT> {
> let EncoderMethod = "getBranchTargetOpValue";
> let OperandType = "OPERAND_PCREL";
> + let DecoderMethod = "DecodeT2BROperand";
> }
>
> // FIXME: get rid of this one?
> @@ -343,6 +344,7 @@
> // Encoded the same as branch targets.
> let EncoderMethod = "getARMBranchTargetOpValue";
> let OperandType = "OPERAND_PCREL";
> + let DecoderMethod = "DecodeBLTargetOperand";
> }
>
>
> @@ -352,6 +354,7 @@
> let EncoderMethod = "getRegisterListOpValue";
> let ParserMatchClass = RegListAsmOperand;
> let PrintMethod = "printRegisterList";
> + let DecoderMethod = "DecodeRegListOperand";
> }
>
> def DPRRegListAsmOperand : AsmOperandClass { let Name = "DPRRegList"; }
> @@ -359,6 +362,7 @@
> let EncoderMethod = "getRegisterListOpValue";
> let ParserMatchClass = DPRRegListAsmOperand;
> let PrintMethod = "printRegisterList";
> + let DecoderMethod = "DecodeDPRRegListOperand";
> }
>
> def SPRRegListAsmOperand : AsmOperandClass { let Name = "SPRRegList"; }
> @@ -366,6 +370,7 @@
> let EncoderMethod = "getRegisterListOpValue";
> let ParserMatchClass = SPRRegListAsmOperand;
> let PrintMethod = "printRegisterList";
> + let DecoderMethod = "DecodeSPRRegListOperand";
> }
>
> // An operand for the CONSTPOOL_ENTRY pseudo-instruction.
> @@ -385,6 +390,7 @@
>
> def neon_vcvt_imm32 : Operand<i32> {
> let EncoderMethod = "getNEONVcvtImm32OpValue";
> + let DecoderMethod = "DecodeVCVTImmOperand";
> }
>
> // rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24.
> @@ -431,6 +437,7 @@
> [shl, srl, sra, rotr]> {
> let EncoderMethod = "getSORegRegOpValue";
> let PrintMethod = "printSORegRegOperand";
> + let DecoderMethod = "DecodeSORegRegOperand";
> let ParserMatchClass = ShiftedRegAsmOperand;
> let MIOperandInfo = (ops GPR, GPR, i32imm);
> }
> @@ -441,6 +448,7 @@
> [shl, srl, sra, rotr]> {
> let EncoderMethod = "getSORegImmOpValue";
> let PrintMethod = "printSORegImmOperand";
> + let DecoderMethod = "DecodeSORegImmOperand";
> let ParserMatchClass = ShiftedImmAsmOperand;
> let MIOperandInfo = (ops GPR, i32imm);
> }
> @@ -451,6 +459,7 @@
> [shl,srl,sra,rotr]> {
> let EncoderMethod = "getSORegRegOpValue";
> let PrintMethod = "printSORegRegOperand";
> + let DecoderMethod = "DecodeSORegRegOperand";
> let MIOperandInfo = (ops GPR, GPR, i32imm);
> }
>
> @@ -460,6 +469,7 @@
> [shl,srl,sra,rotr]> {
> let EncoderMethod = "getSORegImmOpValue";
> let PrintMethod = "printSORegImmOperand";
> + let DecoderMethod = "DecodeSORegImmOperand";
> let MIOperandInfo = (ops GPR, i32imm);
> }
>
> @@ -472,6 +482,7 @@
> }]> {
> let EncoderMethod = "getSOImmOpValue";
> let ParserMatchClass = SOImmAsmOperand;
> + let DecoderMethod = "DecodeSOImmOperand";
> }
>
> // Break so_imm's up into two pieces. This handles immediates with up to 16
> @@ -552,6 +563,7 @@
> }] > {
> let EncoderMethod = "getBitfieldInvertedMaskOpValue";
> let PrintMethod = "printBitfieldInvMaskImmOperand";
> + let DecoderMethod = "DecodeBitfieldMaskOperand";
> let ParserMatchClass = BitfieldAsmOperand;
> }
>
> @@ -599,6 +611,7 @@
>
> let EncoderMethod = "getAddrModeImm12OpValue";
> let PrintMethod = "printAddrModeImm12Operand";
> + let DecoderMethod = "DecodeAddrModeImm12Operand";
> let ParserMatchClass = MemImm12OffsetAsmOperand;
> let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
> }
> @@ -610,6 +623,7 @@
> let EncoderMethod = "getLdStSORegOpValue";
> // FIXME: Simplify the printer
> let PrintMethod = "printAddrMode2Operand";
> + let DecoderMethod = "DecodeSORegMemOperand";
> let ParserMatchClass = MemRegOffsetAsmOperand;
> let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$shift);
> }
> @@ -645,6 +659,7 @@
> }
> def postidx_reg : Operand<i32> {
> let EncoderMethod = "getPostIdxRegOpValue";
> + let DecoderMethod = "DecodePostIdxReg";
> let PrintMethod = "printPostIdxRegOperand";
> let ParserMatchClass = PostIdxRegAsmOperand;
> let MIOperandInfo = (ops GPR, i32imm);
> @@ -707,6 +722,7 @@
> ComplexPattern<i32, 2, "SelectAddrMode3Offset",
> [], [SDNPWantRoot]> {
> let EncoderMethod = "getAddrMode3OffsetOpValue";
> + let DecoderMethod = "DecodeAddrMode3Offset";
> let PrintMethod = "printAddrMode3OffsetOperand";
> let MIOperandInfo = (ops GPR, i32imm);
> }
> @@ -725,6 +741,7 @@
> ComplexPattern<i32, 2, "SelectAddrMode5", []> {
> let PrintMethod = "printAddrMode5Operand";
> let EncoderMethod = "getAddrMode5OpValue";
> + let DecoderMethod = "DecodeAddrMode5Operand";
> let ParserMatchClass = AddrMode5AsmOperand;
> let MIOperandInfo = (ops GPR:$base, i32imm);
> }
> @@ -736,6 +753,7 @@
> let PrintMethod = "printAddrMode6Operand";
> let MIOperandInfo = (ops GPR:$addr, i32imm);
> let EncoderMethod = "getAddrMode6AddressOpValue";
> + let DecoderMethod = "DecodeAddrMode6Operand";
> }
>
> def am6offset : Operand<i32>,
> @@ -744,6 +762,7 @@
> let PrintMethod = "printAddrMode6OffsetOperand";
> let MIOperandInfo = (ops GPR);
> let EncoderMethod = "getAddrMode6OffsetOpValue";
> + let DecoderMethod = "DecodeGPRRegisterClass";
> }
>
> // Special version of addrmode6 to handle alignment encoding for VST1/VLD1
> @@ -778,6 +797,7 @@
> def addr_offset_none : Operand<i32>,
> ComplexPattern<i32, 1, "SelectAddrOffsetNone", []> {
> let PrintMethod = "printAddrMode7Operand";
> + let DecoderMethod = "DecodeAddrMode7Operand";
> let ParserMatchClass = MemNoOffsetAsmOperand;
> let MIOperandInfo = (ops GPR:$base);
> }
> @@ -793,6 +813,7 @@
> def p_imm : Operand<i32> {
> let PrintMethod = "printPImmediate";
> let ParserMatchClass = CoprocNumAsmOperand;
> + let DecoderMethod = "DecodeCoprocessor";
> }
>
> def CoprocRegAsmOperand : AsmOperandClass {
> @@ -1654,6 +1675,7 @@
> [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> {
> bits<24> target;
> let Inst{23-0} = target;
> + let DecoderMethod = "DecodeBranchImmInstruction";
> }
>
> let isBarrier = 1 in {
> @@ -1917,6 +1939,7 @@
> let Inst{23} = addr{12};
> let Inst{19-16} = addr{17-14};
> let Inst{11-0} = addr{11-0};
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
> }
>
> @@ -1933,6 +1956,8 @@
> let Inst{23} = offset{12};
> let Inst{19-16} = addr;
> let Inst{11-0} = offset{11-0};
> +
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
>
> def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
> @@ -1948,7 +1973,10 @@
> let Inst{23} = offset{12};
> let Inst{19-16} = addr;
> let Inst{11-0} = offset{11-0};
> +
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
> +
> }
>
> let mayLoad = 1, neverHasSideEffects = 1 in {
> @@ -2019,20 +2047,39 @@
>
> // LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only.
> let mayLoad = 1, neverHasSideEffects = 1 in {
> -def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
> - (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
> +def LDRTr : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
> + (ins ldst_so_reg:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
> + "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
> + // {17-14} Rn
> + // {13} 1 == Rm, 0 == imm12
> + // {12} isAdd
> + // {11-0} imm12/Rm
> + bits<18> addr;
> + let Inst{25} = 1;
> + let Inst{23} = addr{12};
> + let Inst{21} = 1; // overwrite
> + let Inst{19-16} = addr{17-14};
> + let Inst{11-5} = addr{11-5};
> + let Inst{4} = 0;
> + let Inst{3-0} = addr{3-0};
> + let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> +}
> +def LDRTi : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
> + (ins addrmode_imm12:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
> "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
> // {17-14} Rn
> // {13} 1 == Rm, 0 == imm12
> // {12} isAdd
> // {11-0} imm12/Rm
> bits<18> addr;
> - let Inst{25} = addr{13};
> + let Inst{25} = 0;
> let Inst{23} = addr{12};
> let Inst{21} = 1; // overwrite
> let Inst{19-16} = addr{17-14};
> let Inst{11-0} = addr{11-0};
> let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
>
> def LDRBT_POST_REG : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
> @@ -2049,6 +2096,7 @@
> let Inst{21} = 1; // overwrite
> let Inst{19-16} = addr;
> let Inst{11-0} = offset{11-0};
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
>
> def LDRBT_POST_IMM : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
> @@ -2065,6 +2113,7 @@
> let Inst{21} = 1; // overwrite
> let Inst{19-16} = addr;
> let Inst{11-0} = offset{11-0};
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
>
> multiclass AI3ldrT<bits<4> op, string opc> {
> @@ -2151,6 +2200,8 @@
> let Inst{23} = offset{12};
> let Inst{19-16} = addr;
> let Inst{11-0} = offset{11-0};
> +
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
>
> def _POST_IMM : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb),
> @@ -2166,6 +2217,8 @@
> let Inst{23} = offset{12};
> let Inst{19-16} = addr;
> let Inst{11-0} = offset{11-0};
> +
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
> }
>
> @@ -2287,6 +2340,7 @@
> let Inst{21} = 1; // overwrite
> let Inst{4} = 0;
> let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
>
> def STRTi : AI2stridxT<0, 0, (outs GPR:$Rn_wb),
> @@ -2297,6 +2351,7 @@
> let Inst{25} = 0;
> let Inst{21} = 1; // overwrite
> let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
>
>
> @@ -2309,6 +2364,7 @@
> let Inst{21} = 1; // overwrite
> let Inst{4} = 0;
> let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
>
> def STRBTi : AI2stridxT<1, 0, (outs GPR:$Rn_wb),
> @@ -2319,6 +2375,7 @@
> let Inst{25} = 0;
> let Inst{21} = 1; // overwrite
> let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
> + let DecoderMethod = "DecodeAddrMode2IdxInstruction";
> }
>
> multiclass AI3strT<bits<4> op, string opc> {
> @@ -2373,6 +2430,8 @@
> let Inst{24-23} = 0b01; // Increment After
> let Inst{21} = 1; // Writeback
> let Inst{20} = L_bit;
> +
> + let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
> }
> def DA :
> AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
> @@ -2389,6 +2448,8 @@
> let Inst{24-23} = 0b00; // Decrement After
> let Inst{21} = 1; // Writeback
> let Inst{20} = L_bit;
> +
> + let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
> }
> def DB :
> AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
> @@ -2405,6 +2466,8 @@
> let Inst{24-23} = 0b10; // Decrement Before
> let Inst{21} = 1; // Writeback
> let Inst{20} = L_bit;
> +
> + let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
> }
> def IB :
> AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
> @@ -2421,6 +2484,8 @@
> let Inst{24-23} = 0b11; // Increment Before
> let Inst{21} = 1; // Writeback
> let Inst{20} = L_bit;
> +
> + let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
> }
> }
>
> @@ -2504,8 +2569,6 @@
> let Inst{25} = 0;
> }
>
> -
> -
> let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
> def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi,
> "mov", "\t$Rd, $imm", [(set GPR:$Rd, so_imm:$imm)]>, UnaryDP {
> @@ -3383,6 +3446,7 @@
>
>
> multiclass AI_smla<string opc, PatFrag opnode> {
> + let DecoderMethod = "DecodeSMLAInstruction" in {
> def BB : AMulxyIa<0b0001000, 0b00, (outs GPR:$Rd),
> (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
> IIC_iMAC16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra",
> @@ -3425,6 +3489,7 @@
> [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn,
> (sra GPR:$Rm, (i32 16))), (i32 16))))]>,
> Requires<[IsARM, HasV5TE]>;
> + }
> }
>
> defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
> @@ -3989,7 +4054,7 @@
> }
>
> multiclass LdStCop<bits<4> op31_28, bit load, dag ops, string opc, string cond>{
> -
> + let DecoderNamespace = "Common" in {
> def _OFFSET : ACI<(outs),
> !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
> !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr"> {
> @@ -3998,6 +4063,7 @@
> let Inst{21} = 0; // W = 0
> let Inst{22} = 0; // D = 0
> let Inst{20} = load;
> + let DecoderMethod = "DecodeCopMemInstruction";
> }
>
> def _PRE : ACI<(outs),
> @@ -4008,6 +4074,7 @@
> let Inst{21} = 1; // W = 1
> let Inst{22} = 0; // D = 0
> let Inst{20} = load;
> + let DecoderMethod = "DecodeCopMemInstruction";
> }
>
> def _POST : ACI<(outs),
> @@ -4018,6 +4085,7 @@
> let Inst{21} = 1; // W = 1
> let Inst{22} = 0; // D = 0
> let Inst{20} = load;
> + let DecoderMethod = "DecodeCopMemInstruction";
> }
>
> def _OPTION : ACI<(outs),
> @@ -4030,6 +4098,7 @@
> let Inst{21} = 0; // W = 0
> let Inst{22} = 0; // D = 0
> let Inst{20} = load;
> + let DecoderMethod = "DecodeCopMemInstruction";
> }
>
> def L_OFFSET : ACI<(outs),
> @@ -4040,6 +4109,7 @@
> let Inst{21} = 0; // W = 0
> let Inst{22} = 1; // D = 1
> let Inst{20} = load;
> + let DecoderMethod = "DecodeCopMemInstruction";
> }
>
> def L_PRE : ACI<(outs),
> @@ -4051,6 +4121,7 @@
> let Inst{21} = 1; // W = 1
> let Inst{22} = 1; // D = 1
> let Inst{20} = load;
> + let DecoderMethod = "DecodeCopMemInstruction";
> }
>
> def L_POST : ACI<(outs),
> @@ -4063,6 +4134,7 @@
> let Inst{21} = 1; // W = 1
> let Inst{22} = 1; // D = 1
> let Inst{20} = load;
> + let DecoderMethod = "DecodeCopMemInstruction";
> }
>
> def L_OPTION : ACI<(outs),
> @@ -4076,6 +4148,8 @@
> let Inst{21} = 0; // W = 0
> let Inst{22} = 1; // D = 1
> let Inst{20} = load;
> + let DecoderMethod = "DecodeCopMemInstruction";
> + }
> }
> }
>
>
> Modified: llvm/trunk/lib/Target/ARM/ARMInstrNEON.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrNEON.td?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMInstrNEON.td (original)
> +++ llvm/trunk/lib/Target/ARM/ARMInstrNEON.td Tue Aug 9 15:55:18 2011
> @@ -191,6 +191,7 @@
> "vld1", Dt, "\\{$Vd\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
> class VLD1Q<bits<4> op7_4, string Dt>
> : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2),
> @@ -198,6 +199,7 @@
> "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
>
> def VLD1d8 : VLD1D<{0,0,0,?}, "8">;
> @@ -222,6 +224,7 @@
> "vld1", Dt, "\\{$Vd\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
> class VLD1QWB<bits<4> op7_4, string Dt>
> : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb),
> @@ -229,6 +232,7 @@
> "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
>
> def VLD1d8_UPD : VLD1DWB<{0,0,0,?}, "8">;
> @@ -253,12 +257,14 @@
> "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
> class VLD1D3WB<bits<4> op7_4, string Dt>
> : NLdSt<0,0b10,0b0110,op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb),
> (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1x3u, "vld1", Dt,
> "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm", "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
>
> def VLD1d8T : VLD1D3<{0,0,0,?}, "8">;
> @@ -281,6 +287,7 @@
> "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
> class VLD1D4WB<bits<4> op7_4, string Dt>
> : NLdSt<0,0b10,0b0010,op7_4,
> @@ -289,6 +296,7 @@
> "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", "$Rn.addr = $wb",
> []> {
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
>
> def VLD1d8Q : VLD1D4<{0,0,?,?}, "8">;
> @@ -311,6 +319,7 @@
> "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
> class VLD2Q<bits<4> op7_4, string Dt>
> : NLdSt<0, 0b10, 0b0011, op7_4,
> @@ -319,6 +328,7 @@
> "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
>
> def VLD2d8 : VLD2D<0b1000, {0,0,?,?}, "8">;
> @@ -344,6 +354,7 @@
> "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
> class VLD2QWB<bits<4> op7_4, string Dt>
> : NLdSt<0, 0b10, 0b0011, op7_4,
> @@ -352,6 +363,7 @@
> "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
>
> def VLD2d8_UPD : VLD2DWB<0b1000, {0,0,?,?}, "8">;
> @@ -385,6 +397,7 @@
> "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
>
> def VLD3d8 : VLD3D<0b0100, {0,0,0,?}, "8">;
> @@ -403,6 +416,7 @@
> "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
>
> def VLD3d8_UPD : VLD3DWB<0b0100, {0,0,0,?}, "8">;
> @@ -442,6 +456,7 @@
> "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
>
> def VLD4d8 : VLD4D<0b0000, {0,0,?,?}, "8">;
> @@ -460,6 +475,7 @@
> "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVLDInstruction";
> }
>
> def VLD4d8_UPD : VLD4DWB<0b0000, {0,0,?,?}, "8">;
> @@ -826,6 +842,7 @@
> [(set DPR:$Vd, (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLD1DupInstruction";
> }
> class VLD1QDUPPseudo<ValueType Ty, PatFrag LoadOp> : VLDQPseudo<IIC_VLD1dup> {
> let Pattern = [(set QPR:$dst,
> @@ -853,6 +870,7 @@
> "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLD1DupInstruction";
> }
>
> def VLD1DUPq8 : VLD1QDUP<{0,0,1,0}, "8">;
> @@ -865,12 +883,14 @@
> (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu,
> "vld1", Dt, "\\{$Vd[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLD1DupInstruction";
> }
> class VLD1QDUPWB<bits<4> op7_4, string Dt>
> : NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb),
> (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu,
> "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLD1DupInstruction";
> }
>
> def VLD1DUPd8_UPD : VLD1DUPWB<{0,0,0,0}, "8">;
> @@ -892,6 +912,7 @@
> "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLD2DupInstruction";
> }
>
> def VLD2DUPd8 : VLD2DUP<{0,0,0,?}, "8">;
> @@ -913,6 +934,7 @@
> (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD2dupu,
> "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLD2DupInstruction";
> }
>
> def VLD2DUPd8_UPD : VLD2DUPWB<{0,0,0,0}, "8">;
> @@ -934,6 +956,7 @@
> "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLD3DupInstruction";
> }
>
> def VLD3DUPd8 : VLD3DUP<{0,0,0,?}, "8">;
> @@ -956,6 +979,7 @@
> "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLD3DupInstruction";
> }
>
> def VLD3DUPd8_UPD : VLD3DUPWB<{0,0,0,0}, "8">;
> @@ -978,6 +1002,7 @@
> "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLD4DupInstruction";
> }
>
> def VLD4DUPd8 : VLD4DUP<{0,0,0,?}, "8">;
> @@ -1001,6 +1026,7 @@
> "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVLD4DupInstruction";
> }
>
> def VLD4DUPd8_UPD : VLD4DUPWB<{0,0,0,0}, "8">;
> @@ -1046,6 +1072,7 @@
> IIC_VST1, "vst1", Dt, "\\{$Vd\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
> class VST1Q<bits<4> op7_4, string Dt>
> : NLdSt<0,0b00,0b1010,op7_4, (outs),
> @@ -1053,6 +1080,7 @@
> "vst1", Dt, "\\{$Vd, $src2\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
>
> def VST1d8 : VST1D<{0,0,0,?}, "8">;
> @@ -1076,6 +1104,7 @@
> (ins addrmode6:$Rn, am6offset:$Rm, DPR:$Vd), IIC_VST1u,
> "vst1", Dt, "\\{$Vd\\}, $Rn$Rm", "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
> class VST1QWB<bits<4> op7_4, string Dt>
> : NLdSt<0, 0b00, 0b1010, op7_4, (outs GPR:$wb),
> @@ -1083,6 +1112,7 @@
> IIC_VST1x2u, "vst1", Dt, "\\{$Vd, $src2\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
>
> def VST1d8_UPD : VST1DWB<{0,0,0,?}, "8">;
> @@ -1107,6 +1137,7 @@
> IIC_VST1x3, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
> class VST1D3WB<bits<4> op7_4, string Dt>
> : NLdSt<0, 0b00, 0b0110, op7_4, (outs GPR:$wb),
> @@ -1115,6 +1146,7 @@
> IIC_VST1x3u, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
>
> def VST1d8T : VST1D3<{0,0,0,?}, "8">;
> @@ -1138,6 +1170,7 @@
> []> {
> let Rm = 0b1111;
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
> class VST1D4WB<bits<4> op7_4, string Dt>
> : NLdSt<0, 0b00, 0b0010, op7_4, (outs GPR:$wb),
> @@ -1146,6 +1179,7 @@
> "vst1", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
>
> def VST1d8Q : VST1D4<{0,0,?,?}, "8">;
> @@ -1168,6 +1202,7 @@
> IIC_VST2, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
> class VST2Q<bits<4> op7_4, string Dt>
> : NLdSt<0, 0b00, 0b0011, op7_4, (outs),
> @@ -1176,6 +1211,7 @@
> "", []> {
> let Rm = 0b1111;
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
>
> def VST2d8 : VST2D<0b1000, {0,0,?,?}, "8">;
> @@ -1201,6 +1237,7 @@
> IIC_VST2u, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
> class VST2QWB<bits<4> op7_4, string Dt>
> : NLdSt<0, 0b00, 0b0011, op7_4, (outs GPR:$wb),
> @@ -1209,6 +1246,7 @@
> "vst2", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
>
> def VST2d8_UPD : VST2DWB<0b1000, {0,0,?,?}, "8">;
> @@ -1242,6 +1280,7 @@
> "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []> {
> let Rm = 0b1111;
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
>
> def VST3d8 : VST3D<0b0100, {0,0,0,?}, "8">;
> @@ -1260,6 +1299,7 @@
> "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{4} = Rn{4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
>
> def VST3d8_UPD : VST3DWB<0b0100, {0,0,0,?}, "8">;
> @@ -1299,6 +1339,7 @@
> "", []> {
> let Rm = 0b1111;
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
>
> def VST4d8 : VST4D<0b0000, {0,0,?,?}, "8">;
> @@ -1317,6 +1358,7 @@
> "vst4", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm",
> "$Rn.addr = $wb", []> {
> let Inst{5-4} = Rn{5-4};
> + let DecoderMethod = "DecodeVSTInstruction";
> }
>
> def VST4d8_UPD : VST4DWB<0b0000, {0,0,?,?}, "8">;
> @@ -4040,6 +4082,7 @@
> : N2VLSh<op24, op23, op11_8, op7, op6, op4, OpcodeStr, Dt,
> ResTy, OpTy, OpNode> {
> let Inst{21-16} = op21_16;
> + let DecoderMethod = "DecodeVSHLMaxInstruction";
> }
> def VSHLLi8 : N2VLShMax<1, 1, 0b110010, 0b0011, 0, 0, 0, "vshll", "i8",
> v8i16, v8i8, NEONvshlli>;
> @@ -4754,6 +4797,7 @@
> // Vector Table Lookup and Table Extension.
>
> // VTBL : Vector Table Lookup
> +let DecoderMethod = "DecodeTBLInstruction" in {
> def VTBL1
> : N3V<1,1,0b11,0b1000,0,0, (outs DPR:$Vd),
> (ins DPR:$Vn, DPR:$Vm), NVTBLFrm, IIC_VTB1,
> @@ -4816,6 +4860,7 @@
> def VTBX4Pseudo
> : PseudoNeonI<(outs DPR:$dst), (ins DPR:$orig, QQPR:$tbl, DPR:$src),
> IIC_VTBX4, "$orig = $dst", []>;
> +} // DecoderMethod = "DecodeTBLInstruction"
>
> //===----------------------------------------------------------------------===//
> // NEON instructions for single-precision FP math
>
> Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original)
> +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Tue Aug 9 15:55:18 2011
> @@ -82,14 +82,17 @@
> let OperandType = "OPERAND_PCREL" in {
> def t_brtarget : Operand<OtherVT> {
> let EncoderMethod = "getThumbBRTargetOpValue";
> + let DecoderMethod = "DecodeThumbBROperand";
> }
>
> def t_bcctarget : Operand<i32> {
> let EncoderMethod = "getThumbBCCTargetOpValue";
> + let DecoderMethod = "DecodeThumbBCCTargetOperand";
> }
>
> def t_cbtarget : Operand<i32> {
> let EncoderMethod = "getThumbCBTargetOpValue";
> + let DecoderMethod = "DecodeThumbCmpBROperand";
> }
>
> def t_bltarget : Operand<i32> {
> @@ -119,12 +122,14 @@
> ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S1", []> {
> let EncoderMethod = "getThumbAddrModeRegRegOpValue";
> let PrintMethod = "printThumbAddrModeRROperand";
> + let DecoderMethod = "DecodeThumbAddrModeRR";
> let ParserMatchClass = t_addrmode_rr_asm_operand;
> let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
> }
> def t_addrmode_rrs2 : Operand<i32>,
> ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S2", []> {
> let EncoderMethod = "getThumbAddrModeRegRegOpValue";
> + let DecoderMethod = "DecodeThumbAddrModeRR";
> let PrintMethod = "printThumbAddrModeRROperand";
> let ParserMatchClass = t_addrmode_rr_asm_operand;
> let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
> @@ -132,6 +137,7 @@
> def t_addrmode_rrs4 : Operand<i32>,
> ComplexPattern<i32, 2, "SelectThumbAddrModeRI5S4", []> {
> let EncoderMethod = "getThumbAddrModeRegRegOpValue";
> + let DecoderMethod = "DecodeThumbAddrModeRR";
> let PrintMethod = "printThumbAddrModeRROperand";
> let ParserMatchClass = t_addrmode_rr_asm_operand;
> let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
> @@ -142,6 +148,7 @@
> def t_addrmode_is4 : Operand<i32>,
> ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S4", []> {
> let EncoderMethod = "getAddrModeISOpValue";
> + let DecoderMethod = "DecodeThumbAddrModeIS";
> let PrintMethod = "printThumbAddrModeImm5S4Operand";
> let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
> }
> @@ -151,6 +158,7 @@
> def t_addrmode_is2 : Operand<i32>,
> ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S2", []> {
> let EncoderMethod = "getAddrModeISOpValue";
> + let DecoderMethod = "DecodeThumbAddrModeIS";
> let PrintMethod = "printThumbAddrModeImm5S2Operand";
> let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
> }
> @@ -160,6 +168,7 @@
> def t_addrmode_is1 : Operand<i32>,
> ComplexPattern<i32, 2, "SelectThumbAddrModeImm5S1", []> {
> let EncoderMethod = "getAddrModeISOpValue";
> + let DecoderMethod = "DecodeThumbAddrModeIS";
> let PrintMethod = "printThumbAddrModeImm5S1Operand";
> let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
> }
> @@ -178,6 +187,7 @@
> //
> def t_addrmode_pc : Operand<i32> {
> let EncoderMethod = "getAddrModePCOpValue";
> + let DecoderMethod = "DecodeThumbAddrModePC";
> }
>
> //===----------------------------------------------------------------------===//
> @@ -259,6 +269,7 @@
> let Inst{4} = imod;
> let Inst{3} = 0;
> let Inst{2-0} = iflags;
> + let DecoderMethod = "DecodeThumbCPS";
> }
>
> // For both thumb1 and thumb2.
> @@ -272,17 +283,6 @@
> let Inst{2-0} = dst;
> }
>
> -// PC relative add (ADR).
> -def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi,
> - "add\t$dst, pc, $rhs", []>,
> - T1Encoding<{1,0,1,0,0,?}> {
> - // A6.2 & A8.6.10
> - bits<3> dst;
> - bits<8> rhs;
> - let Inst{10-8} = dst;
> - let Inst{7-0} = rhs;
> -}
> -
> // ADD <Rd>, sp, #<imm8>
> // This is rematerializable, which is particularly useful for taking the
> // address of locals.
> @@ -295,6 +295,7 @@
> bits<8> rhs;
> let Inst{10-8} = dst;
> let Inst{7-0} = rhs;
> + let DecoderMethod = "DecodeThumbAddSpecialReg";
> }
>
> // ADD sp, sp, #<imm7>
> @@ -304,6 +305,7 @@
> // A6.2.5 & A8.6.8
> bits<7> rhs;
> let Inst{6-0} = rhs;
> + let DecoderMethod = "DecodeThumbAddSPImm";
> }
>
> // SUB sp, sp, #<imm7>
> @@ -314,6 +316,7 @@
> // A6.2.5 & A8.6.214
> bits<7> rhs;
> let Inst{6-0} = rhs;
> + let DecoderMethod = "DecodeThumbAddSPImm";
> }
>
> // ADD <Rm>, sp
> @@ -325,6 +328,7 @@
> let Inst{7} = dst{3};
> let Inst{6-3} = 0b1101;
> let Inst{2-0} = dst{2-0};
> + let DecoderMethod = "DecodeThumbAddSPReg";
> }
>
> // ADD sp, <Rm>
> @@ -336,6 +340,7 @@
> let Inst{7} = 1;
> let Inst{6-3} = dst;
> let Inst{2-0} = 0b101;
> + let DecoderMethod = "DecodeThumbAddSPReg";
> }
>
> //===----------------------------------------------------------------------===//
> @@ -1189,6 +1194,7 @@
> bits<8> addr;
> let Inst{10-8} = Rd;
> let Inst{7-0} = addr;
> + let DecoderMethod = "DecodeThumbAddSpecialReg";
> }
>
> let neverHasSideEffects = 1, isReMaterializable = 1 in
>
> Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
> +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Aug 9 15:55:18 2011
> @@ -50,6 +50,7 @@
> }]> {
> let ParserMatchClass = t2_so_imm_asmoperand;
> let EncoderMethod = "getT2SOImmOpValue";
> + let DecoderMethod = "DecodeT2SOImm";
> }
>
> // t2_so_imm_not - Match an immediate that is a complement
> @@ -100,6 +101,7 @@
> ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> {
> let PrintMethod = "printAddrModeImm12Operand";
> let EncoderMethod = "getAddrModeImm12OpValue";
> + let DecoderMethod = "DecodeT2AddrModeImm12";
> let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
> }
>
> @@ -121,6 +123,7 @@
> ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
> let PrintMethod = "printT2AddrModeImm8Operand";
> let EncoderMethod = "getT2AddrModeImm8OpValue";
> + let DecoderMethod = "DecodeT2AddrModeImm8";
> let ParserMatchClass = MemImm8OffsetAsmOperand;
> let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
> }
> @@ -130,12 +133,14 @@
> [], [SDNPWantRoot]> {
> let PrintMethod = "printT2AddrModeImm8OffsetOperand";
> let EncoderMethod = "getT2AddrModeImm8OffsetOpValue";
> + let DecoderMethod = "DecodeT2Imm8";
> }
>
> // t2addrmode_imm8s4 := reg +/- (imm8 << 2)
> def t2addrmode_imm8s4 : Operand<i32> {
> let PrintMethod = "printT2AddrModeImm8s4Operand";
> let EncoderMethod = "getT2AddrModeImm8s4OpValue";
> + let DecoderMethod = "DecodeT2AddrModeImm8s4";
> let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
> }
>
> @@ -149,6 +154,7 @@
> ComplexPattern<i32, 3, "SelectT2AddrModeSoReg", []> {
> let PrintMethod = "printT2AddrModeSoRegOperand";
> let EncoderMethod = "getT2AddrModeSORegOpValue";
> + let DecoderMethod = "DecodeT2AddrModeSOReg";
> let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm);
> }
>
> @@ -158,6 +164,7 @@
> //
> def t2addrmode_reg : Operand<i32> {
> let PrintMethod = "printAddrMode7Operand";
> + let DecoderMethod = "DecodeGPRRegisterClass";
> let MIOperandInfo = (ops GPR);
> }
>
> @@ -892,6 +899,8 @@
> let Inst{19-16} = addr{9-6}; // Rn
> let Inst{3-0} = addr{5-2}; // Rm
> let Inst{5-4} = addr{1-0}; // imm
> +
> + let DecoderMethod = "DecodeT2LoadShift";
> }
>
> // FIXME: Is the pci variant actually needed?
> @@ -1430,6 +1439,8 @@
> let Inst{19-16} = addr{9-6}; // Rn
> let Inst{3-0} = addr{5-2}; // Rm
> let Inst{5-4} = addr{1-0}; // imm2
> +
> + let DecoderMethod = "DecodeT2LoadShift";
> }
> }
>
> @@ -2994,6 +3005,8 @@
> let Inst{13} = target{18};
> let Inst{21-16} = target{17-12};
> let Inst{10-0} = target{11-1};
> +
> + let DecoderMethod = "DecodeThumb2BCCInstruction";
> }
>
> // Tail calls. The Darwin version of thumb tail calls uses a t2 branch, so
>
> Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug 9 15:55:18 2011
> @@ -6,584 +6,2328 @@
> // License. See LICENSE.TXT for details.
> //
> //===----------------------------------------------------------------------===//
> -//
> -// This file is part of the ARM Disassembler.
> -// It contains code to implement the public interfaces of ARMDisassembler and
> -// ThumbDisassembler, both of which are instances of MCDisassembler.
> -//
> -//===----------------------------------------------------------------------===//
>
> #define DEBUG_TYPE "arm-disassembler"
>
> #include "ARMDisassembler.h"
> -#include "ARMDisassemblerCore.h"
> -
> -#include "llvm/ADT/OwningPtr.h"
> +#include "ARM.h"
> +#include "ARMRegisterInfo.h"
> +#include "MCTargetDesc/ARMAddressingModes.h"
> +#include "MCTargetDesc/ARMBaseInfo.h"
> #include "llvm/MC/EDInstInfo.h"
> #include "llvm/MC/MCInst.h"
> +#include "llvm/MC/MCExpr.h"
> +#include "llvm/MC/MCContext.h"
> #include "llvm/Target/TargetRegistry.h"
> #include "llvm/Support/Debug.h"
> #include "llvm/Support/MemoryObject.h"
> #include "llvm/Support/ErrorHandling.h"
> #include "llvm/Support/raw_ostream.h"
>
> -//#define DEBUG(X) do { X; } while (0)
> -
> -/// ARMGenDecoderTables.inc - ARMDecoderTables.inc is tblgen'ed from
> -/// ARMDecoderEmitter.cpp TableGen backend. It contains:
> -///
> -/// o Mappings from opcode to ARM/Thumb instruction format
> -///
> -/// o static uint16_t decodeInstruction(uint32_t insn) - the decoding function
> -/// for an ARM instruction.
> -///
> -/// o static uint16_t decodeThumbInstruction(field_t insn) - the decoding
> -/// function for a Thumb instruction.
> -///
> -#include "ARMGenDecoderTables.inc"
> +// Forward declare these because the autogenerated code will reference them.
> +// Definitions are further down.
> +static bool DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder);
> +static bool DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder);
> +static bool DecodetcGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder);
> +static bool DecoderGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeSPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeDPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeDPR_8RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeDPR_VFP2RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeQPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder);
> +
> +static bool DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeCCOutOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeSOImmOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +
> +static bool DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +
> +static bool DecodeMemMultipleWritebackInstruction(llvm::MCInst & Inst,
> + unsigned Insn,
> + uint64_t Adddress,
> + const void *Decoder);
> +static bool DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeAddrMode7Operand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeBranchImmInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeVCVTImmOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeNEONModImmInstruction(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeShiftRight8Imm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeShiftRight16Imm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeShiftRight32Imm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeCoprocessor(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeAddrMode3Offset(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +
> +
> +static bool DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbBROperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeT2BROperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbCmpBROperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbAddrModeSP(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbAddSPImm(llvm::MCInst &Inst, uint16_t Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbCPS(llvm::MCInst &Inst, uint16_t Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbSRImm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeT2SOImm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbBCCTargetOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
> +static bool DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder);
>
> +#include "ARMGenDisassemblerTables.inc"
> +#include "ARMGenInstrInfo.inc"
> #include "ARMGenEDInfo.inc"
>
> using namespace llvm;
>
> -/// showBitVector - Use the raw_ostream to log a diagnostic message describing
> -/// the inidividual bits of the instruction.
> -///
> -static inline void showBitVector(raw_ostream &os, const uint32_t &insn) {
> - // Split the bit position markers into more than one lines to fit 80 columns.
> - os << " 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11"
> - << " 10 9 8 7 6 5 4 3 2 1 0 \n";
> - os << "---------------------------------------------------------------"
> - << "----------------------------------\n";
> - os << '|';
> - for (unsigned i = 32; i != 0; --i) {
> - if (insn >> (i - 1) & 0x01)
> - os << " 1";
> - else
> - os << " 0";
> - os << (i%4 == 1 ? '|' : ':');
> +static MCDisassembler *createARMDisassembler(const Target &T) {
> + return new ARMDisassembler;
> +}
> +
> +static MCDisassembler *createThumbDisassembler(const Target &T) {
> + return new ThumbDisassembler;
> +}
> +
> +EDInstInfo *ARMDisassembler::getEDInfo() const {
> + return instInfoARM;
> +}
> +
> +EDInstInfo *ThumbDisassembler::getEDInfo() const {
> + return instInfoARM;
> +}
> +
> +
> +bool ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
> + const MemoryObject &Region,
> + uint64_t Address,raw_ostream &os) const {
> + uint8_t bytes[4];
> +
> + // We want to read exactly 4 bytes of data.
> + if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1)
> + return false;
> +
> + // Encoded as a small-endian 32-bit word in the stream.
> + uint32_t insn = (bytes[3] << 24) |
> + (bytes[2] << 16) |
> + (bytes[1] << 8) |
> + (bytes[0] << 0);
> +
> + // Calling the auto-generated decoder function.
> + bool result = decodeARMInstruction32(MI, insn, Address, this);
> + if (result) {
> + Size = 4;
> + return true;
> }
> - os << '\n';
> - // Split the bit position markers into more than one lines to fit 80 columns.
> - os << "---------------------------------------------------------------"
> - << "----------------------------------\n";
> - os << '\n';
> -}
> -
> -/// decodeARMInstruction is a decorator function which tries special cases of
> -/// instruction matching before calling the auto-generated decoder function.
> -static unsigned decodeARMInstruction(uint32_t &insn) {
> - if (slice(insn, 31, 28) == 15)
> - goto AutoGenedDecoder;
> -
> - // Special case processing, if any, goes here....
> -
> - // LLVM combines the offset mode of A8.6.197 & A8.6.198 into STRB.
> - // The insufficient encoding information of the combined instruction confuses
> - // the decoder wrt BFC/BFI. Therefore, we try to recover here.
> - // For BFC, Inst{27-21} = 0b0111110 & Inst{6-0} = 0b0011111.
> - // For BFI, Inst{27-21} = 0b0111110 & Inst{6-4} = 0b001 & Inst{3-0} =! 0b1111.
> - if (slice(insn, 27, 21) == 0x3e && slice(insn, 6, 4) == 1) {
> - if (slice(insn, 3, 0) == 15)
> - return ARM::BFC;
> - else
> - return ARM::BFI;
> +
> + // Instructions that are shared between ARM and Thumb modes.
> + // FIXME: This shouldn't really exist. It's an artifact of the
> + // fact that we fail to encode a few instructions properly for Thumb.
> + MI.clear();
> + result = decodeCommonInstruction32(MI, insn, Address, this);
> + if (result) {
> + Size = 4;
> + return true;
> }
>
> - // Ditto for STRBT, which is a super-instruction for A8.6.199 Encodings
> - // A1 & A2.
> - // As a result, the decoder fails to deocode USAT properly.
> - if (slice(insn, 27, 21) == 0x37 && slice(insn, 5, 4) == 1)
> - return ARM::USAT;
> - // As a result, the decoder fails to deocode UQADD16 properly.
> - if (slice(insn, 27, 20) == 0x66 && slice(insn, 7, 4) == 1)
> - return ARM::UQADD16;
> -
> - // Ditto for ADDSrs, which is a super-instruction for A8.6.7 & A8.6.8.
> - // As a result, the decoder fails to decode UMULL properly.
> - if (slice(insn, 27, 21) == 0x04 && slice(insn, 7, 4) == 9) {
> - return ARM::UMULL;
> - }
> -
> - // Ditto for STR_PRE, which is a super-instruction for A8.6.194 & A8.6.195.
> - // As a result, the decoder fails to decode SBFX properly.
> - if (slice(insn, 27, 21) == 0x3d && slice(insn, 6, 4) == 5)
> - return ARM::SBFX;
> -
> - // And STRB_PRE, which is a super-instruction for A8.6.197 & A8.6.198.
> - // As a result, the decoder fails to decode UBFX properly.
> - if (slice(insn, 27, 21) == 0x3f && slice(insn, 6, 4) == 5)
> - return ARM::UBFX;
> -
> - // Ditto for STRT, which is a super-instruction for A8.6.210 Encoding A1 & A2.
> - // As a result, the decoder fails to deocode SSAT properly.
> - if (slice(insn, 27, 21) == 0x35 && slice(insn, 5, 4) == 1)
> - return ARM::SSAT;
> -
> - // Ditto for RSCrs, which is a super-instruction for A8.6.146 & A8.6.147.
> - // As a result, the decoder fails to decode STRHT/LDRHT/LDRSHT/LDRSBT.
> - if (slice(insn, 27, 24) == 0) {
> - switch (slice(insn, 21, 20)) {
> - case 2:
> - switch (slice(insn, 7, 4)) {
> - case 11:
> - return slice(insn, 22, 22) ? ARM::STRHTi : ARM::STRHTr;
> - default:
> - break; // fallthrough
> - }
> - break;
> - case 3:
> - switch (slice(insn, 7, 4)) {
> - case 11:
> - return slice(insn, 22, 22) ? ARM::LDRHTi : ARM::LDRHTr;
> - case 13:
> - return slice(insn, 22, 22) ? ARM::LDRSBTi : ARM::LDRSBTr;
> - case 15:
> - return slice(insn, 22, 22) ? ARM::LDRSHTi : ARM::LDRSHTr;
> - default:
> - break; // fallthrough
> - }
> - break;
> - default:
> - break; // fallthrough
> - }
> + // VFP and NEON instructions, similarly, are shared between ARM
> + // and Thumb modes.
> + MI.clear();
> + result = decodeVFPInstruction32(MI, insn, Address, this);
> + if (result) {
> + Size = 4;
> + return true;
> }
>
> - // Ditto for SBCrs, which is a super-instruction for A8.6.152 & A8.6.153.
> - // As a result, the decoder fails to decode STRH_Post/LDRD_POST/STRD_POST
> - // properly.
> - if (slice(insn, 27, 25) == 0 && slice(insn, 20, 20) == 0) {
> - unsigned PW = slice(insn, 24, 24) << 1 | slice(insn, 21, 21);
> - switch (slice(insn, 7, 4)) {
> - case 11:
> - switch (PW) {
> - case 2: // Offset
> - return ARM::STRH;
> - case 3: // Pre-indexed
> - return ARM::STRH_PRE;
> - case 0: // Post-indexed
> - return ARM::STRH_POST;
> - default:
> - break; // fallthrough
> - }
> - break;
> - case 13:
> - switch (PW) {
> - case 2: // Offset
> - return ARM::LDRD;
> - case 3: // Pre-indexed
> - return ARM::LDRD_PRE;
> - case 0: // Post-indexed
> - return ARM::LDRD_POST;
> - default:
> - break; // fallthrough
> - }
> - break;
> - case 15:
> - switch (PW) {
> - case 2: // Offset
> - return ARM::STRD;
> - case 3: // Pre-indexed
> - return ARM::STRD_PRE;
> - case 0: // Post-indexed
> - return ARM::STRD_POST;
> - default:
> - break; // fallthrough
> - }
> - break;
> - default:
> - break; // fallthrough
> - }
> + MI.clear();
> + result = decodeNEONInstruction32(MI, insn, Address, this);
> + if (result) {
> + // Add a fake predicate operand, because we share these instruction
> + // definitions with Thumb2 where these instructions are predicable.
> + if (!DecodePredicateOperand(MI, 0xE, Address, this)) return false;
> + Size = 4;
> + return true;
> }
>
> - // Ditto for SBCSSrs, which is a super-instruction for A8.6.152 & A8.6.153.
> - // As a result, the decoder fails to decode LDRH_POST/LDRSB_POST/LDRSH_POST
> - // properly.
> - if (slice(insn, 27, 25) == 0 && slice(insn, 20, 20) == 1) {
> - unsigned PW = slice(insn, 24, 24) << 1 | slice(insn, 21, 21);
> - switch (slice(insn, 7, 4)) {
> - case 11:
> - switch (PW) {
> - case 2: // Offset
> - return ARM::LDRH;
> - case 3: // Pre-indexed
> - return ARM::LDRH_PRE;
> - case 0: // Post-indexed
> - return ARM::LDRH_POST;
> - default:
> - break; // fallthrough
> - }
> - break;
> - case 13:
> - switch (PW) {
> - case 2: // Offset
> - return ARM::LDRSB;
> - case 3: // Pre-indexed
> - return ARM::LDRSB_PRE;
> - case 0: // Post-indexed
> - return ARM::LDRSB_POST;
> - default:
> - break; // fallthrough
> - }
> - break;
> - case 15:
> - switch (PW) {
> - case 2: // Offset
> - return ARM::LDRSH;
> - case 3: // Pre-indexed
> - return ARM::LDRSH_PRE;
> - case 0: // Post-indexed
> - return ARM::LDRSH_POST;
> - default:
> - break; // fallthrough
> - }
> - break;
> - default:
> - break; // fallthrough
> + MI.clear();
> +
> + return false;
> +}
> +
> +namespace llvm {
> +extern MCInstrDesc ARMInsts[];
> +}
> +
> +// Thumb1 instructions don't have explicit S bits. Rather, they
> +// implicitly set CPSR. Since it's not represented in the encoding, the
> +// auto-generated decoder won't inject the CPSR operand. We need to fix
> +// that as a post-pass.
> +static void AddThumb1SBit(MCInst &MI, bool InITBlock) {
> + const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
> + MCInst::iterator I = MI.begin();
> + for (unsigned i = 0; i < MI.size(); ++i, ++I) {
> + if (OpInfo[i].isOptionalDef() && OpInfo[i].RegClass == ARM::CCRRegClassID) {
> + MI.insert(I, MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR));
> + return;
> }
> }
>
> -AutoGenedDecoder:
> - // Calling the auto-generated decoder function.
> - return decodeInstruction(insn);
> + if (OpInfo[MI.size()].isOptionalDef() &&
> + OpInfo[MI.size()].RegClass == ARM::CCRRegClassID)
> + MI.insert(MI.end(), MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR));
> }
>
> -// Helper function for special case handling of LDR (literal) and friends.
> -// See, for example, A6.3.7 Load word: Table A6-18 Load word.
> -// See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode
> -// before returning it.
> -static unsigned T2Morph2LoadLiteral(unsigned Opcode) {
> - switch (Opcode) {
> - default:
> - return Opcode; // Return unmorphed opcode.
> -
> - case ARM::t2LDR_POST: case ARM::t2LDR_PRE:
> - case ARM::t2LDRi12: case ARM::t2LDRi8:
> - case ARM::t2LDRs: case ARM::t2LDRT:
> - return ARM::t2LDRpci;
> -
> - case ARM::t2LDRB_POST: case ARM::t2LDRB_PRE:
> - case ARM::t2LDRBi12: case ARM::t2LDRBi8:
> - case ARM::t2LDRBs: case ARM::t2LDRBT:
> - return ARM::t2LDRBpci;
> -
> - case ARM::t2LDRH_POST: case ARM::t2LDRH_PRE:
> - case ARM::t2LDRHi12: case ARM::t2LDRHi8:
> - case ARM::t2LDRHs: case ARM::t2LDRHT:
> - return ARM::t2LDRHpci;
> -
> - case ARM::t2LDRSB_POST: case ARM::t2LDRSB_PRE:
> - case ARM::t2LDRSBi12: case ARM::t2LDRSBi8:
> - case ARM::t2LDRSBs: case ARM::t2LDRSBT:
> - return ARM::t2LDRSBpci;
> -
> - case ARM::t2LDRSH_POST: case ARM::t2LDRSH_PRE:
> - case ARM::t2LDRSHi12: case ARM::t2LDRSHi8:
> - case ARM::t2LDRSHs: case ARM::t2LDRSHT:
> - return ARM::t2LDRSHpci;
> - }
> -}
> -
> -// Helper function for special case handling of PLD (literal) and friends.
> -// See A8.6.117 T1 & T2 and friends for why we morphed the opcode
> -// before returning it.
> -static unsigned T2Morph2PLDLiteral(unsigned Opcode) {
> - switch (Opcode) {
> - default:
> - return Opcode; // Return unmorphed opcode.
> -
> - case ARM::t2PLDi8: case ARM::t2PLDs:
> - case ARM::t2PLDWi12: case ARM::t2PLDWi8:
> - case ARM::t2PLDWs:
> - return ARM::t2PLDi12;
> -
> - case ARM::t2PLIi8: case ARM::t2PLIs:
> - return ARM::t2PLIi12;
> - }
> -}
> -
> -/// decodeThumbSideEffect is a decorator function which can potentially twiddle
> -/// the instruction or morph the returned opcode under Thumb2.
> -///
> -/// First it checks whether the insn is a NEON or VFP instr; if true, bit
> -/// twiddling could be performed on insn to turn it into an ARM NEON/VFP
> -/// equivalent instruction and decodeInstruction is called with the transformed
> -/// insn.
> -///
> -/// Next, there is special handling for Load byte/halfword/word instruction by
> -/// checking whether Rn=0b1111 and call T2Morph2LoadLiteral() on the decoded
> -/// Thumb2 instruction. See comments below for further details.
> -///
> -/// Finally, one last check is made to see whether the insn is a NEON/VFP and
> -/// decodeInstruction(insn) is invoked on the original insn.
> -///
> -/// Otherwise, decodeThumbInstruction is called with the original insn.
> -static unsigned decodeThumbSideEffect(bool IsThumb2, unsigned &insn) {
> - if (IsThumb2) {
> - uint16_t op1 = slice(insn, 28, 27);
> - uint16_t op2 = slice(insn, 26, 20);
> -
> - // A6.3 32-bit Thumb instruction encoding
> - // Table A6-9 32-bit Thumb instruction encoding
> -
> - // The coprocessor instructions of interest are transformed to their ARM
> - // equivalents.
> -
> - // --------- Transform Begin Marker ---------
> - if ((op1 == 1 || op1 == 3) && slice(op2, 6, 4) == 7) {
> - // A7.4 Advanced SIMD data-processing instructions
> - // U bit of Thumb corresponds to Inst{24} of ARM.
> - uint16_t U = slice(op1, 1, 1);
> -
> - // Inst{28-24} of ARM = {1,0,0,1,U};
> - uint16_t bits28_24 = 9 << 1 | U;
> - DEBUG(showBitVector(errs(), insn));
> - setSlice(insn, 28, 24, bits28_24);
> - return decodeInstruction(insn);
> - }
> -
> - if (op1 == 3 && slice(op2, 6, 4) == 1 && slice(op2, 0, 0) == 0) {
> - // A7.7 Advanced SIMD element or structure load/store instructions
> - // Inst{27-24} of Thumb = 0b1001
> - // Inst{27-24} of ARM = 0b0100
> - DEBUG(showBitVector(errs(), insn));
> - setSlice(insn, 27, 24, 4);
> - return decodeInstruction(insn);
> - }
> - // --------- Transform End Marker ---------
> -
> - unsigned unmorphed = decodeThumbInstruction(insn);
> -
> - // See, for example, A6.3.7 Load word: Table A6-18 Load word.
> - // See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode
> - // before returning it to our caller.
> - if (op1 == 3 && slice(op2, 6, 5) == 0 && slice(op2, 0, 0) == 1
> - && slice(insn, 19, 16) == 15) {
> - unsigned morphed = T2Morph2LoadLiteral(unmorphed);
> - if (morphed != unmorphed)
> - return morphed;
> - }
> -
> - // See, for example, A8.6.117 PLD,PLDW (immediate) T1 & T2, and friends for
> - // why we morphed the opcode before returning it to our caller.
> - if (slice(insn, 31, 25) == 0x7C && slice(insn, 15, 12) == 0xF
> - && slice(insn, 22, 22) == 0 && slice(insn, 20, 20) == 1
> - && slice(insn, 19, 16) == 15) {
> - unsigned morphed = T2Morph2PLDLiteral(unmorphed);
> - if (morphed != unmorphed)
> - return morphed;
> - }
> -
> - // One last check for NEON/VFP instructions.
> - if ((op1 == 1 || op1 == 3) && slice(op2, 6, 6) == 1)
> - return decodeInstruction(insn);
> +// Most Thumb instructions don't have explicit predicates in the
> +// encoding, but rather get their predicates from IT context. We need
> +// to fix up the predicate operands using this context information as a
> +// post-pass.
> +void ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
> + // A few instructions actually have predicates encoded in them. Don't
> + // try to overwrite it if we're seeing one of those.
> + switch (MI.getOpcode()) {
> + case ARM::tBcc:
> + case ARM::t2Bcc:
> + return;
> + default:
> + break;
> + }
>
> - // Fall through.
> + // If we're in an IT block, base the predicate on that. Otherwise,
> + // assume a predicate of AL.
> + unsigned CC;
> + if (ITBlock.size()) {
> + CC = ITBlock.back();
> + ITBlock.pop_back();
> + } else
> + CC = ARMCC::AL;
> +
> + const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
> + MCInst::iterator I = MI.begin();
> + for (unsigned i = 0; i < MI.size(); ++i, ++I) {
> + if (OpInfo[i].isPredicate()) {
> + I = MI.insert(I, MCOperand::CreateImm(CC));
> + ++I;
> + if (CC == ARMCC::AL)
> + MI.insert(I, MCOperand::CreateReg(0));
> + else
> + MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
> + return;
> + }
> }
>
> - return decodeThumbInstruction(insn);
> + MI.insert(MI.end(), MCOperand::CreateImm(CC));
> + if (CC == ARMCC::AL)
> + MI.insert(MI.end(), MCOperand::CreateReg(0));
> + else
> + MI.insert(MI.end(), MCOperand::CreateReg(ARM::CPSR));
> }
>
> -//
> -// Public interface for the disassembler
> -//
> +// Thumb VFP instructions are a special case. Because we share their
> +// encodings between ARM and Thumb modes, and they are predicable in ARM
> +// mode, the auto-generated decoder will give them an (incorrect)
> +// predicate operand. We need to rewrite these operands based on the IT
> +// context as a post-pass.
> +void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst &MI) const {
> + unsigned CC;
> + if (ITBlock.size()) {
> + CC = ITBlock.back();
> + ITBlock.pop_back();
> + } else
> + CC = ARMCC::AL;
> +
> + const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
> + MCInst::iterator I = MI.begin();
> + for (unsigned i = 0; i < MI.size(); ++i, ++I) {
> + if (OpInfo[i].isPredicate() ) {
> + I->setImm(CC);
> + ++I;
> + if (CC == ARMCC::AL)
> + I->setReg(0);
> + else
> + I->setReg(ARM::CPSR);
> + return;
> + }
> + }
> +}
>
> -bool ARMDisassembler::getInstruction(MCInst &MI,
> - uint64_t &Size,
> - const MemoryObject &Region,
> - uint64_t Address,
> - raw_ostream &os) const {
> - // The machine instruction.
> - uint32_t insn;
> +
> +bool ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
> + const MemoryObject &Region,
> + uint64_t Address,raw_ostream &os) const {
> uint8_t bytes[4];
>
> + // We want to read exactly 2 bytes of data.
> + if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1)
> + return false;
> +
> + uint16_t insn16 = (bytes[1] << 8) | bytes[0];
> + bool result = decodeThumbInstruction16(MI, insn16, Address, this);
> + if (result) {
> + Size = 2;
> + bool InITBlock = ITBlock.size();
> + AddThumbPredicate(MI);
> + AddThumb1SBit(MI, InITBlock);
> + return true;
> + }
> +
> + MI.clear();
> + result = decodeThumb2Instruction16(MI, insn16, Address, this);
> + if (result) {
> + Size = 2;
> + AddThumbPredicate(MI);
> +
> + // If we find an IT instruction, we need to parse its condition
> + // code and mask operands so that we can apply them correctly
> + // to the subsequent instructions.
> + if (MI.getOpcode() == ARM::t2IT) {
> + unsigned firstcond = MI.getOperand(0).getImm();
> + uint32_t mask = MI.getOperand(1).getImm();
> + unsigned zeros = CountTrailingZeros_32(mask);
> + mask >>= zeros+1;
> +
> + for (unsigned i = 0; i < 4 - (zeros+1); ++i) {
> + if (firstcond ^ (mask & 1))
> + ITBlock.push_back(firstcond ^ 1);
> + else
> + ITBlock.push_back(firstcond);
> + mask >>= 1;
> + }
> + ITBlock.push_back(firstcond);
> + }
> +
> + return true;
> + }
> +
> // We want to read exactly 4 bytes of data.
> if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1)
> return false;
>
> - // Encoded as a small-endian 32-bit word in the stream.
> - insn = (bytes[3] << 24) |
> - (bytes[2] << 16) |
> - (bytes[1] << 8) |
> - (bytes[0] << 0);
> + uint32_t insn32 = (bytes[3] << 8) |
> + (bytes[2] << 0) |
> + (bytes[1] << 24) |
> + (bytes[0] << 16);
> + MI.clear();
> + result = decodeThumbInstruction32(MI, insn32, Address, this);
> + if (result) {
> + Size = 4;
> + bool InITBlock = ITBlock.size();
> + AddThumbPredicate(MI);
> + AddThumb1SBit(MI, InITBlock);
> + return true;
> + }
> +
> + MI.clear();
> + result = decodeThumb2Instruction32(MI, insn32, Address, this);
> + if (result) {
> + Size = 4;
> + AddThumbPredicate(MI);
> + return true;
> + }
> +
> + MI.clear();
> + result = decodeVFPInstruction32(MI, insn32, Address, this);
> + if (result) {
> + Size = 4;
> + UpdateThumbVFPPredicate(MI);
> + return true;
> + }
> +
> + MI.clear();
> + result = decodeCommonInstruction32(MI, insn32, Address, this);
> + if (result) {
> + Size = 4;
> + AddThumbPredicate(MI);
> + return true;
> + }
> +
> + return false;
> +}
>
> - unsigned Opcode = decodeARMInstruction(insn);
> - ARMFormat Format = ARMFormats[Opcode];
> - Size = 4;
>
> - DEBUG({
> - errs() << "\nOpcode=" << Opcode << " Name=" <<ARMUtils::OpcodeName(Opcode)
> - << " Format=" << stringForARMFormat(Format) << '(' << (int)Format
> - << ")\n";
> - showBitVector(errs(), insn);
> - });
> +extern "C" void LLVMInitializeARMDisassembler() {
> + TargetRegistry::RegisterMCDisassembler(TheARMTarget,
> + createARMDisassembler);
> + TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
> + createThumbDisassembler);
> +}
>
> - OwningPtr<ARMBasicMCBuilder> Builder(CreateMCBuilder(Opcode, Format));
> - if (!Builder)
> +static const unsigned GPRDecoderTable[] = {
> + ARM::R0, ARM::R1, ARM::R2, ARM::R3,
> + ARM::R4, ARM::R5, ARM::R6, ARM::R7,
> + ARM::R8, ARM::R9, ARM::R10, ARM::R11,
> + ARM::R12, ARM::SP, ARM::LR, ARM::PC
> +};
> +
> +static bool DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder) {
> + if (RegNo > 15)
> return false;
>
> - Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(),
> - getDisInfoBlock(), getMCContext(),
> - Address);
> + unsigned Register = GPRDecoderTable[RegNo];
> + Inst.addOperand(MCOperand::CreateReg(Register));
> + return true;
> +}
>
> - if (!Builder->Build(MI, insn))
> +static bool DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder) {
> + if (RegNo > 7)
> return false;
> + return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
> +}
> +
> +static bool DecodetcGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder) {
> + unsigned Register = 0;
> + switch (RegNo) {
> + case 0:
> + Register = ARM::R0;
> + break;
> + case 1:
> + Register = ARM::R1;
> + break;
> + case 2:
> + Register = ARM::R2;
> + break;
> + case 3:
> + Register = ARM::R3;
> + break;
> + case 9:
> + Register = ARM::R9;
> + break;
> + case 12:
> + Register = ARM::R12;
> + break;
> + default:
> + return false;
> + }
>
> + Inst.addOperand(MCOperand::CreateReg(Register));
> return true;
> }
>
> -bool ThumbDisassembler::getInstruction(MCInst &MI,
> - uint64_t &Size,
> - const MemoryObject &Region,
> - uint64_t Address,
> - raw_ostream &os) const {
> - // The Thumb instruction stream is a sequence of halfwords.
> -
> - // This represents the first halfword as well as the machine instruction
> - // passed to decodeThumbInstruction(). For 16-bit Thumb instruction, the top
> - // halfword of insn is 0x00 0x00; otherwise, the first halfword is moved to
> - // the top half followed by the second halfword.
> - unsigned insn = 0;
> - // Possible second halfword.
> - uint16_t insn1 = 0;
> -
> - // A6.1 Thumb instruction set encoding
> - //
> - // If bits [15:11] of the halfword being decoded take any of the following
> - // values, the halfword is the first halfword of a 32-bit instruction:
> - // o 0b11101
> - // o 0b11110
> - // o 0b11111.
> - //
> - // Otherwise, the halfword is a 16-bit instruction.
> +static bool DecoderGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder) {
> + if (RegNo == 13 || RegNo == 15) return false;
> + return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
> +}
>
> - // Read 2 bytes of data first.
> - uint8_t bytes[2];
> - if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1)
> +static const unsigned SPRDecoderTable[] = {
> + ARM::S0, ARM::S1, ARM::S2, ARM::S3,
> + ARM::S4, ARM::S5, ARM::S6, ARM::S7,
> + ARM::S8, ARM::S9, ARM::S10, ARM::S11,
> + ARM::S12, ARM::S13, ARM::S14, ARM::S15,
> + ARM::S16, ARM::S17, ARM::S18, ARM::S19,
> + ARM::S20, ARM::S21, ARM::S22, ARM::S23,
> + ARM::S24, ARM::S25, ARM::S26, ARM::S27,
> + ARM::S28, ARM::S29, ARM::S30, ARM::S31
> +};
> +
> +static bool DecodeSPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder) {
> + if (RegNo > 31)
> return false;
>
> - // Encoded as a small-endian 16-bit halfword in the stream.
> - insn = (bytes[1] << 8) | bytes[0];
> - unsigned bits15_11 = slice(insn, 15, 11);
> - bool IsThumb2 = false;
> -
> - // 32-bit instructions if the bits [15:11] of the halfword matches
> - // { 0b11101 /* 0x1D */, 0b11110 /* 0x1E */, ob11111 /* 0x1F */ }.
> - if (bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F) {
> - IsThumb2 = true;
> - if (Region.readBytes(Address + 2, 2, (uint8_t*)bytes, NULL) == -1)
> - return false;
> - // Encoded as a small-endian 16-bit halfword in the stream.
> - insn1 = (bytes[1] << 8) | bytes[0];
> - insn = (insn << 16 | insn1);
> - }
> + unsigned Register = SPRDecoderTable[RegNo];
> + Inst.addOperand(MCOperand::CreateReg(Register));
> + return true;
> +}
>
> - // The insn could potentially be bit-twiddled in order to be decoded as an ARM
> - // NEON/VFP opcode. In such case, the modified insn is later disassembled as
> - // an ARM NEON/VFP instruction.
> - //
> - // This is a short term solution for lack of encoding bits specified for the
> - // Thumb2 NEON/VFP instructions. The long term solution could be adding some
> - // infrastructure to have each instruction support more than one encodings.
> - // Which encoding is used would be based on which subtarget the compiler/
> - // disassembler is working with at the time. This would allow the sharing of
> - // the NEON patterns between ARM and Thumb2, as well as potential greater
> - // sharing between the regular ARM instructions and the 32-bit wide Thumb2
> - // instructions as well.
> - unsigned Opcode = decodeThumbSideEffect(IsThumb2, insn);
> +static const unsigned DPRDecoderTable[] = {
> + ARM::D0, ARM::D1, ARM::D2, ARM::D3,
> + ARM::D4, ARM::D5, ARM::D6, ARM::D7,
> + ARM::D8, ARM::D9, ARM::D10, ARM::D11,
> + ARM::D12, ARM::D13, ARM::D14, ARM::D15,
> + ARM::D16, ARM::D17, ARM::D18, ARM::D19,
> + ARM::D20, ARM::D21, ARM::D22, ARM::D23,
> + ARM::D24, ARM::D25, ARM::D26, ARM::D27,
> + ARM::D28, ARM::D29, ARM::D30, ARM::D31
> +};
> +
> +static bool DecodeDPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder) {
> + if (RegNo > 31)
> + return false;
>
> - ARMFormat Format = ARMFormats[Opcode];
> - Size = IsThumb2 ? 4 : 2;
> + unsigned Register = DPRDecoderTable[RegNo];
> + Inst.addOperand(MCOperand::CreateReg(Register));
> + return true;
> +}
>
> - DEBUG({
> - errs() << "Opcode=" << Opcode << " Name=" << ARMUtils::OpcodeName(Opcode)
> - << " Format=" << stringForARMFormat(Format) << '(' << (int)Format
> - << ")\n";
> - showBitVector(errs(), insn);
> - });
> +static bool DecodeDPR_8RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder) {
> + if (RegNo > 7)
> + return false;
> + return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
> +}
>
> - OwningPtr<ARMBasicMCBuilder> Builder(CreateMCBuilder(Opcode, Format));
> - if (!Builder)
> +static bool DecodeDPR_VFP2RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder) {
> + if (RegNo > 15)
> return false;
> + return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
> +}
>
> - Builder->SetSession(const_cast<Session *>(&SO));
> +static const unsigned QPRDecoderTable[] = {
> + ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3,
> + ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7,
> + ARM::Q8, ARM::Q9, ARM::Q10, ARM::Q11,
> + ARM::Q12, ARM::Q13, ARM::Q14, ARM::Q15
> +};
>
> - Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(),
> - getDisInfoBlock(), getMCContext(),
> - Address);
>
> - if (!Builder->Build(MI, insn))
> +static bool DecodeQPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
> + uint64_t Address, const void *Decoder) {
> + if (RegNo > 31)
> return false;
> + RegNo >>= 1;
>
> + unsigned Register = QPRDecoderTable[RegNo];
> + Inst.addOperand(MCOperand::CreateReg(Register));
> return true;
> }
>
> -// A8.6.50
> -// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
> -static unsigned short CountITSize(unsigned ITMask) {
> - // First count the trailing zeros of the IT mask.
> - unsigned TZ = CountTrailingZeros_32(ITMask);
> - if (TZ > 3) {
> - DEBUG(errs() << "Encoding error: IT Mask '0000'");
> - return 0;
> - }
> - return (4 - TZ);
> +static bool DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + if (Val == 0xF) return false;
> + Inst.addOperand(MCOperand::CreateImm(Val));
> + if (Val == ARMCC::AL) {
> + Inst.addOperand(MCOperand::CreateReg(0));
> + } else
> + Inst.addOperand(MCOperand::CreateReg(ARM::CPSR));
> + return true;
> }
>
> -/// Init ITState. Note that at least one bit is always 1 in mask.
> -bool Session::InitIT(unsigned short bits7_0) {
> - ITCounter = CountITSize(slice(bits7_0, 3, 0));
> - if (ITCounter == 0)
> - return false;
> +static bool DecodeCCOutOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + if (Val)
> + Inst.addOperand(MCOperand::CreateReg(ARM::CPSR));
> + else
> + Inst.addOperand(MCOperand::CreateReg(0));
> + return true;
> +}
>
> - // A8.6.50 IT
> - unsigned short FirstCond = slice(bits7_0, 7, 4);
> - if (FirstCond == 0xF) {
> - DEBUG(errs() << "Encoding error: IT FirstCond '1111'");
> - return false;
> +static bool DecodeSOImmOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + uint32_t imm = Val & 0xFF;
> + uint32_t rot = (Val & 0xF00) >> 7;
> + uint32_t rot_imm = (imm >> rot) | (imm << (32-rot));
> + Inst.addOperand(MCOperand::CreateImm(rot_imm));
> + return true;
> +}
> +
> +static bool DecodeBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Val <<= 2;
> + Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(Val)));
> + return true;
> +}
> +
> +static bool DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> +
> + unsigned Rm = fieldFromInstruction32(Val, 0, 4);
> + unsigned type = fieldFromInstruction32(Val, 5, 2);
> + unsigned imm = fieldFromInstruction32(Val, 7, 5);
> +
> + // Register-immediate
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> +
> + ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
> + switch (type) {
> + case 0:
> + Shift = ARM_AM::lsl;
> + break;
> + case 1:
> + Shift = ARM_AM::lsr;
> + break;
> + case 2:
> + Shift = ARM_AM::asr;
> + break;
> + case 3:
> + Shift = ARM_AM::ror;
> + break;
> }
> - if (FirstCond == 0xE && ITCounter != 1) {
> - DEBUG(errs() << "Encoding error: IT FirstCond '1110' && Mask != '1000'");
> - return false;
> +
> + if (Shift == ARM_AM::ror && imm == 0)
> + Shift = ARM_AM::rrx;
> +
> + unsigned Op = Shift | (imm << 3);
> + Inst.addOperand(MCOperand::CreateImm(Op));
> +
> + return true;
> +}
> +
> +static bool DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> +
> + unsigned Rm = fieldFromInstruction32(Val, 0, 4);
> + unsigned type = fieldFromInstruction32(Val, 5, 2);
> + unsigned Rs = fieldFromInstruction32(Val, 8, 4);
> +
> + // Register-register
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> + DecodeGPRRegisterClass(Inst, Rs, Address, Decoder);
> +
> + ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
> + switch (type) {
> + case 0:
> + Shift = ARM_AM::lsl;
> + break;
> + case 1:
> + Shift = ARM_AM::lsr;
> + break;
> + case 2:
> + Shift = ARM_AM::asr;
> + break;
> + case 3:
> + Shift = ARM_AM::ror;
> + break;
> }
>
> - ITState = bits7_0;
> + Inst.addOperand(MCOperand::CreateImm(Shift));
>
> return true;
> }
>
> -/// Update ITState if necessary.
> -void Session::UpdateIT() {
> - assert(ITCounter);
> - --ITCounter;
> - if (ITCounter == 0)
> - ITState = 0;
> - else {
> - unsigned short NewITState4_0 = slice(ITState, 4, 0) << 1;
> - setSlice(ITState, 4, 0, NewITState4_0);
> +static bool DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + for (unsigned i = 0; i < 16; ++i) {
> + if (Val & (1 << i))
> + DecodeGPRRegisterClass(Inst, i, Address, Decoder);
> }
> +
> + return true;
> }
>
> -static MCDisassembler *createARMDisassembler(const Target &T) {
> - return new ARMDisassembler;
> +static bool DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Vd = fieldFromInstruction32(Val, 8, 4);
> + unsigned regs = Val & 0xFF;
> +
> + DecodeSPRRegisterClass(Inst, Vd, Address, Decoder);
> + for (unsigned i = 0; i < (regs - 1); ++i)
> + DecodeSPRRegisterClass(Inst, ++Vd, Address, Decoder);
> +
> + return true;
> }
>
> -static MCDisassembler *createThumbDisassembler(const Target &T) {
> - return new ThumbDisassembler;
> +static bool DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Vd = fieldFromInstruction32(Val, 8, 4);
> + unsigned regs = (Val & 0xFF) / 2;
> +
> + DecodeDPRRegisterClass(Inst, Vd, Address, Decoder);
> + for (unsigned i = 0; i < (regs - 1); ++i)
> + DecodeDPRRegisterClass(Inst, ++Vd, Address, Decoder);
> +
> + return true;
> }
>
> -extern "C" void LLVMInitializeARMDisassembler() {
> - // Register the disassembler.
> - TargetRegistry::RegisterMCDisassembler(TheARMTarget,
> - createARMDisassembler);
> - TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
> - createThumbDisassembler);
> +static bool DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned msb = fieldFromInstruction32(Val, 5, 5);
> + unsigned lsb = fieldFromInstruction32(Val, 0, 5);
> + uint32_t msb_mask = (1 << (msb+1)) - 1;
> + uint32_t lsb_mask = (1 << lsb) - 1;
> + Inst.addOperand(MCOperand::CreateImm(~(msb_mask ^ lsb_mask)));
> + return true;
> }
>
> -EDInstInfo *ARMDisassembler::getEDInfo() const {
> - return instInfoARM;
> +static bool DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned pred = fieldFromInstruction32(Insn, 28, 4);
> + unsigned CRd = fieldFromInstruction32(Insn, 12, 4);
> + unsigned coproc = fieldFromInstruction32(Insn, 8, 4);
> + unsigned imm = fieldFromInstruction32(Insn, 0, 8);
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + unsigned U = fieldFromInstruction32(Insn, 23, 1);
> +
> + switch (Inst.getOpcode()) {
> + case ARM::LDC_OFFSET:
> + case ARM::LDC_PRE:
> + case ARM::LDC_POST:
> + case ARM::LDC_OPTION:
> + case ARM::LDCL_OFFSET:
> + case ARM::LDCL_PRE:
> + case ARM::LDCL_POST:
> + case ARM::LDCL_OPTION:
> + case ARM::STC_OFFSET:
> + case ARM::STC_PRE:
> + case ARM::STC_POST:
> + case ARM::STC_OPTION:
> + case ARM::STCL_OFFSET:
> + case ARM::STCL_PRE:
> + case ARM::STCL_POST:
> + case ARM::STCL_OPTION:
> + if (coproc == 0xA || coproc == 0xB)
> + return false;
> + break;
> + default:
> + break;
> + }
> +
> + Inst.addOperand(MCOperand::CreateImm(coproc));
> + Inst.addOperand(MCOperand::CreateImm(CRd));
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + switch (Inst.getOpcode()) {
> + case ARM::LDC_OPTION:
> + case ARM::LDCL_OPTION:
> + case ARM::LDC2_OPTION:
> + case ARM::LDC2L_OPTION:
> + case ARM::STC_OPTION:
> + case ARM::STCL_OPTION:
> + case ARM::STC2_OPTION:
> + case ARM::STC2L_OPTION:
> + case ARM::LDCL_POST:
> + case ARM::STCL_POST:
> + break;
> + default:
> + Inst.addOperand(MCOperand::CreateReg(0));
> + break;
> + }
> +
> + unsigned P = fieldFromInstruction32(Insn, 24, 1);
> + unsigned W = fieldFromInstruction32(Insn, 21, 1);
> +
> + bool writeback = (P == 0) || (W == 1);
> + unsigned idx_mode = 0;
> + if (P && writeback)
> + idx_mode = ARMII::IndexModePre;
> + else if (!P && writeback)
> + idx_mode = ARMII::IndexModePost;
> +
> + switch (Inst.getOpcode()) {
> + case ARM::LDCL_POST:
> + case ARM::STCL_POST:
> + imm |= U << 8;
> + case ARM::LDC_OPTION:
> + case ARM::LDCL_OPTION:
> + case ARM::LDC2_OPTION:
> + case ARM::LDC2L_OPTION:
> + case ARM::STC_OPTION:
> + case ARM::STCL_OPTION:
> + case ARM::STC2_OPTION:
> + case ARM::STC2L_OPTION:
> + Inst.addOperand(MCOperand::CreateImm(imm));
> + break;
> + default:
> + if (U)
> + Inst.addOperand(MCOperand::CreateImm(
> + ARM_AM::getAM2Opc(ARM_AM::add, imm, ARM_AM::lsl, idx_mode)));
> + else
> + Inst.addOperand(MCOperand::CreateImm(
> + ARM_AM::getAM2Opc(ARM_AM::sub, imm, ARM_AM::lsl, idx_mode)));
> + break;
> + }
> +
> + switch (Inst.getOpcode()) {
> + case ARM::LDC_OFFSET:
> + case ARM::LDC_PRE:
> + case ARM::LDC_POST:
> + case ARM::LDC_OPTION:
> + case ARM::LDCL_OFFSET:
> + case ARM::LDCL_PRE:
> + case ARM::LDCL_POST:
> + case ARM::LDCL_OPTION:
> + case ARM::STC_OFFSET:
> + case ARM::STC_PRE:
> + case ARM::STC_POST:
> + case ARM::STC_OPTION:
> + case ARM::STCL_OFFSET:
> + case ARM::STCL_PRE:
> + case ARM::STCL_POST:
> + case ARM::STCL_OPTION:
> + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
> + break;
> + default:
> + break;
> + }
> +
> + return true;
> }
>
> -EDInstInfo *ThumbDisassembler::getEDInfo() const {
> - return instInfoARM;
> +static bool DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> + unsigned imm = fieldFromInstruction32(Insn, 0, 12);
> + unsigned pred = fieldFromInstruction32(Insn, 28, 4);
> + unsigned reg = fieldFromInstruction32(Insn, 25, 1);
> + unsigned P = fieldFromInstruction32(Insn, 24, 1);
> + unsigned W = fieldFromInstruction32(Insn, 21, 1);
> +
> + // On stores, the writeback operand precedes Rt.
> + switch (Inst.getOpcode()) {
> + case ARM::STR_POST_IMM:
> + case ARM::STR_POST_REG:
> + case ARM::STRTr:
> + case ARM::STRTi:
> + case ARM::STRBTr:
> + case ARM::STRBTi:
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> + DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
> +
> + // On loads, the writeback operand comes after Rt.
> + switch (Inst.getOpcode()) {
> + case ARM::LDR_POST_IMM:
> + case ARM::LDR_POST_REG:
> + case ARM::LDR_PRE:
> + case ARM::LDRBT_POST_REG:
> + case ARM::LDRBT_POST_IMM:
> + case ARM::LDRTr:
> + case ARM::LDRTi:
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> +
> + ARM_AM::AddrOpc Op = ARM_AM::add;
> + if (!fieldFromInstruction32(Insn, 23, 1))
> + Op = ARM_AM::sub;
> +
> + bool writeback = (P == 0) || (W == 1);
> + unsigned idx_mode = 0;
> + if (P && writeback)
> + idx_mode = ARMII::IndexModePre;
> + else if (!P && writeback)
> + idx_mode = ARMII::IndexModePost;
> +
> + if (reg) {
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> + ARM_AM::ShiftOpc Opc = ARM_AM::lsl;
> + switch( fieldFromInstruction32(Insn, 5, 2)) {
> + case 0:
> + Opc = ARM_AM::lsl;
> + break;
> + case 1:
> + Opc = ARM_AM::lsr;
> + break;
> + case 2:
> + Opc = ARM_AM::asr;
> + break;
> + case 3:
> + Opc = ARM_AM::ror;
> + break;
> + default:
> + return false;
> + }
> + unsigned amt = fieldFromInstruction32(Insn, 7, 5);
> + unsigned imm = ARM_AM::getAM2Opc(Op, amt, Opc, idx_mode);
> +
> + Inst.addOperand(MCOperand::CreateImm(imm));
> + } else {
> + Inst.addOperand(MCOperand::CreateReg(0));
> + unsigned tmp = ARM_AM::getAM2Opc(Op, imm, ARM_AM::lsl, idx_mode);
> + Inst.addOperand(MCOperand::CreateImm(tmp));
> + }
> +
> + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
> +
> + return true;
> +}
> +
> +static bool DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Val, 13, 4);
> + unsigned Rm = fieldFromInstruction32(Val, 0, 4);
> + unsigned type = fieldFromInstruction32(Val, 5, 2);
> + unsigned imm = fieldFromInstruction32(Val, 7, 5);
> + unsigned U = fieldFromInstruction32(Val, 12, 1);
> +
> + ARM_AM::ShiftOpc ShOp;
> + switch (type) {
> + case 0:
> + ShOp = ARM_AM::lsl;
> + break;
> + case 1:
> + ShOp = ARM_AM::lsr;
> + break;
> + case 2:
> + ShOp = ARM_AM::asr;
> + break;
> + case 3:
> + ShOp = ARM_AM::ror;
> + break;
> + }
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> + unsigned shift;
> + if (U)
> + shift = ARM_AM::getAM2Opc(ARM_AM::add, imm, ShOp);
> + else
> + shift = ARM_AM::getAM2Opc(ARM_AM::sub, imm, ShOp);
> + Inst.addOperand(MCOperand::CreateImm(shift));
> +
> + return true;
> +}
> +
> +static bool DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> + unsigned type = fieldFromInstruction32(Insn, 22, 1);
> + unsigned imm = fieldFromInstruction32(Insn, 8, 4);
> + unsigned U = ((~fieldFromInstruction32(Insn, 23, 1)) & 1) << 8;
> + unsigned pred = fieldFromInstruction32(Insn, 28, 4);
> + unsigned W = fieldFromInstruction32(Insn, 21, 1);
> + unsigned P = fieldFromInstruction32(Insn, 24, 1);
> +
> + bool writeback = (W == 1) | (P == 0);
> + if (writeback) { // Writeback
> + if (P)
> + U |= ARMII::IndexModePre << 9;
> + else
> + U |= ARMII::IndexModePost << 9;
> +
> + // On stores, the writeback operand precedes Rt.
> + switch (Inst.getOpcode()) {
> + case ARM::STRD:
> + case ARM::STRD_PRE:
> + case ARM::STRD_POST:
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> + }
> +
> + DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
> + switch (Inst.getOpcode()) {
> + case ARM::STRD:
> + case ARM::STRD_PRE:
> + case ARM::STRD_POST:
> + case ARM::LDRD:
> + case ARM::LDRD_PRE:
> + case ARM::LDRD_POST:
> + DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> + if (writeback) {
> + // On loads, the writeback operand comes after Rt.
> + switch (Inst.getOpcode()) {
> + case ARM::LDRD:
> + case ARM::LDRD_PRE:
> + case ARM::LDRD_POST:
> + case ARM::LDRHTr:
> + case ARM::LDRSBTr:
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> + }
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> +
> + if (type) {
> + Inst.addOperand(MCOperand::CreateReg(0));
> + Inst.addOperand(MCOperand::CreateImm(U | (imm << 4) | Rm));
> + } else {
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(U));
> + }
> +
> + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
> +
> + return true;
> +}
> +
> +static bool DecodeRFEInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + unsigned mode = fieldFromInstruction32(Insn, 23, 2);
> +
> + switch (mode) {
> + case 0:
> + mode = ARM_AM::da;
> + break;
> + case 1:
> + mode = ARM_AM::ia;
> + break;
> + case 2:
> + mode = ARM_AM::db;
> + break;
> + case 3:
> + mode = ARM_AM::ib;
> + break;
> + }
> +
> + Inst.addOperand(MCOperand::CreateImm(mode));
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeMemMultipleWritebackInstruction(llvm::MCInst &Inst,
> + unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + unsigned pred = fieldFromInstruction32(Insn, 28, 4);
> + unsigned reglist = fieldFromInstruction32(Insn, 0, 16);
> +
> + if (pred == 0xF) {
> + switch (Inst.getOpcode()) {
> + case ARM::STMDA:
> + Inst.setOpcode(ARM::RFEDA);
> + break;
> + case ARM::STMDA_UPD:
> + Inst.setOpcode(ARM::RFEDA_UPD);
> + break;
> + case ARM::STMDB:
> + Inst.setOpcode(ARM::RFEDB);
> + break;
> + case ARM::STMDB_UPD:
> + Inst.setOpcode(ARM::RFEDB_UPD);
> + break;
> + case ARM::STMIA:
> + Inst.setOpcode(ARM::RFEIA);
> + break;
> + case ARM::STMIA_UPD:
> + Inst.setOpcode(ARM::RFEIA_UPD);
> + break;
> + case ARM::STMIB:
> + Inst.setOpcode(ARM::RFEIB);
> + break;
> + case ARM::STMIB_UPD:
> + Inst.setOpcode(ARM::RFEIB_UPD);
> + break;
> +
> + }
> + return DecodeRFEInstruction(Inst, Insn, Address, Decoder);
> + }
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); // Tied
> + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
> + DecodeRegListOperand(Inst, reglist, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeCPSInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned imod = fieldFromInstruction32(Insn, 18, 2);
> + unsigned M = fieldFromInstruction32(Insn, 17, 1);
> + unsigned iflags = fieldFromInstruction32(Insn, 6, 3);
> + unsigned mode = fieldFromInstruction32(Insn, 0, 5);
> +
> + if (M && mode && imod && iflags) {
> + Inst.setOpcode(ARM::CPS3p);
> + Inst.addOperand(MCOperand::CreateImm(imod));
> + Inst.addOperand(MCOperand::CreateImm(iflags));
> + Inst.addOperand(MCOperand::CreateImm(mode));
> + return true;
> + } else if (!mode && !M) {
> + Inst.setOpcode(ARM::CPS2p);
> + Inst.addOperand(MCOperand::CreateImm(imod));
> + Inst.addOperand(MCOperand::CreateImm(iflags));
> + return true;
> + } else if (!imod && !iflags && M) {
> + Inst.setOpcode(ARM::CPS1p);
> + Inst.addOperand(MCOperand::CreateImm(mode));
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static bool DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rd = fieldFromInstruction32(Insn, 16, 4);
> + unsigned Rn = fieldFromInstruction32(Insn, 0, 4);
> + unsigned Rm = fieldFromInstruction32(Insn, 8, 4);
> + unsigned Ra = fieldFromInstruction32(Insn, 12, 4);
> + unsigned pred = fieldFromInstruction32(Insn, 28, 4);
> +
> + if (pred == 0xF)
> + return DecodeCPSInstruction(Inst, Insn, Address, Decoder);
> +
> + DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> + DecodeGPRRegisterClass(Inst, Ra, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned add = fieldFromInstruction32(Val, 12, 1);
> + unsigned imm = fieldFromInstruction32(Val, 0, 12);
> + unsigned Rn = fieldFromInstruction32(Val, 13, 4);
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> +
> + if (!add) imm *= -1;
> + if (imm == 0 && !add) imm = INT32_MIN;
> + Inst.addOperand(MCOperand::CreateImm(imm));
> +
> + return true;
> +}
> +
> +static bool DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Val, 9, 4);
> + unsigned U = fieldFromInstruction32(Val, 8, 1);
> + unsigned imm = fieldFromInstruction32(Val, 0, 8);
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> +
> + if (U)
> + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add, imm)));
> + else
> + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub, imm)));
> +
> + return true;
> +}
> +
> +static bool DecodeAddrMode7Operand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + return DecodeGPRRegisterClass(Inst, Val, Address, Decoder);
> +}
> +
> +static bool DecodeBranchImmInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned pred = fieldFromInstruction32(Insn, 28, 4);
> + unsigned imm = fieldFromInstruction32(Insn, 0, 24) << 2;
> +
> + if (pred == 0xF) {
> + Inst.setOpcode(ARM::BLXi);
> + imm |= fieldFromInstruction32(Insn, 24, 1) << 1;
> + Inst.addOperand(MCOperand::CreateImm(imm));
> + return true;
> + }
> +
> + Inst.addOperand(MCOperand::CreateImm(imm));
> + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
> +
> + return true;
> +}
> +
> +
> +static bool DecodeVCVTImmOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateImm(64 - Val));
> + return true;
> +}
> +
> +static bool DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rm = fieldFromInstruction32(Val, 0, 4);
> + unsigned align = fieldFromInstruction32(Val, 4, 2);
> +
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> + if (!align)
> + Inst.addOperand(MCOperand::CreateImm(0));
> + else
> + Inst.addOperand(MCOperand::CreateImm(4 << align));
> +
> + return true;
> +}
> +
> +static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
> + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
> + unsigned wb = fieldFromInstruction32(Insn, 16, 4);
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + Rn |= fieldFromInstruction32(Insn, 4, 2) << 4;
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> +
> + // First output register
> + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
> +
> + // Second output register
> + switch (Inst.getOpcode()) {
> + case ARM::VLD1q8:
> + case ARM::VLD1q16:
> + case ARM::VLD1q32:
> + case ARM::VLD1q64:
> + case ARM::VLD1q8_UPD:
> + case ARM::VLD1q16_UPD:
> + case ARM::VLD1q32_UPD:
> + case ARM::VLD1q64_UPD:
> + case ARM::VLD1d8T:
> + case ARM::VLD1d16T:
> + case ARM::VLD1d32T:
> + case ARM::VLD1d64T:
> + case ARM::VLD1d8T_UPD:
> + case ARM::VLD1d16T_UPD:
> + case ARM::VLD1d32T_UPD:
> + case ARM::VLD1d64T_UPD:
> + case ARM::VLD1d8Q:
> + case ARM::VLD1d16Q:
> + case ARM::VLD1d32Q:
> + case ARM::VLD1d64Q:
> + case ARM::VLD1d8Q_UPD:
> + case ARM::VLD1d16Q_UPD:
> + case ARM::VLD1d32Q_UPD:
> + case ARM::VLD1d64Q_UPD:
> + case ARM::VLD2d8:
> + case ARM::VLD2d16:
> + case ARM::VLD2d32:
> + case ARM::VLD2d8_UPD:
> + case ARM::VLD2d16_UPD:
> + case ARM::VLD2d32_UPD:
> + case ARM::VLD2q8:
> + case ARM::VLD2q16:
> + case ARM::VLD2q32:
> + case ARM::VLD2q8_UPD:
> + case ARM::VLD2q16_UPD:
> + case ARM::VLD2q32_UPD:
> + case ARM::VLD3d8:
> + case ARM::VLD3d16:
> + case ARM::VLD3d32:
> + case ARM::VLD3d8_UPD:
> + case ARM::VLD3d16_UPD:
> + case ARM::VLD3d32_UPD:
> + case ARM::VLD4d8:
> + case ARM::VLD4d16:
> + case ARM::VLD4d32:
> + case ARM::VLD4d8_UPD:
> + case ARM::VLD4d16_UPD:
> + case ARM::VLD4d32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
> + break;
> + case ARM::VLD2b8:
> + case ARM::VLD2b16:
> + case ARM::VLD2b32:
> + case ARM::VLD2b8_UPD:
> + case ARM::VLD2b16_UPD:
> + case ARM::VLD2b32_UPD:
> + case ARM::VLD3q8:
> + case ARM::VLD3q16:
> + case ARM::VLD3q32:
> + case ARM::VLD3q8_UPD:
> + case ARM::VLD3q16_UPD:
> + case ARM::VLD3q32_UPD:
> + case ARM::VLD4q8:
> + case ARM::VLD4q16:
> + case ARM::VLD4q32:
> + case ARM::VLD4q8_UPD:
> + case ARM::VLD4q16_UPD:
> + case ARM::VLD4q32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
> + default:
> + break;
> + }
> +
> + // Third output register
> + switch(Inst.getOpcode()) {
> + case ARM::VLD1d8T:
> + case ARM::VLD1d16T:
> + case ARM::VLD1d32T:
> + case ARM::VLD1d64T:
> + case ARM::VLD1d8T_UPD:
> + case ARM::VLD1d16T_UPD:
> + case ARM::VLD1d32T_UPD:
> + case ARM::VLD1d64T_UPD:
> + case ARM::VLD1d8Q:
> + case ARM::VLD1d16Q:
> + case ARM::VLD1d32Q:
> + case ARM::VLD1d64Q:
> + case ARM::VLD1d8Q_UPD:
> + case ARM::VLD1d16Q_UPD:
> + case ARM::VLD1d32Q_UPD:
> + case ARM::VLD1d64Q_UPD:
> + case ARM::VLD2q8:
> + case ARM::VLD2q16:
> + case ARM::VLD2q32:
> + case ARM::VLD2q8_UPD:
> + case ARM::VLD2q16_UPD:
> + case ARM::VLD2q32_UPD:
> + case ARM::VLD3d8:
> + case ARM::VLD3d16:
> + case ARM::VLD3d32:
> + case ARM::VLD3d8_UPD:
> + case ARM::VLD3d16_UPD:
> + case ARM::VLD3d32_UPD:
> + case ARM::VLD4d8:
> + case ARM::VLD4d16:
> + case ARM::VLD4d32:
> + case ARM::VLD4d8_UPD:
> + case ARM::VLD4d16_UPD:
> + case ARM::VLD4d32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
> + break;
> + case ARM::VLD3q8:
> + case ARM::VLD3q16:
> + case ARM::VLD3q32:
> + case ARM::VLD3q8_UPD:
> + case ARM::VLD3q16_UPD:
> + case ARM::VLD3q32_UPD:
> + case ARM::VLD4q8:
> + case ARM::VLD4q16:
> + case ARM::VLD4q32:
> + case ARM::VLD4q8_UPD:
> + case ARM::VLD4q16_UPD:
> + case ARM::VLD4q32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> + // Fourth output register
> + switch (Inst.getOpcode()) {
> + case ARM::VLD1d8Q:
> + case ARM::VLD1d16Q:
> + case ARM::VLD1d32Q:
> + case ARM::VLD1d64Q:
> + case ARM::VLD1d8Q_UPD:
> + case ARM::VLD1d16Q_UPD:
> + case ARM::VLD1d32Q_UPD:
> + case ARM::VLD1d64Q_UPD:
> + case ARM::VLD2q8:
> + case ARM::VLD2q16:
> + case ARM::VLD2q32:
> + case ARM::VLD2q8_UPD:
> + case ARM::VLD2q16_UPD:
> + case ARM::VLD2q32_UPD:
> + case ARM::VLD4d8:
> + case ARM::VLD4d16:
> + case ARM::VLD4d32:
> + case ARM::VLD4d8_UPD:
> + case ARM::VLD4d16_UPD:
> + case ARM::VLD4d32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder);
> + break;
> + case ARM::VLD4q8:
> + case ARM::VLD4q16:
> + case ARM::VLD4q32:
> + case ARM::VLD4q8_UPD:
> + case ARM::VLD4q16_UPD:
> + case ARM::VLD4q32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> + // Writeback operand
> + switch (Inst.getOpcode()) {
> + case ARM::VLD1d8_UPD:
> + case ARM::VLD1d16_UPD:
> + case ARM::VLD1d32_UPD:
> + case ARM::VLD1d64_UPD:
> + case ARM::VLD1q8_UPD:
> + case ARM::VLD1q16_UPD:
> + case ARM::VLD1q32_UPD:
> + case ARM::VLD1q64_UPD:
> + case ARM::VLD1d8T_UPD:
> + case ARM::VLD1d16T_UPD:
> + case ARM::VLD1d32T_UPD:
> + case ARM::VLD1d64T_UPD:
> + case ARM::VLD1d8Q_UPD:
> + case ARM::VLD1d16Q_UPD:
> + case ARM::VLD1d32Q_UPD:
> + case ARM::VLD1d64Q_UPD:
> + case ARM::VLD2d8_UPD:
> + case ARM::VLD2d16_UPD:
> + case ARM::VLD2d32_UPD:
> + case ARM::VLD2q8_UPD:
> + case ARM::VLD2q16_UPD:
> + case ARM::VLD2q32_UPD:
> + case ARM::VLD2b8_UPD:
> + case ARM::VLD2b16_UPD:
> + case ARM::VLD2b32_UPD:
> + case ARM::VLD3d8_UPD:
> + case ARM::VLD3d16_UPD:
> + case ARM::VLD3d32_UPD:
> + case ARM::VLD3q8_UPD:
> + case ARM::VLD3q16_UPD:
> + case ARM::VLD3q32_UPD:
> + case ARM::VLD4d8_UPD:
> + case ARM::VLD4d16_UPD:
> + case ARM::VLD4d32_UPD:
> + case ARM::VLD4q8_UPD:
> + case ARM::VLD4q16_UPD:
> + case ARM::VLD4q32_UPD:
> + DecodeGPRRegisterClass(Inst, wb, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> + // AddrMode6 Base (register+alignment)
> + DecodeAddrMode6Operand(Inst, Rn, Address, Decoder);
> +
> + // AddrMode6 Offset (register)
> + if (Rm == 0xD)
> + Inst.addOperand(MCOperand::CreateReg(0));
> + else if (Rm != 0xF)
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
> + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
> + unsigned wb = fieldFromInstruction32(Insn, 16, 4);
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + Rn |= fieldFromInstruction32(Insn, 4, 2) << 4;
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> +
> + // Writeback Operand
> + switch (Inst.getOpcode()) {
> + case ARM::VST1d8_UPD:
> + case ARM::VST1d16_UPD:
> + case ARM::VST1d32_UPD:
> + case ARM::VST1d64_UPD:
> + case ARM::VST1q8_UPD:
> + case ARM::VST1q16_UPD:
> + case ARM::VST1q32_UPD:
> + case ARM::VST1q64_UPD:
> + case ARM::VST1d8T_UPD:
> + case ARM::VST1d16T_UPD:
> + case ARM::VST1d32T_UPD:
> + case ARM::VST1d64T_UPD:
> + case ARM::VST1d8Q_UPD:
> + case ARM::VST1d16Q_UPD:
> + case ARM::VST1d32Q_UPD:
> + case ARM::VST1d64Q_UPD:
> + case ARM::VST2d8_UPD:
> + case ARM::VST2d16_UPD:
> + case ARM::VST2d32_UPD:
> + case ARM::VST2q8_UPD:
> + case ARM::VST2q16_UPD:
> + case ARM::VST2q32_UPD:
> + case ARM::VST2b8_UPD:
> + case ARM::VST2b16_UPD:
> + case ARM::VST2b32_UPD:
> + case ARM::VST3d8_UPD:
> + case ARM::VST3d16_UPD:
> + case ARM::VST3d32_UPD:
> + case ARM::VST3q8_UPD:
> + case ARM::VST3q16_UPD:
> + case ARM::VST3q32_UPD:
> + case ARM::VST4d8_UPD:
> + case ARM::VST4d16_UPD:
> + case ARM::VST4d32_UPD:
> + case ARM::VST4q8_UPD:
> + case ARM::VST4q16_UPD:
> + case ARM::VST4q32_UPD:
> + DecodeGPRRegisterClass(Inst, wb, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> + // AddrMode6 Base (register+alignment)
> + DecodeAddrMode6Operand(Inst, Rn, Address, Decoder);
> +
> + // AddrMode6 Offset (register)
> + if (Rm == 0xD)
> + Inst.addOperand(MCOperand::CreateReg(0));
> + else if (Rm != 0xF)
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> +
> + // First input register
> + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
> +
> + // Second input register
> + switch (Inst.getOpcode()) {
> + case ARM::VST1q8:
> + case ARM::VST1q16:
> + case ARM::VST1q32:
> + case ARM::VST1q64:
> + case ARM::VST1q8_UPD:
> + case ARM::VST1q16_UPD:
> + case ARM::VST1q32_UPD:
> + case ARM::VST1q64_UPD:
> + case ARM::VST1d8T:
> + case ARM::VST1d16T:
> + case ARM::VST1d32T:
> + case ARM::VST1d64T:
> + case ARM::VST1d8T_UPD:
> + case ARM::VST1d16T_UPD:
> + case ARM::VST1d32T_UPD:
> + case ARM::VST1d64T_UPD:
> + case ARM::VST1d8Q:
> + case ARM::VST1d16Q:
> + case ARM::VST1d32Q:
> + case ARM::VST1d64Q:
> + case ARM::VST1d8Q_UPD:
> + case ARM::VST1d16Q_UPD:
> + case ARM::VST1d32Q_UPD:
> + case ARM::VST1d64Q_UPD:
> + case ARM::VST2d8:
> + case ARM::VST2d16:
> + case ARM::VST2d32:
> + case ARM::VST2d8_UPD:
> + case ARM::VST2d16_UPD:
> + case ARM::VST2d32_UPD:
> + case ARM::VST2q8:
> + case ARM::VST2q16:
> + case ARM::VST2q32:
> + case ARM::VST2q8_UPD:
> + case ARM::VST2q16_UPD:
> + case ARM::VST2q32_UPD:
> + case ARM::VST3d8:
> + case ARM::VST3d16:
> + case ARM::VST3d32:
> + case ARM::VST3d8_UPD:
> + case ARM::VST3d16_UPD:
> + case ARM::VST3d32_UPD:
> + case ARM::VST4d8:
> + case ARM::VST4d16:
> + case ARM::VST4d32:
> + case ARM::VST4d8_UPD:
> + case ARM::VST4d16_UPD:
> + case ARM::VST4d32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
> + break;
> + case ARM::VST2b8:
> + case ARM::VST2b16:
> + case ARM::VST2b32:
> + case ARM::VST2b8_UPD:
> + case ARM::VST2b16_UPD:
> + case ARM::VST2b32_UPD:
> + case ARM::VST3q8:
> + case ARM::VST3q16:
> + case ARM::VST3q32:
> + case ARM::VST3q8_UPD:
> + case ARM::VST3q16_UPD:
> + case ARM::VST3q32_UPD:
> + case ARM::VST4q8:
> + case ARM::VST4q16:
> + case ARM::VST4q32:
> + case ARM::VST4q8_UPD:
> + case ARM::VST4q16_UPD:
> + case ARM::VST4q32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> + // Third input register
> + switch (Inst.getOpcode()) {
> + case ARM::VST1d8T:
> + case ARM::VST1d16T:
> + case ARM::VST1d32T:
> + case ARM::VST1d64T:
> + case ARM::VST1d8T_UPD:
> + case ARM::VST1d16T_UPD:
> + case ARM::VST1d32T_UPD:
> + case ARM::VST1d64T_UPD:
> + case ARM::VST1d8Q:
> + case ARM::VST1d16Q:
> + case ARM::VST1d32Q:
> + case ARM::VST1d64Q:
> + case ARM::VST1d8Q_UPD:
> + case ARM::VST1d16Q_UPD:
> + case ARM::VST1d32Q_UPD:
> + case ARM::VST1d64Q_UPD:
> + case ARM::VST2q8:
> + case ARM::VST2q16:
> + case ARM::VST2q32:
> + case ARM::VST2q8_UPD:
> + case ARM::VST2q16_UPD:
> + case ARM::VST2q32_UPD:
> + case ARM::VST3d8:
> + case ARM::VST3d16:
> + case ARM::VST3d32:
> + case ARM::VST3d8_UPD:
> + case ARM::VST3d16_UPD:
> + case ARM::VST3d32_UPD:
> + case ARM::VST4d8:
> + case ARM::VST4d16:
> + case ARM::VST4d32:
> + case ARM::VST4d8_UPD:
> + case ARM::VST4d16_UPD:
> + case ARM::VST4d32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
> + break;
> + case ARM::VST3q8:
> + case ARM::VST3q16:
> + case ARM::VST3q32:
> + case ARM::VST3q8_UPD:
> + case ARM::VST3q16_UPD:
> + case ARM::VST3q32_UPD:
> + case ARM::VST4q8:
> + case ARM::VST4q16:
> + case ARM::VST4q32:
> + case ARM::VST4q8_UPD:
> + case ARM::VST4q16_UPD:
> + case ARM::VST4q32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> + // Fourth input register
> + switch (Inst.getOpcode()) {
> + case ARM::VST1d8Q:
> + case ARM::VST1d16Q:
> + case ARM::VST1d32Q:
> + case ARM::VST1d64Q:
> + case ARM::VST1d8Q_UPD:
> + case ARM::VST1d16Q_UPD:
> + case ARM::VST1d32Q_UPD:
> + case ARM::VST1d64Q_UPD:
> + case ARM::VST2q8:
> + case ARM::VST2q16:
> + case ARM::VST2q32:
> + case ARM::VST2q8_UPD:
> + case ARM::VST2q16_UPD:
> + case ARM::VST2q32_UPD:
> + case ARM::VST4d8:
> + case ARM::VST4d16:
> + case ARM::VST4d32:
> + case ARM::VST4d8_UPD:
> + case ARM::VST4d16_UPD:
> + case ARM::VST4d32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder);
> + break;
> + case ARM::VST4q8:
> + case ARM::VST4q16:
> + case ARM::VST4q32:
> + case ARM::VST4q8_UPD:
> + case ARM::VST4q16_UPD:
> + case ARM::VST4q32_UPD:
> + DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> + return true;
> +}
> +
> +static bool DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
> + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> + unsigned align = fieldFromInstruction32(Insn, 4, 1);
> + unsigned size = fieldFromInstruction32(Insn, 6, 2);
> + unsigned regs = fieldFromInstruction32(Insn, 5, 1) + 1;
> +
> + align *= (1 << size);
> +
> + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
> + if (regs == 2) DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
> + if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(align));
> +
> + if (Rm == 0xD)
> + Inst.addOperand(MCOperand::CreateReg(0));
> + else if (Rm != 0xF)
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
> + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> + unsigned align = fieldFromInstruction32(Insn, 4, 1);
> + unsigned size = 1 << fieldFromInstruction32(Insn, 6, 2);
> + unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
> + align *= 2*size;
> +
> + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
> + DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
> + if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(align));
> +
> + if (Rm == 0xD)
> + Inst.addOperand(MCOperand::CreateReg(0));
> + else if (Rm != 0xF)
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
> + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> + unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
> +
> + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
> + DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
> + DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder);
> + if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(0));
> +
> + if (Rm == 0xD)
> + Inst.addOperand(MCOperand::CreateReg(0));
> + else if (Rm != 0xF)
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
> + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> + unsigned size = fieldFromInstruction32(Insn, 6, 2);
> + unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
> + unsigned align = fieldFromInstruction32(Insn, 4, 1);
> +
> + if (size == 0x3) {
> + size = 4;
> + align = 16;
> + } else {
> + if (size == 2) {
> + size = 1 << size;
> + align *= 8;
> + } else {
> + size = 1 << size;
> + align *= 4*size;
> + }
> + }
> +
> + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
> + DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
> + DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder);
> + DecodeDPRRegisterClass(Inst, (Rd+3*inc)%32, Address, Decoder);
> + if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(align));
> +
> + if (Rm == 0xD)
> + Inst.addOperand(MCOperand::CreateReg(0));
> + else if (Rm != 0xF)
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeNEONModImmInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
> + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
> + unsigned imm = fieldFromInstruction32(Insn, 0, 4);
> + imm |= fieldFromInstruction32(Insn, 16, 3) << 4;
> + imm |= fieldFromInstruction32(Insn, 24, 1) << 7;
> + imm |= fieldFromInstruction32(Insn, 8, 4) << 8;
> + imm |= fieldFromInstruction32(Insn, 5, 1) << 12;
> + unsigned Q = fieldFromInstruction32(Insn, 6, 1);
> +
> + if (Q)
> + DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
> + else
> + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
> +
> + Inst.addOperand(MCOperand::CreateImm(imm));
> +
> + switch (Inst.getOpcode()) {
> + case ARM::VORRiv4i16:
> + case ARM::VORRiv2i32:
> + case ARM::VBICiv4i16:
> + case ARM::VBICiv2i32:
> + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
> + break;
> + case ARM::VORRiv8i16:
> + case ARM::VORRiv4i32:
> + case ARM::VBICiv8i16:
> + case ARM::VBICiv4i32:
> + DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
> + break;
> + default:
> + break;
> + }
> +
> +
> + return true;
> +}
> +
> +static bool DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
> + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> + Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
> + unsigned size = fieldFromInstruction32(Insn, 18, 2);
> +
> + DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
> + DecodeDPRRegisterClass(Inst, Rm, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(8 << size));
> +
> + return true;
> +}
> +
> +static bool DecodeShiftRight8Imm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateImm(8 - Val));
> + return true;
> +}
> +
> +static bool DecodeShiftRight16Imm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateImm(16 - Val));
> + return true;
> +}
> +
> +static bool DecodeShiftRight32Imm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateImm(32 - Val));
> + return true;
> +}
> +
> +static bool DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateImm(64 - Val));
> + return true;
> +}
> +
> +static bool DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
> + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + Rn |= fieldFromInstruction32(Insn, 7, 1) << 4;
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> + Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
> + unsigned op = fieldFromInstruction32(Insn, 6, 1);
> + unsigned length = fieldFromInstruction32(Insn, 8, 2) + 1;
> +
> + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
> + if (op) DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); // Writeback
> +
> + for (unsigned i = 0; i < length; ++i)
> + DecodeDPRRegisterClass(Inst, (Rn+i)%32, Address, Decoder);
> +
> + DecodeDPRRegisterClass(Inst, Rm, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + // The immediate needs to be a fully instantiated float. However, the
> + // auto-generated decoder is only able to fill in some of the bits
> + // necessary. For instance, the 'b' bit is replicated multiple times,
> + // and is even present in inverted form in one bit. We do a little
> + // binary parsing here to fill in those missing bits, and then
> + // reinterpret it all as a float.
> + union {
> + uint32_t integer;
> + float fp;
> + } fp_conv;
> +
> + fp_conv.integer = Val;
> + uint32_t b = fieldFromInstruction32(Val, 25, 1);
> + fp_conv.integer |= b << 26;
> + fp_conv.integer |= b << 27;
> + fp_conv.integer |= b << 28;
> + fp_conv.integer |= b << 29;
> + fp_conv.integer |= (~b & 0x1) << 30;
> +
> + Inst.addOperand(MCOperand::CreateFPImm(fp_conv.fp));
> + return true;
> +}
> +
> +static bool DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned dst = fieldFromInstruction16(Insn, 8, 3);
> + unsigned imm = fieldFromInstruction16(Insn, 0, 8);
> +
> + DecodetGPRRegisterClass(Inst, dst, Address, Decoder);
> +
> + if (Inst.getOpcode() == ARM::tADR)
> + Inst.addOperand(MCOperand::CreateReg(ARM::PC));
> + else if (Inst.getOpcode() == ARM::tADDrSPi)
> + Inst.addOperand(MCOperand::CreateReg(ARM::SP));
> + else
> + return false;
> +
> + Inst.addOperand(MCOperand::CreateImm(imm));
> + return true;
> +}
> +
> +static bool DecodeThumbBROperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateImm(SignExtend32<12>(Val << 1)));
> + return true;
> +}
> +
> +static bool DecodeT2BROperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateImm(SignExtend32<21>(Val)));
> + return true;
> +}
> +
> +static bool DecodeThumbCmpBROperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateImm(SignExtend32<7>(Val << 1)));
> + return true;
> +}
> +
> +static bool DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Val, 0, 3);
> + unsigned Rm = fieldFromInstruction32(Val, 3, 3);
> +
> + DecodetGPRRegisterClass(Inst, Rn, Address, Decoder);
> + DecodetGPRRegisterClass(Inst, Rm, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Val, 0, 3);
> + unsigned imm = fieldFromInstruction32(Val, 3, 5);
> +
> + DecodetGPRRegisterClass(Inst, Rn, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(imm));
> +
> + return true;
> +}
> +
> +static bool DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateImm(Val << 2));
> +
> + return true;
> +}
> +
> +static bool DecodeThumbAddrModeSP(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateReg(ARM::SP));
> + Inst.addOperand(MCOperand::CreateImm(Val << 2));
> +
> + return true;
> +}
> +
> +static bool DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Val, 6, 4);
> + unsigned Rm = fieldFromInstruction32(Val, 2, 4);
> + unsigned imm = fieldFromInstruction32(Val, 0, 2);
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + DecoderGPRRegisterClass(Inst, Rm, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(imm));
> +
> + return true;
> +}
> +
> +static bool DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + if (Inst.getOpcode() != ARM::t2PLDs) {
> + unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
> + DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
> + }
> +
> + unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
> + if (Rn == 0xF) {
> + switch (Inst.getOpcode()) {
> + case ARM::t2LDRBs:
> + Inst.setOpcode(ARM::t2LDRBpci);
> + break;
> + case ARM::t2LDRHs:
> + Inst.setOpcode(ARM::t2LDRHpci);
> + break;
> + case ARM::t2LDRSHs:
> + Inst.setOpcode(ARM::t2LDRSHpci);
> + break;
> + case ARM::t2LDRSBs:
> + Inst.setOpcode(ARM::t2LDRSBpci);
> + break;
> + case ARM::t2PLDs:
> + Inst.setOpcode(ARM::t2PLDi12);
> + Inst.addOperand(MCOperand::CreateReg(ARM::PC));
> + break;
> + default:
> + return false;
> + }
> +
> + int imm = fieldFromInstruction32(Insn, 0, 12);
> + if (!fieldFromInstruction32(Insn, 23, 1)) imm *= -1;
> + Inst.addOperand(MCOperand::CreateImm(imm));
> +
> + return true;
> + }
> +
> + unsigned addrmode = fieldFromInstruction32(Insn, 4, 2);
> + addrmode |= fieldFromInstruction32(Insn, 0, 4) << 2;
> + addrmode |= fieldFromInstruction32(Insn, 16, 4) << 6;
> + DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + int imm = Val & 0xFF;
> + if (!(Val & 0x100)) imm *= -1;
> + Inst.addOperand(MCOperand::CreateImm(imm << 2));
> +
> + return true;
> +}
> +
> +static bool DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Val, 9, 4);
> + unsigned imm = fieldFromInstruction32(Val, 0, 9);
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + DecodeT2Imm8S4(Inst, imm, Address, Decoder);
> +
> + return true;
> +}
> +
> +static bool DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + int imm = Val & 0xFF;
> + if (!(Val & 0x100)) imm *= -1;
> + Inst.addOperand(MCOperand::CreateImm(imm));
> +
> + return true;
> +}
> +
> +
> +static bool DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Val, 9, 4);
> + unsigned imm = fieldFromInstruction32(Val, 0, 9);
> +
> + // Some instructions always use an additive offset.
> + switch (Inst.getOpcode()) {
> + case ARM::t2LDRT:
> + case ARM::t2LDRBT:
> + case ARM::t2LDRHT:
> + case ARM::t2LDRSBT:
> + case ARM::t2LDRSHT:
> + imm |= 0x100;
> + break;
> + default:
> + break;
> + }
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + DecodeT2Imm8(Inst, imm, Address, Decoder);
> +
> + return true;
> +}
> +
> +
> +static bool DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rn = fieldFromInstruction32(Val, 13, 4);
> + unsigned imm = fieldFromInstruction32(Val, 0, 12);
> +
> + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(imm));
> +
> + return true;
> +}
> +
> +
> +static bool DecodeThumbAddSPImm(llvm::MCInst &Inst, uint16_t Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned imm = fieldFromInstruction16(Insn, 0, 7);
> +
> + Inst.addOperand(MCOperand::CreateReg(ARM::SP));
> + Inst.addOperand(MCOperand::CreateReg(ARM::SP));
> + Inst.addOperand(MCOperand::CreateImm(imm));
> +
> + return true;
> +}
> +
> +static bool DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn,
> + uint64_t Address, const void *Decoder) {
> + if (Inst.getOpcode() == ARM::tADDrSP) {
> + unsigned Rdm = fieldFromInstruction16(Insn, 0, 3);
> + Rdm |= fieldFromInstruction16(Insn, 7, 1) << 3;
> +
> + DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateReg(ARM::SP));
> + DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder);
> + } else if (Inst.getOpcode() == ARM::tADDspr) {
> + unsigned Rm = fieldFromInstruction16(Insn, 3, 4);
> +
> + Inst.addOperand(MCOperand::CreateReg(ARM::SP));
> + Inst.addOperand(MCOperand::CreateReg(ARM::SP));
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> + }
> +
> + return true;
> +}
> +
> +static bool DecodeThumbCPS(llvm::MCInst &Inst, uint16_t Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned imod = fieldFromInstruction16(Insn, 4, 1) | 0x2;
> + unsigned flags = fieldFromInstruction16(Insn, 0, 3);
> +
> + Inst.addOperand(MCOperand::CreateImm(imod));
> + Inst.addOperand(MCOperand::CreateImm(flags));
> +
> + return true;
> +}
> +
> +static bool DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
> + unsigned add = fieldFromInstruction32(Insn, 4, 1);
> +
> + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(add));
> +
> + return true;
> +}
> +
> +static bool DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
> + return true;
> +}
> +
> +static bool DecodeCoprocessor(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + if (Val == 0xA || Val == 0xB)
> + return false;
> +
> + Inst.addOperand(MCOperand::CreateImm(Val));
> + return true;
> +}
> +
> +static bool DecodeThumbSRImm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + if (Val == 0)
> + Inst.addOperand(MCOperand::CreateImm(32));
> + else
> + Inst.addOperand(MCOperand::CreateImm(Val));
> + return true;
> +}
> +
> +static bool DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Insn,
> + uint64_t Address, const void *Decoder) {
> + unsigned pred = fieldFromInstruction32(Insn, 22, 4);
> + if (pred == 0xE || pred == 0xF) {
> + unsigned opc = fieldFromInstruction32(Insn, 4, 2);
> + switch (opc) {
> + default:
> + return false;
> + case 0:
> + Inst.setOpcode(ARM::t2DSB);
> + break;
> + case 1:
> + Inst.setOpcode(ARM::t2DMB);
> + break;
> + case 2:
> + Inst.setOpcode(ARM::t2ISB);
> + return true;
> + }
> +
> + unsigned imm = fieldFromInstruction32(Insn, 0, 4);
> + Inst.addOperand(MCOperand::CreateImm(imm));
> + return true;
> + }
> +
> + unsigned brtarget = fieldFromInstruction32(Insn, 0, 11) << 1;
> + brtarget |= fieldFromInstruction32(Insn, 11, 1) << 19;
> + brtarget |= fieldFromInstruction32(Insn, 13, 1) << 18;
> + brtarget |= fieldFromInstruction32(Insn, 16, 6) << 12;
> + brtarget |= fieldFromInstruction32(Insn, 26, 1) << 20;
> +
> + DecodeT2BROperand(Inst, brtarget, Address, Decoder);
> + if (!DecodePredicateOperand(Inst, pred, Address, Decoder))
> + return false;
> +
> + return true;
> +}
> +
> +// Decode a shifted immediate operand. These basically consist
> +// of an 8-bit value, and a 4-bit directive that specifies either
> +// a splat operation or a rotation.
> +static bool DecodeT2SOImm(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + unsigned ctrl = fieldFromInstruction32(Val, 10, 2);
> + if (ctrl == 0) {
> + unsigned byte = fieldFromInstruction32(Val, 8, 2);
> + unsigned imm = fieldFromInstruction32(Val, 0, 8);
> + switch (byte) {
> + case 0:
> + Inst.addOperand(MCOperand::CreateImm(imm));
> + break;
> + case 1:
> + Inst.addOperand(MCOperand::CreateImm((imm << 16) | imm));
> + break;
> + case 2:
> + Inst.addOperand(MCOperand::CreateImm((imm << 24) | (imm << 8)));
> + break;
> + case 3:
> + Inst.addOperand(MCOperand::CreateImm((imm << 24) | (imm << 16) |
> + (imm << 8) | imm));
> + break;
> + }
> + } else {
> + unsigned unrot = fieldFromInstruction32(Val, 0, 7) | 0x80;
> + unsigned rot = fieldFromInstruction32(Val, 7, 5);
> + unsigned imm = (unrot >> rot) | (unrot << ((32-rot)&31));
> + Inst.addOperand(MCOperand::CreateImm(imm));
> + }
> +
> + return true;
> +}
> +
> +static bool DecodeThumbBCCTargetOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder){
> + Inst.addOperand(MCOperand::CreateImm(Val << 1));
> + return true;
> +}
> +
> +static bool DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder){
> + Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
> + return true;
> +}
> +
> +static bool DecodeAddrMode3Offset(llvm::MCInst &Inst, unsigned Val,
> + uint64_t Address, const void *Decoder) {
> + bool isImm = fieldFromInstruction32(Val, 9, 1);
> + bool isAdd = fieldFromInstruction32(Val, 8, 1);
> + unsigned imm = fieldFromInstruction32(Val, 0, 8);
> +
> + if (!isImm) {
> + DecodeGPRRegisterClass(Inst, imm, Address, Decoder);
> + Inst.addOperand(MCOperand::CreateImm(!isAdd << 8));
> + } else {
> + Inst.addOperand(MCOperand::CreateReg(0));
> + Inst.addOperand(MCOperand::CreateImm(imm | (!isAdd << 8)));
> + }
> +
> + return true;
> }
>
> Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h (original)
> +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h Tue Aug 9 15:55:18 2011
> @@ -17,15 +17,16 @@
> #define ARMDISASSEMBLER_H
>
> #include "llvm/MC/MCDisassembler.h"
> +#include <vector>
>
> namespace llvm {
>
> class MCInst;
> class MemoryObject;
> class raw_ostream;
> -
> +
> struct EDInstInfo;
> -
> +
> /// ARMDisassembler - ARM disassembler for all ARM platforms.
> class ARMDisassembler : public MCDisassembler {
> public:
> @@ -44,38 +45,19 @@
> const MemoryObject ®ion,
> uint64_t address,
> raw_ostream &vStream) const;
> -
> +
> /// getEDInfo - See MCDisassembler.
> EDInstInfo *getEDInfo() const;
> private:
> };
>
> -// Forward declaration.
> -class ARMBasicMCBuilder;
> -
> -/// Session - Keep track of the IT Block progression.
> -class Session {
> - friend class ARMBasicMCBuilder;
> -public:
> - Session() : ITCounter(0), ITState(0) {}
> - ~Session() {}
> - /// InitIT - Initializes ITCounter/ITState.
> - bool InitIT(unsigned short bits7_0);
> - /// UpdateIT - Updates ITCounter/ITState as IT Block progresses.
> - void UpdateIT();
> -
> -private:
> - unsigned ITCounter; // Possible values: 0, 1, 2, 3, 4.
> - unsigned ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
> -};
> -
> -/// ThumbDisassembler - Thumb disassembler for all ARM platforms.
> +/// ARMDisassembler - ARM disassembler for all ARM platforms.
> class ThumbDisassembler : public MCDisassembler {
> public:
> /// Constructor - Initializes the disassembler.
> ///
> ThumbDisassembler() :
> - MCDisassembler(), SO() {
> + MCDisassembler() {
> }
>
> ~ThumbDisassembler() {
> @@ -87,13 +69,16 @@
> const MemoryObject ®ion,
> uint64_t address,
> raw_ostream &vStream) const;
> -
> +
> /// getEDInfo - See MCDisassembler.
> EDInstInfo *getEDInfo() const;
> private:
> - Session SO;
> + mutable std::vector<unsigned> ITBlock;
> + void AddThumbPredicate(MCInst&) const;
> + void UpdateThumbVFPPredicate(MCInst&) const;
> };
>
> +
> } // namespace llvm
> -
> +
> #endif
>
> Removed: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=137143&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (removed)
> @@ -1,3894 +0,0 @@
> -//===- ARMDisassemblerCore.cpp - ARM disassembler helpers -------*- C++ -*-===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -//
> -// This file is part of the ARM Disassembler.
> -// It contains code to represent the core concepts of Builder and DisassembleFP
> -// to solve the problem of disassembling an ARM instr.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#define DEBUG_TYPE "arm-disassembler"
> -
> -#include "ARMDisassemblerCore.h"
> -#include "MCTargetDesc/ARMAddressingModes.h"
> -#include "MCTargetDesc/ARMMCExpr.h"
> -#include "llvm/ADT/APInt.h"
> -#include "llvm/ADT/APFloat.h"
> -#include "llvm/Support/Debug.h"
> -#include "llvm/Support/raw_ostream.h"
> -
> -//#define DEBUG(X) do { X; } while (0)
> -
> -/// ARMGenInstrInfo.inc - ARMGenInstrInfo.inc contains the static const
> -/// MCInstrDesc ARMInsts[] definition and the MCOperandInfo[]'s describing the
> -/// operand info for each ARMInsts[i].
> -///
> -/// Together with an instruction's encoding format, we can take advantage of the
> -/// NumOperands and the OpInfo fields of the target instruction description in
> -/// the quest to build out the MCOperand list for an MCInst.
> -///
> -/// The general guideline is that with a known format, the number of dst and src
> -/// operands are well-known. The dst is built first, followed by the src
> -/// operand(s). The operands not yet used at this point are for the Implicit
> -/// Uses and Defs by this instr. For the Uses part, the pred:$p operand is
> -/// defined with two components:
> -///
> -/// def pred { // Operand PredicateOperand
> -/// ValueType Type = OtherVT;
> -/// string PrintMethod = "printPredicateOperand";
> -/// string AsmOperandLowerMethod = ?;
> -/// dag MIOperandInfo = (ops i32imm, CCR);
> -/// AsmOperandClass ParserMatchClass = ImmAsmOperand;
> -/// dag DefaultOps = (ops (i32 14), (i32 zero_reg));
> -/// }
> -///
> -/// which is manifested by the MCOperandInfo[] of:
> -///
> -/// { 0, 0|(1<<MCOI::Predicate), 0 },
> -/// { ARM::CCRRegClassID, 0|(1<<MCOI::Predicate), 0 }
> -///
> -/// So the first predicate MCOperand corresponds to the immediate part of the
> -/// ARM condition field (Inst{31-28}), and the second predicate MCOperand
> -/// corresponds to a register kind of ARM::CPSR.
> -///
> -/// For the Defs part, in the simple case of only cc_out:$s, we have:
> -///
> -/// def cc_out { // Operand OptionalDefOperand
> -/// ValueType Type = OtherVT;
> -/// string PrintMethod = "printSBitModifierOperand";
> -/// string AsmOperandLowerMethod = ?;
> -/// dag MIOperandInfo = (ops CCR);
> -/// AsmOperandClass ParserMatchClass = ImmAsmOperand;
> -/// dag DefaultOps = (ops (i32 zero_reg));
> -/// }
> -///
> -/// which is manifested by the one MCOperandInfo of:
> -///
> -/// { ARM::CCRRegClassID, 0|(1<<MCOI::OptionalDef), 0 }
> -///
> -
> -namespace llvm {
> -extern MCInstrDesc ARMInsts[];
> -}
> -
> -using namespace llvm;
> -
> -const char *ARMUtils::OpcodeName(unsigned Opcode) {
> - return ARMInsts[Opcode].Name;
> -}
> -
> -// Return the register enum Based on RegClass and the raw register number.
> -// FIXME: Auto-gened?
> -static unsigned
> -getRegisterEnum(BO B, unsigned RegClassID, unsigned RawRegister) {
> - if (RegClassID == ARM::rGPRRegClassID) {
> - // Check for The register numbers 13 and 15 that are not permitted for many
> - // Thumb register specifiers.
> - if (RawRegister == 13 || RawRegister == 15) {
> - B->SetErr(-1);
> - return 0;
> - }
> - // For this purpose, we can treat rGPR as if it were GPR.
> - RegClassID = ARM::GPRRegClassID;
> - }
> -
> - // See also decodeNEONRd(), decodeNEONRn(), decodeNEONRm().
> - // A7.3 register encoding
> - // Qd -> bit[12] == 0
> - // Qn -> bit[16] == 0
> - // Qm -> bit[0] == 0
> - //
> - // If one of these bits is 1, the instruction is UNDEFINED.
> - if (RegClassID == ARM::QPRRegClassID && slice(RawRegister, 0, 0) == 1) {
> - B->SetErr(-1);
> - return 0;
> - }
> - unsigned RegNum =
> - RegClassID == ARM::QPRRegClassID ? RawRegister >> 1 : RawRegister;
> -
> - switch (RegNum) {
> - default:
> - break;
> - case 0:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R0;
> - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
> - case ARM::DPR_VFP2RegClassID:
> - return ARM::D0;
> - case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
> - case ARM::QPR_VFP2RegClassID:
> - return ARM::Q0;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S0;
> - }
> - break;
> - case 1:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R1;
> - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
> - case ARM::DPR_VFP2RegClassID:
> - return ARM::D1;
> - case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
> - case ARM::QPR_VFP2RegClassID:
> - return ARM::Q1;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S1;
> - }
> - break;
> - case 2:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R2;
> - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
> - case ARM::DPR_VFP2RegClassID:
> - return ARM::D2;
> - case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
> - case ARM::QPR_VFP2RegClassID:
> - return ARM::Q2;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S2;
> - }
> - break;
> - case 3:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R3;
> - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
> - case ARM::DPR_VFP2RegClassID:
> - return ARM::D3;
> - case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
> - case ARM::QPR_VFP2RegClassID:
> - return ARM::Q3;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S3;
> - }
> - break;
> - case 4:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R4;
> - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
> - case ARM::DPR_VFP2RegClassID:
> - return ARM::D4;
> - case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q4;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S4;
> - }
> - break;
> - case 5:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R5;
> - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
> - case ARM::DPR_VFP2RegClassID:
> - return ARM::D5;
> - case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q5;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S5;
> - }
> - break;
> - case 6:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R6;
> - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
> - case ARM::DPR_VFP2RegClassID:
> - return ARM::D6;
> - case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q6;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S6;
> - }
> - break;
> - case 7:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R7;
> - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
> - case ARM::DPR_VFP2RegClassID:
> - return ARM::D7;
> - case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q7;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S7;
> - }
> - break;
> - case 8:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: return ARM::R8;
> - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D8;
> - case ARM::QPRRegClassID: return ARM::Q8;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S8;
> - }
> - break;
> - case 9:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: return ARM::R9;
> - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D9;
> - case ARM::QPRRegClassID: return ARM::Q9;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S9;
> - }
> - break;
> - case 10:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: return ARM::R10;
> - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D10;
> - case ARM::QPRRegClassID: return ARM::Q10;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S10;
> - }
> - break;
> - case 11:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: return ARM::R11;
> - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D11;
> - case ARM::QPRRegClassID: return ARM::Q11;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S11;
> - }
> - break;
> - case 12:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: return ARM::R12;
> - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D12;
> - case ARM::QPRRegClassID: return ARM::Q12;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S12;
> - }
> - break;
> - case 13:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: return ARM::SP;
> - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D13;
> - case ARM::QPRRegClassID: return ARM::Q13;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S13;
> - }
> - break;
> - case 14:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: return ARM::LR;
> - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D14;
> - case ARM::QPRRegClassID: return ARM::Q14;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S14;
> - }
> - break;
> - case 15:
> - switch (RegClassID) {
> - case ARM::GPRRegClassID: return ARM::PC;
> - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D15;
> - case ARM::QPRRegClassID: return ARM::Q15;
> - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S15;
> - }
> - break;
> - case 16:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D16;
> - case ARM::SPRRegClassID: return ARM::S16;
> - }
> - break;
> - case 17:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D17;
> - case ARM::SPRRegClassID: return ARM::S17;
> - }
> - break;
> - case 18:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D18;
> - case ARM::SPRRegClassID: return ARM::S18;
> - }
> - break;
> - case 19:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D19;
> - case ARM::SPRRegClassID: return ARM::S19;
> - }
> - break;
> - case 20:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D20;
> - case ARM::SPRRegClassID: return ARM::S20;
> - }
> - break;
> - case 21:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D21;
> - case ARM::SPRRegClassID: return ARM::S21;
> - }
> - break;
> - case 22:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D22;
> - case ARM::SPRRegClassID: return ARM::S22;
> - }
> - break;
> - case 23:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D23;
> - case ARM::SPRRegClassID: return ARM::S23;
> - }
> - break;
> - case 24:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D24;
> - case ARM::SPRRegClassID: return ARM::S24;
> - }
> - break;
> - case 25:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D25;
> - case ARM::SPRRegClassID: return ARM::S25;
> - }
> - break;
> - case 26:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D26;
> - case ARM::SPRRegClassID: return ARM::S26;
> - }
> - break;
> - case 27:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D27;
> - case ARM::SPRRegClassID: return ARM::S27;
> - }
> - break;
> - case 28:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D28;
> - case ARM::SPRRegClassID: return ARM::S28;
> - }
> - break;
> - case 29:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D29;
> - case ARM::SPRRegClassID: return ARM::S29;
> - }
> - break;
> - case 30:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D30;
> - case ARM::SPRRegClassID: return ARM::S30;
> - }
> - break;
> - case 31:
> - switch (RegClassID) {
> - case ARM::DPRRegClassID: return ARM::D31;
> - case ARM::SPRRegClassID: return ARM::S31;
> - }
> - break;
> - }
> - DEBUG(errs() << "Invalid (RegClassID, RawRegister) combination\n");
> - // Encoding error. Mark the builder with error code != 0.
> - B->SetErr(-1);
> - return 0;
> -}
> -
> -///////////////////////////////
> -// //
> -// Utility Functions //
> -// //
> -///////////////////////////////
> -
> -// Extract/Decode Rd: Inst{15-12}.
> -static inline unsigned decodeRd(uint32_t insn) {
> - return (insn >> ARMII::RegRdShift) & ARMII::GPRRegMask;
> -}
> -
> -// Extract/Decode Rn: Inst{19-16}.
> -static inline unsigned decodeRn(uint32_t insn) {
> - return (insn >> ARMII::RegRnShift) & ARMII::GPRRegMask;
> -}
> -
> -// Extract/Decode Rm: Inst{3-0}.
> -static inline unsigned decodeRm(uint32_t insn) {
> - return (insn & ARMII::GPRRegMask);
> -}
> -
> -// Extract/Decode Rs: Inst{11-8}.
> -static inline unsigned decodeRs(uint32_t insn) {
> - return (insn >> ARMII::RegRsShift) & ARMII::GPRRegMask;
> -}
> -
> -static inline unsigned getCondField(uint32_t insn) {
> - return (insn >> ARMII::CondShift);
> -}
> -
> -static inline unsigned getIBit(uint32_t insn) {
> - return (insn >> ARMII::I_BitShift) & 1;
> -}
> -
> -static inline unsigned getAM3IBit(uint32_t insn) {
> - return (insn >> ARMII::AM3_I_BitShift) & 1;
> -}
> -
> -static inline unsigned getPBit(uint32_t insn) {
> - return (insn >> ARMII::P_BitShift) & 1;
> -}
> -
> -static inline unsigned getUBit(uint32_t insn) {
> - return (insn >> ARMII::U_BitShift) & 1;
> -}
> -
> -static inline unsigned getPUBits(uint32_t insn) {
> - return (insn >> ARMII::U_BitShift) & 3;
> -}
> -
> -static inline unsigned getSBit(uint32_t insn) {
> - return (insn >> ARMII::S_BitShift) & 1;
> -}
> -
> -static inline unsigned getWBit(uint32_t insn) {
> - return (insn >> ARMII::W_BitShift) & 1;
> -}
> -
> -static inline unsigned getDBit(uint32_t insn) {
> - return (insn >> ARMII::D_BitShift) & 1;
> -}
> -
> -static inline unsigned getNBit(uint32_t insn) {
> - return (insn >> ARMII::N_BitShift) & 1;
> -}
> -
> -static inline unsigned getMBit(uint32_t insn) {
> - return (insn >> ARMII::M_BitShift) & 1;
> -}
> -
> -// See A8.4 Shifts applied to a register.
> -// A8.4.2 Register controlled shifts.
> -//
> -// getShiftOpcForBits - getShiftOpcForBits translates from the ARM encoding bits
> -// into llvm enums for shift opcode. The API clients should pass in the value
> -// encoded with two bits, so the assert stays to signal a wrong API usage.
> -//
> -// A8-12: DecodeRegShift()
> -static inline ARM_AM::ShiftOpc getShiftOpcForBits(unsigned bits) {
> - switch (bits) {
> - default: assert(0 && "No such value"); return ARM_AM::no_shift;
> - case 0: return ARM_AM::lsl;
> - case 1: return ARM_AM::lsr;
> - case 2: return ARM_AM::asr;
> - case 3: return ARM_AM::ror;
> - }
> -}
> -
> -// See A8.4 Shifts applied to a register.
> -// A8.4.1 Constant shifts.
> -//
> -// getImmShiftSE - getImmShiftSE translates from the raw ShiftOpc and raw Imm5
> -// encodings into the intended ShiftOpc and shift amount.
> -//
> -// A8-11: DecodeImmShift()
> -static inline void getImmShiftSE(ARM_AM::ShiftOpc &ShOp, unsigned &ShImm) {
> - if (ShImm != 0)
> - return;
> - switch (ShOp) {
> - case ARM_AM::no_shift:
> - case ARM_AM::rrx:
> - break;
> - case ARM_AM::lsl:
> - ShOp = ARM_AM::no_shift;
> - break;
> - case ARM_AM::lsr:
> - case ARM_AM::asr:
> - ShImm = 32;
> - break;
> - case ARM_AM::ror:
> - ShOp = ARM_AM::rrx;
> - break;
> - }
> -}
> -
> -// getAMSubModeForBits - getAMSubModeForBits translates from the ARM encoding
> -// bits Inst{24-23} (P(24) and U(23)) into llvm enums for AMSubMode. The API
> -// clients should pass in the value encoded with two bits, so the assert stays
> -// to signal a wrong API usage.
> -static inline ARM_AM::AMSubMode getAMSubModeForBits(unsigned bits) {
> - switch (bits) {
> - default: assert(0 && "No such value"); return ARM_AM::bad_am_submode;
> - case 1: return ARM_AM::ia; // P=0 U=1
> - case 3: return ARM_AM::ib; // P=1 U=1
> - case 0: return ARM_AM::da; // P=0 U=0
> - case 2: return ARM_AM::db; // P=1 U=0
> - }
> -}
> -
> -////////////////////////////////////////////
> -// //
> -// Disassemble function definitions //
> -// //
> -////////////////////////////////////////////
> -
> -/// There is a separate Disassemble*Frm function entry for disassembly of an ARM
> -/// instr into a list of MCOperands in the appropriate order, with possible dst,
> -/// followed by possible src(s).
> -///
> -/// The processing of the predicate, and the 'S' modifier bit, if MI modifies
> -/// the CPSR, is factored into ARMBasicMCBuilder's method named
> -/// TryPredicateAndSBitModifier.
> -
> -static bool DisassemblePseudo(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO) {
> -
> - assert(0 && "Unexpected pseudo instruction!");
> - return false;
> -}
> -
> -// A8.6.94 MLA
> -// if d == 15 || n == 15 || m == 15 || a == 15 then UNPREDICTABLE;
> -//
> -// A8.6.105 MUL
> -// if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
> -//
> -// A8.6.246 UMULL
> -// if dLo == 15 || dHi == 15 || n == 15 || m == 15 then UNPREDICTABLE;
> -// if dHi == dLo then UNPREDICTABLE;
> -static bool BadRegsMulFrm(unsigned Opcode, uint32_t insn) {
> - unsigned R19_16 = slice(insn, 19, 16);
> - unsigned R15_12 = slice(insn, 15, 12);
> - unsigned R11_8 = slice(insn, 11, 8);
> - unsigned R3_0 = slice(insn, 3, 0);
> - switch (Opcode) {
> - default:
> - // Did we miss an opcode?
> - DEBUG(errs() << "BadRegsMulFrm: unexpected opcode!");
> - return false;
> - case ARM::MLA: case ARM::MLS: case ARM::SMLABB: case ARM::SMLABT:
> - case ARM::SMLATB: case ARM::SMLATT: case ARM::SMLAWB: case ARM::SMLAWT:
> - case ARM::SMMLA: case ARM::SMMLAR: case ARM::SMMLS: case ARM::SMMLSR:
> - case ARM::USADA8:
> - if (R19_16 == 15 || R15_12 == 15 || R11_8 == 15 || R3_0 == 15)
> - return true;
> - return false;
> - case ARM::MUL: case ARM::SMMUL: case ARM::SMMULR:
> - case ARM::SMULBB: case ARM::SMULBT: case ARM::SMULTB: case ARM::SMULTT:
> - case ARM::SMULWB: case ARM::SMULWT: case ARM::SMUAD: case ARM::SMUADX:
> - // A8.6.167 SMLAD & A8.6.172 SMLSD
> - case ARM::SMLAD: case ARM::SMLADX: case ARM::SMLSD: case ARM::SMLSDX:
> - case ARM::USAD8:
> - if (R19_16 == 15 || R11_8 == 15 || R3_0 == 15)
> - return true;
> - return false;
> - case ARM::SMLAL: case ARM::SMULL: case ARM::UMAAL: case ARM::UMLAL:
> - case ARM::UMULL:
> - case ARM::SMLALBB: case ARM::SMLALBT: case ARM::SMLALTB: case ARM::SMLALTT:
> - case ARM::SMLALD: case ARM::SMLALDX: case ARM::SMLSLD: case ARM::SMLSLDX:
> - if (R19_16 == 15 || R15_12 == 15 || R11_8 == 15 || R3_0 == 15)
> - return true;
> - if (R19_16 == R15_12)
> - return true;
> - return false;;
> - }
> -}
> -
> -// Multiply Instructions.
> -// MLA, MLS, SMLABB, SMLABT, SMLATB, SMLATT, SMLAWB, SMLAWT, SMMLA, SMMLAR,
> -// SMMLS, SMMLAR, SMLAD, SMLADX, SMLSD, SMLSDX, and USADA8 (for convenience):
> -// Rd{19-16} Rn{3-0} Rm{11-8} Ra{15-12}
> -// But note that register checking for {SMLAD, SMLADX, SMLSD, SMLSDX} is
> -// only for {d, n, m}.
> -//
> -// MUL, SMMUL, SMMULR, SMULBB, SMULBT, SMULTB, SMULTT, SMULWB, SMULWT, SMUAD,
> -// SMUADX, and USAD8 (for convenience):
> -// Rd{19-16} Rn{3-0} Rm{11-8}
> -//
> -// SMLAL, SMULL, UMAAL, UMLAL, UMULL, SMLALBB, SMLALBT, SMLALTB, SMLALTT,
> -// SMLALD, SMLADLX, SMLSLD, SMLSLDX:
> -// RdLo{15-12} RdHi{19-16} Rn{3-0} Rm{11-8}
> -//
> -// The mapping of the multiply registers to the "regular" ARM registers, where
> -// there are convenience decoder functions, is:
> -//
> -// Inst{15-12} => Rd
> -// Inst{19-16} => Rn
> -// Inst{3-0} => Rm
> -// Inst{11-8} => Rs
> -static bool DisassembleMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - unsigned short NumDefs = MCID.getNumDefs();
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(NumDefs > 0 && "NumDefs should be greater than 0 for MulFrm");
> - assert(NumOps >= 3
> - && OpInfo[0].RegClass == ARM::GPRRegClassID
> - && OpInfo[1].RegClass == ARM::GPRRegClassID
> - && OpInfo[2].RegClass == ARM::GPRRegClassID
> - && "Expect three register operands");
> -
> - // Sanity check for the register encodings.
> - if (BadRegsMulFrm(Opcode, insn))
> - return false;
> -
> - // Instructions with two destination registers have RdLo{15-12} first.
> - if (NumDefs == 2) {
> - assert(NumOps >= 4 && OpInfo[3].RegClass == ARM::GPRRegClassID &&
> - "Expect 4th register operand");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> - }
> -
> - // The destination register: RdHi{19-16} or Rd{19-16}.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> -
> - // The two src regsiters: Rn{3-0}, then Rm{11-8}.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRs(insn))));
> - OpIdx += 3;
> -
> - // Many multiply instructions (e.g., MLA) have three src registers.
> - // The third register operand is Ra{15-12}.
> - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -// Helper routines for disassembly of coprocessor instructions.
> -
> -static bool LdStCopOpcode(unsigned Opcode) {
> - if ((Opcode >= ARM::LDC2L_OFFSET && Opcode <= ARM::LDC_PRE) ||
> - (Opcode >= ARM::STC2L_OFFSET && Opcode <= ARM::STC_PRE))
> - return true;
> - return false;
> -}
> -static bool CoprocessorOpcode(unsigned Opcode) {
> - if (LdStCopOpcode(Opcode))
> - return true;
> -
> - switch (Opcode) {
> - default:
> - return false;
> - case ARM::CDP: case ARM::CDP2:
> - case ARM::MCR: case ARM::MCR2: case ARM::MRC: case ARM::MRC2:
> - case ARM::MCRR: case ARM::MCRR2: case ARM::MRRC: case ARM::MRRC2:
> - return true;
> - }
> -}
> -static inline unsigned GetCoprocessor(uint32_t insn) {
> - return slice(insn, 11, 8);
> -}
> -static inline unsigned GetCopOpc1(uint32_t insn, bool CDP) {
> - return CDP ? slice(insn, 23, 20) : slice(insn, 23, 21);
> -}
> -static inline unsigned GetCopOpc2(uint32_t insn) {
> - return slice(insn, 7, 5);
> -}
> -static inline unsigned GetCopOpc(uint32_t insn) {
> - return slice(insn, 7, 4);
> -}
> -// Most of the operands are in immediate forms, except Rd and Rn, which are ARM
> -// core registers.
> -//
> -// CDP, CDP2: cop opc1 CRd CRn CRm opc2
> -//
> -// MCR, MCR2, MRC, MRC2: cop opc1 Rd CRn CRm opc2
> -//
> -// MCRR, MCRR2, MRRC, MRRc2: cop opc Rd Rn CRm
> -//
> -// LDC_OFFSET, LDC_PRE, LDC_POST: cop CRd Rn R0 [+/-]imm8:00
> -// and friends
> -// STC_OFFSET, STC_PRE, STC_POST: cop CRd Rn R0 [+/-]imm8:00
> -// and friends
> -// <-- addrmode2 -->
> -//
> -// LDC_OPTION: cop CRd Rn imm8
> -// and friends
> -// STC_OPTION: cop CRd Rn imm8
> -// and friends
> -//
> -static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 4 && "Num of operands >= 4 for coprocessor instr");
> -
> - unsigned &OpIdx = NumOpsAdded;
> - // A8.6.92
> - // if coproc == '101x' then SEE "Advanced SIMD and VFP"
> - // But since the special instructions have more explicit encoding bits
> - // specified, if coproc == 10 or 11, we should reject it as invalid.
> - unsigned coproc = GetCoprocessor(insn);
> - if ((Opcode == ARM::MCR || Opcode == ARM::MCRR ||
> - Opcode == ARM::MRC || Opcode == ARM::MRRC) &&
> - (coproc == 10 || coproc == 11)) {
> - DEBUG(errs() << "Encoding error: coproc == 10 or 11 for MCR[R]/MR[R]C\n");
> - return false;
> - }
> -
> - bool OneCopOpc = (Opcode == ARM::MCRR || Opcode == ARM::MCRR2 ||
> - Opcode == ARM::MRRC || Opcode == ARM::MRRC2);
> -
> - // CDP/CDP2 has no GPR operand; the opc1 operand is also wider (Inst{23-20}).
> - bool NoGPR = (Opcode == ARM::CDP || Opcode == ARM::CDP2);
> - bool LdStCop = LdStCopOpcode(Opcode);
> - bool RtOut = (Opcode == ARM::MRC || Opcode == ARM::MRC2);
> -
> - OpIdx = 0;
> -
> - if (RtOut) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> - }
> - MI.addOperand(MCOperand::CreateImm(coproc));
> - ++OpIdx;
> -
> - if (LdStCop) {
> - // Unindex if P:W = 0b00 --> _OPTION variant
> - unsigned PW = getPBit(insn) << 1 | getWBit(insn);
> -
> - MI.addOperand(MCOperand::CreateImm(decodeRd(insn)));
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - OpIdx += 2;
> -
> - if (PW) {
> - MI.addOperand(MCOperand::CreateReg(0));
> - ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - unsigned IndexMode =
> - (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
> - unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, slice(insn, 7, 0) << 2,
> - ARM_AM::no_shift, IndexMode);
> - MI.addOperand(MCOperand::CreateImm(Offset));
> - OpIdx += 2;
> - } else {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 0)));
> - ++OpIdx;
> - }
> - } else {
> - MI.addOperand(MCOperand::CreateImm(OneCopOpc ? GetCopOpc(insn)
> - : GetCopOpc1(insn, NoGPR)));
> - ++OpIdx;
> -
> - if (!RtOut) {
> - MI.addOperand(NoGPR ? MCOperand::CreateImm(decodeRd(insn))
> - : MCOperand::CreateReg(
> - getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> - }
> -
> - MI.addOperand(OneCopOpc ? MCOperand::CreateReg(
> - getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn)))
> - : MCOperand::CreateImm(decodeRn(insn)));
> -
> - MI.addOperand(MCOperand::CreateImm(decodeRm(insn)));
> -
> - OpIdx += 2;
> -
> - if (!OneCopOpc) {
> - MI.addOperand(MCOperand::CreateImm(GetCopOpc2(insn)));
> - ++OpIdx;
> - }
> - }
> -
> - return true;
> -}
> -
> -// Branch Instructions.
> -// BL: SignExtend(Imm24:'00', 32)
> -// Bcc, BL_pred: SignExtend(Imm24:'00', 32) Pred0 Pred1
> -// SMC: ZeroExtend(imm4, 32)
> -// SVC: ZeroExtend(Imm24, 32)
> -//
> -// Various coprocessor instructions are assigned BrFrm arbitrarily.
> -// Delegates to DisassembleCoprocessor() helper function.
> -//
> -// MRS/MRSsys: Rd
> -// MSR/MSRsys: Rm mask=Inst{19-16}
> -// BXJ: Rm
> -// MSRi/MSRsysi: so_imm
> -// SRS: mode_imm
> -// RFE: Rn
> -static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - if (CoprocessorOpcode(Opcode))
> - return DisassembleCoprocessor(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - // MRS and MRSsys take one GPR reg Rd.
> - if (Opcode == ARM::MRS || Opcode == ARM::MRSsys) {
> - assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - NumOpsAdded = 1;
> - return true;
> - }
> - // BXJ takes one GPR reg Rm.
> - if (Opcode == ARM::BXJ) {
> - assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - NumOpsAdded = 1;
> - return true;
> - }
> - // MSR take a mask, followed by one GPR reg Rm. The mask contains the R Bit in
> - // bit 4, and the special register fields in bits 3-0.
> - if (Opcode == ARM::MSR) {
> - assert(NumOps >= 1 && OpInfo[1].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ |
> - slice(insn, 19, 16) /* Special Reg */ ));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - NumOpsAdded = 2;
> - return true;
> - }
> - // MSRi take a mask, followed by one so_imm operand. The mask contains the
> - // R Bit in bit 4, and the special register fields in bits 3-0.
> - if (Opcode == ARM::MSRi) {
> - // A5.2.11 MSR (immediate), and hints & B6.1.6 MSR (immediate)
> - // The hints instructions have more specific encodings, so if mask == 0,
> - // we should reject this as an invalid instruction.
> - if (slice(insn, 19, 16) == 0)
> - return false;
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ |
> - slice(insn, 19, 16) /* Special Reg */ ));
> - // SOImm is 4-bit rotate amount in bits 11-8 with 8-bit imm in bits 7-0.
> - // A5.2.4 Rotate amount is twice the numeric value of Inst{11-8}.
> - // See also ARMAddressingModes.h: getSOImmValImm() and getSOImmValRot().
> - unsigned Rot = (insn >> ARMII::SoRotImmShift) & 0xF;
> - unsigned Imm = insn & 0xFF;
> - MI.addOperand(MCOperand::CreateImm(ARM_AM::rotr32(Imm, 2*Rot)));
> - NumOpsAdded = 2;
> - return true;
> - }
> - if (Opcode == ARM::SRSDA || Opcode == ARM::SRSDB ||
> - Opcode == ARM::SRSIA || Opcode == ARM::SRSIB ||
> - Opcode == ARM::SRSDA_UPD || Opcode == ARM::SRSDB_UPD ||
> - Opcode == ARM::SRSIA_UPD || Opcode == ARM::SRSIB_UPD) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));
> - NumOpsAdded = 1;
> - return true;
> - }
> - if (Opcode == ARM::RFEDA || Opcode == ARM::RFEDB ||
> - Opcode == ARM::RFEIA || Opcode == ARM::RFEIB ||
> - Opcode == ARM::RFEDA_UPD || Opcode == ARM::RFEDB_UPD ||
> - Opcode == ARM::RFEIA_UPD || Opcode == ARM::RFEIB_UPD) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - NumOpsAdded = 1;
> - return true;
> - }
> -
> - assert((Opcode == ARM::Bcc || Opcode == ARM::BL || Opcode == ARM::BL_pred
> - || Opcode == ARM::SMC || Opcode == ARM::SVC) &&
> - "Unexpected Opcode");
> -
> - assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Imm operand expected");
> -
> - int Imm32 = 0;
> - if (Opcode == ARM::SMC) {
> - // ZeroExtend(imm4, 32) where imm24 = Inst{3-0}.
> - Imm32 = slice(insn, 3, 0);
> - } else if (Opcode == ARM::SVC) {
> - // ZeroExtend(imm24, 32) where imm24 = Inst{23-0}.
> - Imm32 = slice(insn, 23, 0);
> - } else {
> - // SignExtend(imm24:'00', 32) where imm24 = Inst{23-0}.
> - unsigned Imm26 = slice(insn, 23, 0) << 2;
> - //Imm32 = signextend<signed int, 26>(Imm26);
> - Imm32 = SignExtend32<26>(Imm26);
> - }
> -
> - MI.addOperand(MCOperand::CreateImm(Imm32));
> - NumOpsAdded = 1;
> -
> - return true;
> -}
> -
> -// Misc. Branch Instructions.
> -// BX_RET, MOVPCLR
> -// BLX, BLX_pred, BX, BX_pred
> -// BLXi
> -static bool DisassembleBrMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - // BX_RET and MOVPCLR have only two predicate operands; do an early return.
> - if (Opcode == ARM::BX_RET || Opcode == ARM::MOVPCLR)
> - return true;
> -
> - // BLX and BX take one GPR reg.
> - if (Opcode == ARM::BLX || Opcode == ARM::BLX_pred ||
> - Opcode == ARM::BX || Opcode == ARM::BX_pred) {
> - assert(NumOps >= 1 && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - OpIdx = 1;
> - return true;
> - }
> -
> - // BLXi takes imm32 (the PC offset).
> - if (Opcode == ARM::BLXi) {
> - assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Imm operand expected");
> - // SignExtend(imm24:H:'0', 32) where imm24 = Inst{23-0} and H = Inst{24}.
> - unsigned Imm26 = slice(insn, 23, 0) << 2 | slice(insn, 24, 24) << 1;
> - int Imm32 = SignExtend32<26>(Imm26);
> - MI.addOperand(MCOperand::CreateImm(Imm32));
> - OpIdx = 1;
> - return true;
> - }
> -
> - return false;
> -}
> -
> -static inline bool getBFCInvMask(uint32_t insn, uint32_t &mask) {
> - uint32_t lsb = slice(insn, 11, 7);
> - uint32_t msb = slice(insn, 20, 16);
> - uint32_t Val = 0;
> - if (msb < lsb) {
> - DEBUG(errs() << "Encoding error: msb < lsb\n");
> - return false;
> - }
> -
> - for (uint32_t i = lsb; i <= msb; ++i)
> - Val |= (1 << i);
> - mask = ~Val;
> - return true;
> -}
> -
> -// Standard data-processing instructions allow PC as a register specifier,
> -// but we should reject other DPFrm instructions with PC as registers.
> -static bool BadRegsDPFrm(unsigned Opcode, uint32_t insn) {
> - switch (Opcode) {
> - default:
> - // Did we miss an opcode?
> - if (decodeRd(insn) == 15 || decodeRn(insn) == 15 || decodeRm(insn) == 15) {
> - DEBUG(errs() << "DPFrm with bad reg specifier(s)\n");
> - return true;
> - }
> - case ARM::ADCrr: case ARM::ADDSrr: case ARM::ADDrr: case ARM::ANDrr:
> - case ARM::BICrr: case ARM::CMNzrr: case ARM::CMPrr: case ARM::EORrr:
> - case ARM::ORRrr: case ARM::RSBrr: case ARM::RSCrr: case ARM::SBCrr:
> - case ARM::SUBSrr: case ARM::SUBrr: case ARM::TEQrr: case ARM::TSTrr:
> - return false;
> - }
> -}
> -
> -// A major complication is the fact that some of the saturating add/subtract
> -// operations have Rd Rm Rn, instead of the "normal" Rd Rn Rm.
> -// They are QADD, QDADD, QDSUB, and QSUB.
> -static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - unsigned short NumDefs = MCID.getNumDefs();
> - bool isUnary = isUnaryDP(MCID.TSFlags);
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - // Disassemble register def if there is one.
> - if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> - }
> -
> - // Now disassemble the src operands.
> - if (OpIdx >= NumOps)
> - return false;
> -
> - // Special-case handling of BFC/BFI/SBFX/UBFX.
> - if (Opcode == ARM::BFC || Opcode == ARM::BFI) {
> - // A8.6.17 BFC & A8.6.18 BFI
> - // Sanity check Rd.
> - if (decodeRd(insn) == 15)
> - return false;
> - MI.addOperand(MCOperand::CreateReg(0));
> - if (Opcode == ARM::BFI) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - ++OpIdx;
> - }
> - uint32_t mask = 0;
> - if (!getBFCInvMask(insn, mask))
> - return false;
> -
> - MI.addOperand(MCOperand::CreateImm(mask));
> - OpIdx += 2;
> - return true;
> - }
> - if (Opcode == ARM::SBFX || Opcode == ARM::UBFX) {
> - // Sanity check Rd and Rm.
> - if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
> - return false;
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 11, 7)));
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 16)));
> - OpIdx += 3;
> - return true;
> - }
> -
> - bool RmRn = (Opcode == ARM::QADD || Opcode == ARM::QDADD ||
> - Opcode == ARM::QDSUB || Opcode == ARM::QSUB);
> -
> - // BinaryDP has an Rn operand.
> - if (!isUnary) {
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, ARM::GPRRegClassID,
> - RmRn ? decodeRm(insn) : decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - // If this is a two-address operand, skip it, e.g., MOVCCr operand 1.
> - if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) {
> - MI.addOperand(MCOperand::CreateReg(0));
> - ++OpIdx;
> - }
> -
> - // Now disassemble operand 2.
> - if (OpIdx >= NumOps)
> - return false;
> -
> - if (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) {
> - // We have a reg/reg form.
> - // Assert disabled because saturating operations, e.g., A8.6.127 QASX, are
> - // routed here as well.
> - // assert(getIBit(insn) == 0 && "I_Bit != '0' reg/reg form");
> - if (BadRegsDPFrm(Opcode, insn))
> - return false;
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, ARM::GPRRegClassID,
> - RmRn? decodeRn(insn) : decodeRm(insn))));
> - ++OpIdx;
> - } else if (Opcode == ARM::MOVi16 || Opcode == ARM::MOVTi16) {
> - // These two instructions don't allow d as 15.
> - if (decodeRd(insn) == 15)
> - return false;
> - // We have an imm16 = imm4:imm12 (imm4=Inst{19:16}, imm12 = Inst{11:0}).
> - assert(getIBit(insn) == 1 && "I_Bit != '1' reg/imm form");
> - unsigned Imm16 = slice(insn, 19, 16) << 12 | slice(insn, 11, 0);
> - if (!B->tryAddingSymbolicOperand(Imm16, 4, MI))
> - MI.addOperand(MCOperand::CreateImm(Imm16));
> - ++OpIdx;
> - } else {
> - // We have a reg/imm form.
> - // SOImm is 4-bit rotate amount in bits 11-8 with 8-bit imm in bits 7-0.
> - // A5.2.4 Rotate amount is twice the numeric value of Inst{11-8}.
> - // See also ARMAddressingModes.h: getSOImmValImm() and getSOImmValRot().
> - assert(getIBit(insn) == 1 && "I_Bit != '1' reg/imm form");
> - unsigned Rot = (insn >> ARMII::SoRotImmShift) & 0xF;
> - unsigned Imm = insn & 0xFF;
> - MI.addOperand(MCOperand::CreateImm(ARM_AM::rotr32(Imm, 2*Rot)));
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -static bool DisassembleDPSoRegRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - unsigned short NumDefs = MCID.getNumDefs();
> - bool isUnary = isUnaryDP(MCID.TSFlags);
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - // Disassemble register def if there is one.
> - if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> - }
> -
> - // Disassemble the src operands.
> - if (OpIdx >= NumOps)
> - return false;
> -
> - // BinaryDP has an Rn operand.
> - if (!isUnary) {
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - // If this is a two-address operand, skip it, e.g., MOVCCs operand 1.
> - if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) {
> - MI.addOperand(MCOperand::CreateReg(0));
> - ++OpIdx;
> - }
> -
> - // Disassemble operand 2, which consists of three components.
> - if (OpIdx + 2 >= NumOps)
> - return false;
> -
> - assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) &&
> - (OpInfo[OpIdx+1].RegClass == ARM::GPRRegClassID) &&
> - (OpInfo[OpIdx+2].RegClass < 0) &&
> - "Expect 3 reg operands");
> -
> - // Register-controlled shifts have Inst{7} = 0 and Inst{4} = 1.
> - unsigned Rs = slice(insn, 4, 4);
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - if (Rs) {
> - // If Inst{7} != 0, we should reject this insn as an invalid encoding.
> - if (slice(insn, 7, 7))
> - return false;
> -
> - // A8.6.3 ADC (register-shifted register)
> - // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
> - //
> - // This also accounts for shift instructions (register) where, fortunately,
> - // Inst{19-16} = 0b0000.
> - // A8.6.89 LSL (register)
> - // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
> - if (decodeRd(insn) == 15 || decodeRn(insn) == 15 ||
> - decodeRm(insn) == 15 || decodeRs(insn) == 15)
> - return false;
> -
> - // Register-controlled shifts: [Rm, Rs, shift].
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRs(insn))));
> - // Inst{6-5} encodes the shift opcode.
> - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
> - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, 0)));
> - } else {
> - // Constant shifts: [Rm, reg0, shift_imm].
> - MI.addOperand(MCOperand::CreateReg(0)); // NoRegister
> - // Inst{6-5} encodes the shift opcode.
> - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
> - // Inst{11-7} encodes the imm5 shift amount.
> - unsigned ShImm = slice(insn, 11, 7);
> -
> - // A8.4.1. Possible rrx or shift amount of 32...
> - getImmShiftSE(ShOp, ShImm);
> - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShImm)));
> - }
> - OpIdx += 3;
> -
> - return true;
> -}
> -
> -static bool DisassembleDPSoRegImmFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - unsigned short NumDefs = MCID.getNumDefs();
> - bool isUnary = isUnaryDP(MCID.TSFlags);
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - // Disassemble register def if there is one.
> - if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> - }
> -
> - // Disassemble the src operands.
> - if (OpIdx >= NumOps)
> - return false;
> -
> - // BinaryDP has an Rn operand.
> - if (!isUnary) {
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - // If this is a two-address operand, skip it, e.g., MOVCCs operand 1.
> - if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) {
> - MI.addOperand(MCOperand::CreateReg(0));
> - ++OpIdx;
> - }
> -
> - // Disassemble operand 2, which consists of two components.
> - if (OpIdx + 1 >= NumOps)
> - return false;
> -
> - assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) &&
> - (OpInfo[OpIdx+1].RegClass < 0) &&
> - "Expect 2 reg operands");
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> -
> - // Inst{6-5} encodes the shift opcode.
> - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
> - // Inst{11-7} encodes the imm5 shift amount.
> - unsigned ShImm = slice(insn, 11, 7);
> -
> - // A8.4.1. Possible rrx or shift amount of 32...
> - getImmShiftSE(ShOp, ShImm);
> - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShImm)));
> -
> - OpIdx += 2;
> -
> - return true;
> -}
> -
> -
> -static bool BadRegsLdStFrm(unsigned Opcode, uint32_t insn, bool Store, bool WBack,
> - bool Imm) {
> - const StringRef Name = ARMInsts[Opcode].Name;
> - unsigned Rt = decodeRd(insn);
> - unsigned Rn = decodeRn(insn);
> - unsigned Rm = decodeRm(insn);
> - unsigned P = getPBit(insn);
> - unsigned W = getWBit(insn);
> -
> - if (Store) {
> - // Only STR (immediate, register) allows PC as the source.
> - if (Name.startswith("STRB") && Rt == 15) {
> - DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n");
> - return true;
> - }
> - if (WBack && (Rn == 15 || Rn == Rt)) {
> - DEBUG(errs() << "if wback && (n == 15 || n == t) then UNPREDICTABLE\n");
> - return true;
> - }
> - if (!Imm && Rm == 15) {
> - DEBUG(errs() << "if m == 15 then UNPREDICTABLE\n");
> - return true;
> - }
> - } else {
> - // Only LDR (immediate, register) allows PC as the destination.
> - if (Name.startswith("LDRB") && Rt == 15) {
> - DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n");
> - return true;
> - }
> - if (Imm) {
> - // Immediate
> - if (Rn == 15) {
> - // The literal form must be in offset mode; it's an encoding error
> - // otherwise.
> - if (!(P == 1 && W == 0)) {
> - DEBUG(errs() << "Ld literal form with !(P == 1 && W == 0)\n");
> - return true;
> - }
> - // LDRB (literal) does not allow PC as the destination.
> - if (Opcode != ARM::LDRi12 && Rt == 15) {
> - DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n");
> - return true;
> - }
> - } else {
> - // Write back while Rn == Rt does not make sense.
> - if (WBack && (Rn == Rt)) {
> - DEBUG(errs() << "if wback && n == t then UNPREDICTABLE\n");
> - return true;
> - }
> - }
> - } else {
> - // Register
> - if (Rm == 15) {
> - DEBUG(errs() << "if m == 15 then UNPREDICTABLE\n");
> - return true;
> - }
> - if (WBack && (Rn == 15 || Rn == Rt)) {
> - DEBUG(errs() << "if wback && (n == 15 || n == t) then UNPREDICTABLE\n");
> - return true;
> - }
> - }
> - }
> - return false;
> -}
> -
> -static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - bool isPrePost = isPrePostLdSt(MCID.TSFlags);
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - if (!OpInfo) return false;
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(((!isStore && MCID.getNumDefs() > 0) ||
> - (isStore && (MCID.getNumDefs() == 0 || isPrePost)))
> - && "Invalid arguments");
> -
> - // Operand 0 of a pre- and post-indexed store is the address base writeback.
> - if (isPrePost && isStore) {
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - // Disassemble the dst/src operand.
> - if (OpIdx >= NumOps)
> - return false;
> -
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> -
> - // After dst of a pre- and post-indexed load is the address base writeback.
> - if (isPrePost && !isStore) {
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - // Disassemble the base operand.
> - if (OpIdx >= NumOps)
> - return false;
> -
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1))
> - && "Index mode or tied_to operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> -
> - // For reg/reg form, base reg is followed by +/- reg shop imm.
> - // For immediate form, it is followed by +/- imm12.
> - // See also ARMAddressingModes.h (Addressing Mode #2).
> - if (OpIdx + 1 >= NumOps)
> - return false;
> -
> - if (BadRegsLdStFrm(Opcode, insn, isStore, isPrePost, getIBit(insn)==0))
> - return false;
> -
> - ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
> - unsigned IndexMode =
> - (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
> - if (getIBit(insn) == 0) {
> - // For pre- and post-indexed case, add a reg0 operand (Addressing Mode #2).
> - // Otherwise, skip the reg operand since for addrmode_imm12, Rn has already
> - // been populated.
> - if (isPrePost) {
> - MI.addOperand(MCOperand::CreateReg(0));
> - OpIdx += 1;
> - }
> -
> - unsigned Imm12 = slice(insn, 11, 0);
> - if (Opcode == ARM::LDRBi12 || Opcode == ARM::LDRi12 ||
> - Opcode == ARM::STRBi12 || Opcode == ARM::STRi12) {
> - // Disassemble the 12-bit immediate offset, which is the second operand in
> - // $addrmode_imm12 => (ops GPR:$base, i32imm:$offsimm).
> - int Offset = AddrOpcode == ARM_AM::add ? 1 * Imm12 : -1 * Imm12;
> - MI.addOperand(MCOperand::CreateImm(Offset));
> - } else {
> - // Disassemble the 12-bit immediate offset, which is the second operand in
> - // $am2offset => (ops GPR, i32imm).
> - unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift,
> - IndexMode);
> - MI.addOperand(MCOperand::CreateImm(Offset));
> - }
> - OpIdx += 1;
> - } else {
> - // If Inst{25} = 1 and Inst{4} != 0, we should reject this as invalid.
> - if (slice(insn,4,4) == 1)
> - return false;
> -
> - // Disassemble the offset reg (Rm), shift type, and immediate shift length.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - // Inst{6-5} encodes the shift opcode.
> - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
> - // Inst{11-7} encodes the imm5 shift amount.
> - unsigned ShImm = slice(insn, 11, 7);
> -
> - // A8.4.1. Possible rrx or shift amount of 32...
> - getImmShiftSE(ShOp, ShImm);
> - MI.addOperand(MCOperand::CreateImm(
> - ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp, IndexMode)));
> - OpIdx += 2;
> - }
> -
> - return true;
> -}
> -
> -static bool DisassembleLdFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> - return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, false, B);
> -}
> -
> -static bool DisassembleStFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> - return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true, B);
> -}
> -
> -static bool HasDualReg(unsigned Opcode) {
> - switch (Opcode) {
> - default:
> - return false;
> - case ARM::LDRD: case ARM::LDRD_PRE: case ARM::LDRD_POST:
> - case ARM::STRD: case ARM::STRD_PRE: case ARM::STRD_POST:
> - return true;
> - }
> -}
> -
> -static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - bool isPrePost = isPrePostLdSt(MCID.TSFlags);
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - if (!OpInfo) return false;
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(((!isStore && MCID.getNumDefs() > 0) ||
> - (isStore && (MCID.getNumDefs() == 0 || isPrePost)))
> - && "Invalid arguments");
> -
> - // Operand 0 of a pre- and post-indexed store is the address base writeback.
> - if (isPrePost && isStore) {
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - // Disassemble the dst/src operand.
> - if (OpIdx >= NumOps)
> - return false;
> -
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> -
> - // Fill in LDRD and STRD's second operand Rt operand.
> - if (HasDualReg(Opcode)) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn) + 1)));
> - ++OpIdx;
> - }
> -
> - // After dst of a pre- and post-indexed load is the address base writeback.
> - if (isPrePost && !isStore) {
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - // Disassemble the base operand.
> - if (OpIdx >= NumOps)
> - return false;
> -
> - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> - assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1))
> - && "Offset mode or tied_to operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> -
> - // For reg/reg form, base reg is followed by +/- reg.
> - // For immediate form, it is followed by +/- imm8.
> - if (OpIdx + 1 >= NumOps)
> - return false;
> -
> - unsigned IndexMode =
> - (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
> - ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
> - if (getAM3IBit(insn) == 1) {
> - // FIXME: Conditional while in the midst of refactoring addrmode3. Will
> - // go away entirely when the rest are converted.
> - if (Opcode != ARM::STRHTi && Opcode != ARM::LDRSBTi &&
> - Opcode != ARM::LDRHTi && Opcode != ARM::LDRSHTi) {
> - MI.addOperand(MCOperand::CreateReg(0));
> - ++OpIdx;
> - }
> -
> - // Disassemble the 8-bit immediate offset (postidx_imm8).
> - unsigned Imm4H = (insn >> ARMII::ImmHiShift) & 0xF;
> - unsigned Imm4L = insn & 0xF;
> - unsigned Offset;
> - // FIXME: Remove the 'else' once done w/ addrmode3 refactor.
> - if (Opcode == ARM::STRHTi || Opcode == ARM::LDRSBTi ||
> - Opcode == ARM::LDRHTi || Opcode == ARM::LDRSHTi)
> - Offset = (Imm4H << 4) | Imm4L | (getUBit(insn) << 8);
> - else
> - Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L,
> - IndexMode);
> -
> - MI.addOperand(MCOperand::CreateImm(Offset));
> - ++OpIdx;
> - } else {
> - // Disassemble the offset reg (Rm).
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - // FIXME: Remove the 'else' once done w/ addrmode3 refactor.
> - if (Opcode == ARM::STRHTr || Opcode == ARM::LDRSBTr ||
> - Opcode == ARM::LDRHTr || Opcode == ARM::LDRSHTr)
> - MI.addOperand(MCOperand::CreateImm(getUBit(insn)));
> - else {
> - unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0);
> - MI.addOperand(MCOperand::CreateImm(Offset));
> - }
> - OpIdx += 2;
> - }
> -
> - return true;
> -}
> -
> -static bool DisassembleLdMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> - return DisassembleLdStMiscFrm(MI, Opcode, insn, NumOps, NumOpsAdded, false,
> - B);
> -}
> -
> -static bool DisassembleStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> - return DisassembleLdStMiscFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true, B);
> -}
> -
> -// The algorithm for disassembly of LdStMulFrm is different from others because
> -// it explicitly populates the two predicate operands after the base register.
> -// After that, we need to populate the reglist with each affected register
> -// encoded as an MCOperand.
> -static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 4 && "LdStMulFrm expects NumOps >= 4");
> - NumOpsAdded = 0;
> -
> - unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
> -
> - // Writeback to base, if necessary.
> - if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::STMIA_UPD ||
> - Opcode == ARM::LDMDA_UPD || Opcode == ARM::STMDA_UPD ||
> - Opcode == ARM::LDMDB_UPD || Opcode == ARM::STMDB_UPD ||
> - Opcode == ARM::LDMIB_UPD || Opcode == ARM::STMIB_UPD) {
> - MI.addOperand(MCOperand::CreateReg(Base));
> - ++NumOpsAdded;
> - }
> -
> - // Add the base register operand.
> - MI.addOperand(MCOperand::CreateReg(Base));
> -
> - // Handling the two predicate operands before the reglist.
> - int64_t CondVal = getCondField(insn);
> - if (CondVal == 0xF)
> - return false;
> - MI.addOperand(MCOperand::CreateImm(CondVal));
> - MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
> -
> - NumOpsAdded += 3;
> -
> - // Fill the variadic part of reglist.
> - unsigned RegListBits = insn & ((1 << 16) - 1);
> - for (unsigned i = 0; i < 16; ++i) {
> - if ((RegListBits >> i) & 1) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - i)));
> - ++NumOpsAdded;
> - }
> - }
> -
> - return true;
> -}
> -
> -// LDREX, LDREXB, LDREXH: Rd Rn
> -// LDREXD: Rd Rd+1 Rn
> -// STREX, STREXB, STREXH: Rd Rm Rn
> -// STREXD: Rd Rm Rm+1 Rn
> -//
> -// SWP, SWPB: Rd Rm Rn
> -static bool DisassembleLdStExFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(NumOps >= 2
> - && OpInfo[0].RegClass == ARM::GPRRegClassID
> - && OpInfo[1].RegClass == ARM::GPRRegClassID
> - && "Expect 2 reg operands");
> -
> - bool isStore = slice(insn, 20, 20) == 0;
> - bool isDW = (Opcode == ARM::LDREXD || Opcode == ARM::STREXD);
> -
> - // Add the destination operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> -
> - // Store register Exclusive needs a source operand.
> - if (isStore) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - ++OpIdx;
> -
> - if (isDW) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn)+1)));
> - ++OpIdx;
> - }
> - } else if (isDW) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn)+1)));
> - ++OpIdx;
> - }
> -
> - // Finally add the pointer operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> -
> - return true;
> -}
> -
> -// Misc. Arithmetic Instructions.
> -// CLZ: Rd Rm
> -// PKHBT, PKHTB: Rd Rn Rm , LSL/ASR #imm5
> -// RBIT, REV, REV16, REVSH: Rd Rm
> -static bool DisassembleArithMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(NumOps >= 2
> - && OpInfo[0].RegClass == ARM::GPRRegClassID
> - && OpInfo[1].RegClass == ARM::GPRRegClassID
> - && "Expect 2 reg operands");
> -
> - bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID;
> -
> - // Sanity check the registers, which should not be 15.
> - if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
> - return false;
> - if (ThreeReg && decodeRn(insn) == 15)
> - return false;
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> -
> - if (ThreeReg) {
> - assert(NumOps >= 4 && "Expect >= 4 operands");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - ++OpIdx;
> -
> - // If there is still an operand info left which is an immediate operand, add
> - // an additional imm5 LSL/ASR operand.
> - if (ThreeReg && OpInfo[OpIdx].RegClass < 0
> - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
> - // Extract the 5-bit immediate field Inst{11-7}.
> - unsigned ShiftAmt = (insn >> ARMII::ShiftShift) & 0x1F;
> - if (Opcode == ARM::PKHBT || Opcode == ARM::PKHTB)
> - MI.addOperand(MCOperand::CreateImm(ShiftAmt));
> - else
> - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ARM_AM::no_shift,
> - ShiftAmt)));
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -/// DisassembleSatFrm - Disassemble saturate instructions:
> -/// SSAT, SSAT16, USAT, and USAT16.
> -static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - // A8.6.183 SSAT
> - // if d == 15 || n == 15 then UNPREDICTABLE;
> - if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
> - return false;
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands
> -
> - // Disassemble register def.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> -
> - unsigned Pos = slice(insn, 20, 16);
> - MI.addOperand(MCOperand::CreateImm(Pos));
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> -
> - if (NumOpsAdded == 4) {
> - // Inst{6} encodes the shift type.
> - bool isASR = slice(insn, 6, 6);
> - // Inst{11-7} encodes the imm5 shift amount.
> - unsigned ShAmt = slice(insn, 11, 7);
> - MI.addOperand(MCOperand::CreateImm(isASR << 5 | ShAmt));
> - }
> - return true;
> -}
> -
> -// Extend instructions.
> -// SXT* and UXT*: Rd [Rn] Rm [rot_imm].
> -// The 2nd operand register is Rn and the 3rd operand regsiter is Rm for the
> -// three register operand form. Otherwise, Rn=0b1111 and only Rm is used.
> -static bool DisassembleExtFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - // A8.6.220 SXTAB
> - // if d == 15 || m == 15 then UNPREDICTABLE;
> - if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
> - return false;
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(NumOps >= 2
> - && OpInfo[0].RegClass == ARM::GPRRegClassID
> - && OpInfo[1].RegClass == ARM::GPRRegClassID
> - && "Expect 2 reg operands");
> -
> - bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID;
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - ++OpIdx;
> -
> - if (ThreeReg) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - ++OpIdx;
> -
> - // If there is still an operand info left which is an immediate operand, add
> - // an additional rotate immediate operand.
> - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
> - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
> - // Extract the 2-bit rotate field Inst{11-10}.
> - unsigned rot = (insn >> ARMII::ExtRotImmShift) & 3;
> - MI.addOperand(MCOperand::CreateImm(rot));
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -/////////////////////////////////////
> -// //
> -// Utility Functions For VFP //
> -// //
> -/////////////////////////////////////
> -
> -// Extract/Decode Dd/Sd:
> -//
> -// SP => d = UInt(Vd:D)
> -// DP => d = UInt(D:Vd)
> -static unsigned decodeVFPRd(uint32_t insn, bool isSPVFP) {
> - return isSPVFP ? (decodeRd(insn) << 1 | getDBit(insn))
> - : (decodeRd(insn) | getDBit(insn) << 4);
> -}
> -
> -// Extract/Decode Dn/Sn:
> -//
> -// SP => n = UInt(Vn:N)
> -// DP => n = UInt(N:Vn)
> -static unsigned decodeVFPRn(uint32_t insn, bool isSPVFP) {
> - return isSPVFP ? (decodeRn(insn) << 1 | getNBit(insn))
> - : (decodeRn(insn) | getNBit(insn) << 4);
> -}
> -
> -// Extract/Decode Dm/Sm:
> -//
> -// SP => m = UInt(Vm:M)
> -// DP => m = UInt(M:Vm)
> -static unsigned decodeVFPRm(uint32_t insn, bool isSPVFP) {
> - return isSPVFP ? (decodeRm(insn) << 1 | getMBit(insn))
> - : (decodeRm(insn) | getMBit(insn) << 4);
> -}
> -
> -// A7.5.1
> -static APInt VFPExpandImm(unsigned char byte, unsigned N) {
> - assert(N == 32 || N == 64);
> -
> - uint64_t Result;
> - unsigned bit6 = slice(byte, 6, 6);
> - if (N == 32) {
> - Result = slice(byte, 7, 7) << 31 | slice(byte, 5, 0) << 19;
> - if (bit6)
> - Result |= 0x1f << 25;
> - else
> - Result |= 0x1 << 30;
> - } else {
> - Result = (uint64_t)slice(byte, 7, 7) << 63 |
> - (uint64_t)slice(byte, 5, 0) << 48;
> - if (bit6)
> - Result |= 0xffULL << 54;
> - else
> - Result |= 0x1ULL << 62;
> - }
> - return APInt(N, Result);
> -}
> -
> -// VFP Unary Format Instructions:
> -//
> -// VCMP[E]ZD, VCMP[E]ZS: compares one floating-point register with zero
> -// VCVTDS, VCVTSD: converts between double-precision and single-precision
> -// The rest of the instructions have homogeneous [VFP]Rd and [VFP]Rm registers.
> -static bool DisassembleVFPUnaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 1 && "VFPUnaryFrm expects NumOps >= 1");
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - unsigned RegClass = OpInfo[OpIdx].RegClass;
> - assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) &&
> - "Reg operand expected");
> - bool isSP = (RegClass == ARM::SPRRegClassID);
> -
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RegClass, decodeVFPRd(insn, isSP))));
> - ++OpIdx;
> -
> - // Early return for compare with zero instructions.
> - if (Opcode == ARM::VCMPEZD || Opcode == ARM::VCMPEZS
> - || Opcode == ARM::VCMPZD || Opcode == ARM::VCMPZS)
> - return true;
> -
> - RegClass = OpInfo[OpIdx].RegClass;
> - assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) &&
> - "Reg operand expected");
> - isSP = (RegClass == ARM::SPRRegClassID);
> -
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RegClass, decodeVFPRm(insn, isSP))));
> - ++OpIdx;
> -
> - return true;
> -}
> -
> -// All the instructions have homogeneous [VFP]Rd, [VFP]Rn, and [VFP]Rm regs.
> -// Some of them have operand constraints which tie the first operand in the
> -// InOperandList to that of the dst. As far as asm printing is concerned, this
> -// tied_to operand is simply skipped.
> -static bool DisassembleVFPBinaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 3 && "VFPBinaryFrm expects NumOps >= 3");
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - unsigned RegClass = OpInfo[OpIdx].RegClass;
> - assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) &&
> - "Reg operand expected");
> - bool isSP = (RegClass == ARM::SPRRegClassID);
> -
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RegClass, decodeVFPRd(insn, isSP))));
> - ++OpIdx;
> -
> - // Skip tied_to operand constraint.
> - if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
> - assert(NumOps >= 4 && "Expect >=4 operands");
> - MI.addOperand(MCOperand::CreateReg(0));
> - ++OpIdx;
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RegClass, decodeVFPRn(insn, isSP))));
> - ++OpIdx;
> -
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RegClass, decodeVFPRm(insn, isSP))));
> - ++OpIdx;
> -
> - return true;
> -}
> -
> -// A8.6.295 vcvt (floating-point <-> integer)
> -// Int to FP: VSITOD, VSITOS, VUITOD, VUITOS
> -// FP to Int: VTOSI[Z|R]D, VTOSI[Z|R]S, VTOUI[Z|R]D, VTOUI[Z|R]S
> -//
> -// A8.6.297 vcvt (floating-point and fixed-point)
> -// Dd|Sd Dd|Sd(TIED_TO) #fbits(= 16|32 - UInt(imm4:i))
> -static bool DisassembleVFPConv1Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 2 && "VFPConv1Frm expects NumOps >= 2");
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - if (!OpInfo) return false;
> -
> - bool SP = slice(insn, 8, 8) == 0; // A8.6.295 & A8.6.297
> - bool fixed_point = slice(insn, 17, 17) == 1; // A8.6.297
> - unsigned RegClassID = SP ? ARM::SPRRegClassID : ARM::DPRRegClassID;
> -
> - if (fixed_point) {
> - // A8.6.297
> - assert(NumOps >= 3 && "Expect >= 3 operands");
> - int size = slice(insn, 7, 7) == 0 ? 16 : 32;
> - int fbits = size - (slice(insn,3,0) << 1 | slice(insn,5,5));
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RegClassID,
> - decodeVFPRd(insn, SP))));
> -
> - assert(MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 &&
> - "Tied to operand expected");
> - MI.addOperand(MI.getOperand(0));
> -
> - assert(OpInfo[2].RegClass < 0 && !OpInfo[2].isPredicate() &&
> - !OpInfo[2].isOptionalDef() && "Imm operand expected");
> - MI.addOperand(MCOperand::CreateImm(fbits));
> -
> - NumOpsAdded = 3;
> - } else {
> - // A8.6.295
> - // The Rd (destination) and Rm (source) bits have different interpretations
> - // depending on their single-precisonness.
> - unsigned d, m;
> - if (slice(insn, 18, 18) == 1) { // to_integer operation
> - d = decodeVFPRd(insn, true /* Is Single Precision */);
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, ARM::SPRRegClassID, d)));
> - m = decodeVFPRm(insn, SP);
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, m)));
> - } else {
> - d = decodeVFPRd(insn, SP);
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, d)));
> - m = decodeVFPRm(insn, true /* Is Single Precision */);
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, ARM::SPRRegClassID, m)));
> - }
> - NumOpsAdded = 2;
> - }
> -
> - return true;
> -}
> -
> -// VMOVRS - A8.6.330
> -// Rt => Rd; Sn => UInt(Vn:N)
> -static bool DisassembleVFPConv2Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 2 && "VFPConv2Frm expects NumOps >= 2");
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
> - decodeVFPRn(insn, true))));
> - NumOpsAdded = 2;
> - return true;
> -}
> -
> -// VMOVRRD - A8.6.332
> -// Rt => Rd; Rt2 => Rn; Dm => UInt(M:Vm)
> -//
> -// VMOVRRS - A8.6.331
> -// Rt => Rd; Rt2 => Rn; Sm => UInt(Vm:M); Sm1 = Sm+1
> -static bool DisassembleVFPConv3Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 3 && "VFPConv3Frm expects NumOps >= 3");
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - OpIdx = 2;
> -
> - if (OpInfo[OpIdx].RegClass == ARM::SPRRegClassID) {
> - unsigned Sm = decodeVFPRm(insn, true);
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
> - Sm)));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
> - Sm+1)));
> - OpIdx += 2;
> - } else {
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, ARM::DPRRegClassID,
> - decodeVFPRm(insn, false))));
> - ++OpIdx;
> - }
> - return true;
> -}
> -
> -// VMOVSR - A8.6.330
> -// Rt => Rd; Sn => UInt(Vn:N)
> -static bool DisassembleVFPConv4Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 2 && "VFPConv4Frm expects NumOps >= 2");
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
> - decodeVFPRn(insn, true))));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - NumOpsAdded = 2;
> - return true;
> -}
> -
> -// VMOVDRR - A8.6.332
> -// Rt => Rd; Rt2 => Rn; Dm => UInt(M:Vm)
> -//
> -// VMOVRRS - A8.6.331
> -// Rt => Rd; Rt2 => Rn; Sm => UInt(Vm:M); Sm1 = Sm+1
> -static bool DisassembleVFPConv5Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 3 && "VFPConv5Frm expects NumOps >= 3");
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - if (OpInfo[OpIdx].RegClass == ARM::SPRRegClassID) {
> - unsigned Sm = decodeVFPRm(insn, true);
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
> - Sm)));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
> - Sm+1)));
> - OpIdx += 2;
> - } else {
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, ARM::DPRRegClassID,
> - decodeVFPRm(insn, false))));
> - ++OpIdx;
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - OpIdx += 2;
> - return true;
> -}
> -
> -// VFP Load/Store Instructions.
> -// VLDRD, VLDRS, VSTRD, VSTRS
> -static bool DisassembleVFPLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 3 && "VFPLdStFrm expects NumOps >= 3");
> -
> - bool isSPVFP = (Opcode == ARM::VLDRS || Opcode == ARM::VSTRS);
> - unsigned RegClassID = isSPVFP ? ARM::SPRRegClassID : ARM::DPRRegClassID;
> -
> - // Extract Dd/Sd for operand 0.
> - unsigned RegD = decodeVFPRd(insn, isSPVFP);
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, RegD)));
> -
> - unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
> - MI.addOperand(MCOperand::CreateReg(Base));
> -
> - // Next comes the AM5 Opcode.
> - ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
> - unsigned char Imm8 = insn & 0xFF;
> - MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(AddrOpcode, Imm8)));
> -
> - NumOpsAdded = 3;
> -
> - return true;
> -}
> -
> -// VFP Load/Store Multiple Instructions.
> -// We have an optional write back reg, the base, and two predicate operands.
> -// It is then followed by a reglist of either DPR(s) or SPR(s).
> -//
> -// VLDMD[_UPD], VLDMS[_UPD], VSTMD[_UPD], VSTMS[_UPD]
> -static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 4 && "VFPLdStMulFrm expects NumOps >= 4");
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
> -
> - // Writeback to base, if necessary.
> - if (Opcode == ARM::VLDMDIA_UPD || Opcode == ARM::VLDMSIA_UPD ||
> - Opcode == ARM::VLDMDDB_UPD || Opcode == ARM::VLDMSDB_UPD ||
> - Opcode == ARM::VSTMDIA_UPD || Opcode == ARM::VSTMSIA_UPD ||
> - Opcode == ARM::VSTMDDB_UPD || Opcode == ARM::VSTMSDB_UPD) {
> - MI.addOperand(MCOperand::CreateReg(Base));
> - ++OpIdx;
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(Base));
> -
> - // Handling the two predicate operands before the reglist.
> - int64_t CondVal = getCondField(insn);
> - if (CondVal == 0xF)
> - return false;
> - MI.addOperand(MCOperand::CreateImm(CondVal));
> - MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
> -
> - OpIdx += 3;
> -
> - bool isSPVFP = (Opcode == ARM::VLDMSIA ||
> - Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMSDB_UPD ||
> - Opcode == ARM::VSTMSIA ||
> - Opcode == ARM::VSTMSIA_UPD || Opcode == ARM::VSTMSDB_UPD);
> - unsigned RegClassID = isSPVFP ? ARM::SPRRegClassID : ARM::DPRRegClassID;
> -
> - // Extract Dd/Sd.
> - unsigned RegD = decodeVFPRd(insn, isSPVFP);
> -
> - // Fill the variadic part of reglist.
> - unsigned char Imm8 = insn & 0xFF;
> - unsigned Regs = isSPVFP ? Imm8 : Imm8/2;
> -
> - // Apply some sanity checks before proceeding.
> - if (Regs == 0 || (RegD + Regs) > 32 || (!isSPVFP && Regs > 16))
> - return false;
> -
> - for (unsigned i = 0; i < Regs; ++i) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID,
> - RegD + i)));
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -// Misc. VFP Instructions.
> -// FMSTAT (vmrs with Rt=0b1111, i.e., to apsr_nzcv and no register operand)
> -// FCONSTD (DPR and a VFPf64Imm operand)
> -// FCONSTS (SPR and a VFPf32Imm operand)
> -// VMRS/VMSR (GPR operand)
> -static bool DisassembleVFPMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - if (Opcode == ARM::FMSTAT)
> - return true;
> -
> - assert(NumOps >= 2 && "VFPMiscFrm expects >=2 operands");
> -
> - unsigned RegEnum = 0;
> - switch (OpInfo[0].RegClass) {
> - case ARM::DPRRegClassID:
> - RegEnum = getRegisterEnum(B, ARM::DPRRegClassID, decodeVFPRd(insn, false));
> - break;
> - case ARM::SPRRegClassID:
> - RegEnum = getRegisterEnum(B, ARM::SPRRegClassID, decodeVFPRd(insn, true));
> - break;
> - case ARM::GPRRegClassID:
> - RegEnum = getRegisterEnum(B, ARM::GPRRegClassID, decodeRd(insn));
> - break;
> - default:
> - assert(0 && "Invalid reg class id");
> - return false;
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(RegEnum));
> - ++OpIdx;
> -
> - // Extract/decode the f64/f32 immediate.
> - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
> - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
> - // The asm syntax specifies the floating point value, not the 8-bit literal.
> - APInt immRaw = VFPExpandImm(slice(insn,19,16) << 4 | slice(insn, 3, 0),
> - Opcode == ARM::FCONSTD ? 64 : 32);
> - APFloat immFP = APFloat(immRaw, true);
> - double imm = Opcode == ARM::FCONSTD ? immFP.convertToDouble() :
> - immFP.convertToFloat();
> - MI.addOperand(MCOperand::CreateFPImm(imm));
> -
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -// DisassembleThumbFrm() is defined in ThumbDisassemblerCore.h file.
> -#include "ThumbDisassemblerCore.h"
> -
> -/////////////////////////////////////////////////////
> -// //
> -// Utility Functions For ARM Advanced SIMD //
> -// //
> -/////////////////////////////////////////////////////
> -
> -// The following NEON namings are based on A8.6.266 VABA, VABAL. Notice that
> -// A8.6.303 VDUP (ARM core register)'s D/Vd pair is the N/Vn pair of VABA/VABAL.
> -
> -// A7.3 Register encoding
> -
> -// Extract/Decode NEON D/Vd:
> -//
> -// Note that for quadword, Qd = UInt(D:Vd<3:1>) = Inst{22:15-13}, whereas for
> -// doubleword, Dd = UInt(D:Vd). We compensate for this difference by
> -// handling it in the getRegisterEnum() utility function.
> -// D = Inst{22}, Vd = Inst{15-12}
> -static unsigned decodeNEONRd(uint32_t insn) {
> - return ((insn >> ARMII::NEON_D_BitShift) & 1) << 4
> - | ((insn >> ARMII::NEON_RegRdShift) & ARMII::NEONRegMask);
> -}
> -
> -// Extract/Decode NEON N/Vn:
> -//
> -// Note that for quadword, Qn = UInt(N:Vn<3:1>) = Inst{7:19-17}, whereas for
> -// doubleword, Dn = UInt(N:Vn). We compensate for this difference by
> -// handling it in the getRegisterEnum() utility function.
> -// N = Inst{7}, Vn = Inst{19-16}
> -static unsigned decodeNEONRn(uint32_t insn) {
> - return ((insn >> ARMII::NEON_N_BitShift) & 1) << 4
> - | ((insn >> ARMII::NEON_RegRnShift) & ARMII::NEONRegMask);
> -}
> -
> -// Extract/Decode NEON M/Vm:
> -//
> -// Note that for quadword, Qm = UInt(M:Vm<3:1>) = Inst{5:3-1}, whereas for
> -// doubleword, Dm = UInt(M:Vm). We compensate for this difference by
> -// handling it in the getRegisterEnum() utility function.
> -// M = Inst{5}, Vm = Inst{3-0}
> -static unsigned decodeNEONRm(uint32_t insn) {
> - return ((insn >> ARMII::NEON_M_BitShift) & 1) << 4
> - | ((insn >> ARMII::NEON_RegRmShift) & ARMII::NEONRegMask);
> -}
> -
> -namespace {
> -enum ElemSize {
> - ESizeNA = 0,
> - ESize8 = 8,
> - ESize16 = 16,
> - ESize32 = 32,
> - ESize64 = 64
> -};
> -} // End of unnamed namespace
> -
> -// size field -> Inst{11-10}
> -// index_align field -> Inst{7-4}
> -//
> -// The Lane Index interpretation depends on the Data Size:
> -// 8 (encoded as size = 0b00) -> Index = index_align[3:1]
> -// 16 (encoded as size = 0b01) -> Index = index_align[3:2]
> -// 32 (encoded as size = 0b10) -> Index = index_align[3]
> -//
> -// Ref: A8.6.317 VLD4 (single 4-element structure to one lane).
> -static unsigned decodeLaneIndex(uint32_t insn) {
> - unsigned size = insn >> 10 & 3;
> - assert((size == 0 || size == 1 || size == 2) &&
> - "Encoding error: size should be either 0, 1, or 2");
> -
> - unsigned index_align = insn >> 4 & 0xF;
> - return (index_align >> 1) >> size;
> -}
> -
> -// imm64 = AdvSIMDExpandImm(op, cmode, i:imm3:imm4)
> -// op = Inst{5}, cmode = Inst{11-8}
> -// i = Inst{24} (ARM architecture)
> -// imm3 = Inst{18-16}, imm4 = Inst{3-0}
> -// Ref: Table A7-15 Modified immediate values for Advanced SIMD instructions.
> -static uint64_t decodeN1VImm(uint32_t insn, ElemSize esize) {
> - unsigned char op = (insn >> 5) & 1;
> - unsigned char cmode = (insn >> 8) & 0xF;
> - unsigned char Imm8 = ((insn >> 24) & 1) << 7 |
> - ((insn >> 16) & 7) << 4 |
> - (insn & 0xF);
> - return (op << 12) | (cmode << 8) | Imm8;
> -}
> -
> -// A8.6.339 VMUL, VMULL (by scalar)
> -// ESize16 => m = Inst{2-0} (Vm<2:0>) D0-D7
> -// ESize32 => m = Inst{3-0} (Vm<3:0>) D0-D15
> -static unsigned decodeRestrictedDm(uint32_t insn, ElemSize esize) {
> - switch (esize) {
> - case ESize16:
> - return insn & 7;
> - case ESize32:
> - return insn & 0xF;
> - default:
> - assert(0 && "Unreachable code!");
> - return 0;
> - }
> -}
> -
> -// A8.6.339 VMUL, VMULL (by scalar)
> -// ESize16 => index = Inst{5:3} (M:Vm<3>) D0-D7
> -// ESize32 => index = Inst{5} (M) D0-D15
> -static unsigned decodeRestrictedDmIndex(uint32_t insn, ElemSize esize) {
> - switch (esize) {
> - case ESize16:
> - return (((insn >> 5) & 1) << 1) | ((insn >> 3) & 1);
> - case ESize32:
> - return (insn >> 5) & 1;
> - default:
> - assert(0 && "Unreachable code!");
> - return 0;
> - }
> -}
> -
> -// A8.6.296 VCVT (between floating-point and fixed-point, Advanced SIMD)
> -// (64 - <fbits>) is encoded as imm6, i.e., Inst{21-16}.
> -static unsigned decodeVCVTFractionBits(uint32_t insn) {
> - return 64 - ((insn >> 16) & 0x3F);
> -}
> -
> -// A8.6.302 VDUP (scalar)
> -// ESize8 => index = Inst{19-17}
> -// ESize16 => index = Inst{19-18}
> -// ESize32 => index = Inst{19}
> -static unsigned decodeNVLaneDupIndex(uint32_t insn, ElemSize esize) {
> - switch (esize) {
> - case ESize8:
> - return (insn >> 17) & 7;
> - case ESize16:
> - return (insn >> 18) & 3;
> - case ESize32:
> - return (insn >> 19) & 1;
> - default:
> - assert(0 && "Unspecified element size!");
> - return 0;
> - }
> -}
> -
> -// A8.6.328 VMOV (ARM core register to scalar)
> -// A8.6.329 VMOV (scalar to ARM core register)
> -// ESize8 => index = Inst{21:6-5}
> -// ESize16 => index = Inst{21:6}
> -// ESize32 => index = Inst{21}
> -static unsigned decodeNVLaneOpIndex(uint32_t insn, ElemSize esize) {
> - switch (esize) {
> - case ESize8:
> - return ((insn >> 21) & 1) << 2 | ((insn >> 5) & 3);
> - case ESize16:
> - return ((insn >> 21) & 1) << 1 | ((insn >> 6) & 1);
> - case ESize32:
> - return ((insn >> 21) & 1);
> - default:
> - assert(0 && "Unspecified element size!");
> - return 0;
> - }
> -}
> -
> -// Imm6 = Inst{21-16}, L = Inst{7}
> -//
> -// LeftShift == true (A8.6.367 VQSHL, A8.6.387 VSLI):
> -// case L:imm6 of
> -// '0001xxx' => esize = 8; shift_amount = imm6 - 8
> -// '001xxxx' => esize = 16; shift_amount = imm6 - 16
> -// '01xxxxx' => esize = 32; shift_amount = imm6 - 32
> -// '1xxxxxx' => esize = 64; shift_amount = imm6
> -//
> -// LeftShift == false (A8.6.376 VRSHR, A8.6.368 VQSHRN):
> -// case L:imm6 of
> -// '0001xxx' => esize = 8; shift_amount = 16 - imm6
> -// '001xxxx' => esize = 16; shift_amount = 32 - imm6
> -// '01xxxxx' => esize = 32; shift_amount = 64 - imm6
> -// '1xxxxxx' => esize = 64; shift_amount = 64 - imm6
> -//
> -static unsigned decodeNVSAmt(uint32_t insn, bool LeftShift) {
> - ElemSize esize = ESizeNA;
> - unsigned L = (insn >> 7) & 1;
> - unsigned imm6 = (insn >> 16) & 0x3F;
> - if (L == 0) {
> - if (imm6 >> 3 == 1)
> - esize = ESize8;
> - else if (imm6 >> 4 == 1)
> - esize = ESize16;
> - else if (imm6 >> 5 == 1)
> - esize = ESize32;
> - else
> - assert(0 && "Wrong encoding of Inst{7:21-16}!");
> - } else
> - esize = ESize64;
> -
> - if (LeftShift)
> - return esize == ESize64 ? imm6 : (imm6 - esize);
> - else
> - return esize == ESize64 ? (esize - imm6) : (2*esize - imm6);
> -}
> -
> -// A8.6.305 VEXT
> -// Imm4 = Inst{11-8}
> -static unsigned decodeN3VImm(uint32_t insn) {
> - return (insn >> 8) & 0xF;
> -}
> -
> -// VLD*
> -// D[d] D[d2] ... Rn [TIED_TO Rn] align [Rm]
> -// VLD*LN*
> -// D[d] D[d2] ... Rn [TIED_TO Rn] align [Rm] TIED_TO ... imm(idx)
> -// VST*
> -// Rn [TIED_TO Rn] align [Rm] D[d] D[d2] ...
> -// VST*LN*
> -// Rn [TIED_TO Rn] align [Rm] D[d] D[d2] ... [imm(idx)]
> -//
> -// Correctly set VLD*/VST*'s TIED_TO GPR, as the asm printer needs it.
> -static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, bool Store, bool DblSpaced,
> - unsigned alignment, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> -
> - // At least one DPR register plus addressing mode #6.
> - assert(NumOps >= 3 && "Expect >= 3 operands");
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - // We have homogeneous NEON registers for Load/Store.
> - unsigned RegClass = 0;
> -
> - // Double-spaced registers have increments of 2.
> - unsigned Inc = DblSpaced ? 2 : 1;
> -
> - unsigned Rn = decodeRn(insn);
> - unsigned Rm = decodeRm(insn);
> - unsigned Rd = decodeNEONRd(insn);
> -
> - // A7.7.1 Advanced SIMD addressing mode.
> - bool WB = Rm != 15;
> -
> - // LLVM Addressing Mode #6.
> - unsigned RmEnum = 0;
> - if (WB && Rm != 13)
> - RmEnum = getRegisterEnum(B, ARM::GPRRegClassID, Rm);
> -
> - if (Store) {
> - // Consume possible WB, AddrMode6, possible increment reg, the DPR/QPR's,
> - // then possible lane index.
> - assert(OpIdx < NumOps && OpInfo[0].RegClass == ARM::GPRRegClassID &&
> - "Reg operand expected");
> -
> - if (WB) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - Rn)));
> - ++OpIdx;
> - }
> -
> - assert((OpIdx+1) < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - OpInfo[OpIdx + 1].RegClass < 0 && "Addrmode #6 Operands expected");
> - // addrmode6 := (ops GPR:$addr, i32imm)
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - Rn)));
> - MI.addOperand(MCOperand::CreateImm(alignment)); // Alignment
> - OpIdx += 2;
> -
> - if (WB) {
> - MI.addOperand(MCOperand::CreateReg(RmEnum));
> - ++OpIdx;
> - }
> -
> - assert(OpIdx < NumOps &&
> - (OpInfo[OpIdx].RegClass == ARM::DPRRegClassID ||
> - OpInfo[OpIdx].RegClass == ARM::QPRRegClassID) &&
> - "Reg operand expected");
> -
> - RegClass = OpInfo[OpIdx].RegClass;
> - while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) {
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RegClass, Rd)));
> - Rd += Inc;
> - ++OpIdx;
> - }
> -
> - // Handle possible lane index.
> - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
> - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
> - MI.addOperand(MCOperand::CreateImm(decodeLaneIndex(insn)));
> - ++OpIdx;
> - }
> -
> - } else {
> - // Consume the DPR/QPR's, possible WB, AddrMode6, possible incrment reg,
> - // possible TIED_TO DPR/QPR's (ignored), then possible lane index.
> - RegClass = OpInfo[0].RegClass;
> -
> - while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) {
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RegClass, Rd)));
> - Rd += Inc;
> - ++OpIdx;
> - }
> -
> - if (WB) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - Rn)));
> - ++OpIdx;
> - }
> -
> - assert((OpIdx+1) < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
> - OpInfo[OpIdx + 1].RegClass < 0 && "Addrmode #6 Operands expected");
> - // addrmode6 := (ops GPR:$addr, i32imm)
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - Rn)));
> - MI.addOperand(MCOperand::CreateImm(alignment)); // Alignment
> - OpIdx += 2;
> -
> - if (WB) {
> - MI.addOperand(MCOperand::CreateReg(RmEnum));
> - ++OpIdx;
> - }
> -
> - while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) {
> - assert(MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1 &&
> - "Tied to operand expected");
> - MI.addOperand(MCOperand::CreateReg(0));
> - ++OpIdx;
> - }
> -
> - // Handle possible lane index.
> - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
> - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
> - MI.addOperand(MCOperand::CreateImm(decodeLaneIndex(insn)));
> - ++OpIdx;
> - }
> - }
> -
> - // Accessing registers past the end of the NEON register file is not
> - // defined.
> - if (Rd > 32)
> - return false;
> -
> - return true;
> -}
> -
> -// A8.6.308, A8.6.311, A8.6.314, A8.6.317.
> -static bool Align4OneLaneInst(unsigned elem, unsigned size,
> - unsigned index_align, unsigned & alignment) {
> - unsigned bits = 0;
> - switch (elem) {
> - default:
> - return false;
> - case 1:
> - // A8.6.308
> - if (size == 0)
> - return slice(index_align, 0, 0) == 0;
> - else if (size == 1) {
> - bits = slice(index_align, 1, 0);
> - if (bits != 0 && bits != 1)
> - return false;
> - if (bits == 1)
> - alignment = 16;
> - return true;
> - } else if (size == 2) {
> - bits = slice(index_align, 2, 0);
> - if (bits != 0 && bits != 3)
> - return false;
> - if (bits == 3)
> - alignment = 32;
> - return true;;
> - }
> - return true;
> - case 2:
> - // A8.6.311
> - if (size == 0) {
> - if (slice(index_align, 0, 0) == 1)
> - alignment = 16;
> - return true;
> - } if (size == 1) {
> - if (slice(index_align, 0, 0) == 1)
> - alignment = 32;
> - return true;
> - } else if (size == 2) {
> - if (slice(index_align, 1, 1) != 0)
> - return false;
> - if (slice(index_align, 0, 0) == 1)
> - alignment = 64;
> - return true;;
> - }
> - return true;
> - case 3:
> - // A8.6.314
> - if (size == 0) {
> - if (slice(index_align, 0, 0) != 0)
> - return false;
> - return true;
> - } if (size == 1) {
> - if (slice(index_align, 0, 0) != 0)
> - return false;
> - return true;
> - return true;
> - } else if (size == 2) {
> - if (slice(index_align, 1, 0) != 0)
> - return false;
> - return true;;
> - }
> - return true;
> - case 4:
> - // A8.6.317
> - if (size == 0) {
> - if (slice(index_align, 0, 0) == 1)
> - alignment = 32;
> - return true;
> - } if (size == 1) {
> - if (slice(index_align, 0, 0) == 1)
> - alignment = 64;
> - return true;
> - } else if (size == 2) {
> - bits = slice(index_align, 1, 0);
> - if (bits == 3)
> - return false;
> - if (bits == 1)
> - alignment = 64;
> - else if (bits == 2)
> - alignment = 128;
> - return true;;
> - }
> - return true;
> - }
> -}
> -
> -// A7.7
> -// If L (Inst{21}) == 0, store instructions.
> -// Find out about double-spaced-ness of the Opcode and pass it on to
> -// DisassembleNLdSt0().
> -static bool DisassembleNLdSt(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const StringRef Name = ARMInsts[Opcode].Name;
> - bool DblSpaced = false;
> - // 0 represents standard alignment, i.e., unaligned data access.
> - unsigned alignment = 0;
> -
> - unsigned elem = 0; // legal values: {1, 2, 3, 4}
> - if (Name.startswith("VST1") || Name.startswith("VLD1"))
> - elem = 1;
> -
> - if (Name.startswith("VST2") || Name.startswith("VLD2"))
> - elem = 2;
> -
> - if (Name.startswith("VST3") || Name.startswith("VLD3"))
> - elem = 3;
> -
> - if (Name.startswith("VST4") || Name.startswith("VLD4"))
> - elem = 4;
> -
> - if (Name.find("LN") != std::string::npos) {
> - // To one lane instructions.
> - // See, for example, 8.6.317 VLD4 (single 4-element structure to one lane).
> -
> - // Utility function takes number of elements, size, and index_align.
> - if (!Align4OneLaneInst(elem,
> - slice(insn, 11, 10),
> - slice(insn, 7, 4),
> - alignment))
> - return false;
> -
> - // <size> == 16 && Inst{5} == 1 --> DblSpaced = true
> - if (Name.endswith("16") || Name.endswith("16_UPD"))
> - DblSpaced = slice(insn, 5, 5) == 1;
> -
> - // <size> == 32 && Inst{6} == 1 --> DblSpaced = true
> - if (Name.endswith("32") || Name.endswith("32_UPD"))
> - DblSpaced = slice(insn, 6, 6) == 1;
> - } else if (Name.find("DUP") != std::string::npos) {
> - // Single element (or structure) to all lanes.
> - // Inst{9-8} encodes the number of element(s) in the structure, with:
> - // 0b00 (VLD1DUP) (for this, a bit makes sense only for data size 16 and 32.
> - // 0b01 (VLD2DUP)
> - // 0b10 (VLD3DUP) (for this, a bit must be encoded as 0)
> - // 0b11 (VLD4DUP)
> - //
> - // Inst{7-6} encodes the data size, with:
> - // 0b00 => 8, 0b01 => 16, 0b10 => 32
> - //
> - // Inst{4} (the a bit) encodes the align action (0: standard alignment)
> - unsigned elem = slice(insn, 9, 8) + 1;
> - unsigned a = slice(insn, 4, 4);
> - if (elem != 3) {
> - // 0b11 is not a valid encoding for Inst{7-6}.
> - if (slice(insn, 7, 6) == 3)
> - return false;
> - unsigned data_size = 8 << slice(insn, 7, 6);
> - // For VLD1DUP, a bit makes sense only for data size of 16 and 32.
> - if (a && data_size == 8)
> - return false;
> -
> - // Now we can calculate the alignment!
> - if (a)
> - alignment = elem * data_size;
> - } else {
> - if (a) {
> - // A8.6.315 VLD3 (single 3-element structure to all lanes)
> - // The a bit must be encoded as 0.
> - return false;
> - }
> - }
> - } else {
> - // Multiple n-element structures with type encoded as Inst{11-8}.
> - // See, for example, A8.6.316 VLD4 (multiple 4-element structures).
> -
> - // Inst{5-4} encodes alignment.
> - unsigned align = slice(insn, 5, 4);
> - switch (align) {
> - default:
> - break;
> - case 1:
> - alignment = 64; break;
> - case 2:
> - alignment = 128; break;
> - case 3:
> - alignment = 256; break;
> - }
> -
> - unsigned type = slice(insn, 11, 8);
> - // Reject UNDEFINED instructions based on type and align.
> - // Plus set DblSpaced flag where appropriate.
> - switch (elem) {
> - default:
> - break;
> - case 1:
> - // n == 1
> - // A8.6.307 & A8.6.391
> - if ((type == 7 && slice(align, 1, 1) == 1) ||
> - (type == 10 && align == 3) ||
> - (type == 6 && slice(align, 1, 1) == 1))
> - return false;
> - break;
> - case 2:
> - // n == 2 && type == 0b1001 -> DblSpaced = true
> - // A8.6.310 & A8.6.393
> - if ((type == 8 || type == 9) && align == 3)
> - return false;
> - DblSpaced = (type == 9);
> - break;
> - case 3:
> - // n == 3 && type == 0b0101 -> DblSpaced = true
> - // A8.6.313 & A8.6.395
> - if (slice(insn, 7, 6) == 3 || slice(align, 1, 1) == 1)
> - return false;
> - DblSpaced = (type == 5);
> - break;
> - case 4:
> - // n == 4 && type == 0b0001 -> DblSpaced = true
> - // A8.6.316 & A8.6.397
> - if (slice(insn, 7, 6) == 3)
> - return false;
> - DblSpaced = (type == 1);
> - break;
> - }
> - }
> - return DisassembleNLdSt0(MI, Opcode, insn, NumOps, NumOpsAdded,
> - slice(insn, 21, 21) == 0, DblSpaced, alignment/8, B);
> -}
> -
> -// VMOV (immediate)
> -// Qd/Dd imm
> -// VBIC (immediate)
> -// VORR (immediate)
> -// Qd/Dd imm src(=Qd/Dd)
> -static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> -
> - assert(NumOps >= 2 &&
> - (OpInfo[0].RegClass == ARM::DPRRegClassID ||
> - OpInfo[0].RegClass == ARM::QPRRegClassID) &&
> - (OpInfo[1].RegClass < 0) &&
> - "Expect 1 reg operand followed by 1 imm operand");
> -
> - // Qd/Dd = Inst{22:15-12} => NEON Rd
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[0].RegClass,
> - decodeNEONRd(insn))));
> -
> - ElemSize esize = ESizeNA;
> - switch (Opcode) {
> - case ARM::VMOVv8i8:
> - case ARM::VMOVv16i8:
> - esize = ESize8;
> - break;
> - case ARM::VMOVv4i16:
> - case ARM::VMOVv8i16:
> - case ARM::VMVNv4i16:
> - case ARM::VMVNv8i16:
> - case ARM::VBICiv4i16:
> - case ARM::VBICiv8i16:
> - case ARM::VORRiv4i16:
> - case ARM::VORRiv8i16:
> - esize = ESize16;
> - break;
> - case ARM::VMOVv2i32:
> - case ARM::VMOVv4i32:
> - case ARM::VMVNv2i32:
> - case ARM::VMVNv4i32:
> - case ARM::VBICiv2i32:
> - case ARM::VBICiv4i32:
> - case ARM::VORRiv2i32:
> - case ARM::VORRiv4i32:
> - esize = ESize32;
> - break;
> - case ARM::VMOVv1i64:
> - case ARM::VMOVv2i64:
> - esize = ESize64;
> - break;
> - default:
> - assert(0 && "Unexpected opcode!");
> - return false;
> - }
> -
> - // One register and a modified immediate value.
> - // Add the imm operand.
> - MI.addOperand(MCOperand::CreateImm(decodeN1VImm(insn, esize)));
> -
> - NumOpsAdded = 2;
> -
> - // VBIC/VORRiv*i* variants have an extra $src = $Vd to be filled in.
> - if (NumOps >= 3 &&
> - (OpInfo[2].RegClass == ARM::DPRRegClassID ||
> - OpInfo[2].RegClass == ARM::QPRRegClassID)) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[0].RegClass,
> - decodeNEONRd(insn))));
> - NumOpsAdded += 1;
> - }
> -
> - return true;
> -}
> -
> -namespace {
> -enum N2VFlag {
> - N2V_None,
> - N2V_VectorDupLane,
> - N2V_VectorConvert_Between_Float_Fixed
> -};
> -} // End of unnamed namespace
> -
> -// Vector Convert [between floating-point and fixed-point]
> -// Qd/Dd Qm/Dm [fbits]
> -//
> -// Vector Duplicate Lane (from scalar to all elements) Instructions.
> -// VDUPLN16d, VDUPLN16q, VDUPLN32d, VDUPLN32q, VDUPLN8d, VDUPLN8q:
> -// Qd/Dd Dm index
> -//
> -// Vector Move Long:
> -// Qd Dm
> -//
> -// Vector Move Narrow:
> -// Dd Qm
> -//
> -// Others
> -static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, N2VFlag Flag, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opc];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> -
> - assert(NumOps >= 2 &&
> - (OpInfo[0].RegClass == ARM::DPRRegClassID ||
> - OpInfo[0].RegClass == ARM::QPRRegClassID) &&
> - (OpInfo[1].RegClass == ARM::DPRRegClassID ||
> - OpInfo[1].RegClass == ARM::QPRRegClassID) &&
> - "Expect >= 2 operands and first 2 as reg operands");
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - ElemSize esize = ESizeNA;
> - if (Flag == N2V_VectorDupLane) {
> - // VDUPLN has its index embedded. Its size can be inferred from the Opcode.
> - assert(Opc >= ARM::VDUPLN16d && Opc <= ARM::VDUPLN8q &&
> - "Unexpected Opcode");
> - esize = (Opc == ARM::VDUPLN8d || Opc == ARM::VDUPLN8q) ? ESize8
> - : ((Opc == ARM::VDUPLN16d || Opc == ARM::VDUPLN16q) ? ESize16
> - : ESize32);
> - }
> -
> - // Qd/Dd = Inst{22:15-12} => NEON Rd
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - decodeNEONRd(insn))));
> - ++OpIdx;
> -
> - // VPADAL...
> - if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
> - // TIED_TO operand.
> - MI.addOperand(MCOperand::CreateReg(0));
> - ++OpIdx;
> - }
> -
> - // Dm = Inst{5:3-0} => NEON Rm
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - decodeNEONRm(insn))));
> - ++OpIdx;
> -
> - // VZIP and others have two TIED_TO reg operands.
> - int Idx;
> - while (OpIdx < NumOps &&
> - (Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
> - // Add TIED_TO operand.
> - MI.addOperand(MI.getOperand(Idx));
> - ++OpIdx;
> - }
> -
> - // Add the imm operand, if required.
> - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
> - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
> -
> - unsigned imm = 0xFFFFFFFF;
> -
> - if (Flag == N2V_VectorDupLane)
> - imm = decodeNVLaneDupIndex(insn, esize);
> - if (Flag == N2V_VectorConvert_Between_Float_Fixed)
> - imm = decodeVCVTFractionBits(insn);
> -
> - assert(imm != 0xFFFFFFFF && "Internal error");
> - MI.addOperand(MCOperand::CreateImm(imm));
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -static bool DisassembleN2RegFrm(MCInst &MI, unsigned Opc, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
> - N2V_None, B);
> -}
> -static bool DisassembleNVCVTFrm(MCInst &MI, unsigned Opc, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
> - N2V_VectorConvert_Between_Float_Fixed, B);
> -}
> -static bool DisassembleNVecDupLnFrm(MCInst &MI, unsigned Opc, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
> - N2V_VectorDupLane, B);
> -}
> -
> -// Vector Shift [Accumulate] Instructions.
> -// Qd/Dd [Qd/Dd (TIED_TO)] Qm/Dm ShiftAmt
> -//
> -// Vector Shift Left Long (with maximum shift count) Instructions.
> -// VSHLLi16, VSHLLi32, VSHLLi8: Qd Dm imm (== size)
> -//
> -static bool DisassembleNVectorShift(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, bool LeftShift, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> -
> - assert(NumOps >= 3 &&
> - (OpInfo[0].RegClass == ARM::DPRRegClassID ||
> - OpInfo[0].RegClass == ARM::QPRRegClassID) &&
> - (OpInfo[1].RegClass == ARM::DPRRegClassID ||
> - OpInfo[1].RegClass == ARM::QPRRegClassID) &&
> - "Expect >= 3 operands and first 2 as reg operands");
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - // Qd/Dd = Inst{22:15-12} => NEON Rd
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - decodeNEONRd(insn))));
> - ++OpIdx;
> -
> - if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
> - // TIED_TO operand.
> - MI.addOperand(MCOperand::CreateReg(0));
> - ++OpIdx;
> - }
> -
> - assert((OpInfo[OpIdx].RegClass == ARM::DPRRegClassID ||
> - OpInfo[OpIdx].RegClass == ARM::QPRRegClassID) &&
> - "Reg operand expected");
> -
> - // Qm/Dm = Inst{5:3-0} => NEON Rm
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - decodeNEONRm(insn))));
> - ++OpIdx;
> -
> - assert(OpInfo[OpIdx].RegClass < 0 && "Imm operand expected");
> -
> - // Add the imm operand.
> -
> - // VSHLL has maximum shift count as the imm, inferred from its size.
> - unsigned Imm;
> - switch (Opcode) {
> - default:
> - Imm = decodeNVSAmt(insn, LeftShift);
> - break;
> - case ARM::VSHLLi8:
> - Imm = 8;
> - break;
> - case ARM::VSHLLi16:
> - Imm = 16;
> - break;
> - case ARM::VSHLLi32:
> - Imm = 32;
> - break;
> - }
> - MI.addOperand(MCOperand::CreateImm(Imm));
> - ++OpIdx;
> -
> - return true;
> -}
> -
> -// Left shift instructions.
> -static bool DisassembleN2RegVecShLFrm(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, true,
> - B);
> -}
> -// Right shift instructions have different shift amount interpretation.
> -static bool DisassembleN2RegVecShRFrm(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, false,
> - B);
> -}
> -
> -namespace {
> -enum N3VFlag {
> - N3V_None,
> - N3V_VectorExtract,
> - N3V_VectorShift,
> - N3V_Multiply_By_Scalar
> -};
> -} // End of unnamed namespace
> -
> -// NEON Three Register Instructions with Optional Immediate Operand
> -//
> -// Vector Extract Instructions.
> -// Qd/Dd Qn/Dn Qm/Dm imm4
> -//
> -// Vector Shift (Register) Instructions.
> -// Qd/Dd Qm/Dm Qn/Dn (notice the order of m, n)
> -//
> -// Vector Multiply [Accumulate/Subtract] [Long] By Scalar Instructions.
> -// Qd/Dd Qn/Dn RestrictedDm index
> -//
> -// Others
> -static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, N3VFlag Flag, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> -
> - // No checking for OpInfo[2] because of MOVDneon/MOVQ with only two regs.
> - assert(NumOps >= 3 &&
> - (OpInfo[0].RegClass == ARM::DPRRegClassID ||
> - OpInfo[0].RegClass == ARM::QPRRegClassID) &&
> - (OpInfo[1].RegClass == ARM::DPRRegClassID ||
> - OpInfo[1].RegClass == ARM::QPRRegClassID) &&
> - "Expect >= 3 operands and first 2 as reg operands");
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - bool VdVnVm = Flag == N3V_VectorShift ? false : true;
> - bool IsImm4 = Flag == N3V_VectorExtract ? true : false;
> - bool IsDmRestricted = Flag == N3V_Multiply_By_Scalar ? true : false;
> - ElemSize esize = ESizeNA;
> - if (Flag == N3V_Multiply_By_Scalar) {
> - unsigned size = (insn >> 20) & 3;
> - if (size == 1) esize = ESize16;
> - if (size == 2) esize = ESize32;
> - assert (esize == ESize16 || esize == ESize32);
> - }
> -
> - // Qd/Dd = Inst{22:15-12} => NEON Rd
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - decodeNEONRd(insn))));
> - ++OpIdx;
> -
> - // VABA, VABAL, VBSLd, VBSLq, ...
> - if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
> - // TIED_TO operand.
> - MI.addOperand(MCOperand::CreateReg(0));
> - ++OpIdx;
> - }
> -
> - // Dn = Inst{7:19-16} => NEON Rn
> - // or
> - // Dm = Inst{5:3-0} => NEON Rm
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - VdVnVm ? decodeNEONRn(insn)
> - : decodeNEONRm(insn))));
> - ++OpIdx;
> -
> - // Dm = Inst{5:3-0} => NEON Rm
> - // or
> - // Dm is restricted to D0-D7 if size is 16, D0-D15 otherwise
> - // or
> - // Dn = Inst{7:19-16} => NEON Rn
> - unsigned m = VdVnVm ? (IsDmRestricted ? decodeRestrictedDm(insn, esize)
> - : decodeNEONRm(insn))
> - : decodeNEONRn(insn);
> -
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, OpInfo[OpIdx].RegClass, m)));
> - ++OpIdx;
> -
> - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
> - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
> - // Add the imm operand.
> - unsigned Imm = 0;
> - if (IsImm4)
> - Imm = decodeN3VImm(insn);
> - else if (IsDmRestricted)
> - Imm = decodeRestrictedDmIndex(insn, esize);
> - else {
> - assert(0 && "Internal error: unreachable code!");
> - return false;
> - }
> -
> - MI.addOperand(MCOperand::CreateImm(Imm));
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -static bool DisassembleN3RegFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
> - N3V_None, B);
> -}
> -static bool DisassembleN3RegVecShFrm(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
> - N3V_VectorShift, B);
> -}
> -static bool DisassembleNVecExtractFrm(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
> - N3V_VectorExtract, B);
> -}
> -static bool DisassembleNVecMulScalarFrm(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
> - N3V_Multiply_By_Scalar, B);
> -}
> -
> -// Vector Table Lookup
> -//
> -// VTBL1, VTBX1: Dd [Dd(TIED_TO)] Dn Dm
> -// VTBL2, VTBX2: Dd [Dd(TIED_TO)] Dn Dn+1 Dm
> -// VTBL3, VTBX3: Dd [Dd(TIED_TO)] Dn Dn+1 Dn+2 Dm
> -// VTBL4, VTBX4: Dd [Dd(TIED_TO)] Dn Dn+1 Dn+2 Dn+3 Dm
> -static bool DisassembleNVTBLFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - if (!OpInfo) return false;
> -
> - assert(NumOps >= 3 &&
> - OpInfo[0].RegClass == ARM::DPRRegClassID &&
> - OpInfo[1].RegClass == ARM::DPRRegClassID &&
> - OpInfo[2].RegClass == ARM::DPRRegClassID &&
> - "Expect >= 3 operands and first 3 as reg operands");
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - unsigned Rn = decodeNEONRn(insn);
> -
> - // {Dn} encoded as len = 0b00
> - // {Dn Dn+1} encoded as len = 0b01
> - // {Dn Dn+1 Dn+2 } encoded as len = 0b10
> - // {Dn Dn+1 Dn+2 Dn+3} encoded as len = 0b11
> - unsigned Len = slice(insn, 9, 8) + 1;
> -
> - // Dd (the destination vector)
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
> - decodeNEONRd(insn))));
> - ++OpIdx;
> -
> - // Process tied_to operand constraint.
> - int Idx;
> - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
> - MI.addOperand(MI.getOperand(Idx));
> - ++OpIdx;
> - }
> -
> - // Do the <list> now.
> - for (unsigned i = 0; i < Len; ++i) {
> - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::DPRRegClassID &&
> - "Reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
> - Rn + i)));
> - ++OpIdx;
> - }
> -
> - // Dm (the index vector)
> - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::DPRRegClassID &&
> - "Reg operand (index vector) expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
> - decodeNEONRm(insn))));
> - ++OpIdx;
> -
> - return true;
> -}
> -
> -// Vector Get Lane (move scalar to ARM core register) Instructions.
> -// VGETLNi32, VGETLNs16, VGETLNs8, VGETLNu16, VGETLNu8: Rt Dn index
> -static bool DisassembleNGetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - if (!OpInfo) return false;
> -
> - assert(MCID.getNumDefs() == 1 && NumOps >= 3 &&
> - OpInfo[0].RegClass == ARM::GPRRegClassID &&
> - OpInfo[1].RegClass == ARM::DPRRegClassID &&
> - OpInfo[2].RegClass < 0 &&
> - "Expect >= 3 operands with one dst operand");
> -
> - ElemSize esize =
> - Opcode == ARM::VGETLNi32 ? ESize32
> - : ((Opcode == ARM::VGETLNs16 || Opcode == ARM::VGETLNu16) ? ESize16
> - : ESize8);
> -
> - // Rt = Inst{15-12} => ARM Rd
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> -
> - // Dn = Inst{7:19-16} => NEON Rn
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
> - decodeNEONRn(insn))));
> -
> - MI.addOperand(MCOperand::CreateImm(decodeNVLaneOpIndex(insn, esize)));
> -
> - NumOpsAdded = 3;
> - return true;
> -}
> -
> -// Vector Set Lane (move ARM core register to scalar) Instructions.
> -// VSETLNi16, VSETLNi32, VSETLNi8: Dd Dd (TIED_TO) Rt index
> -static bool DisassembleNSetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - if (!OpInfo) return false;
> -
> - assert(MCID.getNumDefs() == 1 && NumOps >= 3 &&
> - OpInfo[0].RegClass == ARM::DPRRegClassID &&
> - OpInfo[1].RegClass == ARM::DPRRegClassID &&
> - MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 &&
> - OpInfo[2].RegClass == ARM::GPRRegClassID &&
> - OpInfo[3].RegClass < 0 &&
> - "Expect >= 3 operands with one dst operand");
> -
> - ElemSize esize =
> - Opcode == ARM::VSETLNi8 ? ESize8
> - : (Opcode == ARM::VSETLNi16 ? ESize16
> - : ESize32);
> -
> - // Dd = Inst{7:19-16} => NEON Rn
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
> - decodeNEONRn(insn))));
> -
> - // TIED_TO operand.
> - MI.addOperand(MCOperand::CreateReg(0));
> -
> - // Rt = Inst{15-12} => ARM Rd
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> -
> - MI.addOperand(MCOperand::CreateImm(decodeNVLaneOpIndex(insn, esize)));
> -
> - NumOpsAdded = 4;
> - return true;
> -}
> -
> -// Vector Duplicate Instructions (from ARM core register to all elements).
> -// VDUP8d, VDUP16d, VDUP32d, VDUP8q, VDUP16q, VDUP32q: Qd/Dd Rt
> -static bool DisassembleNDupFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> -
> - assert(NumOps >= 2 &&
> - (OpInfo[0].RegClass == ARM::DPRRegClassID ||
> - OpInfo[0].RegClass == ARM::QPRRegClassID) &&
> - OpInfo[1].RegClass == ARM::GPRRegClassID &&
> - "Expect >= 2 operands and first 2 as reg operand");
> -
> - unsigned RegClass = OpInfo[0].RegClass;
> -
> - // Qd/Dd = Inst{7:19-16} => NEON Rn
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClass,
> - decodeNEONRn(insn))));
> -
> - // Rt = Inst{15-12} => ARM Rd
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> -
> - NumOpsAdded = 2;
> - return true;
> -}
> -
> -static inline bool PreLoadOpcode(unsigned Opcode) {
> - switch(Opcode) {
> - case ARM::PLDi12: case ARM::PLDrs:
> - case ARM::PLDWi12: case ARM::PLDWrs:
> - case ARM::PLIi12: case ARM::PLIrs:
> - return true;
> - default:
> - return false;
> - }
> -}
> -
> -static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - // Preload Data/Instruction requires either 2 or 3 operands.
> - // PLDi12, PLDWi12, PLIi12: addrmode_imm12
> - // PLDrs, PLDWrs, PLIrs: ldst_so_reg
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> -
> - if (Opcode == ARM::PLDi12 || Opcode == ARM::PLDWi12
> - || Opcode == ARM::PLIi12) {
> - unsigned Imm12 = slice(insn, 11, 0);
> - bool Negative = getUBit(insn) == 0;
> -
> - // A8.6.118 PLD (literal) PLDWi12 with Rn=PC is transformed to PLDi12.
> - if (Opcode == ARM::PLDWi12 && slice(insn, 19, 16) == 0xF) {
> - DEBUG(errs() << "Rn == '1111': PLDWi12 morphed to PLDi12\n");
> - MI.setOpcode(ARM::PLDi12);
> - }
> -
> - // -0 is represented specially. All other values are as normal.
> - int Offset = Negative ? -1 * Imm12 : Imm12;
> - if (Imm12 == 0 && Negative)
> - Offset = INT32_MIN;
> -
> - MI.addOperand(MCOperand::CreateImm(Offset));
> - NumOpsAdded = 2;
> - } else {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> -
> - ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
> -
> - // Inst{6-5} encodes the shift opcode.
> - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
> - // Inst{11-7} encodes the imm5 shift amount.
> - unsigned ShImm = slice(insn, 11, 7);
> -
> - // A8.4.1. Possible rrx or shift amount of 32...
> - getImmShiftSE(ShOp, ShImm);
> - MI.addOperand(MCOperand::CreateImm(
> - ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp)));
> - NumOpsAdded = 3;
> - }
> -
> - return true;
> -}
> -
> -static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - if (Opcode == ARM::DMB || Opcode == ARM::DSB || Opcode == ARM::ISB) {
> - // Inst{3-0} encodes the memory barrier option for the variants.
> - unsigned opt = slice(insn, 3, 0);
> - switch (opt) {
> - case ARM_MB::SY: case ARM_MB::ST:
> - case ARM_MB::ISH: case ARM_MB::ISHST:
> - case ARM_MB::NSH: case ARM_MB::NSHST:
> - case ARM_MB::OSH: case ARM_MB::OSHST:
> - MI.addOperand(MCOperand::CreateImm(opt));
> - NumOpsAdded = 1;
> - return true;
> - default:
> - return false;
> - }
> - }
> -
> - switch (Opcode) {
> - case ARM::CLREX:
> - case ARM::NOP:
> - case ARM::TRAP:
> - case ARM::YIELD:
> - case ARM::WFE:
> - case ARM::WFI:
> - case ARM::SEV:
> - return true;
> - case ARM::SWP:
> - case ARM::SWPB:
> - // SWP, SWPB: Rd Rm Rn
> - // Delegate to DisassembleLdStExFrm()....
> - return DisassembleLdStExFrm(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - default:
> - break;
> - }
> -
> - if (Opcode == ARM::SETEND) {
> - NumOpsAdded = 1;
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 9, 9)));
> - return true;
> - }
> -
> - // FIXME: To enable correct asm parsing and disasm of CPS we need 3 different
> - // opcodes which match the same real instruction. This is needed since there's
> - // no current handling of optional arguments. Fix here when a better handling
> - // of optional arguments is implemented.
> - if (Opcode == ARM::CPS3p) { // M = 1
> - // Let's reject these impossible imod values by returning false:
> - // 1. (imod=0b01)
> - //
> - // AsmPrinter cannot handle imod=0b00, plus (imod=0b00,M=1,iflags!=0) is an
> - // invalid combination, so we just check for imod=0b00 here.
> - if (slice(insn, 19, 18) == 0 || slice(insn, 19, 18) == 1)
> - return false;
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6))); // iflags
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode
> - NumOpsAdded = 3;
> - return true;
> - }
> - if (Opcode == ARM::CPS2p) { // mode = 0, M = 0
> - // Let's reject these impossible imod values by returning false:
> - // 1. (imod=0b00,M=0)
> - // 2. (imod=0b01)
> - if (slice(insn, 19, 18) == 0 || slice(insn, 19, 18) == 1)
> - return false;
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6))); // iflags
> - NumOpsAdded = 2;
> - return true;
> - }
> - if (Opcode == ARM::CPS1p) { // imod = 0, iflags = 0, M = 1
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode
> - NumOpsAdded = 1;
> - return true;
> - }
> -
> - // DBG has its option specified in Inst{3-0}.
> - if (Opcode == ARM::DBG) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 0)));
> - NumOpsAdded = 1;
> - return true;
> - }
> -
> - // BKPT takes an imm32 val equal to ZeroExtend(Inst{19-8:3-0}).
> - if (Opcode == ARM::BKPT) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 8) << 4 |
> - slice(insn, 3, 0)));
> - NumOpsAdded = 1;
> - return true;
> - }
> -
> - if (PreLoadOpcode(Opcode))
> - return DisassemblePreLoadFrm(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> -
> - assert(0 && "Unexpected misc instruction!");
> - return false;
> -}
> -
> -/// FuncPtrs - FuncPtrs maps ARMFormat to its corresponding DisassembleFP.
> -/// We divide the disassembly task into different categories, with each one
> -/// corresponding to a specific instruction encoding format. There could be
> -/// exceptions when handling a specific format, and that is why the Opcode is
> -/// also present in the function prototype.
> -static const DisassembleFP FuncPtrs[] = {
> - &DisassemblePseudo,
> - &DisassembleMulFrm,
> - &DisassembleBrFrm,
> - &DisassembleBrMiscFrm,
> - &DisassembleDPFrm,
> - &DisassembleDPSoRegRegFrm,
> - &DisassembleLdFrm,
> - &DisassembleStFrm,
> - &DisassembleLdMiscFrm,
> - &DisassembleStMiscFrm,
> - &DisassembleLdStMulFrm,
> - &DisassembleLdStExFrm,
> - &DisassembleArithMiscFrm,
> - &DisassembleSatFrm,
> - &DisassembleExtFrm,
> - &DisassembleVFPUnaryFrm,
> - &DisassembleVFPBinaryFrm,
> - &DisassembleVFPConv1Frm,
> - &DisassembleVFPConv2Frm,
> - &DisassembleVFPConv3Frm,
> - &DisassembleVFPConv4Frm,
> - &DisassembleVFPConv5Frm,
> - &DisassembleVFPLdStFrm,
> - &DisassembleVFPLdStMulFrm,
> - &DisassembleVFPMiscFrm,
> - &DisassembleThumbFrm,
> - &DisassembleMiscFrm,
> - &DisassembleNGetLnFrm,
> - &DisassembleNSetLnFrm,
> - &DisassembleNDupFrm,
> -
> - // VLD and VST (including one lane) Instructions.
> - &DisassembleNLdSt,
> -
> - // A7.4.6 One register and a modified immediate value
> - // 1-Register Instructions with imm.
> - // LLVM only defines VMOVv instructions.
> - &DisassembleN1RegModImmFrm,
> -
> - // 2-Register Instructions with no imm.
> - &DisassembleN2RegFrm,
> -
> - // 2-Register Instructions with imm (vector convert float/fixed point).
> - &DisassembleNVCVTFrm,
> -
> - // 2-Register Instructions with imm (vector dup lane).
> - &DisassembleNVecDupLnFrm,
> -
> - // Vector Shift Left Instructions.
> - &DisassembleN2RegVecShLFrm,
> -
> - // Vector Shift Righ Instructions, which has different interpretation of the
> - // shift amount from the imm6 field.
> - &DisassembleN2RegVecShRFrm,
> -
> - // 3-Register Data-Processing Instructions.
> - &DisassembleN3RegFrm,
> -
> - // Vector Shift (Register) Instructions.
> - // D:Vd M:Vm N:Vn (notice that M:Vm is the first operand)
> - &DisassembleN3RegVecShFrm,
> -
> - // Vector Extract Instructions.
> - &DisassembleNVecExtractFrm,
> -
> - // Vector [Saturating Rounding Doubling] Multiply [Accumulate/Subtract] [Long]
> - // By Scalar Instructions.
> - &DisassembleNVecMulScalarFrm,
> -
> - // Vector Table Lookup uses byte indexes in a control vector to look up byte
> - // values in a table and generate a new vector.
> - &DisassembleNVTBLFrm,
> -
> - &DisassembleDPSoRegImmFrm,
> -
> -
> - NULL
> -};
> -
> -/// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder.
> -/// The general idea is to set the Opcode for the MCInst, followed by adding
> -/// the appropriate MCOperands to the MCInst. ARM Basic MC Builder delegates
> -/// to the Format-specific disassemble function for disassembly, followed by
> -/// TryPredicateAndSBitModifier() to do PredicateOperand and OptionalDefOperand
> -/// which follow the Dst/Src Operands.
> -bool ARMBasicMCBuilder::BuildIt(MCInst &MI, uint32_t insn) {
> - // Stage 1 sets the Opcode.
> - MI.setOpcode(Opcode);
> - // If the number of operands is zero, we're done!
> - if (NumOps == 0)
> - return true;
> -
> - // Stage 2 calls the format-specific disassemble function to build the operand
> - // list.
> - if (Disasm == NULL)
> - return false;
> - unsigned NumOpsAdded = 0;
> - bool OK = (*Disasm)(MI, Opcode, insn, NumOps, NumOpsAdded, this);
> -
> - if (!OK || this->Err != 0) return false;
> - if (NumOpsAdded >= NumOps)
> - return true;
> -
> - // Stage 3 deals with operands unaccounted for after stage 2 is finished.
> - // FIXME: Should this be done selectively?
> - return TryPredicateAndSBitModifier(MI, Opcode, insn, NumOps - NumOpsAdded);
> -}
> -
> -// A8.3 Conditional execution
> -// A8.3.1 Pseudocode details of conditional execution
> -// Condition bits '111x' indicate the instruction is always executed.
> -static uint32_t CondCode(uint32_t CondField) {
> - if (CondField == 0xF)
> - return ARMCC::AL;
> - return CondField;
> -}
> -
> -/// DoPredicateOperands - DoPredicateOperands process the predicate operands
> -/// of some Thumb instructions which come before the reglist operands. It
> -/// returns true if the two predicate operands have been processed.
> -bool ARMBasicMCBuilder::DoPredicateOperands(MCInst& MI, unsigned Opcode,
> - uint32_t /* insn */, unsigned short NumOpsRemaining) {
> -
> - assert(NumOpsRemaining > 0 && "Invalid argument");
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - unsigned Idx = MI.getNumOperands();
> -
> - // First, we check whether this instr specifies the PredicateOperand through
> - // a pair of MCOperandInfos with isPredicate() property.
> - if (NumOpsRemaining >= 2 &&
> - OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() &&
> - OpInfo[Idx].RegClass < 0 &&
> - OpInfo[Idx+1].RegClass == ARM::CCRRegClassID)
> - {
> - // If we are inside an IT block, get the IT condition bits maintained via
> - // ARMBasicMCBuilder::ITState[7:0], through ARMBasicMCBuilder::GetITCond().
> - // See also A2.5.2.
> - if (InITBlock())
> - MI.addOperand(MCOperand::CreateImm(GetITCond()));
> - else
> - MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
> - MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
> - return true;
> - }
> -
> - return false;
> -}
> -
> -/// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
> -/// the possible Predicate and SBitModifier, to build the remaining MCOperand
> -/// constituents.
> -bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOpsRemaining) {
> -
> - assert(NumOpsRemaining > 0 && "Invalid argument");
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - const std::string &Name = ARMInsts[Opcode].Name;
> - unsigned Idx = MI.getNumOperands();
> - uint64_t TSFlags = ARMInsts[Opcode].TSFlags;
> -
> - // First, we check whether this instr specifies the PredicateOperand through
> - // a pair of MCOperandInfos with isPredicate() property.
> - if (NumOpsRemaining >= 2 &&
> - OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() &&
> - OpInfo[Idx].RegClass < 0 &&
> - OpInfo[Idx+1].RegClass == ARM::CCRRegClassID)
> - {
> - // If we are inside an IT block, get the IT condition bits maintained via
> - // ARMBasicMCBuilder::ITState[7:0], through ARMBasicMCBuilder::GetITCond().
> - // See also A2.5.2.
> - if (InITBlock())
> - MI.addOperand(MCOperand::CreateImm(GetITCond()));
> - else {
> - if (Name.length() > 1 && Name[0] == 't') {
> - // Thumb conditional branch instructions have their cond field embedded,
> - // like ARM.
> - //
> - // A8.6.16 B
> - // Check for undefined encodings.
> - unsigned cond;
> - if (Name == "t2Bcc") {
> - if ((cond = slice(insn, 25, 22)) >= 14)
> - return false;
> - MI.addOperand(MCOperand::CreateImm(CondCode(cond)));
> - } else if (Name == "tBcc") {
> - if ((cond = slice(insn, 11, 8)) == 14)
> - return false;
> - MI.addOperand(MCOperand::CreateImm(CondCode(cond)));
> - } else
> - MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
> - } else {
> - // ARM instructions get their condition field from Inst{31-28}.
> - // We should reject Inst{31-28} = 0b1111 as invalid encoding.
> - if (!isNEONDomain(TSFlags) && getCondField(insn) == 0xF)
> - return false;
> - MI.addOperand(MCOperand::CreateImm(CondCode(getCondField(insn))));
> - }
> - }
> - MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
> - Idx += 2;
> - NumOpsRemaining -= 2;
> - }
> -
> - if (NumOpsRemaining == 0)
> - return true;
> -
> - // Next, if OptionalDefOperand exists, we check whether the 'S' bit is set.
> - if (OpInfo[Idx].isOptionalDef() && OpInfo[Idx].RegClass==ARM::CCRRegClassID) {
> - MI.addOperand(MCOperand::CreateReg(getSBit(insn) == 1 ? ARM::CPSR : 0));
> - --NumOpsRemaining;
> - }
> -
> - if (NumOpsRemaining == 0)
> - return true;
> - else
> - return false;
> -}
> -
> -/// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary
> -/// after BuildIt is finished.
> -bool ARMBasicMCBuilder::RunBuildAfterHook(bool Status, MCInst &MI,
> - uint32_t insn) {
> -
> - if (!SP) return Status;
> -
> - if (Opcode == ARM::t2IT)
> - Status = SP->InitIT(slice(insn, 7, 0)) ? Status : false;
> - else if (InITBlock())
> - SP->UpdateIT();
> -
> - return Status;
> -}
> -
> -/// Opcode, Format, and NumOperands make up an ARM Basic MCBuilder.
> -ARMBasicMCBuilder::ARMBasicMCBuilder(unsigned opc, ARMFormat format,
> - unsigned short num)
> - : Opcode(opc), Format(format), NumOps(num), SP(0), Err(0) {
> - unsigned Idx = (unsigned)format;
> - assert(Idx < (array_lengthof(FuncPtrs) - 1) && "Unknown format");
> - Disasm = FuncPtrs[Idx];
> -}
> -
> -/// CreateMCBuilder - Return an ARMBasicMCBuilder that can build up the MC
> -/// infrastructure of an MCInst given the Opcode and Format of the instr.
> -/// Return NULL if it fails to create/return a proper builder. API clients
> -/// are responsible for freeing up of the allocated memory. Cacheing can be
> -/// performed by the API clients to improve performance.
> -ARMBasicMCBuilder *llvm::CreateMCBuilder(unsigned Opcode, ARMFormat Format) {
> - // For "Unknown format", fail by returning a NULL pointer.
> - if ((unsigned)Format >= (array_lengthof(FuncPtrs) - 1)) {
> - DEBUG(errs() << "Unknown format\n");
> - return 0;
> - }
> -
> - return new ARMBasicMCBuilder(Opcode, Format,
> - ARMInsts[Opcode].getNumOperands());
> -}
> -
> -/// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic
> -/// operand in place of the immediate Value in the MCInst. The immediate
> -/// Value has had any PC adjustment made by the caller. If the getOpInfo()
> -/// function was set as part of the setupBuilderForSymbolicDisassembly() call
> -/// then that function is called to get any symbolic information at the
> -/// builder's Address for this instrution. If that returns non-zero then the
> -/// symbolic information it returns is used to create an MCExpr and that is
> -/// added as an operand to the MCInst. This function returns true if it adds
> -/// an operand to the MCInst and false otherwise.
> -bool ARMBasicMCBuilder::tryAddingSymbolicOperand(uint64_t Value,
> - uint64_t InstSize,
> - MCInst &MI) {
> - if (!GetOpInfo)
> - return false;
> -
> - struct LLVMOpInfo1 SymbolicOp;
> - SymbolicOp.Value = Value;
> - if (!GetOpInfo(DisInfo, Address, 0 /* Offset */, InstSize, 1, &SymbolicOp))
> - return false;
> -
> - const MCExpr *Add = NULL;
> - if (SymbolicOp.AddSymbol.Present) {
> - if (SymbolicOp.AddSymbol.Name) {
> - StringRef Name(SymbolicOp.AddSymbol.Name);
> - MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name);
> - Add = MCSymbolRefExpr::Create(Sym, *Ctx);
> - } else {
> - Add = MCConstantExpr::Create(SymbolicOp.AddSymbol.Value, *Ctx);
> - }
> - }
> -
> - const MCExpr *Sub = NULL;
> - if (SymbolicOp.SubtractSymbol.Present) {
> - if (SymbolicOp.SubtractSymbol.Name) {
> - StringRef Name(SymbolicOp.SubtractSymbol.Name);
> - MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name);
> - Sub = MCSymbolRefExpr::Create(Sym, *Ctx);
> - } else {
> - Sub = MCConstantExpr::Create(SymbolicOp.SubtractSymbol.Value, *Ctx);
> - }
> - }
> -
> - const MCExpr *Off = NULL;
> - if (SymbolicOp.Value != 0)
> - Off = MCConstantExpr::Create(SymbolicOp.Value, *Ctx);
> -
> - const MCExpr *Expr;
> - if (Sub) {
> - const MCExpr *LHS;
> - if (Add)
> - LHS = MCBinaryExpr::CreateSub(Add, Sub, *Ctx);
> - else
> - LHS = MCUnaryExpr::CreateMinus(Sub, *Ctx);
> - if (Off != 0)
> - Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx);
> - else
> - Expr = LHS;
> - } else if (Add) {
> - if (Off != 0)
> - Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx);
> - else
> - Expr = Add;
> - } else {
> - if (Off != 0)
> - Expr = Off;
> - else
> - Expr = MCConstantExpr::Create(0, *Ctx);
> - }
> -
> - if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_HI16)
> - MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateUpper16(Expr, *Ctx)));
> - else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_LO16)
> - MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateLower16(Expr, *Ctx)));
> - else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_None)
> - MI.addOperand(MCOperand::CreateExpr(Expr));
> - else
> - assert("bad SymbolicOp.VariantKind");
> -
> - return true;
> -}
>
> Removed: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h?rev=137143&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h (original)
> +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h (removed)
> @@ -1,337 +0,0 @@
> -//===- ARMDisassemblerCore.h - ARM disassembler helpers ---------*- C++ -*-===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -//
> -// This file is part of the ARM Disassembler.
> -//
> -// The first part defines the enumeration type of ARM instruction format, which
> -// specifies the encoding used by the instruction, as well as a helper function
> -// to convert the enums to printable char strings.
> -//
> -// It also contains code to represent the concepts of Builder and DisassembleFP
> -// to solve the problem of disassembling an ARM instr.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef ARMDISASSEMBLERCORE_H
> -#define ARMDISASSEMBLERCORE_H
> -
> -#include "llvm/MC/MCInst.h"
> -#include "llvm/MC/MCSymbol.h"
> -#include "llvm/MC/MCExpr.h"
> -#include "llvm/MC/MCContext.h"
> -#include "llvm/Target/TargetInstrInfo.h"
> -#include "llvm-c/Disassembler.h"
> -#include "ARMBaseInstrInfo.h"
> -#include "ARMRegisterInfo.h"
> -#include "ARMDisassembler.h"
> -
> -namespace llvm {
> -class MCContext;
> -
> -class ARMUtils {
> -public:
> - static const char *OpcodeName(unsigned Opcode);
> -};
> -
> -/////////////////////////////////////////////////////
> -// //
> -// Enums and Utilities for ARM Instruction Format //
> -// //
> -/////////////////////////////////////////////////////
> -
> -#define ARM_FORMATS \
> - ENTRY(ARM_FORMAT_PSEUDO, 0) \
> - ENTRY(ARM_FORMAT_MULFRM, 1) \
> - ENTRY(ARM_FORMAT_BRFRM, 2) \
> - ENTRY(ARM_FORMAT_BRMISCFRM, 3) \
> - ENTRY(ARM_FORMAT_DPFRM, 4) \
> - ENTRY(ARM_FORMAT_DPSOREGREGFRM, 5) \
> - ENTRY(ARM_FORMAT_LDFRM, 6) \
> - ENTRY(ARM_FORMAT_STFRM, 7) \
> - ENTRY(ARM_FORMAT_LDMISCFRM, 8) \
> - ENTRY(ARM_FORMAT_STMISCFRM, 9) \
> - ENTRY(ARM_FORMAT_LDSTMULFRM, 10) \
> - ENTRY(ARM_FORMAT_LDSTEXFRM, 11) \
> - ENTRY(ARM_FORMAT_ARITHMISCFRM, 12) \
> - ENTRY(ARM_FORMAT_SATFRM, 13) \
> - ENTRY(ARM_FORMAT_EXTFRM, 14) \
> - ENTRY(ARM_FORMAT_VFPUNARYFRM, 15) \
> - ENTRY(ARM_FORMAT_VFPBINARYFRM, 16) \
> - ENTRY(ARM_FORMAT_VFPCONV1FRM, 17) \
> - ENTRY(ARM_FORMAT_VFPCONV2FRM, 18) \
> - ENTRY(ARM_FORMAT_VFPCONV3FRM, 19) \
> - ENTRY(ARM_FORMAT_VFPCONV4FRM, 20) \
> - ENTRY(ARM_FORMAT_VFPCONV5FRM, 21) \
> - ENTRY(ARM_FORMAT_VFPLDSTFRM, 22) \
> - ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 23) \
> - ENTRY(ARM_FORMAT_VFPMISCFRM, 24) \
> - ENTRY(ARM_FORMAT_THUMBFRM, 25) \
> - ENTRY(ARM_FORMAT_MISCFRM, 26) \
> - ENTRY(ARM_FORMAT_NEONGETLNFRM, 27) \
> - ENTRY(ARM_FORMAT_NEONSETLNFRM, 28) \
> - ENTRY(ARM_FORMAT_NEONDUPFRM, 29) \
> - ENTRY(ARM_FORMAT_NLdSt, 30) \
> - ENTRY(ARM_FORMAT_N1RegModImm, 31) \
> - ENTRY(ARM_FORMAT_N2Reg, 32) \
> - ENTRY(ARM_FORMAT_NVCVT, 33) \
> - ENTRY(ARM_FORMAT_NVecDupLn, 34) \
> - ENTRY(ARM_FORMAT_N2RegVecShL, 35) \
> - ENTRY(ARM_FORMAT_N2RegVecShR, 36) \
> - ENTRY(ARM_FORMAT_N3Reg, 37) \
> - ENTRY(ARM_FORMAT_N3RegVecSh, 38) \
> - ENTRY(ARM_FORMAT_NVecExtract, 39) \
> - ENTRY(ARM_FORMAT_NVecMulScalar, 40) \
> - ENTRY(ARM_FORMAT_NVTBL, 41) \
> - ENTRY(ARM_FORMAT_DPSOREGIMMFRM, 42)
> -
> -// ARM instruction format specifies the encoding used by the instruction.
> -#define ENTRY(n, v) n = v,
> -typedef enum {
> - ARM_FORMATS
> - ARM_FORMAT_NA
> -} ARMFormat;
> -#undef ENTRY
> -
> -// Converts enum to const char*.
> -static const inline char *stringForARMFormat(ARMFormat form) {
> -#define ENTRY(n, v) case n: return #n;
> - switch(form) {
> - ARM_FORMATS
> - case ARM_FORMAT_NA:
> - default:
> - return "";
> - }
> -#undef ENTRY
> -}
> -
> -/// Expands on the enum definitions from ARMBaseInstrInfo.h.
> -/// They are being used by the disassembler implementation.
> -namespace ARMII {
> - enum {
> - NEONRegMask = 15,
> - GPRRegMask = 15,
> - NEON_RegRdShift = 12,
> - NEON_D_BitShift = 22,
> - NEON_RegRnShift = 16,
> - NEON_N_BitShift = 7,
> - NEON_RegRmShift = 0,
> - NEON_M_BitShift = 5
> - };
> -}
> -
> -/// Utility function for extracting [From, To] bits from a uint32_t.
> -static inline unsigned slice(uint32_t Bits, unsigned From, unsigned To) {
> - assert(From < 32 && To < 32 && From >= To);
> - return (Bits >> To) & ((1 << (From - To + 1)) - 1);
> -}
> -
> -/// Utility function for setting [From, To] bits to Val for a uint32_t.
> -static inline void setSlice(unsigned &Bits, unsigned From, unsigned To,
> - unsigned Val) {
> - assert(From < 32 && To < 32 && From >= To);
> - uint32_t Mask = ((1 << (From - To + 1)) - 1);
> - Bits &= ~(Mask << To);
> - Bits |= (Val & Mask) << To;
> -}
> -
> -// Return an integer result equal to the number of bits of x that are ones.
> -static inline uint32_t
> -BitCount (uint64_t x)
> -{
> - // c accumulates the total bits set in x
> - uint32_t c;
> - for (c = 0; x; ++c)
> - {
> - x &= x - 1; // clear the least significant bit set
> - }
> - return c;
> -}
> -
> -static inline bool
> -BitIsSet (const uint64_t value, const uint64_t bit)
> -{
> - return (value & (1ull << bit)) != 0;
> -}
> -
> -static inline bool
> -BitIsClear (const uint64_t value, const uint64_t bit)
> -{
> - return (value & (1ull << bit)) == 0;
> -}
> -
> -/// Various utilities for checking the target specific flags.
> -
> -/// A unary data processing instruction doesn't have an Rn operand.
> -static inline bool isUnaryDP(uint64_t TSFlags) {
> - return (TSFlags & ARMII::UnaryDP);
> -}
> -
> -/// A NEON Domain instruction has cond field (Inst{31-28}) as 0b1111.
> -static inline bool isNEONDomain(uint64_t TSFlags) {
> - return (TSFlags & ARMII::DomainNEON) ||
> - (TSFlags & ARMII::DomainNEONA8);
> -}
> -
> -/// This four-bit field describes the addressing mode used.
> -/// See also ARMBaseInstrInfo.h.
> -static inline unsigned getAddrMode(uint64_t TSFlags) {
> - return (TSFlags & ARMII::AddrModeMask);
> -}
> -
> -/// {IndexModePre, IndexModePost}
> -/// Only valid for load and store ops.
> -/// See also ARMBaseInstrInfo.h.
> -static inline unsigned getIndexMode(uint64_t TSFlags) {
> - return (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
> -}
> -
> -/// Pre-/post-indexed operations define an extra $base_wb in the OutOperandList.
> -static inline bool isPrePostLdSt(uint64_t TSFlags) {
> - return (TSFlags & ARMII::IndexModeMask) != 0;
> -}
> -
> -// Forward declaration.
> -class ARMBasicMCBuilder;
> -
> -// Builder Object is mostly ignored except in some Thumb disassemble functions.
> -typedef ARMBasicMCBuilder *BO;
> -
> -/// DisassembleFP - DisassembleFP points to a function that disassembles an insn
> -/// and builds the MCOperand list upon disassembly. It returns false on failure
> -/// or true on success. The number of operands added is updated upon success.
> -typedef bool (*DisassembleFP)(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO Builder);
> -
> -/// CreateMCBuilder - Return an ARMBasicMCBuilder that can build up the MC
> -/// infrastructure of an MCInst given the Opcode and Format of the instr.
> -/// Return NULL if it fails to create/return a proper builder. API clients
> -/// are responsible for freeing up of the allocated memory. Cacheing can be
> -/// performed by the API clients to improve performance.
> -extern ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format);
> -
> -/// ARMBasicMCBuilder - ARMBasicMCBuilder represents an ARM MCInst builder that
> -/// knows how to build up the MCOperand list.
> -class ARMBasicMCBuilder {
> - friend ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format);
> - unsigned Opcode;
> - ARMFormat Format;
> - unsigned short NumOps;
> - DisassembleFP Disasm;
> - Session *SP;
> - int Err; // !=0 if the builder encounters some error condition during build.
> -
> -private:
> - /// Opcode, Format, and NumOperands make up an ARM Basic MCBuilder.
> - ARMBasicMCBuilder(unsigned opc, ARMFormat format, unsigned short num);
> -
> -public:
> - ARMBasicMCBuilder(ARMBasicMCBuilder &B)
> - : Opcode(B.Opcode), Format(B.Format), NumOps(B.NumOps), Disasm(B.Disasm),
> - SP(B.SP), GetOpInfo(0), DisInfo(0), Ctx(0) {
> - Err = 0;
> - }
> -
> - virtual ~ARMBasicMCBuilder() {}
> -
> - void SetSession(Session *sp) {
> - SP = sp;
> - }
> -
> - void SetErr(int ErrCode) {
> - Err = ErrCode;
> - }
> -
> - /// DoPredicateOperands - DoPredicateOperands process the predicate operands
> - /// of some Thumb instructions which come before the reglist operands. It
> - /// returns true if the two predicate operands have been processed.
> - bool DoPredicateOperands(MCInst& MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOpsRemaning);
> -
> - /// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
> - /// the possible Predicate and SBitModifier, to build the remaining MCOperand
> - /// constituents.
> - bool TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOpsRemaning);
> -
> - /// InITBlock - InITBlock returns true if we are inside an IT block.
> - bool InITBlock() {
> - if (SP)
> - return SP->ITCounter > 0;
> -
> - return false;
> - }
> -
> - /// Build - Build delegates to BuildIt to perform the heavy liftling. After
> - /// that, it invokes RunBuildAfterHook where some housekeepings can be done.
> - virtual bool Build(MCInst &MI, uint32_t insn) {
> - bool Status = BuildIt(MI, insn);
> - return RunBuildAfterHook(Status, MI, insn);
> - }
> -
> - /// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder.
> - /// The general idea is to set the Opcode for the MCInst, followed by adding
> - /// the appropriate MCOperands to the MCInst. ARM Basic MC Builder delegates
> - /// to the Format-specific disassemble function for disassembly, followed by
> - /// TryPredicateAndSBitModifier() for PredicateOperand and OptionalDefOperand
> - /// which follow the Dst/Src Operands.
> - virtual bool BuildIt(MCInst &MI, uint32_t insn);
> -
> - /// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary
> - /// after BuildIt is finished.
> - virtual bool RunBuildAfterHook(bool Status, MCInst &MI, uint32_t insn);
> -
> -private:
> - /// Get condition of the current IT instruction.
> - unsigned GetITCond() {
> - assert(SP);
> - return slice(SP->ITState, 7, 4);
> - }
> -
> -private:
> - //
> - // Hooks for symbolic disassembly via the public 'C' interface.
> - //
> - // The function to get the symbolic information for operands.
> - LLVMOpInfoCallback GetOpInfo;
> - // The pointer to the block of symbolic information for above call back.
> - void *DisInfo;
> - // The assembly context for creating symbols and MCExprs in place of
> - // immediate operands when there is symbolic information.
> - MCContext *Ctx;
> - // The address of the instruction being disassembled.
> - uint64_t Address;
> -
> -public:
> - void setupBuilderForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo,
> - void *disInfo, MCContext *ctx,
> - uint64_t address) {
> - GetOpInfo = getOpInfo;
> - DisInfo = disInfo;
> - Ctx = ctx;
> - Address = address;
> - }
> -
> - uint64_t getBuilderAddress() const { return Address; }
> -
> - /// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic
> - /// operand in place of the immediate Value in the MCInst. The immediate
> - /// Value has had any PC adjustment made by the caller. If the getOpInfo()
> - /// function was set as part of the setupBuilderForSymbolicDisassembly() call
> - /// then that function is called to get any symbolic information at the
> - /// builder's Address for this instrution. If that returns non-zero then the
> - /// symbolic information it returns is used to create an MCExpr and that is
> - /// added as an operand to the MCInst. This function returns true if it adds
> - /// an operand to the MCInst and false otherwise.
> - bool tryAddingSymbolicOperand(uint64_t Value, uint64_t InstSize, MCInst &MI);
> -
> -};
> -
> -} // namespace llvm
> -
> -#endif
>
> Modified: llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt (original)
> +++ llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt Tue Aug 9 15:55:18 2011
> @@ -2,7 +2,6 @@
>
> add_llvm_library(LLVMARMDisassembler
> ARMDisassembler.cpp
> - ARMDisassemblerCore.cpp
> )
> # workaround for hanging compilation on MSVC8, 9 and 10
> if( MSVC_VERSION EQUAL 1400 OR MSVC_VERSION EQUAL 1500 OR MSVC_VERSION EQUAL 1600 )
>
> Removed: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=137143&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original)
> +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (removed)
> @@ -1,2461 +0,0 @@
> -//===- ThumbDisassemblerCore.h - Thumb disassembler helpers -----*- C++ -*-===//
> -//
> -// The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===----------------------------------------------------------------------===//
> -//
> -// This file is part of the ARM Disassembler.
> -// It contains code for disassembling a Thumb instr. It is to be included by
> -// ARMDisassemblerCore.cpp because it contains the static DisassembleThumbFrm()
> -// function which acts as the dispatcher to disassemble a Thumb instruction.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -///////////////////////////////
> -// //
> -// Utility Functions //
> -// //
> -///////////////////////////////
> -
> -// Utilities for 16-bit Thumb instructions.
> -/*
> -15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> - [ tRt ]
> - [ tRm ] [ tRn ] [ tRd ]
> - D [ Rm ] [ Rd ]
> -
> - [ imm3]
> - [ imm5 ]
> - i [ imm5 ]
> - [ imm7 ]
> - [ imm8 ]
> - [ imm11 ]
> -
> - [ cond ]
> -*/
> -
> -// Extract tRt: Inst{10-8}.
> -static inline unsigned getT1tRt(uint32_t insn) {
> - return slice(insn, 10, 8);
> -}
> -
> -// Extract tRm: Inst{8-6}.
> -static inline unsigned getT1tRm(uint32_t insn) {
> - return slice(insn, 8, 6);
> -}
> -
> -// Extract tRn: Inst{5-3}.
> -static inline unsigned getT1tRn(uint32_t insn) {
> - return slice(insn, 5, 3);
> -}
> -
> -// Extract tRd: Inst{2-0}.
> -static inline unsigned getT1tRd(uint32_t insn) {
> - return slice(insn, 2, 0);
> -}
> -
> -// Extract [D:Rd]: Inst{7:2-0}.
> -static inline unsigned getT1Rd(uint32_t insn) {
> - return slice(insn, 7, 7) << 3 | slice(insn, 2, 0);
> -}
> -
> -// Extract Rm: Inst{6-3}.
> -static inline unsigned getT1Rm(uint32_t insn) {
> - return slice(insn, 6, 3);
> -}
> -
> -// Extract imm3: Inst{8-6}.
> -static inline unsigned getT1Imm3(uint32_t insn) {
> - return slice(insn, 8, 6);
> -}
> -
> -// Extract imm5: Inst{10-6}.
> -static inline unsigned getT1Imm5(uint32_t insn) {
> - return slice(insn, 10, 6);
> -}
> -
> -// Extract i:imm5: Inst{9:7-3}.
> -static inline unsigned getT1Imm6(uint32_t insn) {
> - return slice(insn, 9, 9) << 5 | slice(insn, 7, 3);
> -}
> -
> -// Extract imm7: Inst{6-0}.
> -static inline unsigned getT1Imm7(uint32_t insn) {
> - return slice(insn, 6, 0);
> -}
> -
> -// Extract imm8: Inst{7-0}.
> -static inline unsigned getT1Imm8(uint32_t insn) {
> - return slice(insn, 7, 0);
> -}
> -
> -// Extract imm11: Inst{10-0}.
> -static inline unsigned getT1Imm11(uint32_t insn) {
> - return slice(insn, 10, 0);
> -}
> -
> -// Extract cond: Inst{11-8}.
> -static inline unsigned getT1Cond(uint32_t insn) {
> - return slice(insn, 11, 8);
> -}
> -
> -static inline bool IsGPR(unsigned RegClass) {
> - return RegClass == ARM::GPRRegClassID || RegClass == ARM::rGPRRegClassID;
> -}
> -
> -// Utilities for 32-bit Thumb instructions.
> -
> -static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; }
> -
> -// Extract imm4: Inst{19-16}.
> -static inline unsigned getImm4(uint32_t insn) {
> - return slice(insn, 19, 16);
> -}
> -
> -// Extract imm3: Inst{14-12}.
> -static inline unsigned getImm3(uint32_t insn) {
> - return slice(insn, 14, 12);
> -}
> -
> -// Extract imm8: Inst{7-0}.
> -static inline unsigned getImm8(uint32_t insn) {
> - return slice(insn, 7, 0);
> -}
> -
> -// A8.6.61 LDRB (immediate, Thumb) and friends
> -// +/-: Inst{9}
> -// imm8: Inst{7-0}
> -static inline int decodeImm8(uint32_t insn) {
> - int Offset = getImm8(insn);
> - return slice(insn, 9, 9) ? Offset : -Offset;
> -}
> -
> -// Extract imm12: Inst{11-0}.
> -static inline unsigned getImm12(uint32_t insn) {
> - return slice(insn, 11, 0);
> -}
> -
> -// A8.6.63 LDRB (literal) and friends
> -// +/-: Inst{23}
> -// imm12: Inst{11-0}
> -static inline int decodeImm12(uint32_t insn) {
> - int Offset = getImm12(insn);
> - return slice(insn, 23, 23) ? Offset : -Offset;
> -}
> -
> -// Extract imm2: Inst{7-6}.
> -static inline unsigned getImm2(uint32_t insn) {
> - return slice(insn, 7, 6);
> -}
> -
> -// For BFI, BFC, t2SBFX, and t2UBFX.
> -// Extract lsb: Inst{14-12:7-6}.
> -static inline unsigned getLsb(uint32_t insn) {
> - return getImm3(insn) << 2 | getImm2(insn);
> -}
> -
> -// For BFI and BFC.
> -// Extract msb: Inst{4-0}.
> -static inline unsigned getMsb(uint32_t insn) {
> - return slice(insn, 4, 0);
> -}
> -
> -// For t2SBFX and t2UBFX.
> -// Extract widthminus1: Inst{4-0}.
> -static inline unsigned getWidthMinus1(uint32_t insn) {
> - return slice(insn, 4, 0);
> -}
> -
> -// For t2ADDri12 and t2SUBri12.
> -// imm12 = i:imm3:imm8;
> -static inline unsigned getIImm3Imm8(uint32_t insn) {
> - return slice(insn, 26, 26) << 11 | getImm3(insn) << 8 | getImm8(insn);
> -}
> -
> -// For t2MOVi16 and t2MOVTi16.
> -// imm16 = imm4:i:imm3:imm8;
> -static inline unsigned getImm16(uint32_t insn) {
> - return getImm4(insn) << 12 | slice(insn, 26, 26) << 11 |
> - getImm3(insn) << 8 | getImm8(insn);
> -}
> -
> -// Inst{5-4} encodes the shift type.
> -static inline unsigned getShiftTypeBits(uint32_t insn) {
> - return slice(insn, 5, 4);
> -}
> -
> -// Inst{14-12}:Inst{7-6} encodes the imm5 shift amount.
> -static inline unsigned getShiftAmtBits(uint32_t insn) {
> - return getImm3(insn) << 2 | getImm2(insn);
> -}
> -
> -// A8.6.17 BFC
> -// Encoding T1 ARMv6T2, ARMv7
> -// LLVM-specific encoding for #<lsb> and #<width>
> -static inline bool getBitfieldInvMask(uint32_t insn, uint32_t &mask) {
> - uint32_t lsb = getImm3(insn) << 2 | getImm2(insn);
> - uint32_t msb = getMsb(insn);
> - uint32_t Val = 0;
> - if (msb < lsb) {
> - DEBUG(errs() << "Encoding error: msb < lsb\n");
> - return false;
> - }
> - for (uint32_t i = lsb; i <= msb; ++i)
> - Val |= (1 << i);
> - mask = ~Val;
> - return true;
> -}
> -
> -// A8.4 Shifts applied to a register
> -// A8.4.1 Constant shifts
> -// A8.4.3 Pseudocode details of instruction-specified shifts and rotates
> -//
> -// decodeImmShift() returns the shift amount and the the shift opcode.
> -// Note that, as of Jan-06-2010, LLVM does not support rrx shifted operands yet.
> -static inline unsigned decodeImmShift(unsigned bits2, unsigned imm5,
> - ARM_AM::ShiftOpc &ShOp) {
> -
> - assert(imm5 < 32 && "Invalid imm5 argument");
> - switch (bits2) {
> - default: assert(0 && "No such value");
> - case 0:
> - ShOp = (imm5 == 0 ? ARM_AM::no_shift : ARM_AM::lsl);
> - return imm5;
> - case 1:
> - ShOp = ARM_AM::lsr;
> - return (imm5 == 0 ? 32 : imm5);
> - case 2:
> - ShOp = ARM_AM::asr;
> - return (imm5 == 0 ? 32 : imm5);
> - case 3:
> - ShOp = (imm5 == 0 ? ARM_AM::rrx : ARM_AM::ror);
> - return (imm5 == 0 ? 1 : imm5);
> - }
> -}
> -
> -// A6.3.2 Modified immediate constants in Thumb instructions
> -//
> -// ThumbExpandImm() returns the modified immediate constant given an imm12 for
> -// Thumb data-processing instructions with modified immediate.
> -// See also A6.3.1 Data-processing (modified immediate).
> -static inline unsigned ThumbExpandImm(unsigned imm12) {
> - assert(imm12 <= 0xFFF && "Invalid imm12 argument");
> -
> - // If the leading two bits is 0b00, the modified immediate constant is
> - // obtained by splatting the low 8 bits into the first byte, every other byte,
> - // or every byte of a 32-bit value.
> - //
> - // Otherwise, a rotate right of '1':imm12<6:0> by the amount imm12<11:7> is
> - // performed.
> -
> - if (slice(imm12, 11, 10) == 0) {
> - unsigned short control = slice(imm12, 9, 8);
> - unsigned imm8 = slice(imm12, 7, 0);
> - switch (control) {
> - default:
> - assert(0 && "No such value");
> - return 0;
> - case 0:
> - return imm8;
> - case 1:
> - return imm8 << 16 | imm8;
> - case 2:
> - return imm8 << 24 | imm8 << 8;
> - case 3:
> - return imm8 << 24 | imm8 << 16 | imm8 << 8 | imm8;
> - }
> - } else {
> - // A rotate is required.
> - unsigned Val = 1 << 7 | slice(imm12, 6, 0);
> - unsigned Amt = slice(imm12, 11, 7);
> - return ARM_AM::rotr32(Val, Amt);
> - }
> -}
> -
> -static inline int decodeImm32_B_EncodingT3(uint32_t insn) {
> - bool S = slice(insn, 26, 26);
> - bool J1 = slice(insn, 13, 13);
> - bool J2 = slice(insn, 11, 11);
> - unsigned Imm21 = slice(insn, 21, 16) << 12 | slice(insn, 10, 0) << 1;
> - if (S) Imm21 |= 1 << 20;
> - if (J2) Imm21 |= 1 << 19;
> - if (J1) Imm21 |= 1 << 18;
> -
> - return SignExtend32<21>(Imm21);
> -}
> -
> -static inline int decodeImm32_B_EncodingT4(uint32_t insn) {
> - unsigned S = slice(insn, 26, 26);
> - bool I1 = slice(insn, 13, 13) == S;
> - bool I2 = slice(insn, 11, 11) == S;
> - unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 0) << 1;
> - if (S) Imm25 |= 1 << 24;
> - if (I1) Imm25 |= 1 << 23;
> - if (I2) Imm25 |= 1 << 22;
> -
> - return SignExtend32<25>(Imm25);
> -}
> -
> -static inline int decodeImm32_BL(uint32_t insn) {
> - unsigned S = slice(insn, 26, 26);
> - bool I1 = slice(insn, 13, 13) == S;
> - bool I2 = slice(insn, 11, 11) == S;
> - unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 0) << 1;
> - if (S) Imm25 |= 1 << 24;
> - if (I1) Imm25 |= 1 << 23;
> - if (I2) Imm25 |= 1 << 22;
> -
> - return SignExtend32<25>(Imm25);
> -}
> -
> -static inline int decodeImm32_BLX(uint32_t insn) {
> - unsigned S = slice(insn, 26, 26);
> - bool I1 = slice(insn, 13, 13) == S;
> - bool I2 = slice(insn, 11, 11) == S;
> - unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 1) << 2;
> - if (S) Imm25 |= 1 << 24;
> - if (I1) Imm25 |= 1 << 23;
> - if (I2) Imm25 |= 1 << 22;
> -
> - return SignExtend32<25>(Imm25);
> -}
> -
> -///////////////////////////////////////////////
> -// //
> -// Thumb1 instruction disassembly functions. //
> -// //
> -///////////////////////////////////////////////
> -
> -// See "Utilities for 16-bit Thumb instructions" for register naming convention.
> -
> -// A6.2.1 Shift (immediate), add, subtract, move, and compare
> -//
> -// shift immediate: tRd CPSR tRn imm5
> -// add/sub register: tRd CPSR tRn tRm
> -// add/sub 3-bit immediate: tRd CPSR tRn imm3
> -// add/sub 8-bit immediate: tRt CPSR tRt(TIED_TO) imm8
> -// mov/cmp immediate: tRt [CPSR] imm8 (CPSR present for mov)
> -//
> -// Special case:
> -// tMOVSr: tRd tRn
> -static bool DisassembleThumb1General(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID
> - && "Invalid arguments");
> -
> - bool Imm3 = (Opcode == ARM::tADDi3 || Opcode == ARM::tSUBi3);
> -
> - // Use Rt implies use imm8.
> - bool UseRt = (Opcode == ARM::tADDi8 || Opcode == ARM::tSUBi8 ||
> - Opcode == ARM::tMOVi8 || Opcode == ARM::tCMPi8);
> -
> - // Add the destination operand.
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, ARM::tGPRRegClassID,
> - UseRt ? getT1tRt(insn) : getT1tRd(insn))));
> - ++OpIdx;
> -
> - // Check whether the next operand to be added is a CCR Register.
> - if (OpInfo[OpIdx].RegClass == ARM::CCRRegClassID) {
> - assert(OpInfo[OpIdx].isOptionalDef() && "Optional def operand expected");
> - MI.addOperand(MCOperand::CreateReg(B->InITBlock() ? 0 : ARM::CPSR));
> - ++OpIdx;
> - }
> -
> - // Check whether the next operand to be added is a Thumb1 Register.
> - assert(OpIdx < NumOps && "More operands expected");
> - if (OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) {
> - // For UseRt, the reg operand is tied to the first reg operand.
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, ARM::tGPRRegClassID,
> - UseRt ? getT1tRt(insn) : getT1tRn(insn))));
> - ++OpIdx;
> - }
> -
> - // Special case for tMOVSr.
> - if (OpIdx == NumOps)
> - return true;
> -
> - // The next available operand is either a reg operand or an imm operand.
> - if (OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) {
> - // Three register operand instructions.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRm(insn))));
> - } else {
> - assert(OpInfo[OpIdx].RegClass < 0 &&
> - !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()
> - && "Pure imm operand expected");
> - unsigned Imm = 0;
> - if (UseRt)
> - Imm = getT1Imm8(insn);
> - else if (Imm3)
> - Imm = getT1Imm3(insn);
> - else {
> - Imm = getT1Imm5(insn);
> - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 12, 11));
> - getImmShiftSE(ShOp, Imm);
> - }
> - MI.addOperand(MCOperand::CreateImm(Imm));
> - }
> - ++OpIdx;
> -
> - return true;
> -}
> -
> -// A6.2.2 Data-processing
> -//
> -// tCMPr, tTST, tCMN: tRd tRn
> -// tMVN, tRSB: tRd CPSR tRn
> -// Others: tRd CPSR tRd(TIED_TO) tRn
> -static bool DisassembleThumb1DP(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
> - (OpInfo[1].RegClass == ARM::CCRRegClassID
> - || OpInfo[1].RegClass == ARM::tGPRRegClassID)
> - && "Invalid arguments");
> -
> - // Add the destination operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRd(insn))));
> - ++OpIdx;
> -
> - // Check whether the next operand to be added is a CCR Register.
> - if (OpInfo[OpIdx].RegClass == ARM::CCRRegClassID) {
> - assert(OpInfo[OpIdx].isOptionalDef() && "Optional def operand expected");
> - MI.addOperand(MCOperand::CreateReg(B->InITBlock() ? 0 : ARM::CPSR));
> - ++OpIdx;
> - }
> -
> - // We have either { tRd(TIED_TO), tRn } or { tRn } remaining.
> - // Process the TIED_TO operand first.
> -
> - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID
> - && "Thumb reg operand expected");
> - int Idx;
> - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
> - // The reg operand is tied to the first reg operand.
> - MI.addOperand(MI.getOperand(Idx));
> - ++OpIdx;
> - }
> -
> - // Process possible next reg operand.
> - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) {
> - // Add tRn operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRn(insn))));
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -// A6.2.3 Special data instructions and branch and exchange
> -//
> -// tADDhirr: Rd Rd(TIED_TO) Rm
> -// tCMPhir: Rd Rm
> -// tMOVr, tMOVgpr2gpr, tMOVgpr2tgpr, tMOVtgpr2gpr: Rd|tRd Rm|tRn
> -// tBX: Rm
> -// tBX_RET: 0 operand
> -// tBX_RET_vararg: Rm
> -// tBLXr: Rm
> -// tBRIND: Rm
> -static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - // tBX_RET has 0 operand.
> - if (NumOps == 0)
> - return true;
> -
> - // BX/BLX/tBRIND (indirect branch, i.e, mov pc, Rm) has 1 reg operand: Rm.
> - if (Opcode==ARM::tBLXr || Opcode==ARM::tBX || Opcode==ARM::tBRIND) {
> - if (Opcode == ARM::tBLXr) {
> - // Handling the two predicate operands before the reg operand.
> - if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps))
> - return false;
> - NumOpsAdded += 2;
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - getT1Rm(insn))));
> - NumOpsAdded += 1;
> -
> - if (Opcode == ARM::tBX) {
> - // Handling the two predicate operands after the reg operand.
> - if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps))
> - return false;
> - NumOpsAdded += 2;
> - }
> -
> - return true;
> - }
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - // Add the destination operand.
> - unsigned RegClass = OpInfo[OpIdx].RegClass;
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RegClass,
> - IsGPR(RegClass) ? getT1Rd(insn)
> - : getT1tRd(insn))));
> - ++OpIdx;
> -
> - // We have either { Rd(TIED_TO), Rm } or { Rm|tRn } remaining.
> - // Process the TIED_TO operand first.
> -
> - assert(OpIdx < NumOps && "More operands expected");
> - int Idx;
> - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
> - // The reg operand is tied to the first reg operand.
> - MI.addOperand(MI.getOperand(Idx));
> - ++OpIdx;
> - }
> -
> - // The next reg operand is either Rm or tRn.
> - assert(OpIdx < NumOps && "More operands expected");
> - RegClass = OpInfo[OpIdx].RegClass;
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RegClass,
> - IsGPR(RegClass) ? getT1Rm(insn)
> - : getT1tRn(insn))));
> - ++OpIdx;
> -
> - return true;
> -}
> -
> -// A8.6.59 LDR (literal)
> -//
> -// tLDRpci: tRt imm8*4
> -static bool DisassembleThumb1LdPC(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
> - (OpInfo[1].RegClass < 0 &&
> - !OpInfo[1].isPredicate() &&
> - !OpInfo[1].isOptionalDef())
> - && "Invalid arguments");
> -
> - // Add the destination operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRt(insn))));
> -
> - // And the (imm8 << 2) operand.
> - MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn) << 2));
> -
> - NumOpsAdded = 2;
> -
> - return true;
> -}
> -
> -// Thumb specific addressing modes (see ARMInstrThumb.td):
> -//
> -// t_addrmode_rr := reg + reg
> -//
> -// t_addrmode_s4 := reg + reg
> -// reg + imm5 * 4
> -//
> -// t_addrmode_s2 := reg + reg
> -// reg + imm5 * 2
> -//
> -// t_addrmode_s1 := reg + reg
> -// reg + imm5
> -//
> -// t_addrmode_sp := sp + imm8 * 4
> -//
> -
> -// A8.6.63 LDRB (literal)
> -// A8.6.79 LDRSB (literal)
> -// A8.6.75 LDRH (literal)
> -// A8.6.83 LDRSH (literal)
> -// A8.6.59 LDR (literal)
> -//
> -// These instrs calculate an address from the PC value and an immediate offset.
> -// Rd Rn=PC (+/-)imm12 (+ if Inst{23} == 0b1)
> -static bool DisassembleThumb2Ldpci(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - assert(NumOps >= 2 &&
> - OpInfo[0].RegClass == ARM::GPRRegClassID &&
> - OpInfo[1].RegClass < 0 &&
> - "Expect >= 2 operands, first as reg, and second as imm operand");
> -
> - // Build the register operand, followed by the (+/-)imm12 immediate.
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRd(insn))));
> -
> - MI.addOperand(MCOperand::CreateImm(decodeImm12(insn)));
> -
> - NumOpsAdded = 2;
> -
> - return true;
> -}
> -
> -
> -// A6.2.4 Load/store single data item
> -//
> -// Load/Store Register (reg|imm): tRd tRn imm5|tRm
> -// Load Register Signed Byte|Halfword: tRd tRn tRm
> -static bool DisassembleThumb1LdSt(unsigned opA, MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - assert(NumOps >= 2
> - && OpInfo[0].RegClass == ARM::tGPRRegClassID
> - && OpInfo[1].RegClass == ARM::tGPRRegClassID
> - && "Expect >= 2 operands and first two as thumb reg operands");
> -
> - // Add the destination reg and the base reg.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRd(insn))));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRn(insn))));
> - OpIdx = 2;
> -
> - // We have either { imm5 } or { tRm } remaining.
> - // Note that STR/LDR (register) should skip the imm5 offset operand for
> - // t_addrmode_s[1|2|4].
> -
> - assert(OpIdx < NumOps && "More operands expected");
> -
> - if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() &&
> - !OpInfo[OpIdx].isOptionalDef()) {
> - // Table A6-5 16-bit Thumb Load/store instructions
> - // opA = 0b0101 for STR/LDR (register) and friends.
> - // Otherwise, we have STR/LDR (immediate) and friends.
> - assert(opA != 5 && "Immediate operand expected for this opcode");
> - MI.addOperand(MCOperand::CreateImm(getT1Imm5(insn)));
> - ++OpIdx;
> - } else {
> - // The next reg operand is tRm, the offset.
> - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID
> - && "Thumb reg operand expected");
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRm(insn))));
> - ++OpIdx;
> - }
> - return true;
> -}
> -
> -// A6.2.4 Load/store single data item
> -//
> -// Load/Store Register SP relative: tRt ARM::SP imm8
> -static bool DisassembleThumb1LdStSP(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert((Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)
> - && "Unexpected opcode");
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - assert(NumOps >= 3 &&
> - OpInfo[0].RegClass == ARM::tGPRRegClassID &&
> - OpInfo[1].RegClass == ARM::GPRRegClassID &&
> - (OpInfo[2].RegClass < 0 &&
> - !OpInfo[2].isPredicate() &&
> - !OpInfo[2].isOptionalDef())
> - && "Invalid arguments");
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRt(insn))));
> - MI.addOperand(MCOperand::CreateReg(ARM::SP));
> - MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn)));
> - NumOpsAdded = 3;
> - return true;
> -}
> -
> -// Table A6-1 16-bit Thumb instruction encoding
> -// A8.6.10 ADR
> -//
> -// tADDrPCi: tRt imm8
> -static bool DisassembleThumb1AddPCi(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(Opcode == ARM::tADDrPCi && "Unexpected opcode");
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
> - (OpInfo[1].RegClass < 0 &&
> - !OpInfo[1].isPredicate() &&
> - !OpInfo[1].isOptionalDef())
> - && "Invalid arguments");
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRt(insn))));
> - MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn)));
> - NumOpsAdded = 2;
> - return true;
> -}
> -
> -// Table A6-1 16-bit Thumb instruction encoding
> -// A8.6.8 ADD (SP plus immediate)
> -//
> -// tADDrSPi: tRt ARM::SP imm8
> -static bool DisassembleThumb1AddSPi(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(Opcode == ARM::tADDrSPi && "Unexpected opcode");
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - assert(NumOps >= 3 &&
> - OpInfo[0].RegClass == ARM::tGPRRegClassID &&
> - OpInfo[1].RegClass == ARM::GPRRegClassID &&
> - (OpInfo[2].RegClass < 0 &&
> - !OpInfo[2].isPredicate() &&
> - !OpInfo[2].isOptionalDef())
> - && "Invalid arguments");
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRt(insn))));
> - MI.addOperand(MCOperand::CreateReg(ARM::SP));
> - MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn)));
> - NumOpsAdded = 3;
> - return true;
> -}
> -
> -// tPUSH, tPOP: Pred-Imm Pred-CCR register_list
> -//
> -// where register_list = low registers + [lr] for PUSH or
> -// low registers + [pc] for POP
> -//
> -// "low registers" is specified by Inst{7-0}
> -// lr|pc is specified by Inst{8}
> -static bool DisassembleThumb1PushPop(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert((Opcode == ARM::tPUSH || Opcode == ARM::tPOP) && "Unexpected opcode");
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - // Handling the two predicate operands before the reglist.
> - if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
> - OpIdx += 2;
> - else {
> - DEBUG(errs() << "Expected predicate operands not found.\n");
> - return false;
> - }
> -
> - unsigned RegListBits = slice(insn, 8, 8) << (Opcode == ARM::tPUSH ? 14 : 15)
> - | slice(insn, 7, 0);
> -
> - // Fill the variadic part of reglist.
> - for (unsigned i = 0; i < 16; ++i) {
> - if ((RegListBits >> i) & 1) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - i)));
> - ++OpIdx;
> - }
> - }
> -
> - return true;
> -}
> -
> -// A6.2.5 Miscellaneous 16-bit instructions
> -// Delegate to DisassembleThumb1PushPop() for tPUSH & tPOP.
> -//
> -// tADDspi, tSUBspi: ARM::SP ARM::SP(TIED_TO) imm7
> -// t2IT: firstcond=Inst{7-4} mask=Inst{3-0}
> -// tCBNZ, tCBZ: tRd imm6*2
> -// tBKPT: imm8
> -// tNOP, tSEV, tYIELD, tWFE, tWFI:
> -// no operand (except predicate pair)
> -// tSETEND: i1
> -// Others: tRd tRn
> -static bool DisassembleThumb1Misc(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - if (NumOps == 0)
> - return true;
> -
> - if (Opcode == ARM::tPUSH || Opcode == ARM::tPOP)
> - return DisassembleThumb1PushPop(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> -
> - // Predicate operands are handled elsewhere.
> - if (NumOps == 2 &&
> - OpInfo[0].isPredicate() && OpInfo[1].isPredicate() &&
> - OpInfo[0].RegClass < 0 && OpInfo[1].RegClass == ARM::CCRRegClassID) {
> - return true;
> - }
> -
> - if (Opcode == ARM::tADDspi || Opcode == ARM::tSUBspi) {
> - // Special case handling for tADDspi and tSUBspi.
> - // A8.6.8 ADD (SP plus immediate) & A8.6.215 SUB (SP minus immediate)
> - MI.addOperand(MCOperand::CreateReg(ARM::SP));
> - MI.addOperand(MCOperand::CreateReg(ARM::SP));
> - MI.addOperand(MCOperand::CreateImm(getT1Imm7(insn)));
> - NumOpsAdded = 3;
> - return true;
> - }
> -
> - if (Opcode == ARM::t2IT) {
> - // Special case handling for If-Then.
> - // A8.6.50 IT
> - // Tag the (firstcond[0] bit << 4) along with mask.
> -
> - // firstcond
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 4)));
> -
> - // firstcond[0] and mask
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));
> - NumOpsAdded = 2;
> - return true;
> - }
> -
> - if (Opcode == ARM::tBKPT) {
> - MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn))); // breakpoint value
> - NumOpsAdded = 1;
> - return true;
> - }
> -
> - // CPS has a singleton $opt operand that contains the following information:
> - // The first op would be 0b10 as enable and 0b11 as disable in regular ARM,
> - // but in Thumb it's is 0 as enable and 1 as disable. So map it to ARM's
> - // default one. The second get the AIF flags from Inst{2-0}.
> - if (Opcode == ARM::tCPS) {
> - MI.addOperand(MCOperand::CreateImm(2 + slice(insn, 4, 4)));
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 2, 0)));
> - NumOpsAdded = 2;
> - return true;
> - }
> -
> - if (Opcode == ARM::tSETEND) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 1)));
> - NumOpsAdded = 1;
> - return true;
> - }
> -
> - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
> - (OpInfo[1].RegClass < 0 || OpInfo[1].RegClass==ARM::tGPRRegClassID)
> - && "Expect >=2 operands");
> -
> - // Add the destination operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRd(insn))));
> -
> - if (OpInfo[1].RegClass == ARM::tGPRRegClassID) {
> - // Two register instructions.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - getT1tRn(insn))));
> - } else {
> - // CBNZ, CBZ
> - assert((Opcode == ARM::tCBNZ || Opcode == ARM::tCBZ) &&"Unexpected opcode");
> - MI.addOperand(MCOperand::CreateImm(getT1Imm6(insn) * 2));
> - }
> -
> - NumOpsAdded = 2;
> -
> - return true;
> -}
> -
> -// A8.6.53 LDM / LDMIA
> -// A8.6.189 STM / STMIA
> -//
> -// tLDMIA_UPD/tSTMIA_UPD: tRt tRt AM4ModeImm Pred-Imm Pred-CCR register_list
> -// tLDMIA: tRt AM4ModeImm Pred-Imm Pred-CCR register_list
> -static bool DisassembleThumb1LdStMul(bool Ld, MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps,
> - unsigned &NumOpsAdded, BO B) {
> - assert((Opcode == ARM::tLDMIA || Opcode == ARM::tSTMIA) &&
> - "Unexpected opcode");
> -
> - unsigned tRt = getT1tRt(insn);
> - NumOpsAdded = 0;
> -
> - // WB register, if necessary.
> - if (Opcode == ARM::tLDMIA_UPD || Opcode == ARM::tSTMIA_UPD) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - tRt)));
> - ++NumOpsAdded;
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - tRt)));
> - ++NumOpsAdded;
> -
> - // Handling the two predicate operands before the reglist.
> - if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) {
> - NumOpsAdded += 2;
> - } else {
> - DEBUG(errs() << "Expected predicate operands not found.\n");
> - return false;
> - }
> -
> - unsigned RegListBits = slice(insn, 7, 0);
> - if (BitCount(RegListBits) < 1) {
> - DEBUG(errs() << "if BitCount(registers) < 1 then UNPREDICTABLE\n");
> - return false;
> - }
> -
> - // Fill the variadic part of reglist.
> - for (unsigned i = 0; i < 8; ++i)
> - if ((RegListBits >> i) & 1) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
> - i)));
> - ++NumOpsAdded;
> - }
> -
> - return true;
> -}
> -
> -static bool DisassembleThumb1LdMul(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> - return DisassembleThumb1LdStMul(true, MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> -}
> -
> -static bool DisassembleThumb1StMul(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> - return DisassembleThumb1LdStMul(false, MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> -}
> -
> -// A8.6.16 B Encoding T1
> -// cond = Inst{11-8} & imm8 = Inst{7-0}
> -// imm32 = SignExtend(imm8:'0', 32)
> -//
> -// tBcc: offset Pred-Imm Pred-CCR
> -// tSVC: imm8 Pred-Imm Pred-CCR
> -// tTRAP: 0 operand (early return)
> -static bool DisassembleThumb1CondBr(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO) {
> -
> - if (Opcode == ARM::tTRAP)
> - return true;
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - assert(NumOps == 3 && OpInfo[0].RegClass < 0 &&
> - OpInfo[1].isPredicate() && OpInfo[2].RegClass == ARM::CCRRegClassID
> - && "Exactly 3 operands expected");
> -
> - unsigned Imm8 = getT1Imm8(insn);
> - MI.addOperand(MCOperand::CreateImm(
> - Opcode == ARM::tBcc ? SignExtend32<9>(Imm8 << 1)
> - : (int)Imm8));
> -
> - // Predicate operands by ARMBasicMCBuilder::TryPredicateAndSBitModifier().
> - // But note that for tBcc, if cond = '1110' then UNDEFINED.
> - if (Opcode == ARM::tBcc && slice(insn, 11, 8) == 14) {
> - DEBUG(errs() << "if cond = '1110' then UNDEFINED\n");
> - return false;
> - }
> - NumOpsAdded = 1;
> -
> - return true;
> -}
> -
> -// A8.6.16 B Encoding T2
> -// imm11 = Inst{10-0}
> -// imm32 = SignExtend(imm11:'0', 32)
> -//
> -// tB: offset
> -static bool DisassembleThumb1Br(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - assert(NumOps == 1 && OpInfo[0].RegClass < 0 && "1 imm operand expected");
> -
> - unsigned Imm11 = getT1Imm11(insn);
> -
> - MI.addOperand(MCOperand::CreateImm(SignExtend32<12>(Imm11 << 1)));
> -
> - NumOpsAdded = 1;
> -
> - return true;
> -
> -}
> -
> -// See A6.2 16-bit Thumb instruction encoding for instruction classes
> -// corresponding to op.
> -//
> -// Table A6-1 16-bit Thumb instruction encoding (abridged)
> -// op Instruction or instruction class
> -// ------ --------------------------------------------------------------------
> -// 00xxxx Shift (immediate), add, subtract, move, and compare on page A6-7
> -// 010000 Data-processing on page A6-8
> -// 010001 Special data instructions and branch and exchange on page A6-9
> -// 01001x Load from Literal Pool, see LDR (literal) on page A8-122
> -// 0101xx Load/store single data item on page A6-10
> -// 011xxx
> -// 100xxx
> -// 10100x Generate PC-relative address, see ADR on page A8-32
> -// 10101x Generate SP-relative address, see ADD (SP plus immediate) on
> -// page A8-28
> -// 1011xx Miscellaneous 16-bit instructions on page A6-11
> -// 11000x Store multiple registers, see STM / STMIA / STMEA on page A8-374
> -// 11001x Load multiple registers, see LDM / LDMIA / LDMFD on page A8-110 a
> -// 1101xx Conditional branch, and Supervisor Call on page A6-13
> -// 11100x Unconditional Branch, see B on page A8-44
> -//
> -static bool DisassembleThumb1(uint16_t op, MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - unsigned op1 = slice(op, 5, 4);
> - unsigned op2 = slice(op, 3, 2);
> - unsigned op3 = slice(op, 1, 0);
> - unsigned opA = slice(op, 5, 2);
> - switch (op1) {
> - case 0:
> - // A6.2.1 Shift (immediate), add, subtract, move, and compare
> - return DisassembleThumb1General(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - case 1:
> - switch (op2) {
> - case 0:
> - switch (op3) {
> - case 0:
> - // A6.2.2 Data-processing
> - return DisassembleThumb1DP(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - case 1:
> - // A6.2.3 Special data instructions and branch and exchange
> - return DisassembleThumb1Special(MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - default:
> - // A8.6.59 LDR (literal)
> - return DisassembleThumb1LdPC(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - }
> - break;
> - default:
> - // A6.2.4 Load/store single data item
> - return DisassembleThumb1LdSt(opA, MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - break;
> - }
> - break;
> - case 2:
> - switch (op2) {
> - case 0:
> - // A6.2.4 Load/store single data item
> - return DisassembleThumb1LdSt(opA, MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - case 1:
> - // A6.2.4 Load/store single data item
> - return DisassembleThumb1LdStSP(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - case 2:
> - if (op3 <= 1) {
> - // A8.6.10 ADR
> - return DisassembleThumb1AddPCi(MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - } else {
> - // A8.6.8 ADD (SP plus immediate)
> - return DisassembleThumb1AddSPi(MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - }
> - default:
> - // A6.2.5 Miscellaneous 16-bit instructions
> - return DisassembleThumb1Misc(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - }
> - break;
> - case 3:
> - switch (op2) {
> - case 0:
> - if (op3 <= 1) {
> - // A8.6.189 STM / STMIA / STMEA
> - return DisassembleThumb1StMul(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - } else {
> - // A8.6.53 LDM / LDMIA / LDMFD
> - return DisassembleThumb1LdMul(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - }
> - case 1:
> - // A6.2.6 Conditional branch, and Supervisor Call
> - return DisassembleThumb1CondBr(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - case 2:
> - // Unconditional Branch, see B on page A8-44
> - return DisassembleThumb1Br(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - default:
> - assert(0 && "Unreachable code");
> - break;
> - }
> - break;
> - default:
> - assert(0 && "Unreachable code");
> - break;
> - }
> -
> - return false;
> -}
> -
> -///////////////////////////////////////////////
> -// //
> -// Thumb2 instruction disassembly functions. //
> -// //
> -///////////////////////////////////////////////
> -
> -///////////////////////////////////////////////////////////
> -// //
> -// Note: the register naming follows the ARM convention! //
> -// //
> -///////////////////////////////////////////////////////////
> -
> -static inline bool Thumb2SRSOpcode(unsigned Opcode) {
> - switch (Opcode) {
> - default:
> - return false;
> - case ARM::t2SRSDBW: case ARM::t2SRSDB:
> - case ARM::t2SRSIAW: case ARM::t2SRSIA:
> - return true;
> - }
> -}
> -
> -static inline bool Thumb2RFEOpcode(unsigned Opcode) {
> - switch (Opcode) {
> - default:
> - return false;
> - case ARM::t2RFEDBW: case ARM::t2RFEDB:
> - case ARM::t2RFEIAW: case ARM::t2RFEIA:
> - return true;
> - }
> -}
> -
> -// t2SRS[IA|DB]W/t2SRS[IA|DB]: mode_imm = Inst{4-0}
> -static bool DisassembleThumb2SRS(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));
> - NumOpsAdded = 1;
> - return true;
> -}
> -
> -// t2RFE[IA|DB]W/t2RFE[IA|DB]: Rn
> -static bool DisassembleThumb2RFE(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> - unsigned Rn = decodeRn(insn);
> - if (Rn == 15) {
> - DEBUG(errs() << "if n == 15 then UNPREDICTABLE\n");
> - return false;
> - }
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,ARM::GPRRegClassID,Rn)));
> - NumOpsAdded = 1;
> - return true;
> -}
> -
> -static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - if (Thumb2SRSOpcode(Opcode))
> - return DisassembleThumb2SRS(MI, Opcode, insn, NumOps, NumOpsAdded);
> -
> - if (Thumb2RFEOpcode(Opcode))
> - return DisassembleThumb2RFE(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> -
> - assert((Opcode == ARM::t2LDMIA || Opcode == ARM::t2LDMIA_UPD ||
> - Opcode == ARM::t2LDMDB || Opcode == ARM::t2LDMDB_UPD ||
> - Opcode == ARM::t2STMIA || Opcode == ARM::t2STMIA_UPD ||
> - Opcode == ARM::t2STMDB || Opcode == ARM::t2STMDB_UPD)
> - && "Unexpected opcode");
> - assert(NumOps >= 4 && "Thumb2 LdStMul expects NumOps >= 4");
> -
> - NumOpsAdded = 0;
> -
> - unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
> -
> - // Writeback to base.
> - if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD ||
> - Opcode == ARM::t2STMIA_UPD || Opcode == ARM::t2STMDB_UPD) {
> - MI.addOperand(MCOperand::CreateReg(Base));
> - ++NumOpsAdded;
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(Base));
> - ++NumOpsAdded;
> -
> - // Handling the two predicate operands before the reglist.
> - if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) {
> - NumOpsAdded += 2;
> - } else {
> - DEBUG(errs() << "Expected predicate operands not found.\n");
> - return false;
> - }
> -
> - unsigned RegListBits = insn & ((1 << 16) - 1);
> -
> - // Fill the variadic part of reglist.
> - for (unsigned i = 0; i < 16; ++i)
> - if ((RegListBits >> i) & 1) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - i)));
> - ++NumOpsAdded;
> - }
> -
> - return true;
> -}
> -
> -// t2LDREX: Rd Rn
> -// t2LDREXD: Rd Rs Rn
> -// t2LDREXB, t2LDREXH: Rd Rn
> -// t2STREX: Rs Rd Rn
> -// t2STREXD: Rm Rd Rs Rn
> -// t2STREXB, t2STREXH: Rm Rd Rn
> -static bool DisassembleThumb2LdStEx(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(NumOps >= 2
> - && OpInfo[0].RegClass > 0
> - && OpInfo[1].RegClass > 0
> - && "Expect >=2 operands and first two as reg operands");
> -
> - bool isStore = (ARM::t2STREX <= Opcode && Opcode <= ARM::t2STREXH);
> - bool isSW = (Opcode == ARM::t2LDREX || Opcode == ARM::t2STREX);
> - bool isDW = (Opcode == ARM::t2LDREXD || Opcode == ARM::t2STREXD);
> -
> - unsigned Rt = decodeRd(insn);
> - unsigned Rt2 = decodeRs(insn); // But note that this is Rd for t2STREX.
> - unsigned Rd = decodeRm(insn);
> - unsigned Rn = decodeRn(insn);
> -
> - // Some sanity checking first.
> - if (isStore) {
> - // if d == n || d == t then UNPREDICTABLE
> - // if d == n || d == t || d == t2 then UNPREDICTABLE
> - if (isDW) {
> - if (Rd == Rn || Rd == Rt || Rd == Rt2) {
> - DEBUG(errs() << "if d == n || d == t || d == t2 then UNPREDICTABLE\n");
> - return false;
> - }
> - } else {
> - if (isSW) {
> - if (Rt2 == Rn || Rt2 == Rt) {
> - DEBUG(errs() << "if d == n || d == t then UNPREDICTABLE\n");
> - return false;
> - }
> - } else {
> - if (Rd == Rn || Rd == Rt) {
> - DEBUG(errs() << "if d == n || d == t then UNPREDICTABLE\n");
> - return false;
> - }
> - }
> - }
> - } else {
> - // Load
> - // A8.6.71 LDREXD
> - // if t == t2 then UNPREDICTABLE
> - if (isDW && Rt == Rt2) {
> - DEBUG(errs() << "if t == t2 then UNPREDICTABLE\n");
> - return false;
> - }
> - }
> -
> - // Add the destination operand for store.
> - if (isStore) {
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - isSW ? Rt2 : Rd)));
> - ++OpIdx;
> - }
> -
> - // Source operand for store and destination operand for load.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - Rt)));
> - ++OpIdx;
> -
> - // Thumb2 doubleword complication: with an extra source/destination operand.
> - if (isDW) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass,
> - Rt2)));
> - ++OpIdx;
> - }
> -
> - // Finally add the pointer operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - Rn)));
> - ++OpIdx;
> -
> - return true;
> -}
> -
> -// t2LDRDi8: Rd Rs Rn imm8s4 (offset mode)
> -// t2LDRDpci: Rd Rs imm8s4 (Not decoded, prefer the generic t2LDRDi8 version)
> -// t2STRDi8: Rd Rs Rn imm8s4 (offset mode)
> -//
> -// Ditto for t2LDRD_PRE, t2LDRD_POST, t2STRD_PRE, t2STRD_POST, which are for
> -// disassembly only and do not have a tied_to writeback base register operand.
> -static bool DisassembleThumb2LdStDual(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> - if (!OpInfo) return false;
> -
> - // Thumnb allows for specifying Rt and Rt2, unlike ARM (which has Rt2==Rt+1).
> - unsigned Rt = decodeRd(insn);
> - unsigned Rt2 = decodeRs(insn);
> - unsigned Rn = decodeRn(insn);
> -
> - // Some sanity checking first.
> -
> - // A8.6.67 LDRD (literal) has its W bit as (0).
> - if (Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2LDRD_PRE || Opcode == ARM::t2LDRD_POST) {
> - if (Rn == 15 && slice(insn, 21, 21) != 0)
> - return false;
> - } else {
> - // For Dual Store, PC cannot be used as the base register.
> - if (Rn == 15) {
> - DEBUG(errs() << "if n == 15 then UNPREDICTABLE\n");
> - return false;
> - }
> - }
> - if (Rt == Rt2) {
> - DEBUG(errs() << "if t == t2 then UNPREDICTABLE\n");
> - return false;
> - }
> - if (Opcode != ARM::t2LDRDi8 && Opcode != ARM::t2STRDi8) {
> - if (Rn == Rt || Rn == Rt2) {
> - DEBUG(errs() << "if wback && (n == t || n == t2) then UNPREDICTABLE\n");
> - return false;
> - }
> - }
> -
> - // Add the <Rt> <Rt2> operands.
> - unsigned RegClassPair = OpInfo[0].RegClass;
> - unsigned RegClassBase = OpInfo[2].RegClass;
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassPair,
> - decodeRd(insn))));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassPair,
> - decodeRs(insn))));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassBase,
> - decodeRn(insn))));
> - unsigned Added = 4;
> - switch (MI.getOpcode()) {
> - case ARM::t2LDRD_PRE:
> - case ARM::t2LDRD_POST:
> - case ARM::t2STRD_PRE:
> - case ARM::t2STRD_POST:
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassBase,
> - decodeRn(insn))));
> - Added = 5;
> - default:
> - break;
> - }
> -
> - // Finally add (+/-)imm8*4, depending on the U bit.
> - int Offset = getImm8(insn) * 4;
> - if (getUBit(insn) == 0)
> - Offset = -Offset;
> - MI.addOperand(MCOperand::CreateImm(Offset));
> - NumOpsAdded = Added;
> -
> - return true;
> -}
> -
> -// t2TBB, t2TBH: Rn Rm Pred-Imm Pred-CCR
> -static bool DisassembleThumb2TB(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - assert(NumOps >= 2 && "Expect >= 2 operands");
> -
> - // The generic version of TBB/TBH needs a base register.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - // Add the index register.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - NumOpsAdded = 2;
> -
> - return true;
> -}
> -
> -static inline bool Thumb2ShiftOpcode(unsigned Opcode) {
> - switch (Opcode) {
> - default:
> - return false;
> - case ARM::t2MOVCClsl: case ARM::t2MOVCClsr:
> - case ARM::t2MOVCCasr: case ARM::t2MOVCCror:
> - case ARM::t2LSLri: case ARM::t2LSRri:
> - case ARM::t2ASRri: case ARM::t2RORri:
> - return true;
> - }
> -}
> -
> -// A6.3.11 Data-processing (shifted register)
> -//
> -// Two register operands (Rn=0b1111 no 1st operand reg): Rs Rm
> -// Two register operands (Rs=0b1111 no dst operand reg): Rn Rm
> -// Three register operands: Rs Rn Rm
> -// Three register operands: (Rn=0b1111 Conditional Move) Rs Ro(TIED_TO) Rm
> -//
> -// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
> -// register with shift forms: (Rm, ConstantShiftSpecifier).
> -// Constant shift specifier: Imm = (ShOp | ShAmt<<3).
> -//
> -// There are special instructions, like t2MOVsra_flag and t2MOVsrl_flag, which
> -// only require two register operands: Rd, Rm in ARM Reference Manual terms, and
> -// nothing else, because the shift amount is already specified.
> -// Similar case holds for t2MOVrx, t2ADDrr, ..., etc.
> -static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - // Special case handling.
> - if (Opcode == ARM::t2BR_JT) {
> - assert(NumOps == 4
> - && OpInfo[0].RegClass == ARM::GPRRegClassID
> - && OpInfo[1].RegClass == ARM::GPRRegClassID
> - && OpInfo[2].RegClass < 0
> - && OpInfo[3].RegClass < 0
> - && "Exactly 4 operands expect and first two as reg operands");
> - // Only need to populate the src reg operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - MI.addOperand(MCOperand::CreateReg(0));
> - MI.addOperand(MCOperand::CreateImm(0));
> - MI.addOperand(MCOperand::CreateImm(0));
> - NumOpsAdded = 4;
> - return true;
> - }
> -
> - OpIdx = 0;
> -
> - assert(NumOps >= 2
> - && (OpInfo[0].RegClass == ARM::GPRRegClassID ||
> - OpInfo[0].RegClass == ARM::rGPRRegClassID)
> - && (OpInfo[1].RegClass == ARM::GPRRegClassID ||
> - OpInfo[1].RegClass == ARM::rGPRRegClassID)
> - && "Expect >= 2 operands and first two as reg operands");
> -
> - bool ThreeReg = (NumOps > 2 && (OpInfo[2].RegClass == ARM::GPRRegClassID ||
> - OpInfo[2].RegClass == ARM::rGPRRegClassID));
> - bool NoDstReg = (decodeRs(insn) == 0xF);
> -
> - // Build the register operands, followed by the constant shift specifier.
> -
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, OpInfo[0].RegClass,
> - NoDstReg ? decodeRn(insn) : decodeRs(insn))));
> - ++OpIdx;
> -
> - if (ThreeReg) {
> - int Idx;
> - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
> - // Process tied_to operand constraint.
> - MI.addOperand(MI.getOperand(Idx));
> - ++OpIdx;
> - } else if (!NoDstReg) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[1].RegClass,
> - decodeRn(insn))));
> - ++OpIdx;
> - } else {
> - DEBUG(errs() << "Thumb2 encoding error: d==15 for three-reg operands.\n");
> - return false;
> - }
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - decodeRm(insn))));
> - ++OpIdx;
> -
> - if (NumOps == OpIdx)
> - return true;
> -
> - if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
> - && !OpInfo[OpIdx].isOptionalDef()) {
> -
> - if (Thumb2ShiftOpcode(Opcode)) {
> - unsigned Imm = getShiftAmtBits(insn);
> - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 5, 4));
> - getImmShiftSE(ShOp, Imm);
> - MI.addOperand(MCOperand::CreateImm(Imm));
> - } else {
> - // Build the constant shift specifier operand.
> - unsigned imm5 = getShiftAmtBits(insn);
> - // The PKHBT/PKHTB instructions have an implied shift type and so just
> - // use a plain immediate for the amount.
> - if (Opcode == ARM::t2PKHBT || Opcode == ARM::t2PKHTB)
> - MI.addOperand(MCOperand::CreateImm(imm5));
> - else {
> - ARM_AM::ShiftOpc ShOp = ARM_AM::no_shift;
> - unsigned bits2 = getShiftTypeBits(insn);
> - unsigned ShAmt = decodeImmShift(bits2, imm5, ShOp);
> - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShAmt)));
> - }
> - }
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -// A6.3.1 Data-processing (modified immediate)
> -//
> -// Two register operands: Rs Rn ModImm
> -// One register operands (Rs=0b1111 no explicit dest reg): Rn ModImm
> -// One register operands (Rn=0b1111 no explicit src reg): Rs ModImm -
> -// {t2MOVi, t2MVNi}
> -//
> -// ModImm = ThumbExpandImm(i:imm3:imm8)
> -static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - unsigned RdRegClassID = OpInfo[0].RegClass;
> - assert(NumOps >= 2 && (RdRegClassID == ARM::GPRRegClassID ||
> - RdRegClassID == ARM::rGPRRegClassID)
> - && "Expect >= 2 operands and first one as reg operand");
> -
> - unsigned RnRegClassID = OpInfo[1].RegClass;
> - bool TwoReg = (RnRegClassID == ARM::GPRRegClassID
> - || RnRegClassID == ARM::rGPRRegClassID);
> - bool NoDstReg = (decodeRs(insn) == 0xF);
> -
> - // Build the register operands, followed by the modified immediate.
> -
> - MI.addOperand(MCOperand::CreateReg(
> - getRegisterEnum(B, RdRegClassID,
> - NoDstReg ? decodeRn(insn) : decodeRs(insn))));
> - ++OpIdx;
> -
> - if (TwoReg) {
> - if (NoDstReg) {
> - DEBUG(errs()<<"Thumb2 encoding error: d==15 for DPModImm 2-reg instr.\n");
> - return false;
> - }
> - int Idx;
> - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
> - // The reg operand is tied to the first reg operand.
> - MI.addOperand(MI.getOperand(Idx));
> - } else {
> - // Add second reg operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID,
> - decodeRn(insn))));
> - }
> - ++OpIdx;
> - }
> -
> - // The modified immediate operand should come next.
> - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 &&
> - !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()
> - && "Pure imm operand expected");
> -
> - // i:imm3:imm8
> - // A6.3.2 Modified immediate constants in Thumb instructions
> - unsigned imm12 = getIImm3Imm8(insn);
> - MI.addOperand(MCOperand::CreateImm(ThumbExpandImm(imm12)));
> - ++OpIdx;
> -
> - return true;
> -}
> -
> -static inline bool Thumb2SaturateOpcode(unsigned Opcode) {
> - switch (Opcode) {
> - case ARM::t2SSAT: case ARM::t2SSAT16:
> - case ARM::t2USAT: case ARM::t2USAT16:
> - return true;
> - default:
> - return false;
> - }
> -}
> -
> -/// DisassembleThumb2Sat - Disassemble Thumb2 saturate instructions:
> -/// o t2SSAT, t2USAT: Rs sat_pos Rn shamt
> -/// o t2SSAT16, t2USAT16: Rs sat_pos Rn
> -static bool DisassembleThumb2Sat(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned &NumOpsAdded, BO B) {
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands
> -
> - // Disassemble the register def.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
> - decodeRs(insn))));
> -
> - unsigned Pos = slice(insn, 4, 0);
> - MI.addOperand(MCOperand::CreateImm(Pos));
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
> - decodeRn(insn))));
> -
> - if (NumOpsAdded == 4) {
> - // Inst{6} encodes the shift type.
> - bool isASR = slice(insn, 6, 6);
> - // Inst{11-7} encodes the imm5 shift amount.
> - unsigned ShAmt = slice(insn, 11, 7);
> - MI.addOperand(MCOperand::CreateImm(isASR << 5 | ShAmt));
> - }
> - return true;
> -}
> -
> -// A6.3.3 Data-processing (plain binary immediate)
> -//
> -// o t2ADDri12, t2SUBri12: Rs Rn imm12
> -// o t2LEApcrel (ADR): Rs imm12
> -// o t2BFC (BFC): Rs Ro(TIED_TO) bf_inv_mask_imm
> -// o t2BFI (BFI): Rs Ro(TIED_TO) Rn bf_inv_mask_imm
> -// o t2MOVi16: Rs imm16
> -// o t2MOVTi16: Rs imm16
> -// o t2SBFX (SBFX): Rs Rn lsb width
> -// o t2UBFX (UBFX): Rs Rn lsb width
> -// o t2BFI (BFI): Rs Rn lsb width
> -static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - unsigned RdRegClassID = OpInfo[0].RegClass;
> - assert(NumOps >= 2 && (RdRegClassID == ARM::GPRRegClassID ||
> - RdRegClassID == ARM::rGPRRegClassID)
> - && "Expect >= 2 operands and first one as reg operand");
> -
> - unsigned RnRegClassID = OpInfo[1].RegClass;
> - bool TwoReg = (RnRegClassID == ARM::GPRRegClassID
> - || RnRegClassID == ARM::rGPRRegClassID);
> -
> - // Build the register operand(s), followed by the immediate(s).
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RdRegClassID,
> - decodeRs(insn))));
> - ++OpIdx;
> -
> - if (TwoReg) {
> - assert(NumOps >= 3 && "Expect >= 3 operands");
> - int Idx;
> - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
> - // Process tied_to operand constraint.
> - MI.addOperand(MI.getOperand(Idx));
> - } else {
> - // Add src reg operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID,
> - decodeRn(insn))));
> - }
> - ++OpIdx;
> - }
> -
> - if (Opcode == ARM::t2BFI) {
> - // Add val reg operand.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
> - && !OpInfo[OpIdx].isOptionalDef()
> - && "Pure imm operand expected");
> -
> - // Pre-increment OpIdx.
> - ++OpIdx;
> -
> - if (Opcode == ARM::t2ADDri12 || Opcode == ARM::t2SUBri12
> - || Opcode == ARM::t2LEApcrel)
> - MI.addOperand(MCOperand::CreateImm(getIImm3Imm8(insn)));
> - else if (Opcode == ARM::t2MOVi16 || Opcode == ARM::t2MOVTi16) {
> - if (!B->tryAddingSymbolicOperand(getImm16(insn), 4, MI))
> - MI.addOperand(MCOperand::CreateImm(getImm16(insn)));
> - } else if (Opcode == ARM::t2BFC || Opcode == ARM::t2BFI) {
> - uint32_t mask = 0;
> - if (getBitfieldInvMask(insn, mask))
> - MI.addOperand(MCOperand::CreateImm(mask));
> - else
> - return false;
> - } else {
> - // Handle the case of: lsb width
> - assert((Opcode == ARM::t2SBFX || Opcode == ARM::t2UBFX)
> - && "Unexpected opcode");
> - MI.addOperand(MCOperand::CreateImm(getLsb(insn)));
> - MI.addOperand(MCOperand::CreateImm(getWidthMinus1(insn)));
> -
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -// A6.3.4 Table A6-15 Miscellaneous control instructions
> -// A8.6.41 DMB
> -// A8.6.42 DSB
> -// A8.6.49 ISB
> -static inline bool t2MiscCtrlInstr(uint32_t insn) {
> - if (slice(insn, 31, 20) == 0xf3b && slice(insn, 15, 14) == 2 &&
> - slice(insn, 12, 12) == 0)
> - return true;
> -
> - return false;
> -}
> -
> -// A6.3.4 Branches and miscellaneous control
> -//
> -// A8.6.16 B
> -// Branches: t2B, t2Bcc -> imm operand
> -//
> -// Branches: t2TPsoft -> no operand
> -//
> -// A8.6.23 BL, BLX (immediate)
> -// Branches (defined in ARMInstrThumb.td): tBL, tBLXi -> imm operand
> -//
> -// A8.6.26
> -// t2BXJ -> Rn
> -//
> -// Miscellaneous control:
> -// -> no operand (except pred-imm pred-ccr for CLREX, memory barrier variants)
> -//
> -// Hint: t2NOP, t2YIELD, t2WFE, t2WFI, t2SEV
> -// -> no operand (except pred-imm pred-ccr)
> -//
> -// t2DBG -> imm4 = Inst{3-0}
> -//
> -// t2MRS/t2MRSsys -> Rs
> -// t2MSR/t2MSRsys -> Rn mask=Inst{11-8}
> -// t2SMC -> imm4 = Inst{19-16}
> -static bool DisassembleThumb2BrMiscCtrl(MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - if (NumOps == 0)
> - return true;
> -
> - if (Opcode == ARM::t2DMB || Opcode == ARM::t2DSB) {
> - // Inst{3-0} encodes the memory barrier option for the variants.
> - unsigned opt = slice(insn, 3, 0);
> - switch (opt) {
> - case ARM_MB::SY: case ARM_MB::ST:
> - case ARM_MB::ISH: case ARM_MB::ISHST:
> - case ARM_MB::NSH: case ARM_MB::NSHST:
> - case ARM_MB::OSH: case ARM_MB::OSHST:
> - MI.addOperand(MCOperand::CreateImm(opt));
> - NumOpsAdded = 1;
> - return true;
> - default:
> - return false;
> - }
> - }
> -
> - if (t2MiscCtrlInstr(insn))
> - return true;
> -
> - switch (Opcode) {
> - case ARM::t2CLREX:
> - case ARM::t2NOP:
> - case ARM::t2YIELD:
> - case ARM::t2WFE:
> - case ARM::t2WFI:
> - case ARM::t2SEV:
> - return true;
> - default:
> - break;
> - }
> -
> - // FIXME: To enable correct asm parsing and disasm of CPS we need 3 different
> - // opcodes which match the same real instruction. This is needed since there's
> - // no current handling of optional arguments. Fix here when a better handling
> - // of optional arguments is implemented.
> - if (Opcode == ARM::t2CPS3p) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 10, 9))); // imod
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 5))); // iflags
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode
> - NumOpsAdded = 3;
> - return true;
> - }
> - if (Opcode == ARM::t2CPS2p) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 10, 9))); // imod
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 5))); // iflags
> - NumOpsAdded = 2;
> - return true;
> - }
> - if (Opcode == ARM::t2CPS1p) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode
> - NumOpsAdded = 1;
> - return true;
> - }
> -
> - // DBG has its option specified in Inst{3-0}.
> - if (Opcode == ARM::t2DBG) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 0)));
> - NumOpsAdded = 1;
> - return true;
> - }
> -
> - // MRS and MRSsys take one GPR reg Rs.
> - if (Opcode == ARM::t2MRS || Opcode == ARM::t2MRSsys) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRs(insn))));
> - NumOpsAdded = 1;
> - return true;
> - }
> - // BXJ takes one GPR reg Rn.
> - if (Opcode == ARM::t2BXJ) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - NumOpsAdded = 1;
> - return true;
> - }
> - // MSR take a mask, followed by one GPR reg Rn. The mask contains the R Bit in
> - // bit 4, and the special register fields in bits 3-0.
> - if (Opcode == ARM::t2MSR) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 20) << 4 /* R Bit */ |
> - slice(insn, 11, 8) /* Special Reg */));
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - NumOpsAdded = 2;
> - return true;
> - }
> - // SMC take imm4.
> - if (Opcode == ARM::t2SMC) {
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 16)));
> - NumOpsAdded = 1;
> - return true;
> - }
> -
> - // Some instructions have predicate operands first before the immediate.
> - if (Opcode == ARM::tBLXi || Opcode == ARM::tBL) {
> - // Handling the two predicate operands before the imm operand.
> - if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
> - NumOpsAdded += 2;
> - else {
> - DEBUG(errs() << "Expected predicate operands not found.\n");
> - return false;
> - }
> - }
> -
> - // Add the imm operand.
> - int Offset = 0;
> -
> - switch (Opcode) {
> - default:
> - assert(0 && "Unexpected opcode");
> - return false;
> - case ARM::t2B:
> - Offset = decodeImm32_B_EncodingT4(insn);
> - break;
> - case ARM::t2Bcc:
> - Offset = decodeImm32_B_EncodingT3(insn);
> - break;
> - case ARM::tBL:
> - Offset = decodeImm32_BL(insn);
> - break;
> - case ARM::tBLXi:
> - Offset = decodeImm32_BLX(insn);
> - break;
> - }
> -
> - if (!B->tryAddingSymbolicOperand(Offset + B->getBuilderAddress() + 4, 4, MI))
> - MI.addOperand(MCOperand::CreateImm(Offset));
> -
> - // This is an increment as some predicate operands may have been added first.
> - NumOpsAdded += 1;
> -
> - return true;
> -}
> -
> -static inline bool Thumb2PreloadOpcode(unsigned Opcode) {
> - switch (Opcode) {
> - default:
> - return false;
> - case ARM::t2PLDi12: case ARM::t2PLDi8:
> - case ARM::t2PLDs:
> - case ARM::t2PLDWi12: case ARM::t2PLDWi8:
> - case ARM::t2PLDWs:
> - case ARM::t2PLIi12: case ARM::t2PLIi8:
> - case ARM::t2PLIs:
> - return true;
> - }
> -}
> -
> -static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - // Preload Data/Instruction requires either 2 or 3 operands.
> - // t2PLDi12, t2PLDi8, t2PLDpci: Rn [+/-]imm12/imm8
> - // t2PLDr: Rn Rm
> - // t2PLDs: Rn Rm imm2=Inst{5-4}
> - // Same pattern applies for t2PLDW* and t2PLI*.
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(NumOps >= 2 &&
> - OpInfo[0].RegClass == ARM::GPRRegClassID &&
> - "Expect >= 2 operands and first one as reg operand");
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRn(insn))));
> - ++OpIdx;
> -
> - if (OpInfo[OpIdx].RegClass == ARM::rGPRRegClassID) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
> - decodeRm(insn))));
> - } else {
> - assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
> - && !OpInfo[OpIdx].isOptionalDef()
> - && "Pure imm operand expected");
> - int Offset = 0;
> - if (Opcode == ARM::t2PLDi8 || Opcode == ARM::t2PLDWi8 ||
> - Opcode == ARM::t2PLIi8) {
> - // A8.6.117 Encoding T2: add = FALSE
> - unsigned Imm8 = getImm8(insn);
> - Offset = -1 * Imm8;
> - } else {
> - // The i12 forms. See, for example, A8.6.117 Encoding T1.
> - // Note that currently t2PLDi12 also handles the previously named t2PLDpci
> - // opcode, that's why we use decodeImm12(insn) which returns +/- imm12.
> - Offset = decodeImm12(insn);
> - }
> - MI.addOperand(MCOperand::CreateImm(Offset));
> - }
> - ++OpIdx;
> -
> - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 &&
> - !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
> - // Fills in the shift amount for t2PLDs, t2PLDWs, t2PLIs.
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 5, 4)));
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -static bool BadRegsThumb2LdSt(unsigned Opcode, uint32_t insn, bool Load,
> - unsigned R0, unsigned R1, unsigned R2, bool UseRm, bool WB) {
> -
> - // Inst{22-21} encodes the data item transferred for load/store.
> - // For single word, it is encoded as ob10.
> - bool Word = (slice(insn, 22, 21) == 2);
> - bool Half = (slice(insn, 22, 21) == 1);
> - bool Byte = (slice(insn, 22, 21) == 0);
> -
> - if (UseRm && BadReg(R2)) {
> - DEBUG(errs() << "if BadReg(m) then UNPREDICTABLE\n");
> - return true;
> - }
> -
> - if (Load) {
> - if (!Word && R0 == 13) {
> - DEBUG(errs() << "if t == 13 then UNPREDICTABLE\n");
> - return true;
> - }
> - if (Byte) {
> - if (WB && R0 == 15 && slice(insn, 10, 8) == 3) {
> - // A8.6.78 LDRSB (immediate) Encoding T2 (errata markup 8.0)
> - DEBUG(errs() << "if t == 15 && PUW == '011' then UNPREDICTABLE\n");
> - return true;
> - }
> - }
> - // A6.3.8 Load halfword, memory hints
> - if (Half) {
> - if (WB) {
> - if (R0 == R1) {
> - // A8.6.82 LDRSH (immediate) Encoding T2
> - DEBUG(errs() << "if WB && n == t then UNPREDICTABLE\n");
> - return true;
> - }
> - if (R0 == 15 && slice(insn, 10, 8) == 3) {
> - // A8.6.82 LDRSH (immediate) Encoding T2 (errata markup 8.0)
> - DEBUG(errs() << "if t == 15 && PUW == '011' then UNPREDICTABLE\n");
> - return true;
> - }
> - } else {
> - if (Opcode == ARM::t2LDRHi8 || Opcode == ARM::t2LDRSHi8) {
> - if (R0 == 15 && slice(insn, 10, 8) == 4) {
> - // A8.6.82 LDRSH (immediate) Encoding T2
> - DEBUG(errs() << "if Rt == '1111' and PUW == '100' then SEE"
> - << " \"Unallocated memory hints\"\n");
> - return true;
> - }
> - } else {
> - if (R0 == 15) {
> - // A8.6.82 LDRSH (immediate) Encoding T1
> - DEBUG(errs() << "if Rt == '1111' then SEE"
> - << " \"Unallocated memory hints\"\n");
> - return true;
> - }
> - }
> - }
> - }
> - } else {
> - if (WB && R0 == R1) {
> - DEBUG(errs() << "if wback && n == t then UNPREDICTABLE\n");
> - return true;
> - }
> - if ((WB && R0 == 15) || (!WB && R1 == 15)) {
> - DEBUG(errs() << "if Rn == '1111' then UNDEFINED\n");
> - return true;
> - }
> - if (Word) {
> - if ((WB && R1 == 15) || (!WB && R0 == 15)) {
> - DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n");
> - return true;
> - }
> - } else {
> - if ((WB && BadReg(R1)) || (!WB && BadReg(R0))) {
> - DEBUG(errs() << "if BadReg(t) then UNPREDICTABLE\n");
> - return true;
> - }
> - }
> - }
> - return false;
> -}
> -
> -// A6.3.10 Store single data item
> -// A6.3.9 Load byte, memory hints
> -// A6.3.8 Load halfword, memory hints
> -// A6.3.7 Load word
> -//
> -// For example,
> -//
> -// t2LDRi12: Rd Rn (+)imm12
> -// t2LDRi8: Rd Rn (+/-)imm8 (+ if Inst{9} == 0b1)
> -// t2LDRs: Rd Rn Rm ConstantShiftSpecifier (see also
> -// DisassembleThumb2DPSoReg)
> -// t2LDR_POST: Rd Rn Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
> -// t2LDR_PRE: Rd Rn Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
> -//
> -// t2STRi12: Rd Rn (+)imm12
> -// t2STRi8: Rd Rn (+/-)imm8 (+ if Inst{9} == 0b1)
> -// t2STRs: Rd Rn Rm ConstantShiftSpecifier (see also
> -// DisassembleThumb2DPSoReg)
> -// t2STR_POST: Rn Rd Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
> -// t2STR_PRE: Rn Rd Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
> -//
> -// Note that for indexed modes, the Rn(TIED_TO) operand needs to be populated
> -// correctly, as LLVM AsmPrinter depends on it. For indexed stores, the first
> -// operand is Rn; for all the other instructions, Rd is the first operand.
> -//
> -// Delegates to DisassembleThumb2PreLoad() for preload data/instruction.
> -// Delegates to DisassembleThumb2Ldpci() for load * literal operations.
> -static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode,
> - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - unsigned Rn = decodeRn(insn);
> -
> - if (Thumb2PreloadOpcode(Opcode))
> - return DisassembleThumb2PreLoad(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> -
> - // See, for example, A6.3.7 Load word: Table A6-18 Load word.
> - if (Load && Rn == 15)
> - return DisassembleThumb2Ldpci(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(NumOps >= 3 &&
> - OpInfo[0].RegClass > 0 &&
> - OpInfo[1].RegClass > 0 &&
> - "Expect >= 3 operands and first two as reg operands");
> -
> - bool ThreeReg = (OpInfo[2].RegClass > 0);
> - bool TIED_TO = ThreeReg && MCID.getOperandConstraint(2, MCOI::TIED_TO) != -1;
> - bool Imm12 = !ThreeReg && slice(insn, 23, 23) == 1; // ARMInstrThumb2.td
> -
> - // Build the register operands, followed by the immediate.
> - unsigned R0 = 0, R1 = 0, R2 = 0;
> - unsigned Rd = decodeRd(insn);
> - int Imm = 0;
> -
> - if (!Load && TIED_TO) {
> - R0 = Rn;
> - R1 = Rd;
> - } else {
> - R0 = Rd;
> - R1 = Rn;
> - }
> - if (ThreeReg) {
> - if (TIED_TO) {
> - R2 = Rn;
> - Imm = decodeImm8(insn);
> - } else {
> - R2 = decodeRm(insn);
> - // See, for example, A8.6.64 LDRB (register).
> - // And ARMAsmPrinter::printT2AddrModeSoRegOperand().
> - // LSL is the default shift opc, and LLVM does not expect it to be encoded
> - // as part of the immediate operand.
> - // Imm = ARM_AM::getSORegOpc(ARM_AM::lsl, slice(insn, 5, 4));
> - Imm = slice(insn, 5, 4);
> - }
> - } else {
> - if (Imm12)
> - Imm = getImm12(insn);
> - else
> - Imm = decodeImm8(insn);
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - R0)));
> - ++OpIdx;
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - R1)));
> - ++OpIdx;
> -
> - if (ThreeReg) {
> - // This could be an offset register or a TIED_TO register.
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass,
> - R2)));
> - ++OpIdx;
> - }
> -
> - if (BadRegsThumb2LdSt(Opcode, insn, Load, R0, R1, R2, ThreeReg & !TIED_TO,
> - TIED_TO))
> - return false;
> -
> - assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
> - && !OpInfo[OpIdx].isOptionalDef()
> - && "Pure imm operand expected");
> -
> - MI.addOperand(MCOperand::CreateImm(Imm));
> - ++OpIdx;
> -
> - return true;
> -}
> -
> -// A6.3.12 Data-processing (register)
> -//
> -// Two register operands [rotate]: Rs Rm [rotation(= (rotate:'000'))]
> -// Three register operands only: Rs Rn Rm
> -// Three register operands [rotate]: Rs Rn Rm [rotation(= (rotate:'000'))]
> -//
> -// Parallel addition and subtraction 32-bit Thumb instructions: Rs Rn Rm
> -//
> -// Miscellaneous operations: Rs [Rn] Rm
> -static bool DisassembleThumb2DPReg(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCInstrDesc &MCID = ARMInsts[Opcode];
> - const MCOperandInfo *OpInfo = MCID.OpInfo;
> - unsigned &OpIdx = NumOpsAdded;
> -
> - OpIdx = 0;
> -
> - assert(NumOps >= 2 &&
> - OpInfo[0].RegClass > 0 &&
> - OpInfo[1].RegClass > 0 &&
> - "Expect >= 2 operands and first two as reg operands");
> -
> - // Build the register operands, followed by the optional rotation amount.
> -
> - bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass > 0;
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - decodeRs(insn))));
> - ++OpIdx;
> -
> - if (ThreeReg) {
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass,
> - decodeRn(insn))));
> - ++OpIdx;
> - }
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
> - decodeRm(insn))));
> - ++OpIdx;
> -
> - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
> - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
> - // Add the rotation amount immediate.
> - MI.addOperand(MCOperand::CreateImm(slice(insn, 5, 4)));
> - ++OpIdx;
> - }
> -
> - return true;
> -}
> -
> -// A6.3.16 Multiply, multiply accumulate, and absolute difference
> -//
> -// t2MLA, t2MLS, t2SMMLA, t2SMMLS: Rs Rn Rm Ra=Inst{15-12}
> -// t2MUL, t2SMMUL: Rs Rn Rm
> -// t2SMLA[BB|BT|TB|TT|WB|WT]: Rs Rn Rm Ra=Inst{15-12}
> -// t2SMUL[BB|BT|TB|TT|WB|WT]: Rs Rn Rm
> -//
> -// Dual halfword multiply: t2SMUAD[X], t2SMUSD[X], t2SMLAD[X], t2SMLSD[X]:
> -// Rs Rn Rm Ra=Inst{15-12}
> -//
> -// Unsigned Sum of Absolute Differences [and Accumulate]
> -// Rs Rn Rm [Ra=Inst{15-12}]
> -static bool DisassembleThumb2Mul(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> -
> - assert(NumOps >= 3 &&
> - OpInfo[0].RegClass == ARM::rGPRRegClassID &&
> - OpInfo[1].RegClass == ARM::rGPRRegClassID &&
> - OpInfo[2].RegClass == ARM::rGPRRegClassID &&
> - "Expect >= 3 operands and first three as reg operands");
> -
> - // Build the register operands.
> -
> - bool FourReg = NumOps > 3 && OpInfo[3].RegClass == ARM::rGPRRegClassID;
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
> - decodeRs(insn))));
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
> - decodeRn(insn))));
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
> - decodeRm(insn))));
> -
> - if (FourReg)
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
> - decodeRd(insn))));
> -
> - NumOpsAdded = FourReg ? 4 : 3;
> -
> - return true;
> -}
> -
> -// A6.3.17 Long multiply, long multiply accumulate, and divide
> -//
> -// t2SMULL, t2UMULL, t2SMLAL, t2UMLAL, t2UMAAL: RdLo RdHi Rn Rm
> -// where RdLo = Inst{15-12} and RdHi = Inst{11-8}
> -//
> -// Halfword multiple accumulate long: t2SMLAL<x><y>: RdLo RdHi Rn Rm
> -// where RdLo = Inst{15-12} and RdHi = Inst{11-8}
> -//
> -// Dual halfword multiple: t2SMLALD[X], t2SMLSLD[X]: RdLo RdHi Rn Rm
> -// where RdLo = Inst{15-12} and RdHi = Inst{11-8}
> -//
> -// Signed/Unsigned divide: t2SDIV, t2UDIV: Rs Rn Rm
> -static bool DisassembleThumb2LongMul(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
> -
> - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
> -
> - assert(NumOps >= 3 &&
> - OpInfo[0].RegClass == ARM::rGPRRegClassID &&
> - OpInfo[1].RegClass == ARM::rGPRRegClassID &&
> - OpInfo[2].RegClass == ARM::rGPRRegClassID &&
> - "Expect >= 3 operands and first three as reg operands");
> -
> - bool FourReg = NumOps > 3 && OpInfo[3].RegClass == ARM::rGPRRegClassID;
> -
> - // Build the register operands.
> -
> - if (FourReg)
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
> - decodeRd(insn))));
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
> - decodeRs(insn))));
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
> - decodeRn(insn))));
> -
> - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
> - decodeRm(insn))));
> -
> - if (FourReg)
> - NumOpsAdded = 4;
> - else
> - NumOpsAdded = 3;
> -
> - return true;
> -}
> -
> -// See A6.3 32-bit Thumb instruction encoding for instruction classes
> -// corresponding to (op1, op2, op).
> -//
> -// Table A6-9 32-bit Thumb instruction encoding
> -// op1 op2 op Instruction class, see
> -// --- ------- -- -----------------------------------------------------------
> -// 01 00xx0xx - Load/store multiple on page A6-23
> -// 00xx1xx - Load/store dual, load/store exclusive, table branch on
> -// page A6-24
> -// 01xxxxx - Data-processing (shifted register) on page A6-31
> -// 1xxxxxx - Coprocessor instructions on page A6-40
> -// 10 x0xxxxx 0 Data-processing (modified immediate) on page A6-15
> -// x1xxxxx 0 Data-processing (plain binary immediate) on page A6-19
> -// - 1 Branches and miscellaneous control on page A6-20
> -// 11 000xxx0 - Store single data item on page A6-30
> -// 001xxx0 - Advanced SIMD element or structure load/store instructions
> -// on page A7-27
> -// 00xx001 - Load byte, memory hints on page A6-28
> -// 00xx011 - Load halfword, memory hints on page A6-26
> -// 00xx101 - Load word on page A6-25
> -// 00xx111 - UNDEFINED
> -// 010xxxx - Data-processing (register) on page A6-33
> -// 0110xxx - Multiply, multiply accumulate, and absolute difference on
> -// page A6-38
> -// 0111xxx - Long multiply, long multiply accumulate, and divide on
> -// page A6-39
> -// 1xxxxxx - Coprocessor instructions on page A6-40
> -//
> -static bool DisassembleThumb2(uint16_t op1, uint16_t op2, uint16_t op,
> - MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps,
> - unsigned &NumOpsAdded, BO B) {
> -
> - switch (op1) {
> - case 1:
> - if (slice(op2, 6, 5) == 0) {
> - if (slice(op2, 2, 2) == 0) {
> - // Load/store multiple.
> - return DisassembleThumb2LdStMul(MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - }
> -
> - // Load/store dual, load/store exclusive, table branch, otherwise.
> - assert(slice(op2, 2, 2) == 1 && "Thumb2 encoding error!");
> - if ((ARM::t2LDREX <= Opcode && Opcode <= ARM::t2LDREXH) ||
> - (ARM::t2STREX <= Opcode && Opcode <= ARM::t2STREXH)) {
> - // Load/store exclusive.
> - return DisassembleThumb2LdStEx(MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - }
> - if (Opcode == ARM::t2LDRDi8 ||
> - Opcode == ARM::t2LDRD_PRE || Opcode == ARM::t2LDRD_POST ||
> - Opcode == ARM::t2STRDi8 ||
> - Opcode == ARM::t2STRD_PRE || Opcode == ARM::t2STRD_POST) {
> - // Load/store dual.
> - return DisassembleThumb2LdStDual(MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - }
> - if (Opcode == ARM::t2TBB || Opcode == ARM::t2TBH) {
> - // Table branch.
> - return DisassembleThumb2TB(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - }
> - } else if (slice(op2, 6, 5) == 1) {
> - // Data-processing (shifted register).
> - return DisassembleThumb2DPSoReg(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - }
> -
> - // FIXME: A6.3.18 Coprocessor instructions
> - // But see ThumbDisassembler::getInstruction().
> -
> - break;
> - case 2:
> - if (op == 0) {
> - if (slice(op2, 5, 5) == 0)
> - // Data-processing (modified immediate)
> - return DisassembleThumb2DPModImm(MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - if (Thumb2SaturateOpcode(Opcode))
> - return DisassembleThumb2Sat(MI, Opcode, insn, NumOpsAdded, B);
> -
> - // Data-processing (plain binary immediate)
> - return DisassembleThumb2DPBinImm(MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - }
> - // Branches and miscellaneous control on page A6-20.
> - return DisassembleThumb2BrMiscCtrl(MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - case 3:
> - switch (slice(op2, 6, 5)) {
> - case 0:
> - // Load/store instructions...
> - if (slice(op2, 0, 0) == 0) {
> - if (slice(op2, 4, 4) == 0) {
> - // Store single data item on page A6-30
> - return DisassembleThumb2LdSt(false, MI,Opcode,insn,NumOps,NumOpsAdded,
> - B);
> - } else {
> - // FIXME: Advanced SIMD element or structure load/store instructions.
> - // But see ThumbDisassembler::getInstruction().
> - ;
> - }
> - } else {
> - // Table A6-9 32-bit Thumb instruction encoding: Load byte|halfword|word
> - return DisassembleThumb2LdSt(true, MI, Opcode, insn, NumOps,
> - NumOpsAdded, B);
> - }
> - break;
> - case 1:
> - if (slice(op2, 4, 4) == 0) {
> - // A6.3.12 Data-processing (register)
> - return DisassembleThumb2DPReg(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - } else if (slice(op2, 3, 3) == 0) {
> - // A6.3.16 Multiply, multiply accumulate, and absolute difference
> - return DisassembleThumb2Mul(MI, Opcode, insn, NumOps, NumOpsAdded, B);
> - } else {
> - // A6.3.17 Long multiply, long multiply accumulate, and divide
> - return DisassembleThumb2LongMul(MI, Opcode, insn, NumOps, NumOpsAdded,
> - B);
> - }
> - break;
> - default:
> - // FIXME: A6.3.18 Coprocessor instructions
> - // But see ThumbDisassembler::getInstruction().
> - ;
> - break;
> - }
> -
> - break;
> - default:
> - assert(0 && "Thumb2 encoding error!");
> - break;
> - }
> -
> - return false;
> -}
> -
> -static bool DisassembleThumbFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
> - unsigned short NumOps, unsigned &NumOpsAdded, BO Builder) {
> -
> - uint16_t HalfWord = slice(insn, 31, 16);
> -
> - if (HalfWord == 0) {
> - // A6.2 16-bit Thumb instruction encoding
> - // op = bits[15:10]
> - uint16_t op = slice(insn, 15, 10);
> - return DisassembleThumb1(op, MI, Opcode, insn, NumOps, NumOpsAdded,
> - Builder);
> - }
> -
> - unsigned bits15_11 = slice(HalfWord, 15, 11);
> -
> - // A6.1 Thumb instruction set encoding
> - if (!(bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F)) {
> - assert("Bits[15:11] first halfword of Thumb2 instruction is out of range");
> - return false;
> - }
> -
> - // A6.3 32-bit Thumb instruction encoding
> -
> - uint16_t op1 = slice(HalfWord, 12, 11);
> - uint16_t op2 = slice(HalfWord, 10, 4);
> - uint16_t op = slice(insn, 15, 15);
> -
> - return DisassembleThumb2(op1, op2, op, MI, Opcode, insn, NumOps, NumOpsAdded,
> - Builder);
> -}
>
> Modified: llvm/trunk/lib/Target/ARM/Makefile
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Makefile?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/Makefile (original)
> +++ llvm/trunk/lib/Target/ARM/Makefile Tue Aug 9 15:55:18 2011
> @@ -18,7 +18,7 @@
> ARMGenCodeEmitter.inc ARMGenCallingConv.inc \
> ARMGenDecoderTables.inc ARMGenEDInfo.inc \
> ARMGenFastISel.inc ARMGenMCCodeEmitter.inc \
> - ARMGenMCPseudoLowering.inc
> + ARMGenMCPseudoLowering.inc ARMGenDisassemblerTables.inc
>
> DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc
>
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt Tue Aug 9 15:55:18 2011
> @@ -60,11 +60,14 @@
> # CHECK: ldrh r0, [r2], #0
> 0xb0 0x00 0xd2 0xe0
>
> +# CHECK: ldrh r0, [r2]
> +0xb0 0x00 0xd2 0xe1
> +
> # CHECK: ldrht r0, [r2], #15
> 0xbf 0x00 0xf2 0xe0
>
> # CHECK: ldrsbtvs lr, [r2], -r9
> -0xd9 0xe9 0x32 0x60
> +0xd9 0xe0 0x32 0x60
>
> # CHECK: lsls r0, r2, #31
> 0x82 0x0f 0xb0 0xe1
> @@ -177,7 +180,7 @@
> 0x15 0xff 0x2f 0x01
>
> # CHECK: uqadd16mi r6, r11, r8
> -0x18 0x60 0x6b 0x46
> +0x18 0x6F 0x6b 0x46
>
> # CHECK: str r0, [sp, #4]
> 0x04 0x00 0x8d 0xe5
> @@ -230,7 +233,7 @@
> # CHECK: umull r1, r2, r3, r4
> 0x93 0x14 0x82 0xe0
>
> -# CHECK: pld [pc, #-0]
> +# CHECK: pldw [pc, #-0]
> 0x00 0xf0 0x1f 0xf5
>
> # CHECK: pli [pc, #-0]
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,7 +1,8 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=60 Name=BFI Format=ARM_FORMAT_DPFRM(4)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 0| 0: 1: 1: 1| 1: 1: 0: 0| 1: 1: 1: 1| 1: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 1| 0: 1: 1: 0|
> # -------------------------------------------------------------------------------------------------
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,10 +1,11 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=2249 Name=tBcc Format=ARM_FORMAT_THUMBFRM(25)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 1: 0: 1| 1: 1: 1: 0| 0: 1: 1: 0| 1: 1: 1: 1|
> # -------------------------------------------------------------------------------------------------
> -#
> +#
> # if cond = '1110' then UNDEFINED
> 0x6f 0xde
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # invalid imod value (0b01)
> 0xc0 0x67 0x4 0xf1
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # invalid (imod, M, iflags) combination
> 0x93 0x1c 0x02 0xf1
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=1908 Name=t2DMB Format=ARM_FORMAT_THUMBFRM(25)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=102 Name=DSB Format=ARM_FORMAT_MISCFRM(26)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,7 +1,7 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=0 Name=PHI Format=(42)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 0: 1| 1: 1: 0: 0| 0: 0: 0: 1| 1: 1: 1: 1| 1: 0: 1: 1| 0: 1: 0: 0| 1: 0: 0: 1| 0: 0: 1: 0|
> # -------------------------------------------------------------------------------------------------
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=140 Name=LDRB_POST Format=ARM_FORMAT_LDFRM(6)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=1930 Name=t2LDRD_PRE Format=ARM_FORMAT_THUMBFRM(25)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,7 +1,7 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=0 Name=PHI Format=(42)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 0| 0: 1: 1: 0| 0: 0: 1: 1| 0: 1: 1: 1| 0: 1: 0: 1| 0: 0: 0: 1| 0: 0: 0: 1| 0: 0: 0: 0|
> # -------------------------------------------------------------------------------------------------
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # LDR_PRE/POST has encoding Inst{4} = 0.
> 0xde 0x69 0x18 0x46
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=165 Name=LDR_PRE Format=ARM_FORMAT_LDFRM(6)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=196 Name=MOVs Format=ARM_FORMAT_DPSOREGFRM(5)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,7 +1,7 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=171 Name=MCR Format=ARM_FORMAT_BRFRM(2)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 0: 0: 1: 0| 1: 1: 1: 0| 1: 0: 1: 0| 0: 0: 0: 0| 0: 0: 0: 1| 1: 0: 1: 1| 0: 0: 0: 1| 1: 0: 1: 1|
> # -------------------------------------------------------------------------------------------------
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=185 Name=MOVTi16 Format=ARM_FORMAT_DPFRM(4)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,7 +1,7 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=0 Name=PHI Format=(42)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 1| 0: 0: 0: 1| 1: 0: 1: 1| 1: 1: 0: 0| 1: 1: 0: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 1: 0|
> # -------------------------------------------------------------------------------------------------
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,7 +1,7 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=196 Name=MOVs Format=ARM_FORMAT_DPSOREGFRM(5)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 0: 1| 0: 0: 0: 1| 1: 0: 1: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 0: 1: 0| 1: 0: 0: 1| 0: 0: 1: 1|
> # -------------------------------------------------------------------------------------------------
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,7 +1,7 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=0 Name=PHI Format=(42)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 1| 0: 0: 0: 1| 1: 0: 1: 1| 1: 1: 0: 0| 1: 1: 0: 1| 0: 0: 0: 1| 0: 0: 0: 0| 0: 0: 1: 0|
> # -------------------------------------------------------------------------------------------------
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=206 Name=MSRi Format=ARM_FORMAT_BRFRM(2)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,7 +1,7 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=134 Name=LDMIA Format=ARM_FORMAT_LDSTMULFRM(10)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 1| 1: 0: 0: 0| 1: 0: 0: 1| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 0: 1| 0: 0: 1: 1| 0: 0: 1: 0|
> # -------------------------------------------------------------------------------------------------
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=261 Name=RSCrs Format=ARM_FORMAT_DPSOREGFRM(5)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=271 Name=SBFX Format=ARM_FORMAT_DPFRM(4)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=284 Name=SMLAD Format=ARM_FORMAT_MULFRM(1)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,7 +1,7 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=0 Name=PHI Format=(42)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 1| 1: 0: 0: 0| 1: 1: 0: 0| 0: 1: 0: 1| 0: 0: 0: 1| 1: 1: 0: 0| 1: 0: 0: 0| 0: 0: 1: 1|
> # -------------------------------------------------------------------------------------------------
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=322 Name=SSAT Format=ARM_FORMAT_SATFRM(13)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=2313 Name=tSTMIA_UPD Format=ARM_FORMAT_THUMBFRM(25)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=355 Name=STRBrs Format=ARM_FORMAT_STFRM(7)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=390 Name=SXTBr_rot Format=ARM_FORMAT_EXTFRM(14)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,11 +1,11 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=419 Name=UMAAL Format=ARM_FORMAT_MULFRM(1)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 1| 0: 0: 0: 0| 0: 1: 0: 0| 1: 1: 1: 1| 1: 0: 1: 1| 1: 1: 1: 1| 1: 0: 0: 1| 1: 0: 0: 0|
> # -------------------------------------------------------------------------------------------------
> #
> # A8.6.244 UMAAL
> # if dLo == 15 || dHi == 15 || n == 15 || m == 15 then UNPREDICTABLE;
> -0x98 0xbf 0x4f 0xf0
> +0x98 0xbf 0x4f 0xf0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=426 Name=UQADD8 Format=ARM_FORMAT_DPFRM(4)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=737 Name=VLD1DUPq8_UPD Format=ARM_FORMAT_NLdSt(30)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,11 +1,11 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=871 Name=VLD3DUPd32_UPD Format=ARM_FORMAT_NLdSt(30)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 1| 0: 1: 0: 0| 1: 0: 1: 0| 0: 0: 1: 0| 0: 0: 1: 0| 1: 1: 1: 0| 1: 0: 0: 1| 0: 0: 1: 0|
> # -------------------------------------------------------------------------------------------------
> -#
> +#
> # A8.6.315 VLD3 (single 3-element structure to all lanes)
> # The a bit must be encoded as 0.
> 0xa2 0xf9 0x92 0x2e
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # core registers out of range
> 0xa5 0xba 0x72 0xed
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=1225 Name=VQADDsv16i8 Format=ARM_FORMAT_N3Reg(37)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt Tue Aug 9 15:55:18 2011
> @@ -1,7 +1,8 @@
> # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=1641 Name=VST2b32_UPD Format=ARM_FORMAT_NLdSt(30)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 1| 0: 1: 0: 0| 0: 0: 0: 0| 0: 0: 1: 1| 0: 0: 0: 0| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 1: 1|
> # -------------------------------------------------------------------------------------------------
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=1894 Name=t2Bcc Format=ARM_FORMAT_THUMBFRM(25)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,10 +1,10 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=1922 Name=t2LDRBT Format=ARM_FORMAT_THUMBFRM(25)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 1| 1: 0: 0: 0| 0: 0: 0: 1| 0: 0: 0: 0| 1: 1: 1: 1| 1: 1: 1: 0| 0: 0: 0: 0| 0: 0: 1: 1|
> # -------------------------------------------------------------------------------------------------
> -#
> +#
> # The unpriviledged Load/Store cannot have SP or PC as Rt.
> 0x10 0xf8 0x3 0xfe
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=1934 Name=t2LDREXD Format=ARM_FORMAT_THUMBFRM(25)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=1953 Name=t2LDRSHi12 Format=ARM_FORMAT_THUMBFRM(25)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=1954 Name=t2LDRSHi8 Format=ARM_FORMAT_THUMBFRM(25)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=2124 Name=t2STRD_PRE Format=ARM_FORMAT_THUMBFRM(25)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=2127 Name=t2STREXB Format=ARM_FORMAT_THUMBFRM(25)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,10 +1,10 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
>
> # Opcode=2128 Name=t2STREXD Format=ARM_FORMAT_THUMBFRM(25)
> -# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
> # -------------------------------------------------------------------------------------------------
> # | 1: 1: 1: 0| 1: 0: 0: 0| 1: 1: 0: 0| 0: 0: 1: 0| 0: 1: 1: 1| 1: 0: 0: 0| 0: 1: 1: 1| 1: 0: 0: 0|
> # -------------------------------------------------------------------------------------------------
> -#
> +#
> # if d == n || d == t || d == t2 then UNPREDICTABLE
> mc-input.txt:1:1: warning: invalid instruction encoding
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt Tue Aug 9 15:55:18 2011
> @@ -1,4 +1,5 @@
> # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
> +# XFAIL: *
>
> # Opcode=2137 Name=t2STR_POST Format=ARM_FORMAT_THUMBFRM(25)
> # 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
>
> Modified: llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt (original)
> +++ llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt Tue Aug 9 15:55:18 2011
> @@ -24,7 +24,7 @@
> # CHECK: vld1.32 {d3[], d4[]}, [r0, :32]!
> 0xbd 0x3c 0xa0 0xf4
>
> -# CHECK: vld4.16 {d3[], d4[], d5[], d6[]}, [r0, :64]!
> +# CHECK: vld4.16 {d3[], d5[], d7[], d9[]}, [r0, :64]!
> 0x7d 0x3f 0xa0 0xf4
>
> # CHECK: vorr d0, d15, d15
> @@ -87,5 +87,5 @@
> # CHECK: usada8mi r8, r9, r5, r9
> 0x19 0x95 0x88 0x47
>
> -# CHECK: vext.8 q4, q2, q1, #4
> +# CHECK: vext.32 q4, q2, q1, #1
> 0x42 0x84 0xb4 0xf2
>
> Modified: llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp?rev=137144&r1=137143&r2=137144&view=diff
> ==============================================================================
> --- llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp (original)
> +++ llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp Tue Aug 9 15:55:18 2011
> @@ -128,12 +128,5 @@
> return;
> }
>
> - // Fixed-instruction-length targets use a common disassembler.
> - // ARM use its own implementation for now.
> - if (Target.getName() == "ARM") {
> - ARMDecoderEmitter(Records).run(OS);
> - return;
> - }
> -
> FixedLenDecoderEmitter(Records).run(OS);
> }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list