llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
Owen Anderson 9bd655dcde Fix PR10755 by checking for invalid predicate codes from UNPREDICTABLE t2IT instructions when decoding their successors.
This is the last disassembly crash detected by exhaustive Thumb2 instruction space.  Major thanks to Chandler Carruth for making this kind of exhaustive testing possible.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138625 91177308-0d34-0410-b5e6-96231b3b80d8
2011-08-26 06:19:51 +00:00

3322 lines
107 KiB
C++

//===- ARMDisassembler.cpp - Disassembler for ARM/Thumb ISA -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "arm-disassembler"
#include "ARMDisassembler.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/Support/Debug.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
// Pull DecodeStatus and its enum values into the global namespace.
typedef llvm::MCDisassembler::DecodeStatus DecodeStatus;
#define Success llvm::MCDisassembler::Success
#define Unpredictable llvm::MCDisassembler::SoftFail
#define Fail llvm::MCDisassembler::Fail
// Helper macro to perform setwise reduction of the current running status
// and another status, and return if the new status is Fail.
#define CHECK(S,X) do { \
S = (DecodeStatus) ((int)S & (X)); \
if (S == Fail) return Fail; \
} while(0)
// Forward declare these because the autogenerated code will reference them.
// Definitions are further down.
static DecodeStatus DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeGPRnopcRegisterClass(llvm::MCInst &Inst,
unsigned RegNo, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodetcGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecoderGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeDPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeDPR_8RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeDPR_VFP2RegisterClass(llvm::MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeQPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeCCOutOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSOImmOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeAddrMode3Instruction(llvm::MCInst &Inst,unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMemMultipleWritebackInstruction(llvm::MCInst & Inst,
unsigned Insn,
uint64_t Adddress,
const void *Decoder);
static DecodeStatus DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeCPSInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2CPSInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeAddrMode7Operand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeBranchImmInstruction(llvm::MCInst &Inst,unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVCVTImmOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeNEONModImmInstruction(llvm::MCInst &Inst,unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeShiftRight8Imm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeShiftRight16Imm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeShiftRight32Imm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeCoprocessor(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMemBarrierOption(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMSRMask(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeDoubleRegLoad(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeDoubleRegStore(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSTRPreImm(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSTRPreReg(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVLD1LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVLD2LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVLD3LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVLD4LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVST1LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVST2LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVST3LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVST4LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVMOVSRR(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVMOVRRS(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbBROperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2BROperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbCmpBROperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbAddrModeSP(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbAddSPImm(llvm::MCInst &Inst, uint16_t Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbCPS(llvm::MCInst &Inst, uint16_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeT2SOImm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbBCCTargetOperand(llvm::MCInst &Inst,unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeITCond(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeITMask(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder);
#include "ARMGenDisassemblerTables.inc"
#include "ARMGenInstrInfo.inc"
#include "ARMGenEDInfo.inc"
using namespace llvm;
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;
}
DecodeStatus 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 Fail;
// 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.
DecodeStatus result = decodeARMInstruction32(MI, insn, Address, this);
if (result != Fail) {
Size = 4;
return result;
}
// 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 != Fail) {
Size = 4;
return result;
}
// VFP and NEON instructions, similarly, are shared between ARM
// and Thumb modes.
MI.clear();
result = decodeVFPInstruction32(MI, insn, Address, this);
if (result != Fail) {
Size = 4;
return result;
}
MI.clear();
result = decodeNEONDataInstruction32(MI, insn, Address, this);
if (result != Fail) {
Size = 4;
// 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 Fail;
return result;
}
MI.clear();
result = decodeNEONLoadStoreInstruction32(MI, insn, Address, this);
if (result != Fail) {
Size = 4;
// 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 Fail;
return result;
}
MI.clear();
result = decodeNEONDupInstruction32(MI, insn, Address, this);
if (result != Fail) {
Size = 4;
// 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 Fail;
return result;
}
MI.clear();
return Fail;
}
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;
unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
MCInst::iterator I = MI.begin();
for (unsigned i = 0; i < NumOps; ++i, ++I) {
if (I == MI.end()) break;
if (OpInfo[i].isOptionalDef() && OpInfo[i].RegClass == ARM::CCRRegClassID) {
if (i > 0 && OpInfo[i-1].isPredicate()) continue;
MI.insert(I, MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR));
return;
}
}
MI.insert(I, MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR));
}
// 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;
}
// If we're in an IT block, base the predicate on that. Otherwise,
// assume a predicate of AL.
unsigned CC;
if (!ITBlock.empty()) {
CC = ITBlock.back();
if (CC == 0xF)
CC = ARMCC::AL;
ITBlock.pop_back();
} else
CC = ARMCC::AL;
const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
MCInst::iterator I = MI.begin();
for (unsigned i = 0; i < NumOps; ++i, ++I) {
if (I == MI.end()) break;
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;
}
}
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));
}
// 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.empty()) {
CC = ITBlock.back();
ITBlock.pop_back();
} else
CC = ARMCC::AL;
const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
MCInst::iterator I = MI.begin();
unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
for (unsigned i = 0; i < NumOps; ++i, ++I) {
if (OpInfo[i].isPredicate() ) {
I->setImm(CC);
++I;
if (CC == ARMCC::AL)
I->setReg(0);
else
I->setReg(ARM::CPSR);
return;
}
}
}
DecodeStatus 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 Fail;
uint16_t insn16 = (bytes[1] << 8) | bytes[0];
DecodeStatus result = decodeThumbInstruction16(MI, insn16, Address, this);
if (result != Fail) {
Size = 2;
AddThumbPredicate(MI);
return result;
}
MI.clear();
result = decodeThumbSBitInstruction16(MI, insn16, Address, this);
if (result) {
Size = 2;
bool InITBlock = !ITBlock.empty();
AddThumbPredicate(MI);
AddThumb1SBit(MI, InITBlock);
return result;
}
MI.clear();
result = decodeThumb2Instruction16(MI, insn16, Address, this);
if (result != Fail) {
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 result;
}
// We want to read exactly 4 bytes of data.
if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1)
return Fail;
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 != Fail) {
Size = 4;
bool InITBlock = ITBlock.size();
AddThumbPredicate(MI);
AddThumb1SBit(MI, InITBlock);
return result;
}
MI.clear();
result = decodeThumb2Instruction32(MI, insn32, Address, this);
if (result != Fail) {
Size = 4;
AddThumbPredicate(MI);
return result;
}
MI.clear();
result = decodeCommonInstruction32(MI, insn32, Address, this);
if (result != Fail) {
Size = 4;
AddThumbPredicate(MI);
return result;
}
MI.clear();
result = decodeVFPInstruction32(MI, insn32, Address, this);
if (result != Fail) {
Size = 4;
UpdateThumbVFPPredicate(MI);
return result;
}
MI.clear();
result = decodeNEONDupInstruction32(MI, insn32, Address, this);
if (result != Fail) {
Size = 4;
AddThumbPredicate(MI);
return result;
}
if (fieldFromInstruction32(insn32, 24, 8) == 0xF9) {
MI.clear();
uint32_t NEONLdStInsn = insn32;
NEONLdStInsn &= 0xF0FFFFFF;
NEONLdStInsn |= 0x04000000;
result = decodeNEONLoadStoreInstruction32(MI, NEONLdStInsn, Address, this);
if (result != Fail) {
Size = 4;
AddThumbPredicate(MI);
return result;
}
}
if (fieldFromInstruction32(insn32, 24, 4) == 0xF) {
MI.clear();
uint32_t NEONDataInsn = insn32;
NEONDataInsn &= 0xF0FFFFFF; // Clear bits 27-24
NEONDataInsn |= (NEONDataInsn & 0x10000000) >> 4; // Move bit 28 to bit 24
NEONDataInsn |= 0x12000000; // Set bits 28 and 25
result = decodeNEONDataInstruction32(MI, NEONDataInsn, Address, this);
if (result != Fail) {
Size = 4;
AddThumbPredicate(MI);
return result;
}
}
return Fail;
}
extern "C" void LLVMInitializeARMDisassembler() {
TargetRegistry::RegisterMCDisassembler(TheARMTarget,
createARMDisassembler);
TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
createThumbDisassembler);
}
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 DecodeStatus DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo > 15)
return Fail;
unsigned Register = GPRDecoderTable[RegNo];
Inst.addOperand(MCOperand::CreateReg(Register));
return Success;
}
static DecodeStatus
DecodeGPRnopcRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo == 15) return Fail;
return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
}
static DecodeStatus DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo > 7)
return Fail;
return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
}
static DecodeStatus 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 Fail;
}
Inst.addOperand(MCOperand::CreateReg(Register));
return Success;
}
static DecodeStatus DecoderGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo == 13 || RegNo == 15) return Fail;
return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
}
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 DecodeStatus DecodeSPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo > 31)
return Fail;
unsigned Register = SPRDecoderTable[RegNo];
Inst.addOperand(MCOperand::CreateReg(Register));
return Success;
}
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 DecodeStatus DecodeDPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo > 31)
return Fail;
unsigned Register = DPRDecoderTable[RegNo];
Inst.addOperand(MCOperand::CreateReg(Register));
return Success;
}
static DecodeStatus DecodeDPR_8RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo > 7)
return Fail;
return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
}
static DecodeStatus
DecodeDPR_VFP2RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo > 15)
return Fail;
return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
}
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
};
static DecodeStatus DecodeQPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
if (RegNo > 31)
return Fail;
RegNo >>= 1;
unsigned Register = QPRDecoderTable[RegNo];
Inst.addOperand(MCOperand::CreateReg(Register));
return Success;
}
static DecodeStatus DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
if (Val == 0xF) return Fail;
// AL predicate is not allowed on Thumb1 branches.
if (Inst.getOpcode() == ARM::tBcc && Val == 0xE)
return Fail;
Inst.addOperand(MCOperand::CreateImm(Val));
if (Val == ARMCC::AL) {
Inst.addOperand(MCOperand::CreateReg(0));
} else
Inst.addOperand(MCOperand::CreateReg(ARM::CPSR));
return Success;
}
static DecodeStatus 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 Success;
}
static DecodeStatus 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 Success;
}
static DecodeStatus DecodeBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Val <<= 2;
Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(Val)));
return Success;
}
static DecodeStatus DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rm = fieldFromInstruction32(Val, 0, 4);
unsigned type = fieldFromInstruction32(Val, 5, 2);
unsigned imm = fieldFromInstruction32(Val, 7, 5);
// Register-immediate
CHECK(S, 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 (Shift == ARM_AM::ror && imm == 0)
Shift = ARM_AM::rrx;
unsigned Op = Shift | (imm << 3);
Inst.addOperand(MCOperand::CreateImm(Op));
return S;
}
static DecodeStatus DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rm = fieldFromInstruction32(Val, 0, 4);
unsigned type = fieldFromInstruction32(Val, 5, 2);
unsigned Rs = fieldFromInstruction32(Val, 8, 4);
// Register-register
CHECK(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder));
CHECK(S, DecodeGPRnopcRegisterClass(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;
}
Inst.addOperand(MCOperand::CreateImm(Shift));
return S;
}
static DecodeStatus DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
// Empty register lists are not allowed.
if (CountPopulation_32(Val) == 0) return Fail;
for (unsigned i = 0; i < 16; ++i) {
if (Val & (1 << i)) {
CHECK(S, DecodeGPRRegisterClass(Inst, i, Address, Decoder));
}
}
return S;
}
static DecodeStatus DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Vd = fieldFromInstruction32(Val, 8, 4);
unsigned regs = Val & 0xFF;
CHECK(S, DecodeSPRRegisterClass(Inst, Vd, Address, Decoder));
for (unsigned i = 0; i < (regs - 1); ++i) {
CHECK(S, DecodeSPRRegisterClass(Inst, ++Vd, Address, Decoder));
}
return S;
}
static DecodeStatus DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Vd = fieldFromInstruction32(Val, 8, 4);
unsigned regs = (Val & 0xFF) / 2;
CHECK(S, DecodeDPRRegisterClass(Inst, Vd, Address, Decoder));
for (unsigned i = 0; i < (regs - 1); ++i) {
CHECK(S, DecodeDPRRegisterClass(Inst, ++Vd, Address, Decoder));
}
return S;
}
static DecodeStatus DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
// This operand encodes a mask of contiguous zeros between a specified MSB
// and LSB. To decode it, we create the mask of all bits MSB-and-lower,
// the mask of all bits LSB-and-lower, and then xor them to create
// the mask of that's all ones on [msb, lsb]. Finally we not it to
// create the final mask.
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 Success;
}
static DecodeStatus DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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 Fail;
break;
default:
break;
}
Inst.addOperand(MCOperand::CreateImm(coproc));
Inst.addOperand(MCOperand::CreateImm(CRd));
CHECK(S, 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:
case ARM::LDC2L_POST:
case ARM::STC2L_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:
case ARM::LDC2L_POST:
case ARM::STC2L_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:
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
break;
default:
break;
}
return S;
}
static DecodeStatus
DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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::STRB_POST_IMM:
case ARM::STRB_POST_REG:
case ARM::STRT_POST_REG:
case ARM::STRT_POST_IMM:
case ARM::STRBT_POST_REG:
case ARM::STRBT_POST_IMM:
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
break;
default:
break;
}
CHECK(S, 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::LDRB_POST_IMM:
case ARM::LDRB_POST_REG:
case ARM::LDR_PRE:
case ARM::LDRB_PRE:
case ARM::LDRBT_POST_REG:
case ARM::LDRBT_POST_IMM:
case ARM::LDRT_POST_REG:
case ARM::LDRT_POST_IMM:
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
break;
default:
break;
}
CHECK(S, 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 (writeback && (Rn == 15 || Rn == Rt)) S = Unpredictable; // UNPREDICTABLE
if (reg) {
CHECK(S, DecodeGPRnopcRegisterClass(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 Fail;
}
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));
}
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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 = ARM_AM::lsl;
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;
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, 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 S;
}
static DecodeStatus
DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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);
// For {LD,ST}RD, Rt must be even, else undefined.
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:
if (Rt & 0x1) return Fail;
break;
default:
break;
}
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:
case ARM::STRH:
case ARM::STRH_PRE:
case ARM::STRH_POST:
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
break;
default:
break;
}
}
CHECK(S, 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:
CHECK(S, 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::LDRH:
case ARM::LDRH_PRE:
case ARM::LDRH_POST:
case ARM::LDRSH:
case ARM::LDRSH_PRE:
case ARM::LDRSH_POST:
case ARM::LDRSB:
case ARM::LDRSB_PRE:
case ARM::LDRSB_POST:
case ARM::LDRHTr:
case ARM::LDRSBTr:
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
break;
default:
break;
}
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
if (type) {
Inst.addOperand(MCOperand::CreateReg(0));
Inst.addOperand(MCOperand::CreateImm(U | (imm << 4) | Rm));
} else {
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(U));
}
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeRFEInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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));
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
return S;
}
static DecodeStatus DecodeMemMultipleWritebackInstruction(llvm::MCInst &Inst,
unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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::LDMDA:
Inst.setOpcode(ARM::RFEDA);
break;
case ARM::LDMDA_UPD:
Inst.setOpcode(ARM::RFEDA_UPD);
break;
case ARM::LDMDB:
Inst.setOpcode(ARM::RFEDB);
break;
case ARM::LDMDB_UPD:
Inst.setOpcode(ARM::RFEDB_UPD);
break;
case ARM::LDMIA:
Inst.setOpcode(ARM::RFEIA);
break;
case ARM::LDMIA_UPD:
Inst.setOpcode(ARM::RFEIA_UPD);
break;
case ARM::LDMIB:
Inst.setOpcode(ARM::RFEIB);
break;
case ARM::LDMIB_UPD:
Inst.setOpcode(ARM::RFEIB_UPD);
break;
case ARM::STMDA:
Inst.setOpcode(ARM::SRSDA);
break;
case ARM::STMDA_UPD:
Inst.setOpcode(ARM::SRSDA_UPD);
break;
case ARM::STMDB:
Inst.setOpcode(ARM::SRSDB);
break;
case ARM::STMDB_UPD:
Inst.setOpcode(ARM::SRSDB_UPD);
break;
case ARM::STMIA:
Inst.setOpcode(ARM::SRSIA);
break;
case ARM::STMIA_UPD:
Inst.setOpcode(ARM::SRSIA_UPD);
break;
case ARM::STMIB:
Inst.setOpcode(ARM::SRSIB);
break;
case ARM::STMIB_UPD:
Inst.setOpcode(ARM::SRSIB_UPD);
break;
default:
CHECK(S, Fail);
}
// For stores (which become SRS's, the only operand is the mode.
if (fieldFromInstruction32(Insn, 20, 1) == 0) {
Inst.addOperand(
MCOperand::CreateImm(fieldFromInstruction32(Insn, 0, 4)));
return S;
}
return DecodeRFEInstruction(Inst, Insn, Address, Decoder);
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)); // Tied
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
CHECK(S, DecodeRegListOperand(Inst, reglist, Address, Decoder));
return S;
}
static DecodeStatus 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);
DecodeStatus S = Success;
// imod == '01' --> UNPREDICTABLE
// NOTE: Even though this is technically UNPREDICTABLE, we choose to
// return failure here. The '01' imod value is unprintable, so there's
// nothing useful we could do even if we returned UNPREDICTABLE.
if (imod == 1) CHECK(S, Fail);
if (imod && M) {
Inst.setOpcode(ARM::CPS3p);
Inst.addOperand(MCOperand::CreateImm(imod));
Inst.addOperand(MCOperand::CreateImm(iflags));
Inst.addOperand(MCOperand::CreateImm(mode));
} else if (imod && !M) {
Inst.setOpcode(ARM::CPS2p);
Inst.addOperand(MCOperand::CreateImm(imod));
Inst.addOperand(MCOperand::CreateImm(iflags));
if (mode) CHECK(S, Unpredictable);
} else if (!imod && M) {
Inst.setOpcode(ARM::CPS1p);
Inst.addOperand(MCOperand::CreateImm(mode));
if (iflags) CHECK(S, Unpredictable);
} else {
// imod == '00' && M == '0' --> UNPREDICTABLE
Inst.setOpcode(ARM::CPS1p);
Inst.addOperand(MCOperand::CreateImm(mode));
CHECK(S, Unpredictable);
}
return S;
}
static DecodeStatus DecodeT2CPSInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
unsigned imod = fieldFromInstruction32(Insn, 9, 2);
unsigned M = fieldFromInstruction32(Insn, 8, 1);
unsigned iflags = fieldFromInstruction32(Insn, 5, 3);
unsigned mode = fieldFromInstruction32(Insn, 0, 5);
DecodeStatus S = Success;
// imod == '01' --> UNPREDICTABLE
// NOTE: Even though this is technically UNPREDICTABLE, we choose to
// return failure here. The '01' imod value is unprintable, so there's
// nothing useful we could do even if we returned UNPREDICTABLE.
if (imod == 1) CHECK(S, Fail);
if (imod && M) {
Inst.setOpcode(ARM::t2CPS3p);
Inst.addOperand(MCOperand::CreateImm(imod));
Inst.addOperand(MCOperand::CreateImm(iflags));
Inst.addOperand(MCOperand::CreateImm(mode));
} else if (imod && !M) {
Inst.setOpcode(ARM::t2CPS2p);
Inst.addOperand(MCOperand::CreateImm(imod));
Inst.addOperand(MCOperand::CreateImm(iflags));
if (mode) CHECK(S, Unpredictable);
} else if (!imod && M) {
Inst.setOpcode(ARM::t2CPS1p);
Inst.addOperand(MCOperand::CreateImm(mode));
if (iflags) CHECK(S, Unpredictable);
} else {
// imod == '00' && M == '0' --> UNPREDICTABLE
Inst.setOpcode(ARM::t2CPS1p);
Inst.addOperand(MCOperand::CreateImm(mode));
CHECK(S, Unpredictable);
}
return S;
}
static DecodeStatus DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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);
CHECK(S, DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder));
CHECK(S, DecodeGPRnopcRegisterClass(Inst, Ra, Address, Decoder));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned add = fieldFromInstruction32(Val, 12, 1);
unsigned imm = fieldFromInstruction32(Val, 0, 12);
unsigned Rn = fieldFromInstruction32(Val, 13, 4);
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
if (!add) imm *= -1;
if (imm == 0 && !add) imm = INT32_MIN;
Inst.addOperand(MCOperand::CreateImm(imm));
return S;
}
static DecodeStatus DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Val, 9, 4);
unsigned U = fieldFromInstruction32(Val, 8, 1);
unsigned imm = fieldFromInstruction32(Val, 0, 8);
CHECK(S, 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 S;
}
static DecodeStatus DecodeAddrMode7Operand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
return DecodeGPRRegisterClass(Inst, Val, Address, Decoder);
}
static DecodeStatus
DecodeBranchImmInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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(SignExtend32<26>(imm)));
return S;
}
Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(imm)));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeVCVTImmOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(64 - Val));
return Success;
}
static DecodeStatus DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rm = fieldFromInstruction32(Val, 0, 4);
unsigned align = fieldFromInstruction32(Val, 4, 2);
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
if (!align)
Inst.addOperand(MCOperand::CreateImm(0));
else
Inst.addOperand(MCOperand::CreateImm(4 << align));
return S;
}
static DecodeStatus DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, DecodeGPRRegisterClass(Inst, wb, Address, Decoder));
break;
default:
break;
}
// AddrMode6 Base (register+alignment)
CHECK(S, DecodeAddrMode6Operand(Inst, Rn, Address, Decoder));
// AddrMode6 Offset (register)
if (Rm == 0xD)
Inst.addOperand(MCOperand::CreateReg(0));
else if (Rm != 0xF) {
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
}
return S;
}
static DecodeStatus DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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:
CHECK(S, DecodeGPRRegisterClass(Inst, wb, Address, Decoder));
break;
default:
break;
}
// AddrMode6 Base (register+alignment)
CHECK(S, DecodeAddrMode6Operand(Inst, Rn, Address, Decoder));
// AddrMode6 Offset (register)
if (Rm == 0xD)
Inst.addOperand(MCOperand::CreateReg(0));
else if (Rm != 0xF) {
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
}
// First input register
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, 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:
CHECK(S, DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder));
break;
default:
break;
}
return S;
}
static DecodeStatus DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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);
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
if (regs == 2) {
CHECK(S, DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder));
}
if (Rm != 0xF) {
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm == 0xD)
Inst.addOperand(MCOperand::CreateReg(0));
else if (Rm != 0xF) {
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
}
return S;
}
static DecodeStatus DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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;
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder));
if (Rm != 0xF) {
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm == 0xD)
Inst.addOperand(MCOperand::CreateReg(0));
else if (Rm != 0xF) {
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
}
return S;
}
static DecodeStatus DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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;
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder));
if (Rm != 0xF) {
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(0));
if (Rm == 0xD)
Inst.addOperand(MCOperand::CreateReg(0));
else if (Rm != 0xF) {
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
}
return S;
}
static DecodeStatus DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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;
}
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, (Rd+3*inc)%32, Address, Decoder));
if (Rm != 0xF) {
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm == 0xD)
Inst.addOperand(MCOperand::CreateReg(0));
else if (Rm != 0xF) {
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
}
return S;
}
static DecodeStatus
DecodeNEONModImmInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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) {
CHECK(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder));
} else {
CHECK(S, 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:
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
break;
case ARM::VORRiv8i16:
case ARM::VORRiv4i32:
case ARM::VBICiv8i16:
case ARM::VBICiv4i32:
CHECK(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder));
break;
default:
break;
}
return S;
}
static DecodeStatus DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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);
CHECK(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rm, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(8 << size));
return S;
}
static DecodeStatus DecodeShiftRight8Imm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(8 - Val));
return Success;
}
static DecodeStatus DecodeShiftRight16Imm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(16 - Val));
return Success;
}
static DecodeStatus DecodeShiftRight32Imm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(32 - Val));
return Success;
}
static DecodeStatus DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(64 - Val));
return Success;
}
static DecodeStatus DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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;
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
if (op) {
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)); // Writeback
}
for (unsigned i = 0; i < length; ++i) {
CHECK(S, DecodeDPRRegisterClass(Inst, (Rn+i)%32, Address, Decoder));
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rm, Address, Decoder));
return S;
}
static DecodeStatus 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 Success;
}
static DecodeStatus DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned dst = fieldFromInstruction16(Insn, 8, 3);
unsigned imm = fieldFromInstruction16(Insn, 0, 8);
CHECK(S, 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 Fail;
Inst.addOperand(MCOperand::CreateImm(imm));
return S;
}
static DecodeStatus DecodeThumbBROperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(SignExtend32<12>(Val << 1)));
return Success;
}
static DecodeStatus DecodeT2BROperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(SignExtend32<21>(Val)));
return Success;
}
static DecodeStatus DecodeThumbCmpBROperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(SignExtend32<7>(Val << 1)));
return Success;
}
static DecodeStatus DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Val, 0, 3);
unsigned Rm = fieldFromInstruction32(Val, 3, 3);
CHECK(S, DecodetGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodetGPRRegisterClass(Inst, Rm, Address, Decoder));
return S;
}
static DecodeStatus DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Val, 0, 3);
unsigned imm = fieldFromInstruction32(Val, 3, 5);
CHECK(S, DecodetGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(imm));
return S;
}
static DecodeStatus DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(Val << 2));
return Success;
}
static DecodeStatus DecodeThumbAddrModeSP(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateReg(ARM::SP));
Inst.addOperand(MCOperand::CreateImm(Val));
return Success;
}
static DecodeStatus DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Val, 6, 4);
unsigned Rm = fieldFromInstruction32(Val, 2, 4);
unsigned imm = fieldFromInstruction32(Val, 0, 2);
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(imm));
return S;
}
static DecodeStatus DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
switch (Inst.getOpcode()) {
case ARM::t2PLDs:
case ARM::t2PLDWs:
case ARM::t2PLIs:
break;
default: {
unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
CHECK(S, 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 Fail;
}
int imm = fieldFromInstruction32(Insn, 0, 12);
if (!fieldFromInstruction32(Insn, 23, 1)) imm *= -1;
Inst.addOperand(MCOperand::CreateImm(imm));
return S;
}
unsigned addrmode = fieldFromInstruction32(Insn, 4, 2);
addrmode |= fieldFromInstruction32(Insn, 0, 4) << 2;
addrmode |= fieldFromInstruction32(Insn, 16, 4) << 6;
CHECK(S, DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder));
return S;
}
static DecodeStatus 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 Success;
}
static DecodeStatus DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Val, 9, 4);
unsigned imm = fieldFromInstruction32(Val, 0, 9);
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodeT2Imm8S4(Inst, imm, Address, Decoder));
return S;
}
static DecodeStatus 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 Success;
}
static DecodeStatus DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
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;
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodeT2Imm8(Inst, imm, Address, Decoder));
return S;
}
static DecodeStatus DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Val, 13, 4);
unsigned imm = fieldFromInstruction32(Val, 0, 12);
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(imm));
return S;
}
static DecodeStatus 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 Success;
}
static DecodeStatus DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
if (Inst.getOpcode() == ARM::tADDrSP) {
unsigned Rdm = fieldFromInstruction16(Insn, 0, 3);
Rdm |= fieldFromInstruction16(Insn, 7, 1) << 3;
CHECK(S, DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder));
Inst.addOperand(MCOperand::CreateReg(ARM::SP));
} else if (Inst.getOpcode() == ARM::tADDspr) {
unsigned Rm = fieldFromInstruction16(Insn, 3, 4);
Inst.addOperand(MCOperand::CreateReg(ARM::SP));
Inst.addOperand(MCOperand::CreateReg(ARM::SP));
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
}
return S;
}
static DecodeStatus 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 Success;
}
static DecodeStatus DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned add = fieldFromInstruction32(Insn, 4, 1);
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)) ;
Inst.addOperand(MCOperand::CreateImm(add));
return S;
}
static DecodeStatus DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
return Success;
}
static DecodeStatus DecodeCoprocessor(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
if (Val == 0xA || Val == 0xB)
return Fail;
Inst.addOperand(MCOperand::CreateImm(Val));
return Success;
}
static DecodeStatus
DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned pred = fieldFromInstruction32(Insn, 22, 4);
if (pred == 0xE || pred == 0xF) {
unsigned opc = fieldFromInstruction32(Insn, 4, 2);
switch (opc) {
default:
return Fail;
case 0:
Inst.setOpcode(ARM::t2DSB);
break;
case 1:
Inst.setOpcode(ARM::t2DMB);
break;
case 2:
Inst.setOpcode(ARM::t2ISB);
return Success;
}
unsigned imm = fieldFromInstruction32(Insn, 0, 4);
return DecodeMemBarrierOption(Inst, imm, Address, Decoder);
}
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;
CHECK(S, DecodeT2BROperand(Inst, brtarget, Address, Decoder));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
// 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 DecodeStatus 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 Success;
}
static DecodeStatus
DecodeThumbBCCTargetOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder){
Inst.addOperand(MCOperand::CreateImm(Val << 1));
return Success;
}
static DecodeStatus DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder){
Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
return Success;
}
static DecodeStatus DecodeMemBarrierOption(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
switch (Val) {
default:
return Fail;
case 0xF: // SY
case 0xE: // ST
case 0xB: // ISH
case 0xA: // ISHST
case 0x7: // NSH
case 0x6: // NSHST
case 0x3: // OSH
case 0x2: // OSHST
break;
}
Inst.addOperand(MCOperand::CreateImm(Val));
return Success;
}
static DecodeStatus DecodeMSRMask(llvm::MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
if (!Val) return Fail;
Inst.addOperand(MCOperand::CreateImm(Val));
return Success;
}
static DecodeStatus DecodeDoubleRegLoad(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned pred = fieldFromInstruction32(Insn, 28, 4);
if ((Rt & 1) || Rt == 0xE || Rn == 0xF) return Fail;
CHECK(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeDoubleRegStore(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder){
DecodeStatus S = Success;
unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
unsigned Rt = fieldFromInstruction32(Insn, 0, 4);
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned pred = fieldFromInstruction32(Insn, 28, 4);
CHECK(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder));
if ((Rt & 1) || Rt == 0xE || Rn == 0xF) return Fail;
if (Rd == Rn || Rd == Rt || Rd == Rt+1) return Fail;
CHECK(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeSTRPreImm(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
unsigned imm = fieldFromInstruction32(Insn, 0, 12);
imm |= fieldFromInstruction32(Insn, 16, 4) << 13;
imm |= fieldFromInstruction32(Insn, 23, 1) << 12;
unsigned pred = fieldFromInstruction32(Insn, 28, 4);
if (Rn == 0xF || Rn == Rt) CHECK(S, Unpredictable);
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder));
CHECK(S, DecodeAddrModeImm12Operand(Inst, imm, Address, Decoder));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeSTRPreReg(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
unsigned imm = fieldFromInstruction32(Insn, 0, 12);
imm |= fieldFromInstruction32(Insn, 16, 4) << 13;
imm |= fieldFromInstruction32(Insn, 23, 1) << 12;
unsigned pred = fieldFromInstruction32(Insn, 28, 4);
if (Rn == 0xF || Rn == Rt) CHECK(S, Unpredictable);
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder));
CHECK(S, DecodeSORegMemOperand(Inst, imm, Address, Decoder));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeVLD1LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
unsigned size = fieldFromInstruction32(Insn, 10, 2);
unsigned align = 0;
unsigned index = 0;
switch (size) {
default:
return Fail;
case 0:
if (fieldFromInstruction32(Insn, 4, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 5, 3);
break;
case 1:
if (fieldFromInstruction32(Insn, 5, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 6, 2);
if (fieldFromInstruction32(Insn, 4, 1))
align = 2;
break;
case 2:
if (fieldFromInstruction32(Insn, 6, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 7, 1);
if (fieldFromInstruction32(Insn, 4, 2) != 0)
align = 4;
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
if (Rm != 0xF) { // Writeback
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm != 0xF) {
if (Rm != 0xD)
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
else
Inst.addOperand(MCOperand::CreateReg(0));
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(index));
return S;
}
static DecodeStatus DecodeVST1LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
unsigned size = fieldFromInstruction32(Insn, 10, 2);
unsigned align = 0;
unsigned index = 0;
switch (size) {
default:
return Fail;
case 0:
if (fieldFromInstruction32(Insn, 4, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 5, 3);
break;
case 1:
if (fieldFromInstruction32(Insn, 5, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 6, 2);
if (fieldFromInstruction32(Insn, 4, 1))
align = 2;
break;
case 2:
if (fieldFromInstruction32(Insn, 6, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 7, 1);
if (fieldFromInstruction32(Insn, 4, 2) != 0)
align = 4;
}
if (Rm != 0xF) { // Writeback
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm != 0xF) {
if (Rm != 0xD)
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
else
Inst.addOperand(MCOperand::CreateReg(0));
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(index));
return S;
}
static DecodeStatus DecodeVLD2LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
unsigned size = fieldFromInstruction32(Insn, 10, 2);
unsigned align = 0;
unsigned index = 0;
unsigned inc = 1;
switch (size) {
default:
return Fail;
case 0:
index = fieldFromInstruction32(Insn, 5, 3);
if (fieldFromInstruction32(Insn, 4, 1))
align = 2;
break;
case 1:
index = fieldFromInstruction32(Insn, 6, 2);
if (fieldFromInstruction32(Insn, 4, 1))
align = 4;
if (fieldFromInstruction32(Insn, 5, 1))
inc = 2;
break;
case 2:
if (fieldFromInstruction32(Insn, 5, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 7, 1);
if (fieldFromInstruction32(Insn, 4, 1) != 0)
align = 8;
if (fieldFromInstruction32(Insn, 6, 1))
inc = 2;
break;
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder));
if (Rm != 0xF) { // Writeback
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm != 0xF) {
if (Rm != 0xD)
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
else
Inst.addOperand(MCOperand::CreateReg(0));
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(index));
return S;
}
static DecodeStatus DecodeVST2LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
unsigned size = fieldFromInstruction32(Insn, 10, 2);
unsigned align = 0;
unsigned index = 0;
unsigned inc = 1;
switch (size) {
default:
return Fail;
case 0:
index = fieldFromInstruction32(Insn, 5, 3);
if (fieldFromInstruction32(Insn, 4, 1))
align = 2;
break;
case 1:
index = fieldFromInstruction32(Insn, 6, 2);
if (fieldFromInstruction32(Insn, 4, 1))
align = 4;
if (fieldFromInstruction32(Insn, 5, 1))
inc = 2;
break;
case 2:
if (fieldFromInstruction32(Insn, 5, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 7, 1);
if (fieldFromInstruction32(Insn, 4, 1) != 0)
align = 8;
if (fieldFromInstruction32(Insn, 6, 1))
inc = 2;
break;
}
if (Rm != 0xF) { // Writeback
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm != 0xF) {
if (Rm != 0xD)
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
else
Inst.addOperand(MCOperand::CreateReg(0));
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(index));
return S;
}
static DecodeStatus DecodeVLD3LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
unsigned size = fieldFromInstruction32(Insn, 10, 2);
unsigned align = 0;
unsigned index = 0;
unsigned inc = 1;
switch (size) {
default:
return Fail;
case 0:
if (fieldFromInstruction32(Insn, 4, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 5, 3);
break;
case 1:
if (fieldFromInstruction32(Insn, 4, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 6, 2);
if (fieldFromInstruction32(Insn, 5, 1))
inc = 2;
break;
case 2:
if (fieldFromInstruction32(Insn, 4, 2))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 7, 1);
if (fieldFromInstruction32(Insn, 6, 1))
inc = 2;
break;
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder));
if (Rm != 0xF) { // Writeback
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm != 0xF) {
if (Rm != 0xD)
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
else
Inst.addOperand(MCOperand::CreateReg(0));
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(index));
return S;
}
static DecodeStatus DecodeVST3LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
unsigned size = fieldFromInstruction32(Insn, 10, 2);
unsigned align = 0;
unsigned index = 0;
unsigned inc = 1;
switch (size) {
default:
return Fail;
case 0:
if (fieldFromInstruction32(Insn, 4, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 5, 3);
break;
case 1:
if (fieldFromInstruction32(Insn, 4, 1))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 6, 2);
if (fieldFromInstruction32(Insn, 5, 1))
inc = 2;
break;
case 2:
if (fieldFromInstruction32(Insn, 4, 2))
return Fail; // UNDEFINED
index = fieldFromInstruction32(Insn, 7, 1);
if (fieldFromInstruction32(Insn, 6, 1))
inc = 2;
break;
}
if (Rm != 0xF) { // Writeback
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm != 0xF) {
if (Rm != 0xD)
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
else
Inst.addOperand(MCOperand::CreateReg(0));
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(index));
return S;
}
static DecodeStatus DecodeVLD4LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
unsigned size = fieldFromInstruction32(Insn, 10, 2);
unsigned align = 0;
unsigned index = 0;
unsigned inc = 1;
switch (size) {
default:
return Fail;
case 0:
if (fieldFromInstruction32(Insn, 4, 1))
align = 4;
index = fieldFromInstruction32(Insn, 5, 3);
break;
case 1:
if (fieldFromInstruction32(Insn, 4, 1))
align = 8;
index = fieldFromInstruction32(Insn, 6, 2);
if (fieldFromInstruction32(Insn, 5, 1))
inc = 2;
break;
case 2:
if (fieldFromInstruction32(Insn, 4, 2))
align = 4 << fieldFromInstruction32(Insn, 4, 2);
index = fieldFromInstruction32(Insn, 7, 1);
if (fieldFromInstruction32(Insn, 6, 1))
inc = 2;
break;
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+3*inc, Address, Decoder));
if (Rm != 0xF) { // Writeback
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm != 0xF) {
if (Rm != 0xD)
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
else
Inst.addOperand(MCOperand::CreateReg(0));
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+3*inc, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(index));
return S;
}
static DecodeStatus DecodeVST4LN(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
unsigned size = fieldFromInstruction32(Insn, 10, 2);
unsigned align = 0;
unsigned index = 0;
unsigned inc = 1;
switch (size) {
default:
return Fail;
case 0:
if (fieldFromInstruction32(Insn, 4, 1))
align = 4;
index = fieldFromInstruction32(Insn, 5, 3);
break;
case 1:
if (fieldFromInstruction32(Insn, 4, 1))
align = 8;
index = fieldFromInstruction32(Insn, 6, 2);
if (fieldFromInstruction32(Insn, 5, 1))
inc = 2;
break;
case 2:
if (fieldFromInstruction32(Insn, 4, 2))
align = 4 << fieldFromInstruction32(Insn, 4, 2);
index = fieldFromInstruction32(Insn, 7, 1);
if (fieldFromInstruction32(Insn, 6, 1))
inc = 2;
break;
}
if (Rm != 0xF) { // Writeback
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
}
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(align));
if (Rm != 0xF) {
if (Rm != 0xD)
CHECK(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder));
else
Inst.addOperand(MCOperand::CreateReg(0));
}
CHECK(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+inc, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+2*inc, Address, Decoder));
CHECK(S, DecodeDPRRegisterClass(Inst, Rd+3*inc, Address, Decoder));
Inst.addOperand(MCOperand::CreateImm(index));
return S;
}
static DecodeStatus DecodeVMOVSRR(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
unsigned Rt2 = fieldFromInstruction32(Insn, 16, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned pred = fieldFromInstruction32(Insn, 28, 4);
Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
if (Rt == 0xF || Rt2 == 0xF || Rm == 0x1F)
CHECK(S, Unpredictable);
CHECK(S, DecodeSPRRegisterClass(Inst, Rm , Address, Decoder));
CHECK(S, DecodeSPRRegisterClass(Inst, Rm+1, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rt , Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rt2 , Address, Decoder));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeVMOVRRS(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
unsigned Rt2 = fieldFromInstruction32(Insn, 16, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
unsigned pred = fieldFromInstruction32(Insn, 28, 4);
Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
if (Rt == 0xF || Rt2 == 0xF || Rm == 0x1F)
CHECK(S, Unpredictable);
CHECK(S, DecodeGPRRegisterClass(Inst, Rt , Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rt2 , Address, Decoder));
CHECK(S, DecodeSPRRegisterClass(Inst, Rm , Address, Decoder));
CHECK(S, DecodeSPRRegisterClass(Inst, Rm+1, Address, Decoder));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeITCond(llvm::MCInst &Inst, unsigned Cond,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
if (Cond == 0xF) {
Cond = 0xE;
CHECK(S, Unpredictable);
}
Inst.addOperand(MCOperand::CreateImm(Cond));
return S;
}
static DecodeStatus DecodeITMask(llvm::MCInst &Inst, unsigned Mask,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
if (Mask == 0) {
Mask = 0x8;
CHECK(S, Unpredictable);
}
Inst.addOperand(MCOperand::CreateImm(Mask));
return S;
}