//
//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "arm-disassembler"
+
#include "ARMDisassemblerCore.h"
#include "ARMAddressingModes.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
/// ARMGenInstrInfo.inc - ARMGenInstrInfo.inc contains the static const
/// TargetInstrDesc ARMInsts[] definition and the TargetOperandInfo[]'s
// Return the register enum Based on RegClass and the raw register number.
// For DRegPair, see comments below.
// FIXME: Auto-gened?
-static unsigned getRegisterEnum(unsigned RegClassID, unsigned RawRegister,
+static unsigned getRegisterEnum(BO B, unsigned RegClassID, unsigned RawRegister,
bool DRegPair = false) {
if (DRegPair && RegClassID == ARM::QPRRegClassID) {
}
break;
}
- assert(0 && "Invalid (RegClassID, RawRegister) combination");
+ DEBUG(errs() << "Invalid (RegClassID, RawRegister) combination\n");
+ // Encoding error. Mark the builder with error code != 0.
+ B->SetErr(-1);
return 0;
}
// Inst{3-0} => Rm
// Inst{11-8} => Rs
static bool DisassembleMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
unsigned short NumDefs = TID.getNumDefs();
if (NumDefs == 2) {
assert(NumOps >= 4 && OpInfo[3].RegClass == ARM::GPRRegClassID &&
"Expect 4th register operand");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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(ARM::GPRRegClassID,
+ 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(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
++OpIdx;
}
// and friends
//
static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 5 && "Num of operands >= 5 for coprocessor instr");
MI.addOperand(MCOperand::CreateImm(decodeRd(insn)));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
if (PW) {
MI.addOperand(NoGPR ? MCOperand::CreateImm(decodeRd(insn))
: MCOperand::CreateReg(
- getRegisterEnum(ARM::GPRRegClassID,
+ getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
MI.addOperand(OneCopOpc ? MCOperand::CreateReg(
- getRegisterEnum(ARM::GPRRegClassID,
+ getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn)))
: MCOperand::CreateImm(decodeRn(insn)));
// SRSW/SRS: addrmode4:$addr mode_imm
// RFEW/RFE: addrmode4:$addr Rn
static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
if (CoprocessorOpcode(Opcode))
- return DisassembleCoprocessor(MI, Opcode, insn, NumOps, NumOpsAdded);
+ return DisassembleCoprocessor(MI, Opcode, insn, NumOps, NumOpsAdded, B);
const TargetOperandInfo *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(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
NumOpsAdded = 1;
return true;
if (Opcode == ARM::BXJ) {
assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID &&
"Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
NumOpsAdded = 1;
return true;
if (Opcode == ARM::MSR || Opcode == ARM::MSRsys) {
assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID &&
"Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 16)));
NumOpsAdded = 2;
if (Opcode == ARM::SRSW || Opcode == ARM::SRS)
MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));
else
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
NumOpsAdded = 3;
return true;
// BLXr9, BXr9
// BRIND, BX_RET
static bool DisassembleBrMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
+ if (!OpInfo) return false;
+
unsigned &OpIdx = NumOpsAdded;
OpIdx = 0;
if (Opcode == ARM::BLXr9 || Opcode == ARM::BRIND) {
assert(NumOps >= 1 && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
"Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
OpIdx = 1;
return true;
// InOperandList with GPR:$target and GPR:$idx regs.
assert(NumOps == 4 && "Expect 4 operands");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
// Fill in the two remaining imm operands to signify build completion.
// InOperandList with GPR::$target reg.
assert(NumOps == 3 && "Expect 3 operands");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
// Fill in the two remaining imm operands to signify build completion.
// See also ARMAddressingModes.h (Addressing Mode #2).
assert(NumOps == 5 && getIBit(insn) == 1 && "Expect 5 operands && I-bit=1");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
// Disassemble the offset reg (Rm), shift type, and immediate shift length.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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));
return false;
}
-static inline uint32_t getBFCInvMask(uint32_t insn) {
+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;
- assert(lsb <= msb && "Encoding error: lsb > msb");
+ if (msb < lsb) {
+ DEBUG(errs() << "Encoding error: msb < lsb\n");
+ return false;
+ }
+
for (uint32_t i = lsb; i <= msb; ++i)
Val |= (1 << i);
- return ~Val;
+ mask = ~Val;
+ return true;
}
static inline bool SaturateOpcode(unsigned Opcode) {
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
unsigned short NumDefs = TID.getNumDefs();
// Disassemble register def if there is one.
if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
++OpIdx;
}
if (SaturateOpcode(Opcode)) {
MI.addOperand(MCOperand::CreateImm(decodeSaturatePos(Opcode, insn)));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
if (Opcode == ARM::SSAT16 || Opcode == ARM::USAT16) {
if (Opcode == ARM::BFC || Opcode == ARM::BFI) {
// TIED_TO operand skipped for BFC and Inst{3-0} (Reg) for BFI.
MI.addOperand(MCOperand::CreateReg(Opcode == ARM::BFC ? 0
- : getRegisterEnum(ARM::GPRRegClassID,
+ : getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
- MI.addOperand(MCOperand::CreateImm(getBFCInvMask(insn)));
+ 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) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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) + 1));
assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
"Reg operand expected");
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(ARM::GPRRegClassID,
+ getRegisterEnum(B, ARM::GPRRegClassID,
RmRn ? decodeRm(insn) : decodeRn(insn))));
++OpIdx;
}
// routed here as well.
// assert(getIBit(insn) == 0 && "I_Bit != '0' reg/reg form");
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(ARM::GPRRegClassID,
+ getRegisterEnum(B, ARM::GPRRegClassID,
RmRn? decodeRn(insn) : decodeRm(insn))));
++OpIdx;
} else if (Opcode == ARM::MOVi16 || Opcode == ARM::MOVTi16) {
}
static bool DisassembleDPSoRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
unsigned short NumDefs = TID.getNumDefs();
// Disassemble register def if there is one.
if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
++OpIdx;
}
if (!isUnary) {
assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
"Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
++OpIdx;
}
// Register-controlled shifts have Inst{7} = 0 and Inst{4} = 1.
unsigned Rs = slice(insn, 4, 4);
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
if (Rs) {
// Register-controlled shifts: [Rm, Rs, shift].
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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));
}
static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, bool isStore) {
+ unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
- unsigned short NumDefs = TID.getNumDefs();
bool isPrePost = isPrePostLdSt(TID.TSFlags);
const TargetOperandInfo *OpInfo = TID.OpInfo;
+ if (!OpInfo) return false;
+
unsigned &OpIdx = NumOpsAdded;
OpIdx = 0;
- assert(((!isStore && NumDefs > 0) || (isStore && (NumDefs == 0 || isPrePost)))
+ assert(((!isStore && TID.getNumDefs() > 0) ||
+ (isStore && (TID.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(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
++OpIdx;
}
assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
"Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
++OpIdx;
if (isPrePost && !isStore) {
assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
"Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
++OpIdx;
}
"Reg operand expected");
assert((!isPrePost || (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1))
&& "Index mode or tied_to operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
++OpIdx;
MI.addOperand(MCOperand::CreateImm(Offset));
} else {
// Disassemble the offset reg (Rm), shift type, and immediate shift length.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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));
}
static bool DisassembleLdFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
- return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, false);
+ 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) {
- return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true);
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
+ return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true, B);
}
static bool HasDualReg(unsigned Opcode) {
}
static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, bool isStore) {
+ unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
- unsigned short NumDefs = TID.getNumDefs();
bool isPrePost = isPrePostLdSt(TID.TSFlags);
const TargetOperandInfo *OpInfo = TID.OpInfo;
+ if (!OpInfo) return false;
+
unsigned &OpIdx = NumOpsAdded;
OpIdx = 0;
- assert(((!isStore && NumDefs > 0) || (isStore && (NumDefs == 0 || isPrePost)))
+ assert(((!isStore && TID.getNumDefs() > 0) ||
+ (isStore && (TID.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(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
++OpIdx;
}
assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
"Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
++OpIdx;
// Fill in LDRD and STRD's second operand.
if (DualReg) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn) + 1)));
++OpIdx;
}
if (isPrePost && !isStore) {
assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
"Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
++OpIdx;
}
"Reg operand expected");
assert((!isPrePost || (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1))
&& "Index mode or tied_to operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
++OpIdx;
MI.addOperand(MCOperand::CreateImm(Offset));
} else {
// Disassemble the offset reg (Rm).
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0);
MI.addOperand(MCOperand::CreateImm(Offset));
}
static bool DisassembleLdMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
- return DisassembleLdStMiscFrm(MI, Opcode, insn, NumOps, NumOpsAdded, false);
+ 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) {
- return DisassembleLdStMiscFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true);
+ 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
// and operand 1 (the AM4 mode imm). After operand 3, 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 5 && "LdStMulFrm expects NumOps >= 5");
OpIdx = 0;
- unsigned Base = getRegisterEnum(ARM::GPRRegClassID, decodeRn(insn));
+ unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
// Writeback to base, if necessary.
if (Opcode == ARM::LDM_UPD || Opcode == ARM::STM_UPD) {
unsigned RegListBits = insn & ((1 << 16) - 1);
for (unsigned i = 0; i < 16; ++i) {
if ((RegListBits >> i) & 1) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
i)));
++OpIdx;
}
//
// SWP, SWPB: Rd Rm Rn
static bool DisassembleLdStExFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
+ if (!OpInfo) return false;
+
unsigned &OpIdx = NumOpsAdded;
OpIdx = 0;
bool isDW = (Opcode == ARM::LDREXD || Opcode == ARM::STREXD);
// Add the destination operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
++OpIdx;
if (isDW) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn)+1)));
++OpIdx;
}
} else if (isDW) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn)+1)));
++OpIdx;
}
// Finally add the pointer operand.
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
++OpIdx;
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
unsigned &OpIdx = NumOpsAdded;
bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID;
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
++OpIdx;
if (ThreeReg) {
assert(NumOps >= 4 && "Expect >= 4 operands");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
++OpIdx;
}
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
++OpIdx;
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
unsigned &OpIdx = NumOpsAdded;
bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID;
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
++OpIdx;
if (ThreeReg) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
++OpIdx;
}
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
++OpIdx;
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 1 && "VFPUnaryFrm expects NumOps >= 1");
bool isSP = (RegClass == ARM::SPRRegClassID);
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(RegClass, decodeVFPRd(insn, isSP))));
+ getRegisterEnum(B, RegClass, decodeVFPRd(insn, isSP))));
++OpIdx;
// Early return for compare with zero instructions.
isSP = (RegClass == ARM::SPRRegClassID);
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(RegClass, decodeVFPRm(insn, isSP))));
+ getRegisterEnum(B, RegClass, decodeVFPRm(insn, isSP))));
++OpIdx;
return true;
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 3 && "VFPBinaryFrm expects NumOps >= 3");
bool isSP = (RegClass == ARM::SPRRegClassID);
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(RegClass, decodeVFPRd(insn, isSP))));
+ getRegisterEnum(B, RegClass, decodeVFPRd(insn, isSP))));
++OpIdx;
// Skip tied_to operand constraint.
}
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(RegClass, decodeVFPRn(insn, isSP))));
+ getRegisterEnum(B, RegClass, decodeVFPRn(insn, isSP))));
++OpIdx;
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(RegClass, decodeVFPRm(insn, isSP))));
+ getRegisterEnum(B, RegClass, decodeVFPRm(insn, isSP))));
++OpIdx;
return true;
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 2 && "VFPConv1Frm expects NumOps >= 2");
const TargetInstrDesc &TID = ARMInsts[Opcode];
const TargetOperandInfo *OpInfo = TID.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
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(RegClassID,
+ getRegisterEnum(B, RegClassID,
decodeVFPRd(insn, SP))));
assert(TID.getOperandConstraint(1, TOI::TIED_TO) != -1 &&
if (slice(insn, 18, 18) == 1) { // to_integer operation
d = decodeVFPRd(insn, true /* Is Single Precision */);
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(ARM::SPRRegClassID, d)));
+ getRegisterEnum(B, ARM::SPRRegClassID, d)));
m = decodeVFPRm(insn, SP);
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(RegClassID, m)));
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, m)));
} else {
d = decodeVFPRd(insn, SP);
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(RegClassID, d)));
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, d)));
m = decodeVFPRm(insn, true /* Is Single Precision */);
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(ARM::SPRRegClassID, m)));
+ getRegisterEnum(B, ARM::SPRRegClassID, m)));
}
NumOpsAdded = 2;
}
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 2 && "VFPConv2Frm expects NumOps >= 2");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::SPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
decodeVFPRn(insn, true))));
NumOpsAdded = 2;
return true;
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 3 && "VFPConv3Frm expects NumOps >= 3");
const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
unsigned &OpIdx = NumOpsAdded;
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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(ARM::SPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
Sm)));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::SPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
Sm+1)));
OpIdx += 2;
} else {
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(ARM::DPRRegClassID,
+ getRegisterEnum(B, ARM::DPRRegClassID,
decodeVFPRm(insn, false))));
++OpIdx;
}
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 2 && "VFPConv4Frm expects NumOps >= 2");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::SPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
decodeVFPRn(insn, true))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
NumOpsAdded = 2;
return true;
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 3 && "VFPConv5Frm expects NumOps >= 3");
if (OpInfo[OpIdx].RegClass == ARM::SPRRegClassID) {
unsigned Sm = decodeVFPRm(insn, true);
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::SPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
Sm)));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::SPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
Sm+1)));
OpIdx += 2;
} else {
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(ARM::DPRRegClassID,
+ getRegisterEnum(B, ARM::DPRRegClassID,
decodeVFPRm(insn, false))));
++OpIdx;
}
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 3 && "VFPLdStFrm expects NumOps >= 3");
// Extract Dd/Sd for operand 0.
unsigned RegD = decodeVFPRd(insn, isSPVFP);
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(RegClassID, RegD)));
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, RegD)));
- unsigned Base = getRegisterEnum(ARM::GPRRegClassID, decodeRn(insn));
+ unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
MI.addOperand(MCOperand::CreateReg(Base));
// Next comes the AM5 Opcode.
//
// VLDMD[_UPD], VLDMS[_UPD], VSTMD[_UPD], VSTMS[_UPD]
static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
assert(NumOps >= 5 && "VFPLdStMulFrm expects NumOps >= 5");
OpIdx = 0;
- unsigned Base = getRegisterEnum(ARM::GPRRegClassID, decodeRn(insn));
+ unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
// Writeback to base, if necessary.
if (Opcode == ARM::VLDMD_UPD || Opcode == ARM::VLDMS_UPD ||
// Next comes the AM5 Opcode.
ARM_AM::AMSubMode SubMode = getAMSubModeForBits(getPUBits(insn));
+ // Must be either "ia" or "db" submode.
+ if (SubMode != ARM_AM::ia && SubMode != ARM_AM::db) {
+ DEBUG(errs() << "Illegal addressing mode 5 sub-mode!\n");
+ return false;
+ }
+
unsigned char Imm8 = insn & 0xFF;
MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(SubMode, Imm8)));
// Fill the variadic part of reglist.
unsigned Regs = isSPVFP ? Imm8 : Imm8/2;
for (unsigned i = 0; i < Regs; ++i) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(RegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID,
RegD + i)));
++OpIdx;
}
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
unsigned &OpIdx = NumOpsAdded;
unsigned RegEnum = 0;
switch (OpInfo[0].RegClass) {
case ARM::DPRRegClassID:
- RegEnum = getRegisterEnum(ARM::DPRRegClassID, decodeVFPRd(insn, false));
+ RegEnum = getRegisterEnum(B, ARM::DPRRegClassID, decodeVFPRd(insn, false));
break;
case ARM::SPRRegClassID:
- RegEnum = getRegisterEnum(ARM::SPRRegClassID, decodeVFPRd(insn, true));
+ RegEnum = getRegisterEnum(B, ARM::SPRRegClassID, decodeVFPRd(insn, true));
break;
case ARM::GPRRegClassID:
- RegEnum = getRegisterEnum(ARM::GPRRegClassID, decodeRd(insn));
+ RegEnum = getRegisterEnum(B, ARM::GPRRegClassID, decodeRd(insn));
break;
default:
assert(0 && "Invalid reg class id");
case ESize64: {
for (unsigned i = 0; i < 8; ++i)
if ((Imm8 >> i) & 1)
- Imm64 |= 0xFF << 8*i;
+ Imm64 |= (uint64_t)0xFF << 8*i;
break;
}
default:
return (insn >> 8) & 0xF;
}
+static bool UseDRegPair(unsigned Opcode) {
+ switch (Opcode) {
+ default:
+ return false;
+ case ARM::VLD1q8_UPD:
+ case ARM::VLD1q16_UPD:
+ case ARM::VLD1q32_UPD:
+ case ARM::VLD1q64_UPD:
+ case ARM::VST1q8_UPD:
+ case ARM::VST1q16_UPD:
+ case ARM::VST1q32_UPD:
+ case ARM::VST1q64_UPD:
+ return true;
+ }
+}
+
// VLD*
// D[d] D[d2] ... Rn [TIED_TO Rn] align [Rm]
// VLD*LN*
//
// 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 short NumOps, unsigned &NumOpsAdded, bool Store, bool DblSpaced,
+ BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
const TargetOperandInfo *OpInfo = TID.OpInfo;
// LLVM Addressing Mode #6.
unsigned RmEnum = 0;
if (WB && Rm != 13)
- RmEnum = getRegisterEnum(ARM::GPRRegClassID, Rm);
+ RmEnum = getRegisterEnum(B, ARM::GPRRegClassID, Rm);
if (Store) {
// Consume possible WB, AddrMode6, possible increment reg, the DPR/QPR's,
"Reg operand expected");
if (WB) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
Rn)));
MI.addOperand(MCOperand::CreateImm(0)); // Alignment ignored?
OpIdx += 2;
RegClass = OpInfo[OpIdx].RegClass;
while (OpIdx < NumOps && OpInfo[OpIdx].RegClass == RegClass) {
- if (Opcode >= ARM::VST1q16 && Opcode <= ARM::VST1q8)
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(RegClass,Rd,true)));
- else
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(RegClass,Rd)));
+ MI.addOperand(MCOperand::CreateReg(
+ getRegisterEnum(B, RegClass, Rd,
+ UseDRegPair(Opcode))));
Rd += Inc;
++OpIdx;
}
RegClass = OpInfo[0].RegClass;
while (OpIdx < NumOps && OpInfo[OpIdx].RegClass == RegClass) {
- if (Opcode >= ARM::VLD1q16 && Opcode <= ARM::VLD1q8)
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(RegClass,Rd,true)));
- else
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(RegClass,Rd)));
+ MI.addOperand(MCOperand::CreateReg(
+ getRegisterEnum(B, RegClass, Rd,
+ UseDRegPair(Opcode))));
Rd += Inc;
++OpIdx;
}
if (WB) {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ 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");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
Rn)));
MI.addOperand(MCOperand::CreateImm(0)); // Alignment ignored?
OpIdx += 2;
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const StringRef Name = ARMInsts[Opcode].Name;
bool DblSpaced = false;
}
return DisassembleNLdSt0(MI, Opcode, insn, NumOps, NumOpsAdded,
- slice(insn, 21, 21) == 0, DblSpaced);
+ slice(insn, 21, 21) == 0, DblSpaced, B);
}
// VMOV (immediate)
// Qd/Dd imm
static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
const TargetOperandInfo *OpInfo = TID.OpInfo;
"Expect 1 reg operand followed by 1 imm operand");
// Qd/Dd = Inst{22:15-12} => NEON Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(OpInfo[0].RegClass,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[0].RegClass,
decodeNEONRd(insn))));
ElemSize esize = ESizeNA;
case ARM::VMOVv1i64:
case ARM::VMOVv2i64:
esize = ESize64;
+ break;
default:
assert(0 && "Unreachable code!");
return false;
//
// Others
static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, N2VFlag Flag = N2V_None) {
+ unsigned short NumOps, unsigned &NumOpsAdded, N2VFlag Flag, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opc];
const TargetOperandInfo *OpInfo = TID.OpInfo;
}
// Qd/Dd = Inst{22:15-12} => NEON Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(OpInfo[OpIdx].RegClass,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
decodeNEONRd(insn))));
++OpIdx;
}
// Dm = Inst{5:3-0} => NEON Rm
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(OpInfo[OpIdx].RegClass,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
decodeNEONRm(insn))));
++OpIdx;
}
static bool DisassembleN2RegFrm(MCInst &MI, unsigned Opc, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded);
+ 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
- N2V_VectorConvert_Between_Float_Fixed);
+ N2V_VectorConvert_Between_Float_Fixed, B);
}
static bool DisassembleNVecDupLnFrm(MCInst &MI, unsigned Opc, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
- N2V_VectorDupLane);
+ N2V_VectorDupLane, B);
}
// Vector Shift [Accumulate] 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, bool LeftShift, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
const TargetOperandInfo *OpInfo = TID.OpInfo;
OpIdx = 0;
// Qd/Dd = Inst{22:15-12} => NEON Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(OpInfo[OpIdx].RegClass,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
decodeNEONRd(insn))));
++OpIdx;
"Reg operand expected");
// Qm/Dm = Inst{5:3-0} => NEON Rm
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(OpInfo[OpIdx].RegClass,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
decodeNEONRm(insn))));
++OpIdx;
// Left shift instructions.
static bool DisassembleN2RegVecShLFrm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, true);
+ 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) {
+ uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, false);
+ return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, false,
+ B);
}
namespace {
//
// Others
static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, N3VFlag Flag = N3V_None) {
+ unsigned short NumOps, unsigned &NumOpsAdded, N3VFlag Flag, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
const TargetOperandInfo *OpInfo = TID.OpInfo;
}
// Qd/Dd = Inst{22:15-12} => NEON Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(OpInfo[OpIdx].RegClass,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
decodeNEONRd(insn))));
++OpIdx;
// or
// Dm = Inst{5:3-0} => NEON Rm
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(OpInfo[OpIdx].RegClass,
+ getRegisterEnum(B, OpInfo[OpIdx].RegClass,
VdVnVm ? decodeNEONRn(insn)
: decodeNEONRm(insn))));
++OpIdx;
: decodeNEONRn(insn);
MI.addOperand(MCOperand::CreateReg(
- getRegisterEnum(OpInfo[OpIdx].RegClass, m)));
+ getRegisterEnum(B, OpInfo[OpIdx].RegClass, m)));
++OpIdx;
if (OpIdx < NumOps && OpInfo[OpIdx].RegClass == 0
}
static bool DisassembleN3RegFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
- return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded);
+ 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) {
+ uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
- N3V_VectorShift);
+ N3V_VectorShift, B);
}
static bool DisassembleNVecExtractFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
- N3V_VectorExtract);
+ N3V_VectorExtract, B);
}
static bool DisassembleNVecMulScalarFrm(MCInst &MI, unsigned Opcode,
- uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
- N3V_Multiply_By_Scalar);
+ N3V_Multiply_By_Scalar, B);
}
// Vector Table Lookup
// 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) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
const TargetOperandInfo *OpInfo = TID.OpInfo;
+ if (!OpInfo) return false;
assert(NumOps >= 3 &&
OpInfo[0].RegClass == ARM::DPRRegClassID &&
unsigned Len = slice(insn, 9, 8) + 1;
// Dd (the destination vector)
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::DPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
decodeNEONRd(insn))));
++OpIdx;
for (unsigned i = 0; i < Len; ++i) {
assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::DPRRegClassID &&
"Reg operand expected");
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::DPRRegClassID,
+ 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(ARM::DPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
decodeNEONRm(insn))));
++OpIdx;
// Vector Get Lane (move scalar to ARM core register) Instructions.
// VGETLNi32, VGETLNs16, VGETLNs8, VGETLNu16, VGETLNu8: Rt Dn index
static bool DisassembleNEONGetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
- unsigned short NumDefs = TID.getNumDefs();
const TargetOperandInfo *OpInfo = TID.OpInfo;
+ if (!OpInfo) return false;
- assert(NumDefs == 1 && NumOps >= 3 &&
+ assert(TID.getNumDefs() == 1 && NumOps >= 3 &&
OpInfo[0].RegClass == ARM::GPRRegClassID &&
OpInfo[1].RegClass == ARM::DPRRegClassID &&
OpInfo[2].RegClass == 0 &&
: ESize32);
// Rt = Inst{15-12} => ARM Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
// Dn = Inst{7:19-16} => NEON Rn
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::DPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
decodeNEONRn(insn))));
MI.addOperand(MCOperand::CreateImm(decodeNVLaneOpIndex(insn, esize)));
// Vector Set Lane (move ARM core register to scalar) Instructions.
// VSETLNi16, VSETLNi32, VSETLNi8: Dd Dd (TIED_TO) Rt index
static bool DisassembleNEONSetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetInstrDesc &TID = ARMInsts[Opcode];
- unsigned short NumDefs = TID.getNumDefs();
const TargetOperandInfo *OpInfo = TID.OpInfo;
+ if (!OpInfo) return false;
- assert(NumDefs == 1 && NumOps >= 3 &&
+ assert(TID.getNumDefs() == 1 && NumOps >= 3 &&
OpInfo[0].RegClass == ARM::DPRRegClassID &&
OpInfo[1].RegClass == ARM::DPRRegClassID &&
TID.getOperandConstraint(1, TOI::TIED_TO) != -1 &&
: ESize32);
// Dd = Inst{7:19-16} => NEON Rn
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::DPRRegClassID,
+ 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(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
MI.addOperand(MCOperand::CreateImm(decodeNVLaneOpIndex(insn, esize)));
// Vector Duplicate Instructions (from ARM core register to all elements).
// VDUP8d, VDUP16d, VDUP32d, VDUP8q, VDUP16q, VDUP32q: Qd/Dd Rt
static bool DisassembleNEONDupFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
unsigned RegClass = OpInfo[0].RegClass;
// Qd/Dd = Inst{7:19-16} => NEON Rn
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(RegClass,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClass,
decodeNEONRn(insn))));
// Rt = Inst{15-12} => ARM Rd
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRd(insn))));
NumOpsAdded = 2;
}
static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
// Preload Data/Instruction requires either 2 or 4 operands.
// PLDi, PLDWi, PLIi: Rn [+/-]imm12 add = (U == '1')
// PLDr[a|m], PLDWr[a|m], PLIr[a|m]: Rn Rm addrmode2_opc
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
if (Opcode == ARM::PLDi || Opcode == ARM::PLDWi || Opcode == ARM::PLIi) {
MI.addOperand(MCOperand::CreateImm(Offset));
NumOpsAdded = 2;
} else {
- MI.addOperand(MCOperand::CreateReg(getRegisterEnum(ARM::GPRRegClassID,
+ MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
}
static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
- unsigned short NumOps, unsigned &NumOpsAdded, BO) {
+ unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
if (MemBarrierInstr(insn))
return true;
}
if (PreLoadOpcode(Opcode))
- return DisassemblePreLoadFrm(MI, Opcode, insn, NumOps, NumOpsAdded);
+ return DisassemblePreLoadFrm(MI, Opcode, insn, NumOps, NumOpsAdded, B);
assert(0 && "Unexpected misc instruction!");
return false;
unsigned NumOpsAdded = 0;
bool OK = (*Disasm)(MI, Opcode, insn, NumOps, NumOpsAdded, this);
- if (!OK) return false;
+ if (!OK || this->Err != 0) return false;
if (NumOpsAdded >= NumOps)
return true;
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 TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
+ unsigned Idx = MI.getNumOperands();
+
+ // First, we check whether this instr specifies the PredicateOperand through
+ // a pair of TargetOperandInfos 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) {
//
// A8.6.16 B
if (Name == "t2Bcc")
- MI.addOperand(MCOperand::CreateImm(slice(insn, 25, 22)));
+ MI.addOperand(MCOperand::CreateImm(CondCode(slice(insn, 25, 22))));
else if (Name == "tBcc")
- MI.addOperand(MCOperand::CreateImm(slice(insn, 11, 8)));
+ MI.addOperand(MCOperand::CreateImm(CondCode(slice(insn, 11, 8))));
else
MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
} else {
- // ARM Instructions. Check condition field.
- int64_t CondVal = getCondField(insn);
- if (CondVal == 0xF)
- MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
- else
- MI.addOperand(MCOperand::CreateImm(CondVal));
+ // ARM instructions get their condition field from Inst{31-28}.
+ MI.addOperand(MCOperand::CreateImm(CondCode(getCondField(insn))));
}
}
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
Idx += 2;
NumOpsRemaining -= 2;
- if (NumOpsRemaining == 0)
- return true;
}
+ 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));
if (!SP) return Status;
if (Opcode == ARM::t2IT)
- SP->InitIT(slice(insn, 7, 0));
+ Status = SP->InitIT(slice(insn, 7, 0)) ? Status : false;
else if (InITBlock())
SP->UpdateIT();
/// 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) {
+ : 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];
/// 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());