blob: 31248c1ef813328ffc42ff0b0a4d28abe66d5947 [file] [log] [blame]
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
/* Rot127 <unisono@quyllur.org> 2022-2023 */
/* Automatically translated source file from LLVM. */
/* LLVM-commit: <commit> */
/* LLVM-tag: <tag> */
/* Only small edits allowed. */
/* For multiple similar edits, please create a Patch for the translator. */
/* Capstone's C++ file translator: */
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
//===- AArch64Disassembler.cpp - Disassembler for AArch64 -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
#include <capstone/platform.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../../LEB128.h"
#include "../../MCDisassembler.h"
#include "../../MCFixedLenDisassembler.h"
#include "../../MCInst.h"
#include "../../MCInstrDesc.h"
#include "../../MCRegisterInfo.h"
#include "../../cs_priv.h"
#include "../../utils.h"
#include "AArch64AddressingModes.h"
#include "AArch64BaseInfo.h"
#include "AArch64DisassemblerExtension.h"
#include "AArch64Linkage.h"
#include "AArch64Mapping.h"
#define GET_INSTRINFO_MC_DESC
#include "AArch64GenInstrInfo.inc"
#define CONCAT(a, b) CONCAT_(a, b)
#define CONCAT_(a, b) a##_##b
#define DEBUG_TYPE "aarch64-disassembler"
static bool Check(DecodeStatus *Out, DecodeStatus In)
{
switch (In) {
case MCDisassembler_Success:
// Out stays the same.
return true;
case MCDisassembler_SoftFail:
*Out = In;
return true;
case MCDisassembler_Fail:
*Out = In;
return false;
default: // never reached
return false;
}
}
// Pull DecodeStatus and its enum values into the global namespace.
// 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 DecodeGPR64commonRegisterClass(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 DecodeGPR64x8ClassRegisterClass(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
DecodeMatrixIndexGPR32_8_11RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMatrixIndexGPR32_12_15RegisterClass(
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 DecodeZPRRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeZPR_4bRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeZPR_3bRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeZPR2RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeZPR3RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeZPR4RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeZPR2Mul2RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeZPR4Mul4RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeZPR2StridedRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeZPR4StridedRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
#define DECLARE_DecodeMatrixTile(NumBitsForTile) \
static DecodeStatus CONCAT(DecodeMatrixTile, NumBitsForTile)( \
MCInst * Inst, unsigned RegNo, uint64_t Address, const void *Decoder);
DECLARE_DecodeMatrixTile(2);
DECLARE_DecodeMatrixTile(3);
DECLARE_DecodeMatrixTile(1);
DECLARE_DecodeMatrixTile(4);
static DecodeStatus DecodeMatrixTileListRegisterClass(MCInst *Inst,
unsigned RegMask,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePPRRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePPR_3bRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePPR_p8to15RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePPR2RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePPR2Mul2RegisterClass(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 DecodeAuthLoadInstruction(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 DecodeAddSubImmShift(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 DecodeSystemPStateImm0_15Instruction(MCInst *Inst,
uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeSystemPStateImm0_1Instruction(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 DecodeStatus DecodeWSeqPairsClassRegisterClass(MCInst *Inst,
unsigned RegNo,
uint64_t Addr,
const void *Decoder);
static DecodeStatus DecodeXSeqPairsClassRegisterClass(MCInst *Inst,
unsigned RegNo,
uint64_t Addr,
const void *Decoder);
static DecodeStatus DecodeSyspXzrInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
const void *Decoder);
static DecodeStatus DecodeSVELogicalImmInstruction(MCInst *Inst, uint32_t insn,
uint64_t Address,
const void *Decoder);
#define DECLARE_DecodeSImm(Bits) \
static DecodeStatus CONCAT(DecodeSImm, Bits)( \
MCInst * Inst, uint64_t Imm, uint64_t Address, const void *Decoder);
DECLARE_DecodeSImm(4);
DECLARE_DecodeSImm(5);
DECLARE_DecodeSImm(6);
DECLARE_DecodeSImm(8);
DECLARE_DecodeSImm(9);
DECLARE_DecodeSImm(10);
#define DECLARE_DecodeImm8OptLsl(ElementWidth) \
static DecodeStatus CONCAT(DecodeImm8OptLsl, ElementWidth)( \
MCInst * Inst, unsigned Imm, uint64_t Addr, const void *Decoder);
DECLARE_DecodeImm8OptLsl(8);
DECLARE_DecodeImm8OptLsl(16);
DECLARE_DecodeImm8OptLsl(32);
DECLARE_DecodeImm8OptLsl(64);
static DecodeStatus DecodeSVEIncDecImm(MCInst *Inst, unsigned Imm,
uint64_t Addr, const void *Decoder);
static DecodeStatus DecodeSVCROp(MCInst *Inst, unsigned Imm, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeCPYMemOpInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
const void *Decoder);
static DecodeStatus DecodeSETMemOpInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
const void *Decoder);
static DecodeStatus DecodePRFMRegInstruction(MCInst *Inst, uint32_t insn,
uint64_t Address,
const void *Decoder);
#include "AArch64GenDisassemblerTables.inc"
#define Success MCDisassembler_Success
#define Fail MCDisassembler_Fail
#define SoftFail MCDisassembler_SoftFail
static DecodeStatus getInstruction(csh handle, const uint8_t *Bytes, size_t ByteLen,
MCInst *MI, uint16_t *Size, uint64_t Address,
void *Info)
{
*Size = 0;
// We want to read exactly 4 bytes of data.
if (ByteLen < 4)
return Fail;
*Size = 4;
// Encoded as a small-endian 32-bit word in the stream.
uint32_t Insn = readBytes32(MI, Bytes);
const uint8_t *Tables[] = {DecoderTable32, DecoderTableFallback32};
for (int i = 0; i < (sizeof(Tables) / sizeof(Tables[0])); ++i) {
void *Decoder = NULL;
DecodeStatus Result = decodeInstruction_4(Tables[i], MI, Insn, Address, Decoder);
const MCInstrDesc Desc = AArch64Insts[MCInst_getOpcode(MI)];
// For Scalable Matrix Extension (SME) instructions that have an
// implicit operand for the accumulator (ZA) or implicit immediate zero
// which isn't encoded, manually insert operand.
for (unsigned j = 0; j < Desc.NumOperands; j++) {
if (Desc.OpInfo[j].OperandType == MCOI_OPERAND_REGISTER) {
switch (Desc.OpInfo[j].RegClass) {
default:
break;
case AArch64_MPRRegClassID:
MCInst_insert0(MI, j, MCOperand_CreateReg1(MI, AArch64_ZA));
break;
case AArch64_MPR8RegClassID:
MCInst_insert0(MI, j,
MCOperand_CreateReg1(MI, AArch64_ZAB0));
break;
case AArch64_ZTRRegClassID:
MCInst_insert0(MI, j, MCOperand_CreateReg1(MI, AArch64_ZT0));
break;
}
} else if (Desc.OpInfo[j].OperandType ==
AArch64_OP_IMPLICIT_IMM_0) {
MCInst_insert0(MI, j, MCOperand_CreateImm1(MI, 0));
}
}
if (MCInst_getOpcode(MI) == AArch64_LDR_ZA ||
MCInst_getOpcode(MI) == AArch64_STR_ZA) {
// Spill and fill instructions have a single immediate used for both
// the vector select offset and optional memory offset. Replicate
// the decoded immediate.
MCOperand *Imm4Op = MCInst_getOperand(MI, (2));
MCInst_addOperand2(MI, (Imm4Op));
}
if (Result != MCDisassembler_Fail)
return Result;
}
return MCDisassembler_Fail;
}
DecodeStatus AArch64_LLVM_getInstruction(csh handle, const uint8_t *Bytes,
size_t ByteLen, MCInst *MI, uint16_t *Size, uint64_t Address,
void *Info) {
DecodeStatus Result = MCDisassembler_Fail;
Result = getInstruction(handle, Bytes, ByteLen, MI, Size, Address, Info);
MCInst_handleWriteback(MI, AArch64Insts);
return Result;
}
uint64_t suggestBytesToSkip(const uint8_t *Bytes, uint64_t Address)
{
// AArch64 instructions are always 4 bytes wide, so there's no point
// in skipping any smaller number of bytes if an instruction can't
// be decoded.
return 4;
}
static DecodeStatus DecodeFPR128RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_FPR128RegClassID].RegsBegin[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 DecodeStatus DecodeFPR64RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_FPR64RegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeFPR32RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_FPR32RegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeFPR16RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_FPR16RegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeFPR8RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_FPR8RegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeGPR64commonRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
const void *Decoder)
{
if (RegNo > 30)
return Fail;
unsigned Register = AArch64MCRegisterClasses[AArch64_GPR64commonRegClassID]
.RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeGPR64RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_GPR64RegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeGPR64x8ClassRegisterClass(MCInst *Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 22)
return Fail;
if (RegNo & 1)
return Fail;
unsigned Register = AArch64MCRegisterClasses[AArch64_GPR64x8ClassRegClassID]
.RegsBegin[RegNo >> 1];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeGPR64spRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_GPR64spRegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus
DecodeMatrixIndexGPR32_8_11RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 3)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_MatrixIndexGPR32_8_11RegClassID]
.RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus
DecodeMatrixIndexGPR32_12_15RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 3)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_MatrixIndexGPR32_12_15RegClassID]
.RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeGPR32RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_GPR32RegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeGPR32spRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_GPR32spRegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeZPRRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_ZPRRegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeZPR_4bRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 15)
return Fail;
return DecodeZPRRegisterClass(Inst, RegNo, Address, Decoder);
}
static DecodeStatus DecodeZPR_3bRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 7)
return Fail;
return DecodeZPRRegisterClass(Inst, RegNo, Address, Decoder);
}
static DecodeStatus DecodeZPR2RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_ZPR2RegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeZPR3RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_ZPR3RegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeZPR4RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_ZPR4RegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeZPR2Mul2RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo * 2 > 30)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_ZPR2RegClassID].RegsBegin[RegNo * 2];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeZPR4Mul4RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo * 4 > 28)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_ZPR4RegClassID].RegsBegin[RegNo * 4];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeZPR2StridedRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 15)
return Fail;
unsigned Register = AArch64MCRegisterClasses[AArch64_ZPR2StridedRegClassID]
.RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeZPR4StridedRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 7)
return Fail;
unsigned Register = AArch64MCRegisterClasses[AArch64_ZPR4StridedRegClassID]
.RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeMatrixTileListRegisterClass(MCInst *Inst,
unsigned RegMask,
uint64_t Address,
const void *Decoder)
{
if (RegMask > 0xFF)
return Fail;
MCOperand_CreateImm0(Inst, (RegMask));
return Success;
}
static const unsigned
MatrixZATileDecoderTable[5][16] = {
{AArch64_ZAB0},
{AArch64_ZAH0, AArch64_ZAH1},
{AArch64_ZAS0, AArch64_ZAS1, AArch64_ZAS2, AArch64_ZAS3},
{AArch64_ZAD0, AArch64_ZAD1, AArch64_ZAD2, AArch64_ZAD3, AArch64_ZAD4,
AArch64_ZAD5, AArch64_ZAD6, AArch64_ZAD7},
{AArch64_ZAQ0, AArch64_ZAQ1, AArch64_ZAQ2, AArch64_ZAQ3, AArch64_ZAQ4,
AArch64_ZAQ5, AArch64_ZAQ6, AArch64_ZAQ7, AArch64_ZAQ8, AArch64_ZAQ9,
AArch64_ZAQ10, AArch64_ZAQ11, AArch64_ZAQ12, AArch64_ZAQ13,
AArch64_ZAQ14, AArch64_ZAQ15}};
#define DEFINE_DecodeMatrixTile(NumBitsForTile) \
static DecodeStatus CONCAT(DecodeMatrixTile, NumBitsForTile)( \
MCInst * Inst, unsigned RegNo, uint64_t Address, const void *Decoder) \
{ \
unsigned LastReg = (1 << NumBitsForTile) - 1; \
if (RegNo > LastReg) \
return Fail; \
MCOperand_CreateReg0( \
Inst, (MatrixZATileDecoderTable[NumBitsForTile][RegNo])); \
return Success; \
}
DEFINE_DecodeMatrixTile(2);
DEFINE_DecodeMatrixTile(3);
DEFINE_DecodeMatrixTile(1);
DEFINE_DecodeMatrixTile(4);
static DecodeStatus DecodePPRRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 15)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_PPRRegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodePPR_3bRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
const void *Decoder)
{
if (RegNo > 7)
return Fail;
// Just reuse the PPR decode table
return DecodePPRRegisterClass(Inst, RegNo, Addr, Decoder);
}
static DecodeStatus DecodePPR_p8to15RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr,
const void *Decoder)
{
if (RegNo > 7)
return Fail;
// Just reuse the PPR decode table
return DecodePPRRegisterClass(Inst, RegNo + 8, Addr, Decoder);
}
static DecodeStatus DecodePPR2RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 15)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_PPR2RegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodePPR2Mul2RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if ((RegNo * 2) > 14)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_PPR2RegClassID].RegsBegin[RegNo * 2];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeQQRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_QQRegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeQQQRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_QQQRegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeQQQQRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_QQQQRegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeDDRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_DDRegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeDDDRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_DDDRegClassID].RegsBegin[RegNo];
MCOperand_CreateReg0(Inst, (Register));
return Success;
}
static DecodeStatus DecodeDDDDRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Addr, const void *Decoder)
{
if (RegNo > 31)
return Fail;
unsigned Register =
AArch64MCRegisterClasses[AArch64_DDDDRegClassID].RegsBegin[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);
// No symbols supported in Capstone
// if (!Decoder->tryAddingSymbolicOperand(
// Inst, ImmVal * 4, Addr, MCInst_getOpcode(Inst) != AArch64_LDRXl, 0,
// 0, 4))
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)
{
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,
const void *Decoder)
{
MCOperand_CreateImm0(Inst, (Imm));
return Success;
}
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_4(Insn, 0, 5);
unsigned Rn = fieldFromInstruction_4(Insn, 5, 5);
unsigned IsToVec = fieldFromInstruction_4(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_4(insn, 0, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
unsigned Rm = fieldFromInstruction_4(insn, 16, 5);
unsigned shiftHi = fieldFromInstruction_4(insn, 22, 2);
unsigned shiftLo = fieldFromInstruction_4(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;
// fall through
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;
// fall through
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_4(insn, 0, 5);
unsigned imm = fieldFromInstruction_4(insn, 5, 16);
unsigned shift = fieldFromInstruction_4(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_4(insn, 0, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
unsigned offset = fieldFromInstruction_4(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);
// No symbols supported in Capstone
// if (!Decoder->tryAddingSymbolicOperand(Inst, offset, Addr, Fail, 0, 0, 4))
MCOperand_CreateImm0(Inst, (offset));
return Success;
}
static DecodeStatus DecodeSignedLdStInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
const void *Decoder)
{
unsigned Rt = fieldFromInstruction_4(insn, 0, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
int64_t offset = fieldFromInstruction_4(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:
case AArch64_STLURBi:
case AArch64_STLURHi:
case AArch64_STLURWi:
case AArch64_LDAPURBi:
case AArch64_LDAPURSBWi:
case AArch64_LDAPURHi:
case AArch64_LDAPURSHWi:
case AArch64_LDAPURi:
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:
case AArch64_LDAPURSWi:
case AArch64_LDAPURSHXi:
case AArch64_LDAPURSBXi:
case AArch64_STLURXi:
case AArch64_LDAPURXi:
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));
bool IsLoad = fieldFromInstruction_4(insn, 22, 1);
bool IsIndexed = fieldFromInstruction_4(insn, 10, 2) != 0;
bool IsFP = fieldFromInstruction_4(insn, 26, 1);
// 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_4(insn, 0, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
unsigned Rt2 = fieldFromInstruction_4(insn, 10, 5);
unsigned Rs = fieldFromInstruction_4(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);
// fall through
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:
case AArch64_STLLRW:
case AArch64_STLLRB:
case AArch64_STLLRH:
case AArch64_LDLARW:
case AArch64_LDLARB:
case AArch64_LDLARH:
DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_STLXRX:
case AArch64_STXRX:
DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder);
// fall through
case AArch64_LDARX:
case AArch64_LDAXRX:
case AArch64_LDXRX:
case AArch64_STLRX:
case AArch64_LDLARX:
case AArch64_STLLRX:
DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
break;
case AArch64_STLXPW:
case AArch64_STXPW:
DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder);
// fall through
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);
// fall through
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_4(insn, 0, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
unsigned Rt2 = fieldFromInstruction_4(insn, 10, 5);
int64_t offset = fieldFromInstruction_4(insn, 15, 7);
bool IsLoad = fieldFromInstruction_4(insn, 22, 1);
// offset is a 7-bit signed immediate, so sign extend it to
// fill the unsigned.
if (offset & (1 << (7 - 1)))
offset |= ~((1LL << 7) - 1);
unsigned Opcode = MCInst_getOpcode(Inst);
bool NeedsDisjointWritebackTransfer = false;
// 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:
case AArch64_STGPpre:
case AArch64_STGPpost:
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:
case AArch64_STGPpre:
case AArch64_STGPpost:
NeedsDisjointWritebackTransfer = true;
// fall through
case AArch64_LDNPXi:
case AArch64_STNPXi:
case AArch64_LDPXi:
case AArch64_STPXi:
case AArch64_LDPSWi:
case AArch64_STGPi:
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;
// fall through
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 DecodeAuthLoadInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
const void *Decoder)
{
unsigned Rt = fieldFromInstruction_4(insn, 0, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
uint64_t offset = fieldFromInstruction_4(insn, 22, 1) << 9 |
fieldFromInstruction_4(insn, 12, 9);
unsigned writeback = fieldFromInstruction_4(insn, 11, 1);
switch (MCInst_getOpcode(Inst)) {
default:
return Fail;
case AArch64_LDRAAwriteback:
case AArch64_LDRABwriteback:
DecodeGPR64spRegisterClass(Inst, Rn /* writeback register */, Addr,
Decoder);
break;
case AArch64_LDRAAindexed:
case AArch64_LDRABindexed:
break;
}
DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
CONCAT(DecodeSImm, 10)(Inst, offset, Addr, Decoder);
if (writeback && Rt == Rn && Rn != 31) {
return SoftFail;
}
return Success;
}
static DecodeStatus DecodeAddSubERegInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
const void *Decoder)
{
unsigned Rd = fieldFromInstruction_4(insn, 0, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
unsigned Rm = fieldFromInstruction_4(insn, 16, 5);
unsigned extend = fieldFromInstruction_4(insn, 10, 6);
unsigned shift = extend & 0x7;
if (shift > 4)
return Fail;
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_4(insn, 0, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
unsigned Datasize = fieldFromInstruction_4(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_4(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_4(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_4(insn, 0, 5);
unsigned cmode = fieldFromInstruction_4(insn, 12, 4);
unsigned imm = fieldFromInstruction_4(insn, 16, 3) << 5;
imm |= fieldFromInstruction_4(insn, 5, 5);
if (MCInst_getOpcode(Inst) == AArch64_MOVID)
DecodeFPR64RegisterClass(Inst, Rd, Addr, Decoder);
else
DecodeFPR128RegisterClass(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_4(insn, 0, 5);
unsigned cmode = fieldFromInstruction_4(insn, 12, 4);
unsigned imm = fieldFromInstruction_4(insn, 16, 3) << 5;
imm |= fieldFromInstruction_4(insn, 5, 5);
// Tied operands added twice.
DecodeFPR128RegisterClass(Inst, Rd, Addr, Decoder);
DecodeFPR128RegisterClass(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_4(insn, 0, 5);
int64_t imm = fieldFromInstruction_4(insn, 5, 19) << 2;
imm |= fieldFromInstruction_4(insn, 29, 2);
// Sign-extend the 21-bit immediate.
if (imm & (1 << (21 - 1)))
imm |= ~((1LL << 21) - 1);
DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder);
// No symbols supported in Capstone
// if (!Decoder->tryAddingSymbolicOperand(Inst, imm, Addr, Fail, 0, 0, 4))
MCOperand_CreateImm0(Inst, (imm));
return Success;
}
static DecodeStatus DecodeAddSubImmShift(MCInst *Inst, uint32_t insn,
uint64_t Addr, const void *Decoder)
{
unsigned Rd = fieldFromInstruction_4(insn, 0, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
unsigned Imm = fieldFromInstruction_4(insn, 10, 14);
unsigned S = fieldFromInstruction_4(insn, 29, 1);
unsigned Datasize = fieldFromInstruction_4(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);
}
// No symbols supported in Capstone
// if (!Decoder->tryAddingSymbolicOperand(Inst, Imm, Addr, Fail, 0, 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_4(insn, 0, 26);
// Sign-extend the 26-bit immediate.
if (imm & (1 << (26 - 1)))
imm |= ~((1LL << 26) - 1);
// No symbols supported in Capstone
// if (!Decoder->tryAddingSymbolicOperand(Inst, imm * 4, Addr, true, 0, 0, 4))
MCOperand_CreateImm0(Inst, (imm));
return Success;
}
static bool isInvalidPState(uint64_t Op1, uint64_t Op2)
{
return Op1 == 0 && (Op2 == 0 || // CFINV
Op2 == 1 || // XAFlag
Op2 == 2); // AXFlag
}
static DecodeStatus DecodeSystemPStateImm0_15Instruction(MCInst *Inst,
uint32_t insn,
uint64_t Addr,
const void *Decoder)
{
uint64_t op1 = fieldFromInstruction_4(insn, 16, 3);
uint64_t op2 = fieldFromInstruction_4(insn, 5, 3);
uint64_t imm = fieldFromInstruction_4(insn, 8, 4);
uint64_t pstate_field = (op1 << 3) | op2;
if (isInvalidPState(op1, op2))
return Fail;
MCOperand_CreateImm0(Inst, (pstate_field));
MCOperand_CreateImm0(Inst, (imm));
const AArch64PState_PStateImm0_15 *PState = AArch64PState_lookupPStateImm0_15ByEncoding(pstate_field);
if (PState &&
AArch64_testFeatureList(Inst->csh->mode, PState->FeaturesRequired))
return Success;
return Fail;
}
static DecodeStatus DecodeSystemPStateImm0_1Instruction(MCInst *Inst,
uint32_t insn,
uint64_t Addr,
const void *Decoder)
{
uint64_t op1 = fieldFromInstruction_4(insn, 16, 3);
uint64_t op2 = fieldFromInstruction_4(insn, 5, 3);
uint64_t crm_high = fieldFromInstruction_4(insn, 9, 3);
uint64_t imm = fieldFromInstruction_4(insn, 8, 1);
uint64_t pstate_field = (crm_high << 6) | (op1 << 3) | op2;
if (isInvalidPState(op1, op2))
return Fail;
MCOperand_CreateImm0(Inst, (pstate_field));
MCOperand_CreateImm0(Inst, (imm));
const AArch64PState_PStateImm0_1 *PState = AArch64PState_lookupPStateImm0_1ByEncoding(pstate_field);
if (PState &&
AArch64_testFeatureList(Inst->csh->mode, PState->FeaturesRequired))
return Success;
return Fail;
}
static DecodeStatus DecodeTestAndBranch(MCInst *Inst, uint32_t insn,
uint64_t Addr, const void *Decoder)
{
uint64_t Rt = fieldFromInstruction_4(insn, 0, 5);
uint64_t bit = fieldFromInstruction_4(insn, 31, 1) << 5;
bit |= fieldFromInstruction_4(insn, 19, 5);
int64_t dst = fieldFromInstruction_4(insn, 5, 14);
// Sign-extend 14-bit immediate.
if (dst & (1 << (14 - 1)))
dst |= ~((1LL << 14) - 1);
if (fieldFromInstruction_4(insn, 31, 1) == 0)
DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
else
DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
MCOperand_CreateImm0(Inst, (bit));
// No symbols supported in Capstone
// if (!Decoder->tryAddingSymbolicOperand(Inst, dst * 4, Addr, true, 0, 0, 4))
MCOperand_CreateImm0(Inst, (dst));
return Success;
}
static DecodeStatus DecodeGPRSeqPairsClassRegisterClass(MCInst *Inst,
unsigned RegClassID,
unsigned RegNo,
uint64_t Addr,
const void *Decoder)
{
// Register number must be even (see CASP instruction)
if (RegNo & 0x1)
return Fail;
unsigned Reg = AArch64MCRegisterClasses[RegClassID].RegsBegin[RegNo / 2];
MCOperand_CreateReg0(Inst, (Reg));
return Success;
}
static DecodeStatus DecodeWSeqPairsClassRegisterClass(MCInst *Inst,
unsigned RegNo,
uint64_t Addr,
const void *Decoder)
{
return DecodeGPRSeqPairsClassRegisterClass(
Inst, AArch64_WSeqPairsClassRegClassID, RegNo, Addr, Decoder);
}
static DecodeStatus DecodeXSeqPairsClassRegisterClass(MCInst *Inst,
unsigned RegNo,
uint64_t Addr,
const void *Decoder)
{
return DecodeGPRSeqPairsClassRegisterClass(
Inst, AArch64_XSeqPairsClassRegClassID, RegNo, Addr, Decoder);
}
static DecodeStatus DecodeSyspXzrInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr, const void *Decoder)
{
unsigned op1 = fieldFromInstruction_4(insn, 16, 3);
unsigned CRn = fieldFromInstruction_4(insn, 12, 4);
unsigned CRm = fieldFromInstruction_4(insn, 8, 4);
unsigned op2 = fieldFromInstruction_4(insn, 5, 3);
unsigned Rt = fieldFromInstruction_4(insn, 0, 5);
if (Rt != 0x1f)
return Fail;
MCOperand_CreateImm0(Inst, (op1));
MCOperand_CreateImm0(Inst, (CRn));
MCOperand_CreateImm0(Inst, (CRm));
MCOperand_CreateImm0(Inst, (op2));
DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
return Success;
}
static DecodeStatus DecodeSVELogicalImmInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
const void *Decoder)
{
unsigned Zdn = fieldFromInstruction_4(insn, 0, 5);
unsigned imm = fieldFromInstruction_4(insn, 5, 13);
if (!AArch64_AM_isValidDecodeLogicalImmediate(imm, 64))
return Fail;
// The same (tied) operand is added twice to the instruction.
DecodeZPRRegisterClass(Inst, Zdn, Addr, Decoder);
if (MCInst_getOpcode(Inst) != AArch64_DUPM_ZI)
DecodeZPRRegisterClass(Inst, Zdn, Addr, Decoder);
MCOperand_CreateImm0(Inst, (imm));
return Success;
}
#define DEFINE_DecodeSImm(Bits) \
static DecodeStatus CONCAT(DecodeSImm, Bits)( \
MCInst * Inst, uint64_t Imm, uint64_t Address, const void *Decoder) \
{ \
if (Imm & ~((1LL << Bits) - 1)) \
return Fail; \
\
if (Imm & (1 << (Bits - 1))) \
Imm |= ~((1LL << Bits) - 1); \
\
MCOperand_CreateImm0(Inst, (Imm)); \
return Success; \
}
DEFINE_DecodeSImm(4);
DEFINE_DecodeSImm(5);
DEFINE_DecodeSImm(6);
DEFINE_DecodeSImm(8);
DEFINE_DecodeSImm(9);
DEFINE_DecodeSImm(10);
// Decode 8-bit signed/unsigned immediate for a given element width.
#define DEFINE_DecodeImm8OptLsl(ElementWidth) \
static DecodeStatus CONCAT(DecodeImm8OptLsl, ElementWidth)( \
MCInst * Inst, unsigned Imm, uint64_t Addr, const void *Decoder) \
{ \
unsigned Val = (uint8_t)Imm; \
unsigned Shift = (Imm & 0x100) ? 8 : 0; \
if (ElementWidth == 8 && Shift) \
return Fail; \
MCOperand_CreateImm0(Inst, (Val)); \
MCOperand_CreateImm0(Inst, (Shift)); \
return Success; \
}
DEFINE_DecodeImm8OptLsl(8);
DEFINE_DecodeImm8OptLsl(16);
DEFINE_DecodeImm8OptLsl(32);
DEFINE_DecodeImm8OptLsl(64);
// Decode uimm4 ranged from 1-16.
static DecodeStatus DecodeSVEIncDecImm(MCInst *Inst, unsigned Imm,
uint64_t Addr, const void *Decoder)
{
MCOperand_CreateImm0(Inst, (Imm + 1));
return Success;
}
static DecodeStatus DecodeSVCROp(MCInst *Inst, unsigned Imm, uint64_t Address,
const void *Decoder)
{
if (AArch64SVCR_lookupSVCRByEncoding(Imm)) {
MCOperand_CreateImm0(Inst, (Imm));
return Success;
}
return Fail;
}
static DecodeStatus DecodeCPYMemOpInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
const void *Decoder)
{
unsigned Rd = fieldFromInstruction_4(insn, 0, 5);
unsigned Rs = fieldFromInstruction_4(insn, 16, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
// None of the registers may alias: if they do, then the instruction is not
// merely unpredictable but actually entirely unallocated.
if (Rd == Rs || Rs == Rn || Rd == Rn)
return MCDisassembler_Fail;
// All three register operands are written back, so they all appear
// twice in the operand list, once as outputs and once as inputs.
if (!DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) ||
!DecodeGPR64commonRegisterClass(Inst, Rs, Addr, Decoder) ||
!DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder) ||
!DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) ||
!DecodeGPR64commonRegisterClass(Inst, Rs, Addr, Decoder) ||
!DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder))
return MCDisassembler_Fail;
return MCDisassembler_Success;
}
static DecodeStatus DecodeSETMemOpInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr,
const void *Decoder)
{
unsigned Rd = fieldFromInstruction_4(insn, 0, 5);
unsigned Rm = fieldFromInstruction_4(insn, 16, 5);
unsigned Rn = fieldFromInstruction_4(insn, 5, 5);
// None of the registers may alias: if they do, then the instruction is not
// merely unpredictable but actually entirely unallocated.
if (Rd == Rm || Rm == Rn || Rd == Rn)
return MCDisassembler_Fail;
// Rd and Rn (not Rm) register operands are written back, so they appear
// twice in the operand list, once as outputs and once as inputs.
if (!DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) ||
!DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder) ||
!DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) ||
!DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder) ||
!DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder))
return MCDisassembler_Fail;
return MCDisassembler_Success;
}
static DecodeStatus DecodePRFMRegInstruction(MCInst *Inst, uint32_t insn,
uint64_t Addr, const void *Decoder)
{
// PRFM with Rt = '11xxx' should be decoded as RPRFM.
// Fail to decode and defer to fallback decoder table to decode RPRFM.
unsigned Mask = 0x18;
uint64_t Rt = fieldFromInstruction_4(insn, 0, 5);
if ((Rt & Mask) == Mask)
return Fail;
uint64_t Rn = fieldFromInstruction_4(insn, 5, 5);
uint64_t Shift = fieldFromInstruction_4(insn, 12, 1);
uint64_t Extend = fieldFromInstruction_4(insn, 15, 1);
uint64_t Rm = fieldFromInstruction_4(insn, 16, 5);
MCOperand_CreateImm0(Inst, (Rt));
DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
switch (MCInst_getOpcode(Inst)) {
default:
return Fail;
case AArch64_PRFMroW:
DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder);
break;
case AArch64_PRFMroX:
DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder);
break;
}
DecodeMemExtend(Inst, (Extend << 1) | Shift, Addr, Decoder);
return Success;
}