blob: e1654e2e9f64008a02c0f2cd2cca2342abc69c26 [file] [log] [blame]
//===- AArch64Disassembler.cpp - Disassembler for AArch64 ISA -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the functions necessary to decode AArch64 instruction
// bitpatterns into MCInsts (with the help of TableGenerated information from
// the instruction definitions).
//
//===----------------------------------------------------------------------===//
/* Capstone Disassembly Engine */
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
#ifdef CAPSTONE_HAS_ARM64
#include <stdio.h> // DEBUG
#include <stdlib.h>
#include "../../cs_priv.h"
#include "../../utils.h"
#include "../../MCInst.h"
#include "../../MCInstrDesc.h"
#include "../../MCFixedLenDisassembler.h"
#include "../../MCRegisterInfo.h"
#include "../../MCDisassembler.h"
#include "AArch64BaseInfo.h"
#include "AArch64AddressingModes.h"
// Forward declare these because the autogenerated code will reference them.
// Definitions are further down.
static DecodeStatus DecodeFPR128RegisterClass(MCInst *Inst,
unsigned RegNo, uint64_t Address,
void *Decoder);
static DecodeStatus DecodeFPR128_loRegisterClass(MCInst *Inst,
unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeFPR64RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeFPR32RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeFPR16RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeFPR8RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeGPR64RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeGPR64spRegisterClass(MCInst *Inst,
unsigned RegNo, uint64_t Address,
void *Decoder);
static DecodeStatus DecodeGPR32RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeGPR32spRegisterClass(MCInst *Inst,
unsigned RegNo, uint64_t Address,
void *Decoder);
static DecodeStatus DecodeQQRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeQQQRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeQQQQRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeDDRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeDDDRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeDDDDRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeFixedPointScaleImm32(MCInst *Inst, unsigned Imm,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeFixedPointScaleImm64(MCInst *Inst, unsigned Imm,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodePCRelLabel19(MCInst *Inst, unsigned Imm,
uint64_t Address, void *Decoder);
static DecodeStatus DecodeMemExtend(MCInst *Inst, unsigned Imm,
uint64_t Address, void *Decoder);
static DecodeStatus DecodeMRSSystemRegister(MCInst *Inst, unsigned Imm,
uint64_t Address, void *Decoder);
static DecodeStatus DecodeMSRSystemRegister(MCInst *Inst, unsigned Imm,
uint64_t Address, void *Decoder);
static DecodeStatus DecodeThreeAddrSRegInstruction(MCInst *Inst,
uint32_t insn,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeMoveImmInstruction(MCInst *Inst, uint32_t insn,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeUnsignedLdStInstruction(MCInst *Inst,
uint32_t insn,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeSignedLdStInstruction(MCInst *Inst,
uint32_t insn, uint64_t Address,
void *Decoder);
static DecodeStatus DecodeExclusiveLdStInstruction(MCInst *Inst,
uint32_t insn,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodePairLdStInstruction(MCInst *Inst, uint32_t insn,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeAddSubERegInstruction(MCInst *Inst,
uint32_t insn, uint64_t Address,
void *Decoder);
static DecodeStatus DecodeLogicalImmInstruction(MCInst *Inst,
uint32_t insn, uint64_t Address,
void *Decoder);
static DecodeStatus DecodeModImmInstruction(MCInst *Inst, uint32_t insn,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeModImmTiedInstruction(MCInst *Inst,
uint32_t insn, uint64_t Address,
void *Decoder);
static DecodeStatus DecodeAdrInstruction(MCInst *Inst, uint32_t insn,
uint64_t Address, void *Decoder);
static DecodeStatus DecodeBaseAddSubImm(MCInst *Inst, uint32_t insn,
uint64_t Address, void *Decoder);
static DecodeStatus DecodeUnconditionalBranch(MCInst *Inst, uint32_t insn,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeSystemPStateInstruction(MCInst *Inst,
uint32_t insn,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeTestAndBranch(MCInst *Inst, uint32_t insn,
uint64_t Address, void *Decoder);
static DecodeStatus DecodeFMOVLaneInstruction(MCInst *Inst, unsigned Insn,
uint64_t Address,
void *Decoder);
static DecodeStatus DecodeVecShiftR64Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder);
static DecodeStatus DecodeVecShiftR64ImmNarrow(MCInst *Inst, unsigned Imm,
uint64_t Addr,
void *Decoder);
static DecodeStatus DecodeVecShiftR32Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder);
static DecodeStatus DecodeVecShiftR32ImmNarrow(MCInst *Inst, unsigned Imm,
uint64_t Addr,
void *Decoder);
static DecodeStatus DecodeVecShiftR16Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder);
static DecodeStatus DecodeVecShiftR16ImmNarrow(MCInst *Inst, unsigned Imm,
uint64_t Addr,
void *Decoder);
static DecodeStatus DecodeVecShiftR8Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder);
static DecodeStatus DecodeVecShiftL64Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder);
static DecodeStatus DecodeVecShiftL32Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder);
static DecodeStatus DecodeVecShiftL16Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder);
static DecodeStatus DecodeVecShiftL8Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder);
static bool Check(DecodeStatus *Out, DecodeStatus In)
{
switch (In) {
default: // never reach
return true;
case MCDisassembler_Success:
// Out stays the same.
return true;
case MCDisassembler_SoftFail:
*Out = In;
return true;
case MCDisassembler_Fail:
*Out = In;
return false;
}
// llvm_unreachable("Invalid DecodeStatus!");
}
// Hacky: enable all features for disassembler
static uint64_t getFeatureBits(int feature)
{
// enable all features
return (uint64_t)-1;
}
#define GET_SUBTARGETINFO_ENUM
#include "AArch64GenSubtargetInfo.inc"
#include "AArch64GenDisassemblerTables.inc"
#define GET_INSTRINFO_ENUM
#include "AArch64GenInstrInfo.inc"
#define GET_REGINFO_ENUM
#define GET_REGINFO_MC_DESC
#include "AArch64GenRegisterInfo.inc"
#define Success MCDisassembler_Success
#define Fail MCDisassembler_Fail
#define SoftFail MCDisassembler_SoftFail
static DecodeStatus _getInstruction(cs_struct *ud, MCInst *MI,
const uint8_t *code, size_t code_len,
uint16_t *Size,
uint64_t Address, MCRegisterInfo *MRI)
{
uint32_t insn;
DecodeStatus result;
size_t i;
if (code_len < 4) {
// not enough data
*Size = 0;
return MCDisassembler_Fail;
}
if (MI->flat_insn->detail) {
memset(MI->flat_insn->detail, 0, sizeof(cs_detail));
for (i = 0; i < ARR_SIZE(MI->flat_insn->detail->arm64.operands); i++)
MI->flat_insn->detail->arm64.operands[i].vector_index = -1;
}
if (ud->big_endian)
insn = (code[3] << 0) | (code[2] << 8) |
(code[1] << 16) | (code[0] << 24);
else
insn = (code[3] << 24) | (code[2] << 16) |
(code[1] << 8) | (code[0] << 0);
// Calling the auto-generated decoder function.
result = decodeInstruction(DecoderTable32, MI, insn, Address, MRI, 0);
if (result != MCDisassembler_Fail) {
*Size = 4;
return result;
}
MCInst_clear(MI);
*Size = 0;
return MCDisassembler_Fail;
}
bool AArch64_getInstruction(csh ud, const uint8_t *code, size_t code_len,
MCInst *instr, uint16_t *size, uint64_t address, void *info)
{
DecodeStatus status = _getInstruction((cs_struct *)ud, instr,
code, code_len,
size,
address, (MCRegisterInfo *)info);
return status == MCDisassembler_Success;
}
static const unsigned FPR128DecoderTable[] = {
AArch64_Q0, AArch64_Q1, AArch64_Q2, AArch64_Q3, AArch64_Q4,
AArch64_Q5, AArch64_Q6, AArch64_Q7, AArch64_Q8, AArch64_Q9,
AArch64_Q10, AArch64_Q11, AArch64_Q12, AArch64_Q13, AArch64_Q14,
AArch64_Q15, AArch64_Q16, AArch64_Q17, AArch64_Q18, AArch64_Q19,
AArch64_Q20, AArch64_Q21, AArch64_Q22, AArch64_Q23, AArch64_Q24,
AArch64_Q25, AArch64_Q26, AArch64_Q27, AArch64_Q28, AArch64_Q29,
AArch64_Q30, AArch64_Q31
};
static DecodeStatus DecodeFPR128RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = FPR128DecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static DecodeStatus DecodeFPR128_loRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
if (RegNo > 15)
return Fail;
return DecodeFPR128RegisterClass(Inst, RegNo, Addr, Decoder);
}
static const unsigned FPR64DecoderTable[] = {
AArch64_D0, AArch64_D1, AArch64_D2, AArch64_D3, AArch64_D4,
AArch64_D5, AArch64_D6, AArch64_D7, AArch64_D8, AArch64_D9,
AArch64_D10, AArch64_D11, AArch64_D12, AArch64_D13, AArch64_D14,
AArch64_D15, AArch64_D16, AArch64_D17, AArch64_D18, AArch64_D19,
AArch64_D20, AArch64_D21, AArch64_D22, AArch64_D23, AArch64_D24,
AArch64_D25, AArch64_D26, AArch64_D27, AArch64_D28, AArch64_D29,
AArch64_D30, AArch64_D31
};
static DecodeStatus DecodeFPR64RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = FPR64DecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned FPR32DecoderTable[] = {
AArch64_S0, AArch64_S1, AArch64_S2, AArch64_S3, AArch64_S4,
AArch64_S5, AArch64_S6, AArch64_S7, AArch64_S8, AArch64_S9,
AArch64_S10, AArch64_S11, AArch64_S12, AArch64_S13, AArch64_S14,
AArch64_S15, AArch64_S16, AArch64_S17, AArch64_S18, AArch64_S19,
AArch64_S20, AArch64_S21, AArch64_S22, AArch64_S23, AArch64_S24,
AArch64_S25, AArch64_S26, AArch64_S27, AArch64_S28, AArch64_S29,
AArch64_S30, AArch64_S31
};
static DecodeStatus DecodeFPR32RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = FPR32DecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned FPR16DecoderTable[] = {
AArch64_H0, AArch64_H1, AArch64_H2, AArch64_H3, AArch64_H4,
AArch64_H5, AArch64_H6, AArch64_H7, AArch64_H8, AArch64_H9,
AArch64_H10, AArch64_H11, AArch64_H12, AArch64_H13, AArch64_H14,
AArch64_H15, AArch64_H16, AArch64_H17, AArch64_H18, AArch64_H19,
AArch64_H20, AArch64_H21, AArch64_H22, AArch64_H23, AArch64_H24,
AArch64_H25, AArch64_H26, AArch64_H27, AArch64_H28, AArch64_H29,
AArch64_H30, AArch64_H31
};
static DecodeStatus DecodeFPR16RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = FPR16DecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned FPR8DecoderTable[] = {
AArch64_B0, AArch64_B1, AArch64_B2, AArch64_B3, AArch64_B4,
AArch64_B5, AArch64_B6, AArch64_B7, AArch64_B8, AArch64_B9,
AArch64_B10, AArch64_B11, AArch64_B12, AArch64_B13, AArch64_B14,
AArch64_B15, AArch64_B16, AArch64_B17, AArch64_B18, AArch64_B19,
AArch64_B20, AArch64_B21, AArch64_B22, AArch64_B23, AArch64_B24,
AArch64_B25, AArch64_B26, AArch64_B27, AArch64_B28, AArch64_B29,
AArch64_B30, AArch64_B31
};
static DecodeStatus DecodeFPR8RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = FPR8DecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned GPR64DecoderTable[] = {
AArch64_X0, AArch64_X1, AArch64_X2, AArch64_X3, AArch64_X4,
AArch64_X5, AArch64_X6, AArch64_X7, AArch64_X8, AArch64_X9,
AArch64_X10, AArch64_X11, AArch64_X12, AArch64_X13, AArch64_X14,
AArch64_X15, AArch64_X16, AArch64_X17, AArch64_X18, AArch64_X19,
AArch64_X20, AArch64_X21, AArch64_X22, AArch64_X23, AArch64_X24,
AArch64_X25, AArch64_X26, AArch64_X27, AArch64_X28, AArch64_FP,
AArch64_LR, AArch64_XZR
};
static DecodeStatus DecodeGPR64RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = GPR64DecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static DecodeStatus DecodeGPR64spRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = GPR64DecoderTable[RegNo];
if (Register == AArch64_XZR)
Register = AArch64_SP;
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned GPR32DecoderTable[] = {
AArch64_W0, AArch64_W1, AArch64_W2, AArch64_W3, AArch64_W4,
AArch64_W5, AArch64_W6, AArch64_W7, AArch64_W8, AArch64_W9,
AArch64_W10, AArch64_W11, AArch64_W12, AArch64_W13, AArch64_W14,
AArch64_W15, AArch64_W16, AArch64_W17, AArch64_W18, AArch64_W19,
AArch64_W20, AArch64_W21, AArch64_W22, AArch64_W23, AArch64_W24,
AArch64_W25, AArch64_W26, AArch64_W27, AArch64_W28, AArch64_W29,
AArch64_W30, AArch64_WZR
};
static DecodeStatus DecodeGPR32RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = GPR32DecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static DecodeStatus DecodeGPR32spRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = GPR32DecoderTable[RegNo];
if (Register == AArch64_WZR)
Register = AArch64_WSP;
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned VectorDecoderTable[] = {
AArch64_Q0, AArch64_Q1, AArch64_Q2, AArch64_Q3, AArch64_Q4,
AArch64_Q5, AArch64_Q6, AArch64_Q7, AArch64_Q8, AArch64_Q9,
AArch64_Q10, AArch64_Q11, AArch64_Q12, AArch64_Q13, AArch64_Q14,
AArch64_Q15, AArch64_Q16, AArch64_Q17, AArch64_Q18, AArch64_Q19,
AArch64_Q20, AArch64_Q21, AArch64_Q22, AArch64_Q23, AArch64_Q24,
AArch64_Q25, AArch64_Q26, AArch64_Q27, AArch64_Q28, AArch64_Q29,
AArch64_Q30, AArch64_Q31
};
static DecodeStatus DecodeVectorRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = VectorDecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned QQDecoderTable[] = {
AArch64_Q0_Q1, AArch64_Q1_Q2, AArch64_Q2_Q3, AArch64_Q3_Q4,
AArch64_Q4_Q5, AArch64_Q5_Q6, AArch64_Q6_Q7, AArch64_Q7_Q8,
AArch64_Q8_Q9, AArch64_Q9_Q10, AArch64_Q10_Q11, AArch64_Q11_Q12,
AArch64_Q12_Q13, AArch64_Q13_Q14, AArch64_Q14_Q15, AArch64_Q15_Q16,
AArch64_Q16_Q17, AArch64_Q17_Q18, AArch64_Q18_Q19, AArch64_Q19_Q20,
AArch64_Q20_Q21, AArch64_Q21_Q22, AArch64_Q22_Q23, AArch64_Q23_Q24,
AArch64_Q24_Q25, AArch64_Q25_Q26, AArch64_Q26_Q27, AArch64_Q27_Q28,
AArch64_Q28_Q29, AArch64_Q29_Q30, AArch64_Q30_Q31, AArch64_Q31_Q0
};
static DecodeStatus DecodeQQRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = QQDecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned QQQDecoderTable[] = {
AArch64_Q0_Q1_Q2, AArch64_Q1_Q2_Q3, AArch64_Q2_Q3_Q4,
AArch64_Q3_Q4_Q5, AArch64_Q4_Q5_Q6, AArch64_Q5_Q6_Q7,
AArch64_Q6_Q7_Q8, AArch64_Q7_Q8_Q9, AArch64_Q8_Q9_Q10,
AArch64_Q9_Q10_Q11, AArch64_Q10_Q11_Q12, AArch64_Q11_Q12_Q13,
AArch64_Q12_Q13_Q14, AArch64_Q13_Q14_Q15, AArch64_Q14_Q15_Q16,
AArch64_Q15_Q16_Q17, AArch64_Q16_Q17_Q18, AArch64_Q17_Q18_Q19,
AArch64_Q18_Q19_Q20, AArch64_Q19_Q20_Q21, AArch64_Q20_Q21_Q22,
AArch64_Q21_Q22_Q23, AArch64_Q22_Q23_Q24, AArch64_Q23_Q24_Q25,
AArch64_Q24_Q25_Q26, AArch64_Q25_Q26_Q27, AArch64_Q26_Q27_Q28,
AArch64_Q27_Q28_Q29, AArch64_Q28_Q29_Q30, AArch64_Q29_Q30_Q31,
AArch64_Q30_Q31_Q0, AArch64_Q31_Q0_Q1
};
static DecodeStatus DecodeQQQRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = QQQDecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned QQQQDecoderTable[] = {
AArch64_Q0_Q1_Q2_Q3, AArch64_Q1_Q2_Q3_Q4, AArch64_Q2_Q3_Q4_Q5,
AArch64_Q3_Q4_Q5_Q6, AArch64_Q4_Q5_Q6_Q7, AArch64_Q5_Q6_Q7_Q8,
AArch64_Q6_Q7_Q8_Q9, AArch64_Q7_Q8_Q9_Q10, AArch64_Q8_Q9_Q10_Q11,
AArch64_Q9_Q10_Q11_Q12, AArch64_Q10_Q11_Q12_Q13, AArch64_Q11_Q12_Q13_Q14,
AArch64_Q12_Q13_Q14_Q15, AArch64_Q13_Q14_Q15_Q16, AArch64_Q14_Q15_Q16_Q17,
AArch64_Q15_Q16_Q17_Q18, AArch64_Q16_Q17_Q18_Q19, AArch64_Q17_Q18_Q19_Q20,
AArch64_Q18_Q19_Q20_Q21, AArch64_Q19_Q20_Q21_Q22, AArch64_Q20_Q21_Q22_Q23,
AArch64_Q21_Q22_Q23_Q24, AArch64_Q22_Q23_Q24_Q25, AArch64_Q23_Q24_Q25_Q26,
AArch64_Q24_Q25_Q26_Q27, AArch64_Q25_Q26_Q27_Q28, AArch64_Q26_Q27_Q28_Q29,
AArch64_Q27_Q28_Q29_Q30, AArch64_Q28_Q29_Q30_Q31, AArch64_Q29_Q30_Q31_Q0,
AArch64_Q30_Q31_Q0_Q1, AArch64_Q31_Q0_Q1_Q2
};
static DecodeStatus DecodeQQQQRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = QQQQDecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned DDDecoderTable[] = {
AArch64_D0_D1, AArch64_D1_D2, AArch64_D2_D3, AArch64_D3_D4,
AArch64_D4_D5, AArch64_D5_D6, AArch64_D6_D7, AArch64_D7_D8,
AArch64_D8_D9, AArch64_D9_D10, AArch64_D10_D11, AArch64_D11_D12,
AArch64_D12_D13, AArch64_D13_D14, AArch64_D14_D15, AArch64_D15_D16,
AArch64_D16_D17, AArch64_D17_D18, AArch64_D18_D19, AArch64_D19_D20,
AArch64_D20_D21, AArch64_D21_D22, AArch64_D22_D23, AArch64_D23_D24,
AArch64_D24_D25, AArch64_D25_D26, AArch64_D26_D27, AArch64_D27_D28,
AArch64_D28_D29, AArch64_D29_D30, AArch64_D30_D31, AArch64_D31_D0
};
static DecodeStatus DecodeDDRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = DDDecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned DDDDecoderTable[] = {
AArch64_D0_D1_D2, AArch64_D1_D2_D3, AArch64_D2_D3_D4,
AArch64_D3_D4_D5, AArch64_D4_D5_D6, AArch64_D5_D6_D7,
AArch64_D6_D7_D8, AArch64_D7_D8_D9, AArch64_D8_D9_D10,
AArch64_D9_D10_D11, AArch64_D10_D11_D12, AArch64_D11_D12_D13,
AArch64_D12_D13_D14, AArch64_D13_D14_D15, AArch64_D14_D15_D16,
AArch64_D15_D16_D17, AArch64_D16_D17_D18, AArch64_D17_D18_D19,
AArch64_D18_D19_D20, AArch64_D19_D20_D21, AArch64_D20_D21_D22,
AArch64_D21_D22_D23, AArch64_D22_D23_D24, AArch64_D23_D24_D25,
AArch64_D24_D25_D26, AArch64_D25_D26_D27, AArch64_D26_D27_D28,
AArch64_D27_D28_D29, AArch64_D28_D29_D30, AArch64_D29_D30_D31,
AArch64_D30_D31_D0, AArch64_D31_D0_D1
};
static DecodeStatus DecodeDDDRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = DDDDecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static const unsigned DDDDDecoderTable[] = {
AArch64_D0_D1_D2_D3, AArch64_D1_D2_D3_D4, AArch64_D2_D3_D4_D5,
AArch64_D3_D4_D5_D6, AArch64_D4_D5_D6_D7, AArch64_D5_D6_D7_D8,
AArch64_D6_D7_D8_D9, AArch64_D7_D8_D9_D10, AArch64_D8_D9_D10_D11,
AArch64_D9_D10_D11_D12, AArch64_D10_D11_D12_D13, AArch64_D11_D12_D13_D14,
AArch64_D12_D13_D14_D15, AArch64_D13_D14_D15_D16, AArch64_D14_D15_D16_D17,
AArch64_D15_D16_D17_D18, AArch64_D16_D17_D18_D19, AArch64_D17_D18_D19_D20,
AArch64_D18_D19_D20_D21, AArch64_D19_D20_D21_D22, AArch64_D20_D21_D22_D23,
AArch64_D21_D22_D23_D24, AArch64_D22_D23_D24_D25, AArch64_D23_D24_D25_D26,
AArch64_D24_D25_D26_D27, AArch64_D25_D26_D27_D28, AArch64_D26_D27_D28_D29,
AArch64_D27_D28_D29_D30, AArch64_D28_D29_D30_D31, AArch64_D29_D30_D31_D0,
AArch64_D30_D31_D0_D1, AArch64_D31_D0_D1_D2
};
static DecodeStatus DecodeDDDDRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
void *Decoder)
{
unsigned Register;
if (RegNo > 31)
return Fail;
Register = DDDDDecoderTable[RegNo];
MCOperand_CreateReg0(Inst, Register);
return Success;
}
static DecodeStatus DecodeFixedPointScaleImm32(MCInst *Inst, unsigned Imm,
uint64_t Addr,
void *Decoder)
{
// scale{5} is asserted as 1 in tblgen.
Imm |= 0x20;
MCOperand_CreateImm0(Inst, 64 - Imm);
return Success;
}
static DecodeStatus DecodeFixedPointScaleImm64(MCInst *Inst, unsigned Imm,
uint64_t Addr,
void *Decoder)
{
MCOperand_CreateImm0(Inst, 64 - Imm);
return Success;
}
static DecodeStatus DecodePCRelLabel19(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder)
{
int64_t ImmVal = Imm;
// Sign-extend 19-bit immediate.
if (ImmVal & (1 << (19 - 1)))
ImmVal |= ~((1LL << 19) - 1);
MCOperand_CreateImm0(Inst, ImmVal);
return Success;
}
static DecodeStatus DecodeMemExtend(MCInst *Inst, unsigned Imm,
uint64_t Address, void *Decoder)
{
MCOperand_CreateImm0(Inst, (Imm >> 1) & 1);
MCOperand_CreateImm0(Inst, Imm & 1);
return Success;
}
static DecodeStatus DecodeMRSSystemRegister(MCInst *Inst, unsigned Imm,
uint64_t Address, void *Decoder)
{
MCOperand_CreateImm0(Inst, Imm);
// Every system register in the encoding space is valid with the syntax
// S<op0>_<op1>_<Cn>_<Cm>_<op2>, so decoding system registers always succeeds.
return Success;
}
static DecodeStatus DecodeMSRSystemRegister(MCInst *Inst, unsigned Imm,
uint64_t Address,
void *Decoder)
{
MCOperand_CreateImm0(Inst, Imm);
return Success;
}
static DecodeStatus DecodeFMOVLaneInstruction(MCInst *Inst, unsigned Insn,
uint64_t Address,
void *Decoder)
{
// This decoder exists to add the dummy Lane operand to the MCInst, which must
// be 1 in assembly but has no other real manifestation.
unsigned Rd = fieldFromInstruction(Insn, 0, 5);
unsigned Rn = fieldFromInstruction(Insn, 5, 5);
unsigned IsToVec = fieldFromInstruction(Insn, 16, 1);
if (IsToVec) {
DecodeFPR128RegisterClass(Inst, Rd, Address, Decoder);
DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder);
} else {
DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder);
DecodeFPR128RegisterClass(Inst, Rn, Address, Decoder);
}
// Add the lane
MCOperand_CreateImm0(Inst, 1);
return Success;
}
static DecodeStatus DecodeVecShiftRImm(MCInst *Inst, unsigned Imm,
unsigned Add)
{
MCOperand_CreateImm0(Inst, Add - Imm);
return Success;
}
static DecodeStatus DecodeVecShiftLImm(MCInst *Inst, unsigned Imm,
unsigned Add)
{
MCOperand_CreateImm0(Inst, (Imm + Add) & (Add - 1));
return Success;
}
static DecodeStatus DecodeVecShiftR64Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder)
{
return DecodeVecShiftRImm(Inst, Imm, 64);
}
static DecodeStatus DecodeVecShiftR64ImmNarrow(MCInst *Inst, unsigned Imm,
uint64_t Addr,
void *Decoder)
{
return DecodeVecShiftRImm(Inst, Imm | 0x20, 64);
}
static DecodeStatus DecodeVecShiftR32Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder)
{
return DecodeVecShiftRImm(Inst, Imm, 32);
}
static DecodeStatus DecodeVecShiftR32ImmNarrow(MCInst *Inst, unsigned Imm,
uint64_t Addr,
void *Decoder)
{
return DecodeVecShiftRImm(Inst, Imm | 0x10, 32);
}
static DecodeStatus DecodeVecShiftR16Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder)
{
return DecodeVecShiftRImm(Inst, Imm, 16);
}
static DecodeStatus DecodeVecShiftR16ImmNarrow(MCInst *Inst, unsigned Imm,
uint64_t Addr,
void *Decoder)
{
return DecodeVecShiftRImm(Inst, Imm | 0x8, 16);
}
static DecodeStatus DecodeVecShiftR8Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder)
{
return DecodeVecShiftRImm(Inst, Imm, 8);
}
static DecodeStatus DecodeVecShiftL64Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder)
{
return DecodeVecShiftLImm(Inst, Imm, 64);
}
static DecodeStatus DecodeVecShiftL32Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder)
{
return DecodeVecShiftLImm(Inst, Imm, 32);
}
static DecodeStatus DecodeVecShiftL16Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder)
{
return DecodeVecShiftLImm(Inst, Imm, 16);
}
static DecodeStatus DecodeVecShiftL8Imm(MCInst *Inst, unsigned Imm,
uint64_t Addr, void *Decoder)
{
return DecodeVecShiftLImm(Inst, Imm, 8);
}
static DecodeStatus DecodeThreeAddrSRegInstruction(MCInst *Inst,
uint32_t insn, uint64_t Addr,
void *Decoder)
{
unsigned Rd = fieldFromInstruction(insn, 0, 5);
unsigned Rn = fieldFromInstruction(insn, 5, 5);
unsigned Rm = fieldFromInstruction(insn, 16, 5);
unsigned shiftHi = fieldFromInstruction(insn, 22, 2);
unsigned shiftLo = fieldFromInstruction(insn, 10, 6);
unsigned shift = (shiftHi << 6) | shiftLo;
switch (MCInst_getOpcode(Inst)) {
default:
return Fail;
case AArch64_ADDWrs:
case AArch64_ADDSWrs:
case AArch64_SUBWrs:
case AArch64_SUBSWrs:
// if shift == '11' then ReservedValue()
if (shiftHi == 0x3)
return Fail;
// Deliberate fallthrough
case AArch64_ANDWrs:
case AArch64_ANDSWrs:
case AArch64_BICWrs:
case AArch64_BICSWrs:
case AArch64_ORRWrs:
case AArch64_ORNWrs:
case AArch64_EORWrs:
case AArch64_EONWrs: {
// if sf == '0' and imm6<5> == '1' then ReservedValue()
if (shiftLo >> 5 == 1)
return Fail;
DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR32RegisterClass(Inst, Rn, Addr, Decoder);
DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder);
break;
}
case AArch64_ADDXrs:
case AArch64_ADDSXrs:
case AArch64_SUBXrs:
case AArch64_SUBSXrs:
// if shift == '11' then ReservedValue()
if (shiftHi == 0x3)
return Fail;
// Deliberate fallthrough
case AArch64_ANDXrs:
case AArch64_ANDSXrs:
case AArch64_BICXrs:
case AArch64_BICSXrs:
case AArch64_ORRXrs:
case AArch64_ORNXrs:
case AArch64_EORXrs:
case AArch64_EONXrs:
DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder);
DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder);
break;
}
MCOperand_CreateImm0(Inst, shift);
return Success;
}
static DecodeStatus DecodeMoveImmInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
void *Decoder)
{
unsigned Rd = fieldFromInstruction(insn, 0, 5);
unsigned imm = fieldFromInstruction(insn, 5, 16);
unsigned shift = fieldFromInstruction(insn, 21, 2);
shift <<= 4;
switch (MCInst_getOpcode(Inst)) {
default:
return Fail;
case AArch64_MOVZWi:
case AArch64_MOVNWi:
case AArch64_MOVKWi:
if (shift & (1U << 5))
return Fail;
DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder);
break;
case AArch64_MOVZXi:
case AArch64_MOVNXi:
case AArch64_MOVKXi:
DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder);
break;
}
if (MCInst_getOpcode(Inst) == AArch64_MOVKWi ||
MCInst_getOpcode(Inst) == AArch64_MOVKXi)
MCInst_addOperand2(Inst, MCInst_getOperand(Inst, 0));
MCOperand_CreateImm0(Inst, imm);
MCOperand_CreateImm0(Inst, shift);
return Success;
}
static DecodeStatus DecodeUnsignedLdStInstruction(MCInst *Inst,
uint32_t insn, uint64_t Addr,
void *Decoder)
{
unsigned Rt = fieldFromInstruction(insn, 0, 5);
unsigned Rn = fieldFromInstruction(insn, 5, 5);
unsigned offset = fieldFromInstruction(insn, 10, 12);
switch (MCInst_getOpcode(Inst)) {
default:
return Fail;
case AArch64_PRFMui:
// Rt is an immediate in prefetch.
MCOperand_CreateImm0(Inst, Rt);
break;
case AArch64_STRBBui:
case AArch64_LDRBBui:
case AArch64_LDRSBWui:
case AArch64_STRHHui:
case AArch64_LDRHHui:
case AArch64_LDRSHWui:
case AArch64_STRWui:
case AArch64_LDRWui:
DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDRSBXui:
case AArch64_LDRSHXui:
case AArch64_LDRSWui:
case AArch64_STRXui:
case AArch64_LDRXui:
DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDRQui:
case AArch64_STRQui:
DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDRDui:
case AArch64_STRDui:
DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDRSui:
case AArch64_STRSui:
DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDRHui:
case AArch64_STRHui:
DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDRBui:
case AArch64_STRBui:
DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder);
break;
}
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
//if (!Dis->tryAddingSymbolicOperand(Inst, offset, Addr, Fail, 0, 4))
MCOperand_CreateImm0(Inst, offset);
return Success;
}
static DecodeStatus DecodeSignedLdStInstruction(MCInst *Inst,
uint32_t insn, uint64_t Addr,
void *Decoder)
{
bool IsLoad;
bool IsIndexed;
bool IsFP;
unsigned Rt = fieldFromInstruction(insn, 0, 5);
unsigned Rn = fieldFromInstruction(insn, 5, 5);
int32_t offset = fieldFromInstruction(insn, 12, 9);
// offset is a 9-bit signed immediate, so sign extend it to
// fill the unsigned.
if (offset & (1 << (9 - 1)))
offset |= ~((1LL << 9) - 1);
// First operand is always the writeback to the address register, if needed.
switch (MCInst_getOpcode(Inst)) {
default:
break;
case AArch64_LDRSBWpre:
case AArch64_LDRSHWpre:
case AArch64_STRBBpre:
case AArch64_LDRBBpre:
case AArch64_STRHHpre:
case AArch64_LDRHHpre:
case AArch64_STRWpre:
case AArch64_LDRWpre:
case AArch64_LDRSBWpost:
case AArch64_LDRSHWpost:
case AArch64_STRBBpost:
case AArch64_LDRBBpost:
case AArch64_STRHHpost:
case AArch64_LDRHHpost:
case AArch64_STRWpost:
case AArch64_LDRWpost:
case AArch64_LDRSBXpre:
case AArch64_LDRSHXpre:
case AArch64_STRXpre:
case AArch64_LDRSWpre:
case AArch64_LDRXpre:
case AArch64_LDRSBXpost:
case AArch64_LDRSHXpost:
case AArch64_STRXpost:
case AArch64_LDRSWpost:
case AArch64_LDRXpost:
case AArch64_LDRQpre:
case AArch64_STRQpre:
case AArch64_LDRQpost:
case AArch64_STRQpost:
case AArch64_LDRDpre:
case AArch64_STRDpre:
case AArch64_LDRDpost:
case AArch64_STRDpost:
case AArch64_LDRSpre:
case AArch64_STRSpre:
case AArch64_LDRSpost:
case AArch64_STRSpost:
case AArch64_LDRHpre:
case AArch64_STRHpre:
case AArch64_LDRHpost:
case AArch64_STRHpost:
case AArch64_LDRBpre:
case AArch64_STRBpre:
case AArch64_LDRBpost:
case AArch64_STRBpost:
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
break;
}
switch (MCInst_getOpcode(Inst)) {
default:
return Fail;
case AArch64_PRFUMi:
// Rt is an immediate in prefetch.
MCOperand_CreateImm0(Inst, Rt);
break;
case AArch64_STURBBi:
case AArch64_LDURBBi:
case AArch64_LDURSBWi:
case AArch64_STURHHi:
case AArch64_LDURHHi:
case AArch64_LDURSHWi:
case AArch64_STURWi:
case AArch64_LDURWi:
case AArch64_LDTRSBWi:
case AArch64_LDTRSHWi:
case AArch64_STTRWi:
case AArch64_LDTRWi:
case AArch64_STTRHi:
case AArch64_LDTRHi:
case AArch64_LDTRBi:
case AArch64_STTRBi:
case AArch64_LDRSBWpre:
case AArch64_LDRSHWpre:
case AArch64_STRBBpre:
case AArch64_LDRBBpre:
case AArch64_STRHHpre:
case AArch64_LDRHHpre:
case AArch64_STRWpre:
case AArch64_LDRWpre:
case AArch64_LDRSBWpost:
case AArch64_LDRSHWpost:
case AArch64_STRBBpost:
case AArch64_LDRBBpost:
case AArch64_STRHHpost:
case AArch64_LDRHHpost:
case AArch64_STRWpost:
case AArch64_LDRWpost:
DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDURSBXi:
case AArch64_LDURSHXi:
case AArch64_LDURSWi:
case AArch64_STURXi:
case AArch64_LDURXi:
case AArch64_LDTRSBXi:
case AArch64_LDTRSHXi:
case AArch64_LDTRSWi:
case AArch64_STTRXi:
case AArch64_LDTRXi:
case AArch64_LDRSBXpre:
case AArch64_LDRSHXpre:
case AArch64_STRXpre:
case AArch64_LDRSWpre:
case AArch64_LDRXpre:
case AArch64_LDRSBXpost:
case AArch64_LDRSHXpost:
case AArch64_STRXpost:
case AArch64_LDRSWpost:
case AArch64_LDRXpost:
DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDURQi:
case AArch64_STURQi:
case AArch64_LDRQpre:
case AArch64_STRQpre:
case AArch64_LDRQpost:
case AArch64_STRQpost:
DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDURDi:
case AArch64_STURDi:
case AArch64_LDRDpre:
case AArch64_STRDpre:
case AArch64_LDRDpost:
case AArch64_STRDpost:
DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDURSi:
case AArch64_STURSi:
case AArch64_LDRSpre:
case AArch64_STRSpre:
case AArch64_LDRSpost:
case AArch64_STRSpost:
DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDURHi:
case AArch64_STURHi:
case AArch64_LDRHpre:
case AArch64_STRHpre:
case AArch64_LDRHpost:
case AArch64_STRHpost:
DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_LDURBi:
case AArch64_STURBi:
case AArch64_LDRBpre:
case AArch64_STRBpre:
case AArch64_LDRBpost:
case AArch64_STRBpost:
DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder);
break;
}
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
MCOperand_CreateImm0(Inst, offset);
IsLoad = fieldFromInstruction(insn, 22, 1) != 0;
IsIndexed = fieldFromInstruction(insn, 10, 2) != 0;
IsFP = fieldFromInstruction(insn, 26, 1) != 0;
// Cannot write back to a transfer register (but xzr != sp).
if (IsLoad && IsIndexed && !IsFP && Rn != 31 && Rt == Rn)
return SoftFail;
return Success;
}
static DecodeStatus DecodeExclusiveLdStInstruction(MCInst *Inst,
uint32_t insn, uint64_t Addr,
void *Decoder)
{
unsigned Rt = fieldFromInstruction(insn, 0, 5);
unsigned Rn = fieldFromInstruction(insn, 5, 5);
unsigned Rt2 = fieldFromInstruction(insn, 10, 5);
unsigned Rs = fieldFromInstruction(insn, 16, 5);
unsigned Opcode = MCInst_getOpcode(Inst);
switch (Opcode) {
default:
return Fail;
case AArch64_STLXRW:
case AArch64_STLXRB:
case AArch64_STLXRH:
case AArch64_STXRW:
case AArch64_STXRB:
case AArch64_STXRH:
DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder);
// FALLTHROUGH
case AArch64_LDARW:
case AArch64_LDARB:
case AArch64_LDARH:
case AArch64_LDAXRW:
case AArch64_LDAXRB:
case AArch64_LDAXRH:
case AArch64_LDXRW:
case AArch64_LDXRB:
case AArch64_LDXRH:
case AArch64_STLRW:
case AArch64_STLRB:
case AArch64_STLRH:
DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_STLXRX:
case AArch64_STXRX:
DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder);
// FALLTHROUGH
case AArch64_LDARX:
case AArch64_LDAXRX:
case AArch64_LDXRX:
case AArch64_STLRX:
DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_STLXPW:
case AArch64_STXPW:
DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder);
// FALLTHROUGH
case AArch64_LDAXPW:
case AArch64_LDXPW:
DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
DecodeGPR32RegisterClass(Inst, Rt2, Addr, Decoder);
break;
case AArch64_STLXPX:
case AArch64_STXPX:
DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder);
// FALLTHROUGH
case AArch64_LDAXPX:
case AArch64_LDXPX:
DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
DecodeGPR64RegisterClass(Inst, Rt2, Addr, Decoder);
break;
}
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
// You shouldn't load to the same register twice in an instruction...
if ((Opcode == AArch64_LDAXPW || Opcode == AArch64_LDXPW ||
Opcode == AArch64_LDAXPX || Opcode == AArch64_LDXPX) &&
Rt == Rt2)
return SoftFail;
return Success;
}
static DecodeStatus DecodePairLdStInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
void *Decoder)
{
unsigned Rt = fieldFromInstruction(insn, 0, 5);
unsigned Rn = fieldFromInstruction(insn, 5, 5);
unsigned Rt2 = fieldFromInstruction(insn, 10, 5);
int32_t offset = fieldFromInstruction(insn, 15, 7);
bool IsLoad = fieldFromInstruction(insn, 22, 1) != 0;
unsigned Opcode = MCInst_getOpcode(Inst);
bool NeedsDisjointWritebackTransfer = false;
// offset is a 7-bit signed immediate, so sign extend it to
// fill the unsigned.
if (offset & (1 << (7 - 1)))
offset |= ~((1LL << 7) - 1);
// First operand is always writeback of base register.
switch (Opcode) {
default:
break;
case AArch64_LDPXpost:
case AArch64_STPXpost:
case AArch64_LDPSWpost:
case AArch64_LDPXpre:
case AArch64_STPXpre:
case AArch64_LDPSWpre:
case AArch64_LDPWpost:
case AArch64_STPWpost:
case AArch64_LDPWpre:
case AArch64_STPWpre:
case AArch64_LDPQpost:
case AArch64_STPQpost:
case AArch64_LDPQpre:
case AArch64_STPQpre:
case AArch64_LDPDpost:
case AArch64_STPDpost:
case AArch64_LDPDpre:
case AArch64_STPDpre:
case AArch64_LDPSpost:
case AArch64_STPSpost:
case AArch64_LDPSpre:
case AArch64_STPSpre:
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
break;
}
switch (Opcode) {
default:
return Fail;
case AArch64_LDPXpost:
case AArch64_STPXpost:
case AArch64_LDPSWpost:
case AArch64_LDPXpre:
case AArch64_STPXpre:
case AArch64_LDPSWpre:
NeedsDisjointWritebackTransfer = true;
// Fallthrough
case AArch64_LDNPXi:
case AArch64_STNPXi:
case AArch64_LDPXi:
case AArch64_STPXi:
case AArch64_LDPSWi:
DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
DecodeGPR64RegisterClass(Inst, Rt2, Addr, Decoder);
break;
case AArch64_LDPWpost:
case AArch64_STPWpost:
case AArch64_LDPWpre:
case AArch64_STPWpre:
NeedsDisjointWritebackTransfer = true;
// Fallthrough
case AArch64_LDNPWi:
case AArch64_STNPWi:
case AArch64_LDPWi:
case AArch64_STPWi:
DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
DecodeGPR32RegisterClass(Inst, Rt2, Addr, Decoder);
break;
case AArch64_LDNPQi:
case AArch64_STNPQi:
case AArch64_LDPQpost:
case AArch64_STPQpost:
case AArch64_LDPQi:
case AArch64_STPQi:
case AArch64_LDPQpre:
case AArch64_STPQpre:
DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder);
DecodeFPR128RegisterClass(Inst, Rt2, Addr, Decoder);
break;
case AArch64_LDNPDi:
case AArch64_STNPDi:
case AArch64_LDPDpost:
case AArch64_STPDpost:
case AArch64_LDPDi:
case AArch64_STPDi:
case AArch64_LDPDpre:
case AArch64_STPDpre:
DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder);
DecodeFPR64RegisterClass(Inst, Rt2, Addr, Decoder);
break;
case AArch64_LDNPSi:
case AArch64_STNPSi:
case AArch64_LDPSpost:
case AArch64_STPSpost:
case AArch64_LDPSi:
case AArch64_STPSi:
case AArch64_LDPSpre:
case AArch64_STPSpre:
DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder);
DecodeFPR32RegisterClass(Inst, Rt2, Addr, Decoder);
break;
}
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
MCOperand_CreateImm0(Inst, offset);
// You shouldn't load to the same register twice in an instruction...
if (IsLoad && Rt == Rt2)
return SoftFail;
// ... or do any operation that writes-back to a transfer register. But note
// that "stp xzr, xzr, [sp], #4" is fine because xzr and sp are different.
if (NeedsDisjointWritebackTransfer && Rn != 31 && (Rt == Rn || Rt2 == Rn))
return SoftFail;
return Success;
}
static DecodeStatus DecodeAddSubERegInstruction(MCInst *Inst,
uint32_t insn, uint64_t Addr,
void *Decoder)
{
unsigned Rd, Rn, Rm;
unsigned extend = fieldFromInstruction(insn, 10, 6);
unsigned shift = extend & 0x7;
if (shift > 4)
return Fail;
Rd = fieldFromInstruction(insn, 0, 5);
Rn = fieldFromInstruction(insn, 5, 5);
Rm = fieldFromInstruction(insn, 16, 5);
switch (MCInst_getOpcode(Inst)) {
default:
return Fail;
case AArch64_ADDWrx:
case AArch64_SUBWrx:
DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder);
DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder);
break;
case AArch64_ADDSWrx:
case AArch64_SUBSWrx:
DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder);
DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder);
break;
case AArch64_ADDXrx:
case AArch64_SUBXrx:
DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder);
break;
case AArch64_ADDSXrx:
case AArch64_SUBSXrx:
DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder);
break;
case AArch64_ADDXrx64:
case AArch64_SUBXrx64:
DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder);
break;
case AArch64_SUBSXrx64:
case AArch64_ADDSXrx64:
DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder);
break;
}
MCOperand_CreateImm0(Inst, extend);
return Success;
}
static DecodeStatus DecodeLogicalImmInstruction(MCInst *Inst,
uint32_t insn, uint64_t Addr,
void *Decoder)
{
unsigned Rd = fieldFromInstruction(insn, 0, 5);
unsigned Rn = fieldFromInstruction(insn, 5, 5);
unsigned Datasize = fieldFromInstruction(insn, 31, 1);
unsigned imm;
if (Datasize) {
if (MCInst_getOpcode(Inst) == AArch64_ANDSXri)
DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder);
else
DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder);
imm = fieldFromInstruction(insn, 10, 13);
if (!AArch64_AM_isValidDecodeLogicalImmediate(imm, 64))
return Fail;
} else {
if (MCInst_getOpcode(Inst) == AArch64_ANDSWri)
DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder);
else
DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR32RegisterClass(Inst, Rn, Addr, Decoder);
imm = fieldFromInstruction(insn, 10, 12);
if (!AArch64_AM_isValidDecodeLogicalImmediate(imm, 32))
return Fail;
}
MCOperand_CreateImm0(Inst, imm);
return Success;
}
static DecodeStatus DecodeModImmInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
void *Decoder)
{
unsigned Rd = fieldFromInstruction(insn, 0, 5);
unsigned cmode = fieldFromInstruction(insn, 12, 4);
unsigned imm = fieldFromInstruction(insn, 16, 3) << 5;
imm |= fieldFromInstruction(insn, 5, 5);
if (MCInst_getOpcode(Inst) == AArch64_MOVID)
DecodeFPR64RegisterClass(Inst, Rd, Addr, Decoder);
else
DecodeVectorRegisterClass(Inst, Rd, Addr, Decoder);
MCOperand_CreateImm0(Inst, imm);
switch (MCInst_getOpcode(Inst)) {
default:
break;
case AArch64_MOVIv4i16:
case AArch64_MOVIv8i16:
case AArch64_MVNIv4i16:
case AArch64_MVNIv8i16:
case AArch64_MOVIv2i32:
case AArch64_MOVIv4i32:
case AArch64_MVNIv2i32:
case AArch64_MVNIv4i32:
MCOperand_CreateImm0(Inst, (cmode & 6) << 2);
break;
case AArch64_MOVIv2s_msl:
case AArch64_MOVIv4s_msl:
case AArch64_MVNIv2s_msl:
case AArch64_MVNIv4s_msl:
MCOperand_CreateImm0(Inst, cmode & 1 ? 0x110 : 0x108);
break;
}
return Success;
}
static DecodeStatus DecodeModImmTiedInstruction(MCInst *Inst,
uint32_t insn, uint64_t Addr,
void *Decoder)
{
unsigned Rd = fieldFromInstruction(insn, 0, 5);
unsigned cmode = fieldFromInstruction(insn, 12, 4);
unsigned imm = fieldFromInstruction(insn, 16, 3) << 5;
imm |= fieldFromInstruction(insn, 5, 5);
// Tied operands added twice.
DecodeVectorRegisterClass(Inst, Rd, Addr, Decoder);
DecodeVectorRegisterClass(Inst, Rd, Addr, Decoder);
MCOperand_CreateImm0(Inst, imm);
MCOperand_CreateImm0(Inst, (cmode & 6) << 2);
return Success;
}
static DecodeStatus DecodeAdrInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr, void *Decoder)
{
unsigned Rd = fieldFromInstruction(insn, 0, 5);
int32_t imm = fieldFromInstruction(insn, 5, 19) << 2;
imm |= fieldFromInstruction(insn, 29, 2);
// Sign-extend the 21-bit immediate.
if (imm & (1 << (21 - 1)))
imm |= ~((1LL << 21) - 1);
DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder);
//if (!Dis->tryAddingSymbolicOperand(Inst, imm, Addr, Fail, 0, 4))
MCOperand_CreateImm0(Inst, imm);
return Success;
}
static DecodeStatus DecodeBaseAddSubImm(MCInst *Inst, uint32_t insn,
uint64_t Addr, void *Decoder)
{
unsigned Rd = fieldFromInstruction(insn, 0, 5);
unsigned Rn = fieldFromInstruction(insn, 5, 5);
unsigned Imm = fieldFromInstruction(insn, 10, 14);
unsigned S = fieldFromInstruction(insn, 29, 1);
unsigned Datasize = fieldFromInstruction(insn, 31, 1);
unsigned ShifterVal = (Imm >> 12) & 3;
unsigned ImmVal = Imm & 0xFFF;
if (ShifterVal != 0 && ShifterVal != 1)
return Fail;
if (Datasize) {
if (Rd == 31 && !S)
DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder);
else
DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
} else {
if (Rd == 31 && !S)
DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder);
else
DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder);
DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder);
}
//if (!Dis->tryAddingSymbolicOperand(Inst, Imm, Addr, Fail, 0, 4))
MCOperand_CreateImm0(Inst, ImmVal);
MCOperand_CreateImm0(Inst, 12 * ShifterVal);
return Success;
}
static DecodeStatus DecodeUnconditionalBranch(MCInst *Inst, uint32_t insn,
uint64_t Addr,
void *Decoder)
{
int32_t imm = fieldFromInstruction(insn, 0, 26);
// Sign-extend the 26-bit immediate.
if (imm & (1 << (26 - 1)))
imm |= ~((1LL << 26) - 1);
// if (!Dis->tryAddingSymbolicOperand(Inst, imm << 2, Addr, true, 0, 4))
MCOperand_CreateImm0(Inst, imm);
return Success;
}
static DecodeStatus DecodeSystemPStateInstruction(MCInst *Inst,
uint32_t insn, uint64_t Addr,
void *Decoder)
{
uint32_t op1 = fieldFromInstruction(insn, 16, 3);
uint32_t op2 = fieldFromInstruction(insn, 5, 3);
uint32_t crm = fieldFromInstruction(insn, 8, 4);
bool ValidNamed;
uint32_t pstate_field = (op1 << 3) | op2;
MCOperand_CreateImm0(Inst, pstate_field);
MCOperand_CreateImm0(Inst, crm);
A64NamedImmMapper_toString(&A64PState_PStateMapper, pstate_field, &ValidNamed);
return ValidNamed ? Success : Fail;
}
static DecodeStatus DecodeTestAndBranch(MCInst *Inst, uint32_t insn,
uint64_t Addr, void *Decoder)
{
uint32_t Rt = fieldFromInstruction(insn, 0, 5);
uint32_t bit = fieldFromInstruction(insn, 31, 1) << 5;
int32_t dst = fieldFromInstruction(insn, 5, 14);
bit |= fieldFromInstruction(insn, 19, 5);
// Sign-extend 14-bit immediate.
if (dst & (1 << (14 - 1)))
dst |= ~((1LL << 14) - 1);
if (fieldFromInstruction(insn, 31, 1) == 0)
DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
else
DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
MCOperand_CreateImm0(Inst, bit);
//if (!Dis->tryAddingSymbolicOperand(Inst, dst << 2, Addr, true, 0, 4))
MCOperand_CreateImm0(Inst, dst);
return Success;
}
void AArch64_init(MCRegisterInfo *MRI)
{
/*
InitMCRegisterInfo(AArch64RegDesc, 420,
RA, PC,
AArch64MCRegisterClasses, 43,
AArch64RegUnitRoots, 66, AArch64RegDiffLists,
AArch64RegStrings,
AArch64SubRegIdxLists, 53,
AArch64SubRegIdxRanges,
AArch64RegEncodingTable);
*/
MCRegisterInfo_InitMCRegisterInfo(MRI, AArch64RegDesc, 420,
0, 0,
AArch64MCRegisterClasses, 43,
0, 0, AArch64RegDiffLists,
0,
AArch64SubRegIdxLists, 53,
0);
}
#endif