1673 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1673 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-2015 */
 | |
| 
 | |
| #ifdef CAPSTONE_HAS_ARM64
 | |
| 
 | |
| #include <stdio.h>	// DEBUG
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #include "../../cs_priv.h"
 | |
| #include "../../utils.h"
 | |
| 
 | |
| #include "AArch64Disassembler.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, offsetof(cs_detail, arm64)+sizeof(cs_arm64));
 | |
| 		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) | ((uint32_t) code[0] << 24);
 | |
| 	else
 | |
| 		insn = ((uint32_t) 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)
 | |
| {
 | |
| 	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(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);
 | |
| 	int32_t offset = fieldFromInstruction(insn, 15, 7);
 | |
| 	bool IsLoad = fieldFromInstruction(insn, 22, 1) != 0;
 | |
| 	unsigned Opcode = MCInst_getOpcode(Inst);
 | |
| 	bool NeedsDisjointWritebackTransfer = false;
 | |
| 
 | |
| 	// offset is a 7-bit signed immediate, so sign extend it to
 | |
| 	// fill the unsigned.
 | |
| 	if (offset & (1 << (7 - 1)))
 | |
| 		offset |= ~((1LL << 7) - 1);
 | |
| 
 | |
| 	// First operand is always writeback of base register.
 | |
| 	switch (Opcode) {
 | |
| 		default:
 | |
| 			break;
 | |
| 		case AArch64_LDPXpost:
 | |
| 		case AArch64_STPXpost:
 | |
| 		case AArch64_LDPSWpost:
 | |
| 		case AArch64_LDPXpre:
 | |
| 		case AArch64_STPXpre:
 | |
| 		case AArch64_LDPSWpre:
 | |
| 		case AArch64_LDPWpost:
 | |
| 		case AArch64_STPWpost:
 | |
| 		case AArch64_LDPWpre:
 | |
| 		case AArch64_STPWpre:
 | |
| 		case AArch64_LDPQpost:
 | |
| 		case AArch64_STPQpost:
 | |
| 		case AArch64_LDPQpre:
 | |
| 		case AArch64_STPQpre:
 | |
| 		case AArch64_LDPDpost:
 | |
| 		case AArch64_STPDpost:
 | |
| 		case AArch64_LDPDpre:
 | |
| 		case AArch64_STPDpre:
 | |
| 		case AArch64_LDPSpost:
 | |
| 		case AArch64_STPSpost:
 | |
| 		case AArch64_LDPSpre:
 | |
| 		case AArch64_STPSpre:
 | |
| 			DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	switch (Opcode) {
 | |
| 		default:
 | |
| 			return Fail;
 | |
| 		case AArch64_LDPXpost:
 | |
| 		case AArch64_STPXpost:
 | |
| 		case AArch64_LDPSWpost:
 | |
| 		case AArch64_LDPXpre:
 | |
| 		case AArch64_STPXpre:
 | |
| 		case AArch64_LDPSWpre:
 | |
| 			NeedsDisjointWritebackTransfer = true;
 | |
| 			// Fallthrough
 | |
| 		case AArch64_LDNPXi:
 | |
| 		case AArch64_STNPXi:
 | |
| 		case AArch64_LDPXi:
 | |
| 		case AArch64_STPXi:
 | |
| 		case AArch64_LDPSWi:
 | |
| 			DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder);
 | |
| 			DecodeGPR64RegisterClass(Inst, Rt2, Addr, Decoder);
 | |
| 			break;
 | |
| 		case AArch64_LDPWpost:
 | |
| 		case AArch64_STPWpost:
 | |
| 		case AArch64_LDPWpre:
 | |
| 		case AArch64_STPWpre:
 | |
| 			NeedsDisjointWritebackTransfer = true;
 | |
| 			// Fallthrough
 | |
| 		case AArch64_LDNPWi:
 | |
| 		case AArch64_STNPWi:
 | |
| 		case AArch64_LDPWi:
 | |
| 		case AArch64_STPWi:
 | |
| 			DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder);
 | |
| 			DecodeGPR32RegisterClass(Inst, Rt2, Addr, Decoder);
 | |
| 			break;
 | |
| 		case AArch64_LDNPQi:
 | |
| 		case AArch64_STNPQi:
 | |
| 		case AArch64_LDPQpost:
 | |
| 		case AArch64_STPQpost:
 | |
| 		case AArch64_LDPQi:
 | |
| 		case AArch64_STPQi:
 | |
| 		case AArch64_LDPQpre:
 | |
| 		case AArch64_STPQpre:
 | |
| 			DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder);
 | |
| 			DecodeFPR128RegisterClass(Inst, Rt2, Addr, Decoder);
 | |
| 			break;
 | |
| 		case AArch64_LDNPDi:
 | |
| 		case AArch64_STNPDi:
 | |
| 		case AArch64_LDPDpost:
 | |
| 		case AArch64_STPDpost:
 | |
| 		case AArch64_LDPDi:
 | |
| 		case AArch64_STPDi:
 | |
| 		case AArch64_LDPDpre:
 | |
| 		case AArch64_STPDpre:
 | |
| 			DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder);
 | |
| 			DecodeFPR64RegisterClass(Inst, Rt2, Addr, Decoder);
 | |
| 			break;
 | |
| 		case AArch64_LDNPSi:
 | |
| 		case AArch64_STNPSi:
 | |
| 		case AArch64_LDPSpost:
 | |
| 		case AArch64_STPSpost:
 | |
| 		case AArch64_LDPSi:
 | |
| 		case AArch64_STPSi:
 | |
| 		case AArch64_LDPSpre:
 | |
| 		case AArch64_STPSpre:
 | |
| 			DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder);
 | |
| 			DecodeFPR32RegisterClass(Inst, Rt2, Addr, Decoder);
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder);
 | |
| 	MCOperand_CreateImm0(Inst, offset);
 | |
| 
 | |
| 	// You shouldn't load to the same register twice in an instruction...
 | |
| 	if (IsLoad && Rt == Rt2)
 | |
| 		return SoftFail;
 | |
| 
 | |
| 	// ... or do any operation that writes-back to a transfer register. But note
 | |
| 	// that "stp xzr, xzr, [sp], #4" is fine because xzr and sp are different.
 | |
| 	if (NeedsDisjointWritebackTransfer && Rn != 31 && (Rt == Rn || Rt2 == Rn))
 | |
| 		return SoftFail;
 | |
| 
 | |
| 	return Success;
 | |
| }
 | |
| 
 | |
| static DecodeStatus DecodeAddSubERegInstruction(MCInst *Inst,
 | |
| 		uint32_t insn, uint64_t Addr,
 | |
| 		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;
 | |
| 	uint64_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
 |