1680 lines
48 KiB
C
1680 lines
48 KiB
C
//===- 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-2014 */
|
|
|
|
#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,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeFPR128_loRegisterClass(MCInst *Inst,
|
|
unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeFPR64RegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeFPR32RegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeFPR16RegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeFPR8RegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeGPR64RegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeGPR64spRegisterClass(MCInst *Inst,
|
|
unsigned RegNo, uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeGPR32RegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeGPR32spRegisterClass(MCInst *Inst,
|
|
unsigned RegNo, uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeQQRegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeQQQRegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeQQQQRegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeDDRegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeDDDRegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeDDDDRegisterClass(MCInst *Inst, unsigned RegNo,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
|
|
static DecodeStatus DecodeFixedPointScaleImm32(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeFixedPointScaleImm64(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodePCRelLabel19(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address, const void *Decoder);
|
|
static DecodeStatus DecodeMemExtend(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address, const void *Decoder);
|
|
static DecodeStatus DecodeMRSSystemRegister(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address, const void *Decoder);
|
|
static DecodeStatus DecodeMSRSystemRegister(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address, const void *Decoder);
|
|
static DecodeStatus DecodeThreeAddrSRegInstruction(MCInst *Inst,
|
|
uint32_t insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeMoveImmInstruction(MCInst *Inst, uint32_t insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeUnsignedLdStInstruction(MCInst *Inst,
|
|
uint32_t insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeSignedLdStInstruction(MCInst *Inst,
|
|
uint32_t insn, uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeExclusiveLdStInstruction(MCInst *Inst,
|
|
uint32_t insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodePairLdStInstruction(MCInst *Inst, uint32_t insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeAddSubERegInstruction(MCInst *Inst,
|
|
uint32_t insn, uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeLogicalImmInstruction(MCInst *Inst,
|
|
uint32_t insn, uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeModImmInstruction(MCInst *Inst, uint32_t insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeModImmTiedInstruction(MCInst *Inst,
|
|
uint32_t insn, uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeAdrInstruction(MCInst *Inst, uint32_t insn,
|
|
uint64_t Address, const void *Decoder);
|
|
static DecodeStatus DecodeBaseAddSubImm(MCInst *Inst, uint32_t insn,
|
|
uint64_t Address, const void *Decoder);
|
|
static DecodeStatus DecodeUnconditionalBranch(MCInst *Inst, uint32_t insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeSystemPStateInstruction(MCInst *Inst,
|
|
uint32_t insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeTestAndBranch(MCInst *Inst, uint32_t insn,
|
|
uint64_t Address, const void *Decoder);
|
|
|
|
static DecodeStatus DecodeFMOVLaneInstruction(MCInst *Inst, unsigned Insn,
|
|
uint64_t Address,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftR64Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftR64ImmNarrow(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftR32Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftR32ImmNarrow(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftR16Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftR16ImmNarrow(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr,
|
|
const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftR8Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftL64Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftL32Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftL16Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder);
|
|
static DecodeStatus DecodeVecShiftL8Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const 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 (MODE_IS_BIG_ENDIAN(ud->mode))
|
|
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,
|
|
const 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,
|
|
const 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,
|
|
const 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,
|
|
const 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,
|
|
const 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,
|
|
const 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,
|
|
const 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,
|
|
const 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,
|
|
const 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,
|
|
const 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,
|
|
const 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, const 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, const 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,
|
|
const 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, const 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, const 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,
|
|
const 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,
|
|
const 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,
|
|
const void *Decoder)
|
|
{
|
|
MCOperand_CreateImm0(Inst, 64 - Imm);
|
|
return Success;
|
|
}
|
|
|
|
static DecodeStatus DecodePCRelLabel19(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const 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, const 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, const void *Decoder)
|
|
{
|
|
bool ValidNamed;
|
|
char result[128];
|
|
|
|
Imm |= 0x8000;
|
|
MCOperand_CreateImm0(Inst, Imm);
|
|
|
|
A64SysRegMapper_toString(&AArch64_MRSMapper, Imm, &ValidNamed, result);
|
|
|
|
return ValidNamed ? Success : Fail;
|
|
}
|
|
|
|
static DecodeStatus DecodeMSRSystemRegister(MCInst *Inst, unsigned Imm,
|
|
uint64_t Address,
|
|
const void *Decoder)
|
|
{
|
|
bool ValidNamed;
|
|
char result[128];
|
|
|
|
Imm |= 0x8000;
|
|
MCOperand_CreateImm0(Inst, Imm);
|
|
|
|
A64SysRegMapper_toString(&AArch64_MSRMapper, Imm, &ValidNamed, result);
|
|
|
|
return ValidNamed ? Success : Fail;
|
|
}
|
|
|
|
static DecodeStatus DecodeFMOVLaneInstruction(MCInst *Inst, unsigned Insn,
|
|
uint64_t Address,
|
|
const 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, const void *Decoder)
|
|
{
|
|
return DecodeVecShiftRImm(Inst, Imm, 64);
|
|
}
|
|
|
|
static DecodeStatus DecodeVecShiftR64ImmNarrow(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr,
|
|
const void *Decoder)
|
|
{
|
|
return DecodeVecShiftRImm(Inst, Imm | 0x20, 64);
|
|
}
|
|
|
|
static DecodeStatus DecodeVecShiftR32Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder)
|
|
{
|
|
return DecodeVecShiftRImm(Inst, Imm, 32);
|
|
}
|
|
|
|
static DecodeStatus DecodeVecShiftR32ImmNarrow(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr,
|
|
const void *Decoder)
|
|
{
|
|
return DecodeVecShiftRImm(Inst, Imm | 0x10, 32);
|
|
}
|
|
|
|
static DecodeStatus DecodeVecShiftR16Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder)
|
|
{
|
|
return DecodeVecShiftRImm(Inst, Imm, 16);
|
|
}
|
|
|
|
static DecodeStatus DecodeVecShiftR16ImmNarrow(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr,
|
|
const void *Decoder)
|
|
{
|
|
return DecodeVecShiftRImm(Inst, Imm | 0x8, 16);
|
|
}
|
|
|
|
static DecodeStatus DecodeVecShiftR8Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder)
|
|
{
|
|
return DecodeVecShiftRImm(Inst, Imm, 8);
|
|
}
|
|
|
|
static DecodeStatus DecodeVecShiftL64Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder)
|
|
{
|
|
return DecodeVecShiftLImm(Inst, Imm, 64);
|
|
}
|
|
|
|
static DecodeStatus DecodeVecShiftL32Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder)
|
|
{
|
|
return DecodeVecShiftLImm(Inst, Imm, 32);
|
|
}
|
|
|
|
static DecodeStatus DecodeVecShiftL16Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder)
|
|
{
|
|
return DecodeVecShiftLImm(Inst, Imm, 16);
|
|
}
|
|
|
|
static DecodeStatus DecodeVecShiftL8Imm(MCInst *Inst, unsigned Imm,
|
|
uint64_t Addr, const void *Decoder)
|
|
{
|
|
return DecodeVecShiftLImm(Inst, Imm, 8);
|
|
}
|
|
|
|
static DecodeStatus DecodeThreeAddrSRegInstruction(MCInst *Inst,
|
|
uint32_t insn, uint64_t Addr,
|
|
const 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,
|
|
const 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,
|
|
const 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,
|
|
const void *Decoder)
|
|
{
|
|
bool IsLoad;
|
|
bool IsIndexed;
|
|
bool IsFP;
|
|
unsigned Rt = fieldFromInstruction(insn, 0, 5);
|
|
unsigned Rn = fieldFromInstruction(insn, 5, 5);
|
|
int64_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,
|
|
const 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,
|
|
const void *Decoder)
|
|
{
|
|
unsigned Rt = fieldFromInstruction(insn, 0, 5);
|
|
unsigned Rn = fieldFromInstruction(insn, 5, 5);
|
|
unsigned Rt2 = fieldFromInstruction(insn, 10, 5);
|
|
int64_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,
|
|
const 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,
|
|
const 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,
|
|
const 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,
|
|
const 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, const void *Decoder)
|
|
{
|
|
unsigned Rd = fieldFromInstruction(insn, 0, 5);
|
|
int64_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, const 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,
|
|
const void *Decoder)
|
|
{
|
|
int64_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,
|
|
const 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, const void *Decoder)
|
|
{
|
|
uint32_t Rt = fieldFromInstruction(insn, 0, 5);
|
|
uint32_t bit = fieldFromInstruction(insn, 31, 1) << 5;
|
|
uint32_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
|