1249259Sdim//===- AArch64Disassembler.cpp - Disassembler for AArch64 ISA -------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file contains the functions necessary to decode AArch64 instruction 11249259Sdim// bitpatterns into MCInsts (with the help of TableGenerated information from 12249259Sdim// the instruction definitions). 13249259Sdim// 14249259Sdim//===----------------------------------------------------------------------===// 15249259Sdim 16249259Sdim#define DEBUG_TYPE "arm-disassembler" 17249259Sdim 18249259Sdim#include "AArch64.h" 19249259Sdim#include "AArch64RegisterInfo.h" 20249259Sdim#include "AArch64Subtarget.h" 21249259Sdim#include "Utils/AArch64BaseInfo.h" 22249259Sdim#include "llvm/MC/MCInst.h" 23249259Sdim#include "llvm/MC/MCInstrDesc.h" 24249259Sdim#include "llvm/MC/MCExpr.h" 25249259Sdim#include "llvm/MC/MCContext.h" 26249259Sdim#include "llvm/MC/MCDisassembler.h" 27249259Sdim#include "llvm/MC/MCFixedLenDisassembler.h" 28249259Sdim#include "llvm/Support/Debug.h" 29249259Sdim#include "llvm/Support/MemoryObject.h" 30249259Sdim#include "llvm/Support/ErrorHandling.h" 31249259Sdim#include "llvm/Support/TargetRegistry.h" 32249259Sdim#include "llvm/Support/raw_ostream.h" 33249259Sdim 34249259Sdimusing namespace llvm; 35249259Sdim 36249259Sdimtypedef MCDisassembler::DecodeStatus DecodeStatus; 37249259Sdim 38249259Sdimnamespace { 39249259Sdim/// AArch64 disassembler for all AArch64 platforms. 40249259Sdimclass AArch64Disassembler : public MCDisassembler { 41263508Sdim OwningPtr<const MCRegisterInfo> RegInfo; 42249259Sdimpublic: 43249259Sdim /// Initializes the disassembler. 44249259Sdim /// 45249259Sdim AArch64Disassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info) 46249259Sdim : MCDisassembler(STI), RegInfo(Info) { 47249259Sdim } 48249259Sdim 49263508Sdim ~AArch64Disassembler() {} 50249259Sdim 51249259Sdim /// See MCDisassembler. 52249259Sdim DecodeStatus getInstruction(MCInst &instr, 53249259Sdim uint64_t &size, 54249259Sdim const MemoryObject ®ion, 55249259Sdim uint64_t address, 56249259Sdim raw_ostream &vStream, 57249259Sdim raw_ostream &cStream) const; 58249259Sdim 59263508Sdim const MCRegisterInfo *getRegInfo() const { return RegInfo.get(); } 60249259Sdim}; 61249259Sdim 62249259Sdim} 63249259Sdim 64249259Sdim// Forward-declarations used in the auto-generated files. 65249259Sdimstatic DecodeStatus DecodeGPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 66249259Sdim uint64_t Address, const void *Decoder); 67249259Sdimstatic DecodeStatus 68249259SdimDecodeGPR64xspRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 69249259Sdim uint64_t Address, const void *Decoder); 70249259Sdim 71249259Sdimstatic DecodeStatus DecodeGPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 72249259Sdim uint64_t Address, const void *Decoder); 73249259Sdimstatic DecodeStatus 74249259SdimDecodeGPR32wspRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 75249259Sdim uint64_t Address, const void *Decoder); 76249259Sdim 77249259Sdimstatic DecodeStatus DecodeFPR8RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 78249259Sdim uint64_t Address, const void *Decoder); 79249259Sdimstatic DecodeStatus DecodeFPR16RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 80249259Sdim uint64_t Address, const void *Decoder); 81249259Sdimstatic DecodeStatus DecodeFPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 82249259Sdim uint64_t Address, const void *Decoder); 83249259Sdimstatic DecodeStatus DecodeFPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 84249259Sdim uint64_t Address, const void *Decoder); 85263508Sdimstatic DecodeStatus DecodeFPR64LoRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 86263508Sdim uint64_t Address, const void *Decoder); 87249259Sdimstatic DecodeStatus DecodeFPR128RegisterClass(llvm::MCInst &Inst, 88249259Sdim unsigned RegNo, uint64_t Address, 89249259Sdim const void *Decoder); 90263508Sdimstatic DecodeStatus DecodeFPR128LoRegisterClass(llvm::MCInst &Inst, 91263508Sdim unsigned RegNo, uint64_t Address, 92263508Sdim const void *Decoder); 93249259Sdim 94263508Sdimstatic DecodeStatus DecodeGPR64noxzrRegisterClass(llvm::MCInst &Inst, 95263508Sdim unsigned RegNo, 96263508Sdim uint64_t Address, 97263508Sdim const void *Decoder); 98263508Sdim 99263508Sdimstatic DecodeStatus DecodeDPairRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 100263508Sdim uint64_t Address, 101263508Sdim const void *Decoder); 102263508Sdimstatic DecodeStatus DecodeQPairRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 103263508Sdim uint64_t Address, 104263508Sdim const void *Decoder); 105263508Sdimstatic DecodeStatus DecodeDTripleRegisterClass(llvm::MCInst &Inst, 106263508Sdim unsigned RegNo, uint64_t Address, 107263508Sdim const void *Decoder); 108263508Sdimstatic DecodeStatus DecodeQTripleRegisterClass(llvm::MCInst &Inst, 109263508Sdim unsigned RegNo, uint64_t Address, 110263508Sdim const void *Decoder); 111263508Sdimstatic DecodeStatus DecodeDQuadRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 112263508Sdim uint64_t Address, 113263508Sdim const void *Decoder); 114263508Sdimstatic DecodeStatus DecodeQQuadRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 115263508Sdim uint64_t Address, 116263508Sdim const void *Decoder); 117263508Sdim 118249259Sdimstatic DecodeStatus DecodeAddrRegExtendOperand(llvm::MCInst &Inst, 119249259Sdim unsigned OptionHiS, 120249259Sdim uint64_t Address, 121249259Sdim const void *Decoder); 122249259Sdim 123249259Sdim 124249259Sdimstatic DecodeStatus DecodeBitfield32ImmOperand(llvm::MCInst &Inst, 125249259Sdim unsigned Imm6Bits, 126249259Sdim uint64_t Address, 127249259Sdim const void *Decoder); 128249259Sdim 129249259Sdimstatic DecodeStatus DecodeCVT32FixedPosOperand(llvm::MCInst &Inst, 130249259Sdim unsigned Imm6Bits, 131249259Sdim uint64_t Address, 132249259Sdim const void *Decoder); 133249259Sdim 134249259Sdimstatic DecodeStatus DecodeFPZeroOperand(llvm::MCInst &Inst, 135249259Sdim unsigned RmBits, 136249259Sdim uint64_t Address, 137249259Sdim const void *Decoder); 138249259Sdim 139263508Sdimstatic DecodeStatus DecodeShiftRightImm8(MCInst &Inst, unsigned Val, 140263508Sdim uint64_t Address, const void *Decoder); 141263508Sdimstatic DecodeStatus DecodeShiftRightImm16(MCInst &Inst, unsigned Val, 142263508Sdim uint64_t Address, 143263508Sdim const void *Decoder); 144263508Sdimstatic DecodeStatus DecodeShiftRightImm32(MCInst &Inst, unsigned Val, 145263508Sdim uint64_t Address, 146263508Sdim const void *Decoder); 147263508Sdimstatic DecodeStatus DecodeShiftRightImm64(MCInst &Inst, unsigned Val, 148263508Sdim uint64_t Address, 149263508Sdim const void *Decoder); 150263508Sdim 151263508Sdimstatic DecodeStatus DecodeShiftLeftImm8(MCInst &Inst, unsigned Val, 152263508Sdim uint64_t Address, const void *Decoder); 153263508Sdimstatic DecodeStatus DecodeShiftLeftImm16(MCInst &Inst, unsigned Val, 154263508Sdim uint64_t Address, 155263508Sdim const void *Decoder); 156263508Sdimstatic DecodeStatus DecodeShiftLeftImm32(MCInst &Inst, unsigned Val, 157263508Sdim uint64_t Address, 158263508Sdim const void *Decoder); 159263508Sdimstatic DecodeStatus DecodeShiftLeftImm64(MCInst &Inst, unsigned Val, 160263508Sdim uint64_t Address, 161263508Sdim const void *Decoder); 162263508Sdim 163249259Sdimtemplate<int RegWidth> 164249259Sdimstatic DecodeStatus DecodeMoveWideImmOperand(llvm::MCInst &Inst, 165249259Sdim unsigned FullImm, 166249259Sdim uint64_t Address, 167249259Sdim const void *Decoder); 168249259Sdim 169249259Sdimtemplate<int RegWidth> 170249259Sdimstatic DecodeStatus DecodeLogicalImmOperand(llvm::MCInst &Inst, 171249259Sdim unsigned Bits, 172249259Sdim uint64_t Address, 173249259Sdim const void *Decoder); 174249259Sdim 175249259Sdimstatic DecodeStatus DecodeRegExtendOperand(llvm::MCInst &Inst, 176249259Sdim unsigned ShiftAmount, 177249259Sdim uint64_t Address, 178249259Sdim const void *Decoder); 179263508Sdimtemplate <A64SE::ShiftExtSpecifiers Ext, bool IsHalf> 180263508Sdimstatic DecodeStatus 181263508SdimDecodeNeonMovImmShiftOperand(llvm::MCInst &Inst, unsigned ShiftAmount, 182263508Sdim uint64_t Address, const void *Decoder); 183249259Sdim 184249259Sdimstatic DecodeStatus Decode32BitShiftOperand(llvm::MCInst &Inst, 185249259Sdim unsigned ShiftAmount, 186249259Sdim uint64_t Address, 187249259Sdim const void *Decoder); 188249259Sdimstatic DecodeStatus DecodeBitfieldInstruction(llvm::MCInst &Inst, unsigned Insn, 189249259Sdim uint64_t Address, 190249259Sdim const void *Decoder); 191249259Sdim 192249259Sdimstatic DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn, 193249259Sdim uint64_t Address, 194249259Sdim const void *Decoder); 195249259Sdim 196249259Sdimstatic DecodeStatus DecodeLDSTPairInstruction(llvm::MCInst &Inst, 197249259Sdim unsigned Insn, 198249259Sdim uint64_t Address, 199249259Sdim const void *Decoder); 200249259Sdim 201249259Sdimstatic DecodeStatus DecodeLoadPairExclusiveInstruction(llvm::MCInst &Inst, 202249259Sdim unsigned Val, 203249259Sdim uint64_t Address, 204249259Sdim const void *Decoder); 205249259Sdim 206249259Sdimtemplate<typename SomeNamedImmMapper> 207249259Sdimstatic DecodeStatus DecodeNamedImmOperand(llvm::MCInst &Inst, 208249259Sdim unsigned Val, 209249259Sdim uint64_t Address, 210249259Sdim const void *Decoder); 211249259Sdim 212249259Sdimstatic DecodeStatus 213249259SdimDecodeSysRegOperand(const A64SysReg::SysRegMapper &InstMapper, 214249259Sdim llvm::MCInst &Inst, unsigned Val, 215249259Sdim uint64_t Address, const void *Decoder); 216249259Sdim 217249259Sdimstatic DecodeStatus DecodeMRSOperand(llvm::MCInst &Inst, 218249259Sdim unsigned Val, 219249259Sdim uint64_t Address, 220249259Sdim const void *Decoder); 221249259Sdim 222249259Sdimstatic DecodeStatus DecodeMSROperand(llvm::MCInst &Inst, 223249259Sdim unsigned Val, 224249259Sdim uint64_t Address, 225249259Sdim const void *Decoder); 226249259Sdim 227249259Sdim 228249259Sdimstatic DecodeStatus DecodeSingleIndexedInstruction(llvm::MCInst &Inst, 229249259Sdim unsigned Val, 230249259Sdim uint64_t Address, 231249259Sdim const void *Decoder); 232249259Sdim 233263508Sdimstatic DecodeStatus DecodeVLDSTPostInstruction(MCInst &Inst, unsigned Val, 234263508Sdim uint64_t Address, 235263508Sdim const void *Decoder); 236249259Sdim 237263508Sdimstatic DecodeStatus DecodeVLDSTLanePostInstruction(MCInst &Inst, unsigned Insn, 238263508Sdim uint64_t Address, 239263508Sdim const void *Decoder); 240263508Sdim 241263508Sdimstatic DecodeStatus DecodeSHLLInstruction(MCInst &Inst, unsigned Insn, 242263508Sdim uint64_t Address, 243263508Sdim const void *Decoder); 244263508Sdim 245249259Sdimstatic bool Check(DecodeStatus &Out, DecodeStatus In); 246249259Sdim 247249259Sdim#include "AArch64GenDisassemblerTables.inc" 248249259Sdim#include "AArch64GenInstrInfo.inc" 249249259Sdim 250249259Sdimstatic bool Check(DecodeStatus &Out, DecodeStatus In) { 251249259Sdim switch (In) { 252249259Sdim case MCDisassembler::Success: 253249259Sdim // Out stays the same. 254249259Sdim return true; 255249259Sdim case MCDisassembler::SoftFail: 256249259Sdim Out = In; 257249259Sdim return true; 258249259Sdim case MCDisassembler::Fail: 259249259Sdim Out = In; 260249259Sdim return false; 261249259Sdim } 262249259Sdim llvm_unreachable("Invalid DecodeStatus!"); 263249259Sdim} 264249259Sdim 265249259SdimDecodeStatus AArch64Disassembler::getInstruction(MCInst &MI, uint64_t &Size, 266249259Sdim const MemoryObject &Region, 267249259Sdim uint64_t Address, 268249259Sdim raw_ostream &os, 269249259Sdim raw_ostream &cs) const { 270249259Sdim CommentStream = &cs; 271249259Sdim 272249259Sdim uint8_t bytes[4]; 273249259Sdim 274249259Sdim // We want to read exactly 4 bytes of data. 275263508Sdim if (Region.readBytes(Address, 4, bytes) == -1) { 276249259Sdim Size = 0; 277249259Sdim return MCDisassembler::Fail; 278249259Sdim } 279249259Sdim 280249259Sdim // Encoded as a small-endian 32-bit word in the stream. 281249259Sdim uint32_t insn = (bytes[3] << 24) | 282249259Sdim (bytes[2] << 16) | 283249259Sdim (bytes[1] << 8) | 284249259Sdim (bytes[0] << 0); 285249259Sdim 286249259Sdim // Calling the auto-generated decoder function. 287249259Sdim DecodeStatus result = decodeInstruction(DecoderTableA6432, MI, insn, Address, 288249259Sdim this, STI); 289249259Sdim if (result != MCDisassembler::Fail) { 290249259Sdim Size = 4; 291249259Sdim return result; 292249259Sdim } 293249259Sdim 294249259Sdim MI.clear(); 295249259Sdim Size = 0; 296249259Sdim return MCDisassembler::Fail; 297249259Sdim} 298249259Sdim 299249259Sdimstatic unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { 300249259Sdim const AArch64Disassembler *Dis = static_cast<const AArch64Disassembler*>(D); 301249259Sdim return Dis->getRegInfo()->getRegClass(RC).getRegister(RegNo); 302249259Sdim} 303249259Sdim 304249259Sdimstatic DecodeStatus DecodeGPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 305249259Sdim uint64_t Address, const void *Decoder) { 306249259Sdim if (RegNo > 31) 307249259Sdim return MCDisassembler::Fail; 308249259Sdim 309249259Sdim uint16_t Register = getReg(Decoder, AArch64::GPR64RegClassID, RegNo); 310249259Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 311249259Sdim return MCDisassembler::Success; 312249259Sdim} 313249259Sdim 314249259Sdimstatic DecodeStatus 315249259SdimDecodeGPR64xspRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 316249259Sdim uint64_t Address, const void *Decoder) { 317249259Sdim if (RegNo > 31) 318249259Sdim return MCDisassembler::Fail; 319249259Sdim 320249259Sdim uint16_t Register = getReg(Decoder, AArch64::GPR64xspRegClassID, RegNo); 321249259Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 322249259Sdim return MCDisassembler::Success; 323249259Sdim} 324249259Sdim 325249259Sdimstatic DecodeStatus DecodeGPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 326249259Sdim uint64_t Address, 327249259Sdim const void *Decoder) { 328249259Sdim if (RegNo > 31) 329249259Sdim return MCDisassembler::Fail; 330249259Sdim 331249259Sdim uint16_t Register = getReg(Decoder, AArch64::GPR32RegClassID, RegNo); 332249259Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 333249259Sdim return MCDisassembler::Success; 334249259Sdim} 335249259Sdim 336249259Sdimstatic DecodeStatus 337249259SdimDecodeGPR32wspRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 338249259Sdim uint64_t Address, const void *Decoder) { 339249259Sdim if (RegNo > 31) 340249259Sdim return MCDisassembler::Fail; 341249259Sdim 342249259Sdim uint16_t Register = getReg(Decoder, AArch64::GPR32wspRegClassID, RegNo); 343249259Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 344249259Sdim return MCDisassembler::Success; 345249259Sdim} 346249259Sdim 347249259Sdimstatic DecodeStatus 348249259SdimDecodeFPR8RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 349249259Sdim uint64_t Address, const void *Decoder) { 350249259Sdim if (RegNo > 31) 351249259Sdim return MCDisassembler::Fail; 352249259Sdim 353249259Sdim uint16_t Register = getReg(Decoder, AArch64::FPR8RegClassID, RegNo); 354249259Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 355249259Sdim return MCDisassembler::Success; 356249259Sdim} 357249259Sdim 358249259Sdimstatic DecodeStatus 359249259SdimDecodeFPR16RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 360249259Sdim uint64_t Address, const void *Decoder) { 361249259Sdim if (RegNo > 31) 362249259Sdim return MCDisassembler::Fail; 363249259Sdim 364249259Sdim uint16_t Register = getReg(Decoder, AArch64::FPR16RegClassID, RegNo); 365249259Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 366249259Sdim return MCDisassembler::Success; 367249259Sdim} 368249259Sdim 369249259Sdim 370249259Sdimstatic DecodeStatus 371249259SdimDecodeFPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 372249259Sdim uint64_t Address, const void *Decoder) { 373249259Sdim if (RegNo > 31) 374249259Sdim return MCDisassembler::Fail; 375249259Sdim 376249259Sdim uint16_t Register = getReg(Decoder, AArch64::FPR32RegClassID, RegNo); 377249259Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 378249259Sdim return MCDisassembler::Success; 379249259Sdim} 380249259Sdim 381249259Sdimstatic DecodeStatus 382249259SdimDecodeFPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 383249259Sdim uint64_t Address, const void *Decoder) { 384249259Sdim if (RegNo > 31) 385249259Sdim return MCDisassembler::Fail; 386249259Sdim 387249259Sdim uint16_t Register = getReg(Decoder, AArch64::FPR64RegClassID, RegNo); 388249259Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 389249259Sdim return MCDisassembler::Success; 390249259Sdim} 391249259Sdim 392263508Sdimstatic DecodeStatus 393263508SdimDecodeFPR64LoRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 394263508Sdim uint64_t Address, const void *Decoder) { 395263508Sdim if (RegNo > 15) 396263508Sdim return MCDisassembler::Fail; 397249259Sdim 398263508Sdim return DecodeFPR64RegisterClass(Inst, RegNo, Address, Decoder); 399263508Sdim} 400263508Sdim 401249259Sdimstatic DecodeStatus 402249259SdimDecodeFPR128RegisterClass(llvm::MCInst &Inst, unsigned RegNo, 403249259Sdim uint64_t Address, const void *Decoder) { 404249259Sdim if (RegNo > 31) 405249259Sdim return MCDisassembler::Fail; 406249259Sdim 407249259Sdim uint16_t Register = getReg(Decoder, AArch64::FPR128RegClassID, RegNo); 408249259Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 409249259Sdim return MCDisassembler::Success; 410249259Sdim} 411249259Sdim 412249259Sdimstatic DecodeStatus 413263508SdimDecodeFPR128LoRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 414263508Sdim uint64_t Address, const void *Decoder) { 415263508Sdim if (RegNo > 15) 416263508Sdim return MCDisassembler::Fail; 417263508Sdim 418263508Sdim return DecodeFPR128RegisterClass(Inst, RegNo, Address, Decoder); 419263508Sdim} 420263508Sdim 421263508Sdimstatic DecodeStatus DecodeGPR64noxzrRegisterClass(llvm::MCInst &Inst, 422263508Sdim unsigned RegNo, 423263508Sdim uint64_t Address, 424263508Sdim const void *Decoder) { 425263508Sdim if (RegNo > 30) 426263508Sdim return MCDisassembler::Fail; 427263508Sdim 428263508Sdim uint16_t Register = getReg(Decoder, AArch64::GPR64noxzrRegClassID, RegNo); 429263508Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 430263508Sdim return MCDisassembler::Success; 431263508Sdim} 432263508Sdim 433263508Sdimstatic DecodeStatus DecodeRegisterClassByID(llvm::MCInst &Inst, unsigned RegNo, 434263508Sdim unsigned RegID, 435263508Sdim const void *Decoder) { 436249259Sdim if (RegNo > 31) 437249259Sdim return MCDisassembler::Fail; 438249259Sdim 439263508Sdim uint16_t Register = getReg(Decoder, RegID, RegNo); 440249259Sdim Inst.addOperand(MCOperand::CreateReg(Register)); 441249259Sdim return MCDisassembler::Success; 442249259Sdim} 443249259Sdim 444263508Sdimstatic DecodeStatus DecodeDPairRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 445263508Sdim uint64_t Address, 446263508Sdim const void *Decoder) { 447263508Sdim return DecodeRegisterClassByID(Inst, RegNo, AArch64::DPairRegClassID, 448263508Sdim Decoder); 449263508Sdim} 450263508Sdim 451263508Sdimstatic DecodeStatus DecodeQPairRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 452263508Sdim uint64_t Address, 453263508Sdim const void *Decoder) { 454263508Sdim return DecodeRegisterClassByID(Inst, RegNo, AArch64::QPairRegClassID, 455263508Sdim Decoder); 456263508Sdim} 457263508Sdim 458263508Sdimstatic DecodeStatus DecodeDTripleRegisterClass(llvm::MCInst &Inst, 459263508Sdim unsigned RegNo, uint64_t Address, 460263508Sdim const void *Decoder) { 461263508Sdim return DecodeRegisterClassByID(Inst, RegNo, AArch64::DTripleRegClassID, 462263508Sdim Decoder); 463263508Sdim} 464263508Sdim 465263508Sdimstatic DecodeStatus DecodeQTripleRegisterClass(llvm::MCInst &Inst, 466263508Sdim unsigned RegNo, uint64_t Address, 467263508Sdim const void *Decoder) { 468263508Sdim return DecodeRegisterClassByID(Inst, RegNo, AArch64::QTripleRegClassID, 469263508Sdim Decoder); 470263508Sdim} 471263508Sdim 472263508Sdimstatic DecodeStatus DecodeDQuadRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 473263508Sdim uint64_t Address, 474263508Sdim const void *Decoder) { 475263508Sdim return DecodeRegisterClassByID(Inst, RegNo, AArch64::DQuadRegClassID, 476263508Sdim Decoder); 477263508Sdim} 478263508Sdim 479263508Sdimstatic DecodeStatus DecodeQQuadRegisterClass(llvm::MCInst &Inst, unsigned RegNo, 480263508Sdim uint64_t Address, 481263508Sdim const void *Decoder) { 482263508Sdim return DecodeRegisterClassByID(Inst, RegNo, AArch64::QQuadRegClassID, 483263508Sdim Decoder); 484263508Sdim} 485263508Sdim 486249259Sdimstatic DecodeStatus DecodeAddrRegExtendOperand(llvm::MCInst &Inst, 487249259Sdim unsigned OptionHiS, 488249259Sdim uint64_t Address, 489249259Sdim const void *Decoder) { 490249259Sdim // Option{1} must be 1. OptionHiS is made up of {Option{2}, Option{1}, 491249259Sdim // S}. Hence we want to check bit 1. 492249259Sdim if (!(OptionHiS & 2)) 493249259Sdim return MCDisassembler::Fail; 494249259Sdim 495249259Sdim Inst.addOperand(MCOperand::CreateImm(OptionHiS)); 496249259Sdim return MCDisassembler::Success; 497249259Sdim} 498249259Sdim 499249259Sdimstatic DecodeStatus DecodeBitfield32ImmOperand(llvm::MCInst &Inst, 500249259Sdim unsigned Imm6Bits, 501249259Sdim uint64_t Address, 502249259Sdim const void *Decoder) { 503249259Sdim // In the 32-bit variant, bit 6 must be zero. I.e. the immediate must be 504249259Sdim // between 0 and 31. 505249259Sdim if (Imm6Bits > 31) 506249259Sdim return MCDisassembler::Fail; 507249259Sdim 508249259Sdim Inst.addOperand(MCOperand::CreateImm(Imm6Bits)); 509249259Sdim return MCDisassembler::Success; 510249259Sdim} 511249259Sdim 512249259Sdimstatic DecodeStatus DecodeCVT32FixedPosOperand(llvm::MCInst &Inst, 513249259Sdim unsigned Imm6Bits, 514249259Sdim uint64_t Address, 515249259Sdim const void *Decoder) { 516249259Sdim // 1 <= Imm <= 32. Encoded as 64 - Imm so: 63 >= Encoded >= 32. 517249259Sdim if (Imm6Bits < 32) 518249259Sdim return MCDisassembler::Fail; 519249259Sdim 520249259Sdim Inst.addOperand(MCOperand::CreateImm(Imm6Bits)); 521249259Sdim return MCDisassembler::Success; 522249259Sdim} 523249259Sdim 524249259Sdimstatic DecodeStatus DecodeFPZeroOperand(llvm::MCInst &Inst, 525249259Sdim unsigned RmBits, 526249259Sdim uint64_t Address, 527249259Sdim const void *Decoder) { 528249259Sdim // Any bits are valid in the instruction (they're architecturally ignored), 529249259Sdim // but a code generator should insert 0. 530249259Sdim Inst.addOperand(MCOperand::CreateImm(0)); 531249259Sdim return MCDisassembler::Success; 532249259Sdim} 533249259Sdim 534263508Sdimstatic DecodeStatus DecodeShiftRightImm8(MCInst &Inst, unsigned Val, 535263508Sdim uint64_t Address, 536263508Sdim const void *Decoder) { 537263508Sdim Inst.addOperand(MCOperand::CreateImm(8 - Val)); 538263508Sdim return MCDisassembler::Success; 539263508Sdim} 540249259Sdim 541263508Sdimstatic DecodeStatus DecodeShiftRightImm16(MCInst &Inst, unsigned Val, 542263508Sdim uint64_t Address, 543263508Sdim const void *Decoder) { 544263508Sdim Inst.addOperand(MCOperand::CreateImm(16 - Val)); 545263508Sdim return MCDisassembler::Success; 546263508Sdim} 547249259Sdim 548263508Sdimstatic DecodeStatus DecodeShiftRightImm32(MCInst &Inst, unsigned Val, 549263508Sdim uint64_t Address, 550263508Sdim const void *Decoder) { 551263508Sdim Inst.addOperand(MCOperand::CreateImm(32 - Val)); 552263508Sdim return MCDisassembler::Success; 553263508Sdim} 554263508Sdim 555263508Sdimstatic DecodeStatus DecodeShiftRightImm64(MCInst &Inst, unsigned Val, 556263508Sdim uint64_t Address, 557263508Sdim const void *Decoder) { 558263508Sdim Inst.addOperand(MCOperand::CreateImm(64 - Val)); 559263508Sdim return MCDisassembler::Success; 560263508Sdim} 561263508Sdim 562263508Sdimstatic DecodeStatus DecodeShiftLeftImm8(MCInst &Inst, unsigned Val, 563263508Sdim uint64_t Address, 564263508Sdim const void *Decoder) { 565263508Sdim if (Val > 7) 566263508Sdim return MCDisassembler::Fail; 567263508Sdim 568263508Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 569263508Sdim return MCDisassembler::Success; 570263508Sdim} 571263508Sdim 572263508Sdimstatic DecodeStatus DecodeShiftLeftImm16(MCInst &Inst, unsigned Val, 573263508Sdim uint64_t Address, 574263508Sdim const void *Decoder) { 575263508Sdim if (Val > 15) 576263508Sdim return MCDisassembler::Fail; 577263508Sdim 578263508Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 579263508Sdim return MCDisassembler::Success; 580263508Sdim} 581263508Sdim 582263508Sdimstatic DecodeStatus DecodeShiftLeftImm32(MCInst &Inst, unsigned Val, 583263508Sdim uint64_t Address, 584263508Sdim const void *Decoder) { 585263508Sdim if (Val > 31) 586263508Sdim return MCDisassembler::Fail; 587263508Sdim 588263508Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 589263508Sdim return MCDisassembler::Success; 590263508Sdim} 591263508Sdim 592263508Sdimstatic DecodeStatus DecodeShiftLeftImm64(MCInst &Inst, unsigned Val, 593263508Sdim uint64_t Address, 594263508Sdim const void *Decoder) { 595263508Sdim if (Val > 63) 596263508Sdim return MCDisassembler::Fail; 597263508Sdim 598263508Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 599263508Sdim return MCDisassembler::Success; 600263508Sdim} 601263508Sdim 602249259Sdimtemplate<int RegWidth> 603249259Sdimstatic DecodeStatus DecodeMoveWideImmOperand(llvm::MCInst &Inst, 604249259Sdim unsigned FullImm, 605249259Sdim uint64_t Address, 606249259Sdim const void *Decoder) { 607249259Sdim unsigned Imm16 = FullImm & 0xffff; 608249259Sdim unsigned Shift = FullImm >> 16; 609249259Sdim 610249259Sdim if (RegWidth == 32 && Shift > 1) return MCDisassembler::Fail; 611249259Sdim 612249259Sdim Inst.addOperand(MCOperand::CreateImm(Imm16)); 613249259Sdim Inst.addOperand(MCOperand::CreateImm(Shift)); 614249259Sdim return MCDisassembler::Success; 615249259Sdim} 616249259Sdim 617249259Sdimtemplate<int RegWidth> 618249259Sdimstatic DecodeStatus DecodeLogicalImmOperand(llvm::MCInst &Inst, 619249259Sdim unsigned Bits, 620249259Sdim uint64_t Address, 621249259Sdim const void *Decoder) { 622249259Sdim uint64_t Imm; 623249259Sdim if (!A64Imms::isLogicalImmBits(RegWidth, Bits, Imm)) 624249259Sdim return MCDisassembler::Fail; 625249259Sdim 626249259Sdim Inst.addOperand(MCOperand::CreateImm(Bits)); 627249259Sdim return MCDisassembler::Success; 628249259Sdim} 629249259Sdim 630249259Sdim 631249259Sdimstatic DecodeStatus DecodeRegExtendOperand(llvm::MCInst &Inst, 632249259Sdim unsigned ShiftAmount, 633249259Sdim uint64_t Address, 634249259Sdim const void *Decoder) { 635249259Sdim // Only values 0-4 are valid for this 3-bit field 636249259Sdim if (ShiftAmount > 4) 637249259Sdim return MCDisassembler::Fail; 638249259Sdim 639249259Sdim Inst.addOperand(MCOperand::CreateImm(ShiftAmount)); 640249259Sdim return MCDisassembler::Success; 641249259Sdim} 642249259Sdim 643249259Sdimstatic DecodeStatus Decode32BitShiftOperand(llvm::MCInst &Inst, 644249259Sdim unsigned ShiftAmount, 645249259Sdim uint64_t Address, 646249259Sdim const void *Decoder) { 647249259Sdim // Only values below 32 are valid for a 32-bit register 648249259Sdim if (ShiftAmount > 31) 649249259Sdim return MCDisassembler::Fail; 650249259Sdim 651249259Sdim Inst.addOperand(MCOperand::CreateImm(ShiftAmount)); 652249259Sdim return MCDisassembler::Success; 653249259Sdim} 654249259Sdim 655249259Sdimstatic DecodeStatus DecodeBitfieldInstruction(llvm::MCInst &Inst, unsigned Insn, 656249259Sdim uint64_t Address, 657249259Sdim const void *Decoder) { 658249259Sdim unsigned Rd = fieldFromInstruction(Insn, 0, 5); 659249259Sdim unsigned Rn = fieldFromInstruction(Insn, 5, 5); 660249259Sdim unsigned ImmS = fieldFromInstruction(Insn, 10, 6); 661249259Sdim unsigned ImmR = fieldFromInstruction(Insn, 16, 6); 662249259Sdim unsigned SF = fieldFromInstruction(Insn, 31, 1); 663249259Sdim 664249259Sdim // Undef for 0b11 just in case it occurs. Don't want the compiler to optimise 665249259Sdim // out assertions that it thinks should never be hit. 666249259Sdim enum OpcTypes { SBFM = 0, BFM, UBFM, Undef } Opc; 667249259Sdim Opc = (OpcTypes)fieldFromInstruction(Insn, 29, 2); 668249259Sdim 669249259Sdim if (!SF) { 670249259Sdim // ImmR and ImmS must be between 0 and 31 for 32-bit instructions. 671249259Sdim if (ImmR > 31 || ImmS > 31) 672249259Sdim return MCDisassembler::Fail; 673249259Sdim } 674249259Sdim 675249259Sdim if (SF) { 676249259Sdim DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder); 677249259Sdim // BFM MCInsts use Rd as a source too. 678249259Sdim if (Opc == BFM) DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder); 679249259Sdim DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder); 680249259Sdim } else { 681249259Sdim DecodeGPR32RegisterClass(Inst, Rd, Address, Decoder); 682249259Sdim // BFM MCInsts use Rd as a source too. 683249259Sdim if (Opc == BFM) DecodeGPR32RegisterClass(Inst, Rd, Address, Decoder); 684249259Sdim DecodeGPR32RegisterClass(Inst, Rn, Address, Decoder); 685249259Sdim } 686249259Sdim 687249259Sdim // ASR and LSR have more specific patterns so they won't get here: 688249259Sdim assert(!(ImmS == 31 && !SF && Opc != BFM) 689249259Sdim && "shift should have used auto decode"); 690249259Sdim assert(!(ImmS == 63 && SF && Opc != BFM) 691249259Sdim && "shift should have used auto decode"); 692249259Sdim 693249259Sdim // Extension instructions similarly: 694249259Sdim if (Opc == SBFM && ImmR == 0) { 695249259Sdim assert((ImmS != 7 && ImmS != 15) && "extension got here"); 696249259Sdim assert((ImmS != 31 || SF == 0) && "extension got here"); 697249259Sdim } else if (Opc == UBFM && ImmR == 0) { 698249259Sdim assert((SF != 0 || (ImmS != 7 && ImmS != 15)) && "extension got here"); 699249259Sdim } 700249259Sdim 701249259Sdim if (Opc == UBFM) { 702249259Sdim // It might be a LSL instruction, which actually takes the shift amount 703249259Sdim // itself as an MCInst operand. 704249259Sdim if (SF && (ImmS + 1) % 64 == ImmR) { 705249259Sdim Inst.setOpcode(AArch64::LSLxxi); 706249259Sdim Inst.addOperand(MCOperand::CreateImm(63 - ImmS)); 707249259Sdim return MCDisassembler::Success; 708249259Sdim } else if (!SF && (ImmS + 1) % 32 == ImmR) { 709249259Sdim Inst.setOpcode(AArch64::LSLwwi); 710249259Sdim Inst.addOperand(MCOperand::CreateImm(31 - ImmS)); 711249259Sdim return MCDisassembler::Success; 712249259Sdim } 713249259Sdim } 714249259Sdim 715249259Sdim // Otherwise it's definitely either an extract or an insert depending on which 716249259Sdim // of ImmR or ImmS is larger. 717249259Sdim unsigned ExtractOp, InsertOp; 718249259Sdim switch (Opc) { 719249259Sdim default: llvm_unreachable("unexpected instruction trying to decode bitfield"); 720249259Sdim case SBFM: 721249259Sdim ExtractOp = SF ? AArch64::SBFXxxii : AArch64::SBFXwwii; 722249259Sdim InsertOp = SF ? AArch64::SBFIZxxii : AArch64::SBFIZwwii; 723249259Sdim break; 724249259Sdim case BFM: 725249259Sdim ExtractOp = SF ? AArch64::BFXILxxii : AArch64::BFXILwwii; 726249259Sdim InsertOp = SF ? AArch64::BFIxxii : AArch64::BFIwwii; 727249259Sdim break; 728249259Sdim case UBFM: 729249259Sdim ExtractOp = SF ? AArch64::UBFXxxii : AArch64::UBFXwwii; 730249259Sdim InsertOp = SF ? AArch64::UBFIZxxii : AArch64::UBFIZwwii; 731249259Sdim break; 732249259Sdim } 733249259Sdim 734249259Sdim // Otherwise it's a boring insert or extract 735249259Sdim Inst.addOperand(MCOperand::CreateImm(ImmR)); 736249259Sdim Inst.addOperand(MCOperand::CreateImm(ImmS)); 737249259Sdim 738249259Sdim 739249259Sdim if (ImmS < ImmR) 740249259Sdim Inst.setOpcode(InsertOp); 741249259Sdim else 742249259Sdim Inst.setOpcode(ExtractOp); 743249259Sdim 744249259Sdim return MCDisassembler::Success; 745249259Sdim} 746249259Sdim 747249259Sdimstatic DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn, 748249259Sdim uint64_t Address, 749249259Sdim const void *Decoder) { 750249259Sdim // This decoder exists to add the dummy Lane operand to the MCInst, which must 751249259Sdim // be 1 in assembly but has no other real manifestation. 752249259Sdim unsigned Rd = fieldFromInstruction(Insn, 0, 5); 753249259Sdim unsigned Rn = fieldFromInstruction(Insn, 5, 5); 754249259Sdim unsigned IsToVec = fieldFromInstruction(Insn, 16, 1); 755249259Sdim 756249259Sdim if (IsToVec) { 757263508Sdim DecodeFPR128RegisterClass(Inst, Rd, Address, Decoder); 758249259Sdim DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder); 759249259Sdim } else { 760249259Sdim DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder); 761263508Sdim DecodeFPR128RegisterClass(Inst, Rn, Address, Decoder); 762249259Sdim } 763249259Sdim 764249259Sdim // Add the lane 765249259Sdim Inst.addOperand(MCOperand::CreateImm(1)); 766249259Sdim 767249259Sdim return MCDisassembler::Success; 768249259Sdim} 769249259Sdim 770249259Sdim 771249259Sdimstatic DecodeStatus DecodeLDSTPairInstruction(llvm::MCInst &Inst, 772249259Sdim unsigned Insn, 773249259Sdim uint64_t Address, 774249259Sdim const void *Decoder) { 775249259Sdim DecodeStatus Result = MCDisassembler::Success; 776249259Sdim unsigned Rt = fieldFromInstruction(Insn, 0, 5); 777249259Sdim unsigned Rn = fieldFromInstruction(Insn, 5, 5); 778249259Sdim unsigned Rt2 = fieldFromInstruction(Insn, 10, 5); 779249259Sdim unsigned SImm7 = fieldFromInstruction(Insn, 15, 7); 780249259Sdim unsigned L = fieldFromInstruction(Insn, 22, 1); 781249259Sdim unsigned V = fieldFromInstruction(Insn, 26, 1); 782249259Sdim unsigned Opc = fieldFromInstruction(Insn, 30, 2); 783249259Sdim 784249259Sdim // Not an official name, but it turns out that bit 23 distinguishes indexed 785249259Sdim // from non-indexed operations. 786249259Sdim unsigned Indexed = fieldFromInstruction(Insn, 23, 1); 787249259Sdim 788249259Sdim if (Indexed && L == 0) { 789249259Sdim // The MCInst for an indexed store has an out operand and 4 ins: 790249259Sdim // Rn_wb, Rt, Rt2, Rn, Imm 791249259Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 792249259Sdim } 793249259Sdim 794249259Sdim // You shouldn't load to the same register twice in an instruction... 795249259Sdim if (L && Rt == Rt2) 796249259Sdim Result = MCDisassembler::SoftFail; 797249259Sdim 798249259Sdim // ... or do any operation that writes-back to a transfer register. But note 799249259Sdim // that "stp xzr, xzr, [sp], #4" is fine because xzr and sp are different. 800249259Sdim if (Indexed && V == 0 && Rn != 31 && (Rt == Rn || Rt2 == Rn)) 801249259Sdim Result = MCDisassembler::SoftFail; 802249259Sdim 803249259Sdim // Exactly how we decode the MCInst's registers depends on the Opc and V 804249259Sdim // fields of the instruction. These also obviously determine the size of the 805249259Sdim // operation so we can fill in that information while we're at it. 806249259Sdim if (V) { 807249259Sdim // The instruction operates on the FP/SIMD registers 808249259Sdim switch (Opc) { 809249259Sdim default: return MCDisassembler::Fail; 810249259Sdim case 0: 811249259Sdim DecodeFPR32RegisterClass(Inst, Rt, Address, Decoder); 812249259Sdim DecodeFPR32RegisterClass(Inst, Rt2, Address, Decoder); 813249259Sdim break; 814249259Sdim case 1: 815249259Sdim DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder); 816249259Sdim DecodeFPR64RegisterClass(Inst, Rt2, Address, Decoder); 817249259Sdim break; 818249259Sdim case 2: 819249259Sdim DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder); 820249259Sdim DecodeFPR128RegisterClass(Inst, Rt2, Address, Decoder); 821249259Sdim break; 822249259Sdim } 823249259Sdim } else { 824249259Sdim switch (Opc) { 825249259Sdim default: return MCDisassembler::Fail; 826249259Sdim case 0: 827249259Sdim DecodeGPR32RegisterClass(Inst, Rt, Address, Decoder); 828249259Sdim DecodeGPR32RegisterClass(Inst, Rt2, Address, Decoder); 829249259Sdim break; 830249259Sdim case 1: 831249259Sdim assert(L && "unexpected \"store signed\" attempt"); 832249259Sdim DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder); 833249259Sdim DecodeGPR64RegisterClass(Inst, Rt2, Address, Decoder); 834249259Sdim break; 835249259Sdim case 2: 836249259Sdim DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder); 837249259Sdim DecodeGPR64RegisterClass(Inst, Rt2, Address, Decoder); 838249259Sdim break; 839249259Sdim } 840249259Sdim } 841249259Sdim 842249259Sdim if (Indexed && L == 1) { 843249259Sdim // The MCInst for an indexed load has 3 out operands and an 3 ins: 844249259Sdim // Rt, Rt2, Rn_wb, Rt2, Rn, Imm 845249259Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 846249259Sdim } 847249259Sdim 848249259Sdim 849249259Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 850249259Sdim Inst.addOperand(MCOperand::CreateImm(SImm7)); 851249259Sdim 852249259Sdim return Result; 853249259Sdim} 854249259Sdim 855249259Sdimstatic DecodeStatus DecodeLoadPairExclusiveInstruction(llvm::MCInst &Inst, 856249259Sdim uint32_t Val, 857249259Sdim uint64_t Address, 858249259Sdim const void *Decoder) { 859249259Sdim unsigned Rt = fieldFromInstruction(Val, 0, 5); 860249259Sdim unsigned Rn = fieldFromInstruction(Val, 5, 5); 861249259Sdim unsigned Rt2 = fieldFromInstruction(Val, 10, 5); 862249259Sdim unsigned MemSize = fieldFromInstruction(Val, 30, 2); 863249259Sdim 864249259Sdim DecodeStatus S = MCDisassembler::Success; 865249259Sdim if (Rt == Rt2) S = MCDisassembler::SoftFail; 866249259Sdim 867249259Sdim switch (MemSize) { 868249259Sdim case 2: 869249259Sdim if (!Check(S, DecodeGPR32RegisterClass(Inst, Rt, Address, Decoder))) 870249259Sdim return MCDisassembler::Fail; 871249259Sdim if (!Check(S, DecodeGPR32RegisterClass(Inst, Rt2, Address, Decoder))) 872249259Sdim return MCDisassembler::Fail; 873249259Sdim break; 874249259Sdim case 3: 875249259Sdim if (!Check(S, DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder))) 876249259Sdim return MCDisassembler::Fail; 877249259Sdim if (!Check(S, DecodeGPR64RegisterClass(Inst, Rt2, Address, Decoder))) 878249259Sdim return MCDisassembler::Fail; 879249259Sdim break; 880249259Sdim default: 881249259Sdim llvm_unreachable("Invalid MemSize in DecodeLoadPairExclusiveInstruction"); 882249259Sdim } 883249259Sdim 884249259Sdim if (!Check(S, DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder))) 885249259Sdim return MCDisassembler::Fail; 886249259Sdim 887249259Sdim return S; 888249259Sdim} 889249259Sdim 890249259Sdimtemplate<typename SomeNamedImmMapper> 891249259Sdimstatic DecodeStatus DecodeNamedImmOperand(llvm::MCInst &Inst, 892249259Sdim unsigned Val, 893249259Sdim uint64_t Address, 894249259Sdim const void *Decoder) { 895249259Sdim SomeNamedImmMapper Mapper; 896249259Sdim bool ValidNamed; 897249259Sdim Mapper.toString(Val, ValidNamed); 898249259Sdim if (ValidNamed || Mapper.validImm(Val)) { 899249259Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 900249259Sdim return MCDisassembler::Success; 901249259Sdim } 902249259Sdim 903249259Sdim return MCDisassembler::Fail; 904249259Sdim} 905249259Sdim 906249259Sdimstatic DecodeStatus DecodeSysRegOperand(const A64SysReg::SysRegMapper &Mapper, 907249259Sdim llvm::MCInst &Inst, 908249259Sdim unsigned Val, 909249259Sdim uint64_t Address, 910249259Sdim const void *Decoder) { 911249259Sdim bool ValidNamed; 912249259Sdim Mapper.toString(Val, ValidNamed); 913249259Sdim 914249259Sdim Inst.addOperand(MCOperand::CreateImm(Val)); 915249259Sdim 916249259Sdim return ValidNamed ? MCDisassembler::Success : MCDisassembler::Fail; 917249259Sdim} 918249259Sdim 919249259Sdimstatic DecodeStatus DecodeMRSOperand(llvm::MCInst &Inst, 920249259Sdim unsigned Val, 921249259Sdim uint64_t Address, 922249259Sdim const void *Decoder) { 923249259Sdim return DecodeSysRegOperand(A64SysReg::MRSMapper(), Inst, Val, Address, 924249259Sdim Decoder); 925249259Sdim} 926249259Sdim 927249259Sdimstatic DecodeStatus DecodeMSROperand(llvm::MCInst &Inst, 928249259Sdim unsigned Val, 929249259Sdim uint64_t Address, 930249259Sdim const void *Decoder) { 931249259Sdim return DecodeSysRegOperand(A64SysReg::MSRMapper(), Inst, Val, Address, 932249259Sdim Decoder); 933249259Sdim} 934249259Sdim 935249259Sdimstatic DecodeStatus DecodeSingleIndexedInstruction(llvm::MCInst &Inst, 936249259Sdim unsigned Insn, 937249259Sdim uint64_t Address, 938249259Sdim const void *Decoder) { 939249259Sdim unsigned Rt = fieldFromInstruction(Insn, 0, 5); 940249259Sdim unsigned Rn = fieldFromInstruction(Insn, 5, 5); 941249259Sdim unsigned Imm9 = fieldFromInstruction(Insn, 12, 9); 942249259Sdim 943249259Sdim unsigned Opc = fieldFromInstruction(Insn, 22, 2); 944249259Sdim unsigned V = fieldFromInstruction(Insn, 26, 1); 945249259Sdim unsigned Size = fieldFromInstruction(Insn, 30, 2); 946249259Sdim 947249259Sdim if (Opc == 0 || (V == 1 && Opc == 2)) { 948249259Sdim // It's a store, the MCInst gets: Rn_wb, Rt, Rn, Imm 949249259Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 950249259Sdim } 951249259Sdim 952249259Sdim if (V == 0 && (Opc == 2 || Size == 3)) { 953249259Sdim DecodeGPR64RegisterClass(Inst, Rt, Address, Decoder); 954249259Sdim } else if (V == 0) { 955249259Sdim DecodeGPR32RegisterClass(Inst, Rt, Address, Decoder); 956249259Sdim } else if (V == 1 && (Opc & 2)) { 957249259Sdim DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder); 958249259Sdim } else { 959249259Sdim switch (Size) { 960249259Sdim case 0: 961249259Sdim DecodeFPR8RegisterClass(Inst, Rt, Address, Decoder); 962249259Sdim break; 963249259Sdim case 1: 964249259Sdim DecodeFPR16RegisterClass(Inst, Rt, Address, Decoder); 965249259Sdim break; 966249259Sdim case 2: 967249259Sdim DecodeFPR32RegisterClass(Inst, Rt, Address, Decoder); 968249259Sdim break; 969249259Sdim case 3: 970249259Sdim DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder); 971249259Sdim break; 972249259Sdim } 973249259Sdim } 974249259Sdim 975249259Sdim if (Opc != 0 && (V != 1 || Opc != 2)) { 976249259Sdim // It's a load, the MCInst gets: Rt, Rn_wb, Rn, Imm 977249259Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 978249259Sdim } 979249259Sdim 980249259Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 981249259Sdim 982249259Sdim Inst.addOperand(MCOperand::CreateImm(Imm9)); 983249259Sdim 984249259Sdim // N.b. The official documentation says undpredictable if Rt == Rn, but this 985249259Sdim // takes place at the architectural rather than encoding level: 986249259Sdim // 987249259Sdim // "STR xzr, [sp], #4" is perfectly valid. 988249259Sdim if (V == 0 && Rt == Rn && Rn != 31) 989249259Sdim return MCDisassembler::SoftFail; 990249259Sdim else 991249259Sdim return MCDisassembler::Success; 992249259Sdim} 993249259Sdim 994249259Sdimstatic MCDisassembler *createAArch64Disassembler(const Target &T, 995249259Sdim const MCSubtargetInfo &STI) { 996249259Sdim return new AArch64Disassembler(STI, T.createMCRegInfo("")); 997249259Sdim} 998249259Sdim 999249259Sdimextern "C" void LLVMInitializeAArch64Disassembler() { 1000249259Sdim TargetRegistry::RegisterMCDisassembler(TheAArch64Target, 1001249259Sdim createAArch64Disassembler); 1002249259Sdim} 1003249259Sdim 1004263508Sdimtemplate <A64SE::ShiftExtSpecifiers Ext, bool IsHalf> 1005263508Sdimstatic DecodeStatus 1006263508SdimDecodeNeonMovImmShiftOperand(llvm::MCInst &Inst, unsigned ShiftAmount, 1007263508Sdim uint64_t Address, const void *Decoder) { 1008263508Sdim bool IsLSL = false; 1009263508Sdim if (Ext == A64SE::LSL) 1010263508Sdim IsLSL = true; 1011263508Sdim else if (Ext != A64SE::MSL) 1012263508Sdim return MCDisassembler::Fail; 1013249259Sdim 1014263508Sdim // MSL and LSLH accepts encoded shift amount 0 or 1. 1015263508Sdim if ((!IsLSL || (IsLSL && IsHalf)) && ShiftAmount != 0 && ShiftAmount != 1) 1016263508Sdim return MCDisassembler::Fail; 1017263508Sdim 1018263508Sdim // LSL accepts encoded shift amount 0, 1, 2 or 3. 1019263508Sdim if (IsLSL && ShiftAmount > 3) 1020263508Sdim return MCDisassembler::Fail; 1021263508Sdim 1022263508Sdim Inst.addOperand(MCOperand::CreateImm(ShiftAmount)); 1023263508Sdim return MCDisassembler::Success; 1024263508Sdim} 1025263508Sdim 1026263508Sdim// Decode post-index vector load/store instructions. 1027263508Sdim// This is necessary as we need to decode Rm: if Rm == 0b11111, the last 1028263508Sdim// operand is an immediate equal the the length of vector list in bytes, 1029263508Sdim// or Rm is decoded to a GPR64noxzr register. 1030263508Sdimstatic DecodeStatus DecodeVLDSTPostInstruction(MCInst &Inst, unsigned Insn, 1031263508Sdim uint64_t Address, 1032263508Sdim const void *Decoder) { 1033263508Sdim unsigned Rt = fieldFromInstruction(Insn, 0, 5); 1034263508Sdim unsigned Rn = fieldFromInstruction(Insn, 5, 5); 1035263508Sdim unsigned Rm = fieldFromInstruction(Insn, 16, 5); 1036263508Sdim unsigned Opcode = fieldFromInstruction(Insn, 12, 4); 1037263508Sdim unsigned IsLoad = fieldFromInstruction(Insn, 22, 1); 1038263508Sdim // 0 for 64bit vector list, 1 for 128bit vector list 1039263508Sdim unsigned Is128BitVec = fieldFromInstruction(Insn, 30, 1); 1040263508Sdim 1041263508Sdim unsigned NumVecs; 1042263508Sdim switch (Opcode) { 1043263508Sdim case 0: // ld4/st4 1044263508Sdim case 2: // ld1/st1 with 4 vectors 1045263508Sdim NumVecs = 4; break; 1046263508Sdim case 4: // ld3/st3 1047263508Sdim case 6: // ld1/st1 with 3 vectors 1048263508Sdim NumVecs = 3; break; 1049263508Sdim case 7: // ld1/st1 with 1 vector 1050263508Sdim NumVecs = 1; break; 1051263508Sdim case 8: // ld2/st2 1052263508Sdim case 10: // ld1/st1 with 2 vectors 1053263508Sdim NumVecs = 2; break; 1054263508Sdim default: 1055263508Sdim llvm_unreachable("Invalid opcode for post-index load/store instructions"); 1056263508Sdim } 1057263508Sdim 1058263508Sdim // Decode vector list of 1/2/3/4 vectors for load instructions. 1059263508Sdim if (IsLoad) { 1060263508Sdim switch (NumVecs) { 1061263508Sdim case 1: 1062263508Sdim Is128BitVec ? DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder) 1063263508Sdim : DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder); 1064263508Sdim break; 1065263508Sdim case 2: 1066263508Sdim Is128BitVec ? DecodeQPairRegisterClass(Inst, Rt, Address, Decoder) 1067263508Sdim : DecodeDPairRegisterClass(Inst, Rt, Address, Decoder); 1068263508Sdim break; 1069263508Sdim case 3: 1070263508Sdim Is128BitVec ? DecodeQTripleRegisterClass(Inst, Rt, Address, Decoder) 1071263508Sdim : DecodeDTripleRegisterClass(Inst, Rt, Address, Decoder); 1072263508Sdim break; 1073263508Sdim case 4: 1074263508Sdim Is128BitVec ? DecodeQQuadRegisterClass(Inst, Rt, Address, Decoder) 1075263508Sdim : DecodeDQuadRegisterClass(Inst, Rt, Address, Decoder); 1076263508Sdim break; 1077263508Sdim } 1078263508Sdim } 1079263508Sdim 1080263508Sdim // Decode write back register, which is equal to Rn. 1081263508Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 1082263508Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 1083263508Sdim 1084263508Sdim if (Rm == 31) // If Rm is 0x11111, add the vector list length in byte 1085263508Sdim Inst.addOperand(MCOperand::CreateImm(NumVecs * (Is128BitVec ? 16 : 8))); 1086263508Sdim else // Decode Rm 1087263508Sdim DecodeGPR64noxzrRegisterClass(Inst, Rm, Address, Decoder); 1088263508Sdim 1089263508Sdim // Decode vector list of 1/2/3/4 vectors for load instructions. 1090263508Sdim if (!IsLoad) { 1091263508Sdim switch (NumVecs) { 1092263508Sdim case 1: 1093263508Sdim Is128BitVec ? DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder) 1094263508Sdim : DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder); 1095263508Sdim break; 1096263508Sdim case 2: 1097263508Sdim Is128BitVec ? DecodeQPairRegisterClass(Inst, Rt, Address, Decoder) 1098263508Sdim : DecodeDPairRegisterClass(Inst, Rt, Address, Decoder); 1099263508Sdim break; 1100263508Sdim case 3: 1101263508Sdim Is128BitVec ? DecodeQTripleRegisterClass(Inst, Rt, Address, Decoder) 1102263508Sdim : DecodeDTripleRegisterClass(Inst, Rt, Address, Decoder); 1103263508Sdim break; 1104263508Sdim case 4: 1105263508Sdim Is128BitVec ? DecodeQQuadRegisterClass(Inst, Rt, Address, Decoder) 1106263508Sdim : DecodeDQuadRegisterClass(Inst, Rt, Address, Decoder); 1107263508Sdim break; 1108263508Sdim } 1109263508Sdim } 1110263508Sdim 1111263508Sdim return MCDisassembler::Success; 1112263508Sdim} 1113263508Sdim 1114263508Sdim// Decode post-index vector load/store lane instructions. 1115263508Sdim// This is necessary as we need to decode Rm: if Rm == 0b11111, the last 1116263508Sdim// operand is an immediate equal the the length of the changed bytes, 1117263508Sdim// or Rm is decoded to a GPR64noxzr register. 1118263508Sdimstatic DecodeStatus DecodeVLDSTLanePostInstruction(MCInst &Inst, unsigned Insn, 1119263508Sdim uint64_t Address, 1120263508Sdim const void *Decoder) { 1121263508Sdim bool Is64bitVec = false; 1122263508Sdim bool IsLoadDup = false; 1123263508Sdim bool IsLoad = false; 1124263508Sdim // The total number of bytes transferred. 1125263508Sdim // TransferBytes = NumVecs * OneLaneBytes 1126263508Sdim unsigned TransferBytes = 0; 1127263508Sdim unsigned NumVecs = 0; 1128263508Sdim unsigned Opc = Inst.getOpcode(); 1129263508Sdim switch (Opc) { 1130263508Sdim case AArch64::LD1R_WB_8B_fixed: case AArch64::LD1R_WB_8B_register: 1131263508Sdim case AArch64::LD1R_WB_4H_fixed: case AArch64::LD1R_WB_4H_register: 1132263508Sdim case AArch64::LD1R_WB_2S_fixed: case AArch64::LD1R_WB_2S_register: 1133263508Sdim case AArch64::LD1R_WB_1D_fixed: case AArch64::LD1R_WB_1D_register: { 1134263508Sdim switch (Opc) { 1135263508Sdim case AArch64::LD1R_WB_8B_fixed: case AArch64::LD1R_WB_8B_register: 1136263508Sdim TransferBytes = 1; break; 1137263508Sdim case AArch64::LD1R_WB_4H_fixed: case AArch64::LD1R_WB_4H_register: 1138263508Sdim TransferBytes = 2; break; 1139263508Sdim case AArch64::LD1R_WB_2S_fixed: case AArch64::LD1R_WB_2S_register: 1140263508Sdim TransferBytes = 4; break; 1141263508Sdim case AArch64::LD1R_WB_1D_fixed: case AArch64::LD1R_WB_1D_register: 1142263508Sdim TransferBytes = 8; break; 1143263508Sdim } 1144263508Sdim Is64bitVec = true; 1145263508Sdim IsLoadDup = true; 1146263508Sdim NumVecs = 1; 1147263508Sdim break; 1148263508Sdim } 1149263508Sdim 1150263508Sdim case AArch64::LD1R_WB_16B_fixed: case AArch64::LD1R_WB_16B_register: 1151263508Sdim case AArch64::LD1R_WB_8H_fixed: case AArch64::LD1R_WB_8H_register: 1152263508Sdim case AArch64::LD1R_WB_4S_fixed: case AArch64::LD1R_WB_4S_register: 1153263508Sdim case AArch64::LD1R_WB_2D_fixed: case AArch64::LD1R_WB_2D_register: { 1154263508Sdim switch (Opc) { 1155263508Sdim case AArch64::LD1R_WB_16B_fixed: case AArch64::LD1R_WB_16B_register: 1156263508Sdim TransferBytes = 1; break; 1157263508Sdim case AArch64::LD1R_WB_8H_fixed: case AArch64::LD1R_WB_8H_register: 1158263508Sdim TransferBytes = 2; break; 1159263508Sdim case AArch64::LD1R_WB_4S_fixed: case AArch64::LD1R_WB_4S_register: 1160263508Sdim TransferBytes = 4; break; 1161263508Sdim case AArch64::LD1R_WB_2D_fixed: case AArch64::LD1R_WB_2D_register: 1162263508Sdim TransferBytes = 8; break; 1163263508Sdim } 1164263508Sdim IsLoadDup = true; 1165263508Sdim NumVecs = 1; 1166263508Sdim break; 1167263508Sdim } 1168263508Sdim 1169263508Sdim case AArch64::LD2R_WB_8B_fixed: case AArch64::LD2R_WB_8B_register: 1170263508Sdim case AArch64::LD2R_WB_4H_fixed: case AArch64::LD2R_WB_4H_register: 1171263508Sdim case AArch64::LD2R_WB_2S_fixed: case AArch64::LD2R_WB_2S_register: 1172263508Sdim case AArch64::LD2R_WB_1D_fixed: case AArch64::LD2R_WB_1D_register: { 1173263508Sdim switch (Opc) { 1174263508Sdim case AArch64::LD2R_WB_8B_fixed: case AArch64::LD2R_WB_8B_register: 1175263508Sdim TransferBytes = 2; break; 1176263508Sdim case AArch64::LD2R_WB_4H_fixed: case AArch64::LD2R_WB_4H_register: 1177263508Sdim TransferBytes = 4; break; 1178263508Sdim case AArch64::LD2R_WB_2S_fixed: case AArch64::LD2R_WB_2S_register: 1179263508Sdim TransferBytes = 8; break; 1180263508Sdim case AArch64::LD2R_WB_1D_fixed: case AArch64::LD2R_WB_1D_register: 1181263508Sdim TransferBytes = 16; break; 1182263508Sdim } 1183263508Sdim Is64bitVec = true; 1184263508Sdim IsLoadDup = true; 1185263508Sdim NumVecs = 2; 1186263508Sdim break; 1187263508Sdim } 1188263508Sdim 1189263508Sdim case AArch64::LD2R_WB_16B_fixed: case AArch64::LD2R_WB_16B_register: 1190263508Sdim case AArch64::LD2R_WB_8H_fixed: case AArch64::LD2R_WB_8H_register: 1191263508Sdim case AArch64::LD2R_WB_4S_fixed: case AArch64::LD2R_WB_4S_register: 1192263508Sdim case AArch64::LD2R_WB_2D_fixed: case AArch64::LD2R_WB_2D_register: { 1193263508Sdim switch (Opc) { 1194263508Sdim case AArch64::LD2R_WB_16B_fixed: case AArch64::LD2R_WB_16B_register: 1195263508Sdim TransferBytes = 2; break; 1196263508Sdim case AArch64::LD2R_WB_8H_fixed: case AArch64::LD2R_WB_8H_register: 1197263508Sdim TransferBytes = 4; break; 1198263508Sdim case AArch64::LD2R_WB_4S_fixed: case AArch64::LD2R_WB_4S_register: 1199263508Sdim TransferBytes = 8; break; 1200263508Sdim case AArch64::LD2R_WB_2D_fixed: case AArch64::LD2R_WB_2D_register: 1201263508Sdim TransferBytes = 16; break; 1202263508Sdim } 1203263508Sdim IsLoadDup = true; 1204263508Sdim NumVecs = 2; 1205263508Sdim break; 1206263508Sdim } 1207263508Sdim 1208263508Sdim case AArch64::LD3R_WB_8B_fixed: case AArch64::LD3R_WB_8B_register: 1209263508Sdim case AArch64::LD3R_WB_4H_fixed: case AArch64::LD3R_WB_4H_register: 1210263508Sdim case AArch64::LD3R_WB_2S_fixed: case AArch64::LD3R_WB_2S_register: 1211263508Sdim case AArch64::LD3R_WB_1D_fixed: case AArch64::LD3R_WB_1D_register: { 1212263508Sdim switch (Opc) { 1213263508Sdim case AArch64::LD3R_WB_8B_fixed: case AArch64::LD3R_WB_8B_register: 1214263508Sdim TransferBytes = 3; break; 1215263508Sdim case AArch64::LD3R_WB_4H_fixed: case AArch64::LD3R_WB_4H_register: 1216263508Sdim TransferBytes = 6; break; 1217263508Sdim case AArch64::LD3R_WB_2S_fixed: case AArch64::LD3R_WB_2S_register: 1218263508Sdim TransferBytes = 12; break; 1219263508Sdim case AArch64::LD3R_WB_1D_fixed: case AArch64::LD3R_WB_1D_register: 1220263508Sdim TransferBytes = 24; break; 1221263508Sdim } 1222263508Sdim Is64bitVec = true; 1223263508Sdim IsLoadDup = true; 1224263508Sdim NumVecs = 3; 1225263508Sdim break; 1226263508Sdim } 1227263508Sdim 1228263508Sdim case AArch64::LD3R_WB_16B_fixed: case AArch64::LD3R_WB_16B_register: 1229263508Sdim case AArch64::LD3R_WB_4S_fixed: case AArch64::LD3R_WB_8H_register: 1230263508Sdim case AArch64::LD3R_WB_8H_fixed: case AArch64::LD3R_WB_4S_register: 1231263508Sdim case AArch64::LD3R_WB_2D_fixed: case AArch64::LD3R_WB_2D_register: { 1232263508Sdim switch (Opc) { 1233263508Sdim case AArch64::LD3R_WB_16B_fixed: case AArch64::LD3R_WB_16B_register: 1234263508Sdim TransferBytes = 3; break; 1235263508Sdim case AArch64::LD3R_WB_8H_fixed: case AArch64::LD3R_WB_8H_register: 1236263508Sdim TransferBytes = 6; break; 1237263508Sdim case AArch64::LD3R_WB_4S_fixed: case AArch64::LD3R_WB_4S_register: 1238263508Sdim TransferBytes = 12; break; 1239263508Sdim case AArch64::LD3R_WB_2D_fixed: case AArch64::LD3R_WB_2D_register: 1240263508Sdim TransferBytes = 24; break; 1241263508Sdim } 1242263508Sdim IsLoadDup = true; 1243263508Sdim NumVecs = 3; 1244263508Sdim break; 1245263508Sdim } 1246263508Sdim 1247263508Sdim case AArch64::LD4R_WB_8B_fixed: case AArch64::LD4R_WB_8B_register: 1248263508Sdim case AArch64::LD4R_WB_4H_fixed: case AArch64::LD4R_WB_4H_register: 1249263508Sdim case AArch64::LD4R_WB_2S_fixed: case AArch64::LD4R_WB_2S_register: 1250263508Sdim case AArch64::LD4R_WB_1D_fixed: case AArch64::LD4R_WB_1D_register: { 1251263508Sdim switch (Opc) { 1252263508Sdim case AArch64::LD4R_WB_8B_fixed: case AArch64::LD4R_WB_8B_register: 1253263508Sdim TransferBytes = 4; break; 1254263508Sdim case AArch64::LD4R_WB_4H_fixed: case AArch64::LD4R_WB_4H_register: 1255263508Sdim TransferBytes = 8; break; 1256263508Sdim case AArch64::LD4R_WB_2S_fixed: case AArch64::LD4R_WB_2S_register: 1257263508Sdim TransferBytes = 16; break; 1258263508Sdim case AArch64::LD4R_WB_1D_fixed: case AArch64::LD4R_WB_1D_register: 1259263508Sdim TransferBytes = 32; break; 1260263508Sdim } 1261263508Sdim Is64bitVec = true; 1262263508Sdim IsLoadDup = true; 1263263508Sdim NumVecs = 4; 1264263508Sdim break; 1265263508Sdim } 1266263508Sdim 1267263508Sdim case AArch64::LD4R_WB_16B_fixed: case AArch64::LD4R_WB_16B_register: 1268263508Sdim case AArch64::LD4R_WB_4S_fixed: case AArch64::LD4R_WB_8H_register: 1269263508Sdim case AArch64::LD4R_WB_8H_fixed: case AArch64::LD4R_WB_4S_register: 1270263508Sdim case AArch64::LD4R_WB_2D_fixed: case AArch64::LD4R_WB_2D_register: { 1271263508Sdim switch (Opc) { 1272263508Sdim case AArch64::LD4R_WB_16B_fixed: case AArch64::LD4R_WB_16B_register: 1273263508Sdim TransferBytes = 4; break; 1274263508Sdim case AArch64::LD4R_WB_8H_fixed: case AArch64::LD4R_WB_8H_register: 1275263508Sdim TransferBytes = 8; break; 1276263508Sdim case AArch64::LD4R_WB_4S_fixed: case AArch64::LD4R_WB_4S_register: 1277263508Sdim TransferBytes = 16; break; 1278263508Sdim case AArch64::LD4R_WB_2D_fixed: case AArch64::LD4R_WB_2D_register: 1279263508Sdim TransferBytes = 32; break; 1280263508Sdim } 1281263508Sdim IsLoadDup = true; 1282263508Sdim NumVecs = 4; 1283263508Sdim break; 1284263508Sdim } 1285263508Sdim 1286263508Sdim case AArch64::LD1LN_WB_B_fixed: case AArch64::LD1LN_WB_B_register: 1287263508Sdim case AArch64::LD1LN_WB_H_fixed: case AArch64::LD1LN_WB_H_register: 1288263508Sdim case AArch64::LD1LN_WB_S_fixed: case AArch64::LD1LN_WB_S_register: 1289263508Sdim case AArch64::LD1LN_WB_D_fixed: case AArch64::LD1LN_WB_D_register: { 1290263508Sdim switch (Opc) { 1291263508Sdim case AArch64::LD1LN_WB_B_fixed: case AArch64::LD1LN_WB_B_register: 1292263508Sdim TransferBytes = 1; break; 1293263508Sdim case AArch64::LD1LN_WB_H_fixed: case AArch64::LD1LN_WB_H_register: 1294263508Sdim TransferBytes = 2; break; 1295263508Sdim case AArch64::LD1LN_WB_S_fixed: case AArch64::LD1LN_WB_S_register: 1296263508Sdim TransferBytes = 4; break; 1297263508Sdim case AArch64::LD1LN_WB_D_fixed: case AArch64::LD1LN_WB_D_register: 1298263508Sdim TransferBytes = 8; break; 1299263508Sdim } 1300263508Sdim IsLoad = true; 1301263508Sdim NumVecs = 1; 1302263508Sdim break; 1303263508Sdim } 1304263508Sdim 1305263508Sdim case AArch64::LD2LN_WB_B_fixed: case AArch64::LD2LN_WB_B_register: 1306263508Sdim case AArch64::LD2LN_WB_H_fixed: case AArch64::LD2LN_WB_H_register: 1307263508Sdim case AArch64::LD2LN_WB_S_fixed: case AArch64::LD2LN_WB_S_register: 1308263508Sdim case AArch64::LD2LN_WB_D_fixed: case AArch64::LD2LN_WB_D_register: { 1309263508Sdim switch (Opc) { 1310263508Sdim case AArch64::LD2LN_WB_B_fixed: case AArch64::LD2LN_WB_B_register: 1311263508Sdim TransferBytes = 2; break; 1312263508Sdim case AArch64::LD2LN_WB_H_fixed: case AArch64::LD2LN_WB_H_register: 1313263508Sdim TransferBytes = 4; break; 1314263508Sdim case AArch64::LD2LN_WB_S_fixed: case AArch64::LD2LN_WB_S_register: 1315263508Sdim TransferBytes = 8; break; 1316263508Sdim case AArch64::LD2LN_WB_D_fixed: case AArch64::LD2LN_WB_D_register: 1317263508Sdim TransferBytes = 16; break; 1318263508Sdim } 1319263508Sdim IsLoad = true; 1320263508Sdim NumVecs = 2; 1321263508Sdim break; 1322263508Sdim } 1323263508Sdim 1324263508Sdim case AArch64::LD3LN_WB_B_fixed: case AArch64::LD3LN_WB_B_register: 1325263508Sdim case AArch64::LD3LN_WB_H_fixed: case AArch64::LD3LN_WB_H_register: 1326263508Sdim case AArch64::LD3LN_WB_S_fixed: case AArch64::LD3LN_WB_S_register: 1327263508Sdim case AArch64::LD3LN_WB_D_fixed: case AArch64::LD3LN_WB_D_register: { 1328263508Sdim switch (Opc) { 1329263508Sdim case AArch64::LD3LN_WB_B_fixed: case AArch64::LD3LN_WB_B_register: 1330263508Sdim TransferBytes = 3; break; 1331263508Sdim case AArch64::LD3LN_WB_H_fixed: case AArch64::LD3LN_WB_H_register: 1332263508Sdim TransferBytes = 6; break; 1333263508Sdim case AArch64::LD3LN_WB_S_fixed: case AArch64::LD3LN_WB_S_register: 1334263508Sdim TransferBytes = 12; break; 1335263508Sdim case AArch64::LD3LN_WB_D_fixed: case AArch64::LD3LN_WB_D_register: 1336263508Sdim TransferBytes = 24; break; 1337263508Sdim } 1338263508Sdim IsLoad = true; 1339263508Sdim NumVecs = 3; 1340263508Sdim break; 1341263508Sdim } 1342263508Sdim 1343263508Sdim case AArch64::LD4LN_WB_B_fixed: case AArch64::LD4LN_WB_B_register: 1344263508Sdim case AArch64::LD4LN_WB_H_fixed: case AArch64::LD4LN_WB_H_register: 1345263508Sdim case AArch64::LD4LN_WB_S_fixed: case AArch64::LD4LN_WB_S_register: 1346263508Sdim case AArch64::LD4LN_WB_D_fixed: case AArch64::LD4LN_WB_D_register: { 1347263508Sdim switch (Opc) { 1348263508Sdim case AArch64::LD4LN_WB_B_fixed: case AArch64::LD4LN_WB_B_register: 1349263508Sdim TransferBytes = 4; break; 1350263508Sdim case AArch64::LD4LN_WB_H_fixed: case AArch64::LD4LN_WB_H_register: 1351263508Sdim TransferBytes = 8; break; 1352263508Sdim case AArch64::LD4LN_WB_S_fixed: case AArch64::LD4LN_WB_S_register: 1353263508Sdim TransferBytes = 16; break; 1354263508Sdim case AArch64::LD4LN_WB_D_fixed: case AArch64::LD4LN_WB_D_register: 1355263508Sdim TransferBytes = 32; break; 1356263508Sdim } 1357263508Sdim IsLoad = true; 1358263508Sdim NumVecs = 4; 1359263508Sdim break; 1360263508Sdim } 1361263508Sdim 1362263508Sdim case AArch64::ST1LN_WB_B_fixed: case AArch64::ST1LN_WB_B_register: 1363263508Sdim case AArch64::ST1LN_WB_H_fixed: case AArch64::ST1LN_WB_H_register: 1364263508Sdim case AArch64::ST1LN_WB_S_fixed: case AArch64::ST1LN_WB_S_register: 1365263508Sdim case AArch64::ST1LN_WB_D_fixed: case AArch64::ST1LN_WB_D_register: { 1366263508Sdim switch (Opc) { 1367263508Sdim case AArch64::ST1LN_WB_B_fixed: case AArch64::ST1LN_WB_B_register: 1368263508Sdim TransferBytes = 1; break; 1369263508Sdim case AArch64::ST1LN_WB_H_fixed: case AArch64::ST1LN_WB_H_register: 1370263508Sdim TransferBytes = 2; break; 1371263508Sdim case AArch64::ST1LN_WB_S_fixed: case AArch64::ST1LN_WB_S_register: 1372263508Sdim TransferBytes = 4; break; 1373263508Sdim case AArch64::ST1LN_WB_D_fixed: case AArch64::ST1LN_WB_D_register: 1374263508Sdim TransferBytes = 8; break; 1375263508Sdim } 1376263508Sdim NumVecs = 1; 1377263508Sdim break; 1378263508Sdim } 1379263508Sdim 1380263508Sdim case AArch64::ST2LN_WB_B_fixed: case AArch64::ST2LN_WB_B_register: 1381263508Sdim case AArch64::ST2LN_WB_H_fixed: case AArch64::ST2LN_WB_H_register: 1382263508Sdim case AArch64::ST2LN_WB_S_fixed: case AArch64::ST2LN_WB_S_register: 1383263508Sdim case AArch64::ST2LN_WB_D_fixed: case AArch64::ST2LN_WB_D_register: { 1384263508Sdim switch (Opc) { 1385263508Sdim case AArch64::ST2LN_WB_B_fixed: case AArch64::ST2LN_WB_B_register: 1386263508Sdim TransferBytes = 2; break; 1387263508Sdim case AArch64::ST2LN_WB_H_fixed: case AArch64::ST2LN_WB_H_register: 1388263508Sdim TransferBytes = 4; break; 1389263508Sdim case AArch64::ST2LN_WB_S_fixed: case AArch64::ST2LN_WB_S_register: 1390263508Sdim TransferBytes = 8; break; 1391263508Sdim case AArch64::ST2LN_WB_D_fixed: case AArch64::ST2LN_WB_D_register: 1392263508Sdim TransferBytes = 16; break; 1393263508Sdim } 1394263508Sdim NumVecs = 2; 1395263508Sdim break; 1396263508Sdim } 1397263508Sdim 1398263508Sdim case AArch64::ST3LN_WB_B_fixed: case AArch64::ST3LN_WB_B_register: 1399263508Sdim case AArch64::ST3LN_WB_H_fixed: case AArch64::ST3LN_WB_H_register: 1400263508Sdim case AArch64::ST3LN_WB_S_fixed: case AArch64::ST3LN_WB_S_register: 1401263508Sdim case AArch64::ST3LN_WB_D_fixed: case AArch64::ST3LN_WB_D_register: { 1402263508Sdim switch (Opc) { 1403263508Sdim case AArch64::ST3LN_WB_B_fixed: case AArch64::ST3LN_WB_B_register: 1404263508Sdim TransferBytes = 3; break; 1405263508Sdim case AArch64::ST3LN_WB_H_fixed: case AArch64::ST3LN_WB_H_register: 1406263508Sdim TransferBytes = 6; break; 1407263508Sdim case AArch64::ST3LN_WB_S_fixed: case AArch64::ST3LN_WB_S_register: 1408263508Sdim TransferBytes = 12; break; 1409263508Sdim case AArch64::ST3LN_WB_D_fixed: case AArch64::ST3LN_WB_D_register: 1410263508Sdim TransferBytes = 24; break; 1411263508Sdim } 1412263508Sdim NumVecs = 3; 1413263508Sdim break; 1414263508Sdim } 1415263508Sdim 1416263508Sdim case AArch64::ST4LN_WB_B_fixed: case AArch64::ST4LN_WB_B_register: 1417263508Sdim case AArch64::ST4LN_WB_H_fixed: case AArch64::ST4LN_WB_H_register: 1418263508Sdim case AArch64::ST4LN_WB_S_fixed: case AArch64::ST4LN_WB_S_register: 1419263508Sdim case AArch64::ST4LN_WB_D_fixed: case AArch64::ST4LN_WB_D_register: { 1420263508Sdim switch (Opc) { 1421263508Sdim case AArch64::ST4LN_WB_B_fixed: case AArch64::ST4LN_WB_B_register: 1422263508Sdim TransferBytes = 4; break; 1423263508Sdim case AArch64::ST4LN_WB_H_fixed: case AArch64::ST4LN_WB_H_register: 1424263508Sdim TransferBytes = 8; break; 1425263508Sdim case AArch64::ST4LN_WB_S_fixed: case AArch64::ST4LN_WB_S_register: 1426263508Sdim TransferBytes = 16; break; 1427263508Sdim case AArch64::ST4LN_WB_D_fixed: case AArch64::ST4LN_WB_D_register: 1428263508Sdim TransferBytes = 32; break; 1429263508Sdim } 1430263508Sdim NumVecs = 4; 1431263508Sdim break; 1432263508Sdim } 1433263508Sdim 1434263508Sdim default: 1435263508Sdim return MCDisassembler::Fail; 1436263508Sdim } // End of switch (Opc) 1437263508Sdim 1438263508Sdim unsigned Rt = fieldFromInstruction(Insn, 0, 5); 1439263508Sdim unsigned Rn = fieldFromInstruction(Insn, 5, 5); 1440263508Sdim unsigned Rm = fieldFromInstruction(Insn, 16, 5); 1441263508Sdim 1442263508Sdim // Decode post-index of load duplicate lane 1443263508Sdim if (IsLoadDup) { 1444263508Sdim switch (NumVecs) { 1445263508Sdim case 1: 1446263508Sdim Is64bitVec ? DecodeFPR64RegisterClass(Inst, Rt, Address, Decoder) 1447263508Sdim : DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder); 1448263508Sdim break; 1449263508Sdim case 2: 1450263508Sdim Is64bitVec ? DecodeDPairRegisterClass(Inst, Rt, Address, Decoder) 1451263508Sdim : DecodeQPairRegisterClass(Inst, Rt, Address, Decoder); 1452263508Sdim break; 1453263508Sdim case 3: 1454263508Sdim Is64bitVec ? DecodeDTripleRegisterClass(Inst, Rt, Address, Decoder) 1455263508Sdim : DecodeQTripleRegisterClass(Inst, Rt, Address, Decoder); 1456263508Sdim break; 1457263508Sdim case 4: 1458263508Sdim Is64bitVec ? DecodeDQuadRegisterClass(Inst, Rt, Address, Decoder) 1459263508Sdim : DecodeQQuadRegisterClass(Inst, Rt, Address, Decoder); 1460263508Sdim } 1461263508Sdim 1462263508Sdim // Decode write back register, which is equal to Rn. 1463263508Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 1464263508Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 1465263508Sdim 1466263508Sdim if (Rm == 31) // If Rm is 0x11111, add the number of transferred bytes 1467263508Sdim Inst.addOperand(MCOperand::CreateImm(TransferBytes)); 1468263508Sdim else // Decode Rm 1469263508Sdim DecodeGPR64noxzrRegisterClass(Inst, Rm, Address, Decoder); 1470263508Sdim 1471263508Sdim return MCDisassembler::Success; 1472263508Sdim } 1473263508Sdim 1474263508Sdim // Decode post-index of load/store lane 1475263508Sdim // Loads have a vector list as output. 1476263508Sdim if (IsLoad) { 1477263508Sdim switch (NumVecs) { 1478263508Sdim case 1: 1479263508Sdim DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder); 1480263508Sdim break; 1481263508Sdim case 2: 1482263508Sdim DecodeQPairRegisterClass(Inst, Rt, Address, Decoder); 1483263508Sdim break; 1484263508Sdim case 3: 1485263508Sdim DecodeQTripleRegisterClass(Inst, Rt, Address, Decoder); 1486263508Sdim break; 1487263508Sdim case 4: 1488263508Sdim DecodeQQuadRegisterClass(Inst, Rt, Address, Decoder); 1489263508Sdim } 1490263508Sdim } 1491263508Sdim 1492263508Sdim // Decode write back register, which is equal to Rn. 1493263508Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 1494263508Sdim DecodeGPR64xspRegisterClass(Inst, Rn, Address, Decoder); 1495263508Sdim 1496263508Sdim if (Rm == 31) // If Rm is 0x11111, add the number of transferred bytes 1497263508Sdim Inst.addOperand(MCOperand::CreateImm(TransferBytes)); 1498263508Sdim else // Decode Rm 1499263508Sdim DecodeGPR64noxzrRegisterClass(Inst, Rm, Address, Decoder); 1500263508Sdim 1501263508Sdim // Decode the source vector list. 1502263508Sdim switch (NumVecs) { 1503263508Sdim case 1: 1504263508Sdim DecodeFPR128RegisterClass(Inst, Rt, Address, Decoder); 1505263508Sdim break; 1506263508Sdim case 2: 1507263508Sdim DecodeQPairRegisterClass(Inst, Rt, Address, Decoder); 1508263508Sdim break; 1509263508Sdim case 3: 1510263508Sdim DecodeQTripleRegisterClass(Inst, Rt, Address, Decoder); 1511263508Sdim break; 1512263508Sdim case 4: 1513263508Sdim DecodeQQuadRegisterClass(Inst, Rt, Address, Decoder); 1514263508Sdim } 1515263508Sdim 1516263508Sdim // Decode lane 1517263508Sdim unsigned Q = fieldFromInstruction(Insn, 30, 1); 1518263508Sdim unsigned S = fieldFromInstruction(Insn, 10, 3); 1519263508Sdim unsigned lane = 0; 1520263508Sdim // Calculate the number of lanes by number of vectors and transfered bytes. 1521263508Sdim // NumLanes = 16 bytes / bytes of each lane 1522263508Sdim unsigned NumLanes = 16 / (TransferBytes / NumVecs); 1523263508Sdim switch (NumLanes) { 1524263508Sdim case 16: // A vector has 16 lanes, each lane is 1 bytes. 1525263508Sdim lane = (Q << 3) | S; 1526263508Sdim break; 1527263508Sdim case 8: 1528263508Sdim lane = (Q << 2) | (S >> 1); 1529263508Sdim break; 1530263508Sdim case 4: 1531263508Sdim lane = (Q << 1) | (S >> 2); 1532263508Sdim break; 1533263508Sdim case 2: 1534263508Sdim lane = Q; 1535263508Sdim break; 1536263508Sdim } 1537263508Sdim Inst.addOperand(MCOperand::CreateImm(lane)); 1538263508Sdim 1539263508Sdim return MCDisassembler::Success; 1540263508Sdim} 1541263508Sdim 1542263508Sdimstatic DecodeStatus DecodeSHLLInstruction(MCInst &Inst, unsigned Insn, 1543263508Sdim uint64_t Address, 1544263508Sdim const void *Decoder) { 1545263508Sdim unsigned Rd = fieldFromInstruction(Insn, 0, 5); 1546263508Sdim unsigned Rn = fieldFromInstruction(Insn, 5, 5); 1547263508Sdim unsigned size = fieldFromInstruction(Insn, 22, 2); 1548263508Sdim unsigned Q = fieldFromInstruction(Insn, 30, 1); 1549263508Sdim 1550263508Sdim DecodeFPR128RegisterClass(Inst, Rd, Address, Decoder); 1551263508Sdim 1552263508Sdim if(Q) 1553263508Sdim DecodeFPR128RegisterClass(Inst, Rn, Address, Decoder); 1554263508Sdim else 1555263508Sdim DecodeFPR64RegisterClass(Inst, Rn, Address, Decoder); 1556263508Sdim 1557263508Sdim switch (size) { 1558263508Sdim case 0: 1559263508Sdim Inst.addOperand(MCOperand::CreateImm(8)); 1560263508Sdim break; 1561263508Sdim case 1: 1562263508Sdim Inst.addOperand(MCOperand::CreateImm(16)); 1563263508Sdim break; 1564263508Sdim case 2: 1565263508Sdim Inst.addOperand(MCOperand::CreateImm(32)); 1566263508Sdim break; 1567263508Sdim default : 1568263508Sdim return MCDisassembler::Fail; 1569263508Sdim } 1570263508Sdim return MCDisassembler::Success; 1571263508Sdim} 1572263508Sdim 1573