From b6fc49a460e5a0b3e6c39d4f68b6df29f4bc6308 Mon Sep 17 00:00:00 2001 From: noone Date: Thu, 22 Aug 2024 14:22:49 -0700 Subject: [PATCH 01/19] Bring in new decode logic This commit just brings it in and makes sure it builds, but doesn't change anything in the arch plugin to use it yet. --- arch/powerpc/CMakeLists.txt | 2 + arch/powerpc/decode/decode.c | 6635 ++++++++++++++++++++++++++++++++++ arch/powerpc/decode/decode.h | 1155 ++++++ 3 files changed, 7792 insertions(+) create mode 100644 arch/powerpc/decode/decode.c create mode 100644 arch/powerpc/decode/decode.h diff --git a/arch/powerpc/CMakeLists.txt b/arch/powerpc/CMakeLists.txt index d148c690a..66ba9068a 100644 --- a/arch/powerpc/CMakeLists.txt +++ b/arch/powerpc/CMakeLists.txt @@ -13,6 +13,8 @@ file(GLOB SOURCES il.cpp util.cpp *.h + decode/*.c + decode/*.h ) if(DEMO) diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c new file mode 100644 index 000000000..1548f4b18 --- /dev/null +++ b/arch/powerpc/decode/decode.c @@ -0,0 +1,6635 @@ +#include +#include + +#include "decode.h" + +// Documentation: +// * [ProgrammingEnvironments32]: "Programming Environments Manual for 32-bit +// Implementations of the PowerPC^TM Architecture" by Freescale/NXP +// + +// see stanford bit twiddling hacks +static int32_t sign_extend(uint32_t x, unsigned numBits) +{ + int32_t r; + int32_t const m = 1U << (numBits - 1); + + x = x & ((1U << numBits) - 1); + return (x ^ m) - m; +} + +static Register Gpr(uint32_t value) +{ + return NUPPC_REG_GPR0 + value; +} + +static Register Fr(uint32_t value) +{ + return NUPPC_REG_FR0 + value; +} + +static Register Crf(uint32_t value) +{ + return NUPPC_REG_CRF0 + value; +} + +static Register Crbit(uint32_t value) +{ + return NUPPC_REG_CR_BIT0 + value; +} + +static Register AltivecVr(uint32_t value) +{ + return NUPPC_REG_AV_VR0 + value; +} + +static Register VsxVr(uint32_t value) +{ + return NUPPC_REG_VSX_VR0 + value; +} + +static void PushUIMMValue(Instruction* instruction, uint32_t uimm) +{ + instruction->operands[instruction->numOperands].cls = UIMM; + instruction->operands[instruction->numOperands].uimm = uimm; + ++instruction->numOperands; +} + +static void PushSIMMValue(Instruction* instruction, int32_t simm) +{ + instruction->operands[instruction->numOperands].cls = SIMM; + instruction->operands[instruction->numOperands].simm = simm; + ++instruction->numOperands; +} + +static void PushRegister(Instruction* instruction, OperandClass cls, Register reg) +{ + instruction->operands[instruction->numOperands].cls = cls; + instruction->operands[instruction->numOperands].reg = reg; + ++instruction->numOperands; +} + +static uint64_t ComputeBranchTarget(Instruction* instruction, uint64_t address, uint32_t word32) +{ + int32_t bd = (int32_t)((int16_t)(word32 & 0xfffc)); + + return instruction->flags.aa ? bd : address + bd; +} + +// this assumes that instruction->flags.aa has been properly set! +static void PushBranchTarget(Instruction* instruction, uint64_t address, uint32_t word32) +{ + instruction->operands[instruction->numOperands].cls = LABEL; + instruction->operands[instruction->numOperands].label = ComputeBranchTarget(instruction, address, word32); + ++instruction->numOperands; +} + +static uint32_t GetA(uint32_t word32) +{ + return (word32 >> 16) & 0x1f; +} + +static uint32_t GetB(uint32_t word32) +{ + return (word32 >> 11) & 0x1f; +} + +static uint32_t GetC(uint32_t word32) +{ + return (word32 >> 6) & 0x1f; +} + +static uint32_t GetD(uint32_t word32) +{ + return (word32 >> 21) & 0x1f; +} + +static uint32_t GetS(uint32_t word32) +{ + return (word32 >> 21) & 0x1f; +} + +static void PushRA(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_RA, Gpr(GetA(word32))); +} + +static void PushRAor0(Instruction* instruction, uint32_t word32) +{ + uint32_t ra = GetA(word32); + + if (ra == 0) + PushUIMMValue(instruction, 0); + else + PushRegister(instruction, REG_RA, Gpr(ra)); +} + +static void PushRB(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_RB, Gpr(GetB(word32))); +} + +static void PushRD(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_RD, Gpr(GetD(word32))); +} + +static void PushRS(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_RS, Gpr(GetS(word32))); +} + +static void PushFRA(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_FRA, Fr(GetA(word32))); +} + +static void PushFRB(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_FRB, Fr(GetB(word32))); +} + +static void PushFRC(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_FRC, Fr(GetC(word32))); +} + +static void PushFRD(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_FRD, Fr(GetD(word32))); +} + +static void PushFRS(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_FRS, Fr(GetS(word32))); +} + +static void PushCRFD(Instruction* instruction, uint32_t word32) +{ + uint32_t crfd = (word32 >> 23) & 0x7; + PushRegister(instruction, REG_CRFD, Crf(crfd)); +} + +static void PushCRFS(Instruction* instruction, uint32_t word32) +{ + uint32_t crfs = (word32 >> 18) & 0x7; + PushRegister(instruction, REG_CRFS, Crf(crfs)); +} + +static void PushCRFDImplyCR0(Instruction* instruction, uint32_t word32) +{ + uint32_t crfd = (word32 >> 23) & 0x7; + + if (crfd) + PushRegister(instruction, REG_CRFD, Crf(crfd)); +} + +static void PushCRBitA(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_CRBA, Crbit(GetA(word32))); +} + +static void PushCRBitB(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_CRBB, Crbit(GetB(word32))); +} + +static void PushCRBitD(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, REG_CRBD, Crbit(GetD(word32))); +} + +static void PushMem(Instruction* instruction, OperandClass cls, Register reg, int32_t offset) +{ + instruction->operands[instruction->numOperands].cls = cls; + instruction->operands[instruction->numOperands].mem.reg = reg; + instruction->operands[instruction->numOperands].mem.offset = offset; + ++instruction->numOperands; +} + +static uint32_t GetBI(uint32_t word32) +{ + return (word32 >> 16) & 0x1f; +} + +static uint32_t GetBO(uint32_t word32) +{ + return (word32 >> 21) & 0x1f; +} + +static void FillBranchLikelyHint(Instruction* instruction, uint32_t word32) +{ + uint32_t bo = GetBO(word32); + uint32_t bi = GetBI(word32); + + switch (bo >> 2) + { + // 001at + // 011at + case 1: + case 3: + instruction->flags.branchLikelyHint = bo & 0x3; + break; + + // 1a00t + // 1a01t + case 4: + case 6: + instruction->flags.branchLikelyHint = ((bo >> 2) & 0x2) | (bo & 0x1); + break; + + // all others don't have hints + default: + instruction->flags.branchLikelyHint = 0; + } +} + +static void PushMemRA(Instruction* instruction, uint32_t word32) +{ + int32_t offset = (int32_t)((int16_t)(word32 & 0xffff)); + PushMem(instruction, MEM_RA, Gpr(GetA(word32)), offset); +} + +static uint32_t GetVsxA(uint32_t word32) +{ + uint32_t ax = (word32 >> 2) & 0x1; + uint32_t a = (word32 >> 16) & 0x1f; + + return (ax << 5) | a; +} + +static void PushVsxA(Instruction* instruction, uint32_t word32, VsxWidth width) +{ + PushRegister(instruction, + width == VSX_WIDTH_FULL ? REG_VSX_RA : REG_VSX_RA_DWORD0, + VsxVr(GetVsxA(word32))); +} + +static uint32_t GetVsxB(uint32_t word32) +{ + uint32_t bx = (word32 >> 1) & 0x1; + uint32_t b = (word32 >> 11) & 0x1f; + + return (bx << 5) | b; +} + +static void PushVsxB(Instruction* instruction, uint32_t word32, VsxWidth width) +{ + PushRegister(instruction, + width == VSX_WIDTH_FULL ? REG_VSX_RB : REG_VSX_RB_DWORD0, + VsxVr(GetVsxB(word32))); +} + +static uint32_t GetVsxC(uint32_t word32) +{ + uint32_t cx = (word32 >> 3) & 0x1; + uint32_t c = (word32 >> 6) & 0x1f; + + return (cx << 5) | c; +} + +static void PushVsxC(Instruction* instruction, uint32_t word32, VsxWidth width) +{ + PushRegister(instruction, + width == VSX_WIDTH_FULL ? REG_VSX_RC : REG_VSX_RC_DWORD0, + VsxVr(GetVsxC(word32))); +} + +static uint32_t GetVsxD(uint32_t word32) +{ + uint32_t dx = word32 & 0x1; + uint32_t d = (word32 >> 21) & 0x1f; + + return (dx << 5) | d; +} + +static void PushVsxD(Instruction* instruction, uint32_t word32, VsxWidth width) +{ + PushRegister(instruction, + width == VSX_WIDTH_FULL ? REG_VSX_RD : REG_VSX_RD_DWORD0, + VsxVr(GetVsxD(word32))); +} + +static void PushVsxS(Instruction* instruction, uint32_t word32, VsxWidth width) +{ + uint32_t sx = word32 & 0x1; + uint32_t s = (word32 >> 21) & 0x1f; + PushRegister(instruction, + width == VSX_WIDTH_FULL ? REG_VSX_RS : REG_VSX_RS_DWORD0, + VsxVr((sx << 5) | s)); +} + +static uint32_t GetSpecialRegisterCommon(uint32_t word32) +{ + uint32_t xr5_9 = (word32 >> 16) & 0x1f; + uint32_t xr0_4 = (word32 >> 11) & 0x1f; + uint32_t xr = (xr0_4 << 5) | xr5_9; + + return xr; +} + +static uint32_t GetME(uint32_t word32) +{ + return (word32 >> 1) & 0x1f; +} + +static uint32_t GetMB(uint32_t word32) +{ + return (word32 >> 6) & 0x1f; +} + +static uint32_t GetSH(uint32_t word32) +{ + return (word32 >> 11) & 0x1f; +} + +static uint32_t GetSH64(uint32_t word32) +{ + uint32_t sh5 = (word32 >> 1) & 0x1; + uint32_t sh4_0 = (word32 >> 11) & 0x1f; + + return (sh5 << 5) | sh4_0; +} + +static uint32_t GetMX64(uint32_t word32) +{ + uint32_t mx = (word32 >> 5) & 0x3f; + + // x <- mx5 || mx[0:5] in powerpc's stupid bit order + return ((mx & 0x1) << 5) | (mx >> 1); +} + +static void PushAltivecVA(Instruction* instruction, uint32_t word32) +{ + uint32_t va = (word32 >> 16) & 0x1f; + PushRegister(instruction, REG_AV_VA, AltivecVr(va)); +} + +static void PushAltivecVB(Instruction* instruction, uint32_t word32) +{ + uint32_t vb = (word32 >> 11) & 0x1f; + PushRegister(instruction, REG_AV_VB, AltivecVr(vb)); +} + +static void PushAltivecVC(Instruction* instruction, uint32_t word32) +{ + uint32_t vc = (word32 >> 6) & 0x1f; + PushRegister(instruction, REG_AV_VC, AltivecVr(vc)); +} + +static void PushAltivecVD(Instruction* instruction, uint32_t word32) +{ + uint32_t vd = (word32 >> 21) & 0x1f; + PushRegister(instruction, REG_AV_VD, AltivecVr(vd)); +} + +static void PushAltivecVS(Instruction* instruction, uint32_t word32) +{ + uint32_t vs = (word32 >> 21) & 0x1f; + PushRegister(instruction, REG_AV_VS, AltivecVr(vs)); +} + +static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) +{ + uint32_t subop = word32 & 0x3f; + + uint32_t a = GetA(word32); + uint32_t b = GetB(word32); + uint32_t d = GetD(word32); + + switch (subop) + { + case 0x20: + return PPC_ID_AV_VMHADDSHS; + + case 0x21: + return PPC_ID_AV_VMHRADDSHS; + + case 0x22: + return PPC_ID_AV_VMLADDUHM; + + case 0x24: + return PPC_ID_AV_VMSUMUBM; + + case 0x25: + return PPC_ID_AV_VMSUMMBM; + + case 0x26: + return PPC_ID_AV_VMSUMUHM; + + case 0x27: + return PPC_ID_AV_VMSUMUHS; + + case 0x28: + return PPC_ID_AV_VMSUMSHM; + + case 0x29: + return PPC_ID_AV_VMSUMSHS; + + case 0x2a: + return PPC_ID_AV_VSEL; + + case 0x2b: + return PPC_ID_AV_VPERM; + + case 0x2c: + if ((word32 & 0x400) != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VSLDOI; + + case 0x2e: + return PPC_ID_AV_VMADDFP; + + case 0x2f: + return PPC_ID_AV_VNMSUBFP; + + default: + ; + } + + subop = word32 & 0x7ff; + switch (subop) + { + case 0x000: + return PPC_ID_AV_VADDUBM; + + case 0x002: + return PPC_ID_AV_VMAXUB; + + case 0x004: + return PPC_ID_AV_VRLB; + + + case 0x006: + case 0x406: + return PPC_ID_AV_VCMPEQUBx; + + case 0x008: + return PPC_ID_AV_VMULOUB; + + case 0x00a: + return PPC_ID_AV_VADDFP; + + case 0x00c: + return PPC_ID_AV_VMRGHB; + + case 0x00e: + return PPC_ID_AV_VPKUHUM; + + case 0x040: + return PPC_ID_AV_VADDUHM; + + case 0x042: + return PPC_ID_AV_VMAXUH; + + case 0x044: + return PPC_ID_AV_VRLH; + + + case 0x046: + case 0x446: + return PPC_ID_AV_VCMPEQUHx; + + case 0x048: + return PPC_ID_AV_VMULOUH; + + case 0x04a: + return PPC_ID_AV_VSUBFP; + + case 0x04c: + return PPC_ID_AV_VMRGHH; + + case 0x04e: + return PPC_ID_AV_VPKUWUM; + + case 0x080: + return PPC_ID_AV_VADDUWM; + + case 0x082: + return PPC_ID_AV_VMAXUW; + + case 0x084: + return PPC_ID_AV_VRLW; + + + case 0x086: + case 0x486: + return PPC_ID_AV_VCMPEQUWx; + + case 0x88: + return PPC_ID_AV_VMULOUW; + + case 0x89: + return PPC_ID_AV_VMULUWM; + + case 0x08c: + return PPC_ID_AV_VMRGHW; + + case 0x08e: + return PPC_ID_AV_VPKUHUS; + + case 0x0c0: + return PPC_ID_AV_VADDUDM; + + case 0x0c2: + return PPC_ID_AV_VMAXUD; + + case 0x0c4: + return PPC_ID_AV_VRLD; + + + case 0x0c6: + case 0x4c6: + return PPC_ID_AV_VCMPEQFPx; + + case 0x0c7: + case 0x4c7: + return PPC_ID_AV_VCMPEQUDx; + + case 0x0ce: + return PPC_ID_AV_VPKUWUS; + + case 0x102: + return PPC_ID_AV_VMAXSB; + + case 0x104: + return PPC_ID_AV_VSLB; + + case 0x108: + return PPC_ID_AV_VMULOSB; + + case 0x10a: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VREFP; + + case 0x10c: + return PPC_ID_AV_VMRGLB; + + case 0x10e: + return PPC_ID_AV_VPKSHUS; + + case 0x142: + return PPC_ID_AV_VMAXSH; + + case 0x144: + return PPC_ID_AV_VSLH; + + case 0x148: + return PPC_ID_AV_VMULOSH; + + case 0x14a: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VRSQRTEFP; + + case 0x14c: + return PPC_ID_AV_VMRGLH; + + case 0x14e: + return PPC_ID_AV_VPKSWUS; + + case 0x180: + return PPC_ID_AV_VADDCUW; + + case 0x182: + return PPC_ID_AV_VMAXSW; + + case 0x184: + return PPC_ID_AV_VSLW; + + case 0x188: + return PPC_ID_AV_VMULOSW; + + case 0x18a: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VEXPTEFP; + + case 0x18c: + return PPC_ID_AV_VMRGLW; + + case 0x18e: + return PPC_ID_AV_VPKSHSS; + + case 0x1c2: + return PPC_ID_AV_VMAXSD; + + case 0x1c4: + return PPC_ID_AV_VSL; + + case 0x1c6: + case 0x5c6: + return PPC_ID_AV_VCMPGEFPx; + + case 0x1ca: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VLOGEFP; + + case 0x1ce: + return PPC_ID_AV_VPKSWSS; + + case 0x200: + return PPC_ID_AV_VADDUBS; + + case 0x202: + return PPC_ID_AV_VMINUB; + + case 0x204: + return PPC_ID_AV_VSRB; + + + case 0x206: + case 0x606: + return PPC_ID_AV_VCMPGTUBx; + + case 0x208: + return PPC_ID_AV_VMULEUB; + + case 0x20a: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VRFIN; + + case 0x20c: + return PPC_ID_AV_VSPLTB; + + case 0x20e: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VUPKHSB; + + case 0x240: + return PPC_ID_AV_VADDUHS; + + case 0x242: + return PPC_ID_AV_VMINUH; + + case 0x244: + return PPC_ID_AV_VSRH; + + case 0x246: + case 0x646: + return PPC_ID_AV_VCMPGTUHx; + + case 0x248: + return PPC_ID_AV_VMULEUH; + + case 0x24a: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VRFIZ; + + case 0x24c: + return PPC_ID_AV_VSPLTH; + + case 0x24e: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VUPKHSH; + + case 0x280: + return PPC_ID_AV_VADDUWS; + + case 0x282: + return PPC_ID_AV_VMINUW; + + case 0x284: + return PPC_ID_AV_VSRW; + + case 0x286: + case 0x686: + return PPC_ID_AV_VCMPGTUWx; + + case 0x288: + return PPC_ID_AV_VMULEUW; + + case 0x28a: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VRFIP; + + case 0x28c: + return PPC_ID_AV_VSPLTW; + + case 0x28e: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VUPKLSB; + + case 0x2c2: + return PPC_ID_AV_VMINUD; + + case 0x2c4: + return PPC_ID_AV_VSR; + + case 0x2c6: + case 0x6c6: + return PPC_ID_AV_VCMPGTFPx; + + case 0x2c7: + case 0x6c7: + return PPC_ID_AV_VCMPGTUDx; + + case 0x2ca: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VRFIM; + + case 0x2ce: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VUPKLSH; + + case 0x300: + return PPC_ID_AV_VADDSBS; + + case 0x302: + return PPC_ID_AV_VMINSB; + + case 0x304: + return PPC_ID_AV_VSRAB; + + case 0x306: + case 0x706: + return PPC_ID_AV_VCMPGTSBx; + + case 0x308: + return PPC_ID_AV_VMULESB; + + case 0x30a: + return PPC_ID_AV_VCFUX; + + case 0x30c: + if ((b) != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VSPLTISB; + + case 0x30e: + return PPC_ID_AV_VPKPX; + + case 0x340: + return PPC_ID_AV_VADDSHS; + + case 0x342: + return PPC_ID_AV_VMINSH; + + case 0x344: + return PPC_ID_AV_VSRAH; + + case 0x346: + case 0x746: + return PPC_ID_AV_VCMPGTSHx; + + case 0x348: + return PPC_ID_AV_VMULESH; + + case 0x34a: + return PPC_ID_AV_VCFSX; + + case 0x34c: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VSPLTISH; + + case 0x34e: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VUPKHPX; + + case 0x380: + return PPC_ID_AV_VADDSWS; + + case 0x382: + return PPC_ID_AV_VMINSW; + + case 0x384: + return PPC_ID_AV_VSRAW; + + case 0x386: + case 0x786: + return PPC_ID_AV_VCMPGTSWx; + + case 0x388: + return PPC_ID_AV_VMULESW; + + case 0x38a: + return PPC_ID_AV_VCTUXS; + + case 0x38c: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VSPLTISW; + + case 0x3c2: + return PPC_ID_AV_VMINSD; + + case 0x3c4: + return PPC_ID_AV_VSRAD; + + case 0x3c6: + case 0x7c6: + return PPC_ID_AV_VCMPBFPx; + + case 0x3c7: + case 0x7c7: + return PPC_ID_AV_VCMPGTSDx; + + case 0x3ca: + return PPC_ID_AV_VCTSXS; + + case 0x3ce: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VUPKLPX; + + case 0x400: + return PPC_ID_AV_VSUBUBM; + + case 0x402: + return PPC_ID_AV_VAVGUB; + + case 0x404: + return PPC_ID_AV_VAND; + + case 0x40a: + return PPC_ID_AV_VMAXFP; + + case 0x40c: + return PPC_ID_AV_VSLO; + + case 0x440: + return PPC_ID_AV_VSUBUHM; + + case 0x442: + return PPC_ID_AV_VAVGUH; + + case 0x444: + return PPC_ID_AV_VANDC; + + case 0x44a: + return PPC_ID_AV_VMINFP; + + case 0x44c: + return PPC_ID_AV_VSRO; + + case 0x480: + return PPC_ID_AV_VSUBUWM; + + case 0x482: + return PPC_ID_AV_VAVGUW; + + case 0x484: + return PPC_ID_AV_VOR; + + case 0x4c0: + return PPC_ID_AV_VSUBUDM; + + case 0x4c4: + return PPC_ID_AV_VXOR; + + case 0x502: + return PPC_ID_AV_VAVGSB; + + case 0x504: + return PPC_ID_AV_VNOR; + + case 0x542: + return PPC_ID_AV_VAVGSH; + + case 0x544: + return PPC_ID_AV_VORC; + + case 0x580: + return PPC_ID_AV_VSUBCUW; + + case 0x582: + return PPC_ID_AV_VAVGSW; + + case 0x584: + return PPC_ID_AV_VNAND; + + case 0x5c4: + return PPC_ID_AV_VSLD; + + case 0x600: + return PPC_ID_AV_VSUBUBS; + + case 0x604: + if ((a != 0) || (b != 0)) + return PPC_ID_INVALID; + + return PPC_ID_AV_MFVSCR; + + case 0x608: + return PPC_ID_AV_VSUM4UBS; + + case 0x640: + return PPC_ID_AV_VSUBUHS; + + case 0x644: + if ((d != 0) || (a != 0)) + return PPC_ID_INVALID; + + return PPC_ID_AV_MTVSCR; + + case 0x648: + return PPC_ID_AV_VSUM4SHS; + + case 0x680: + return PPC_ID_AV_VSUBUWS; + + case 0x684: + return PPC_ID_AV_VEQV; + + case 0x688: + return PPC_ID_AV_VSUM2SWS; + + case 0x6c4: + return PPC_ID_AV_VSRD; + + case 0x700: + return PPC_ID_AV_VSUBSBS; + + case 0x702: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VCLZB; + + case 0x703: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VPOPCNTB; + + case 0x708: + return PPC_ID_AV_VSUM4SBS; + + case 0x740: + return PPC_ID_AV_VSUBSHS; + + case 0x742: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VCLZH; + + case 0x743: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VPOPCNTH; + + case 0x780: + return PPC_ID_AV_VSUBSWS; + + case 0x782: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VCLZW; + + case 0x783: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VPOPCNTW; + + case 0x788: + return PPC_ID_AV_VSUMSWS; + + case 0x7c2: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VCLZD; + + case 0x7c3: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VPOPCNTD; + + default: + return PPC_ID_INVALID; + } +} + +static InstructionId Decode0x13(uint32_t word32, uint32_t decodeFlags) +{ + uint32_t a = GetA(word32); + uint32_t b = GetB(word32); + uint32_t d = GetD(word32); + + uint32_t subop = word32 & 0x7ff; + switch (subop) + { + case 0x000: + if ((word32 & 0x0063f800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MCRF; + + case 0x020: + case 0x021: + { + // for PowerPC, this is 0x0000f800, but POWER + // introduces BH bits + if ((word32 & 0x0000e000) != 0) + return PPC_ID_INVALID; + + // these are the only values that capstone recognizes + // as BLR/BLRL + if ((word32 & 0xfffffffe) == 0x4e800020) + return PPC_ID_BLRx; + + uint32_t bo = GetBO(word32); + uint32_t bi = GetBI(word32); + + // mask away the "y" bit + switch (bo & 0x1e) + { + case 0: return PPC_ID_BDNZFLRx; + case 2: return PPC_ID_BDZFLRx; + + case 4: + case 6: + switch (bi & 0x3) + { + case 0: return PPC_ID_BGELRx; + case 1: return PPC_ID_BLELRx; + case 2: return PPC_ID_BNELRx; + case 3: return PPC_ID_BNSLRx; + + // should be unreachable + default: return PPC_ID_BFLRx; + } + + case 8: return PPC_ID_BDNZTLRx; + case 10: return PPC_ID_BDZTLRx; + + case 12: + case 14: + switch (bi & 0x3) + { + case 0: return PPC_ID_BLTLRx; + case 1: return PPC_ID_BGTLRx; + case 2: return PPC_ID_BEQLRx; + case 3: return PPC_ID_BSOLRx; + + // should be unreachable + default: return PPC_ID_BTLRx; + } + + // technically these aren't terribly well defined + // when BI != 0, since these BOs don't involve + // a condition bit to test in BI to test against + case 16: + case 24: + return PPC_ID_BDNZLRx; + + case 18: + case 26: + return PPC_ID_BDZLRx; + + // these are to match capstone's behavior, but + // not super sure why since they seem to match + // the "Branch always" part of the BO table + case 20: + case 28: + return PPC_ID_BDNZLRx; + case 22: + case 30: + return PPC_ID_BDZLRx; + + default: return PPC_ID_BCLRx; + } + } + + case 0x024: + if ((word32 & 0x03fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_RFID; + + case 0x042: + if (a == b) + return PPC_ID_CRNOT; + else + return PPC_ID_CRNOR; + + case 0x04c: + if ((word32 & 0x03fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_RFMCI; + + case 0x04e: + if ((word32 & 0x03fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_RFDI; + + case 0x064: + if ((word32 & 0x03fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_RFI; + + case 0x066: + if ((word32 & 0x03fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_RFCI; + + case 0x102: + return PPC_ID_CRANDC; + + case 0x12c: + if ((word32 & 0x3fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_ISYNC; + + case 0x182: + if (d == a && d == b) + return PPC_ID_CRCLR; + else + return PPC_ID_CRXOR; + + case 0x1c2: + return PPC_ID_CRNAND; + + case 0x202: + return PPC_ID_CRAND; + + case 0x242: + if (d == a && d == b) + return PPC_ID_CRSET; + else + return PPC_ID_CREQV; + + case 0x342: + return PPC_ID_CRORC; + + case 0x382: + if (a == b) + return PPC_ID_CRMOVE; + else + return PPC_ID_CROR; + + case 0x420: + case 0x421: + // for PowerPC, this is 0x0000f800, but POWER + // introduces BH bits + if ((word32 & 0x0000e000) != 0) + return PPC_ID_INVALID; + + // these are the only values that capstone recognizes + // as BLR/BLRL + if ((word32 & 0xfffffffe) == 0x4e800420) + return PPC_ID_BCTRx; + + uint32_t bo = GetBO(word32); + uint32_t bi = GetBI(word32); + + // mask away the "y" bit + switch (bo & 0x1e) + { + case 0: return PPC_ID_BDNZFCTRx; + case 2: return PPC_ID_BDZFCTRx; + + case 4: + case 6: + switch (bi & 0x3) + { + case 0: return PPC_ID_BGECTRx; + case 1: return PPC_ID_BLECTRx; + case 2: return PPC_ID_BNECTRx; + case 3: return PPC_ID_BNSCTRx; + + // should be unreachable + default: return PPC_ID_BFCTRx; + } + + case 8: return PPC_ID_BDNZTCTRx; + case 10: return PPC_ID_BDZTCTRx; + + case 12: + case 14: + switch (bi & 0x3) + { + case 0: return PPC_ID_BLTCTRx; + case 1: return PPC_ID_BGTCTRx; + case 2: return PPC_ID_BEQCTRx; + case 3: return PPC_ID_BSOCTRx; + + // should be unreachable + default: return PPC_ID_BTCTRx; + } + + // technically these aren't terribly well defined + // when BI != 0, since these BOs don't involve + // a condition bit to test in BI to test against + case 16: + case 24: + return PPC_ID_BDNZCTRx; + + // these represent "branch always" in the BO field, so it's + // not super clear why these disassemble to bdnzctr + case 20: + case 28: + return PPC_ID_BDNZCTRx; + + case 18: + case 22: + case 26: + return PPC_ID_BDZCTRx; + + // these represent "branch always" in the BO field, so it's + // not super clear why these disassemble to bdzctr + case 30: + return PPC_ID_BDZCTRx; + + default: return PPC_ID_BCCTRx; + } + + default: + return PPC_ID_INVALID; + } +} + +static InstructionId Decode0x1E(uint32_t word32, uint32_t decodeFlags) +{ + uint32_t sh = GetSH64(word32); + uint32_t mx = GetMX64(word32); + + uint32_t subop = (word32 >> 1) & 0xf; + switch (subop) + { + case 0x0: + case 0x1: + if (mx == 0) + return PPC_ID_ROTLDIx; + else if (sh == 0) + return PPC_ID_CLRLDIx; + else + return PPC_ID_RLDICLx; + + case 0x2: + case 0x3: + if (sh + mx == 63) + return PPC_ID_SLDIx; + else + return PPC_ID_RLDICRx; + + case 0x4: + case 0x5: + return PPC_ID_RLDICx; + + case 0x6: + case 0x7: + return PPC_ID_RLDIMIx; + + case 0x8: + if (mx == 0) + return PPC_ID_ROTLDx; + else + return PPC_ID_RLDCLx; + + case 0x9: + return PPC_ID_RLDCRx; + + default: + return PPC_ID_INVALID; + } +} + +static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) +{ + uint32_t a = GetA(word32); + uint32_t b = GetB(word32); + uint32_t d = GetD(word32); + uint32_t s = GetS(word32); + + uint32_t subop = word32 & 0x3f; + switch (subop) + { + case 0x1e: + return PPC_ID_ISEL; + + default: break; + } + + subop = word32 & 0x7ff; + switch (subop) + { + case 0x000: + if ((word32 & 0x00400000) == 0) + { + if ((word32 & 0x00200000) != 0) + { + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return PPC_ID_CMPD; + } + else + { + return PPC_ID_CMPW; + } + } + + return PPC_ID_INVALID; + + case 0x008: + { + uint32_t to = (word32 >> 21) & 0x1f; + + switch (to) + { + case 1: return PPC_ID_TWLGT; + case 2: return PPC_ID_TWLLT; + case 4: return PPC_ID_TWEQ; + case 8: return PPC_ID_TWGT; + case 16: return PPC_ID_TWLT; + case 24: return PPC_ID_TWNE; + case 31: return PPC_ID_TWU; + default: return PPC_ID_TW; + } + } + + case 0x00c: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_LVSL; + + return PPC_ID_INVALID; + + case 0x00e: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_LVEBX; + + return PPC_ID_INVALID; + + case 0x010: + case 0x011: + case 0x410: + case 0x411: + return PPC_ID_SUBFCx; + + case 0x012: + case 0x013: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return PPC_ID_MULHDUx; + + case 0x014: + case 0x015: + case 0x414: + case 0x415: + return PPC_ID_ADDCx; + + case 0x016: + case 0x017: + return PPC_ID_MULHWUx; + + case 0x026: + if ((word32 & 0x00100000) != 0) + { + if ((word32 & 0x800) != 0) + return PPC_ID_INVALID; + + uint32_t fxm = (word32 >> 12) & 0xff; + if (fxm == 0) + return PPC_ID_INVALID; + + return PPC_ID_MFOCRF; + } + + if ((word32 & 0x000ff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MFCR; + + case 0x028: + return PPC_ID_LWARX; + + case 0x02a: + return PPC_ID_LDX; + + case 0x2c: + if ((word32 & 0x02000000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_ICBT; + + case 0x02e: + return PPC_ID_LWZX; + + case 0x030: + case 0x031: + return PPC_ID_SLWx; + + case 0x034: + case 0x035: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_CNTLZWx; + + case 0x036: + case 0x037: + return PPC_ID_SLDx; + + case 0x038: + case 0x039: + return PPC_ID_ANDx; + + case 0x040: + if ((word32 & 0x00400000) == 0) + { + if ((word32 & 0x00200000) != 0) + { + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return PPC_ID_CMPLD; + } + else + { + return PPC_ID_CMPLW; + } + + break; + } + + return PPC_ID_INVALID; + + case 0x04c: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_LVSR; + + return PPC_ID_INVALID; + + case 0x04e: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_LVEHX; + + return PPC_ID_INVALID; + + case 0x050: + case 0x051: + case 0x450: + case 0x451: + return PPC_ID_SUBFx; + + case 0x06a: + return PPC_ID_LDUX; + + case 0x06c: + if (d != 0) + return PPC_ID_INVALID; + + return PPC_ID_DCBST; + + case 0x06e: + return PPC_ID_LWZUX; + + case 0x074: + case 0x075: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_CNTLZDx; + + case 0x078: + case 0x079: + return PPC_ID_ANDCx; + + case 0x07c: + { + if ((word32 & 0x039ff800) != 0) + return false; + + uint32_t wc = (word32 >> 21) & 0x3; + switch (wc) + { + case 0: return PPC_ID_WAIT; + case 1: return PPC_ID_WAITRSV; + case 2: return PPC_ID_WAITIMPL; + + default: return PPC_ID_WAIT; + } + } + + case 0x088: + { + uint32_t to = (word32 >> 21) & 0x1f; + + switch (to) + { + case 1: return PPC_ID_TDLGT; + case 2: return PPC_ID_TDLLT; + case 4: return PPC_ID_TDEQ; + case 8: return PPC_ID_TDGT; + case 16: return PPC_ID_TDLT; + case 24: return PPC_ID_TDNE; + case 31: return PPC_ID_TDU; + default: return PPC_ID_TD; + } + } + + case 0x08e: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_LVEWX; + + return PPC_ID_INVALID; + + case 0x092: + case 0x093: + if ((decodeFlags & DECODE_FLAGS_PPC64) != 0) + return PPC_ID_MULHDx; + + return PPC_ID_INVALID; + + + case 0x096: + case 0x097: + return PPC_ID_MULHWx; + + case 0x0a6: + if ((a != 0) || (b != 0)) + return PPC_ID_INVALID; + + return PPC_ID_MFMSR; + + case 0x0a8: + return PPC_ID_LDARX; + + case 0x0ac: + if (d != 0) + return PPC_ID_INVALID; + + return PPC_ID_DCBF; + + case 0x0ae: + return PPC_ID_LBZX; + + case 0x0ce: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_LVX; + + return PPC_ID_INVALID; + + case 0x0d0: + case 0x0d1: + case 0x4d0: + case 0x4d1: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_NEGx; + + case 0x0ee: + return PPC_ID_LBZUX; + + case 0x0f8: + case 0x0f9: + return PPC_ID_NORx; + + case 0x106: + if ((a != 0) || (b != 0)) + return PPC_ID_INVALID; + + return PPC_ID_WRTEE; + + case 0x10e: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_STVEBX; + + return PPC_ID_INVALID; + + case 0x110: + case 0x111: + case 0x510: + case 0x511: + return PPC_ID_SUBFEx; + + case 0x114: + case 0x115: + case 0x514: + case 0x515: + return PPC_ID_ADDEx; + + case 0x120: + if ((word32 & 0x00100000) != 0) + { + if ((word32 & 0x800) != 0) + return PPC_ID_INVALID; + + uint32_t fxm = (word32 >> 12) & 0xff; + if (fxm == 0) + return PPC_ID_INVALID; + + return PPC_ID_MTOCRF; + } + + if ((word32 & 0x00000800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MTCRF; + + case 0x124: + if ((a != 0) || (b != 0)) + return PPC_ID_INVALID; + + return PPC_ID_MTMSR; + + case 0x12a: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return PPC_ID_STDX; + + case 0x12d: + return PPC_ID_STWCX; + + case 0x12e: + return PPC_ID_STWX; + + case 0x146: + if ((word32 & 0x03ff7800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_WRTEEI; + + case 0x14e: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_STVEHX; + + return PPC_ID_INVALID; + + case 0x164: + if ((a != 0) || (b != 0)) + return PPC_ID_INVALID; + + return PPC_ID_MTMSRD; + + case 0x16a: + return PPC_ID_STDUX; + + case 0x16e: + return PPC_ID_STWUX; + + case 0x18e: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_STVEWX; + + return PPC_ID_INVALID; + + case 0x190: + case 0x191: + case 0x590: + case 0x591: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SUBFZEx; + + case 0x194: + case 0x195: + case 0x594: + case 0x595: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_ADDZEx; + + case 0x1a4: + if ((word32 & 0x0010f800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MTSR; + + case 0x1ad: + return PPC_ID_STDCX; + + case 0x1ae: + return PPC_ID_STBX; + + case 0x1ce: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_STVX; + + return PPC_ID_INVALID; + + case 0x1d0: + case 0x1d1: + case 0x5d0: + case 0x5d1: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SUBFMEx; + + case 0x1d2: + case 0x1d3: + case 0x5d2: + case 0x5d3: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return PPC_ID_MULLDx; + + case 0x1d4: + case 0x1d5: + case 0x5d4: + case 0x5d5: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_ADDMEx; + + case 0x1d6: + case 0x1d7: + case 0x5d6: + case 0x5d7: + return PPC_ID_MULLWx; + + case 0x1e4: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_MTSRIN; + + case 0x1ec: + if (d != 0) + return PPC_ID_INVALID; + + return PPC_ID_DCBTST; + + case 0x1ee: + return PPC_ID_STBUX; + + case 0x214: + case 0x215: + case 0x614: + case 0x615: + return PPC_ID_ADDx; + + case 0x224: + if ((d != 0) || (a != 0)) + return PPC_ID_INVALID; + + return PPC_ID_TLBIEL; + + case 0x22c: + if (d != 0) + return PPC_ID_INVALID; + + return PPC_ID_DCBT; + + case 0x22e: + return PPC_ID_LHZX; + + case 0x238: + case 0x239: + return PPC_ID_EQVx; + + case 0x264: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_TLBIE; + + case 0x26c: + return PPC_ID_ECIWX; + + case 0x26e: + return PPC_ID_LHZUX; + + case 0x278: + case 0x279: + return PPC_ID_XORx; + + case 0x286: + { + uint32_t dcr = GetSpecialRegisterCommon(word32); + + switch (dcr) + { + case 0x80: return PPC_ID_MFBR0; + case 0x81: return PPC_ID_MFBR1; + case 0x82: return PPC_ID_MFBR2; + case 0x83: return PPC_ID_MFBR3; + case 0x84: return PPC_ID_MFBR4; + case 0x85: return PPC_ID_MFBR5; + case 0x86: return PPC_ID_MFBR6; + case 0x87: return PPC_ID_MFBR7; + + default: return PPC_ID_MFDCR; + } + } + + case 0x298: + case 0x299: + if ((decodeFlags & DECODE_FLAGS_VSX) == 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_LXVDSX; + + case 0x2a6: + { + uint32_t spr = GetSpecialRegisterCommon(word32); + + // there are a bunch of other MF + // instructions; instead of handling them all, we just + // give a few common SPRs their own special opcodes, and + // bundle the rest into MFSPR + // + // this avoids adding a bazillion separate instructions + // that need to be lifted separately, AND are highly + // arch-dependent + switch (spr) + { + case 1: return PPC_ID_MFXER; + case 8: return PPC_ID_MFLR; + case 9: return PPC_ID_MFCTR; + + default: return PPC_ID_MFSPR; + } + } + + case 0x2aa: + return PPC_ID_LWAX; + + case 0x2ac: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) == 0) + return PPC_ID_INVALID; + + if ((word32 & 0x01800000) != 0) + return PPC_ID_INVALID; + + if ((word32 & 0x02000000) != 0) + return PPC_ID_AV_DSTT; + else + return PPC_ID_AV_DST; + + case 0x2ae: + return PPC_ID_LHAX; + + case 0x2ce: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_LVXL; + + return PPC_ID_INVALID; + + case 0x2e4: + if ((word32 & 0x03fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_TLBIA; + + case 0x2e6: + { + uint32_t special = GetSpecialRegisterCommon(word32); + switch (special) + { + case 269: return PPC_ID_MFTBU; + + default: return PPC_ID_MFTB; + } + } + + case 0x2ea: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return PPC_ID_LWAUX; + + case 0x2ec: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) == 0) + return PPC_ID_INVALID; + + if ((word32 & 0x01800000) != 0) + return PPC_ID_INVALID; + + if ((word32 & 0x02000000) != 0) + return PPC_ID_AV_DSTSTT; + else + return PPC_ID_AV_DSTST; + + case 0x2ee: + return PPC_ID_LHAUX; + + case 0x2f4: + if (b != 0) + return PPC_ID_INVALID; + + // TODO: [Category: Server] + // TODO: [Category: Embedded.Phased-In] + return PPC_ID_POPCNTW; + + case 0x324: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SLBMTE; + + case 0x32e: + return PPC_ID_STHX; + + case 0x338: + case 0x339: + return PPC_ID_ORCx; + + case 0x364: + if ((d != 0) || (a != 0)) + return PPC_ID_INVALID; + + return PPC_ID_SLBIE; + + case 0x36c: + return PPC_ID_ECOWX; + + case 0x36e: + return PPC_ID_STHUX; + + case 0x378: + case 0x379: + // TODO: it would be nice to disassemble "mr.", but + // capstone doesn't handle this (and technically + // "mr." isn't listed as a valid instruction in + // the documentation, but it IS a bit more user + // friendly for disassembly purposes) + if (b == s && ((word32 & 0x1) == 0)) + return PPC_ID_MRx; + else + return PPC_ID_ORx; + + case 0x386: + { + uint32_t dcr = GetSpecialRegisterCommon(word32); + + switch (dcr) + { + case 0x80: return PPC_ID_MTBR0; + case 0x81: return PPC_ID_MTBR1; + case 0x82: return PPC_ID_MTBR2; + case 0x83: return PPC_ID_MTBR3; + case 0x84: return PPC_ID_MTBR4; + case 0x85: return PPC_ID_MTBR5; + case 0x86: return PPC_ID_MTBR6; + case 0x87: return PPC_ID_MTBR7; + + default: return PPC_ID_MTDCR; + } + } + + case 0x38c: + { + if ((word32 & 0x021ff800) != 0) + return PPC_ID_INVALID; + + uint32_t ct = (word32 >> 21) & 0xf; + + if (ct == 0) + return PPC_ID_DCCCI; + else + return PPC_ID_DCI; + } + + case 0x392: + case 0x393: + case 0x792: + case 0x793: + return PPC_ID_DIVDUx; + + case 0x396: + case 0x397: + case 0x796: + case 0x797: + return PPC_ID_DIVWUx; + + case 0x3a6: + { + uint32_t spr = GetSpecialRegisterCommon(word32); + + switch (spr) + { + // there are a bunch of other MF + // instructions; instead of handling them all, we just + // give a few common SPRs their own special opcodes, and + // bundle the rest into MFSPR + // + // this avoids adding a bazillion separate instructions + // that need to be lifted separately, AND are highly + // arch-dependent + case 1: return PPC_ID_MTXER; + case 8: return PPC_ID_MTLR; + case 9: return PPC_ID_MTCTR; + + default: return PPC_ID_MTSPR; + } + } + + case 0x3ac: + if (d != 0) + return PPC_ID_INVALID; + + return PPC_ID_DCBI; + + case 0x3b8: + case 0x3b9: + return PPC_ID_NANDx; + + case 0x3ce: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_STVXL; + + return PPC_ID_INVALID; + + case 0x3d2: + case 0x3d3: + case 0x7d2: + case 0x7d3: + return PPC_ID_DIVDx; + + case 0x3d6: + case 0x3d7: + case 0x7d6: + case 0x7d7: + return PPC_ID_DIVWx; + + case 0x3e4: + if ((word32 & 0x03fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SLBIA; + + case 0x3f4: + if (b != 0) + return PPC_ID_INVALID; + + // TODO: [Category: Server.64-bit] + // TODO: [Category: Embedded.64-bit.Phased-In] + return PPC_ID_POPCNTD; + + case 0x3f8: + return PPC_ID_CMPB; + + case 0x400: + if ((word32 & 0x00fff800) != 0) + return PPC_ID_INVALID; + + break; + + case 0x428: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return PPC_ID_LDBRX; + + case 0x42a: + return PPC_ID_LSWX; + + case 0x42c: + return PPC_ID_LWBRX; + + case 0x42e: + return PPC_ID_LFSX; + + case 0x430: + case 0x431: + return PPC_ID_SRWx; + + case 0x436: + case 0x437: + return PPC_ID_SRDx; + + case 0x46c: + if ((word32 & 0x03fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_TLBSYNC; + + case 0x46e: + return PPC_ID_LFSUX; + + case 0x498: + case 0x499: + if ((decodeFlags & DECODE_FLAGS_VSX) == 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_LXSDX; + + case 0x4a6: + if ((word32 & 0x0010f801) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MFSR; + + case 0x4aa: + return PPC_ID_LSWI; + + case 0x4ac: + { + if ((word32 & 0x039ff800) != 0) + return PPC_ID_INVALID; + + uint32_t l = (word32 >> 21) & 0x3; + switch (l) + { + case 0: return PPC_ID_SYNC; + case 1: return PPC_ID_LWSYNC; + case 2: return PPC_ID_PTESYNC; + + default: return PPC_ID_SYNC; + + } + } + + case 0x4ae: + return PPC_ID_LFDX; + + case 0x4ee: + return PPC_ID_LFDUX; + + case 0x4e4: + if ((word32 & 0x03fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_TLBIA; + + case 0x526: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_MFSRIN; + + case 0x528: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return PPC_ID_STDBRX; + + case 0x52a: + return PPC_ID_STSWX; + + case 0x52c: + return PPC_ID_STWBRX; + + case 0x52e: + return PPC_ID_STFSX; + + case 0x56e: + return PPC_ID_STFSUX; + + case 0x598: + case 0x599: + if ((decodeFlags & DECODE_FLAGS_VSX) == 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_STXSDX; + + case 0x5aa: + return PPC_ID_STSWI; + + case 0x5ae: + return PPC_ID_STFDX; + + case 0x5ec: + if (d != 0) + return PPC_ID_INVALID; + + return PPC_ID_DCBA; + + case 0x5ee: + return PPC_ID_STFDUX; + + case 0x618: + case 0x619: + if ((decodeFlags & DECODE_FLAGS_VSX) == 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_LXVW4X; + + case 0x624: + if ((word32 & 0x03e00000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_TLBIVAX; + + case 0x62a: + return PPC_ID_LWZCIX; + + case 0x62c: + return PPC_ID_LHBRX; + + case 0x630: + case 0x631: + return PPC_ID_SRAWx; + + case 0x634: + case 0x635: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return PPC_ID_SRADx; + + case 0x66a: + return PPC_ID_LHZCIX; + + case 0x66c: + { + if ((word32 & 0x019ff800) != 0) + return PPC_ID_INVALID; + + uint32_t all = ((word32 >> 25) & 0x1) != 0; + + if (all) + { + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + else + return PPC_ID_AV_DSSALL; + } + else + { + return PPC_ID_AV_DSS; + } + } + + case 0x670: + case 0x671: + return PPC_ID_SRAWIx; + + case 0x674: + case 0x675: + case 0x676: + case 0x677: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return PPC_ID_SRADIx; + + case 0x698: + case 0x699: + if ((decodeFlags & DECODE_FLAGS_VSX) == 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_LXVD2X; + + case 0x6aa: + return PPC_ID_LBZCIX; + + case 0x6ac: + if ((a != 0) || (b != 0)) + return PPC_ID_INVALID; + + if (d == 0) + return PPC_ID_EIEIO; + else + return PPC_ID_MBAR; + + case 0x6ae: + return PPC_ID_LFIWAX; + + case 0x6ea: + return PPC_ID_LDCIX; + + case 0x6ee: + return PPC_ID_LFIWZX; + + + case 0x718: + case 0x719: + if ((decodeFlags & DECODE_FLAGS_VSX) == 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_STXVW4X; + + case 0x724: + if ((word32 & 0x03e00000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_TLBSX; + + case 0x726: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SLBMFEE; + + case 0x72a: + return PPC_ID_STWCIX; + + case 0x72c: + return PPC_ID_STHBRX; + + case 0x734: + case 0x735: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_EXTSHx; + + case 0x764: + if ((word32 & 0x800) != 0) + return PPC_ID_TLBREHI; + else + return PPC_ID_TLBRELO; + + case 0x76a: + return PPC_ID_STHCIX; + + case 0x774: + case 0x775: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_EXTSBx; + + case 0x78c: + { + if ((word32 & 0x021ff801) != 0) + return PPC_ID_INVALID; + + uint32_t ct = (word32 >> 21) & 0xf; + + if (ct == 0) + return PPC_ID_ICCCI; + else + return PPC_ID_ICI; + } + + case 0x798: + case 0x799: + if ((decodeFlags & DECODE_FLAGS_VSX) == 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_STXVD2X; + + case 0x7a4: + if ((word32 & 0x800) != 0) + return PPC_ID_TLBWELO; + else + return PPC_ID_TLBWEHI; + + case 0x7aa: + return PPC_ID_STBCIX; + + case 0x7ac: + if (d != 0) + return PPC_ID_INVALID; + + return PPC_ID_ICBI; + + case 0x7ae: + return PPC_ID_STFIWX; + + case 0x7b4: + case 0x7b5: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_EXTSWx; + + case 0x7e4: + if (d != 0 || a != 0) + return PPC_ID_INVALID; + + // NOTE: this is only valid for 603 processors? + return PPC_ID_TLBLI; + + case 0x7ea: + return PPC_ID_STDCIX; + + case 0x7ec: + { + // NOTE: I can't find anything about the "DCBZL" opcode + // anywhere, but this seems to match capstone + if ((word32 & 0x03e00000) == 0x00200000) + return PPC_ID_DCBZL; + else if ((word32 & 0x03e00000) == 0) + return PPC_ID_DCBZ; + else + return PPC_ID_INVALID; + } + + default: + return PPC_ID_INVALID; + } + + return true; +} + +static InstructionId Decode0x3B(uint32_t word32, uint32_t flags) +{ + uint32_t a = GetA(word32); + uint32_t b = GetB(word32); + uint32_t c = GetC(word32); + + uint32_t subop = word32 & 0x3f; + switch (subop) + { + case 0x24: + case 0x25: + if (c != 0) + return PPC_ID_INVALID; + + return PPC_ID_FDIVSx; + + case 0x28: + case 0x29: + if (c != 0) + return PPC_ID_INVALID; + + return PPC_ID_FSUBSx; + + case 0x2a: + case 0x2b: + if (c != 0) + return PPC_ID_INVALID; + + return PPC_ID_FADDSx; + + case 0x2c: + case 0x2d: + if ((a != 0) || (c != 0)) + return PPC_ID_INVALID; + + return PPC_ID_FSQRTSx; + + case 0x30: + case 0x31: + if ((a != 0) || (c != 0)) + return PPC_ID_INVALID; + + return PPC_ID_FRESx; + + case 0x32: + case 0x33: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_FMULSx; + + case 0x34: + case 0x35: + if ((a != 0) || (c != 0)) + return PPC_ID_INVALID; + + return PPC_ID_FRSQRTESx; + + case 0x38: + case 0x39: + return PPC_ID_FMSUBSx; + + case 0x3a: + case 0x3b: + return PPC_ID_FMADDSx; + + case 0x3c: + case 0x3d: + return PPC_ID_FNMSUBSx; + + case 0x3e: + case 0x3f: + return PPC_ID_FNMADDSx; + + default: + break; + } + + subop = word32 & 0x7ff; + switch (subop) + { + case 0x69c: + case 0x69d: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCFIDSx; + + case 0x79c: + case 0x79d: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCFIDUSx; + + default: + return PPC_ID_INVALID; + } + + return true; +} + +static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) +{ + uint32_t bit21 = (word32 >> 10) & 0x1; + uint32_t subop = (word32 >> 4) & 0x3; + uint32_t vsxA = GetVsxA(word32); + uint32_t vsxB = GetVsxB(word32); + + switch (subop) + { + case 0x3: return PPC_ID_VSX_XXSEL; + default: break; + } + + subop = (word32 >> 2) & 0x1ff; + switch (subop) + { + case 0x048: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVDPUXWS; + + case 0x049: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRDPI; + + case 0x04a: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRSQRTEDP; + + case 0x04b: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSSQRTDP; + + case 0x058: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVDPSXWS; + + case 0x059: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRDPIZ; + + case 0x05a: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSREDP; + + case 0x069: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRDPIP; + + case 0x6a: + if ((word32 & 0x007f0001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSTSQRTDP; + + case 0x06b: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRDPIC; + + case 0x079: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRDPIM; + + case 0x088: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVSPUXWS; + + case 0x089: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRSPI; + + case 0x08a: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRSQRTESP; + + case 0x08b: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVSQRTSP; + + case 0x098: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVSPSXWS; + + case 0x099: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRSPIZ; + + case 0x09a: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRESP; + + case 0x0a4: + if ((word32 & 0x001c0004) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XXSPLTW; + + case 0x0a8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVUXWSP; + + case 0x0a9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRSPIP; + + case 0xaa: + if ((word32 & 0x007f0001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVTSQRTSP; + + case 0x0ab: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRSPIC; + + case 0x0b8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVSXWSP; + + case 0x0b9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRSPIM; + + case 0x0c8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVDPUXWS; + + case 0x0c9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRDPI; + + case 0x0ca: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRSQRTEDP; + + case 0x0cb: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVSQRTDP; + + case 0x0d8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVDPSXWS; + + case 0x0d9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRDPIZ; + + case 0x0da: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVREDP; + + case 0x0e8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVUXWDP; + + case 0x0e9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRDPIP; + + case 0xea: + if ((word32 & 0x007f0001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVTSQRTDP; + + case 0x0eb: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRDPIC; + + case 0x0f8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVSXWDP; + + case 0x0f9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVRDPIM; + + case 0x109: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVDPSP; + + case 0x148: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVDPUXDS; + + case 0x149: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVSPDP; + + case 0x158: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVDPSXDS; + + case 0x159: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSABSDP; + + case 0x168: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVUXDDP; + + case 0x169: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSNABSDP; + + case 0x178: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVSXDDP; + + case 0x179: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSNEGDP; + + case 0x188: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVSPUXDS; + + case 0x189: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVDPSP; + + case 0x198: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVSPSXDS; + + case 0x199: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVABSSP; + + case 0x1a8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVUXDSP; + + case 0x1a9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVNABSSP; + + case 0x1b8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVSXDSP; + + case 0x1b9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVNEGSP; + + case 0x1c8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVDPUXDS; + + case 0x1c9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVSPDP; + + case 0x1d8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVDPSXDS; + + case 0x1d9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVABSDP; + + case 0x1e8: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVUXDDP; + + case 0x1e9: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVNABSDP; + + case 0x1f8: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVSXDDP; + + case 0x1f9: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVNEGDP; + + default: + break; + } + + subop = (word32 >> 3) & 0xff; + switch (subop) + { + case 0x00: + // TODO: XSADDSP? + return PPC_ID_INVALID; + + case 0x02: + case 0x22: + case 0x42: + case 0x62: + return PPC_ID_VSX_XXSLDWI; + + case 0x0a: + case 0x2a: + case 0x4a: + case 0x6a: + { + uint32_t dm = (word32 >> 8) & 0x3; + + if (vsxA == vsxB) + { + switch (dm) + { + case 0: return PPC_ID_VSX_XXSPLTD; + case 2: return PPC_ID_VSX_XXSWAPD; + case 3: return PPC_ID_VSX_XXSPLTD; + default: return PPC_ID_VSX_XXPERMDI; + } + } + else + { + switch (dm) + { + case 0: return PPC_ID_VSX_XXMRGHD; + case 3: return PPC_ID_VSX_XXMRGLD; + default: return PPC_ID_VSX_XXPERMDI; + } + } + } + + case 0x12: + return PPC_ID_VSX_XXMRGHW; + + case 0x20: + return PPC_ID_VSX_XSADDDP; + + case 0x21: + return PPC_ID_VSX_XSMADDADP; + + case 0x23: + if ((word32 & 0x00600001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCMPUDP; + + case 0x28: + return PPC_ID_VSX_XSSUBDP; + + case 0x29: + return PPC_ID_VSX_XSMADDMDP; + + case 0x2b: + if ((word32 & 0x00600001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCMPODP; + + case 0x30: + return PPC_ID_VSX_XSMULDP; + + case 0x31: + return PPC_ID_VSX_XSMSUBADP; + + case 0x32: + return PPC_ID_VSX_XXMRGLW; + + case 0x38: + return PPC_ID_VSX_XSDIVDP; + + case 0x39: + return PPC_ID_VSX_XSMSUBMDP; + + case 0x3d: + if ((word32 & 0x00600001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSTDIVDP; + + case 0x40: + return PPC_ID_VSX_XVADDSP; + + case 0x41: + return PPC_ID_VSX_XVMADDASP; + + case 0x43: + case 0xc3: + return PPC_ID_VSX_XVCMPEQSPx; + + case 0x48: + return PPC_ID_VSX_XVSUBSP; + + case 0x49: + return PPC_ID_VSX_XVMADDMSP; + + case 0x4b: + case 0xcb: + return PPC_ID_VSX_XVCMPGTSPx; + + case 0x50: + return PPC_ID_VSX_XVMULSP; + + case 0x51: + return PPC_ID_VSX_XVMSUBASP; + + case 0x53: + case 0xd3: + return PPC_ID_VSX_XVCMPGESPx; + + case 0x58: + return PPC_ID_VSX_XVDIVSP; + + case 0x59: + return PPC_ID_VSX_XVMSUBMSP; + + case 0x5d: + if ((word32 & 0x00600001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVTDIVSP; + + case 0x60: + return PPC_ID_VSX_XVADDDP; + + case 0x61: + return PPC_ID_VSX_XVMADDADP; + + case 0x63: + case 0xe3: + return PPC_ID_VSX_XVCMPEQDPx; + + case 0x68: + return PPC_ID_VSX_XVSUBDP; + + case 0x69: + return PPC_ID_VSX_XVMADDMDP; + + case 0x6b: + case 0xeb: + return PPC_ID_VSX_XVCMPGTDPx; + + case 0x70: + return PPC_ID_VSX_XVMULDP; + + case 0x71: + return PPC_ID_VSX_XVMSUBADP; + + case 0x73: + case 0xf3: + return PPC_ID_VSX_XVCMPGEDPx; + + case 0x78: + return PPC_ID_VSX_XVDIVDP; + + case 0x79: + return PPC_ID_VSX_XVMSUBMDP; + + case 0x7d: + if ((word32 & 0x00600001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVTDIVDP; + + case 0x81: + // TODO: XSNMADDASP not handled by capstone? + return PPC_ID_INVALID; + + case 0x82: + return PPC_ID_VSX_XXLAND; + + case 0x89: + // TODO: XSNMADDMSP not handled by capstone? + return PPC_ID_INVALID; + + case 0x8a: + return PPC_ID_VSX_XXLANDC; + + case 0x92: + return PPC_ID_VSX_XXLOR; + + case 0x9a: + return PPC_ID_VSX_XXLXOR; + + case 0xa0: + return PPC_ID_VSX_XSMAXDP; + + case 0xa1: + return PPC_ID_VSX_XSNMADDADP; + + case 0xa9: + return PPC_ID_VSX_XSNMADDMDP; + + case 0xa2: + return PPC_ID_VSX_XXLNOR; + + case 0xa8: + return PPC_ID_VSX_XSMINDP; + + case 0xaa: + return PPC_ID_VSX_XXLORC; + + case 0xb0: + return PPC_ID_VSX_XSCPSGNDP; + + case 0xb1: + return PPC_ID_VSX_XSNMSUBADP; + + case 0xb2: + return PPC_ID_VSX_XXLNAND; + + case 0xb9: + return PPC_ID_VSX_XSNMSUBMDP; + + case 0xba: + return PPC_ID_VSX_XXLEQV; + + case 0xc0: + return PPC_ID_VSX_XVMAXSP; + + case 0xc1: + return PPC_ID_VSX_XVNMADDASP; + + case 0xc8: + return PPC_ID_VSX_XVMINSP; + + case 0xc9: + return PPC_ID_VSX_XVNMADDMSP; + + case 0xd0: + if (vsxA == vsxB) + return PPC_ID_VSX_XVMOVSP; + else + return PPC_ID_VSX_XVCPSGNSP; + + case 0xd1: + return PPC_ID_VSX_XVNMSUBASP; + + case 0xd9: + return PPC_ID_VSX_XVNMSUBMSP; + + case 0xe0: + return PPC_ID_VSX_XVMAXDP; + + case 0xe1: + return PPC_ID_VSX_XVNMADDADP; + + case 0xe8: + return PPC_ID_VSX_XVMINDP; + + case 0xe9: + return PPC_ID_VSX_XVNMADDMDP; + + case 0xf0: + if (vsxA == vsxB) + return PPC_ID_VSX_XVMOVDP; + else + return PPC_ID_VSX_XVCPSGNDP; + + case 0xf1: + return PPC_ID_VSX_XVNMSUBADP; + + case 0xf9: + return PPC_ID_VSX_XVNMSUBMDP; + + default: + return PPC_ID_INVALID; + } +} + +static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) +{ + uint32_t a = GetA(word32); + uint32_t b = GetB(word32); + + uint32_t subop = word32 & 0x3f; + switch (subop) + { + case 0x02e: + case 0x02f: + return PPC_ID_FSELx; + + case 0x032: + case 0x033: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_FMULx; + + case 0x038: + case 0x039: + return PPC_ID_FMSUBx; + + case 0x03a: + case 0x03b: + return PPC_ID_FMADDx; + + case 0x03c: + case 0x03d: + return PPC_ID_FNMSUBx; + + case 0x03e: + case 0x03f: + return PPC_ID_FNMADDx; + + default: + break; + } + + subop = word32 & 0x7ff; + switch (subop) + { + case 0x000: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCMPU; + + case 0x010: + case 0x011: + return PPC_ID_FCPSGNx; + + case 0x018: + case 0x019: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FRSPx; + + case 0x01c: + case 0x01d: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCTIWx; + + case 0x01e: + case 0x01f: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCTIWZx; + + case 0x020: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCMPO; + + case 0x024: + case 0x025: + return PPC_ID_FDIVx; + + case 0x028: + case 0x029: + return PPC_ID_FSUBx; + + case 0x02a: + case 0x02b: + return PPC_ID_FADDx; + + case 0x02c: + case 0x02d: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FSQRTx; + + case 0x030: + case 0x031: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FREx; + + case 0x034: + case 0x035: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FRSQRTEx; + + case 0x04c: + case 0x04d: + if ((a != 0) || (b != 0)) + return PPC_ID_INVALID; + + return PPC_ID_MTFSB1x; + + case 0x050: + case 0x051: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FNEGx; + + case 0x080: + if ((word32 & 0x0063f800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MCRFS; + + case 0x08c: + case 0x08d: + if ((a != 0) || (b != 0)) + return PPC_ID_INVALID; + + return PPC_ID_MTFSB0x; + + case 0x090: + case 0x091: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FMRx; + + case 0x10c: + case 0x10d: + if ((word32 & 0x007e0800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MTFSFIx; + + case 0x110: + case 0x111: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FNABSx; + + case 0x11e: + case 0x11f: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCTIWUZx; + + case 0x210: + case 0x211: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FABSx; + + case 0x310: + case 0x311: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FRINx; + + case 0x350: + case 0x351: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FRIZx; + + case 0x390: + case 0x391: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FRIPx; + + case 0x3d0: + case 0x3d1: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FRIMx; + + case 0x48e: + case 0x48f: + if ((a != 0) || (b != 0)) + return PPC_ID_INVALID; + + return PPC_ID_MFFSx; + + case 0x58e: + case 0x58f: + return PPC_ID_MTFSFx; + + case 0x65c: + case 0x65d: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCTIDx; + + case 0x65e: + case 0x65f: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCTIDZx; + + case 0x69c: + case 0x69d: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCFIDx; + + case 0x75e: + case 0x75f: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCTIDUZx; + + case 0x79c: + case 0x79d: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCFIDUx; + + default: + return PPC_ID_INVALID; + } + + return true; +} + +static InstructionId Decode(uint32_t word32, uint32_t decodeFlags) +{ + uint32_t a = GetA(word32); + + uint32_t primary = (word32 >> 26) & 0x3f; + switch (primary) + { + case 0x00: + { + // "ATTN" instruction documented in section 12.1.1 of + // the user manual for the IBM A2 processor + if ((word32 & 0x7fe) != 0x200) + return PPC_ID_INVALID; + + return PPC_ID_ATTN; + } + + case 0x02: + { + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + uint32_t to = (word32 >> 21) & 0x1f; + switch (to) + { + case 1: return PPC_ID_TDLGTI; + case 2: return PPC_ID_TDLLTI; + case 4: return PPC_ID_TDEQI; + case 8: return PPC_ID_TDGTI; + case 16: return PPC_ID_TDLTI; + case 24: return PPC_ID_TDNEI; + case 31: return PPC_ID_TDUI; + default: return PPC_ID_TDI; + } + } + + case 0x03: + { + uint32_t to = (word32 >> 21) & 0x1f; + + switch (to) + { + case 1: return PPC_ID_TWLGTI; + case 2: return PPC_ID_TWLLTI; + case 4: return PPC_ID_TWEQI; + case 8: return PPC_ID_TWGTI; + case 16: return PPC_ID_TWLTI; + case 24: return PPC_ID_TWNEI; + case 31: return PPC_ID_TWUI; + default: return PPC_ID_TWI; + } + } + + case 0x04: + { + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) == 0) + return PPC_ID_INVALID; + + return DecodeAltivec0x04(word32, decodeFlags); + } + + case 0x07: + return PPC_ID_MULLI; + + case 0x08: + return PPC_ID_SUBFIC; + + + case 0x0a: + if ((word32 & 0x00400000) == 0) + { + if ((word32 & 0x00200000) != 0) + { + if (decodeFlags & DECODE_FLAGS_PPC64 == 0) + return PPC_ID_INVALID; + + return PPC_ID_CMPLDI; + } + else + { + return PPC_ID_CMPLWI; + } + } + + return PPC_ID_INVALID; + + case 0x0b: + if ((word32 & 0x00400000) == 0) + { + if ((word32 & 0x00200000) != 0) + { + if (decodeFlags & DECODE_FLAGS_PPC64 == 0) + return PPC_ID_INVALID; + + return PPC_ID_CMPDI; + } + else + { + return PPC_ID_CMPWI; + } + } + + return PPC_ID_INVALID; + + case 0x0c: + return PPC_ID_ADDICx; + + case 0x0d: + return PPC_ID_ADDICx; + + case 0x0e: + if (a == 0) + return PPC_ID_LI; + else + return PPC_ID_ADDI; + + case 0x0f: + if (a == 0) + return PPC_ID_LIS; + else + return PPC_ID_ADDIS; + + case 0x10: + { + uint32_t bo = GetBO(word32); + uint32_t bi = GetBI(word32); + + // mask away the "y" bit + switch (bo & 0x1e) + { + case 0: return PPC_ID_BDNZFx; + case 2: return PPC_ID_BDZFx; + + case 4: + case 6: + switch (bi & 0x3) + { + case 0: return PPC_ID_BGEx; + case 1: return PPC_ID_BLEx; + case 2: return PPC_ID_BNEx; + case 3: return PPC_ID_BNSx; + + // should be unreachable + default: return PPC_ID_BFx; + } + + case 8: return PPC_ID_BDNZTx; + case 10: return PPC_ID_BDZTx; + + case 12: + case 14: + switch (bi & 0x3) + { + case 0: return PPC_ID_BLTx; + case 1: return PPC_ID_BGTx; + case 2: return PPC_ID_BEQx; + case 3: return PPC_ID_BSOx; + + // should be unreachable + default: return PPC_ID_BTx; + } + + // technically these aren't terribly well defined + // when BI != 0, since these BOs don't involve + // a condition bit to test in BI to test against + case 16: + case 24: + return PPC_ID_BDNZx; + + // these represent "branch always" in the BO field, so it's + // not super clear why these disassemble to bdnz + case 20: + case 28: + return PPC_ID_BDNZx; + + case 18: + case 22: + case 26: + return PPC_ID_BDZx; + + // these represent "branch always" in the BO field, so it's + // not super clear why these disassemble to bdz + case 30: + return PPC_ID_BDZx; + + default: return PPC_ID_BCx; + } + } + + case 0x11: + if ((word32 & 0x03fff01f) != 2) + return PPC_ID_INVALID; + + return PPC_ID_SC; + + case 0x12: + return PPC_ID_Bx; + + case 0x13: + return Decode0x13(word32, decodeFlags); + + case 0x14: + return PPC_ID_RLWIMIx; + + case 0x15: + { + uint32_t me = GetME(word32); + uint32_t mb = GetMB(word32); + uint32_t sh = GetSH(word32); + + if (mb == 0 && ((sh + me) == 31)) + return PPC_ID_SLWIx; + else if (mb == 0 && me == 31) + return PPC_ID_ROTLWIx; + else if (me == 31 && ((sh + mb) == 32)) + return PPC_ID_SRWIx; + else if (sh == 0 && mb == 0) + return PPC_ID_CLRRWIx; + else if (sh == 0 && me == 31) + return PPC_ID_CLRLWIx; + else + return PPC_ID_RLWINMx; + } + + case 0x17: + { + uint32_t me = GetME(word32); + uint32_t mb = GetMB(word32); + + if (mb == 0 && me == 31) + return PPC_ID_ROTLWx; + else + return PPC_ID_RLWNMx; + } + + case 0x18: + if (word32 == 0x60000000) + return PPC_ID_NOP; + else + return PPC_ID_ORI; + + case 0x19: + return PPC_ID_ORIS; + + case 0x1a: + if (word32 == 0x68000000) + return PPC_ID_XNOP; + else + return PPC_ID_XORI; + + case 0x1b: + return PPC_ID_XORIS; + + case 0x1c: + return PPC_ID_ANDI; + + case 0x1d: + return PPC_ID_ANDIS; + + case 0x1e: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + return Decode0x1E(word32, decodeFlags); + + case 0x1f: + return Decode0x1F(word32, decodeFlags); + + case 0x20: + return PPC_ID_LWZ; + + case 0x21: + return PPC_ID_LWZU; + + case 0x22: + return PPC_ID_LBZ; + + case 0x23: + return PPC_ID_LBZU; + + case 0x24: + return PPC_ID_STW; + + case 0x25: + return PPC_ID_STWU; + + case 0x26: + return PPC_ID_STB; + + case 0x27: + return PPC_ID_STBU; + + case 0x28: + return PPC_ID_LHZ; + + case 0x29: + return PPC_ID_LHZU; + + case 0x2a: + return PPC_ID_LHA; + + case 0x2b: + return PPC_ID_LHAU; + + case 0x2c: + return PPC_ID_STH; + + case 0x2d: + return PPC_ID_STHU; + + case 0x2e: + return PPC_ID_LMW; + + case 0x2f: + return PPC_ID_STMW; + + case 0x30: + return PPC_ID_LFS; + + case 0x31: + return PPC_ID_LFSU; + + case 0x32: + return PPC_ID_LFD; + + case 0x33: + return PPC_ID_LFDU; + + case 0x34: + return PPC_ID_STFS; + + case 0x35: + return PPC_ID_STFSU; + + case 0x36: + return PPC_ID_STFD; + + case 0x37: + return PPC_ID_STFDU; + + case 0x3a: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + switch (word32 & 0x3) + { + case 0: return PPC_ID_LD; + case 1: return PPC_ID_LDU; + case 2: return PPC_ID_LWA; + default: return PPC_ID_INVALID; + } + + case 0x3b: + return Decode0x3B(word32, decodeFlags); + + case 0x3c: + if ((decodeFlags & DECODE_FLAGS_VSX) == 0) + return PPC_ID_INVALID; + + return DecodeVsx0x3C(word32, decodeFlags); + + case 0x3e: + if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) + return PPC_ID_INVALID; + + switch (word32 & 0x3) + { + case 0: return PPC_ID_STD; + case 1: return PPC_ID_STDU; + default: return PPC_ID_INVALID; + } + + case 0x3f: + return Decode0x3F(word32, decodeFlags); + + default: + return PPC_ID_INVALID; + } +} + +static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t address) +{ + switch (instruction->id) + { + // instructions with no operands + case PPC_ID_ATTN: + case PPC_ID_DCCCI: + case PPC_ID_ICCCI: + case PPC_ID_ISYNC: + case PPC_ID_LWSYNC: + case PPC_ID_NOP: + case PPC_ID_PTESYNC: + case PPC_ID_RFCI: + case PPC_ID_RFDI: + case PPC_ID_RFI: + case PPC_ID_RFID: + case PPC_ID_RFMCI: + case PPC_ID_TLBIA: + case PPC_ID_TLBSYNC: + case PPC_ID_SLBIA: + case PPC_ID_XNOP: + case PPC_ID_WAITIMPL: + case PPC_ID_WAITRSV: + case PPC_ID_AV_DSSALL: + break; + + // rD + case PPC_ID_MFBR0: + case PPC_ID_MFBR1: + case PPC_ID_MFBR2: + case PPC_ID_MFBR3: + case PPC_ID_MFBR4: + case PPC_ID_MFBR5: + case PPC_ID_MFBR6: + case PPC_ID_MFBR7: + case PPC_ID_MFCR: + case PPC_ID_MFCTR: + case PPC_ID_MFLR: + case PPC_ID_MFMSR: + case PPC_ID_MFTBU: + case PPC_ID_MFXER: + PushRD(instruction, word32); + break; + + // rS + case PPC_ID_MTBR0: + case PPC_ID_MTBR1: + case PPC_ID_MTBR2: + case PPC_ID_MTBR3: + case PPC_ID_MTBR4: + case PPC_ID_MTBR5: + case PPC_ID_MTBR6: + case PPC_ID_MTBR7: + case PPC_ID_MTCTR: + case PPC_ID_MTLR: + case PPC_ID_MTMSR: + case PPC_ID_MTMSRD: + case PPC_ID_MTXER: + case PPC_ID_WRTEE: + PushRS(instruction, word32); + break; + + // rB + case PPC_ID_TLBIEL: + case PPC_ID_TLBLI: + case PPC_ID_SLBIE: + PushRB(instruction, word32); + break; + + // [.] rD, rA (arithmetic) + case PPC_ID_NEGx: + case PPC_ID_SUBFZEx: + case PPC_ID_ADDZEx: + case PPC_ID_SUBFMEx: + case PPC_ID_ADDMEx: + PushRD(instruction, word32); + PushRA(instruction, word32); + + // some of these instructions don't have an "oe" flag, + // but we rely on the fact that those instructions have + // bitmask 0x400 clear in the switch statement on the + instruction->flags.rc = word32 & 0x1; + instruction->flags.oe = (word32 & 0x400) != 0; + break; + + // [.] rD, rA, rB (arithmetic) + case PPC_ID_ADDx: + case PPC_ID_ADDCx: + case PPC_ID_ADDEx: + case PPC_ID_DIVDx: + case PPC_ID_DIVDUx: + case PPC_ID_DIVWx: + case PPC_ID_DIVWUx: + case PPC_ID_MULHDx: + case PPC_ID_MULHDUx: + case PPC_ID_MULHWx: + case PPC_ID_MULHWUx: + case PPC_ID_MULLDx: + case PPC_ID_MULLWx: + case PPC_ID_SUBFx: + case PPC_ID_SUBFCx: + case PPC_ID_SUBFEx: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + + // some of these instructions don't have an "oe" flag, + // but we rely on the fact that those instructions have + // bitmask 0x400 clear in the switch statement on the + // 0x7ff mask + instruction->flags.rc = word32 & 0x1; + instruction->flags.oe = (word32 & 0x400) != 0; + break; + + + // [.] rA, rS (logical) + case PPC_ID_CNTLZWx: + case PPC_ID_CNTLZDx: + case PPC_ID_POPCNTD: + case PPC_ID_POPCNTW: + case PPC_ID_EXTSHx: + case PPC_ID_EXTSBx: + case PPC_ID_EXTSWx: + PushRA(instruction, word32); + PushRS(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + // [.] rA, rS, rB + case PPC_ID_ANDx: + case PPC_ID_ANDCx: + case PPC_ID_CMPB: + case PPC_ID_ECIWX: + case PPC_ID_ECOWX: + case PPC_ID_EQVx: + case PPC_ID_NANDx: + case PPC_ID_NORx: + case PPC_ID_ORx: + case PPC_ID_ORCx: + case PPC_ID_ROTLWx: + case PPC_ID_ROTLDx: + case PPC_ID_SLDx: + case PPC_ID_SLWx: + case PPC_ID_SRADx: + case PPC_ID_SRAWx: + case PPC_ID_SRDx: + case PPC_ID_SRWx: + case PPC_ID_XORx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushRB(instruction, word32); + + // not all of these have an rc bit, but they just don't + // get recognized at the switch statement with &0x7ff + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_ROTLWIx: + case PPC_ID_SLWIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_CLRLWIx: + case PPC_ID_SRWIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetMB(word32)); + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_CLRRWIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + + // me = 31 - n --> n = 31 - me + PushUIMMValue(instruction, 31 - GetME(word32)); + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_RLDCLx: + case PPC_ID_RLDCRx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushRB(instruction, word32); + PushUIMMValue(instruction, GetMX64(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_RLDICx: + case PPC_ID_RLDICLx: + case PPC_ID_RLDICRx: + case PPC_ID_RLDIMIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH64(word32)); + PushUIMMValue(instruction, GetMX64(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_CLRLDIx: + case PPC_ID_SRDIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetMX64(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_ROTLDIx: + case PPC_ID_SLDIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH64(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_BCx: + { + uint32_t bo = GetBO(word32); + uint32_t bi = GetBI(word32); + + instruction->flags.lk = word32 & 0x1; + instruction->flags.aa = (word32 & 0x2) != 0; + + PushUIMMValue(instruction, bo); + PushUIMMValue(instruction, bi); + PushBranchTarget(instruction, address, word32); + + break; + } + + case PPC_ID_BDNZFx: + case PPC_ID_BDNZTx: + case PPC_ID_BDZFx: + case PPC_ID_BDZTx: + case PPC_ID_BFx: + case PPC_ID_BTx: + { + uint32_t bi = GetBI(word32); + + instruction->flags.lk = word32 & 0x1; + instruction->flags.aa = (word32 & 0x2) != 0; + + PushUIMMValue(instruction, bi); + PushBranchTarget(instruction, address, word32); + break; + } + + case PPC_ID_BEQx: + case PPC_ID_BGEx: + case PPC_ID_BGTx: + case PPC_ID_BLEx: + case PPC_ID_BLTx: + case PPC_ID_BNEx: + case PPC_ID_BNSx: + case PPC_ID_BSOx: + { + uint32_t crn = GetBI(word32) >> 2; + + instruction->flags.lk = word32 & 0x1; + instruction->flags.aa = (word32 & 0x2) != 0; + FillBranchLikelyHint(instruction, word32); + + if (crn != 0) + PushRegister(instruction, REG_CRFS, Crf(crn)); + + PushBranchTarget(instruction, address, word32); + break; + } + + case PPC_ID_BDZx: + case PPC_ID_BDNZx: + instruction->flags.lk = word32 & 0x1; + instruction->flags.aa = (word32 & 0x2) != 0; + FillBranchLikelyHint(instruction, word32); + + PushBranchTarget(instruction, address, word32); + break; + + case PPC_ID_BDNZFCTRx: + case PPC_ID_BDNZFLRx: + case PPC_ID_BDNZTCTRx: + case PPC_ID_BDNZTLRx: + case PPC_ID_BDZFCTRx: + case PPC_ID_BDZFLRx: + case PPC_ID_BDZTCTRx: + case PPC_ID_BDZTLRx: + instruction->flags.lk = word32 & 0x1; + + PushUIMMValue(instruction, GetBI(word32)); + break; + + case PPC_ID_BCTRx: + case PPC_ID_BDNZCTRx: + case PPC_ID_BDNZLRx: + case PPC_ID_BDZCTRx: + case PPC_ID_BDZLRx: + case PPC_ID_BLRx: + // these don't test any conditions, so no operands + instruction->flags.lk = word32 & 0x1; + FillBranchLikelyHint(instruction, word32); + break; + + case PPC_ID_BEQCTRx: + case PPC_ID_BEQLRx: + case PPC_ID_BGECTRx: + case PPC_ID_BGELRx: + case PPC_ID_BGTCTRx: + case PPC_ID_BGTLRx: + case PPC_ID_BLECTRx: + case PPC_ID_BLELRx: + case PPC_ID_BLTCTRx: + case PPC_ID_BLTLRx: + case PPC_ID_BNECTRx: + case PPC_ID_BNELRx: + case PPC_ID_BNSCTRx: + case PPC_ID_BNSLRx: + case PPC_ID_BSOCTRx: + case PPC_ID_BSOLRx: + { + uint32_t crn = GetBI(word32) >> 2; + + instruction->flags.lk = word32 & 0x1; + FillBranchLikelyHint(instruction, word32); + + if (crn != 0) + PushRegister(instruction, REG_CRFS, Crf(crn)); + + break; + } + + // crfD, rA, rB + case PPC_ID_CMPD: + case PPC_ID_CMPW: + case PPC_ID_CMPLD: + case PPC_ID_CMPLW: + PushCRFDImplyCR0(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // crfD, rA, SIMM + case PPC_ID_CMPDI: + case PPC_ID_CMPWI: + { + int32_t simm = (int32_t)((int16_t)(word32 & 0xffff)); + + PushCRFDImplyCR0(instruction, word32); + PushRA(instruction, word32); + PushSIMMValue(instruction, simm); + break; + } + + // crfD, rA, UIMM + case PPC_ID_CMPLDI: + case PPC_ID_CMPLWI: + { + uint32_t uimm = word32 & 0xffff; + + PushCRFDImplyCR0(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, uimm); + break; + } + + // rA, rB + case PPC_ID_TDEQ: + case PPC_ID_TDGT: + case PPC_ID_TDLGT: + case PPC_ID_TDLLT: + case PPC_ID_TDLT: + case PPC_ID_TDNE: + case PPC_ID_TDU: + case PPC_ID_TLBSX: + case PPC_ID_TWEQ: + case PPC_ID_TWGT: + case PPC_ID_TWLGT: + case PPC_ID_TWLLT: + case PPC_ID_TWLT: + case PPC_ID_TWNE: + case PPC_ID_TWU: + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // TO, rA, rB + case PPC_ID_TD: + case PPC_ID_TW: + { + uint32_t to = (word32 >> 21) & 0x1f; + + PushUIMMValue(instruction, to); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + } + + // rA, SIMM + case PPC_ID_TDEQI: + case PPC_ID_TDGTI: + case PPC_ID_TDLGTI: + case PPC_ID_TDLLTI: + case PPC_ID_TDLTI: + case PPC_ID_TDNEI: + case PPC_ID_TDUI: + case PPC_ID_TWEQI: + case PPC_ID_TWGTI: + case PPC_ID_TWLGTI: + case PPC_ID_TWLLTI: + case PPC_ID_TWLTI: + case PPC_ID_TWNEI: + case PPC_ID_TWUI: + { + int32_t simm = (int32_t)((int16_t)(word32 & 0xffff)); + + PushRA(instruction, word32); + PushSIMMValue(instruction, simm); + break; + } + + // TO, rA, SIMM + case PPC_ID_TDI: + case PPC_ID_TWI: + { + uint32_t to = (word32 >> 21) & 0x1f; + int32_t simm = (int32_t)((int16_t)(word32 & 0xffff)); + + PushUIMMValue(instruction, to); + PushRA(instruction, word32); + PushSIMMValue(instruction, simm); + break; + } + + // rD, rA, SIMM + case PPC_ID_ADDI: + case PPC_ID_MULLI: + case PPC_ID_SUBFIC: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); + break; + + // rA, rS, UIMM + case PPC_ID_ORI: + case PPC_ID_XORI: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, word32 & 0xffff); + break; + + // differentiated in case it makes sense to use the shifted value as an operand + // (which we do for now since it matches capstone) + // rA, rS, UIMM + case PPC_ID_ORIS: + case PPC_ID_XORIS: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, word32 & 0xffff); + break; + + // rD, d(rA) + case PPC_ID_LBZ: + case PPC_ID_LBZU: + case PPC_ID_LHA: + case PPC_ID_LHAU: + case PPC_ID_LHZ: + case PPC_ID_LHZU: + case PPC_ID_LMW: + case PPC_ID_LWZ: + case PPC_ID_LWZU: + PushRD(instruction, word32); + PushMemRA(instruction, word32); + break; + + // rD, d(rA) (64-bit) + case PPC_ID_LD: + case PPC_ID_LDU: + case PPC_ID_LWA: + { + PushRD(instruction, word32); + + int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); + PushMem(instruction, MEM_RA, Gpr(GetA(word32)), ds); + break; + } + + // rD, rA, rB (indexed load) + case PPC_ID_LBZCIX: + case PPC_ID_LBZUX: + case PPC_ID_LBZX: + case PPC_ID_LDARX: + case PPC_ID_LDBRX: + case PPC_ID_LDCIX: + case PPC_ID_LDUX: + case PPC_ID_LDX: + case PPC_ID_LHAUX: + case PPC_ID_LHAX: + case PPC_ID_LHBRX: + case PPC_ID_LHZCIX: + case PPC_ID_LHZX: + case PPC_ID_LHZUX: + case PPC_ID_LSWX: + case PPC_ID_LWAX: + case PPC_ID_LWAUX: + case PPC_ID_LWARX: + case PPC_ID_LWBRX: + case PPC_ID_LWZCIX: + case PPC_ID_LWZUX: + case PPC_ID_LWZX: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // rS, d(RA) + case PPC_ID_STB: + case PPC_ID_STBU: + case PPC_ID_STH: + case PPC_ID_STHU: + case PPC_ID_STMW: + case PPC_ID_STW: + case PPC_ID_STWU: + PushRS(instruction, word32); + PushMemRA(instruction, word32); + break; + + // rS, d(RA) (64-bit) + case PPC_ID_STD: + case PPC_ID_STDU: + { + PushRS(instruction, word32); + + int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); + PushMem(instruction, MEM_RA, Gpr(GetA(word32)), ds); + break; + } + + // rS, rA, rB (indexed store) + case PPC_ID_STDBRX: + case PPC_ID_STDCIX: + case PPC_ID_STDUX: + case PPC_ID_STDX: + case PPC_ID_STBCIX: + case PPC_ID_STBUX: + case PPC_ID_STBX: + case PPC_ID_STHBRX: + case PPC_ID_STHCIX: + case PPC_ID_STHUX: + case PPC_ID_STHX: + case PPC_ID_STSWX: + case PPC_ID_STWBRX: + case PPC_ID_STWCIX: + case PPC_ID_STWUX: + case PPC_ID_STWX: + PushRS(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // . rS, rA, rB (indexed store with reserve) + case PPC_ID_STDCX: + case PPC_ID_STWCX: + PushRS(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + instruction->flags.rc = 1; + break; + + // frD, d(rA) + case PPC_ID_LFD: + case PPC_ID_LFDU: + case PPC_ID_LFS: + case PPC_ID_LFSU: + PushFRD(instruction, word32); + PushMemRA(instruction, word32); + break; + + // frD, rA, rB + case PPC_ID_LFDUX: + case PPC_ID_LFDX: + case PPC_ID_LFIWAX: + case PPC_ID_LFIWZX: + case PPC_ID_LFSUX: + case PPC_ID_LFSX: + PushFRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // frS, d(rA) + case PPC_ID_STFD: + case PPC_ID_STFDU: + case PPC_ID_STFS: + case PPC_ID_STFSU: + PushFRS(instruction, word32); + PushMemRA(instruction, word32); + break; + + // frS, rA, rB + case PPC_ID_STFDUX: + case PPC_ID_STFDX: + case PPC_ID_STFIWX: + case PPC_ID_STFSUX: + case PPC_ID_STFSX: + PushFRS(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // crfD, crfS + case PPC_ID_MCRF: + case PPC_ID_MCRFS: + PushCRFD(instruction, word32); + PushCRFS(instruction, word32); + break; + + // crbD, crbA + case PPC_ID_CRMOVE: + case PPC_ID_CRNOT: + PushCRBitD(instruction, word32); + PushCRBitA(instruction, word32); + break; + + // crbD, crbA, crbB + case PPC_ID_CRAND: + case PPC_ID_CRANDC: + case PPC_ID_CREQV: + case PPC_ID_CRNAND: + case PPC_ID_CRNOR: + case PPC_ID_CROR: + case PPC_ID_CRORC: + case PPC_ID_CRXOR: + PushCRBitD(instruction, word32); + PushCRBitA(instruction, word32); + PushCRBitB(instruction, word32); + break; + + case PPC_ID_CRCLR: + case PPC_ID_CRSET: + PushCRBitD(instruction, word32); + break; + + // conditional branches to registers + case PPC_ID_BCLRx: + case PPC_ID_BCCTRx: + // TODO BO, BI + instruction->flags.lk = word32 & 0x1; + break; + + // frD, frA, frB + case PPC_ID_FADDx: + case PPC_ID_FADDSx: + case PPC_ID_FCPSGNx: + case PPC_ID_FDIVx: + case PPC_ID_FDIVSx: + case PPC_ID_FSUBx: + case PPC_ID_FSUBSx: + PushFRD(instruction, word32); + PushFRA(instruction, word32); + PushFRB(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + // [.] frD, frA, frC + case PPC_ID_FMULx: + case PPC_ID_FMULSx: + PushFRD(instruction, word32); + PushFRA(instruction, word32); + PushFRC(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + // [.] frD, frA, frC, frB + case PPC_ID_FMADDx: + case PPC_ID_FMADDSx: + case PPC_ID_FMSUBx: + case PPC_ID_FMSUBSx: + case PPC_ID_FNMADDx: + case PPC_ID_FNMADDSx: + case PPC_ID_FNMSUBx: + case PPC_ID_FNMSUBSx: + case PPC_ID_FSELx: + PushFRD(instruction, word32); + PushFRA(instruction, word32); + PushFRC(instruction, word32); + PushFRB(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + // [.] frD, frB + case PPC_ID_FABSx: + case PPC_ID_FCFIDx: + case PPC_ID_FCFIDUx: + case PPC_ID_FCTIDUZx: + case PPC_ID_FCFIDSx: + case PPC_ID_FCFIDUSx: + case PPC_ID_FCTIDx: + case PPC_ID_FCTIDZx: + case PPC_ID_FCTIWx: + case PPC_ID_FCTIWUZx: + case PPC_ID_FCTIWZx: + case PPC_ID_FMRx: + case PPC_ID_FNABSx: + case PPC_ID_FNEGx: + case PPC_ID_FREx: + case PPC_ID_FRESx: + case PPC_ID_FRIMx: + case PPC_ID_FRINx: + case PPC_ID_FRIPx: + case PPC_ID_FRIZx: + case PPC_ID_FRSPx: + case PPC_ID_FRSQRTEx: + case PPC_ID_FRSQRTESx: + case PPC_ID_FSQRTx: + case PPC_ID_FSQRTSx: + PushFRD(instruction, word32); + PushFRB(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + + case PPC_ID_FCMPO: + case PPC_ID_FCMPU: + PushCRFD(instruction, word32); + PushFRA(instruction, word32); + PushFRB(instruction, word32); + break; + + // rD, UIMM (special register) + case PPC_ID_MFDCR: + case PPC_ID_MFSPR: + case PPC_ID_MFTB: + { + uint32_t special = GetSpecialRegisterCommon(word32); + + PushRD(instruction, word32); + PushUIMMValue(instruction, special); + break; + } + + // UIMM, rS (special register) + case PPC_ID_MTDCR: + case PPC_ID_MTSPR: + { + uint32_t special = GetSpecialRegisterCommon(word32); + + PushUIMMValue(instruction, special); + PushRS(instruction, word32); + break; + } + + // rA, rB (cache-related) + case PPC_ID_DCBA: + case PPC_ID_DCBST: + case PPC_ID_DCBF: + case PPC_ID_DCBI: + case PPC_ID_DCBT: + case PPC_ID_DCBTST: + case PPC_ID_DCBZ: + case PPC_ID_DCBZL: + case PPC_ID_ICBI: + // TODO: this should be PushRAor0 + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // CT (cache-related) + case PPC_ID_DCI: + case PPC_ID_ICI: + { + uint32_t ct = (word32 >> 21) & 0xf; + + PushUIMMValue(instruction, ct); + break; + } + + case PPC_ID_MTFSB0x: + case PPC_ID_MTFSB1x: + { + uint32_t bt = (word32 >> 21) & 0x1f; + + PushUIMMValue(instruction, bt); + instruction->flags.rc = word32 & 0x1; + break; + } + + case PPC_ID_TLBREHI: + case PPC_ID_TLBRELO: + // TODO: this is how capstone disassembles these + // instructions, but some architectures have no + // operands and this is just "tlbre" + PushRD(instruction, word32); + PushRA(instruction, word32); + + break; + + case PPC_ID_TLBWEHI: + case PPC_ID_TLBWELO: + // TODO: this is how capstone disassembles these + // instructions, but some architectures have no + // operands and this is just "tlbwe" + PushRS(instruction, word32); + PushRA(instruction, word32); + + break; + + // one-off instructions + case PPC_ID_ADDICx: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); + + instruction->flags.rc = (word32 >> 26) == 0x0d; + break; + + case PPC_ID_ADDIS: + // different from other shifted immediates because signed imm + PushRD(instruction, word32); + PushRA(instruction, word32); + PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); + break; + + case PPC_ID_ANDI: + // different from other logical immediates because of rc bit + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, word32 & 0xffff); + instruction->flags.rc = 1; + break; + + case PPC_ID_ANDIS: + // different from other logical shifted immediates because of rc bit + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, word32 & 0xffff); + + instruction->flags.rc = 1; + break; + + case PPC_ID_Bx: + { + instruction->flags.lk = word32 & 0x1; + instruction->flags.aa = (word32 & 0x2) != 0; + + uint32_t li = word32 & 0x03fffffc; + uint32_t target = instruction->flags.aa ? li : address + li; + + PushUIMMValue(instruction, target); + + break; + } + + case PPC_ID_MFOCRF: + { + uint32_t fxm = (word32 >> 12) & 0xff; + + PushRD(instruction, word32); + PushUIMMValue(instruction, fxm); + break; + } + + + case PPC_ID_ICBT: + { + uint32_t ct = (word32 >> 21) & 0xf; + + PushUIMMValue(instruction, ct); + PushRA(instruction, word32); + PushRB(instruction, word32); + + break; + } + + case PPC_ID_ISEL: + { + uint32_t bc = (word32 >> 6) & 0x1f; + + PushRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + PushUIMMValue(instruction, bc); + break; + } + + case PPC_ID_LI: + PushRD(instruction, word32); + PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); + break; + + case PPC_ID_LIS: + { + int32_t shifted_value = (int32_t)((word32 & 0xffff) << 16); + + PushRD(instruction, word32); + PushSIMMValue(instruction, shifted_value); + break; + } + + case PPC_ID_LSWI: + { + uint32_t nb = (word32 >> 11) & 0x1f; + + PushRD(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, nb); + break; + } + + case PPC_ID_MBAR: + { + uint32_t mo = (word32 >> 21) & 0x1f; + PushUIMMValue(instruction, mo); + break; + } + + case PPC_ID_MFFSx: + PushFRD(instruction, word32); + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_MFSR: + { + uint32_t sr = (word32 >> 16) & 0xf; + + PushRD(instruction, word32); + PushUIMMValue(instruction, sr); + break; + } + + case PPC_ID_MFSRIN: + PushRD(instruction, word32); + PushRB(instruction, word32); + break; + + + case PPC_ID_MRx: + PushRA(instruction, word32); + PushRS(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_MTCRF: + { + uint32_t crm = (word32 >> 12) & 0xff; + + PushUIMMValue(instruction, crm); + PushRS(instruction, word32); + break; + } + + case PPC_ID_MTFSFx: + { + uint32_t w = (word32 >> 16) & 0x1; + uint32_t l = (word32 >> 25) & 0x1; + uint32_t flm = (word32 >> 17) & 0xff; + + PushUIMMValue(instruction, flm); + PushFRB(instruction, word32); + + if (w != 0 || l != 0) + { + PushUIMMValue(instruction, l); + PushUIMMValue(instruction, w); + } + + instruction->flags.rc = word32 & 0x1; + break; + } + + case PPC_ID_MTFSFIx: + { + uint32_t u = (word32 >> 12) & 0xf; + uint32_t w = (word32 >> 16) & 0x1; + + PushCRFD(instruction, word32); + PushUIMMValue(instruction, u); + if (w != 0) + PushUIMMValue(instruction, w); + + instruction->flags.rc = word32 & 0x1; + break; + } + + case PPC_ID_MTOCRF: + { + uint32_t fxm = (word32 >> 12) & 0xff; + + PushRS(instruction, word32); + PushUIMMValue(instruction, fxm); + break; + } + + case PPC_ID_MTSR: + { + uint32_t sr = (word32 >> 16) & 0xf; + + PushUIMMValue(instruction, sr); + PushRS(instruction, word32); + + break; + } + + case PPC_ID_MTSRIN: + PushRS(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_RLWIMIx: + case PPC_ID_RLWINMx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH(word32)); + PushUIMMValue(instruction, GetMB(word32)); + PushUIMMValue(instruction, GetME(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_RLWNMx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushRB(instruction, word32); + PushUIMMValue(instruction, GetMB(word32)); + PushUIMMValue(instruction, GetME(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_SC: + { + uint32_t lev = (word32 >> 5) & 0x7f; + if (lev != 0) + PushUIMMValue(instruction, lev); + + break; + } + + case PPC_ID_SLBMFEE: + PushRD(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_SLBMTE: + PushRS(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_SRADIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH64(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_SRAWIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_STSWI: + { + uint32_t nb = (word32 >> 11) & 0x1f; + + PushRS(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, nb); + break; + } + + case PPC_ID_SYNC: + { + uint32_t l = (word32 >> 21) & 0x3; + + PushUIMMValue(instruction, l); + break; + } + + case PPC_ID_TLBIE: + PushRB(instruction, word32); + PushRS(instruction, word32); + break; + + case PPC_ID_TLBIVAX: + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_WAIT: + { + uint32_t wc = (word32 >> 21) & 0x3; + + if (wc != 0) + PushUIMMValue(instruction, wc); + + break; + } + + case PPC_ID_WRTEEI: + { + uint32_t e = (word32 & 0x00008000) != 0; + + PushUIMMValue(instruction, e); + break; + } + + // ALTIVEC INSTRUCTIONS + + // vD, vA, vB, vC + case PPC_ID_AV_VMHADDSHS: + case PPC_ID_AV_VMHRADDSHS: + case PPC_ID_AV_VMLADDUHM: + case PPC_ID_AV_VMSUMMBM: + case PPC_ID_AV_VMSUMUBM: + case PPC_ID_AV_VMSUMSHM: + case PPC_ID_AV_VMSUMSHS: + case PPC_ID_AV_VMSUMUHM: + case PPC_ID_AV_VMSUMUHS: + case PPC_ID_AV_VPERM: + case PPC_ID_AV_VSEL: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVB(instruction, word32); + PushAltivecVC(instruction, word32); + break; + + // vD, vA, vC, vB (note swapped vC, vB) + case PPC_ID_AV_VMADDFP: + case PPC_ID_AV_VNMSUBFP: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVC(instruction, word32); + PushAltivecVB(instruction, word32); + break; + + // vD, vA, vB + case PPC_ID_AV_VADDCUW: + case PPC_ID_AV_VADDFP: + case PPC_ID_AV_VADDSBS: + case PPC_ID_AV_VADDSHS: + case PPC_ID_AV_VADDSWS: + case PPC_ID_AV_VADDUBM: + case PPC_ID_AV_VADDUBS: + case PPC_ID_AV_VADDUDM: + case PPC_ID_AV_VADDUHM: + case PPC_ID_AV_VADDUHS: + case PPC_ID_AV_VADDUWM: + case PPC_ID_AV_VADDUWS: + case PPC_ID_AV_VAND: + case PPC_ID_AV_VANDC: + case PPC_ID_AV_VAVGSB: + case PPC_ID_AV_VAVGSH: + case PPC_ID_AV_VAVGSW: + case PPC_ID_AV_VAVGUB: + case PPC_ID_AV_VAVGUH: + case PPC_ID_AV_VAVGUW: + case PPC_ID_AV_VEQV: + case PPC_ID_AV_VMAXFP: + case PPC_ID_AV_VMAXSB: + case PPC_ID_AV_VMAXSD: + case PPC_ID_AV_VMAXSH: + case PPC_ID_AV_VMAXSW: + case PPC_ID_AV_VMAXUB: + case PPC_ID_AV_VMAXUD: + case PPC_ID_AV_VMAXUH: + case PPC_ID_AV_VMAXUW: + case PPC_ID_AV_VMINFP: + case PPC_ID_AV_VMINUB: + case PPC_ID_AV_VMINUD: + case PPC_ID_AV_VMINUH: + case PPC_ID_AV_VMINUW: + case PPC_ID_AV_VMINSB: + case PPC_ID_AV_VMINSD: + case PPC_ID_AV_VMINSH: + case PPC_ID_AV_VMINSW: + case PPC_ID_AV_VMRGHB: + case PPC_ID_AV_VMRGHH: + case PPC_ID_AV_VMRGHW: + case PPC_ID_AV_VMRGLB: + case PPC_ID_AV_VMRGLH: + case PPC_ID_AV_VMRGLW: + case PPC_ID_AV_VMULESB: + case PPC_ID_AV_VMULESH: + case PPC_ID_AV_VMULESW: + case PPC_ID_AV_VMULEUB: + case PPC_ID_AV_VMULEUH: + case PPC_ID_AV_VMULEUW: + case PPC_ID_AV_VMULOSB: + case PPC_ID_AV_VMULOSH: + case PPC_ID_AV_VMULOSW: + case PPC_ID_AV_VMULOUB: + case PPC_ID_AV_VMULOUH: + case PPC_ID_AV_VMULOUW: + case PPC_ID_AV_VMULUWM: + case PPC_ID_AV_VNAND: + case PPC_ID_AV_VNOR: + case PPC_ID_AV_VOR: + case PPC_ID_AV_VORC: + case PPC_ID_AV_VPKPX: + case PPC_ID_AV_VPKSHUS: + case PPC_ID_AV_VPKSHSS: + case PPC_ID_AV_VPKSWSS: + case PPC_ID_AV_VPKSWUS: + case PPC_ID_AV_VPKUHUM: + case PPC_ID_AV_VPKUHUS: + case PPC_ID_AV_VPKUWUM: + case PPC_ID_AV_VPKUWUS: + case PPC_ID_AV_VRLB: + case PPC_ID_AV_VRLD: + case PPC_ID_AV_VRLH: + case PPC_ID_AV_VRLW: + case PPC_ID_AV_VSL: + case PPC_ID_AV_VSLB: + case PPC_ID_AV_VSLD: + case PPC_ID_AV_VSLH: + case PPC_ID_AV_VSLO: + case PPC_ID_AV_VSLW: + case PPC_ID_AV_VSR: + case PPC_ID_AV_VSRAB: + case PPC_ID_AV_VSRAD: + case PPC_ID_AV_VSRAH: + case PPC_ID_AV_VSRAW: + case PPC_ID_AV_VSRB: + case PPC_ID_AV_VSRD: + case PPC_ID_AV_VSRH: + case PPC_ID_AV_VSRO: + case PPC_ID_AV_VSRW: + case PPC_ID_AV_VSUBCUW: + case PPC_ID_AV_VSUBFP: + case PPC_ID_AV_VSUBSBS: + case PPC_ID_AV_VSUBSHS: + case PPC_ID_AV_VSUBSWS: + case PPC_ID_AV_VSUBUBS: + case PPC_ID_AV_VSUBUHS: + case PPC_ID_AV_VSUBUWS: + case PPC_ID_AV_VSUBUBM: + case PPC_ID_AV_VSUBUDM: + case PPC_ID_AV_VSUBUHM: + case PPC_ID_AV_VSUBUWM: + case PPC_ID_AV_VSUM2SWS: + case PPC_ID_AV_VSUM4SBS: + case PPC_ID_AV_VSUM4SHS: + case PPC_ID_AV_VSUM4UBS: + case PPC_ID_AV_VSUMSWS: + case PPC_ID_AV_VXOR: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVB(instruction, word32); + break; + + // [.] vD, vA, vB + case PPC_ID_AV_VCMPBFPx: + case PPC_ID_AV_VCMPEQFPx: + case PPC_ID_AV_VCMPGEFPx: + case PPC_ID_AV_VCMPEQUBx: + case PPC_ID_AV_VCMPEQUDx: + case PPC_ID_AV_VCMPEQUHx: + case PPC_ID_AV_VCMPEQUWx: + case PPC_ID_AV_VCMPGTFPx: + case PPC_ID_AV_VCMPGTSBx: + case PPC_ID_AV_VCMPGTSDx: + case PPC_ID_AV_VCMPGTSHx: + case PPC_ID_AV_VCMPGTSWx: + case PPC_ID_AV_VCMPGTUBx: + case PPC_ID_AV_VCMPGTUDx: + case PPC_ID_AV_VCMPGTUHx: + case PPC_ID_AV_VCMPGTUWx: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVB(instruction, word32); + + instruction->flags.rc = (word32 >> 10) & 0x1; + break; + + // vD, vB + case PPC_ID_AV_VCLZB: + case PPC_ID_AV_VCLZD: + case PPC_ID_AV_VCLZH: + case PPC_ID_AV_VCLZW: + case PPC_ID_AV_VEXPTEFP: + case PPC_ID_AV_VLOGEFP: + case PPC_ID_AV_VPOPCNTB: + case PPC_ID_AV_VPOPCNTD: + case PPC_ID_AV_VPOPCNTH: + case PPC_ID_AV_VPOPCNTW: + case PPC_ID_AV_VREFP: + case PPC_ID_AV_VRFIM: + case PPC_ID_AV_VRFIN: + case PPC_ID_AV_VRFIP: + case PPC_ID_AV_VRFIZ: + case PPC_ID_AV_VRSQRTEFP: + case PPC_ID_AV_VUPKHPX: + case PPC_ID_AV_VUPKHSB: + case PPC_ID_AV_VUPKHSH: + case PPC_ID_AV_VUPKLPX: + case PPC_ID_AV_VUPKLSB: + case PPC_ID_AV_VUPKLSH: + PushAltivecVD(instruction, word32); + PushAltivecVB(instruction, word32); + break; + + // vD, vB, UIMM + case PPC_ID_AV_VCFSX: + case PPC_ID_AV_VCFUX: + case PPC_ID_AV_VCTSXS: + case PPC_ID_AV_VCTUXS: + case PPC_ID_AV_VSPLTB: + case PPC_ID_AV_VSPLTH: + case PPC_ID_AV_VSPLTW: + PushAltivecVD(instruction, word32); + PushAltivecVB(instruction, word32); + PushUIMMValue(instruction, (word32 >> 16) & 0x1f); + break; + + // vD, SIMM + case PPC_ID_AV_VSPLTISB: + case PPC_ID_AV_VSPLTISH: + case PPC_ID_AV_VSPLTISW: + { + PushAltivecVD(instruction, word32); + + int32_t simm = sign_extend((word32 >> 16) & 0x1f, 5); + PushSIMMValue(instruction, simm); + break; + } + + // vD, d(rA) + case PPC_ID_AV_LVEBX: + case PPC_ID_AV_LVEHX: + case PPC_ID_AV_LVEWX: + case PPC_ID_AV_LVSL: + case PPC_ID_AV_LVSR: + case PPC_ID_AV_LVX: + case PPC_ID_AV_LVXL: + PushAltivecVD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // vS, d(rA) + case PPC_ID_AV_STVEBX: + case PPC_ID_AV_STVEHX: + case PPC_ID_AV_STVEWX: + case PPC_ID_AV_STVX: + case PPC_ID_AV_STVXL: + PushAltivecVS(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_AV_DST: + case PPC_ID_AV_DSTST: + case PPC_ID_AV_DSTSTT: + case PPC_ID_AV_DSTT: + { + uint32_t strm = (word32 >> 21) & 0x3; + + PushRA(instruction, word32); + PushRB(instruction, word32); + PushUIMMValue(instruction, strm); + break; + } + + case PPC_ID_AV_DSS: + { + uint32_t strm = (word32 >> 21) & 0x3; + PushUIMMValue(instruction, strm); + break; + } + + case PPC_ID_AV_MFVSCR: + // mfvscr vD + PushAltivecVD(instruction, word32); + break; + + case PPC_ID_AV_MTVSCR: + // mtvscr vB + PushAltivecVB(instruction, word32); + break; + + case PPC_ID_AV_VSLDOI: + // vsldoi vD, vA, vB, UIMM + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVB(instruction, word32); + PushUIMMValue(instruction, (word32 >> 6) & 0xf); + break; + + // VSX INSTRUCTIONS + + // vrD, vrA, vrB + case PPC_ID_VSX_XVADDDP: + case PPC_ID_VSX_XVADDSP: + case PPC_ID_VSX_XVCPSGNDP: + case PPC_ID_VSX_XVCPSGNSP: + case PPC_ID_VSX_XVDIVDP: + case PPC_ID_VSX_XVDIVSP: + case PPC_ID_VSX_XVMADDADP: + case PPC_ID_VSX_XVMADDASP: + case PPC_ID_VSX_XVMADDMDP: + case PPC_ID_VSX_XVMADDMSP: + case PPC_ID_VSX_XVMAXDP: + case PPC_ID_VSX_XVMAXSP: + case PPC_ID_VSX_XVMINDP: + case PPC_ID_VSX_XVMINSP: + case PPC_ID_VSX_XVMSUBADP: + case PPC_ID_VSX_XVMSUBMDP: + case PPC_ID_VSX_XVMSUBASP: + case PPC_ID_VSX_XVMSUBMSP: + case PPC_ID_VSX_XVMULDP: + case PPC_ID_VSX_XVMULSP: + case PPC_ID_VSX_XVNMADDADP: + case PPC_ID_VSX_XVNMADDASP: + case PPC_ID_VSX_XVNMADDMDP: + case PPC_ID_VSX_XVNMADDMSP: + case PPC_ID_VSX_XVNMSUBADP: + case PPC_ID_VSX_XVNMSUBASP: + case PPC_ID_VSX_XVNMSUBMDP: + case PPC_ID_VSX_XVNMSUBMSP: + case PPC_ID_VSX_XVSUBDP: + case PPC_ID_VSX_XVSUBSP: + case PPC_ID_VSX_XXLAND: + case PPC_ID_VSX_XXLANDC: + case PPC_ID_VSX_XXLEQV: + case PPC_ID_VSX_XXLOR: + case PPC_ID_VSX_XXLNAND: + case PPC_ID_VSX_XXLNOR: + case PPC_ID_VSX_XXLORC: + case PPC_ID_VSX_XXLXOR: + case PPC_ID_VSX_XXMRGHD: + case PPC_ID_VSX_XXMRGHW: + case PPC_ID_VSX_XXMRGLD: + case PPC_ID_VSX_XXMRGLW: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + break; + + // [.] vrD, rA, vrB + case PPC_ID_VSX_XVCMPEQDPx: + case PPC_ID_VSX_XVCMPEQSPx: + case PPC_ID_VSX_XVCMPGEDPx: + case PPC_ID_VSX_XVCMPGESPx: + case PPC_ID_VSX_XVCMPGTDPx: + case PPC_ID_VSX_XVCMPGTSPx: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + instruction->flags.rc = (word32 & 0x400) != 0; + break; + + // vrD, vrA, vrB + case PPC_ID_VSX_XSADDDP: + case PPC_ID_VSX_XSCPSGNDP: + case PPC_ID_VSX_XSDIVDP: + case PPC_ID_VSX_XSMADDADP: + case PPC_ID_VSX_XSMADDMDP: + case PPC_ID_VSX_XSMAXDP: + case PPC_ID_VSX_XSMINDP: + case PPC_ID_VSX_XSMSUBADP: + case PPC_ID_VSX_XSMSUBMDP: + case PPC_ID_VSX_XSMULDP: + case PPC_ID_VSX_XSNMADDADP: + case PPC_ID_VSX_XSNMADDMDP: + case PPC_ID_VSX_XSNMSUBADP: + case PPC_ID_VSX_XSNMSUBMDP: + case PPC_ID_VSX_XSSUBDP: + PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); + PushVsxA(instruction, word32, VSX_WIDTH_DWORD0); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + break; + + // vrD, vrB + case PPC_ID_VSX_XVABSDP: + case PPC_ID_VSX_XVABSSP: + case PPC_ID_VSX_XVCVDPSP: + case PPC_ID_VSX_XVCVDPSXDS: + case PPC_ID_VSX_XVCVDPSXWS: + case PPC_ID_VSX_XVCVDPUXDS: + case PPC_ID_VSX_XVCVDPUXWS: + case PPC_ID_VSX_XVCVSPDP: + case PPC_ID_VSX_XVCVSPSXDS: + case PPC_ID_VSX_XVCVSPSXWS: + case PPC_ID_VSX_XVCVSPUXDS: + case PPC_ID_VSX_XVCVSPUXWS: + case PPC_ID_VSX_XVCVSXDDP: + case PPC_ID_VSX_XVCVSXDSP: + case PPC_ID_VSX_XVCVSXWDP: + case PPC_ID_VSX_XVCVSXWSP: + case PPC_ID_VSX_XVCVUXDDP: + case PPC_ID_VSX_XVCVUXDSP: + case PPC_ID_VSX_XVCVUXWDP: + case PPC_ID_VSX_XVCVUXWSP: + case PPC_ID_VSX_XVNABSDP: + case PPC_ID_VSX_XVNABSSP: + case PPC_ID_VSX_XVNEGDP: + case PPC_ID_VSX_XVNEGSP: + case PPC_ID_VSX_XVRDPI: + case PPC_ID_VSX_XVRDPIC: + case PPC_ID_VSX_XVRDPIM: + case PPC_ID_VSX_XVRDPIP: + case PPC_ID_VSX_XVRDPIZ: + case PPC_ID_VSX_XVREDP: + case PPC_ID_VSX_XVRESP: + case PPC_ID_VSX_XVRSPI: + case PPC_ID_VSX_XVRSPIC: + case PPC_ID_VSX_XVRSPIM: + case PPC_ID_VSX_XVRSPIP: + case PPC_ID_VSX_XVRSPIZ: + case PPC_ID_VSX_XVRSQRTEDP: + case PPC_ID_VSX_XVRSQRTESP: + case PPC_ID_VSX_XVSQRTSP: + case PPC_ID_VSX_XVSQRTDP: + case PPC_ID_VSX_XVMOVDP: + case PPC_ID_VSX_XVMOVSP: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + break; + + + case PPC_ID_VSX_XSABSDP: + case PPC_ID_VSX_XSCVDPSXDS: + case PPC_ID_VSX_XSCVDPSP: + case PPC_ID_VSX_XSCVDPSXWS: + case PPC_ID_VSX_XSCVDPUXDS: + case PPC_ID_VSX_XSCVDPUXWS: + case PPC_ID_VSX_XSCVSPDP: + case PPC_ID_VSX_XSCVSXDDP: + case PPC_ID_VSX_XSCVUXDDP: + case PPC_ID_VSX_XSNABSDP: + case PPC_ID_VSX_XSNEGDP: + case PPC_ID_VSX_XSRDPI: + case PPC_ID_VSX_XSRDPIC: + case PPC_ID_VSX_XSRDPIM: + case PPC_ID_VSX_XSRDPIP: + case PPC_ID_VSX_XSRDPIZ: + case PPC_ID_VSX_XSREDP: + case PPC_ID_VSX_XSRSQRTEDP: + case PPC_ID_VSX_XSSQRTDP: + PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + break; + + // + + // vrD, vrA, vrB, + case PPC_ID_VSX_XXPERMDI: + case PPC_ID_VSX_XXSLDWI: + { + uint32_t uimm = (word32 >> 8) & 0x3; + + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + PushUIMMValue(instruction, uimm); + break; + } + + // vrD, rA, rB (load indexed) + case PPC_ID_VSX_LXVD2X: + case PPC_ID_VSX_LXVDSX: + case PPC_ID_VSX_LXVW4X: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_VSX_LXSDX: + PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // vrS, rA, rB (store indexed) + case PPC_ID_VSX_STXVD2X: + case PPC_ID_VSX_STXVW4X: + PushVsxS(instruction, word32, VSX_WIDTH_FULL); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_VSX_STXSDX: + PushVsxS(instruction, word32, VSX_WIDTH_DWORD0); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // crfD, vrA, vrB + case PPC_ID_VSX_XSCMPODP: + case PPC_ID_VSX_XSCMPUDP: + case PPC_ID_VSX_XSTDIVDP: + PushCRFD(instruction, word32); + PushVsxA(instruction, word32, VSX_WIDTH_DWORD0); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + break; + + // crfD, vrA, vrB + case PPC_ID_VSX_XVTDIVDP: + case PPC_ID_VSX_XVTDIVSP: + PushCRFD(instruction, word32); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + break; + + // crfD, vrB + case PPC_ID_VSX_XVTSQRTSP: + case PPC_ID_VSX_XVTSQRTDP: + PushCRFD(instruction, word32); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + break; + + case PPC_ID_VSX_XSTSQRTDP: + PushCRFD(instruction, word32); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + break; + + case PPC_ID_VSX_XXSPLTD: + { + uint32_t uimm = (word32 >> 8) & 0x3; + + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + + if (uimm == 3) + PushUIMMValue(instruction, 1); + else + PushUIMMValue(instruction, 0); + + break; + } + + case PPC_ID_VSX_XXSPLTW: + { + uint32_t um = (word32 >> 16) & 0x3; + + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + PushUIMMValue(instruction, um); + break; + } + + case PPC_ID_VSX_XXSWAPD: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + break; + + case PPC_ID_VSX_XXSEL: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + PushVsxC(instruction, word32, VSX_WIDTH_FULL); + break; + + default: + break; + } +} + +// the hope is to avoid having to manipulate strings in something that's +// somewhat hot, so we create a bunch of lookup tables for each mnemonic + +// for "OP" and "OP." +#define DEFINE_SUBMNEM_RC(_identifier, base) \ + const char* _identifier[2] = \ + { \ + base, \ + base ".", \ + }; + +// for "OP", "OP.", "OPo", and "OPo." +#define DEFINE_SUBMNEM_OE_RC(_identifier, base) \ + const char* _identifier[4] = \ + { \ + base, \ + base ".", \ + base "o", \ + base "o.", \ + }; + +// for "OP" and "OPl" +#define DEFINE_SUBMNEM_LK(_identifier, base) \ + const char* _identifier[2] = \ + { \ + base, \ + base "l", \ + }; + +// for "OP" and "OPl" and +/- hints +#define DEFINE_SUBMNEM_LK_HINT(_identifier, base) \ + const char* _identifier[8] = \ + { \ + base, \ + base "l", \ + base, \ + base "l", \ + base "-", \ + base "l-", \ + base "+", \ + base "l+", \ + }; + +// for "OP", "OPl", "OPa", and "OPla" +#define DEFINE_SUBMNEM_AA_LK(_identifier, base) \ + const char* _identifier[4] = \ + { \ + base, \ + base "l", \ + base "a", \ + base "la", \ + }; + +// for "OP", "OPl", "OPa", "OPla" and +/- hints +#define DEFINE_SUBMNEM_AA_LK_HINT(_identifier, base) \ + const char* _identifier[16] = \ + { \ + base, \ + base "l", \ + base "a", \ + base "la", \ + base, \ + base "l", \ + base "a", \ + base "la", \ + base "-", \ + base "l-", \ + base "a-", \ + base "la-", \ + base "+", \ + base "l+", \ + base "a+", \ + base "la+" \ + }; + +DEFINE_SUBMNEM_OE_RC(SubMnemADDx, "add") +DEFINE_SUBMNEM_OE_RC(SubMnemADDCx, "addc") +DEFINE_SUBMNEM_OE_RC(SubMnemADDEx, "adde") +DEFINE_SUBMNEM_RC(SubMnemADDICx, "addic") +DEFINE_SUBMNEM_OE_RC(SubMnemADDMEx, "addme") +DEFINE_SUBMNEM_OE_RC(SubMnemADDZEx, "addze") +DEFINE_SUBMNEM_RC(SubMnemANDx, "and") +DEFINE_SUBMNEM_RC(SubMnemANDCx, "andc") +DEFINE_SUBMNEM_AA_LK(SubMnemBx, "b") +DEFINE_SUBMNEM_AA_LK(SubMnemBCx, "bc") +DEFINE_SUBMNEM_LK(SubMnemBCTRx, "bctr") +DEFINE_SUBMNEM_LK(SubMnemBCCTRx, "bcctr") +DEFINE_SUBMNEM_LK(SubMnemBCLRx, "bclr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBDZx, "bdz") +DEFINE_SUBMNEM_LK_HINT(SubMnemBDZCTRx, "bdzctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBDZLRx, "bdzlr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBDNZx, "bdnz") +DEFINE_SUBMNEM_LK_HINT(SubMnemBDNZCTRx, "bdnzctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBDNZLRx, "bdnzlr") +DEFINE_SUBMNEM_AA_LK(SubMnemBDNZFx, "bdnzf") +DEFINE_SUBMNEM_LK(SubMnemBDNZFCTRx, "bdnzfctr") +DEFINE_SUBMNEM_LK(SubMnemBDNZFLRx, "bdnzflr") +DEFINE_SUBMNEM_AA_LK(SubMnemBDNZTx, "bdnzt") +DEFINE_SUBMNEM_LK(SubMnemBDNZTCTRx, "bdnztctr") +DEFINE_SUBMNEM_LK(SubMnemBDNZTLRx, "bdnztlr") +DEFINE_SUBMNEM_AA_LK(SubMnemBDZFx, "bdzf") +DEFINE_SUBMNEM_LK(SubMnemBDZFCTRx, "bdzfctr") +DEFINE_SUBMNEM_LK(SubMnemBDZFLRx, "bdzflr") +DEFINE_SUBMNEM_LK(SubMnemBDFLRx, "bdzlr") +DEFINE_SUBMNEM_AA_LK(SubMnemBDZTx, "bdzt") +DEFINE_SUBMNEM_LK(SubMnemBDZTCTRx, "bdztctr") +DEFINE_SUBMNEM_LK(SubMnemBDZTLRx, "bdztlr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBEQx, "beq") +DEFINE_SUBMNEM_LK_HINT(SubMnemBEQCTRx, "beqctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBEQLRx, "beqlr") +DEFINE_SUBMNEM_AA_LK(SubMnemBFx, "bf") +DEFINE_SUBMNEM_AA_LK(SubMnemBFLRx, "bflr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBGEx, "bge") +DEFINE_SUBMNEM_LK_HINT(SubMnemBGECTRx, "bgectr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBGELRx, "bgelr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBGTx, "bgt") +DEFINE_SUBMNEM_LK_HINT(SubMnemBGTCTRx, "bgtctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBGTLRx, "bgtlr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBLEx, "ble") +DEFINE_SUBMNEM_LK_HINT(SubMnemBLECTRx, "blectr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBLELRx, "blelr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBLTx, "blt") +DEFINE_SUBMNEM_LK_HINT(SubMnemBLTCTRx, "bltctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBLTLRx, "bltlr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBLRx, "blr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBNEx, "bne") +DEFINE_SUBMNEM_LK_HINT(SubMnemBNECTRx, "bnectr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBNELRx, "bnelr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBNSx, "bns") +DEFINE_SUBMNEM_LK_HINT(SubMnemBNSCTRx, "bnsctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBNSLRx, "bnslr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBSOx, "bso") +DEFINE_SUBMNEM_LK_HINT(SubMnemBSOCTRx, "bsoctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBSOLRx, "bsolr") +DEFINE_SUBMNEM_AA_LK(SubMnemBTx, "bt") +DEFINE_SUBMNEM_AA_LK(SubMnemBTLRx, "btlr") +DEFINE_SUBMNEM_RC(SubMnemCLRLDIx, "clrldi") +DEFINE_SUBMNEM_RC(SubMnemCLRLWIx, "clrlwi") +DEFINE_SUBMNEM_RC(SubMnemCLRRWIx, "clrrwi") +DEFINE_SUBMNEM_RC(SubMnemCNTLZDx, "cntlzd") +DEFINE_SUBMNEM_RC(SubMnemCNTLZWx, "cntlzw") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVDx, "divd") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVDUx, "divdu") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVWx, "divw") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVWUx, "divwu") +DEFINE_SUBMNEM_RC(SubMnemEQVx, "eqv") +DEFINE_SUBMNEM_RC(SubMnemEXTSBx, "extsb") +DEFINE_SUBMNEM_RC(SubMnemEXTSHx, "extsh") +DEFINE_SUBMNEM_RC(SubMnemEXTSWx, "extsw") +DEFINE_SUBMNEM_RC(SubMnemFABSx, "fabs") +DEFINE_SUBMNEM_RC(SubMnemFADDx, "fadd") +DEFINE_SUBMNEM_RC(SubMnemFADDSx, "fadds") +DEFINE_SUBMNEM_RC(SubMnemFCFIDx, "fcfid") +DEFINE_SUBMNEM_RC(SubMnemFCFIDSx, "fcfids") +DEFINE_SUBMNEM_RC(SubMnemFCFIDUx, "fcfidu") +DEFINE_SUBMNEM_RC(SubMnemFCFIDUSx, "fcfidus") +DEFINE_SUBMNEM_RC(SubMnemFCPSGNx, "fcpsgn") +DEFINE_SUBMNEM_RC(SubMnemFCTIDx, "fctid") +DEFINE_SUBMNEM_RC(SubMnemFCTIDUZx, "fctiduz") +DEFINE_SUBMNEM_RC(SubMnemFCTIDZx, "fctidz") +DEFINE_SUBMNEM_RC(SubMnemFCTIWx, "fctiw") +DEFINE_SUBMNEM_RC(SubMnemFCTIWUZx, "fctiwuz") +DEFINE_SUBMNEM_RC(SubMnemFCTIWZx, "fctiwz") +DEFINE_SUBMNEM_RC(SubMnemFDIVx, "fdiv") +DEFINE_SUBMNEM_RC(SubMnemFDIVSx, "fdivs") +DEFINE_SUBMNEM_RC(SubMnemFMADDx, "fmadd") +DEFINE_SUBMNEM_RC(SubMnemFMADDSx, "fmadds") +DEFINE_SUBMNEM_RC(SubMnemFMRx, "fmr") +DEFINE_SUBMNEM_RC(SubMnemFMSUBx, "fmsub") +DEFINE_SUBMNEM_RC(SubMnemFMSUBSx, "fmsubs") +DEFINE_SUBMNEM_RC(SubMnemFMULx, "fmul") +DEFINE_SUBMNEM_RC(SubMnemFMULSx, "fmuls") +DEFINE_SUBMNEM_RC(SubMnemFNABSx, "fnabs") +DEFINE_SUBMNEM_RC(SubMnemFNEGx, "fneg") +DEFINE_SUBMNEM_RC(SubMnemFNMADDx, "fnmadd") +DEFINE_SUBMNEM_RC(SubMnemFNMADDSx, "fnmadds") +DEFINE_SUBMNEM_RC(SubMnemFNMSUBx, "fnmsub") +DEFINE_SUBMNEM_RC(SubMnemFNMSUBSx, "fnmsubs") +DEFINE_SUBMNEM_RC(SubMnemFREx, "fre") +DEFINE_SUBMNEM_RC(SubMnemFRESx, "fres") +DEFINE_SUBMNEM_RC(SubMnemFRIMx, "frim") +DEFINE_SUBMNEM_RC(SubMnemFRINx, "frin") +DEFINE_SUBMNEM_RC(SubMnemFRIPx, "frip") +DEFINE_SUBMNEM_RC(SubMnemFRIZx, "friz") +DEFINE_SUBMNEM_RC(SubMnemFRSPx, "frsp") +DEFINE_SUBMNEM_RC(SubMnemFRSQRTEx, "frsqrte") +DEFINE_SUBMNEM_RC(SubMnemFRSQRTESx, "frsqrtes") +DEFINE_SUBMNEM_RC(SubMnemFSELx, "fsel") +DEFINE_SUBMNEM_RC(SubMnemFSQRTx, "fsqrt") +DEFINE_SUBMNEM_RC(SubMnemFSQRTSx, "fsqrts") +DEFINE_SUBMNEM_RC(SubMnemFSUBx, "fsub") +DEFINE_SUBMNEM_RC(SubMnemFSUBSx, "fsubs") +DEFINE_SUBMNEM_RC(SubMnemMFFSx, "mffs") +DEFINE_SUBMNEM_RC(SubMnemMTFSB0x, "mtfsb0") +DEFINE_SUBMNEM_RC(SubMnemMTFSB1x, "mtfsb1") +DEFINE_SUBMNEM_RC(SubMnemMTFSFx, "mtfsf") +DEFINE_SUBMNEM_RC(SubMnemMTFSFIx, "mtfsfi") +DEFINE_SUBMNEM_RC(SubMnemMRx, "mr") +DEFINE_SUBMNEM_RC(SubMnemMULHDx, "mulhd") +DEFINE_SUBMNEM_RC(SubMnemMULHDUx, "mulhdu") +DEFINE_SUBMNEM_RC(SubMnemMULHWx, "mulhw") +DEFINE_SUBMNEM_RC(SubMnemMULHWUx, "mulhwu") +DEFINE_SUBMNEM_OE_RC(SubMnemMULLDx, "mulld") +DEFINE_SUBMNEM_OE_RC(SubMnemMULLWx, "mullw") +DEFINE_SUBMNEM_RC(SubMnemNANDx, "nand") +DEFINE_SUBMNEM_OE_RC(SubMnemNEGx, "neg") +DEFINE_SUBMNEM_RC(SubMnemNORx, "nor") +DEFINE_SUBMNEM_RC(SubMnemORx, "or") +DEFINE_SUBMNEM_RC(SubMnemORCx, "orc") +DEFINE_SUBMNEM_RC(SubMnemRLDICLx, "rldicl") +DEFINE_SUBMNEM_RC(SubMnemRLDICRx, "rldicr") +DEFINE_SUBMNEM_RC(SubMnemRLDICx, "rldic") +DEFINE_SUBMNEM_RC(SubMnemRLDIMIx, "rldimi") +DEFINE_SUBMNEM_RC(SubMnemRLDCLx, "rldcl") +DEFINE_SUBMNEM_RC(SubMnemRLDCRx, "rldcr") +DEFINE_SUBMNEM_RC(SubMnemRLWIMIx, "rlwimi") +DEFINE_SUBMNEM_RC(SubMnemRLWINMx, "rlwinm") +DEFINE_SUBMNEM_RC(SubMnemRLWNMx, "rlwnm") +DEFINE_SUBMNEM_RC(SubMnemROTLDx, "rotld") +DEFINE_SUBMNEM_RC(SubMnemROTLDIx, "rotldi") +DEFINE_SUBMNEM_RC(SubMnemROTLWx, "rotlw") +DEFINE_SUBMNEM_RC(SubMnemROTLWIx, "rotlwi") +DEFINE_SUBMNEM_RC(SubMnemSLDx, "sld") +DEFINE_SUBMNEM_RC(SubMnemSLDIx, "sldi") +DEFINE_SUBMNEM_RC(SubMnemSLWx, "slw") +DEFINE_SUBMNEM_RC(SubMnemSLWIx, "slwi") +DEFINE_SUBMNEM_RC(SubMnemSRADx, "srad") +DEFINE_SUBMNEM_RC(SubMnemSRADIx, "sradi") +DEFINE_SUBMNEM_RC(SubMnemSRAWx, "sraw") +DEFINE_SUBMNEM_RC(SubMnemSRAWIx, "srawi") +DEFINE_SUBMNEM_RC(SubMnemSRDx, "srd") +DEFINE_SUBMNEM_RC(SubMnemSRDIx, "srdi") +DEFINE_SUBMNEM_RC(SubMnemSRWx, "srw") +DEFINE_SUBMNEM_RC(SubMnemSRWIx, "srwi") +DEFINE_SUBMNEM_OE_RC(SubMnemSUBFx, "subf") +DEFINE_SUBMNEM_OE_RC(SubMnemSUBFCx, "subfc") +DEFINE_SUBMNEM_OE_RC(SubMnemSUBFEx, "subfe") +DEFINE_SUBMNEM_OE_RC(SubMnemSUBFMEx, "subfme") +DEFINE_SUBMNEM_OE_RC(SubMnemSUBFZEx, "subfze") +DEFINE_SUBMNEM_RC(SubMnemXORx, "xor") + +// ALTIVEC MNEMONICS +DEFINE_SUBMNEM_RC(SubMnemVCMPBFPx, "vcmpbfp"); +DEFINE_SUBMNEM_RC(SubMnemVCMPEQFPx, "vcmpeqfp"); +DEFINE_SUBMNEM_RC(SubMnemVCMPEQUBx, "vcmpequb"); +DEFINE_SUBMNEM_RC(SubMnemVCMPEQUDx, "vcmpequd"); +DEFINE_SUBMNEM_RC(SubMnemVCMPEQUHx, "vcmpequh"); +DEFINE_SUBMNEM_RC(SubMnemVCMPEQUWx, "vcmpequw"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGEFPx, "vcmpgefp"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTFPx, "vcmpgtfp"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTSBx, "vcmpgtsb"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTSDx, "vcmpgtsd"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTSHx, "vcmpgtsh"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTSWx, "vcmpgtsw"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTUBx, "vcmpgtub"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTUDx, "vcmpgtud"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTUHx, "vcmpgtuh"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTUWx, "vcmpgtuw"); + +// VSX MNEMONICS +DEFINE_SUBMNEM_RC(SubMnemXVCMPEQDPx, "xvcmpeqdp"); +DEFINE_SUBMNEM_RC(SubMnemXVCMPEQSPx, "xvcmpeqsp"); +DEFINE_SUBMNEM_RC(SubMnemXVCMPGEDPx, "xvcmpgedp"); +DEFINE_SUBMNEM_RC(SubMnemXVCMPGESPx, "xvcmpgesp"); +DEFINE_SUBMNEM_RC(SubMnemXVCMPGTDPx, "xvcmpgtdp"); +DEFINE_SUBMNEM_RC(SubMnemXVCMPGTSPx, "xvcmpgtsp"); + +static const char* RcMnemonic(const Instruction* instruction, const char* names[2]) +{ + return names[instruction->flags.rc]; +} + +static const char* OeRcMnemonic(const Instruction* instruction, const char* names[4]) +{ + return names[2*instruction->flags.oe + instruction->flags.rc]; +} + +static const char* LkMnemonic(const Instruction* instruction, const char* names[2]) +{ + return names[instruction->flags.lk]; +} + +static const char* LkHintMnemonic(const Instruction* instruction, const char* names[8]) +{ + return names[2*instruction->flags.branchLikelyHint + instruction->flags.lk]; +} + +static const char* AaLkMnemonic(const Instruction* instruction, const char* names[4]) +{ + return names[2*instruction->flags.aa + instruction->flags.lk]; +} + +static const char* AaLkHintMnemonic(const Instruction* instruction, const char* names[16]) +{ + return names[4*instruction->flags.branchLikelyHint + 2*instruction->flags.aa + instruction->flags.lk]; +} + +const char* GetMnemonic(const Instruction* instruction) +{ + unsigned int index; + + switch (instruction->id) + { + case PPC_ID_ADDx: return OeRcMnemonic(instruction, SubMnemADDx); + case PPC_ID_ADDCx: return OeRcMnemonic(instruction, SubMnemADDCx); + case PPC_ID_ADDEx: return OeRcMnemonic(instruction, SubMnemADDEx); + case PPC_ID_ADDI: return "addi"; + case PPC_ID_ADDICx: return RcMnemonic(instruction, SubMnemADDICx); + case PPC_ID_ADDIS: return "addis"; + case PPC_ID_ADDMEx: return OeRcMnemonic(instruction, SubMnemADDMEx); + case PPC_ID_ADDZEx: return OeRcMnemonic(instruction, SubMnemADDZEx); + case PPC_ID_ANDx: return RcMnemonic(instruction, SubMnemANDx); + case PPC_ID_ANDCx: return RcMnemonic(instruction, SubMnemANDCx); + case PPC_ID_ANDI: return "andi."; + case PPC_ID_ANDIS: return "andis."; + case PPC_ID_ATTN: return "attn"; + case PPC_ID_Bx: return AaLkMnemonic(instruction, SubMnemBx); + case PPC_ID_BCx: return AaLkMnemonic(instruction, SubMnemBCx); + case PPC_ID_BCTRx: return LkMnemonic(instruction, SubMnemBCTRx); + case PPC_ID_BCCTRx: return LkMnemonic(instruction, SubMnemBCCTRx); + case PPC_ID_BCLRx: return LkMnemonic(instruction, SubMnemBCLRx); + case PPC_ID_BDZx: return AaLkHintMnemonic(instruction, SubMnemBDZx); + case PPC_ID_BDZCTRx: return LkHintMnemonic(instruction, SubMnemBDZCTRx); + case PPC_ID_BDNZx: return AaLkHintMnemonic(instruction, SubMnemBDNZx); + case PPC_ID_BDNZCTRx: return LkHintMnemonic(instruction, SubMnemBDNZCTRx); + case PPC_ID_BDNZLRx: return LkHintMnemonic(instruction, SubMnemBDNZLRx); + case PPC_ID_BDNZFx: return AaLkMnemonic(instruction, SubMnemBDNZFx); + case PPC_ID_BDNZFCTRx: return LkMnemonic(instruction, SubMnemBDNZFCTRx); + case PPC_ID_BDNZFLRx: return LkMnemonic(instruction, SubMnemBDNZFLRx); + case PPC_ID_BDNZTx: return AaLkMnemonic(instruction, SubMnemBDNZTx); + case PPC_ID_BDNZTCTRx: return LkMnemonic(instruction, SubMnemBDNZTCTRx); + case PPC_ID_BDNZTLRx: return LkMnemonic(instruction, SubMnemBDNZTLRx); + case PPC_ID_BDZFx: return AaLkMnemonic(instruction, SubMnemBDZFx); + case PPC_ID_BDZFCTRx: return LkMnemonic(instruction, SubMnemBDZFCTRx); + case PPC_ID_BDZFLRx: return LkMnemonic(instruction, SubMnemBDZFLRx); + case PPC_ID_BDZLRx: return LkHintMnemonic(instruction, SubMnemBDZLRx); + case PPC_ID_BDZTx: return AaLkMnemonic(instruction, SubMnemBDZTx); + case PPC_ID_BDZTCTRx: return AaLkMnemonic(instruction, SubMnemBDZTCTRx); + case PPC_ID_BDZTLRx: return AaLkMnemonic(instruction, SubMnemBDZTLRx); + case PPC_ID_BEQx: return AaLkHintMnemonic(instruction, SubMnemBEQx); + case PPC_ID_BEQLRx: return LkHintMnemonic(instruction, SubMnemBEQLRx); + case PPC_ID_BEQCTRx: return LkHintMnemonic(instruction, SubMnemBEQCTRx); + case PPC_ID_BFx: return AaLkMnemonic(instruction, SubMnemBFx); + case PPC_ID_BGEx: return AaLkHintMnemonic(instruction, SubMnemBGEx); + case PPC_ID_BGECTRx: return LkHintMnemonic(instruction, SubMnemBGECTRx); + case PPC_ID_BGELRx: return LkHintMnemonic(instruction, SubMnemBGELRx); + case PPC_ID_BGTx: return AaLkHintMnemonic(instruction, SubMnemBGTx); + case PPC_ID_BGTCTRx: return LkHintMnemonic(instruction, SubMnemBGTCTRx); + case PPC_ID_BGTLRx: return LkHintMnemonic(instruction, SubMnemBGTLRx); + case PPC_ID_BLEx: return AaLkHintMnemonic(instruction, SubMnemBLEx); + case PPC_ID_BLECTRx: return LkHintMnemonic(instruction, SubMnemBLECTRx); + case PPC_ID_BLELRx: return LkHintMnemonic(instruction, SubMnemBLELRx); + case PPC_ID_BLTx: return AaLkHintMnemonic(instruction, SubMnemBLTx); + case PPC_ID_BLTCTRx: return LkHintMnemonic(instruction, SubMnemBLTCTRx); + case PPC_ID_BLTLRx: return LkHintMnemonic(instruction, SubMnemBLTLRx); + case PPC_ID_BLRx: return LkHintMnemonic(instruction, SubMnemBLRx); + case PPC_ID_BNEx: return AaLkHintMnemonic(instruction, SubMnemBNEx); + case PPC_ID_BNECTRx: return LkHintMnemonic(instruction, SubMnemBNECTRx); + case PPC_ID_BNELRx: return LkHintMnemonic(instruction, SubMnemBNELRx); + case PPC_ID_BNSx: return AaLkHintMnemonic(instruction, SubMnemBNSx); + case PPC_ID_BNSCTRx: return LkHintMnemonic(instruction, SubMnemBNSCTRx); + case PPC_ID_BNSLRx: return LkHintMnemonic(instruction, SubMnemBNSLRx); + case PPC_ID_BSOx: return AaLkHintMnemonic(instruction, SubMnemBSOx); + case PPC_ID_BSOCTRx: return LkHintMnemonic(instruction, SubMnemBSOCTRx); + case PPC_ID_BSOLRx: return LkHintMnemonic(instruction, SubMnemBSOLRx); + case PPC_ID_BTx: return AaLkMnemonic(instruction, SubMnemBTx); + case PPC_ID_CLRLDIx: return RcMnemonic(instruction, SubMnemCLRLDIx); + case PPC_ID_CLRLWIx: return RcMnemonic(instruction, SubMnemCLRLWIx); + case PPC_ID_CLRRWIx: return RcMnemonic(instruction, SubMnemCLRRWIx); + case PPC_ID_CMPB: return "cmpb"; + case PPC_ID_CMPD: return "cmpd"; + case PPC_ID_CMPDI: return "cmpdi"; + case PPC_ID_CMPW: return "cmpw"; + case PPC_ID_CMPWI: return "cmpwi"; + case PPC_ID_CMPLD: return "cmpld"; + case PPC_ID_CMPLDI: return "cmpldi"; + case PPC_ID_CMPLW: return "cmplw"; + case PPC_ID_CMPLWI: return "cmplwi"; + case PPC_ID_CNTLZDx: return RcMnemonic(instruction, SubMnemCNTLZDx); + case PPC_ID_CNTLZWx: return RcMnemonic(instruction, SubMnemCNTLZWx); + case PPC_ID_CRAND: return "crand"; + case PPC_ID_CRANDC: return "crandc"; + case PPC_ID_CRCLR: return "crclr"; + case PPC_ID_CREQV: return "creqv"; + case PPC_ID_CRMOVE: return "crmove"; + case PPC_ID_CRNAND: return "crnand"; + case PPC_ID_CRNOR: return "crnor"; + case PPC_ID_CRNOT: return "crnot"; + case PPC_ID_CROR: return "cror"; + case PPC_ID_CRORC: return "crorc"; + case PPC_ID_CRSET: return "crset"; + case PPC_ID_CRXOR: return "crxor"; + case PPC_ID_DCBA: return "dcba"; + case PPC_ID_DCBF: return "dcbf"; + case PPC_ID_DCBI: return "dcbi"; + case PPC_ID_DCBST: return "dcbst"; + case PPC_ID_DCBT: return "dcbt"; + case PPC_ID_DCBTST: return "dcbtst"; + case PPC_ID_DCBZ: return "dcbz"; + case PPC_ID_DCBZL: return "dcbzl"; + case PPC_ID_DCCCI: return "dccci"; + case PPC_ID_DCI: return "dci"; + case PPC_ID_DIVDx: return OeRcMnemonic(instruction, SubMnemDIVDx); + case PPC_ID_DIVDUx: return OeRcMnemonic(instruction, SubMnemDIVDUx); + case PPC_ID_DIVWx: return OeRcMnemonic(instruction, SubMnemDIVWx); + case PPC_ID_DIVWUx: return OeRcMnemonic(instruction, SubMnemDIVWUx); + case PPC_ID_ECIWX: return "eciwx"; + case PPC_ID_ECOWX: return "ecowx"; + case PPC_ID_EIEIO: return "eieio"; + case PPC_ID_EQVx: return RcMnemonic(instruction, SubMnemEQVx); + case PPC_ID_EXTSBx: return RcMnemonic(instruction, SubMnemEXTSBx); + case PPC_ID_EXTSHx: return RcMnemonic(instruction, SubMnemEXTSHx); + case PPC_ID_EXTSWx: return RcMnemonic(instruction, SubMnemEXTSWx); + case PPC_ID_FABSx: return RcMnemonic(instruction, SubMnemFABSx); + case PPC_ID_FADDx: return RcMnemonic(instruction, SubMnemFADDx); + case PPC_ID_FADDSx: return RcMnemonic(instruction, SubMnemFADDSx); + case PPC_ID_FCFIDx: return RcMnemonic(instruction, SubMnemFCFIDx); + case PPC_ID_FCFIDSx: return RcMnemonic(instruction, SubMnemFCFIDSx); + case PPC_ID_FCFIDUx: return RcMnemonic(instruction, SubMnemFCFIDUx); + case PPC_ID_FCFIDUSx: return RcMnemonic(instruction, SubMnemFCFIDUSx); + case PPC_ID_FCMPO: return "fcmpo"; + case PPC_ID_FCMPU: return "fcmpu"; + case PPC_ID_FCPSGNx: return RcMnemonic(instruction, SubMnemFCPSGNx); + case PPC_ID_FCTIDx: return RcMnemonic(instruction, SubMnemFCTIDx); + case PPC_ID_FCTIDUZx: return RcMnemonic(instruction, SubMnemFCTIDUZx); + case PPC_ID_FCTIDZx: return RcMnemonic(instruction, SubMnemFCTIDZx); + case PPC_ID_FCTIWx: return RcMnemonic(instruction, SubMnemFCTIWx); + case PPC_ID_FCTIWUZx: return RcMnemonic(instruction, SubMnemFCTIWUZx); + case PPC_ID_FCTIWZx: return RcMnemonic(instruction, SubMnemFCTIWZx); + case PPC_ID_FDIVx: return RcMnemonic(instruction, SubMnemFDIVx); + case PPC_ID_FDIVSx: return RcMnemonic(instruction, SubMnemFDIVSx); + case PPC_ID_FMADDx: return RcMnemonic(instruction, SubMnemFMADDx); + case PPC_ID_FMADDSx: return RcMnemonic(instruction, SubMnemFMADDSx); + case PPC_ID_FMRx: return RcMnemonic(instruction, SubMnemFMRx); + case PPC_ID_FMSUBx: return RcMnemonic(instruction, SubMnemFMSUBx); + case PPC_ID_FMSUBSx: return RcMnemonic(instruction, SubMnemFMSUBSx); + case PPC_ID_FMULx: return RcMnemonic(instruction, SubMnemFMULx); + case PPC_ID_FMULSx: return RcMnemonic(instruction, SubMnemFMULSx); + case PPC_ID_FNABSx: return RcMnemonic(instruction, SubMnemFNABSx); + case PPC_ID_FNEGx: return RcMnemonic(instruction, SubMnemFNEGx); + case PPC_ID_FNMADDx: return RcMnemonic(instruction, SubMnemFNMADDx); + case PPC_ID_FNMADDSx: return RcMnemonic(instruction, SubMnemFNMADDSx); + case PPC_ID_FNMSUBx: return RcMnemonic(instruction, SubMnemFNMSUBx); + case PPC_ID_FNMSUBSx: return RcMnemonic(instruction, SubMnemFNMSUBSx); + case PPC_ID_FREx: return RcMnemonic(instruction, SubMnemFREx); + case PPC_ID_FRESx: return RcMnemonic(instruction, SubMnemFRESx); + case PPC_ID_FRIMx: return RcMnemonic(instruction, SubMnemFRIMx); + case PPC_ID_FRINx: return RcMnemonic(instruction, SubMnemFRINx); + case PPC_ID_FRIPx: return RcMnemonic(instruction, SubMnemFRIPx); + case PPC_ID_FRIZx: return RcMnemonic(instruction, SubMnemFRIZx); + case PPC_ID_FRSPx: return RcMnemonic(instruction, SubMnemFRSPx); + case PPC_ID_FRSQRTEx: return RcMnemonic(instruction, SubMnemFRSQRTEx); + case PPC_ID_FRSQRTESx: return RcMnemonic(instruction, SubMnemFRSQRTESx); + case PPC_ID_FSELx: return RcMnemonic(instruction, SubMnemFSELx); + case PPC_ID_FSQRTx: return RcMnemonic(instruction, SubMnemFSQRTx); + case PPC_ID_FSQRTSx: return RcMnemonic(instruction, SubMnemFSQRTSx); + case PPC_ID_FSUBx: return RcMnemonic(instruction, SubMnemFSUBx); + case PPC_ID_FSUBSx: return RcMnemonic(instruction, SubMnemFSUBSx); + case PPC_ID_ICBI: return "icbi"; + case PPC_ID_ICBT: return "icbt"; + case PPC_ID_ICCCI: return "iccci"; + case PPC_ID_ICI: return "ici"; + case PPC_ID_ISEL: return "isel"; + case PPC_ID_ISYNC: return "isync"; + case PPC_ID_LBZ: return "lbz"; + case PPC_ID_LBZCIX: return "lbzcix"; + case PPC_ID_LBZU: return "lbzu"; + case PPC_ID_LBZUX: return "lbzux"; + case PPC_ID_LBZX: return "lbzx"; + case PPC_ID_LDARX: return "ldarx"; + case PPC_ID_LDBRX: return "ldbrx"; + case PPC_ID_LDCIX: return "ldcix"; + case PPC_ID_LD: return "ld"; + case PPC_ID_LDU: return "ldu"; + case PPC_ID_LDUX: return "ldux"; + case PPC_ID_LDX: return "ldx"; + case PPC_ID_LFD: return "lfd"; + case PPC_ID_LFDU: return "lfdu"; + case PPC_ID_LFDUX: return "lfdux"; + case PPC_ID_LFDX: return "lfdx"; + case PPC_ID_LFIWAX: return "lfiwax"; + case PPC_ID_LFIWZX: return "lfiwzx"; + case PPC_ID_LFS: return "lfs"; + case PPC_ID_LFSU: return "lfsu"; + case PPC_ID_LFSUX: return "lfsux"; + case PPC_ID_LFSX: return "lfsx"; + case PPC_ID_LHA: return "lha"; + case PPC_ID_LHAU: return "lhau"; + case PPC_ID_LHAUX: return "lhaux"; + case PPC_ID_LHAX: return "lhax"; + case PPC_ID_LHBRX: return "lhbrx"; + case PPC_ID_LHZ: return "lhz"; + case PPC_ID_LHZCIX: return "lhzcix"; + case PPC_ID_LHZU: return "lhzu"; + case PPC_ID_LHZUX: return "lhzux"; + case PPC_ID_LHZX: return "lhzx"; + case PPC_ID_LI: return "li"; + case PPC_ID_LIS: return "lis"; + case PPC_ID_LMW: return "lmw"; + case PPC_ID_LSWI: return "lswi"; + case PPC_ID_LSWX: return "lswx"; + case PPC_ID_LWA: return "lwa"; + case PPC_ID_LWAX: return "lwax"; + case PPC_ID_LWARX: return "lwarx"; + case PPC_ID_LWAUX: return "lwaux"; + case PPC_ID_LWBRX: return "lwbrx"; + case PPC_ID_LWSYNC: return "lwsync"; + case PPC_ID_LWZ: return "lwz"; + case PPC_ID_LWZCIX: return "lwzcix"; + case PPC_ID_LWZU: return "lwzu"; + case PPC_ID_LWZUX: return "lwzux"; + case PPC_ID_LWZX: return "lwzx"; + case PPC_ID_MBAR: return "mbar"; + case PPC_ID_MCRF: return "mcrf"; + case PPC_ID_MCRFS: return "mcrfs"; + case PPC_ID_MCRXR: return "mcrxr"; + case PPC_ID_MFBR0: return "mfbr0"; + case PPC_ID_MFBR1: return "mfbr1"; + case PPC_ID_MFBR2: return "mfbr2"; + case PPC_ID_MFBR3: return "mfbr3"; + case PPC_ID_MFBR4: return "mfbr4"; + case PPC_ID_MFBR5: return "mfbr5"; + case PPC_ID_MFBR6: return "mfbr6"; + case PPC_ID_MFBR7: return "mfbr7"; + case PPC_ID_MFCR: return "mfcr"; + case PPC_ID_MFCTR: return "mfctr"; + case PPC_ID_MFDCR: return "mfdcr"; + case PPC_ID_MFDCRUX: return "mfdcrux"; + case PPC_ID_MFDCRX: return "mfdcrx"; + case PPC_ID_MFFSx: return RcMnemonic(instruction, SubMnemMFFSx); + case PPC_ID_MFLR: return "mflr"; + case PPC_ID_MFMSR: return "mfmsr"; + case PPC_ID_MFOCRF: return "mfocrf"; + case PPC_ID_MFSPR: return "mfspr"; + case PPC_ID_MFSR: return "mfsr"; + case PPC_ID_MFSRIN: return "mfsrin"; + case PPC_ID_MFTB: return "mftb"; + case PPC_ID_MFTBU: return "mftbu"; + case PPC_ID_MFXER: return "mfxer"; + case PPC_ID_MRx: return RcMnemonic(instruction, SubMnemMRx); + case PPC_ID_MTAMR: return "mtamr"; + case PPC_ID_MTBR0: return "mtbr0"; + case PPC_ID_MTBR1: return "mtbr1"; + case PPC_ID_MTBR2: return "mtbr2"; + case PPC_ID_MTBR3: return "mtbr3"; + case PPC_ID_MTBR4: return "mtbr4"; + case PPC_ID_MTBR5: return "mtbr5"; + case PPC_ID_MTBR6: return "mtbr6"; + case PPC_ID_MTBR7: return "mtbr7"; + case PPC_ID_MTCRF: return "mtcrf"; + case PPC_ID_MTCTR: return "mtctr"; + case PPC_ID_MTDCR: return "mtdcr"; + case PPC_ID_MTDCRUX: return "mtdcrux"; + case PPC_ID_MTDCRX: return "mtdcrx"; + case PPC_ID_MTFSB0x: return RcMnemonic(instruction, SubMnemMTFSB0x); + case PPC_ID_MTFSB1x: return RcMnemonic(instruction, SubMnemMTFSB1x); + case PPC_ID_MTFSFx: return RcMnemonic(instruction, SubMnemMTFSFx); + case PPC_ID_MTFSFIx: return RcMnemonic(instruction, SubMnemMTFSFIx); + case PPC_ID_MTLR: return "mtlr"; + case PPC_ID_MTMSR: return "mtmsr"; + case PPC_ID_MTMSRD: return "mtmsrd"; + case PPC_ID_MTOCRF: return "mtocrf"; + case PPC_ID_MTSPR: return "mtspr"; + case PPC_ID_MTSR: return "mtsr"; + case PPC_ID_MTSRIN: return "mtsrin"; + case PPC_ID_MTXER: return "mtxer"; + case PPC_ID_MULHDx: return RcMnemonic(instruction, SubMnemMULHDx); + case PPC_ID_MULHDUx: return RcMnemonic(instruction, SubMnemMULHDUx); + case PPC_ID_MULHWx: return RcMnemonic(instruction, SubMnemMULHWx); + case PPC_ID_MULHWUx: return RcMnemonic(instruction, SubMnemMULHWUx); + case PPC_ID_MULLI: return "mulli"; + case PPC_ID_MULLDx: return OeRcMnemonic(instruction, SubMnemMULLDx); + case PPC_ID_MULLWx: return OeRcMnemonic(instruction, SubMnemMULLWx); + case PPC_ID_NANDx: return RcMnemonic(instruction, SubMnemNANDx); + case PPC_ID_NEGx: return OeRcMnemonic(instruction, SubMnemNEGx); + case PPC_ID_NOP: return "nop"; + case PPC_ID_NORx: return RcMnemonic(instruction, SubMnemNORx); + case PPC_ID_ORx: return RcMnemonic(instruction, SubMnemORx); + case PPC_ID_ORCx: return RcMnemonic(instruction, SubMnemORCx); + case PPC_ID_ORI: return "ori"; + case PPC_ID_ORIS: return "oris"; + case PPC_ID_POPCNTB: return "popcntb"; + case PPC_ID_POPCNTD: return "popcntd"; + case PPC_ID_POPCNTW: return "popcntw"; + case PPC_ID_PTESYNC: return "ptesync"; + case PPC_ID_RFCI: return "rfci"; + case PPC_ID_RFDI: return "rfdi"; + case PPC_ID_RFI: return "rfi"; + case PPC_ID_RFID: return "rfid"; + case PPC_ID_RFMCI: return "rfmci"; + case PPC_ID_RLDICLx: return RcMnemonic(instruction, SubMnemRLDICLx); + case PPC_ID_RLDICRx: return RcMnemonic(instruction, SubMnemRLDICRx); + case PPC_ID_RLDICx: return RcMnemonic(instruction, SubMnemRLDICx); + case PPC_ID_RLDIMIx: return RcMnemonic(instruction, SubMnemRLDIMIx); + case PPC_ID_RLDCLx: return RcMnemonic(instruction, SubMnemRLDCLx); + case PPC_ID_RLDCRx: return RcMnemonic(instruction, SubMnemRLDCRx); + case PPC_ID_RLWIMIx: return RcMnemonic(instruction, SubMnemRLWIMIx); + case PPC_ID_RLWINMx: return RcMnemonic(instruction, SubMnemRLWINMx); + case PPC_ID_RLWNMx: return RcMnemonic(instruction, SubMnemRLWNMx); + case PPC_ID_ROTLDx: return RcMnemonic(instruction, SubMnemROTLDx); + case PPC_ID_ROTLDIx: return RcMnemonic(instruction, SubMnemROTLDIx); + case PPC_ID_ROTLWx: return RcMnemonic(instruction, SubMnemROTLWx); + case PPC_ID_ROTLWIx: return RcMnemonic(instruction, SubMnemROTLWIx); + case PPC_ID_SC: return "sc"; + case PPC_ID_SLBIA: return "slbia"; + case PPC_ID_SLBIE: return "slbie"; + case PPC_ID_SLBMFEE: return "slbmfee"; + case PPC_ID_SLBMTE: return "slbmte"; + case PPC_ID_SLDx: return RcMnemonic(instruction, SubMnemSLDx); + case PPC_ID_SLDIx: return RcMnemonic(instruction, SubMnemSLDIx); + case PPC_ID_SLWx: return RcMnemonic(instruction, SubMnemSLWx); + case PPC_ID_SLWIx: return RcMnemonic(instruction, SubMnemSLWIx); + case PPC_ID_SRADx: return RcMnemonic(instruction, SubMnemSRADx); + case PPC_ID_SRADIx: return RcMnemonic(instruction, SubMnemSRADIx); + case PPC_ID_SRAWx: return RcMnemonic(instruction, SubMnemSRAWx); + case PPC_ID_SRAWIx: return RcMnemonic(instruction, SubMnemSRAWIx); + case PPC_ID_SRDx: return RcMnemonic(instruction, SubMnemSRDx); + case PPC_ID_SRDIx: return RcMnemonic(instruction, SubMnemSRDIx); + case PPC_ID_SRWx: return RcMnemonic(instruction, SubMnemSRWx); + case PPC_ID_SRWIx: return RcMnemonic(instruction, SubMnemSRWIx); + case PPC_ID_STB: return "stb"; + case PPC_ID_STBU: return "stbu"; + case PPC_ID_STBUX: return "stbux"; + case PPC_ID_STBX: return "stbx"; + case PPC_ID_STBCIX: return "stbcix"; + case PPC_ID_STD: return "std"; + case PPC_ID_STDBRX: return "stdbrx"; + case PPC_ID_STDCIX: return "stdcix"; + case PPC_ID_STDCX: return "stdcx."; + case PPC_ID_STDU: return "stdu"; + case PPC_ID_STDUX: return "stdux"; + case PPC_ID_STDX: return "stdx"; + case PPC_ID_STFD: return "stfd"; + case PPC_ID_STFDU: return "stfdu"; + case PPC_ID_STFDUX: return "stfdux"; + case PPC_ID_STFDX: return "stfdx"; + case PPC_ID_STFIWX: return "stfiwx"; + case PPC_ID_STFS: return "stfs"; + case PPC_ID_STFSU: return "stfsu"; + case PPC_ID_STFSUX: return "stfsux"; + case PPC_ID_STFSX: return "stfsx"; + case PPC_ID_STH: return "sth"; + case PPC_ID_STHBRX: return "sthbrx"; + case PPC_ID_STHCIX: return "sthcix"; + case PPC_ID_STHU: return "sthu"; + case PPC_ID_STHUX: return "sthux"; + case PPC_ID_STHX: return "sthx"; + case PPC_ID_STMW: return "stmw"; + case PPC_ID_STSWI: return "stswi"; + case PPC_ID_STSWX: return "stswx"; + case PPC_ID_STW: return "stw"; + case PPC_ID_STWBRX: return "stwbrx"; + case PPC_ID_STWCIX: return "stwcix"; + case PPC_ID_STWCX: return "stwcx."; + case PPC_ID_STWU: return "stwu"; + case PPC_ID_STWUX: return "stwux"; + case PPC_ID_STWX: return "stwx"; + case PPC_ID_SUBFx: return OeRcMnemonic(instruction, SubMnemSUBFx); + case PPC_ID_SUBFCx: return OeRcMnemonic(instruction, SubMnemSUBFCx); + case PPC_ID_SUBFEx: return OeRcMnemonic(instruction, SubMnemSUBFEx); + case PPC_ID_SUBFIC: return "subfic"; + case PPC_ID_SUBFMEx: return OeRcMnemonic(instruction, SubMnemSUBFMEx); + case PPC_ID_SUBFZEx: return OeRcMnemonic(instruction, SubMnemSUBFZEx); + case PPC_ID_SYNC: return "sync"; + case PPC_ID_TD: return "td"; + case PPC_ID_TDEQ: return "tdeq"; + case PPC_ID_TDEQI: return "tdeqi"; + case PPC_ID_TDGT: return "tdgt"; + case PPC_ID_TDGTI: return "tdgti"; + case PPC_ID_TDI: return "tdi"; + case PPC_ID_TDLGT: return "tdlgt"; + case PPC_ID_TDLGTI: return "tdlgti"; + case PPC_ID_TDLLT: return "tdllt"; + case PPC_ID_TDLLTI: return "tdllti"; + case PPC_ID_TDLT: return "tdlt"; + case PPC_ID_TDLTI: return "tdlti"; + case PPC_ID_TDNE: return "tdne"; + case PPC_ID_TDNEI: return "tdnei"; + case PPC_ID_TDU: return "tdu"; + case PPC_ID_TDUI: return "tdui"; + case PPC_ID_TLBIA: return "tlbia"; + case PPC_ID_TLBIE: return "tlbie"; + case PPC_ID_TLBIEL: return "tlbiel"; + case PPC_ID_TLBIVAX: return "tlbivax"; + case PPC_ID_TLBLI: return "tlbli"; + case PPC_ID_TLBSX: return "tlbsx"; + case PPC_ID_TLBSYNC: return "tlbsync"; + case PPC_ID_TLBRE: return "tlbre"; + case PPC_ID_TLBRELO: return "tlbrehi"; + case PPC_ID_TLBREHI: return "tlbrelo"; + case PPC_ID_TLBWE: return "tlbwe"; + case PPC_ID_TLBWEHI: return "tlbwehi"; + case PPC_ID_TLBWELO: return "tlbwelo"; + case PPC_ID_TW: return "tw"; + case PPC_ID_TWEQ: return "tweq"; + case PPC_ID_TWEQI: return "tweqi"; + case PPC_ID_TWGT: return "twgt"; + case PPC_ID_TWGTI: return "twgti"; + case PPC_ID_TWGEI: return "twgei"; + case PPC_ID_TWI: return "twi"; + case PPC_ID_TWLEI: return "twlei"; + case PPC_ID_TWLLEI: return "twllei"; + case PPC_ID_TWLGT: return "twlgt"; + case PPC_ID_TWLGTI: return "twlgti"; + case PPC_ID_TWLLT: return "twllt"; + case PPC_ID_TWLLTI: return "twllti"; + case PPC_ID_TWLT: return "twlt"; + case PPC_ID_TWLTI: return "twlti"; + case PPC_ID_TWNE: return "twne"; + case PPC_ID_TWNEI: return "twnei"; + case PPC_ID_TWU: return "twu"; + case PPC_ID_TWUI: return "twui"; + case PPC_ID_WAIT: return "wait"; + case PPC_ID_WAITIMPL: return "waitimpl"; + case PPC_ID_WAITRSV: return "waitrsv"; + case PPC_ID_WRTEE: return "wrtee"; + case PPC_ID_WRTEEI: return "wrteei"; + case PPC_ID_XNOP: return "xnop"; + case PPC_ID_XORx: return RcMnemonic(instruction, SubMnemXORx); + case PPC_ID_XORI: return "xori"; + case PPC_ID_XORIS: return "xoris"; + + case PPC_ID_AV_DSS: return "dss"; + case PPC_ID_AV_DSSALL: return "dssall"; + case PPC_ID_AV_DST: return "dst"; + case PPC_ID_AV_DSTST: return "dstst"; + case PPC_ID_AV_DSTSTT: return "dststt"; + case PPC_ID_AV_DSTT: return "dstt"; + case PPC_ID_AV_LVEBX: return "lvebx"; + case PPC_ID_AV_LVEHX: return "lvehx"; + case PPC_ID_AV_LVEWX: return "lvewx"; + case PPC_ID_AV_LVSL: return "lvsl"; + case PPC_ID_AV_LVSR: return "lvsr"; + case PPC_ID_AV_LVX: return "lvx"; + case PPC_ID_AV_LVXL: return "lvxl"; + case PPC_ID_AV_MFVSCR: return "mfvscr"; + case PPC_ID_AV_MTVSCR: return "mtvscr"; + case PPC_ID_AV_STVEBX: return "stvebx"; + case PPC_ID_AV_STVEHX: return "stvehx"; + case PPC_ID_AV_STVEWX: return "stvewx"; + case PPC_ID_AV_STVX: return "stvx"; + case PPC_ID_AV_STVXL: return "stvxl"; + case PPC_ID_AV_VADDCUW: return "vaddcuw"; + case PPC_ID_AV_VADDFP: return "vaddfp"; + case PPC_ID_AV_VADDSBS: return "vaddsbs"; + case PPC_ID_AV_VADDSHS: return "vaddshs"; + case PPC_ID_AV_VADDSWS: return "vaddsws"; + case PPC_ID_AV_VADDUBM: return "vaddubm"; + case PPC_ID_AV_VADDUBS: return "vaddubs"; + case PPC_ID_AV_VADDUDM: return "vaddudm"; + case PPC_ID_AV_VADDUHM: return "vadduhm"; + case PPC_ID_AV_VADDUHS: return "vadduhs"; + case PPC_ID_AV_VADDUWM: return "vadduwm"; + case PPC_ID_AV_VADDUWS: return "vadduws"; + case PPC_ID_AV_VAND: return "vand"; + case PPC_ID_AV_VANDC: return "vandc"; + case PPC_ID_AV_VAVGSB: return "vavgsb"; + case PPC_ID_AV_VAVGSH: return "vavgsh"; + case PPC_ID_AV_VAVGSW: return "vavgsw"; + case PPC_ID_AV_VAVGUB: return "vavgub"; + case PPC_ID_AV_VAVGUH: return "vavguh"; + case PPC_ID_AV_VAVGUW: return "vavguw"; + case PPC_ID_AV_VCFSX: return "vcfsx"; + case PPC_ID_AV_VCFUX: return "vcfux"; + case PPC_ID_AV_VCLZB: return "vclzb"; + case PPC_ID_AV_VCLZD: return "vclzd"; + case PPC_ID_AV_VCLZH: return "vclzh"; + case PPC_ID_AV_VCLZW: return "vclzw"; + case PPC_ID_AV_VCMPBFPx: return RcMnemonic(instruction, SubMnemVCMPBFPx); + case PPC_ID_AV_VCMPEQFPx: return RcMnemonic(instruction, SubMnemVCMPEQFPx); + case PPC_ID_AV_VCMPEQUBx: return RcMnemonic(instruction, SubMnemVCMPEQUBx); + case PPC_ID_AV_VCMPEQUDx: return RcMnemonic(instruction, SubMnemVCMPEQUDx); + case PPC_ID_AV_VCMPEQUHx: return RcMnemonic(instruction, SubMnemVCMPEQUHx); + case PPC_ID_AV_VCMPEQUWx: return RcMnemonic(instruction, SubMnemVCMPEQUWx); + case PPC_ID_AV_VCMPGEFPx: return RcMnemonic(instruction, SubMnemVCMPGEFPx); + case PPC_ID_AV_VCMPGTFPx: return RcMnemonic(instruction, SubMnemVCMPGTFPx); + case PPC_ID_AV_VCMPGTSBx: return RcMnemonic(instruction, SubMnemVCMPGTSBx); + case PPC_ID_AV_VCMPGTSDx: return RcMnemonic(instruction, SubMnemVCMPGTSDx); + case PPC_ID_AV_VCMPGTSHx: return RcMnemonic(instruction, SubMnemVCMPGTSHx); + case PPC_ID_AV_VCMPGTSWx: return RcMnemonic(instruction, SubMnemVCMPGTSWx); + case PPC_ID_AV_VCMPGTUBx: return RcMnemonic(instruction, SubMnemVCMPGTUBx); + case PPC_ID_AV_VCMPGTUDx: return RcMnemonic(instruction, SubMnemVCMPGTUDx); + case PPC_ID_AV_VCMPGTUHx: return RcMnemonic(instruction, SubMnemVCMPGTUHx); + case PPC_ID_AV_VCMPGTUWx: return RcMnemonic(instruction, SubMnemVCMPGTUWx); + case PPC_ID_AV_VCTSXS: return "vctsxs"; + case PPC_ID_AV_VCTUXS: return "vctuxs"; + case PPC_ID_AV_VEQV: return "veqv"; + case PPC_ID_AV_VEXPTEFP: return "vexptefp"; + case PPC_ID_AV_VLOGEFP: return "vlogefp"; + case PPC_ID_AV_VMADDFP: return "vmaddfp"; + case PPC_ID_AV_VMAXFP: return "vmaxfp"; + case PPC_ID_AV_VMAXSB: return "vmaxsb"; + case PPC_ID_AV_VMAXSD: return "vmaxsd"; + case PPC_ID_AV_VMAXSH: return "vmaxsh"; + case PPC_ID_AV_VMAXSW: return "vmaxsw"; + case PPC_ID_AV_VMAXUB: return "vmaxub"; + case PPC_ID_AV_VMAXUD: return "vmaxud"; + case PPC_ID_AV_VMAXUH: return "vmaxuh"; + case PPC_ID_AV_VMAXUW: return "vmaxuw"; + case PPC_ID_AV_VMHADDSHS: return "vmhaddshs"; + case PPC_ID_AV_VMHRADDSHS: return "vmhraddshs"; + case PPC_ID_AV_VMINFP: return "vminfp"; + case PPC_ID_AV_VMINSB: return "vminsb"; + case PPC_ID_AV_VMINSD: return "vminsd"; + case PPC_ID_AV_VMINSH: return "vminsh"; + case PPC_ID_AV_VMINSW: return "vminsw"; + case PPC_ID_AV_VMINUB: return "vminub"; + case PPC_ID_AV_VMINUD: return "vminud"; + case PPC_ID_AV_VMINUH: return "vminuh"; + case PPC_ID_AV_VMINUW: return "vminuw"; + case PPC_ID_AV_VMLADDUHM: return "vmladduhm"; + case PPC_ID_AV_VMRGHB: return "vmrghb"; + case PPC_ID_AV_VMRGHH: return "vmrghh"; + case PPC_ID_AV_VMRGHW: return "vmrghw"; + case PPC_ID_AV_VMRGLB: return "vmrglb"; + case PPC_ID_AV_VMRGLH: return "vmrglh"; + case PPC_ID_AV_VMRGLW: return "vmrglw"; + case PPC_ID_AV_VMSUMMBM: return "vmsummbm"; + case PPC_ID_AV_VMSUMSHM: return "vmsumshm"; + case PPC_ID_AV_VMSUMSHS: return "vmsumshs"; + case PPC_ID_AV_VMSUMUBM: return "vmsumubm"; + case PPC_ID_AV_VMSUMUHM: return "vmsumuhm"; + case PPC_ID_AV_VMSUMUHS: return "vmsumuhs"; + case PPC_ID_AV_VMULESB: return "vmulesb"; + case PPC_ID_AV_VMULESH: return "vmulesh"; + case PPC_ID_AV_VMULESW: return "vmulesw"; + case PPC_ID_AV_VMULEUB: return "vmuleub"; + case PPC_ID_AV_VMULEUH: return "vmuleuh"; + case PPC_ID_AV_VMULEUW: return "vmuleuw"; + case PPC_ID_AV_VMULOSB: return "vmulosb"; + case PPC_ID_AV_VMULOSH: return "vmulosh"; + case PPC_ID_AV_VMULOSW: return "vmulosw"; + case PPC_ID_AV_VMULOUB: return "vmuloub"; + case PPC_ID_AV_VMULOUH: return "vmulouh"; + case PPC_ID_AV_VMULOUW: return "vmulouw"; + case PPC_ID_AV_VMULUWM: return "vmuluwm"; + case PPC_ID_AV_VNAND: return "vnand"; + case PPC_ID_AV_VNMSUBFP: return "vnmsubfp"; + case PPC_ID_AV_VNOR: return "vnor"; + case PPC_ID_AV_VOR: return "vor"; + case PPC_ID_AV_VORC: return "vorc"; + case PPC_ID_AV_VPERM: return "vperm"; + case PPC_ID_AV_VPKPX: return "vpkpx"; + case PPC_ID_AV_VPKSHSS: return "vpkshss"; + case PPC_ID_AV_VPKSHUS: return "vpkshus"; + case PPC_ID_AV_VPKSWSS: return "vpkswss"; + case PPC_ID_AV_VPKSWUS: return "vpkswus"; + case PPC_ID_AV_VPKUHUM: return "vpkuhum"; + case PPC_ID_AV_VPKUHUS: return "vpkuhus"; + case PPC_ID_AV_VPKUWUM: return "vpkuwum"; + case PPC_ID_AV_VPKUWUS: return "vpkuwus"; + case PPC_ID_AV_VPOPCNTB: return "vpopcntb"; + case PPC_ID_AV_VPOPCNTD: return "vpopcntd"; + case PPC_ID_AV_VPOPCNTH: return "vpopcnth"; + case PPC_ID_AV_VPOPCNTW: return "vpopcntw"; + case PPC_ID_AV_VREFP: return "vrefp"; + case PPC_ID_AV_VRFIM: return "vrfim"; + case PPC_ID_AV_VRFIN: return "vrfin"; + case PPC_ID_AV_VRFIP: return "vrfip"; + case PPC_ID_AV_VRFIZ: return "vrfiz"; + case PPC_ID_AV_VRLB: return "vrlb"; + case PPC_ID_AV_VRLD: return "vrld"; + case PPC_ID_AV_VRLH: return "vrlh"; + case PPC_ID_AV_VRLW: return "vrlw"; + case PPC_ID_AV_VRSQRTEFP: return "vrsqrtefp"; + case PPC_ID_AV_VSEL: return "vsel"; + case PPC_ID_AV_VSL: return "vsl"; + case PPC_ID_AV_VSLB: return "vslb"; + case PPC_ID_AV_VSLD: return "vsld"; + case PPC_ID_AV_VSLDOI: return "vsldoi"; + case PPC_ID_AV_VSLH: return "vslh"; + case PPC_ID_AV_VSLO: return "vslo"; + case PPC_ID_AV_VSLW: return "vslw"; + case PPC_ID_AV_VSPLTB: return "vspltb"; + case PPC_ID_AV_VSPLTH: return "vsplth"; + case PPC_ID_AV_VSPLTISB: return "vspltisb"; + case PPC_ID_AV_VSPLTISH: return "vspltish"; + case PPC_ID_AV_VSPLTISW: return "vspltisw"; + case PPC_ID_AV_VSPLTW: return "vspltw"; + case PPC_ID_AV_VSR: return "vsr"; + case PPC_ID_AV_VSRAB: return "vsrab"; + case PPC_ID_AV_VSRAD: return "vsrad"; + case PPC_ID_AV_VSRAH: return "vsrah"; + case PPC_ID_AV_VSRAW: return "vsraw"; + case PPC_ID_AV_VSRB: return "vsrb"; + case PPC_ID_AV_VSRD: return "vsrd"; + case PPC_ID_AV_VSRH: return "vsrh"; + case PPC_ID_AV_VSRO: return "vsro"; + case PPC_ID_AV_VSRW: return "vsrw"; + case PPC_ID_AV_VSUBCUW: return "vsubcuw"; + case PPC_ID_AV_VSUBFP: return "vsubfp"; + case PPC_ID_AV_VSUBSBS: return "vsubsbs"; + case PPC_ID_AV_VSUBSHS: return "vsubshs"; + case PPC_ID_AV_VSUBSWS: return "vsubsws"; + case PPC_ID_AV_VSUBUBM: return "vsububm"; + case PPC_ID_AV_VSUBUBS: return "vsububs"; + case PPC_ID_AV_VSUBUDM: return "vsubudm"; + case PPC_ID_AV_VSUBUHM: return "vsubuhm"; + case PPC_ID_AV_VSUBUHS: return "vsubuhs"; + case PPC_ID_AV_VSUBUWM: return "vsubuwm"; + case PPC_ID_AV_VSUBUWS: return "vsubuws"; + case PPC_ID_AV_VSUMSWS: return "vsumsws"; + case PPC_ID_AV_VSUM2SWS: return "vsum2sws"; + case PPC_ID_AV_VSUM4SBS: return "vsum4sbs"; + case PPC_ID_AV_VSUM4SHS: return "vsum4shs"; + case PPC_ID_AV_VSUM4UBS: return "vsum4ubs"; + case PPC_ID_AV_VUPKHPX: return "vupkhpx"; + case PPC_ID_AV_VUPKHSB: return "vupkhsb"; + case PPC_ID_AV_VUPKHSH: return "vupkhsh"; + case PPC_ID_AV_VUPKLPX: return "vupklpx"; + case PPC_ID_AV_VUPKLSB: return "vupklsb"; + case PPC_ID_AV_VUPKLSH: return "vupklsh"; + case PPC_ID_AV_VXOR: return "vxor"; + + case PPC_ID_VSX_LXSDX: return "lxsdx"; + case PPC_ID_VSX_LXSIWAX: return "lxsiwax"; + case PPC_ID_VSX_LXSIWZX: return "lxsiwzx"; + case PPC_ID_VSX_LXSSPX: return "lxsspx"; + case PPC_ID_VSX_LXVD2X: return "lxvd2x"; + case PPC_ID_VSX_LXVDSX: return "lxvdsx"; + case PPC_ID_VSX_LXVW4X: return "lxvw4x"; + case PPC_ID_VSX_STXSDX: return "stxsdx"; + case PPC_ID_VSX_STXSIWX: return "stxsiwx"; + case PPC_ID_VSX_STXSSPX: return "stxsspx"; + case PPC_ID_VSX_STXVD2X: return "stxvd2x"; + case PPC_ID_VSX_STXVW4X: return "stxvw4x"; + case PPC_ID_VSX_XSABSDP: return "xsabsdp"; + case PPC_ID_VSX_XSADDDP: return "xsadddp"; + case PPC_ID_VSX_XSADDSP: return "xsaddsp"; + case PPC_ID_VSX_XSCMPODP: return "xscmpodp"; + case PPC_ID_VSX_XSCMPUDP: return "xscmpudp"; + case PPC_ID_VSX_XSCPSGNDP: return "xscpsgndp"; + case PPC_ID_VSX_XSCVDPSP: return "xscvdpsp"; + case PPC_ID_VSX_XSCVDPSXDS: return "xscvdpsxds"; + case PPC_ID_VSX_XSCVDPSXWS: return "xscvdpsxws"; + case PPC_ID_VSX_XSCVDPUXDS: return "xscvdpuxds"; + case PPC_ID_VSX_XSCVDPUXWS: return "xscvdpuxws"; + case PPC_ID_VSX_XSCVSPDP: return "xscvspdp"; + case PPC_ID_VSX_XSCVSPDPN: return "xscvspdpn"; + case PPC_ID_VSX_XSCVSXDDP: return "xscvsxddp"; + case PPC_ID_VSX_XSCVSXDSP: return "xscvsxdsp"; + case PPC_ID_VSX_XSCVUXDDP: return "xscvuxddp"; + case PPC_ID_VSX_XSCVUXDSP: return "xscvuxdsp"; + case PPC_ID_VSX_XSDIVDP: return "xsdivdp"; + case PPC_ID_VSX_XSDIVSP: return "xsdivsp"; + case PPC_ID_VSX_XSMADDADP: return "xsmaddadp"; + case PPC_ID_VSX_XSMADDASP: return "xsmaddasp"; + case PPC_ID_VSX_XSMADDMDP: return "xsmaddmdp"; + case PPC_ID_VSX_XSMADDMSP: return "xsmaddmsp"; + case PPC_ID_VSX_XSMAXDP: return "xsmaxdp"; + case PPC_ID_VSX_XSMINDP: return "xsmindp"; + case PPC_ID_VSX_XSMSUBADP: return "xsmsubadp"; + case PPC_ID_VSX_XSMSUBASP: return "xsmsubasp"; + case PPC_ID_VSX_XSMSUBMDP: return "xsmsubmdp"; + case PPC_ID_VSX_XSMSUBMSP: return "xsmsubmsp"; + case PPC_ID_VSX_XSMULDP: return "xsmuldp"; + case PPC_ID_VSX_XSMULSP: return "xsmulsp"; + case PPC_ID_VSX_XSNABSDP: return "xsnabsdp"; + case PPC_ID_VSX_XSNEGDP: return "xsnegdp"; + case PPC_ID_VSX_XSNMADDADP: return "xsnmaddadp"; + case PPC_ID_VSX_XSNMADDASP: return "xsnmaddasp"; + case PPC_ID_VSX_XSNMADDMDP: return "xsnmaddmdp"; + case PPC_ID_VSX_XSNMADDMSP: return "xsnmaddmsp"; + case PPC_ID_VSX_XSNMSUBADP: return "xsnmsubadp"; + case PPC_ID_VSX_XSNMSUBASP: return "xsnmsubasp"; + case PPC_ID_VSX_XSNMSUBMDP: return "xsnmsubmdp"; + case PPC_ID_VSX_XSNMSUBMSP: return "xsnmsubmsp"; + case PPC_ID_VSX_XSRDPI: return "xsrdpi"; + case PPC_ID_VSX_XSRDPIC: return "xsrdpic"; + case PPC_ID_VSX_XSRDPIM: return "xsrdpim"; + case PPC_ID_VSX_XSRDPIP: return "xsrdpip"; + case PPC_ID_VSX_XSRDPIZ: return "xsrdpiz"; + case PPC_ID_VSX_XSREDP: return "xsredp"; + case PPC_ID_VSX_XSRESP: return "xsresp"; + case PPC_ID_VSX_XSRSQRTEDP: return "xsrsqrtedp"; + case PPC_ID_VSX_XSRSQRTESP: return "xsrsqrtesp"; + case PPC_ID_VSX_XSSQRTDP: return "xssqrtdp"; + case PPC_ID_VSX_XSSQRTSP: return "xssqrtsp"; + case PPC_ID_VSX_XSSUBDP: return "xssubdp"; + case PPC_ID_VSX_XSSUBSP: return "xssubsp"; + case PPC_ID_VSX_XSTDIVDP: return "xstdivdp"; + case PPC_ID_VSX_XSTDIVSP: return "xstdivsp"; + case PPC_ID_VSX_XSTSQRTDP: return "xstsqrtdp"; + case PPC_ID_VSX_XVABSSP: return "xvabssp"; + case PPC_ID_VSX_XVABSDP: return "xvabsdp"; + case PPC_ID_VSX_XVADDSP: return "xvaddsp"; + case PPC_ID_VSX_XVADDDP: return "xvadddp"; + case PPC_ID_VSX_XVCMPEQDPx: return RcMnemonic(instruction, SubMnemXVCMPEQDPx); + case PPC_ID_VSX_XVCMPEQSPx: return RcMnemonic(instruction, SubMnemXVCMPEQSPx); + case PPC_ID_VSX_XVCMPGEDPx: return RcMnemonic(instruction, SubMnemXVCMPGEDPx); + case PPC_ID_VSX_XVCMPGESPx: return RcMnemonic(instruction, SubMnemXVCMPGESPx); + case PPC_ID_VSX_XVCMPGTDPx: return RcMnemonic(instruction, SubMnemXVCMPGTDPx); + case PPC_ID_VSX_XVCMPGTSPx: return RcMnemonic(instruction, SubMnemXVCMPGTSPx); + case PPC_ID_VSX_XVCPSGNDP: return "xvcpsgndp"; + case PPC_ID_VSX_XVCPSGNSP: return "xvcpsgnsp"; + case PPC_ID_VSX_XVCVDPSP: return "xvcvdpsp"; + case PPC_ID_VSX_XVCVDPSXDS: return "xvcvdpsxds"; + case PPC_ID_VSX_XVCVDPSXWS: return "xvcvdpsxws"; + case PPC_ID_VSX_XVCVDPUXDS: return "xvcvdpuxds"; + case PPC_ID_VSX_XVCVDPUXWS: return "xvcvdpuxws"; + case PPC_ID_VSX_XVCVSPDP: return "xvcvspdp"; + case PPC_ID_VSX_XVCVSPSXDS: return "xvcvspsxds"; + case PPC_ID_VSX_XVCVSPSXWS: return "xvcvspsxws"; + case PPC_ID_VSX_XVCVSPUXDS: return "xvcvspuxds"; + case PPC_ID_VSX_XVCVSPUXWS: return "xvcvspuxws"; + case PPC_ID_VSX_XVCVSXDDP: return "xvcvsxddp"; + case PPC_ID_VSX_XVCVSXDSP: return "xvcvsxdsp"; + case PPC_ID_VSX_XVCVSXWDP: return "xvcvsxwdp"; + case PPC_ID_VSX_XVCVSXWSP: return "xvcvsxwsp"; + case PPC_ID_VSX_XVCVUXDDP: return "xvcvuxddp"; + case PPC_ID_VSX_XVCVUXDSP: return "xvcvuxdsp"; + case PPC_ID_VSX_XVCVUXWDP: return "xvcvuxwdp"; + case PPC_ID_VSX_XVCVUXWSP: return "xvcvuxwsp"; + case PPC_ID_VSX_XVDIVDP: return "xvdivdp"; + case PPC_ID_VSX_XVDIVSP: return "xvdivsp"; + case PPC_ID_VSX_XVMADDADP: return "xvmaddadp"; + case PPC_ID_VSX_XVMADDASP: return "xvmaddasp"; + case PPC_ID_VSX_XVMADDMDP: return "xvmaddmdp"; + case PPC_ID_VSX_XVMADDMSP: return "xvmaddmsp"; + case PPC_ID_VSX_XVMAXDP: return "xvmaxdp"; + case PPC_ID_VSX_XVMAXSP: return "xvmaxsp"; + case PPC_ID_VSX_XVMINDP: return "xvmindp"; + case PPC_ID_VSX_XVMINSP: return "xvminsp"; + case PPC_ID_VSX_XVMOVDP: return "xvmovdp"; + case PPC_ID_VSX_XVMOVSP: return "xvmovsp"; + case PPC_ID_VSX_XVMSUBADP: return "xvmsubadp"; + case PPC_ID_VSX_XVMSUBASP: return "xvmsubasp"; + case PPC_ID_VSX_XVMSUBMDP: return "xvmsubmdp"; + case PPC_ID_VSX_XVMSUBMSP: return "xvmsubmsp"; + case PPC_ID_VSX_XVMULSP: return "xvmulsp"; + case PPC_ID_VSX_XVMULDP: return "xvmuldp"; + case PPC_ID_VSX_XVNABSDP: return "xvnabsdp"; + case PPC_ID_VSX_XVNABSSP: return "xvnabssp"; + case PPC_ID_VSX_XVNMADDADP: return "xvnmaddadp"; + case PPC_ID_VSX_XVNMADDASP: return "xvnmaddasp"; + case PPC_ID_VSX_XVNMADDMDP: return "xvnmaddmdp"; + case PPC_ID_VSX_XVNMADDMSP: return "xvnmaddmsp"; + case PPC_ID_VSX_XVNEGDP: return "xvnegdp"; + case PPC_ID_VSX_XVNEGSP: return "xvnegsp"; + case PPC_ID_VSX_XVNMSUBADP: return "xvnmsubadp"; + case PPC_ID_VSX_XVNMSUBASP: return "xvnmsubasp"; + case PPC_ID_VSX_XVNMSUBMSP: return "xvnmsubmsp"; + case PPC_ID_VSX_XVNMSUBMDP: return "xvnmsubmdp"; + case PPC_ID_VSX_XVRDPI: return "xvrdpi"; + case PPC_ID_VSX_XVRDPIC: return "xvrdpic"; + case PPC_ID_VSX_XVRDPIM: return "xvrdpim"; + case PPC_ID_VSX_XVRDPIP: return "xvrdpip"; + case PPC_ID_VSX_XVRDPIZ: return "xvrdpiz"; + case PPC_ID_VSX_XVREDP: return "xvredp"; + case PPC_ID_VSX_XVRESP: return "xvresp"; + case PPC_ID_VSX_XVRSPI: return "xvrspi"; + case PPC_ID_VSX_XVRSPIC: return "xvrspic"; + case PPC_ID_VSX_XVRSPIM: return "xvrspim"; + case PPC_ID_VSX_XVRSPIP: return "xvrspip"; + case PPC_ID_VSX_XVRSPIZ: return "xvrspiz"; + case PPC_ID_VSX_XVRSQRTEDP: return "xvrsqrtedp"; + case PPC_ID_VSX_XVRSQRTESP: return "xvrsqrtesp"; + case PPC_ID_VSX_XVSQRTDP: return "xvsqrtdp"; + case PPC_ID_VSX_XVSQRTSP: return "xvsqrtsp"; + case PPC_ID_VSX_XVSUBSP: return "xvsubsp"; + case PPC_ID_VSX_XVSUBDP: return "xvsubdp"; + case PPC_ID_VSX_XVTDIVDP: return "xvtdivdp"; + case PPC_ID_VSX_XVTDIVSP: return "xvtdivsp"; + case PPC_ID_VSX_XVTSQRTDP: return "xvtsqrtdp"; + case PPC_ID_VSX_XVTSQRTSP: return "xvtsqrtsp"; + case PPC_ID_VSX_XXLAND: return "xxland"; + case PPC_ID_VSX_XXLANDC: return "xxlandc"; + case PPC_ID_VSX_XXLEQV: return "xxleqv"; + case PPC_ID_VSX_XXLNAND: return "xxlnand"; + case PPC_ID_VSX_XXLNOR: return "xxlnor"; + case PPC_ID_VSX_XXLORC: return "xxlorc"; + case PPC_ID_VSX_XXMRGHD: return "xxmrghd"; + case PPC_ID_VSX_XXMRGHW: return "xxmrghw"; + case PPC_ID_VSX_XXMRGLD: return "xxmrgld"; + case PPC_ID_VSX_XXMRGLW: return "xxmrglw"; + case PPC_ID_VSX_XXLOR: return "xxlor"; + case PPC_ID_VSX_XXLXOR: return "xxlxor"; + case PPC_ID_VSX_XXPERMDI: return "xxpermdi"; + case PPC_ID_VSX_XXSEL: return "xxsel"; + case PPC_ID_VSX_XXSLDWI: return "xxsldwi"; + case PPC_ID_VSX_XXSPLTD: return "xxspltd"; + case PPC_ID_VSX_XXSPLTW: return "xxspltw"; + case PPC_ID_VSX_XXSWAPD: return "xxswapd"; + + default: return NULL; + } +} + + +bool Decompose(Instruction* instruction, uint32_t word32, uint64_t address, uint32_t flags) +{ + memset(instruction, 0, sizeof *instruction); + + instruction->id = Decode(word32, flags); + if (instruction->id == PPC_ID_INVALID) + return false; + + FillOperands(instruction, word32, address); + return true; +} diff --git a/arch/powerpc/decode/decode.h b/arch/powerpc/decode/decode.h new file mode 100644 index 000000000..0c85559fc --- /dev/null +++ b/arch/powerpc/decode/decode.h @@ -0,0 +1,1155 @@ +#ifndef DECODE_PPC_H +#define DECODE_PPC_H + +#include +#include +#include + +#define DECODE_FLAGS_PPC64 0x01 +#define DECODE_FLAGS_ALTIVEC 0x02 +#define DECODE_FLAGS_VSX 0x04 + +#ifdef __cplusplus +extern "C" { +#endif + enum Register + { + NUPPC_REG_GPR0, + NUPPC_REG_GPR1, + NUPPC_REG_GPR2, + NUPPC_REG_GPR3, + NUPPC_REG_GPR4, + NUPPC_REG_GPR5, + NUPPC_REG_GPR6, + NUPPC_REG_GPR7, + NUPPC_REG_GPR8, + NUPPC_REG_GPR9, + NUPPC_REG_GPR10, + NUPPC_REG_GPR11, + NUPPC_REG_GPR12, + NUPPC_REG_GPR13, + NUPPC_REG_GPR14, + NUPPC_REG_GPR15, + NUPPC_REG_GPR16, + NUPPC_REG_GPR17, + NUPPC_REG_GPR18, + NUPPC_REG_GPR19, + NUPPC_REG_GPR20, + NUPPC_REG_GPR21, + NUPPC_REG_GPR22, + NUPPC_REG_GPR23, + NUPPC_REG_GPR24, + NUPPC_REG_GPR25, + NUPPC_REG_GPR26, + NUPPC_REG_GPR27, + NUPPC_REG_GPR28, + NUPPC_REG_GPR29, + NUPPC_REG_GPR30, + NUPPC_REG_GPR31, + + NUPPC_REG_FR0, + NUPPC_REG_FR1, + NUPPC_REG_FR2, + NUPPC_REG_FR3, + NUPPC_REG_FR4, + NUPPC_REG_FR5, + NUPPC_REG_FR6, + NUPPC_REG_FR7, + NUPPC_REG_FR8, + NUPPC_REG_FR9, + NUPPC_REG_FR10, + NUPPC_REG_FR11, + NUPPC_REG_FR12, + NUPPC_REG_FR13, + NUPPC_REG_FR14, + NUPPC_REG_FR15, + NUPPC_REG_FR16, + NUPPC_REG_FR17, + NUPPC_REG_FR18, + NUPPC_REG_FR19, + NUPPC_REG_FR20, + NUPPC_REG_FR21, + NUPPC_REG_FR22, + NUPPC_REG_FR23, + NUPPC_REG_FR24, + NUPPC_REG_FR25, + NUPPC_REG_FR26, + NUPPC_REG_FR27, + NUPPC_REG_FR28, + NUPPC_REG_FR29, + NUPPC_REG_FR30, + NUPPC_REG_FR31, + + // each 4-bit CR register + NUPPC_REG_CRF0, + NUPPC_REG_CRF1, + NUPPC_REG_CRF2, + NUPPC_REG_CRF3, + NUPPC_REG_CRF4, + NUPPC_REG_CRF5, + NUPPC_REG_CRF6, + NUPPC_REG_CRF7, + + // each bit in the CR register + NUPPC_REG_CR_BIT0, + NUPPC_REG_CR_BIT1, + NUPPC_REG_CR_BIT2, + NUPPC_REG_CR_BIT3, + NUPPC_REG_CR_BIT4, + NUPPC_REG_CR_BIT5, + NUPPC_REG_CR_BIT6, + NUPPC_REG_CR_BIT7, + NUPPC_REG_CR_BIT8, + NUPPC_REG_CR_BIT9, + NUPPC_REG_CR_BIT10, + NUPPC_REG_CR_BIT11, + NUPPC_REG_CR_BIT12, + NUPPC_REG_CR_BIT13, + NUPPC_REG_CR_BIT14, + NUPPC_REG_CR_BIT15, + NUPPC_REG_CR_BIT16, + NUPPC_REG_CR_BIT17, + NUPPC_REG_CR_BIT18, + NUPPC_REG_CR_BIT19, + NUPPC_REG_CR_BIT20, + NUPPC_REG_CR_BIT21, + NUPPC_REG_CR_BIT22, + NUPPC_REG_CR_BIT23, + NUPPC_REG_CR_BIT24, + NUPPC_REG_CR_BIT25, + NUPPC_REG_CR_BIT26, + NUPPC_REG_CR_BIT27, + NUPPC_REG_CR_BIT28, + NUPPC_REG_CR_BIT29, + NUPPC_REG_CR_BIT30, + NUPPC_REG_CR_BIT31, + + NUPPC_REG_AV_VR0, + NUPPC_REG_AV_VR1, + NUPPC_REG_AV_VR2, + NUPPC_REG_AV_VR3, + NUPPC_REG_AV_VR4, + NUPPC_REG_AV_VR5, + NUPPC_REG_AV_VR6, + NUPPC_REG_AV_VR7, + NUPPC_REG_AV_VR8, + NUPPC_REG_AV_VR9, + NUPPC_REG_AV_VR10, + NUPPC_REG_AV_VR11, + NUPPC_REG_AV_VR12, + NUPPC_REG_AV_VR13, + NUPPC_REG_AV_VR14, + NUPPC_REG_AV_VR15, + NUPPC_REG_AV_VR16, + NUPPC_REG_AV_VR17, + NUPPC_REG_AV_VR18, + NUPPC_REG_AV_VR19, + NUPPC_REG_AV_VR20, + NUPPC_REG_AV_VR21, + NUPPC_REG_AV_VR22, + NUPPC_REG_AV_VR23, + NUPPC_REG_AV_VR24, + NUPPC_REG_AV_VR25, + NUPPC_REG_AV_VR26, + NUPPC_REG_AV_VR27, + NUPPC_REG_AV_VR28, + NUPPC_REG_AV_VR29, + NUPPC_REG_AV_VR30, + NUPPC_REG_AV_VR31, + + NUPPC_REG_VSX_VR0, + NUPPC_REG_VSX_VR1, + NUPPC_REG_VSX_VR2, + NUPPC_REG_VSX_VR3, + NUPPC_REG_VSX_VR4, + NUPPC_REG_VSX_VR5, + NUPPC_REG_VSX_VR6, + NUPPC_REG_VSX_VR7, + NUPPC_REG_VSX_VR8, + NUPPC_REG_VSX_VR9, + NUPPC_REG_VSX_VR10, + NUPPC_REG_VSX_VR11, + NUPPC_REG_VSX_VR12, + NUPPC_REG_VSX_VR13, + NUPPC_REG_VSX_VR14, + NUPPC_REG_VSX_VR15, + NUPPC_REG_VSX_VR16, + NUPPC_REG_VSX_VR17, + NUPPC_REG_VSX_VR18, + NUPPC_REG_VSX_VR19, + NUPPC_REG_VSX_VR20, + NUPPC_REG_VSX_VR21, + NUPPC_REG_VSX_VR22, + NUPPC_REG_VSX_VR23, + NUPPC_REG_VSX_VR24, + NUPPC_REG_VSX_VR25, + NUPPC_REG_VSX_VR26, + NUPPC_REG_VSX_VR27, + NUPPC_REG_VSX_VR28, + NUPPC_REG_VSX_VR29, + NUPPC_REG_VSX_VR30, + NUPPC_REG_VSX_VR31, + NUPPC_REG_VSX_VR32, + NUPPC_REG_VSX_VR33, + NUPPC_REG_VSX_VR34, + NUPPC_REG_VSX_VR35, + NUPPC_REG_VSX_VR36, + NUPPC_REG_VSX_VR37, + NUPPC_REG_VSX_VR38, + NUPPC_REG_VSX_VR39, + NUPPC_REG_VSX_VR40, + NUPPC_REG_VSX_VR41, + NUPPC_REG_VSX_VR42, + NUPPC_REG_VSX_VR43, + NUPPC_REG_VSX_VR44, + NUPPC_REG_VSX_VR45, + NUPPC_REG_VSX_VR46, + NUPPC_REG_VSX_VR47, + NUPPC_REG_VSX_VR48, + NUPPC_REG_VSX_VR49, + NUPPC_REG_VSX_VR50, + NUPPC_REG_VSX_VR51, + NUPPC_REG_VSX_VR52, + NUPPC_REG_VSX_VR53, + NUPPC_REG_VSX_VR54, + NUPPC_REG_VSX_VR55, + NUPPC_REG_VSX_VR56, + NUPPC_REG_VSX_VR57, + NUPPC_REG_VSX_VR58, + NUPPC_REG_VSX_VR59, + NUPPC_REG_VSX_VR60, + NUPPC_REG_VSX_VR61, + NUPPC_REG_VSX_VR62, + NUPPC_REG_VSX_VR63, + }; + +#ifndef __cplusplus + typedef enum Register Register; +#endif + + enum OperandClass + { + NONE = 0, + UIMM, + SIMM, + LABEL, + MEM_RA, + BI, + + REG_RA, + REG_RB, + REG_RD, + REG_RS, + REG_FRA, + REG_FRB, + REG_FRC, + REG_FRD, + REG_FRS, + REG_CRFD, + REG_CRFS, + REG_CRBA, + REG_CRBB, + REG_CRBD, + + REG_AV_VA, + REG_AV_VB, + REG_AV_VC, + REG_AV_VD, + REG_AV_VS, + + // DWORD0 means that only the 0th dword is affected, which + // has an overlap with floating registers + REG_VSX_RA, + REG_VSX_RA_DWORD0, + + REG_VSX_RB, + REG_VSX_RB_DWORD0, + + REG_VSX_RC, + REG_VSX_RC_DWORD0, + + REG_VSX_RD, + REG_VSX_RD_DWORD0, + + REG_VSX_RS, + REG_VSX_RS_DWORD0, + }; + +#ifndef __cplusplus + typedef enum OperandClass OperandClass; +#endif + + enum VsxWidth + { + VSX_WIDTH_FULL, + VSX_WIDTH_DWORD0, + }; + +#ifndef __cplusplus + typedef enum VsxWidth VsxWidth; +#endif + + struct MemoryOperand + { + enum Register reg; + int32_t offset; + }; + +#ifndef __cplusplus + typedef struct MemoryOperand MemoryOperand; +#endif + + struct Operand + { + OperandClass cls; + union { + enum Register reg; + uint64_t uimm; + int64_t simm; + MemoryOperand mem; + uint64_t label; + }; + }; + +#ifndef __cplusplus + typedef struct Operand Operand; +#endif + + // trailing lowercase 'x' indicates potential other mnemonics (rc, oe, lk, + // etc. bits) + enum InstructionId + { + PPC_ID_INVALID, + + PPC_ID_ADDx, + PPC_ID_ADDCx, + PPC_ID_ADDEx, + PPC_ID_ADDI, + PPC_ID_ADDICx, + PPC_ID_ADDIS, + PPC_ID_ADDMEx, + PPC_ID_ADDZEx, + PPC_ID_ANDx, + PPC_ID_ANDCx, + PPC_ID_ANDI, + PPC_ID_ANDIS, + PPC_ID_ATTN, + PPC_ID_Bx, + PPC_ID_BCx, + PPC_ID_BCCTRx, + PPC_ID_BCLRx, + PPC_ID_BCTRx, + PPC_ID_BDZx, + PPC_ID_BDZCTRx, + PPC_ID_BDZLRx, + PPC_ID_BDNZx, + PPC_ID_BDNZCTRx, + PPC_ID_BDNZLRx, + PPC_ID_BDNZFx, + PPC_ID_BDNZFCTRx, + PPC_ID_BDNZFLRx, + PPC_ID_BDNZTx, + PPC_ID_BDNZTCTRx, + PPC_ID_BDNZTLRx, + PPC_ID_BDZFx, + PPC_ID_BDZFCTRx, + PPC_ID_BDZFLRx, + PPC_ID_BDZTx, + PPC_ID_BDZTCTRx, + PPC_ID_BDZTLRx, + PPC_ID_BEQx, + PPC_ID_BEQCTRx, + PPC_ID_BEQLRx, + PPC_ID_BFx, + PPC_ID_BFCTRx, + PPC_ID_BFLRx, + PPC_ID_BGEx, + PPC_ID_BGECTRx, + PPC_ID_BGELRx, + PPC_ID_BGTx, + PPC_ID_BGTCTRx, + PPC_ID_BGTLRx, + PPC_ID_BLEx, + PPC_ID_BLECTRx, + PPC_ID_BLELRx, + PPC_ID_BLTx, + PPC_ID_BLTCTRx, + PPC_ID_BLTLRx, + PPC_ID_BLRx, + PPC_ID_BNEx, + PPC_ID_BNECTRx, + PPC_ID_BNELRx, + PPC_ID_BNSx, + PPC_ID_BNSCTRx, + PPC_ID_BNSLRx, + PPC_ID_BSOx, + PPC_ID_BSOCTRx, + PPC_ID_BSOLRx, + PPC_ID_BTx, + PPC_ID_BTCTRx, + PPC_ID_BTLRx, + PPC_ID_CLRLDIx, + PPC_ID_CLRLWIx, + PPC_ID_CLRRWIx, + PPC_ID_CMPB, + PPC_ID_CMPD, + PPC_ID_CMPDI, + PPC_ID_CMPW, + PPC_ID_CMPWI, + PPC_ID_CMPLD, + PPC_ID_CMPLDI, + PPC_ID_CMPLW, + PPC_ID_CMPLWI, + PPC_ID_CNTLZDx, + PPC_ID_CNTLZWx, + PPC_ID_CRAND, + PPC_ID_CRANDC, + PPC_ID_CRCLR, + PPC_ID_CREQV, + PPC_ID_CRMOVE, + PPC_ID_CRNAND, + PPC_ID_CRNOR, + PPC_ID_CRNOT, + PPC_ID_CROR, + PPC_ID_CRORC, + PPC_ID_CRSET, + PPC_ID_CRXOR, + PPC_ID_DCBA, + PPC_ID_DCBF, + PPC_ID_DCBI, + PPC_ID_DCBST, + PPC_ID_DCBT, + PPC_ID_DCBTST, + PPC_ID_DCBZ, + PPC_ID_DCBZL, + PPC_ID_DCCCI, + PPC_ID_DCI, + PPC_ID_DIVDx, + PPC_ID_DIVDUx, + PPC_ID_DIVWx, + PPC_ID_DIVWUx, + PPC_ID_ECIWX, + PPC_ID_ECOWX, + PPC_ID_EIEIO, + PPC_ID_EQVx, + PPC_ID_EXTSBx, + PPC_ID_EXTSHx, + PPC_ID_EXTSWx, + PPC_ID_FABSx, + PPC_ID_FADDx, + PPC_ID_FADDSx, + PPC_ID_FCFIDx, + PPC_ID_FCFIDSx, + PPC_ID_FCFIDUx, + PPC_ID_FCFIDUSx, + PPC_ID_FCMPO, + PPC_ID_FCMPU, + PPC_ID_FCPSGNx, + PPC_ID_FCTIDx, + PPC_ID_FCTIDUZx, + PPC_ID_FCTIDZx, + PPC_ID_FCTIWx, + PPC_ID_FCTIWUZx, + PPC_ID_FCTIWZx, + PPC_ID_FDIVx, + PPC_ID_FDIVSx, + PPC_ID_FMADDx, + PPC_ID_FMADDSx, + PPC_ID_FMRx, + PPC_ID_FMSUBx, + PPC_ID_FMSUBSx, + PPC_ID_FMULx, + PPC_ID_FMULSx, + PPC_ID_FNABSx, + PPC_ID_FNEGx, + PPC_ID_FNMADDx, + PPC_ID_FNMADDSx, + PPC_ID_FNMSUBx, + PPC_ID_FNMSUBSx, + PPC_ID_FREx, + PPC_ID_FRESx, + PPC_ID_FRIMx, + PPC_ID_FRINx, + PPC_ID_FRIPx, + PPC_ID_FRIZx, + PPC_ID_FRSPx, + PPC_ID_FRSQRTEx, + PPC_ID_FRSQRTESx, + PPC_ID_FSELx, + PPC_ID_FSQRTx, + PPC_ID_FSQRTSx, + PPC_ID_FSUBx, + PPC_ID_FSUBSx, + PPC_ID_ICBI, + PPC_ID_ICBT, + PPC_ID_ICCCI, + PPC_ID_ICI, + PPC_ID_ISEL, + PPC_ID_ISYNC, + PPC_ID_LBZ, + PPC_ID_LBZCIX, + PPC_ID_LBZU, + PPC_ID_LBZUX, + PPC_ID_LBZX, + PPC_ID_LDARX, + PPC_ID_LDBRX, + PPC_ID_LDCIX, + PPC_ID_LD, + PPC_ID_LDU, + PPC_ID_LDUX, + PPC_ID_LDX, + PPC_ID_LFD, + PPC_ID_LFDU, + PPC_ID_LFDUX, + PPC_ID_LFDX, + PPC_ID_LFIWAX, + PPC_ID_LFIWZX, + PPC_ID_LFS, + PPC_ID_LFSU, + PPC_ID_LFSUX, + PPC_ID_LFSX, + PPC_ID_LHA, + PPC_ID_LHAU, + PPC_ID_LHAUX, + PPC_ID_LHAX, + PPC_ID_LHBRX, + PPC_ID_LHZ, + PPC_ID_LHZCIX, + PPC_ID_LHZU, + PPC_ID_LHZUX, + PPC_ID_LHZX, + PPC_ID_LI, + PPC_ID_LIS, + PPC_ID_LMW, + PPC_ID_LSWI, + PPC_ID_LSWX, + PPC_ID_LWA, + PPC_ID_LWAX, + PPC_ID_LWARX, + PPC_ID_LWAUX, + PPC_ID_LWBRX, + PPC_ID_LWSYNC, + PPC_ID_LWZ, + PPC_ID_LWZCIX, + PPC_ID_LWZU, + PPC_ID_LWZUX, + PPC_ID_LWZX, + PPC_ID_MBAR, + PPC_ID_MCRF, + PPC_ID_MCRFS, + PPC_ID_MCRXR, + PPC_ID_MFBR0, + PPC_ID_MFBR1, + PPC_ID_MFBR2, + PPC_ID_MFBR3, + PPC_ID_MFBR4, + PPC_ID_MFBR5, + PPC_ID_MFBR6, + PPC_ID_MFBR7, + PPC_ID_MFCR, + PPC_ID_MFCTR, + PPC_ID_MFDCR, + PPC_ID_MFDCRUX, + PPC_ID_MFDCRX, + PPC_ID_MFFSx, + PPC_ID_MFLR, + PPC_ID_MFMSR, + PPC_ID_MFOCRF, + PPC_ID_MFSPR, + PPC_ID_MFSR, + PPC_ID_MFSRIN, + PPC_ID_MFTB, + PPC_ID_MFTBU, + PPC_ID_MFXER, + PPC_ID_MRx, + PPC_ID_MTAMR, + PPC_ID_MTBR0, + PPC_ID_MTBR1, + PPC_ID_MTBR2, + PPC_ID_MTBR3, + PPC_ID_MTBR4, + PPC_ID_MTBR5, + PPC_ID_MTBR6, + PPC_ID_MTBR7, + PPC_ID_MTCFAR, + PPC_ID_MTCRF, + PPC_ID_MTCTR, + PPC_ID_MTDAR, + PPC_ID_MTDCCR, + PPC_ID_MTDCR, + PPC_ID_MTDCRUX, + PPC_ID_MTDCRX, + PPC_ID_MTFSB0x, + PPC_ID_MTFSB1x, + PPC_ID_MTFSFx, + PPC_ID_MTFSFIx, + PPC_ID_MTICCR, + PPC_ID_MTLR, + PPC_ID_MTMSR, + PPC_ID_MTMSRD, + PPC_ID_MTOCRF, + PPC_ID_MTSPR, + PPC_ID_MTSR, + PPC_ID_MTSRIN, + PPC_ID_MTSRR2, + PPC_ID_MTSRR3, + PPC_ID_MTTBHI, + PPC_ID_MTTBL, + PPC_ID_MTTBU, + PPC_ID_MTXER, + PPC_ID_MULHDx, + PPC_ID_MULHDUx, + PPC_ID_MULHWx, + PPC_ID_MULHWUx, + PPC_ID_MULLDx, + PPC_ID_MULLI, + PPC_ID_MULLWx, + PPC_ID_NANDx, + PPC_ID_NEGx, + PPC_ID_NOP, + PPC_ID_NORx, + PPC_ID_ORx, + PPC_ID_ORCx, + PPC_ID_ORI, + PPC_ID_ORIS, + PPC_ID_POPCNTB, + PPC_ID_POPCNTD, + PPC_ID_POPCNTW, + PPC_ID_PTESYNC, + PPC_ID_RFCI, + PPC_ID_RFDI, + PPC_ID_RFI, + PPC_ID_RFID, + PPC_ID_RFMCI, + PPC_ID_RLDICLx, + PPC_ID_RLDICRx, + PPC_ID_RLDICx, + PPC_ID_RLDIMIx, + PPC_ID_RLDCLx, + PPC_ID_RLDCRx, + PPC_ID_RLWIMIx, + PPC_ID_RLWINMx, + PPC_ID_RLWNMx, + PPC_ID_ROTLDx, + PPC_ID_ROTLDIx, + PPC_ID_ROTLWx, + PPC_ID_ROTLWIx, + PPC_ID_SC, + PPC_ID_SLBIA, + PPC_ID_SLBIE, + PPC_ID_SLBMFEE, + PPC_ID_SLBMTE, + PPC_ID_SLDx, + PPC_ID_SLDIx, + PPC_ID_SLWx, + PPC_ID_SLWIx, + PPC_ID_SRADx, + PPC_ID_SRADIx, + PPC_ID_SRAWx, + PPC_ID_SRAWIx, + PPC_ID_SRDx, + PPC_ID_SRDIx, + PPC_ID_SRWx, + PPC_ID_SRWIx, + PPC_ID_STB, + PPC_ID_STBU, + PPC_ID_STBUX, + PPC_ID_STBX, + PPC_ID_STBCIX, + PPC_ID_STD, + PPC_ID_STDBRX, + PPC_ID_STDCIX, + PPC_ID_STDCX, + PPC_ID_STDU, + PPC_ID_STDUX, + PPC_ID_STDX, + PPC_ID_STFD, + PPC_ID_STFDU, + PPC_ID_STFDUX, + PPC_ID_STFDX, + PPC_ID_STFIWX, + PPC_ID_STFS, + PPC_ID_STFSU, + PPC_ID_STFSUX, + PPC_ID_STFSX, + PPC_ID_STH, + PPC_ID_STHBRX, + PPC_ID_STHCIX, + PPC_ID_STHU, + PPC_ID_STHUX, + PPC_ID_STHX, + PPC_ID_STMW, + PPC_ID_STSWI, + PPC_ID_STSWX, + PPC_ID_STW, + PPC_ID_STWBRX, + PPC_ID_STWCIX, + PPC_ID_STWCX, + PPC_ID_STWU, + PPC_ID_STWUX, + PPC_ID_STWX, + PPC_ID_SUBFx, + PPC_ID_SUBFCx, + PPC_ID_SUBFEx, + PPC_ID_SUBFIC, + PPC_ID_SUBFMEx, + PPC_ID_SUBFZEx, + PPC_ID_SYNC, + PPC_ID_TD, + PPC_ID_TDEQ, + PPC_ID_TDEQI, + PPC_ID_TDGT, + PPC_ID_TDGTI, + PPC_ID_TDI, + PPC_ID_TDLGT, + PPC_ID_TDLGTI, + PPC_ID_TDLLT, + PPC_ID_TDLLTI, + PPC_ID_TDLT, + PPC_ID_TDLTI, + PPC_ID_TDNE, + PPC_ID_TDNEI, + PPC_ID_TDU, + PPC_ID_TDUI, + PPC_ID_TLBIA, + PPC_ID_TLBIE, + PPC_ID_TLBIEL, + PPC_ID_TLBIVAX, + PPC_ID_TLBLI, + PPC_ID_TLBSX, + PPC_ID_TLBSYNC, + PPC_ID_TLBRE, + PPC_ID_TLBRELO, + PPC_ID_TLBREHI, + PPC_ID_TLBWE, + PPC_ID_TLBWEHI, + PPC_ID_TLBWELO, + PPC_ID_TW, + PPC_ID_TWEQ, + PPC_ID_TWEQI, + PPC_ID_TWGT, + PPC_ID_TWGTI, + PPC_ID_TWGEI, + PPC_ID_TWI, + PPC_ID_TWLEI, + PPC_ID_TWLLEI, + PPC_ID_TWLGT, + PPC_ID_TWLGTI, + PPC_ID_TWLLT, + PPC_ID_TWLLTI, + PPC_ID_TWLT, + PPC_ID_TWLTI, + PPC_ID_TWNE, + PPC_ID_TWNEI, + PPC_ID_TWU, + PPC_ID_TWUI, + PPC_ID_WAIT, + PPC_ID_WAITIMPL, + PPC_ID_WAITRSV, + PPC_ID_WRTEE, + PPC_ID_WRTEEI, + PPC_ID_XNOP, + PPC_ID_XORx, + PPC_ID_XORI, + PPC_ID_XORIS, + + // AltiVec instructions + PPC_ID_AV_DSS, + PPC_ID_AV_DSSALL, + PPC_ID_AV_DST, + PPC_ID_AV_DSTST, + PPC_ID_AV_DSTSTT, + PPC_ID_AV_DSTT, + PPC_ID_AV_LVEBX, + PPC_ID_AV_LVEHX, + PPC_ID_AV_LVEWX, + PPC_ID_AV_LVSL, + PPC_ID_AV_LVSR, + PPC_ID_AV_LVX, + PPC_ID_AV_LVXL, + PPC_ID_AV_MFVSCR, + PPC_ID_AV_MTVSCR, + PPC_ID_AV_STVEBX, + PPC_ID_AV_STVEHX, + PPC_ID_AV_STVEWX, + PPC_ID_AV_STVX, + PPC_ID_AV_STVXL, + PPC_ID_AV_VADDCUW, + PPC_ID_AV_VADDFP, + PPC_ID_AV_VADDSBS, + PPC_ID_AV_VADDSHS, + PPC_ID_AV_VADDSWS, + PPC_ID_AV_VADDUBM, + PPC_ID_AV_VADDUBS, + PPC_ID_AV_VADDUDM, + PPC_ID_AV_VADDUHM, + PPC_ID_AV_VADDUHS, + PPC_ID_AV_VADDUWM, + PPC_ID_AV_VADDUWS, + PPC_ID_AV_VAND, + PPC_ID_AV_VANDC, + PPC_ID_AV_VAVGSB, + PPC_ID_AV_VAVGSH, + PPC_ID_AV_VAVGSW, + PPC_ID_AV_VAVGUB, + PPC_ID_AV_VAVGUH, + PPC_ID_AV_VAVGUW, + PPC_ID_AV_VCFSX, + PPC_ID_AV_VCFUX, + PPC_ID_AV_VCLZB, + PPC_ID_AV_VCLZD, + PPC_ID_AV_VCLZH, + PPC_ID_AV_VCLZW, + PPC_ID_AV_VCMPBFPx, + PPC_ID_AV_VCMPEQFPx, + PPC_ID_AV_VCMPEQUBx, + PPC_ID_AV_VCMPEQUDx, + PPC_ID_AV_VCMPEQUHx, + PPC_ID_AV_VCMPEQUWx, + PPC_ID_AV_VCMPGEFPx, + PPC_ID_AV_VCMPGTFPx, + PPC_ID_AV_VCMPGTSBx, + PPC_ID_AV_VCMPGTSDx, + PPC_ID_AV_VCMPGTSHx, + PPC_ID_AV_VCMPGTSWx, + PPC_ID_AV_VCMPGTUBx, + PPC_ID_AV_VCMPGTUDx, + PPC_ID_AV_VCMPGTUHx, + PPC_ID_AV_VCMPGTUWx, + PPC_ID_AV_VCTSXS, + PPC_ID_AV_VCTUXS, + PPC_ID_AV_VEQV, + PPC_ID_AV_VEXPTEFP, + PPC_ID_AV_VLOGEFP, + PPC_ID_AV_VMADDFP, + PPC_ID_AV_VMAXFP, + PPC_ID_AV_VMAXSB, + PPC_ID_AV_VMAXSD, + PPC_ID_AV_VMAXSH, + PPC_ID_AV_VMAXSW, + PPC_ID_AV_VMAXUB, + PPC_ID_AV_VMAXUD, + PPC_ID_AV_VMAXUH, + PPC_ID_AV_VMAXUW, + PPC_ID_AV_VMHADDSHS, + PPC_ID_AV_VMHRADDSHS, + PPC_ID_AV_VMINFP, + PPC_ID_AV_VMINSB, + PPC_ID_AV_VMINSD, + PPC_ID_AV_VMINSH, + PPC_ID_AV_VMINSW, + PPC_ID_AV_VMINUB, + PPC_ID_AV_VMINUD, + PPC_ID_AV_VMINUH, + PPC_ID_AV_VMINUW, + PPC_ID_AV_VMLADDUHM, + PPC_ID_AV_VMRGHB, + PPC_ID_AV_VMRGHH, + PPC_ID_AV_VMRGHW, + PPC_ID_AV_VMRGLB, + PPC_ID_AV_VMRGLH, + PPC_ID_AV_VMRGLW, + PPC_ID_AV_VMSUMMBM, + PPC_ID_AV_VMSUMSHM, + PPC_ID_AV_VMSUMSHS, + PPC_ID_AV_VMSUMUBM, + PPC_ID_AV_VMSUMUHM, + PPC_ID_AV_VMSUMUHS, + PPC_ID_AV_VMULESB, + PPC_ID_AV_VMULESH, + PPC_ID_AV_VMULESW, + PPC_ID_AV_VMULEUB, + PPC_ID_AV_VMULEUH, + PPC_ID_AV_VMULEUW, + PPC_ID_AV_VMULOSB, + PPC_ID_AV_VMULOSH, + PPC_ID_AV_VMULOSW, + PPC_ID_AV_VMULOUB, + PPC_ID_AV_VMULOUH, + PPC_ID_AV_VMULOUW, + PPC_ID_AV_VMULUWM, + PPC_ID_AV_VNAND, + PPC_ID_AV_VNMSUBFP, + PPC_ID_AV_VNOR, + PPC_ID_AV_VOR, + PPC_ID_AV_VORC, + PPC_ID_AV_VPERM, + PPC_ID_AV_VPKPX, + PPC_ID_AV_VPKSHSS, + PPC_ID_AV_VPKSHUS, + PPC_ID_AV_VPKSWSS, + PPC_ID_AV_VPKSWUS, + PPC_ID_AV_VPKUHUM, + PPC_ID_AV_VPKUHUS, + PPC_ID_AV_VPKUWUM, + PPC_ID_AV_VPKUWUS, + PPC_ID_AV_VPOPCNTB, + PPC_ID_AV_VPOPCNTD, + PPC_ID_AV_VPOPCNTH, + PPC_ID_AV_VPOPCNTW, + PPC_ID_AV_VREFP, + PPC_ID_AV_VRFIM, + PPC_ID_AV_VRFIN, + PPC_ID_AV_VRFIP, + PPC_ID_AV_VRFIZ, + PPC_ID_AV_VRLB, + PPC_ID_AV_VRLD, + PPC_ID_AV_VRLH, + PPC_ID_AV_VRLW, + PPC_ID_AV_VRSQRTEFP, + PPC_ID_AV_VSEL, + PPC_ID_AV_VSL, + PPC_ID_AV_VSLB, + PPC_ID_AV_VSLD, + PPC_ID_AV_VSLDOI, + PPC_ID_AV_VSLH, + PPC_ID_AV_VSLO, + PPC_ID_AV_VSLW, + PPC_ID_AV_VSPLTB, + PPC_ID_AV_VSPLTH, + PPC_ID_AV_VSPLTISB, + PPC_ID_AV_VSPLTISH, + PPC_ID_AV_VSPLTISW, + PPC_ID_AV_VSPLTW, + PPC_ID_AV_VSR, + PPC_ID_AV_VSRAB, + PPC_ID_AV_VSRAD, + PPC_ID_AV_VSRAH, + PPC_ID_AV_VSRAW, + PPC_ID_AV_VSRB, + PPC_ID_AV_VSRD, + PPC_ID_AV_VSRH, + PPC_ID_AV_VSRO, + PPC_ID_AV_VSRW, + PPC_ID_AV_VSUBCUW, + PPC_ID_AV_VSUBFP, + PPC_ID_AV_VSUBSBS, + PPC_ID_AV_VSUBSHS, + PPC_ID_AV_VSUBSWS, + PPC_ID_AV_VSUBUBM, + PPC_ID_AV_VSUBUBS, + PPC_ID_AV_VSUBUDM, + PPC_ID_AV_VSUBUHM, + PPC_ID_AV_VSUBUHS, + PPC_ID_AV_VSUBUWM, + PPC_ID_AV_VSUBUWS, + PPC_ID_AV_VSUMSWS, + PPC_ID_AV_VSUM2SWS, + PPC_ID_AV_VSUM4SBS, + PPC_ID_AV_VSUM4SHS, + PPC_ID_AV_VSUM4UBS, + PPC_ID_AV_VUPKHPX, + PPC_ID_AV_VUPKHSB, + PPC_ID_AV_VUPKHSH, + PPC_ID_AV_VUPKLPX, + PPC_ID_AV_VUPKLSB, + PPC_ID_AV_VUPKLSH, + PPC_ID_AV_VXOR, + + // VSX instructions + PPC_ID_VSX_LXSDX, + PPC_ID_VSX_LXSIWAX, + PPC_ID_VSX_LXSIWZX, + PPC_ID_VSX_LXSSPX, + PPC_ID_VSX_LXVD2X, + PPC_ID_VSX_LXVDSX, + PPC_ID_VSX_LXVW4X, + PPC_ID_VSX_STXSDX, + PPC_ID_VSX_STXSIWX, + PPC_ID_VSX_STXSSPX, + PPC_ID_VSX_STXVD2X, + PPC_ID_VSX_STXVW4X, + PPC_ID_VSX_XSABSDP, + PPC_ID_VSX_XSADDDP, + PPC_ID_VSX_XSADDSP, + PPC_ID_VSX_XSCMPODP, + PPC_ID_VSX_XSCMPUDP, + PPC_ID_VSX_XSCPSGNDP, + PPC_ID_VSX_XSCVDPSP, + PPC_ID_VSX_XSCVDPSXDS, + PPC_ID_VSX_XSCVDPSXWS, + PPC_ID_VSX_XSCVDPUXDS, + PPC_ID_VSX_XSCVDPUXWS, + PPC_ID_VSX_XSCVSPDP, + PPC_ID_VSX_XSCVSPDPN, + PPC_ID_VSX_XSCVSXDDP, + PPC_ID_VSX_XSCVSXDSP, + PPC_ID_VSX_XSCVUXDDP, + PPC_ID_VSX_XSCVUXDSP, + PPC_ID_VSX_XSDIVDP, + PPC_ID_VSX_XSDIVSP, + PPC_ID_VSX_XSMADDADP, + PPC_ID_VSX_XSMADDASP, + PPC_ID_VSX_XSMADDMDP, + PPC_ID_VSX_XSMADDMSP, + PPC_ID_VSX_XSMAXDP, + PPC_ID_VSX_XSMINDP, + PPC_ID_VSX_XSMSUBADP, + PPC_ID_VSX_XSMSUBASP, + PPC_ID_VSX_XSMSUBMDP, + PPC_ID_VSX_XSMSUBMSP, + PPC_ID_VSX_XSMULDP, + PPC_ID_VSX_XSMULSP, + PPC_ID_VSX_XSNABSDP, + PPC_ID_VSX_XSNEGDP, + PPC_ID_VSX_XSNMADDADP, + PPC_ID_VSX_XSNMADDASP, + PPC_ID_VSX_XSNMADDMDP, + PPC_ID_VSX_XSNMADDMSP, + PPC_ID_VSX_XSNMSUBADP, + PPC_ID_VSX_XSNMSUBASP, + PPC_ID_VSX_XSNMSUBMDP, + PPC_ID_VSX_XSNMSUBMSP, + PPC_ID_VSX_XSRDPI, + PPC_ID_VSX_XSRDPIC, + PPC_ID_VSX_XSRDPIM, + PPC_ID_VSX_XSRDPIP, + PPC_ID_VSX_XSRDPIZ, + PPC_ID_VSX_XSREDP, + PPC_ID_VSX_XSRESP, + PPC_ID_VSX_XSRSQRTEDP, + PPC_ID_VSX_XSRSQRTESP, + PPC_ID_VSX_XSSQRTDP, + PPC_ID_VSX_XSSQRTSP, + PPC_ID_VSX_XSSUBDP, + PPC_ID_VSX_XSSUBSP, + PPC_ID_VSX_XSTDIVDP, + PPC_ID_VSX_XSTDIVSP, + PPC_ID_VSX_XSTSQRTDP, + PPC_ID_VSX_XVABSDP, + PPC_ID_VSX_XVABSSP, + PPC_ID_VSX_XVADDDP, + PPC_ID_VSX_XVADDSP, + PPC_ID_VSX_XVCMPEQDPx, + PPC_ID_VSX_XVCMPEQSPx, + PPC_ID_VSX_XVCMPGEDPx, + PPC_ID_VSX_XVCMPGESPx, + PPC_ID_VSX_XVCMPGTDPx, + PPC_ID_VSX_XVCMPGTSPx, + PPC_ID_VSX_XVCPSGNDP, + PPC_ID_VSX_XVCPSGNSP, + PPC_ID_VSX_XVCVDPSP, + PPC_ID_VSX_XVCVDPSXDS, + PPC_ID_VSX_XVCVDPSXWS, + PPC_ID_VSX_XVCVDPUXDS, + PPC_ID_VSX_XVCVDPUXWS, + PPC_ID_VSX_XVCVSPDP, + PPC_ID_VSX_XVCVSPSXDS, + PPC_ID_VSX_XVCVSPSXWS, + PPC_ID_VSX_XVCVSPUXDS, + PPC_ID_VSX_XVCVSPUXWS, + PPC_ID_VSX_XVCVSXDDP, + PPC_ID_VSX_XVCVSXDSP, + PPC_ID_VSX_XVCVSXWDP, + PPC_ID_VSX_XVCVSXWSP, + PPC_ID_VSX_XVCVUXDDP, + PPC_ID_VSX_XVCVUXDSP, + PPC_ID_VSX_XVCVUXWDP, + PPC_ID_VSX_XVCVUXWSP, + PPC_ID_VSX_XVDIVDP, + PPC_ID_VSX_XVDIVSP, + PPC_ID_VSX_XVMADDADP, + PPC_ID_VSX_XVMADDASP, + PPC_ID_VSX_XVMADDMDP, + PPC_ID_VSX_XVMADDMSP, + PPC_ID_VSX_XVMAXDP, + PPC_ID_VSX_XVMAXSP, + PPC_ID_VSX_XVMINDP, + PPC_ID_VSX_XVMINSP, + PPC_ID_VSX_XVMOVDP, + PPC_ID_VSX_XVMOVSP, + PPC_ID_VSX_XVMSUBADP, + PPC_ID_VSX_XVMSUBASP, + PPC_ID_VSX_XVMSUBMDP, + PPC_ID_VSX_XVMSUBMSP, + PPC_ID_VSX_XVMULDP, + PPC_ID_VSX_XVMULSP, + PPC_ID_VSX_XVNABSDP, + PPC_ID_VSX_XVNABSSP, + PPC_ID_VSX_XVNMADDADP, + PPC_ID_VSX_XVNMADDASP, + PPC_ID_VSX_XVNMADDMDP, + PPC_ID_VSX_XVNMADDMSP, + PPC_ID_VSX_XVNEGDP, + PPC_ID_VSX_XVNEGSP, + PPC_ID_VSX_XVNMSUBADP, + PPC_ID_VSX_XVNMSUBASP, + PPC_ID_VSX_XVNMSUBMDP, + PPC_ID_VSX_XVNMSUBMSP, + PPC_ID_VSX_XVRDPI, + PPC_ID_VSX_XVRDPIC, + PPC_ID_VSX_XVRDPIM, + PPC_ID_VSX_XVRDPIP, + PPC_ID_VSX_XVRDPIZ, + PPC_ID_VSX_XVREDP, + PPC_ID_VSX_XVRESP, + PPC_ID_VSX_XVRSPI, + PPC_ID_VSX_XVRSPIC, + PPC_ID_VSX_XVRSPIM, + PPC_ID_VSX_XVRSPIP, + PPC_ID_VSX_XVRSPIZ, + PPC_ID_VSX_XVRSQRTEDP, + PPC_ID_VSX_XVRSQRTESP, + PPC_ID_VSX_XVSQRTDP, + PPC_ID_VSX_XVSQRTSP, + PPC_ID_VSX_XVSUBDP, + PPC_ID_VSX_XVSUBSP, + PPC_ID_VSX_XVTDIVDP, + PPC_ID_VSX_XVTDIVSP, + PPC_ID_VSX_XVTSQRTDP, + PPC_ID_VSX_XVTSQRTSP, + PPC_ID_VSX_XXLAND, + PPC_ID_VSX_XXLANDC, + PPC_ID_VSX_XXLEQV, + PPC_ID_VSX_XXLNAND, + PPC_ID_VSX_XXLNOR, + PPC_ID_VSX_XXLOR, + PPC_ID_VSX_XXLORC, + PPC_ID_VSX_XXLXOR, + PPC_ID_VSX_XXMRGHD, + PPC_ID_VSX_XXMRGHW, + PPC_ID_VSX_XXMRGLD, + PPC_ID_VSX_XXMRGLW, + PPC_ID_VSX_XXPERMDI, + PPC_ID_VSX_XXSEL, + PPC_ID_VSX_XXSLDWI, + PPC_ID_VSX_XXSPLTD, + PPC_ID_VSX_XXSPLTW, + PPC_ID_VSX_XXSWAPD, + }; + +#ifndef __cplusplus + typedef enum InstructionId InstructionId; +#endif + + struct Instruction + { + InstructionId id; + + // these acronyms are from the documentation; sometimes they + // refer to the same bit (like RC and LK) + struct { + uint32_t rc: 1; + uint32_t oe: 1; + uint32_t lk: 1; + uint32_t aa: 1; + uint32_t branchLikelyHint: 2; + } flags; + + size_t numOperands; + Operand operands[8]; + }; + +#ifndef __cplusplus + typedef struct Instruction Instruction; +#endif + + bool Decompose(Instruction* instruction, uint32_t word32, uint64_t address, uint32_t flags); + const char* GetMnemonic(const Instruction* instruction); + +#ifdef __cplusplus +} +#endif + + +#endif // DECODE_PPC_H From 35b7b2c4f8874d5f00d8801b4596cf262a2c269c Mon Sep 17 00:00:00 2001 From: noone Date: Tue, 27 Aug 2024 10:19:23 -0700 Subject: [PATCH 02/19] Fix some compiler warnings --- arch/powerpc/decode/decode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c index 1548f4b18..6accad96b 100644 --- a/arch/powerpc/decode/decode.c +++ b/arch/powerpc/decode/decode.c @@ -5870,8 +5870,8 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_BDZFLRx: return LkMnemonic(instruction, SubMnemBDZFLRx); case PPC_ID_BDZLRx: return LkHintMnemonic(instruction, SubMnemBDZLRx); case PPC_ID_BDZTx: return AaLkMnemonic(instruction, SubMnemBDZTx); - case PPC_ID_BDZTCTRx: return AaLkMnemonic(instruction, SubMnemBDZTCTRx); - case PPC_ID_BDZTLRx: return AaLkMnemonic(instruction, SubMnemBDZTLRx); + case PPC_ID_BDZTCTRx: return LkMnemonic(instruction, SubMnemBDZTCTRx); + case PPC_ID_BDZTLRx: return LkMnemonic(instruction, SubMnemBDZTLRx); case PPC_ID_BEQx: return AaLkHintMnemonic(instruction, SubMnemBEQx); case PPC_ID_BEQLRx: return LkHintMnemonic(instruction, SubMnemBEQLRx); case PPC_ID_BEQCTRx: return LkHintMnemonic(instruction, SubMnemBEQCTRx); From 9650c0fd20bb3c9459e67a44b5ae79918ca0c021 Mon Sep 17 00:00:00 2001 From: noone Date: Tue, 27 Aug 2024 10:20:21 -0700 Subject: [PATCH 03/19] Make OperandClass enum variants more unique --- arch/powerpc/decode/decode.c | 77 +++++++++++++++++++----------------- arch/powerpc/decode/decode.h | 72 +++++++++++++++++---------------- 2 files changed, 78 insertions(+), 71 deletions(-) diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c index 6accad96b..3d875c00b 100644 --- a/arch/powerpc/decode/decode.c +++ b/arch/powerpc/decode/decode.c @@ -50,14 +50,14 @@ static Register VsxVr(uint32_t value) static void PushUIMMValue(Instruction* instruction, uint32_t uimm) { - instruction->operands[instruction->numOperands].cls = UIMM; + instruction->operands[instruction->numOperands].cls = PPC_OP_UIMM; instruction->operands[instruction->numOperands].uimm = uimm; ++instruction->numOperands; } static void PushSIMMValue(Instruction* instruction, int32_t simm) { - instruction->operands[instruction->numOperands].cls = SIMM; + instruction->operands[instruction->numOperands].cls = PPC_OP_SIMM; instruction->operands[instruction->numOperands].simm = simm; ++instruction->numOperands; } @@ -76,12 +76,17 @@ static uint64_t ComputeBranchTarget(Instruction* instruction, uint64_t address, return instruction->flags.aa ? bd : address + bd; } +static void PushLabel(Instruction* instruction, uint64_t address) +{ + instruction->operands[instruction->numOperands].cls = PPC_OP_LABEL; + instruction->operands[instruction->numOperands].label = address; + ++instruction->numOperands; +} + // this assumes that instruction->flags.aa has been properly set! static void PushBranchTarget(Instruction* instruction, uint64_t address, uint32_t word32) { - instruction->operands[instruction->numOperands].cls = LABEL; - instruction->operands[instruction->numOperands].label = ComputeBranchTarget(instruction, address, word32); - ++instruction->numOperands; + PushLabel(instruction, ComputeBranchTarget(instruction, address, word32)); } static uint32_t GetA(uint32_t word32) @@ -111,7 +116,7 @@ static uint32_t GetS(uint32_t word32) static void PushRA(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_RA, Gpr(GetA(word32))); + PushRegister(instruction, PPC_OP_REG_RA, Gpr(GetA(word32))); } static void PushRAor0(Instruction* instruction, uint32_t word32) @@ -121,59 +126,59 @@ static void PushRAor0(Instruction* instruction, uint32_t word32) if (ra == 0) PushUIMMValue(instruction, 0); else - PushRegister(instruction, REG_RA, Gpr(ra)); + PushRegister(instruction, PPC_OP_REG_RA, Gpr(ra)); } static void PushRB(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_RB, Gpr(GetB(word32))); + PushRegister(instruction, PPC_OP_REG_RB, Gpr(GetB(word32))); } static void PushRD(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_RD, Gpr(GetD(word32))); + PushRegister(instruction, PPC_OP_REG_RD, Gpr(GetD(word32))); } static void PushRS(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_RS, Gpr(GetS(word32))); + PushRegister(instruction, PPC_OP_REG_RS, Gpr(GetS(word32))); } static void PushFRA(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_FRA, Fr(GetA(word32))); + PushRegister(instruction, PPC_OP_REG_FRA, Fr(GetA(word32))); } static void PushFRB(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_FRB, Fr(GetB(word32))); + PushRegister(instruction, PPC_OP_REG_FRB, Fr(GetB(word32))); } static void PushFRC(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_FRC, Fr(GetC(word32))); + PushRegister(instruction, PPC_OP_REG_FRC, Fr(GetC(word32))); } static void PushFRD(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_FRD, Fr(GetD(word32))); + PushRegister(instruction, PPC_OP_REG_FRD, Fr(GetD(word32))); } static void PushFRS(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_FRS, Fr(GetS(word32))); + PushRegister(instruction, PPC_OP_REG_FRS, Fr(GetS(word32))); } static void PushCRFD(Instruction* instruction, uint32_t word32) { uint32_t crfd = (word32 >> 23) & 0x7; - PushRegister(instruction, REG_CRFD, Crf(crfd)); + PushRegister(instruction, PPC_OP_REG_CRFD, Crf(crfd)); } static void PushCRFS(Instruction* instruction, uint32_t word32) { uint32_t crfs = (word32 >> 18) & 0x7; - PushRegister(instruction, REG_CRFS, Crf(crfs)); + PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crfs)); } static void PushCRFDImplyCR0(Instruction* instruction, uint32_t word32) @@ -181,22 +186,22 @@ static void PushCRFDImplyCR0(Instruction* instruction, uint32_t word32) uint32_t crfd = (word32 >> 23) & 0x7; if (crfd) - PushRegister(instruction, REG_CRFD, Crf(crfd)); + PushRegister(instruction, PPC_OP_REG_CRFD, Crf(crfd)); } static void PushCRBitA(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_CRBA, Crbit(GetA(word32))); + PushRegister(instruction, PPC_OP_REG_CRBA, Crbit(GetA(word32))); } static void PushCRBitB(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_CRBB, Crbit(GetB(word32))); + PushRegister(instruction, PPC_OP_REG_CRBB, Crbit(GetB(word32))); } static void PushCRBitD(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, REG_CRBD, Crbit(GetD(word32))); + PushRegister(instruction, PPC_OP_REG_CRBD, Crbit(GetD(word32))); } static void PushMem(Instruction* instruction, OperandClass cls, Register reg, int32_t offset) @@ -247,7 +252,7 @@ static void FillBranchLikelyHint(Instruction* instruction, uint32_t word32) static void PushMemRA(Instruction* instruction, uint32_t word32) { int32_t offset = (int32_t)((int16_t)(word32 & 0xffff)); - PushMem(instruction, MEM_RA, Gpr(GetA(word32)), offset); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), offset); } static uint32_t GetVsxA(uint32_t word32) @@ -261,7 +266,7 @@ static uint32_t GetVsxA(uint32_t word32) static void PushVsxA(Instruction* instruction, uint32_t word32, VsxWidth width) { PushRegister(instruction, - width == VSX_WIDTH_FULL ? REG_VSX_RA : REG_VSX_RA_DWORD0, + width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RA : PPC_OP_REG_VSX_RA_DWORD0, VsxVr(GetVsxA(word32))); } @@ -276,7 +281,7 @@ static uint32_t GetVsxB(uint32_t word32) static void PushVsxB(Instruction* instruction, uint32_t word32, VsxWidth width) { PushRegister(instruction, - width == VSX_WIDTH_FULL ? REG_VSX_RB : REG_VSX_RB_DWORD0, + width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RB : PPC_OP_REG_VSX_RB_DWORD0, VsxVr(GetVsxB(word32))); } @@ -291,7 +296,7 @@ static uint32_t GetVsxC(uint32_t word32) static void PushVsxC(Instruction* instruction, uint32_t word32, VsxWidth width) { PushRegister(instruction, - width == VSX_WIDTH_FULL ? REG_VSX_RC : REG_VSX_RC_DWORD0, + width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RC : PPC_OP_REG_VSX_RC_DWORD0, VsxVr(GetVsxC(word32))); } @@ -306,7 +311,7 @@ static uint32_t GetVsxD(uint32_t word32) static void PushVsxD(Instruction* instruction, uint32_t word32, VsxWidth width) { PushRegister(instruction, - width == VSX_WIDTH_FULL ? REG_VSX_RD : REG_VSX_RD_DWORD0, + width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RD : PPC_OP_REG_VSX_RD_DWORD0, VsxVr(GetVsxD(word32))); } @@ -315,7 +320,7 @@ static void PushVsxS(Instruction* instruction, uint32_t word32, VsxWidth width) uint32_t sx = word32 & 0x1; uint32_t s = (word32 >> 21) & 0x1f; PushRegister(instruction, - width == VSX_WIDTH_FULL ? REG_VSX_RS : REG_VSX_RS_DWORD0, + width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RS : PPC_OP_REG_VSX_RS_DWORD0, VsxVr((sx << 5) | s)); } @@ -362,31 +367,31 @@ static uint32_t GetMX64(uint32_t word32) static void PushAltivecVA(Instruction* instruction, uint32_t word32) { uint32_t va = (word32 >> 16) & 0x1f; - PushRegister(instruction, REG_AV_VA, AltivecVr(va)); + PushRegister(instruction, PPC_OP_REG_AV_VA, AltivecVr(va)); } static void PushAltivecVB(Instruction* instruction, uint32_t word32) { uint32_t vb = (word32 >> 11) & 0x1f; - PushRegister(instruction, REG_AV_VB, AltivecVr(vb)); + PushRegister(instruction, PPC_OP_REG_AV_VB, AltivecVr(vb)); } static void PushAltivecVC(Instruction* instruction, uint32_t word32) { uint32_t vc = (word32 >> 6) & 0x1f; - PushRegister(instruction, REG_AV_VC, AltivecVr(vc)); + PushRegister(instruction, PPC_OP_REG_AV_VC, AltivecVr(vc)); } static void PushAltivecVD(Instruction* instruction, uint32_t word32) { uint32_t vd = (word32 >> 21) & 0x1f; - PushRegister(instruction, REG_AV_VD, AltivecVr(vd)); + PushRegister(instruction, PPC_OP_REG_AV_VD, AltivecVr(vd)); } static void PushAltivecVS(Instruction* instruction, uint32_t word32) { uint32_t vs = (word32 >> 21) & 0x1f; - PushRegister(instruction, REG_AV_VS, AltivecVr(vs)); + PushRegister(instruction, PPC_OP_REG_AV_VS, AltivecVr(vs)); } static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) @@ -4131,7 +4136,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add FillBranchLikelyHint(instruction, word32); if (crn != 0) - PushRegister(instruction, REG_CRFS, Crf(crn)); + PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crn)); PushBranchTarget(instruction, address, word32); break; @@ -4193,7 +4198,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add FillBranchLikelyHint(instruction, word32); if (crn != 0) - PushRegister(instruction, REG_CRFS, Crf(crn)); + PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crn)); break; } @@ -4349,7 +4354,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushRD(instruction, word32); int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); - PushMem(instruction, MEM_RA, Gpr(GetA(word32)), ds); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); break; } @@ -4400,7 +4405,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushRS(instruction, word32); int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); - PushMem(instruction, MEM_RA, Gpr(GetA(word32)), ds); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); break; } diff --git a/arch/powerpc/decode/decode.h b/arch/powerpc/decode/decode.h index 0c85559fc..75a249b92 100644 --- a/arch/powerpc/decode/decode.h +++ b/arch/powerpc/decode/decode.h @@ -229,50 +229,52 @@ extern "C" { enum OperandClass { - NONE = 0, - UIMM, - SIMM, - LABEL, - MEM_RA, - BI, + PPC_OP_NONE = 0, + PPC_OP_UIMM, + PPC_OP_SIMM, + PPC_OP_LABEL, + PPC_OP_MEM_RA, + PPC_OP_BI, - REG_RA, - REG_RB, - REG_RD, - REG_RS, - REG_FRA, - REG_FRB, - REG_FRC, - REG_FRD, - REG_FRS, - REG_CRFD, - REG_CRFS, - REG_CRBA, - REG_CRBB, - REG_CRBD, + PPC_OP_REG_RA, + PPC_OP_REG_RB, + PPC_OP_REG_RD, + PPC_OP_REG_RS, - REG_AV_VA, - REG_AV_VB, - REG_AV_VC, - REG_AV_VD, - REG_AV_VS, + PPC_OP_REG_FRA, + PPC_OP_REG_FRB, + PPC_OP_REG_FRC, + PPC_OP_REG_FRD, + PPC_OP_REG_FRS, + + PPC_OP_REG_CRFD, + PPC_OP_REG_CRFS, + PPC_OP_REG_CRBA, + PPC_OP_REG_CRBB, + PPC_OP_REG_CRBD, + + PPC_OP_REG_AV_VA, + PPC_OP_REG_AV_VB, + PPC_OP_REG_AV_VC, + PPC_OP_REG_AV_VD, + PPC_OP_REG_AV_VS, // DWORD0 means that only the 0th dword is affected, which // has an overlap with floating registers - REG_VSX_RA, - REG_VSX_RA_DWORD0, + PPC_OP_REG_VSX_RA, + PPC_OP_REG_VSX_RA_DWORD0, - REG_VSX_RB, - REG_VSX_RB_DWORD0, + PPC_OP_REG_VSX_RB, + PPC_OP_REG_VSX_RB_DWORD0, - REG_VSX_RC, - REG_VSX_RC_DWORD0, + PPC_OP_REG_VSX_RC, + PPC_OP_REG_VSX_RC_DWORD0, - REG_VSX_RD, - REG_VSX_RD_DWORD0, + PPC_OP_REG_VSX_RD, + PPC_OP_REG_VSX_RD_DWORD0, - REG_VSX_RS, - REG_VSX_RS_DWORD0, + PPC_OP_REG_VSX_RS, + PPC_OP_REG_VSX_RS_DWORD0, }; #ifndef __cplusplus From 55c12e83b333fc29f5f1ac544346121297d54def Mon Sep 17 00:00:00 2001 From: noone Date: Tue, 27 Aug 2024 10:21:02 -0700 Subject: [PATCH 04/19] Add common useful registers Decoding instructions don't need these, but it's useful for the architecture plugin. --- arch/powerpc/decode/decode.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/powerpc/decode/decode.h b/arch/powerpc/decode/decode.h index 75a249b92..277829c1a 100644 --- a/arch/powerpc/decode/decode.h +++ b/arch/powerpc/decode/decode.h @@ -47,6 +47,10 @@ extern "C" { NUPPC_REG_GPR30, NUPPC_REG_GPR31, + NUPPC_REG_XER, + NUPPC_REG_LR, + NUPPC_REG_CTR, + NUPPC_REG_FR0, NUPPC_REG_FR1, NUPPC_REG_FR2, From 8418d417dbd6d29c56d530ed2253ebd1cb773aff Mon Sep 17 00:00:00 2001 From: noone Date: Mon, 2 Sep 2024 16:27:18 -0700 Subject: [PATCH 05/19] Rework branches We take a divergence from capstone: instead of treating every single branch pseudo-op as its own distinct instruction ID, we just group all of the BCx, BCLRx, and BCCTRx in a group, and just change the mnemonic depending on the value of BI and BO. This will drastically simplify the arch plugin for things like getting instruction info and lifting. --- arch/powerpc/decode/decode.c | 766 +++++++++++++++++++---------------- arch/powerpc/decode/decode.h | 63 +-- 2 files changed, 422 insertions(+), 407 deletions(-) diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c index 3d875c00b..7db2371d7 100644 --- a/arch/powerpc/decode/decode.c +++ b/arch/powerpc/decode/decode.c @@ -18,6 +18,11 @@ static int32_t sign_extend(uint32_t x, unsigned numBits) return (x ^ m) - m; } +static void CopyOperand(Operand* dst, const Operand* src) +{ + memcpy(dst, src, sizeof *dst); +} + static Register Gpr(uint32_t value) { return NUPPC_REG_GPR0 + value; @@ -1057,79 +1062,12 @@ static InstructionId Decode0x13(uint32_t word32, uint32_t decodeFlags) case 0x020: case 0x021: - { // for PowerPC, this is 0x0000f800, but POWER // introduces BH bits if ((word32 & 0x0000e000) != 0) return PPC_ID_INVALID; - // these are the only values that capstone recognizes - // as BLR/BLRL - if ((word32 & 0xfffffffe) == 0x4e800020) - return PPC_ID_BLRx; - - uint32_t bo = GetBO(word32); - uint32_t bi = GetBI(word32); - - // mask away the "y" bit - switch (bo & 0x1e) - { - case 0: return PPC_ID_BDNZFLRx; - case 2: return PPC_ID_BDZFLRx; - - case 4: - case 6: - switch (bi & 0x3) - { - case 0: return PPC_ID_BGELRx; - case 1: return PPC_ID_BLELRx; - case 2: return PPC_ID_BNELRx; - case 3: return PPC_ID_BNSLRx; - - // should be unreachable - default: return PPC_ID_BFLRx; - } - - case 8: return PPC_ID_BDNZTLRx; - case 10: return PPC_ID_BDZTLRx; - - case 12: - case 14: - switch (bi & 0x3) - { - case 0: return PPC_ID_BLTLRx; - case 1: return PPC_ID_BGTLRx; - case 2: return PPC_ID_BEQLRx; - case 3: return PPC_ID_BSOLRx; - - // should be unreachable - default: return PPC_ID_BTLRx; - } - - // technically these aren't terribly well defined - // when BI != 0, since these BOs don't involve - // a condition bit to test in BI to test against - case 16: - case 24: - return PPC_ID_BDNZLRx; - - case 18: - case 26: - return PPC_ID_BDZLRx; - - // these are to match capstone's behavior, but - // not super sure why since they seem to match - // the "Branch always" part of the BO table - case 20: - case 28: - return PPC_ID_BDNZLRx; - case 22: - case 30: - return PPC_ID_BDZLRx; - - default: return PPC_ID_BCLRx; - } - } + return PPC_ID_BCLRx; case 0x024: if ((word32 & 0x03fff800) != 0) @@ -1205,79 +1143,16 @@ static InstructionId Decode0x13(uint32_t word32, uint32_t decodeFlags) case 0x420: case 0x421: + // TODO: return invalid when BO[2] == 0 (ie when & 0x00800000 == 0) + // keeping it in makes it easier to compare against capstone + // for now + // for PowerPC, this is 0x0000f800, but POWER // introduces BH bits if ((word32 & 0x0000e000) != 0) return PPC_ID_INVALID; - // these are the only values that capstone recognizes - // as BLR/BLRL - if ((word32 & 0xfffffffe) == 0x4e800420) - return PPC_ID_BCTRx; - - uint32_t bo = GetBO(word32); - uint32_t bi = GetBI(word32); - - // mask away the "y" bit - switch (bo & 0x1e) - { - case 0: return PPC_ID_BDNZFCTRx; - case 2: return PPC_ID_BDZFCTRx; - - case 4: - case 6: - switch (bi & 0x3) - { - case 0: return PPC_ID_BGECTRx; - case 1: return PPC_ID_BLECTRx; - case 2: return PPC_ID_BNECTRx; - case 3: return PPC_ID_BNSCTRx; - - // should be unreachable - default: return PPC_ID_BFCTRx; - } - - case 8: return PPC_ID_BDNZTCTRx; - case 10: return PPC_ID_BDZTCTRx; - - case 12: - case 14: - switch (bi & 0x3) - { - case 0: return PPC_ID_BLTCTRx; - case 1: return PPC_ID_BGTCTRx; - case 2: return PPC_ID_BEQCTRx; - case 3: return PPC_ID_BSOCTRx; - - // should be unreachable - default: return PPC_ID_BTCTRx; - } - - // technically these aren't terribly well defined - // when BI != 0, since these BOs don't involve - // a condition bit to test in BI to test against - case 16: - case 24: - return PPC_ID_BDNZCTRx; - - // these represent "branch always" in the BO field, so it's - // not super clear why these disassemble to bdnzctr - case 20: - case 28: - return PPC_ID_BDNZCTRx; - - case 18: - case 22: - case 26: - return PPC_ID_BDZCTRx; - - // these represent "branch always" in the BO field, so it's - // not super clear why these disassemble to bdzctr - case 30: - return PPC_ID_BDZCTRx; - - default: return PPC_ID_BCCTRx; - } + return PPC_ID_BCCTRx; default: return PPC_ID_INVALID; @@ -3607,71 +3482,7 @@ static InstructionId Decode(uint32_t word32, uint32_t decodeFlags) return PPC_ID_ADDIS; case 0x10: - { - uint32_t bo = GetBO(word32); - uint32_t bi = GetBI(word32); - - // mask away the "y" bit - switch (bo & 0x1e) - { - case 0: return PPC_ID_BDNZFx; - case 2: return PPC_ID_BDZFx; - - case 4: - case 6: - switch (bi & 0x3) - { - case 0: return PPC_ID_BGEx; - case 1: return PPC_ID_BLEx; - case 2: return PPC_ID_BNEx; - case 3: return PPC_ID_BNSx; - - // should be unreachable - default: return PPC_ID_BFx; - } - - case 8: return PPC_ID_BDNZTx; - case 10: return PPC_ID_BDZTx; - - case 12: - case 14: - switch (bi & 0x3) - { - case 0: return PPC_ID_BLTx; - case 1: return PPC_ID_BGTx; - case 2: return PPC_ID_BEQx; - case 3: return PPC_ID_BSOx; - - // should be unreachable - default: return PPC_ID_BTx; - } - - // technically these aren't terribly well defined - // when BI != 0, since these BOs don't involve - // a condition bit to test in BI to test against - case 16: - case 24: - return PPC_ID_BDNZx; - - // these represent "branch always" in the BO field, so it's - // not super clear why these disassemble to bdnz - case 20: - case 28: - return PPC_ID_BDNZx; - - case 18: - case 22: - case 26: - return PPC_ID_BDZx; - - // these represent "branch always" in the BO field, so it's - // not super clear why these disassemble to bdz - case 30: - return PPC_ID_BDZx; - - default: return PPC_ID_BCx; - } - } + return PPC_ID_BCx; case 0x11: if ((word32 & 0x03fff01f) != 2) @@ -4096,109 +3907,13 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add instruction->flags.lk = word32 & 0x1; instruction->flags.aa = (word32 & 0x2) != 0; - PushUIMMValue(instruction, bo); - PushUIMMValue(instruction, bi); - PushBranchTarget(instruction, address, word32); - - break; - } - - case PPC_ID_BDNZFx: - case PPC_ID_BDNZTx: - case PPC_ID_BDZFx: - case PPC_ID_BDZTx: - case PPC_ID_BFx: - case PPC_ID_BTx: - { - uint32_t bi = GetBI(word32); - - instruction->flags.lk = word32 & 0x1; - instruction->flags.aa = (word32 & 0x2) != 0; - - PushUIMMValue(instruction, bi); - PushBranchTarget(instruction, address, word32); - break; - } - - case PPC_ID_BEQx: - case PPC_ID_BGEx: - case PPC_ID_BGTx: - case PPC_ID_BLEx: - case PPC_ID_BLTx: - case PPC_ID_BNEx: - case PPC_ID_BNSx: - case PPC_ID_BSOx: - { - uint32_t crn = GetBI(word32) >> 2; - - instruction->flags.lk = word32 & 0x1; - instruction->flags.aa = (word32 & 0x2) != 0; - FillBranchLikelyHint(instruction, word32); - - if (crn != 0) - PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crn)); - - PushBranchTarget(instruction, address, word32); - break; - } - - case PPC_ID_BDZx: - case PPC_ID_BDNZx: - instruction->flags.lk = word32 & 0x1; - instruction->flags.aa = (word32 & 0x2) != 0; + // not all BCx have hints, but if they don't, then those + // hints won't be read by anything anyways FillBranchLikelyHint(instruction, word32); + PushUIMMValue(instruction, bo); + PushUIMMValue(instruction, bi); PushBranchTarget(instruction, address, word32); - break; - - case PPC_ID_BDNZFCTRx: - case PPC_ID_BDNZFLRx: - case PPC_ID_BDNZTCTRx: - case PPC_ID_BDNZTLRx: - case PPC_ID_BDZFCTRx: - case PPC_ID_BDZFLRx: - case PPC_ID_BDZTCTRx: - case PPC_ID_BDZTLRx: - instruction->flags.lk = word32 & 0x1; - - PushUIMMValue(instruction, GetBI(word32)); - break; - - case PPC_ID_BCTRx: - case PPC_ID_BDNZCTRx: - case PPC_ID_BDNZLRx: - case PPC_ID_BDZCTRx: - case PPC_ID_BDZLRx: - case PPC_ID_BLRx: - // these don't test any conditions, so no operands - instruction->flags.lk = word32 & 0x1; - FillBranchLikelyHint(instruction, word32); - break; - - case PPC_ID_BEQCTRx: - case PPC_ID_BEQLRx: - case PPC_ID_BGECTRx: - case PPC_ID_BGELRx: - case PPC_ID_BGTCTRx: - case PPC_ID_BGTLRx: - case PPC_ID_BLECTRx: - case PPC_ID_BLELRx: - case PPC_ID_BLTCTRx: - case PPC_ID_BLTLRx: - case PPC_ID_BNECTRx: - case PPC_ID_BNELRx: - case PPC_ID_BNSCTRx: - case PPC_ID_BNSLRx: - case PPC_ID_BSOCTRx: - case PPC_ID_BSOLRx: - { - uint32_t crn = GetBI(word32) >> 2; - - instruction->flags.lk = word32 & 0x1; - FillBranchLikelyHint(instruction, word32); - - if (crn != 0) - PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crn)); break; } @@ -4517,7 +4232,13 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add // conditional branches to registers case PPC_ID_BCLRx: case PPC_ID_BCCTRx: - // TODO BO, BI + // not all BCx have hints, but if they don't, then those + // hints won't be read by anything anyways + FillBranchLikelyHint(instruction, word32); + + PushUIMMValue(instruction, GetBO(word32)); + PushUIMMValue(instruction, GetBI(word32)); + instruction->flags.lk = word32 & 0x1; break; @@ -5627,23 +5348,17 @@ DEFINE_SUBMNEM_LK(SubMnemBCTRx, "bctr") DEFINE_SUBMNEM_LK(SubMnemBCCTRx, "bcctr") DEFINE_SUBMNEM_LK(SubMnemBCLRx, "bclr") DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBDZx, "bdz") -DEFINE_SUBMNEM_LK_HINT(SubMnemBDZCTRx, "bdzctr") DEFINE_SUBMNEM_LK_HINT(SubMnemBDZLRx, "bdzlr") DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBDNZx, "bdnz") -DEFINE_SUBMNEM_LK_HINT(SubMnemBDNZCTRx, "bdnzctr") DEFINE_SUBMNEM_LK_HINT(SubMnemBDNZLRx, "bdnzlr") DEFINE_SUBMNEM_AA_LK(SubMnemBDNZFx, "bdnzf") -DEFINE_SUBMNEM_LK(SubMnemBDNZFCTRx, "bdnzfctr") DEFINE_SUBMNEM_LK(SubMnemBDNZFLRx, "bdnzflr") DEFINE_SUBMNEM_AA_LK(SubMnemBDNZTx, "bdnzt") -DEFINE_SUBMNEM_LK(SubMnemBDNZTCTRx, "bdnztctr") DEFINE_SUBMNEM_LK(SubMnemBDNZTLRx, "bdnztlr") DEFINE_SUBMNEM_AA_LK(SubMnemBDZFx, "bdzf") -DEFINE_SUBMNEM_LK(SubMnemBDZFCTRx, "bdzfctr") DEFINE_SUBMNEM_LK(SubMnemBDZFLRx, "bdzflr") DEFINE_SUBMNEM_LK(SubMnemBDFLRx, "bdzlr") DEFINE_SUBMNEM_AA_LK(SubMnemBDZTx, "bdzt") -DEFINE_SUBMNEM_LK(SubMnemBDZTCTRx, "bdztctr") DEFINE_SUBMNEM_LK(SubMnemBDZTLRx, "bdztlr") DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBEQx, "beq") DEFINE_SUBMNEM_LK_HINT(SubMnemBEQCTRx, "beqctr") @@ -5835,6 +5550,163 @@ static const char* AaLkHintMnemonic(const Instruction* instruction, const char* return names[4*instruction->flags.branchLikelyHint + 2*instruction->flags.aa + instruction->flags.lk]; } +void FillBcxOperands(OperandsList* bcx, const Instruction* instruction) +{ + memset(bcx, 0, sizeof *bcx); + + if (instruction->id != PPC_ID_BCx) + return; + + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + switch (bo & 0x1e) + { + // copy BI, target + case 0: + case 2: + case 8: + case 10: + CopyOperand(&bcx->operands[0], &instruction->operands[1]); + CopyOperand(&bcx->operands[1], &instruction->operands[2]); + bcx->numOperands = 2; + break; + + // copy BI, target + case 4: + case 6: + case 12: + case 14: + { + uint32_t crn = bi >> 2; + + bcx->operands[0].cls = PPC_OP_REG_CRFS; + bcx->operands[0].reg = Crf(crn); + CopyOperand(&bcx->operands[1], &instruction->operands[2]); + bcx->numOperands = 2; + break; + } + + // just copy target + case 16: + case 18: + case 20: + case 22: + case 24: + case 26: + case 28: + case 30: + CopyOperand(&bcx->operands[0], &instruction->operands[2]); + bcx->numOperands = 1; + break; + + // copy BO, BI, target + default: + CopyOperand(&bcx->operands[0], &instruction->operands[0]); + CopyOperand(&bcx->operands[1], &instruction->operands[1]); + CopyOperand(&bcx->operands[2], &instruction->operands[2]); + bcx->numOperands = 3; + + break; + } +} + +void FillBcctrxOperands(OperandsList* bcctrx, const Instruction* instruction) +{ + memset(bcctrx, 0, sizeof *bcctrx); + + if (instruction->id != PPC_ID_BCCTRx) + return; + + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + switch (bo & 0x1e) + { + // copy BI --> crn + case 4: + case 6: + case 12: + case 14: + { + uint32_t crn = bi >> 2; + + bcctrx->operands[0].cls = PPC_OP_REG_CRFS; + bcctrx->operands[0].reg = Crf(crn); + bcctrx->numOperands = 1; + break; + } + + // no ops (BCTR, BCTRL) + case 20: + break; + + // copy BO, BI + default: + CopyOperand(&bcctrx->operands[0], &instruction->operands[0]); + CopyOperand(&bcctrx->operands[1], &instruction->operands[1]); + bcctrx->numOperands = 2; + + break; + } + +} + +void FillBclrxOperands(OperandsList* bclrx, const Instruction* instruction) +{ + memset(bclrx, 0, sizeof *bclrx); + + if (instruction->id != PPC_ID_BCLRx) + return; + + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + switch (bo & 0x1e) + { + // copy BI + case 0: + case 2: + case 8: + case 10: + CopyOperand(&bclrx->operands[0], &instruction->operands[1]); + bclrx->numOperands = 1; + break; + + // copy BI --> crn + case 4: + case 6: + case 12: + case 14: + { + uint32_t crn = bi >> 2; + + bclrx->operands[0].cls = PPC_OP_REG_CRFS; + bclrx->operands[0].reg = Crf(crn); + bclrx->numOperands = 1; + break; + } + + // no ops (decrement CTR, compare to 0, but no condition check) + case 16: + case 18: + case 24: + case 26: + + // no ops (BLR, BLRL) + case 20: + break; + + // copy BO, BI + default: + CopyOperand(&bclrx->operands[0], &instruction->operands[0]); + CopyOperand(&bclrx->operands[1], &instruction->operands[1]); + bclrx->numOperands = 2; + + break; + } +} + const char* GetMnemonic(const Instruction* instruction) { unsigned int index; @@ -5855,55 +5727,235 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_ANDIS: return "andis."; case PPC_ID_ATTN: return "attn"; case PPC_ID_Bx: return AaLkMnemonic(instruction, SubMnemBx); - case PPC_ID_BCx: return AaLkMnemonic(instruction, SubMnemBCx); - case PPC_ID_BCTRx: return LkMnemonic(instruction, SubMnemBCTRx); - case PPC_ID_BCCTRx: return LkMnemonic(instruction, SubMnemBCCTRx); - case PPC_ID_BCLRx: return LkMnemonic(instruction, SubMnemBCLRx); - case PPC_ID_BDZx: return AaLkHintMnemonic(instruction, SubMnemBDZx); - case PPC_ID_BDZCTRx: return LkHintMnemonic(instruction, SubMnemBDZCTRx); - case PPC_ID_BDNZx: return AaLkHintMnemonic(instruction, SubMnemBDNZx); - case PPC_ID_BDNZCTRx: return LkHintMnemonic(instruction, SubMnemBDNZCTRx); - case PPC_ID_BDNZLRx: return LkHintMnemonic(instruction, SubMnemBDNZLRx); - case PPC_ID_BDNZFx: return AaLkMnemonic(instruction, SubMnemBDNZFx); - case PPC_ID_BDNZFCTRx: return LkMnemonic(instruction, SubMnemBDNZFCTRx); - case PPC_ID_BDNZFLRx: return LkMnemonic(instruction, SubMnemBDNZFLRx); - case PPC_ID_BDNZTx: return AaLkMnemonic(instruction, SubMnemBDNZTx); - case PPC_ID_BDNZTCTRx: return LkMnemonic(instruction, SubMnemBDNZTCTRx); - case PPC_ID_BDNZTLRx: return LkMnemonic(instruction, SubMnemBDNZTLRx); - case PPC_ID_BDZFx: return AaLkMnemonic(instruction, SubMnemBDZFx); - case PPC_ID_BDZFCTRx: return LkMnemonic(instruction, SubMnemBDZFCTRx); - case PPC_ID_BDZFLRx: return LkMnemonic(instruction, SubMnemBDZFLRx); - case PPC_ID_BDZLRx: return LkHintMnemonic(instruction, SubMnemBDZLRx); - case PPC_ID_BDZTx: return AaLkMnemonic(instruction, SubMnemBDZTx); - case PPC_ID_BDZTCTRx: return LkMnemonic(instruction, SubMnemBDZTCTRx); - case PPC_ID_BDZTLRx: return LkMnemonic(instruction, SubMnemBDZTLRx); - case PPC_ID_BEQx: return AaLkHintMnemonic(instruction, SubMnemBEQx); - case PPC_ID_BEQLRx: return LkHintMnemonic(instruction, SubMnemBEQLRx); - case PPC_ID_BEQCTRx: return LkHintMnemonic(instruction, SubMnemBEQCTRx); - case PPC_ID_BFx: return AaLkMnemonic(instruction, SubMnemBFx); - case PPC_ID_BGEx: return AaLkHintMnemonic(instruction, SubMnemBGEx); - case PPC_ID_BGECTRx: return LkHintMnemonic(instruction, SubMnemBGECTRx); - case PPC_ID_BGELRx: return LkHintMnemonic(instruction, SubMnemBGELRx); - case PPC_ID_BGTx: return AaLkHintMnemonic(instruction, SubMnemBGTx); - case PPC_ID_BGTCTRx: return LkHintMnemonic(instruction, SubMnemBGTCTRx); - case PPC_ID_BGTLRx: return LkHintMnemonic(instruction, SubMnemBGTLRx); - case PPC_ID_BLEx: return AaLkHintMnemonic(instruction, SubMnemBLEx); - case PPC_ID_BLECTRx: return LkHintMnemonic(instruction, SubMnemBLECTRx); - case PPC_ID_BLELRx: return LkHintMnemonic(instruction, SubMnemBLELRx); - case PPC_ID_BLTx: return AaLkHintMnemonic(instruction, SubMnemBLTx); - case PPC_ID_BLTCTRx: return LkHintMnemonic(instruction, SubMnemBLTCTRx); - case PPC_ID_BLTLRx: return LkHintMnemonic(instruction, SubMnemBLTLRx); - case PPC_ID_BLRx: return LkHintMnemonic(instruction, SubMnemBLRx); - case PPC_ID_BNEx: return AaLkHintMnemonic(instruction, SubMnemBNEx); - case PPC_ID_BNECTRx: return LkHintMnemonic(instruction, SubMnemBNECTRx); - case PPC_ID_BNELRx: return LkHintMnemonic(instruction, SubMnemBNELRx); - case PPC_ID_BNSx: return AaLkHintMnemonic(instruction, SubMnemBNSx); - case PPC_ID_BNSCTRx: return LkHintMnemonic(instruction, SubMnemBNSCTRx); - case PPC_ID_BNSLRx: return LkHintMnemonic(instruction, SubMnemBNSLRx); - case PPC_ID_BSOx: return AaLkHintMnemonic(instruction, SubMnemBSOx); - case PPC_ID_BSOCTRx: return LkHintMnemonic(instruction, SubMnemBSOCTRx); - case PPC_ID_BSOLRx: return LkHintMnemonic(instruction, SubMnemBSOLRx); - case PPC_ID_BTx: return AaLkMnemonic(instruction, SubMnemBTx); + case PPC_ID_BCx: + { + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + const char** mnemonics = NULL; + const char** mnemonicsHint = NULL; + + // mask away the "y" bit + switch (bo & 0x1e) + { + case 0: + mnemonics = SubMnemBDNZFx; + break; + + case 2: + mnemonics = SubMnemBDZFx; + break; + + case 4: + case 6: + switch (bi & 0x3) + { + case 0: + mnemonicsHint = SubMnemBGEx; + break; + case 1: + mnemonicsHint = SubMnemBLEx; + break; + case 2: + mnemonicsHint = SubMnemBNEx; + break; + case 3: + mnemonicsHint = SubMnemBNSx; + break; + + // should be unreachable + default: + return NULL; + } + + break; + + case 8: + mnemonics = SubMnemBDNZTx; + break; + + case 10: + mnemonics = SubMnemBDZTx; + break; + + case 12: + case 14: + switch (bi & 0x3) + { + case 0: + mnemonicsHint = SubMnemBLTx; + break; + + case 1: + mnemonicsHint = SubMnemBGTx; + break; + + case 2: + mnemonicsHint = SubMnemBEQx; + break; + + case 3: + mnemonicsHint = SubMnemBSOx; + break; + + // should be unreachable + default: + return NULL; + } + break; + + // technically these aren't terribly well defined + // when BI != 0, since these BOs don't involve + // a condition bit to test in BI to test against + case 16: + case 24: + mnemonicsHint = SubMnemBDNZx; + break; + + // these represent "branch always" in the BO field, so it's + // not super clear why these disassemble to bdnz + case 20: + case 28: + mnemonicsHint = SubMnemBDNZx; + break; + + case 18: + case 22: + case 26: + mnemonicsHint = SubMnemBDZx; + break; + + // these represent "branch always" in the BO field, so it's + // not super clear why these disassemble to bdz + case 30: + mnemonicsHint = SubMnemBDZx; + break; + + default: + mnemonics = SubMnemBCx; + } + + if (mnemonicsHint) + return AaLkHintMnemonic(instruction, mnemonicsHint); + + if (mnemonics) + return AaLkMnemonic(instruction, mnemonics); + + // should be unreachable + return NULL; + } + + case PPC_ID_BCCTRx: + { + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + // mask away the "y" bit + switch (bo & 0x1e) + { + case 4: + case 6: + switch (bi & 0x3) + { + case 0: return LkHintMnemonic(instruction, SubMnemBGECTRx); + case 1: return LkHintMnemonic(instruction, SubMnemBLECTRx); + case 2: return LkHintMnemonic(instruction, SubMnemBNECTRx); + case 3: return LkHintMnemonic(instruction, SubMnemBNSCTRx); + + // should be unreachable + default: return NULL; + } + + break; + + case 12: + case 14: + switch (bi & 0x3) + { + case 0: return LkHintMnemonic(instruction, SubMnemBLTCTRx); + case 1: return LkHintMnemonic(instruction, SubMnemBGTCTRx); + case 2: return LkHintMnemonic(instruction, SubMnemBEQCTRx); + case 3: return LkHintMnemonic(instruction, SubMnemBSOCTRx); + + // should be unreachable + default: return NULL; + } + + break; + + case 20: + return LkMnemonic(instruction, SubMnemBCTRx); + + default: + return LkMnemonic(instruction, SubMnemBCCTRx); + } + } + + case PPC_ID_BCLRx: + { + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + // mask away the "y" bit + switch (bo & 0x1e) + { + case 0: + return LkMnemonic(instruction, SubMnemBDNZFLRx); + + case 2: + return LkMnemonic(instruction, SubMnemBDZFLRx); + + case 4: + case 6: + switch (bi & 0x3) + { + case 0: return LkHintMnemonic(instruction, SubMnemBGELRx); + case 1: return LkHintMnemonic(instruction, SubMnemBLELRx); + case 2: return LkHintMnemonic(instruction, SubMnemBNELRx); + case 3: return LkHintMnemonic(instruction, SubMnemBNSLRx); + + // should be unreachable + default: return NULL; + } + + case 8: + return LkMnemonic(instruction, SubMnemBDNZTLRx); + + case 10: + return LkMnemonic(instruction, SubMnemBDZTLRx); + + case 12: + case 14: + switch (bi & 0x3) + { + case 0: return LkHintMnemonic(instruction, SubMnemBLTLRx); + case 1: return LkHintMnemonic(instruction, SubMnemBGTLRx); + case 2: return LkHintMnemonic(instruction, SubMnemBEQLRx); + case 3: return LkHintMnemonic(instruction, SubMnemBSOLRx); + + // should be unreachable + default: return NULL; + } + + // technically these aren't terribly well defined + // when BI != 0, since these BOs don't involve + // a condition bit to test in BI to test against + case 16: + case 24: + return LkHintMnemonic(instruction, SubMnemBDNZLRx); + + case 18: + case 26: + return LkHintMnemonic(instruction, SubMnemBDZLRx); + + case 20: + return LkHintMnemonic(instruction, SubMnemBLRx); + + default: + return LkMnemonic(instruction, SubMnemBCLRx); + } + } + case PPC_ID_CLRLDIx: return RcMnemonic(instruction, SubMnemCLRLDIx); case PPC_ID_CLRLWIx: return RcMnemonic(instruction, SubMnemCLRLWIx); case PPC_ID_CLRRWIx: return RcMnemonic(instruction, SubMnemCLRRWIx); diff --git a/arch/powerpc/decode/decode.h b/arch/powerpc/decode/decode.h index 277829c1a..a235f48d7 100644 --- a/arch/powerpc/decode/decode.h +++ b/arch/powerpc/decode/decode.h @@ -321,6 +321,16 @@ extern "C" { typedef struct Operand Operand; #endif + struct OperandsList + { + size_t numOperands; + Operand operands[8]; + }; + +#ifndef __cplusplus + typedef struct OperandsList OperandsList; +#endif + // trailing lowercase 'x' indicates potential other mnemonics (rc, oe, lk, // etc. bits) enum InstructionId @@ -344,56 +354,6 @@ extern "C" { PPC_ID_BCx, PPC_ID_BCCTRx, PPC_ID_BCLRx, - PPC_ID_BCTRx, - PPC_ID_BDZx, - PPC_ID_BDZCTRx, - PPC_ID_BDZLRx, - PPC_ID_BDNZx, - PPC_ID_BDNZCTRx, - PPC_ID_BDNZLRx, - PPC_ID_BDNZFx, - PPC_ID_BDNZFCTRx, - PPC_ID_BDNZFLRx, - PPC_ID_BDNZTx, - PPC_ID_BDNZTCTRx, - PPC_ID_BDNZTLRx, - PPC_ID_BDZFx, - PPC_ID_BDZFCTRx, - PPC_ID_BDZFLRx, - PPC_ID_BDZTx, - PPC_ID_BDZTCTRx, - PPC_ID_BDZTLRx, - PPC_ID_BEQx, - PPC_ID_BEQCTRx, - PPC_ID_BEQLRx, - PPC_ID_BFx, - PPC_ID_BFCTRx, - PPC_ID_BFLRx, - PPC_ID_BGEx, - PPC_ID_BGECTRx, - PPC_ID_BGELRx, - PPC_ID_BGTx, - PPC_ID_BGTCTRx, - PPC_ID_BGTLRx, - PPC_ID_BLEx, - PPC_ID_BLECTRx, - PPC_ID_BLELRx, - PPC_ID_BLTx, - PPC_ID_BLTCTRx, - PPC_ID_BLTLRx, - PPC_ID_BLRx, - PPC_ID_BNEx, - PPC_ID_BNECTRx, - PPC_ID_BNELRx, - PPC_ID_BNSx, - PPC_ID_BNSCTRx, - PPC_ID_BNSLRx, - PPC_ID_BSOx, - PPC_ID_BSOCTRx, - PPC_ID_BSOLRx, - PPC_ID_BTx, - PPC_ID_BTCTRx, - PPC_ID_BTLRx, PPC_ID_CLRLDIx, PPC_ID_CLRLWIx, PPC_ID_CLRRWIx, @@ -1151,6 +1111,9 @@ extern "C" { #endif bool Decompose(Instruction* instruction, uint32_t word32, uint64_t address, uint32_t flags); + void FillBcxOperands(OperandsList* bcx, const Instruction* instruction); + void FillBcctrxOperands(OperandsList* bcctrx, const Instruction* instruction); + void FillBclrxOperands(OperandsList* bclrx, const Instruction* instruction); const char* GetMnemonic(const Instruction* instruction); #ifdef __cplusplus From bd762de1bbfea4eaf3a331a3484ec2b8dfbfd2db Mon Sep 17 00:00:00 2001 From: noone Date: Mon, 23 Dec 2024 12:46:34 -0800 Subject: [PATCH 06/19] Use new decode logic in ppc arch --- arch/powerpc/CMakeLists.txt | 2 - arch/powerpc/arch_ppc.cpp | 964 +++++++++-------- arch/powerpc/decode/decode.c | 386 ++++++- arch/powerpc/decode/decode.h | 410 ++++--- arch/powerpc/disassembler.cpp | 358 ------- arch/powerpc/disassembler.h | 98 -- arch/powerpc/il.cpp | 1898 +++++++++------------------------ arch/powerpc/il.h | 4 +- arch/powerpc/util.cpp | 81 -- arch/powerpc/util.h | 4 +- 10 files changed, 1525 insertions(+), 2680 deletions(-) diff --git a/arch/powerpc/CMakeLists.txt b/arch/powerpc/CMakeLists.txt index 66ba9068a..98721d693 100644 --- a/arch/powerpc/CMakeLists.txt +++ b/arch/powerpc/CMakeLists.txt @@ -9,9 +9,7 @@ endif() file(GLOB SOURCES arch_ppc.cpp assembler.cpp - disassembler.cpp il.cpp - util.cpp *.h decode/*.c decode/*.h diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index f732b561b..3819ebd91 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -12,9 +12,10 @@ #include "lowlevelilinstruction.h" using namespace BinaryNinja; // for ::LogDebug, etc. -#include "disassembler.h" #include "assembler.h" +#include "decode/decode.h" + #include "il.h" #include "util.h" @@ -281,8 +282,8 @@ class PowerpcArchitecture: public Architecture { private: BNEndianness endian; - int cs_mode_local; size_t addressSize; + uint32_t decodeFlags; /* this can maybe be moved to the API later */ BNRegisterInfo RegisterInfo(uint32_t fullWidthReg, size_t offset, size_t size, bool zeroExtend = false) @@ -298,11 +299,13 @@ class PowerpcArchitecture: public Architecture public: /* initialization list */ - PowerpcArchitecture(const char* name, BNEndianness endian_, size_t addressSize_=4, int cs_mode_=0): Architecture(name) + PowerpcArchitecture(const char* name, BNEndianness endian_, size_t addressSize_=4, uint32_t decodeFlags_=DECODE_FLAGS_ALTIVEC | DECODE_FLAGS_VSX): Architecture(name) { endian = endian_; addressSize = addressSize_; - cs_mode_local = cs_mode_; + decodeFlags = decodeFlags_; + if (addressSize == 8) + decodeFlags |= DECODE_FLAGS_PPC64; } /*************************************************************************/ @@ -335,6 +338,16 @@ class PowerpcArchitecture: public Architecture return 4; } + bool FillInstruction(Instruction* instruction, const uint8_t* data, size_t length, uint64_t address) + { + uint32_t word32 = *(const uint32_t *) data; + + if (endian == BigEndian) + word32 = bswap32(word32); + + return Decompose(instruction, word32, address, decodeFlags); + } + /* think "GetInstructionBranchBehavior()" populates struct Instruction Info (api/binaryninjaapi.h) @@ -348,76 +361,48 @@ class PowerpcArchitecture: public Architecture virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override { - struct decomp_result res; - struct cs_insn *insn = &(res.insn); + Instruction instruction; - //MYLOG("%s()\n", __func__); - - if (maxLen < 4) { + if (maxLen < 4) + { MYLOG("ERROR: need at least 4 bytes\n"); return false; } - if (DoesQualifyForLocalDisassembly(data, endian == BigEndian)) { - result.length = 4; - return true; - } + result.length = 4; - /* decompose the instruction to get branch info */ - if(powerpc_decompose(data, 4, addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { - MYLOG("ERROR: powerpc_decompose()\n"); + if (!FillInstruction(&instruction, data, maxLen, addr)) + { + MYLOG("ERROR: FillInstruction()\n"); return false; } - uint32_t raw_insn = *(const uint32_t *) data; - - if (endian == BigEndian) - raw_insn = bswap32(raw_insn); - - switch (raw_insn >> 26) + switch (instruction.id) { - case 18: /* b (b, ba, bl, bla) */ + case PPC_ID_Bx: { - uint64_t target = raw_insn & 0x03fffffc; - - /* sign extend target */ - target = sign_extend(addressSize, target, 25); - - /* account for absolute addressing */ - if (!(raw_insn & 2)) - { - target += addr; - ADDRMASK(addressSize, target); - } + uint64_t target = instruction.operands[0].label; - if (raw_insn & 1) + if (instruction.flags.lk) result.AddBranch(CallDestination, target); else result.AddBranch(UnconditionalBranch, target); break; } - case 16: /* bc */ - { - uint64_t target = raw_insn & 0xfffc; - uint8_t bo = (raw_insn >> 21) & 0x1f; - bool lk = raw_insn & 1; - - /* sign extend target */ - target = sign_extend(addressSize, target, 15); - /* account for absolute addressing */ - if (!(raw_insn & 2)) - { - target += addr; - ADDRMASK(addressSize, target); - } + case PPC_ID_BCx: + { + uint32_t bo = instruction.operands[0].uimm; + uint64_t target = instruction.operands[2].label; if (target != addr + 4) { if ((bo & 0x14) == 0x14) - result.AddBranch(lk ? CallDestination : UnconditionalBranch, target); - else if (!lk) + { + result.AddBranch(instruction.flags.lk ? CallDestination : UnconditionalBranch, target); + } + else if (!instruction.flags.lk) { result.AddBranch(FalseBranch, addr + 4); result.AddBranch(TrueBranch, target); @@ -426,90 +411,120 @@ class PowerpcArchitecture: public Architecture break; } - case 19: /* bcctr, bclr */ - { - uint8_t bo = (raw_insn >> 21) & 0x1f; - bool lk = raw_insn & 1; - bool blr = false; - switch ((raw_insn >> 1) & 0x3ff) - { - case 16: - blr = true; - FALL_THROUGH - case 528: - if ((bo & 0x14) == 0x14 && !lk) - result.AddBranch(blr ? FunctionReturn : UnresolvedBranch); - - break; - } + case PPC_ID_BCLRx: + if (!instruction.flags.lk) + result.AddBranch(FunctionReturn); + else + result.AddBranch(UnresolvedBranch); break; - } - } - switch(insn->id) { - case PPC_INS_TRAP: + case PPC_ID_BCCTRx: result.AddBranch(UnresolvedBranch); break; - case PPC_INS_RFI: + + case PPC_ID_TWU: + result.AddBranch(UnresolvedBranch); + break; + + case PPC_ID_RFI: result.AddBranch(UnresolvedBranch); break; } - result.length = 4; return true; } - bool PrintLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, vector &result, decomp_result* res) + // Returns whether any token was pushed (ie if operand is implied) + bool PushOperandTokens(vector& result, const Operand* op) { - (void)addr; - char buf[16]; - uint32_t local_op = PPC_INS_INVALID; + char buf[32]; + switch (op->cls) + { + case PPC_OP_REG_CRFD_IMPLY0: + case PPC_OP_REG_CRFS_IMPLY0: + if (op->reg == PPC_REG_CRF0) + return false; - struct cs_detail *detail = 0; - struct cs_ppc *ppc = 0; - struct cs_insn *insn = &(res->insn); + result.emplace_back(RegisterToken, GetRegisterName(op->reg)); - detail = &(res->detail); - ppc = &(detail->ppc); + break; - if (len < 4) - return false; - len = 4; + case PPC_OP_REG_RA: + case PPC_OP_REG_RB: + case PPC_OP_REG_RD: + case PPC_OP_REG_RS: + case PPC_OP_REG_FRA: + case PPC_OP_REG_FRB: + case PPC_OP_REG_FRC: + case PPC_OP_REG_FRD: + case PPC_OP_REG_FRS: + case PPC_OP_REG_CRFD: + case PPC_OP_REG_CRFS: + case PPC_OP_REG_AV_VA: + case PPC_OP_REG_AV_VB: + case PPC_OP_REG_AV_VC: + case PPC_OP_REG_AV_VD: + case PPC_OP_REG_AV_VS: + case PPC_OP_REG_VSX_RA: + case PPC_OP_REG_VSX_RA_DWORD0: + case PPC_OP_REG_VSX_RB: + case PPC_OP_REG_VSX_RB_DWORD0: + case PPC_OP_REG_VSX_RC: + case PPC_OP_REG_VSX_RC_DWORD0: + case PPC_OP_REG_VSX_RD: + case PPC_OP_REG_VSX_RD_DWORD0: + case PPC_OP_REG_VSX_RS: + case PPC_OP_REG_VSX_RS_DWORD0: + result.emplace_back(RegisterToken, GetRegisterName(op->reg)); + break; - local_op = DoesQualifyForLocalDisassembly(data, endian == BigEndian); - PerformLocalDisassembly(data, addr, len, res, endian == BigEndian); + case PPC_OP_UIMM: + snprintf(buf, sizeof(buf), "0x%x", op->uimm); + result.emplace_back(IntegerToken, buf, op->uimm, 4); + break; - switch (local_op) - { - case PPC_INS_BN_FCMPO: - result.emplace_back(InstructionToken, insn->mnemonic); - result.emplace_back(TextToken, " "); - snprintf(buf, sizeof(buf), "cr%d", ppc->operands[0].reg - PPC_REG_CR0); - result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "f%d", ppc->operands[1].reg - PPC_REG_F0); - result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "f%d", ppc->operands[2].reg - PPC_REG_F0); - result.emplace_back(RegisterToken, buf); - break; - case PPC_INS_BN_XXPERMR: - result.emplace_back(InstructionToken, insn->mnemonic); - result.emplace_back(TextToken, " "); - snprintf(buf, sizeof(buf), "vs%d", ppc->operands[0].reg - PPC_REG_VS0); - result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "vs%d", ppc->operands[1].reg - PPC_REG_VS0); - result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "vs%d", ppc->operands[2].reg - PPC_REG_VS0); - result.emplace_back(RegisterToken, buf); - break; - default: - return false; + case PPC_OP_SIMM: + if (op->simm < 0 && op->simm > -0x10000) + snprintf(buf, sizeof(buf), "-0x%llx", -op->simm); + else + snprintf(buf, sizeof(buf), "0x%llx", op->simm); + result.emplace_back(IntegerToken, buf, op->simm, 4); + break; + + case PPC_OP_LABEL: + snprintf(buf, sizeof(buf), "0x%llx", op->label); + result.emplace_back(CodeRelativeAddressToken, buf, op->label, 4); + break; + + case PPC_OP_CRBIT_A: + case PPC_OP_CRBIT_B: + case PPC_OP_CRBIT_D: + result.emplace_back(RegisterToken, GetCRBitName(op->crbit)); + break; + + case PPC_OP_MEM_RA: + // eg: lwz r11, 8(r11) + // + // TODO: it would be nice to have the option to print these + // in hex; printed in decimal now for backwards compatibility + snprintf(buf, sizeof(buf), "%d", op->mem.offset); + result.emplace_back(IntegerToken, buf, op->mem.offset, 4); + + result.emplace_back(BraceToken, "("); + if (op->mem.reg == PPC_REG_GPR0) + result.emplace_back(PossibleAddressToken, "0", 0, 4); + else + result.emplace_back(RegisterToken, GetRegisterName(op->mem.reg)); + result.emplace_back(BraceToken, ")"); + break; + + default: + //MYLOG("pushing a ???\n"); + result.emplace_back(TextToken, "???"); } + return true; } @@ -519,128 +534,82 @@ class PowerpcArchitecture: public Architecture virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, vector& result) override { bool rc = false; - bool capstoneWorkaround = false; char buf[32]; size_t strlenMnem; - struct decomp_result res; - struct cs_insn *insn = &(res.insn); - struct cs_detail *detail = &(res.detail); - struct cs_ppc *ppc = &(detail->ppc); + Instruction instruction; + const char* mnemonic = NULL; //MYLOG("%s()\n", __func__); - if (len < 4) { - MYLOG("ERROR: need at least 4 bytes\n"); - goto cleanup; - } - - if (DoesQualifyForLocalDisassembly(data, endian == BigEndian)) + if (len < 4) { - // PerformLocalDisassembly(data, addr, len, &res, endian == BigEndian); - return PrintLocalDisassembly(data, addr, len, result, &res); - } - if(powerpc_decompose(data, 4, addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { - MYLOG("ERROR: powerpc_decompose()\n"); - goto cleanup; + MYLOG("ERROR: need at least 4 bytes\n"); + return false; } - switch (insn->id) + len = 4; + if (!FillInstruction(&instruction, data, len, addr)) { - case PPC_INS_CRAND: - case PPC_INS_CRANDC: - case PPC_INS_CRNAND: - case PPC_INS_CROR: - case PPC_INS_CRORC: - case PPC_INS_CRNOR: - case PPC_INS_CREQV: - case PPC_INS_CRXOR: - case PPC_INS_CRSET: - case PPC_INS_CRCLR: - case PPC_INS_CRNOT: - case PPC_INS_CRMOVE: - capstoneWorkaround = true; + MYLOG("ERROR: FillInstruction()\n"); + return false; } /* mnemonic */ - result.emplace_back(InstructionToken, insn->mnemonic); + mnemonic = GetMnemonic(&instruction); + result.emplace_back(InstructionToken, mnemonic); /* padding between mnemonic and operands */ memset(buf, ' ', 8); - strlenMnem = strlen(insn->mnemonic); - if(strlenMnem < 8) + strlenMnem = strlen(mnemonic); + if (strlenMnem < 8) buf[8-strlenMnem] = '\0'; else buf[1] = '\0'; result.emplace_back(TextToken, buf); - /* operands */ - for(int i=0; iop_count; ++i) { - struct cs_ppc_op *op = &(ppc->operands[i]); + // To make IL easier to reason about, sometimes an instruction's + // internal representation always has an operand that's omitted + // in assembly; we take care of overriding those cases here + OperandsList operand_list; + memset(&operand_list, 0, sizeof(operand_list)); - switch(op->type) { - case PPC_OP_REG: - //MYLOG("pushing a register\n"); - if (capstoneWorkaround || (insn->id == PPC_INS_ISEL && i == 3)) - result.emplace_back(RegisterToken, GetFlagName(op->reg)); - else - result.emplace_back(RegisterToken, GetRegisterName(op->reg)); - break; - case PPC_OP_IMM: - //MYLOG("pushing an integer\n"); - - switch(insn->id) { - case PPC_INS_B: - case PPC_INS_BA: - case PPC_INS_BC: - case PPC_INS_BCL: - case PPC_INS_BL: - case PPC_INS_BLA: - snprintf(buf, sizeof(buf), "0x%" PRIx64, op->imm); - result.emplace_back(CodeRelativeAddressToken, buf, (uint32_t) op->imm, 4); - break; - case PPC_INS_ADDIS: - case PPC_INS_LIS: - case PPC_INS_ORIS: - case PPC_INS_XORIS: - case PPC_INS_ORI: - snprintf(buf, sizeof(buf), "0x%x", (uint16_t)op->imm); - result.emplace_back(IntegerToken, buf, (uint16_t) op->imm, 4); - break; - default: - if (op->imm < 0 && op->imm > -0x10000) - snprintf(buf, sizeof(buf), "-0x%" PRIx64, -op->imm); - else - snprintf(buf, sizeof(buf), "0x%" PRIx64, op->imm); - result.emplace_back(IntegerToken, buf, op->imm, 4); - } + // The default is to just copy every operand, to simplify the + // alternate code path for special cases + operand_list.numOperands = instruction.numOperands; + for (int i = 0; i < instruction.numOperands; ++i) + { + operand_list.operands[i] = instruction.operands[i]; + } - break; - case PPC_OP_MEM: - // eg: lwz r11, 8(r11) - snprintf(buf, sizeof(buf), "%d", op->mem.disp); - result.emplace_back(IntegerToken, buf, op->mem.disp, 4); - - result.emplace_back(BraceToken, "("); - result.emplace_back(RegisterToken, GetRegisterName(op->mem.base)); - result.emplace_back(BraceToken, ")"); - break; - case PPC_OP_CRX: - case PPC_OP_INVALID: - default: - //MYLOG("pushing a ???\n"); - result.emplace_back(TextToken, "???"); - } + switch(instruction.id) + { + case PPC_ID_BCx: + FillBcxOperands(&operand_list, &instruction); + break; + case PPC_ID_BCCTRx: + FillBcctrxOperands(&operand_list, &instruction); + break; + case PPC_ID_BCLRx: + FillBclrxOperands(&operand_list, &instruction); + break; + default: + // Already copied by default + ; + } - if(i < ppc->op_count-1) { + for (int i = 0; i < operand_list.numOperands; ++i) + { + Operand* op = &(operand_list.operands[i]); + bool was_pushed = PushOperandTokens(result, op); + + if (was_pushed && i < operand_list.numOperands - 1) + { //MYLOG("pushing a comma\n"); result.emplace_back(OperandSeparatorToken, ", "); } } - rc = true; - len = 4; - cleanup: - return rc; + return true; } static string GetIntrinsicName_ppc_ps(uint32_t intrinsic) @@ -666,7 +635,7 @@ class PowerpcArchitecture: public Architecture case PPC_INTRIN_FRSP: return "float_round"; default: - if (cs_mode_local == CS_MODE_PS) + if ((decodeFlags & DECODE_FLAGS_PS)) { return GetIntrinsicName_ppc_ps(intrinsic); } @@ -726,7 +695,7 @@ class PowerpcArchitecture: public Architecture return {NameAndType(Type::FloatType(4))}; // for now, quantize is operating on the float in, and the gqr that holds the scale default: - if (cs_mode_local == CS_MODE_PS) + if ((decodeFlags & DECODE_FLAGS_PS)) { return GetIntrinsicInputs_ppc_ps(intrinsic); } @@ -759,7 +728,7 @@ class PowerpcArchitecture: public Architecture case PPC_INTRIN_FRSP: return {Type::FloatType(4)}; default: - if (cs_mode_local == CS_MODE_PS) + if ((decodeFlags & DECODE_FLAGS_PS)) { return GetIntrinsicOutputs_ppc_ps(intrinsic); } @@ -771,29 +740,23 @@ class PowerpcArchitecture: public Architecture virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override { + Instruction instruction; bool rc = false; - struct decomp_result res = {0}; - if (len < 4) { + if (len < 4) + { MYLOG("ERROR: need at least 4 bytes\n"); goto cleanup; } - //if(addr >= 0x10000300 && addr <= 0x10000320) { - // MYLOG("%s(data, 0x%llX, 0x%zX, il)\n", __func__, addr, len); - //} - - if (DoesQualifyForLocalDisassembly(data, endian == BigEndian)) { - PerformLocalDisassembly(data, addr, len, &res, endian == BigEndian); - } - else if(powerpc_decompose(data, 4, addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { - MYLOG("ERROR: powerpc_decompose()\n"); + if (!FillInstruction(&instruction, data, len, addr)) + { + MYLOG("ERROR: FillInstruction()\n"); il.AddInstruction(il.Undefined()); goto cleanup; } -// getil: - rc = GetLowLevelILForPPCInstruction(this, il, data, addr, &res, endian == LittleEndian); + rc = GetLowLevelILForPPCInstruction(this, il, &instruction, addr); len = 4; cleanup: @@ -959,9 +922,9 @@ class PowerpcArchitecture: public Architecture virtual string GetRegisterName(uint32_t regId) override { - const char *result = powerpc_reg_to_str(regId, cs_mode_local); + const char *result = PowerPCRegisterName(regId); - if(result == NULL) + if (result == NULL) result = ""; //MYLOG("%s(%d) returns %s\n", __func__, regId, result); @@ -999,8 +962,7 @@ class PowerpcArchitecture: public Architecture virtual string GetFlagName(uint32_t flag) override { // MYLOG("%s() flag:%d\n", __func__, flag); - - switch(powerpc_crx_to_reg(flag)) { + switch(flag) { case IL_FLAG_LT: return "lt"; case IL_FLAG_GT: return "gt"; case IL_FLAG_EQ: return "eq"; @@ -1548,10 +1510,14 @@ class PowerpcArchitecture: public Architecture // MYLOG("%s()\n", __func__); return vector{ - PPC_REG_R0, PPC_REG_R1, PPC_REG_R2, PPC_REG_R3, PPC_REG_R4, PPC_REG_R5, PPC_REG_R6, PPC_REG_R7, - PPC_REG_R8, PPC_REG_R9, PPC_REG_R10, PPC_REG_R11, PPC_REG_R12, PPC_REG_R13, PPC_REG_R14, PPC_REG_R15, - PPC_REG_R16, PPC_REG_R17, PPC_REG_R18, PPC_REG_R19, PPC_REG_R20, PPC_REG_R21, PPC_REG_R22, PPC_REG_R23, - PPC_REG_R24, PPC_REG_R25, PPC_REG_R26, PPC_REG_R27, PPC_REG_R28, PPC_REG_R29, PPC_REG_R30, PPC_REG_R31 + PPC_REG_GPR0, PPC_REG_GPR1, PPC_REG_GPR2, PPC_REG_GPR3, + PPC_REG_GPR4, PPC_REG_GPR5, PPC_REG_GPR6, PPC_REG_GPR7, + PPC_REG_GPR8, PPC_REG_GPR9, PPC_REG_GPR10, PPC_REG_GPR11, + PPC_REG_GPR12, PPC_REG_GPR13, PPC_REG_GPR14, PPC_REG_GPR15, + PPC_REG_GPR16, PPC_REG_GPR17, PPC_REG_GPR18, PPC_REG_GPR19, + PPC_REG_GPR20, PPC_REG_GPR21, PPC_REG_GPR22, PPC_REG_GPR23, + PPC_REG_GPR24, PPC_REG_GPR25, PPC_REG_GPR26, PPC_REG_GPR27, + PPC_REG_GPR28, PPC_REG_GPR29, PPC_REG_GPR30, PPC_REG_GPR31 }; } @@ -1559,45 +1525,63 @@ class PowerpcArchitecture: public Architecture virtual vector GetAllRegisters() override { vector result = { - PPC_REG_CARRY, - - PPC_REG_CR0, PPC_REG_CR1, PPC_REG_CR2, PPC_REG_CR3, PPC_REG_CR4, PPC_REG_CR5, PPC_REG_CR6, PPC_REG_CR7, - - PPC_REG_CTR, - - PPC_REG_F0, PPC_REG_F1, PPC_REG_F2, PPC_REG_F3, PPC_REG_F4, PPC_REG_F5, PPC_REG_F6, PPC_REG_F7, - PPC_REG_F8, PPC_REG_F9, PPC_REG_F10, PPC_REG_F11, PPC_REG_F12, PPC_REG_F13, PPC_REG_F14, PPC_REG_F15, - PPC_REG_F16, PPC_REG_F17, PPC_REG_F18, PPC_REG_F19, PPC_REG_F20, PPC_REG_F21, PPC_REG_F22, PPC_REG_F23, - PPC_REG_F24, PPC_REG_F25, PPC_REG_F26, PPC_REG_F27, PPC_REG_F28, PPC_REG_F29, PPC_REG_F30, PPC_REG_F31, - - PPC_REG_LR, - - PPC_REG_R0, PPC_REG_R1, PPC_REG_R2, PPC_REG_R3, PPC_REG_R4, PPC_REG_R5, PPC_REG_R6, PPC_REG_R7, - PPC_REG_R8, PPC_REG_R9, PPC_REG_R10, PPC_REG_R11, PPC_REG_R12, PPC_REG_R13, PPC_REG_R14, PPC_REG_R15, - PPC_REG_R16, PPC_REG_R17, PPC_REG_R18, PPC_REG_R19, PPC_REG_R20, PPC_REG_R21, PPC_REG_R22, PPC_REG_R23, - PPC_REG_R24, PPC_REG_R25, PPC_REG_R26, PPC_REG_R27, PPC_REG_R28, PPC_REG_R29, PPC_REG_R30, PPC_REG_R31, - - PPC_REG_V0, PPC_REG_V1, PPC_REG_V2, PPC_REG_V3, PPC_REG_V4, PPC_REG_V5, PPC_REG_V6, PPC_REG_V7, - PPC_REG_V8, PPC_REG_V9, PPC_REG_V10, PPC_REG_V11, PPC_REG_V12, PPC_REG_V13, PPC_REG_V14, PPC_REG_V15, - PPC_REG_V16, PPC_REG_V17, PPC_REG_V18, PPC_REG_V19, PPC_REG_V20, PPC_REG_V21, PPC_REG_V22, PPC_REG_V23, - PPC_REG_V24, PPC_REG_V25, PPC_REG_V26, PPC_REG_V27, PPC_REG_V28, PPC_REG_V29, PPC_REG_V30, PPC_REG_V31, - PPC_REG_VRSAVE, - PPC_REG_VS0, PPC_REG_VS1, PPC_REG_VS2, PPC_REG_VS3, PPC_REG_VS4, PPC_REG_VS5, PPC_REG_VS6, PPC_REG_VS7, - PPC_REG_VS8, PPC_REG_VS9, PPC_REG_VS10, PPC_REG_VS11, PPC_REG_VS12, PPC_REG_VS13, PPC_REG_VS14, PPC_REG_VS15, - PPC_REG_VS16, PPC_REG_VS17, PPC_REG_VS18, PPC_REG_VS19, PPC_REG_VS20, PPC_REG_VS21, PPC_REG_VS22, PPC_REG_VS23, - PPC_REG_VS24, PPC_REG_VS25, PPC_REG_VS26, PPC_REG_VS27, PPC_REG_VS28, PPC_REG_VS29, PPC_REG_VS30, PPC_REG_VS31, - PPC_REG_VS32, PPC_REG_VS33, PPC_REG_VS34, PPC_REG_VS35, PPC_REG_VS36, PPC_REG_VS37, PPC_REG_VS38, PPC_REG_VS39, - PPC_REG_VS40, PPC_REG_VS41, PPC_REG_VS42, PPC_REG_VS43, PPC_REG_VS44, PPC_REG_VS45, PPC_REG_VS46, PPC_REG_VS47, - PPC_REG_VS48, PPC_REG_VS49, PPC_REG_VS50, PPC_REG_VS51, PPC_REG_VS52, PPC_REG_VS53, PPC_REG_VS54, PPC_REG_VS55, - PPC_REG_VS56, PPC_REG_VS57, PPC_REG_VS58, PPC_REG_VS59, PPC_REG_VS60, PPC_REG_VS61, PPC_REG_VS62, PPC_REG_VS63, + PPC_REG_GPR0, PPC_REG_GPR1, PPC_REG_GPR2, PPC_REG_GPR3, + PPC_REG_GPR4, PPC_REG_GPR5, PPC_REG_GPR6, PPC_REG_GPR7, + PPC_REG_GPR8, PPC_REG_GPR9, PPC_REG_GPR10, PPC_REG_GPR11, + PPC_REG_GPR12, PPC_REG_GPR13, PPC_REG_GPR14, PPC_REG_GPR15, + PPC_REG_GPR16, PPC_REG_GPR17, PPC_REG_GPR18, PPC_REG_GPR19, + PPC_REG_GPR20, PPC_REG_GPR21, PPC_REG_GPR22, PPC_REG_GPR23, + PPC_REG_GPR24, PPC_REG_GPR25, PPC_REG_GPR26, PPC_REG_GPR27, + PPC_REG_GPR28, PPC_REG_GPR29, PPC_REG_GPR30, PPC_REG_GPR31, + + PPC_REG_XER, PPC_REG_LR, PPC_REG_CTR, + + PPC_REG_FR0, PPC_REG_FR1, PPC_REG_FR2, PPC_REG_FR3, + PPC_REG_FR4, PPC_REG_FR5, PPC_REG_FR6, PPC_REG_FR7, + PPC_REG_FR8, PPC_REG_FR9, PPC_REG_FR10, PPC_REG_FR11, + PPC_REG_FR12, PPC_REG_FR13, PPC_REG_FR14, PPC_REG_FR15, + PPC_REG_FR16, PPC_REG_FR17, PPC_REG_FR18, PPC_REG_FR19, + PPC_REG_FR20, PPC_REG_FR21, PPC_REG_FR22, PPC_REG_FR23, + PPC_REG_FR24, PPC_REG_FR25, PPC_REG_FR26, PPC_REG_FR27, + PPC_REG_FR28, PPC_REG_FR29, PPC_REG_FR30, PPC_REG_FR31, + + PPC_REG_CRF0, PPC_REG_CRF1, PPC_REG_CRF2, PPC_REG_CRF3, + PPC_REG_CRF4, PPC_REG_CRF5, PPC_REG_CRF6, PPC_REG_CRF7, + + PPC_REG_AV_VR0, PPC_REG_AV_VR1, PPC_REG_AV_VR2, PPC_REG_AV_VR3, + PPC_REG_AV_VR4, PPC_REG_AV_VR5, PPC_REG_AV_VR6, PPC_REG_AV_VR7, + PPC_REG_AV_VR8, PPC_REG_AV_VR9, PPC_REG_AV_VR10, PPC_REG_AV_VR11, + PPC_REG_AV_VR12, PPC_REG_AV_VR13, PPC_REG_AV_VR14, PPC_REG_AV_VR15, + PPC_REG_AV_VR16, PPC_REG_AV_VR17, PPC_REG_AV_VR18, PPC_REG_AV_VR19, + PPC_REG_AV_VR20, PPC_REG_AV_VR21, PPC_REG_AV_VR22, PPC_REG_AV_VR23, + PPC_REG_AV_VR24, PPC_REG_AV_VR25, PPC_REG_AV_VR26, PPC_REG_AV_VR27, + PPC_REG_AV_VR28, PPC_REG_AV_VR29, PPC_REG_AV_VR30, PPC_REG_AV_VR31, + + PPC_REG_VSX_VR0, PPC_REG_VSX_VR1, PPC_REG_VSX_VR2, PPC_REG_VSX_VR3, + PPC_REG_VSX_VR4, PPC_REG_VSX_VR5, PPC_REG_VSX_VR6, PPC_REG_VSX_VR7, + PPC_REG_VSX_VR8, PPC_REG_VSX_VR9, PPC_REG_VSX_VR10, PPC_REG_VSX_VR11, + PPC_REG_VSX_VR12, PPC_REG_VSX_VR13, PPC_REG_VSX_VR14, PPC_REG_VSX_VR15, + PPC_REG_VSX_VR16, PPC_REG_VSX_VR17, PPC_REG_VSX_VR18, PPC_REG_VSX_VR19, + PPC_REG_VSX_VR20, PPC_REG_VSX_VR21, PPC_REG_VSX_VR22, PPC_REG_VSX_VR23, + PPC_REG_VSX_VR24, PPC_REG_VSX_VR25, PPC_REG_VSX_VR26, PPC_REG_VSX_VR27, + PPC_REG_VSX_VR28, PPC_REG_VSX_VR29, PPC_REG_VSX_VR30, PPC_REG_VSX_VR31, + PPC_REG_VSX_VR32, PPC_REG_VSX_VR33, PPC_REG_VSX_VR34, PPC_REG_VSX_VR35, + PPC_REG_VSX_VR36, PPC_REG_VSX_VR37, PPC_REG_VSX_VR38, PPC_REG_VSX_VR39, + PPC_REG_VSX_VR40, PPC_REG_VSX_VR41, PPC_REG_VSX_VR42, PPC_REG_VSX_VR43, + PPC_REG_VSX_VR44, PPC_REG_VSX_VR45, PPC_REG_VSX_VR46, PPC_REG_VSX_VR47, + PPC_REG_VSX_VR48, PPC_REG_VSX_VR49, PPC_REG_VSX_VR50, PPC_REG_VSX_VR51, + PPC_REG_VSX_VR52, PPC_REG_VSX_VR53, PPC_REG_VSX_VR54, PPC_REG_VSX_VR55, + PPC_REG_VSX_VR56, PPC_REG_VSX_VR57, PPC_REG_VSX_VR58, PPC_REG_VSX_VR59, + PPC_REG_VSX_VR60, PPC_REG_VSX_VR61, PPC_REG_VSX_VR62, PPC_REG_VSX_VR63, }; vector gqrarray = { - PPC_REG_BN_GQR0, PPC_REG_BN_GQR1, PPC_REG_BN_GQR2, PPC_REG_BN_GQR3, - PPC_REG_BN_GQR4, PPC_REG_BN_GQR5, PPC_REG_BN_GQR6, PPC_REG_BN_GQR7}; + PPC_REG_GQR0, PPC_REG_GQR1, PPC_REG_GQR2, PPC_REG_GQR3, + PPC_REG_GQR4, PPC_REG_GQR5, PPC_REG_GQR6, PPC_REG_GQR7 + }; - if ((cs_mode_local & CS_MODE_PS) != 0) + if ((decodeFlags & DECODE_FLAGS_PS) != 0) { result.insert(result.end(), gqrarray.begin(), gqrarray.end()); } @@ -1608,7 +1592,7 @@ class PowerpcArchitecture: public Architecture virtual std::vector GetGlobalRegisters() override { - return vector{ PPC_REG_R2, PPC_REG_R13 }; + return vector{ PPC_REG_GPR2, PPC_REG_GPR13 }; } @@ -1618,195 +1602,199 @@ class PowerpcArchitecture: public Architecture and our size */ virtual BNRegisterInfo GetRegisterInfo(uint32_t regId) override { - //MYLOG("%s(%s)\n", __func__, powerpc_reg_to_str(regId)); + //MYLOG("%s(%s)\n", __func__, PowerPCRegisterName(regId)); switch(regId) { - // BNRegisterInfo RegisterInfo(uint32_t fullWidthReg, size_t offset, - // size_t size, bool zeroExtend = false) - - case PPC_REG_CARRY: return RegisterInfo(PPC_REG_CARRY, 0, 4); - case PPC_REG_CR0: return RegisterInfo(PPC_REG_CR0, 0, 4); - case PPC_REG_CR1: return RegisterInfo(PPC_REG_CR1, 0, 4); - case PPC_REG_CR2: return RegisterInfo(PPC_REG_CR2, 0, 4); - case PPC_REG_CR3: return RegisterInfo(PPC_REG_CR3, 0, 4); - case PPC_REG_CR4: return RegisterInfo(PPC_REG_CR4, 0, 4); - case PPC_REG_CR5: return RegisterInfo(PPC_REG_CR5, 0, 4); - case PPC_REG_CR6: return RegisterInfo(PPC_REG_CR6, 0, 4); - case PPC_REG_CR7: return RegisterInfo(PPC_REG_CR7, 0, 4); - case PPC_REG_CTR: return RegisterInfo(PPC_REG_CTR, 0, addressSize); - case PPC_REG_F0: return RegisterInfo(PPC_REG_F0, 0, 8); - case PPC_REG_F1: return RegisterInfo(PPC_REG_F1, 0, 8); - case PPC_REG_F2: return RegisterInfo(PPC_REG_F2, 0, 8); - case PPC_REG_F3: return RegisterInfo(PPC_REG_F3, 0, 8); - case PPC_REG_F4: return RegisterInfo(PPC_REG_F4, 0, 8); - case PPC_REG_F5: return RegisterInfo(PPC_REG_F5, 0, 8); - case PPC_REG_F6: return RegisterInfo(PPC_REG_F6, 0, 8); - case PPC_REG_F7: return RegisterInfo(PPC_REG_F7, 0, 8); - case PPC_REG_F8: return RegisterInfo(PPC_REG_F8, 0, 8); - case PPC_REG_F9: return RegisterInfo(PPC_REG_F9, 0, 8); - case PPC_REG_F10: return RegisterInfo(PPC_REG_F10, 0, 8); - case PPC_REG_F11: return RegisterInfo(PPC_REG_F11, 0, 8); - case PPC_REG_F12: return RegisterInfo(PPC_REG_F12, 0, 8); - case PPC_REG_F13: return RegisterInfo(PPC_REG_F13, 0, 8); - case PPC_REG_F14: return RegisterInfo(PPC_REG_F14, 0, 8); - case PPC_REG_F15: return RegisterInfo(PPC_REG_F15, 0, 8); - case PPC_REG_F16: return RegisterInfo(PPC_REG_F16, 0, 8); - case PPC_REG_F17: return RegisterInfo(PPC_REG_F17, 0, 8); - case PPC_REG_F18: return RegisterInfo(PPC_REG_F18, 0, 8); - case PPC_REG_F19: return RegisterInfo(PPC_REG_F19, 0, 8); - case PPC_REG_F20: return RegisterInfo(PPC_REG_F20, 0, 8); - case PPC_REG_F21: return RegisterInfo(PPC_REG_F21, 0, 8); - case PPC_REG_F22: return RegisterInfo(PPC_REG_F22, 0, 8); - case PPC_REG_F23: return RegisterInfo(PPC_REG_F23, 0, 8); - case PPC_REG_F24: return RegisterInfo(PPC_REG_F24, 0, 8); - case PPC_REG_F25: return RegisterInfo(PPC_REG_F25, 0, 8); - case PPC_REG_F26: return RegisterInfo(PPC_REG_F26, 0, 8); - case PPC_REG_F27: return RegisterInfo(PPC_REG_F27, 0, 8); - case PPC_REG_F28: return RegisterInfo(PPC_REG_F28, 0, 8); - case PPC_REG_F29: return RegisterInfo(PPC_REG_F29, 0, 8); - case PPC_REG_F30: return RegisterInfo(PPC_REG_F30, 0, 8); - case PPC_REG_F31: return RegisterInfo(PPC_REG_F31, 0, 8); + case PPC_REG_GPR0: return RegisterInfo(PPC_REG_GPR0, 0, addressSize); + case PPC_REG_GPR1: return RegisterInfo(PPC_REG_GPR1, 0, addressSize); + case PPC_REG_GPR2: return RegisterInfo(PPC_REG_GPR2, 0, addressSize); + case PPC_REG_GPR3: return RegisterInfo(PPC_REG_GPR3, 0, addressSize); + case PPC_REG_GPR4: return RegisterInfo(PPC_REG_GPR4, 0, addressSize); + case PPC_REG_GPR5: return RegisterInfo(PPC_REG_GPR5, 0, addressSize); + case PPC_REG_GPR6: return RegisterInfo(PPC_REG_GPR6, 0, addressSize); + case PPC_REG_GPR7: return RegisterInfo(PPC_REG_GPR7, 0, addressSize); + case PPC_REG_GPR8: return RegisterInfo(PPC_REG_GPR8, 0, addressSize); + case PPC_REG_GPR9: return RegisterInfo(PPC_REG_GPR9, 0, addressSize); + case PPC_REG_GPR10: return RegisterInfo(PPC_REG_GPR10, 0, addressSize); + case PPC_REG_GPR11: return RegisterInfo(PPC_REG_GPR11, 0, addressSize); + case PPC_REG_GPR12: return RegisterInfo(PPC_REG_GPR12, 0, addressSize); + case PPC_REG_GPR13: return RegisterInfo(PPC_REG_GPR13, 0, addressSize); + case PPC_REG_GPR14: return RegisterInfo(PPC_REG_GPR14, 0, addressSize); + case PPC_REG_GPR15: return RegisterInfo(PPC_REG_GPR15, 0, addressSize); + case PPC_REG_GPR16: return RegisterInfo(PPC_REG_GPR16, 0, addressSize); + case PPC_REG_GPR17: return RegisterInfo(PPC_REG_GPR17, 0, addressSize); + case PPC_REG_GPR18: return RegisterInfo(PPC_REG_GPR18, 0, addressSize); + case PPC_REG_GPR19: return RegisterInfo(PPC_REG_GPR19, 0, addressSize); + case PPC_REG_GPR20: return RegisterInfo(PPC_REG_GPR20, 0, addressSize); + case PPC_REG_GPR21: return RegisterInfo(PPC_REG_GPR21, 0, addressSize); + case PPC_REG_GPR22: return RegisterInfo(PPC_REG_GPR22, 0, addressSize); + case PPC_REG_GPR23: return RegisterInfo(PPC_REG_GPR23, 0, addressSize); + case PPC_REG_GPR24: return RegisterInfo(PPC_REG_GPR24, 0, addressSize); + case PPC_REG_GPR25: return RegisterInfo(PPC_REG_GPR25, 0, addressSize); + case PPC_REG_GPR26: return RegisterInfo(PPC_REG_GPR26, 0, addressSize); + case PPC_REG_GPR27: return RegisterInfo(PPC_REG_GPR27, 0, addressSize); + case PPC_REG_GPR28: return RegisterInfo(PPC_REG_GPR28, 0, addressSize); + case PPC_REG_GPR29: return RegisterInfo(PPC_REG_GPR29, 0, addressSize); + case PPC_REG_GPR30: return RegisterInfo(PPC_REG_GPR30, 0, addressSize); + case PPC_REG_GPR31: return RegisterInfo(PPC_REG_GPR31, 0, addressSize); + + case PPC_REG_XER: return RegisterInfo(PPC_REG_XER, 0, 4); case PPC_REG_LR: return RegisterInfo(PPC_REG_LR, 0, addressSize); - case PPC_REG_R0: return RegisterInfo(PPC_REG_R0, 0, addressSize); - case PPC_REG_R1: return RegisterInfo(PPC_REG_R1, 0, addressSize); - case PPC_REG_R2: return RegisterInfo(PPC_REG_R2, 0, addressSize); - case PPC_REG_R3: return RegisterInfo(PPC_REG_R3, 0, addressSize); - case PPC_REG_R4: return RegisterInfo(PPC_REG_R4, 0, addressSize); - case PPC_REG_R5: return RegisterInfo(PPC_REG_R5, 0, addressSize); - case PPC_REG_R6: return RegisterInfo(PPC_REG_R6, 0, addressSize); - case PPC_REG_R7: return RegisterInfo(PPC_REG_R7, 0, addressSize); - case PPC_REG_R8: return RegisterInfo(PPC_REG_R8, 0, addressSize); - case PPC_REG_R9: return RegisterInfo(PPC_REG_R9, 0, addressSize); - case PPC_REG_R10: return RegisterInfo(PPC_REG_R10, 0, addressSize); - case PPC_REG_R11: return RegisterInfo(PPC_REG_R11, 0, addressSize); - case PPC_REG_R12: return RegisterInfo(PPC_REG_R12, 0, addressSize); - case PPC_REG_R13: return RegisterInfo(PPC_REG_R13, 0, addressSize); - case PPC_REG_R14: return RegisterInfo(PPC_REG_R14, 0, addressSize); - case PPC_REG_R15: return RegisterInfo(PPC_REG_R15, 0, addressSize); - case PPC_REG_R16: return RegisterInfo(PPC_REG_R16, 0, addressSize); - case PPC_REG_R17: return RegisterInfo(PPC_REG_R17, 0, addressSize); - case PPC_REG_R18: return RegisterInfo(PPC_REG_R18, 0, addressSize); - case PPC_REG_R19: return RegisterInfo(PPC_REG_R19, 0, addressSize); - case PPC_REG_R20: return RegisterInfo(PPC_REG_R20, 0, addressSize); - case PPC_REG_R21: return RegisterInfo(PPC_REG_R21, 0, addressSize); - case PPC_REG_R22: return RegisterInfo(PPC_REG_R22, 0, addressSize); - case PPC_REG_R23: return RegisterInfo(PPC_REG_R23, 0, addressSize); - case PPC_REG_R24: return RegisterInfo(PPC_REG_R24, 0, addressSize); - case PPC_REG_R25: return RegisterInfo(PPC_REG_R25, 0, addressSize); - case PPC_REG_R26: return RegisterInfo(PPC_REG_R26, 0, addressSize); - case PPC_REG_R27: return RegisterInfo(PPC_REG_R27, 0, addressSize); - case PPC_REG_R28: return RegisterInfo(PPC_REG_R28, 0, addressSize); - case PPC_REG_R29: return RegisterInfo(PPC_REG_R29, 0, addressSize); - case PPC_REG_R30: return RegisterInfo(PPC_REG_R30, 0, addressSize); - case PPC_REG_R31: return RegisterInfo(PPC_REG_R31, 0, addressSize); - case PPC_REG_V0: return RegisterInfo(PPC_REG_V0, 0, 4); - case PPC_REG_V1: return RegisterInfo(PPC_REG_V1, 0, 4); - case PPC_REG_V2: return RegisterInfo(PPC_REG_V2, 0, 4); - case PPC_REG_V3: return RegisterInfo(PPC_REG_V3, 0, 4); - case PPC_REG_V4: return RegisterInfo(PPC_REG_V4, 0, 4); - case PPC_REG_V5: return RegisterInfo(PPC_REG_V5, 0, 4); - case PPC_REG_V6: return RegisterInfo(PPC_REG_V6, 0, 4); - case PPC_REG_V7: return RegisterInfo(PPC_REG_V7, 0, 4); - case PPC_REG_V8: return RegisterInfo(PPC_REG_V8, 0, 4); - case PPC_REG_V9: return RegisterInfo(PPC_REG_V9, 0, 4); - case PPC_REG_V10: return RegisterInfo(PPC_REG_V10, 0, 4); - case PPC_REG_V11: return RegisterInfo(PPC_REG_V11, 0, 4); - case PPC_REG_V12: return RegisterInfo(PPC_REG_V12, 0, 4); - case PPC_REG_V13: return RegisterInfo(PPC_REG_V13, 0, 4); - case PPC_REG_V14: return RegisterInfo(PPC_REG_V14, 0, 4); - case PPC_REG_V15: return RegisterInfo(PPC_REG_V15, 0, 4); - case PPC_REG_V16: return RegisterInfo(PPC_REG_V16, 0, 4); - case PPC_REG_V17: return RegisterInfo(PPC_REG_V17, 0, 4); - case PPC_REG_V18: return RegisterInfo(PPC_REG_V18, 0, 4); - case PPC_REG_V19: return RegisterInfo(PPC_REG_V19, 0, 4); - case PPC_REG_V20: return RegisterInfo(PPC_REG_V20, 0, 4); - case PPC_REG_V21: return RegisterInfo(PPC_REG_V21, 0, 4); - case PPC_REG_V22: return RegisterInfo(PPC_REG_V22, 0, 4); - case PPC_REG_V23: return RegisterInfo(PPC_REG_V23, 0, 4); - case PPC_REG_V24: return RegisterInfo(PPC_REG_V24, 0, 4); - case PPC_REG_V25: return RegisterInfo(PPC_REG_V25, 0, 4); - case PPC_REG_V26: return RegisterInfo(PPC_REG_V26, 0, 4); - case PPC_REG_V27: return RegisterInfo(PPC_REG_V27, 0, 4); - case PPC_REG_V28: return RegisterInfo(PPC_REG_V28, 0, 4); - case PPC_REG_V29: return RegisterInfo(PPC_REG_V29, 0, 4); - case PPC_REG_V30: return RegisterInfo(PPC_REG_V30, 0, 4); - case PPC_REG_V31: return RegisterInfo(PPC_REG_V31, 0, 4); - case PPC_REG_VRSAVE: return RegisterInfo(PPC_REG_VRSAVE, 0, 4); - case PPC_REG_VS0: return RegisterInfo(PPC_REG_VS0, 0, 4); - case PPC_REG_VS1: return RegisterInfo(PPC_REG_VS1, 0, 4); - case PPC_REG_VS2: return RegisterInfo(PPC_REG_VS2, 0, 4); - case PPC_REG_VS3: return RegisterInfo(PPC_REG_VS3, 0, 4); - case PPC_REG_VS4: return RegisterInfo(PPC_REG_VS4, 0, 4); - case PPC_REG_VS5: return RegisterInfo(PPC_REG_VS5, 0, 4); - case PPC_REG_VS6: return RegisterInfo(PPC_REG_VS6, 0, 4); - case PPC_REG_VS7: return RegisterInfo(PPC_REG_VS7, 0, 4); - case PPC_REG_VS8: return RegisterInfo(PPC_REG_VS8, 0, 4); - case PPC_REG_VS9: return RegisterInfo(PPC_REG_VS9, 0, 4); - case PPC_REG_VS10: return RegisterInfo(PPC_REG_VS10, 0, 4); - case PPC_REG_VS11: return RegisterInfo(PPC_REG_VS11, 0, 4); - case PPC_REG_VS12: return RegisterInfo(PPC_REG_VS12, 0, 4); - case PPC_REG_VS13: return RegisterInfo(PPC_REG_VS13, 0, 4); - case PPC_REG_VS14: return RegisterInfo(PPC_REG_VS14, 0, 4); - case PPC_REG_VS15: return RegisterInfo(PPC_REG_VS15, 0, 4); - case PPC_REG_VS16: return RegisterInfo(PPC_REG_VS16, 0, 4); - case PPC_REG_VS17: return RegisterInfo(PPC_REG_VS17, 0, 4); - case PPC_REG_VS18: return RegisterInfo(PPC_REG_VS18, 0, 4); - case PPC_REG_VS19: return RegisterInfo(PPC_REG_VS19, 0, 4); - case PPC_REG_VS20: return RegisterInfo(PPC_REG_VS20, 0, 4); - case PPC_REG_VS21: return RegisterInfo(PPC_REG_VS21, 0, 4); - case PPC_REG_VS22: return RegisterInfo(PPC_REG_VS22, 0, 4); - case PPC_REG_VS23: return RegisterInfo(PPC_REG_VS23, 0, 4); - case PPC_REG_VS24: return RegisterInfo(PPC_REG_VS24, 0, 4); - case PPC_REG_VS25: return RegisterInfo(PPC_REG_VS25, 0, 4); - case PPC_REG_VS26: return RegisterInfo(PPC_REG_VS26, 0, 4); - case PPC_REG_VS27: return RegisterInfo(PPC_REG_VS27, 0, 4); - case PPC_REG_VS28: return RegisterInfo(PPC_REG_VS28, 0, 4); - case PPC_REG_VS29: return RegisterInfo(PPC_REG_VS29, 0, 4); - case PPC_REG_VS30: return RegisterInfo(PPC_REG_VS30, 0, 4); - case PPC_REG_VS31: return RegisterInfo(PPC_REG_VS31, 0, 4); - case PPC_REG_VS32: return RegisterInfo(PPC_REG_VS32, 0, 4); - case PPC_REG_VS33: return RegisterInfo(PPC_REG_VS33, 0, 4); - case PPC_REG_VS34: return RegisterInfo(PPC_REG_VS34, 0, 4); - case PPC_REG_VS35: return RegisterInfo(PPC_REG_VS35, 0, 4); - case PPC_REG_VS36: return RegisterInfo(PPC_REG_VS36, 0, 4); - case PPC_REG_VS37: return RegisterInfo(PPC_REG_VS37, 0, 4); - case PPC_REG_VS38: return RegisterInfo(PPC_REG_VS38, 0, 4); - case PPC_REG_VS39: return RegisterInfo(PPC_REG_VS39, 0, 4); - case PPC_REG_VS40: return RegisterInfo(PPC_REG_VS40, 0, 4); - case PPC_REG_VS41: return RegisterInfo(PPC_REG_VS41, 0, 4); - case PPC_REG_VS42: return RegisterInfo(PPC_REG_VS42, 0, 4); - case PPC_REG_VS43: return RegisterInfo(PPC_REG_VS43, 0, 4); - case PPC_REG_VS44: return RegisterInfo(PPC_REG_VS44, 0, 4); - case PPC_REG_VS45: return RegisterInfo(PPC_REG_VS45, 0, 4); - case PPC_REG_VS46: return RegisterInfo(PPC_REG_VS46, 0, 4); - case PPC_REG_VS47: return RegisterInfo(PPC_REG_VS47, 0, 4); - case PPC_REG_VS48: return RegisterInfo(PPC_REG_VS48, 0, 4); - case PPC_REG_VS49: return RegisterInfo(PPC_REG_VS49, 0, 4); - case PPC_REG_VS50: return RegisterInfo(PPC_REG_VS50, 0, 4); - case PPC_REG_VS51: return RegisterInfo(PPC_REG_VS51, 0, 4); - case PPC_REG_VS52: return RegisterInfo(PPC_REG_VS52, 0, 4); - case PPC_REG_VS53: return RegisterInfo(PPC_REG_VS53, 0, 4); - case PPC_REG_VS54: return RegisterInfo(PPC_REG_VS54, 0, 4); - case PPC_REG_VS55: return RegisterInfo(PPC_REG_VS55, 0, 4); - case PPC_REG_VS56: return RegisterInfo(PPC_REG_VS56, 0, 4); - case PPC_REG_VS57: return RegisterInfo(PPC_REG_VS57, 0, 4); - case PPC_REG_VS58: return RegisterInfo(PPC_REG_VS58, 0, 4); - case PPC_REG_VS59: return RegisterInfo(PPC_REG_VS59, 0, 4); - case PPC_REG_VS60: return RegisterInfo(PPC_REG_VS60, 0, 4); - case PPC_REG_VS61: return RegisterInfo(PPC_REG_VS61, 0, 4); - case PPC_REG_VS62: return RegisterInfo(PPC_REG_VS62, 0, 4); - case PPC_REG_VS63: return RegisterInfo(PPC_REG_VS63, 0, 4); - case PPC_REG_BN_GQR0: return RegisterInfo(PPC_REG_BN_GQR0, 0, 4); - case PPC_REG_BN_GQR1: return RegisterInfo(PPC_REG_BN_GQR1, 0, 4); - case PPC_REG_BN_GQR2: return RegisterInfo(PPC_REG_BN_GQR2, 0, 4); - case PPC_REG_BN_GQR3: return RegisterInfo(PPC_REG_BN_GQR3, 0, 4); - case PPC_REG_BN_GQR4: return RegisterInfo(PPC_REG_BN_GQR4, 0, 4); - case PPC_REG_BN_GQR5: return RegisterInfo(PPC_REG_BN_GQR5, 0, 4); - case PPC_REG_BN_GQR6: return RegisterInfo(PPC_REG_BN_GQR6, 0, 4); - case PPC_REG_BN_GQR7: return RegisterInfo(PPC_REG_BN_GQR7, 0, 4); + case PPC_REG_CTR: return RegisterInfo(PPC_REG_CTR, 0, addressSize); + + case PPC_REG_FR0: return RegisterInfo(PPC_REG_FR0, 0, 4); + case PPC_REG_FR1: return RegisterInfo(PPC_REG_FR1, 0, 4); + case PPC_REG_FR2: return RegisterInfo(PPC_REG_FR2, 0, 4); + case PPC_REG_FR3: return RegisterInfo(PPC_REG_FR3, 0, 4); + case PPC_REG_FR4: return RegisterInfo(PPC_REG_FR4, 0, 4); + case PPC_REG_FR5: return RegisterInfo(PPC_REG_FR5, 0, 4); + case PPC_REG_FR6: return RegisterInfo(PPC_REG_FR6, 0, 4); + case PPC_REG_FR7: return RegisterInfo(PPC_REG_FR7, 0, 4); + case PPC_REG_FR8: return RegisterInfo(PPC_REG_FR8, 0, 4); + case PPC_REG_FR9: return RegisterInfo(PPC_REG_FR9, 0, 4); + case PPC_REG_FR10: return RegisterInfo(PPC_REG_FR10, 0, 4); + case PPC_REG_FR11: return RegisterInfo(PPC_REG_FR11, 0, 4); + case PPC_REG_FR12: return RegisterInfo(PPC_REG_FR12, 0, 4); + case PPC_REG_FR13: return RegisterInfo(PPC_REG_FR13, 0, 4); + case PPC_REG_FR14: return RegisterInfo(PPC_REG_FR14, 0, 4); + case PPC_REG_FR15: return RegisterInfo(PPC_REG_FR15, 0, 4); + case PPC_REG_FR16: return RegisterInfo(PPC_REG_FR16, 0, 4); + case PPC_REG_FR17: return RegisterInfo(PPC_REG_FR17, 0, 4); + case PPC_REG_FR18: return RegisterInfo(PPC_REG_FR18, 0, 4); + case PPC_REG_FR19: return RegisterInfo(PPC_REG_FR19, 0, 4); + case PPC_REG_FR20: return RegisterInfo(PPC_REG_FR20, 0, 4); + case PPC_REG_FR21: return RegisterInfo(PPC_REG_FR21, 0, 4); + case PPC_REG_FR22: return RegisterInfo(PPC_REG_FR22, 0, 4); + case PPC_REG_FR23: return RegisterInfo(PPC_REG_FR23, 0, 4); + case PPC_REG_FR24: return RegisterInfo(PPC_REG_FR24, 0, 4); + case PPC_REG_FR25: return RegisterInfo(PPC_REG_FR25, 0, 4); + case PPC_REG_FR26: return RegisterInfo(PPC_REG_FR26, 0, 4); + case PPC_REG_FR27: return RegisterInfo(PPC_REG_FR27, 0, 4); + case PPC_REG_FR28: return RegisterInfo(PPC_REG_FR28, 0, 4); + case PPC_REG_FR29: return RegisterInfo(PPC_REG_FR29, 0, 4); + case PPC_REG_FR30: return RegisterInfo(PPC_REG_FR30, 0, 4); + case PPC_REG_FR31: return RegisterInfo(PPC_REG_FR31, 0, 4); + + case PPC_REG_CRF0: return RegisterInfo(PPC_REG_CRF0, 0, 4); + case PPC_REG_CRF1: return RegisterInfo(PPC_REG_CRF1, 0, 4); + case PPC_REG_CRF2: return RegisterInfo(PPC_REG_CRF2, 0, 4); + case PPC_REG_CRF3: return RegisterInfo(PPC_REG_CRF3, 0, 4); + case PPC_REG_CRF4: return RegisterInfo(PPC_REG_CRF4, 0, 4); + case PPC_REG_CRF5: return RegisterInfo(PPC_REG_CRF5, 0, 4); + case PPC_REG_CRF6: return RegisterInfo(PPC_REG_CRF6, 0, 4); + case PPC_REG_CRF7: return RegisterInfo(PPC_REG_CRF7, 0, 4); + + // TODO: make these subregisters of VSX registers + case PPC_REG_AV_VR0: return RegisterInfo(PPC_REG_AV_VR0, 0, 4); + case PPC_REG_AV_VR1: return RegisterInfo(PPC_REG_AV_VR1, 0, 4); + case PPC_REG_AV_VR2: return RegisterInfo(PPC_REG_AV_VR2, 0, 4); + case PPC_REG_AV_VR3: return RegisterInfo(PPC_REG_AV_VR3, 0, 4); + case PPC_REG_AV_VR4: return RegisterInfo(PPC_REG_AV_VR4, 0, 4); + case PPC_REG_AV_VR5: return RegisterInfo(PPC_REG_AV_VR5, 0, 4); + case PPC_REG_AV_VR6: return RegisterInfo(PPC_REG_AV_VR6, 0, 4); + case PPC_REG_AV_VR7: return RegisterInfo(PPC_REG_AV_VR7, 0, 4); + case PPC_REG_AV_VR8: return RegisterInfo(PPC_REG_AV_VR8, 0, 4); + case PPC_REG_AV_VR9: return RegisterInfo(PPC_REG_AV_VR9, 0, 4); + case PPC_REG_AV_VR10: return RegisterInfo(PPC_REG_AV_VR10, 0, 4); + case PPC_REG_AV_VR11: return RegisterInfo(PPC_REG_AV_VR11, 0, 4); + case PPC_REG_AV_VR12: return RegisterInfo(PPC_REG_AV_VR12, 0, 4); + case PPC_REG_AV_VR13: return RegisterInfo(PPC_REG_AV_VR13, 0, 4); + case PPC_REG_AV_VR14: return RegisterInfo(PPC_REG_AV_VR14, 0, 4); + case PPC_REG_AV_VR15: return RegisterInfo(PPC_REG_AV_VR15, 0, 4); + case PPC_REG_AV_VR16: return RegisterInfo(PPC_REG_AV_VR16, 0, 4); + case PPC_REG_AV_VR17: return RegisterInfo(PPC_REG_AV_VR17, 0, 4); + case PPC_REG_AV_VR18: return RegisterInfo(PPC_REG_AV_VR18, 0, 4); + case PPC_REG_AV_VR19: return RegisterInfo(PPC_REG_AV_VR19, 0, 4); + case PPC_REG_AV_VR20: return RegisterInfo(PPC_REG_AV_VR20, 0, 4); + case PPC_REG_AV_VR21: return RegisterInfo(PPC_REG_AV_VR21, 0, 4); + case PPC_REG_AV_VR22: return RegisterInfo(PPC_REG_AV_VR22, 0, 4); + case PPC_REG_AV_VR23: return RegisterInfo(PPC_REG_AV_VR23, 0, 4); + case PPC_REG_AV_VR24: return RegisterInfo(PPC_REG_AV_VR24, 0, 4); + case PPC_REG_AV_VR25: return RegisterInfo(PPC_REG_AV_VR25, 0, 4); + case PPC_REG_AV_VR26: return RegisterInfo(PPC_REG_AV_VR26, 0, 4); + case PPC_REG_AV_VR27: return RegisterInfo(PPC_REG_AV_VR27, 0, 4); + case PPC_REG_AV_VR28: return RegisterInfo(PPC_REG_AV_VR28, 0, 4); + case PPC_REG_AV_VR29: return RegisterInfo(PPC_REG_AV_VR29, 0, 4); + case PPC_REG_AV_VR30: return RegisterInfo(PPC_REG_AV_VR30, 0, 4); + case PPC_REG_AV_VR31: return RegisterInfo(PPC_REG_AV_VR31, 0, 4); + + case PPC_REG_VSX_VR0: return RegisterInfo(PPC_REG_VSX_VR0, 0, 8); + case PPC_REG_VSX_VR1: return RegisterInfo(PPC_REG_VSX_VR1, 0, 8); + case PPC_REG_VSX_VR2: return RegisterInfo(PPC_REG_VSX_VR2, 0, 8); + case PPC_REG_VSX_VR3: return RegisterInfo(PPC_REG_VSX_VR3, 0, 8); + case PPC_REG_VSX_VR4: return RegisterInfo(PPC_REG_VSX_VR4, 0, 8); + case PPC_REG_VSX_VR5: return RegisterInfo(PPC_REG_VSX_VR5, 0, 8); + case PPC_REG_VSX_VR6: return RegisterInfo(PPC_REG_VSX_VR6, 0, 8); + case PPC_REG_VSX_VR7: return RegisterInfo(PPC_REG_VSX_VR7, 0, 8); + case PPC_REG_VSX_VR8: return RegisterInfo(PPC_REG_VSX_VR8, 0, 8); + case PPC_REG_VSX_VR9: return RegisterInfo(PPC_REG_VSX_VR9, 0, 8); + case PPC_REG_VSX_VR10: return RegisterInfo(PPC_REG_VSX_VR10, 0, 8); + case PPC_REG_VSX_VR11: return RegisterInfo(PPC_REG_VSX_VR11, 0, 8); + case PPC_REG_VSX_VR12: return RegisterInfo(PPC_REG_VSX_VR12, 0, 8); + case PPC_REG_VSX_VR13: return RegisterInfo(PPC_REG_VSX_VR13, 0, 8); + case PPC_REG_VSX_VR14: return RegisterInfo(PPC_REG_VSX_VR14, 0, 8); + case PPC_REG_VSX_VR15: return RegisterInfo(PPC_REG_VSX_VR15, 0, 8); + case PPC_REG_VSX_VR16: return RegisterInfo(PPC_REG_VSX_VR16, 0, 8); + case PPC_REG_VSX_VR17: return RegisterInfo(PPC_REG_VSX_VR17, 0, 8); + case PPC_REG_VSX_VR18: return RegisterInfo(PPC_REG_VSX_VR18, 0, 8); + case PPC_REG_VSX_VR19: return RegisterInfo(PPC_REG_VSX_VR19, 0, 8); + case PPC_REG_VSX_VR20: return RegisterInfo(PPC_REG_VSX_VR20, 0, 8); + case PPC_REG_VSX_VR21: return RegisterInfo(PPC_REG_VSX_VR21, 0, 8); + case PPC_REG_VSX_VR22: return RegisterInfo(PPC_REG_VSX_VR22, 0, 8); + case PPC_REG_VSX_VR23: return RegisterInfo(PPC_REG_VSX_VR23, 0, 8); + case PPC_REG_VSX_VR24: return RegisterInfo(PPC_REG_VSX_VR24, 0, 8); + case PPC_REG_VSX_VR25: return RegisterInfo(PPC_REG_VSX_VR25, 0, 8); + case PPC_REG_VSX_VR26: return RegisterInfo(PPC_REG_VSX_VR26, 0, 8); + case PPC_REG_VSX_VR27: return RegisterInfo(PPC_REG_VSX_VR27, 0, 8); + case PPC_REG_VSX_VR28: return RegisterInfo(PPC_REG_VSX_VR28, 0, 8); + case PPC_REG_VSX_VR29: return RegisterInfo(PPC_REG_VSX_VR29, 0, 8); + case PPC_REG_VSX_VR30: return RegisterInfo(PPC_REG_VSX_VR30, 0, 8); + case PPC_REG_VSX_VR31: return RegisterInfo(PPC_REG_VSX_VR31, 0, 8); + case PPC_REG_VSX_VR32: return RegisterInfo(PPC_REG_VSX_VR32, 0, 8); + case PPC_REG_VSX_VR33: return RegisterInfo(PPC_REG_VSX_VR33, 0, 8); + case PPC_REG_VSX_VR34: return RegisterInfo(PPC_REG_VSX_VR34, 0, 8); + case PPC_REG_VSX_VR35: return RegisterInfo(PPC_REG_VSX_VR35, 0, 8); + case PPC_REG_VSX_VR36: return RegisterInfo(PPC_REG_VSX_VR36, 0, 8); + case PPC_REG_VSX_VR37: return RegisterInfo(PPC_REG_VSX_VR37, 0, 8); + case PPC_REG_VSX_VR38: return RegisterInfo(PPC_REG_VSX_VR38, 0, 8); + case PPC_REG_VSX_VR39: return RegisterInfo(PPC_REG_VSX_VR39, 0, 8); + case PPC_REG_VSX_VR40: return RegisterInfo(PPC_REG_VSX_VR40, 0, 8); + case PPC_REG_VSX_VR41: return RegisterInfo(PPC_REG_VSX_VR41, 0, 8); + case PPC_REG_VSX_VR42: return RegisterInfo(PPC_REG_VSX_VR42, 0, 8); + case PPC_REG_VSX_VR43: return RegisterInfo(PPC_REG_VSX_VR43, 0, 8); + case PPC_REG_VSX_VR44: return RegisterInfo(PPC_REG_VSX_VR44, 0, 8); + case PPC_REG_VSX_VR45: return RegisterInfo(PPC_REG_VSX_VR45, 0, 8); + case PPC_REG_VSX_VR46: return RegisterInfo(PPC_REG_VSX_VR46, 0, 8); + case PPC_REG_VSX_VR47: return RegisterInfo(PPC_REG_VSX_VR47, 0, 8); + case PPC_REG_VSX_VR48: return RegisterInfo(PPC_REG_VSX_VR48, 0, 8); + case PPC_REG_VSX_VR49: return RegisterInfo(PPC_REG_VSX_VR49, 0, 8); + case PPC_REG_VSX_VR50: return RegisterInfo(PPC_REG_VSX_VR50, 0, 8); + case PPC_REG_VSX_VR51: return RegisterInfo(PPC_REG_VSX_VR51, 0, 8); + case PPC_REG_VSX_VR52: return RegisterInfo(PPC_REG_VSX_VR52, 0, 8); + case PPC_REG_VSX_VR53: return RegisterInfo(PPC_REG_VSX_VR53, 0, 8); + case PPC_REG_VSX_VR54: return RegisterInfo(PPC_REG_VSX_VR54, 0, 8); + case PPC_REG_VSX_VR55: return RegisterInfo(PPC_REG_VSX_VR55, 0, 8); + case PPC_REG_VSX_VR56: return RegisterInfo(PPC_REG_VSX_VR56, 0, 8); + case PPC_REG_VSX_VR57: return RegisterInfo(PPC_REG_VSX_VR57, 0, 8); + case PPC_REG_VSX_VR58: return RegisterInfo(PPC_REG_VSX_VR58, 0, 8); + case PPC_REG_VSX_VR59: return RegisterInfo(PPC_REG_VSX_VR59, 0, 8); + case PPC_REG_VSX_VR60: return RegisterInfo(PPC_REG_VSX_VR60, 0, 8); + case PPC_REG_VSX_VR61: return RegisterInfo(PPC_REG_VSX_VR61, 0, 8); + case PPC_REG_VSX_VR62: return RegisterInfo(PPC_REG_VSX_VR62, 0, 8); + case PPC_REG_VSX_VR63: return RegisterInfo(PPC_REG_VSX_VR63, 0, 8); + + case PPC_REG_GQR0: return RegisterInfo(PPC_REG_GQR0, 0, 4); + case PPC_REG_GQR1: return RegisterInfo(PPC_REG_GQR1, 0, 4); + case PPC_REG_GQR2: return RegisterInfo(PPC_REG_GQR2, 0, 4); + case PPC_REG_GQR3: return RegisterInfo(PPC_REG_GQR3, 0, 4); + case PPC_REG_GQR4: return RegisterInfo(PPC_REG_GQR4, 0, 4); + case PPC_REG_GQR5: return RegisterInfo(PPC_REG_GQR5, 0, 4); + case PPC_REG_GQR6: return RegisterInfo(PPC_REG_GQR6, 0, 4); + case PPC_REG_GQR7: return RegisterInfo(PPC_REG_GQR7, 0, 4); + default: //LogError("%s(%d == \"%s\") invalid argument", __func__, - // regId, powerpc_reg_to_str(regId)); + // regId, PowerPCRegisterName(regId)); return RegisterInfo(0,0,0); } } @@ -1814,7 +1802,7 @@ class PowerpcArchitecture: public Architecture virtual uint32_t GetStackPointerRegister() override { //MYLOG("%s()\n", __func__); - return PPC_REG_R1; + return PPC_REG_GPR1; } virtual uint32_t GetLinkRegister() override @@ -2257,8 +2245,8 @@ class PpcSvr4CallingConvention: public CallingConvention virtual vector GetIntegerArgumentRegisters() override { return vector{ - PPC_REG_R3, PPC_REG_R4, PPC_REG_R5, PPC_REG_R6, - PPC_REG_R7, PPC_REG_R8, PPC_REG_R9, PPC_REG_R10 + PPC_REG_GPR3, PPC_REG_GPR4, PPC_REG_GPR5, PPC_REG_GPR6, + PPC_REG_GPR7, PPC_REG_GPR8, PPC_REG_GPR9, PPC_REG_GPR10 /* remaining arguments onto stack */ }; } @@ -2267,10 +2255,10 @@ class PpcSvr4CallingConvention: public CallingConvention virtual vector GetFloatArgumentRegisters() override { return vector{ - PPC_REG_F1, PPC_REG_F2, PPC_REG_F3, PPC_REG_F4, - PPC_REG_F5, PPC_REG_F6, PPC_REG_F7, PPC_REG_F8, - PPC_REG_F9, PPC_REG_F10, PPC_REG_F11, PPC_REG_F12, - PPC_REG_F13 + PPC_REG_FR1, PPC_REG_FR2, PPC_REG_FR3, PPC_REG_FR4, + PPC_REG_FR5, PPC_REG_FR6, PPC_REG_FR7, PPC_REG_FR8, + PPC_REG_FR9, PPC_REG_FR10, PPC_REG_FR11, PPC_REG_FR12, + PPC_REG_FR13 }; } @@ -2278,14 +2266,14 @@ class PpcSvr4CallingConvention: public CallingConvention virtual vector GetCallerSavedRegisters() override { return vector{ - PPC_REG_R0, PPC_REG_R2, PPC_REG_R3, PPC_REG_R4, - PPC_REG_R5, PPC_REG_R6, PPC_REG_R7, PPC_REG_R8, - PPC_REG_R9, PPC_REG_R10, PPC_REG_R12, + PPC_REG_GPR0, PPC_REG_GPR2, PPC_REG_GPR3, PPC_REG_GPR4, + PPC_REG_GPR5, PPC_REG_GPR6, PPC_REG_GPR7, PPC_REG_GPR8, + PPC_REG_GPR9, PPC_REG_GPR10, PPC_REG_GPR12, - PPC_REG_F0, PPC_REG_F1, PPC_REG_F2, PPC_REG_F3, - PPC_REG_F4, PPC_REG_F5, PPC_REG_F6, PPC_REG_F7, - PPC_REG_F8, PPC_REG_F9, PPC_REG_F10, PPC_REG_F11, - PPC_REG_F12, PPC_REG_F13, + PPC_REG_FR0, PPC_REG_FR1, PPC_REG_FR2, PPC_REG_FR3, + PPC_REG_FR4, PPC_REG_FR5, PPC_REG_FR6, PPC_REG_FR7, + PPC_REG_FR8, PPC_REG_FR9, PPC_REG_FR10, PPC_REG_FR11, + PPC_REG_FR12, PPC_REG_FR13, PPC_REG_LR, PPC_REG_CTR, }; @@ -2295,30 +2283,30 @@ class PpcSvr4CallingConvention: public CallingConvention virtual vector GetCalleeSavedRegisters() override { return vector{ - PPC_REG_R14, PPC_REG_R15, PPC_REG_R16, PPC_REG_R17, - PPC_REG_R18, PPC_REG_R19, PPC_REG_R20, PPC_REG_R21, - PPC_REG_R22, PPC_REG_R23, PPC_REG_R24, PPC_REG_R25, - PPC_REG_R26, PPC_REG_R27, PPC_REG_R28, PPC_REG_R29, - PPC_REG_R30, PPC_REG_R31 + PPC_REG_GPR14, PPC_REG_GPR15, PPC_REG_GPR16, PPC_REG_GPR17, + PPC_REG_GPR18, PPC_REG_GPR19, PPC_REG_GPR20, PPC_REG_GPR21, + PPC_REG_GPR22, PPC_REG_GPR23, PPC_REG_GPR24, PPC_REG_GPR25, + PPC_REG_GPR26, PPC_REG_GPR27, PPC_REG_GPR28, PPC_REG_GPR29, + PPC_REG_GPR30, PPC_REG_GPR31 }; } virtual uint32_t GetGlobalPointerRegister() override { - return PPC_REG_R13; + return PPC_REG_GPR13; } virtual uint32_t GetIntegerReturnValueRegister() override { - return PPC_REG_R3; + return PPC_REG_GPR3; } virtual uint32_t GetFloatReturnValueRegister() override { - return PPC_REG_F1; + return PPC_REG_FR1; } }; @@ -2332,33 +2320,33 @@ class PpcLinuxSyscallCallingConvention: public CallingConvention virtual vector GetIntegerArgumentRegisters() override { return vector{ - PPC_REG_R0, - PPC_REG_R3, PPC_REG_R4, PPC_REG_R5, PPC_REG_R6, - PPC_REG_R7, PPC_REG_R8, PPC_REG_R9, PPC_REG_R10 + PPC_REG_GPR0, + PPC_REG_GPR3, PPC_REG_GPR4, PPC_REG_GPR5, PPC_REG_GPR6, + PPC_REG_GPR7, PPC_REG_GPR8, PPC_REG_GPR9, PPC_REG_GPR10 }; } virtual vector GetCallerSavedRegisters() override { return vector{ - PPC_REG_R3 + PPC_REG_GPR3 }; } virtual vector GetCalleeSavedRegisters() override { - return vector{ - PPC_REG_R14, PPC_REG_R15, PPC_REG_R16, PPC_REG_R17, - PPC_REG_R18, PPC_REG_R19, PPC_REG_R20, PPC_REG_R21, - PPC_REG_R22, PPC_REG_R23, PPC_REG_R24, PPC_REG_R25, - PPC_REG_R26, PPC_REG_R27, PPC_REG_R28, PPC_REG_R29, - PPC_REG_R30, PPC_REG_R31 + return vector { + PPC_REG_GPR14, PPC_REG_GPR15, PPC_REG_GPR16, PPC_REG_GPR17, + PPC_REG_GPR18, PPC_REG_GPR19, PPC_REG_GPR20, PPC_REG_GPR21, + PPC_REG_GPR22, PPC_REG_GPR23, PPC_REG_GPR24, PPC_REG_GPR25, + PPC_REG_GPR26, PPC_REG_GPR27, PPC_REG_GPR28, PPC_REG_GPR29, + PPC_REG_GPR30, PPC_REG_GPR31 }; } virtual uint32_t GetIntegerReturnValueRegister() override { - return PPC_REG_R3; + return PPC_REG_GPR3; } virtual bool IsEligibleForHeuristics() override @@ -2554,13 +2542,13 @@ extern "C" Architecture* ppc = new PowerpcArchitecture("ppc", BigEndian); Architecture::Register(ppc); - Architecture* ppc_qpx = new PowerpcArchitecture("ppc_qpx", BigEndian, 4, CS_MODE_QPX); + Architecture* ppc_qpx = new PowerpcArchitecture("ppc_qpx", BigEndian, 4, DECODE_FLAGS_QPX); Architecture::Register(ppc_qpx); - Architecture* ppc_spe = new PowerpcArchitecture("ppc_spe", BigEndian, 4, CS_MODE_SPE); + Architecture* ppc_spe = new PowerpcArchitecture("ppc_spe", BigEndian, 4, DECODE_FLAGS_SPE); Architecture::Register(ppc_spe); - Architecture* ppc_ps = new PowerpcArchitecture("ppc_ps", BigEndian, 4, CS_MODE_PS); + Architecture* ppc_ps = new PowerpcArchitecture("ppc_ps", BigEndian, 4, DECODE_FLAGS_PS); Architecture::Register(ppc_ps); Architecture* ppc64 = new PowerpcArchitecture("ppc64", BigEndian, 8); diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c index 7db2371d7..86bd39761 100644 --- a/arch/powerpc/decode/decode.c +++ b/arch/powerpc/decode/decode.c @@ -25,32 +25,27 @@ static void CopyOperand(Operand* dst, const Operand* src) static Register Gpr(uint32_t value) { - return NUPPC_REG_GPR0 + value; + return PPC_REG_GPR0 + value; } static Register Fr(uint32_t value) { - return NUPPC_REG_FR0 + value; + return PPC_REG_FR0 + value; } static Register Crf(uint32_t value) { - return NUPPC_REG_CRF0 + value; -} - -static Register Crbit(uint32_t value) -{ - return NUPPC_REG_CR_BIT0 + value; + return PPC_REG_CRF0 + value; } static Register AltivecVr(uint32_t value) { - return NUPPC_REG_AV_VR0 + value; + return PPC_REG_AV_VR0 + value; } static Register VsxVr(uint32_t value) { - return NUPPC_REG_VSX_VR0 + value; + return PPC_REG_VSX_VR0 + value; } static void PushUIMMValue(Instruction* instruction, uint32_t uimm) @@ -180,33 +175,44 @@ static void PushCRFD(Instruction* instruction, uint32_t word32) PushRegister(instruction, PPC_OP_REG_CRFD, Crf(crfd)); } +static void PushCRFDImplyCR0(Instruction* instruction, uint32_t word32) +{ + uint32_t crfd = (word32 >> 23) & 0x7; + + PushRegister(instruction, PPC_OP_REG_CRFD_IMPLY0, Crf(crfd)); +} + static void PushCRFS(Instruction* instruction, uint32_t word32) { uint32_t crfs = (word32 >> 18) & 0x7; PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crfs)); } -static void PushCRFDImplyCR0(Instruction* instruction, uint32_t word32) +static void PushCRFSImply0(Instruction* instruction, uint32_t word32) { - uint32_t crfd = (word32 >> 23) & 0x7; - - if (crfd) - PushRegister(instruction, PPC_OP_REG_CRFD, Crf(crfd)); + uint32_t crfs = (word32 >> 18) & 0x7; + PushRegister(instruction, PPC_OP_REG_CRFS_IMPLY0, Crf(crfs)); } static void PushCRBitA(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, PPC_OP_REG_CRBA, Crbit(GetA(word32))); + instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_A; + instruction->operands[instruction->numOperands].crbit = GetA(word32); + ++instruction->numOperands; } static void PushCRBitB(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, PPC_OP_REG_CRBB, Crbit(GetB(word32))); + instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_B; + instruction->operands[instruction->numOperands].crbit = GetB(word32); + ++instruction->numOperands; } static void PushCRBitD(Instruction* instruction, uint32_t word32) { - PushRegister(instruction, PPC_OP_REG_CRBD, Crbit(GetD(word32))); + instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_D; + instruction->operands[instruction->numOperands].crbit = GetD(word32); + ++instruction->numOperands; } static void PushMem(Instruction* instruction, OperandClass cls, Register reg, int32_t offset) @@ -1254,7 +1260,13 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 8: return PPC_ID_TWGT; case 16: return PPC_ID_TWLT; case 24: return PPC_ID_TWNE; - case 31: return PPC_ID_TWU; + case 31: + { + if ((GetA(word32) == 0) && (GetB(word32) == 0)) + return PPC_ID_TRAP; + + return PPC_ID_TWU; + } default: return PPC_ID_TW; } } @@ -2908,6 +2920,9 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) case 0x39: return PPC_ID_VSX_XSMSUBMDP; + case 0x3a: + return PPC_ID_VSX_XXPERMR; + case 0x3d: if ((word32 & 0x00600001) != 0) return PPC_ID_INVALID; @@ -3177,12 +3192,6 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FCTIWZx; - case 0x020: - if ((word32 & 0x00600000) != 0) - return PPC_ID_INVALID; - - return PPC_ID_FCMPO; - case 0x024: case 0x025: return PPC_ID_FDIVx; @@ -3216,6 +3225,12 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FRSQRTEx; + case 0x040: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCMPO; + case 0x04c: case 0x04d: if ((a != 0) || (b != 0)) @@ -3694,6 +3709,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_RFMCI: case PPC_ID_TLBIA: case PPC_ID_TLBSYNC: + case PPC_ID_TRAP: case PPC_ID_SLBIA: case PPC_ID_XNOP: case PPC_ID_WAITIMPL: @@ -4097,7 +4113,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_LWZUX: case PPC_ID_LWZX: PushRD(instruction, word32); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; @@ -4441,10 +4457,11 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add instruction->flags.lk = word32 & 0x1; instruction->flags.aa = (word32 & 0x2) != 0; - uint32_t li = word32 & 0x03fffffc; - uint32_t target = instruction->flags.aa ? li : address + li; + uint64_t li = word32 & 0x03fffffc; + li = (uint64_t)(int64_t)sign_extend(li, 26); + uint64_t target = instruction->flags.aa ? li : address + li; - PushUIMMValue(instruction, target); + PushLabel(instruction, target); break; } @@ -4488,10 +4505,8 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_LIS: { - int32_t shifted_value = (int32_t)((word32 & 0xffff) << 16); - PushRD(instruction, word32); - PushSIMMValue(instruction, shifted_value); + PushSIMMValue(instruction, (int32_t)(word32 & 0xffff)); break; } @@ -5034,6 +5049,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_VSX_XXMRGHW: case PPC_ID_VSX_XXMRGLD: case PPC_ID_VSX_XXMRGLW: + case PPC_ID_VSX_XXPERMR: PushVsxD(instruction, word32, VSX_WIDTH_FULL); PushVsxA(instruction, word32, VSX_WIDTH_FULL); PushVsxB(instruction, word32, VSX_WIDTH_FULL); @@ -5580,7 +5596,7 @@ void FillBcxOperands(OperandsList* bcx, const Instruction* instruction) { uint32_t crn = bi >> 2; - bcx->operands[0].cls = PPC_OP_REG_CRFS; + bcx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0; bcx->operands[0].reg = Crf(crn); CopyOperand(&bcx->operands[1], &instruction->operands[2]); bcx->numOperands = 2; @@ -5631,7 +5647,7 @@ void FillBcctrxOperands(OperandsList* bcctrx, const Instruction* instruction) { uint32_t crn = bi >> 2; - bcctrx->operands[0].cls = PPC_OP_REG_CRFS; + bcctrx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0; bcctrx->operands[0].reg = Crf(crn); bcctrx->numOperands = 1; break; @@ -5681,7 +5697,7 @@ void FillBclrxOperands(OperandsList* bclrx, const Instruction* instruction) { uint32_t crn = bi >> 2; - bclrx->operands[0].cls = PPC_OP_REG_CRFS; + bclrx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0; bclrx->operands[0].reg = Crf(crn); bclrx->numOperands = 1; break; @@ -6283,6 +6299,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_TLBWE: return "tlbwe"; case PPC_ID_TLBWEHI: return "tlbwehi"; case PPC_ID_TLBWELO: return "tlbwelo"; + case PPC_ID_TRAP: return "trap"; case PPC_ID_TW: return "tw"; case PPC_ID_TWEQ: return "tweq"; case PPC_ID_TWEQI: return "tweqi"; @@ -6668,12 +6685,22 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_VSX_XXLOR: return "xxlor"; case PPC_ID_VSX_XXLXOR: return "xxlxor"; case PPC_ID_VSX_XXPERMDI: return "xxpermdi"; + case PPC_ID_VSX_XXPERMR: return "xxpermr"; case PPC_ID_VSX_XXSEL: return "xxsel"; case PPC_ID_VSX_XXSLDWI: return "xxsldwi"; case PPC_ID_VSX_XXSPLTD: return "xxspltd"; case PPC_ID_VSX_XXSPLTW: return "xxspltw"; case PPC_ID_VSX_XXSWAPD: return "xxswapd"; + case PPC_ID_PSQ_L: return "psq_l"; + case PPC_ID_PSQ_LU: return "psq_lu"; + case PPC_ID_PSQ_LUX: return "psq_lux"; + case PPC_ID_PSQ_LX: return "psq_lx"; + case PPC_ID_PSQ_ST: return "psq_st"; + case PPC_ID_PSQ_STU: return "psq_stu"; + case PPC_ID_PSQ_STUX: return "psq_stux"; + case PPC_ID_PSQ_STX: return "psq_stx"; + default: return NULL; } } @@ -6690,3 +6717,292 @@ bool Decompose(Instruction* instruction, uint32_t word32, uint64_t address, uint FillOperands(instruction, word32, address); return true; } + +const char* PowerPCRegisterName(uint32_t regId) +{ + switch (regId) + { + case PPC_REG_GPR0: return "r0"; + case PPC_REG_GPR1: return "r1"; + case PPC_REG_GPR2: return "r2"; + case PPC_REG_GPR3: return "r3"; + case PPC_REG_GPR4: return "r4"; + case PPC_REG_GPR5: return "r5"; + case PPC_REG_GPR6: return "r6"; + case PPC_REG_GPR7: return "r7"; + case PPC_REG_GPR8: return "r8"; + case PPC_REG_GPR9: return "r9"; + case PPC_REG_GPR10: return "r10"; + case PPC_REG_GPR11: return "r11"; + case PPC_REG_GPR12: return "r12"; + case PPC_REG_GPR13: return "r13"; + case PPC_REG_GPR14: return "r14"; + case PPC_REG_GPR15: return "r15"; + case PPC_REG_GPR16: return "r16"; + case PPC_REG_GPR17: return "r17"; + case PPC_REG_GPR18: return "r18"; + case PPC_REG_GPR19: return "r19"; + case PPC_REG_GPR20: return "r20"; + case PPC_REG_GPR21: return "r21"; + case PPC_REG_GPR22: return "r22"; + case PPC_REG_GPR23: return "r23"; + case PPC_REG_GPR24: return "r24"; + case PPC_REG_GPR25: return "r25"; + case PPC_REG_GPR26: return "r26"; + case PPC_REG_GPR27: return "r27"; + case PPC_REG_GPR28: return "r28"; + case PPC_REG_GPR29: return "r29"; + case PPC_REG_GPR30: return "r30"; + case PPC_REG_GPR31: return "r31"; + + case PPC_REG_XER: return "xer"; + case PPC_REG_LR: return "lr"; + case PPC_REG_CTR: return "ctr"; + + case PPC_REG_FR0: return "f0"; + case PPC_REG_FR1: return "f1"; + case PPC_REG_FR2: return "f2"; + case PPC_REG_FR3: return "f3"; + case PPC_REG_FR4: return "f4"; + case PPC_REG_FR5: return "f5"; + case PPC_REG_FR6: return "f6"; + case PPC_REG_FR7: return "f7"; + case PPC_REG_FR8: return "f8"; + case PPC_REG_FR9: return "f9"; + case PPC_REG_FR10: return "f10"; + case PPC_REG_FR11: return "f11"; + case PPC_REG_FR12: return "f12"; + case PPC_REG_FR13: return "f13"; + case PPC_REG_FR14: return "f14"; + case PPC_REG_FR15: return "f15"; + case PPC_REG_FR16: return "f16"; + case PPC_REG_FR17: return "f17"; + case PPC_REG_FR18: return "f18"; + case PPC_REG_FR19: return "f19"; + case PPC_REG_FR20: return "f20"; + case PPC_REG_FR21: return "f21"; + case PPC_REG_FR22: return "f22"; + case PPC_REG_FR23: return "f23"; + case PPC_REG_FR24: return "f24"; + case PPC_REG_FR25: return "f25"; + case PPC_REG_FR26: return "f26"; + case PPC_REG_FR27: return "f27"; + case PPC_REG_FR28: return "f28"; + case PPC_REG_FR29: return "f29"; + case PPC_REG_FR30: return "f30"; + case PPC_REG_FR31: return "f31"; + + case PPC_REG_CRF0: return "cr0"; + case PPC_REG_CRF1: return "cr1"; + case PPC_REG_CRF2: return "cr2"; + case PPC_REG_CRF3: return "cr3"; + case PPC_REG_CRF4: return "cr4"; + case PPC_REG_CRF5: return "cr5"; + case PPC_REG_CRF6: return "cr6"; + case PPC_REG_CRF7: return "cr7"; + + case PPC_REG_AV_VR0: return "v0"; + case PPC_REG_AV_VR1: return "v1"; + case PPC_REG_AV_VR2: return "v2"; + case PPC_REG_AV_VR3: return "v3"; + case PPC_REG_AV_VR4: return "v4"; + case PPC_REG_AV_VR5: return "v5"; + case PPC_REG_AV_VR6: return "v6"; + case PPC_REG_AV_VR7: return "v7"; + case PPC_REG_AV_VR8: return "v8"; + case PPC_REG_AV_VR9: return "v9"; + case PPC_REG_AV_VR10: return "v10"; + case PPC_REG_AV_VR11: return "v11"; + case PPC_REG_AV_VR12: return "v12"; + case PPC_REG_AV_VR13: return "v13"; + case PPC_REG_AV_VR14: return "v14"; + case PPC_REG_AV_VR15: return "v15"; + case PPC_REG_AV_VR16: return "v16"; + case PPC_REG_AV_VR17: return "v17"; + case PPC_REG_AV_VR18: return "v18"; + case PPC_REG_AV_VR19: return "v19"; + case PPC_REG_AV_VR20: return "v20"; + case PPC_REG_AV_VR21: return "v21"; + case PPC_REG_AV_VR22: return "v22"; + case PPC_REG_AV_VR23: return "v23"; + case PPC_REG_AV_VR24: return "v24"; + case PPC_REG_AV_VR25: return "v25"; + case PPC_REG_AV_VR26: return "v26"; + case PPC_REG_AV_VR27: return "v27"; + case PPC_REG_AV_VR28: return "v28"; + case PPC_REG_AV_VR29: return "v29"; + case PPC_REG_AV_VR30: return "v30"; + case PPC_REG_AV_VR31: return "v31"; + + case PPC_REG_VSX_VR0: return "vs0"; + case PPC_REG_VSX_VR1: return "vs1"; + case PPC_REG_VSX_VR2: return "vs2"; + case PPC_REG_VSX_VR3: return "vs3"; + case PPC_REG_VSX_VR4: return "vs4"; + case PPC_REG_VSX_VR5: return "vs5"; + case PPC_REG_VSX_VR6: return "vs6"; + case PPC_REG_VSX_VR7: return "vs7"; + case PPC_REG_VSX_VR8: return "vs8"; + case PPC_REG_VSX_VR9: return "vs9"; + case PPC_REG_VSX_VR10: return "vs10"; + case PPC_REG_VSX_VR11: return "vs11"; + case PPC_REG_VSX_VR12: return "vs12"; + case PPC_REG_VSX_VR13: return "vs13"; + case PPC_REG_VSX_VR14: return "vs14"; + case PPC_REG_VSX_VR15: return "vs15"; + case PPC_REG_VSX_VR16: return "vs16"; + case PPC_REG_VSX_VR17: return "vs17"; + case PPC_REG_VSX_VR18: return "vs18"; + case PPC_REG_VSX_VR19: return "vs19"; + case PPC_REG_VSX_VR20: return "vs20"; + case PPC_REG_VSX_VR21: return "vs21"; + case PPC_REG_VSX_VR22: return "vs22"; + case PPC_REG_VSX_VR23: return "vs23"; + case PPC_REG_VSX_VR24: return "vs24"; + case PPC_REG_VSX_VR25: return "vs25"; + case PPC_REG_VSX_VR26: return "vs26"; + case PPC_REG_VSX_VR27: return "vs27"; + case PPC_REG_VSX_VR28: return "vs28"; + case PPC_REG_VSX_VR29: return "vs29"; + case PPC_REG_VSX_VR30: return "vs30"; + case PPC_REG_VSX_VR31: return "vs31"; + case PPC_REG_VSX_VR32: return "vs32"; + case PPC_REG_VSX_VR33: return "vs33"; + case PPC_REG_VSX_VR34: return "vs34"; + case PPC_REG_VSX_VR35: return "vs35"; + case PPC_REG_VSX_VR36: return "vs36"; + case PPC_REG_VSX_VR37: return "vs37"; + case PPC_REG_VSX_VR38: return "vs38"; + case PPC_REG_VSX_VR39: return "vs39"; + case PPC_REG_VSX_VR40: return "vs40"; + case PPC_REG_VSX_VR41: return "vs41"; + case PPC_REG_VSX_VR42: return "vs42"; + case PPC_REG_VSX_VR43: return "vs43"; + case PPC_REG_VSX_VR44: return "vs44"; + case PPC_REG_VSX_VR45: return "vs45"; + case PPC_REG_VSX_VR46: return "vs46"; + case PPC_REG_VSX_VR47: return "vs47"; + case PPC_REG_VSX_VR48: return "vs48"; + case PPC_REG_VSX_VR49: return "vs49"; + case PPC_REG_VSX_VR50: return "vs50"; + case PPC_REG_VSX_VR51: return "vs51"; + case PPC_REG_VSX_VR52: return "vs52"; + case PPC_REG_VSX_VR53: return "vs53"; + case PPC_REG_VSX_VR54: return "vs54"; + case PPC_REG_VSX_VR55: return "vs55"; + case PPC_REG_VSX_VR56: return "vs56"; + case PPC_REG_VSX_VR57: return "vs57"; + case PPC_REG_VSX_VR58: return "vs58"; + case PPC_REG_VSX_VR59: return "vs59"; + case PPC_REG_VSX_VR60: return "vs60"; + case PPC_REG_VSX_VR61: return "vs61"; + case PPC_REG_VSX_VR62: return "vs62"; + case PPC_REG_VSX_VR63: return "vs63"; + + case PPC_REG_GQR0: return "gqr0"; + case PPC_REG_GQR1: return "gqr1"; + case PPC_REG_GQR2: return "gqr2"; + case PPC_REG_GQR3: return "gqr3"; + case PPC_REG_GQR4: return "gqr4"; + case PPC_REG_GQR5: return "gqr5"; + case PPC_REG_GQR6: return "gqr6"; + case PPC_REG_GQR7: return "gqr7"; + + default: return NULL; + } +} + +const char* OperandClassName(uint32_t cls) +{ + switch (cls) + { + case PPC_OP_NONE: return ""; + case PPC_OP_UIMM: return "UIMM"; + case PPC_OP_SIMM: return "SIMM"; + case PPC_OP_LABEL: return "LABEL"; + case PPC_OP_MEM_RA: return "MEM(RA)"; + + case PPC_OP_REG_RA: return "RA"; + case PPC_OP_REG_RB: return "RB"; + case PPC_OP_REG_RD: return "RD"; + case PPC_OP_REG_RS: return "RS"; + + case PPC_OP_REG_FRA: return "FRA"; + case PPC_OP_REG_FRB: return "FRB"; + case PPC_OP_REG_FRC: return "FRC"; + case PPC_OP_REG_FRD: return "FRD"; + case PPC_OP_REG_FRS: return "FRS"; + + case PPC_OP_REG_CRFD: return "CRFD"; + case PPC_OP_REG_CRFD_IMPLY0: return "CRFD"; + case PPC_OP_REG_CRFS: return "CRFS"; + case PPC_OP_CRBIT_A: return "CRBIT_A"; + case PPC_OP_CRBIT_B: return "CRBIT_B"; + case PPC_OP_CRBIT_D: return "CRBIT_C"; + + case PPC_OP_REG_AV_VA: return "ALTIVEC_VA"; + case PPC_OP_REG_AV_VB: return "ALTIVEC_VB"; + case PPC_OP_REG_AV_VC: return "ALTIVEC_VC"; + case PPC_OP_REG_AV_VD: return "ALTIVEC_VD"; + case PPC_OP_REG_AV_VS: return "ALTIVEC_VS"; + + case PPC_OP_REG_VSX_RA: return "VSX_RA"; + case PPC_OP_REG_VSX_RA_DWORD0: return "VSX_RA0"; + + case PPC_OP_REG_VSX_RB: return "VSX_RB"; + case PPC_OP_REG_VSX_RB_DWORD0: return "VSX_RB0"; + + case PPC_OP_REG_VSX_RC: return "VSX_RC"; + case PPC_OP_REG_VSX_RC_DWORD0: return "VSX_RC0"; + + case PPC_OP_REG_VSX_RD: return "VSX_RD"; + case PPC_OP_REG_VSX_RD_DWORD0: return "VSX_RD0"; + + case PPC_OP_REG_VSX_RS: return "VSX_RS"; + case PPC_OP_REG_VSX_RS_DWORD0: return "VSX_RS0"; + + return "???"; + } +} + +// These match the names in the "Condition Register" section +const char* GetCRBitName(uint32_t crbit) +{ + switch (crbit) + { + case 0: return "lt"; + case 1: return "gt"; + case 2: return "eq"; + case 3: return "so"; + case 4: return "cr1lt"; + case 5: return "cr1gt"; + case 6: return "cr1eq"; + case 7: return "cr1so"; + case 8: return "cr2lt"; + case 9: return "cr2gt"; + case 10: return "cr2eq"; + case 11: return "cr2so"; + case 12: return "cr3lt"; + case 13: return "cr3gt"; + case 14: return "cr3eq"; + case 15: return "cr3so"; + case 16: return "cr4lt"; + case 17: return "cr4gt"; + case 18: return "cr4eq"; + case 19: return "cr4so"; + case 20: return "cr5lt"; + case 21: return "cr5gt"; + case 22: return "cr5eq"; + case 23: return "cr5so"; + case 24: return "cr6lt"; + case 25: return "cr6gt"; + case 26: return "cr6eq"; + case 27: return "cr6so"; + case 28: return "cr7lt"; + case 29: return "cr7gt"; + case 30: return "cr7eq"; + case 31: return "cr7so"; + default: + return NULL; + } +} diff --git a/arch/powerpc/decode/decode.h b/arch/powerpc/decode/decode.h index a235f48d7..92c6bbf2e 100644 --- a/arch/powerpc/decode/decode.h +++ b/arch/powerpc/decode/decode.h @@ -8,223 +8,201 @@ #define DECODE_FLAGS_PPC64 0x01 #define DECODE_FLAGS_ALTIVEC 0x02 #define DECODE_FLAGS_VSX 0x04 +#define DECODE_FLAGS_QPX 0x08 +#define DECODE_FLAGS_PS 0x10 +#define DECODE_FLAGS_SPE 0x20 #ifdef __cplusplus extern "C" { #endif enum Register { - NUPPC_REG_GPR0, - NUPPC_REG_GPR1, - NUPPC_REG_GPR2, - NUPPC_REG_GPR3, - NUPPC_REG_GPR4, - NUPPC_REG_GPR5, - NUPPC_REG_GPR6, - NUPPC_REG_GPR7, - NUPPC_REG_GPR8, - NUPPC_REG_GPR9, - NUPPC_REG_GPR10, - NUPPC_REG_GPR11, - NUPPC_REG_GPR12, - NUPPC_REG_GPR13, - NUPPC_REG_GPR14, - NUPPC_REG_GPR15, - NUPPC_REG_GPR16, - NUPPC_REG_GPR17, - NUPPC_REG_GPR18, - NUPPC_REG_GPR19, - NUPPC_REG_GPR20, - NUPPC_REG_GPR21, - NUPPC_REG_GPR22, - NUPPC_REG_GPR23, - NUPPC_REG_GPR24, - NUPPC_REG_GPR25, - NUPPC_REG_GPR26, - NUPPC_REG_GPR27, - NUPPC_REG_GPR28, - NUPPC_REG_GPR29, - NUPPC_REG_GPR30, - NUPPC_REG_GPR31, + PPC_REG_GPR0, + PPC_REG_GPR1, + PPC_REG_GPR2, + PPC_REG_GPR3, + PPC_REG_GPR4, + PPC_REG_GPR5, + PPC_REG_GPR6, + PPC_REG_GPR7, + PPC_REG_GPR8, + PPC_REG_GPR9, + PPC_REG_GPR10, + PPC_REG_GPR11, + PPC_REG_GPR12, + PPC_REG_GPR13, + PPC_REG_GPR14, + PPC_REG_GPR15, + PPC_REG_GPR16, + PPC_REG_GPR17, + PPC_REG_GPR18, + PPC_REG_GPR19, + PPC_REG_GPR20, + PPC_REG_GPR21, + PPC_REG_GPR22, + PPC_REG_GPR23, + PPC_REG_GPR24, + PPC_REG_GPR25, + PPC_REG_GPR26, + PPC_REG_GPR27, + PPC_REG_GPR28, + PPC_REG_GPR29, + PPC_REG_GPR30, + PPC_REG_GPR31, - NUPPC_REG_XER, - NUPPC_REG_LR, - NUPPC_REG_CTR, + PPC_REG_XER, + PPC_REG_LR, + PPC_REG_CTR, - NUPPC_REG_FR0, - NUPPC_REG_FR1, - NUPPC_REG_FR2, - NUPPC_REG_FR3, - NUPPC_REG_FR4, - NUPPC_REG_FR5, - NUPPC_REG_FR6, - NUPPC_REG_FR7, - NUPPC_REG_FR8, - NUPPC_REG_FR9, - NUPPC_REG_FR10, - NUPPC_REG_FR11, - NUPPC_REG_FR12, - NUPPC_REG_FR13, - NUPPC_REG_FR14, - NUPPC_REG_FR15, - NUPPC_REG_FR16, - NUPPC_REG_FR17, - NUPPC_REG_FR18, - NUPPC_REG_FR19, - NUPPC_REG_FR20, - NUPPC_REG_FR21, - NUPPC_REG_FR22, - NUPPC_REG_FR23, - NUPPC_REG_FR24, - NUPPC_REG_FR25, - NUPPC_REG_FR26, - NUPPC_REG_FR27, - NUPPC_REG_FR28, - NUPPC_REG_FR29, - NUPPC_REG_FR30, - NUPPC_REG_FR31, + PPC_REG_FR0, + PPC_REG_FR1, + PPC_REG_FR2, + PPC_REG_FR3, + PPC_REG_FR4, + PPC_REG_FR5, + PPC_REG_FR6, + PPC_REG_FR7, + PPC_REG_FR8, + PPC_REG_FR9, + PPC_REG_FR10, + PPC_REG_FR11, + PPC_REG_FR12, + PPC_REG_FR13, + PPC_REG_FR14, + PPC_REG_FR15, + PPC_REG_FR16, + PPC_REG_FR17, + PPC_REG_FR18, + PPC_REG_FR19, + PPC_REG_FR20, + PPC_REG_FR21, + PPC_REG_FR22, + PPC_REG_FR23, + PPC_REG_FR24, + PPC_REG_FR25, + PPC_REG_FR26, + PPC_REG_FR27, + PPC_REG_FR28, + PPC_REG_FR29, + PPC_REG_FR30, + PPC_REG_FR31, // each 4-bit CR register - NUPPC_REG_CRF0, - NUPPC_REG_CRF1, - NUPPC_REG_CRF2, - NUPPC_REG_CRF3, - NUPPC_REG_CRF4, - NUPPC_REG_CRF5, - NUPPC_REG_CRF6, - NUPPC_REG_CRF7, + PPC_REG_CRF0, + PPC_REG_CRF1, + PPC_REG_CRF2, + PPC_REG_CRF3, + PPC_REG_CRF4, + PPC_REG_CRF5, + PPC_REG_CRF6, + PPC_REG_CRF7, - // each bit in the CR register - NUPPC_REG_CR_BIT0, - NUPPC_REG_CR_BIT1, - NUPPC_REG_CR_BIT2, - NUPPC_REG_CR_BIT3, - NUPPC_REG_CR_BIT4, - NUPPC_REG_CR_BIT5, - NUPPC_REG_CR_BIT6, - NUPPC_REG_CR_BIT7, - NUPPC_REG_CR_BIT8, - NUPPC_REG_CR_BIT9, - NUPPC_REG_CR_BIT10, - NUPPC_REG_CR_BIT11, - NUPPC_REG_CR_BIT12, - NUPPC_REG_CR_BIT13, - NUPPC_REG_CR_BIT14, - NUPPC_REG_CR_BIT15, - NUPPC_REG_CR_BIT16, - NUPPC_REG_CR_BIT17, - NUPPC_REG_CR_BIT18, - NUPPC_REG_CR_BIT19, - NUPPC_REG_CR_BIT20, - NUPPC_REG_CR_BIT21, - NUPPC_REG_CR_BIT22, - NUPPC_REG_CR_BIT23, - NUPPC_REG_CR_BIT24, - NUPPC_REG_CR_BIT25, - NUPPC_REG_CR_BIT26, - NUPPC_REG_CR_BIT27, - NUPPC_REG_CR_BIT28, - NUPPC_REG_CR_BIT29, - NUPPC_REG_CR_BIT30, - NUPPC_REG_CR_BIT31, + PPC_REG_AV_VR0, + PPC_REG_AV_VR1, + PPC_REG_AV_VR2, + PPC_REG_AV_VR3, + PPC_REG_AV_VR4, + PPC_REG_AV_VR5, + PPC_REG_AV_VR6, + PPC_REG_AV_VR7, + PPC_REG_AV_VR8, + PPC_REG_AV_VR9, + PPC_REG_AV_VR10, + PPC_REG_AV_VR11, + PPC_REG_AV_VR12, + PPC_REG_AV_VR13, + PPC_REG_AV_VR14, + PPC_REG_AV_VR15, + PPC_REG_AV_VR16, + PPC_REG_AV_VR17, + PPC_REG_AV_VR18, + PPC_REG_AV_VR19, + PPC_REG_AV_VR20, + PPC_REG_AV_VR21, + PPC_REG_AV_VR22, + PPC_REG_AV_VR23, + PPC_REG_AV_VR24, + PPC_REG_AV_VR25, + PPC_REG_AV_VR26, + PPC_REG_AV_VR27, + PPC_REG_AV_VR28, + PPC_REG_AV_VR29, + PPC_REG_AV_VR30, + PPC_REG_AV_VR31, - NUPPC_REG_AV_VR0, - NUPPC_REG_AV_VR1, - NUPPC_REG_AV_VR2, - NUPPC_REG_AV_VR3, - NUPPC_REG_AV_VR4, - NUPPC_REG_AV_VR5, - NUPPC_REG_AV_VR6, - NUPPC_REG_AV_VR7, - NUPPC_REG_AV_VR8, - NUPPC_REG_AV_VR9, - NUPPC_REG_AV_VR10, - NUPPC_REG_AV_VR11, - NUPPC_REG_AV_VR12, - NUPPC_REG_AV_VR13, - NUPPC_REG_AV_VR14, - NUPPC_REG_AV_VR15, - NUPPC_REG_AV_VR16, - NUPPC_REG_AV_VR17, - NUPPC_REG_AV_VR18, - NUPPC_REG_AV_VR19, - NUPPC_REG_AV_VR20, - NUPPC_REG_AV_VR21, - NUPPC_REG_AV_VR22, - NUPPC_REG_AV_VR23, - NUPPC_REG_AV_VR24, - NUPPC_REG_AV_VR25, - NUPPC_REG_AV_VR26, - NUPPC_REG_AV_VR27, - NUPPC_REG_AV_VR28, - NUPPC_REG_AV_VR29, - NUPPC_REG_AV_VR30, - NUPPC_REG_AV_VR31, + PPC_REG_VSX_VR0, + PPC_REG_VSX_VR1, + PPC_REG_VSX_VR2, + PPC_REG_VSX_VR3, + PPC_REG_VSX_VR4, + PPC_REG_VSX_VR5, + PPC_REG_VSX_VR6, + PPC_REG_VSX_VR7, + PPC_REG_VSX_VR8, + PPC_REG_VSX_VR9, + PPC_REG_VSX_VR10, + PPC_REG_VSX_VR11, + PPC_REG_VSX_VR12, + PPC_REG_VSX_VR13, + PPC_REG_VSX_VR14, + PPC_REG_VSX_VR15, + PPC_REG_VSX_VR16, + PPC_REG_VSX_VR17, + PPC_REG_VSX_VR18, + PPC_REG_VSX_VR19, + PPC_REG_VSX_VR20, + PPC_REG_VSX_VR21, + PPC_REG_VSX_VR22, + PPC_REG_VSX_VR23, + PPC_REG_VSX_VR24, + PPC_REG_VSX_VR25, + PPC_REG_VSX_VR26, + PPC_REG_VSX_VR27, + PPC_REG_VSX_VR28, + PPC_REG_VSX_VR29, + PPC_REG_VSX_VR30, + PPC_REG_VSX_VR31, + PPC_REG_VSX_VR32, + PPC_REG_VSX_VR33, + PPC_REG_VSX_VR34, + PPC_REG_VSX_VR35, + PPC_REG_VSX_VR36, + PPC_REG_VSX_VR37, + PPC_REG_VSX_VR38, + PPC_REG_VSX_VR39, + PPC_REG_VSX_VR40, + PPC_REG_VSX_VR41, + PPC_REG_VSX_VR42, + PPC_REG_VSX_VR43, + PPC_REG_VSX_VR44, + PPC_REG_VSX_VR45, + PPC_REG_VSX_VR46, + PPC_REG_VSX_VR47, + PPC_REG_VSX_VR48, + PPC_REG_VSX_VR49, + PPC_REG_VSX_VR50, + PPC_REG_VSX_VR51, + PPC_REG_VSX_VR52, + PPC_REG_VSX_VR53, + PPC_REG_VSX_VR54, + PPC_REG_VSX_VR55, + PPC_REG_VSX_VR56, + PPC_REG_VSX_VR57, + PPC_REG_VSX_VR58, + PPC_REG_VSX_VR59, + PPC_REG_VSX_VR60, + PPC_REG_VSX_VR61, + PPC_REG_VSX_VR62, + PPC_REG_VSX_VR63, - NUPPC_REG_VSX_VR0, - NUPPC_REG_VSX_VR1, - NUPPC_REG_VSX_VR2, - NUPPC_REG_VSX_VR3, - NUPPC_REG_VSX_VR4, - NUPPC_REG_VSX_VR5, - NUPPC_REG_VSX_VR6, - NUPPC_REG_VSX_VR7, - NUPPC_REG_VSX_VR8, - NUPPC_REG_VSX_VR9, - NUPPC_REG_VSX_VR10, - NUPPC_REG_VSX_VR11, - NUPPC_REG_VSX_VR12, - NUPPC_REG_VSX_VR13, - NUPPC_REG_VSX_VR14, - NUPPC_REG_VSX_VR15, - NUPPC_REG_VSX_VR16, - NUPPC_REG_VSX_VR17, - NUPPC_REG_VSX_VR18, - NUPPC_REG_VSX_VR19, - NUPPC_REG_VSX_VR20, - NUPPC_REG_VSX_VR21, - NUPPC_REG_VSX_VR22, - NUPPC_REG_VSX_VR23, - NUPPC_REG_VSX_VR24, - NUPPC_REG_VSX_VR25, - NUPPC_REG_VSX_VR26, - NUPPC_REG_VSX_VR27, - NUPPC_REG_VSX_VR28, - NUPPC_REG_VSX_VR29, - NUPPC_REG_VSX_VR30, - NUPPC_REG_VSX_VR31, - NUPPC_REG_VSX_VR32, - NUPPC_REG_VSX_VR33, - NUPPC_REG_VSX_VR34, - NUPPC_REG_VSX_VR35, - NUPPC_REG_VSX_VR36, - NUPPC_REG_VSX_VR37, - NUPPC_REG_VSX_VR38, - NUPPC_REG_VSX_VR39, - NUPPC_REG_VSX_VR40, - NUPPC_REG_VSX_VR41, - NUPPC_REG_VSX_VR42, - NUPPC_REG_VSX_VR43, - NUPPC_REG_VSX_VR44, - NUPPC_REG_VSX_VR45, - NUPPC_REG_VSX_VR46, - NUPPC_REG_VSX_VR47, - NUPPC_REG_VSX_VR48, - NUPPC_REG_VSX_VR49, - NUPPC_REG_VSX_VR50, - NUPPC_REG_VSX_VR51, - NUPPC_REG_VSX_VR52, - NUPPC_REG_VSX_VR53, - NUPPC_REG_VSX_VR54, - NUPPC_REG_VSX_VR55, - NUPPC_REG_VSX_VR56, - NUPPC_REG_VSX_VR57, - NUPPC_REG_VSX_VR58, - NUPPC_REG_VSX_VR59, - NUPPC_REG_VSX_VR60, - NUPPC_REG_VSX_VR61, - NUPPC_REG_VSX_VR62, - NUPPC_REG_VSX_VR63, + PPC_REG_GQR0, + PPC_REG_GQR1, + PPC_REG_GQR2, + PPC_REG_GQR3, + PPC_REG_GQR4, + PPC_REG_GQR5, + PPC_REG_GQR6, + PPC_REG_GQR7, }; #ifndef __cplusplus @@ -238,7 +216,6 @@ extern "C" { PPC_OP_SIMM, PPC_OP_LABEL, PPC_OP_MEM_RA, - PPC_OP_BI, PPC_OP_REG_RA, PPC_OP_REG_RB, @@ -252,10 +229,12 @@ extern "C" { PPC_OP_REG_FRS, PPC_OP_REG_CRFD, + PPC_OP_REG_CRFD_IMPLY0, PPC_OP_REG_CRFS, - PPC_OP_REG_CRBA, - PPC_OP_REG_CRBB, - PPC_OP_REG_CRBD, + PPC_OP_REG_CRFS_IMPLY0, + PPC_OP_CRBIT_A, + PPC_OP_CRBIT_B, + PPC_OP_CRBIT_D, PPC_OP_REG_AV_VA, PPC_OP_REG_AV_VB, @@ -314,6 +293,7 @@ extern "C" { int64_t simm; MemoryOperand mem; uint64_t label; + uint32_t crbit; }; }; @@ -690,6 +670,7 @@ extern "C" { PPC_ID_TLBWE, PPC_ID_TLBWEHI, PPC_ID_TLBWELO, + PPC_ID_TRAP, PPC_ID_TW, PPC_ID_TWEQ, PPC_ID_TWEQI, @@ -1077,11 +1058,21 @@ extern "C" { PPC_ID_VSX_XXMRGLD, PPC_ID_VSX_XXMRGLW, PPC_ID_VSX_XXPERMDI, + PPC_ID_VSX_XXPERMR, PPC_ID_VSX_XXSEL, PPC_ID_VSX_XXSLDWI, PPC_ID_VSX_XXSPLTD, PPC_ID_VSX_XXSPLTW, PPC_ID_VSX_XXSWAPD, + + PPC_ID_PSQ_L, + PPC_ID_PSQ_LU, + PPC_ID_PSQ_LUX, + PPC_ID_PSQ_LX, + PPC_ID_PSQ_ST, + PPC_ID_PSQ_STU, + PPC_ID_PSQ_STUX, + PPC_ID_PSQ_STX, }; #ifndef __cplusplus @@ -1115,6 +1106,9 @@ extern "C" { void FillBcctrxOperands(OperandsList* bcctrx, const Instruction* instruction); void FillBclrxOperands(OperandsList* bclrx, const Instruction* instruction); const char* GetMnemonic(const Instruction* instruction); + const char* PowerPCRegisterName(uint32_t regId); + const char* OperandClassName(uint32_t cls); + const char* GetCRBitName(uint32_t crbit); #ifdef __cplusplus } diff --git a/arch/powerpc/disassembler.cpp b/arch/powerpc/disassembler.cpp index 2a421971d..e69de29bb 100644 --- a/arch/powerpc/disassembler.cpp +++ b/arch/powerpc/disassembler.cpp @@ -1,358 +0,0 @@ -/****************************************************************************** - -See disassembler.h for more information about how this fits into the PPC -architecture plugin picture. - -******************************************************************************/ - -#include // strcpy, etc. - -#define MYLOG(...) while(0); -//#include -//#define MYLOG BinaryNinja::LogDebug - -#include "disassembler.h" -#include "util.h" - -/* have to do this... while options can be toggled after initialization (thru - cs_option(), the modes cannot, and endianness is considered a mode) */ -thread_local csh handle_lil = 0; -thread_local csh handle_big = 0; - -int DoesQualifyForLocalDisassembly(const uint8_t *data, bool bigendian) -{ - uint32_t insword = *(uint32_t *)data; - int result = PPC_INS_INVALID; - uint32_t tmp = 0; - - if(bigendian == true) - { - insword = bswap32(insword); - } - - // 111111xxx00xxxxxxxxxx00001000000 <- fcmpo - tmp = insword & 0xFC6007FF; - if (tmp==0xFC000040) - result = PPC_INS_BN_FCMPO; - // 111100xxxxxxxxxxxxxxx00111010xxx <- xxpermr - if((insword & 0xFC0007F8) == 0xF00001D0) - result = PPC_INS_BN_XXPERMR; - - return result; -} - -void ppc_fcmpo(uint32_t insword, decomp_result *res) -{ - unsigned regtmp = 0; - - // 111111AAA00BBBBBCCCCC00001000000 "fcmpo crA,fB,fC" - regtmp = PPC_REG_CR0 + ((insword >> 23) & 7); - res->detail.ppc.operands[0].reg = (ppc_reg)(regtmp); - res->detail.ppc.operands[0].type = PPC_OP_REG; - - regtmp = PPC_REG_F0 + ((insword >> 16) & 31); - res->detail.ppc.operands[1].reg = (ppc_reg)(regtmp); - res->detail.ppc.operands[1].type = PPC_OP_REG; - - regtmp = PPC_REG_F0 + ((insword >> 11) & 31); - res->detail.ppc.operands[2].reg = (ppc_reg)(regtmp); - res->detail.ppc.operands[2].type = PPC_OP_REG; - - -#ifdef FORCE_TEST - SStream ss; - struct cs_struct* handle = 0; - struct MCInst tempmc = {0}; - char* first_space = 0; - - // SStream_Init(&ss); - ss.index = 0; - ss.buffer[0] = '\0'; - regtmp = PPC_REG_CR0 + ((insword >> 23) & 7); - tempmc.Operands[0].MachineOperandType = MCOperand::kRegister; - tempmc.Operands[0].Kind = 1; - tempmc.Operands[0].RegVal = regtmp; - regtmp = PPC_REG_F0 + ((insword >> 16) & 31); - tempmc.Operands[1].MachineOperandType = MCOperand::kRegister; - tempmc.Operands[1].Kind = 1; - tempmc.Operands[1].RegVal = regtmp; - regtmp = PPC_REG_F0 + ((insword >> 11) & 31); - tempmc.Operands[2].Kind = 1; - tempmc.Operands[2].MachineOperandType = MCOperand::kRegister; - tempmc.Operands[2].RegVal = regtmp; - - // temporarily set this so that print processing succeeds - res->insn.id = PPC_INS_FCMPU; - - if (handle_big != 0) - { - handle = (struct cs_struct*)handle_big; - } - else if (handle_lil != 0) - { - handle = (struct cs_struct*)handle_lil; - } - -#define PPC_FCMPUS 804 - - tempmc.csh = handle; - tempmc.Opcode = PPC_FCMPUS; - tempmc.flat_insn = &res->insn; - tempmc.flat_insn->detail = &res->detail; - - if (handle != 0) - { - handle->printer(&tempmc, &ss, handle->printer_info); - } - - // replace the 'fcmpu' with 'fcmpo' - first_space = strchr(ss.buffer, ' '); - strncpy(res->insn.op_str, first_space + 1, sizeof(res->insn.op_str)); -#endif - - strncpy(res->insn.mnemonic, "fcmpo", sizeof(res->insn.mnemonic)); - - // reset this to the target value - res->insn.id = PPC_INS_BN_FCMPO; - res->detail.ppc.op_count = 3; -} - -void ppc_xxpermr(uint32_t insword, decomp_result *res) -{ - // 111100AAAAABBBBBCCCCC00011010BCA "xxpermr vsA,vsB,vsC" - int a = ((insword & 0x3E00000)>>21)|((insword & 0x1)<<5); - int b = ((insword & 0x1F0000)>>16)|((insword & 0x4)<<3); - int c = ((insword & 0xF800)>>11)|((insword & 0x2)<<4); - - res->detail.ppc.operands[0].reg = (ppc_reg)(PPC_REG_VS0 + a); - res->detail.ppc.operands[0].type = PPC_OP_REG; - res->detail.ppc.operands[1].reg = (ppc_reg)(PPC_REG_VS0 + b); - res->detail.ppc.operands[1].type = PPC_OP_REG; - res->detail.ppc.operands[2].reg = (ppc_reg)(PPC_REG_VS0 + c); - res->detail.ppc.operands[2].type = PPC_OP_REG; - - res->insn.id = PPC_INS_BN_XXPERMR; - res->detail.ppc.op_count = 3; - strncpy(res->insn.mnemonic, "xxpermr", sizeof(res->insn.mnemonic)); -} - -bool PerformLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, decomp_result* res, bool bigendian) -{ - uint32_t local_op = 0; - uint32_t insword = *(uint32_t *)data; - - if(bigendian == true) - { - insword = bswap32(insword); - } - - local_op = DoesQualifyForLocalDisassembly(data, bigendian); - - switch(local_op) - { - case PPC_INS_BN_FCMPO: - ppc_fcmpo(insword, res); - break; - case PPC_INS_BN_XXPERMR: - ppc_xxpermr(insword, res); - break; - default: - return false; - } - return true; -} - -extern "C" int -powerpc_init(int cs_mode_arg) -{ - int rc = -1; - - MYLOG("powerpc_init()\n"); - - if(handle_lil || handle_big) { - MYLOG("ERROR: already initialized!\n"); - goto cleanup; - } - - /* initialize capstone handle */ - if(cs_open(CS_ARCH_PPC, (cs_mode)((int)CS_MODE_BIG_ENDIAN | cs_mode_arg), &handle_big) != CS_ERR_OK) { - MYLOG("ERROR: cs_open()\n"); - goto cleanup; - } - - if(cs_open(CS_ARCH_PPC, (cs_mode)((int)CS_MODE_LITTLE_ENDIAN | cs_mode_arg), &handle_lil) != CS_ERR_OK) { - MYLOG("ERROR: cs_open()\n"); - goto cleanup; - } - - cs_option(handle_big, CS_OPT_DETAIL, CS_OPT_ON); - cs_option(handle_lil, CS_OPT_DETAIL, CS_OPT_ON); - - rc = 0; - cleanup: - if(rc) { - powerpc_release(); - } - - return rc; -} - -extern "C" void -powerpc_release(void) -{ - if(handle_lil) { - cs_close(&handle_lil); - handle_lil = 0; - } - - if(handle_big) { - cs_close(&handle_big); - handle_big = 0; - } -} - -extern "C" int -powerpc_decompose(const uint8_t *data, int size, uint64_t addr, bool lil_end, - struct decomp_result *res, bool is_64bit, int cs_mode_arg) -{ - int rc = -1; - res->status = STATUS_ERROR_UNSPEC; - - if(!handle_lil) { - powerpc_init(cs_mode_arg); - } - - //typedef struct cs_insn { - // unsigned int id; /* see capstone/ppc.h for PPC_INS_ADD, etc. */ - // uint64_t address; - // uint16_t size; - // uint8_t bytes[16]; - // char mnemonic[32]; /* string */ - // char op_str[160]; /* string */ - // cs_detail *detail; /* need CS_OP_DETAIL ON and CS_OP_SKIPDATA is OFF */ - //} cs_insn; - - // where cs_detail is some details + architecture specific part - // typedef struct cs_detail { - // uint8_t regs_read[12]; - // uint8_t regs_read_count; - // uint8_t regs_write; - // uint8_t regs_write_count; - // uint8_t groups[8]; - // uint8_t groups_count; - // cs_ppc *ppc; - // } - - // and finally ppc is: - // typedef struct cs_ppc { - // ppc_bc bc; /* branch code, see capstone/ppc.h for PPC_BC_LT, etc. */ - // ppc_bh bh; /* branch hint, see capstone/ppc.h for PPC_BH_PLUS, etc. */ - // bool update_cr0; - // uint8_t op_count; - // cs_ppc_op operands[8]; - // } cs_ppc; - - // and each operand is: - // typedef struct cs_ppc_op { - // ppc_op_type type; /* see capstone/ppc.h for PPC_OP_REG, etc. */ - // union { - // unsigned int reg; // register value for REG operand - // int32_t imm; // immediate value for IMM operand - // ppc_op_mem mem; // struct ppc_op_mem { uint base; int disp } - // ppc_op_crx crx; // struct ppc_op_crx { uint scale, uint reg } - // }; - // } cs_ppc_op; - - csh handle; - struct cs_struct *hand_tmp = 0; - cs_insn *insn = 0; /* instruction information - cs_disasm() will allocate array of cs_insn here */ - - /* which handle to use? - BIG end or LITTLE end? */ - handle = handle_big; - if(lil_end) handle = handle_lil; - res->handle = handle; - - hand_tmp = (struct cs_struct *)handle; - hand_tmp->mode = (cs_mode)((int)hand_tmp->mode | cs_mode_arg); - - /* call */ - size_t n = cs_disasm(handle, data, size, addr, 1, &insn); - if(n != 1) { - MYLOG("ERROR: cs_disasm() returned %" PRIdPTR " (cs_errno:%d)\n", n, cs_errno(handle)); - goto cleanup; - } - - /* set the status */ - res->status = STATUS_SUCCESS; - - /* copy the instruction struct, and detail sub struct to result */ - memcpy(&(res->insn), insn, sizeof(cs_insn)); - memcpy(&(res->detail), insn->detail, sizeof(cs_detail)); - - rc = 0; - cleanup: - if(insn) { - cs_free(insn, 1); - insn = 0; - } - return rc; -} - -extern "C" int -powerpc_disassemble(struct decomp_result *res, char *buf, size_t len) -{ - /* ideally the "heavy" string disassemble result is derived from light data - in the decomposition result, but capstone doesn't make this distinction */ - int rc = -1; - - if(len < strlen(res->insn.mnemonic)+strlen(res->insn.op_str) + 2) { - MYLOG("ERROR: insufficient room\n"); - goto cleanup; - } - - strcpy(buf, res->insn.mnemonic); - strcat(buf, " "); - strcat(buf, res->insn.op_str); - - rc = 0; - cleanup: - return rc; -} - -static const char* const gqr_array[] = {"gqr0", "gqr1", "gqr2", "gqr3", "gqr4", "gqr5", "gqr6", "gqr7"}; - -extern "C" const char * -powerpc_reg_to_str(uint32_t rid, int cs_mode_arg) -{ - if ((cs_mode_arg & CS_MODE_PS) != 0) - { - if ((rid >= PPC_REG_BN_GQR0) && (rid < PPC_REG_BN_ENDING)) - { - return gqr_array[rid - PPC_REG_BN_GQR0]; - } - } - - if(!handle_lil) { - powerpc_init(cs_mode_arg); - } - - return cs_reg_name(handle_lil, rid); -} - -extern "C" const uint32_t -powerpc_crx_to_reg(uint32_t rid) -{ - if (rid >= PPC_REG_CR0EQ && rid <= PPC_REG_CR7EQ) - return (rid - PPC_REG_CR0EQ) * 4 + 2; - else if (rid >= PPC_REG_CR0GT && rid <= PPC_REG_CR7GT) - return (rid - PPC_REG_CR0GT) * 4 + 1; - else if (rid >= PPC_REG_CR0LT && rid <= PPC_REG_CR7LT) - return (rid - PPC_REG_CR0LT) * 4 + 0; - else if (rid >= PPC_REG_CR0UN && rid <= PPC_REG_CR7UN) - return (rid - PPC_REG_CR0UN) * 4 + 3; - else - return rid; -} - diff --git a/arch/powerpc/disassembler.h b/arch/powerpc/disassembler.h index d4679ae0c..e69de29bb 100644 --- a/arch/powerpc/disassembler.h +++ b/arch/powerpc/disassembler.h @@ -1,98 +0,0 @@ -/****************************************************************************** - -This is the layer that the architecture module uses to access disassemble -functionality. - -Currently, it wraps capstone, but that could change in the future. It exists -precisely to make swapping out disassemblers easy, because disassembler details -(like capstone types) will not be intertwined in the architecture plugin code. - -Also, with the disassembler object separate, we can link it against -easy-to-compile test harnesses like the speed test. - -There are three main functions: - -powerpc_init() - initializes this module -powerpc_release() - un-initializes this module -powerpc_decompose() - converts bytes into decomp_result -powerpc_disassemble() - converts decomp_result to string - -Then some helpers if you need them: - -******************************************************************************/ - -/* capstone stuff /usr/local/include/capstone */ -#include "capstone/capstone.h" -#include "capstone/cs_priv.h" -#include "capstone/ppc.h" - -#define PPC_CRX_REG_MASK 0x1ff -#define PPC_CRX_FLOAT_MASK 0x200 - -// TODO this is some sorta capstone baddy, where xori is showing as xnop's -// opcode. Maybe pulling capstone will fix, need for xori to correctly -// lift. Capstone is posting that XORI is 1452, though that is XNOP -#define PPC_BN_INS_XORI PPC_INS_XNOP - -//***************************************************************************** -// structs and types -//***************************************************************************** -enum ppc_status_t { - STATUS_ERROR_UNSPEC=-1, STATUS_SUCCESS=0, STATUS_UNDEF_INSTR -}; - -typedef enum ppc_insn_bn { - PPC_INS_BN_FCMPO = PPC_INS_ENDING+1, - PPC_INS_BN_XXPERMR, - PPC_INS_BN_ENDING -} ppc_insn_bn; - -typedef enum ppc_reg_bn { - PPC_REG_BN_GQR0 = PPC_REG_ENDING+1, - PPC_REG_BN_GQR1, - PPC_REG_BN_GQR2, - PPC_REG_BN_GQR3, - PPC_REG_BN_GQR4, - PPC_REG_BN_GQR5, - PPC_REG_BN_GQR6, - PPC_REG_BN_GQR7, - PPC_REG_BN_ENDING -} ppc_reg_bn; - -/* operand type */ -enum operand_type_t { REG, VAL, LABEL }; - -struct decomp_request -{ - uint8_t *data; - int size; - uint32_t addr; - bool lil_end; -}; - -struct decomp_result -{ - /* actual capstone handle used, in case caller wants to do extra stuff - (this can be one of two handles opened for BE or LE disassembling) */ - csh handle; - - ppc_status_t status; - - cs_insn insn; - cs_detail detail; -}; - -//***************************************************************************** -// function prototypes -//***************************************************************************** -int DoesQualifyForLocalDisassembly(const uint8_t *data, bool bigendian); -bool PerformLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, decomp_result* res, bool bigendian); - -extern "C" int powerpc_init(int); -extern "C" void powerpc_release(void); -extern "C" int powerpc_decompose(const uint8_t *data, int size, uint64_t addr, - bool lil_end, struct decomp_result *result, bool is_64bit, int cs_mode); -extern "C" int powerpc_disassemble(struct decomp_result *, char *buf, size_t len); - -extern "C" const char *powerpc_reg_to_str(uint32_t rid, int cs_mode_arg); -extern "C" const uint32_t powerpc_crx_to_reg(uint32_t rid); diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 28883e5af..57d4ac9b9 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -1,23 +1,13 @@ #include "lowlevelilinstruction.h" #include -#include "disassembler.h" +#include "decode/decode.h" using namespace BinaryNinja; #include "il.h" #include "util.h" -#define OTI_SEXT32_REGS 1 -#define OTI_SEXT64_REGS 2 -#define OTI_ZEXT32_REGS 4 -#define OTI_ZEXT64_REGS 8 -#define OTI_SEXT32_IMMS 16 -#define OTI_SEXT64_IMMS 32 -#define OTI_ZEXT32_IMMS 64 -#define OTI_ZEXT64_IMMS 128 -#define OTI_IMM_CPTR 256 -#define OTI_IMM_REL_CPTR 512 #define OTI_IMM_BIAS 1024 #define OTI_GPR0_ZERO 2048 @@ -36,140 +26,89 @@ static uint32_t genMask(uint32_t mb, uint32_t me) #define PPC_IL_EXTRA_DEFAULT 0 #define RZF 4 -static ExprId operToIL(LowLevelILFunction &il, struct cs_ppc_op *op, +static ExprId operToIL(LowLevelILFunction &il, Operand* op, int options=PPC_IL_OPTIONS_DEFAULT, uint64_t extra=PPC_IL_EXTRA_DEFAULT, size_t regsz=4) { ExprId res; - if(!op) { + if (!op) + { MYLOG("ERROR: operToIL() got NULL operand\n"); return il.Unimplemented(); } - switch(op->type) { - case PPC_OP_REG: - //MYLOG("case PPC_OP_REG returning reg %d\n", op->reg); - if (options & OTI_GPR0_ZERO && op->reg == PPC_REG_R0) + switch (op->cls) + { + case PPC_OP_REG_RA: + case PPC_OP_REG_RB: + case PPC_OP_REG_RD: + case PPC_OP_REG_RS: + if (options & OTI_GPR0_ZERO && op->reg == PPC_REG_GPR0) res = il.Const(regsz, 0); else res = il.Register(regsz, op->reg); break; - case PPC_OP_IMM: - /* the immediate is a constant pointer (eg: absolute address) */ - if(options & OTI_IMM_CPTR) { - res = il.ConstPointer(regsz, op->imm); + + case PPC_OP_SIMM: + if (options & OTI_IMM_BIAS) + { + /* the immediate should be biased with given value */ + res = il.Const(regsz, op->simm + extra); } - /* the immediate is a displacement (eg: relative addressing) */ - else if(options & OTI_IMM_REL_CPTR) { - res = il.ConstPointer(regsz, op->imm + extra); + else + { + /* the immediate is just a plain boring immediate */ + res = il.Const(regsz, op->simm); } - /* the immediate should be biased with given value */ - else if(options & OTI_IMM_BIAS) { - res = il.Const(regsz, op->imm + extra); + break; + + case PPC_OP_UIMM: + if (options & OTI_IMM_BIAS) + { + /* the immediate should be biased with given value */ + res = il.Const(regsz, op->uimm + extra); } - /* the immediate is just a plain boring immediate */ - else { - res = il.Const(regsz, op->imm); + else + { + /* the immediate is just a plain boring immediate */ + res = il.Const(regsz, op->uimm); } break; - case PPC_OP_MEM: - //MYLOG("case PPC_OP_MEM returning regs (%d,%d)\n", op->mem.base, op->mem.disp); - - if (options & OTI_GPR0_ZERO && op->mem.base == PPC_REG_R0) + case PPC_OP_MEM_RA: + if (options & OTI_GPR0_ZERO && op->mem.reg == PPC_REG_GPR0) res = il.Const(regsz, 0); else - res = il.Register(regsz, op->mem.base); + res = il.Register(regsz, op->mem.reg); if(options & OTI_IMM_BIAS) - res = il.Add(regsz, res, il.Const(4, op->mem.disp + extra)); + res = il.Add(regsz, res, il.Const(regsz, op->mem.offset + extra)); else - res = il.Add(regsz, res, il.Const(4, op->mem.disp)); + res = il.Add(regsz, res, il.Const(regsz, op->mem.offset)); break; - case PPC_OP_CRX: - case PPC_OP_INVALID: + case PPC_OP_NONE: default: MYLOG("ERROR: don't know how to convert operand to IL\n"); res = il.Unimplemented(); } - switch(options) { - case OTI_SEXT32_REGS: - if(op->type == PPC_OP_REG) - res = il.SignExtend(4, res); - break; - case OTI_SEXT64_REGS: - if(op->type == PPC_OP_REG) - res = il.SignExtend(8, res); - break; - case OTI_ZEXT32_REGS: - if(op->type == PPC_OP_REG) - res = il.ZeroExtend(4, res); - break; - case OTI_ZEXT64_REGS: - if(op->type == PPC_OP_REG) - res = il.ZeroExtend(8, res); - break; - case OTI_SEXT32_IMMS: - if(op->type == PPC_OP_REG) - res = il.SignExtend(4, res); - break; - case OTI_SEXT64_IMMS: - if(op->type == PPC_OP_REG) - res = il.SignExtend(8, res); - break; - case OTI_ZEXT32_IMMS: - if(op->type == PPC_OP_REG) - res = il.ZeroExtend(4, res); - break; - case OTI_ZEXT64_IMMS: - if(op->type == PPC_OP_REG) - res = il.ZeroExtend(8, res); - break; - } - return res; } #define operToIL_a(il, op, regSz) operToIL(il, op, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, regSz) /* map PPC_REG_CRX to an IL flagwrite type (a named set of written flags */ -int crxToFlagWriteType(int crx, bool signedComparison = true) +int crxToFlagWriteType(Register reg, ppc_suf suf) { - // MYLOG("%s() crx:%d", __func__, crx); - int flag_out = 0; - int crx_local = 0; - int crx_type = 0; - int crx_index = 0; - int suf = 0; - - crx_local = crx & PPC_CRX_REG_MASK; - crx_type = crx & PPC_CRX_FLOAT_MASK; - if ((crx_local < PPC_REG_CR0) || (crx_local > PPC_REG_CR7)) - { - goto fail; - } - - crx_index = crx_local - PPC_REG_CR0; - - if (crx_type != 0) - { - suf = PPC_SUF_F; - } - else if (signedComparison == false) - { - suf = PPC_SUF_U; - } + if ((reg < PPC_REG_CRF0) || (reg > PPC_REG_CRF7)) + return IL_FLAGWRITE_NONE; /* when we have more flags... */ - flag_out = (crx_index * PPC_SUF_SZ) + IL_FLAGWRITE_CR0_S + suf; - -fail: - return flag_out; + int crx_index = reg - PPC_REG_CRF0; + return (crx_index * PPC_SUF_SZ) + IL_FLAGWRITE_CR0_S + suf; } - static ExprId ExtractConditionClause(LowLevelILFunction& il, uint8_t crBit, bool negate = false) { // MYLOG("%s() crbit:%x", __func__, crBit); @@ -242,44 +181,23 @@ static bool LiftConditionalBranch(LowLevelILFunction& il, uint8_t bo, uint8_t bi return isConditional; } -static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8_t* data, uint64_t addr, bool le) +static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const Instruction *instruction, uint64_t addr) { - // MYLOG("%s() addr:0x%08llx\n", __func__, addr); - uint32_t insn = *(const uint32_t *) data; - bool lk; size_t addressSize_l = arch->GetAddressSize(); - - if (!le) + switch (instruction->id) { - insn = bswap32(insn); - } - - lk = insn & 1; - - switch (insn >> 26) - { - case PPC_INS_BCA: /* b (b, ba, bl, bla) */ + case PPC_ID_Bx: { - uint64_t target = insn & 0x03fffffc; - - /* sign extend target */ - target = sign_extend(addressSize_l, target, 25); - - /* account for absolute addressing */ - if (!(insn & 2)) - { - target += addr; - ADDRMASK(addressSize_l, target); - } + uint64_t target = instruction->operands[0].label; BNLowLevelILLabel* label = il.GetLabelForAddress(arch, target); - if (label && !(lk && (target != (addr+4)))) + if (label && !(instruction->flags.lk && (target != (addr+4)))) { /* branch to an instruction within the same function -- take * 'lk' bit behavior into account, but don't emit as a call */ - if (lk) + if (instruction->flags.lk) { il.AddInstruction(il.SetRegister(addressSize_l, PPC_REG_LR, il.ConstPointer(addressSize_l, addr + 4))); } @@ -288,9 +206,9 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 } else { - ExprId dest = il.ConstPointer(4, target); + ExprId dest = il.ConstPointer(addressSize_l, target); - if (lk) + if (instruction->flags.lk) il.AddInstruction(il.Call(dest)); else il.AddInstruction(il.Jump(dest)); @@ -298,26 +216,16 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 break; } - case PPC_INS_BA: /* bc */ + case PPC_ID_BCx: /* bc */ { - uint64_t target = insn & 0xfffc; - uint8_t bo = (insn >> 21) & 0x1f; - uint8_t bi = (insn >> 16) & 0x1f; - - /* sign extend target */ - target = sign_extend(addressSize_l, target, 15); - - /* account for absolute addressing */ - if (!(insn & 2)) - { - target += addr; - ADDRMASK(addressSize_l, target); - } + uint8_t bo = instruction->operands[0].uimm; + uint8_t bi = instruction->operands[1].uimm; + uint64_t target = instruction->operands[2].label; BNLowLevelILLabel *existingTakenLabel = il.GetLabelForAddress(arch, target); BNLowLevelILLabel *existingFalseLabel = il.GetLabelForAddress(arch, addr + 4); - if (lk) + if (instruction->flags.lk) { il.AddInstruction(il.SetRegister(addressSize_l, PPC_REG_LR, il.ConstPointer(addressSize_l, addr + 4))); } @@ -345,7 +253,7 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 } else if (target != addr + 4) { - if (lk) + if (instruction->flags.lk) { il.AddInstruction(il.Call(il.ConstPointer(addressSize_l, target))); if (wasConditionalBranch) @@ -364,23 +272,24 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 break; } - case PPC_INS_BCCTR: /* bcctr, bclr */ + case PPC_ID_BCCTRx: /* bcctr, bclr */ + case PPC_ID_BCLRx: { - uint8_t bo = (insn >> 21) & 0x1f; - uint8_t bi = (insn >> 16) & 0x1f; + uint8_t bo = instruction->operands[0].uimm; + uint8_t bi = instruction->operands[1].uimm; bool blr = false; ExprId expr; - - switch ((insn >> 1) & 0x3ff) + switch (instruction->id) { - case 16: - expr = il.Register(addressSize_l, PPC_REG_LR); - blr = true; - break; - case 528: - if (!(bo & 4)) + case PPC_ID_BCCTRx: + if (!(bo & 0x4)) return false; expr = il.Register(addressSize_l, PPC_REG_CTR); + blr = false; + break; + case PPC_ID_BCLRx: + expr = il.Register(addressSize_l, PPC_REG_LR); + blr = true; break; default: return false; @@ -399,7 +308,7 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 if (wasConditionalBranch) il.MarkLabel(takenLabel); - if (lk) + if (instruction->flags.lk) { il.AddInstruction(il.Call(expr)); if (wasConditionalBranch) @@ -455,67 +364,67 @@ static ExprId ByteReverseRegister(LowLevelILFunction &il, uint32_t reg, size_t s } -static void ByteReversedLoad(LowLevelILFunction &il, struct cs_ppc* ppc, size_t size, size_t addressSize_a=4) +static void ByteReversedLoad(LowLevelILFunction &il, Instruction* instruction, size_t size, size_t address_size_a=4) { - ExprId addr = operToIL(il, &ppc->operands[1], OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_a); // (rA|0) - ExprId val = il.Load(size, il.Add(addressSize_a, addr, operToIL_a(il, &ppc->operands[2], addressSize_a))); // [(rA|0) + (rB)] + ExprId addr = operToIL(il, &instruction->operands[1], OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, address_size_a); // (rA|0) + ExprId val = il.Load(size, il.Add(address_size_a, addr, operToIL_a(il, &instruction->operands[2], address_size_a))); // [(rA|0) + (rB)] - if (size < addressSize_a) + if (size < address_size_a) { - val = il.ZeroExtend(addressSize_a, val); + val = il.ZeroExtend(address_size_a, val); } /* set reg immediately; this will cause xrefs to be sized correctly, * we'll use this as the scratch while we calculate the swapped value */ - il.AddInstruction(il.SetRegister(addressSize_a, ppc->operands[0].reg, val)); // rD = [(rA|0) + (rB)] - ExprId swap = ByteReverseRegister(il, ppc->operands[0].reg, size); + il.AddInstruction(il.SetRegister(address_size_a, instruction->operands[0].reg, val)); // rD = [(rA|0) + (rB)] + ExprId swap = ByteReverseRegister(il, instruction->operands[0].reg, size); - il.AddInstruction(il.SetRegister(addressSize_a, ppc->operands[0].reg, swap)); // rD = swap([(rA|0) + (rB)]) + il.AddInstruction(il.SetRegister(address_size_a, instruction->operands[0].reg, swap)); // rD = swap([(rA|0) + (rB)]) } -static void ByteReversedStore(LowLevelILFunction &il, struct cs_ppc* ppc, size_t size, size_t addressSize_a=4) +static void ByteReversedStore(LowLevelILFunction &il, Instruction* instruction, size_t size, size_t addressSize_a=4) { - ExprId addr = operToIL(il, &ppc->operands[1], OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_a); // (rA|0) - addr = il.Add(addressSize_a, addr, operToIL_a(il, &ppc->operands[2], addressSize_a)); // (rA|0) + (rB) - ExprId val = ByteReverseRegister(il, ppc->operands[0].reg, size); // rS = swap(rS) - il.AddInstruction(il.Store(size, addr, val)); // [(rA|0) + (rB)] = swap(rS) + ExprId addr = operToIL(il, &instruction->operands[1], OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_a); // (rA|0) + addr = il.Add(addressSize_a, addr, operToIL_a(il, &instruction->operands[2], addressSize_a)); // (rA|0) + (rB) + ExprId val = ByteReverseRegister(il, instruction->operands[0].reg, size); // rS = swap(rS) + il.AddInstruction(il.Store(size, addr, val)); // [(rA|0) + (rB)] = swap(rS) } -static void loadstoreppcfs(LowLevelILFunction& il, - int load_store_sz, - cs_ppc_op* operand1, /* register that gets read/written */ - cs_ppc_op* operand2, /* location the read/write occurs */ - cs_ppc_op* operand3=0, +static void load_float(LowLevelILFunction& il, + int load_sz, + Operand* operand1, /* register that gets read/written */ + Operand* operand2, /* location the read/write occurs */ + Operand* operand3=0, bool update=false ) { ExprId tmp = 0; const int addrsz = 4; // assume single - if (!load_store_sz) - load_store_sz = 4; + if (!load_sz) + load_sz = 4; // operand1.reg = [operand2.reg + operand2.imm] - if (operand2->type == PPC_OP_MEM) + if (operand2->cls == PPC_OP_MEM_RA) { - if (operand2->mem.disp == 0) + if (operand2->mem.reg == 0) { - tmp = il.Register(4, operand2->mem.base); + tmp = il.Const(addrsz, operand2->mem.offset); } else { - tmp = il.Add(addrsz, il.Register(addrsz, operand2->mem.base), il.Const(addrsz, operand2->mem.disp)); + tmp = il.Add(addrsz, il.Register(addrsz, operand2->mem.reg), il.Const(addrsz, operand2->mem.offset)); } } - else if(operand2->type == PPC_OP_REG) + else if(operand2->cls == PPC_OP_REG_RA) { - if ((operand3 != 0) && (operand3->type == PPC_OP_REG)) + if ((operand3 != 0) && (operand3->cls == PPC_OP_REG_RB)) { tmp = il.Add(4, il.Register(addrsz, operand2->reg), il.Register(addrsz, operand3->reg)); } } - il.AddInstruction(il.SetRegister(load_store_sz, operand1->reg, il.FloatConvert(load_store_sz, il.Operand(1, il.Load(load_store_sz, tmp))))); + il.AddInstruction(il.SetRegister(load_sz, operand1->reg, il.FloatConvert(load_sz, il.Operand(1, il.Load(load_sz, tmp))))); if (update == true) { @@ -527,100 +436,44 @@ static void loadstoreppcfs(LowLevelILFunction& il, /* returns TRUE - if this IL continues FALSE - if this IL terminates a block */ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, - const uint8_t* data, uint64_t addr, decomp_result *res, bool le) + Instruction* instruction, uint64_t addr) { + if (LiftBranches(arch, il, instruction, addr)) + return true; + int i; - bool rc = true; - struct cs_insn *insn = 0; - struct cs_detail *detail = 0; - struct cs_ppc *ppc = 0; - size_t addressSize_l = 0; - int extend_l = 0; - uint32_t rawInsn = *(const uint32_t *) data; + size_t addressSize_l = arch->GetAddressSize(); // for ppc_ps - // ppc_reg_bn gqr_l = (ppc_reg_bn)0; - // int w_l = 0; - - addressSize_l = arch->GetAddressSize(); - if (!le) - { - rawInsn = bswap32(rawInsn); - } - - - /* bypass capstone path for *all* branching instructions; capstone - * is too difficult to work with and is outright broken for some - * branch instructions (bdnz, etc.) - */ - if (LiftBranches(arch, il, data, addr, le)) - return true; - - insn = &(res->insn); - detail = &(res->detail); - ppc = &(detail->ppc); - - /* There is a simplifying reduction available for: - * rlwinm , , , , - * When == == 0, this can be translated to: - * clrwi , , 31- - * - * Unfortunately capstone screws this up, replacing just the instruction id with PPC_INSN_CLRWI. - * The mnemonic ("rlwinm"), operands, etc. all stay the same. - */ - if (insn->id == PPC_INS_CLRLWI && insn->mnemonic[0] == 'r') - { - insn->id = PPC_INS_RLWINM; - } + int w_l = 0; + bool rc = true; /* create convenient access to instruction operands */ - cs_ppc_op *oper0=NULL, *oper1=NULL, *oper2=NULL, *oper3=NULL, *oper4=NULL; + Operand *oper0=NULL, *oper1=NULL, *oper2=NULL, *oper3=NULL, *oper4=NULL; #define REQUIRE1OP if(!oper0) goto ReturnUnimpl; #define REQUIRE2OPS if(!oper0 || !oper1) goto ReturnUnimpl; #define REQUIRE3OPS if(!oper0 || !oper1 || !oper2) goto ReturnUnimpl; #define REQUIRE4OPS if(!oper0 || !oper1 || !oper2 || !oper3) goto ReturnUnimpl; #define REQUIRE5OPS if(!oper0 || !oper1 || !oper2 || !oper3 || !oper4) goto ReturnUnimpl; - switch(ppc->op_count) { + switch (instruction->numOperands) + { default: - case 5: oper4 = &(ppc->operands[4]); FALL_THROUGH - case 4: oper3 = &(ppc->operands[3]); FALL_THROUGH - case 3: oper2 = &(ppc->operands[2]); FALL_THROUGH - case 2: oper1 = &(ppc->operands[1]); FALL_THROUGH - case 1: oper0 = &(ppc->operands[0]); FALL_THROUGH + case 5: oper4 = &(instruction->operands[4]); FALL_THROUGH + case 4: oper3 = &(instruction->operands[3]); FALL_THROUGH + case 3: oper2 = &(instruction->operands[2]); FALL_THROUGH + case 2: oper1 = &(instruction->operands[1]); FALL_THROUGH + case 1: oper0 = &(instruction->operands[0]); FALL_THROUGH case 0: while(0); } - /* for conditionals that specify a crx, treat it special */ - if(ppc->bc != PPC_BC_INVALID) { - if(oper0 && oper0->type == PPC_OP_REG && oper0->reg >= PPC_REG_CR0 && - ppc->operands[0].reg <= PPC_REG_CR7) { - oper0 = oper1; - oper1 = oper2; - oper2 = oper3; - oper3 = NULL; - } - } - - if(0 && insn->id == PPC_INS_CMPLWI) { - MYLOG("%s() %08llx: %02X %02X %02X %02X %s %s has %d operands\n", - __func__, addr, data[0], data[1], data[2], data[3], - insn->mnemonic, insn->op_str, ppc->op_count - ); - - //printInstructionVerbose(res); - //MYLOG("oper0: %p\n", oper0); - //MYLOG("oper1: %p\n", oper1); - //MYLOG("oper2: %p\n", oper2); - //MYLOG("oper3: %p\n", oper3); - } - ExprId ei0 = 0, ei1 = 0, ei2 = 0; - switch(insn->id) { + switch (instruction->id) + { /* add "add." also updates the CR0 bits */ - case PPC_INS_ADD: /* add */ + case PPC_ID_ADDx: /* add */ REQUIRE2OPS ei0 = il.Add( addressSize_l, @@ -628,12 +481,12 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, operToIL_a(il, oper2, addressSize_l) ); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - (insn->id == PPC_INS_ADD && ppc->update_cr0) ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_ADDE: /* add, extended (+ carry flag) */ + case PPC_ID_ADDEx: /* add, extended (+ carry flag) */ REQUIRE3OPS ei0 = il.AddCarry( addressSize_l, @@ -643,15 +496,15 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, IL_FLAGWRITE_XER_CA ); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_ADDME: /* add, extended (+ carry flag) minus one */ - case PPC_INS_ADDZE: + case PPC_ID_ADDMEx: /* add, extended (+ carry flag) minus one */ + case PPC_ID_ADDZEx: REQUIRE2OPS - if (insn->id == PPC_INS_ADDME) + if (instruction->id == PPC_ID_ADDMEx) ei0 = il.Const(addressSize_l, ADDRNEG1(addressSize_l)); else ei0 = il.Const(addressSize_l, 0); @@ -663,13 +516,13 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, IL_FLAGWRITE_XER_CA ); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_ADDC: /* add, carrying */ - case PPC_INS_ADDIC: /* add immediate, carrying */ + case PPC_ID_ADDCx: /* add, carrying */ + case PPC_ID_ADDICx: /* add immediate, carrying */ REQUIRE3OPS ei0 = il.Add( addressSize_l, @@ -678,18 +531,18 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, IL_FLAGWRITE_XER_CA ); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_ADDI: /* add immediate, eg: addi rD, rA, */ - case PPC_INS_ADDIS: /* add immediate, shifted */ + case PPC_ID_ADDI: /* add immediate, eg: addi rD, rA, */ + case PPC_ID_ADDIS: /* add immediate, shifted */ REQUIRE2OPS - if (insn->id == PPC_INS_ADDIS) - ei0 = il.Const(addressSize_l, oper2->imm << 16); + if (instruction->id == PPC_ID_ADDIS) + ei0 = il.Const(addressSize_l, oper2->simm << 16); else - ei0 = il.Const(addressSize_l, oper2->imm); + ei0 = il.Const(addressSize_l, oper2->simm); ei0 = il.Add( addressSize_l, operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l), @@ -699,90 +552,98 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); break; - case PPC_INS_LIS: /* load immediate, shifted */ + case PPC_ID_LIS: /* load immediate, shifted */ REQUIRE2OPS ei0 = il.SetRegister( addressSize_l, oper0->reg, - il.ConstPointer(addressSize_l, oper1->imm << 16) + il.ConstPointer(addressSize_l, oper1->simm << 16) ); il.AddInstruction(ei0); break; - case PPC_INS_LI: /* load immediate */ - case PPC_INS_LA: /* load displacement */ + case PPC_ID_LI: /* load immediate */ REQUIRE2OPS il.AddInstruction(il.SetRegister(addressSize_l, oper0->reg, operToIL_a(il, oper1, addressSize_l))); break; - case PPC_INS_AND: - case PPC_INS_ANDC: // and [with complement] - case PPC_INS_NAND: + case PPC_ID_ANDx: + case PPC_ID_ANDCx: // and [with complement] + case PPC_ID_NANDx: REQUIRE3OPS - ei0 = operToIL_a(il, oper2, addressSize_l); - if (insn->id == PPC_INS_ANDC) + ei0 = operToIL(il, oper2); + if (instruction->id == PPC_ID_ANDCx) ei0 = il.Not(addressSize_l, ei0); - ei0 = il.And(addressSize_l, operToIL_a(il, oper1, addressSize_l), ei0); - if (insn->id == PPC_INS_NAND) + ei0 = il.And(addressSize_l, operToIL(il, oper1), ei0); + if (instruction->id == PPC_ID_NANDx) ei0 = il.Not(addressSize_l, ei0); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_ANDIS: - case PPC_INS_ANDI: + case PPC_ID_ANDIS: + case PPC_ID_ANDI: REQUIRE3OPS - if (insn->id == PPC_INS_ANDIS) - ei0 = il.Const(addressSize_l, oper2->imm << 16); + if (instruction->id == PPC_ID_ANDIS) + ei0 = il.Const(addressSize_l, oper2->uimm << 16); else - ei0 = il.Const(addressSize_l, oper2->imm); - ei0 = il.And(addressSize_l, operToIL_a(il, oper1, addressSize_l), ei0); + ei0 = il.Const(addressSize_l, oper2->uimm); + ei0 = il.And(addressSize_l, operToIL(il, oper1), ei0); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, IL_FLAGWRITE_CR0_S); il.AddInstruction(ei0); break; - case PPC_INS_CMP: - case PPC_INS_CMPW: /* compare (signed) word(32-bit) */ + case PPC_ID_CMPW: /* compare (signed) word(32-bit) */ + REQUIRE2OPS + ei0 = operToIL(il, oper1); + ei1 = operToIL(il, oper2); + ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper0->reg, PPC_SUF_S)); + il.AddInstruction(ei2); + break; + + case PPC_ID_CMPLW: /* compare logical(unsigned) word(32-bit) */ REQUIRE2OPS - ei0 = operToIL_a(il, oper2 ? oper1 : oper0, addressSize_l); - ei1 = operToIL_a(il, oper2 ? oper2 : oper1, addressSize_l); - ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0)); + ei0 = operToIL(il, oper1); + ei1 = operToIL(il, oper2); + ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper0->reg, PPC_SUF_U)); il.AddInstruction(ei2); break; - case PPC_INS_CMPL: - case PPC_INS_CMPLW: /* compare logical(unsigned) word(32-bit) */ + case PPC_ID_CMPWI: /* compare (signed) word(32-bit) immediate */ REQUIRE2OPS - ei0 = operToIL_a(il, oper2 ? oper1 : oper0, addressSize_l); - ei1 = operToIL_a(il, oper2 ? oper2 : oper1, addressSize_l); - ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0, false)); + ei0 = operToIL(il, oper1); + ei1 = operToIL_a(il, oper2, addressSize_l); + ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper0->reg, PPC_SUF_S)); il.AddInstruction(ei2); break; - case PPC_INS_CMPI: - case PPC_INS_CMPWI: /* compare (signed) word(32-bit) immediate */ - case PPC_INS_CMPDI: + case PPC_ID_CMPLWI: /* compare logical(unsigned) word(32-bit) immediate */ REQUIRE2OPS - EXTOPTS(rawInsn, addressSize_l, extend_l); - ei0 = operToIL_a(il, oper2 ? oper1 : oper0, addressSize_l); - ei1 = operToIL(il, oper2 ? oper2 : oper1, extend_l, PPC_IL_EXTRA_DEFAULT, addressSize_l); - ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0)); + ei0 = operToIL(il, oper1); + ei1 = operToIL_a(il, oper2, addressSize_l); + ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper0->reg, PPC_SUF_U)); il.AddInstruction(ei2); break; - case PPC_INS_CMPLI: - case PPC_INS_CMPLWI: /* compare logical(unsigned) word(32-bit) immediate */ + case PPC_ID_CMPDI: REQUIRE2OPS - EXTOPTZ(rawInsn, addressSize_l, extend_l); - ei0 = operToIL_a(il, oper2 ? oper1 : oper0, addressSize_l); - ei1 = operToIL(il, oper2 ? oper2 : oper1, extend_l, PPC_IL_EXTRA_DEFAULT, addressSize_l); - ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0, false)); + ei0 = operToIL(il, oper1, 8); + ei1 = operToIL_a(il, oper2, 8); + ei2 = il.Sub(8, ei0, ei1, crxToFlagWriteType(oper0->reg, PPC_SUF_S)); il.AddInstruction(ei2); break; - //case PPC_INS_CMPD: /* compare (signed) d-word(64-bit) */ + case PPC_ID_CMPLDI: + REQUIRE2OPS + ei0 = operToIL(il, oper1, 8); + ei1 = operToIL_a(il, oper2, 8); + ei2 = il.Sub(8, ei0, ei1, crxToFlagWriteType(oper0->reg, PPC_SUF_U)); + il.AddInstruction(ei2); + break; + + //case PPC_ID_CMPD: /* compare (signed) d-word(64-bit) */ // REQUIRE2OPS // ei0 = operToIL(il, oper0); // ei1 = operToIL(il, oper1, OTI_SEXT64_REGS); @@ -790,7 +651,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // il.AddInstruction(ei2); // break; - //case PPC_INS_CMPLD: /* compare logical(unsigned) d-word(64-bit) */ + //case PPC_ID_CMPLD: /* compare logical(unsigned) d-word(64-bit) */ // REQUIRE2OPS // ei0 = operToIL(il, oper0); // ei1 = operToIL(il, oper1, OTI_ZEXT64_REGS); @@ -798,15 +659,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // il.AddInstruction(ei2); // break; - //case PPC_INS_CMPDI: /* compare (signed) d-word(64-bit) immediate */ - // REQUIRE2OPS - // ei0 = operToIL(il, oper0); - // ei1 = operToIL(il, oper1, OTI_SEXT64_IMMS); - // ei2 = il.Sub(4, ei0, ei1, flagWriteType); - // il.AddInstruction(ei2); - // break; - - //case PPC_INS_CMPLDI: /* compare logical(unsigned) d-word(64-bit) immediate */ + //case PPC_ID_CMPLDI: /* compare logical(unsigned) d-word(64-bit) immediate */ // REQUIRE2OPS // ei0 = operToIL(il, oper0); // ei1 = operToIL(il, oper1, OTI_ZEXT64_IMMS); @@ -814,68 +667,74 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // il.AddInstruction(ei2); // break; - case PPC_INS_CRAND: - case PPC_INS_CRANDC: - case PPC_INS_CRNAND: + // case PPC_ID_FCMPU: + // REQUIRE3OPS + // ei0 = il.FloatSub(4, il.Unimplemented(), il.Unimplemented(), (oper0->reg - PPC_REG_CR0) + IL_FLAGWRITE_INVL0); + // il.AddInstruction(ei0); + // break; + + case PPC_ID_CRAND: + case PPC_ID_CRANDC: + case PPC_ID_CRNAND: REQUIRE3OPS - ei0 = il.Flag(oper1->reg - PPC_REG_R0); - ei1 = il.Flag(oper2->reg - PPC_REG_R0); - if (insn->id == PPC_INS_CRANDC) + ei0 = il.Flag(oper1->crbit); + ei1 = il.Flag(oper2->crbit); + if (instruction->id == PPC_ID_CRANDC) ei1 = il.Not(0, ei1); ei0 = il.And(0, ei0, ei1); - if (insn->id == PPC_INS_CRNAND) + if (instruction->id == PPC_ID_CRNAND) ei0 = il.Not(0, ei0); - il.AddInstruction(il.SetFlag(oper0->reg - PPC_REG_R0, ei0)); + il.AddInstruction(il.SetFlag(oper0->crbit, ei0)); break; - case PPC_INS_CROR: - case PPC_INS_CRORC: - case PPC_INS_CRNOR: + case PPC_ID_CROR: + case PPC_ID_CRORC: + case PPC_ID_CRNOR: REQUIRE3OPS - ei0 = il.Flag(oper1->reg - PPC_REG_R0); - ei1 = il.Flag(oper2->reg - PPC_REG_R0); - if (insn->id == PPC_INS_CRORC) + ei0 = il.Flag(oper1->crbit); + ei1 = il.Flag(oper2->crbit); + if (instruction->id == PPC_ID_CRORC) ei1 = il.Not(0, ei1); ei0 = il.Or(0, ei0, ei1); - if (insn->id == PPC_INS_CRNOR) + if (instruction->id == PPC_ID_CRNOR) ei0 = il.Not(0, ei0); - il.AddInstruction(il.SetFlag(oper0->reg - PPC_REG_R0, ei0)); + il.AddInstruction(il.SetFlag(oper0->crbit, ei0)); break; - case PPC_INS_CREQV: - case PPC_INS_CRXOR: + case PPC_ID_CREQV: + case PPC_ID_CRXOR: REQUIRE3OPS - ei0 = il.Flag(oper1->reg - PPC_REG_R0); - ei1 = il.Flag(oper2->reg - PPC_REG_R0); + ei0 = il.Flag(oper1->crbit); + ei1 = il.Flag(oper2->crbit); ei0 = il.Xor(0, ei0, ei1); - if (insn->id == PPC_INS_CREQV) + if (instruction->id == PPC_ID_CREQV) ei0 = il.Not(0, ei0); - il.AddInstruction(il.SetFlag(oper0->reg - PPC_REG_R0, ei0)); + il.AddInstruction(il.SetFlag(oper0->crbit, ei0)); break; - case PPC_INS_CRSET: + case PPC_ID_CRSET: REQUIRE1OP - ei0 = il.SetFlag(oper0->reg - PPC_REG_R0, il.Const(0, 1)); + ei0 = il.SetFlag(oper0->crbit, il.Const(0, 1)); il.AddInstruction(ei0); break; - case PPC_INS_CRCLR: + case PPC_ID_CRCLR: REQUIRE1OP - ei0 = il.SetFlag(oper0->reg - PPC_REG_R0, il.Const(0, 0)); + ei0 = il.SetFlag(oper0->crbit, il.Const(0, 0)); il.AddInstruction(ei0); break; - case PPC_INS_CRNOT: - case PPC_INS_CRMOVE: + case PPC_ID_CRNOT: + case PPC_ID_CRMOVE: REQUIRE2OPS - ei0 = il.Flag(oper1->reg - PPC_REG_R0); - if (insn->id == PPC_INS_CRNOT) + ei0 = il.Flag(oper1->crbit); + if (instruction->id == PPC_ID_CRNOT) ei0 = il.Not(0, ei0); - ei0 = il.SetFlag(oper0->reg - PPC_REG_R0, ei0); + ei0 = il.SetFlag(oper0->crbit, ei0); il.AddInstruction(ei0); break; - case PPC_INS_MFCR: + case PPC_ID_MFCR: REQUIRE1OP il.AddInstruction(il.SetRegister(4, oper0->reg, il.Or(4, il.FlagBit(4, IL_FLAG_LT, 31), @@ -912,11 +771,11 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.FlagBit(4, IL_FLAG_SO_7, 0)))))))))))))))))))))))))))))))))); break; - case PPC_INS_MTCRF: + case PPC_ID_MTCRF: REQUIRE2OPS for (uint8_t test = 0x80, i = 0; test; test >>= 1, i++) { - if (test & oper0->imm) + if (test & oper0->uimm) { ei0 = il.Or(4, il.Register(4, oper1->reg), il.Const(4, 0), IL_FLAGWRITE_MTCR0 + i); il.AddInstruction(ei0); @@ -924,11 +783,11 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, } break; - case PPC_INS_EXTSB: - case PPC_INS_EXTSH: + case PPC_ID_EXTSBx: + case PPC_ID_EXTSHx: REQUIRE2OPS ei0 = il.Register(addressSize_l, oper1->reg); - if (insn->id == PPC_INS_EXTSB) + if (instruction->id == PPC_ID_EXTSBx) { ei0 = il.LowPart(1, ei0); } @@ -938,27 +797,27 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, } ei0 = il.SignExtend(addressSize_l, ei0); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_EXTSW: + case PPC_ID_EXTSWx: REQUIRE2OPS ei0 = il.Register(8, oper1->reg); ei0 = il.LowPart(4, ei0); ei0 = il.SignExtend(8, ei0); ei0 = il.SetRegister(8, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_ISEL: + case PPC_ID_ISEL: REQUIRE4OPS { LowLevelILLabel trueLabel, falseLabel, doneLabel; - uint32_t crBit = powerpc_crx_to_reg(oper3->reg); + uint32_t crBit = oper3->crbit; uint32_t cr = crBit / 4; switch (crBit % 4) @@ -996,9 +855,10 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, } break; - case PPC_INS_LMW: + case PPC_ID_LMW: REQUIRE2OPS - for(i=oper0->reg; i<=PPC_REG_R31; ++i) { + for (i = oper0->reg; i <= PPC_REG_GPR31; ++i) + { ei0 = il.SetRegister(4, i, // dest il.Load(4, // source @@ -1014,8 +874,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, /* load byte and zero extend [and update] */ - case PPC_INS_LBZ: - case PPC_INS_LBZU: + case PPC_ID_LBZ: + case PPC_ID_LBZU: REQUIRE2OPS ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 ei0 = il.Load(1, ei0); // [d(rA)] @@ -1024,8 +884,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) - if(insn->id == PPC_INS_LBZU) { - ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); + if(instruction->id == PPC_ID_LBZU) { + ei0 = il.SetRegister(addressSize_l, oper1->mem.reg, operToIL(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1034,8 +894,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, /* load half word [and zero/sign extend] [and update] */ - case PPC_INS_LBZX: - case PPC_INS_LBZUX: + case PPC_ID_LBZX: + case PPC_ID_LBZUX: REQUIRE3OPS ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 ei0 = il.Load(1, il.Add(addressSize_l, ei0, operToIL_a(il, oper2, addressSize_l))); // [d(rA) + d(rB)] @@ -1044,7 +904,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) - if(insn->id == PPC_INS_LBZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_R0) { + if (instruction->id == PPC_ID_LBZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_GPR0) + { ei0 = il.SetRegister(addressSize_l, oper1->reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1054,14 +915,14 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, /* load half word [and zero/sign extend] [and update] */ - case PPC_INS_LHZ: - case PPC_INS_LHZU: - case PPC_INS_LHA: - case PPC_INS_LHAU: + case PPC_ID_LHZ: + case PPC_ID_LHZU: + case PPC_ID_LHA: + case PPC_ID_LHAU: REQUIRE2OPS ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 ei0 = il.Load(2, ei0); // [d(rA)] - if(insn->id == PPC_INS_LHZ || insn->id == PPC_INS_LHZU) + if(instruction->id == PPC_ID_LHZ || instruction->id == PPC_ID_LHZU) ei0 = il.ZeroExtend(addressSize_l, ei0); else ei0 = il.SignExtend(addressSize_l, ei0); @@ -1069,8 +930,9 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) - if(insn->id == PPC_INS_LHZU || insn->id == PPC_INS_LHAU) { - ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); + if (instruction->id == PPC_ID_LHZU || instruction->id == PPC_ID_LHAU) + { + ei0 = il.SetRegister(addressSize_l, oper1->mem.reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1079,14 +941,14 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, /* load half word [and zero/sign extend] [and update] */ - case PPC_INS_LHZX: - case PPC_INS_LHZUX: - case PPC_INS_LHAX: - case PPC_INS_LHAUX: + case PPC_ID_LHZX: + case PPC_ID_LHZUX: + case PPC_ID_LHAX: + case PPC_ID_LHAUX: REQUIRE3OPS ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 ei0 = il.Load(2, il.Add(addressSize_l, ei0, operToIL_a(il, oper2, addressSize_l))); // [d(rA) + d(rB)] - if(insn->id == PPC_INS_LHZX || insn->id == PPC_INS_LHZUX) + if(instruction->id == PPC_ID_LHZX || instruction->id == PPC_ID_LHZUX) ei0 = il.ZeroExtend(addressSize_l, ei0); else ei0 = il.SignExtend(addressSize_l, ei0); @@ -1094,7 +956,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) - if((insn->id == PPC_INS_LHZUX || insn->id == PPC_INS_LHAUX) && oper1->reg != oper0->reg && oper1->reg != PPC_REG_R0) { + if((instruction->id == PPC_ID_LHZUX || instruction->id == PPC_ID_LHAUX) && oper1->reg != oper0->reg && oper1->reg != PPC_REG_GPR0) { ei0 = il.SetRegister(addressSize_l, oper1->reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1104,8 +966,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, /* load word [and zero] [and update] */ - case PPC_INS_LWZ: - case PPC_INS_LWZU: + case PPC_ID_LWZ: + case PPC_ID_LWZU: REQUIRE2OPS ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 ei0 = il.Load(4, ei0); // [d(rA)] @@ -1117,9 +979,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) - if(insn->id == PPC_INS_LWZU) - { - ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); + if(instruction->id == PPC_ID_LWZU) { + ei0 = il.SetRegister(addressSize_l, oper1->mem.reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1128,8 +989,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, /* load word [and zero] [and update] */ - case PPC_INS_LWZX: - case PPC_INS_LWZUX: + case PPC_ID_LWZX: + case PPC_ID_LWZUX: REQUIRE3OPS ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 ei0 = il.Load(4, il.Add(addressSize_l, ei0, operToIL_a(il, oper2, addressSize_l))); // [d(rA) + d(rB)] @@ -1141,8 +1002,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) - if(insn->id == PPC_INS_LWZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_R0) - { + if(instruction->id == PPC_ID_LWZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_GPR0) { ei0 = il.SetRegister(addressSize_l, oper1->reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1152,8 +1012,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, /* load doubleword [and update] */ - case PPC_INS_LD: - case PPC_INS_LDU: + case PPC_ID_LD: + case PPC_ID_LDU: REQUIRE2OPS ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 ei0 = il.Load(8, ei0); // [d(rA)] @@ -1161,8 +1021,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) - if(insn->id == PPC_INS_LWZU) { - ei0 = il.SetRegister(8, oper1->mem.base, operToIL(il, oper1)); + if(instruction->id == PPC_ID_LWZU) { + ei0 = il.SetRegister(8, oper1->mem.reg, operToIL(il, oper1)); il.AddInstruction(ei0); } @@ -1171,8 +1031,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, /* load doubleword [and update] */ - case PPC_INS_LDX: - case PPC_INS_LDUX: + case PPC_ID_LDX: + case PPC_ID_LDUX: REQUIRE3OPS ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 ei0 = il.Load(8, il.Add(8, ei0, operToIL(il, oper2))); // [d(rA) + d(rB)] @@ -1180,124 +1040,115 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) - if(insn->id == PPC_INS_LWZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_R0) { + if(instruction->id == PPC_ID_LWZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_GPR0) { ei0 = il.SetRegister(8, oper1->reg, operToIL(il, oper1)); il.AddInstruction(ei0); } break; - case PPC_INS_LHBRX: + case PPC_ID_LHBRX: REQUIRE3OPS - ByteReversedLoad(il, ppc, 2, addressSize_l); + ByteReversedLoad(il, instruction, 2, addressSize_l); break; - case PPC_INS_LWBRX: + case PPC_ID_LWBRX: REQUIRE3OPS - ByteReversedLoad(il, ppc, 4, addressSize_l); + ByteReversedLoad(il, instruction, 4, addressSize_l); break; - case PPC_INS_STHBRX: + case PPC_ID_STHBRX: REQUIRE3OPS - ByteReversedStore(il, ppc, 2, addressSize_l); + ByteReversedStore(il, instruction, 2, addressSize_l); break; - case PPC_INS_STWBRX: + case PPC_ID_STWBRX: REQUIRE3OPS - ByteReversedStore(il, ppc, 4, addressSize_l); + ByteReversedStore(il, instruction, 4, addressSize_l); break; - case PPC_INS_MFCTR: // move from ctr + case PPC_ID_MFCTR: // move from ctr REQUIRE1OP il.AddInstruction(il.SetRegister(addressSize_l, oper0->reg, il.Register(addressSize_l, PPC_REG_CTR))); break; - case PPC_INS_MFLR: // move from link register + case PPC_ID_MFLR: // move from link register REQUIRE1OP il.AddInstruction(il.SetRegister(addressSize_l, oper0->reg, il.Register(addressSize_l, PPC_REG_LR))); break; - case PPC_INS_MTCTR: // move to ctr + case PPC_ID_MTCTR: // move to ctr REQUIRE1OP il.AddInstruction(il.SetRegister(addressSize_l, PPC_REG_CTR, operToIL_a(il, oper0, addressSize_l))); break; - case PPC_INS_MTLR: // move to link register + case PPC_ID_MTLR: // move to link register REQUIRE1OP il.AddInstruction(il.SetRegister(addressSize_l, PPC_REG_LR, operToIL_a(il, oper0, addressSize_l))); break; - case PPC_INS_NEG: + case PPC_ID_NEGx: REQUIRE2OPS - ei0 = il.Neg(addressSize_l, operToIL_a(il, oper1, addressSize_l)); + ei0 = il.Neg(addressSize_l, operToIL(il, oper1)); il.AddInstruction(il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_NOP: + case PPC_ID_NOP: il.AddInstruction(il.Nop()); break; - case PPC_INS_NOT: - REQUIRE2OPS - ei0 = il.Not(addressSize_l, operToIL_a(il, oper1, addressSize_l)); - il.AddInstruction(il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 - )); - break; - - case PPC_INS_OR: - case PPC_INS_ORC: - case PPC_INS_NOR: + case PPC_ID_ORx: + case PPC_ID_ORCx: + case PPC_ID_NORx: REQUIRE3OPS ei0 = operToIL_a(il, oper2, addressSize_l); - if (insn->id == PPC_INS_ORC) + if (instruction->id == PPC_ID_ORCx) ei0 = il.Not(addressSize_l, ei0); ei0 = il.Or(addressSize_l, operToIL_a(il, oper1, addressSize_l), ei0); - if (insn->id == PPC_INS_NOR) + if (instruction->id == PPC_ID_NORx) ei0 = il.Not(addressSize_l, ei0); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_ORI: - case PPC_INS_ORIS: + case PPC_ID_ORI: + case PPC_ID_ORIS: REQUIRE3OPS - if (insn->id == PPC_INS_ORIS) - ei0 = il.Const(addressSize_l, oper2->imm << 16); + if (instruction->id == PPC_ID_ORIS) + ei0 = il.Const(addressSize_l, oper2->uimm << 16); else - ei0 = il.Const(addressSize_l, oper2->imm); + ei0 = il.Const(addressSize_l, oper2->uimm); ei0 = il.Or(addressSize_l, operToIL_a(il, oper1, addressSize_l), ei0); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0); il.AddInstruction(ei0); break; - case PPC_INS_XOR: - case PPC_INS_EQV: + case PPC_ID_XORx: + case PPC_ID_EQVx: REQUIRE3OPS ei0 = il.Xor(addressSize_l, operToIL_a(il, oper1, addressSize_l), operToIL_a(il, oper2, addressSize_l) ); - if (insn->id == PPC_INS_EQV) + if (instruction->id == PPC_ID_EQVx) ei0 = il.Not(addressSize_l, ei0); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_XORI: - case PPC_BN_INS_XORI: - case PPC_INS_XORIS: + case PPC_ID_XORI: + case PPC_ID_XORIS: REQUIRE3OPS - if (insn->id == PPC_INS_XORIS) - ei0 = il.Const(addressSize_l, oper2->imm << 16); + if (instruction->id == PPC_ID_XORIS) + ei0 = il.Const(addressSize_l, oper2->uimm << 16); else - ei0 = il.Const(addressSize_l, oper2->imm); + ei0 = il.Const(addressSize_l, oper2->uimm); ei0 = il.SetRegister( addressSize_l, oper0->reg, @@ -1309,23 +1160,23 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); break; - case PPC_INS_SUBF: - case PPC_INS_SUBFC: - case PPC_INS_SUBFIC: + case PPC_ID_SUBFx: + case PPC_ID_SUBFCx: + case PPC_ID_SUBFIC: REQUIRE3OPS ei0 = il.Sub( addressSize_l, operToIL_a(il, oper2, addressSize_l), operToIL_a(il, oper1, addressSize_l), - (insn->id != PPC_INS_SUBF) ? IL_FLAGWRITE_XER_CA : 0 + (instruction->id != PPC_ID_SUBFx) ? IL_FLAGWRITE_XER_CA : 0 ); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_SUBFE: + case PPC_ID_SUBFEx: REQUIRE3OPS ei0 = il.SubBorrow( addressSize_l, @@ -1335,15 +1186,15 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, IL_FLAGWRITE_XER_CA ); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_SUBFME: - case PPC_INS_SUBFZE: + case PPC_ID_SUBFMEx: + case PPC_ID_SUBFZEx: REQUIRE2OPS - if (insn->id == PPC_INS_SUBFME) + if (instruction->id == PPC_ID_SUBFMEx) ei0 = il.Const(addressSize_l, ADDRNEG1(addressSize_l)); else ei0 = il.Const(addressSize_l, 0); @@ -1355,14 +1206,15 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, IL_FLAGWRITE_XER_CA ); ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_STMW: + case PPC_ID_STMW: REQUIRE2OPS - for(i=oper0->reg; i<=PPC_REG_R31; ++i) { + for (i = oper0->reg; i <= PPC_REG_GPR31; ++i) + { ei0 = il.Register(4, i); // source ei1 = operToIL(il, oper1, OTI_IMM_BIAS, (i-(oper0->reg))*4, addressSize_l); il.AddInstruction( @@ -1376,8 +1228,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, break; /* store half word [with update] */ - case PPC_INS_STB: - case PPC_INS_STBU: /* store(size, addr, val) */ + case PPC_ID_STB: + case PPC_ID_STBU: /* store(size, addr, val) */ REQUIRE2OPS ei0 = il.Store(1, operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l), @@ -1386,16 +1238,16 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, then rA gets updated address - if(insn->id == PPC_INS_STBU) { - ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); + if(instruction->id == PPC_ID_STBU) { + ei0 = il.SetRegister(addressSize_l, oper1->mem.reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } break; /* store half word indexed [with update] */ - case PPC_INS_STBX: - case PPC_INS_STBUX: /* store(size, addr, val) */ + case PPC_ID_STBX: + case PPC_ID_STBUX: /* store(size, addr, val) */ REQUIRE3OPS ei0 = il.Store(1, il.Add( @@ -1407,7 +1259,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, then rA gets updated address - if(insn->id == PPC_INS_STBUX) { + if(instruction->id == PPC_ID_STBUX) { ei0 = il.SetRegister(addressSize_l, oper1->reg, il.Add(addressSize_l, operToIL_a(il, oper1, addressSize_l), operToIL_a(il, oper2, addressSize_l)) ); @@ -1417,8 +1269,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, break; /* store half word [with update] */ - case PPC_INS_STH: - case PPC_INS_STHU: /* store(size, addr, val) */ + case PPC_ID_STH: + case PPC_ID_STHU: /* store(size, addr, val) */ REQUIRE2OPS ei0 = il.Store(2, operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l), @@ -1427,16 +1279,16 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, then rA gets updated address - if(insn->id == PPC_INS_STHU) { - ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); + if(instruction->id == PPC_ID_STHU) { + ei0 = il.SetRegister(addressSize_l, oper1->mem.reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } break; /* store half word indexed [with update] */ - case PPC_INS_STHX: - case PPC_INS_STHUX: /* store(size, addr, val) */ + case PPC_ID_STHX: + case PPC_ID_STHUX: /* store(size, addr, val) */ REQUIRE3OPS ei0 = il.Store(2, il.Add( @@ -1448,7 +1300,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, then rA gets updated address - if(insn->id == PPC_INS_STHUX) { + if(instruction->id == PPC_ID_STHUX) { ei0 = il.SetRegister(addressSize_l, oper1->reg, il.Add(addressSize_l, operToIL_a(il, oper1, addressSize_l), operToIL_a(il, oper2, addressSize_l)) ); @@ -1458,8 +1310,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, break; /* store word [with update] */ - case PPC_INS_STW: - case PPC_INS_STWU: /* store(size, addr, val) */ + case PPC_ID_STW: + case PPC_ID_STWU: /* store(size, addr, val) */ REQUIRE2OPS if (addressSize_l == 8) { @@ -1476,16 +1328,16 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, then rA gets updated address - if(insn->id == PPC_INS_STWU) { - ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); + if(instruction->id == PPC_ID_STWU) { + ei0 = il.SetRegister(addressSize_l, oper1->mem.reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } break; /* store word indexed [with update] */ - case PPC_INS_STWX: - case PPC_INS_STWUX: /* store(size, addr, val) */ + case PPC_ID_STWX: + case PPC_ID_STWUX: /* store(size, addr, val) */ REQUIRE3OPS if (addressSize_l == 8) { @@ -1505,7 +1357,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, then rA gets updated address - if(insn->id == PPC_INS_STWUX) { + if(instruction->id == PPC_ID_STWUX) { ei0 = il.SetRegister(addressSize_l, oper1->reg, il.Add(addressSize_l, operToIL_a(il, oper1, addressSize_l), operToIL_a(il, oper2, addressSize_l)) ); @@ -1515,8 +1367,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, break; /* store double word [with update] */ - case PPC_INS_STD: - case PPC_INS_STDU: /* store(size, addr, val) */ + case PPC_ID_STD: + case PPC_ID_STDU: /* store(size, addr, val) */ REQUIRE2OPS ei0 = il.Store(8, operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_OPTIONS_DEFAULT, addressSize_l), @@ -1525,16 +1377,16 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, then rA gets updated address - if(insn->id == PPC_INS_STDU) { - ei0 = il.SetRegister(8, oper1->mem.base, operToIL_a(il, oper1, 8)); + if(instruction->id == PPC_ID_STWU) { + ei0 = il.SetRegister(8, oper1->mem.reg, operToIL_a(il, oper1, 8)); il.AddInstruction(ei0); } break; /* store word indexed [with update] */ - case PPC_INS_STDX: - case PPC_INS_STDUX: /* store(size, addr, val) */ + case PPC_ID_STDX: + case PPC_ID_STDUX: /* store(size, addr, val) */ REQUIRE3OPS ei0 = il.Store(8, il.Add(8, operToIL(il, oper1, OTI_GPR0_ZERO), operToIL_a(il, oper2, addressSize_l)), @@ -1543,7 +1395,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); // if update, then rA gets updated address - if(insn->id == PPC_INS_STDUX) { + if(instruction->id == PPC_ID_STDUX) { ei0 = il.SetRegister(8, oper1->reg, il.Add(8, operToIL_a(il, oper1, 8), operToIL_a(il, oper2, 8)) ); @@ -1552,21 +1404,21 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, break; - case PPC_INS_RLWIMI: + case PPC_ID_RLWIMIx: REQUIRE5OPS { - uint32_t mask = genMask(oper3->imm, oper4->imm); + uint32_t mask = genMask(oper3->uimm, oper4->uimm); ei0 = il.Register(4, oper1->reg); - if (oper2->imm != 0) + if (oper2->uimm != 0) { - if ((mask & (~0u >> (32 - oper2->imm))) == 0) - ei0 = il.ShiftLeft(4, ei0, il.Const(4, oper2->imm)); - else if ((mask & (~0u << oper2->imm)) == 0) - ei0 = il.LogicalShiftRight(4, ei0, il.Const(4, 32 - oper2->imm)); + if ((mask & (~0u >> (32 - oper2->uimm))) == 0) + ei0 = il.ShiftLeft(4, ei0, il.Const(4, oper2->uimm)); + else if ((mask & (~0u << oper2->uimm)) == 0) + ei0 = il.LogicalShiftRight(4, ei0, il.Const(4, 32 - oper2->uimm)); else - ei0 = il.RotateLeft(4, ei0, il.Const(4, oper2->imm)); + ei0 = il.RotateLeft(4, ei0, il.Const(4, oper2->uimm)); } ei0 = il.And(4, ei0, il.Const(4, mask)); @@ -1574,38 +1426,38 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, ei0 = il.Or(4, il.And(4, il.Register(4, oper0->reg), il.Const(4, invertMask)), ei0); ei0 = il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); } break; - case PPC_INS_RLWINM: + case PPC_ID_RLWINMx: REQUIRE5OPS { - uint32_t mask = genMask(oper3->imm, oper4->imm); + uint32_t mask = genMask(oper3->uimm, oper4->uimm); ei0 = il.Register(4, oper1->reg); - if (oper2->imm != 0) + if (oper2->uimm != 0) { - if ((mask & (~0u >> (32 - oper2->imm))) == 0) + if ((mask & (~0u >> (32 - oper2->uimm))) == 0) { if (mask != 0xffffffff) - ei0 = il.And(4, ei0, il.Const(4, mask >> oper2->imm)); + ei0 = il.And(4, ei0, il.Const(4, mask >> oper2->uimm)); - ei0 = il.ShiftLeft(4, ei0, il.Const(4, oper2->imm)); + ei0 = il.ShiftLeft(4, ei0, il.Const(4, oper2->uimm)); } - else if ((mask & (~0u << oper2->imm)) == 0) + else if ((mask & (~0u << oper2->uimm)) == 0) { if (mask != 0xffffffff) - ei0 = il.And(4, ei0, il.Const(4, mask << (32 - oper2->imm))); + ei0 = il.And(4, ei0, il.Const(4, mask << (32 - oper2->uimm))); - ei0 = il.LogicalShiftRight(4, ei0, il.Const(4, 32 - oper2->imm)); + ei0 = il.LogicalShiftRight(4, ei0, il.Const(4, 32 - oper2->uimm)); } else { - ei0 = il.RotateLeft(4, ei0, il.Const(4, oper2->imm)); + ei0 = il.RotateLeft(4, ei0, il.Const(4, oper2->uimm)); if (mask != 0xffffffff) ei0 = il.And(4, ei0, il.Const(4, mask)); @@ -1617,64 +1469,64 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, } ei0 = il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); } break; - case PPC_INS_SLWI: + case PPC_ID_SLWIx: REQUIRE3OPS - ei0 = il.Const(4, oper2->imm); // amt: shift amount + ei0 = il.Const(4, oper2->uimm); // amt: shift amount ei1 = il.Register(4, oper1->reg); // rS: reg to be shifted ei0 = il.ShiftLeft(4, ei1, ei0); // (rS << amt) ei0 = il.SetRegister(4, oper0->reg, ei0, // rD = (rs << amt) - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_SRWI: + case PPC_ID_SRWIx: REQUIRE3OPS - ei0 = il.Const(4, oper2->imm); // amt: shift amount + ei0 = il.Const(4, oper2->uimm); // amt: shift amount ei1 = il.Register(4, oper1->reg); // rS: reg to be shifted ei0 = il.LogicalShiftRight(4, ei1, ei0); // (rS << amt) ei0 = il.SetRegister(4, oper0->reg, ei0, // rD = (rs << amt) - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_CLRLWI: + case PPC_ID_CLRLWIx: REQUIRE3OPS - ei0 = il.Const(4, (uint32_t) (0xffffffff >> oper2->imm)); + ei0 = il.Const(4, (uint32_t) (0xffffffff >> oper2->uimm)); ei1 = il.Register(4, oper1->reg); ei0 = il.And(4, ei1, ei0); ei0 = il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_ROTLWI: + case PPC_ID_ROTLWIx: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); - ei0 = il.RotateLeft(4, ei0, il.Const(4, oper2->imm)); + ei0 = il.RotateLeft(4, ei0, il.Const(4, oper2->uimm)); ei0 = il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; - case PPC_INS_ROTLW: - case PPC_INS_RLWNM: + case PPC_ID_ROTLWx: + case PPC_ID_RLWNMx: REQUIRE3OPS { uint32_t mask = 0xffffffff; - if (insn->id == PPC_INS_RLWNM) + if (instruction->id == PPC_ID_RLWNMx) { REQUIRE5OPS - mask = genMask(oper3->imm, oper4->imm); + mask = genMask(oper3->uimm, oper4->uimm); } ei0 = il.Register(4, oper1->reg); ei1 = il.Register(4, oper2->reg); @@ -1683,226 +1535,211 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, if (mask != 0xffffffff) ei0 = il.And(4, ei0, il.Const(4, mask)); ei0 = il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); } break; - case PPC_INS_SLW: - case PPC_INS_SRW: + case PPC_ID_SLWx: + case PPC_ID_SRWx: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); // permit bit 26 to survive to enable clearing the whole register ei1 = il.And(4, il.Register(4, oper2->reg), il.Const(4, 0x3f)); - if (insn->id == PPC_INS_SLW) + if (instruction->id == PPC_ID_SLWx) ei0 = il.ShiftLeft(4, ei0, ei1); else ei0 = il.LogicalShiftRight(4, ei0, ei1); il.AddInstruction(il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_SLD: - case PPC_INS_SRD: + case PPC_ID_SLDx: + case PPC_ID_SRDx: REQUIRE3OPS ei0 = il.Register(8, oper1->reg); // permit bit 25 to survive to enable clearing the whole register ei1 = il.And(8, il.Register(8, oper2->reg), il.Const(8, 0x7f)); - if (insn->id == PPC_INS_SLD) + if (instruction->id == PPC_ID_SLDx) ei0 = il.ShiftLeft(8, ei0, ei1); else ei0 = il.LogicalShiftRight(8, ei0, ei1); il.AddInstruction(il.SetRegister(8, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_SRAW: + case PPC_ID_SRAWx: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); ei1 = il.And(4, il.Register(4, oper2->reg), il.Const(4, 0x1f)); ei0 = il.ArithShiftRight(4, ei0, ei1, IL_FLAGWRITE_XER_CA); il.AddInstruction(il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_SRAWI: + case PPC_ID_SRAWIx: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); - ei0 = il.ArithShiftRight(4, ei0, il.Const(4, oper2->imm), IL_FLAGWRITE_XER_CA); + ei0 = il.ArithShiftRight(4, ei0, il.Const(4, oper2->uimm), IL_FLAGWRITE_XER_CA); il.AddInstruction(il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_SRAD: + case PPC_ID_SRADx: REQUIRE3OPS ei0 = il.Register(8, oper1->reg); ei1 = il.And(8, il.Register(8, oper2->reg), il.Const(8, 0x3f)); ei0 = il.ArithShiftRight(8, ei0, ei1, IL_FLAGWRITE_XER_CA); il.AddInstruction(il.SetRegister(8, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_SRADI: + case PPC_ID_SRADIx: REQUIRE3OPS ei0 = il.Register(8, oper1->reg); - ei0 = il.ArithShiftRight(8, ei0, il.Const(8, oper2->imm), IL_FLAGWRITE_XER_CA); + ei0 = il.ArithShiftRight(8, ei0, il.Const(8, oper2->uimm), IL_FLAGWRITE_XER_CA); il.AddInstruction(il.SetRegister(8, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_MULLW: + case PPC_ID_MULLWx: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); ei0 = il.Mult(4, ei0, il.Register(4, oper2->reg)); il.AddInstruction(il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_MULLI: + case PPC_ID_MULLI: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); - ei0 = il.Mult(4, ei0, il.Const(4, oper2->imm)); + ei0 = il.Mult(4, ei0, il.Const(4, oper2->uimm)); il.AddInstruction(il.SetRegister(4, oper0->reg, ei0)); break; - case PPC_INS_MULHW: + case PPC_ID_MULHWx: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); ei0 = il.MultDoublePrecSigned(4, ei0, il.Register(4, oper2->reg)); ei0 = il.LowPart(4, il.LogicalShiftRight(8, ei0, il.Const(1, 32))); il.AddInstruction(il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_MULHWU: + case PPC_ID_MULHWUx: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); ei0 = il.MultDoublePrecUnsigned(4, ei0, il.Register(4, oper2->reg)); ei0 = il.LowPart(4, il.LogicalShiftRight(8, ei0, il.Const(1, 32))); il.AddInstruction(il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_DIVW: + case PPC_ID_DIVWx: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); ei0 = il.DivSigned(4, ei0, il.Register(4, oper2->reg)); il.AddInstruction(il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_DIVWU: + case PPC_ID_DIVWUx: REQUIRE3OPS ei0 = il.Register(4, oper1->reg); ei0 = il.DivUnsigned(4, ei0, il.Register(4, oper2->reg)); il.AddInstruction(il.SetRegister(4, oper0->reg, ei0, - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0 )); break; - case PPC_INS_MR: /* move register */ + case PPC_ID_MRx: /* move register */ REQUIRE2OPS ei0 = il.SetRegister(addressSize_l, oper0->reg, operToIL_a(il, oper1, addressSize_l), - ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0); + instruction->flags.rc ? IL_FLAGWRITE_CR0_S : 0); il.AddInstruction(ei0); break; - case PPC_INS_SC: + case PPC_ID_SC: il.AddInstruction(il.SystemCall()); break; - case PPC_INS_RFI: + case PPC_ID_RFI: il.AddInstruction(il.Return(il.Unimplemented())); break; - case PPC_INS_TRAP: + case PPC_ID_TWU: il.AddInstruction(il.Trap(0)); break; -// ===================================== -// =====FLOATING POINT INSTRUCTIONS===== -// ===================================== + // ===================================== + // =====FLOATING POINT INSTRUCTIONS===== + // ===================================== - // case PPC_INS_FCMPO: /* compare (signed) word(32-bit) */ - // REQUIRE2OPS - // ei0 = operToIL(il, oper2 ? oper1 : oper0); - // ei1 = operToIL(il, oper2 ? oper2 : oper1); - // ei2 = il.Sub(4, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0)); - // il.AddInstruction(ei2); - // break; - - // for this one, i guess the easiest thing to do is to summarize it by - // the end result. For this instuction to happen, the end result is: - // register Fn is stored at Rn. - // how do we achieve this result in IL? - // had it not had the quantization, we could probably get away with - // a cast and then store. - - case PPC_INS_FADD: + case PPC_ID_FADDx: REQUIRE3OPS ei0 = il.FloatAdd(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); - ei0 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.SetRegister(8, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei0); break; - case PPC_INS_FADDS: + case PPC_ID_FADDSx: REQUIRE3OPS ei0 = il.FloatAdd(4, operToIL(il, oper1), operToIL(il, oper2)); - ei0 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.SetRegister(4, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei0); break; - case PPC_INS_FSUB: + case PPC_ID_FSUBx: REQUIRE3OPS ei0 = il.FloatSub(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); - ei0 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.SetRegister(8, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei0); break; - case PPC_INS_FSUBS: + case PPC_ID_FSUBSx: REQUIRE3OPS ei0 = il.FloatSub(4, operToIL(il, oper1), operToIL(il, oper2)); - ei0 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.SetRegister(4, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei0); break; - case PPC_INS_FCMPU: + case PPC_ID_FCMPU: REQUIRE3OPS ei0 = il.Register(RZF, oper1->reg); ei1 = il.Register(RZF, oper2->reg); - ei2 = il.FloatSub(RZF, ei0, ei1, crxToFlagWriteType(oper0->reg | PPC_CRX_FLOAT_MASK)); + ei2 = il.FloatSub(RZF, ei0, ei1, crxToFlagWriteType(oper0->reg, PPC_SUF_F)); il.AddInstruction(ei2); break; - case PPC_INS_BN_FCMPO: + case PPC_ID_FCMPO: REQUIRE3OPS ei0 = il.Register(RZF, oper1->reg); ei1 = il.Register(RZF, oper2->reg); - ei2 = il.FloatSub(RZF, ei0, ei1, crxToFlagWriteType(oper0->reg | PPC_CRX_FLOAT_MASK)); + ei2 = il.FloatSub(RZF, ei0, ei1, crxToFlagWriteType(oper0->reg, PPC_SUF_F)); il.AddInstruction(ei2); break; - case PPC_INS_FMR: + case PPC_ID_FMRx: REQUIRE2OPS ei0 = il.SetRegister(8, oper0->reg, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); il.AddInstruction(ei0); break; - case PPC_INS_STFS: + case PPC_ID_STFS: REQUIRE2OPS ei0 = il.FloatConvert(4, operToIL(il, oper0)); ei0 = il.Store(4, operToIL(il, oper1), ei0); @@ -1910,7 +1747,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); break; - case PPC_INS_STFSX: + case PPC_ID_STFSX: REQUIRE3OPS ei0 = il.FloatConvert(4, operToIL(il, oper0)); ei1 = il.Add(4, operToIL(il, oper1), operToIL(il, oper2)); @@ -1919,7 +1756,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); break; - case PPC_INS_STFD: + case PPC_ID_STFD: REQUIRE2OPS ei0 = il.Store(8, operToIL(il, oper1), il.FloatConvert(8, operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8))); @@ -1927,7 +1764,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); break; - case PPC_INS_LFS: + case PPC_ID_LFS: REQUIRE2OPS // ei0 = operToIL(il, oper1); // d(rA) or 0 // ei0 = il.Load(4, ei0); // [d(rA)] @@ -1936,10 +1773,10 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // il.AddInstruction(ei1); // alternatively, do it the way arm64 does it - loadstoreppcfs(il, 4, oper0, oper1); + load_float(il, 4, oper0, oper1); break; - case PPC_INS_LFSX: + case PPC_ID_LFSX: REQUIRE3OPS // ei0 = il.Add(4, operToIL(il, oper1), operToIL(il, oper2)); // ei0 = il.Load(4, ei0); @@ -1949,20 +1786,20 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // // alternatively, do it the way arm64 does it // il.AddInstruction(ei0); - loadstoreppcfs(il, 4, oper0, oper1, oper2); + load_float(il, 4, oper0, oper1, oper2); break; - case PPC_INS_LFSU: + case PPC_ID_LFSU: REQUIRE2OPS - loadstoreppcfs(il, 4, oper0, oper1, 0, true); + load_float(il, 4, oper0, oper1, 0, true); break; - case PPC_INS_LFSUX: + case PPC_ID_LFSUX: REQUIRE3OPS - loadstoreppcfs(il, 4, oper0, oper1, oper2, true); + load_float(il, 4, oper0, oper1, oper2, true); break; - case PPC_INS_LFD: + case PPC_ID_LFD: REQUIRE2OPS // ei0 = operToIL(il, oper1); // d(rA) or 0 // ei0 = il.Load(8, ei0); // [d(rA)] @@ -1970,70 +1807,70 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // il.AddInstruction(ei0); // same as lfs - loadstoreppcfs(il, 8, oper0, oper1); + load_float(il, 8, oper0, oper1); break; - case PPC_INS_FMUL: + case PPC_ID_FMULx: REQUIRE3OPS ei0 = il.MultDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); - ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(8, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FMULS: + case PPC_ID_FMULSx: REQUIRE3OPS ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper2)); - ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(4, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FDIV: + case PPC_ID_FDIVx: REQUIRE3OPS ei0 = il.DivDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); - ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(8, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FDIVS: + case PPC_ID_FDIVSx: REQUIRE3OPS ei0 = il.FloatDiv(4, operToIL(il, oper1), operToIL(il, oper2)); - ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(4, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FMADD: + case PPC_ID_FMADDx: REQUIRE4OPS ei0 = il.MultDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), operToIL(il, oper3, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); ei0 = il.FloatAdd(8, ei0, operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); - ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(8, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FMADDS: + case PPC_ID_FMADDSx: REQUIRE4OPS - ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper3), (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); - ei0 = il.FloatAdd(4, ei0, operToIL(il, oper2), (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper3), (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.FloatAdd(4, ei0, operToIL(il, oper2), (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); ei1 = il.SetRegister(4, oper0->reg, ei0); il.AddInstruction(ei1); break; - case PPC_INS_FMSUB: + case PPC_ID_FMSUBx: REQUIRE4OPS ei0 = il.MultDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), operToIL(il, oper3, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); ei0 = il.FloatSub(8, ei0, operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); - ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(8, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FMSUBS: + case PPC_ID_FMSUBSx: REQUIRE4OPS ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper3)); ei0 = il.FloatSub(4, ei0, operToIL(il, oper2)); - ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(4, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; @@ -2041,103 +1878,103 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // bits 32-63 of a double reg to that result, ignoring the lower 32 bits 0-31. // TODO: needs further testing to verify that this is functional, and verify that the // method used was correct, as well as the registers afffected, like FPSCR. - case PPC_INS_FCTIWZ: + case PPC_ID_FCTIWZx: REQUIRE2OPS ei0 = il.FloatTrunc(RZF, operToIL(il, oper1)); ei1 = il.Const(4, 32); ei2 = il.ShiftLeft(8, ei0, ei1); - ei0 = il.SetRegister(8, oper0->reg, ei2, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.SetRegister(8, oper0->reg, ei2, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei0); break; - case PPC_INS_FNEG: + case PPC_ID_FNEGx: REQUIRE2OPS ei0 = il.FloatNeg(4, operToIL(il, oper1)); - ei0 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.SetRegister(4, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei0); break; - case PPC_INS_FNMADD: + case PPC_ID_FNMADDx: REQUIRE4OPS ei0 = il.MultDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), operToIL(il, oper3, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); ei0 = il.FloatAdd(8, ei0, operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); ei0 = il.FloatNeg(8, ei0); - ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(8, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FNMADDS: + case PPC_ID_FNMADDSx: REQUIRE4OPS - ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper3), (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); - ei0 = il.FloatAdd(4, ei0, operToIL(il, oper2), (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper3), (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.FloatAdd(4, ei0, operToIL(il, oper2), (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); ei0 = il.FloatNeg(4, ei0); ei1 = il.SetRegister(4, oper0->reg, ei0); il.AddInstruction(ei1); break; - case PPC_INS_FNMSUB: + case PPC_ID_FNMSUBx: REQUIRE4OPS ei0 = il.MultDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), operToIL(il, oper3, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); ei0 = il.FloatSub(8, ei0, operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); ei0 = il.FloatNeg(8, ei0); - ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(8, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FNMSUBS: + case PPC_ID_FNMSUBSx: REQUIRE4OPS ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper3)); ei0 = il.FloatSub(4, ei0, operToIL(il, oper2)); ei0 = il.FloatNeg(4, ei0); - ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(4, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FABS: + case PPC_ID_FABSx: REQUIRE2OPS ei0 = il.FloatAbs(4, operToIL(il, oper1)); - ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(4, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FNABS: + case PPC_ID_FNABSx: REQUIRE2OPS ei0 = il.FloatAbs(4, operToIL(il, oper1)); ei0 = il.FloatNeg(4, ei0); - ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(4, oper0->reg, ei0, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; // TODO: needs more testing to make sure that stuff is good. the decompilation is a // little rough, seems to be making the const double 1 into an int by default, // gonna have to figure out how if its right and FPSCR is correct. - case PPC_INS_FRSQRTE: + case PPC_ID_FRSQRTEx: REQUIRE2OPS ei0 = il.FloatConstDouble(1); ei1 = il.FloatSqrt(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); ei1 = il.DivDoublePrecSigned(8, ei0, ei1); - ei1 = il.SetRegister(8, oper0->reg, ei1, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(8, oper0->reg, ei1, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_FRSQRTES: + case PPC_ID_FRSQRTESx: REQUIRE2OPS ei0 = il.FloatConstSingle(1); ei1 = il.FloatSqrt(4, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); ei1 = il.FloatDiv(4, ei0, ei1); - ei1 = il.SetRegister(4, oper0->reg, ei1, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(4, oper0->reg, ei1, (instruction->flags.rc) ? IL_FLAGWRITE_CR0_F : 0); il.AddInstruction(ei1); break; - case PPC_INS_CNTLZW: + case PPC_ID_CNTLZWx: ei0 = il.Intrinsic({RegisterOrFlag::Register(oper1->reg)}, PPC_INTRIN_CNTLZW, {operToIL(il, oper0)}); il.AddInstruction(ei0); break; - case PPC_INS_PSQ_ST: + case PPC_ID_PSQ_ST: REQUIRE4OPS MYLOG("0x%08x psq_st args f%d r%d[%d] w:%lldd gcqr:%lld\n", (uint32_t)addr, oper0->reg - PPC_REG_F0, oper1->mem.base - PPC_REG_R0, oper1->mem.disp, oper2->imm, @@ -2153,7 +1990,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, PPC_PS_INTRIN_QUANTIZE, { operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 4), - il.Const(4, oper3->imm) + il.Const(4, oper3->uimm) } ); @@ -2175,7 +2012,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // } break; - case PPC_INS_PSQ_L: + case PPC_ID_PSQ_L: REQUIRE4OPS // w_l = oper2->imm; @@ -2186,7 +2023,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, { ei0, operToIL(il, oper0), - il.Const(4, oper3->imm) + il.Const(4, oper3->uimm) } ); @@ -2200,7 +2037,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, break; - case PPC_INS_FRSP: + case PPC_ID_FRSPx: ei0 = il.Intrinsic( {RegisterOrFlag::Register(oper0->reg)}, PPC_INTRIN_FRSP, @@ -2208,757 +2045,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); break; - // ===================================== - // =====TO BE DEFINED INSTRUCTIONS====== - // ===================================== - - case PPC_INS_BCL: - case PPC_INS_BCLR: - case PPC_INS_BCLRL: - case PPC_INS_CNTLZD: - case PPC_INS_DCBA: - case PPC_INS_DCBF: - case PPC_INS_DCBI: - case PPC_INS_DCBST: - case PPC_INS_DCBT: - case PPC_INS_DCBTST: - case PPC_INS_DCBZ: - case PPC_INS_DCBZL: - case PPC_INS_DCCCI: - case PPC_INS_DIVD: - case PPC_INS_DIVDU: - case PPC_INS_DSS: - case PPC_INS_DSSALL: - case PPC_INS_DST: - case PPC_INS_DSTST: - case PPC_INS_DSTSTT: - case PPC_INS_DSTT: - case PPC_INS_EIEIO: - case PPC_INS_EVABS: - case PPC_INS_EVADDIW: - case PPC_INS_EVADDSMIAAW: - case PPC_INS_EVADDSSIAAW: - case PPC_INS_EVADDUMIAAW: - case PPC_INS_EVADDUSIAAW: - case PPC_INS_EVADDW: - case PPC_INS_EVAND: - case PPC_INS_EVANDC: - case PPC_INS_EVCMPEQ: - case PPC_INS_EVCMPGTS: - case PPC_INS_EVCMPGTU: - case PPC_INS_EVCMPLTS: - case PPC_INS_EVCMPLTU: - case PPC_INS_EVCNTLSW: - case PPC_INS_EVCNTLZW: - case PPC_INS_EVDIVWS: - case PPC_INS_EVDIVWU: - case PPC_INS_EVEQV: - case PPC_INS_EVEXTSB: - case PPC_INS_EVEXTSH: - case PPC_INS_EVLDD: - case PPC_INS_EVLDDX: - case PPC_INS_EVLDH: - case PPC_INS_EVLDHX: - case PPC_INS_EVLDW: - case PPC_INS_EVLDWX: - case PPC_INS_EVLHHESPLAT: - case PPC_INS_EVLHHESPLATX: - case PPC_INS_EVLHHOSSPLAT: - case PPC_INS_EVLHHOSSPLATX: - case PPC_INS_EVLHHOUSPLAT: - case PPC_INS_EVLHHOUSPLATX: - case PPC_INS_EVLWHE: - case PPC_INS_EVLWHEX: - case PPC_INS_EVLWHOS: - case PPC_INS_EVLWHOSX: - case PPC_INS_EVLWHOU: - case PPC_INS_EVLWHOUX: - case PPC_INS_EVLWHSPLAT: - case PPC_INS_EVLWHSPLATX: - case PPC_INS_EVLWWSPLAT: - case PPC_INS_EVLWWSPLATX: - case PPC_INS_EVMERGEHI: - case PPC_INS_EVMERGEHILO: - case PPC_INS_EVMERGELO: - case PPC_INS_EVMERGELOHI: - case PPC_INS_EVMHEGSMFAA: - case PPC_INS_EVMHEGSMFAN: - case PPC_INS_EVMHEGSMIAA: - case PPC_INS_EVMHEGSMIAN: - case PPC_INS_EVMHEGUMIAA: - case PPC_INS_EVMHEGUMIAN: - case PPC_INS_EVMHESMF: - case PPC_INS_EVMHESMFA: - case PPC_INS_EVMHESMFAAW: - case PPC_INS_EVMHESMFANW: - case PPC_INS_EVMHESMI: - case PPC_INS_EVMHESMIA: - case PPC_INS_EVMHESMIAAW: - case PPC_INS_EVMHESMIANW: - case PPC_INS_EVMHESSF: - case PPC_INS_EVMHESSFA: - case PPC_INS_EVMHESSFAAW: - case PPC_INS_EVMHESSFANW: - case PPC_INS_EVMHESSIAAW: - case PPC_INS_EVMHESSIANW: - case PPC_INS_EVMHEUMI: - case PPC_INS_EVMHEUMIA: - case PPC_INS_EVMHEUMIAAW: - case PPC_INS_EVMHEUMIANW: - case PPC_INS_EVMHEUSIAAW: - case PPC_INS_EVMHEUSIANW: - case PPC_INS_EVMHOGSMFAA: - case PPC_INS_EVMHOGSMFAN: - case PPC_INS_EVMHOGSMIAA: - case PPC_INS_EVMHOGSMIAN: - case PPC_INS_EVMHOGUMIAA: - case PPC_INS_EVMHOGUMIAN: - case PPC_INS_EVMHOSMF: - case PPC_INS_EVMHOSMFA: - case PPC_INS_EVMHOSMFAAW: - case PPC_INS_EVMHOSMFANW: - case PPC_INS_EVMHOSMI: - case PPC_INS_EVMHOSMIA: - case PPC_INS_EVMHOSMIAAW: - case PPC_INS_EVMHOSMIANW: - case PPC_INS_EVMHOSSF: - case PPC_INS_EVMHOSSFA: - case PPC_INS_EVMHOSSFAAW: - case PPC_INS_EVMHOSSFANW: - case PPC_INS_EVMHOSSIAAW: - case PPC_INS_EVMHOSSIANW: - case PPC_INS_EVMHOUMI: - case PPC_INS_EVMHOUMIA: - case PPC_INS_EVMHOUMIAAW: - case PPC_INS_EVMHOUMIANW: - case PPC_INS_EVMHOUSIAAW: - case PPC_INS_EVMHOUSIANW: - case PPC_INS_EVMRA: - case PPC_INS_EVMWHSMF: - case PPC_INS_EVMWHSMFA: - case PPC_INS_EVMWHSMI: - case PPC_INS_EVMWHSMIA: - case PPC_INS_EVMWHSSF: - case PPC_INS_EVMWHSSFA: - case PPC_INS_EVMWHUMI: - case PPC_INS_EVMWHUMIA: - case PPC_INS_EVMWLSMIAAW: - case PPC_INS_EVMWLSMIANW: - case PPC_INS_EVMWLSSIAAW: - case PPC_INS_EVMWLSSIANW: - case PPC_INS_EVMWLUMI: - case PPC_INS_EVMWLUMIA: - case PPC_INS_EVMWLUMIAAW: - case PPC_INS_EVMWLUMIANW: - case PPC_INS_EVMWLUSIAAW: - case PPC_INS_EVMWLUSIANW: - case PPC_INS_EVMWSMF: - case PPC_INS_EVMWSMFA: - case PPC_INS_EVMWSMFAA: - case PPC_INS_EVMWSMFAN: - case PPC_INS_EVMWSMI: - case PPC_INS_EVMWSMIA: - case PPC_INS_EVMWSMIAA: - case PPC_INS_EVMWSMIAN: - case PPC_INS_EVMWSSF: - case PPC_INS_EVMWSSFA: - case PPC_INS_EVMWSSFAA: - case PPC_INS_EVMWSSFAN: - case PPC_INS_EVMWUMI: - case PPC_INS_EVMWUMIA: - case PPC_INS_EVMWUMIAA: - case PPC_INS_EVMWUMIAN: - case PPC_INS_EVNAND: - case PPC_INS_EVNEG: - case PPC_INS_EVNOR: - case PPC_INS_EVOR: - case PPC_INS_EVORC: - case PPC_INS_EVRLW: - case PPC_INS_EVRLWI: - case PPC_INS_EVRNDW: - case PPC_INS_EVSLW: - case PPC_INS_EVSLWI: - case PPC_INS_EVSPLATFI: - case PPC_INS_EVSPLATI: - case PPC_INS_EVSRWIS: - case PPC_INS_EVSRWIU: - case PPC_INS_EVSRWS: - case PPC_INS_EVSRWU: - case PPC_INS_EVSTDD: - case PPC_INS_EVSTDDX: - case PPC_INS_EVSTDH: - case PPC_INS_EVSTDHX: - case PPC_INS_EVSTDW: - case PPC_INS_EVSTDWX: - case PPC_INS_EVSTWHE: - case PPC_INS_EVSTWHEX: - case PPC_INS_EVSTWHO: - case PPC_INS_EVSTWHOX: - case PPC_INS_EVSTWWE: - case PPC_INS_EVSTWWEX: - case PPC_INS_EVSTWWO: - case PPC_INS_EVSTWWOX: - case PPC_INS_EVSUBFSMIAAW: - case PPC_INS_EVSUBFSSIAAW: - case PPC_INS_EVSUBFUMIAAW: - case PPC_INS_EVSUBFUSIAAW: - case PPC_INS_EVSUBFW: - case PPC_INS_EVSUBIFW: - case PPC_INS_EVXOR: - case PPC_INS_FCFID: - case PPC_INS_FCFIDS: - case PPC_INS_FCFIDU: - case PPC_INS_FCFIDUS: - case PPC_INS_FCPSGN: - case PPC_INS_FCTID: - case PPC_INS_FCTIDUZ: - case PPC_INS_FCTIDZ: - case PPC_INS_FCTIW: - case PPC_INS_FCTIWUZ: - case PPC_INS_FRE: - case PPC_INS_FRES: - case PPC_INS_FRIM: - case PPC_INS_FRIN: - case PPC_INS_FRIP: - case PPC_INS_FRIZ: - case PPC_INS_FSEL: - case PPC_INS_FSQRT: - case PPC_INS_FSQRTS: - case PPC_INS_ICBI: - case PPC_INS_ICCCI: - case PPC_INS_ISYNC: - case PPC_INS_LDARX: - case PPC_INS_LDBRX: - case PPC_INS_LFDU: - case PPC_INS_LFDUX: - case PPC_INS_LFDX: - case PPC_INS_LFIWAX: - case PPC_INS_LFIWZX: - case PPC_INS_LSWI: - case PPC_INS_LVEBX: - case PPC_INS_LVEHX: - case PPC_INS_LVEWX: - case PPC_INS_LVSL: - case PPC_INS_LVSR: - case PPC_INS_LVX: - case PPC_INS_LVXL: - case PPC_INS_LWA: - case PPC_INS_LWARX: - case PPC_INS_LWAUX: - case PPC_INS_LWAX: - case PPC_INS_LXSDX: - case PPC_INS_LXVD2X: - case PPC_INS_LXVDSX: - case PPC_INS_LXVW4X: - case PPC_INS_MBAR: - case PPC_INS_MCRF: - case PPC_INS_MFDCR: - case PPC_INS_MFFS: - case PPC_INS_MFMSR: - case PPC_INS_MFOCRF: - case PPC_INS_MFSPR: - case PPC_INS_MFSR: - case PPC_INS_MFSRIN: - case PPC_INS_MFTB: - case PPC_INS_MFVSCR: - case PPC_INS_MSYNC: - case PPC_INS_MTDCR: - case PPC_INS_MTFSB0: - case PPC_INS_MTFSB1: - case PPC_INS_MTFSF: - case PPC_INS_MTMSR: - case PPC_INS_MTMSRD: - case PPC_INS_MTOCRF: - case PPC_INS_MTSPR: - case PPC_INS_MTSR: - case PPC_INS_MTSRIN: - case PPC_INS_MTVSCR: - case PPC_INS_MULHD: - case PPC_INS_MULHDU: - case PPC_INS_MULLD: - case PPC_INS_POPCNTD: - case PPC_INS_POPCNTW: - case PPC_INS_RFCI: - case PPC_INS_RFDI: - case PPC_INS_RFID: - case PPC_INS_RFMCI: - case PPC_INS_RLDCL: - case PPC_INS_RLDCR: - case PPC_INS_RLDIC: - case PPC_INS_RLDICL: - case PPC_INS_RLDICR: - case PPC_INS_RLDIMI: - case PPC_INS_SLBIA: - case PPC_INS_SLBIE: - case PPC_INS_SLBMFEE: - case PPC_INS_SLBMTE: - case PPC_INS_STDBRX: - case PPC_INS_STDCX: - case PPC_INS_STFDU: - case PPC_INS_STFDUX: - case PPC_INS_STFDX: - case PPC_INS_STFIWX: - case PPC_INS_STFSU: - case PPC_INS_STFSUX: - case PPC_INS_STSWI: - case PPC_INS_STVEBX: - case PPC_INS_STVEHX: - case PPC_INS_STVEWX: - case PPC_INS_STVX: - case PPC_INS_STVXL: - case PPC_INS_STWCX: - case PPC_INS_STXSDX: - case PPC_INS_STXVD2X: - case PPC_INS_STXVW4X: - case PPC_INS_SYNC: - case PPC_INS_TD: - case PPC_INS_TDI: - case PPC_INS_TLBIA: - case PPC_INS_TLBIE: - case PPC_INS_TLBIEL: - case PPC_INS_TLBIVAX: - case PPC_INS_TLBLD: - case PPC_INS_TLBLI: - case PPC_INS_TLBRE: - case PPC_INS_TLBSX: - case PPC_INS_TLBSYNC: - case PPC_INS_TLBWE: - case PPC_INS_TW: - case PPC_INS_TWI: - case PPC_INS_VADDCUW: - case PPC_INS_VADDFP: - case PPC_INS_VADDSBS: - case PPC_INS_VADDSHS: - case PPC_INS_VADDSWS: - case PPC_INS_VADDUBM: - case PPC_INS_VADDUBS: - case PPC_INS_VADDUHM: - case PPC_INS_VADDUHS: - case PPC_INS_VADDUWM: - case PPC_INS_VADDUWS: - case PPC_INS_VAND: - case PPC_INS_VANDC: - case PPC_INS_VAVGSB: - case PPC_INS_VAVGSH: - case PPC_INS_VAVGSW: - case PPC_INS_VAVGUB: - case PPC_INS_VAVGUH: - case PPC_INS_VAVGUW: - case PPC_INS_VCFSX: - case PPC_INS_VCFUX: - case PPC_INS_VCMPBFP: - case PPC_INS_VCMPEQFP: - case PPC_INS_VCMPEQUB: - case PPC_INS_VCMPEQUH: - case PPC_INS_VCMPEQUW: - case PPC_INS_VCMPGEFP: - case PPC_INS_VCMPGTFP: - case PPC_INS_VCMPGTSB: - case PPC_INS_VCMPGTSH: - case PPC_INS_VCMPGTSW: - case PPC_INS_VCMPGTUB: - case PPC_INS_VCMPGTUH: - case PPC_INS_VCMPGTUW: - case PPC_INS_VCTSXS: - case PPC_INS_VCTUXS: - case PPC_INS_VEXPTEFP: - case PPC_INS_VLOGEFP: - case PPC_INS_VMADDFP: - case PPC_INS_VMAXFP: - case PPC_INS_VMAXSB: - case PPC_INS_VMAXSH: - case PPC_INS_VMAXSW: - case PPC_INS_VMAXUB: - case PPC_INS_VMAXUH: - case PPC_INS_VMAXUW: - case PPC_INS_VMHADDSHS: - case PPC_INS_VMHRADDSHS: - case PPC_INS_VMINFP: - case PPC_INS_VMINSB: - case PPC_INS_VMINSH: - case PPC_INS_VMINSW: - case PPC_INS_VMINUB: - case PPC_INS_VMINUH: - case PPC_INS_VMINUW: - case PPC_INS_VMLADDUHM: - case PPC_INS_VMRGHB: - case PPC_INS_VMRGHH: - case PPC_INS_VMRGHW: - case PPC_INS_VMRGLB: - case PPC_INS_VMRGLH: - case PPC_INS_VMRGLW: - case PPC_INS_VMSUMMBM: - case PPC_INS_VMSUMSHM: - case PPC_INS_VMSUMSHS: - case PPC_INS_VMSUMUBM: - case PPC_INS_VMSUMUHM: - case PPC_INS_VMSUMUHS: - case PPC_INS_VMULESB: - case PPC_INS_VMULESH: - case PPC_INS_VMULEUB: - case PPC_INS_VMULEUH: - case PPC_INS_VMULOSB: - case PPC_INS_VMULOSH: - case PPC_INS_VMULOUB: - case PPC_INS_VMULOUH: - case PPC_INS_VNMSUBFP: - case PPC_INS_VNOR: - case PPC_INS_VOR: - case PPC_INS_VPERM: - case PPC_INS_VPKPX: - case PPC_INS_VPKSHSS: - case PPC_INS_VPKSHUS: - case PPC_INS_VPKSWSS: - case PPC_INS_VPKSWUS: - case PPC_INS_VPKUHUM: - case PPC_INS_VPKUHUS: - case PPC_INS_VPKUWUM: - case PPC_INS_VPKUWUS: - case PPC_INS_VREFP: - case PPC_INS_VRFIM: - case PPC_INS_VRFIN: - case PPC_INS_VRFIP: - case PPC_INS_VRFIZ: - case PPC_INS_VRLB: - case PPC_INS_VRLH: - case PPC_INS_VRLW: - case PPC_INS_VRSQRTEFP: - case PPC_INS_VSEL: - case PPC_INS_VSL: - case PPC_INS_VSLB: - case PPC_INS_VSLDOI: - case PPC_INS_VSLH: - case PPC_INS_VSLO: - case PPC_INS_VSLW: - case PPC_INS_VSPLTB: - case PPC_INS_VSPLTH: - case PPC_INS_VSPLTISB: - case PPC_INS_VSPLTISH: - case PPC_INS_VSPLTISW: - case PPC_INS_VSPLTW: - case PPC_INS_VSR: - case PPC_INS_VSRAB: - case PPC_INS_VSRAH: - case PPC_INS_VSRAW: - case PPC_INS_VSRB: - case PPC_INS_VSRH: - case PPC_INS_VSRO: - case PPC_INS_VSRW: - case PPC_INS_VSUBCUW: - case PPC_INS_VSUBFP: - case PPC_INS_VSUBSBS: - case PPC_INS_VSUBSHS: - case PPC_INS_VSUBSWS: - case PPC_INS_VSUBUBM: - case PPC_INS_VSUBUBS: - case PPC_INS_VSUBUHM: - case PPC_INS_VSUBUHS: - case PPC_INS_VSUBUWM: - case PPC_INS_VSUBUWS: - case PPC_INS_VSUM2SWS: - case PPC_INS_VSUM4SBS: - case PPC_INS_VSUM4SHS: - case PPC_INS_VSUM4UBS: - case PPC_INS_VSUMSWS: - case PPC_INS_VUPKHPX: - case PPC_INS_VUPKHSB: - case PPC_INS_VUPKHSH: - case PPC_INS_VUPKLPX: - case PPC_INS_VUPKLSB: - case PPC_INS_VUPKLSH: - case PPC_INS_VXOR: - case PPC_INS_WAIT: - case PPC_INS_WRTEE: - case PPC_INS_WRTEEI: - case PPC_INS_XSABSDP: - case PPC_INS_XSADDDP: - case PPC_INS_XSCMPODP: - case PPC_INS_XSCMPUDP: - case PPC_INS_XSCPSGNDP: - case PPC_INS_XSCVDPSP: - case PPC_INS_XSCVDPSXDS: - case PPC_INS_XSCVDPSXWS: - case PPC_INS_XSCVDPUXDS: - case PPC_INS_XSCVDPUXWS: - case PPC_INS_XSCVSPDP: - case PPC_INS_XSCVSXDDP: - case PPC_INS_XSCVUXDDP: - case PPC_INS_XSDIVDP: - case PPC_INS_XSMADDADP: - case PPC_INS_XSMADDMDP: - case PPC_INS_XSMAXDP: - case PPC_INS_XSMINDP: - case PPC_INS_XSMSUBADP: - case PPC_INS_XSMSUBMDP: - case PPC_INS_XSMULDP: - case PPC_INS_XSNABSDP: - case PPC_INS_XSNEGDP: - case PPC_INS_XSNMADDADP: - case PPC_INS_XSNMADDMDP: - case PPC_INS_XSNMSUBADP: - case PPC_INS_XSNMSUBMDP: - case PPC_INS_XSRDPI: - case PPC_INS_XSRDPIC: - case PPC_INS_XSRDPIM: - case PPC_INS_XSRDPIP: - case PPC_INS_XSRDPIZ: - case PPC_INS_XSREDP: - case PPC_INS_XSRSQRTEDP: - case PPC_INS_XSSQRTDP: - case PPC_INS_XSSUBDP: - case PPC_INS_XSTDIVDP: - case PPC_INS_XSTSQRTDP: - case PPC_INS_XVABSDP: - case PPC_INS_XVABSSP: - case PPC_INS_XVADDDP: - case PPC_INS_XVADDSP: - case PPC_INS_XVCMPEQDP: - case PPC_INS_XVCMPEQSP: - case PPC_INS_XVCMPGEDP: - case PPC_INS_XVCMPGESP: - case PPC_INS_XVCMPGTDP: - case PPC_INS_XVCMPGTSP: - case PPC_INS_XVCPSGNDP: - case PPC_INS_XVCPSGNSP: - case PPC_INS_XVCVDPSP: - case PPC_INS_XVCVDPSXDS: - case PPC_INS_XVCVDPSXWS: - case PPC_INS_XVCVDPUXDS: - case PPC_INS_XVCVDPUXWS: - case PPC_INS_XVCVSPDP: - case PPC_INS_XVCVSPSXDS: - case PPC_INS_XVCVSPSXWS: - case PPC_INS_XVCVSPUXDS: - case PPC_INS_XVCVSPUXWS: - case PPC_INS_XVCVSXDDP: - case PPC_INS_XVCVSXDSP: - case PPC_INS_XVCVSXWDP: - case PPC_INS_XVCVSXWSP: - case PPC_INS_XVCVUXDDP: - case PPC_INS_XVCVUXDSP: - case PPC_INS_XVCVUXWDP: - case PPC_INS_XVCVUXWSP: - case PPC_INS_XVDIVDP: - case PPC_INS_XVDIVSP: - case PPC_INS_XVMADDADP: - case PPC_INS_XVMADDASP: - case PPC_INS_XVMADDMDP: - case PPC_INS_XVMADDMSP: - case PPC_INS_XVMAXDP: - case PPC_INS_XVMAXSP: - case PPC_INS_XVMINDP: - case PPC_INS_XVMINSP: - case PPC_INS_XVMSUBADP: - case PPC_INS_XVMSUBASP: - case PPC_INS_XVMSUBMDP: - case PPC_INS_XVMSUBMSP: - case PPC_INS_XVMULDP: - case PPC_INS_XVMULSP: - case PPC_INS_XVNABSDP: - case PPC_INS_XVNABSSP: - case PPC_INS_XVNEGDP: - case PPC_INS_XVNEGSP: - case PPC_INS_XVNMADDADP: - case PPC_INS_XVNMADDASP: - case PPC_INS_XVNMADDMDP: - case PPC_INS_XVNMADDMSP: - case PPC_INS_XVNMSUBADP: - case PPC_INS_XVNMSUBASP: - case PPC_INS_XVNMSUBMDP: - case PPC_INS_XVNMSUBMSP: - case PPC_INS_XVRDPI: - case PPC_INS_XVRDPIC: - case PPC_INS_XVRDPIM: - case PPC_INS_XVRDPIP: - case PPC_INS_XVRDPIZ: - case PPC_INS_XVREDP: - case PPC_INS_XVRESP: - case PPC_INS_XVRSPI: - case PPC_INS_XVRSPIC: - case PPC_INS_XVRSPIM: - case PPC_INS_XVRSPIP: - case PPC_INS_XVRSPIZ: - case PPC_INS_XVRSQRTEDP: - case PPC_INS_XVRSQRTESP: - case PPC_INS_XVSQRTDP: - case PPC_INS_XVSQRTSP: - case PPC_INS_XVSUBDP: - case PPC_INS_XVSUBSP: - case PPC_INS_XVTDIVDP: - case PPC_INS_XVTDIVSP: - case PPC_INS_XVTSQRTDP: - case PPC_INS_XVTSQRTSP: - case PPC_INS_XXLAND: - case PPC_INS_XXLANDC: - case PPC_INS_XXLNOR: - case PPC_INS_XXLOR: - case PPC_INS_XXLXOR: - case PPC_INS_XXMRGHW: - case PPC_INS_XXMRGLW: - case PPC_INS_XXPERMDI: - case PPC_INS_XXSEL: - case PPC_INS_XXSLDWI: - case PPC_INS_XXSPLTW: - case PPC_INS_BCA: - case PPC_INS_BCLA: - case PPC_INS_SLDI: - case PPC_INS_BTA: - case PPC_INS_MFBR0: - case PPC_INS_MFBR1: - case PPC_INS_MFBR2: - case PPC_INS_MFBR3: - case PPC_INS_MFBR4: - case PPC_INS_MFBR5: - case PPC_INS_MFBR6: - case PPC_INS_MFBR7: - case PPC_INS_MFXER: - case PPC_INS_MFRTCU: - case PPC_INS_MFRTCL: - case PPC_INS_MFDSCR: - case PPC_INS_MFDSISR: - case PPC_INS_MFDAR: - case PPC_INS_MFSRR2: - case PPC_INS_MFSRR3: - case PPC_INS_MFCFAR: - case PPC_INS_MFAMR: - case PPC_INS_MFPID: - case PPC_INS_MFTBLO: - case PPC_INS_MFTBHI: - case PPC_INS_MFDBATU: - case PPC_INS_MFDBATL: - case PPC_INS_MFIBATU: - case PPC_INS_MFIBATL: - case PPC_INS_MFDCCR: - case PPC_INS_MFICCR: - case PPC_INS_MFDEAR: - case PPC_INS_MFESR: - case PPC_INS_MFSPEFSCR: - case PPC_INS_MFTCR: - case PPC_INS_MFASR: - case PPC_INS_MFPVR: - case PPC_INS_MFTBU: - case PPC_INS_MTCR: - case PPC_INS_MTBR0: - case PPC_INS_MTBR1: - case PPC_INS_MTBR2: - case PPC_INS_MTBR3: - case PPC_INS_MTBR4: - case PPC_INS_MTBR5: - case PPC_INS_MTBR6: - case PPC_INS_MTBR7: - case PPC_INS_MTXER: - case PPC_INS_MTDSCR: - case PPC_INS_MTDSISR: - case PPC_INS_MTDAR: - case PPC_INS_MTSRR2: - case PPC_INS_MTSRR3: - case PPC_INS_MTCFAR: - case PPC_INS_MTAMR: - case PPC_INS_MTPID: - case PPC_INS_MTTBL: - case PPC_INS_MTTBU: - case PPC_INS_MTTBLO: - case PPC_INS_MTTBHI: - case PPC_INS_MTDBATU: - case PPC_INS_MTDBATL: - case PPC_INS_MTIBATU: - case PPC_INS_MTIBATL: - case PPC_INS_MTDCCR: - case PPC_INS_MTICCR: - case PPC_INS_MTDEAR: - case PPC_INS_MTESR: - case PPC_INS_MTSPEFSCR: - case PPC_INS_MTTCR: - case PPC_INS_ROTLD: - case PPC_INS_ROTLDI: - case PPC_INS_CLRLDI: - case PPC_INS_SUB: - case PPC_INS_SUBC: - case PPC_INS_LWSYNC: - case PPC_INS_PTESYNC: - case PPC_INS_TDLT: - case PPC_INS_TDEQ: - case PPC_INS_TDGT: - case PPC_INS_TDNE: - case PPC_INS_TDLLT: - case PPC_INS_TDLGT: - case PPC_INS_TDU: - case PPC_INS_TDLTI: - case PPC_INS_TDEQI: - case PPC_INS_TDGTI: - case PPC_INS_TDNEI: - case PPC_INS_TDLLTI: - case PPC_INS_TDLGTI: - case PPC_INS_TDUI: - case PPC_INS_TLBREHI: - case PPC_INS_TLBRELO: - case PPC_INS_TLBWEHI: - case PPC_INS_TLBWELO: - case PPC_INS_TWLT: - case PPC_INS_TWEQ: - case PPC_INS_TWGT: - case PPC_INS_TWNE: - case PPC_INS_TWLLT: - case PPC_INS_TWLGT: - case PPC_INS_TWU: - case PPC_INS_TWLTI: - case PPC_INS_TWEQI: - case PPC_INS_TWGTI: - case PPC_INS_TWNEI: - case PPC_INS_TWLLTI: - case PPC_INS_TWLGTI: - case PPC_INS_TWUI: - case PPC_INS_WAITRSV: - case PPC_INS_WAITIMPL: - // TODO not technically implemented but capstone misinterprettation - // where it is posting that XORI is 1452, though that is XNOP - // case PPC_INS_XNOP: - case PPC_INS_XVMOVDP: - case PPC_INS_XVMOVSP: - case PPC_INS_XXSPLTD: - case PPC_INS_XXMRGHD: - case PPC_INS_XXMRGLD: - case PPC_INS_XXSWAPD: - case PPC_INS_BT: - case PPC_INS_BF: - case PPC_INS_BDNZT: - case PPC_INS_BDNZF: - case PPC_INS_BDZF: - case PPC_INS_BDZT: - case PPC_INS_BFA: - case PPC_INS_BDNZTA: - case PPC_INS_BDNZFA: - case PPC_INS_BDZTA: - case PPC_INS_BDZFA: - case PPC_INS_BTCTR: - case PPC_INS_BFCTR: - case PPC_INS_BTCTRL: - case PPC_INS_BFCTRL: - case PPC_INS_BTL: - case PPC_INS_BFL: - case PPC_INS_BDNZTL: - case PPC_INS_BDNZFL: - case PPC_INS_BDZTL: - case PPC_INS_BDZFL: - case PPC_INS_BTLA: - case PPC_INS_BFLA: - case PPC_INS_BDNZTLA: - case PPC_INS_BDNZFLA: - case PPC_INS_BDZTLA: - case PPC_INS_BDZFLA: - case PPC_INS_BTLR: - case PPC_INS_BFLR: - case PPC_INS_BDNZTLR: - case PPC_INS_BDZTLR: - case PPC_INS_BDZFLR: - case PPC_INS_BTLRL: - case PPC_INS_BFLRL: - case PPC_INS_BDNZTLRL: - case PPC_INS_BDNZFLRL: - case PPC_INS_BDZTLRL: - case PPC_INS_BDZFLRL: - case PPC_INS_BRINC: - ReturnUnimpl: default: MYLOG("%s:%s() returning Unimplemented(...) on:\n", diff --git a/arch/powerpc/il.h b/arch/powerpc/il.h index b4ca2526c..1e8f67c21 100644 --- a/arch/powerpc/il.h +++ b/arch/powerpc/il.h @@ -1,3 +1,5 @@ +#include "decode/decode.h" + /* these are the flags in cr0 (the default condition field in condition register CR) @@ -219,4 +221,4 @@ enum PPCIntrinsic : uint32_t }; -bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction& il, const uint8_t *data, uint64_t addr, decomp_result *res, bool le); +bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction& il, Instruction* instruction, uint64_t addr); diff --git a/arch/powerpc/util.cpp b/arch/powerpc/util.cpp index 5e37f735c..9b7b11194 100644 --- a/arch/powerpc/util.cpp +++ b/arch/powerpc/util.cpp @@ -4,87 +4,6 @@ #define MYLOG(...) while(0); //#define MYLOG BinaryNinja::LogDebug -void printOperandVerbose(decomp_result *res, cs_ppc_op *op) -{ - (void)res; - if(op == NULL) { - MYLOG("NULL\n"); - return; - } - - switch(op->type) { - case PPC_OP_INVALID: - MYLOG("invalid\n"); - break; - case PPC_OP_REG: - MYLOG("reg: %s\n", cs_reg_name(res->handle, op->reg)); - break; - case PPC_OP_IMM: - MYLOG("imm: 0x%X\n", op->imm); - break; - case PPC_OP_MEM: - MYLOG("mem (%s + %d)\n", cs_reg_name(res->handle, op->mem.base), - op->mem.disp); - break; - case PPC_OP_CRX: - MYLOG("crx (scale:%d, reg:%s)\n", op->crx.scale, - cs_reg_name(res->handle, op->crx.reg)); - break; - default: - MYLOG("unknown (%d)\n", op->type); - break; - } -} - -void printInstructionVerbose(decomp_result *res) -{ - struct cs_insn *insn = &(res->insn); - struct cs_detail *detail = &(res->detail); - struct cs_ppc *ppc = &(detail->ppc); - (void)insn; - - /* LEVEL1: id, address, size, bytes, mnemonic, op_str */ - MYLOG("instruction id: %d \"%s %s\"\n", insn->id, insn->mnemonic, - insn->op_str); - - MYLOG(" bytes: %02X %02X %02X %02X\n", insn->bytes[0], insn->bytes[1], - insn->bytes[2], insn->bytes[3]); - - /* LEVEL2: regs_read, regs_write, groups */ - MYLOG(" regs read:"); - for(int j=0; jregs_read_count; ++j) { - MYLOG(" %s", cs_reg_name(res->handle, detail->regs_read[j])); - } - MYLOG("\n"); - MYLOG(" regs write:"); - for(int j=0; jregs_write_count; ++j) { - MYLOG(" %s", cs_reg_name(res->handle, detail->regs_write[j])); - } - MYLOG("\n"); - MYLOG(" groups:"); - for(int j=0; jgroups_count; ++j) { - int group = detail->groups[j]; - (void)group; - MYLOG(" %d(%s)", group, cs_group_name(res->handle, group)); - } - MYLOG("\n"); - - /* LEVEL3: branch code, branch hint, update_cr0, operands */ - if(1 /* branch instruction */) { - MYLOG(" branch code: %d\n", ppc->bc); // PPC_BC_LT, PPC_BC_LE, etc. - MYLOG(" branch hint: %d\n", ppc->bh); // PPC_BH_PLUS, PPC_BH_MINUS - } - - MYLOG(" update_cr0: %d\n", ppc->update_cr0); - - // .op_count is number of operands - // .operands[] is array of cs_ppc_op - for(int j=0; jop_count; ++j) { - MYLOG(" operand%d: ", j); - printOperandVerbose(res, &(ppc->operands[j])); - } -} - uint64_t sign_extend(size_t addressSize_local, uint64_t target, int signBit) { if ((target >> signBit) & 1) diff --git a/arch/powerpc/util.h b/arch/powerpc/util.h index 0eb146515..8fd9e851f 100644 --- a/arch/powerpc/util.h +++ b/arch/powerpc/util.h @@ -38,6 +38,4 @@ inline uint32_t bswap32(uint32_t x) ((x&0xFF000000)>>24); } -void printOperandVerbose(decomp_result *res, cs_ppc_op *opers); -void printInstructionVerbose(decomp_result *res); -uint64_t sign_extend(size_t addressSize_local, uint64_t target, int signBit); \ No newline at end of file +uint64_t sign_extend(size_t addressSize_local, uint64_t target, int signBit); From cf9d7ec5430cc217d2adac9e393897a526695c98 Mon Sep 17 00:00:00 2001 From: noone Date: Wed, 25 Dec 2024 14:46:48 -0800 Subject: [PATCH 07/19] Add SPE instruction support Note that this hasn't been tested against capstone 5.0.3 yet: I said "ooh it looks like binaryninja supports SPE now", added it, then when I went to test it, it looks like capstone 5.0.3 doesn't support it yet (`CS_MODE_SPE` isn't yet in the allowed bitmask for powerpc in the `arch_configs` table in `cs.c`). There's enough work that I'm leaving it in here for now. --- arch/powerpc/decode/decode.c | 1616 +++++++++++++++++++++++++++++++++- arch/powerpc/decode/decode.h | 256 ++++++ 2 files changed, 1869 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c index 86bd39761..0b304895c 100644 --- a/arch/powerpc/decode/decode.c +++ b/arch/powerpc/decode/decode.c @@ -1051,6 +1051,1031 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) } } +static InstructionId DecodeSpe0x04(uint32_t word32, uint32_t decodeFlags) +{ + uint32_t a = GetA(word32); + uint32_t b = GetB(word32); + uint32_t d = GetD(word32); + uint32_t subop = word32 & 0x7ff; + + switch (subop) + { + case 512: + return PPC_ID_SPE_EVADDW; + + case 514: + return PPC_ID_SPE_EVADDIW; + + case 516: + return PPC_ID_SPE_EVSUBFW; + + case 518: + return PPC_ID_SPE_EVSUBIFW; + + case 520: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVABS; + + case 521: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVNEG; + + case 522: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVEXTSB; + + case 523: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVEXTSH; + + case 524: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVRNDW; + + case 525: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVCNTLZW; + + case 526: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVCNTLSW; + + case 527: + return PPC_ID_SPE_BRINC; + + case 529: + return PPC_ID_SPE_EVAND; + + case 530: + return PPC_ID_SPE_EVANDC; + + case 534: + return PPC_ID_SPE_EVXOR; + + case 535: + if (a == b) + return PPC_ID_SPE_EVMR; + else + return PPC_ID_SPE_EVOR; + + case 536: + if (a == b) + return PPC_ID_SPE_EVNOT; + else + return PPC_ID_SPE_EVNOR; + + case 537: + return PPC_ID_SPE_EVEQV; + + case 539: + return PPC_ID_SPE_EVORC; + + case 542: + return PPC_ID_SPE_EVNAND; + + case 544: + return PPC_ID_SPE_EVSRWU; + + case 545: + return PPC_ID_SPE_EVSRWS; + + case 546: + return PPC_ID_SPE_EVSRWIU; + + case 547: + return PPC_ID_SPE_EVSRWIS; + + case 548: + return PPC_ID_SPE_EVSLW; + + case 550: + return PPC_ID_SPE_EVSLWI; + + case 552: + return PPC_ID_SPE_EVRLW; + + case 553: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVSPLATI; + + case 554: + return PPC_ID_SPE_EVRLWI; + + case 555: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVSPLATFI; + + case 556: + return PPC_ID_SPE_EVMERGEHI; + + case 557: + return PPC_ID_SPE_EVMERGELO; + + case 558: + return PPC_ID_SPE_EVMERGEHILO; + + case 559: + return PPC_ID_SPE_EVMERGELOHI; + + case 560: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVCMPGTU; + + case 561: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVCMPGTS; + + case 562: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVCMPLTU; + + case 563: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVCMPLTS; + + case 564: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVCMPEQ; + + case 632: + return PPC_ID_SPE_EVSEL; + + case 633: + return PPC_ID_SPE_EVSEL; + + case 634: + return PPC_ID_SPE_EVSEL; + + case 635: + return PPC_ID_SPE_EVSEL; + + case 636: + return PPC_ID_SPE_EVSEL; + + case 637: + return PPC_ID_SPE_EVSEL; + + case 638: + return PPC_ID_SPE_EVSEL; + + case 639: + return PPC_ID_SPE_EVSEL; + + case 640: + return PPC_ID_SPE_EVFSADD; + + case 641: + return PPC_ID_SPE_EVFSSUB; + + case 644: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSABS; + + case 645: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSNABS; + + case 646: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSNEG; + + case 648: + return PPC_ID_SPE_EVFSMUL; + + case 649: + return PPC_ID_SPE_EVFSDIV; + + case 652: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCMPGT; + + case 653: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCMPLT; + + case 654: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCMPEQ; + + case 656: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCFUI; + + case 657: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCFSI; + + case 658: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCFUF; + + case 659: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCFSF; + + case 660: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCTUI; + + case 661: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCTSI; + + case 662: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCTUF; + + case 663: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCTSF; + + case 664: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCTUIZ; + + case 666: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSCTSIZ; + + case 668: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSTSTGT; + + case 669: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSTSTLT; + + case 670: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVFSTSTEQ; + + case 704: + return PPC_ID_SPE_EFSADD; + + case 705: + return PPC_ID_SPE_EFSSUB; + + case 708: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSABS; + + case 709: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSNABS; + + case 710: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSNEG; + + case 712: + return PPC_ID_SPE_EFSMUL; + + case 713: + return PPC_ID_SPE_EFSDIV; + + case 716: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSCMPGT; + + case 717: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSCMPLT; + + case 718: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSCMPEQ; + + case 719: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSCFD; + + case 720: + return PPC_ID_SPE_EFSCFUI; + + case 721: + return PPC_ID_SPE_EFSCFSI; + + case 722: + return PPC_ID_SPE_EFSCFUF; + + case 723: + return PPC_ID_SPE_EFSCFSF; + + case 724: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSCTUI; + + case 725: + return PPC_ID_SPE_EFSCTSI; + + case 726: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSCTUF; + + case 727: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSCTSF; + + case 728: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSCTUIZ; + + case 730: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSCTSIZ; + + case 732: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSTSTGT; + + case 733: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSTSTLT; + + case 734: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFSTSTEQ; + + case 736: + return PPC_ID_SPE_EFDADD; + + case 737: + return PPC_ID_SPE_EFDSUB; + + case 738: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCFUID; + + case 739: + return PPC_ID_SPE_EFDCFSID; + + case 740: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDABS; + + case 741: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDNABS; + + case 742: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDNEG; + + case 744: + return PPC_ID_SPE_EFDMUL; + + case 745: + return PPC_ID_SPE_EFDDIV; + + case 746: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCTUIDZ; + + case 747: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCTSIDZ; + + case 748: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCMPGT; + + case 749: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCMPLT; + + case 750: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCMPEQ; + + case 751: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCFS; + + case 752: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCFUI; + + case 753: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCFSI; + + case 754: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCFUF; + + case 755: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCFSF; + + case 756: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCTUI; + + case 757: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCTSI; + + case 758: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCTUF; + + case 759: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCTSF; + + case 760: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCTUIZ; + + case 762: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDCTSIZ; + + case 764: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDTSTGT; + + case 765: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDTSTLT; + + case 766: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EFDTSTEQ; + + case 768: + return PPC_ID_SPE_EVLDDX; + + case 769: + return PPC_ID_SPE_EVLDD; + + case 770: + return PPC_ID_SPE_EVLDWX; + + case 771: + return PPC_ID_SPE_EVLDW; + + case 772: + return PPC_ID_SPE_EVLDHX; + + case 773: + return PPC_ID_SPE_EVLDH; + + case 776: + return PPC_ID_SPE_EVLHHESPLATX; + + case 777: + return PPC_ID_SPE_EVLHHESPLAT; + + case 780: + return PPC_ID_SPE_EVLHHOUSPLATX; + + case 781: + return PPC_ID_SPE_EVLHHOUSPLAT; + + case 782: + return PPC_ID_SPE_EVLHHOSSPLATX; + + case 783: + return PPC_ID_SPE_EVLHHOSSPLAT; + + case 784: + return PPC_ID_SPE_EVLWHEX; + + case 785: + return PPC_ID_SPE_EVLWHE; + + case 788: + return PPC_ID_SPE_EVLWHOUX; + + case 789: + return PPC_ID_SPE_EVLWHOU; + + case 790: + return PPC_ID_SPE_EVLWHOSX; + + case 791: + return PPC_ID_SPE_EVLWHOS; + + case 792: + return PPC_ID_SPE_EVLWWSPLATX; + + case 793: + return PPC_ID_SPE_EVLWWSPLAT; + + case 796: + return PPC_ID_SPE_EVLWHSPLATX; + + case 797: + return PPC_ID_SPE_EVLWHSPLAT; + + case 800: + return PPC_ID_SPE_EVSTDDX; + + case 801: + return PPC_ID_SPE_EVSTDD; + + case 802: + return PPC_ID_SPE_EVSTDWX; + + case 803: + return PPC_ID_SPE_EVSTDW; + + case 804: + return PPC_ID_SPE_EVSTDHX; + + case 805: + return PPC_ID_SPE_EVSTDH; + + case 816: + return PPC_ID_SPE_EVSTWHEX; + + case 817: + return PPC_ID_SPE_EVSTWHE; + + case 820: + return PPC_ID_SPE_EVSTWHOX; + + case 821: + return PPC_ID_SPE_EVSTWHO; + + case 824: + return PPC_ID_SPE_EVSTWWEX; + + case 825: + return PPC_ID_SPE_EVSTWWE; + + case 828: + return PPC_ID_SPE_EVSTWWOX; + + case 829: + return PPC_ID_SPE_EVSTWWO; + + case 1027: + return PPC_ID_SPE_EVMHESSF; + + case 1031: + return PPC_ID_SPE_EVMHOSSF; + + case 1032: + return PPC_ID_SPE_EVMHEUMI; + + case 1033: + return PPC_ID_SPE_EVMHESMI; + + case 1035: + return PPC_ID_SPE_EVMHESMF; + + case 1036: + return PPC_ID_SPE_EVMHOUMI; + + case 1037: + return PPC_ID_SPE_EVMHOSMI; + + case 1039: + return PPC_ID_SPE_EVMHOSMF; + + case 1059: + return PPC_ID_SPE_EVMHESSFA; + + case 1063: + return PPC_ID_SPE_EVMHOSSFA; + + case 1064: + return PPC_ID_SPE_EVMHEUMIA; + + case 1065: + return PPC_ID_SPE_EVMHESMIA; + + case 1067: + return PPC_ID_SPE_EVMHESMFA; + + case 1068: + return PPC_ID_SPE_EVMHOUMIA; + + case 1069: + return PPC_ID_SPE_EVMHOSMIA; + + case 1071: + return PPC_ID_SPE_EVMHOSMFA; + + case 1095: + return PPC_ID_SPE_EVMWHSSF; + + case 1096: + return PPC_ID_SPE_EVMWLUMI; + + case 1100: + return PPC_ID_SPE_EVMWHUMI; + + case 1101: + return PPC_ID_SPE_EVMWHSMI; + + case 1103: + return PPC_ID_SPE_EVMWHSMF; + + case 1107: + return PPC_ID_SPE_EVMWSSF; + + case 1112: + return PPC_ID_SPE_EVMWUMI; + + case 1113: + return PPC_ID_SPE_EVMWSMI; + + case 1115: + return PPC_ID_SPE_EVMWSMF; + + case 1127: + return PPC_ID_SPE_EVMWHSSFA; + + case 1128: + return PPC_ID_SPE_EVMWLUMIA; + + case 1132: + return PPC_ID_SPE_EVMWHUMIA; + + case 1133: + return PPC_ID_SPE_EVMWHSMIA; + + case 1135: + return PPC_ID_SPE_EVMWHSMFA; + + case 1139: + return PPC_ID_SPE_EVMWSSFA; + + case 1144: + return PPC_ID_SPE_EVMWUMIA; + + case 1145: + return PPC_ID_SPE_EVMWSMIA; + + case 1147: + return PPC_ID_SPE_EVMWSMFA; + + case 1216: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVADDUSIAAW; + + case 1217: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVADDSSIAAW; + + case 1218: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVSUBFUSIAAW; + + case 1219: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVSUBFSSIAAW; + + case 1220: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVMRA; + + case 1222: + return PPC_ID_SPE_EVDIVWS; + + case 1223: + return PPC_ID_SPE_EVDIVWU; + + case 1224: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVADDUMIAAW; + + case 1225: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVADDSMIAAW; + + case 1226: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVSUBFUMIAAW; + + case 1227: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_SPE_EVSUBFSMIAAW; + + case 1280: + return PPC_ID_SPE_EVMHEUSIAAW; + + case 1281: + return PPC_ID_SPE_EVMHESSIAAW; + + case 1283: + return PPC_ID_SPE_EVMHESSFAAW; + + case 1284: + return PPC_ID_SPE_EVMHOUSIAAW; + + case 1285: + return PPC_ID_SPE_EVMHOSSIAAW; + + case 1287: + return PPC_ID_SPE_EVMHOSSFAAW; + + case 1288: + return PPC_ID_SPE_EVMHEUMIAAW; + + case 1289: + return PPC_ID_SPE_EVMHESMIAAW; + + case 1291: + return PPC_ID_SPE_EVMHESMFAAW; + + case 1292: + return PPC_ID_SPE_EVMHOUMIAAW; + + case 1293: + return PPC_ID_SPE_EVMHOSMIAAW; + + case 1295: + return PPC_ID_SPE_EVMHOSMFAAW; + + case 1320: + return PPC_ID_SPE_EVMHEGUMIAA; + + case 1321: + return PPC_ID_SPE_EVMHEGSMIAA; + + case 1323: + return PPC_ID_SPE_EVMHEGSMFAA; + + case 1324: + return PPC_ID_SPE_EVMHOGUMIAA; + + case 1325: + return PPC_ID_SPE_EVMHOGSMIAA; + + case 1327: + return PPC_ID_SPE_EVMHOGSMFAA; + + case 1344: + return PPC_ID_SPE_EVMWLUSIAAW; + + case 1345: + return PPC_ID_SPE_EVMWLSSIAAW; + + case 1352: + return PPC_ID_SPE_EVMWLUMIAAW; + + case 1353: + return PPC_ID_SPE_EVMWLSMIAAW; + + case 1363: + return PPC_ID_SPE_EVMWSSFAA; + + case 1368: + return PPC_ID_SPE_EVMWUMIAA; + + case 1369: + return PPC_ID_SPE_EVMWSMIAA; + + case 1371: + return PPC_ID_SPE_EVMWSMFAA; + + case 1408: + return PPC_ID_SPE_EVMHEUSIANW; + + case 1409: + return PPC_ID_SPE_EVMHESSIANW; + + case 1411: + return PPC_ID_SPE_EVMHESSFANW; + + case 1412: + return PPC_ID_SPE_EVMHOUSIANW; + + case 1413: + return PPC_ID_SPE_EVMHOSSIANW; + + case 1415: + return PPC_ID_SPE_EVMHOSSFANW; + + case 1416: + return PPC_ID_SPE_EVMHEUMIANW; + + case 1417: + return PPC_ID_SPE_EVMHESMIANW; + + case 1419: + return PPC_ID_SPE_EVMHESMFANW; + + case 1420: + return PPC_ID_SPE_EVMHOUMIANW; + + case 1421: + return PPC_ID_SPE_EVMHOSMIANW; + + case 1423: + return PPC_ID_SPE_EVMHOSMFANW; + + case 1448: + return PPC_ID_SPE_EVMHEGUMIAN; + + case 1449: + return PPC_ID_SPE_EVMHEGSMIAN; + + case 1451: + return PPC_ID_SPE_EVMHEGSMFAN; + + case 1452: + return PPC_ID_SPE_EVMHOGUMIAN; + + case 1453: + return PPC_ID_SPE_EVMHOGSMIAN; + + case 1455: + return PPC_ID_SPE_EVMHOGSMFAN; + + case 1472: + return PPC_ID_SPE_EVMWLUSIANW; + + case 1473: + return PPC_ID_SPE_EVMWLSSIANW; + + case 1480: + return PPC_ID_SPE_EVMWLUMIANW; + + case 1481: + return PPC_ID_SPE_EVMWLSMIANW; + + case 1491: + return PPC_ID_SPE_EVMWSSFAN; + + case 1496: + return PPC_ID_SPE_EVMWUMIAN; + + case 1497: + return PPC_ID_SPE_EVMWSMIAN; + + case 1499: + return PPC_ID_SPE_EVMWSMFAN; + + default: + return PPC_ID_INVALID; + } +} + static InstructionId Decode0x13(uint32_t word32, uint32_t decodeFlags) { uint32_t a = GetA(word32); @@ -3429,10 +4454,12 @@ static InstructionId Decode(uint32_t word32, uint32_t decodeFlags) case 0x04: { - if ((decodeFlags & DECODE_FLAGS_ALTIVEC) == 0) + if ((decodeFlags & DECODE_FLAGS_ALTIVEC)) + return DecodeAltivec0x04(word32, decodeFlags); + else if ((decodeFlags & DECODE_FLAGS_SPE)) + return DecodeSpe0x04(word32, decodeFlags); + else return PPC_ID_INVALID; - - return DecodeAltivec0x04(word32, decodeFlags); } case 0x07: @@ -5270,6 +6297,335 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushVsxC(instruction, word32, VSX_WIDTH_FULL); break; + // SPE INSTRUCTIONS + + // SPE rD, rA, rB + case PPC_ID_SPE_BRINC: + case PPC_ID_SPE_EFDADD: + case PPC_ID_SPE_EFDDIV: + case PPC_ID_SPE_EFDMUL: + case PPC_ID_SPE_EFDSUB: + case PPC_ID_SPE_EFSADD: + case PPC_ID_SPE_EFSDIV: + case PPC_ID_SPE_EFSMUL: + case PPC_ID_SPE_EFSSUB: + case PPC_ID_SPE_EVADDW: + case PPC_ID_SPE_EVAND: + case PPC_ID_SPE_EVANDC: + case PPC_ID_SPE_EVDIVWS: + case PPC_ID_SPE_EVDIVWU: + case PPC_ID_SPE_EVEQV: + case PPC_ID_SPE_EVFSADD: + case PPC_ID_SPE_EVFSDIV: + case PPC_ID_SPE_EVFSMUL: + case PPC_ID_SPE_EVFSSUB: + case PPC_ID_SPE_EVLDDX: + case PPC_ID_SPE_EVLDHX: + case PPC_ID_SPE_EVLDWX: + case PPC_ID_SPE_EVLHHESPLATX: + case PPC_ID_SPE_EVLHHOSSPLATX: + case PPC_ID_SPE_EVLHHOUSPLATX: + case PPC_ID_SPE_EVLWHEX: + case PPC_ID_SPE_EVLWHOSX: + case PPC_ID_SPE_EVLWHOUX: + case PPC_ID_SPE_EVLWHSPLATX: + case PPC_ID_SPE_EVLWWSPLATX: + case PPC_ID_SPE_EVMERGEHI: + case PPC_ID_SPE_EVMERGEHILO: + case PPC_ID_SPE_EVMERGELO: + case PPC_ID_SPE_EVMERGELOHI: + case PPC_ID_SPE_EVMHEGSMFAA: + case PPC_ID_SPE_EVMHEGSMFAN: + case PPC_ID_SPE_EVMHEGSMIAA: + case PPC_ID_SPE_EVMHEGSMIAN: + case PPC_ID_SPE_EVMHEGUMIAA: + case PPC_ID_SPE_EVMHEGUMIAN: + case PPC_ID_SPE_EVMHESMF: + case PPC_ID_SPE_EVMHESMFA: + case PPC_ID_SPE_EVMHESMFAAW: + case PPC_ID_SPE_EVMHESMFANW: + case PPC_ID_SPE_EVMHESMI: + case PPC_ID_SPE_EVMHESMIA: + case PPC_ID_SPE_EVMHESMIAAW: + case PPC_ID_SPE_EVMHESMIANW: + case PPC_ID_SPE_EVMHESSF: + case PPC_ID_SPE_EVMHESSFA: + case PPC_ID_SPE_EVMHESSFAAW: + case PPC_ID_SPE_EVMHESSFANW: + case PPC_ID_SPE_EVMHESSIAAW: + case PPC_ID_SPE_EVMHESSIANW: + case PPC_ID_SPE_EVMHEUMI: + case PPC_ID_SPE_EVMHEUMIA: + case PPC_ID_SPE_EVMHEUMIAAW: + case PPC_ID_SPE_EVMHEUMIANW: + case PPC_ID_SPE_EVMHEUSIAAW: + case PPC_ID_SPE_EVMHEUSIANW: + case PPC_ID_SPE_EVMHOGSMFAA: + case PPC_ID_SPE_EVMHOGSMFAN: + case PPC_ID_SPE_EVMHOGSMIAA: + case PPC_ID_SPE_EVMHOGSMIAN: + case PPC_ID_SPE_EVMHOGUMIAA: + case PPC_ID_SPE_EVMHOGUMIAN: + case PPC_ID_SPE_EVMHOSMF: + case PPC_ID_SPE_EVMHOSMFA: + case PPC_ID_SPE_EVMHOSMFAAW: + case PPC_ID_SPE_EVMHOSMFANW: + case PPC_ID_SPE_EVMHOSMI: + case PPC_ID_SPE_EVMHOSMIA: + case PPC_ID_SPE_EVMHOSMIAAW: + case PPC_ID_SPE_EVMHOSMIANW: + case PPC_ID_SPE_EVMHOSSF: + case PPC_ID_SPE_EVMHOSSFA: + case PPC_ID_SPE_EVMHOSSFAAW: + case PPC_ID_SPE_EVMHOSSFANW: + case PPC_ID_SPE_EVMHOSSIAAW: + case PPC_ID_SPE_EVMHOSSIANW: + case PPC_ID_SPE_EVMHOUMI: + case PPC_ID_SPE_EVMHOUMIA: + case PPC_ID_SPE_EVMHOUMIAAW: + case PPC_ID_SPE_EVMHOUMIANW: + case PPC_ID_SPE_EVMHOUSIAAW: + case PPC_ID_SPE_EVMHOUSIANW: + case PPC_ID_SPE_EVMWHSMF: + case PPC_ID_SPE_EVMWHSMFA: + case PPC_ID_SPE_EVMWHSMI: + case PPC_ID_SPE_EVMWHSMIA: + case PPC_ID_SPE_EVMWHSSF: + case PPC_ID_SPE_EVMWHSSFA: + case PPC_ID_SPE_EVMWLSMIAAW: + case PPC_ID_SPE_EVMWLSMIANW: + case PPC_ID_SPE_EVMWLSSIAAW: + case PPC_ID_SPE_EVMWLSSIANW: + case PPC_ID_SPE_EVMWHUMI: + case PPC_ID_SPE_EVMWHUMIA: + case PPC_ID_SPE_EVMWHUSIAAW: + case PPC_ID_SPE_EVMWHUSIANW: + case PPC_ID_SPE_EVMWLUMI: + case PPC_ID_SPE_EVMWLUMIA: + case PPC_ID_SPE_EVMWLUMIAAW: + case PPC_ID_SPE_EVMWLUMIANW: + case PPC_ID_SPE_EVMWLUSIAAW: + case PPC_ID_SPE_EVMWLUSIANW: + case PPC_ID_SPE_EVMWSMF: + case PPC_ID_SPE_EVMWSMFA: + case PPC_ID_SPE_EVMWSMFAA: + case PPC_ID_SPE_EVMWSMFAN: + case PPC_ID_SPE_EVMWSMI: + case PPC_ID_SPE_EVMWSMIA: + case PPC_ID_SPE_EVMWSMIAA: + case PPC_ID_SPE_EVMWSMIAN: + case PPC_ID_SPE_EVMWSSF: + case PPC_ID_SPE_EVMWSSFA: + case PPC_ID_SPE_EVMWSSFAA: + case PPC_ID_SPE_EVMWSSFAN: + case PPC_ID_SPE_EVMWUMI: + case PPC_ID_SPE_EVMWUMIA: + case PPC_ID_SPE_EVMWUMIAA: + case PPC_ID_SPE_EVMWUMIAN: + case PPC_ID_SPE_EVNAND: + case PPC_ID_SPE_EVNOR: + case PPC_ID_SPE_EVOR: + case PPC_ID_SPE_EVORC: + case PPC_ID_SPE_EVRLW: + case PPC_ID_SPE_EVSLW: + case PPC_ID_SPE_EVSRWS: + case PPC_ID_SPE_EVSRWU: + case PPC_ID_SPE_EVSUBFW: + case PPC_ID_SPE_EVXOR: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // rD, rA, /// + case PPC_ID_SPE_EFDABS: + case PPC_ID_SPE_EFDNABS: + case PPC_ID_SPE_EFDNEG: + case PPC_ID_SPE_EFSABS: + case PPC_ID_SPE_EFSNABS: + case PPC_ID_SPE_EFSNEG: + case PPC_ID_SPE_EVABS: + case PPC_ID_SPE_EVADDSMIAAW: + case PPC_ID_SPE_EVADDSSIAAW: + case PPC_ID_SPE_EVADDUMIAAW: + case PPC_ID_SPE_EVADDUSIAAW: + case PPC_ID_SPE_EVCNTLSW: + case PPC_ID_SPE_EVCNTLZW: + case PPC_ID_SPE_EVEXTSB: + case PPC_ID_SPE_EVEXTSH: + case PPC_ID_SPE_EVFSABS: + case PPC_ID_SPE_EVFSNABS: + case PPC_ID_SPE_EVFSNEG: + case PPC_ID_SPE_EVMRA: + case PPC_ID_SPE_EVNEG: + case PPC_ID_SPE_EVSUBFSMIAAW: + case PPC_ID_SPE_EVSUBFSSIAAW: + case PPC_ID_SPE_EVSUBFUMIAAW: + case PPC_ID_SPE_EVSUBFUSIAAW: + PushRD(instruction, word32); + PushRA(instruction, word32); + break; + + // rD, ///, rB + case PPC_ID_SPE_EFDCFS: + case PPC_ID_SPE_EFDCFSF: + case PPC_ID_SPE_EFDCFSI: + case PPC_ID_SPE_EFDCFSID: + case PPC_ID_SPE_EFDCFUF: + case PPC_ID_SPE_EFDCFUI: + case PPC_ID_SPE_EFDCFUID: + case PPC_ID_SPE_EFDCTSF: + case PPC_ID_SPE_EFDCTSI: + case PPC_ID_SPE_EFDCTSIDZ: + case PPC_ID_SPE_EFDCTSIZ: + case PPC_ID_SPE_EFDCTUF: + case PPC_ID_SPE_EFDCTUI: + case PPC_ID_SPE_EFDCTUIDZ: + case PPC_ID_SPE_EFDCTUIZ: + case PPC_ID_SPE_EFSCFD: + case PPC_ID_SPE_EFSCFSF: + case PPC_ID_SPE_EFSCFSI: + case PPC_ID_SPE_EFSCFUF: + case PPC_ID_SPE_EFSCFUI: + case PPC_ID_SPE_EFSCTSF: + case PPC_ID_SPE_EFSCTSI: + case PPC_ID_SPE_EFSCTSIZ: + case PPC_ID_SPE_EFSCTUF: + case PPC_ID_SPE_EFSCTUI: + case PPC_ID_SPE_EFSCTUIZ: + case PPC_ID_SPE_EVFSCFSF: + case PPC_ID_SPE_EVFSCFSI: + case PPC_ID_SPE_EVFSCFUF: + case PPC_ID_SPE_EVFSCFUI: + case PPC_ID_SPE_EVFSCTSF: + case PPC_ID_SPE_EVFSCTSI: + case PPC_ID_SPE_EVFSCTSIZ: + case PPC_ID_SPE_EVFSCTUF: + case PPC_ID_SPE_EVFSCTUI: + case PPC_ID_SPE_EVFSCTUIZ: + PushRD(instruction, word32); + PushRA(instruction, word32); + break; + + // crfD//, rA, rB + case PPC_ID_SPE_EFDCMPEQ: + case PPC_ID_SPE_EFDCMPGT: + case PPC_ID_SPE_EFDCMPLT: + case PPC_ID_SPE_EFDTSTEQ: + case PPC_ID_SPE_EFDTSTGT: + case PPC_ID_SPE_EFDTSTLT: + case PPC_ID_SPE_EFSCMPEQ: + case PPC_ID_SPE_EFSCMPGT: + case PPC_ID_SPE_EFSCMPLT: + case PPC_ID_SPE_EFSTSTEQ: + case PPC_ID_SPE_EFSTSTGT: + case PPC_ID_SPE_EFSTSTLT: + case PPC_ID_SPE_EVCMPEQ: + case PPC_ID_SPE_EVCMPGTS: + case PPC_ID_SPE_EVCMPGTU: + case PPC_ID_SPE_EVCMPLTS: + case PPC_ID_SPE_EVCMPLTU: + case PPC_ID_SPE_EVFSCMPEQ: + case PPC_ID_SPE_EVFSCMPGT: + case PPC_ID_SPE_EVFSCMPLT: + case PPC_ID_SPE_EVFSTSTEQ: + case PPC_ID_SPE_EVFSTSTGT: + case PPC_ID_SPE_EVFSTSTLT: + PushCRFDImplyCR0(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // rD, UIMM, rB + case PPC_ID_SPE_EVADDIW: + case PPC_ID_SPE_EVSUBIFW: + PushRD(instruction, word32); + PushUIMMValue(instruction, (word32 >> 16) & 0x1f); + PushRB(instruction, word32); + break; + + // rD, SIMM, /// + case PPC_ID_SPE_EVSPLATFI: + case PPC_ID_SPE_EVSPLATI: + { + int32_t simm = sign_extend((word32 >> 16) & 0x1f, 5); + PushRD(instruction, word32); + PushSIMMValue(instruction, simm); + break; + } + + // rD, rA, UIMM (SPE) + case PPC_ID_SPE_EVRLWI: + case PPC_ID_SPE_EVSLWI: + case PPC_ID_SPE_EVSRWIS: + case PPC_ID_SPE_EVSRWIU: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, (word32 >> 11) & 0x1f); + break; + + // rD, rA, UIMM (SPE loads) + case PPC_ID_SPE_EVLDD: + case PPC_ID_SPE_EVLDH: + case PPC_ID_SPE_EVLDW: + case PPC_ID_SPE_EVLHHESPLAT: + case PPC_ID_SPE_EVLHHOSSPLAT: + case PPC_ID_SPE_EVLHHOUSPLAT: + case PPC_ID_SPE_EVLWHE: + case PPC_ID_SPE_EVLWHOS: + case PPC_ID_SPE_EVLWHOU: + case PPC_ID_SPE_EVLWHSPLAT: + case PPC_ID_SPE_EVLWWSPLAT: + PushRD(instruction, word32); + PushRAor0(instruction, word32); + PushUIMMValue(instruction, (word32 >> 11) & 0x1f); + break; + + // rS, rA, UIMM (SPE) + case PPC_ID_SPE_EVSTDD: + case PPC_ID_SPE_EVSTDH: + case PPC_ID_SPE_EVSTDW: + case PPC_ID_SPE_EVSTWHE: + case PPC_ID_SPE_EVSTWHO: + case PPC_ID_SPE_EVSTWWE: + case PPC_ID_SPE_EVSTWWO: + PushRS(instruction, word32); + PushRAor0(instruction, word32); + PushUIMMValue(instruction, (word32 >> 11) & 0x1f); + break; + + // rS, rA, rB (SPE store-indexed) + case PPC_ID_SPE_EVSTDDX: + case PPC_ID_SPE_EVSTDHX: + case PPC_ID_SPE_EVSTDWX: + case PPC_ID_SPE_EVSTWHEX: + case PPC_ID_SPE_EVSTWHOX: + case PPC_ID_SPE_EVSTWWEX: + case PPC_ID_SPE_EVSTWWOX: + PushRS(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, (word32 >> 11) & 0x1f); + break; + + // rD, rA + case PPC_ID_SPE_EVMR: + case PPC_ID_SPE_EVNOT: + case PPC_ID_SPE_EVRNDW: + PushRD(instruction, word32); + PushRA(instruction, word32); + break; + + // rD, rA, rB, crfS + case PPC_ID_SPE_EVSEL: + { + PushRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + uint32_t crfs = word32 & 0x7; + PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crfs)); + break; + } + default: break; } @@ -6701,6 +8057,260 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_PSQ_STUX: return "psq_stux"; case PPC_ID_PSQ_STX: return "psq_stx"; + case PPC_ID_SPE_BRINC: return "brinc"; + case PPC_ID_SPE_EFDABS: return "efdabs"; + case PPC_ID_SPE_EFDADD: return "efdadd"; + case PPC_ID_SPE_EFDCFS: return "efdcfs"; + case PPC_ID_SPE_EFDCFSF: return "efdcfsf"; + case PPC_ID_SPE_EFDCFSI: return "efdcfsi"; + case PPC_ID_SPE_EFDCFSID: return "efdcfsid"; + case PPC_ID_SPE_EFDCFUF: return "efdcfuf"; + case PPC_ID_SPE_EFDCFUI: return "efdcfui"; + case PPC_ID_SPE_EFDCFUID: return "efdcfuid"; + case PPC_ID_SPE_EFDCMPEQ: return "efdcmpeq"; + case PPC_ID_SPE_EFDCMPGT: return "efdcmpgt"; + case PPC_ID_SPE_EFDCMPLT: return "efdcmplt"; + case PPC_ID_SPE_EFDCTSF: return "efdctsf"; + case PPC_ID_SPE_EFDCTSI: return "efdctsi"; + case PPC_ID_SPE_EFDCTSIDZ: return "efdctsidz"; + case PPC_ID_SPE_EFDCTSIZ: return "efdctsiz"; + case PPC_ID_SPE_EFDCTUF: return "efdctuf"; + case PPC_ID_SPE_EFDCTUI: return "efdctui"; + case PPC_ID_SPE_EFDCTUIDZ: return "efdctuidz"; + case PPC_ID_SPE_EFDCTUIZ: return "efdctuiz"; + case PPC_ID_SPE_EFDDIV: return "efddiv"; + case PPC_ID_SPE_EFDMUL: return "efdmul"; + case PPC_ID_SPE_EFDNABS: return "efdnabs"; + case PPC_ID_SPE_EFDNEG: return "efdneg"; + case PPC_ID_SPE_EFDSUB: return "efdsub"; + case PPC_ID_SPE_EFDTSTEQ: return "efdtsteq"; + case PPC_ID_SPE_EFDTSTGT: return "efdtstgt"; + case PPC_ID_SPE_EFDTSTLT: return "efdtstlt"; + case PPC_ID_SPE_EFSABS: return "efsabs"; + case PPC_ID_SPE_EFSADD: return "efsadd"; + case PPC_ID_SPE_EFSCFD: return "efscfd"; + case PPC_ID_SPE_EFSCFSF: return "efscfsf"; + case PPC_ID_SPE_EFSCFSI: return "efscfsi"; + case PPC_ID_SPE_EFSCFUF: return "efscfuf"; + case PPC_ID_SPE_EFSCFUI: return "efscfui"; + case PPC_ID_SPE_EFSCMPEQ: return "efscmpeq"; + case PPC_ID_SPE_EFSCMPGT: return "efscmpgt"; + case PPC_ID_SPE_EFSCMPLT: return "efscmplt"; + case PPC_ID_SPE_EFSCTSF: return "efsctsf"; + case PPC_ID_SPE_EFSCTSI: return "efsctsi"; + case PPC_ID_SPE_EFSCTSIZ: return "efsctsiz"; + case PPC_ID_SPE_EFSCTUF: return "efsctuf"; + case PPC_ID_SPE_EFSCTUI: return "efsctui"; + case PPC_ID_SPE_EFSCTUIZ: return "efsctuiz"; + case PPC_ID_SPE_EFSDIV: return "efsdiv"; + case PPC_ID_SPE_EFSMUL: return "efsmul"; + case PPC_ID_SPE_EFSNABS: return "efsnabs"; + case PPC_ID_SPE_EFSNEG: return "efsneg"; + case PPC_ID_SPE_EFSSUB: return "efssub"; + case PPC_ID_SPE_EFSTSTEQ: return "efststeq"; + case PPC_ID_SPE_EFSTSTGT: return "efststgt"; + case PPC_ID_SPE_EFSTSTLT: return "efststlt"; + case PPC_ID_SPE_EVABS: return "evabs"; + case PPC_ID_SPE_EVADDIW: return "evaddiw"; + case PPC_ID_SPE_EVADDSMIAAW: return "evaddsmiaaw"; + case PPC_ID_SPE_EVADDSSIAAW: return "evaddssiaaw"; + case PPC_ID_SPE_EVADDUMIAAW: return "evaddumiaaw"; + case PPC_ID_SPE_EVADDUSIAAW: return "evaddusiaaw"; + case PPC_ID_SPE_EVADDW: return "evaddw"; + case PPC_ID_SPE_EVAND: return "evand"; + case PPC_ID_SPE_EVANDC: return "evandc"; + case PPC_ID_SPE_EVCMPEQ: return "evcmpeq"; + case PPC_ID_SPE_EVCMPGTS: return "evcmpgts"; + case PPC_ID_SPE_EVCMPGTU: return "evcmpgtu"; + case PPC_ID_SPE_EVCMPLTS: return "evcmplts"; + case PPC_ID_SPE_EVCMPLTU: return "evcmpltu"; + case PPC_ID_SPE_EVCNTLSW: return "evcntlsw"; + case PPC_ID_SPE_EVCNTLZW: return "evcntlzw"; + case PPC_ID_SPE_EVDIVWS: return "evdivws"; + case PPC_ID_SPE_EVDIVWU: return "evdivwu"; + case PPC_ID_SPE_EVEQV: return "eveqv"; + case PPC_ID_SPE_EVEXTSB: return "evextsb"; + case PPC_ID_SPE_EVEXTSH: return "evextsh"; + case PPC_ID_SPE_EVFSABS: return "evfsabs"; + case PPC_ID_SPE_EVFSADD: return "evfsadd"; + case PPC_ID_SPE_EVFSCFSF: return "evfscfsf"; + case PPC_ID_SPE_EVFSCFSI: return "evfscfsi"; + case PPC_ID_SPE_EVFSCFUF: return "evfscfuf"; + case PPC_ID_SPE_EVFSCFUI: return "evfscfui"; + case PPC_ID_SPE_EVSCFUI: return "evscfui"; + case PPC_ID_SPE_EVFSCMPEQ: return "evfscmpeq"; + case PPC_ID_SPE_EVFSCMPGT: return "evfscmpgt"; + case PPC_ID_SPE_EVFSCMPLT: return "evfscmplt"; + case PPC_ID_SPE_EVFSCTSF: return "evfsctsf"; + case PPC_ID_SPE_EVFSCTSI: return "evfsctsi"; + case PPC_ID_SPE_EVFSCTSIZ: return "evfsctsiz"; + case PPC_ID_SPE_EVFSCTUF: return "evfsctuf"; + case PPC_ID_SPE_EVFSCTUI: return "evfsctui"; + case PPC_ID_SPE_EVFSCTUIZ: return "evfsctuiz"; + case PPC_ID_SPE_EVFSDIV: return "evfsdiv"; + case PPC_ID_SPE_EVFSMUL: return "evfsmul"; + case PPC_ID_SPE_EVFSNABS: return "evfsnabs"; + case PPC_ID_SPE_EVFSNEG: return "evfsneg"; + case PPC_ID_SPE_EVFSSUB: return "evfssub"; + case PPC_ID_SPE_EVFSTSTEQ: return "evfststeq"; + case PPC_ID_SPE_EVFSTSTGT: return "evfststgt"; + case PPC_ID_SPE_EVFSTSTLT: return "evfststlt"; + case PPC_ID_SPE_EVLDD: return "evldd"; + case PPC_ID_SPE_EVLDDX: return "evlddx"; + case PPC_ID_SPE_EVLDH: return "evldh"; + case PPC_ID_SPE_EVLDHX: return "evldhx"; + case PPC_ID_SPE_EVLDW: return "evldw"; + case PPC_ID_SPE_EVLDWX: return "evldwx"; + case PPC_ID_SPE_EVLHHESPLAT: return "evlhhesplat"; + case PPC_ID_SPE_EVLHHESPLATX: return "evlhhesplatx"; + case PPC_ID_SPE_EVLHHOSSPLAT: return "evlhhossplat"; + case PPC_ID_SPE_EVLHHOSSPLATX: return "evlhhossplatx"; + case PPC_ID_SPE_EVLHHOUSPLAT: return "evlhhousplat"; + case PPC_ID_SPE_EVLHHOUSPLATX: return "evlhhousplatx"; + case PPC_ID_SPE_EVLWHE: return "evlwhe"; + case PPC_ID_SPE_EVLWHEX: return "evlwhex"; + case PPC_ID_SPE_EVLWHOS: return "evlwhos"; + case PPC_ID_SPE_EVLWHOSX: return "evlwhosx"; + case PPC_ID_SPE_EVLWHOU: return "evlwhou"; + case PPC_ID_SPE_EVLWHOUX: return "evlwhoux"; + case PPC_ID_SPE_EVLWHSPLAT: return "evlwhsplat"; + case PPC_ID_SPE_EVLWHSPLATX: return "evlwhsplatx"; + case PPC_ID_SPE_EVLWWSPLAT: return "evlwwsplat"; + case PPC_ID_SPE_EVLWWSPLATX: return "evlwwsplatx"; + case PPC_ID_SPE_EVMERGEHI: return "evmergehi"; + case PPC_ID_SPE_EVMERGEHILO: return "evmergehilo"; + case PPC_ID_SPE_EVMERGELO: return "evmergelo"; + case PPC_ID_SPE_EVMERGELOHI: return "evmergelohi"; + case PPC_ID_SPE_EVMHEGSMFAA: return "evmhegsmfaa"; + case PPC_ID_SPE_EVMHEGSMFAN: return "evmhegsmfan"; + case PPC_ID_SPE_EVMHEGSMIAA: return "evmhegsmiaa"; + case PPC_ID_SPE_EVMHEGSMIAN: return "evmhegsmian"; + case PPC_ID_SPE_EVMHEGUMIAA: return "evmhegumiaa"; + case PPC_ID_SPE_EVMHEGUMIAN: return "evmhegumian"; + case PPC_ID_SPE_EVMHESMF: return "evmhesmf"; + case PPC_ID_SPE_EVMHESMFA: return "evmhesmfa"; + case PPC_ID_SPE_EVMHESMFAAW: return "evmhesmfaaw"; + case PPC_ID_SPE_EVMHESMFANW: return "evmhesmfanw"; + case PPC_ID_SPE_EVMHESMI: return "evmhesmi"; + case PPC_ID_SPE_EVMHESMIA: return "evmhesmia"; + case PPC_ID_SPE_EVMHESMIAAW: return "evmhesmiaaw"; + case PPC_ID_SPE_EVMHESMIANW: return "evmhesmianw"; + case PPC_ID_SPE_EVMHESSF: return "evmhessf"; + case PPC_ID_SPE_EVMHESSFA: return "evmhessfa"; + case PPC_ID_SPE_EVMHESSFAAW: return "evmhessfaaw"; + case PPC_ID_SPE_EVMHESSFANW: return "evmhessfanw"; + case PPC_ID_SPE_EVMHESSIAAW: return "evmhessiaaw"; + case PPC_ID_SPE_EVMHESSIANW: return "evmhessianw"; + case PPC_ID_SPE_EVMHEUMI: return "evmheumi"; + case PPC_ID_SPE_EVMHEUMIA: return "evmheumia"; + case PPC_ID_SPE_EVMHEUMIAAW: return "evmheumiaaw"; + case PPC_ID_SPE_EVMHEUMIANW: return "evmheumianw"; + case PPC_ID_SPE_EVMHEUSIAAW: return "evmheusiaaw"; + case PPC_ID_SPE_EVMHEUSIANW: return "evmheusianw"; + case PPC_ID_SPE_EVMHOGSMFAA: return "evmhogsmfaa"; + case PPC_ID_SPE_EVMHOGSMFAN: return "evmhogsmfan"; + case PPC_ID_SPE_EVMHOGSMIAA: return "evmhogsmiaa"; + case PPC_ID_SPE_EVMHOGSMIAN: return "evmhogsmian"; + case PPC_ID_SPE_EVMHOGUMIAA: return "evmhogumiaa"; + case PPC_ID_SPE_EVMHOGUMIAN: return "evmhogumian"; + case PPC_ID_SPE_EVMHOSMF: return "evmhosmf"; + case PPC_ID_SPE_EVMHOSMFA: return "evmhosmfa"; + case PPC_ID_SPE_EVMHOSMFAAW: return "evmhosmfaaw"; + case PPC_ID_SPE_EVMHOSMFANW: return "evmhosmfanw"; + case PPC_ID_SPE_EVMHOSMI: return "evmhosmi"; + case PPC_ID_SPE_EVMHOSMIA: return "evmhosmia"; + case PPC_ID_SPE_EVMHOSMIAAW: return "evmhosmiaaw"; + case PPC_ID_SPE_EVMHOSMIANW: return "evmhosmianw"; + case PPC_ID_SPE_EVMHOSSF: return "evmhossf"; + case PPC_ID_SPE_EVMHOSSFA: return "evmhossfa"; + case PPC_ID_SPE_EVMHOSSFAAW: return "evmhossfaaw"; + case PPC_ID_SPE_EVMHOSSFANW: return "evmhossfanw"; + case PPC_ID_SPE_EVMHOSSIAAW: return "evmhossiaaw"; + case PPC_ID_SPE_EVMHOSSIANW: return "evmhossianw"; + case PPC_ID_SPE_EVMHOUMI: return "evmhoumi"; + case PPC_ID_SPE_EVMHOUMIA: return "evmhoumia"; + case PPC_ID_SPE_EVMHOUMIAAW: return "evmhoumiaaw"; + case PPC_ID_SPE_EVMHOUMIANW: return "evmhoumianw"; + case PPC_ID_SPE_EVMHOUSIAAW: return "evmhousiaaw"; + case PPC_ID_SPE_EVMHOUSIANW: return "evmhousianw"; + case PPC_ID_SPE_EVMR: return "evmr"; + case PPC_ID_SPE_EVMRA: return "evmra"; + case PPC_ID_SPE_EVMWHSMF: return "evmwhsmf"; + case PPC_ID_SPE_EVMWHSMFA: return "evmwhsmfa"; + case PPC_ID_SPE_EVMWHSMI: return "evmwhsmi"; + case PPC_ID_SPE_EVMWHSMIA: return "evmwhsmia"; + case PPC_ID_SPE_EVMWHSSF: return "evmwhssf"; + case PPC_ID_SPE_EVMWHSSFA: return "evmwhssfa"; + case PPC_ID_SPE_EVMWHUMI: return "evmwhumi"; + case PPC_ID_SPE_EVMWHUMIA: return "evmwhumia"; + case PPC_ID_SPE_EVMWHUSIAAW: return "evmwhusiaaw"; + case PPC_ID_SPE_EVMWHUSIANW: return "evmwhusianw"; + case PPC_ID_SPE_EVMWLSMIAAW: return "evmwlsmiaaw"; + case PPC_ID_SPE_EVMWLSMIANW: return "evmwlsmianw"; + case PPC_ID_SPE_EVMWLSSIANW: return "evmwlssianw"; + case PPC_ID_SPE_EVMWLSSIAAW: return "evmwlssiaaw"; + case PPC_ID_SPE_EVMWLUMI: return "evmwlumi"; + case PPC_ID_SPE_EVMWLUMIA: return "evmwlumia"; + case PPC_ID_SPE_EVMWLUMIAAW: return "evmwlumiaaw"; + case PPC_ID_SPE_EVMWLUMIANW: return "evmwlumianw"; + case PPC_ID_SPE_EVMWLUSIAAW: return "evmwlusiaaw"; + case PPC_ID_SPE_EVMWLUSIANW: return "evmwlusianw"; + case PPC_ID_SPE_EVMWSMF: return "evmwsmf"; + case PPC_ID_SPE_EVMWSMFA: return "evmwsmfa"; + case PPC_ID_SPE_EVMWSMFAA: return "evmwsmfaa"; + case PPC_ID_SPE_EVMWSMFAN: return "evmwsmfan"; + case PPC_ID_SPE_EVMWSMI: return "evmwsmi"; + case PPC_ID_SPE_EVMWSMIA: return "evmwsmia"; + case PPC_ID_SPE_EVMWSMIAA: return "evmwsmiaa"; + case PPC_ID_SPE_EVMWSMIAN: return "evmwsmian"; + case PPC_ID_SPE_EVMWSSF: return "evmwssf"; + case PPC_ID_SPE_EVMWSSFA: return "evmwssfa"; + case PPC_ID_SPE_EVMWSSFAA: return "evmwssfaa"; + case PPC_ID_SPE_EVMWSSFAN: return "evmwssfan"; + case PPC_ID_SPE_EVMWUMI: return "evmwumi"; + case PPC_ID_SPE_EVMWUMIA: return "evmwumia"; + case PPC_ID_SPE_EVMWUMIAA: return "evmwumiaa"; + case PPC_ID_SPE_EVMWUMIAN: return "evmwumian"; + case PPC_ID_SPE_EVNAND: return "evnand"; + case PPC_ID_SPE_EVNEG: return "evneg"; + case PPC_ID_SPE_EVNOR: return "evnor"; + case PPC_ID_SPE_EVNOT: return "evnot"; + case PPC_ID_SPE_EVOR: return "evor"; + case PPC_ID_SPE_EVORC: return "evorc"; + case PPC_ID_SPE_EVRLW: return "evrlw"; + case PPC_ID_SPE_EVRLWI: return "evrlwi"; + case PPC_ID_SPE_EVRNDW: return "evrndw"; + case PPC_ID_SPE_EVSEL: return "evsel"; + case PPC_ID_SPE_EVSLW: return "evslw"; + case PPC_ID_SPE_EVSLWI: return "evslwi"; + case PPC_ID_SPE_EVSPLATFI: return "evsplatfi"; + case PPC_ID_SPE_EVSPLATI: return "evsplati"; + case PPC_ID_SPE_EVSRWIS: return "evsrwis"; + case PPC_ID_SPE_EVSRWIU: return "evsrwiu"; + case PPC_ID_SPE_EVSRWS: return "evsrws"; + case PPC_ID_SPE_EVSRWU: return "evsrwu"; + case PPC_ID_SPE_EVSTDD: return "evstdd"; + case PPC_ID_SPE_EVSTDDX: return "evstddx"; + case PPC_ID_SPE_EVSTDH: return "evstdh"; + case PPC_ID_SPE_EVSTDHX: return "evstdhx"; + case PPC_ID_SPE_EVSTDW: return "evstdw"; + case PPC_ID_SPE_EVSTDWX: return "evstdwx"; + case PPC_ID_SPE_EVSTWHE: return "evstwhe"; + case PPC_ID_SPE_EVSTWHEX: return "evstwhex"; + case PPC_ID_SPE_EVSTWHO: return "evstwho"; + case PPC_ID_SPE_EVSTWHOX: return "evstwhox"; + case PPC_ID_SPE_EVSTWWE: return "evstwwe"; + case PPC_ID_SPE_EVSTWWEX: return "evstwwex"; + case PPC_ID_SPE_EVSTWWO: return "evstwwo"; + case PPC_ID_SPE_EVSTWWOX: return "evstwwox"; + case PPC_ID_SPE_EVSUBFSMIAAW: return "evsubfsmiaaw"; + case PPC_ID_SPE_EVSUBFSSIAAW: return "evsubfssiaaw"; + case PPC_ID_SPE_EVSUBFUMIAAW: return "evsubfumiaaw"; + case PPC_ID_SPE_EVSUBFUSIAAW: return "evsubfusiaaw"; + case PPC_ID_SPE_EVSUBFW: return "evsubfw"; + case PPC_ID_SPE_EVSUBIFW: return "evsubifw"; + case PPC_ID_SPE_EVXOR: return "evxor"; + default: return NULL; } } diff --git a/arch/powerpc/decode/decode.h b/arch/powerpc/decode/decode.h index 92c6bbf2e..404f070cb 100644 --- a/arch/powerpc/decode/decode.h +++ b/arch/powerpc/decode/decode.h @@ -1065,6 +1065,7 @@ extern "C" { PPC_ID_VSX_XXSPLTW, PPC_ID_VSX_XXSWAPD, + // Pair-stored PPC_ID_PSQ_L, PPC_ID_PSQ_LU, PPC_ID_PSQ_LUX, @@ -1073,6 +1074,261 @@ extern "C" { PPC_ID_PSQ_STU, PPC_ID_PSQ_STUX, PPC_ID_PSQ_STX, + + // SPE (Signal Processing Engine) instructions + PPC_ID_SPE_BRINC, + PPC_ID_SPE_EFDABS, + PPC_ID_SPE_EFDADD, + PPC_ID_SPE_EFDCFS, + PPC_ID_SPE_EFDCFSF, + PPC_ID_SPE_EFDCFSI, + PPC_ID_SPE_EFDCFSID, + PPC_ID_SPE_EFDCFUF, + PPC_ID_SPE_EFDCFUI, + PPC_ID_SPE_EFDCFUID, + PPC_ID_SPE_EFDCMPEQ, + PPC_ID_SPE_EFDCMPGT, + PPC_ID_SPE_EFDCMPLT, + PPC_ID_SPE_EFDCTSF, + PPC_ID_SPE_EFDCTSI, + PPC_ID_SPE_EFDCTSIDZ, + PPC_ID_SPE_EFDCTSIZ, + PPC_ID_SPE_EFDCTUF, + PPC_ID_SPE_EFDCTUI, + PPC_ID_SPE_EFDCTUIDZ, + PPC_ID_SPE_EFDCTUIZ, + PPC_ID_SPE_EFDDIV, + PPC_ID_SPE_EFDMUL, + PPC_ID_SPE_EFDNABS, + PPC_ID_SPE_EFDNEG, + PPC_ID_SPE_EFDSUB, + PPC_ID_SPE_EFDTSTEQ, + PPC_ID_SPE_EFDTSTGT, + PPC_ID_SPE_EFDTSTLT, + PPC_ID_SPE_EFSABS, + PPC_ID_SPE_EFSADD, + PPC_ID_SPE_EFSCFD, + PPC_ID_SPE_EFSCFSF, + PPC_ID_SPE_EFSCFSI, + PPC_ID_SPE_EFSCFUF, + PPC_ID_SPE_EFSCFUI, + PPC_ID_SPE_EFSCMPEQ, + PPC_ID_SPE_EFSCMPGT, + PPC_ID_SPE_EFSCMPLT, + PPC_ID_SPE_EFSCTSF, + PPC_ID_SPE_EFSCTSI, + PPC_ID_SPE_EFSCTSIZ, + PPC_ID_SPE_EFSCTUF, + PPC_ID_SPE_EFSCTUI, + PPC_ID_SPE_EFSCTUIZ, + PPC_ID_SPE_EFSDIV, + PPC_ID_SPE_EFSMUL, + PPC_ID_SPE_EFSNABS, + PPC_ID_SPE_EFSNEG, + PPC_ID_SPE_EFSSUB, + PPC_ID_SPE_EFSTSTEQ, + PPC_ID_SPE_EFSTSTGT, + PPC_ID_SPE_EFSTSTLT, + PPC_ID_SPE_EVABS, + PPC_ID_SPE_EVADDIW, + PPC_ID_SPE_EVADDSMIAAW, + PPC_ID_SPE_EVADDSSIAAW, + PPC_ID_SPE_EVADDUMIAAW, + PPC_ID_SPE_EVADDUSIAAW, + PPC_ID_SPE_EVADDW, + PPC_ID_SPE_EVAND, + PPC_ID_SPE_EVANDC, + PPC_ID_SPE_EVCMPEQ, + PPC_ID_SPE_EVCMPGTS, + PPC_ID_SPE_EVCMPGTU, + PPC_ID_SPE_EVCMPLTS, + PPC_ID_SPE_EVCMPLTU, + PPC_ID_SPE_EVCNTLSW, + PPC_ID_SPE_EVCNTLZW, + PPC_ID_SPE_EVDIVWS, + PPC_ID_SPE_EVDIVWU, + PPC_ID_SPE_EVEQV, + PPC_ID_SPE_EVEXTSB, + PPC_ID_SPE_EVEXTSH, + PPC_ID_SPE_EVFSABS, + PPC_ID_SPE_EVFSADD, + PPC_ID_SPE_EVFSCFSF, + PPC_ID_SPE_EVFSCFSI, + PPC_ID_SPE_EVFSCFUF, + PPC_ID_SPE_EVFSCFUI, + PPC_ID_SPE_EVSCFUI, + PPC_ID_SPE_EVFSCMPEQ, + PPC_ID_SPE_EVFSCMPGT, + PPC_ID_SPE_EVFSCMPLT, + PPC_ID_SPE_EVFSCTSF, + PPC_ID_SPE_EVFSCTSI, + PPC_ID_SPE_EVFSCTSIZ, + PPC_ID_SPE_EVFSCTUF, + PPC_ID_SPE_EVFSCTUI, + PPC_ID_SPE_EVFSCTUIZ, + PPC_ID_SPE_EVFSDIV, + PPC_ID_SPE_EVFSMUL, + PPC_ID_SPE_EVFSNABS, + PPC_ID_SPE_EVFSNEG, + PPC_ID_SPE_EVFSSUB, + PPC_ID_SPE_EVFSTSTEQ, + PPC_ID_SPE_EVFSTSTGT, + PPC_ID_SPE_EVFSTSTLT, + PPC_ID_SPE_EVLDD, + PPC_ID_SPE_EVLDDX, + PPC_ID_SPE_EVLDH, + PPC_ID_SPE_EVLDHX, + PPC_ID_SPE_EVLDW, + PPC_ID_SPE_EVLDWX, + PPC_ID_SPE_EVLHHESPLAT, + PPC_ID_SPE_EVLHHESPLATX, + PPC_ID_SPE_EVLHHOSSPLAT, + PPC_ID_SPE_EVLHHOSSPLATX, + PPC_ID_SPE_EVLHHOUSPLAT, + PPC_ID_SPE_EVLHHOUSPLATX, + PPC_ID_SPE_EVLWHE, + PPC_ID_SPE_EVLWHEX, + PPC_ID_SPE_EVLWHOS, + PPC_ID_SPE_EVLWHOSX, + PPC_ID_SPE_EVLWHOU, + PPC_ID_SPE_EVLWHOUX, + PPC_ID_SPE_EVLWHSPLAT, + PPC_ID_SPE_EVLWHSPLATX, + PPC_ID_SPE_EVLWWSPLAT, + PPC_ID_SPE_EVLWWSPLATX, + PPC_ID_SPE_EVMERGEHI, + PPC_ID_SPE_EVMERGEHILO, + PPC_ID_SPE_EVMERGELO, + PPC_ID_SPE_EVMERGELOHI, + PPC_ID_SPE_EVMHEGSMFAA, + PPC_ID_SPE_EVMHEGSMFAN, + PPC_ID_SPE_EVMHEGSMIAA, + PPC_ID_SPE_EVMHEGSMIAN, + PPC_ID_SPE_EVMHEGUMIAA, + PPC_ID_SPE_EVMHEGUMIAN, + PPC_ID_SPE_EVMHESMF, + PPC_ID_SPE_EVMHESMFA, + PPC_ID_SPE_EVMHESMFAAW, + PPC_ID_SPE_EVMHESMFANW, + PPC_ID_SPE_EVMHESMI, + PPC_ID_SPE_EVMHESMIA, + PPC_ID_SPE_EVMHESMIAAW, + PPC_ID_SPE_EVMHESMIANW, + PPC_ID_SPE_EVMHESSF, + PPC_ID_SPE_EVMHESSFA, + PPC_ID_SPE_EVMHESSFAAW, + PPC_ID_SPE_EVMHESSFANW, + PPC_ID_SPE_EVMHESSIAAW, + PPC_ID_SPE_EVMHESSIANW, + PPC_ID_SPE_EVMHEUMI, + PPC_ID_SPE_EVMHEUMIA, + PPC_ID_SPE_EVMHEUMIAAW, + PPC_ID_SPE_EVMHEUMIANW, + PPC_ID_SPE_EVMHEUSIAAW, + PPC_ID_SPE_EVMHEUSIANW, + PPC_ID_SPE_EVMHOGSMFAA, + PPC_ID_SPE_EVMHOGSMFAN, + PPC_ID_SPE_EVMHOGSMIAA, + PPC_ID_SPE_EVMHOGSMIAN, + PPC_ID_SPE_EVMHOGUMIAA, + PPC_ID_SPE_EVMHOGUMIAN, + PPC_ID_SPE_EVMHOSMF, + PPC_ID_SPE_EVMHOSMFA, + PPC_ID_SPE_EVMHOSMFAAW, + PPC_ID_SPE_EVMHOSMFANW, + PPC_ID_SPE_EVMHOSMI, + PPC_ID_SPE_EVMHOSMIA, + PPC_ID_SPE_EVMHOSMIAAW, + PPC_ID_SPE_EVMHOSMIANW, + PPC_ID_SPE_EVMHOSSF, + PPC_ID_SPE_EVMHOSSFA, + PPC_ID_SPE_EVMHOSSFAAW, + PPC_ID_SPE_EVMHOSSFANW, + PPC_ID_SPE_EVMHOSSIAAW, + PPC_ID_SPE_EVMHOSSIANW, + PPC_ID_SPE_EVMHOUMI, + PPC_ID_SPE_EVMHOUMIA, + PPC_ID_SPE_EVMHOUMIAAW, + PPC_ID_SPE_EVMHOUMIANW, + PPC_ID_SPE_EVMHOUSIAAW, + PPC_ID_SPE_EVMHOUSIANW, + PPC_ID_SPE_EVMR, + PPC_ID_SPE_EVMRA, + PPC_ID_SPE_EVMWHSMF, + PPC_ID_SPE_EVMWHSMFA, + PPC_ID_SPE_EVMWHSMI, + PPC_ID_SPE_EVMWHSMIA, + PPC_ID_SPE_EVMWHSSF, + PPC_ID_SPE_EVMWHSSFA, + PPC_ID_SPE_EVMWHUMI, + PPC_ID_SPE_EVMWHUMIA, + PPC_ID_SPE_EVMWHUSIAAW, + PPC_ID_SPE_EVMWHUSIANW, + PPC_ID_SPE_EVMWLSMIAAW, + PPC_ID_SPE_EVMWLSMIANW, + PPC_ID_SPE_EVMWLSSIANW, + PPC_ID_SPE_EVMWLSSIAAW, + PPC_ID_SPE_EVMWLUMI, + PPC_ID_SPE_EVMWLUMIA, + PPC_ID_SPE_EVMWLUMIAAW, + PPC_ID_SPE_EVMWLUMIANW, + PPC_ID_SPE_EVMWLUSIAAW, + PPC_ID_SPE_EVMWLUSIANW, + PPC_ID_SPE_EVMWSMF, + PPC_ID_SPE_EVMWSMFA, + PPC_ID_SPE_EVMWSMFAA, + PPC_ID_SPE_EVMWSMFAN, + PPC_ID_SPE_EVMWSMI, + PPC_ID_SPE_EVMWSMIA, + PPC_ID_SPE_EVMWSMIAA, + PPC_ID_SPE_EVMWSMIAN, + PPC_ID_SPE_EVMWSSF, + PPC_ID_SPE_EVMWSSFA, + PPC_ID_SPE_EVMWSSFAA, + PPC_ID_SPE_EVMWSSFAN, + PPC_ID_SPE_EVMWUMI, + PPC_ID_SPE_EVMWUMIA, + PPC_ID_SPE_EVMWUMIAA, + PPC_ID_SPE_EVMWUMIAN, + PPC_ID_SPE_EVNAND, + PPC_ID_SPE_EVNEG, + PPC_ID_SPE_EVNOR, + PPC_ID_SPE_EVNOT, + PPC_ID_SPE_EVOR, + PPC_ID_SPE_EVORC, + PPC_ID_SPE_EVRLW, + PPC_ID_SPE_EVRLWI, + PPC_ID_SPE_EVRNDW, + PPC_ID_SPE_EVSEL, + PPC_ID_SPE_EVSLW, + PPC_ID_SPE_EVSLWI, + PPC_ID_SPE_EVSPLATFI, + PPC_ID_SPE_EVSPLATI, + PPC_ID_SPE_EVSRWIS, + PPC_ID_SPE_EVSRWIU, + PPC_ID_SPE_EVSRWS, + PPC_ID_SPE_EVSRWU, + PPC_ID_SPE_EVSTDD, + PPC_ID_SPE_EVSTDDX, + PPC_ID_SPE_EVSTDH, + PPC_ID_SPE_EVSTDHX, + PPC_ID_SPE_EVSTDW, + PPC_ID_SPE_EVSTDWX, + PPC_ID_SPE_EVSTWHE, + PPC_ID_SPE_EVSTWHEX, + PPC_ID_SPE_EVSTWHO, + PPC_ID_SPE_EVSTWHOX, + PPC_ID_SPE_EVSTWWE, + PPC_ID_SPE_EVSTWWEX, + PPC_ID_SPE_EVSTWWO, + PPC_ID_SPE_EVSTWWOX, + PPC_ID_SPE_EVSUBFSMIAAW, + PPC_ID_SPE_EVSUBFSSIAAW, + PPC_ID_SPE_EVSUBFUMIAAW, + PPC_ID_SPE_EVSUBFUSIAAW, + PPC_ID_SPE_EVSUBFW, + PPC_ID_SPE_EVSUBIFW, + PPC_ID_SPE_EVXOR, }; #ifndef __cplusplus From 2d255a9bb5c5896ae895f4169b5d6b0e4317113b Mon Sep 17 00:00:00 2001 From: noone Date: Sun, 29 Dec 2024 20:12:03 -0800 Subject: [PATCH 08/19] Catch decoding up capstone 5.0.3 --- arch/powerpc/decode/decode.c | 2662 ++++++++++++++++++++++++++++++++-- arch/powerpc/decode/decode.h | 282 +++- 2 files changed, 2855 insertions(+), 89 deletions(-) diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c index 0b304895c..0eb0ab5c2 100644 --- a/arch/powerpc/decode/decode.c +++ b/arch/powerpc/decode/decode.c @@ -48,6 +48,11 @@ static Register VsxVr(uint32_t value) return PPC_REG_VSX_VR0 + value; } +static Register VsxVrHi(uint32_t value) +{ + return PPC_REG_VSX_VR0 + value + 32; +} + static void PushUIMMValue(Instruction* instruction, uint32_t uimm) { instruction->operands[instruction->numOperands].cls = PPC_OP_UIMM; @@ -134,6 +139,11 @@ static void PushRB(Instruction* instruction, uint32_t word32) PushRegister(instruction, PPC_OP_REG_RB, Gpr(GetB(word32))); } +static void PushRC(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_RC, Gpr(GetC(word32))); +} + static void PushRD(Instruction* instruction, uint32_t word32) { PushRegister(instruction, PPC_OP_REG_RD, Gpr(GetD(word32))); @@ -281,6 +291,11 @@ static void PushVsxA(Instruction* instruction, uint32_t word32, VsxWidth width) VsxVr(GetVsxA(word32))); } +static void PushVsxHiA(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_VSX_RA, VsxVrHi(GetA(word32))); +} + static uint32_t GetVsxB(uint32_t word32) { uint32_t bx = (word32 >> 1) & 0x1; @@ -296,6 +311,11 @@ static void PushVsxB(Instruction* instruction, uint32_t word32, VsxWidth width) VsxVr(GetVsxB(word32))); } +static void PushVsxHiB(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_VSX_RB, VsxVrHi(GetB(word32))); +} + static uint32_t GetVsxC(uint32_t word32) { uint32_t cx = (word32 >> 3) & 0x1; @@ -326,6 +346,11 @@ static void PushVsxD(Instruction* instruction, uint32_t word32, VsxWidth width) VsxVr(GetVsxD(word32))); } +static void PushVsxHiD(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_VSX_RD, VsxVrHi(GetD(word32))); +} + static void PushVsxS(Instruction* instruction, uint32_t word32, VsxWidth width) { uint32_t sx = word32 & 0x1; @@ -454,12 +479,39 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) return PPC_ID_AV_VSLDOI; + case 0x2d: + return PPC_ID_AV_VPERMXOR; + case 0x2e: return PPC_ID_AV_VMADDFP; case 0x2f: return PPC_ID_AV_VNMSUBFP; + case 0x30: + return PPC_ID_AV_MADDHD; + + case 0x31: + return PPC_ID_AV_MADDHDU; + + case 0x33: + return PPC_ID_AV_MADDLD; + + case 0x3b: + return PPC_ID_AV_VPERMR; + + case 0x3c: + return PPC_ID_AV_VADDEUQM; + + case 0x3d: + return PPC_ID_AV_VADDECUQ; + + case 0x3e: + return PPC_ID_AV_VSUBEUQM; + + case 0x3f: + return PPC_ID_AV_VSUBECUQ; + default: ; } @@ -470,6 +522,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x000: return PPC_ID_AV_VADDUBM; + case 0x001: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VMUL10CUQ; + case 0x002: return PPC_ID_AV_VMAXUB; @@ -481,6 +539,10 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x406: return PPC_ID_AV_VCMPEQUBx; + case 0x007: + case 0x407: + return PPC_ID_AV_VCMPNEBx; + case 0x008: return PPC_ID_AV_VMULOUB; @@ -496,6 +558,9 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x040: return PPC_ID_AV_VADDUHM; + case 0x041: + return PPC_ID_AV_VMUL10ECUQ; + case 0x042: return PPC_ID_AV_VMAXUH; @@ -507,6 +572,10 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x446: return PPC_ID_AV_VCMPEQUHx; + case 0x047: + case 0x447: + return PPC_ID_AV_VCMPNEHx; + case 0x048: return PPC_ID_AV_VMULOUH; @@ -528,11 +597,17 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x084: return PPC_ID_AV_VRLW; + case 0x085: + return PPC_ID_AV_VRLWMI; case 0x086: case 0x486: return PPC_ID_AV_VCMPEQUWx; + case 0x087: + case 0x487: + return PPC_ID_AV_VCMPNEWx; + case 0x88: return PPC_ID_AV_VMULOUW; @@ -554,6 +629,8 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x0c4: return PPC_ID_AV_VRLD; + case 0x0c5: + return PPC_ID_AV_VRLDMI; case 0x0c6: case 0x4c6: @@ -566,12 +643,19 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x0ce: return PPC_ID_AV_VPKUWUS; + case 0x100: + return PPC_ID_AV_VADDUQM; + case 0x102: return PPC_ID_AV_VMAXSB; case 0x104: return PPC_ID_AV_VSLB; + case 0x107: + case 0x507: + return PPC_ID_AV_VCMPNEZBx; + case 0x108: return PPC_ID_AV_VMULOSB; @@ -587,12 +671,19 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x10e: return PPC_ID_AV_VPKSHUS; + case 0x140: + return PPC_ID_AV_VADDCUQ; + case 0x142: return PPC_ID_AV_VMAXSH; case 0x144: return PPC_ID_AV_VSLH; + case 0x147: + case 0x547: + return PPC_ID_AV_VCMPNEZHx; + case 0x148: return PPC_ID_AV_VMULOSH; @@ -617,6 +708,13 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x184: return PPC_ID_AV_VSLW; + case 0x185: + return PPC_ID_AV_VRLWNM; + + case 0x187: + case 0x587: + return PPC_ID_AV_VCMPNEZWx; + case 0x188: return PPC_ID_AV_VMULOSW; @@ -638,6 +736,9 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x1c4: return PPC_ID_AV_VSL; + case 0x1c5: + return PPC_ID_AV_VRLDNM; + case 0x1c6: case 0x5c6: return PPC_ID_AV_VCMPGEFPx; @@ -654,6 +755,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x200: return PPC_ID_AV_VADDUBS; + case 0x201: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VMUL10UQ; + case 0x202: return PPC_ID_AV_VMINUB; @@ -677,6 +784,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x20c: return PPC_ID_AV_VSPLTB; + case 0x20d: + if ((word32 & 0x00100000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VEXTRACTUB; + case 0x20e: if (a != 0) return PPC_ID_INVALID; @@ -686,6 +799,9 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x240: return PPC_ID_AV_VADDUHS; + case 0x241: + return PPC_ID_AV_VMUL10EUQ; + case 0x242: return PPC_ID_AV_VMINUH; @@ -708,6 +824,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x24c: return PPC_ID_AV_VSPLTH; + case 0x24d: + if ((word32 & 0x00100000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VEXTRACTUH; + case 0x24e: if (a != 0) return PPC_ID_INVALID; @@ -739,6 +861,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x28c: return PPC_ID_AV_VSPLTW; + case 0x28d: + if ((word32 & 0x00100000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VEXTRACTUW; + case 0x28e: if (a != 0) return PPC_ID_INVALID; @@ -765,6 +893,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) return PPC_ID_AV_VRFIM; + case 0x2cd: + if ((word32 & 0x00100000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VEXTRACTD; + case 0x2ce: if (a != 0) return PPC_ID_INVALID; @@ -796,12 +930,21 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) return PPC_ID_AV_VSPLTISB; + case 0x30d: + if ((word32 & 0x00100000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VINSERTB; + case 0x30e: return PPC_ID_AV_VPKPX; case 0x340: return PPC_ID_AV_VADDSHS; + case 0x341: + return PPC_ID_AV_BCDCPSGN; + case 0x342: return PPC_ID_AV_VMINSH; @@ -824,6 +967,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) return PPC_ID_AV_VSPLTISH; + case 0x34d: + if ((word32 & 0x00100000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VINSERTH; + case 0x34e: if (a != 0) return PPC_ID_INVALID; @@ -855,6 +1004,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) return PPC_ID_AV_VSPLTISW; + case 0x38d: + if ((word32 & 0x00100000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VINSERTW; + case 0x3c2: return PPC_ID_AV_VMINSD; @@ -872,6 +1027,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x3ca: return PPC_ID_AV_VCTSXS; + case 0x3cd: + if ((word32 & 0x00100000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VINSERTD; + case 0x3ce: if (a != 0) return PPC_ID_INVALID; @@ -881,12 +1042,22 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x400: return PPC_ID_AV_VSUBUBM; + case 0x401: + case 0x601: + return PPC_ID_AV_BCDADD; + case 0x402: return PPC_ID_AV_VAVGUB; + case 0x403: + return PPC_ID_AV_VABSDUB; + case 0x404: return PPC_ID_AV_VAND; + case 0x408: + return PPC_ID_AV_VPMSUMB; + case 0x40a: return PPC_ID_AV_VMAXFP; @@ -896,38 +1067,101 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x440: return PPC_ID_AV_VSUBUHM; + case 0x441: + case 0x641: + return PPC_ID_AV_BCDSUB; + case 0x442: return PPC_ID_AV_VAVGUH; + case 0x443: + return PPC_ID_AV_VABSDUH; + case 0x444: return PPC_ID_AV_VANDC; + case 0x448: + return PPC_ID_AV_VPMSUMH; + case 0x44a: return PPC_ID_AV_VMINFP; case 0x44c: return PPC_ID_AV_VSRO; + case 0x44e: + return PPC_ID_AV_VPKUDUM; + case 0x480: return PPC_ID_AV_VSUBUWM; + case 0x481: + return PPC_ID_AV_BCDUS; + case 0x482: return PPC_ID_AV_VAVGUW; + case 0x483: + return PPC_ID_AV_VABSDUW; + case 0x484: - return PPC_ID_AV_VOR; + if (a == b) + return PPC_ID_AV_VMR; + else + return PPC_ID_AV_VOR; + + case 0x488: + return PPC_ID_AV_VPMSUMW; case 0x4c0: return PPC_ID_AV_VSUBUDM; + case 0x4c1: + case 0x6c1: + return PPC_ID_AV_BCDS; + case 0x4c4: return PPC_ID_AV_VXOR; + case 0x4c8: + return PPC_ID_AV_VPMSUMD; + + case 0x4ce: + return PPC_ID_AV_VPKUDUS; + + case 0x500: + return PPC_ID_AV_VSUBUQM; + + case 0x501: + case 0x701: + return PPC_ID_AV_BCDTRUNC; + case 0x502: return PPC_ID_AV_VAVGSB; case 0x504: - return PPC_ID_AV_VNOR; + if (a == b) + return PPC_ID_AV_VNOT; + else + return PPC_ID_AV_VNOR; + + case 0x508: + return PPC_ID_AV_VCIPHER; + + case 0x509: + return PPC_ID_AV_VCIPHERLAST; + + case 0x50c: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VGBBD; + + case 0x540: + return PPC_ID_AV_VSUBCUQ; + + case 0x541: + return PPC_ID_AV_BCDUTRUNC; case 0x542: return PPC_ID_AV_VAVGSH; @@ -935,27 +1169,148 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x544: return PPC_ID_AV_VORC; + case 0x548: + return PPC_ID_AV_VNCIPHER; + + case 0x549: + return PPC_ID_AV_VNCIPHERLAST; + + case 0x54c: + return PPC_ID_AV_VBPERMQ; + + case 0x54e: + return PPC_ID_AV_VPKSDUS; + case 0x580: return PPC_ID_AV_VSUBCUW; + case 0x581: + case 0x781: + switch (a) + { + case 0x00: + if (subop == 0x581) + return PPC_ID_AV_BCDCTSQ; + else + return PPC_ID_INVALID; + + case 0x02: + return PPC_ID_AV_BCDCFSQ; + + case 0x04: + return PPC_ID_AV_BCDCTZ; + + case 0x05: + if (subop == 0x581) + return PPC_ID_AV_BCDCTN; + else + return PPC_ID_INVALID; + + case 0x06: + return PPC_ID_AV_BCDCFZ; + + case 0x07: + return PPC_ID_AV_BCDCFN; + + case 0x1f: + return PPC_ID_AV_BCDSETSGN; + + default: + return PPC_ID_INVALID; + } + case 0x582: return PPC_ID_AV_VAVGSW; case 0x584: return PPC_ID_AV_VNAND; + case 0x5c1: + case 0x7c1: + return PPC_ID_AV_BCDSR; + case 0x5c4: return PPC_ID_AV_VSLD; + case 0x5c8: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VSBOX; + + case 0x5cc: + return PPC_ID_AV_VBPERMD; + + case 0x5ce: + return PPC_ID_AV_VPKSDSS; + case 0x600: return PPC_ID_AV_VSUBUBS; + case 0x602: + switch (a) + { + case 0x00: + return PPC_ID_AV_VCLZLSBB; + + case 0x01: + return PPC_ID_AV_VCTZLSBB; + + case 0x06: + return PPC_ID_AV_VNEGW; + + case 0x07: + return PPC_ID_AV_VNEGD; + + case 0x08: + return PPC_ID_AV_VPRTYBW; + + case 0x09: + return PPC_ID_AV_VPRTYBD; + + case 0x0a: + return PPC_ID_AV_VPRTYBQ; + + case 0x10: + return PPC_ID_AV_VEXTSB2W; + + case 0x11: + return PPC_ID_AV_VEXTSH2W; + + case 0x18: + return PPC_ID_AV_VEXTSB2D; + + case 0x19: + return PPC_ID_AV_VEXTSH2D; + + case 0x1a: + return PPC_ID_AV_VEXTSW2D; + + case 0x1c: + return PPC_ID_AV_VCTZB; + + case 0x1d: + return PPC_ID_AV_VCTZH; + + case 0x1e: + return PPC_ID_AV_VCTZW; + + case 0x1f: + return PPC_ID_AV_VCTZD; + + default: + return PPC_ID_INVALID; + } + case 0x604: if ((a != 0) || (b != 0)) return PPC_ID_INVALID; return PPC_ID_AV_MFVSCR; + case 0x60d: + return PPC_ID_AV_VEXTUBLX; + case 0x608: return PPC_ID_AV_VSUM4UBS; @@ -971,18 +1326,45 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x648: return PPC_ID_AV_VSUM4SHS; + case 0x64d: + return PPC_ID_AV_VEXTUHLX; + + case 0x64e: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VUPKHSW; + case 0x680: return PPC_ID_AV_VSUBUWS; + case 0x682: + return PPC_ID_AV_VSHASIGMAW; + case 0x684: return PPC_ID_AV_VEQV; case 0x688: return PPC_ID_AV_VSUM2SWS; + case 0x68c: + return PPC_ID_AV_VMRGOW; + + case 0x68d: + return PPC_ID_AV_VEXTUWLX; + + case 0x6c2: + return PPC_ID_AV_VSHASIGMAD; + case 0x6c4: return PPC_ID_AV_VSRD; + case 0x6ce: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_AV_VUPKLSW; + case 0x700: return PPC_ID_AV_VSUBSBS; @@ -998,9 +1380,15 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) return PPC_ID_AV_VPOPCNTB; + case 0x704: + return PPC_ID_AV_VSRV; + case 0x708: return PPC_ID_AV_VSUM4SBS; + case 0x70d: + return PPC_ID_AV_VEXTUBRX; + case 0x740: return PPC_ID_AV_VSUBSHS; @@ -1016,6 +1404,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) return PPC_ID_AV_VPOPCNTH; + case 0x744: + return PPC_ID_AV_VSLV; + + case 0x74d: + return PPC_ID_AV_VEXTUHRX; + case 0x780: return PPC_ID_AV_VSUBSWS; @@ -1034,6 +1428,12 @@ static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) case 0x788: return PPC_ID_AV_VSUMSWS; + case 0x78c: + return PPC_ID_AV_VMRGEW; + + case 0x78d: + return PPC_ID_AV_VEXTUWRX; + case 0x7c2: if (a != 0) return PPC_ID_INVALID; @@ -2082,7 +2482,20 @@ static InstructionId Decode0x13(uint32_t word32, uint32_t decodeFlags) uint32_t b = GetB(word32); uint32_t d = GetD(word32); - uint32_t subop = word32 & 0x7ff; + uint32_t subop = (word32 >> 1) & 0x1f; + switch (subop) + { + case 0x2: + if ((word32 & 0x001fffff) == 4) + return PPC_ID_LNIA; + + return PPC_ID_ADDPCIS; + + default: + ; + } + + subop = word32 & 0x7ff; switch (subop) { case 0x000: @@ -2331,6 +2744,10 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x017: return PPC_ID_MULHWUx; + case 0x018: + case 0x019: + return PPC_ID_VSX_LXSIWZX; + case 0x026: if ((word32 & 0x00100000) != 0) { @@ -2350,12 +2767,13 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_MFCR; case 0x028: + case 0x029: return PPC_ID_LWARX; case 0x02a: return PPC_ID_LDX; - case 0x2c: + case 0x02c: if ((word32 & 0x02000000) != 0) return PPC_ID_INVALID; @@ -2383,6 +2801,9 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x039: return PPC_ID_ANDx; + case 0x03e: + return PPC_ID_LWEPX; + case 0x040: if ((word32 & 0x00400000) == 0) { @@ -2421,6 +2842,24 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x451: return PPC_ID_SUBFx; + case 0x066: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_MFFPRD; + + case 0x067: + if (b != 0) + return PPC_ID_INVALID; + + // either MFVSRD or MFVRD; we use MFVRD for backwards + // compatibility with capstone + return PPC_ID_VSX_MFVSRD; + + case 0x068: + case 0x069: + return PPC_ID_LBARX; + case 0x06a: return PPC_ID_LDUX; @@ -2444,7 +2883,13 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x079: return PPC_ID_ANDCx; - case 0x07c: + case 0x07e: + if (d != 0) + return PPC_ID_INVALID; + + return PPC_ID_DCBSTEP; + + case 0x03c: { if ((word32 & 0x039ff800) != 0) return false; @@ -2495,6 +2940,10 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x097: return PPC_ID_MULHWx; + case 0x098: + case 0x099: + return PPC_ID_VSX_LXSIWAX; + case 0x0a6: if ((a != 0) || (b != 0)) return PPC_ID_INVALID; @@ -2502,17 +2951,34 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_MFMSR; case 0x0a8: + case 0x0a9: return PPC_ID_LDARX; case 0x0ac: - if (d != 0) + { + if ((word32 & 0x03800000) != 0) return PPC_ID_INVALID; - return PPC_ID_DCBF; + uint32_t l = (word32 >> 21) & 0x3; + switch (l) + { + case 1: + return PPC_ID_DCBFL; + + case 3: + return PPC_ID_DCBFLP; + + default: + return PPC_ID_DCBF; + } + } case 0x0ae: return PPC_ID_LBZX; + case 0x0be: + return PPC_ID_LBEPX; + case 0x0ce: if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) return PPC_ID_AV_LVX; @@ -2528,13 +2994,42 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_NEGx; + case 0xe6: + case 0xe7: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_MFVSRWZ; + + case 0x0e8: + case 0x0e9: + return PPC_ID_LHARX; + case 0x0ee: return PPC_ID_LBZUX; + case 0x0f4: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_POPCNTB; + case 0x0f8: case 0x0f9: return PPC_ID_NORx; + case 0x0fe: + if ((word32 & 0x03800000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_DCBFEP; + + case 0x100: + if ((word32 & 0x0003f800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SETB; + case 0x106: if ((a != 0) || (b != 0)) return PPC_ID_INVALID; @@ -2559,6 +3054,10 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x515: return PPC_ID_ADDEx; + case 0x118: + case 0x119: + return PPC_ID_VSX_STXSIWX; + case 0x120: if ((word32 & 0x00100000) != 0) { @@ -2595,6 +3094,12 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x12e: return PPC_ID_STWX; + case 0x13a: + return PPC_ID_STDEPX; + + case 0x13e: + return PPC_ID_STWEPX; + case 0x146: if ((word32 & 0x03ff7800) != 0) return PPC_ID_INVALID; @@ -2613,15 +3118,34 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_MTMSRD; + case 0x166: + case 0x167: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_MTVSRD; + case 0x16a: return PPC_ID_STDUX; case 0x16e: return PPC_ID_STWUX; - case 0x18e: - if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) - return PPC_ID_AV_STVEWX; + case 0x180: + if ((word32 & 0x00400000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_CMPRB; + + case 0x18d: + if ((word32 & 0x02000000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_ICBLQ; + + case 0x18e: + if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) + return PPC_ID_AV_STVEWX; return PPC_ID_INVALID; @@ -2649,12 +3173,34 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_MTSR; + case 0x1a6: + case 0x1a7: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_MTVSRWA; + case 0x1ad: return PPC_ID_STDCX; case 0x1ae: return PPC_ID_STBX; + case 0x1be: + return PPC_ID_STBEPX; + + case 0x1c0: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_CMPEQB; + + case 0x1cc: + if ((word32 & 0x02000000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_ICBLC; + case 0x1ce: if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) return PPC_ID_AV_STVX; @@ -2700,21 +3246,51 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_MTSRIN; - case 0x1ec: - if (d != 0) + case 0x1e6: + case 0x1e7: + if (b != 0) return PPC_ID_INVALID; - return PPC_ID_DCBTST; + return PPC_ID_VSX_MTVSRWZ; + + case 0x1ec: + { + uint32_t th = (word32 >> 21) & 0x1f; + if (th == 0x10) + return PPC_ID_DCBTSTT; + else + return PPC_ID_DCBTST; + } case 0x1ee: return PPC_ID_STBUX; + case 0x1f8: + return PPC_ID_BPERMD; + + case 0x1fe: + return PPC_ID_DCBTSTEP; + + case 0x212: + return PPC_ID_MODUD; + case 0x214: case 0x215: case 0x614: case 0x615: return PPC_ID_ADDx; + case 0x216: + return PPC_ID_MODUW; + + case 0x218: + case 0x219: + return PPC_ID_VSX_LXVX; + + case 0x21a: + case 0x21b: + return PPC_ID_VSX_LXVL; + case 0x224: if ((d != 0) || (a != 0)) return PPC_ID_INVALID; @@ -2722,10 +3298,13 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_TLBIEL; case 0x22c: - if (d != 0) - return PPC_ID_INVALID; - - return PPC_ID_DCBT; + { + uint32_t th = (word32 >> 21) & 0x1f; + if (th == 0x10) + return PPC_ID_DCBTT; + else + return PPC_ID_DCBT; + } case 0x22e: return PPC_ID_LHZX; @@ -2734,12 +3313,29 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x239: return PPC_ID_EQVx; + case 0x23e: + return PPC_ID_LHEPX; + + case 0x25a: + case 0x25b: + return PPC_ID_VSX_LXVLL; + + case 0x25c: + return PPC_ID_MFBHRBE; + case 0x264: if (a != 0) return PPC_ID_INVALID; return PPC_ID_TLBIE; + case 0x266: + case 0x267: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_MFVSRLD; + case 0x26c: return PPC_ID_ECIWX; @@ -2750,6 +3346,9 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x279: return PPC_ID_XORx; + case 0x27e: + return PPC_ID_DCBTEP; + case 0x286: { uint32_t dcr = GetSpecialRegisterCommon(word32); @@ -2776,6 +3375,15 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_VSX_LXVDSX; + case 0x29c: + return PPC_ID_MFPMR; + + case 0x2a4: + if (a != 0 || b != 0 || d != 0) + return PPC_ID_INVALID; + + return PPC_ID_SLBSYNC; + case 0x2a6: { uint32_t spr = GetSpecialRegisterCommon(word32); @@ -2822,6 +3430,10 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_INVALID; + case 0x2d8: + case 0x2d9: + return PPC_ID_VSX_LXVWSX; + case 0x2e4: if ((word32 & 0x03fff800) != 0) return PPC_ID_INVALID; @@ -2868,12 +3480,39 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) // TODO: [Category: Embedded.Phased-In] return PPC_ID_POPCNTW; + case 0x312: + case 0x313: + case 0x712: + case 0x713: + return PPC_ID_DIVDEUx; + + case 0x316: + case 0x317: + case 0x716: + case 0x717: + return PPC_ID_DIVWEUx; + + case 0x318: + case 0x319: + return PPC_ID_VSX_STXVX; + + case 0x31a: + case 0x31b: + return PPC_ID_VSX_STXVL; + case 0x324: if (a != 0) return PPC_ID_INVALID; return PPC_ID_SLBMTE; + case 0x326: + case 0x327: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_MTVSRWS; + case 0x32e: return PPC_ID_STHX; @@ -2881,12 +3520,41 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x339: return PPC_ID_ORCx; + case 0x33e: + return PPC_ID_STHEPX; + + case 0x352: + case 0x353: + case 0x752: + case 0x753: + return PPC_ID_DIVDEx; + + case 0x356: + case 0x357: + case 0x756: + case 0x757: + return PPC_ID_DIVWEx; + + case 0x35a: + case 0x35b: + return PPC_ID_VSX_STXVLL; + + case 0x35c: + if ((a != 0) || (b != 0) || (d != 0)) + return PPC_ID_INVALID; + + return PPC_ID_CLRBHRB; + case 0x364: if ((d != 0) || (a != 0)) return PPC_ID_INVALID; return PPC_ID_SLBIE; + case 0x366: + case 0x367: + return PPC_ID_VSX_MTVSRDD; + case 0x36c: return PPC_ID_ECOWX; @@ -2949,6 +3617,15 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x797: return PPC_ID_DIVWUx; + case 0x39c: + return PPC_ID_MTPMR; + + case 0x3a4: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_SLBIEG; + case 0x3a6: { uint32_t spr = GetSpecialRegisterCommon(word32); @@ -2981,6 +3658,12 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x3b9: return PPC_ID_NANDx; + case 0x3cc: + if ((word32 & 0x02000000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_ICBTLS; + case 0x3ce: if ((decodeFlags & DECODE_FLAGS_ALTIVEC) != 0) return PPC_ID_AV_STVXL; @@ -3022,6 +3705,10 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) break; + case 0x418: + case 0x419: + return PPC_ID_VSX_LXSSPX; + case 0x428: if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) return PPC_ID_INVALID; @@ -3041,6 +3728,13 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x431: return PPC_ID_SRWx; + case 0x434: + case 0x435: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_CNTTZWx; + case 0x436: case 0x437: return PPC_ID_SRDx; @@ -3054,6 +3748,22 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x46e: return PPC_ID_LFSUX; + case 0x474: + case 0x475: + if (b != 0) + return PPC_ID_INVALID; + + return PPC_ID_CNTTZDx; + + case 0x480: + if ((word32 & 0x007ff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MCRXRX; + + case 0x48c: + return PPC_ID_LWAT; + case 0x498: case 0x499: if ((decodeFlags & DECODE_FLAGS_VSX) == 0) @@ -3090,6 +3800,12 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x4ae: return PPC_ID_LFDX; + case 0x4be: + return PPC_ID_LFDEPX; + + case 0x4cc: + return PPC_ID_LDAT; + case 0x4ee: return PPC_ID_LFDUX; @@ -3099,6 +3815,16 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_TLBIA; + case 0x518: + case 0x519: + return PPC_ID_VSX_STXSSPX; + + case 0x51d: + if ((word32 & 0x03eff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_TBEGIN; + case 0x526: if (a != 0) return PPC_ID_INVALID; @@ -3120,9 +3846,21 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x52e: return PPC_ID_STFSX; + case 0x55d: + if ((word32 & 0x01fff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_TEND; + + case 0x56d: + return PPC_ID_STBCX; + case 0x56e: return PPC_ID_STFSUX; + case 0x58c: + return PPC_ID_STWAT; + case 0x598: case 0x599: if ((decodeFlags & DECODE_FLAGS_VSX) == 0) @@ -3130,12 +3868,39 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_VSX_STXSDX; + case 0x59c: + if ((word32 & 0x007ff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_TCHECK; + case 0x5aa: return PPC_ID_STSWI; + case 0x5ad: + return PPC_ID_STHCX; + case 0x5ae: return PPC_ID_STFDX; + case 0x5be: + return PPC_ID_STFDEPX; + + case 0x5cc: + return PPC_ID_STDAT; + + case 0x5dd: + if ((word32 & 0x03dff800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_TSR; + + case 0x5e6: + if ((word32 & 0x001cf800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_DARN; + case 0x5ec: if (d != 0) return PPC_ID_INVALID; @@ -3145,6 +3910,18 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x5ee: return PPC_ID_STFDUX; + case 0x60c: + if (d != 1) + return PPC_ID_INVALID; + + return PPC_ID_COPY; + + case 0x612: + return PPC_ID_MODSD; + + case 0x616: + return PPC_ID_MODSW; + case 0x618: case 0x619: if ((decodeFlags & DECODE_FLAGS_VSX) == 0) @@ -3152,6 +3929,13 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_VSX_LXVW4X; + case 0x61a: + case 0x61b: + return PPC_ID_VSX_LXSIBZX; + + case 0x61d: + return PPC_ID_TABORTWC; + case 0x624: if ((word32 & 0x03e00000) != 0) return PPC_ID_INVALID; @@ -3175,6 +3959,17 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_SRADx; + case 0x658: + case 0x659: + return PPC_ID_VSX_LXVH8X; + + case 0x65a: + case 0x65b: + return PPC_ID_VSX_LXSIHZX; + + case 0x65d: + return PPC_ID_TABORTDC; + case 0x66a: return PPC_ID_LHZCIX; @@ -3211,6 +4006,12 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_SRADIx; + case 0x68c: + if (a != 0 || b != 0 || d != 0) + return PPC_ID_INVALID; + + return PPC_ID_CP_ABORT; + case 0x698: case 0x699: if ((decodeFlags & DECODE_FLAGS_VSX) == 0) @@ -3218,6 +4019,15 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_VSX_LXVD2X; + case 0x69d: + return PPC_ID_TABORTWCI; + + case 0x6a6: + if ((word32 & 0x001e0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_SLBMFEV; + case 0x6aa: return PPC_ID_LBZCIX; @@ -3233,12 +4043,36 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) case 0x6ae: return PPC_ID_LFIWAX; + case 0x6d8: + case 0x6d9: + return PPC_ID_VSX_LXVB16X; + + case 0x6dd: + return PPC_ID_TABORTDCI; + case 0x6ea: return PPC_ID_LDCIX; + case 0x6ec: + if ((a != 0) || (b != 0) || (d != 0)) + return PPC_ID_INVALID; + + return PPC_ID_MSGSYNC; + case 0x6ee: return PPC_ID_LFIWZX; + case 0x6f4: + case 0x6f5: + case 0x6f6: + case 0x6f7: + return PPC_ID_EXTSWSLIx; + + case 0x70d: + if (d != 1) + return PPC_ID_INVALID; + + return PPC_ID_PASTE; case 0x718: case 0x719: @@ -3247,6 +4081,16 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_VSX_STXVW4X; + case 0x71a: + case 0x71b: + return PPC_ID_VSX_STXSIBX; + + case 0x71d: + if (d != 0 || b != 0) + return PPC_ID_INVALID; + + return PPC_ID_TABORT; + case 0x724: if ((word32 & 0x03e00000) != 0) return PPC_ID_INVALID; @@ -3272,6 +4116,20 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_EXTSHx; + case 0x758: + case 0x759: + return PPC_ID_VSX_STXVH8X; + + case 0x75a: + case 0x75b: + return PPC_ID_VSX_STXSIHX; + + case 0x75d: + if ((d != 0) || (b != 0)) + return PPC_ID_INVALID; + + return PPC_ID_TRECLAIM; + case 0x764: if ((word32 & 0x800) != 0) return PPC_ID_TLBREHI; @@ -3333,6 +4191,22 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_EXTSWx; + case 0x7be: + if (d != 0) + return PPC_ID_INVALID; + + return PPC_ID_ICBIEP; + + case 0x7d8: + case 0x7d9: + return PPC_ID_VSX_STXVB16X; + + case 0x7dd: + if ((a != 0) || (b != 0) || (d != 0)) + return PPC_ID_INVALID; + + return PPC_ID_TRECHKPT; + case 0x7e4: if (d != 0 || a != 0) return PPC_ID_INVALID; @@ -3355,6 +4229,12 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_INVALID; } + case 0x7fe: + if (d != 0) + return PPC_ID_INVALID; + + return PPC_ID_DCBZEP; + default: return PPC_ID_INVALID; } @@ -3477,9 +4357,43 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) default: break; } + subop = (word32 >> 1) & 0x3ff; + switch (subop) + { + case 0x168: + if ((word32 & 0x00180000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XXSPLTIB; + + case 0x396: + return PPC_ID_VSX_XSIEXPDP; + + default: + ; + } + subop = (word32 >> 2) & 0x1ff; switch (subop) { + case 0x00a: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRSQRTESP; + + case 0x00b: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSSQRTSP; + + case 0x01a: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRESP; + case 0x048: if ((word32 & 0x001f0000) != 0x0) return PPC_ID_INVALID; @@ -3594,6 +4508,12 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) return PPC_ID_VSX_XXSPLTW; + case 0x0a5: + if ((word32 & 0x00100000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XXEXTRACTUW; + case 0x0a8: if ((word32 & 0x001f0000) != 0x0) return PPC_ID_INVALID; @@ -3606,7 +4526,7 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) return PPC_ID_VSX_XVRSPIP; - case 0xaa: + case 0x0aa: if ((word32 & 0x007f0001) != 0) return PPC_ID_INVALID; @@ -3618,6 +4538,12 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) return PPC_ID_VSX_XVRSPIC; + case 0x0b5: + if ((word32 & 0x00100000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XXINSERTW; + case 0x0b8: if ((word32 & 0x001f0000) != 0x0) return PPC_ID_INVALID; @@ -3714,6 +4640,36 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) return PPC_ID_VSX_XSCVDPSP; + case 0x10b: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVDPSPN; + + case 0x119: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRSP; + + case 0x128: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVUXDSP; + + case 0x12a: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSTSTDCSP; + + case 0x138: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVSXDSP; + case 0x148: if ((word32 & 0x001f0000) != 0x0) return PPC_ID_INVALID; @@ -3726,6 +4682,12 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) return PPC_ID_VSX_XSCVSPDP; + case 0x14b: + if ((word32 & 0x001f0000) != 0x0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVSPDPN; + case 0x158: if ((word32 & 0x001f0000) != 0x0) return PPC_ID_INVALID; @@ -3738,6 +4700,34 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) return PPC_ID_VSX_XSABSDP; + case 0x15b: + { + uint32_t subsubop = (word32 >> 16) & 0x1f; + switch (subsubop) + { + case 0x00: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSXEXPDP; + + case 0x01: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSXSIGDP; + + case 0x10: + return PPC_ID_VSX_XSCVHPDP; + + case 0x11: + return PPC_ID_VSX_XSCVDPHP; + + default: + return PPC_ID_INVALID; + } + } + case 0x168: if ((word32 & 0x001f0000) != 0x0) return PPC_ID_INVALID; @@ -3750,6 +4740,12 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) return PPC_ID_VSX_XSNABSDP; + case 0x16a: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSTSTDCDP; + case 0x178: if ((word32 & 0x001f0000) != 0x0) return PPC_ID_INVALID; @@ -3834,19 +4830,60 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) return PPC_ID_VSX_XVABSDP; - case 0x1e8: - if ((word32 & 0x001f0000) != 0) - return PPC_ID_INVALID; + case 0x1db: + { + uint32_t subsubop = (word32 >> 16) & 0x1f; + switch (subsubop) + { + case 0x00: + return PPC_ID_VSX_XVXEXPDP; - return PPC_ID_VSX_XVCVUXDDP; + case 0x01: + return PPC_ID_VSX_XVXSIGDP; - case 0x1e9: - if ((word32 & 0x001f0000) != 0) - return PPC_ID_INVALID; + case 0x07: + return PPC_ID_VSX_XXBRH; - return PPC_ID_VSX_XVNABSDP; + case 0x08: + return PPC_ID_VSX_XVXEXPSP; - case 0x1f8: + case 0x09: + return PPC_ID_VSX_XVXSIGSP; + + case 0x0f: + return PPC_ID_VSX_XXBRW; + + case 0x17: + return PPC_ID_VSX_XXBRD; + + case 0x18: + return PPC_ID_VSX_XVCVHPSP; + + case 0x19: + return PPC_ID_VSX_XVCVSPHP; + + case 0x1f: + return PPC_ID_VSX_XXBRQ; + + default: + return PPC_ID_INVALID; + + } + } + + case 0x1e8: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVCVUXDDP; + + case 0x1e9: + if ((word32 & 0x001f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XVNABSDP; + + case 0x1f8: if ((word32 & 0x001f0000) != 0x0) return PPC_ID_INVALID; @@ -3866,8 +4903,10 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) switch (subop) { case 0x00: - // TODO: XSADDSP? - return PPC_ID_INVALID; + return PPC_ID_VSX_XSADDSP; + + case 0x01: + return PPC_ID_VSX_XSMADDASP; case 0x02: case 0x22: @@ -3875,6 +4914,15 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) case 0x62: return PPC_ID_VSX_XXSLDWI; + case 0x03: + return PPC_ID_VSX_XSCMPEQDP; + + case 0x08: + return PPC_ID_VSX_XSSUBSP; + + case 0x09: + return PPC_ID_VSX_XSMADDMSP; + case 0x0a: case 0x2a: case 0x4a: @@ -3903,9 +4951,30 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) } } + case 0x0b: + return PPC_ID_VSX_XSCMPGTDP; + + case 0x10: + return PPC_ID_VSX_XSMULSP; + + case 0x11: + return PPC_ID_VSX_XSMSUBASP; + case 0x12: return PPC_ID_VSX_XXMRGHW; + case 0x13: + return PPC_ID_VSX_XSCMPGEDP; + + case 0x18: + return PPC_ID_VSX_XSDIVSP; + + case 0x19: + return PPC_ID_VSX_XSMSUBMSP; + + case 0x1a: + return PPC_ID_VSX_XXPERM; + case 0x20: return PPC_ID_VSX_XSADDDP; @@ -3948,6 +5017,12 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) case 0x3a: return PPC_ID_VSX_XXPERMR; + case 0x3b: + if ((word32 & 0x00600001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCMPEXPDP; + case 0x3d: if ((word32 & 0x00600001) != 0) return PPC_ID_INVALID; @@ -4038,23 +5113,39 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) return PPC_ID_VSX_XVTDIVDP; + case 0x80: + return PPC_ID_VSX_XSMAXCDP; + case 0x81: - // TODO: XSNMADDASP not handled by capstone? - return PPC_ID_INVALID; + return PPC_ID_VSX_XSNMADDASP; case 0x82: return PPC_ID_VSX_XXLAND; + case 0x88: + return PPC_ID_VSX_XSMINCDP; + case 0x89: - // TODO: XSNMADDMSP not handled by capstone? - return PPC_ID_INVALID; + return PPC_ID_VSX_XSNMADDMSP; case 0x8a: return PPC_ID_VSX_XXLANDC; + case 0x90: + return PPC_ID_VSX_XSMAXJDP; + + case 0x91: + return PPC_ID_VSX_XSNMSUBASP; + case 0x92: return PPC_ID_VSX_XXLOR; + case 0x98: + return PPC_ID_VSX_XSMINJDP; + + case 0x99: + return PPC_ID_VSX_XSNMSUBMSP; + case 0x9a: return PPC_ID_VSX_XXLXOR; @@ -4112,6 +5203,13 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) case 0xd1: return PPC_ID_VSX_XVNMSUBASP; + case 0xd5: + case 0xdd: + return PPC_ID_VSX_XVTSTDCSP; + + case 0xd8: + return PPC_ID_VSX_XVIEXPSP; + case 0xd9: return PPC_ID_VSX_XVNMSUBMSP; @@ -4136,6 +5234,13 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) case 0xf1: return PPC_ID_VSX_XVNMSUBADP; + case 0xf5: + case 0xfd: + return PPC_ID_VSX_XVTSTDCDP; + + case 0xf8: + return PPC_ID_VSX_XVIEXPDP; + case 0xf9: return PPC_ID_VSX_XVNMSUBMDP; @@ -4144,6 +5249,30 @@ static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) } } +static InstructionId DecodeVsx0x3D(uint32_t word32, uint32_t flags) +{ + uint32_t subop = word32 & 0x7; + switch (subop) + { + case 1: + return PPC_ID_VSX_LXV; + + case 2: + case 6: + return PPC_ID_VSX_STXSD; + + case 3: + case 7: + return PPC_ID_VSX_STXSSP; + + case 5: + return PPC_ID_VSX_STXV; + + default: + return PPC_ID_INVALID; + } +} + static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) { uint32_t a = GetA(word32); @@ -4192,6 +5321,26 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FCMPU; + case 0x008: + case 0x009: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSADDQPx; + else + return PPC_ID_INVALID; + + case 0x00a: + case 0x00b: + case 0x20a: + case 0x20b: + case 0x40a: + case 0x40b: + case 0x60a: + case 0x60b: + if ((word32 & 0x001e0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRQPIx; + case 0x010: case 0x011: return PPC_ID_FCPSGNx; @@ -4256,6 +5405,29 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FCMPO; + case 0x048: + case 0x049: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSMULQPx; + else + return PPC_ID_INVALID; + + case 0x04a: + case 0x24a: + case 0x44a: + case 0x64a: + if ((flags & DECODE_FLAGS_VSX) != 0) + { + if ((word32 & 0x001e0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSRQPXP; + } + else + { + return PPC_ID_INVALID; + } + case 0x04c: case 0x04d: if ((a != 0) || (b != 0)) @@ -4290,6 +5462,31 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FMRx; + case 0x0c8: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSCPSGNQP; + else + return PPC_ID_INVALID; + + case 0x100: + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_FTDIV; + + case 0x108: + if ((flags & DECODE_FLAGS_VSX) != 0) + { + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCMPOQP; + } + else + { + return PPC_ID_INVALID; + } + case 0x10c: case 0x10d: if ((word32 & 0x007e0800) != 0) @@ -4304,6 +5501,13 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FNABSx; + case 0x11c: + case 0x11d: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCTIWUx; + case 0x11e: case 0x11f: if (a != 0) @@ -4311,6 +5515,25 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FCTIWUZx; + case 0x140: + if ((word32 & 0x007f0000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_FTSQRT; + + case 0x148: + if ((flags & DECODE_FLAGS_VSX) != 0) + { + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCMPEXPQP; + } + else + { + return PPC_ID_INVALID; + } + case 0x210: case 0x211: if (a != 0) @@ -4318,6 +5541,13 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FABSx; + case 0x308: + case 0x309: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSMADDQPx; + else + return PPC_ID_INVALID; + case 0x310: case 0x311: if (a != 0) @@ -4325,6 +5555,13 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FRINx; + case 0x348: + case 0x349: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSMSUBQPx; + else + return PPC_ID_INVALID; + case 0x350: case 0x351: if (a != 0) @@ -4332,6 +5569,13 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FRIZx; + case 0x388: + case 0x389: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSNMADDQPx; + else + return PPC_ID_INVALID; + case 0x390: case 0x391: if (a != 0) @@ -4339,6 +5583,13 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FRIPx; + case 0x3c8: + case 0x3c9: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSNMSUBQPx; + else + return PPC_ID_INVALID; + case 0x3d0: case 0x3d1: if (a != 0) @@ -4346,17 +5597,146 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FRIMx; + case 0x408: + case 0x409: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSSUBQPx; + else + return PPC_ID_INVALID; + + case 0x448: + case 0x449: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSDIVQPx; + else + return PPC_ID_INVALID; + case 0x48e: case 0x48f: - if ((a != 0) || (b != 0)) + { + uint32_t subsubop = (word32 >> 16) & 0x1f; + switch (subsubop) + { + case 0x00: + if ((word32 & 0x0000f800) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MFFSx; + + case 0x01: + if ((word32 & 0x0000f801) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MFFSCE; + + case 0x14: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MFFSCDRN; + + case 0x15: + if ((word32 & 0x0000c001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MFFSCDRNI; + + case 0x16: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MFFSCRN; + + case 0x17: + if ((word32 & 0x0000e001) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MFFSCRNI; + + case 0x18: + if ((word32 & 0x0000f801) != 0) + return PPC_ID_INVALID; + + return PPC_ID_MFFSL; + + default: + return PPC_ID_INVALID; + } + } + + case 0x508: + if ((flags & DECODE_FLAGS_VSX) != 0) + { + if ((word32 & 0x00600000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCMPUQP; + } + else + { return PPC_ID_INVALID; + } - return PPC_ID_MFFSx; + case 0x588: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSTSTDCQP; + else + return PPC_ID_INVALID; case 0x58e: case 0x58f: return PPC_ID_MTFSFx; + case 0x648: + case 0x649: + if ((flags & DECODE_FLAGS_VSX) != 0) + { + uint32_t subsubop = (word32 >> 16) & 0x1f; + switch (subsubop) + { + case 0x00: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSABSQP; + + case 0x02: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSXEXPQP; + + case 0x08: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSNABSQP; + + case 0x10: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSNEGQP; + + case 0x12: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSXSIGQP; + + case 0x1b: + return PPC_ID_VSX_XSSQRTQPx; + + default: + PPC_ID_INVALID; + + } + } + else + { + return PPC_ID_INVALID; + } + case 0x65c: case 0x65d: if (a != 0) @@ -4371,6 +5751,67 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FCTIDZx; + case 0x688: + case 0x689: + if ((flags & DECODE_FLAGS_VSX) != 0) + { + uint32_t subsubop = (word32 >> 16) & 0x1f; + switch (subsubop) + { + case 0x01: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVQPUWZ; + + case 0x02: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVUDQP; + + case 0x09: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVQPSWZ; + + case 0x0a: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVSDQP; + + case 0x11: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVQPUDZ; + + case 0x14: + return PPC_ID_VSX_XSCVQPDPx; + + case 0x16: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVDPQP; + + case 0x19: + if ((word32 & 0x1) != 0) + return PPC_ID_INVALID; + + return PPC_ID_VSX_XSCVQPSDZ; + + default: + return PPC_ID_INVALID; + } + } + else + { + return PPC_ID_INVALID; + } + case 0x69c: case 0x69d: if (a != 0) @@ -4378,6 +5819,19 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_FCFIDx; + case 0x6c8: + if ((flags & DECODE_FLAGS_VSX) != 0) + return PPC_ID_VSX_XSIEXPQP; + else + return PPC_ID_INVALID; + + case 0x75c: + case 0x75d: + if (a != 0) + return PPC_ID_INVALID; + + return PPC_ID_FCTIDUx; + case 0x75e: case 0x75f: if (a != 0) @@ -4693,10 +6147,16 @@ static InstructionId Decode(uint32_t word32, uint32_t decodeFlags) return Decode0x3B(word32, decodeFlags); case 0x3c: - if ((decodeFlags & DECODE_FLAGS_VSX) == 0) + if ((decodeFlags & DECODE_FLAGS_VSX) != 0) + return DecodeVsx0x3C(word32, decodeFlags); + else return PPC_ID_INVALID; - return DecodeVsx0x3C(word32, decodeFlags); + case 0x3d: + if ((decodeFlags & DECODE_FLAGS_VSX) != 0) + return DecodeVsx0x3D(word32, decodeFlags); + else + return PPC_ID_INVALID; case 0x3e: if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) @@ -4723,10 +6183,12 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add { // instructions with no operands case PPC_ID_ATTN: + case PPC_ID_CP_ABORT: case PPC_ID_DCCCI: case PPC_ID_ICCCI: case PPC_ID_ISYNC: case PPC_ID_LWSYNC: + case PPC_ID_MSGSYNC: case PPC_ID_NOP: case PPC_ID_PTESYNC: case PPC_ID_RFCI: @@ -4734,10 +6196,13 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_RFI: case PPC_ID_RFID: case PPC_ID_RFMCI: + case PPC_ID_SYNC: case PPC_ID_TLBIA: case PPC_ID_TLBSYNC: case PPC_ID_TRAP: + case PPC_ID_TRECHKPT: case PPC_ID_SLBIA: + case PPC_ID_SLBSYNC: case PPC_ID_XNOP: case PPC_ID_WAITIMPL: case PPC_ID_WAITRSV: @@ -4745,6 +6210,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; // rD + case PPC_ID_LNIA: case PPC_ID_MFBR0: case PPC_ID_MFBR1: case PPC_ID_MFBR2: @@ -4780,6 +6246,12 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushRS(instruction, word32); break; + // rA + case PPC_ID_TABORT: + case PPC_ID_TRECLAIM: + PushRA(instruction, word32); + break; + // rB case PPC_ID_TLBIEL: case PPC_ID_TLBLI: @@ -4808,9 +6280,17 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_ADDCx: case PPC_ID_ADDEx: case PPC_ID_DIVDx: + case PPC_ID_DIVDEx: + case PPC_ID_DIVDEUx: case PPC_ID_DIVDUx: case PPC_ID_DIVWx: + case PPC_ID_DIVWEx: + case PPC_ID_DIVWEUx: case PPC_ID_DIVWUx: + case PPC_ID_MODSD: + case PPC_ID_MODSW: + case PPC_ID_MODUD: + case PPC_ID_MODUW: case PPC_ID_MULHDx: case PPC_ID_MULHDUx: case PPC_ID_MULHWx: @@ -4836,6 +6316,9 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add // [.] rA, rS (logical) case PPC_ID_CNTLZWx: case PPC_ID_CNTLZDx: + case PPC_ID_CNTTZWx: + case PPC_ID_CNTTZDx: + case PPC_ID_POPCNTB: case PPC_ID_POPCNTD: case PPC_ID_POPCNTW: case PPC_ID_EXTSHx: @@ -4844,12 +6327,15 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushRA(instruction, word32); PushRS(instruction, word32); + // not all of these have RC bits, but it gets filtered + // at subop decode step instruction->flags.rc = word32 & 0x1; break; // [.] rA, rS, rB case PPC_ID_ANDx: case PPC_ID_ANDCx: + case PPC_ID_BPERMD: case PPC_ID_CMPB: case PPC_ID_ECIWX: case PPC_ID_ECOWX: @@ -4963,6 +6449,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add // crfD, rA, rB case PPC_ID_CMPD: + case PPC_ID_CMPEQB: case PPC_ID_CMPW: case PPC_ID_CMPLD: case PPC_ID_CMPLW: @@ -4996,6 +6483,8 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add } // rA, rB + case PPC_ID_COPY: + case PPC_ID_PASTE: case PPC_ID_TDEQ: case PPC_ID_TDGT: case PPC_ID_TDLGT: @@ -5018,6 +6507,8 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add // TO, rA, rB case PPC_ID_TD: case PPC_ID_TW: + case PPC_ID_TABORTDC: + case PPC_ID_TABORTWC: { uint32_t to = (word32 >> 21) & 0x1f; @@ -5063,6 +6554,19 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; } + // TO, rA, SIMM + case PPC_ID_TABORTDCI: + case PPC_ID_TABORTWCI: + { + uint32_t to = (word32 >> 21) & 0x1f; + int32_t simm = sign_extend((word32 >> 11) & 0x1f, 5); + + PushUIMMValue(instruction, to); + PushRA(instruction, word32); + PushSIMMValue(instruction, simm); + break; + } + // rD, rA, SIMM case PPC_ID_ADDI: case PPC_ID_MULLI: @@ -5117,10 +6621,10 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add } // rD, rA, rB (indexed load) + case PPC_ID_LBEPX: case PPC_ID_LBZCIX: case PPC_ID_LBZUX: case PPC_ID_LBZX: - case PPC_ID_LDARX: case PPC_ID_LDBRX: case PPC_ID_LDCIX: case PPC_ID_LDUX: @@ -5128,14 +6632,15 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_LHAUX: case PPC_ID_LHAX: case PPC_ID_LHBRX: + case PPC_ID_LHEPX: case PPC_ID_LHZCIX: case PPC_ID_LHZX: case PPC_ID_LHZUX: case PPC_ID_LSWX: case PPC_ID_LWAX: case PPC_ID_LWAUX: - case PPC_ID_LWARX: case PPC_ID_LWBRX: + case PPC_ID_LWEPX: case PPC_ID_LWZCIX: case PPC_ID_LWZUX: case PPC_ID_LWZX: @@ -5144,6 +6649,46 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushRB(instruction, word32); break; + // rD, rA, rB, [EH if nonzero] (indexed load) + case PPC_ID_LBARX: + case PPC_ID_LDARX: + case PPC_ID_LHARX: + case PPC_ID_LWARX: + { + PushRD(instruction, word32); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + uint32_t eh = word32 & 0x1; + // NOTE: this breaks with convention by only + // conditionally including EH + if (eh) + PushUIMMValue(instruction, word32 & 0x1); + break; + } + + // rD, rA, FC + case PPC_ID_LDAT: + case PPC_ID_LWAT: + { + uint32_t fc = (word32 >> 11) & 0x1f; + PushRD(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, fc); + break; + } + + // rS, rA, FC + case PPC_ID_STDAT: + case PPC_ID_STWAT: + { + uint32_t fc = (word32 >> 11) & 0x1f; + PushRS(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, fc); + break; + } + + // rS, d(RA) case PPC_ID_STB: case PPC_ID_STBU: @@ -5168,24 +6713,30 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add } // rS, rA, rB (indexed store) + case PPC_ID_STBCX: + case PPC_ID_STBCIX: + case PPC_ID_STBEPX: + case PPC_ID_STBUX: + case PPC_ID_STBX: case PPC_ID_STDBRX: case PPC_ID_STDCIX: + case PPC_ID_STDEPX: case PPC_ID_STDUX: case PPC_ID_STDX: - case PPC_ID_STBCIX: - case PPC_ID_STBUX: - case PPC_ID_STBX: case PPC_ID_STHBRX: case PPC_ID_STHCIX: + case PPC_ID_STHCX: + case PPC_ID_STHEPX: case PPC_ID_STHUX: case PPC_ID_STHX: case PPC_ID_STSWX: case PPC_ID_STWBRX: case PPC_ID_STWCIX: + case PPC_ID_STWEPX: case PPC_ID_STWUX: case PPC_ID_STWX: PushRS(instruction, word32); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; @@ -5193,7 +6744,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_STDCX: case PPC_ID_STWCX: PushRS(instruction, word32); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); instruction->flags.rc = 1; break; @@ -5208,6 +6759,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; // frD, rA, rB + case PPC_ID_LFDEPX: case PPC_ID_LFDUX: case PPC_ID_LFDX: case PPC_ID_LFIWAX: @@ -5215,7 +6767,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_LFSUX: case PPC_ID_LFSX: PushFRD(instruction, word32); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; @@ -5229,13 +6781,14 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; // frS, rA, rB + case PPC_ID_STFDEPX: case PPC_ID_STFDUX: case PPC_ID_STFDX: case PPC_ID_STFIWX: case PPC_ID_STFSUX: case PPC_ID_STFSX: PushFRS(instruction, word32); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; @@ -5267,11 +6820,18 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushCRBitB(instruction, word32); break; + // crbD case PPC_ID_CRCLR: case PPC_ID_CRSET: PushCRBitD(instruction, word32); break; + // crfS + case PPC_ID_MCRXRX: + case PPC_ID_TCHECK: + PushCRFD(instruction, word32); + break; + // conditional branches to registers case PPC_ID_BCLRx: case PPC_ID_BCCTRx: @@ -5331,13 +6891,15 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add // [.] frD, frB case PPC_ID_FABSx: case PPC_ID_FCFIDx: - case PPC_ID_FCFIDUx: - case PPC_ID_FCTIDUZx: case PPC_ID_FCFIDSx: + case PPC_ID_FCFIDUx: case PPC_ID_FCFIDUSx: case PPC_ID_FCTIDx: + case PPC_ID_FCTIDUx: + case PPC_ID_FCTIDUZx: case PPC_ID_FCTIDZx: case PPC_ID_FCTIWx: + case PPC_ID_FCTIWUx: case PPC_ID_FCTIWUZx: case PPC_ID_FCTIWZx: case PPC_ID_FMRx: @@ -5370,6 +6932,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add // rD, UIMM (special register) case PPC_ID_MFDCR: + case PPC_ID_MFPMR: case PPC_ID_MFSPR: case PPC_ID_MFTB: { @@ -5382,6 +6945,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add // UIMM, rS (special register) case PPC_ID_MTDCR: + case PPC_ID_MTPMR: case PPC_ID_MTSPR: { uint32_t special = GetSpecialRegisterCommon(word32); @@ -5394,15 +6958,18 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add // rA, rB (cache-related) case PPC_ID_DCBA: case PPC_ID_DCBST: - case PPC_ID_DCBF: + case PPC_ID_DCBSTEP: + case PPC_ID_DCBFL: + case PPC_ID_DCBFLP: case PPC_ID_DCBI: - case PPC_ID_DCBT: - case PPC_ID_DCBTST: + case PPC_ID_DCBTSTT: + case PPC_ID_DCBTT: case PPC_ID_DCBZ: + case PPC_ID_DCBZEP: case PPC_ID_DCBZL: case PPC_ID_ICBI: - // TODO: this should be PushRAor0 - PushRA(instruction, word32); + case PPC_ID_ICBIEP: + PushRAor0(instruction, word32); PushRB(instruction, word32); break; @@ -5416,6 +6983,49 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; } + // CT, rA, rB (cache-related) + case PPC_ID_ICBLC: + case PPC_ID_ICBLQ: + case PPC_ID_ICBTLS: + uint32_t ct = (word32 >> 21) & 0xf; + + PushUIMMValue(instruction, ct); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // TH, rA, rB (cache-related) + case PPC_ID_DCBTEP: + case PPC_ID_DCBTSTEP: + { + uint32_t th = (word32 >> 21) & 0x1f; + PushUIMMValue(instruction, th); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + } + + // rA, rB, TH + case PPC_ID_DCBT: + { + PushRAor0(instruction, word32); + PushRB(instruction, word32); + uint32_t th = (word32 >> 21) & 0x1f; + if (th != 0) + PushUIMMValue(instruction, th); + break; + } + + case PPC_ID_DCBTST: + { + PushRAor0(instruction, word32); + PushRB(instruction, word32); + uint32_t th = (word32 >> 21) & 0x1f; + if (th != 0) + PushUIMMValue(instruction, th); + break; + } + case PPC_ID_MTFSB0x: case PPC_ID_MTFSB1x: { @@ -5462,34 +7072,108 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); break; - case PPC_ID_ANDI: - // different from other logical immediates because of rc bit - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, word32 & 0xffff); - instruction->flags.rc = 1; + case PPC_ID_ADDPCIS: + { + PushRD(instruction, word32); + uint64_t d1 = (word32 >> 16) & 0x1f; + uint64_t d0 = (word32 >> 6) & 0x3ff; + uint64_t d2 = word32 & 0x1; + uint64_t d = (d0 << 6) | (d1 << 1) | d2; + PushUIMMValue(instruction, d); + break; + } + + case PPC_ID_ANDI: + // different from other logical immediates because of rc bit + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, word32 & 0xffff); + instruction->flags.rc = 1; + break; + + case PPC_ID_ANDIS: + // different from other logical shifted immediates because of rc bit + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, word32 & 0xffff); + + instruction->flags.rc = 1; + break; + + case PPC_ID_Bx: + { + instruction->flags.lk = word32 & 0x1; + instruction->flags.aa = (word32 & 0x2) != 0; + + uint64_t li = word32 & 0x03fffffc; + li = (uint64_t)(int64_t)sign_extend(li, 26); + uint64_t target = instruction->flags.aa ? li : address + li; + + PushLabel(instruction, target); + + break; + } + + case PPC_ID_CMPRB: + { + PushCRFD(instruction, word32); + + uint32_t l = (word32 >> 21) & 0x1; + PushUIMMValue(instruction, l); + + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + } + + case PPC_ID_DARN: + { + uint32_t l = (word32 >> 16) & 0x3; + PushRD(instruction, word32); + PushUIMMValue(instruction, l); + break; + } + + case PPC_ID_DCBF: + case PPC_ID_DCBFEP: + { + uint32_t l = (word32 >> 21) & 0x3; + PushRAor0(instruction, word32); + PushRB(instruction, word32); + if (l != 0) + PushUIMMValue(instruction, l); + break; + } - case PPC_ID_ANDIS: - // different from other logical shifted immediates because of rc bit + case PPC_ID_EXTSWSLIx: + { PushRA(instruction, word32); PushRS(instruction, word32); - PushUIMMValue(instruction, word32 & 0xffff); + uint32_t sh5 = (word32 >> 1) & 0x1; + uint32_t sh0_4 = (word32 >> 11) & 0x1f; + PushUIMMValue(instruction, (sh5 << 5) | sh0_4); - instruction->flags.rc = 1; + instruction->flags.rc = word32 & 0x1; break; + } - case PPC_ID_Bx: - { - instruction->flags.lk = word32 & 0x1; - instruction->flags.aa = (word32 & 0x2) != 0; - - uint64_t li = word32 & 0x03fffffc; - li = (uint64_t)(int64_t)sign_extend(li, 26); - uint64_t target = instruction->flags.aa ? li : address + li; + case PPC_ID_FTDIV: + PushCRFD(instruction, word32); + PushFRA(instruction, word32); + PushFRB(instruction, word32); + break; - PushLabel(instruction, target); + case PPC_ID_FTSQRT: + PushCRFD(instruction, word32); + PushFRB(instruction, word32); + break; + case PPC_ID_MFBHRBE: + { + uint32_t bhrbe = (word32 >> 11) & 0x3ff; + PushRD(instruction, word32); + PushUIMMValue(instruction, bhrbe); break; } @@ -5508,7 +7192,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add uint32_t ct = (word32 >> 21) & 0xf; PushUIMMValue(instruction, ct); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; @@ -5519,7 +7203,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add uint32_t bc = (word32 >> 6) & 0x1f; PushRD(instruction, word32); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); PushUIMMValue(instruction, bc); break; @@ -5555,10 +7239,34 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add } case PPC_ID_MFFSx: + case PPC_ID_MFFSCE: + case PPC_ID_MFFSL: PushFRD(instruction, word32); instruction->flags.rc = word32 & 0x1; break; + case PPC_ID_MFFSCDRN: + case PPC_ID_MFFSCRN: + PushFRD(instruction, word32); + PushFRB(instruction, word32); + break; + + case PPC_ID_MFFSCDRNI: + { + uint32_t drm = (word32 >> 11) & 0x7; + PushFRD(instruction, word32); + PushUIMMValue(instruction, drm); + break; + } + + case PPC_ID_MFFSCRNI: + { + uint32_t rm = (word32 >> 11) & 0x3; + PushFRD(instruction, word32); + PushUIMMValue(instruction, rm); + break; + } + case PPC_ID_MFSR: { uint32_t sr = (word32 >> 16) & 0xf; @@ -5677,12 +7385,19 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; } + case PPC_ID_SETB: + PushRD(instruction, word32); + PushCRFS(instruction, word32); + break; + case PPC_ID_SLBMFEE: + case PPC_ID_SLBMFEV: PushRD(instruction, word32); PushRB(instruction, word32); break; case PPC_ID_SLBMTE: + case PPC_ID_SLBIEG: PushRS(instruction, word32); PushRB(instruction, word32); break; @@ -5713,11 +7428,19 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; } - case PPC_ID_SYNC: + case PPC_ID_TBEGIN: { - uint32_t l = (word32 >> 21) & 0x3; + uint32_t r = (word32 >> 21) & 0x1; - PushUIMMValue(instruction, l); + PushUIMMValue(instruction, r); + break; + } + + case PPC_ID_TEND: + { + uint32_t a = (word32 >> 25) & 0x1; + + PushUIMMValue(instruction, a); break; } @@ -5731,6 +7454,14 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushRB(instruction, word32); break; + case PPC_ID_TSR: + { + uint32_t l = (word32 >> 21) & 0x1; + + PushUIMMValue(instruction, l); + break; + } + case PPC_ID_WAIT: { uint32_t wc = (word32 >> 21) & 0x3; @@ -5752,9 +7483,13 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add // ALTIVEC INSTRUCTIONS // vD, vA, vB, vC + case PPC_ID_AV_VADDECUQ: + case PPC_ID_AV_VADDEUQM: case PPC_ID_AV_VMHADDSHS: case PPC_ID_AV_VMHRADDSHS: case PPC_ID_AV_VMLADDUHM: + case PPC_ID_AV_VSUBECUQ: + case PPC_ID_AV_VSUBEUQM: case PPC_ID_AV_VMSUMMBM: case PPC_ID_AV_VMSUMUBM: case PPC_ID_AV_VMSUMSHM: @@ -5762,6 +7497,8 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_AV_VMSUMUHM: case PPC_ID_AV_VMSUMUHS: case PPC_ID_AV_VPERM: + case PPC_ID_AV_VPERMR: + case PPC_ID_AV_VPERMXOR: case PPC_ID_AV_VSEL: PushAltivecVD(instruction, word32); PushAltivecVA(instruction, word32); @@ -5779,6 +7516,14 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; // vD, vA, vB + case PPC_ID_AV_VABSDUB: + case PPC_ID_AV_VABSDUH: + case PPC_ID_AV_VABSDUW: + case PPC_ID_AV_VADDUQM: + case PPC_ID_AV_VADDCUQ: + case PPC_ID_AV_BCDUS: + case PPC_ID_AV_BCDUTRUNC: + case PPC_ID_AV_BCDCPSGN: case PPC_ID_AV_VADDCUW: case PPC_ID_AV_VADDFP: case PPC_ID_AV_VADDSBS: @@ -5799,6 +7544,10 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_AV_VAVGUB: case PPC_ID_AV_VAVGUH: case PPC_ID_AV_VAVGUW: + case PPC_ID_AV_VBPERMD: + case PPC_ID_AV_VBPERMQ: + case PPC_ID_AV_VCIPHER: + case PPC_ID_AV_VCIPHERLAST: case PPC_ID_AV_VEQV: case PPC_ID_AV_VMAXFP: case PPC_ID_AV_VMAXSB: @@ -5818,12 +7567,16 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_AV_VMINSD: case PPC_ID_AV_VMINSH: case PPC_ID_AV_VMINSW: + case PPC_ID_AV_VMRGEW: case PPC_ID_AV_VMRGHB: case PPC_ID_AV_VMRGHH: case PPC_ID_AV_VMRGHW: case PPC_ID_AV_VMRGLB: case PPC_ID_AV_VMRGLH: case PPC_ID_AV_VMRGLW: + case PPC_ID_AV_VMRGOW: + case PPC_ID_AV_VMUL10EUQ: + case PPC_ID_AV_VMUL10ECUQ: case PPC_ID_AV_VMULESB: case PPC_ID_AV_VMULESH: case PPC_ID_AV_VMULESW: @@ -5838,27 +7591,42 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_AV_VMULOUW: case PPC_ID_AV_VMULUWM: case PPC_ID_AV_VNAND: + case PPC_ID_AV_VNCIPHER: + case PPC_ID_AV_VNCIPHERLAST: case PPC_ID_AV_VNOR: case PPC_ID_AV_VOR: case PPC_ID_AV_VORC: case PPC_ID_AV_VPKPX: - case PPC_ID_AV_VPKSHUS: + case PPC_ID_AV_VPKSDSS: + case PPC_ID_AV_VPKSDUS: case PPC_ID_AV_VPKSHSS: + case PPC_ID_AV_VPKSHUS: case PPC_ID_AV_VPKSWSS: case PPC_ID_AV_VPKSWUS: + case PPC_ID_AV_VPKUDUM: + case PPC_ID_AV_VPKUDUS: case PPC_ID_AV_VPKUHUM: case PPC_ID_AV_VPKUHUS: case PPC_ID_AV_VPKUWUM: case PPC_ID_AV_VPKUWUS: + case PPC_ID_AV_VPMSUMB: + case PPC_ID_AV_VPMSUMD: + case PPC_ID_AV_VPMSUMH: + case PPC_ID_AV_VPMSUMW: case PPC_ID_AV_VRLB: case PPC_ID_AV_VRLD: + case PPC_ID_AV_VRLDMI: + case PPC_ID_AV_VRLDNM: case PPC_ID_AV_VRLH: case PPC_ID_AV_VRLW: + case PPC_ID_AV_VRLWMI: + case PPC_ID_AV_VRLWNM: case PPC_ID_AV_VSL: case PPC_ID_AV_VSLB: case PPC_ID_AV_VSLD: case PPC_ID_AV_VSLH: case PPC_ID_AV_VSLO: + case PPC_ID_AV_VSLV: case PPC_ID_AV_VSLW: case PPC_ID_AV_VSR: case PPC_ID_AV_VSRAB: @@ -5869,7 +7637,9 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_AV_VSRD: case PPC_ID_AV_VSRH: case PPC_ID_AV_VSRO: + case PPC_ID_AV_VSRV: case PPC_ID_AV_VSRW: + case PPC_ID_AV_VSUBCUQ: case PPC_ID_AV_VSUBCUW: case PPC_ID_AV_VSUBFP: case PPC_ID_AV_VSUBSBS: @@ -5877,6 +7647,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_AV_VSUBSWS: case PPC_ID_AV_VSUBUBS: case PPC_ID_AV_VSUBUHS: + case PPC_ID_AV_VSUBUQM: case PPC_ID_AV_VSUBUWS: case PPC_ID_AV_VSUBUBM: case PPC_ID_AV_VSUBUDM: @@ -5910,6 +7681,12 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_AV_VCMPGTUDx: case PPC_ID_AV_VCMPGTUHx: case PPC_ID_AV_VCMPGTUWx: + case PPC_ID_AV_VCMPNEBx: + case PPC_ID_AV_VCMPNEHx: + case PPC_ID_AV_VCMPNEWx: + case PPC_ID_AV_VCMPNEZBx: + case PPC_ID_AV_VCMPNEZHx: + case PPC_ID_AV_VCMPNEZWx: PushAltivecVD(instruction, word32); PushAltivecVA(instruction, word32); PushAltivecVB(instruction, word32); @@ -5917,17 +7694,44 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add instruction->flags.rc = (word32 >> 10) & 0x1; break; + // vD, vA + case PPC_ID_AV_VMUL10CUQ: + case PPC_ID_AV_VMUL10UQ: + case PPC_ID_AV_VSBOX: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + break; + // vD, vB + case PPC_ID_AV_BCDCTN: + case PPC_ID_AV_BCDCTSQ: case PPC_ID_AV_VCLZB: case PPC_ID_AV_VCLZD: case PPC_ID_AV_VCLZH: case PPC_ID_AV_VCLZW: + case PPC_ID_AV_VCTZB: + case PPC_ID_AV_VCTZD: + case PPC_ID_AV_VCTZH: + case PPC_ID_AV_VCTZW: case PPC_ID_AV_VEXPTEFP: + case PPC_ID_AV_VEXTSB2D: + case PPC_ID_AV_VEXTSB2W: + case PPC_ID_AV_VEXTSH2D: + case PPC_ID_AV_VEXTSH2W: + case PPC_ID_AV_VEXTSW2D: + case PPC_ID_AV_VGBBD: case PPC_ID_AV_VLOGEFP: + case PPC_ID_AV_VMR: + case PPC_ID_AV_VNEGD: + case PPC_ID_AV_VNEGW: + case PPC_ID_AV_VNOT: case PPC_ID_AV_VPOPCNTB: case PPC_ID_AV_VPOPCNTD: case PPC_ID_AV_VPOPCNTH: case PPC_ID_AV_VPOPCNTW: + case PPC_ID_AV_VPRTYBD: + case PPC_ID_AV_VPRTYBQ: + case PPC_ID_AV_VPRTYBW: case PPC_ID_AV_VREFP: case PPC_ID_AV_VRFIM: case PPC_ID_AV_VRFIN: @@ -5937,9 +7741,11 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_AV_VUPKHPX: case PPC_ID_AV_VUPKHSB: case PPC_ID_AV_VUPKHSH: + case PPC_ID_AV_VUPKHSW: case PPC_ID_AV_VUPKLPX: case PPC_ID_AV_VUPKLSB: case PPC_ID_AV_VUPKLSH: + case PPC_ID_AV_VUPKLSW: PushAltivecVD(instruction, word32); PushAltivecVB(instruction, word32); break; @@ -5978,7 +7784,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_AV_LVX: case PPC_ID_AV_LVXL: PushAltivecVD(instruction, word32); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; @@ -5989,7 +7795,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_AV_STVX: case PPC_ID_AV_STVXL: PushAltivecVS(instruction, word32); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; @@ -6031,6 +7837,89 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushUIMMValue(instruction, (word32 >> 6) & 0xf); break; + // rD, rA, rB, rC (normal registers) + case PPC_ID_AV_MADDHD: + case PPC_ID_AV_MADDHDU: + case PPC_ID_AV_MADDLD: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + PushRC(instruction, word32); + break; + + // vrD, vrA, vrB, ps + case PPC_ID_AV_BCDADD: + case PPC_ID_AV_BCDSUB: + case PPC_ID_AV_BCDS: + case PPC_ID_AV_BCDSR: + case PPC_ID_AV_BCDTRUNC: + { + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVB(instruction, word32); + uint32_t ps = (word32 & 0x200) != 0; + PushUIMMValue(instruction, ps); + break; + } + + + // vrD, vrB, ps + case PPC_ID_AV_BCDCFN: + case PPC_ID_AV_BCDCFZ: + case PPC_ID_AV_BCDCTZ: + case PPC_ID_AV_BCDCFSQ: + case PPC_ID_AV_BCDSETSGN: + // PS isn't in all of these instructions, but it gets + // filtered out in subop decode + PushAltivecVD(instruction, word32); + PushAltivecVB(instruction, word32); + uint32_t ps = (word32 & 0x200) != 0; + PushUIMMValue(instruction, ps); + break; + + + // vrD, vrB, UIM + case PPC_ID_AV_VEXTRACTD: + case PPC_ID_AV_VEXTRACTUB: + case PPC_ID_AV_VEXTRACTUH: + case PPC_ID_AV_VEXTRACTUW: + case PPC_ID_AV_VINSERTB: + case PPC_ID_AV_VINSERTD: + case PPC_ID_AV_VINSERTH: + case PPC_ID_AV_VINSERTW: + PushAltivecVD(instruction, word32); + PushAltivecVB(instruction, word32); + PushUIMMValue(instruction, (word32 >> 16) & 0xf); + break; + + // rD, rA, vB + case PPC_ID_AV_VEXTUBLX: + case PPC_ID_AV_VEXTUHLX: + case PPC_ID_AV_VEXTUWLX: + case PPC_ID_AV_VEXTUBRX: + case PPC_ID_AV_VEXTUHRX: + case PPC_ID_AV_VEXTUWRX: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushAltivecVB(instruction, word32); + break; + + // vD, vA, ST, SIX + case PPC_ID_AV_VSHASIGMAD: + case PPC_ID_AV_VSHASIGMAW: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushUIMMValue(instruction, (word32 >> 15) & 0x1); + PushUIMMValue(instruction, (word32 >> 11) & 0xf); + break; + + // rD, vB + case PPC_ID_AV_VCLZLSBB: + case PPC_ID_AV_VCTZLSBB: + PushRD(instruction, word32); + PushAltivecVB(instruction, word32); + break; + // VSX INSTRUCTIONS // vrD, vrA, vrB @@ -6040,6 +7929,8 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_VSX_XVCPSGNSP: case PPC_ID_VSX_XVDIVDP: case PPC_ID_VSX_XVDIVSP: + case PPC_ID_VSX_XVIEXPDP: + case PPC_ID_VSX_XVIEXPSP: case PPC_ID_VSX_XVMADDADP: case PPC_ID_VSX_XVMADDASP: case PPC_ID_VSX_XVMADDMDP: @@ -6076,6 +7967,7 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_VSX_XXMRGHW: case PPC_ID_VSX_XXMRGLD: case PPC_ID_VSX_XXMRGLW: + case PPC_ID_VSX_XXPERM: case PPC_ID_VSX_XXPERMR: PushVsxD(instruction, word32, VSX_WIDTH_FULL); PushVsxA(instruction, word32, VSX_WIDTH_FULL); @@ -6096,21 +7988,40 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; // vrD, vrA, vrB + case PPC_ID_VSX_XSADDSP: case PPC_ID_VSX_XSADDDP: + case PPC_ID_VSX_XSCMPEQDP: + case PPC_ID_VSX_XSCMPGEDP: + case PPC_ID_VSX_XSCMPGTDP: case PPC_ID_VSX_XSCPSGNDP: case PPC_ID_VSX_XSDIVDP: + case PPC_ID_VSX_XSDIVSP: case PPC_ID_VSX_XSMADDADP: case PPC_ID_VSX_XSMADDMDP: + case PPC_ID_VSX_XSMADDASP: + case PPC_ID_VSX_XSMADDMSP: + case PPC_ID_VSX_XSMAXCDP: case PPC_ID_VSX_XSMAXDP: + case PPC_ID_VSX_XSMAXJDP: + case PPC_ID_VSX_XSMINCDP: case PPC_ID_VSX_XSMINDP: + case PPC_ID_VSX_XSMINJDP: case PPC_ID_VSX_XSMSUBADP: + case PPC_ID_VSX_XSMSUBASP: case PPC_ID_VSX_XSMSUBMDP: + case PPC_ID_VSX_XSMSUBMSP: case PPC_ID_VSX_XSMULDP: + case PPC_ID_VSX_XSMULSP: case PPC_ID_VSX_XSNMADDADP: + case PPC_ID_VSX_XSNMADDASP: case PPC_ID_VSX_XSNMADDMDP: + case PPC_ID_VSX_XSNMADDMSP: case PPC_ID_VSX_XSNMSUBADP: + case PPC_ID_VSX_XSNMSUBASP: case PPC_ID_VSX_XSNMSUBMDP: + case PPC_ID_VSX_XSNMSUBMSP: case PPC_ID_VSX_XSSUBDP: + case PPC_ID_VSX_XSSUBSP: PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); PushVsxA(instruction, word32, VSX_WIDTH_DWORD0); PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); @@ -6159,20 +8070,34 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_VSX_XVSQRTDP: case PPC_ID_VSX_XVMOVDP: case PPC_ID_VSX_XVMOVSP: + case PPC_ID_VSX_XVXEXPDP: + case PPC_ID_VSX_XVXEXPSP: + case PPC_ID_VSX_XVXSIGDP: + case PPC_ID_VSX_XVXSIGSP: + case PPC_ID_VSX_XXBRD: + case PPC_ID_VSX_XXBRH: + case PPC_ID_VSX_XXBRQ: + case PPC_ID_VSX_XXBRW: PushVsxD(instruction, word32, VSX_WIDTH_FULL); PushVsxB(instruction, word32, VSX_WIDTH_FULL); break; - + // vrD, vrB case PPC_ID_VSX_XSABSDP: + case PPC_ID_VSX_XSCVDPHP: case PPC_ID_VSX_XSCVDPSXDS: case PPC_ID_VSX_XSCVDPSP: + case PPC_ID_VSX_XSCVDPSPN: case PPC_ID_VSX_XSCVDPSXWS: case PPC_ID_VSX_XSCVDPUXDS: case PPC_ID_VSX_XSCVDPUXWS: case PPC_ID_VSX_XSCVSPDP: + case PPC_ID_VSX_XSCVHPDP: + case PPC_ID_VSX_XSCVSPDPN: case PPC_ID_VSX_XSCVSXDDP: + case PPC_ID_VSX_XSCVSXDSP: case PPC_ID_VSX_XSCVUXDDP: + case PPC_ID_VSX_XSCVUXDSP: case PPC_ID_VSX_XSNABSDP: case PPC_ID_VSX_XSNEGDP: case PPC_ID_VSX_XSRDPI: @@ -6181,14 +8106,18 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add case PPC_ID_VSX_XSRDPIP: case PPC_ID_VSX_XSRDPIZ: case PPC_ID_VSX_XSREDP: + case PPC_ID_VSX_XSRESP: + case PPC_ID_VSX_XSRSP: + case PPC_ID_VSX_XSRSQRTESP: case PPC_ID_VSX_XSRSQRTEDP: case PPC_ID_VSX_XSSQRTDP: + case PPC_ID_VSX_XSSQRTSP: + case PPC_ID_VSX_XVCVHPSP: + case PPC_ID_VSX_XVCVSPHP: PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); break; - // - // vrD, vrA, vrB, case PPC_ID_VSX_XXPERMDI: case PPC_ID_VSX_XXSLDWI: @@ -6202,36 +8131,64 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; } + // vrD, rA, rB + case PPC_ID_VSX_MTVSRDD: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + // vrD, rA, rB (load indexed) + case PPC_ID_VSX_LXVB16X: case PPC_ID_VSX_LXVD2X: case PPC_ID_VSX_LXVDSX: + case PPC_ID_VSX_LXVH8X: + case PPC_ID_VSX_LXVL: + case PPC_ID_VSX_LXVLL: case PPC_ID_VSX_LXVW4X: + case PPC_ID_VSX_LXVWSX: + case PPC_ID_VSX_LXVX: PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; case PPC_ID_VSX_LXSDX: + case PPC_ID_VSX_LXSIBZX: + case PPC_ID_VSX_LXSIHZX: + case PPC_ID_VSX_LXSIWAX: + case PPC_ID_VSX_LXSIWZX: + case PPC_ID_VSX_LXSSPX: PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; // vrS, rA, rB (store indexed) + case PPC_ID_VSX_STXVB16X: case PPC_ID_VSX_STXVD2X: + case PPC_ID_VSX_STXVH8X: + case PPC_ID_VSX_STXVL: + case PPC_ID_VSX_STXVLL: case PPC_ID_VSX_STXVW4X: + case PPC_ID_VSX_STXVX: PushVsxS(instruction, word32, VSX_WIDTH_FULL); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; case PPC_ID_VSX_STXSDX: + case PPC_ID_VSX_STXSIBX: + case PPC_ID_VSX_STXSIHX: + case PPC_ID_VSX_STXSIWX: + case PPC_ID_VSX_STXSSPX: PushVsxS(instruction, word32, VSX_WIDTH_DWORD0); - PushRA(instruction, word32); + PushRAor0(instruction, word32); PushRB(instruction, word32); break; // crfD, vrA, vrB + case PPC_ID_VSX_XSCMPEXPDP: case PPC_ID_VSX_XSCMPODP: case PPC_ID_VSX_XSCMPUDP: case PPC_ID_VSX_XSTDIVDP: @@ -6260,6 +8217,198 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); break; + // vrD, rA + case PPC_ID_VSX_MTVSRWS: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushRA(instruction, word32); + break; + + case PPC_ID_VSX_MTVSRD: + case PPC_ID_VSX_MTVSRWA: + case PPC_ID_VSX_MTVSRWZ: + PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); + PushRA(instruction, word32); + break; + + // rA, vrS + case PPC_ID_VSX_MFVSRLD: + PushRA(instruction, word32); + PushVsxS(instruction, word32, VSX_WIDTH_FULL); + break; + + case PPC_ID_VSX_MFFPRD: + case PPC_ID_VSX_MFVSRWZ: + case PPC_ID_VSX_MFVSRD: + PushRA(instruction, word32); + PushVsxS(instruction, word32, VSX_WIDTH_DWORD0); + break; + + // vrD, vrB, UIM + case PPC_ID_VSX_XXINSERTW: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + PushUIMMValue(instruction, (word32 >> 16) & 0xf); + break; + + case PPC_ID_VSX_XXEXTRACTUW: + PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + PushUIMMValue(instruction, (word32 >> 16) & 0xf); + break; + + case PPC_ID_VSX_LXV: + { + uint32_t dx = (word32 >> 3) & 0x1; + uint32_t d = GetD(word32); + uint32_t vsxd = (dx << 5) | d; + + PushRegister(instruction, PPC_OP_REG_VSX_RD, VsxVr(vsxd)); + + uint32_t dq = (int32_t)((int16_t)(word32 & 0xfff0)); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), dq); + + break; + } + + case PPC_ID_VSX_STXV: + { + uint32_t sx = (word32 >> 3) & 0x1; + uint32_t s = GetS(word32); + uint32_t vsxs = (sx << 5) | s; + + PushRegister(instruction, PPC_OP_REG_VSX_RS, VsxVr(vsxs)); + + int32_t dq = (int32_t)((int16_t)(word32 & 0xfff0)); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), dq); + + break; + } + + case PPC_ID_VSX_STXSD: + case PPC_ID_VSX_STXSSP: + { + uint32_t xs = GetS(word32) + 32; + PushRegister(instruction, PPC_OP_REG_VSX_RS, VsxVr(xs)); + + int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); + break; + } + + // [o] vrdHi, vraHi, vrbHi + case PPC_ID_VSX_XSADDQPx: + case PPC_ID_VSX_XSCPSGNQP: + case PPC_ID_VSX_XSDIVQPx: + case PPC_ID_VSX_XSIEXPQP: + case PPC_ID_VSX_XSMADDQPx: + case PPC_ID_VSX_XSMSUBQPx: + case PPC_ID_VSX_XSMULQPx: + case PPC_ID_VSX_XSNMADDQPx: + case PPC_ID_VSX_XSNMSUBQPx: + case PPC_ID_VSX_XSSUBQPx: + { + PushVsxHiD(instruction, word32); + PushVsxHiA(instruction, word32); + PushVsxHiB(instruction, word32); + + instruction->flags.round2odd = word32 & 0x1; + break; + } + + case PPC_ID_VSX_XSABSQP: + case PPC_ID_VSX_XSCVQPUWZ: + case PPC_ID_VSX_XSCVUDQP: + case PPC_ID_VSX_XSNABSQP: + case PPC_ID_VSX_XSCVDPQP: + case PPC_ID_VSX_XSCVQPDPx: + case PPC_ID_VSX_XSCVQPSDZ: + case PPC_ID_VSX_XSCVQPSWZ: + case PPC_ID_VSX_XSCVQPUDZ: + case PPC_ID_VSX_XSCVSDQP: + case PPC_ID_VSX_XSNEGQP: + case PPC_ID_VSX_XSSQRTQPx: + case PPC_ID_VSX_XSXEXPQP: + case PPC_ID_VSX_XSXSIGQP: + { + PushVsxHiD(instruction, word32); + PushVsxHiB(instruction, word32); + + instruction->flags.round2odd = word32 & 0x1; + break; + } + + case PPC_ID_VSX_XSCMPEXPQP: + case PPC_ID_VSX_XSCMPOQP: + case PPC_ID_VSX_XSCMPUQP: + PushCRFD(instruction, word32); + PushVsxHiA(instruction, word32); + PushVsxHiB(instruction, word32); + + break; + + case PPC_ID_VSX_XSTSTDCQP: + { + uint32_t dcmx = (word32 >> 16) & 0x7f; + PushCRFD(instruction, word32); + PushVsxHiB(instruction, word32); + PushUIMMValue(instruction, dcmx); + break; + } + + // one-off VSX instructions + case PPC_ID_VSX_XSIEXPDP: + { + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + } + + case PPC_ID_VSX_XSRQPIx: + case PPC_ID_VSX_XSRQPXP: + { + uint32_t r = (word32 >> 16) & 0x1; + PushUIMMValue(instruction, r); + PushVsxHiD(instruction, word32); + PushVsxHiB(instruction, word32); + + uint32_t rmc = (word32 >> 9) & 0x3; + PushUIMMValue(instruction, rmc); + + instruction->flags.inexact = word32 & 0x1; + break; + } + + case PPC_ID_VSX_XSTSTDCDP: + case PPC_ID_VSX_XSTSTDCSP: + { + uint32_t dcmx = (word32 >> 16) & 0x7f; + PushCRFD(instruction, word32); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + PushUIMMValue(instruction, dcmx); + break; + } + + case PPC_ID_VSX_XSXEXPDP: + case PPC_ID_VSX_XSXSIGDP: + PushRD(instruction, word32); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + break; + + case PPC_ID_VSX_XVTSTDCDP: + case PPC_ID_VSX_XVTSTDCSP: + { + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + uint32_t dm = (word32 >> 2) & 0x1; + uint32_t dc = (word32 >> 6) & 0x1; + uint32_t dx = (word32 >> 16) & 0x1f; + uint32_t dcmx = (dc << 6) | (dm << 5) | dx; + PushUIMMValue(instruction, dcmx); + break; + } + + case PPC_ID_VSX_XXSPLTD: { uint32_t uimm = (word32 >> 8) & 0x3; @@ -6275,6 +8424,14 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add break; } + case PPC_ID_VSX_XXSPLTIB: + { + uint32_t uimm8 = (word32 >> 11) & 0xff; + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushUIMMValue(instruction, uimm8); + break; + } + case PPC_ID_VSX_XXSPLTW: { uint32_t um = (word32 >> 16) & 0x3; @@ -6706,6 +8863,20 @@ static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t add base "la+" \ }; +#define DEFINE_SUBMNEM_ROUND2ODD(_identifier, base) \ + const char* _identifier[2] = \ + { \ + base, \ + base "o", \ + }; + +#define DEFINE_SUBMNEM_INEXACT(_identifier, base) \ + const char* _identifier[2] = \ + { \ + base, \ + base "x", \ + }; + DEFINE_SUBMNEM_OE_RC(SubMnemADDx, "add") DEFINE_SUBMNEM_OE_RC(SubMnemADDCx, "addc") DEFINE_SUBMNEM_OE_RC(SubMnemADDEx, "adde") @@ -6766,14 +8937,21 @@ DEFINE_SUBMNEM_RC(SubMnemCLRLWIx, "clrlwi") DEFINE_SUBMNEM_RC(SubMnemCLRRWIx, "clrrwi") DEFINE_SUBMNEM_RC(SubMnemCNTLZDx, "cntlzd") DEFINE_SUBMNEM_RC(SubMnemCNTLZWx, "cntlzw") +DEFINE_SUBMNEM_RC(SubMnemCNTTZDx, "cnttzd") +DEFINE_SUBMNEM_RC(SubMnemCNTTZWx, "cnttzw") DEFINE_SUBMNEM_OE_RC(SubMnemDIVDx, "divd") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVDEx, "divde") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVDEUx, "divdeu") DEFINE_SUBMNEM_OE_RC(SubMnemDIVDUx, "divdu") DEFINE_SUBMNEM_OE_RC(SubMnemDIVWx, "divw") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVWEx, "divwe") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVWEUx, "divweu") DEFINE_SUBMNEM_OE_RC(SubMnemDIVWUx, "divwu") DEFINE_SUBMNEM_RC(SubMnemEQVx, "eqv") DEFINE_SUBMNEM_RC(SubMnemEXTSBx, "extsb") DEFINE_SUBMNEM_RC(SubMnemEXTSHx, "extsh") DEFINE_SUBMNEM_RC(SubMnemEXTSWx, "extsw") +DEFINE_SUBMNEM_RC(SubMnemEXTSWSLIx, "extswsli") DEFINE_SUBMNEM_RC(SubMnemFABSx, "fabs") DEFINE_SUBMNEM_RC(SubMnemFADDx, "fadd") DEFINE_SUBMNEM_RC(SubMnemFADDSx, "fadds") @@ -6783,9 +8961,11 @@ DEFINE_SUBMNEM_RC(SubMnemFCFIDUx, "fcfidu") DEFINE_SUBMNEM_RC(SubMnemFCFIDUSx, "fcfidus") DEFINE_SUBMNEM_RC(SubMnemFCPSGNx, "fcpsgn") DEFINE_SUBMNEM_RC(SubMnemFCTIDx, "fctid") +DEFINE_SUBMNEM_RC(SubMnemFCTIDUx, "fctidu") DEFINE_SUBMNEM_RC(SubMnemFCTIDUZx, "fctiduz") DEFINE_SUBMNEM_RC(SubMnemFCTIDZx, "fctidz") DEFINE_SUBMNEM_RC(SubMnemFCTIWx, "fctiw") +DEFINE_SUBMNEM_RC(SubMnemFCTIWUx, "fctiwu") DEFINE_SUBMNEM_RC(SubMnemFCTIWUZx, "fctiwuz") DEFINE_SUBMNEM_RC(SubMnemFCTIWZx, "fctiwz") DEFINE_SUBMNEM_RC(SubMnemFDIVx, "fdiv") @@ -6883,6 +9063,12 @@ DEFINE_SUBMNEM_RC(SubMnemVCMPGTUBx, "vcmpgtub"); DEFINE_SUBMNEM_RC(SubMnemVCMPGTUDx, "vcmpgtud"); DEFINE_SUBMNEM_RC(SubMnemVCMPGTUHx, "vcmpgtuh"); DEFINE_SUBMNEM_RC(SubMnemVCMPGTUWx, "vcmpgtuw"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEBx, "vcmpneb"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEHx, "vcmpneh"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEWx, "vcmpnew"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEZBx, "vcmpnezb"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEZHx, "vcmpnezh"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEZWx, "vcmpnezw"); // VSX MNEMONICS DEFINE_SUBMNEM_RC(SubMnemXVCMPEQDPx, "xvcmpeqdp"); @@ -6891,6 +9077,17 @@ DEFINE_SUBMNEM_RC(SubMnemXVCMPGEDPx, "xvcmpgedp"); DEFINE_SUBMNEM_RC(SubMnemXVCMPGESPx, "xvcmpgesp"); DEFINE_SUBMNEM_RC(SubMnemXVCMPGTDPx, "xvcmpgtdp"); DEFINE_SUBMNEM_RC(SubMnemXVCMPGTSPx, "xvcmpgtsp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSADDQPx, "xsaddqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSCVQPDPx, "xscvqpdp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSDIVQPx, "xsdivqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSMADDQPx, "xsmaddqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSMULQPx, "xsmulqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSMSUBQPx, "xsmsubqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSNMADDQPx, "xsnmaddqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSNMSUBQPx, "xsnmsubqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSSQRTQPx, "xssqrtqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSSUBQPx, "xssubqp"); +DEFINE_SUBMNEM_INEXACT(SubMnemXSRQPIx, "xsrqpi"); static const char* RcMnemonic(const Instruction* instruction, const char* names[2]) { @@ -6922,6 +9119,16 @@ static const char* AaLkHintMnemonic(const Instruction* instruction, const char* return names[4*instruction->flags.branchLikelyHint + 2*instruction->flags.aa + instruction->flags.lk]; } +static const char* Round2OddMnemonic(const Instruction* instruction, const char* names[2]) +{ + return names[instruction->flags.round2odd]; +} + +static const char* InexactMnemonic(const Instruction* instruction, const char* names[2]) +{ + return names[instruction->flags.inexact]; +} + void FillBcxOperands(OperandsList* bcx, const Instruction* instruction) { memset(bcx, 0, sizeof *bcx); @@ -7042,6 +9249,8 @@ void FillBclrxOperands(OperandsList* bclrx, const Instruction* instruction) case 8: case 10: CopyOperand(&bclrx->operands[0], &instruction->operands[1]); + bclrx->operands[0].cls = PPC_OP_CRBIT; + bclrx->operands[0].crbit = (uint32_t)instruction->operands[1].uimm; bclrx->numOperands = 1; break; @@ -7092,6 +9301,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_ADDICx: return RcMnemonic(instruction, SubMnemADDICx); case PPC_ID_ADDIS: return "addis"; case PPC_ID_ADDMEx: return OeRcMnemonic(instruction, SubMnemADDMEx); + case PPC_ID_ADDPCIS: return "addpcis"; case PPC_ID_ADDZEx: return OeRcMnemonic(instruction, SubMnemADDZEx); case PPC_ID_ANDx: return RcMnemonic(instruction, SubMnemANDx); case PPC_ID_ANDCx: return RcMnemonic(instruction, SubMnemANDCx); @@ -7328,12 +9538,16 @@ const char* GetMnemonic(const Instruction* instruction) } } + case PPC_ID_BPERMD: return "bpermd"; + case PPC_ID_CLRBHRB: return "clrbhrb"; case PPC_ID_CLRLDIx: return RcMnemonic(instruction, SubMnemCLRLDIx); case PPC_ID_CLRLWIx: return RcMnemonic(instruction, SubMnemCLRLWIx); case PPC_ID_CLRRWIx: return RcMnemonic(instruction, SubMnemCLRRWIx); case PPC_ID_CMPB: return "cmpb"; case PPC_ID_CMPD: return "cmpd"; case PPC_ID_CMPDI: return "cmpdi"; + case PPC_ID_CMPEQB: return "cmpeqb"; + case PPC_ID_CMPRB: return "cmprb"; case PPC_ID_CMPW: return "cmpw"; case PPC_ID_CMPWI: return "cmpwi"; case PPC_ID_CMPLD: return "cmpld"; @@ -7342,6 +9556,10 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_CMPLWI: return "cmplwi"; case PPC_ID_CNTLZDx: return RcMnemonic(instruction, SubMnemCNTLZDx); case PPC_ID_CNTLZWx: return RcMnemonic(instruction, SubMnemCNTLZWx); + case PPC_ID_CNTTZDx: return RcMnemonic(instruction, SubMnemCNTTZDx); + case PPC_ID_CNTTZWx: return RcMnemonic(instruction, SubMnemCNTTZWx); + case PPC_ID_COPY: return "copy"; + case PPC_ID_CP_ABORT: return "cp_abort"; case PPC_ID_CRAND: return "crand"; case PPC_ID_CRANDC: return "crandc"; case PPC_ID_CRCLR: return "crclr"; @@ -7354,19 +9572,33 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_CRORC: return "crorc"; case PPC_ID_CRSET: return "crset"; case PPC_ID_CRXOR: return "crxor"; + case PPC_ID_DARN: return "darn"; case PPC_ID_DCBA: return "dcba"; case PPC_ID_DCBF: return "dcbf"; + case PPC_ID_DCBFEP: return "dcbfep"; + case PPC_ID_DCBFL: return "dcbfl"; + case PPC_ID_DCBFLP: return "dcbflp"; case PPC_ID_DCBI: return "dcbi"; case PPC_ID_DCBST: return "dcbst"; + case PPC_ID_DCBSTEP: return "dcbstep"; case PPC_ID_DCBT: return "dcbt"; + case PPC_ID_DCBTT: return "dcbtt"; + case PPC_ID_DCBTEP: return "dcbtep"; case PPC_ID_DCBTST: return "dcbtst"; + case PPC_ID_DCBTSTEP: return "dcbtstep"; + case PPC_ID_DCBTSTT: return "dcbtstt"; case PPC_ID_DCBZ: return "dcbz"; + case PPC_ID_DCBZEP: return "dcbzep"; case PPC_ID_DCBZL: return "dcbzl"; case PPC_ID_DCCCI: return "dccci"; case PPC_ID_DCI: return "dci"; case PPC_ID_DIVDx: return OeRcMnemonic(instruction, SubMnemDIVDx); + case PPC_ID_DIVDEx: return OeRcMnemonic(instruction, SubMnemDIVDEx); + case PPC_ID_DIVDEUx: return OeRcMnemonic(instruction, SubMnemDIVDEUx); case PPC_ID_DIVDUx: return OeRcMnemonic(instruction, SubMnemDIVDUx); case PPC_ID_DIVWx: return OeRcMnemonic(instruction, SubMnemDIVWx); + case PPC_ID_DIVWEx: return OeRcMnemonic(instruction, SubMnemDIVWEx); + case PPC_ID_DIVWEUx: return OeRcMnemonic(instruction, SubMnemDIVWEUx); case PPC_ID_DIVWUx: return OeRcMnemonic(instruction, SubMnemDIVWUx); case PPC_ID_ECIWX: return "eciwx"; case PPC_ID_ECOWX: return "ecowx"; @@ -7375,6 +9607,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_EXTSBx: return RcMnemonic(instruction, SubMnemEXTSBx); case PPC_ID_EXTSHx: return RcMnemonic(instruction, SubMnemEXTSHx); case PPC_ID_EXTSWx: return RcMnemonic(instruction, SubMnemEXTSWx); + case PPC_ID_EXTSWSLIx: return RcMnemonic(instruction, SubMnemEXTSWSLIx); case PPC_ID_FABSx: return RcMnemonic(instruction, SubMnemFABSx); case PPC_ID_FADDx: return RcMnemonic(instruction, SubMnemFADDx); case PPC_ID_FADDSx: return RcMnemonic(instruction, SubMnemFADDSx); @@ -7386,9 +9619,11 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_FCMPU: return "fcmpu"; case PPC_ID_FCPSGNx: return RcMnemonic(instruction, SubMnemFCPSGNx); case PPC_ID_FCTIDx: return RcMnemonic(instruction, SubMnemFCTIDx); + case PPC_ID_FCTIDUx: return RcMnemonic(instruction, SubMnemFCTIDUx); case PPC_ID_FCTIDUZx: return RcMnemonic(instruction, SubMnemFCTIDUZx); case PPC_ID_FCTIDZx: return RcMnemonic(instruction, SubMnemFCTIDZx); case PPC_ID_FCTIWx: return RcMnemonic(instruction, SubMnemFCTIWx); + case PPC_ID_FCTIWUx: return RcMnemonic(instruction, SubMnemFCTIWUx); case PPC_ID_FCTIWUZx: return RcMnemonic(instruction, SubMnemFCTIWUZx); case PPC_ID_FCTIWZx: return RcMnemonic(instruction, SubMnemFCTIWZx); case PPC_ID_FDIVx: return RcMnemonic(instruction, SubMnemFDIVx); @@ -7420,18 +9655,27 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_FSQRTSx: return RcMnemonic(instruction, SubMnemFSQRTSx); case PPC_ID_FSUBx: return RcMnemonic(instruction, SubMnemFSUBx); case PPC_ID_FSUBSx: return RcMnemonic(instruction, SubMnemFSUBSx); + case PPC_ID_FTDIV: return "ftdiv"; + case PPC_ID_FTSQRT: return "ftsqrt"; case PPC_ID_ICBI: return "icbi"; + case PPC_ID_ICBIEP: return "icbiep"; + case PPC_ID_ICBLC: return "icblc"; + case PPC_ID_ICBLQ: return "icblq."; case PPC_ID_ICBT: return "icbt"; + case PPC_ID_ICBTLS: return "icbtls"; case PPC_ID_ICCCI: return "iccci"; case PPC_ID_ICI: return "ici"; case PPC_ID_ISEL: return "isel"; case PPC_ID_ISYNC: return "isync"; + case PPC_ID_LBARX: return "lbarx"; + case PPC_ID_LBEPX: return "lbepx"; case PPC_ID_LBZ: return "lbz"; case PPC_ID_LBZCIX: return "lbzcix"; case PPC_ID_LBZU: return "lbzu"; case PPC_ID_LBZUX: return "lbzux"; case PPC_ID_LBZX: return "lbzx"; case PPC_ID_LDARX: return "ldarx"; + case PPC_ID_LDAT: return "ldat"; case PPC_ID_LDBRX: return "ldbrx"; case PPC_ID_LDCIX: return "ldcix"; case PPC_ID_LD: return "ld"; @@ -7439,6 +9683,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_LDUX: return "ldux"; case PPC_ID_LDX: return "ldx"; case PPC_ID_LFD: return "lfd"; + case PPC_ID_LFDEPX: return "lfdepx"; case PPC_ID_LFDU: return "lfdu"; case PPC_ID_LFDUX: return "lfdux"; case PPC_ID_LFDX: return "lfdx"; @@ -7449,10 +9694,12 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_LFSUX: return "lfsux"; case PPC_ID_LFSX: return "lfsx"; case PPC_ID_LHA: return "lha"; + case PPC_ID_LHARX: return "lharx"; case PPC_ID_LHAU: return "lhau"; case PPC_ID_LHAUX: return "lhaux"; case PPC_ID_LHAX: return "lhax"; case PPC_ID_LHBRX: return "lhbrx"; + case PPC_ID_LHEPX: return "lhepx"; case PPC_ID_LHZ: return "lhz"; case PPC_ID_LHZCIX: return "lhzcix"; case PPC_ID_LHZU: return "lhzu"; @@ -7461,13 +9708,16 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_LI: return "li"; case PPC_ID_LIS: return "lis"; case PPC_ID_LMW: return "lmw"; + case PPC_ID_LNIA: return "lnia"; case PPC_ID_LSWI: return "lswi"; case PPC_ID_LSWX: return "lswx"; case PPC_ID_LWA: return "lwa"; + case PPC_ID_LWAT: return "lwat"; case PPC_ID_LWAX: return "lwax"; case PPC_ID_LWARX: return "lwarx"; case PPC_ID_LWAUX: return "lwaux"; case PPC_ID_LWBRX: return "lwbrx"; + case PPC_ID_LWEPX: return "lwepx"; case PPC_ID_LWSYNC: return "lwsync"; case PPC_ID_LWZ: return "lwz"; case PPC_ID_LWZCIX: return "lwzcix"; @@ -7478,6 +9728,8 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_MCRF: return "mcrf"; case PPC_ID_MCRFS: return "mcrfs"; case PPC_ID_MCRXR: return "mcrxr"; + case PPC_ID_MCRXRX: return "mcrxrx"; + case PPC_ID_MFBHRBE: return "mfbhrbe"; case PPC_ID_MFBR0: return "mfbr0"; case PPC_ID_MFBR1: return "mfbr1"; case PPC_ID_MFBR2: return "mfbr2"; @@ -7492,9 +9744,16 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_MFDCRUX: return "mfdcrux"; case PPC_ID_MFDCRX: return "mfdcrx"; case PPC_ID_MFFSx: return RcMnemonic(instruction, SubMnemMFFSx); + case PPC_ID_MFFSCDRN: return "mffscdrn"; + case PPC_ID_MFFSCDRNI: return "mffscdrni"; + case PPC_ID_MFFSCE: return "mffsce"; + case PPC_ID_MFFSCRN: return "mffscrn"; + case PPC_ID_MFFSCRNI: return "mffscrni"; + case PPC_ID_MFFSL: return "mffsl"; case PPC_ID_MFLR: return "mflr"; case PPC_ID_MFMSR: return "mfmsr"; case PPC_ID_MFOCRF: return "mfocrf"; + case PPC_ID_MFPMR: return "mfpmr"; case PPC_ID_MFSPR: return "mfspr"; case PPC_ID_MFSR: return "mfsr"; case PPC_ID_MFSRIN: return "mfsrin"; @@ -7502,6 +9761,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_MFTBU: return "mftbu"; case PPC_ID_MFXER: return "mfxer"; case PPC_ID_MRx: return RcMnemonic(instruction, SubMnemMRx); + case PPC_ID_MSGSYNC: return "msgsync"; case PPC_ID_MTAMR: return "mtamr"; case PPC_ID_MTBR0: return "mtbr0"; case PPC_ID_MTBR1: return "mtbr1"; @@ -7520,10 +9780,15 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_MTFSB1x: return RcMnemonic(instruction, SubMnemMTFSB1x); case PPC_ID_MTFSFx: return RcMnemonic(instruction, SubMnemMTFSFx); case PPC_ID_MTFSFIx: return RcMnemonic(instruction, SubMnemMTFSFIx); + case PPC_ID_MODSD: return "modsd"; + case PPC_ID_MODSW: return "modsw"; + case PPC_ID_MODUD: return "modud"; + case PPC_ID_MODUW: return "moduw"; case PPC_ID_MTLR: return "mtlr"; case PPC_ID_MTMSR: return "mtmsr"; case PPC_ID_MTMSRD: return "mtmsrd"; case PPC_ID_MTOCRF: return "mtocrf"; + case PPC_ID_MTPMR: return "mtpmr"; case PPC_ID_MTSPR: return "mtspr"; case PPC_ID_MTSR: return "mtsr"; case PPC_ID_MTSRIN: return "mtsrin"; @@ -7543,6 +9808,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_ORCx: return RcMnemonic(instruction, SubMnemORCx); case PPC_ID_ORI: return "ori"; case PPC_ID_ORIS: return "oris"; + case PPC_ID_PASTE: return "paste."; case PPC_ID_POPCNTB: return "popcntb"; case PPC_ID_POPCNTD: return "popcntd"; case PPC_ID_POPCNTW: return "popcntw"; @@ -7566,10 +9832,14 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_ROTLWx: return RcMnemonic(instruction, SubMnemROTLWx); case PPC_ID_ROTLWIx: return RcMnemonic(instruction, SubMnemROTLWIx); case PPC_ID_SC: return "sc"; + case PPC_ID_SETB: return "setb"; case PPC_ID_SLBIA: return "slbia"; case PPC_ID_SLBIE: return "slbie"; + case PPC_ID_SLBIEG: return "slbieg"; case PPC_ID_SLBMFEE: return "slbmfee"; + case PPC_ID_SLBMFEV: return "slbmfev"; case PPC_ID_SLBMTE: return "slbmte"; + case PPC_ID_SLBSYNC: return "slbsync"; case PPC_ID_SLDx: return RcMnemonic(instruction, SubMnemSLDx); case PPC_ID_SLDIx: return RcMnemonic(instruction, SubMnemSLDIx); case PPC_ID_SLWx: return RcMnemonic(instruction, SubMnemSLWx); @@ -7583,18 +9853,23 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_SRWx: return RcMnemonic(instruction, SubMnemSRWx); case PPC_ID_SRWIx: return RcMnemonic(instruction, SubMnemSRWIx); case PPC_ID_STB: return "stb"; + case PPC_ID_STBCIX: return "stbcix"; + case PPC_ID_STBCX: return "stbcx."; + case PPC_ID_STBEPX: return "stbepx"; case PPC_ID_STBU: return "stbu"; case PPC_ID_STBUX: return "stbux"; case PPC_ID_STBX: return "stbx"; - case PPC_ID_STBCIX: return "stbcix"; case PPC_ID_STD: return "std"; + case PPC_ID_STDAT: return "stdat"; case PPC_ID_STDBRX: return "stdbrx"; case PPC_ID_STDCIX: return "stdcix"; case PPC_ID_STDCX: return "stdcx."; + case PPC_ID_STDEPX: return "stdepx"; case PPC_ID_STDU: return "stdu"; case PPC_ID_STDUX: return "stdux"; case PPC_ID_STDX: return "stdx"; case PPC_ID_STFD: return "stfd"; + case PPC_ID_STFDEPX: return "stfdepx"; case PPC_ID_STFDU: return "stfdu"; case PPC_ID_STFDUX: return "stfdux"; case PPC_ID_STFDX: return "stfdx"; @@ -7606,6 +9881,8 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_STH: return "sth"; case PPC_ID_STHBRX: return "sthbrx"; case PPC_ID_STHCIX: return "sthcix"; + case PPC_ID_STHCX: return "sthcx."; + case PPC_ID_STHEPX: return "sthepx"; case PPC_ID_STHU: return "sthu"; case PPC_ID_STHUX: return "sthux"; case PPC_ID_STHX: return "sthx"; @@ -7613,9 +9890,11 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_STSWI: return "stswi"; case PPC_ID_STSWX: return "stswx"; case PPC_ID_STW: return "stw"; + case PPC_ID_STWAT: return "stwat"; case PPC_ID_STWBRX: return "stwbrx"; case PPC_ID_STWCIX: return "stwcix"; case PPC_ID_STWCX: return "stwcx."; + case PPC_ID_STWEPX: return "stwepx"; case PPC_ID_STWU: return "stwu"; case PPC_ID_STWUX: return "stwux"; case PPC_ID_STWX: return "stwx"; @@ -7626,6 +9905,13 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_SUBFMEx: return OeRcMnemonic(instruction, SubMnemSUBFMEx); case PPC_ID_SUBFZEx: return OeRcMnemonic(instruction, SubMnemSUBFZEx); case PPC_ID_SYNC: return "sync"; + case PPC_ID_TABORT: return "tabort."; + case PPC_ID_TABORTDC: return "tabortdc."; + case PPC_ID_TABORTDCI: return "tabortdci."; + case PPC_ID_TABORTWC: return "tabortwc."; + case PPC_ID_TABORTWCI: return "tabortwci."; + case PPC_ID_TBEGIN: return "tbegin."; + case PPC_ID_TCHECK: return "tcheck"; case PPC_ID_TD: return "td"; case PPC_ID_TDEQ: return "tdeq"; case PPC_ID_TDEQI: return "tdeqi"; @@ -7642,6 +9928,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_TDNEI: return "tdnei"; case PPC_ID_TDU: return "tdu"; case PPC_ID_TDUI: return "tdui"; + case PPC_ID_TEND: return "tend."; case PPC_ID_TLBIA: return "tlbia"; case PPC_ID_TLBIE: return "tlbie"; case PPC_ID_TLBIEL: return "tlbiel"; @@ -7656,6 +9943,9 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_TLBWEHI: return "tlbwehi"; case PPC_ID_TLBWELO: return "tlbwelo"; case PPC_ID_TRAP: return "trap"; + case PPC_ID_TRECHKPT: return "trechkpt."; + case PPC_ID_TRECLAIM: return "treclaim."; + case PPC_ID_TSR: return "tsr."; case PPC_ID_TW: return "tw"; case PPC_ID_TWEQ: return "tweq"; case PPC_ID_TWEQI: return "tweqi"; @@ -7685,6 +9975,26 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_XORI: return "xori"; case PPC_ID_XORIS: return "xoris"; + case PPC_ID_AV_VABSDUB: return "vabsdub"; + case PPC_ID_AV_VABSDUH: return "vabsduh"; + case PPC_ID_AV_VABSDUW: return "vabsduw"; + case PPC_ID_AV_VADDUQM: return "vadduqm"; + case PPC_ID_AV_VADDCUQ: return "vaddcuq"; + case PPC_ID_AV_BCDADD: return "bcdadd."; + case PPC_ID_AV_BCDCFN: return "bcdcfn."; + case PPC_ID_AV_BCDCFSQ: return "bcdcfsq."; + case PPC_ID_AV_BCDCFZ: return "bcdcfz."; + case PPC_ID_AV_BCDCPSGN: return "bcdcpsgn."; + case PPC_ID_AV_BCDCTN: return "bcdctn."; + case PPC_ID_AV_BCDCTSQ: return "bcdctsq."; + case PPC_ID_AV_BCDCTZ: return "bcdctz."; + case PPC_ID_AV_BCDS: return "bcds."; + case PPC_ID_AV_BCDSETSGN: return "bcdsetsgn."; + case PPC_ID_AV_BCDSR: return "bcdsr."; + case PPC_ID_AV_BCDSUB: return "bcdsub."; + case PPC_ID_AV_BCDTRUNC: return "bcdtrunc."; + case PPC_ID_AV_BCDUS: return "bcdus."; + case PPC_ID_AV_BCDUTRUNC: return "bcdutrunc."; case PPC_ID_AV_DSS: return "dss"; case PPC_ID_AV_DSSALL: return "dssall"; case PPC_ID_AV_DST: return "dst"; @@ -7698,6 +10008,9 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_LVSR: return "lvsr"; case PPC_ID_AV_LVX: return "lvx"; case PPC_ID_AV_LVXL: return "lvxl"; + case PPC_ID_AV_MADDHD: return "maddhd"; + case PPC_ID_AV_MADDHDU: return "maddhdu"; + case PPC_ID_AV_MADDLD: return "maddld"; case PPC_ID_AV_MFVSCR: return "mfvscr"; case PPC_ID_AV_MTVSCR: return "mtvscr"; case PPC_ID_AV_STVEBX: return "stvebx"; @@ -7706,6 +10019,8 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_STVX: return "stvx"; case PPC_ID_AV_STVXL: return "stvxl"; case PPC_ID_AV_VADDCUW: return "vaddcuw"; + case PPC_ID_AV_VADDECUQ: return "vaddecuq"; + case PPC_ID_AV_VADDEUQM: return "vaddeuqm"; case PPC_ID_AV_VADDFP: return "vaddfp"; case PPC_ID_AV_VADDSBS: return "vaddsbs"; case PPC_ID_AV_VADDSHS: return "vaddshs"; @@ -7725,11 +10040,16 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_VAVGUB: return "vavgub"; case PPC_ID_AV_VAVGUH: return "vavguh"; case PPC_ID_AV_VAVGUW: return "vavguw"; + case PPC_ID_AV_VBPERMD: return "vbpermd"; + case PPC_ID_AV_VBPERMQ: return "vbpermq"; case PPC_ID_AV_VCFSX: return "vcfsx"; case PPC_ID_AV_VCFUX: return "vcfux"; + case PPC_ID_AV_VCIPHER: return "vcipher"; + case PPC_ID_AV_VCIPHERLAST: return "vcipherlast"; case PPC_ID_AV_VCLZB: return "vclzb"; case PPC_ID_AV_VCLZD: return "vclzd"; case PPC_ID_AV_VCLZH: return "vclzh"; + case PPC_ID_AV_VCLZLSBB: return "vclzlsbb"; case PPC_ID_AV_VCLZW: return "vclzw"; case PPC_ID_AV_VCMPBFPx: return RcMnemonic(instruction, SubMnemVCMPBFPx); case PPC_ID_AV_VCMPEQFPx: return RcMnemonic(instruction, SubMnemVCMPEQFPx); @@ -7747,10 +10067,41 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_VCMPGTUDx: return RcMnemonic(instruction, SubMnemVCMPGTUDx); case PPC_ID_AV_VCMPGTUHx: return RcMnemonic(instruction, SubMnemVCMPGTUHx); case PPC_ID_AV_VCMPGTUWx: return RcMnemonic(instruction, SubMnemVCMPGTUWx); + case PPC_ID_AV_VCMPNEBx: return RcMnemonic(instruction, SubMnemVCMPNEBx); + case PPC_ID_AV_VCMPNEHx: return RcMnemonic(instruction, SubMnemVCMPNEHx); + case PPC_ID_AV_VCMPNEWx: return RcMnemonic(instruction, SubMnemVCMPNEWx); + case PPC_ID_AV_VCMPNEZBx: return RcMnemonic(instruction, SubMnemVCMPNEZBx); + case PPC_ID_AV_VCMPNEZHx: return RcMnemonic(instruction, SubMnemVCMPNEZHx); + case PPC_ID_AV_VCMPNEZWx: return RcMnemonic(instruction, SubMnemVCMPNEZWx); case PPC_ID_AV_VCTSXS: return "vctsxs"; case PPC_ID_AV_VCTUXS: return "vctuxs"; + case PPC_ID_AV_VCTZB: return "vctzb"; + case PPC_ID_AV_VCTZD: return "vctzd"; + case PPC_ID_AV_VCTZH: return "vctzh"; + case PPC_ID_AV_VCTZLSBB: return "vctzlsbb"; + case PPC_ID_AV_VCTZW: return "vctzw"; case PPC_ID_AV_VEQV: return "veqv"; case PPC_ID_AV_VEXPTEFP: return "vexptefp"; + case PPC_ID_AV_VEXTRACTD: return "vextractd"; + case PPC_ID_AV_VEXTRACTUB: return "vextractub"; + case PPC_ID_AV_VEXTRACTUH: return "vextractuh"; + case PPC_ID_AV_VEXTRACTUW: return "vextractuw"; + case PPC_ID_AV_VEXTSB2D: return "vextsb2d"; + case PPC_ID_AV_VEXTSB2W: return "vextsb2w"; + case PPC_ID_AV_VEXTSH2D: return "vextsh2d"; + case PPC_ID_AV_VEXTSH2W: return "vextsh2w"; + case PPC_ID_AV_VEXTSW2D: return "vextsw2d"; + case PPC_ID_AV_VEXTUBLX: return "vextublx"; + case PPC_ID_AV_VEXTUHLX: return "vextuhlx"; + case PPC_ID_AV_VEXTUWLX: return "vextuwlx"; + case PPC_ID_AV_VEXTUBRX: return "vextubrx"; + case PPC_ID_AV_VEXTUHRX: return "vextuhrx"; + case PPC_ID_AV_VEXTUWRX: return "vextuwrx"; + case PPC_ID_AV_VGBBD: return "vgbbd"; + case PPC_ID_AV_VINSERTB: return "vinsertb"; + case PPC_ID_AV_VINSERTD: return "vinsertd"; + case PPC_ID_AV_VINSERTH: return "vinserth"; + case PPC_ID_AV_VINSERTW: return "vinsertw"; case PPC_ID_AV_VLOGEFP: return "vlogefp"; case PPC_ID_AV_VMADDFP: return "vmaddfp"; case PPC_ID_AV_VMAXFP: return "vmaxfp"; @@ -7774,18 +10125,25 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_VMINUH: return "vminuh"; case PPC_ID_AV_VMINUW: return "vminuw"; case PPC_ID_AV_VMLADDUHM: return "vmladduhm"; + case PPC_ID_AV_VMR: return "vmr"; + case PPC_ID_AV_VMRGEW: return "vmrgew"; case PPC_ID_AV_VMRGHB: return "vmrghb"; case PPC_ID_AV_VMRGHH: return "vmrghh"; case PPC_ID_AV_VMRGHW: return "vmrghw"; case PPC_ID_AV_VMRGLB: return "vmrglb"; case PPC_ID_AV_VMRGLH: return "vmrglh"; case PPC_ID_AV_VMRGLW: return "vmrglw"; + case PPC_ID_AV_VMRGOW: return "vmrgow"; case PPC_ID_AV_VMSUMMBM: return "vmsummbm"; case PPC_ID_AV_VMSUMSHM: return "vmsumshm"; case PPC_ID_AV_VMSUMSHS: return "vmsumshs"; case PPC_ID_AV_VMSUMUBM: return "vmsumubm"; case PPC_ID_AV_VMSUMUHM: return "vmsumuhm"; case PPC_ID_AV_VMSUMUHS: return "vmsumuhs"; + case PPC_ID_AV_VMUL10CUQ: return "vmul10cuq"; + case PPC_ID_AV_VMUL10EUQ: return "vmul10euq"; + case PPC_ID_AV_VMUL10ECUQ: return "vmul10ecuq"; + case PPC_ID_AV_VMUL10UQ: return "vmul10uq"; case PPC_ID_AV_VMULESB: return "vmulesb"; case PPC_ID_AV_VMULESH: return "vmulesh"; case PPC_ID_AV_VMULESW: return "vmulesw"; @@ -7800,24 +10158,42 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_VMULOUW: return "vmulouw"; case PPC_ID_AV_VMULUWM: return "vmuluwm"; case PPC_ID_AV_VNAND: return "vnand"; + case PPC_ID_AV_VNCIPHER: return "vncipher"; + case PPC_ID_AV_VNCIPHERLAST: return "vncipherlast"; case PPC_ID_AV_VNMSUBFP: return "vnmsubfp"; + case PPC_ID_AV_VNEGD: return "vnegd"; + case PPC_ID_AV_VNEGW: return "vnegw"; case PPC_ID_AV_VNOR: return "vnor"; + case PPC_ID_AV_VNOT: return "vnot"; case PPC_ID_AV_VOR: return "vor"; case PPC_ID_AV_VORC: return "vorc"; case PPC_ID_AV_VPERM: return "vperm"; + case PPC_ID_AV_VPERMR: return "vpermr"; + case PPC_ID_AV_VPERMXOR: return "vpermxor"; case PPC_ID_AV_VPKPX: return "vpkpx"; + case PPC_ID_AV_VPKSDSS: return "vpksdss"; + case PPC_ID_AV_VPKSDUS: return "vpksdus"; case PPC_ID_AV_VPKSHSS: return "vpkshss"; case PPC_ID_AV_VPKSHUS: return "vpkshus"; case PPC_ID_AV_VPKSWSS: return "vpkswss"; case PPC_ID_AV_VPKSWUS: return "vpkswus"; + case PPC_ID_AV_VPKUDUM: return "vpkudum"; + case PPC_ID_AV_VPKUDUS: return "vpkudus"; case PPC_ID_AV_VPKUHUM: return "vpkuhum"; case PPC_ID_AV_VPKUHUS: return "vpkuhus"; case PPC_ID_AV_VPKUWUM: return "vpkuwum"; case PPC_ID_AV_VPKUWUS: return "vpkuwus"; + case PPC_ID_AV_VPMSUMB: return "vpmsumb"; + case PPC_ID_AV_VPMSUMD: return "vpmsumd"; + case PPC_ID_AV_VPMSUMH: return "vpmsumh"; + case PPC_ID_AV_VPMSUMW: return "vpmsumw"; case PPC_ID_AV_VPOPCNTB: return "vpopcntb"; case PPC_ID_AV_VPOPCNTD: return "vpopcntd"; case PPC_ID_AV_VPOPCNTH: return "vpopcnth"; case PPC_ID_AV_VPOPCNTW: return "vpopcntw"; + case PPC_ID_AV_VPRTYBD: return "vprtybd"; + case PPC_ID_AV_VPRTYBQ: return "vprtybq"; + case PPC_ID_AV_VPRTYBW: return "vprtybw"; case PPC_ID_AV_VREFP: return "vrefp"; case PPC_ID_AV_VRFIM: return "vrfim"; case PPC_ID_AV_VRFIN: return "vrfin"; @@ -7825,16 +10201,24 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_VRFIZ: return "vrfiz"; case PPC_ID_AV_VRLB: return "vrlb"; case PPC_ID_AV_VRLD: return "vrld"; + case PPC_ID_AV_VRLDNM: return "vrldnm"; + case PPC_ID_AV_VRLDMI: return "vrldmi"; case PPC_ID_AV_VRLH: return "vrlh"; case PPC_ID_AV_VRLW: return "vrlw"; + case PPC_ID_AV_VRLWMI: return "vrlwmi"; + case PPC_ID_AV_VRLWNM: return "vrlwnm"; case PPC_ID_AV_VRSQRTEFP: return "vrsqrtefp"; + case PPC_ID_AV_VSBOX: return "vsbox"; case PPC_ID_AV_VSEL: return "vsel"; + case PPC_ID_AV_VSHASIGMAD: return "vshasigmad"; + case PPC_ID_AV_VSHASIGMAW: return "vshasigmaw"; case PPC_ID_AV_VSL: return "vsl"; case PPC_ID_AV_VSLB: return "vslb"; case PPC_ID_AV_VSLD: return "vsld"; case PPC_ID_AV_VSLDOI: return "vsldoi"; case PPC_ID_AV_VSLH: return "vslh"; case PPC_ID_AV_VSLO: return "vslo"; + case PPC_ID_AV_VSLV: return "vslv"; case PPC_ID_AV_VSLW: return "vslw"; case PPC_ID_AV_VSPLTB: return "vspltb"; case PPC_ID_AV_VSPLTH: return "vsplth"; @@ -7851,8 +10235,12 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_VSRD: return "vsrd"; case PPC_ID_AV_VSRH: return "vsrh"; case PPC_ID_AV_VSRO: return "vsro"; + case PPC_ID_AV_VSRV: return "vsrv"; case PPC_ID_AV_VSRW: return "vsrw"; + case PPC_ID_AV_VSUBCUQ: return "vsubcuq"; case PPC_ID_AV_VSUBCUW: return "vsubcuw"; + case PPC_ID_AV_VSUBECUQ: return "vsubecuq"; + case PPC_ID_AV_VSUBEUQM: return "vsubeuqm"; case PPC_ID_AV_VSUBFP: return "vsubfp"; case PPC_ID_AV_VSUBSBS: return "vsubsbs"; case PPC_ID_AV_VSUBSHS: return "vsubshs"; @@ -7862,6 +10250,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_VSUBUDM: return "vsubudm"; case PPC_ID_AV_VSUBUHM: return "vsubuhm"; case PPC_ID_AV_VSUBUHS: return "vsubuhs"; + case PPC_ID_AV_VSUBUQM: return "vsubuqm"; case PPC_ID_AV_VSUBUWM: return "vsubuwm"; case PPC_ID_AV_VSUBUWS: return "vsubuws"; case PPC_ID_AV_VSUMSWS: return "vsumsws"; @@ -7872,64 +10261,129 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_VUPKHPX: return "vupkhpx"; case PPC_ID_AV_VUPKHSB: return "vupkhsb"; case PPC_ID_AV_VUPKHSH: return "vupkhsh"; + case PPC_ID_AV_VUPKHSW: return "vupkhsw"; case PPC_ID_AV_VUPKLPX: return "vupklpx"; case PPC_ID_AV_VUPKLSB: return "vupklsb"; case PPC_ID_AV_VUPKLSH: return "vupklsh"; + case PPC_ID_AV_VUPKLSW: return "vupklsw"; case PPC_ID_AV_VXOR: return "vxor"; case PPC_ID_VSX_LXSDX: return "lxsdx"; + case PPC_ID_VSX_LXSIBZX: return "lxsibzx"; + case PPC_ID_VSX_LXSIHZX: return "lxsihzx"; case PPC_ID_VSX_LXSIWAX: return "lxsiwax"; case PPC_ID_VSX_LXSIWZX: return "lxsiwzx"; case PPC_ID_VSX_LXSSPX: return "lxsspx"; + case PPC_ID_VSX_LXV: return "lxv"; + case PPC_ID_VSX_LXVB16X: return "lxvb16x"; case PPC_ID_VSX_LXVD2X: return "lxvd2x"; case PPC_ID_VSX_LXVDSX: return "lxvdsx"; + case PPC_ID_VSX_LXVH8X: return "lxvh8x"; + case PPC_ID_VSX_LXVL: return "lxvl"; + case PPC_ID_VSX_LXVLL: return "lxvll"; case PPC_ID_VSX_LXVW4X: return "lxvw4x"; + case PPC_ID_VSX_LXVWSX: return "lxvwsx"; + case PPC_ID_VSX_LXVX: return "lxvx"; + case PPC_ID_VSX_MFFPRD: return "mffprd"; + case PPC_ID_VSX_MFVSRD: return "mfvsrd"; + case PPC_ID_VSX_MFVSRLD: return "mfvsrld"; + case PPC_ID_VSX_MFVSRWZ: return "mfvsrwz"; + case PPC_ID_VSX_MTVSRD: return "mtvsrd"; + case PPC_ID_VSX_MTVSRDD: return "mtvsrdd"; + case PPC_ID_VSX_MTVSRWA: return "mtvsrwa"; + case PPC_ID_VSX_MTVSRWS: return "mtvsrws"; + case PPC_ID_VSX_MTVSRWZ: return "mtvsrwz"; + case PPC_ID_VSX_STXSD: return "stxsd"; case PPC_ID_VSX_STXSDX: return "stxsdx"; + case PPC_ID_VSX_STXSIBX: return "stxsibx"; + case PPC_ID_VSX_STXSIHX: return "stxsihx"; case PPC_ID_VSX_STXSIWX: return "stxsiwx"; + case PPC_ID_VSX_STXSSP: return "stxssp"; case PPC_ID_VSX_STXSSPX: return "stxsspx"; + case PPC_ID_VSX_STXVB16X: return "stxvb16x"; case PPC_ID_VSX_STXVD2X: return "stxvd2x"; + case PPC_ID_VSX_STXVH8X: return "stxvh8x"; + case PPC_ID_VSX_STXV: return "stxv"; + case PPC_ID_VSX_STXVL: return "stxvl"; + case PPC_ID_VSX_STXVLL: return "stxvll"; case PPC_ID_VSX_STXVW4X: return "stxvw4x"; + case PPC_ID_VSX_STXVX: return "stxvx"; case PPC_ID_VSX_XSABSDP: return "xsabsdp"; + case PPC_ID_VSX_XSABSQP: return "xsabsqp"; case PPC_ID_VSX_XSADDDP: return "xsadddp"; case PPC_ID_VSX_XSADDSP: return "xsaddsp"; + case PPC_ID_VSX_XSADDQPx: return Round2OddMnemonic(instruction, SubMnemXSADDQPx); + case PPC_ID_VSX_XSCMPEQDP: return "xscmpeqdp"; + case PPC_ID_VSX_XSCMPEXPDP: return "xscmpexpdp"; + case PPC_ID_VSX_XSCMPEXPQP: return "xscmpexpqp"; + case PPC_ID_VSX_XSCMPGEDP: return "xscmpgedp"; + case PPC_ID_VSX_XSCMPGTDP: return "xscmpgtdp"; case PPC_ID_VSX_XSCMPODP: return "xscmpodp"; + case PPC_ID_VSX_XSCMPOQP: return "xscmpoqp"; case PPC_ID_VSX_XSCMPUDP: return "xscmpudp"; + case PPC_ID_VSX_XSCMPUQP: return "xscmpuqp"; case PPC_ID_VSX_XSCPSGNDP: return "xscpsgndp"; + case PPC_ID_VSX_XSCPSGNQP: return "xscpsgnqp"; + case PPC_ID_VSX_XSCVDPHP: return "xscvdphp"; + case PPC_ID_VSX_XSCVDPQP: return "xscvdpqp"; case PPC_ID_VSX_XSCVDPSP: return "xscvdpsp"; + case PPC_ID_VSX_XSCVDPSPN: return "xscvdpspn"; case PPC_ID_VSX_XSCVDPSXDS: return "xscvdpsxds"; case PPC_ID_VSX_XSCVDPSXWS: return "xscvdpsxws"; case PPC_ID_VSX_XSCVDPUXDS: return "xscvdpuxds"; case PPC_ID_VSX_XSCVDPUXWS: return "xscvdpuxws"; + case PPC_ID_VSX_XSCVHPDP: return "xscvhpdp"; + case PPC_ID_VSX_XSCVQPDPx: return Round2OddMnemonic(instruction, SubMnemXSCVQPDPx); + case PPC_ID_VSX_XSCVQPSDZ: return "xscvqpsdz"; + case PPC_ID_VSX_XSCVQPSWZ: return "xscvqpswz"; + case PPC_ID_VSX_XSCVQPUDZ: return "xscvqpudz"; + case PPC_ID_VSX_XSCVQPUWZ: return "xscvqpuwz"; + case PPC_ID_VSX_XSCVSDQP: return "xscvsdqp"; case PPC_ID_VSX_XSCVSPDP: return "xscvspdp"; case PPC_ID_VSX_XSCVSPDPN: return "xscvspdpn"; case PPC_ID_VSX_XSCVSXDDP: return "xscvsxddp"; case PPC_ID_VSX_XSCVSXDSP: return "xscvsxdsp"; + case PPC_ID_VSX_XSCVUDQP: return "xscvudqp"; case PPC_ID_VSX_XSCVUXDDP: return "xscvuxddp"; case PPC_ID_VSX_XSCVUXDSP: return "xscvuxdsp"; case PPC_ID_VSX_XSDIVDP: return "xsdivdp"; case PPC_ID_VSX_XSDIVSP: return "xsdivsp"; + case PPC_ID_VSX_XSDIVQPx: return Round2OddMnemonic(instruction, SubMnemXSDIVQPx); + case PPC_ID_VSX_XSIEXPDP: return "xsiexpdp"; + case PPC_ID_VSX_XSIEXPQP: return "xsiexpqp"; case PPC_ID_VSX_XSMADDADP: return "xsmaddadp"; case PPC_ID_VSX_XSMADDASP: return "xsmaddasp"; case PPC_ID_VSX_XSMADDMDP: return "xsmaddmdp"; case PPC_ID_VSX_XSMADDMSP: return "xsmaddmsp"; + case PPC_ID_VSX_XSMADDQPx: return Round2OddMnemonic(instruction, SubMnemXSMADDQPx); + case PPC_ID_VSX_XSMAXCDP: return "xsmaxcdp"; case PPC_ID_VSX_XSMAXDP: return "xsmaxdp"; + case PPC_ID_VSX_XSMAXJDP: return "xsmaxjdp"; case PPC_ID_VSX_XSMINDP: return "xsmindp"; + case PPC_ID_VSX_XSMINCDP: return "xsmincdp"; + case PPC_ID_VSX_XSMINJDP: return "xsminjdp"; case PPC_ID_VSX_XSMSUBADP: return "xsmsubadp"; case PPC_ID_VSX_XSMSUBASP: return "xsmsubasp"; case PPC_ID_VSX_XSMSUBMDP: return "xsmsubmdp"; case PPC_ID_VSX_XSMSUBMSP: return "xsmsubmsp"; + case PPC_ID_VSX_XSMSUBQPx: return Round2OddMnemonic(instruction, SubMnemXSMSUBQPx); case PPC_ID_VSX_XSMULDP: return "xsmuldp"; case PPC_ID_VSX_XSMULSP: return "xsmulsp"; + case PPC_ID_VSX_XSMULQPx: return Round2OddMnemonic(instruction, SubMnemXSMULQPx); case PPC_ID_VSX_XSNABSDP: return "xsnabsdp"; + case PPC_ID_VSX_XSNABSQP: return "xsnabsqp"; case PPC_ID_VSX_XSNEGDP: return "xsnegdp"; + case PPC_ID_VSX_XSNEGQP: return "xsnegqp"; case PPC_ID_VSX_XSNMADDADP: return "xsnmaddadp"; case PPC_ID_VSX_XSNMADDASP: return "xsnmaddasp"; + case PPC_ID_VSX_XSNMADDQPx: return Round2OddMnemonic(instruction, SubMnemXSNMADDQPx); case PPC_ID_VSX_XSNMADDMDP: return "xsnmaddmdp"; case PPC_ID_VSX_XSNMADDMSP: return "xsnmaddmsp"; case PPC_ID_VSX_XSNMSUBADP: return "xsnmsubadp"; case PPC_ID_VSX_XSNMSUBASP: return "xsnmsubasp"; case PPC_ID_VSX_XSNMSUBMDP: return "xsnmsubmdp"; case PPC_ID_VSX_XSNMSUBMSP: return "xsnmsubmsp"; + case PPC_ID_VSX_XSNMSUBQPx: return Round2OddMnemonic(instruction, SubMnemXSNMSUBQPx); case PPC_ID_VSX_XSRDPI: return "xsrdpi"; case PPC_ID_VSX_XSRDPIC: return "xsrdpic"; case PPC_ID_VSX_XSRDPIM: return "xsrdpim"; @@ -7937,15 +10391,27 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_VSX_XSRDPIZ: return "xsrdpiz"; case PPC_ID_VSX_XSREDP: return "xsredp"; case PPC_ID_VSX_XSRESP: return "xsresp"; + case PPC_ID_VSX_XSRSP: return "xsrsp"; case PPC_ID_VSX_XSRSQRTEDP: return "xsrsqrtedp"; case PPC_ID_VSX_XSRSQRTESP: return "xsrsqrtesp"; case PPC_ID_VSX_XSSQRTDP: return "xssqrtdp"; + case PPC_ID_VSX_XSSQRTQPx: return Round2OddMnemonic(instruction, SubMnemXSSQRTQPx); case PPC_ID_VSX_XSSQRTSP: return "xssqrtsp"; case PPC_ID_VSX_XSSUBDP: return "xssubdp"; case PPC_ID_VSX_XSSUBSP: return "xssubsp"; + case PPC_ID_VSX_XSSUBQPx: return Round2OddMnemonic(instruction, SubMnemXSSUBQPx); + case PPC_ID_VSX_XSRQPIx: return InexactMnemonic(instruction, SubMnemXSRQPIx); + case PPC_ID_VSX_XSRQPXP: return "xsrqpxp"; case PPC_ID_VSX_XSTDIVDP: return "xstdivdp"; case PPC_ID_VSX_XSTDIVSP: return "xstdivsp"; + case PPC_ID_VSX_XSTSTDCDP: return "xststdcdp"; + case PPC_ID_VSX_XSTSTDCQP: return "xststdcqp"; + case PPC_ID_VSX_XSTSTDCSP: return "xststdcsp"; case PPC_ID_VSX_XSTSQRTDP: return "xstsqrtdp"; + case PPC_ID_VSX_XSXEXPDP: return "xsxexpdp"; + case PPC_ID_VSX_XSXEXPQP: return "xsxexpqp"; + case PPC_ID_VSX_XSXSIGDP: return "xsxsigdp"; + case PPC_ID_VSX_XSXSIGQP: return "xsxsigqp"; case PPC_ID_VSX_XVABSSP: return "xvabssp"; case PPC_ID_VSX_XVABSDP: return "xvabsdp"; case PPC_ID_VSX_XVADDSP: return "xvaddsp"; @@ -7963,7 +10429,9 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_VSX_XVCVDPSXWS: return "xvcvdpsxws"; case PPC_ID_VSX_XVCVDPUXDS: return "xvcvdpuxds"; case PPC_ID_VSX_XVCVDPUXWS: return "xvcvdpuxws"; + case PPC_ID_VSX_XVCVHPSP: return "xvcvhpsp"; case PPC_ID_VSX_XVCVSPDP: return "xvcvspdp"; + case PPC_ID_VSX_XVCVSPHP: return "xvcvsphp"; case PPC_ID_VSX_XVCVSPSXDS: return "xvcvspsxds"; case PPC_ID_VSX_XVCVSPSXWS: return "xvcvspsxws"; case PPC_ID_VSX_XVCVSPUXDS: return "xvcvspuxds"; @@ -7978,6 +10446,8 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_VSX_XVCVUXWSP: return "xvcvuxwsp"; case PPC_ID_VSX_XVDIVDP: return "xvdivdp"; case PPC_ID_VSX_XVDIVSP: return "xvdivsp"; + case PPC_ID_VSX_XVIEXPDP: return "xviexpdp"; + case PPC_ID_VSX_XVIEXPSP: return "xviexpsp"; case PPC_ID_VSX_XVMADDADP: return "xvmaddadp"; case PPC_ID_VSX_XVMADDASP: return "xvmaddasp"; case PPC_ID_VSX_XVMADDMDP: return "xvmaddmdp"; @@ -8028,6 +10498,18 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_VSX_XVTDIVSP: return "xvtdivsp"; case PPC_ID_VSX_XVTSQRTDP: return "xvtsqrtdp"; case PPC_ID_VSX_XVTSQRTSP: return "xvtsqrtsp"; + case PPC_ID_VSX_XVTSTDCDP: return "xvtstdcdp"; + case PPC_ID_VSX_XVTSTDCSP: return "xvtstdcsp"; + case PPC_ID_VSX_XVXEXPDP: return "xvxexpdp"; + case PPC_ID_VSX_XVXEXPSP: return "xvxexpsp"; + case PPC_ID_VSX_XVXSIGDP: return "xvxsigdp"; + case PPC_ID_VSX_XVXSIGSP: return "xvxsigsp"; + case PPC_ID_VSX_XXBRD: return "xxbrd"; + case PPC_ID_VSX_XXBRH: return "xxbrh"; + case PPC_ID_VSX_XXBRQ: return "xxbrq"; + case PPC_ID_VSX_XXBRW: return "xxbrw"; + case PPC_ID_VSX_XXEXTRACTUW: return "xxextractuw"; + case PPC_ID_VSX_XXINSERTW: return "xxinsertw"; case PPC_ID_VSX_XXLAND: return "xxland"; case PPC_ID_VSX_XXLANDC: return "xxlandc"; case PPC_ID_VSX_XXLEQV: return "xxleqv"; @@ -8040,11 +10522,13 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_VSX_XXMRGLW: return "xxmrglw"; case PPC_ID_VSX_XXLOR: return "xxlor"; case PPC_ID_VSX_XXLXOR: return "xxlxor"; + case PPC_ID_VSX_XXPERM: return "xxperm"; case PPC_ID_VSX_XXPERMDI: return "xxpermdi"; case PPC_ID_VSX_XXPERMR: return "xxpermr"; case PPC_ID_VSX_XXSEL: return "xxsel"; case PPC_ID_VSX_XXSLDWI: return "xxsldwi"; case PPC_ID_VSX_XXSPLTD: return "xxspltd"; + case PPC_ID_VSX_XXSPLTIB: return "xxspltib"; case PPC_ID_VSX_XXSPLTW: return "xxspltw"; case PPC_ID_VSX_XXSWAPD: return "xxswapd"; @@ -8534,6 +11018,7 @@ const char* OperandClassName(uint32_t cls) case PPC_OP_REG_RA: return "RA"; case PPC_OP_REG_RB: return "RB"; + case PPC_OP_REG_RC: return "RC"; case PPC_OP_REG_RD: return "RD"; case PPC_OP_REG_RS: return "RS"; @@ -8546,6 +11031,7 @@ const char* OperandClassName(uint32_t cls) case PPC_OP_REG_CRFD: return "CRFD"; case PPC_OP_REG_CRFD_IMPLY0: return "CRFD"; case PPC_OP_REG_CRFS: return "CRFS"; + case PPC_OP_CRBIT: return "CRBIT"; case PPC_OP_CRBIT_A: return "CRBIT_A"; case PPC_OP_CRBIT_B: return "CRBIT_B"; case PPC_OP_CRBIT_D: return "CRBIT_C"; diff --git a/arch/powerpc/decode/decode.h b/arch/powerpc/decode/decode.h index 404f070cb..78ce1858e 100644 --- a/arch/powerpc/decode/decode.h +++ b/arch/powerpc/decode/decode.h @@ -219,6 +219,7 @@ extern "C" { PPC_OP_REG_RA, PPC_OP_REG_RB, + PPC_OP_REG_RC, PPC_OP_REG_RD, PPC_OP_REG_RS, @@ -232,6 +233,7 @@ extern "C" { PPC_OP_REG_CRFD_IMPLY0, PPC_OP_REG_CRFS, PPC_OP_REG_CRFS_IMPLY0, + PPC_OP_CRBIT, PPC_OP_CRBIT_A, PPC_OP_CRBIT_B, PPC_OP_CRBIT_D, @@ -324,6 +326,7 @@ extern "C" { PPC_ID_ADDICx, PPC_ID_ADDIS, PPC_ID_ADDMEx, + PPC_ID_ADDPCIS, PPC_ID_ADDZEx, PPC_ID_ANDx, PPC_ID_ANDCx, @@ -334,12 +337,16 @@ extern "C" { PPC_ID_BCx, PPC_ID_BCCTRx, PPC_ID_BCLRx, + PPC_ID_BPERMD, + PPC_ID_CLRBHRB, PPC_ID_CLRLDIx, PPC_ID_CLRLWIx, PPC_ID_CLRRWIx, PPC_ID_CMPB, PPC_ID_CMPD, PPC_ID_CMPDI, + PPC_ID_CMPEQB, + PPC_ID_CMPRB, PPC_ID_CMPW, PPC_ID_CMPWI, PPC_ID_CMPLD, @@ -348,6 +355,10 @@ extern "C" { PPC_ID_CMPLWI, PPC_ID_CNTLZDx, PPC_ID_CNTLZWx, + PPC_ID_CNTTZDx, + PPC_ID_CNTTZWx, + PPC_ID_COPY, + PPC_ID_CP_ABORT, PPC_ID_CRAND, PPC_ID_CRANDC, PPC_ID_CRCLR, @@ -360,19 +371,34 @@ extern "C" { PPC_ID_CRORC, PPC_ID_CRSET, PPC_ID_CRXOR, + PPC_ID_DARN, PPC_ID_DCBA, PPC_ID_DCBF, + PPC_ID_DCBFEP, + PPC_ID_DCBFL, + PPC_ID_DCBFLP, PPC_ID_DCBI, PPC_ID_DCBST, + PPC_ID_DCBSTEP, PPC_ID_DCBT, + PPC_ID_DCBTEP, PPC_ID_DCBTST, + PPC_ID_DCBTSTEP, + PPC_ID_DCBTSTT, + PPC_ID_DCBTT, PPC_ID_DCBZ, + PPC_ID_DCBZEP, PPC_ID_DCBZL, + PPC_ID_DCBZLEP, PPC_ID_DCCCI, PPC_ID_DCI, PPC_ID_DIVDx, + PPC_ID_DIVDEx, + PPC_ID_DIVDEUx, PPC_ID_DIVDUx, PPC_ID_DIVWx, + PPC_ID_DIVWEx, + PPC_ID_DIVWEUx, PPC_ID_DIVWUx, PPC_ID_ECIWX, PPC_ID_ECOWX, @@ -381,6 +407,7 @@ extern "C" { PPC_ID_EXTSBx, PPC_ID_EXTSHx, PPC_ID_EXTSWx, + PPC_ID_EXTSWSLIx, PPC_ID_FABSx, PPC_ID_FADDx, PPC_ID_FADDSx, @@ -392,9 +419,11 @@ extern "C" { PPC_ID_FCMPU, PPC_ID_FCPSGNx, PPC_ID_FCTIDx, + PPC_ID_FCTIDUx, PPC_ID_FCTIDUZx, PPC_ID_FCTIDZx, PPC_ID_FCTIWx, + PPC_ID_FCTIWUx, PPC_ID_FCTIWUZx, PPC_ID_FCTIWZx, PPC_ID_FDIVx, @@ -426,25 +455,35 @@ extern "C" { PPC_ID_FSQRTSx, PPC_ID_FSUBx, PPC_ID_FSUBSx, + PPC_ID_FTDIV, + PPC_ID_FTSQRT, PPC_ID_ICBI, + PPC_ID_ICBIEP, + PPC_ID_ICBLC, + PPC_ID_ICBLQ, PPC_ID_ICBT, + PPC_ID_ICBTLS, PPC_ID_ICCCI, PPC_ID_ICI, PPC_ID_ISEL, PPC_ID_ISYNC, + PPC_ID_LBARX, + PPC_ID_LBEPX, PPC_ID_LBZ, PPC_ID_LBZCIX, PPC_ID_LBZU, PPC_ID_LBZUX, PPC_ID_LBZX, + PPC_ID_LD, + PPC_ID_LDAT, PPC_ID_LDARX, PPC_ID_LDBRX, PPC_ID_LDCIX, - PPC_ID_LD, PPC_ID_LDU, PPC_ID_LDUX, PPC_ID_LDX, PPC_ID_LFD, + PPC_ID_LFDEPX, PPC_ID_LFDU, PPC_ID_LFDUX, PPC_ID_LFDX, @@ -458,7 +497,9 @@ extern "C" { PPC_ID_LHAU, PPC_ID_LHAUX, PPC_ID_LHAX, + PPC_ID_LHARX, PPC_ID_LHBRX, + PPC_ID_LHEPX, PPC_ID_LHZ, PPC_ID_LHZCIX, PPC_ID_LHZU, @@ -467,13 +508,16 @@ extern "C" { PPC_ID_LI, PPC_ID_LIS, PPC_ID_LMW, + PPC_ID_LNIA, PPC_ID_LSWI, PPC_ID_LSWX, PPC_ID_LWA, + PPC_ID_LWAT, PPC_ID_LWAX, PPC_ID_LWARX, PPC_ID_LWAUX, PPC_ID_LWBRX, + PPC_ID_LWEPX, PPC_ID_LWSYNC, PPC_ID_LWZ, PPC_ID_LWZCIX, @@ -484,6 +528,8 @@ extern "C" { PPC_ID_MCRF, PPC_ID_MCRFS, PPC_ID_MCRXR, + PPC_ID_MCRXRX, + PPC_ID_MFBHRBE, PPC_ID_MFBR0, PPC_ID_MFBR1, PPC_ID_MFBR2, @@ -498,9 +544,16 @@ extern "C" { PPC_ID_MFDCRUX, PPC_ID_MFDCRX, PPC_ID_MFFSx, + PPC_ID_MFFSCDRN, + PPC_ID_MFFSCDRNI, + PPC_ID_MFFSCE, + PPC_ID_MFFSCRN, + PPC_ID_MFFSCRNI, + PPC_ID_MFFSL, PPC_ID_MFLR, PPC_ID_MFMSR, PPC_ID_MFOCRF, + PPC_ID_MFPMR, PPC_ID_MFSPR, PPC_ID_MFSR, PPC_ID_MFSRIN, @@ -508,6 +561,7 @@ extern "C" { PPC_ID_MFTBU, PPC_ID_MFXER, PPC_ID_MRx, + PPC_ID_MSGSYNC, PPC_ID_MTAMR, PPC_ID_MTBR0, PPC_ID_MTBR1, @@ -529,11 +583,16 @@ extern "C" { PPC_ID_MTFSB1x, PPC_ID_MTFSFx, PPC_ID_MTFSFIx, + PPC_ID_MODSD, + PPC_ID_MODSW, + PPC_ID_MODUD, + PPC_ID_MODUW, PPC_ID_MTICCR, PPC_ID_MTLR, PPC_ID_MTMSR, PPC_ID_MTMSRD, PPC_ID_MTOCRF, + PPC_ID_MTPMR, PPC_ID_MTSPR, PPC_ID_MTSR, PPC_ID_MTSRIN, @@ -558,6 +617,7 @@ extern "C" { PPC_ID_ORCx, PPC_ID_ORI, PPC_ID_ORIS, + PPC_ID_PASTE, PPC_ID_POPCNTB, PPC_ID_POPCNTD, PPC_ID_POPCNTW, @@ -581,10 +641,14 @@ extern "C" { PPC_ID_ROTLWx, PPC_ID_ROTLWIx, PPC_ID_SC, + PPC_ID_SETB, PPC_ID_SLBIA, PPC_ID_SLBIE, + PPC_ID_SLBIEG, PPC_ID_SLBMFEE, + PPC_ID_SLBMFEV, PPC_ID_SLBMTE, + PPC_ID_SLBSYNC, PPC_ID_SLDx, PPC_ID_SLDIx, PPC_ID_SLWx, @@ -598,18 +662,23 @@ extern "C" { PPC_ID_SRWx, PPC_ID_SRWIx, PPC_ID_STB, + PPC_ID_STBCX, PPC_ID_STBU, PPC_ID_STBUX, PPC_ID_STBX, PPC_ID_STBCIX, + PPC_ID_STBEPX, PPC_ID_STD, + PPC_ID_STDAT, PPC_ID_STDBRX, PPC_ID_STDCIX, PPC_ID_STDCX, + PPC_ID_STDEPX, PPC_ID_STDU, PPC_ID_STDUX, PPC_ID_STDX, PPC_ID_STFD, + PPC_ID_STFDEPX, PPC_ID_STFDU, PPC_ID_STFDUX, PPC_ID_STFDX, @@ -620,7 +689,9 @@ extern "C" { PPC_ID_STFSX, PPC_ID_STH, PPC_ID_STHBRX, + PPC_ID_STHCX, PPC_ID_STHCIX, + PPC_ID_STHEPX, PPC_ID_STHU, PPC_ID_STHUX, PPC_ID_STHX, @@ -628,9 +699,11 @@ extern "C" { PPC_ID_STSWI, PPC_ID_STSWX, PPC_ID_STW, + PPC_ID_STWAT, PPC_ID_STWBRX, PPC_ID_STWCIX, PPC_ID_STWCX, + PPC_ID_STWEPX, PPC_ID_STWU, PPC_ID_STWUX, PPC_ID_STWX, @@ -641,6 +714,13 @@ extern "C" { PPC_ID_SUBFMEx, PPC_ID_SUBFZEx, PPC_ID_SYNC, + PPC_ID_TABORT, + PPC_ID_TABORTDC, + PPC_ID_TABORTDCI, + PPC_ID_TABORTWC, + PPC_ID_TABORTWCI, + PPC_ID_TBEGIN, + PPC_ID_TCHECK, PPC_ID_TD, PPC_ID_TDEQ, PPC_ID_TDEQI, @@ -657,6 +737,7 @@ extern "C" { PPC_ID_TDNEI, PPC_ID_TDU, PPC_ID_TDUI, + PPC_ID_TEND, PPC_ID_TLBIA, PPC_ID_TLBIE, PPC_ID_TLBIEL, @@ -671,6 +752,9 @@ extern "C" { PPC_ID_TLBWEHI, PPC_ID_TLBWELO, PPC_ID_TRAP, + PPC_ID_TRECHKPT, + PPC_ID_TRECLAIM, + PPC_ID_TSR, PPC_ID_TW, PPC_ID_TWEQ, PPC_ID_TWEQI, @@ -701,6 +785,26 @@ extern "C" { PPC_ID_XORIS, // AltiVec instructions + PPC_ID_AV_VABSDUB, + PPC_ID_AV_VABSDUH, + PPC_ID_AV_VABSDUW, + PPC_ID_AV_VADDUQM, + PPC_ID_AV_VADDCUQ, + PPC_ID_AV_BCDADD, + PPC_ID_AV_BCDCFN, + PPC_ID_AV_BCDCFSQ, + PPC_ID_AV_BCDCFZ, + PPC_ID_AV_BCDCPSGN, + PPC_ID_AV_BCDCTN, + PPC_ID_AV_BCDCTSQ, + PPC_ID_AV_BCDCTZ, + PPC_ID_AV_BCDS, + PPC_ID_AV_BCDSETSGN, + PPC_ID_AV_BCDSR, + PPC_ID_AV_BCDSUB, + PPC_ID_AV_BCDTRUNC, + PPC_ID_AV_BCDUS, + PPC_ID_AV_BCDUTRUNC, PPC_ID_AV_DSS, PPC_ID_AV_DSSALL, PPC_ID_AV_DST, @@ -714,6 +818,9 @@ extern "C" { PPC_ID_AV_LVSR, PPC_ID_AV_LVX, PPC_ID_AV_LVXL, + PPC_ID_AV_MADDHD, + PPC_ID_AV_MADDHDU, + PPC_ID_AV_MADDLD, PPC_ID_AV_MFVSCR, PPC_ID_AV_MTVSCR, PPC_ID_AV_STVEBX, @@ -722,6 +829,8 @@ extern "C" { PPC_ID_AV_STVX, PPC_ID_AV_STVXL, PPC_ID_AV_VADDCUW, + PPC_ID_AV_VADDECUQ, + PPC_ID_AV_VADDEUQM, PPC_ID_AV_VADDFP, PPC_ID_AV_VADDSBS, PPC_ID_AV_VADDSHS, @@ -741,11 +850,16 @@ extern "C" { PPC_ID_AV_VAVGUB, PPC_ID_AV_VAVGUH, PPC_ID_AV_VAVGUW, + PPC_ID_AV_VBPERMD, + PPC_ID_AV_VBPERMQ, PPC_ID_AV_VCFSX, PPC_ID_AV_VCFUX, + PPC_ID_AV_VCIPHER, + PPC_ID_AV_VCIPHERLAST, PPC_ID_AV_VCLZB, PPC_ID_AV_VCLZD, PPC_ID_AV_VCLZH, + PPC_ID_AV_VCLZLSBB, PPC_ID_AV_VCLZW, PPC_ID_AV_VCMPBFPx, PPC_ID_AV_VCMPEQFPx, @@ -763,10 +877,41 @@ extern "C" { PPC_ID_AV_VCMPGTUDx, PPC_ID_AV_VCMPGTUHx, PPC_ID_AV_VCMPGTUWx, + PPC_ID_AV_VCMPNEBx, + PPC_ID_AV_VCMPNEHx, + PPC_ID_AV_VCMPNEWx, + PPC_ID_AV_VCMPNEZBx, + PPC_ID_AV_VCMPNEZHx, + PPC_ID_AV_VCMPNEZWx, PPC_ID_AV_VCTSXS, PPC_ID_AV_VCTUXS, + PPC_ID_AV_VCTZB, + PPC_ID_AV_VCTZD, + PPC_ID_AV_VCTZH, + PPC_ID_AV_VCTZLSBB, + PPC_ID_AV_VCTZW, PPC_ID_AV_VEQV, PPC_ID_AV_VEXPTEFP, + PPC_ID_AV_VEXTRACTD, + PPC_ID_AV_VEXTRACTUB, + PPC_ID_AV_VEXTRACTUH, + PPC_ID_AV_VEXTRACTUW, + PPC_ID_AV_VEXTSB2D, + PPC_ID_AV_VEXTSB2W, + PPC_ID_AV_VEXTSH2D, + PPC_ID_AV_VEXTSH2W, + PPC_ID_AV_VEXTSW2D, + PPC_ID_AV_VEXTUBLX, + PPC_ID_AV_VEXTUHLX, + PPC_ID_AV_VEXTUWLX, + PPC_ID_AV_VEXTUBRX, + PPC_ID_AV_VEXTUHRX, + PPC_ID_AV_VEXTUWRX, + PPC_ID_AV_VGBBD, + PPC_ID_AV_VINSERTB, + PPC_ID_AV_VINSERTD, + PPC_ID_AV_VINSERTH, + PPC_ID_AV_VINSERTW, PPC_ID_AV_VLOGEFP, PPC_ID_AV_VMADDFP, PPC_ID_AV_VMAXFP, @@ -790,18 +935,25 @@ extern "C" { PPC_ID_AV_VMINUH, PPC_ID_AV_VMINUW, PPC_ID_AV_VMLADDUHM, + PPC_ID_AV_VMR, + PPC_ID_AV_VMRGEW, PPC_ID_AV_VMRGHB, PPC_ID_AV_VMRGHH, PPC_ID_AV_VMRGHW, PPC_ID_AV_VMRGLB, PPC_ID_AV_VMRGLH, PPC_ID_AV_VMRGLW, + PPC_ID_AV_VMRGOW, PPC_ID_AV_VMSUMMBM, PPC_ID_AV_VMSUMSHM, PPC_ID_AV_VMSUMSHS, PPC_ID_AV_VMSUMUBM, PPC_ID_AV_VMSUMUHM, PPC_ID_AV_VMSUMUHS, + PPC_ID_AV_VMUL10CUQ, + PPC_ID_AV_VMUL10EUQ, + PPC_ID_AV_VMUL10ECUQ, + PPC_ID_AV_VMUL10UQ, PPC_ID_AV_VMULESB, PPC_ID_AV_VMULESH, PPC_ID_AV_VMULESW, @@ -816,24 +968,42 @@ extern "C" { PPC_ID_AV_VMULOUW, PPC_ID_AV_VMULUWM, PPC_ID_AV_VNAND, + PPC_ID_AV_VNCIPHER, + PPC_ID_AV_VNCIPHERLAST, PPC_ID_AV_VNMSUBFP, + PPC_ID_AV_VNEGD, + PPC_ID_AV_VNEGW, PPC_ID_AV_VNOR, + PPC_ID_AV_VNOT, PPC_ID_AV_VOR, PPC_ID_AV_VORC, PPC_ID_AV_VPERM, + PPC_ID_AV_VPERMR, + PPC_ID_AV_VPERMXOR, PPC_ID_AV_VPKPX, + PPC_ID_AV_VPKSDSS, + PPC_ID_AV_VPKSDUS, PPC_ID_AV_VPKSHSS, PPC_ID_AV_VPKSHUS, PPC_ID_AV_VPKSWSS, PPC_ID_AV_VPKSWUS, + PPC_ID_AV_VPKUDUM, + PPC_ID_AV_VPKUDUS, PPC_ID_AV_VPKUHUM, PPC_ID_AV_VPKUHUS, PPC_ID_AV_VPKUWUM, PPC_ID_AV_VPKUWUS, + PPC_ID_AV_VPMSUMB, + PPC_ID_AV_VPMSUMD, + PPC_ID_AV_VPMSUMH, + PPC_ID_AV_VPMSUMW, PPC_ID_AV_VPOPCNTB, PPC_ID_AV_VPOPCNTD, PPC_ID_AV_VPOPCNTH, PPC_ID_AV_VPOPCNTW, + PPC_ID_AV_VPRTYBD, + PPC_ID_AV_VPRTYBQ, + PPC_ID_AV_VPRTYBW, PPC_ID_AV_VREFP, PPC_ID_AV_VRFIM, PPC_ID_AV_VRFIN, @@ -841,16 +1011,24 @@ extern "C" { PPC_ID_AV_VRFIZ, PPC_ID_AV_VRLB, PPC_ID_AV_VRLD, + PPC_ID_AV_VRLDNM, + PPC_ID_AV_VRLDMI, PPC_ID_AV_VRLH, PPC_ID_AV_VRLW, + PPC_ID_AV_VRLWMI, + PPC_ID_AV_VRLWNM, PPC_ID_AV_VRSQRTEFP, + PPC_ID_AV_VSBOX, PPC_ID_AV_VSEL, + PPC_ID_AV_VSHASIGMAD, + PPC_ID_AV_VSHASIGMAW, PPC_ID_AV_VSL, PPC_ID_AV_VSLB, PPC_ID_AV_VSLD, PPC_ID_AV_VSLDOI, PPC_ID_AV_VSLH, PPC_ID_AV_VSLO, + PPC_ID_AV_VSLV, PPC_ID_AV_VSLW, PPC_ID_AV_VSPLTB, PPC_ID_AV_VSPLTH, @@ -867,8 +1045,12 @@ extern "C" { PPC_ID_AV_VSRD, PPC_ID_AV_VSRH, PPC_ID_AV_VSRO, + PPC_ID_AV_VSRV, PPC_ID_AV_VSRW, + PPC_ID_AV_VSUBCUQ, PPC_ID_AV_VSUBCUW, + PPC_ID_AV_VSUBECUQ, + PPC_ID_AV_VSUBEUQM, PPC_ID_AV_VSUBFP, PPC_ID_AV_VSUBSBS, PPC_ID_AV_VSUBSHS, @@ -878,6 +1060,7 @@ extern "C" { PPC_ID_AV_VSUBUDM, PPC_ID_AV_VSUBUHM, PPC_ID_AV_VSUBUHS, + PPC_ID_AV_VSUBUQM, PPC_ID_AV_VSUBUWM, PPC_ID_AV_VSUBUWS, PPC_ID_AV_VSUMSWS, @@ -888,65 +1071,130 @@ extern "C" { PPC_ID_AV_VUPKHPX, PPC_ID_AV_VUPKHSB, PPC_ID_AV_VUPKHSH, + PPC_ID_AV_VUPKHSW, PPC_ID_AV_VUPKLPX, PPC_ID_AV_VUPKLSB, PPC_ID_AV_VUPKLSH, + PPC_ID_AV_VUPKLSW, PPC_ID_AV_VXOR, // VSX instructions PPC_ID_VSX_LXSDX, + PPC_ID_VSX_LXSIBZX, + PPC_ID_VSX_LXSIHZX, PPC_ID_VSX_LXSIWAX, PPC_ID_VSX_LXSIWZX, PPC_ID_VSX_LXSSPX, + PPC_ID_VSX_LXV, + PPC_ID_VSX_LXVB16X, PPC_ID_VSX_LXVD2X, PPC_ID_VSX_LXVDSX, + PPC_ID_VSX_LXVH8X, + PPC_ID_VSX_LXVL, + PPC_ID_VSX_LXVLL, PPC_ID_VSX_LXVW4X, + PPC_ID_VSX_LXVWSX, + PPC_ID_VSX_LXVX, + PPC_ID_VSX_MFFPRD, + PPC_ID_VSX_MFVSRD, + PPC_ID_VSX_MFVSRLD, + PPC_ID_VSX_MFVSRWZ, + PPC_ID_VSX_MTVSRD, + PPC_ID_VSX_MTVSRDD, + PPC_ID_VSX_MTVSRWA, + PPC_ID_VSX_MTVSRWS, + PPC_ID_VSX_MTVSRWZ, + PPC_ID_VSX_STXSD, PPC_ID_VSX_STXSDX, + PPC_ID_VSX_STXSIBX, + PPC_ID_VSX_STXSIHX, PPC_ID_VSX_STXSIWX, + PPC_ID_VSX_STXSSP, PPC_ID_VSX_STXSSPX, + PPC_ID_VSX_STXV, + PPC_ID_VSX_STXVB16X, PPC_ID_VSX_STXVD2X, + PPC_ID_VSX_STXVH8X, + PPC_ID_VSX_STXVL, + PPC_ID_VSX_STXVLL, PPC_ID_VSX_STXVW4X, + PPC_ID_VSX_STXVX, PPC_ID_VSX_XSABSDP, + PPC_ID_VSX_XSABSQP, PPC_ID_VSX_XSADDDP, PPC_ID_VSX_XSADDSP, + PPC_ID_VSX_XSADDQPx, + PPC_ID_VSX_XSCMPEQDP, + PPC_ID_VSX_XSCMPEXPDP, + PPC_ID_VSX_XSCMPEXPQP, + PPC_ID_VSX_XSCMPGEDP, + PPC_ID_VSX_XSCMPGTDP, PPC_ID_VSX_XSCMPODP, + PPC_ID_VSX_XSCMPOQP, PPC_ID_VSX_XSCMPUDP, + PPC_ID_VSX_XSCMPUQP, PPC_ID_VSX_XSCPSGNDP, + PPC_ID_VSX_XSCPSGNQP, + PPC_ID_VSX_XSCVDPHP, + PPC_ID_VSX_XSCVDPQP, PPC_ID_VSX_XSCVDPSP, + PPC_ID_VSX_XSCVDPSPN, PPC_ID_VSX_XSCVDPSXDS, PPC_ID_VSX_XSCVDPSXWS, PPC_ID_VSX_XSCVDPUXDS, PPC_ID_VSX_XSCVDPUXWS, + PPC_ID_VSX_XSCVHPDP, + PPC_ID_VSX_XSCVQPDPx, + PPC_ID_VSX_XSCVQPSDZ, + PPC_ID_VSX_XSCVQPSWZ, + PPC_ID_VSX_XSCVQPUDZ, + PPC_ID_VSX_XSCVQPUWZ, + PPC_ID_VSX_XSCVSDQP, PPC_ID_VSX_XSCVSPDP, PPC_ID_VSX_XSCVSPDPN, PPC_ID_VSX_XSCVSXDDP, PPC_ID_VSX_XSCVSXDSP, + PPC_ID_VSX_XSCVUDQP, PPC_ID_VSX_XSCVUXDDP, PPC_ID_VSX_XSCVUXDSP, PPC_ID_VSX_XSDIVDP, PPC_ID_VSX_XSDIVSP, + PPC_ID_VSX_XSDIVQPx, + PPC_ID_VSX_XSIEXPDP, + PPC_ID_VSX_XSIEXPQP, PPC_ID_VSX_XSMADDADP, PPC_ID_VSX_XSMADDASP, PPC_ID_VSX_XSMADDMDP, PPC_ID_VSX_XSMADDMSP, + PPC_ID_VSX_XSMADDQPx, + PPC_ID_VSX_XSMAXCDP, PPC_ID_VSX_XSMAXDP, + PPC_ID_VSX_XSMAXJDP, + PPC_ID_VSX_XSMINCDP, PPC_ID_VSX_XSMINDP, + PPC_ID_VSX_XSMINJDP, PPC_ID_VSX_XSMSUBADP, PPC_ID_VSX_XSMSUBASP, PPC_ID_VSX_XSMSUBMDP, PPC_ID_VSX_XSMSUBMSP, + PPC_ID_VSX_XSMSUBQPx, PPC_ID_VSX_XSMULDP, PPC_ID_VSX_XSMULSP, + PPC_ID_VSX_XSMULQPx, PPC_ID_VSX_XSNABSDP, + PPC_ID_VSX_XSNABSQP, PPC_ID_VSX_XSNEGDP, + PPC_ID_VSX_XSNEGQP, PPC_ID_VSX_XSNMADDADP, PPC_ID_VSX_XSNMADDASP, PPC_ID_VSX_XSNMADDMDP, PPC_ID_VSX_XSNMADDMSP, + PPC_ID_VSX_XSNMADDQPx, PPC_ID_VSX_XSNMSUBADP, PPC_ID_VSX_XSNMSUBASP, PPC_ID_VSX_XSNMSUBMDP, PPC_ID_VSX_XSNMSUBMSP, + PPC_ID_VSX_XSNMSUBQPx, PPC_ID_VSX_XSRDPI, PPC_ID_VSX_XSRDPIC, PPC_ID_VSX_XSRDPIM, @@ -954,15 +1202,27 @@ extern "C" { PPC_ID_VSX_XSRDPIZ, PPC_ID_VSX_XSREDP, PPC_ID_VSX_XSRESP, + PPC_ID_VSX_XSRQPIx, + PPC_ID_VSX_XSRQPXP, + PPC_ID_VSX_XSRSP, PPC_ID_VSX_XSRSQRTEDP, PPC_ID_VSX_XSRSQRTESP, PPC_ID_VSX_XSSQRTDP, + PPC_ID_VSX_XSSQRTQPx, PPC_ID_VSX_XSSQRTSP, PPC_ID_VSX_XSSUBDP, PPC_ID_VSX_XSSUBSP, + PPC_ID_VSX_XSSUBQPx, PPC_ID_VSX_XSTDIVDP, PPC_ID_VSX_XSTDIVSP, + PPC_ID_VSX_XSTSTDCQP, + PPC_ID_VSX_XSTSTDCDP, + PPC_ID_VSX_XSTSTDCSP, PPC_ID_VSX_XSTSQRTDP, + PPC_ID_VSX_XSXEXPDP, + PPC_ID_VSX_XSXEXPQP, + PPC_ID_VSX_XSXSIGDP, + PPC_ID_VSX_XSXSIGQP, PPC_ID_VSX_XVABSDP, PPC_ID_VSX_XVABSSP, PPC_ID_VSX_XVADDDP, @@ -980,7 +1240,9 @@ extern "C" { PPC_ID_VSX_XVCVDPSXWS, PPC_ID_VSX_XVCVDPUXDS, PPC_ID_VSX_XVCVDPUXWS, + PPC_ID_VSX_XVCVHPSP, PPC_ID_VSX_XVCVSPDP, + PPC_ID_VSX_XVCVSPHP, PPC_ID_VSX_XVCVSPSXDS, PPC_ID_VSX_XVCVSPSXWS, PPC_ID_VSX_XVCVSPUXDS, @@ -995,6 +1257,8 @@ extern "C" { PPC_ID_VSX_XVCVUXWSP, PPC_ID_VSX_XVDIVDP, PPC_ID_VSX_XVDIVSP, + PPC_ID_VSX_XVIEXPDP, + PPC_ID_VSX_XVIEXPSP, PPC_ID_VSX_XVMADDADP, PPC_ID_VSX_XVMADDASP, PPC_ID_VSX_XVMADDMDP, @@ -1045,6 +1309,18 @@ extern "C" { PPC_ID_VSX_XVTDIVSP, PPC_ID_VSX_XVTSQRTDP, PPC_ID_VSX_XVTSQRTSP, + PPC_ID_VSX_XVTSTDCDP, + PPC_ID_VSX_XVTSTDCSP, + PPC_ID_VSX_XVXEXPDP, + PPC_ID_VSX_XVXEXPSP, + PPC_ID_VSX_XVXSIGDP, + PPC_ID_VSX_XVXSIGSP, + PPC_ID_VSX_XXBRD, + PPC_ID_VSX_XXBRH, + PPC_ID_VSX_XXBRQ, + PPC_ID_VSX_XXBRW, + PPC_ID_VSX_XXEXTRACTUW, + PPC_ID_VSX_XXINSERTW, PPC_ID_VSX_XXLAND, PPC_ID_VSX_XXLANDC, PPC_ID_VSX_XXLEQV, @@ -1057,11 +1333,13 @@ extern "C" { PPC_ID_VSX_XXMRGHW, PPC_ID_VSX_XXMRGLD, PPC_ID_VSX_XXMRGLW, + PPC_ID_VSX_XXPERM, PPC_ID_VSX_XXPERMDI, PPC_ID_VSX_XXPERMR, PPC_ID_VSX_XXSEL, PPC_ID_VSX_XXSLDWI, PPC_ID_VSX_XXSPLTD, + PPC_ID_VSX_XXSPLTIB, PPC_ID_VSX_XXSPLTW, PPC_ID_VSX_XXSWAPD, @@ -1347,6 +1625,8 @@ extern "C" { uint32_t lk: 1; uint32_t aa: 1; uint32_t branchLikelyHint: 2; + uint32_t round2odd: 1; + uint32_t inexact: 1; } flags; size_t numOperands; From 1512f5bbdcd4db9b50c55918e9dfd02dd7d5a71e Mon Sep 17 00:00:00 2001 From: noone Date: Sun, 29 Dec 2024 20:15:34 -0800 Subject: [PATCH 09/19] Fix compiler warnings --- arch/powerpc/decode/decode.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c index 0eb0ab5c2..67549a9b7 100644 --- a/arch/powerpc/decode/decode.c +++ b/arch/powerpc/decode/decode.c @@ -11,7 +11,6 @@ // see stanford bit twiddling hacks static int32_t sign_extend(uint32_t x, unsigned numBits) { - int32_t r; int32_t const m = 1U << (numBits - 1); x = x & ((1U << numBits) - 1); @@ -198,12 +197,6 @@ static void PushCRFS(Instruction* instruction, uint32_t word32) PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crfs)); } -static void PushCRFSImply0(Instruction* instruction, uint32_t word32) -{ - uint32_t crfs = (word32 >> 18) & 0x7; - PushRegister(instruction, PPC_OP_REG_CRFS_IMPLY0, Crf(crfs)); -} - static void PushCRBitA(Instruction* instruction, uint32_t word32) { instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_A; @@ -246,7 +239,6 @@ static uint32_t GetBO(uint32_t word32) static void FillBranchLikelyHint(Instruction* instruction, uint32_t word32) { uint32_t bo = GetBO(word32); - uint32_t bi = GetBI(word32); switch (bo >> 2) { @@ -1455,7 +1447,6 @@ static InstructionId DecodeSpe0x04(uint32_t word32, uint32_t decodeFlags) { uint32_t a = GetA(word32); uint32_t b = GetB(word32); - uint32_t d = GetD(word32); uint32_t subop = word32 & 0x7ff; switch (subop) @@ -4346,7 +4337,6 @@ static InstructionId Decode0x3B(uint32_t word32, uint32_t flags) static InstructionId DecodeVsx0x3C(uint32_t word32, uint32_t flags) { - uint32_t bit21 = (word32 >> 10) & 0x1; uint32_t subop = (word32 >> 4) & 0x3; uint32_t vsxA = GetVsxA(word32); uint32_t vsxB = GetVsxB(word32); @@ -5728,8 +5718,7 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return PPC_ID_VSX_XSSQRTQPx; default: - PPC_ID_INVALID; - + return PPC_ID_INVALID; } } else @@ -5928,10 +5917,10 @@ static InstructionId Decode(uint32_t word32, uint32_t decodeFlags) { if ((word32 & 0x00200000) != 0) { - if (decodeFlags & DECODE_FLAGS_PPC64 == 0) + if ((decodeFlags & DECODE_FLAGS_PPC64) != 0) + return PPC_ID_CMPLDI; + else return PPC_ID_INVALID; - - return PPC_ID_CMPLDI; } else { @@ -5946,10 +5935,11 @@ static InstructionId Decode(uint32_t word32, uint32_t decodeFlags) { if ((word32 & 0x00200000) != 0) { - if (decodeFlags & DECODE_FLAGS_PPC64 == 0) + if ((decodeFlags & DECODE_FLAGS_PPC64) != 0) + return PPC_ID_CMPDI; + else return PPC_ID_INVALID; - return PPC_ID_CMPDI; } else { @@ -9290,8 +9280,6 @@ void FillBclrxOperands(OperandsList* bclrx, const Instruction* instruction) const char* GetMnemonic(const Instruction* instruction) { - unsigned int index; - switch (instruction->id) { case PPC_ID_ADDx: return OeRcMnemonic(instruction, SubMnemADDx); @@ -11057,7 +11045,8 @@ const char* OperandClassName(uint32_t cls) case PPC_OP_REG_VSX_RS: return "VSX_RS"; case PPC_OP_REG_VSX_RS_DWORD0: return "VSX_RS0"; - return "???"; + default: + return "???"; } } From 3c2e6d7277efe4c2a63160775c6583562b38366e Mon Sep 17 00:00:00 2001 From: noone Date: Mon, 30 Dec 2024 08:27:27 -0800 Subject: [PATCH 10/19] Split into multiple files This was getting unwieldly. --- arch/powerpc/decode/decode.c | 5338 +------------------------------- arch/powerpc/decode/decode.h | 10 + arch/powerpc/decode/mnemonic.c | 1851 +++++++++++ arch/powerpc/decode/names.c | 293 ++ arch/powerpc/decode/operands.c | 3081 ++++++++++++++++++ arch/powerpc/decode/priv.c | 109 + arch/powerpc/decode/priv.h | 27 + 7 files changed, 5377 insertions(+), 5332 deletions(-) create mode 100644 arch/powerpc/decode/mnemonic.c create mode 100644 arch/powerpc/decode/names.c create mode 100644 arch/powerpc/decode/operands.c create mode 100644 arch/powerpc/decode/priv.c create mode 100644 arch/powerpc/decode/priv.h diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c index 67549a9b7..1b3b128ee 100644 --- a/arch/powerpc/decode/decode.c +++ b/arch/powerpc/decode/decode.c @@ -2,426 +2,13 @@ #include #include "decode.h" +#include "priv.h" // Documentation: // * [ProgrammingEnvironments32]: "Programming Environments Manual for 32-bit // Implementations of the PowerPC^TM Architecture" by Freescale/NXP // -// see stanford bit twiddling hacks -static int32_t sign_extend(uint32_t x, unsigned numBits) -{ - int32_t const m = 1U << (numBits - 1); - - x = x & ((1U << numBits) - 1); - return (x ^ m) - m; -} - -static void CopyOperand(Operand* dst, const Operand* src) -{ - memcpy(dst, src, sizeof *dst); -} - -static Register Gpr(uint32_t value) -{ - return PPC_REG_GPR0 + value; -} - -static Register Fr(uint32_t value) -{ - return PPC_REG_FR0 + value; -} - -static Register Crf(uint32_t value) -{ - return PPC_REG_CRF0 + value; -} - -static Register AltivecVr(uint32_t value) -{ - return PPC_REG_AV_VR0 + value; -} - -static Register VsxVr(uint32_t value) -{ - return PPC_REG_VSX_VR0 + value; -} - -static Register VsxVrHi(uint32_t value) -{ - return PPC_REG_VSX_VR0 + value + 32; -} - -static void PushUIMMValue(Instruction* instruction, uint32_t uimm) -{ - instruction->operands[instruction->numOperands].cls = PPC_OP_UIMM; - instruction->operands[instruction->numOperands].uimm = uimm; - ++instruction->numOperands; -} - -static void PushSIMMValue(Instruction* instruction, int32_t simm) -{ - instruction->operands[instruction->numOperands].cls = PPC_OP_SIMM; - instruction->operands[instruction->numOperands].simm = simm; - ++instruction->numOperands; -} - -static void PushRegister(Instruction* instruction, OperandClass cls, Register reg) -{ - instruction->operands[instruction->numOperands].cls = cls; - instruction->operands[instruction->numOperands].reg = reg; - ++instruction->numOperands; -} - -static uint64_t ComputeBranchTarget(Instruction* instruction, uint64_t address, uint32_t word32) -{ - int32_t bd = (int32_t)((int16_t)(word32 & 0xfffc)); - - return instruction->flags.aa ? bd : address + bd; -} - -static void PushLabel(Instruction* instruction, uint64_t address) -{ - instruction->operands[instruction->numOperands].cls = PPC_OP_LABEL; - instruction->operands[instruction->numOperands].label = address; - ++instruction->numOperands; -} - -// this assumes that instruction->flags.aa has been properly set! -static void PushBranchTarget(Instruction* instruction, uint64_t address, uint32_t word32) -{ - PushLabel(instruction, ComputeBranchTarget(instruction, address, word32)); -} - -static uint32_t GetA(uint32_t word32) -{ - return (word32 >> 16) & 0x1f; -} - -static uint32_t GetB(uint32_t word32) -{ - return (word32 >> 11) & 0x1f; -} - -static uint32_t GetC(uint32_t word32) -{ - return (word32 >> 6) & 0x1f; -} - -static uint32_t GetD(uint32_t word32) -{ - return (word32 >> 21) & 0x1f; -} - -static uint32_t GetS(uint32_t word32) -{ - return (word32 >> 21) & 0x1f; -} - -static void PushRA(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_RA, Gpr(GetA(word32))); -} - -static void PushRAor0(Instruction* instruction, uint32_t word32) -{ - uint32_t ra = GetA(word32); - - if (ra == 0) - PushUIMMValue(instruction, 0); - else - PushRegister(instruction, PPC_OP_REG_RA, Gpr(ra)); -} - -static void PushRB(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_RB, Gpr(GetB(word32))); -} - -static void PushRC(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_RC, Gpr(GetC(word32))); -} - -static void PushRD(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_RD, Gpr(GetD(word32))); -} - -static void PushRS(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_RS, Gpr(GetS(word32))); -} - -static void PushFRA(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_FRA, Fr(GetA(word32))); -} - -static void PushFRB(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_FRB, Fr(GetB(word32))); -} - -static void PushFRC(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_FRC, Fr(GetC(word32))); -} - -static void PushFRD(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_FRD, Fr(GetD(word32))); -} - -static void PushFRS(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_FRS, Fr(GetS(word32))); -} - -static void PushCRFD(Instruction* instruction, uint32_t word32) -{ - uint32_t crfd = (word32 >> 23) & 0x7; - PushRegister(instruction, PPC_OP_REG_CRFD, Crf(crfd)); -} - -static void PushCRFDImplyCR0(Instruction* instruction, uint32_t word32) -{ - uint32_t crfd = (word32 >> 23) & 0x7; - - PushRegister(instruction, PPC_OP_REG_CRFD_IMPLY0, Crf(crfd)); -} - -static void PushCRFS(Instruction* instruction, uint32_t word32) -{ - uint32_t crfs = (word32 >> 18) & 0x7; - PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crfs)); -} - -static void PushCRBitA(Instruction* instruction, uint32_t word32) -{ - instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_A; - instruction->operands[instruction->numOperands].crbit = GetA(word32); - ++instruction->numOperands; -} - -static void PushCRBitB(Instruction* instruction, uint32_t word32) -{ - instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_B; - instruction->operands[instruction->numOperands].crbit = GetB(word32); - ++instruction->numOperands; -} - -static void PushCRBitD(Instruction* instruction, uint32_t word32) -{ - instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_D; - instruction->operands[instruction->numOperands].crbit = GetD(word32); - ++instruction->numOperands; -} - -static void PushMem(Instruction* instruction, OperandClass cls, Register reg, int32_t offset) -{ - instruction->operands[instruction->numOperands].cls = cls; - instruction->operands[instruction->numOperands].mem.reg = reg; - instruction->operands[instruction->numOperands].mem.offset = offset; - ++instruction->numOperands; -} - -static uint32_t GetBI(uint32_t word32) -{ - return (word32 >> 16) & 0x1f; -} - -static uint32_t GetBO(uint32_t word32) -{ - return (word32 >> 21) & 0x1f; -} - -static void FillBranchLikelyHint(Instruction* instruction, uint32_t word32) -{ - uint32_t bo = GetBO(word32); - - switch (bo >> 2) - { - // 001at - // 011at - case 1: - case 3: - instruction->flags.branchLikelyHint = bo & 0x3; - break; - - // 1a00t - // 1a01t - case 4: - case 6: - instruction->flags.branchLikelyHint = ((bo >> 2) & 0x2) | (bo & 0x1); - break; - - // all others don't have hints - default: - instruction->flags.branchLikelyHint = 0; - } -} - -static void PushMemRA(Instruction* instruction, uint32_t word32) -{ - int32_t offset = (int32_t)((int16_t)(word32 & 0xffff)); - PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), offset); -} - -static uint32_t GetVsxA(uint32_t word32) -{ - uint32_t ax = (word32 >> 2) & 0x1; - uint32_t a = (word32 >> 16) & 0x1f; - - return (ax << 5) | a; -} - -static void PushVsxA(Instruction* instruction, uint32_t word32, VsxWidth width) -{ - PushRegister(instruction, - width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RA : PPC_OP_REG_VSX_RA_DWORD0, - VsxVr(GetVsxA(word32))); -} - -static void PushVsxHiA(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_VSX_RA, VsxVrHi(GetA(word32))); -} - -static uint32_t GetVsxB(uint32_t word32) -{ - uint32_t bx = (word32 >> 1) & 0x1; - uint32_t b = (word32 >> 11) & 0x1f; - - return (bx << 5) | b; -} - -static void PushVsxB(Instruction* instruction, uint32_t word32, VsxWidth width) -{ - PushRegister(instruction, - width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RB : PPC_OP_REG_VSX_RB_DWORD0, - VsxVr(GetVsxB(word32))); -} - -static void PushVsxHiB(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_VSX_RB, VsxVrHi(GetB(word32))); -} - -static uint32_t GetVsxC(uint32_t word32) -{ - uint32_t cx = (word32 >> 3) & 0x1; - uint32_t c = (word32 >> 6) & 0x1f; - - return (cx << 5) | c; -} - -static void PushVsxC(Instruction* instruction, uint32_t word32, VsxWidth width) -{ - PushRegister(instruction, - width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RC : PPC_OP_REG_VSX_RC_DWORD0, - VsxVr(GetVsxC(word32))); -} - -static uint32_t GetVsxD(uint32_t word32) -{ - uint32_t dx = word32 & 0x1; - uint32_t d = (word32 >> 21) & 0x1f; - - return (dx << 5) | d; -} - -static void PushVsxD(Instruction* instruction, uint32_t word32, VsxWidth width) -{ - PushRegister(instruction, - width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RD : PPC_OP_REG_VSX_RD_DWORD0, - VsxVr(GetVsxD(word32))); -} - -static void PushVsxHiD(Instruction* instruction, uint32_t word32) -{ - PushRegister(instruction, PPC_OP_REG_VSX_RD, VsxVrHi(GetD(word32))); -} - -static void PushVsxS(Instruction* instruction, uint32_t word32, VsxWidth width) -{ - uint32_t sx = word32 & 0x1; - uint32_t s = (word32 >> 21) & 0x1f; - PushRegister(instruction, - width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RS : PPC_OP_REG_VSX_RS_DWORD0, - VsxVr((sx << 5) | s)); -} - -static uint32_t GetSpecialRegisterCommon(uint32_t word32) -{ - uint32_t xr5_9 = (word32 >> 16) & 0x1f; - uint32_t xr0_4 = (word32 >> 11) & 0x1f; - uint32_t xr = (xr0_4 << 5) | xr5_9; - - return xr; -} - -static uint32_t GetME(uint32_t word32) -{ - return (word32 >> 1) & 0x1f; -} - -static uint32_t GetMB(uint32_t word32) -{ - return (word32 >> 6) & 0x1f; -} - -static uint32_t GetSH(uint32_t word32) -{ - return (word32 >> 11) & 0x1f; -} - -static uint32_t GetSH64(uint32_t word32) -{ - uint32_t sh5 = (word32 >> 1) & 0x1; - uint32_t sh4_0 = (word32 >> 11) & 0x1f; - - return (sh5 << 5) | sh4_0; -} - -static uint32_t GetMX64(uint32_t word32) -{ - uint32_t mx = (word32 >> 5) & 0x3f; - - // x <- mx5 || mx[0:5] in powerpc's stupid bit order - return ((mx & 0x1) << 5) | (mx >> 1); -} - -static void PushAltivecVA(Instruction* instruction, uint32_t word32) -{ - uint32_t va = (word32 >> 16) & 0x1f; - PushRegister(instruction, PPC_OP_REG_AV_VA, AltivecVr(va)); -} - -static void PushAltivecVB(Instruction* instruction, uint32_t word32) -{ - uint32_t vb = (word32 >> 11) & 0x1f; - PushRegister(instruction, PPC_OP_REG_AV_VB, AltivecVr(vb)); -} - -static void PushAltivecVC(Instruction* instruction, uint32_t word32) -{ - uint32_t vc = (word32 >> 6) & 0x1f; - PushRegister(instruction, PPC_OP_REG_AV_VC, AltivecVr(vc)); -} - -static void PushAltivecVD(Instruction* instruction, uint32_t word32) -{ - uint32_t vd = (word32 >> 21) & 0x1f; - PushRegister(instruction, PPC_OP_REG_AV_VD, AltivecVr(vd)); -} - -static void PushAltivecVS(Instruction* instruction, uint32_t word32) -{ - uint32_t vs = (word32 >> 21) & 0x1f; - PushRegister(instruction, PPC_OP_REG_AV_VS, AltivecVr(vs)); -} - static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) { uint32_t subop = word32 & 0x3f; @@ -6167,4927 +5754,14 @@ static InstructionId Decode(uint32_t word32, uint32_t decodeFlags) } } -static void FillOperands(Instruction* instruction, uint32_t word32, uint64_t address) +bool Decompose(Instruction* instruction, uint32_t word32, uint64_t address, uint32_t flags) { - switch (instruction->id) - { - // instructions with no operands - case PPC_ID_ATTN: - case PPC_ID_CP_ABORT: - case PPC_ID_DCCCI: - case PPC_ID_ICCCI: - case PPC_ID_ISYNC: - case PPC_ID_LWSYNC: - case PPC_ID_MSGSYNC: - case PPC_ID_NOP: - case PPC_ID_PTESYNC: - case PPC_ID_RFCI: - case PPC_ID_RFDI: - case PPC_ID_RFI: - case PPC_ID_RFID: - case PPC_ID_RFMCI: - case PPC_ID_SYNC: - case PPC_ID_TLBIA: - case PPC_ID_TLBSYNC: - case PPC_ID_TRAP: - case PPC_ID_TRECHKPT: - case PPC_ID_SLBIA: - case PPC_ID_SLBSYNC: - case PPC_ID_XNOP: - case PPC_ID_WAITIMPL: - case PPC_ID_WAITRSV: - case PPC_ID_AV_DSSALL: - break; - - // rD - case PPC_ID_LNIA: - case PPC_ID_MFBR0: - case PPC_ID_MFBR1: - case PPC_ID_MFBR2: - case PPC_ID_MFBR3: - case PPC_ID_MFBR4: - case PPC_ID_MFBR5: - case PPC_ID_MFBR6: - case PPC_ID_MFBR7: - case PPC_ID_MFCR: - case PPC_ID_MFCTR: - case PPC_ID_MFLR: - case PPC_ID_MFMSR: - case PPC_ID_MFTBU: - case PPC_ID_MFXER: - PushRD(instruction, word32); - break; - - // rS - case PPC_ID_MTBR0: - case PPC_ID_MTBR1: - case PPC_ID_MTBR2: - case PPC_ID_MTBR3: - case PPC_ID_MTBR4: - case PPC_ID_MTBR5: - case PPC_ID_MTBR6: - case PPC_ID_MTBR7: - case PPC_ID_MTCTR: - case PPC_ID_MTLR: - case PPC_ID_MTMSR: - case PPC_ID_MTMSRD: - case PPC_ID_MTXER: - case PPC_ID_WRTEE: - PushRS(instruction, word32); - break; - - // rA - case PPC_ID_TABORT: - case PPC_ID_TRECLAIM: - PushRA(instruction, word32); - break; - - // rB - case PPC_ID_TLBIEL: - case PPC_ID_TLBLI: - case PPC_ID_SLBIE: - PushRB(instruction, word32); - break; - - // [.] rD, rA (arithmetic) - case PPC_ID_NEGx: - case PPC_ID_SUBFZEx: - case PPC_ID_ADDZEx: - case PPC_ID_SUBFMEx: - case PPC_ID_ADDMEx: - PushRD(instruction, word32); - PushRA(instruction, word32); - - // some of these instructions don't have an "oe" flag, - // but we rely on the fact that those instructions have - // bitmask 0x400 clear in the switch statement on the - instruction->flags.rc = word32 & 0x1; - instruction->flags.oe = (word32 & 0x400) != 0; - break; - - // [.] rD, rA, rB (arithmetic) - case PPC_ID_ADDx: - case PPC_ID_ADDCx: - case PPC_ID_ADDEx: - case PPC_ID_DIVDx: - case PPC_ID_DIVDEx: - case PPC_ID_DIVDEUx: - case PPC_ID_DIVDUx: - case PPC_ID_DIVWx: - case PPC_ID_DIVWEx: - case PPC_ID_DIVWEUx: - case PPC_ID_DIVWUx: - case PPC_ID_MODSD: - case PPC_ID_MODSW: - case PPC_ID_MODUD: - case PPC_ID_MODUW: - case PPC_ID_MULHDx: - case PPC_ID_MULHDUx: - case PPC_ID_MULHWx: - case PPC_ID_MULHWUx: - case PPC_ID_MULLDx: - case PPC_ID_MULLWx: - case PPC_ID_SUBFx: - case PPC_ID_SUBFCx: - case PPC_ID_SUBFEx: - PushRD(instruction, word32); - PushRA(instruction, word32); - PushRB(instruction, word32); - - // some of these instructions don't have an "oe" flag, - // but we rely on the fact that those instructions have - // bitmask 0x400 clear in the switch statement on the - // 0x7ff mask - instruction->flags.rc = word32 & 0x1; - instruction->flags.oe = (word32 & 0x400) != 0; - break; - - - // [.] rA, rS (logical) - case PPC_ID_CNTLZWx: - case PPC_ID_CNTLZDx: - case PPC_ID_CNTTZWx: - case PPC_ID_CNTTZDx: - case PPC_ID_POPCNTB: - case PPC_ID_POPCNTD: - case PPC_ID_POPCNTW: - case PPC_ID_EXTSHx: - case PPC_ID_EXTSBx: - case PPC_ID_EXTSWx: - PushRA(instruction, word32); - PushRS(instruction, word32); - - // not all of these have RC bits, but it gets filtered - // at subop decode step - instruction->flags.rc = word32 & 0x1; - break; - - // [.] rA, rS, rB - case PPC_ID_ANDx: - case PPC_ID_ANDCx: - case PPC_ID_BPERMD: - case PPC_ID_CMPB: - case PPC_ID_ECIWX: - case PPC_ID_ECOWX: - case PPC_ID_EQVx: - case PPC_ID_NANDx: - case PPC_ID_NORx: - case PPC_ID_ORx: - case PPC_ID_ORCx: - case PPC_ID_ROTLWx: - case PPC_ID_ROTLDx: - case PPC_ID_SLDx: - case PPC_ID_SLWx: - case PPC_ID_SRADx: - case PPC_ID_SRAWx: - case PPC_ID_SRDx: - case PPC_ID_SRWx: - case PPC_ID_XORx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushRB(instruction, word32); - - // not all of these have an rc bit, but they just don't - // get recognized at the switch statement with &0x7ff - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_ROTLWIx: - case PPC_ID_SLWIx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, GetSH(word32)); - - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_CLRLWIx: - case PPC_ID_SRWIx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, GetMB(word32)); - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_CLRRWIx: - PushRA(instruction, word32); - PushRS(instruction, word32); - - // me = 31 - n --> n = 31 - me - PushUIMMValue(instruction, 31 - GetME(word32)); - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_RLDCLx: - case PPC_ID_RLDCRx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushRB(instruction, word32); - PushUIMMValue(instruction, GetMX64(word32)); - - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_RLDICx: - case PPC_ID_RLDICLx: - case PPC_ID_RLDICRx: - case PPC_ID_RLDIMIx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, GetSH64(word32)); - PushUIMMValue(instruction, GetMX64(word32)); - - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_CLRLDIx: - case PPC_ID_SRDIx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, GetMX64(word32)); - - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_ROTLDIx: - case PPC_ID_SLDIx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, GetSH64(word32)); + memset(instruction, 0, sizeof *instruction); - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_BCx: - { - uint32_t bo = GetBO(word32); - uint32_t bi = GetBI(word32); - - instruction->flags.lk = word32 & 0x1; - instruction->flags.aa = (word32 & 0x2) != 0; - - // not all BCx have hints, but if they don't, then those - // hints won't be read by anything anyways - FillBranchLikelyHint(instruction, word32); - - PushUIMMValue(instruction, bo); - PushUIMMValue(instruction, bi); - PushBranchTarget(instruction, address, word32); - - break; - } - - // crfD, rA, rB - case PPC_ID_CMPD: - case PPC_ID_CMPEQB: - case PPC_ID_CMPW: - case PPC_ID_CMPLD: - case PPC_ID_CMPLW: - PushCRFDImplyCR0(instruction, word32); - PushRA(instruction, word32); - PushRB(instruction, word32); - break; - - // crfD, rA, SIMM - case PPC_ID_CMPDI: - case PPC_ID_CMPWI: - { - int32_t simm = (int32_t)((int16_t)(word32 & 0xffff)); - - PushCRFDImplyCR0(instruction, word32); - PushRA(instruction, word32); - PushSIMMValue(instruction, simm); - break; - } - - // crfD, rA, UIMM - case PPC_ID_CMPLDI: - case PPC_ID_CMPLWI: - { - uint32_t uimm = word32 & 0xffff; - - PushCRFDImplyCR0(instruction, word32); - PushRA(instruction, word32); - PushUIMMValue(instruction, uimm); - break; - } - - // rA, rB - case PPC_ID_COPY: - case PPC_ID_PASTE: - case PPC_ID_TDEQ: - case PPC_ID_TDGT: - case PPC_ID_TDLGT: - case PPC_ID_TDLLT: - case PPC_ID_TDLT: - case PPC_ID_TDNE: - case PPC_ID_TDU: - case PPC_ID_TLBSX: - case PPC_ID_TWEQ: - case PPC_ID_TWGT: - case PPC_ID_TWLGT: - case PPC_ID_TWLLT: - case PPC_ID_TWLT: - case PPC_ID_TWNE: - case PPC_ID_TWU: - PushRA(instruction, word32); - PushRB(instruction, word32); - break; - - // TO, rA, rB - case PPC_ID_TD: - case PPC_ID_TW: - case PPC_ID_TABORTDC: - case PPC_ID_TABORTWC: - { - uint32_t to = (word32 >> 21) & 0x1f; - - PushUIMMValue(instruction, to); - PushRA(instruction, word32); - PushRB(instruction, word32); - break; - } - - // rA, SIMM - case PPC_ID_TDEQI: - case PPC_ID_TDGTI: - case PPC_ID_TDLGTI: - case PPC_ID_TDLLTI: - case PPC_ID_TDLTI: - case PPC_ID_TDNEI: - case PPC_ID_TDUI: - case PPC_ID_TWEQI: - case PPC_ID_TWGTI: - case PPC_ID_TWLGTI: - case PPC_ID_TWLLTI: - case PPC_ID_TWLTI: - case PPC_ID_TWNEI: - case PPC_ID_TWUI: - { - int32_t simm = (int32_t)((int16_t)(word32 & 0xffff)); - - PushRA(instruction, word32); - PushSIMMValue(instruction, simm); - break; - } - - // TO, rA, SIMM - case PPC_ID_TDI: - case PPC_ID_TWI: - { - uint32_t to = (word32 >> 21) & 0x1f; - int32_t simm = (int32_t)((int16_t)(word32 & 0xffff)); - - PushUIMMValue(instruction, to); - PushRA(instruction, word32); - PushSIMMValue(instruction, simm); - break; - } - - // TO, rA, SIMM - case PPC_ID_TABORTDCI: - case PPC_ID_TABORTWCI: - { - uint32_t to = (word32 >> 21) & 0x1f; - int32_t simm = sign_extend((word32 >> 11) & 0x1f, 5); - - PushUIMMValue(instruction, to); - PushRA(instruction, word32); - PushSIMMValue(instruction, simm); - break; - } - - // rD, rA, SIMM - case PPC_ID_ADDI: - case PPC_ID_MULLI: - case PPC_ID_SUBFIC: - PushRD(instruction, word32); - PushRA(instruction, word32); - PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); - break; - - // rA, rS, UIMM - case PPC_ID_ORI: - case PPC_ID_XORI: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, word32 & 0xffff); - break; - - // differentiated in case it makes sense to use the shifted value as an operand - // (which we do for now since it matches capstone) - // rA, rS, UIMM - case PPC_ID_ORIS: - case PPC_ID_XORIS: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, word32 & 0xffff); - break; - - // rD, d(rA) - case PPC_ID_LBZ: - case PPC_ID_LBZU: - case PPC_ID_LHA: - case PPC_ID_LHAU: - case PPC_ID_LHZ: - case PPC_ID_LHZU: - case PPC_ID_LMW: - case PPC_ID_LWZ: - case PPC_ID_LWZU: - PushRD(instruction, word32); - PushMemRA(instruction, word32); - break; - - // rD, d(rA) (64-bit) - case PPC_ID_LD: - case PPC_ID_LDU: - case PPC_ID_LWA: - { - PushRD(instruction, word32); - - int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); - PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); - break; - } - - // rD, rA, rB (indexed load) - case PPC_ID_LBEPX: - case PPC_ID_LBZCIX: - case PPC_ID_LBZUX: - case PPC_ID_LBZX: - case PPC_ID_LDBRX: - case PPC_ID_LDCIX: - case PPC_ID_LDUX: - case PPC_ID_LDX: - case PPC_ID_LHAUX: - case PPC_ID_LHAX: - case PPC_ID_LHBRX: - case PPC_ID_LHEPX: - case PPC_ID_LHZCIX: - case PPC_ID_LHZX: - case PPC_ID_LHZUX: - case PPC_ID_LSWX: - case PPC_ID_LWAX: - case PPC_ID_LWAUX: - case PPC_ID_LWBRX: - case PPC_ID_LWEPX: - case PPC_ID_LWZCIX: - case PPC_ID_LWZUX: - case PPC_ID_LWZX: - PushRD(instruction, word32); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - // rD, rA, rB, [EH if nonzero] (indexed load) - case PPC_ID_LBARX: - case PPC_ID_LDARX: - case PPC_ID_LHARX: - case PPC_ID_LWARX: - { - PushRD(instruction, word32); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - uint32_t eh = word32 & 0x1; - // NOTE: this breaks with convention by only - // conditionally including EH - if (eh) - PushUIMMValue(instruction, word32 & 0x1); - break; - } - - // rD, rA, FC - case PPC_ID_LDAT: - case PPC_ID_LWAT: - { - uint32_t fc = (word32 >> 11) & 0x1f; - PushRD(instruction, word32); - PushRA(instruction, word32); - PushUIMMValue(instruction, fc); - break; - } - - // rS, rA, FC - case PPC_ID_STDAT: - case PPC_ID_STWAT: - { - uint32_t fc = (word32 >> 11) & 0x1f; - PushRS(instruction, word32); - PushRA(instruction, word32); - PushUIMMValue(instruction, fc); - break; - } - - - // rS, d(RA) - case PPC_ID_STB: - case PPC_ID_STBU: - case PPC_ID_STH: - case PPC_ID_STHU: - case PPC_ID_STMW: - case PPC_ID_STW: - case PPC_ID_STWU: - PushRS(instruction, word32); - PushMemRA(instruction, word32); - break; - - // rS, d(RA) (64-bit) - case PPC_ID_STD: - case PPC_ID_STDU: - { - PushRS(instruction, word32); - - int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); - PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); - break; - } - - // rS, rA, rB (indexed store) - case PPC_ID_STBCX: - case PPC_ID_STBCIX: - case PPC_ID_STBEPX: - case PPC_ID_STBUX: - case PPC_ID_STBX: - case PPC_ID_STDBRX: - case PPC_ID_STDCIX: - case PPC_ID_STDEPX: - case PPC_ID_STDUX: - case PPC_ID_STDX: - case PPC_ID_STHBRX: - case PPC_ID_STHCIX: - case PPC_ID_STHCX: - case PPC_ID_STHEPX: - case PPC_ID_STHUX: - case PPC_ID_STHX: - case PPC_ID_STSWX: - case PPC_ID_STWBRX: - case PPC_ID_STWCIX: - case PPC_ID_STWEPX: - case PPC_ID_STWUX: - case PPC_ID_STWX: - PushRS(instruction, word32); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - // . rS, rA, rB (indexed store with reserve) - case PPC_ID_STDCX: - case PPC_ID_STWCX: - PushRS(instruction, word32); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - instruction->flags.rc = 1; - break; - - // frD, d(rA) - case PPC_ID_LFD: - case PPC_ID_LFDU: - case PPC_ID_LFS: - case PPC_ID_LFSU: - PushFRD(instruction, word32); - PushMemRA(instruction, word32); - break; - - // frD, rA, rB - case PPC_ID_LFDEPX: - case PPC_ID_LFDUX: - case PPC_ID_LFDX: - case PPC_ID_LFIWAX: - case PPC_ID_LFIWZX: - case PPC_ID_LFSUX: - case PPC_ID_LFSX: - PushFRD(instruction, word32); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - // frS, d(rA) - case PPC_ID_STFD: - case PPC_ID_STFDU: - case PPC_ID_STFS: - case PPC_ID_STFSU: - PushFRS(instruction, word32); - PushMemRA(instruction, word32); - break; - - // frS, rA, rB - case PPC_ID_STFDEPX: - case PPC_ID_STFDUX: - case PPC_ID_STFDX: - case PPC_ID_STFIWX: - case PPC_ID_STFSUX: - case PPC_ID_STFSX: - PushFRS(instruction, word32); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - // crfD, crfS - case PPC_ID_MCRF: - case PPC_ID_MCRFS: - PushCRFD(instruction, word32); - PushCRFS(instruction, word32); - break; - - // crbD, crbA - case PPC_ID_CRMOVE: - case PPC_ID_CRNOT: - PushCRBitD(instruction, word32); - PushCRBitA(instruction, word32); - break; - - // crbD, crbA, crbB - case PPC_ID_CRAND: - case PPC_ID_CRANDC: - case PPC_ID_CREQV: - case PPC_ID_CRNAND: - case PPC_ID_CRNOR: - case PPC_ID_CROR: - case PPC_ID_CRORC: - case PPC_ID_CRXOR: - PushCRBitD(instruction, word32); - PushCRBitA(instruction, word32); - PushCRBitB(instruction, word32); - break; - - // crbD - case PPC_ID_CRCLR: - case PPC_ID_CRSET: - PushCRBitD(instruction, word32); - break; - - // crfS - case PPC_ID_MCRXRX: - case PPC_ID_TCHECK: - PushCRFD(instruction, word32); - break; - - // conditional branches to registers - case PPC_ID_BCLRx: - case PPC_ID_BCCTRx: - // not all BCx have hints, but if they don't, then those - // hints won't be read by anything anyways - FillBranchLikelyHint(instruction, word32); - - PushUIMMValue(instruction, GetBO(word32)); - PushUIMMValue(instruction, GetBI(word32)); - - instruction->flags.lk = word32 & 0x1; - break; - - // frD, frA, frB - case PPC_ID_FADDx: - case PPC_ID_FADDSx: - case PPC_ID_FCPSGNx: - case PPC_ID_FDIVx: - case PPC_ID_FDIVSx: - case PPC_ID_FSUBx: - case PPC_ID_FSUBSx: - PushFRD(instruction, word32); - PushFRA(instruction, word32); - PushFRB(instruction, word32); - - instruction->flags.rc = word32 & 0x1; - break; - - // [.] frD, frA, frC - case PPC_ID_FMULx: - case PPC_ID_FMULSx: - PushFRD(instruction, word32); - PushFRA(instruction, word32); - PushFRC(instruction, word32); - - instruction->flags.rc = word32 & 0x1; - break; - - // [.] frD, frA, frC, frB - case PPC_ID_FMADDx: - case PPC_ID_FMADDSx: - case PPC_ID_FMSUBx: - case PPC_ID_FMSUBSx: - case PPC_ID_FNMADDx: - case PPC_ID_FNMADDSx: - case PPC_ID_FNMSUBx: - case PPC_ID_FNMSUBSx: - case PPC_ID_FSELx: - PushFRD(instruction, word32); - PushFRA(instruction, word32); - PushFRC(instruction, word32); - PushFRB(instruction, word32); - - instruction->flags.rc = word32 & 0x1; - break; - - // [.] frD, frB - case PPC_ID_FABSx: - case PPC_ID_FCFIDx: - case PPC_ID_FCFIDSx: - case PPC_ID_FCFIDUx: - case PPC_ID_FCFIDUSx: - case PPC_ID_FCTIDx: - case PPC_ID_FCTIDUx: - case PPC_ID_FCTIDUZx: - case PPC_ID_FCTIDZx: - case PPC_ID_FCTIWx: - case PPC_ID_FCTIWUx: - case PPC_ID_FCTIWUZx: - case PPC_ID_FCTIWZx: - case PPC_ID_FMRx: - case PPC_ID_FNABSx: - case PPC_ID_FNEGx: - case PPC_ID_FREx: - case PPC_ID_FRESx: - case PPC_ID_FRIMx: - case PPC_ID_FRINx: - case PPC_ID_FRIPx: - case PPC_ID_FRIZx: - case PPC_ID_FRSPx: - case PPC_ID_FRSQRTEx: - case PPC_ID_FRSQRTESx: - case PPC_ID_FSQRTx: - case PPC_ID_FSQRTSx: - PushFRD(instruction, word32); - PushFRB(instruction, word32); - - instruction->flags.rc = word32 & 0x1; - break; - - - case PPC_ID_FCMPO: - case PPC_ID_FCMPU: - PushCRFD(instruction, word32); - PushFRA(instruction, word32); - PushFRB(instruction, word32); - break; - - // rD, UIMM (special register) - case PPC_ID_MFDCR: - case PPC_ID_MFPMR: - case PPC_ID_MFSPR: - case PPC_ID_MFTB: - { - uint32_t special = GetSpecialRegisterCommon(word32); - - PushRD(instruction, word32); - PushUIMMValue(instruction, special); - break; - } - - // UIMM, rS (special register) - case PPC_ID_MTDCR: - case PPC_ID_MTPMR: - case PPC_ID_MTSPR: - { - uint32_t special = GetSpecialRegisterCommon(word32); - - PushUIMMValue(instruction, special); - PushRS(instruction, word32); - break; - } - - // rA, rB (cache-related) - case PPC_ID_DCBA: - case PPC_ID_DCBST: - case PPC_ID_DCBSTEP: - case PPC_ID_DCBFL: - case PPC_ID_DCBFLP: - case PPC_ID_DCBI: - case PPC_ID_DCBTSTT: - case PPC_ID_DCBTT: - case PPC_ID_DCBZ: - case PPC_ID_DCBZEP: - case PPC_ID_DCBZL: - case PPC_ID_ICBI: - case PPC_ID_ICBIEP: - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - // CT (cache-related) - case PPC_ID_DCI: - case PPC_ID_ICI: - { - uint32_t ct = (word32 >> 21) & 0xf; - - PushUIMMValue(instruction, ct); - break; - } - - // CT, rA, rB (cache-related) - case PPC_ID_ICBLC: - case PPC_ID_ICBLQ: - case PPC_ID_ICBTLS: - uint32_t ct = (word32 >> 21) & 0xf; - - PushUIMMValue(instruction, ct); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - // TH, rA, rB (cache-related) - case PPC_ID_DCBTEP: - case PPC_ID_DCBTSTEP: - { - uint32_t th = (word32 >> 21) & 0x1f; - PushUIMMValue(instruction, th); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - } - - // rA, rB, TH - case PPC_ID_DCBT: - { - PushRAor0(instruction, word32); - PushRB(instruction, word32); - uint32_t th = (word32 >> 21) & 0x1f; - if (th != 0) - PushUIMMValue(instruction, th); - break; - } - - case PPC_ID_DCBTST: - { - PushRAor0(instruction, word32); - PushRB(instruction, word32); - uint32_t th = (word32 >> 21) & 0x1f; - if (th != 0) - PushUIMMValue(instruction, th); - break; - } - - case PPC_ID_MTFSB0x: - case PPC_ID_MTFSB1x: - { - uint32_t bt = (word32 >> 21) & 0x1f; - - PushUIMMValue(instruction, bt); - instruction->flags.rc = word32 & 0x1; - break; - } - - case PPC_ID_TLBREHI: - case PPC_ID_TLBRELO: - // TODO: this is how capstone disassembles these - // instructions, but some architectures have no - // operands and this is just "tlbre" - PushRD(instruction, word32); - PushRA(instruction, word32); - - break; - - case PPC_ID_TLBWEHI: - case PPC_ID_TLBWELO: - // TODO: this is how capstone disassembles these - // instructions, but some architectures have no - // operands and this is just "tlbwe" - PushRS(instruction, word32); - PushRA(instruction, word32); - - break; - - // one-off instructions - case PPC_ID_ADDICx: - PushRD(instruction, word32); - PushRA(instruction, word32); - PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); - - instruction->flags.rc = (word32 >> 26) == 0x0d; - break; - - case PPC_ID_ADDIS: - // different from other shifted immediates because signed imm - PushRD(instruction, word32); - PushRA(instruction, word32); - PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); - break; - - case PPC_ID_ADDPCIS: - { - PushRD(instruction, word32); - uint64_t d1 = (word32 >> 16) & 0x1f; - uint64_t d0 = (word32 >> 6) & 0x3ff; - uint64_t d2 = word32 & 0x1; - uint64_t d = (d0 << 6) | (d1 << 1) | d2; - PushUIMMValue(instruction, d); - break; - } - - case PPC_ID_ANDI: - // different from other logical immediates because of rc bit - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, word32 & 0xffff); - instruction->flags.rc = 1; - break; - - case PPC_ID_ANDIS: - // different from other logical shifted immediates because of rc bit - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, word32 & 0xffff); - - instruction->flags.rc = 1; - break; - - case PPC_ID_Bx: - { - instruction->flags.lk = word32 & 0x1; - instruction->flags.aa = (word32 & 0x2) != 0; - - uint64_t li = word32 & 0x03fffffc; - li = (uint64_t)(int64_t)sign_extend(li, 26); - uint64_t target = instruction->flags.aa ? li : address + li; - - PushLabel(instruction, target); - - break; - } - - case PPC_ID_CMPRB: - { - PushCRFD(instruction, word32); - - uint32_t l = (word32 >> 21) & 0x1; - PushUIMMValue(instruction, l); - - PushRA(instruction, word32); - PushRB(instruction, word32); - break; - } - - case PPC_ID_DARN: - { - uint32_t l = (word32 >> 16) & 0x3; - PushRD(instruction, word32); - PushUIMMValue(instruction, l); - break; - } - - case PPC_ID_DCBF: - case PPC_ID_DCBFEP: - { - uint32_t l = (word32 >> 21) & 0x3; - PushRAor0(instruction, word32); - PushRB(instruction, word32); - if (l != 0) - PushUIMMValue(instruction, l); - - break; - } - - case PPC_ID_EXTSWSLIx: - { - PushRA(instruction, word32); - PushRS(instruction, word32); - uint32_t sh5 = (word32 >> 1) & 0x1; - uint32_t sh0_4 = (word32 >> 11) & 0x1f; - PushUIMMValue(instruction, (sh5 << 5) | sh0_4); - - instruction->flags.rc = word32 & 0x1; - break; - } - - case PPC_ID_FTDIV: - PushCRFD(instruction, word32); - PushFRA(instruction, word32); - PushFRB(instruction, word32); - break; - - case PPC_ID_FTSQRT: - PushCRFD(instruction, word32); - PushFRB(instruction, word32); - break; - - case PPC_ID_MFBHRBE: - { - uint32_t bhrbe = (word32 >> 11) & 0x3ff; - PushRD(instruction, word32); - PushUIMMValue(instruction, bhrbe); - break; - } - - case PPC_ID_MFOCRF: - { - uint32_t fxm = (word32 >> 12) & 0xff; - - PushRD(instruction, word32); - PushUIMMValue(instruction, fxm); - break; - } - - - case PPC_ID_ICBT: - { - uint32_t ct = (word32 >> 21) & 0xf; - - PushUIMMValue(instruction, ct); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - - break; - } - - case PPC_ID_ISEL: - { - uint32_t bc = (word32 >> 6) & 0x1f; - - PushRD(instruction, word32); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - PushUIMMValue(instruction, bc); - break; - } - - case PPC_ID_LI: - PushRD(instruction, word32); - PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); - break; - - case PPC_ID_LIS: - { - PushRD(instruction, word32); - PushSIMMValue(instruction, (int32_t)(word32 & 0xffff)); - break; - } - - case PPC_ID_LSWI: - { - uint32_t nb = (word32 >> 11) & 0x1f; - - PushRD(instruction, word32); - PushRA(instruction, word32); - PushUIMMValue(instruction, nb); - break; - } - - case PPC_ID_MBAR: - { - uint32_t mo = (word32 >> 21) & 0x1f; - PushUIMMValue(instruction, mo); - break; - } - - case PPC_ID_MFFSx: - case PPC_ID_MFFSCE: - case PPC_ID_MFFSL: - PushFRD(instruction, word32); - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_MFFSCDRN: - case PPC_ID_MFFSCRN: - PushFRD(instruction, word32); - PushFRB(instruction, word32); - break; - - case PPC_ID_MFFSCDRNI: - { - uint32_t drm = (word32 >> 11) & 0x7; - PushFRD(instruction, word32); - PushUIMMValue(instruction, drm); - break; - } - - case PPC_ID_MFFSCRNI: - { - uint32_t rm = (word32 >> 11) & 0x3; - PushFRD(instruction, word32); - PushUIMMValue(instruction, rm); - break; - } - - case PPC_ID_MFSR: - { - uint32_t sr = (word32 >> 16) & 0xf; - - PushRD(instruction, word32); - PushUIMMValue(instruction, sr); - break; - } - - case PPC_ID_MFSRIN: - PushRD(instruction, word32); - PushRB(instruction, word32); - break; - - - case PPC_ID_MRx: - PushRA(instruction, word32); - PushRS(instruction, word32); - - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_MTCRF: - { - uint32_t crm = (word32 >> 12) & 0xff; - - PushUIMMValue(instruction, crm); - PushRS(instruction, word32); - break; - } - - case PPC_ID_MTFSFx: - { - uint32_t w = (word32 >> 16) & 0x1; - uint32_t l = (word32 >> 25) & 0x1; - uint32_t flm = (word32 >> 17) & 0xff; - - PushUIMMValue(instruction, flm); - PushFRB(instruction, word32); - - if (w != 0 || l != 0) - { - PushUIMMValue(instruction, l); - PushUIMMValue(instruction, w); - } - - instruction->flags.rc = word32 & 0x1; - break; - } - - case PPC_ID_MTFSFIx: - { - uint32_t u = (word32 >> 12) & 0xf; - uint32_t w = (word32 >> 16) & 0x1; - - PushCRFD(instruction, word32); - PushUIMMValue(instruction, u); - if (w != 0) - PushUIMMValue(instruction, w); - - instruction->flags.rc = word32 & 0x1; - break; - } - - case PPC_ID_MTOCRF: - { - uint32_t fxm = (word32 >> 12) & 0xff; - - PushRS(instruction, word32); - PushUIMMValue(instruction, fxm); - break; - } - - case PPC_ID_MTSR: - { - uint32_t sr = (word32 >> 16) & 0xf; - - PushUIMMValue(instruction, sr); - PushRS(instruction, word32); - - break; - } - - case PPC_ID_MTSRIN: - PushRS(instruction, word32); - PushRB(instruction, word32); - break; - - case PPC_ID_RLWIMIx: - case PPC_ID_RLWINMx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, GetSH(word32)); - PushUIMMValue(instruction, GetMB(word32)); - PushUIMMValue(instruction, GetME(word32)); - - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_RLWNMx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushRB(instruction, word32); - PushUIMMValue(instruction, GetMB(word32)); - PushUIMMValue(instruction, GetME(word32)); - - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_SC: - { - uint32_t lev = (word32 >> 5) & 0x7f; - if (lev != 0) - PushUIMMValue(instruction, lev); - - break; - } - - case PPC_ID_SETB: - PushRD(instruction, word32); - PushCRFS(instruction, word32); - break; - - case PPC_ID_SLBMFEE: - case PPC_ID_SLBMFEV: - PushRD(instruction, word32); - PushRB(instruction, word32); - break; - - case PPC_ID_SLBMTE: - case PPC_ID_SLBIEG: - PushRS(instruction, word32); - PushRB(instruction, word32); - break; - - case PPC_ID_SRADIx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, GetSH64(word32)); - - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_SRAWIx: - PushRA(instruction, word32); - PushRS(instruction, word32); - PushUIMMValue(instruction, GetSH(word32)); - - instruction->flags.rc = word32 & 0x1; - break; - - case PPC_ID_STSWI: - { - uint32_t nb = (word32 >> 11) & 0x1f; - - PushRS(instruction, word32); - PushRA(instruction, word32); - PushUIMMValue(instruction, nb); - break; - } - - case PPC_ID_TBEGIN: - { - uint32_t r = (word32 >> 21) & 0x1; - - PushUIMMValue(instruction, r); - break; - } - - case PPC_ID_TEND: - { - uint32_t a = (word32 >> 25) & 0x1; - - PushUIMMValue(instruction, a); - break; - } - - case PPC_ID_TLBIE: - PushRB(instruction, word32); - PushRS(instruction, word32); - break; - - case PPC_ID_TLBIVAX: - PushRA(instruction, word32); - PushRB(instruction, word32); - break; - - case PPC_ID_TSR: - { - uint32_t l = (word32 >> 21) & 0x1; - - PushUIMMValue(instruction, l); - break; - } - - case PPC_ID_WAIT: - { - uint32_t wc = (word32 >> 21) & 0x3; - - if (wc != 0) - PushUIMMValue(instruction, wc); - - break; - } - - case PPC_ID_WRTEEI: - { - uint32_t e = (word32 & 0x00008000) != 0; - - PushUIMMValue(instruction, e); - break; - } - - // ALTIVEC INSTRUCTIONS - - // vD, vA, vB, vC - case PPC_ID_AV_VADDECUQ: - case PPC_ID_AV_VADDEUQM: - case PPC_ID_AV_VMHADDSHS: - case PPC_ID_AV_VMHRADDSHS: - case PPC_ID_AV_VMLADDUHM: - case PPC_ID_AV_VSUBECUQ: - case PPC_ID_AV_VSUBEUQM: - case PPC_ID_AV_VMSUMMBM: - case PPC_ID_AV_VMSUMUBM: - case PPC_ID_AV_VMSUMSHM: - case PPC_ID_AV_VMSUMSHS: - case PPC_ID_AV_VMSUMUHM: - case PPC_ID_AV_VMSUMUHS: - case PPC_ID_AV_VPERM: - case PPC_ID_AV_VPERMR: - case PPC_ID_AV_VPERMXOR: - case PPC_ID_AV_VSEL: - PushAltivecVD(instruction, word32); - PushAltivecVA(instruction, word32); - PushAltivecVB(instruction, word32); - PushAltivecVC(instruction, word32); - break; - - // vD, vA, vC, vB (note swapped vC, vB) - case PPC_ID_AV_VMADDFP: - case PPC_ID_AV_VNMSUBFP: - PushAltivecVD(instruction, word32); - PushAltivecVA(instruction, word32); - PushAltivecVC(instruction, word32); - PushAltivecVB(instruction, word32); - break; - - // vD, vA, vB - case PPC_ID_AV_VABSDUB: - case PPC_ID_AV_VABSDUH: - case PPC_ID_AV_VABSDUW: - case PPC_ID_AV_VADDUQM: - case PPC_ID_AV_VADDCUQ: - case PPC_ID_AV_BCDUS: - case PPC_ID_AV_BCDUTRUNC: - case PPC_ID_AV_BCDCPSGN: - case PPC_ID_AV_VADDCUW: - case PPC_ID_AV_VADDFP: - case PPC_ID_AV_VADDSBS: - case PPC_ID_AV_VADDSHS: - case PPC_ID_AV_VADDSWS: - case PPC_ID_AV_VADDUBM: - case PPC_ID_AV_VADDUBS: - case PPC_ID_AV_VADDUDM: - case PPC_ID_AV_VADDUHM: - case PPC_ID_AV_VADDUHS: - case PPC_ID_AV_VADDUWM: - case PPC_ID_AV_VADDUWS: - case PPC_ID_AV_VAND: - case PPC_ID_AV_VANDC: - case PPC_ID_AV_VAVGSB: - case PPC_ID_AV_VAVGSH: - case PPC_ID_AV_VAVGSW: - case PPC_ID_AV_VAVGUB: - case PPC_ID_AV_VAVGUH: - case PPC_ID_AV_VAVGUW: - case PPC_ID_AV_VBPERMD: - case PPC_ID_AV_VBPERMQ: - case PPC_ID_AV_VCIPHER: - case PPC_ID_AV_VCIPHERLAST: - case PPC_ID_AV_VEQV: - case PPC_ID_AV_VMAXFP: - case PPC_ID_AV_VMAXSB: - case PPC_ID_AV_VMAXSD: - case PPC_ID_AV_VMAXSH: - case PPC_ID_AV_VMAXSW: - case PPC_ID_AV_VMAXUB: - case PPC_ID_AV_VMAXUD: - case PPC_ID_AV_VMAXUH: - case PPC_ID_AV_VMAXUW: - case PPC_ID_AV_VMINFP: - case PPC_ID_AV_VMINUB: - case PPC_ID_AV_VMINUD: - case PPC_ID_AV_VMINUH: - case PPC_ID_AV_VMINUW: - case PPC_ID_AV_VMINSB: - case PPC_ID_AV_VMINSD: - case PPC_ID_AV_VMINSH: - case PPC_ID_AV_VMINSW: - case PPC_ID_AV_VMRGEW: - case PPC_ID_AV_VMRGHB: - case PPC_ID_AV_VMRGHH: - case PPC_ID_AV_VMRGHW: - case PPC_ID_AV_VMRGLB: - case PPC_ID_AV_VMRGLH: - case PPC_ID_AV_VMRGLW: - case PPC_ID_AV_VMRGOW: - case PPC_ID_AV_VMUL10EUQ: - case PPC_ID_AV_VMUL10ECUQ: - case PPC_ID_AV_VMULESB: - case PPC_ID_AV_VMULESH: - case PPC_ID_AV_VMULESW: - case PPC_ID_AV_VMULEUB: - case PPC_ID_AV_VMULEUH: - case PPC_ID_AV_VMULEUW: - case PPC_ID_AV_VMULOSB: - case PPC_ID_AV_VMULOSH: - case PPC_ID_AV_VMULOSW: - case PPC_ID_AV_VMULOUB: - case PPC_ID_AV_VMULOUH: - case PPC_ID_AV_VMULOUW: - case PPC_ID_AV_VMULUWM: - case PPC_ID_AV_VNAND: - case PPC_ID_AV_VNCIPHER: - case PPC_ID_AV_VNCIPHERLAST: - case PPC_ID_AV_VNOR: - case PPC_ID_AV_VOR: - case PPC_ID_AV_VORC: - case PPC_ID_AV_VPKPX: - case PPC_ID_AV_VPKSDSS: - case PPC_ID_AV_VPKSDUS: - case PPC_ID_AV_VPKSHSS: - case PPC_ID_AV_VPKSHUS: - case PPC_ID_AV_VPKSWSS: - case PPC_ID_AV_VPKSWUS: - case PPC_ID_AV_VPKUDUM: - case PPC_ID_AV_VPKUDUS: - case PPC_ID_AV_VPKUHUM: - case PPC_ID_AV_VPKUHUS: - case PPC_ID_AV_VPKUWUM: - case PPC_ID_AV_VPKUWUS: - case PPC_ID_AV_VPMSUMB: - case PPC_ID_AV_VPMSUMD: - case PPC_ID_AV_VPMSUMH: - case PPC_ID_AV_VPMSUMW: - case PPC_ID_AV_VRLB: - case PPC_ID_AV_VRLD: - case PPC_ID_AV_VRLDMI: - case PPC_ID_AV_VRLDNM: - case PPC_ID_AV_VRLH: - case PPC_ID_AV_VRLW: - case PPC_ID_AV_VRLWMI: - case PPC_ID_AV_VRLWNM: - case PPC_ID_AV_VSL: - case PPC_ID_AV_VSLB: - case PPC_ID_AV_VSLD: - case PPC_ID_AV_VSLH: - case PPC_ID_AV_VSLO: - case PPC_ID_AV_VSLV: - case PPC_ID_AV_VSLW: - case PPC_ID_AV_VSR: - case PPC_ID_AV_VSRAB: - case PPC_ID_AV_VSRAD: - case PPC_ID_AV_VSRAH: - case PPC_ID_AV_VSRAW: - case PPC_ID_AV_VSRB: - case PPC_ID_AV_VSRD: - case PPC_ID_AV_VSRH: - case PPC_ID_AV_VSRO: - case PPC_ID_AV_VSRV: - case PPC_ID_AV_VSRW: - case PPC_ID_AV_VSUBCUQ: - case PPC_ID_AV_VSUBCUW: - case PPC_ID_AV_VSUBFP: - case PPC_ID_AV_VSUBSBS: - case PPC_ID_AV_VSUBSHS: - case PPC_ID_AV_VSUBSWS: - case PPC_ID_AV_VSUBUBS: - case PPC_ID_AV_VSUBUHS: - case PPC_ID_AV_VSUBUQM: - case PPC_ID_AV_VSUBUWS: - case PPC_ID_AV_VSUBUBM: - case PPC_ID_AV_VSUBUDM: - case PPC_ID_AV_VSUBUHM: - case PPC_ID_AV_VSUBUWM: - case PPC_ID_AV_VSUM2SWS: - case PPC_ID_AV_VSUM4SBS: - case PPC_ID_AV_VSUM4SHS: - case PPC_ID_AV_VSUM4UBS: - case PPC_ID_AV_VSUMSWS: - case PPC_ID_AV_VXOR: - PushAltivecVD(instruction, word32); - PushAltivecVA(instruction, word32); - PushAltivecVB(instruction, word32); - break; - - // [.] vD, vA, vB - case PPC_ID_AV_VCMPBFPx: - case PPC_ID_AV_VCMPEQFPx: - case PPC_ID_AV_VCMPGEFPx: - case PPC_ID_AV_VCMPEQUBx: - case PPC_ID_AV_VCMPEQUDx: - case PPC_ID_AV_VCMPEQUHx: - case PPC_ID_AV_VCMPEQUWx: - case PPC_ID_AV_VCMPGTFPx: - case PPC_ID_AV_VCMPGTSBx: - case PPC_ID_AV_VCMPGTSDx: - case PPC_ID_AV_VCMPGTSHx: - case PPC_ID_AV_VCMPGTSWx: - case PPC_ID_AV_VCMPGTUBx: - case PPC_ID_AV_VCMPGTUDx: - case PPC_ID_AV_VCMPGTUHx: - case PPC_ID_AV_VCMPGTUWx: - case PPC_ID_AV_VCMPNEBx: - case PPC_ID_AV_VCMPNEHx: - case PPC_ID_AV_VCMPNEWx: - case PPC_ID_AV_VCMPNEZBx: - case PPC_ID_AV_VCMPNEZHx: - case PPC_ID_AV_VCMPNEZWx: - PushAltivecVD(instruction, word32); - PushAltivecVA(instruction, word32); - PushAltivecVB(instruction, word32); - - instruction->flags.rc = (word32 >> 10) & 0x1; - break; - - // vD, vA - case PPC_ID_AV_VMUL10CUQ: - case PPC_ID_AV_VMUL10UQ: - case PPC_ID_AV_VSBOX: - PushAltivecVD(instruction, word32); - PushAltivecVA(instruction, word32); - break; - - // vD, vB - case PPC_ID_AV_BCDCTN: - case PPC_ID_AV_BCDCTSQ: - case PPC_ID_AV_VCLZB: - case PPC_ID_AV_VCLZD: - case PPC_ID_AV_VCLZH: - case PPC_ID_AV_VCLZW: - case PPC_ID_AV_VCTZB: - case PPC_ID_AV_VCTZD: - case PPC_ID_AV_VCTZH: - case PPC_ID_AV_VCTZW: - case PPC_ID_AV_VEXPTEFP: - case PPC_ID_AV_VEXTSB2D: - case PPC_ID_AV_VEXTSB2W: - case PPC_ID_AV_VEXTSH2D: - case PPC_ID_AV_VEXTSH2W: - case PPC_ID_AV_VEXTSW2D: - case PPC_ID_AV_VGBBD: - case PPC_ID_AV_VLOGEFP: - case PPC_ID_AV_VMR: - case PPC_ID_AV_VNEGD: - case PPC_ID_AV_VNEGW: - case PPC_ID_AV_VNOT: - case PPC_ID_AV_VPOPCNTB: - case PPC_ID_AV_VPOPCNTD: - case PPC_ID_AV_VPOPCNTH: - case PPC_ID_AV_VPOPCNTW: - case PPC_ID_AV_VPRTYBD: - case PPC_ID_AV_VPRTYBQ: - case PPC_ID_AV_VPRTYBW: - case PPC_ID_AV_VREFP: - case PPC_ID_AV_VRFIM: - case PPC_ID_AV_VRFIN: - case PPC_ID_AV_VRFIP: - case PPC_ID_AV_VRFIZ: - case PPC_ID_AV_VRSQRTEFP: - case PPC_ID_AV_VUPKHPX: - case PPC_ID_AV_VUPKHSB: - case PPC_ID_AV_VUPKHSH: - case PPC_ID_AV_VUPKHSW: - case PPC_ID_AV_VUPKLPX: - case PPC_ID_AV_VUPKLSB: - case PPC_ID_AV_VUPKLSH: - case PPC_ID_AV_VUPKLSW: - PushAltivecVD(instruction, word32); - PushAltivecVB(instruction, word32); - break; - - // vD, vB, UIMM - case PPC_ID_AV_VCFSX: - case PPC_ID_AV_VCFUX: - case PPC_ID_AV_VCTSXS: - case PPC_ID_AV_VCTUXS: - case PPC_ID_AV_VSPLTB: - case PPC_ID_AV_VSPLTH: - case PPC_ID_AV_VSPLTW: - PushAltivecVD(instruction, word32); - PushAltivecVB(instruction, word32); - PushUIMMValue(instruction, (word32 >> 16) & 0x1f); - break; - - // vD, SIMM - case PPC_ID_AV_VSPLTISB: - case PPC_ID_AV_VSPLTISH: - case PPC_ID_AV_VSPLTISW: - { - PushAltivecVD(instruction, word32); - - int32_t simm = sign_extend((word32 >> 16) & 0x1f, 5); - PushSIMMValue(instruction, simm); - break; - } - - // vD, d(rA) - case PPC_ID_AV_LVEBX: - case PPC_ID_AV_LVEHX: - case PPC_ID_AV_LVEWX: - case PPC_ID_AV_LVSL: - case PPC_ID_AV_LVSR: - case PPC_ID_AV_LVX: - case PPC_ID_AV_LVXL: - PushAltivecVD(instruction, word32); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - // vS, d(rA) - case PPC_ID_AV_STVEBX: - case PPC_ID_AV_STVEHX: - case PPC_ID_AV_STVEWX: - case PPC_ID_AV_STVX: - case PPC_ID_AV_STVXL: - PushAltivecVS(instruction, word32); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - case PPC_ID_AV_DST: - case PPC_ID_AV_DSTST: - case PPC_ID_AV_DSTSTT: - case PPC_ID_AV_DSTT: - { - uint32_t strm = (word32 >> 21) & 0x3; - - PushRA(instruction, word32); - PushRB(instruction, word32); - PushUIMMValue(instruction, strm); - break; - } - - case PPC_ID_AV_DSS: - { - uint32_t strm = (word32 >> 21) & 0x3; - PushUIMMValue(instruction, strm); - break; - } - - case PPC_ID_AV_MFVSCR: - // mfvscr vD - PushAltivecVD(instruction, word32); - break; - - case PPC_ID_AV_MTVSCR: - // mtvscr vB - PushAltivecVB(instruction, word32); - break; - - case PPC_ID_AV_VSLDOI: - // vsldoi vD, vA, vB, UIMM - PushAltivecVD(instruction, word32); - PushAltivecVA(instruction, word32); - PushAltivecVB(instruction, word32); - PushUIMMValue(instruction, (word32 >> 6) & 0xf); - break; - - // rD, rA, rB, rC (normal registers) - case PPC_ID_AV_MADDHD: - case PPC_ID_AV_MADDHDU: - case PPC_ID_AV_MADDLD: - PushRD(instruction, word32); - PushRA(instruction, word32); - PushRB(instruction, word32); - PushRC(instruction, word32); - break; - - // vrD, vrA, vrB, ps - case PPC_ID_AV_BCDADD: - case PPC_ID_AV_BCDSUB: - case PPC_ID_AV_BCDS: - case PPC_ID_AV_BCDSR: - case PPC_ID_AV_BCDTRUNC: - { - PushAltivecVD(instruction, word32); - PushAltivecVA(instruction, word32); - PushAltivecVB(instruction, word32); - uint32_t ps = (word32 & 0x200) != 0; - PushUIMMValue(instruction, ps); - break; - } - - - // vrD, vrB, ps - case PPC_ID_AV_BCDCFN: - case PPC_ID_AV_BCDCFZ: - case PPC_ID_AV_BCDCTZ: - case PPC_ID_AV_BCDCFSQ: - case PPC_ID_AV_BCDSETSGN: - // PS isn't in all of these instructions, but it gets - // filtered out in subop decode - PushAltivecVD(instruction, word32); - PushAltivecVB(instruction, word32); - uint32_t ps = (word32 & 0x200) != 0; - PushUIMMValue(instruction, ps); - break; - - - // vrD, vrB, UIM - case PPC_ID_AV_VEXTRACTD: - case PPC_ID_AV_VEXTRACTUB: - case PPC_ID_AV_VEXTRACTUH: - case PPC_ID_AV_VEXTRACTUW: - case PPC_ID_AV_VINSERTB: - case PPC_ID_AV_VINSERTD: - case PPC_ID_AV_VINSERTH: - case PPC_ID_AV_VINSERTW: - PushAltivecVD(instruction, word32); - PushAltivecVB(instruction, word32); - PushUIMMValue(instruction, (word32 >> 16) & 0xf); - break; - - // rD, rA, vB - case PPC_ID_AV_VEXTUBLX: - case PPC_ID_AV_VEXTUHLX: - case PPC_ID_AV_VEXTUWLX: - case PPC_ID_AV_VEXTUBRX: - case PPC_ID_AV_VEXTUHRX: - case PPC_ID_AV_VEXTUWRX: - PushRD(instruction, word32); - PushRA(instruction, word32); - PushAltivecVB(instruction, word32); - break; - - // vD, vA, ST, SIX - case PPC_ID_AV_VSHASIGMAD: - case PPC_ID_AV_VSHASIGMAW: - PushAltivecVD(instruction, word32); - PushAltivecVA(instruction, word32); - PushUIMMValue(instruction, (word32 >> 15) & 0x1); - PushUIMMValue(instruction, (word32 >> 11) & 0xf); - break; - - // rD, vB - case PPC_ID_AV_VCLZLSBB: - case PPC_ID_AV_VCTZLSBB: - PushRD(instruction, word32); - PushAltivecVB(instruction, word32); - break; - - // VSX INSTRUCTIONS - - // vrD, vrA, vrB - case PPC_ID_VSX_XVADDDP: - case PPC_ID_VSX_XVADDSP: - case PPC_ID_VSX_XVCPSGNDP: - case PPC_ID_VSX_XVCPSGNSP: - case PPC_ID_VSX_XVDIVDP: - case PPC_ID_VSX_XVDIVSP: - case PPC_ID_VSX_XVIEXPDP: - case PPC_ID_VSX_XVIEXPSP: - case PPC_ID_VSX_XVMADDADP: - case PPC_ID_VSX_XVMADDASP: - case PPC_ID_VSX_XVMADDMDP: - case PPC_ID_VSX_XVMADDMSP: - case PPC_ID_VSX_XVMAXDP: - case PPC_ID_VSX_XVMAXSP: - case PPC_ID_VSX_XVMINDP: - case PPC_ID_VSX_XVMINSP: - case PPC_ID_VSX_XVMSUBADP: - case PPC_ID_VSX_XVMSUBMDP: - case PPC_ID_VSX_XVMSUBASP: - case PPC_ID_VSX_XVMSUBMSP: - case PPC_ID_VSX_XVMULDP: - case PPC_ID_VSX_XVMULSP: - case PPC_ID_VSX_XVNMADDADP: - case PPC_ID_VSX_XVNMADDASP: - case PPC_ID_VSX_XVNMADDMDP: - case PPC_ID_VSX_XVNMADDMSP: - case PPC_ID_VSX_XVNMSUBADP: - case PPC_ID_VSX_XVNMSUBASP: - case PPC_ID_VSX_XVNMSUBMDP: - case PPC_ID_VSX_XVNMSUBMSP: - case PPC_ID_VSX_XVSUBDP: - case PPC_ID_VSX_XVSUBSP: - case PPC_ID_VSX_XXLAND: - case PPC_ID_VSX_XXLANDC: - case PPC_ID_VSX_XXLEQV: - case PPC_ID_VSX_XXLOR: - case PPC_ID_VSX_XXLNAND: - case PPC_ID_VSX_XXLNOR: - case PPC_ID_VSX_XXLORC: - case PPC_ID_VSX_XXLXOR: - case PPC_ID_VSX_XXMRGHD: - case PPC_ID_VSX_XXMRGHW: - case PPC_ID_VSX_XXMRGLD: - case PPC_ID_VSX_XXMRGLW: - case PPC_ID_VSX_XXPERM: - case PPC_ID_VSX_XXPERMR: - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushVsxA(instruction, word32, VSX_WIDTH_FULL); - PushVsxB(instruction, word32, VSX_WIDTH_FULL); - break; - - // [.] vrD, rA, vrB - case PPC_ID_VSX_XVCMPEQDPx: - case PPC_ID_VSX_XVCMPEQSPx: - case PPC_ID_VSX_XVCMPGEDPx: - case PPC_ID_VSX_XVCMPGESPx: - case PPC_ID_VSX_XVCMPGTDPx: - case PPC_ID_VSX_XVCMPGTSPx: - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushVsxA(instruction, word32, VSX_WIDTH_FULL); - PushVsxB(instruction, word32, VSX_WIDTH_FULL); - instruction->flags.rc = (word32 & 0x400) != 0; - break; - - // vrD, vrA, vrB - case PPC_ID_VSX_XSADDSP: - case PPC_ID_VSX_XSADDDP: - case PPC_ID_VSX_XSCMPEQDP: - case PPC_ID_VSX_XSCMPGEDP: - case PPC_ID_VSX_XSCMPGTDP: - case PPC_ID_VSX_XSCPSGNDP: - case PPC_ID_VSX_XSDIVDP: - case PPC_ID_VSX_XSDIVSP: - case PPC_ID_VSX_XSMADDADP: - case PPC_ID_VSX_XSMADDMDP: - case PPC_ID_VSX_XSMADDASP: - case PPC_ID_VSX_XSMADDMSP: - case PPC_ID_VSX_XSMAXCDP: - case PPC_ID_VSX_XSMAXDP: - case PPC_ID_VSX_XSMAXJDP: - case PPC_ID_VSX_XSMINCDP: - case PPC_ID_VSX_XSMINDP: - case PPC_ID_VSX_XSMINJDP: - case PPC_ID_VSX_XSMSUBADP: - case PPC_ID_VSX_XSMSUBASP: - case PPC_ID_VSX_XSMSUBMDP: - case PPC_ID_VSX_XSMSUBMSP: - case PPC_ID_VSX_XSMULDP: - case PPC_ID_VSX_XSMULSP: - case PPC_ID_VSX_XSNMADDADP: - case PPC_ID_VSX_XSNMADDASP: - case PPC_ID_VSX_XSNMADDMDP: - case PPC_ID_VSX_XSNMADDMSP: - case PPC_ID_VSX_XSNMSUBADP: - case PPC_ID_VSX_XSNMSUBASP: - case PPC_ID_VSX_XSNMSUBMDP: - case PPC_ID_VSX_XSNMSUBMSP: - case PPC_ID_VSX_XSSUBDP: - case PPC_ID_VSX_XSSUBSP: - PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); - PushVsxA(instruction, word32, VSX_WIDTH_DWORD0); - PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); - break; - - // vrD, vrB - case PPC_ID_VSX_XVABSDP: - case PPC_ID_VSX_XVABSSP: - case PPC_ID_VSX_XVCVDPSP: - case PPC_ID_VSX_XVCVDPSXDS: - case PPC_ID_VSX_XVCVDPSXWS: - case PPC_ID_VSX_XVCVDPUXDS: - case PPC_ID_VSX_XVCVDPUXWS: - case PPC_ID_VSX_XVCVSPDP: - case PPC_ID_VSX_XVCVSPSXDS: - case PPC_ID_VSX_XVCVSPSXWS: - case PPC_ID_VSX_XVCVSPUXDS: - case PPC_ID_VSX_XVCVSPUXWS: - case PPC_ID_VSX_XVCVSXDDP: - case PPC_ID_VSX_XVCVSXDSP: - case PPC_ID_VSX_XVCVSXWDP: - case PPC_ID_VSX_XVCVSXWSP: - case PPC_ID_VSX_XVCVUXDDP: - case PPC_ID_VSX_XVCVUXDSP: - case PPC_ID_VSX_XVCVUXWDP: - case PPC_ID_VSX_XVCVUXWSP: - case PPC_ID_VSX_XVNABSDP: - case PPC_ID_VSX_XVNABSSP: - case PPC_ID_VSX_XVNEGDP: - case PPC_ID_VSX_XVNEGSP: - case PPC_ID_VSX_XVRDPI: - case PPC_ID_VSX_XVRDPIC: - case PPC_ID_VSX_XVRDPIM: - case PPC_ID_VSX_XVRDPIP: - case PPC_ID_VSX_XVRDPIZ: - case PPC_ID_VSX_XVREDP: - case PPC_ID_VSX_XVRESP: - case PPC_ID_VSX_XVRSPI: - case PPC_ID_VSX_XVRSPIC: - case PPC_ID_VSX_XVRSPIM: - case PPC_ID_VSX_XVRSPIP: - case PPC_ID_VSX_XVRSPIZ: - case PPC_ID_VSX_XVRSQRTEDP: - case PPC_ID_VSX_XVRSQRTESP: - case PPC_ID_VSX_XVSQRTSP: - case PPC_ID_VSX_XVSQRTDP: - case PPC_ID_VSX_XVMOVDP: - case PPC_ID_VSX_XVMOVSP: - case PPC_ID_VSX_XVXEXPDP: - case PPC_ID_VSX_XVXEXPSP: - case PPC_ID_VSX_XVXSIGDP: - case PPC_ID_VSX_XVXSIGSP: - case PPC_ID_VSX_XXBRD: - case PPC_ID_VSX_XXBRH: - case PPC_ID_VSX_XXBRQ: - case PPC_ID_VSX_XXBRW: - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushVsxB(instruction, word32, VSX_WIDTH_FULL); - break; - - // vrD, vrB - case PPC_ID_VSX_XSABSDP: - case PPC_ID_VSX_XSCVDPHP: - case PPC_ID_VSX_XSCVDPSXDS: - case PPC_ID_VSX_XSCVDPSP: - case PPC_ID_VSX_XSCVDPSPN: - case PPC_ID_VSX_XSCVDPSXWS: - case PPC_ID_VSX_XSCVDPUXDS: - case PPC_ID_VSX_XSCVDPUXWS: - case PPC_ID_VSX_XSCVSPDP: - case PPC_ID_VSX_XSCVHPDP: - case PPC_ID_VSX_XSCVSPDPN: - case PPC_ID_VSX_XSCVSXDDP: - case PPC_ID_VSX_XSCVSXDSP: - case PPC_ID_VSX_XSCVUXDDP: - case PPC_ID_VSX_XSCVUXDSP: - case PPC_ID_VSX_XSNABSDP: - case PPC_ID_VSX_XSNEGDP: - case PPC_ID_VSX_XSRDPI: - case PPC_ID_VSX_XSRDPIC: - case PPC_ID_VSX_XSRDPIM: - case PPC_ID_VSX_XSRDPIP: - case PPC_ID_VSX_XSRDPIZ: - case PPC_ID_VSX_XSREDP: - case PPC_ID_VSX_XSRESP: - case PPC_ID_VSX_XSRSP: - case PPC_ID_VSX_XSRSQRTESP: - case PPC_ID_VSX_XSRSQRTEDP: - case PPC_ID_VSX_XSSQRTDP: - case PPC_ID_VSX_XSSQRTSP: - case PPC_ID_VSX_XVCVHPSP: - case PPC_ID_VSX_XVCVSPHP: - PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); - PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); - break; - - // vrD, vrA, vrB, - case PPC_ID_VSX_XXPERMDI: - case PPC_ID_VSX_XXSLDWI: - { - uint32_t uimm = (word32 >> 8) & 0x3; - - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushVsxA(instruction, word32, VSX_WIDTH_FULL); - PushVsxB(instruction, word32, VSX_WIDTH_FULL); - PushUIMMValue(instruction, uimm); - break; - } - - // vrD, rA, rB - case PPC_ID_VSX_MTVSRDD: - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - // vrD, rA, rB (load indexed) - case PPC_ID_VSX_LXVB16X: - case PPC_ID_VSX_LXVD2X: - case PPC_ID_VSX_LXVDSX: - case PPC_ID_VSX_LXVH8X: - case PPC_ID_VSX_LXVL: - case PPC_ID_VSX_LXVLL: - case PPC_ID_VSX_LXVW4X: - case PPC_ID_VSX_LXVWSX: - case PPC_ID_VSX_LXVX: - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - case PPC_ID_VSX_LXSDX: - case PPC_ID_VSX_LXSIBZX: - case PPC_ID_VSX_LXSIHZX: - case PPC_ID_VSX_LXSIWAX: - case PPC_ID_VSX_LXSIWZX: - case PPC_ID_VSX_LXSSPX: - PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - // vrS, rA, rB (store indexed) - case PPC_ID_VSX_STXVB16X: - case PPC_ID_VSX_STXVD2X: - case PPC_ID_VSX_STXVH8X: - case PPC_ID_VSX_STXVL: - case PPC_ID_VSX_STXVLL: - case PPC_ID_VSX_STXVW4X: - case PPC_ID_VSX_STXVX: - PushVsxS(instruction, word32, VSX_WIDTH_FULL); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - case PPC_ID_VSX_STXSDX: - case PPC_ID_VSX_STXSIBX: - case PPC_ID_VSX_STXSIHX: - case PPC_ID_VSX_STXSIWX: - case PPC_ID_VSX_STXSSPX: - PushVsxS(instruction, word32, VSX_WIDTH_DWORD0); - PushRAor0(instruction, word32); - PushRB(instruction, word32); - break; - - // crfD, vrA, vrB - case PPC_ID_VSX_XSCMPEXPDP: - case PPC_ID_VSX_XSCMPODP: - case PPC_ID_VSX_XSCMPUDP: - case PPC_ID_VSX_XSTDIVDP: - PushCRFD(instruction, word32); - PushVsxA(instruction, word32, VSX_WIDTH_DWORD0); - PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); - break; - - // crfD, vrA, vrB - case PPC_ID_VSX_XVTDIVDP: - case PPC_ID_VSX_XVTDIVSP: - PushCRFD(instruction, word32); - PushVsxA(instruction, word32, VSX_WIDTH_FULL); - PushVsxB(instruction, word32, VSX_WIDTH_FULL); - break; - - // crfD, vrB - case PPC_ID_VSX_XVTSQRTSP: - case PPC_ID_VSX_XVTSQRTDP: - PushCRFD(instruction, word32); - PushVsxB(instruction, word32, VSX_WIDTH_FULL); - break; - - case PPC_ID_VSX_XSTSQRTDP: - PushCRFD(instruction, word32); - PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); - break; - - // vrD, rA - case PPC_ID_VSX_MTVSRWS: - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushRA(instruction, word32); - break; - - case PPC_ID_VSX_MTVSRD: - case PPC_ID_VSX_MTVSRWA: - case PPC_ID_VSX_MTVSRWZ: - PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); - PushRA(instruction, word32); - break; - - // rA, vrS - case PPC_ID_VSX_MFVSRLD: - PushRA(instruction, word32); - PushVsxS(instruction, word32, VSX_WIDTH_FULL); - break; - - case PPC_ID_VSX_MFFPRD: - case PPC_ID_VSX_MFVSRWZ: - case PPC_ID_VSX_MFVSRD: - PushRA(instruction, word32); - PushVsxS(instruction, word32, VSX_WIDTH_DWORD0); - break; - - // vrD, vrB, UIM - case PPC_ID_VSX_XXINSERTW: - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushVsxB(instruction, word32, VSX_WIDTH_FULL); - PushUIMMValue(instruction, (word32 >> 16) & 0xf); - break; - - case PPC_ID_VSX_XXEXTRACTUW: - PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); - PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); - PushUIMMValue(instruction, (word32 >> 16) & 0xf); - break; - - case PPC_ID_VSX_LXV: - { - uint32_t dx = (word32 >> 3) & 0x1; - uint32_t d = GetD(word32); - uint32_t vsxd = (dx << 5) | d; - - PushRegister(instruction, PPC_OP_REG_VSX_RD, VsxVr(vsxd)); - - uint32_t dq = (int32_t)((int16_t)(word32 & 0xfff0)); - PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), dq); - - break; - } - - case PPC_ID_VSX_STXV: - { - uint32_t sx = (word32 >> 3) & 0x1; - uint32_t s = GetS(word32); - uint32_t vsxs = (sx << 5) | s; - - PushRegister(instruction, PPC_OP_REG_VSX_RS, VsxVr(vsxs)); - - int32_t dq = (int32_t)((int16_t)(word32 & 0xfff0)); - PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), dq); - - break; - } - - case PPC_ID_VSX_STXSD: - case PPC_ID_VSX_STXSSP: - { - uint32_t xs = GetS(word32) + 32; - PushRegister(instruction, PPC_OP_REG_VSX_RS, VsxVr(xs)); - - int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); - PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); - break; - } - - // [o] vrdHi, vraHi, vrbHi - case PPC_ID_VSX_XSADDQPx: - case PPC_ID_VSX_XSCPSGNQP: - case PPC_ID_VSX_XSDIVQPx: - case PPC_ID_VSX_XSIEXPQP: - case PPC_ID_VSX_XSMADDQPx: - case PPC_ID_VSX_XSMSUBQPx: - case PPC_ID_VSX_XSMULQPx: - case PPC_ID_VSX_XSNMADDQPx: - case PPC_ID_VSX_XSNMSUBQPx: - case PPC_ID_VSX_XSSUBQPx: - { - PushVsxHiD(instruction, word32); - PushVsxHiA(instruction, word32); - PushVsxHiB(instruction, word32); - - instruction->flags.round2odd = word32 & 0x1; - break; - } - - case PPC_ID_VSX_XSABSQP: - case PPC_ID_VSX_XSCVQPUWZ: - case PPC_ID_VSX_XSCVUDQP: - case PPC_ID_VSX_XSNABSQP: - case PPC_ID_VSX_XSCVDPQP: - case PPC_ID_VSX_XSCVQPDPx: - case PPC_ID_VSX_XSCVQPSDZ: - case PPC_ID_VSX_XSCVQPSWZ: - case PPC_ID_VSX_XSCVQPUDZ: - case PPC_ID_VSX_XSCVSDQP: - case PPC_ID_VSX_XSNEGQP: - case PPC_ID_VSX_XSSQRTQPx: - case PPC_ID_VSX_XSXEXPQP: - case PPC_ID_VSX_XSXSIGQP: - { - PushVsxHiD(instruction, word32); - PushVsxHiB(instruction, word32); - - instruction->flags.round2odd = word32 & 0x1; - break; - } - - case PPC_ID_VSX_XSCMPEXPQP: - case PPC_ID_VSX_XSCMPOQP: - case PPC_ID_VSX_XSCMPUQP: - PushCRFD(instruction, word32); - PushVsxHiA(instruction, word32); - PushVsxHiB(instruction, word32); - - break; - - case PPC_ID_VSX_XSTSTDCQP: - { - uint32_t dcmx = (word32 >> 16) & 0x7f; - PushCRFD(instruction, word32); - PushVsxHiB(instruction, word32); - PushUIMMValue(instruction, dcmx); - break; - } - - // one-off VSX instructions - case PPC_ID_VSX_XSIEXPDP: - { - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushRA(instruction, word32); - PushRB(instruction, word32); - break; - } - - case PPC_ID_VSX_XSRQPIx: - case PPC_ID_VSX_XSRQPXP: - { - uint32_t r = (word32 >> 16) & 0x1; - PushUIMMValue(instruction, r); - PushVsxHiD(instruction, word32); - PushVsxHiB(instruction, word32); - - uint32_t rmc = (word32 >> 9) & 0x3; - PushUIMMValue(instruction, rmc); - - instruction->flags.inexact = word32 & 0x1; - break; - } - - case PPC_ID_VSX_XSTSTDCDP: - case PPC_ID_VSX_XSTSTDCSP: - { - uint32_t dcmx = (word32 >> 16) & 0x7f; - PushCRFD(instruction, word32); - PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); - PushUIMMValue(instruction, dcmx); - break; - } - - case PPC_ID_VSX_XSXEXPDP: - case PPC_ID_VSX_XSXSIGDP: - PushRD(instruction, word32); - PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); - break; - - case PPC_ID_VSX_XVTSTDCDP: - case PPC_ID_VSX_XVTSTDCSP: - { - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushVsxB(instruction, word32, VSX_WIDTH_FULL); - uint32_t dm = (word32 >> 2) & 0x1; - uint32_t dc = (word32 >> 6) & 0x1; - uint32_t dx = (word32 >> 16) & 0x1f; - uint32_t dcmx = (dc << 6) | (dm << 5) | dx; - PushUIMMValue(instruction, dcmx); - break; - } - - - case PPC_ID_VSX_XXSPLTD: - { - uint32_t uimm = (word32 >> 8) & 0x3; - - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushVsxA(instruction, word32, VSX_WIDTH_FULL); - - if (uimm == 3) - PushUIMMValue(instruction, 1); - else - PushUIMMValue(instruction, 0); - - break; - } - - case PPC_ID_VSX_XXSPLTIB: - { - uint32_t uimm8 = (word32 >> 11) & 0xff; - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushUIMMValue(instruction, uimm8); - break; - } - - case PPC_ID_VSX_XXSPLTW: - { - uint32_t um = (word32 >> 16) & 0x3; - - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushVsxB(instruction, word32, VSX_WIDTH_FULL); - PushUIMMValue(instruction, um); - break; - } - - case PPC_ID_VSX_XXSWAPD: - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushVsxA(instruction, word32, VSX_WIDTH_FULL); - break; - - case PPC_ID_VSX_XXSEL: - PushVsxD(instruction, word32, VSX_WIDTH_FULL); - PushVsxA(instruction, word32, VSX_WIDTH_FULL); - PushVsxB(instruction, word32, VSX_WIDTH_FULL); - PushVsxC(instruction, word32, VSX_WIDTH_FULL); - break; - - // SPE INSTRUCTIONS - - // SPE rD, rA, rB - case PPC_ID_SPE_BRINC: - case PPC_ID_SPE_EFDADD: - case PPC_ID_SPE_EFDDIV: - case PPC_ID_SPE_EFDMUL: - case PPC_ID_SPE_EFDSUB: - case PPC_ID_SPE_EFSADD: - case PPC_ID_SPE_EFSDIV: - case PPC_ID_SPE_EFSMUL: - case PPC_ID_SPE_EFSSUB: - case PPC_ID_SPE_EVADDW: - case PPC_ID_SPE_EVAND: - case PPC_ID_SPE_EVANDC: - case PPC_ID_SPE_EVDIVWS: - case PPC_ID_SPE_EVDIVWU: - case PPC_ID_SPE_EVEQV: - case PPC_ID_SPE_EVFSADD: - case PPC_ID_SPE_EVFSDIV: - case PPC_ID_SPE_EVFSMUL: - case PPC_ID_SPE_EVFSSUB: - case PPC_ID_SPE_EVLDDX: - case PPC_ID_SPE_EVLDHX: - case PPC_ID_SPE_EVLDWX: - case PPC_ID_SPE_EVLHHESPLATX: - case PPC_ID_SPE_EVLHHOSSPLATX: - case PPC_ID_SPE_EVLHHOUSPLATX: - case PPC_ID_SPE_EVLWHEX: - case PPC_ID_SPE_EVLWHOSX: - case PPC_ID_SPE_EVLWHOUX: - case PPC_ID_SPE_EVLWHSPLATX: - case PPC_ID_SPE_EVLWWSPLATX: - case PPC_ID_SPE_EVMERGEHI: - case PPC_ID_SPE_EVMERGEHILO: - case PPC_ID_SPE_EVMERGELO: - case PPC_ID_SPE_EVMERGELOHI: - case PPC_ID_SPE_EVMHEGSMFAA: - case PPC_ID_SPE_EVMHEGSMFAN: - case PPC_ID_SPE_EVMHEGSMIAA: - case PPC_ID_SPE_EVMHEGSMIAN: - case PPC_ID_SPE_EVMHEGUMIAA: - case PPC_ID_SPE_EVMHEGUMIAN: - case PPC_ID_SPE_EVMHESMF: - case PPC_ID_SPE_EVMHESMFA: - case PPC_ID_SPE_EVMHESMFAAW: - case PPC_ID_SPE_EVMHESMFANW: - case PPC_ID_SPE_EVMHESMI: - case PPC_ID_SPE_EVMHESMIA: - case PPC_ID_SPE_EVMHESMIAAW: - case PPC_ID_SPE_EVMHESMIANW: - case PPC_ID_SPE_EVMHESSF: - case PPC_ID_SPE_EVMHESSFA: - case PPC_ID_SPE_EVMHESSFAAW: - case PPC_ID_SPE_EVMHESSFANW: - case PPC_ID_SPE_EVMHESSIAAW: - case PPC_ID_SPE_EVMHESSIANW: - case PPC_ID_SPE_EVMHEUMI: - case PPC_ID_SPE_EVMHEUMIA: - case PPC_ID_SPE_EVMHEUMIAAW: - case PPC_ID_SPE_EVMHEUMIANW: - case PPC_ID_SPE_EVMHEUSIAAW: - case PPC_ID_SPE_EVMHEUSIANW: - case PPC_ID_SPE_EVMHOGSMFAA: - case PPC_ID_SPE_EVMHOGSMFAN: - case PPC_ID_SPE_EVMHOGSMIAA: - case PPC_ID_SPE_EVMHOGSMIAN: - case PPC_ID_SPE_EVMHOGUMIAA: - case PPC_ID_SPE_EVMHOGUMIAN: - case PPC_ID_SPE_EVMHOSMF: - case PPC_ID_SPE_EVMHOSMFA: - case PPC_ID_SPE_EVMHOSMFAAW: - case PPC_ID_SPE_EVMHOSMFANW: - case PPC_ID_SPE_EVMHOSMI: - case PPC_ID_SPE_EVMHOSMIA: - case PPC_ID_SPE_EVMHOSMIAAW: - case PPC_ID_SPE_EVMHOSMIANW: - case PPC_ID_SPE_EVMHOSSF: - case PPC_ID_SPE_EVMHOSSFA: - case PPC_ID_SPE_EVMHOSSFAAW: - case PPC_ID_SPE_EVMHOSSFANW: - case PPC_ID_SPE_EVMHOSSIAAW: - case PPC_ID_SPE_EVMHOSSIANW: - case PPC_ID_SPE_EVMHOUMI: - case PPC_ID_SPE_EVMHOUMIA: - case PPC_ID_SPE_EVMHOUMIAAW: - case PPC_ID_SPE_EVMHOUMIANW: - case PPC_ID_SPE_EVMHOUSIAAW: - case PPC_ID_SPE_EVMHOUSIANW: - case PPC_ID_SPE_EVMWHSMF: - case PPC_ID_SPE_EVMWHSMFA: - case PPC_ID_SPE_EVMWHSMI: - case PPC_ID_SPE_EVMWHSMIA: - case PPC_ID_SPE_EVMWHSSF: - case PPC_ID_SPE_EVMWHSSFA: - case PPC_ID_SPE_EVMWLSMIAAW: - case PPC_ID_SPE_EVMWLSMIANW: - case PPC_ID_SPE_EVMWLSSIAAW: - case PPC_ID_SPE_EVMWLSSIANW: - case PPC_ID_SPE_EVMWHUMI: - case PPC_ID_SPE_EVMWHUMIA: - case PPC_ID_SPE_EVMWHUSIAAW: - case PPC_ID_SPE_EVMWHUSIANW: - case PPC_ID_SPE_EVMWLUMI: - case PPC_ID_SPE_EVMWLUMIA: - case PPC_ID_SPE_EVMWLUMIAAW: - case PPC_ID_SPE_EVMWLUMIANW: - case PPC_ID_SPE_EVMWLUSIAAW: - case PPC_ID_SPE_EVMWLUSIANW: - case PPC_ID_SPE_EVMWSMF: - case PPC_ID_SPE_EVMWSMFA: - case PPC_ID_SPE_EVMWSMFAA: - case PPC_ID_SPE_EVMWSMFAN: - case PPC_ID_SPE_EVMWSMI: - case PPC_ID_SPE_EVMWSMIA: - case PPC_ID_SPE_EVMWSMIAA: - case PPC_ID_SPE_EVMWSMIAN: - case PPC_ID_SPE_EVMWSSF: - case PPC_ID_SPE_EVMWSSFA: - case PPC_ID_SPE_EVMWSSFAA: - case PPC_ID_SPE_EVMWSSFAN: - case PPC_ID_SPE_EVMWUMI: - case PPC_ID_SPE_EVMWUMIA: - case PPC_ID_SPE_EVMWUMIAA: - case PPC_ID_SPE_EVMWUMIAN: - case PPC_ID_SPE_EVNAND: - case PPC_ID_SPE_EVNOR: - case PPC_ID_SPE_EVOR: - case PPC_ID_SPE_EVORC: - case PPC_ID_SPE_EVRLW: - case PPC_ID_SPE_EVSLW: - case PPC_ID_SPE_EVSRWS: - case PPC_ID_SPE_EVSRWU: - case PPC_ID_SPE_EVSUBFW: - case PPC_ID_SPE_EVXOR: - PushRD(instruction, word32); - PushRA(instruction, word32); - PushRB(instruction, word32); - break; - - // rD, rA, /// - case PPC_ID_SPE_EFDABS: - case PPC_ID_SPE_EFDNABS: - case PPC_ID_SPE_EFDNEG: - case PPC_ID_SPE_EFSABS: - case PPC_ID_SPE_EFSNABS: - case PPC_ID_SPE_EFSNEG: - case PPC_ID_SPE_EVABS: - case PPC_ID_SPE_EVADDSMIAAW: - case PPC_ID_SPE_EVADDSSIAAW: - case PPC_ID_SPE_EVADDUMIAAW: - case PPC_ID_SPE_EVADDUSIAAW: - case PPC_ID_SPE_EVCNTLSW: - case PPC_ID_SPE_EVCNTLZW: - case PPC_ID_SPE_EVEXTSB: - case PPC_ID_SPE_EVEXTSH: - case PPC_ID_SPE_EVFSABS: - case PPC_ID_SPE_EVFSNABS: - case PPC_ID_SPE_EVFSNEG: - case PPC_ID_SPE_EVMRA: - case PPC_ID_SPE_EVNEG: - case PPC_ID_SPE_EVSUBFSMIAAW: - case PPC_ID_SPE_EVSUBFSSIAAW: - case PPC_ID_SPE_EVSUBFUMIAAW: - case PPC_ID_SPE_EVSUBFUSIAAW: - PushRD(instruction, word32); - PushRA(instruction, word32); - break; - - // rD, ///, rB - case PPC_ID_SPE_EFDCFS: - case PPC_ID_SPE_EFDCFSF: - case PPC_ID_SPE_EFDCFSI: - case PPC_ID_SPE_EFDCFSID: - case PPC_ID_SPE_EFDCFUF: - case PPC_ID_SPE_EFDCFUI: - case PPC_ID_SPE_EFDCFUID: - case PPC_ID_SPE_EFDCTSF: - case PPC_ID_SPE_EFDCTSI: - case PPC_ID_SPE_EFDCTSIDZ: - case PPC_ID_SPE_EFDCTSIZ: - case PPC_ID_SPE_EFDCTUF: - case PPC_ID_SPE_EFDCTUI: - case PPC_ID_SPE_EFDCTUIDZ: - case PPC_ID_SPE_EFDCTUIZ: - case PPC_ID_SPE_EFSCFD: - case PPC_ID_SPE_EFSCFSF: - case PPC_ID_SPE_EFSCFSI: - case PPC_ID_SPE_EFSCFUF: - case PPC_ID_SPE_EFSCFUI: - case PPC_ID_SPE_EFSCTSF: - case PPC_ID_SPE_EFSCTSI: - case PPC_ID_SPE_EFSCTSIZ: - case PPC_ID_SPE_EFSCTUF: - case PPC_ID_SPE_EFSCTUI: - case PPC_ID_SPE_EFSCTUIZ: - case PPC_ID_SPE_EVFSCFSF: - case PPC_ID_SPE_EVFSCFSI: - case PPC_ID_SPE_EVFSCFUF: - case PPC_ID_SPE_EVFSCFUI: - case PPC_ID_SPE_EVFSCTSF: - case PPC_ID_SPE_EVFSCTSI: - case PPC_ID_SPE_EVFSCTSIZ: - case PPC_ID_SPE_EVFSCTUF: - case PPC_ID_SPE_EVFSCTUI: - case PPC_ID_SPE_EVFSCTUIZ: - PushRD(instruction, word32); - PushRA(instruction, word32); - break; - - // crfD//, rA, rB - case PPC_ID_SPE_EFDCMPEQ: - case PPC_ID_SPE_EFDCMPGT: - case PPC_ID_SPE_EFDCMPLT: - case PPC_ID_SPE_EFDTSTEQ: - case PPC_ID_SPE_EFDTSTGT: - case PPC_ID_SPE_EFDTSTLT: - case PPC_ID_SPE_EFSCMPEQ: - case PPC_ID_SPE_EFSCMPGT: - case PPC_ID_SPE_EFSCMPLT: - case PPC_ID_SPE_EFSTSTEQ: - case PPC_ID_SPE_EFSTSTGT: - case PPC_ID_SPE_EFSTSTLT: - case PPC_ID_SPE_EVCMPEQ: - case PPC_ID_SPE_EVCMPGTS: - case PPC_ID_SPE_EVCMPGTU: - case PPC_ID_SPE_EVCMPLTS: - case PPC_ID_SPE_EVCMPLTU: - case PPC_ID_SPE_EVFSCMPEQ: - case PPC_ID_SPE_EVFSCMPGT: - case PPC_ID_SPE_EVFSCMPLT: - case PPC_ID_SPE_EVFSTSTEQ: - case PPC_ID_SPE_EVFSTSTGT: - case PPC_ID_SPE_EVFSTSTLT: - PushCRFDImplyCR0(instruction, word32); - PushRA(instruction, word32); - PushRB(instruction, word32); - break; - - // rD, UIMM, rB - case PPC_ID_SPE_EVADDIW: - case PPC_ID_SPE_EVSUBIFW: - PushRD(instruction, word32); - PushUIMMValue(instruction, (word32 >> 16) & 0x1f); - PushRB(instruction, word32); - break; - - // rD, SIMM, /// - case PPC_ID_SPE_EVSPLATFI: - case PPC_ID_SPE_EVSPLATI: - { - int32_t simm = sign_extend((word32 >> 16) & 0x1f, 5); - PushRD(instruction, word32); - PushSIMMValue(instruction, simm); - break; - } - - // rD, rA, UIMM (SPE) - case PPC_ID_SPE_EVRLWI: - case PPC_ID_SPE_EVSLWI: - case PPC_ID_SPE_EVSRWIS: - case PPC_ID_SPE_EVSRWIU: - PushRD(instruction, word32); - PushRA(instruction, word32); - PushUIMMValue(instruction, (word32 >> 11) & 0x1f); - break; - - // rD, rA, UIMM (SPE loads) - case PPC_ID_SPE_EVLDD: - case PPC_ID_SPE_EVLDH: - case PPC_ID_SPE_EVLDW: - case PPC_ID_SPE_EVLHHESPLAT: - case PPC_ID_SPE_EVLHHOSSPLAT: - case PPC_ID_SPE_EVLHHOUSPLAT: - case PPC_ID_SPE_EVLWHE: - case PPC_ID_SPE_EVLWHOS: - case PPC_ID_SPE_EVLWHOU: - case PPC_ID_SPE_EVLWHSPLAT: - case PPC_ID_SPE_EVLWWSPLAT: - PushRD(instruction, word32); - PushRAor0(instruction, word32); - PushUIMMValue(instruction, (word32 >> 11) & 0x1f); - break; - - // rS, rA, UIMM (SPE) - case PPC_ID_SPE_EVSTDD: - case PPC_ID_SPE_EVSTDH: - case PPC_ID_SPE_EVSTDW: - case PPC_ID_SPE_EVSTWHE: - case PPC_ID_SPE_EVSTWHO: - case PPC_ID_SPE_EVSTWWE: - case PPC_ID_SPE_EVSTWWO: - PushRS(instruction, word32); - PushRAor0(instruction, word32); - PushUIMMValue(instruction, (word32 >> 11) & 0x1f); - break; - - // rS, rA, rB (SPE store-indexed) - case PPC_ID_SPE_EVSTDDX: - case PPC_ID_SPE_EVSTDHX: - case PPC_ID_SPE_EVSTDWX: - case PPC_ID_SPE_EVSTWHEX: - case PPC_ID_SPE_EVSTWHOX: - case PPC_ID_SPE_EVSTWWEX: - case PPC_ID_SPE_EVSTWWOX: - PushRS(instruction, word32); - PushRA(instruction, word32); - PushUIMMValue(instruction, (word32 >> 11) & 0x1f); - break; - - // rD, rA - case PPC_ID_SPE_EVMR: - case PPC_ID_SPE_EVNOT: - case PPC_ID_SPE_EVRNDW: - PushRD(instruction, word32); - PushRA(instruction, word32); - break; - - // rD, rA, rB, crfS - case PPC_ID_SPE_EVSEL: - { - PushRD(instruction, word32); - PushRA(instruction, word32); - PushRB(instruction, word32); - uint32_t crfs = word32 & 0x7; - PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crfs)); - break; - } - - default: - break; - } -} - -// the hope is to avoid having to manipulate strings in something that's -// somewhat hot, so we create a bunch of lookup tables for each mnemonic - -// for "OP" and "OP." -#define DEFINE_SUBMNEM_RC(_identifier, base) \ - const char* _identifier[2] = \ - { \ - base, \ - base ".", \ - }; - -// for "OP", "OP.", "OPo", and "OPo." -#define DEFINE_SUBMNEM_OE_RC(_identifier, base) \ - const char* _identifier[4] = \ - { \ - base, \ - base ".", \ - base "o", \ - base "o.", \ - }; - -// for "OP" and "OPl" -#define DEFINE_SUBMNEM_LK(_identifier, base) \ - const char* _identifier[2] = \ - { \ - base, \ - base "l", \ - }; - -// for "OP" and "OPl" and +/- hints -#define DEFINE_SUBMNEM_LK_HINT(_identifier, base) \ - const char* _identifier[8] = \ - { \ - base, \ - base "l", \ - base, \ - base "l", \ - base "-", \ - base "l-", \ - base "+", \ - base "l+", \ - }; - -// for "OP", "OPl", "OPa", and "OPla" -#define DEFINE_SUBMNEM_AA_LK(_identifier, base) \ - const char* _identifier[4] = \ - { \ - base, \ - base "l", \ - base "a", \ - base "la", \ - }; - -// for "OP", "OPl", "OPa", "OPla" and +/- hints -#define DEFINE_SUBMNEM_AA_LK_HINT(_identifier, base) \ - const char* _identifier[16] = \ - { \ - base, \ - base "l", \ - base "a", \ - base "la", \ - base, \ - base "l", \ - base "a", \ - base "la", \ - base "-", \ - base "l-", \ - base "a-", \ - base "la-", \ - base "+", \ - base "l+", \ - base "a+", \ - base "la+" \ - }; - -#define DEFINE_SUBMNEM_ROUND2ODD(_identifier, base) \ - const char* _identifier[2] = \ - { \ - base, \ - base "o", \ - }; - -#define DEFINE_SUBMNEM_INEXACT(_identifier, base) \ - const char* _identifier[2] = \ - { \ - base, \ - base "x", \ - }; - -DEFINE_SUBMNEM_OE_RC(SubMnemADDx, "add") -DEFINE_SUBMNEM_OE_RC(SubMnemADDCx, "addc") -DEFINE_SUBMNEM_OE_RC(SubMnemADDEx, "adde") -DEFINE_SUBMNEM_RC(SubMnemADDICx, "addic") -DEFINE_SUBMNEM_OE_RC(SubMnemADDMEx, "addme") -DEFINE_SUBMNEM_OE_RC(SubMnemADDZEx, "addze") -DEFINE_SUBMNEM_RC(SubMnemANDx, "and") -DEFINE_SUBMNEM_RC(SubMnemANDCx, "andc") -DEFINE_SUBMNEM_AA_LK(SubMnemBx, "b") -DEFINE_SUBMNEM_AA_LK(SubMnemBCx, "bc") -DEFINE_SUBMNEM_LK(SubMnemBCTRx, "bctr") -DEFINE_SUBMNEM_LK(SubMnemBCCTRx, "bcctr") -DEFINE_SUBMNEM_LK(SubMnemBCLRx, "bclr") -DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBDZx, "bdz") -DEFINE_SUBMNEM_LK_HINT(SubMnemBDZLRx, "bdzlr") -DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBDNZx, "bdnz") -DEFINE_SUBMNEM_LK_HINT(SubMnemBDNZLRx, "bdnzlr") -DEFINE_SUBMNEM_AA_LK(SubMnemBDNZFx, "bdnzf") -DEFINE_SUBMNEM_LK(SubMnemBDNZFLRx, "bdnzflr") -DEFINE_SUBMNEM_AA_LK(SubMnemBDNZTx, "bdnzt") -DEFINE_SUBMNEM_LK(SubMnemBDNZTLRx, "bdnztlr") -DEFINE_SUBMNEM_AA_LK(SubMnemBDZFx, "bdzf") -DEFINE_SUBMNEM_LK(SubMnemBDZFLRx, "bdzflr") -DEFINE_SUBMNEM_LK(SubMnemBDFLRx, "bdzlr") -DEFINE_SUBMNEM_AA_LK(SubMnemBDZTx, "bdzt") -DEFINE_SUBMNEM_LK(SubMnemBDZTLRx, "bdztlr") -DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBEQx, "beq") -DEFINE_SUBMNEM_LK_HINT(SubMnemBEQCTRx, "beqctr") -DEFINE_SUBMNEM_LK_HINT(SubMnemBEQLRx, "beqlr") -DEFINE_SUBMNEM_AA_LK(SubMnemBFx, "bf") -DEFINE_SUBMNEM_AA_LK(SubMnemBFLRx, "bflr") -DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBGEx, "bge") -DEFINE_SUBMNEM_LK_HINT(SubMnemBGECTRx, "bgectr") -DEFINE_SUBMNEM_LK_HINT(SubMnemBGELRx, "bgelr") -DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBGTx, "bgt") -DEFINE_SUBMNEM_LK_HINT(SubMnemBGTCTRx, "bgtctr") -DEFINE_SUBMNEM_LK_HINT(SubMnemBGTLRx, "bgtlr") -DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBLEx, "ble") -DEFINE_SUBMNEM_LK_HINT(SubMnemBLECTRx, "blectr") -DEFINE_SUBMNEM_LK_HINT(SubMnemBLELRx, "blelr") -DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBLTx, "blt") -DEFINE_SUBMNEM_LK_HINT(SubMnemBLTCTRx, "bltctr") -DEFINE_SUBMNEM_LK_HINT(SubMnemBLTLRx, "bltlr") -DEFINE_SUBMNEM_LK_HINT(SubMnemBLRx, "blr") -DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBNEx, "bne") -DEFINE_SUBMNEM_LK_HINT(SubMnemBNECTRx, "bnectr") -DEFINE_SUBMNEM_LK_HINT(SubMnemBNELRx, "bnelr") -DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBNSx, "bns") -DEFINE_SUBMNEM_LK_HINT(SubMnemBNSCTRx, "bnsctr") -DEFINE_SUBMNEM_LK_HINT(SubMnemBNSLRx, "bnslr") -DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBSOx, "bso") -DEFINE_SUBMNEM_LK_HINT(SubMnemBSOCTRx, "bsoctr") -DEFINE_SUBMNEM_LK_HINT(SubMnemBSOLRx, "bsolr") -DEFINE_SUBMNEM_AA_LK(SubMnemBTx, "bt") -DEFINE_SUBMNEM_AA_LK(SubMnemBTLRx, "btlr") -DEFINE_SUBMNEM_RC(SubMnemCLRLDIx, "clrldi") -DEFINE_SUBMNEM_RC(SubMnemCLRLWIx, "clrlwi") -DEFINE_SUBMNEM_RC(SubMnemCLRRWIx, "clrrwi") -DEFINE_SUBMNEM_RC(SubMnemCNTLZDx, "cntlzd") -DEFINE_SUBMNEM_RC(SubMnemCNTLZWx, "cntlzw") -DEFINE_SUBMNEM_RC(SubMnemCNTTZDx, "cnttzd") -DEFINE_SUBMNEM_RC(SubMnemCNTTZWx, "cnttzw") -DEFINE_SUBMNEM_OE_RC(SubMnemDIVDx, "divd") -DEFINE_SUBMNEM_OE_RC(SubMnemDIVDEx, "divde") -DEFINE_SUBMNEM_OE_RC(SubMnemDIVDEUx, "divdeu") -DEFINE_SUBMNEM_OE_RC(SubMnemDIVDUx, "divdu") -DEFINE_SUBMNEM_OE_RC(SubMnemDIVWx, "divw") -DEFINE_SUBMNEM_OE_RC(SubMnemDIVWEx, "divwe") -DEFINE_SUBMNEM_OE_RC(SubMnemDIVWEUx, "divweu") -DEFINE_SUBMNEM_OE_RC(SubMnemDIVWUx, "divwu") -DEFINE_SUBMNEM_RC(SubMnemEQVx, "eqv") -DEFINE_SUBMNEM_RC(SubMnemEXTSBx, "extsb") -DEFINE_SUBMNEM_RC(SubMnemEXTSHx, "extsh") -DEFINE_SUBMNEM_RC(SubMnemEXTSWx, "extsw") -DEFINE_SUBMNEM_RC(SubMnemEXTSWSLIx, "extswsli") -DEFINE_SUBMNEM_RC(SubMnemFABSx, "fabs") -DEFINE_SUBMNEM_RC(SubMnemFADDx, "fadd") -DEFINE_SUBMNEM_RC(SubMnemFADDSx, "fadds") -DEFINE_SUBMNEM_RC(SubMnemFCFIDx, "fcfid") -DEFINE_SUBMNEM_RC(SubMnemFCFIDSx, "fcfids") -DEFINE_SUBMNEM_RC(SubMnemFCFIDUx, "fcfidu") -DEFINE_SUBMNEM_RC(SubMnemFCFIDUSx, "fcfidus") -DEFINE_SUBMNEM_RC(SubMnemFCPSGNx, "fcpsgn") -DEFINE_SUBMNEM_RC(SubMnemFCTIDx, "fctid") -DEFINE_SUBMNEM_RC(SubMnemFCTIDUx, "fctidu") -DEFINE_SUBMNEM_RC(SubMnemFCTIDUZx, "fctiduz") -DEFINE_SUBMNEM_RC(SubMnemFCTIDZx, "fctidz") -DEFINE_SUBMNEM_RC(SubMnemFCTIWx, "fctiw") -DEFINE_SUBMNEM_RC(SubMnemFCTIWUx, "fctiwu") -DEFINE_SUBMNEM_RC(SubMnemFCTIWUZx, "fctiwuz") -DEFINE_SUBMNEM_RC(SubMnemFCTIWZx, "fctiwz") -DEFINE_SUBMNEM_RC(SubMnemFDIVx, "fdiv") -DEFINE_SUBMNEM_RC(SubMnemFDIVSx, "fdivs") -DEFINE_SUBMNEM_RC(SubMnemFMADDx, "fmadd") -DEFINE_SUBMNEM_RC(SubMnemFMADDSx, "fmadds") -DEFINE_SUBMNEM_RC(SubMnemFMRx, "fmr") -DEFINE_SUBMNEM_RC(SubMnemFMSUBx, "fmsub") -DEFINE_SUBMNEM_RC(SubMnemFMSUBSx, "fmsubs") -DEFINE_SUBMNEM_RC(SubMnemFMULx, "fmul") -DEFINE_SUBMNEM_RC(SubMnemFMULSx, "fmuls") -DEFINE_SUBMNEM_RC(SubMnemFNABSx, "fnabs") -DEFINE_SUBMNEM_RC(SubMnemFNEGx, "fneg") -DEFINE_SUBMNEM_RC(SubMnemFNMADDx, "fnmadd") -DEFINE_SUBMNEM_RC(SubMnemFNMADDSx, "fnmadds") -DEFINE_SUBMNEM_RC(SubMnemFNMSUBx, "fnmsub") -DEFINE_SUBMNEM_RC(SubMnemFNMSUBSx, "fnmsubs") -DEFINE_SUBMNEM_RC(SubMnemFREx, "fre") -DEFINE_SUBMNEM_RC(SubMnemFRESx, "fres") -DEFINE_SUBMNEM_RC(SubMnemFRIMx, "frim") -DEFINE_SUBMNEM_RC(SubMnemFRINx, "frin") -DEFINE_SUBMNEM_RC(SubMnemFRIPx, "frip") -DEFINE_SUBMNEM_RC(SubMnemFRIZx, "friz") -DEFINE_SUBMNEM_RC(SubMnemFRSPx, "frsp") -DEFINE_SUBMNEM_RC(SubMnemFRSQRTEx, "frsqrte") -DEFINE_SUBMNEM_RC(SubMnemFRSQRTESx, "frsqrtes") -DEFINE_SUBMNEM_RC(SubMnemFSELx, "fsel") -DEFINE_SUBMNEM_RC(SubMnemFSQRTx, "fsqrt") -DEFINE_SUBMNEM_RC(SubMnemFSQRTSx, "fsqrts") -DEFINE_SUBMNEM_RC(SubMnemFSUBx, "fsub") -DEFINE_SUBMNEM_RC(SubMnemFSUBSx, "fsubs") -DEFINE_SUBMNEM_RC(SubMnemMFFSx, "mffs") -DEFINE_SUBMNEM_RC(SubMnemMTFSB0x, "mtfsb0") -DEFINE_SUBMNEM_RC(SubMnemMTFSB1x, "mtfsb1") -DEFINE_SUBMNEM_RC(SubMnemMTFSFx, "mtfsf") -DEFINE_SUBMNEM_RC(SubMnemMTFSFIx, "mtfsfi") -DEFINE_SUBMNEM_RC(SubMnemMRx, "mr") -DEFINE_SUBMNEM_RC(SubMnemMULHDx, "mulhd") -DEFINE_SUBMNEM_RC(SubMnemMULHDUx, "mulhdu") -DEFINE_SUBMNEM_RC(SubMnemMULHWx, "mulhw") -DEFINE_SUBMNEM_RC(SubMnemMULHWUx, "mulhwu") -DEFINE_SUBMNEM_OE_RC(SubMnemMULLDx, "mulld") -DEFINE_SUBMNEM_OE_RC(SubMnemMULLWx, "mullw") -DEFINE_SUBMNEM_RC(SubMnemNANDx, "nand") -DEFINE_SUBMNEM_OE_RC(SubMnemNEGx, "neg") -DEFINE_SUBMNEM_RC(SubMnemNORx, "nor") -DEFINE_SUBMNEM_RC(SubMnemORx, "or") -DEFINE_SUBMNEM_RC(SubMnemORCx, "orc") -DEFINE_SUBMNEM_RC(SubMnemRLDICLx, "rldicl") -DEFINE_SUBMNEM_RC(SubMnemRLDICRx, "rldicr") -DEFINE_SUBMNEM_RC(SubMnemRLDICx, "rldic") -DEFINE_SUBMNEM_RC(SubMnemRLDIMIx, "rldimi") -DEFINE_SUBMNEM_RC(SubMnemRLDCLx, "rldcl") -DEFINE_SUBMNEM_RC(SubMnemRLDCRx, "rldcr") -DEFINE_SUBMNEM_RC(SubMnemRLWIMIx, "rlwimi") -DEFINE_SUBMNEM_RC(SubMnemRLWINMx, "rlwinm") -DEFINE_SUBMNEM_RC(SubMnemRLWNMx, "rlwnm") -DEFINE_SUBMNEM_RC(SubMnemROTLDx, "rotld") -DEFINE_SUBMNEM_RC(SubMnemROTLDIx, "rotldi") -DEFINE_SUBMNEM_RC(SubMnemROTLWx, "rotlw") -DEFINE_SUBMNEM_RC(SubMnemROTLWIx, "rotlwi") -DEFINE_SUBMNEM_RC(SubMnemSLDx, "sld") -DEFINE_SUBMNEM_RC(SubMnemSLDIx, "sldi") -DEFINE_SUBMNEM_RC(SubMnemSLWx, "slw") -DEFINE_SUBMNEM_RC(SubMnemSLWIx, "slwi") -DEFINE_SUBMNEM_RC(SubMnemSRADx, "srad") -DEFINE_SUBMNEM_RC(SubMnemSRADIx, "sradi") -DEFINE_SUBMNEM_RC(SubMnemSRAWx, "sraw") -DEFINE_SUBMNEM_RC(SubMnemSRAWIx, "srawi") -DEFINE_SUBMNEM_RC(SubMnemSRDx, "srd") -DEFINE_SUBMNEM_RC(SubMnemSRDIx, "srdi") -DEFINE_SUBMNEM_RC(SubMnemSRWx, "srw") -DEFINE_SUBMNEM_RC(SubMnemSRWIx, "srwi") -DEFINE_SUBMNEM_OE_RC(SubMnemSUBFx, "subf") -DEFINE_SUBMNEM_OE_RC(SubMnemSUBFCx, "subfc") -DEFINE_SUBMNEM_OE_RC(SubMnemSUBFEx, "subfe") -DEFINE_SUBMNEM_OE_RC(SubMnemSUBFMEx, "subfme") -DEFINE_SUBMNEM_OE_RC(SubMnemSUBFZEx, "subfze") -DEFINE_SUBMNEM_RC(SubMnemXORx, "xor") - -// ALTIVEC MNEMONICS -DEFINE_SUBMNEM_RC(SubMnemVCMPBFPx, "vcmpbfp"); -DEFINE_SUBMNEM_RC(SubMnemVCMPEQFPx, "vcmpeqfp"); -DEFINE_SUBMNEM_RC(SubMnemVCMPEQUBx, "vcmpequb"); -DEFINE_SUBMNEM_RC(SubMnemVCMPEQUDx, "vcmpequd"); -DEFINE_SUBMNEM_RC(SubMnemVCMPEQUHx, "vcmpequh"); -DEFINE_SUBMNEM_RC(SubMnemVCMPEQUWx, "vcmpequw"); -DEFINE_SUBMNEM_RC(SubMnemVCMPGEFPx, "vcmpgefp"); -DEFINE_SUBMNEM_RC(SubMnemVCMPGTFPx, "vcmpgtfp"); -DEFINE_SUBMNEM_RC(SubMnemVCMPGTSBx, "vcmpgtsb"); -DEFINE_SUBMNEM_RC(SubMnemVCMPGTSDx, "vcmpgtsd"); -DEFINE_SUBMNEM_RC(SubMnemVCMPGTSHx, "vcmpgtsh"); -DEFINE_SUBMNEM_RC(SubMnemVCMPGTSWx, "vcmpgtsw"); -DEFINE_SUBMNEM_RC(SubMnemVCMPGTUBx, "vcmpgtub"); -DEFINE_SUBMNEM_RC(SubMnemVCMPGTUDx, "vcmpgtud"); -DEFINE_SUBMNEM_RC(SubMnemVCMPGTUHx, "vcmpgtuh"); -DEFINE_SUBMNEM_RC(SubMnemVCMPGTUWx, "vcmpgtuw"); -DEFINE_SUBMNEM_RC(SubMnemVCMPNEBx, "vcmpneb"); -DEFINE_SUBMNEM_RC(SubMnemVCMPNEHx, "vcmpneh"); -DEFINE_SUBMNEM_RC(SubMnemVCMPNEWx, "vcmpnew"); -DEFINE_SUBMNEM_RC(SubMnemVCMPNEZBx, "vcmpnezb"); -DEFINE_SUBMNEM_RC(SubMnemVCMPNEZHx, "vcmpnezh"); -DEFINE_SUBMNEM_RC(SubMnemVCMPNEZWx, "vcmpnezw"); - -// VSX MNEMONICS -DEFINE_SUBMNEM_RC(SubMnemXVCMPEQDPx, "xvcmpeqdp"); -DEFINE_SUBMNEM_RC(SubMnemXVCMPEQSPx, "xvcmpeqsp"); -DEFINE_SUBMNEM_RC(SubMnemXVCMPGEDPx, "xvcmpgedp"); -DEFINE_SUBMNEM_RC(SubMnemXVCMPGESPx, "xvcmpgesp"); -DEFINE_SUBMNEM_RC(SubMnemXVCMPGTDPx, "xvcmpgtdp"); -DEFINE_SUBMNEM_RC(SubMnemXVCMPGTSPx, "xvcmpgtsp"); -DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSADDQPx, "xsaddqp"); -DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSCVQPDPx, "xscvqpdp"); -DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSDIVQPx, "xsdivqp"); -DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSMADDQPx, "xsmaddqp"); -DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSMULQPx, "xsmulqp"); -DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSMSUBQPx, "xsmsubqp"); -DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSNMADDQPx, "xsnmaddqp"); -DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSNMSUBQPx, "xsnmsubqp"); -DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSSQRTQPx, "xssqrtqp"); -DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSSUBQPx, "xssubqp"); -DEFINE_SUBMNEM_INEXACT(SubMnemXSRQPIx, "xsrqpi"); - -static const char* RcMnemonic(const Instruction* instruction, const char* names[2]) -{ - return names[instruction->flags.rc]; -} - -static const char* OeRcMnemonic(const Instruction* instruction, const char* names[4]) -{ - return names[2*instruction->flags.oe + instruction->flags.rc]; -} - -static const char* LkMnemonic(const Instruction* instruction, const char* names[2]) -{ - return names[instruction->flags.lk]; -} - -static const char* LkHintMnemonic(const Instruction* instruction, const char* names[8]) -{ - return names[2*instruction->flags.branchLikelyHint + instruction->flags.lk]; -} - -static const char* AaLkMnemonic(const Instruction* instruction, const char* names[4]) -{ - return names[2*instruction->flags.aa + instruction->flags.lk]; -} - -static const char* AaLkHintMnemonic(const Instruction* instruction, const char* names[16]) -{ - return names[4*instruction->flags.branchLikelyHint + 2*instruction->flags.aa + instruction->flags.lk]; -} - -static const char* Round2OddMnemonic(const Instruction* instruction, const char* names[2]) -{ - return names[instruction->flags.round2odd]; -} - -static const char* InexactMnemonic(const Instruction* instruction, const char* names[2]) -{ - return names[instruction->flags.inexact]; -} - -void FillBcxOperands(OperandsList* bcx, const Instruction* instruction) -{ - memset(bcx, 0, sizeof *bcx); - - if (instruction->id != PPC_ID_BCx) - return; - - uint32_t bo = instruction->operands[0].uimm; - uint32_t bi = instruction->operands[1].uimm; - - switch (bo & 0x1e) - { - // copy BI, target - case 0: - case 2: - case 8: - case 10: - CopyOperand(&bcx->operands[0], &instruction->operands[1]); - CopyOperand(&bcx->operands[1], &instruction->operands[2]); - bcx->numOperands = 2; - break; - - // copy BI, target - case 4: - case 6: - case 12: - case 14: - { - uint32_t crn = bi >> 2; - - bcx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0; - bcx->operands[0].reg = Crf(crn); - CopyOperand(&bcx->operands[1], &instruction->operands[2]); - bcx->numOperands = 2; - break; - } - - // just copy target - case 16: - case 18: - case 20: - case 22: - case 24: - case 26: - case 28: - case 30: - CopyOperand(&bcx->operands[0], &instruction->operands[2]); - bcx->numOperands = 1; - break; - - // copy BO, BI, target - default: - CopyOperand(&bcx->operands[0], &instruction->operands[0]); - CopyOperand(&bcx->operands[1], &instruction->operands[1]); - CopyOperand(&bcx->operands[2], &instruction->operands[2]); - bcx->numOperands = 3; - - break; - } -} - -void FillBcctrxOperands(OperandsList* bcctrx, const Instruction* instruction) -{ - memset(bcctrx, 0, sizeof *bcctrx); - - if (instruction->id != PPC_ID_BCCTRx) - return; - - uint32_t bo = instruction->operands[0].uimm; - uint32_t bi = instruction->operands[1].uimm; - - switch (bo & 0x1e) - { - // copy BI --> crn - case 4: - case 6: - case 12: - case 14: - { - uint32_t crn = bi >> 2; - - bcctrx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0; - bcctrx->operands[0].reg = Crf(crn); - bcctrx->numOperands = 1; - break; - } - - // no ops (BCTR, BCTRL) - case 20: - break; - - // copy BO, BI - default: - CopyOperand(&bcctrx->operands[0], &instruction->operands[0]); - CopyOperand(&bcctrx->operands[1], &instruction->operands[1]); - bcctrx->numOperands = 2; - - break; - } - -} - -void FillBclrxOperands(OperandsList* bclrx, const Instruction* instruction) -{ - memset(bclrx, 0, sizeof *bclrx); - - if (instruction->id != PPC_ID_BCLRx) - return; - - uint32_t bo = instruction->operands[0].uimm; - uint32_t bi = instruction->operands[1].uimm; - - switch (bo & 0x1e) - { - // copy BI - case 0: - case 2: - case 8: - case 10: - CopyOperand(&bclrx->operands[0], &instruction->operands[1]); - bclrx->operands[0].cls = PPC_OP_CRBIT; - bclrx->operands[0].crbit = (uint32_t)instruction->operands[1].uimm; - bclrx->numOperands = 1; - break; - - // copy BI --> crn - case 4: - case 6: - case 12: - case 14: - { - uint32_t crn = bi >> 2; - - bclrx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0; - bclrx->operands[0].reg = Crf(crn); - bclrx->numOperands = 1; - break; - } - - // no ops (decrement CTR, compare to 0, but no condition check) - case 16: - case 18: - case 24: - case 26: - - // no ops (BLR, BLRL) - case 20: - break; - - // copy BO, BI - default: - CopyOperand(&bclrx->operands[0], &instruction->operands[0]); - CopyOperand(&bclrx->operands[1], &instruction->operands[1]); - bclrx->numOperands = 2; - - break; - } -} - -const char* GetMnemonic(const Instruction* instruction) -{ - switch (instruction->id) - { - case PPC_ID_ADDx: return OeRcMnemonic(instruction, SubMnemADDx); - case PPC_ID_ADDCx: return OeRcMnemonic(instruction, SubMnemADDCx); - case PPC_ID_ADDEx: return OeRcMnemonic(instruction, SubMnemADDEx); - case PPC_ID_ADDI: return "addi"; - case PPC_ID_ADDICx: return RcMnemonic(instruction, SubMnemADDICx); - case PPC_ID_ADDIS: return "addis"; - case PPC_ID_ADDMEx: return OeRcMnemonic(instruction, SubMnemADDMEx); - case PPC_ID_ADDPCIS: return "addpcis"; - case PPC_ID_ADDZEx: return OeRcMnemonic(instruction, SubMnemADDZEx); - case PPC_ID_ANDx: return RcMnemonic(instruction, SubMnemANDx); - case PPC_ID_ANDCx: return RcMnemonic(instruction, SubMnemANDCx); - case PPC_ID_ANDI: return "andi."; - case PPC_ID_ANDIS: return "andis."; - case PPC_ID_ATTN: return "attn"; - case PPC_ID_Bx: return AaLkMnemonic(instruction, SubMnemBx); - case PPC_ID_BCx: - { - uint32_t bo = instruction->operands[0].uimm; - uint32_t bi = instruction->operands[1].uimm; - - const char** mnemonics = NULL; - const char** mnemonicsHint = NULL; - - // mask away the "y" bit - switch (bo & 0x1e) - { - case 0: - mnemonics = SubMnemBDNZFx; - break; - - case 2: - mnemonics = SubMnemBDZFx; - break; - - case 4: - case 6: - switch (bi & 0x3) - { - case 0: - mnemonicsHint = SubMnemBGEx; - break; - case 1: - mnemonicsHint = SubMnemBLEx; - break; - case 2: - mnemonicsHint = SubMnemBNEx; - break; - case 3: - mnemonicsHint = SubMnemBNSx; - break; - - // should be unreachable - default: - return NULL; - } - - break; - - case 8: - mnemonics = SubMnemBDNZTx; - break; - - case 10: - mnemonics = SubMnemBDZTx; - break; - - case 12: - case 14: - switch (bi & 0x3) - { - case 0: - mnemonicsHint = SubMnemBLTx; - break; - - case 1: - mnemonicsHint = SubMnemBGTx; - break; - - case 2: - mnemonicsHint = SubMnemBEQx; - break; - - case 3: - mnemonicsHint = SubMnemBSOx; - break; - - // should be unreachable - default: - return NULL; - } - break; - - // technically these aren't terribly well defined - // when BI != 0, since these BOs don't involve - // a condition bit to test in BI to test against - case 16: - case 24: - mnemonicsHint = SubMnemBDNZx; - break; - - // these represent "branch always" in the BO field, so it's - // not super clear why these disassemble to bdnz - case 20: - case 28: - mnemonicsHint = SubMnemBDNZx; - break; - - case 18: - case 22: - case 26: - mnemonicsHint = SubMnemBDZx; - break; - - // these represent "branch always" in the BO field, so it's - // not super clear why these disassemble to bdz - case 30: - mnemonicsHint = SubMnemBDZx; - break; - - default: - mnemonics = SubMnemBCx; - } - - if (mnemonicsHint) - return AaLkHintMnemonic(instruction, mnemonicsHint); - - if (mnemonics) - return AaLkMnemonic(instruction, mnemonics); - - // should be unreachable - return NULL; - } - - case PPC_ID_BCCTRx: - { - uint32_t bo = instruction->operands[0].uimm; - uint32_t bi = instruction->operands[1].uimm; - - // mask away the "y" bit - switch (bo & 0x1e) - { - case 4: - case 6: - switch (bi & 0x3) - { - case 0: return LkHintMnemonic(instruction, SubMnemBGECTRx); - case 1: return LkHintMnemonic(instruction, SubMnemBLECTRx); - case 2: return LkHintMnemonic(instruction, SubMnemBNECTRx); - case 3: return LkHintMnemonic(instruction, SubMnemBNSCTRx); - - // should be unreachable - default: return NULL; - } - - break; - - case 12: - case 14: - switch (bi & 0x3) - { - case 0: return LkHintMnemonic(instruction, SubMnemBLTCTRx); - case 1: return LkHintMnemonic(instruction, SubMnemBGTCTRx); - case 2: return LkHintMnemonic(instruction, SubMnemBEQCTRx); - case 3: return LkHintMnemonic(instruction, SubMnemBSOCTRx); - - // should be unreachable - default: return NULL; - } - - break; - - case 20: - return LkMnemonic(instruction, SubMnemBCTRx); - - default: - return LkMnemonic(instruction, SubMnemBCCTRx); - } - } - - case PPC_ID_BCLRx: - { - uint32_t bo = instruction->operands[0].uimm; - uint32_t bi = instruction->operands[1].uimm; - - // mask away the "y" bit - switch (bo & 0x1e) - { - case 0: - return LkMnemonic(instruction, SubMnemBDNZFLRx); - - case 2: - return LkMnemonic(instruction, SubMnemBDZFLRx); - - case 4: - case 6: - switch (bi & 0x3) - { - case 0: return LkHintMnemonic(instruction, SubMnemBGELRx); - case 1: return LkHintMnemonic(instruction, SubMnemBLELRx); - case 2: return LkHintMnemonic(instruction, SubMnemBNELRx); - case 3: return LkHintMnemonic(instruction, SubMnemBNSLRx); - - // should be unreachable - default: return NULL; - } - - case 8: - return LkMnemonic(instruction, SubMnemBDNZTLRx); - - case 10: - return LkMnemonic(instruction, SubMnemBDZTLRx); - - case 12: - case 14: - switch (bi & 0x3) - { - case 0: return LkHintMnemonic(instruction, SubMnemBLTLRx); - case 1: return LkHintMnemonic(instruction, SubMnemBGTLRx); - case 2: return LkHintMnemonic(instruction, SubMnemBEQLRx); - case 3: return LkHintMnemonic(instruction, SubMnemBSOLRx); - - // should be unreachable - default: return NULL; - } - - // technically these aren't terribly well defined - // when BI != 0, since these BOs don't involve - // a condition bit to test in BI to test against - case 16: - case 24: - return LkHintMnemonic(instruction, SubMnemBDNZLRx); - - case 18: - case 26: - return LkHintMnemonic(instruction, SubMnemBDZLRx); - - case 20: - return LkHintMnemonic(instruction, SubMnemBLRx); - - default: - return LkMnemonic(instruction, SubMnemBCLRx); - } - } - - case PPC_ID_BPERMD: return "bpermd"; - case PPC_ID_CLRBHRB: return "clrbhrb"; - case PPC_ID_CLRLDIx: return RcMnemonic(instruction, SubMnemCLRLDIx); - case PPC_ID_CLRLWIx: return RcMnemonic(instruction, SubMnemCLRLWIx); - case PPC_ID_CLRRWIx: return RcMnemonic(instruction, SubMnemCLRRWIx); - case PPC_ID_CMPB: return "cmpb"; - case PPC_ID_CMPD: return "cmpd"; - case PPC_ID_CMPDI: return "cmpdi"; - case PPC_ID_CMPEQB: return "cmpeqb"; - case PPC_ID_CMPRB: return "cmprb"; - case PPC_ID_CMPW: return "cmpw"; - case PPC_ID_CMPWI: return "cmpwi"; - case PPC_ID_CMPLD: return "cmpld"; - case PPC_ID_CMPLDI: return "cmpldi"; - case PPC_ID_CMPLW: return "cmplw"; - case PPC_ID_CMPLWI: return "cmplwi"; - case PPC_ID_CNTLZDx: return RcMnemonic(instruction, SubMnemCNTLZDx); - case PPC_ID_CNTLZWx: return RcMnemonic(instruction, SubMnemCNTLZWx); - case PPC_ID_CNTTZDx: return RcMnemonic(instruction, SubMnemCNTTZDx); - case PPC_ID_CNTTZWx: return RcMnemonic(instruction, SubMnemCNTTZWx); - case PPC_ID_COPY: return "copy"; - case PPC_ID_CP_ABORT: return "cp_abort"; - case PPC_ID_CRAND: return "crand"; - case PPC_ID_CRANDC: return "crandc"; - case PPC_ID_CRCLR: return "crclr"; - case PPC_ID_CREQV: return "creqv"; - case PPC_ID_CRMOVE: return "crmove"; - case PPC_ID_CRNAND: return "crnand"; - case PPC_ID_CRNOR: return "crnor"; - case PPC_ID_CRNOT: return "crnot"; - case PPC_ID_CROR: return "cror"; - case PPC_ID_CRORC: return "crorc"; - case PPC_ID_CRSET: return "crset"; - case PPC_ID_CRXOR: return "crxor"; - case PPC_ID_DARN: return "darn"; - case PPC_ID_DCBA: return "dcba"; - case PPC_ID_DCBF: return "dcbf"; - case PPC_ID_DCBFEP: return "dcbfep"; - case PPC_ID_DCBFL: return "dcbfl"; - case PPC_ID_DCBFLP: return "dcbflp"; - case PPC_ID_DCBI: return "dcbi"; - case PPC_ID_DCBST: return "dcbst"; - case PPC_ID_DCBSTEP: return "dcbstep"; - case PPC_ID_DCBT: return "dcbt"; - case PPC_ID_DCBTT: return "dcbtt"; - case PPC_ID_DCBTEP: return "dcbtep"; - case PPC_ID_DCBTST: return "dcbtst"; - case PPC_ID_DCBTSTEP: return "dcbtstep"; - case PPC_ID_DCBTSTT: return "dcbtstt"; - case PPC_ID_DCBZ: return "dcbz"; - case PPC_ID_DCBZEP: return "dcbzep"; - case PPC_ID_DCBZL: return "dcbzl"; - case PPC_ID_DCCCI: return "dccci"; - case PPC_ID_DCI: return "dci"; - case PPC_ID_DIVDx: return OeRcMnemonic(instruction, SubMnemDIVDx); - case PPC_ID_DIVDEx: return OeRcMnemonic(instruction, SubMnemDIVDEx); - case PPC_ID_DIVDEUx: return OeRcMnemonic(instruction, SubMnemDIVDEUx); - case PPC_ID_DIVDUx: return OeRcMnemonic(instruction, SubMnemDIVDUx); - case PPC_ID_DIVWx: return OeRcMnemonic(instruction, SubMnemDIVWx); - case PPC_ID_DIVWEx: return OeRcMnemonic(instruction, SubMnemDIVWEx); - case PPC_ID_DIVWEUx: return OeRcMnemonic(instruction, SubMnemDIVWEUx); - case PPC_ID_DIVWUx: return OeRcMnemonic(instruction, SubMnemDIVWUx); - case PPC_ID_ECIWX: return "eciwx"; - case PPC_ID_ECOWX: return "ecowx"; - case PPC_ID_EIEIO: return "eieio"; - case PPC_ID_EQVx: return RcMnemonic(instruction, SubMnemEQVx); - case PPC_ID_EXTSBx: return RcMnemonic(instruction, SubMnemEXTSBx); - case PPC_ID_EXTSHx: return RcMnemonic(instruction, SubMnemEXTSHx); - case PPC_ID_EXTSWx: return RcMnemonic(instruction, SubMnemEXTSWx); - case PPC_ID_EXTSWSLIx: return RcMnemonic(instruction, SubMnemEXTSWSLIx); - case PPC_ID_FABSx: return RcMnemonic(instruction, SubMnemFABSx); - case PPC_ID_FADDx: return RcMnemonic(instruction, SubMnemFADDx); - case PPC_ID_FADDSx: return RcMnemonic(instruction, SubMnemFADDSx); - case PPC_ID_FCFIDx: return RcMnemonic(instruction, SubMnemFCFIDx); - case PPC_ID_FCFIDSx: return RcMnemonic(instruction, SubMnemFCFIDSx); - case PPC_ID_FCFIDUx: return RcMnemonic(instruction, SubMnemFCFIDUx); - case PPC_ID_FCFIDUSx: return RcMnemonic(instruction, SubMnemFCFIDUSx); - case PPC_ID_FCMPO: return "fcmpo"; - case PPC_ID_FCMPU: return "fcmpu"; - case PPC_ID_FCPSGNx: return RcMnemonic(instruction, SubMnemFCPSGNx); - case PPC_ID_FCTIDx: return RcMnemonic(instruction, SubMnemFCTIDx); - case PPC_ID_FCTIDUx: return RcMnemonic(instruction, SubMnemFCTIDUx); - case PPC_ID_FCTIDUZx: return RcMnemonic(instruction, SubMnemFCTIDUZx); - case PPC_ID_FCTIDZx: return RcMnemonic(instruction, SubMnemFCTIDZx); - case PPC_ID_FCTIWx: return RcMnemonic(instruction, SubMnemFCTIWx); - case PPC_ID_FCTIWUx: return RcMnemonic(instruction, SubMnemFCTIWUx); - case PPC_ID_FCTIWUZx: return RcMnemonic(instruction, SubMnemFCTIWUZx); - case PPC_ID_FCTIWZx: return RcMnemonic(instruction, SubMnemFCTIWZx); - case PPC_ID_FDIVx: return RcMnemonic(instruction, SubMnemFDIVx); - case PPC_ID_FDIVSx: return RcMnemonic(instruction, SubMnemFDIVSx); - case PPC_ID_FMADDx: return RcMnemonic(instruction, SubMnemFMADDx); - case PPC_ID_FMADDSx: return RcMnemonic(instruction, SubMnemFMADDSx); - case PPC_ID_FMRx: return RcMnemonic(instruction, SubMnemFMRx); - case PPC_ID_FMSUBx: return RcMnemonic(instruction, SubMnemFMSUBx); - case PPC_ID_FMSUBSx: return RcMnemonic(instruction, SubMnemFMSUBSx); - case PPC_ID_FMULx: return RcMnemonic(instruction, SubMnemFMULx); - case PPC_ID_FMULSx: return RcMnemonic(instruction, SubMnemFMULSx); - case PPC_ID_FNABSx: return RcMnemonic(instruction, SubMnemFNABSx); - case PPC_ID_FNEGx: return RcMnemonic(instruction, SubMnemFNEGx); - case PPC_ID_FNMADDx: return RcMnemonic(instruction, SubMnemFNMADDx); - case PPC_ID_FNMADDSx: return RcMnemonic(instruction, SubMnemFNMADDSx); - case PPC_ID_FNMSUBx: return RcMnemonic(instruction, SubMnemFNMSUBx); - case PPC_ID_FNMSUBSx: return RcMnemonic(instruction, SubMnemFNMSUBSx); - case PPC_ID_FREx: return RcMnemonic(instruction, SubMnemFREx); - case PPC_ID_FRESx: return RcMnemonic(instruction, SubMnemFRESx); - case PPC_ID_FRIMx: return RcMnemonic(instruction, SubMnemFRIMx); - case PPC_ID_FRINx: return RcMnemonic(instruction, SubMnemFRINx); - case PPC_ID_FRIPx: return RcMnemonic(instruction, SubMnemFRIPx); - case PPC_ID_FRIZx: return RcMnemonic(instruction, SubMnemFRIZx); - case PPC_ID_FRSPx: return RcMnemonic(instruction, SubMnemFRSPx); - case PPC_ID_FRSQRTEx: return RcMnemonic(instruction, SubMnemFRSQRTEx); - case PPC_ID_FRSQRTESx: return RcMnemonic(instruction, SubMnemFRSQRTESx); - case PPC_ID_FSELx: return RcMnemonic(instruction, SubMnemFSELx); - case PPC_ID_FSQRTx: return RcMnemonic(instruction, SubMnemFSQRTx); - case PPC_ID_FSQRTSx: return RcMnemonic(instruction, SubMnemFSQRTSx); - case PPC_ID_FSUBx: return RcMnemonic(instruction, SubMnemFSUBx); - case PPC_ID_FSUBSx: return RcMnemonic(instruction, SubMnemFSUBSx); - case PPC_ID_FTDIV: return "ftdiv"; - case PPC_ID_FTSQRT: return "ftsqrt"; - case PPC_ID_ICBI: return "icbi"; - case PPC_ID_ICBIEP: return "icbiep"; - case PPC_ID_ICBLC: return "icblc"; - case PPC_ID_ICBLQ: return "icblq."; - case PPC_ID_ICBT: return "icbt"; - case PPC_ID_ICBTLS: return "icbtls"; - case PPC_ID_ICCCI: return "iccci"; - case PPC_ID_ICI: return "ici"; - case PPC_ID_ISEL: return "isel"; - case PPC_ID_ISYNC: return "isync"; - case PPC_ID_LBARX: return "lbarx"; - case PPC_ID_LBEPX: return "lbepx"; - case PPC_ID_LBZ: return "lbz"; - case PPC_ID_LBZCIX: return "lbzcix"; - case PPC_ID_LBZU: return "lbzu"; - case PPC_ID_LBZUX: return "lbzux"; - case PPC_ID_LBZX: return "lbzx"; - case PPC_ID_LDARX: return "ldarx"; - case PPC_ID_LDAT: return "ldat"; - case PPC_ID_LDBRX: return "ldbrx"; - case PPC_ID_LDCIX: return "ldcix"; - case PPC_ID_LD: return "ld"; - case PPC_ID_LDU: return "ldu"; - case PPC_ID_LDUX: return "ldux"; - case PPC_ID_LDX: return "ldx"; - case PPC_ID_LFD: return "lfd"; - case PPC_ID_LFDEPX: return "lfdepx"; - case PPC_ID_LFDU: return "lfdu"; - case PPC_ID_LFDUX: return "lfdux"; - case PPC_ID_LFDX: return "lfdx"; - case PPC_ID_LFIWAX: return "lfiwax"; - case PPC_ID_LFIWZX: return "lfiwzx"; - case PPC_ID_LFS: return "lfs"; - case PPC_ID_LFSU: return "lfsu"; - case PPC_ID_LFSUX: return "lfsux"; - case PPC_ID_LFSX: return "lfsx"; - case PPC_ID_LHA: return "lha"; - case PPC_ID_LHARX: return "lharx"; - case PPC_ID_LHAU: return "lhau"; - case PPC_ID_LHAUX: return "lhaux"; - case PPC_ID_LHAX: return "lhax"; - case PPC_ID_LHBRX: return "lhbrx"; - case PPC_ID_LHEPX: return "lhepx"; - case PPC_ID_LHZ: return "lhz"; - case PPC_ID_LHZCIX: return "lhzcix"; - case PPC_ID_LHZU: return "lhzu"; - case PPC_ID_LHZUX: return "lhzux"; - case PPC_ID_LHZX: return "lhzx"; - case PPC_ID_LI: return "li"; - case PPC_ID_LIS: return "lis"; - case PPC_ID_LMW: return "lmw"; - case PPC_ID_LNIA: return "lnia"; - case PPC_ID_LSWI: return "lswi"; - case PPC_ID_LSWX: return "lswx"; - case PPC_ID_LWA: return "lwa"; - case PPC_ID_LWAT: return "lwat"; - case PPC_ID_LWAX: return "lwax"; - case PPC_ID_LWARX: return "lwarx"; - case PPC_ID_LWAUX: return "lwaux"; - case PPC_ID_LWBRX: return "lwbrx"; - case PPC_ID_LWEPX: return "lwepx"; - case PPC_ID_LWSYNC: return "lwsync"; - case PPC_ID_LWZ: return "lwz"; - case PPC_ID_LWZCIX: return "lwzcix"; - case PPC_ID_LWZU: return "lwzu"; - case PPC_ID_LWZUX: return "lwzux"; - case PPC_ID_LWZX: return "lwzx"; - case PPC_ID_MBAR: return "mbar"; - case PPC_ID_MCRF: return "mcrf"; - case PPC_ID_MCRFS: return "mcrfs"; - case PPC_ID_MCRXR: return "mcrxr"; - case PPC_ID_MCRXRX: return "mcrxrx"; - case PPC_ID_MFBHRBE: return "mfbhrbe"; - case PPC_ID_MFBR0: return "mfbr0"; - case PPC_ID_MFBR1: return "mfbr1"; - case PPC_ID_MFBR2: return "mfbr2"; - case PPC_ID_MFBR3: return "mfbr3"; - case PPC_ID_MFBR4: return "mfbr4"; - case PPC_ID_MFBR5: return "mfbr5"; - case PPC_ID_MFBR6: return "mfbr6"; - case PPC_ID_MFBR7: return "mfbr7"; - case PPC_ID_MFCR: return "mfcr"; - case PPC_ID_MFCTR: return "mfctr"; - case PPC_ID_MFDCR: return "mfdcr"; - case PPC_ID_MFDCRUX: return "mfdcrux"; - case PPC_ID_MFDCRX: return "mfdcrx"; - case PPC_ID_MFFSx: return RcMnemonic(instruction, SubMnemMFFSx); - case PPC_ID_MFFSCDRN: return "mffscdrn"; - case PPC_ID_MFFSCDRNI: return "mffscdrni"; - case PPC_ID_MFFSCE: return "mffsce"; - case PPC_ID_MFFSCRN: return "mffscrn"; - case PPC_ID_MFFSCRNI: return "mffscrni"; - case PPC_ID_MFFSL: return "mffsl"; - case PPC_ID_MFLR: return "mflr"; - case PPC_ID_MFMSR: return "mfmsr"; - case PPC_ID_MFOCRF: return "mfocrf"; - case PPC_ID_MFPMR: return "mfpmr"; - case PPC_ID_MFSPR: return "mfspr"; - case PPC_ID_MFSR: return "mfsr"; - case PPC_ID_MFSRIN: return "mfsrin"; - case PPC_ID_MFTB: return "mftb"; - case PPC_ID_MFTBU: return "mftbu"; - case PPC_ID_MFXER: return "mfxer"; - case PPC_ID_MRx: return RcMnemonic(instruction, SubMnemMRx); - case PPC_ID_MSGSYNC: return "msgsync"; - case PPC_ID_MTAMR: return "mtamr"; - case PPC_ID_MTBR0: return "mtbr0"; - case PPC_ID_MTBR1: return "mtbr1"; - case PPC_ID_MTBR2: return "mtbr2"; - case PPC_ID_MTBR3: return "mtbr3"; - case PPC_ID_MTBR4: return "mtbr4"; - case PPC_ID_MTBR5: return "mtbr5"; - case PPC_ID_MTBR6: return "mtbr6"; - case PPC_ID_MTBR7: return "mtbr7"; - case PPC_ID_MTCRF: return "mtcrf"; - case PPC_ID_MTCTR: return "mtctr"; - case PPC_ID_MTDCR: return "mtdcr"; - case PPC_ID_MTDCRUX: return "mtdcrux"; - case PPC_ID_MTDCRX: return "mtdcrx"; - case PPC_ID_MTFSB0x: return RcMnemonic(instruction, SubMnemMTFSB0x); - case PPC_ID_MTFSB1x: return RcMnemonic(instruction, SubMnemMTFSB1x); - case PPC_ID_MTFSFx: return RcMnemonic(instruction, SubMnemMTFSFx); - case PPC_ID_MTFSFIx: return RcMnemonic(instruction, SubMnemMTFSFIx); - case PPC_ID_MODSD: return "modsd"; - case PPC_ID_MODSW: return "modsw"; - case PPC_ID_MODUD: return "modud"; - case PPC_ID_MODUW: return "moduw"; - case PPC_ID_MTLR: return "mtlr"; - case PPC_ID_MTMSR: return "mtmsr"; - case PPC_ID_MTMSRD: return "mtmsrd"; - case PPC_ID_MTOCRF: return "mtocrf"; - case PPC_ID_MTPMR: return "mtpmr"; - case PPC_ID_MTSPR: return "mtspr"; - case PPC_ID_MTSR: return "mtsr"; - case PPC_ID_MTSRIN: return "mtsrin"; - case PPC_ID_MTXER: return "mtxer"; - case PPC_ID_MULHDx: return RcMnemonic(instruction, SubMnemMULHDx); - case PPC_ID_MULHDUx: return RcMnemonic(instruction, SubMnemMULHDUx); - case PPC_ID_MULHWx: return RcMnemonic(instruction, SubMnemMULHWx); - case PPC_ID_MULHWUx: return RcMnemonic(instruction, SubMnemMULHWUx); - case PPC_ID_MULLI: return "mulli"; - case PPC_ID_MULLDx: return OeRcMnemonic(instruction, SubMnemMULLDx); - case PPC_ID_MULLWx: return OeRcMnemonic(instruction, SubMnemMULLWx); - case PPC_ID_NANDx: return RcMnemonic(instruction, SubMnemNANDx); - case PPC_ID_NEGx: return OeRcMnemonic(instruction, SubMnemNEGx); - case PPC_ID_NOP: return "nop"; - case PPC_ID_NORx: return RcMnemonic(instruction, SubMnemNORx); - case PPC_ID_ORx: return RcMnemonic(instruction, SubMnemORx); - case PPC_ID_ORCx: return RcMnemonic(instruction, SubMnemORCx); - case PPC_ID_ORI: return "ori"; - case PPC_ID_ORIS: return "oris"; - case PPC_ID_PASTE: return "paste."; - case PPC_ID_POPCNTB: return "popcntb"; - case PPC_ID_POPCNTD: return "popcntd"; - case PPC_ID_POPCNTW: return "popcntw"; - case PPC_ID_PTESYNC: return "ptesync"; - case PPC_ID_RFCI: return "rfci"; - case PPC_ID_RFDI: return "rfdi"; - case PPC_ID_RFI: return "rfi"; - case PPC_ID_RFID: return "rfid"; - case PPC_ID_RFMCI: return "rfmci"; - case PPC_ID_RLDICLx: return RcMnemonic(instruction, SubMnemRLDICLx); - case PPC_ID_RLDICRx: return RcMnemonic(instruction, SubMnemRLDICRx); - case PPC_ID_RLDICx: return RcMnemonic(instruction, SubMnemRLDICx); - case PPC_ID_RLDIMIx: return RcMnemonic(instruction, SubMnemRLDIMIx); - case PPC_ID_RLDCLx: return RcMnemonic(instruction, SubMnemRLDCLx); - case PPC_ID_RLDCRx: return RcMnemonic(instruction, SubMnemRLDCRx); - case PPC_ID_RLWIMIx: return RcMnemonic(instruction, SubMnemRLWIMIx); - case PPC_ID_RLWINMx: return RcMnemonic(instruction, SubMnemRLWINMx); - case PPC_ID_RLWNMx: return RcMnemonic(instruction, SubMnemRLWNMx); - case PPC_ID_ROTLDx: return RcMnemonic(instruction, SubMnemROTLDx); - case PPC_ID_ROTLDIx: return RcMnemonic(instruction, SubMnemROTLDIx); - case PPC_ID_ROTLWx: return RcMnemonic(instruction, SubMnemROTLWx); - case PPC_ID_ROTLWIx: return RcMnemonic(instruction, SubMnemROTLWIx); - case PPC_ID_SC: return "sc"; - case PPC_ID_SETB: return "setb"; - case PPC_ID_SLBIA: return "slbia"; - case PPC_ID_SLBIE: return "slbie"; - case PPC_ID_SLBIEG: return "slbieg"; - case PPC_ID_SLBMFEE: return "slbmfee"; - case PPC_ID_SLBMFEV: return "slbmfev"; - case PPC_ID_SLBMTE: return "slbmte"; - case PPC_ID_SLBSYNC: return "slbsync"; - case PPC_ID_SLDx: return RcMnemonic(instruction, SubMnemSLDx); - case PPC_ID_SLDIx: return RcMnemonic(instruction, SubMnemSLDIx); - case PPC_ID_SLWx: return RcMnemonic(instruction, SubMnemSLWx); - case PPC_ID_SLWIx: return RcMnemonic(instruction, SubMnemSLWIx); - case PPC_ID_SRADx: return RcMnemonic(instruction, SubMnemSRADx); - case PPC_ID_SRADIx: return RcMnemonic(instruction, SubMnemSRADIx); - case PPC_ID_SRAWx: return RcMnemonic(instruction, SubMnemSRAWx); - case PPC_ID_SRAWIx: return RcMnemonic(instruction, SubMnemSRAWIx); - case PPC_ID_SRDx: return RcMnemonic(instruction, SubMnemSRDx); - case PPC_ID_SRDIx: return RcMnemonic(instruction, SubMnemSRDIx); - case PPC_ID_SRWx: return RcMnemonic(instruction, SubMnemSRWx); - case PPC_ID_SRWIx: return RcMnemonic(instruction, SubMnemSRWIx); - case PPC_ID_STB: return "stb"; - case PPC_ID_STBCIX: return "stbcix"; - case PPC_ID_STBCX: return "stbcx."; - case PPC_ID_STBEPX: return "stbepx"; - case PPC_ID_STBU: return "stbu"; - case PPC_ID_STBUX: return "stbux"; - case PPC_ID_STBX: return "stbx"; - case PPC_ID_STD: return "std"; - case PPC_ID_STDAT: return "stdat"; - case PPC_ID_STDBRX: return "stdbrx"; - case PPC_ID_STDCIX: return "stdcix"; - case PPC_ID_STDCX: return "stdcx."; - case PPC_ID_STDEPX: return "stdepx"; - case PPC_ID_STDU: return "stdu"; - case PPC_ID_STDUX: return "stdux"; - case PPC_ID_STDX: return "stdx"; - case PPC_ID_STFD: return "stfd"; - case PPC_ID_STFDEPX: return "stfdepx"; - case PPC_ID_STFDU: return "stfdu"; - case PPC_ID_STFDUX: return "stfdux"; - case PPC_ID_STFDX: return "stfdx"; - case PPC_ID_STFIWX: return "stfiwx"; - case PPC_ID_STFS: return "stfs"; - case PPC_ID_STFSU: return "stfsu"; - case PPC_ID_STFSUX: return "stfsux"; - case PPC_ID_STFSX: return "stfsx"; - case PPC_ID_STH: return "sth"; - case PPC_ID_STHBRX: return "sthbrx"; - case PPC_ID_STHCIX: return "sthcix"; - case PPC_ID_STHCX: return "sthcx."; - case PPC_ID_STHEPX: return "sthepx"; - case PPC_ID_STHU: return "sthu"; - case PPC_ID_STHUX: return "sthux"; - case PPC_ID_STHX: return "sthx"; - case PPC_ID_STMW: return "stmw"; - case PPC_ID_STSWI: return "stswi"; - case PPC_ID_STSWX: return "stswx"; - case PPC_ID_STW: return "stw"; - case PPC_ID_STWAT: return "stwat"; - case PPC_ID_STWBRX: return "stwbrx"; - case PPC_ID_STWCIX: return "stwcix"; - case PPC_ID_STWCX: return "stwcx."; - case PPC_ID_STWEPX: return "stwepx"; - case PPC_ID_STWU: return "stwu"; - case PPC_ID_STWUX: return "stwux"; - case PPC_ID_STWX: return "stwx"; - case PPC_ID_SUBFx: return OeRcMnemonic(instruction, SubMnemSUBFx); - case PPC_ID_SUBFCx: return OeRcMnemonic(instruction, SubMnemSUBFCx); - case PPC_ID_SUBFEx: return OeRcMnemonic(instruction, SubMnemSUBFEx); - case PPC_ID_SUBFIC: return "subfic"; - case PPC_ID_SUBFMEx: return OeRcMnemonic(instruction, SubMnemSUBFMEx); - case PPC_ID_SUBFZEx: return OeRcMnemonic(instruction, SubMnemSUBFZEx); - case PPC_ID_SYNC: return "sync"; - case PPC_ID_TABORT: return "tabort."; - case PPC_ID_TABORTDC: return "tabortdc."; - case PPC_ID_TABORTDCI: return "tabortdci."; - case PPC_ID_TABORTWC: return "tabortwc."; - case PPC_ID_TABORTWCI: return "tabortwci."; - case PPC_ID_TBEGIN: return "tbegin."; - case PPC_ID_TCHECK: return "tcheck"; - case PPC_ID_TD: return "td"; - case PPC_ID_TDEQ: return "tdeq"; - case PPC_ID_TDEQI: return "tdeqi"; - case PPC_ID_TDGT: return "tdgt"; - case PPC_ID_TDGTI: return "tdgti"; - case PPC_ID_TDI: return "tdi"; - case PPC_ID_TDLGT: return "tdlgt"; - case PPC_ID_TDLGTI: return "tdlgti"; - case PPC_ID_TDLLT: return "tdllt"; - case PPC_ID_TDLLTI: return "tdllti"; - case PPC_ID_TDLT: return "tdlt"; - case PPC_ID_TDLTI: return "tdlti"; - case PPC_ID_TDNE: return "tdne"; - case PPC_ID_TDNEI: return "tdnei"; - case PPC_ID_TDU: return "tdu"; - case PPC_ID_TDUI: return "tdui"; - case PPC_ID_TEND: return "tend."; - case PPC_ID_TLBIA: return "tlbia"; - case PPC_ID_TLBIE: return "tlbie"; - case PPC_ID_TLBIEL: return "tlbiel"; - case PPC_ID_TLBIVAX: return "tlbivax"; - case PPC_ID_TLBLI: return "tlbli"; - case PPC_ID_TLBSX: return "tlbsx"; - case PPC_ID_TLBSYNC: return "tlbsync"; - case PPC_ID_TLBRE: return "tlbre"; - case PPC_ID_TLBRELO: return "tlbrehi"; - case PPC_ID_TLBREHI: return "tlbrelo"; - case PPC_ID_TLBWE: return "tlbwe"; - case PPC_ID_TLBWEHI: return "tlbwehi"; - case PPC_ID_TLBWELO: return "tlbwelo"; - case PPC_ID_TRAP: return "trap"; - case PPC_ID_TRECHKPT: return "trechkpt."; - case PPC_ID_TRECLAIM: return "treclaim."; - case PPC_ID_TSR: return "tsr."; - case PPC_ID_TW: return "tw"; - case PPC_ID_TWEQ: return "tweq"; - case PPC_ID_TWEQI: return "tweqi"; - case PPC_ID_TWGT: return "twgt"; - case PPC_ID_TWGTI: return "twgti"; - case PPC_ID_TWGEI: return "twgei"; - case PPC_ID_TWI: return "twi"; - case PPC_ID_TWLEI: return "twlei"; - case PPC_ID_TWLLEI: return "twllei"; - case PPC_ID_TWLGT: return "twlgt"; - case PPC_ID_TWLGTI: return "twlgti"; - case PPC_ID_TWLLT: return "twllt"; - case PPC_ID_TWLLTI: return "twllti"; - case PPC_ID_TWLT: return "twlt"; - case PPC_ID_TWLTI: return "twlti"; - case PPC_ID_TWNE: return "twne"; - case PPC_ID_TWNEI: return "twnei"; - case PPC_ID_TWU: return "twu"; - case PPC_ID_TWUI: return "twui"; - case PPC_ID_WAIT: return "wait"; - case PPC_ID_WAITIMPL: return "waitimpl"; - case PPC_ID_WAITRSV: return "waitrsv"; - case PPC_ID_WRTEE: return "wrtee"; - case PPC_ID_WRTEEI: return "wrteei"; - case PPC_ID_XNOP: return "xnop"; - case PPC_ID_XORx: return RcMnemonic(instruction, SubMnemXORx); - case PPC_ID_XORI: return "xori"; - case PPC_ID_XORIS: return "xoris"; - - case PPC_ID_AV_VABSDUB: return "vabsdub"; - case PPC_ID_AV_VABSDUH: return "vabsduh"; - case PPC_ID_AV_VABSDUW: return "vabsduw"; - case PPC_ID_AV_VADDUQM: return "vadduqm"; - case PPC_ID_AV_VADDCUQ: return "vaddcuq"; - case PPC_ID_AV_BCDADD: return "bcdadd."; - case PPC_ID_AV_BCDCFN: return "bcdcfn."; - case PPC_ID_AV_BCDCFSQ: return "bcdcfsq."; - case PPC_ID_AV_BCDCFZ: return "bcdcfz."; - case PPC_ID_AV_BCDCPSGN: return "bcdcpsgn."; - case PPC_ID_AV_BCDCTN: return "bcdctn."; - case PPC_ID_AV_BCDCTSQ: return "bcdctsq."; - case PPC_ID_AV_BCDCTZ: return "bcdctz."; - case PPC_ID_AV_BCDS: return "bcds."; - case PPC_ID_AV_BCDSETSGN: return "bcdsetsgn."; - case PPC_ID_AV_BCDSR: return "bcdsr."; - case PPC_ID_AV_BCDSUB: return "bcdsub."; - case PPC_ID_AV_BCDTRUNC: return "bcdtrunc."; - case PPC_ID_AV_BCDUS: return "bcdus."; - case PPC_ID_AV_BCDUTRUNC: return "bcdutrunc."; - case PPC_ID_AV_DSS: return "dss"; - case PPC_ID_AV_DSSALL: return "dssall"; - case PPC_ID_AV_DST: return "dst"; - case PPC_ID_AV_DSTST: return "dstst"; - case PPC_ID_AV_DSTSTT: return "dststt"; - case PPC_ID_AV_DSTT: return "dstt"; - case PPC_ID_AV_LVEBX: return "lvebx"; - case PPC_ID_AV_LVEHX: return "lvehx"; - case PPC_ID_AV_LVEWX: return "lvewx"; - case PPC_ID_AV_LVSL: return "lvsl"; - case PPC_ID_AV_LVSR: return "lvsr"; - case PPC_ID_AV_LVX: return "lvx"; - case PPC_ID_AV_LVXL: return "lvxl"; - case PPC_ID_AV_MADDHD: return "maddhd"; - case PPC_ID_AV_MADDHDU: return "maddhdu"; - case PPC_ID_AV_MADDLD: return "maddld"; - case PPC_ID_AV_MFVSCR: return "mfvscr"; - case PPC_ID_AV_MTVSCR: return "mtvscr"; - case PPC_ID_AV_STVEBX: return "stvebx"; - case PPC_ID_AV_STVEHX: return "stvehx"; - case PPC_ID_AV_STVEWX: return "stvewx"; - case PPC_ID_AV_STVX: return "stvx"; - case PPC_ID_AV_STVXL: return "stvxl"; - case PPC_ID_AV_VADDCUW: return "vaddcuw"; - case PPC_ID_AV_VADDECUQ: return "vaddecuq"; - case PPC_ID_AV_VADDEUQM: return "vaddeuqm"; - case PPC_ID_AV_VADDFP: return "vaddfp"; - case PPC_ID_AV_VADDSBS: return "vaddsbs"; - case PPC_ID_AV_VADDSHS: return "vaddshs"; - case PPC_ID_AV_VADDSWS: return "vaddsws"; - case PPC_ID_AV_VADDUBM: return "vaddubm"; - case PPC_ID_AV_VADDUBS: return "vaddubs"; - case PPC_ID_AV_VADDUDM: return "vaddudm"; - case PPC_ID_AV_VADDUHM: return "vadduhm"; - case PPC_ID_AV_VADDUHS: return "vadduhs"; - case PPC_ID_AV_VADDUWM: return "vadduwm"; - case PPC_ID_AV_VADDUWS: return "vadduws"; - case PPC_ID_AV_VAND: return "vand"; - case PPC_ID_AV_VANDC: return "vandc"; - case PPC_ID_AV_VAVGSB: return "vavgsb"; - case PPC_ID_AV_VAVGSH: return "vavgsh"; - case PPC_ID_AV_VAVGSW: return "vavgsw"; - case PPC_ID_AV_VAVGUB: return "vavgub"; - case PPC_ID_AV_VAVGUH: return "vavguh"; - case PPC_ID_AV_VAVGUW: return "vavguw"; - case PPC_ID_AV_VBPERMD: return "vbpermd"; - case PPC_ID_AV_VBPERMQ: return "vbpermq"; - case PPC_ID_AV_VCFSX: return "vcfsx"; - case PPC_ID_AV_VCFUX: return "vcfux"; - case PPC_ID_AV_VCIPHER: return "vcipher"; - case PPC_ID_AV_VCIPHERLAST: return "vcipherlast"; - case PPC_ID_AV_VCLZB: return "vclzb"; - case PPC_ID_AV_VCLZD: return "vclzd"; - case PPC_ID_AV_VCLZH: return "vclzh"; - case PPC_ID_AV_VCLZLSBB: return "vclzlsbb"; - case PPC_ID_AV_VCLZW: return "vclzw"; - case PPC_ID_AV_VCMPBFPx: return RcMnemonic(instruction, SubMnemVCMPBFPx); - case PPC_ID_AV_VCMPEQFPx: return RcMnemonic(instruction, SubMnemVCMPEQFPx); - case PPC_ID_AV_VCMPEQUBx: return RcMnemonic(instruction, SubMnemVCMPEQUBx); - case PPC_ID_AV_VCMPEQUDx: return RcMnemonic(instruction, SubMnemVCMPEQUDx); - case PPC_ID_AV_VCMPEQUHx: return RcMnemonic(instruction, SubMnemVCMPEQUHx); - case PPC_ID_AV_VCMPEQUWx: return RcMnemonic(instruction, SubMnemVCMPEQUWx); - case PPC_ID_AV_VCMPGEFPx: return RcMnemonic(instruction, SubMnemVCMPGEFPx); - case PPC_ID_AV_VCMPGTFPx: return RcMnemonic(instruction, SubMnemVCMPGTFPx); - case PPC_ID_AV_VCMPGTSBx: return RcMnemonic(instruction, SubMnemVCMPGTSBx); - case PPC_ID_AV_VCMPGTSDx: return RcMnemonic(instruction, SubMnemVCMPGTSDx); - case PPC_ID_AV_VCMPGTSHx: return RcMnemonic(instruction, SubMnemVCMPGTSHx); - case PPC_ID_AV_VCMPGTSWx: return RcMnemonic(instruction, SubMnemVCMPGTSWx); - case PPC_ID_AV_VCMPGTUBx: return RcMnemonic(instruction, SubMnemVCMPGTUBx); - case PPC_ID_AV_VCMPGTUDx: return RcMnemonic(instruction, SubMnemVCMPGTUDx); - case PPC_ID_AV_VCMPGTUHx: return RcMnemonic(instruction, SubMnemVCMPGTUHx); - case PPC_ID_AV_VCMPGTUWx: return RcMnemonic(instruction, SubMnemVCMPGTUWx); - case PPC_ID_AV_VCMPNEBx: return RcMnemonic(instruction, SubMnemVCMPNEBx); - case PPC_ID_AV_VCMPNEHx: return RcMnemonic(instruction, SubMnemVCMPNEHx); - case PPC_ID_AV_VCMPNEWx: return RcMnemonic(instruction, SubMnemVCMPNEWx); - case PPC_ID_AV_VCMPNEZBx: return RcMnemonic(instruction, SubMnemVCMPNEZBx); - case PPC_ID_AV_VCMPNEZHx: return RcMnemonic(instruction, SubMnemVCMPNEZHx); - case PPC_ID_AV_VCMPNEZWx: return RcMnemonic(instruction, SubMnemVCMPNEZWx); - case PPC_ID_AV_VCTSXS: return "vctsxs"; - case PPC_ID_AV_VCTUXS: return "vctuxs"; - case PPC_ID_AV_VCTZB: return "vctzb"; - case PPC_ID_AV_VCTZD: return "vctzd"; - case PPC_ID_AV_VCTZH: return "vctzh"; - case PPC_ID_AV_VCTZLSBB: return "vctzlsbb"; - case PPC_ID_AV_VCTZW: return "vctzw"; - case PPC_ID_AV_VEQV: return "veqv"; - case PPC_ID_AV_VEXPTEFP: return "vexptefp"; - case PPC_ID_AV_VEXTRACTD: return "vextractd"; - case PPC_ID_AV_VEXTRACTUB: return "vextractub"; - case PPC_ID_AV_VEXTRACTUH: return "vextractuh"; - case PPC_ID_AV_VEXTRACTUW: return "vextractuw"; - case PPC_ID_AV_VEXTSB2D: return "vextsb2d"; - case PPC_ID_AV_VEXTSB2W: return "vextsb2w"; - case PPC_ID_AV_VEXTSH2D: return "vextsh2d"; - case PPC_ID_AV_VEXTSH2W: return "vextsh2w"; - case PPC_ID_AV_VEXTSW2D: return "vextsw2d"; - case PPC_ID_AV_VEXTUBLX: return "vextublx"; - case PPC_ID_AV_VEXTUHLX: return "vextuhlx"; - case PPC_ID_AV_VEXTUWLX: return "vextuwlx"; - case PPC_ID_AV_VEXTUBRX: return "vextubrx"; - case PPC_ID_AV_VEXTUHRX: return "vextuhrx"; - case PPC_ID_AV_VEXTUWRX: return "vextuwrx"; - case PPC_ID_AV_VGBBD: return "vgbbd"; - case PPC_ID_AV_VINSERTB: return "vinsertb"; - case PPC_ID_AV_VINSERTD: return "vinsertd"; - case PPC_ID_AV_VINSERTH: return "vinserth"; - case PPC_ID_AV_VINSERTW: return "vinsertw"; - case PPC_ID_AV_VLOGEFP: return "vlogefp"; - case PPC_ID_AV_VMADDFP: return "vmaddfp"; - case PPC_ID_AV_VMAXFP: return "vmaxfp"; - case PPC_ID_AV_VMAXSB: return "vmaxsb"; - case PPC_ID_AV_VMAXSD: return "vmaxsd"; - case PPC_ID_AV_VMAXSH: return "vmaxsh"; - case PPC_ID_AV_VMAXSW: return "vmaxsw"; - case PPC_ID_AV_VMAXUB: return "vmaxub"; - case PPC_ID_AV_VMAXUD: return "vmaxud"; - case PPC_ID_AV_VMAXUH: return "vmaxuh"; - case PPC_ID_AV_VMAXUW: return "vmaxuw"; - case PPC_ID_AV_VMHADDSHS: return "vmhaddshs"; - case PPC_ID_AV_VMHRADDSHS: return "vmhraddshs"; - case PPC_ID_AV_VMINFP: return "vminfp"; - case PPC_ID_AV_VMINSB: return "vminsb"; - case PPC_ID_AV_VMINSD: return "vminsd"; - case PPC_ID_AV_VMINSH: return "vminsh"; - case PPC_ID_AV_VMINSW: return "vminsw"; - case PPC_ID_AV_VMINUB: return "vminub"; - case PPC_ID_AV_VMINUD: return "vminud"; - case PPC_ID_AV_VMINUH: return "vminuh"; - case PPC_ID_AV_VMINUW: return "vminuw"; - case PPC_ID_AV_VMLADDUHM: return "vmladduhm"; - case PPC_ID_AV_VMR: return "vmr"; - case PPC_ID_AV_VMRGEW: return "vmrgew"; - case PPC_ID_AV_VMRGHB: return "vmrghb"; - case PPC_ID_AV_VMRGHH: return "vmrghh"; - case PPC_ID_AV_VMRGHW: return "vmrghw"; - case PPC_ID_AV_VMRGLB: return "vmrglb"; - case PPC_ID_AV_VMRGLH: return "vmrglh"; - case PPC_ID_AV_VMRGLW: return "vmrglw"; - case PPC_ID_AV_VMRGOW: return "vmrgow"; - case PPC_ID_AV_VMSUMMBM: return "vmsummbm"; - case PPC_ID_AV_VMSUMSHM: return "vmsumshm"; - case PPC_ID_AV_VMSUMSHS: return "vmsumshs"; - case PPC_ID_AV_VMSUMUBM: return "vmsumubm"; - case PPC_ID_AV_VMSUMUHM: return "vmsumuhm"; - case PPC_ID_AV_VMSUMUHS: return "vmsumuhs"; - case PPC_ID_AV_VMUL10CUQ: return "vmul10cuq"; - case PPC_ID_AV_VMUL10EUQ: return "vmul10euq"; - case PPC_ID_AV_VMUL10ECUQ: return "vmul10ecuq"; - case PPC_ID_AV_VMUL10UQ: return "vmul10uq"; - case PPC_ID_AV_VMULESB: return "vmulesb"; - case PPC_ID_AV_VMULESH: return "vmulesh"; - case PPC_ID_AV_VMULESW: return "vmulesw"; - case PPC_ID_AV_VMULEUB: return "vmuleub"; - case PPC_ID_AV_VMULEUH: return "vmuleuh"; - case PPC_ID_AV_VMULEUW: return "vmuleuw"; - case PPC_ID_AV_VMULOSB: return "vmulosb"; - case PPC_ID_AV_VMULOSH: return "vmulosh"; - case PPC_ID_AV_VMULOSW: return "vmulosw"; - case PPC_ID_AV_VMULOUB: return "vmuloub"; - case PPC_ID_AV_VMULOUH: return "vmulouh"; - case PPC_ID_AV_VMULOUW: return "vmulouw"; - case PPC_ID_AV_VMULUWM: return "vmuluwm"; - case PPC_ID_AV_VNAND: return "vnand"; - case PPC_ID_AV_VNCIPHER: return "vncipher"; - case PPC_ID_AV_VNCIPHERLAST: return "vncipherlast"; - case PPC_ID_AV_VNMSUBFP: return "vnmsubfp"; - case PPC_ID_AV_VNEGD: return "vnegd"; - case PPC_ID_AV_VNEGW: return "vnegw"; - case PPC_ID_AV_VNOR: return "vnor"; - case PPC_ID_AV_VNOT: return "vnot"; - case PPC_ID_AV_VOR: return "vor"; - case PPC_ID_AV_VORC: return "vorc"; - case PPC_ID_AV_VPERM: return "vperm"; - case PPC_ID_AV_VPERMR: return "vpermr"; - case PPC_ID_AV_VPERMXOR: return "vpermxor"; - case PPC_ID_AV_VPKPX: return "vpkpx"; - case PPC_ID_AV_VPKSDSS: return "vpksdss"; - case PPC_ID_AV_VPKSDUS: return "vpksdus"; - case PPC_ID_AV_VPKSHSS: return "vpkshss"; - case PPC_ID_AV_VPKSHUS: return "vpkshus"; - case PPC_ID_AV_VPKSWSS: return "vpkswss"; - case PPC_ID_AV_VPKSWUS: return "vpkswus"; - case PPC_ID_AV_VPKUDUM: return "vpkudum"; - case PPC_ID_AV_VPKUDUS: return "vpkudus"; - case PPC_ID_AV_VPKUHUM: return "vpkuhum"; - case PPC_ID_AV_VPKUHUS: return "vpkuhus"; - case PPC_ID_AV_VPKUWUM: return "vpkuwum"; - case PPC_ID_AV_VPKUWUS: return "vpkuwus"; - case PPC_ID_AV_VPMSUMB: return "vpmsumb"; - case PPC_ID_AV_VPMSUMD: return "vpmsumd"; - case PPC_ID_AV_VPMSUMH: return "vpmsumh"; - case PPC_ID_AV_VPMSUMW: return "vpmsumw"; - case PPC_ID_AV_VPOPCNTB: return "vpopcntb"; - case PPC_ID_AV_VPOPCNTD: return "vpopcntd"; - case PPC_ID_AV_VPOPCNTH: return "vpopcnth"; - case PPC_ID_AV_VPOPCNTW: return "vpopcntw"; - case PPC_ID_AV_VPRTYBD: return "vprtybd"; - case PPC_ID_AV_VPRTYBQ: return "vprtybq"; - case PPC_ID_AV_VPRTYBW: return "vprtybw"; - case PPC_ID_AV_VREFP: return "vrefp"; - case PPC_ID_AV_VRFIM: return "vrfim"; - case PPC_ID_AV_VRFIN: return "vrfin"; - case PPC_ID_AV_VRFIP: return "vrfip"; - case PPC_ID_AV_VRFIZ: return "vrfiz"; - case PPC_ID_AV_VRLB: return "vrlb"; - case PPC_ID_AV_VRLD: return "vrld"; - case PPC_ID_AV_VRLDNM: return "vrldnm"; - case PPC_ID_AV_VRLDMI: return "vrldmi"; - case PPC_ID_AV_VRLH: return "vrlh"; - case PPC_ID_AV_VRLW: return "vrlw"; - case PPC_ID_AV_VRLWMI: return "vrlwmi"; - case PPC_ID_AV_VRLWNM: return "vrlwnm"; - case PPC_ID_AV_VRSQRTEFP: return "vrsqrtefp"; - case PPC_ID_AV_VSBOX: return "vsbox"; - case PPC_ID_AV_VSEL: return "vsel"; - case PPC_ID_AV_VSHASIGMAD: return "vshasigmad"; - case PPC_ID_AV_VSHASIGMAW: return "vshasigmaw"; - case PPC_ID_AV_VSL: return "vsl"; - case PPC_ID_AV_VSLB: return "vslb"; - case PPC_ID_AV_VSLD: return "vsld"; - case PPC_ID_AV_VSLDOI: return "vsldoi"; - case PPC_ID_AV_VSLH: return "vslh"; - case PPC_ID_AV_VSLO: return "vslo"; - case PPC_ID_AV_VSLV: return "vslv"; - case PPC_ID_AV_VSLW: return "vslw"; - case PPC_ID_AV_VSPLTB: return "vspltb"; - case PPC_ID_AV_VSPLTH: return "vsplth"; - case PPC_ID_AV_VSPLTISB: return "vspltisb"; - case PPC_ID_AV_VSPLTISH: return "vspltish"; - case PPC_ID_AV_VSPLTISW: return "vspltisw"; - case PPC_ID_AV_VSPLTW: return "vspltw"; - case PPC_ID_AV_VSR: return "vsr"; - case PPC_ID_AV_VSRAB: return "vsrab"; - case PPC_ID_AV_VSRAD: return "vsrad"; - case PPC_ID_AV_VSRAH: return "vsrah"; - case PPC_ID_AV_VSRAW: return "vsraw"; - case PPC_ID_AV_VSRB: return "vsrb"; - case PPC_ID_AV_VSRD: return "vsrd"; - case PPC_ID_AV_VSRH: return "vsrh"; - case PPC_ID_AV_VSRO: return "vsro"; - case PPC_ID_AV_VSRV: return "vsrv"; - case PPC_ID_AV_VSRW: return "vsrw"; - case PPC_ID_AV_VSUBCUQ: return "vsubcuq"; - case PPC_ID_AV_VSUBCUW: return "vsubcuw"; - case PPC_ID_AV_VSUBECUQ: return "vsubecuq"; - case PPC_ID_AV_VSUBEUQM: return "vsubeuqm"; - case PPC_ID_AV_VSUBFP: return "vsubfp"; - case PPC_ID_AV_VSUBSBS: return "vsubsbs"; - case PPC_ID_AV_VSUBSHS: return "vsubshs"; - case PPC_ID_AV_VSUBSWS: return "vsubsws"; - case PPC_ID_AV_VSUBUBM: return "vsububm"; - case PPC_ID_AV_VSUBUBS: return "vsububs"; - case PPC_ID_AV_VSUBUDM: return "vsubudm"; - case PPC_ID_AV_VSUBUHM: return "vsubuhm"; - case PPC_ID_AV_VSUBUHS: return "vsubuhs"; - case PPC_ID_AV_VSUBUQM: return "vsubuqm"; - case PPC_ID_AV_VSUBUWM: return "vsubuwm"; - case PPC_ID_AV_VSUBUWS: return "vsubuws"; - case PPC_ID_AV_VSUMSWS: return "vsumsws"; - case PPC_ID_AV_VSUM2SWS: return "vsum2sws"; - case PPC_ID_AV_VSUM4SBS: return "vsum4sbs"; - case PPC_ID_AV_VSUM4SHS: return "vsum4shs"; - case PPC_ID_AV_VSUM4UBS: return "vsum4ubs"; - case PPC_ID_AV_VUPKHPX: return "vupkhpx"; - case PPC_ID_AV_VUPKHSB: return "vupkhsb"; - case PPC_ID_AV_VUPKHSH: return "vupkhsh"; - case PPC_ID_AV_VUPKHSW: return "vupkhsw"; - case PPC_ID_AV_VUPKLPX: return "vupklpx"; - case PPC_ID_AV_VUPKLSB: return "vupklsb"; - case PPC_ID_AV_VUPKLSH: return "vupklsh"; - case PPC_ID_AV_VUPKLSW: return "vupklsw"; - case PPC_ID_AV_VXOR: return "vxor"; - - case PPC_ID_VSX_LXSDX: return "lxsdx"; - case PPC_ID_VSX_LXSIBZX: return "lxsibzx"; - case PPC_ID_VSX_LXSIHZX: return "lxsihzx"; - case PPC_ID_VSX_LXSIWAX: return "lxsiwax"; - case PPC_ID_VSX_LXSIWZX: return "lxsiwzx"; - case PPC_ID_VSX_LXSSPX: return "lxsspx"; - case PPC_ID_VSX_LXV: return "lxv"; - case PPC_ID_VSX_LXVB16X: return "lxvb16x"; - case PPC_ID_VSX_LXVD2X: return "lxvd2x"; - case PPC_ID_VSX_LXVDSX: return "lxvdsx"; - case PPC_ID_VSX_LXVH8X: return "lxvh8x"; - case PPC_ID_VSX_LXVL: return "lxvl"; - case PPC_ID_VSX_LXVLL: return "lxvll"; - case PPC_ID_VSX_LXVW4X: return "lxvw4x"; - case PPC_ID_VSX_LXVWSX: return "lxvwsx"; - case PPC_ID_VSX_LXVX: return "lxvx"; - case PPC_ID_VSX_MFFPRD: return "mffprd"; - case PPC_ID_VSX_MFVSRD: return "mfvsrd"; - case PPC_ID_VSX_MFVSRLD: return "mfvsrld"; - case PPC_ID_VSX_MFVSRWZ: return "mfvsrwz"; - case PPC_ID_VSX_MTVSRD: return "mtvsrd"; - case PPC_ID_VSX_MTVSRDD: return "mtvsrdd"; - case PPC_ID_VSX_MTVSRWA: return "mtvsrwa"; - case PPC_ID_VSX_MTVSRWS: return "mtvsrws"; - case PPC_ID_VSX_MTVSRWZ: return "mtvsrwz"; - case PPC_ID_VSX_STXSD: return "stxsd"; - case PPC_ID_VSX_STXSDX: return "stxsdx"; - case PPC_ID_VSX_STXSIBX: return "stxsibx"; - case PPC_ID_VSX_STXSIHX: return "stxsihx"; - case PPC_ID_VSX_STXSIWX: return "stxsiwx"; - case PPC_ID_VSX_STXSSP: return "stxssp"; - case PPC_ID_VSX_STXSSPX: return "stxsspx"; - case PPC_ID_VSX_STXVB16X: return "stxvb16x"; - case PPC_ID_VSX_STXVD2X: return "stxvd2x"; - case PPC_ID_VSX_STXVH8X: return "stxvh8x"; - case PPC_ID_VSX_STXV: return "stxv"; - case PPC_ID_VSX_STXVL: return "stxvl"; - case PPC_ID_VSX_STXVLL: return "stxvll"; - case PPC_ID_VSX_STXVW4X: return "stxvw4x"; - case PPC_ID_VSX_STXVX: return "stxvx"; - case PPC_ID_VSX_XSABSDP: return "xsabsdp"; - case PPC_ID_VSX_XSABSQP: return "xsabsqp"; - case PPC_ID_VSX_XSADDDP: return "xsadddp"; - case PPC_ID_VSX_XSADDSP: return "xsaddsp"; - case PPC_ID_VSX_XSADDQPx: return Round2OddMnemonic(instruction, SubMnemXSADDQPx); - case PPC_ID_VSX_XSCMPEQDP: return "xscmpeqdp"; - case PPC_ID_VSX_XSCMPEXPDP: return "xscmpexpdp"; - case PPC_ID_VSX_XSCMPEXPQP: return "xscmpexpqp"; - case PPC_ID_VSX_XSCMPGEDP: return "xscmpgedp"; - case PPC_ID_VSX_XSCMPGTDP: return "xscmpgtdp"; - case PPC_ID_VSX_XSCMPODP: return "xscmpodp"; - case PPC_ID_VSX_XSCMPOQP: return "xscmpoqp"; - case PPC_ID_VSX_XSCMPUDP: return "xscmpudp"; - case PPC_ID_VSX_XSCMPUQP: return "xscmpuqp"; - case PPC_ID_VSX_XSCPSGNDP: return "xscpsgndp"; - case PPC_ID_VSX_XSCPSGNQP: return "xscpsgnqp"; - case PPC_ID_VSX_XSCVDPHP: return "xscvdphp"; - case PPC_ID_VSX_XSCVDPQP: return "xscvdpqp"; - case PPC_ID_VSX_XSCVDPSP: return "xscvdpsp"; - case PPC_ID_VSX_XSCVDPSPN: return "xscvdpspn"; - case PPC_ID_VSX_XSCVDPSXDS: return "xscvdpsxds"; - case PPC_ID_VSX_XSCVDPSXWS: return "xscvdpsxws"; - case PPC_ID_VSX_XSCVDPUXDS: return "xscvdpuxds"; - case PPC_ID_VSX_XSCVDPUXWS: return "xscvdpuxws"; - case PPC_ID_VSX_XSCVHPDP: return "xscvhpdp"; - case PPC_ID_VSX_XSCVQPDPx: return Round2OddMnemonic(instruction, SubMnemXSCVQPDPx); - case PPC_ID_VSX_XSCVQPSDZ: return "xscvqpsdz"; - case PPC_ID_VSX_XSCVQPSWZ: return "xscvqpswz"; - case PPC_ID_VSX_XSCVQPUDZ: return "xscvqpudz"; - case PPC_ID_VSX_XSCVQPUWZ: return "xscvqpuwz"; - case PPC_ID_VSX_XSCVSDQP: return "xscvsdqp"; - case PPC_ID_VSX_XSCVSPDP: return "xscvspdp"; - case PPC_ID_VSX_XSCVSPDPN: return "xscvspdpn"; - case PPC_ID_VSX_XSCVSXDDP: return "xscvsxddp"; - case PPC_ID_VSX_XSCVSXDSP: return "xscvsxdsp"; - case PPC_ID_VSX_XSCVUDQP: return "xscvudqp"; - case PPC_ID_VSX_XSCVUXDDP: return "xscvuxddp"; - case PPC_ID_VSX_XSCVUXDSP: return "xscvuxdsp"; - case PPC_ID_VSX_XSDIVDP: return "xsdivdp"; - case PPC_ID_VSX_XSDIVSP: return "xsdivsp"; - case PPC_ID_VSX_XSDIVQPx: return Round2OddMnemonic(instruction, SubMnemXSDIVQPx); - case PPC_ID_VSX_XSIEXPDP: return "xsiexpdp"; - case PPC_ID_VSX_XSIEXPQP: return "xsiexpqp"; - case PPC_ID_VSX_XSMADDADP: return "xsmaddadp"; - case PPC_ID_VSX_XSMADDASP: return "xsmaddasp"; - case PPC_ID_VSX_XSMADDMDP: return "xsmaddmdp"; - case PPC_ID_VSX_XSMADDMSP: return "xsmaddmsp"; - case PPC_ID_VSX_XSMADDQPx: return Round2OddMnemonic(instruction, SubMnemXSMADDQPx); - case PPC_ID_VSX_XSMAXCDP: return "xsmaxcdp"; - case PPC_ID_VSX_XSMAXDP: return "xsmaxdp"; - case PPC_ID_VSX_XSMAXJDP: return "xsmaxjdp"; - case PPC_ID_VSX_XSMINDP: return "xsmindp"; - case PPC_ID_VSX_XSMINCDP: return "xsmincdp"; - case PPC_ID_VSX_XSMINJDP: return "xsminjdp"; - case PPC_ID_VSX_XSMSUBADP: return "xsmsubadp"; - case PPC_ID_VSX_XSMSUBASP: return "xsmsubasp"; - case PPC_ID_VSX_XSMSUBMDP: return "xsmsubmdp"; - case PPC_ID_VSX_XSMSUBMSP: return "xsmsubmsp"; - case PPC_ID_VSX_XSMSUBQPx: return Round2OddMnemonic(instruction, SubMnemXSMSUBQPx); - case PPC_ID_VSX_XSMULDP: return "xsmuldp"; - case PPC_ID_VSX_XSMULSP: return "xsmulsp"; - case PPC_ID_VSX_XSMULQPx: return Round2OddMnemonic(instruction, SubMnemXSMULQPx); - case PPC_ID_VSX_XSNABSDP: return "xsnabsdp"; - case PPC_ID_VSX_XSNABSQP: return "xsnabsqp"; - case PPC_ID_VSX_XSNEGDP: return "xsnegdp"; - case PPC_ID_VSX_XSNEGQP: return "xsnegqp"; - case PPC_ID_VSX_XSNMADDADP: return "xsnmaddadp"; - case PPC_ID_VSX_XSNMADDASP: return "xsnmaddasp"; - case PPC_ID_VSX_XSNMADDQPx: return Round2OddMnemonic(instruction, SubMnemXSNMADDQPx); - case PPC_ID_VSX_XSNMADDMDP: return "xsnmaddmdp"; - case PPC_ID_VSX_XSNMADDMSP: return "xsnmaddmsp"; - case PPC_ID_VSX_XSNMSUBADP: return "xsnmsubadp"; - case PPC_ID_VSX_XSNMSUBASP: return "xsnmsubasp"; - case PPC_ID_VSX_XSNMSUBMDP: return "xsnmsubmdp"; - case PPC_ID_VSX_XSNMSUBMSP: return "xsnmsubmsp"; - case PPC_ID_VSX_XSNMSUBQPx: return Round2OddMnemonic(instruction, SubMnemXSNMSUBQPx); - case PPC_ID_VSX_XSRDPI: return "xsrdpi"; - case PPC_ID_VSX_XSRDPIC: return "xsrdpic"; - case PPC_ID_VSX_XSRDPIM: return "xsrdpim"; - case PPC_ID_VSX_XSRDPIP: return "xsrdpip"; - case PPC_ID_VSX_XSRDPIZ: return "xsrdpiz"; - case PPC_ID_VSX_XSREDP: return "xsredp"; - case PPC_ID_VSX_XSRESP: return "xsresp"; - case PPC_ID_VSX_XSRSP: return "xsrsp"; - case PPC_ID_VSX_XSRSQRTEDP: return "xsrsqrtedp"; - case PPC_ID_VSX_XSRSQRTESP: return "xsrsqrtesp"; - case PPC_ID_VSX_XSSQRTDP: return "xssqrtdp"; - case PPC_ID_VSX_XSSQRTQPx: return Round2OddMnemonic(instruction, SubMnemXSSQRTQPx); - case PPC_ID_VSX_XSSQRTSP: return "xssqrtsp"; - case PPC_ID_VSX_XSSUBDP: return "xssubdp"; - case PPC_ID_VSX_XSSUBSP: return "xssubsp"; - case PPC_ID_VSX_XSSUBQPx: return Round2OddMnemonic(instruction, SubMnemXSSUBQPx); - case PPC_ID_VSX_XSRQPIx: return InexactMnemonic(instruction, SubMnemXSRQPIx); - case PPC_ID_VSX_XSRQPXP: return "xsrqpxp"; - case PPC_ID_VSX_XSTDIVDP: return "xstdivdp"; - case PPC_ID_VSX_XSTDIVSP: return "xstdivsp"; - case PPC_ID_VSX_XSTSTDCDP: return "xststdcdp"; - case PPC_ID_VSX_XSTSTDCQP: return "xststdcqp"; - case PPC_ID_VSX_XSTSTDCSP: return "xststdcsp"; - case PPC_ID_VSX_XSTSQRTDP: return "xstsqrtdp"; - case PPC_ID_VSX_XSXEXPDP: return "xsxexpdp"; - case PPC_ID_VSX_XSXEXPQP: return "xsxexpqp"; - case PPC_ID_VSX_XSXSIGDP: return "xsxsigdp"; - case PPC_ID_VSX_XSXSIGQP: return "xsxsigqp"; - case PPC_ID_VSX_XVABSSP: return "xvabssp"; - case PPC_ID_VSX_XVABSDP: return "xvabsdp"; - case PPC_ID_VSX_XVADDSP: return "xvaddsp"; - case PPC_ID_VSX_XVADDDP: return "xvadddp"; - case PPC_ID_VSX_XVCMPEQDPx: return RcMnemonic(instruction, SubMnemXVCMPEQDPx); - case PPC_ID_VSX_XVCMPEQSPx: return RcMnemonic(instruction, SubMnemXVCMPEQSPx); - case PPC_ID_VSX_XVCMPGEDPx: return RcMnemonic(instruction, SubMnemXVCMPGEDPx); - case PPC_ID_VSX_XVCMPGESPx: return RcMnemonic(instruction, SubMnemXVCMPGESPx); - case PPC_ID_VSX_XVCMPGTDPx: return RcMnemonic(instruction, SubMnemXVCMPGTDPx); - case PPC_ID_VSX_XVCMPGTSPx: return RcMnemonic(instruction, SubMnemXVCMPGTSPx); - case PPC_ID_VSX_XVCPSGNDP: return "xvcpsgndp"; - case PPC_ID_VSX_XVCPSGNSP: return "xvcpsgnsp"; - case PPC_ID_VSX_XVCVDPSP: return "xvcvdpsp"; - case PPC_ID_VSX_XVCVDPSXDS: return "xvcvdpsxds"; - case PPC_ID_VSX_XVCVDPSXWS: return "xvcvdpsxws"; - case PPC_ID_VSX_XVCVDPUXDS: return "xvcvdpuxds"; - case PPC_ID_VSX_XVCVDPUXWS: return "xvcvdpuxws"; - case PPC_ID_VSX_XVCVHPSP: return "xvcvhpsp"; - case PPC_ID_VSX_XVCVSPDP: return "xvcvspdp"; - case PPC_ID_VSX_XVCVSPHP: return "xvcvsphp"; - case PPC_ID_VSX_XVCVSPSXDS: return "xvcvspsxds"; - case PPC_ID_VSX_XVCVSPSXWS: return "xvcvspsxws"; - case PPC_ID_VSX_XVCVSPUXDS: return "xvcvspuxds"; - case PPC_ID_VSX_XVCVSPUXWS: return "xvcvspuxws"; - case PPC_ID_VSX_XVCVSXDDP: return "xvcvsxddp"; - case PPC_ID_VSX_XVCVSXDSP: return "xvcvsxdsp"; - case PPC_ID_VSX_XVCVSXWDP: return "xvcvsxwdp"; - case PPC_ID_VSX_XVCVSXWSP: return "xvcvsxwsp"; - case PPC_ID_VSX_XVCVUXDDP: return "xvcvuxddp"; - case PPC_ID_VSX_XVCVUXDSP: return "xvcvuxdsp"; - case PPC_ID_VSX_XVCVUXWDP: return "xvcvuxwdp"; - case PPC_ID_VSX_XVCVUXWSP: return "xvcvuxwsp"; - case PPC_ID_VSX_XVDIVDP: return "xvdivdp"; - case PPC_ID_VSX_XVDIVSP: return "xvdivsp"; - case PPC_ID_VSX_XVIEXPDP: return "xviexpdp"; - case PPC_ID_VSX_XVIEXPSP: return "xviexpsp"; - case PPC_ID_VSX_XVMADDADP: return "xvmaddadp"; - case PPC_ID_VSX_XVMADDASP: return "xvmaddasp"; - case PPC_ID_VSX_XVMADDMDP: return "xvmaddmdp"; - case PPC_ID_VSX_XVMADDMSP: return "xvmaddmsp"; - case PPC_ID_VSX_XVMAXDP: return "xvmaxdp"; - case PPC_ID_VSX_XVMAXSP: return "xvmaxsp"; - case PPC_ID_VSX_XVMINDP: return "xvmindp"; - case PPC_ID_VSX_XVMINSP: return "xvminsp"; - case PPC_ID_VSX_XVMOVDP: return "xvmovdp"; - case PPC_ID_VSX_XVMOVSP: return "xvmovsp"; - case PPC_ID_VSX_XVMSUBADP: return "xvmsubadp"; - case PPC_ID_VSX_XVMSUBASP: return "xvmsubasp"; - case PPC_ID_VSX_XVMSUBMDP: return "xvmsubmdp"; - case PPC_ID_VSX_XVMSUBMSP: return "xvmsubmsp"; - case PPC_ID_VSX_XVMULSP: return "xvmulsp"; - case PPC_ID_VSX_XVMULDP: return "xvmuldp"; - case PPC_ID_VSX_XVNABSDP: return "xvnabsdp"; - case PPC_ID_VSX_XVNABSSP: return "xvnabssp"; - case PPC_ID_VSX_XVNMADDADP: return "xvnmaddadp"; - case PPC_ID_VSX_XVNMADDASP: return "xvnmaddasp"; - case PPC_ID_VSX_XVNMADDMDP: return "xvnmaddmdp"; - case PPC_ID_VSX_XVNMADDMSP: return "xvnmaddmsp"; - case PPC_ID_VSX_XVNEGDP: return "xvnegdp"; - case PPC_ID_VSX_XVNEGSP: return "xvnegsp"; - case PPC_ID_VSX_XVNMSUBADP: return "xvnmsubadp"; - case PPC_ID_VSX_XVNMSUBASP: return "xvnmsubasp"; - case PPC_ID_VSX_XVNMSUBMSP: return "xvnmsubmsp"; - case PPC_ID_VSX_XVNMSUBMDP: return "xvnmsubmdp"; - case PPC_ID_VSX_XVRDPI: return "xvrdpi"; - case PPC_ID_VSX_XVRDPIC: return "xvrdpic"; - case PPC_ID_VSX_XVRDPIM: return "xvrdpim"; - case PPC_ID_VSX_XVRDPIP: return "xvrdpip"; - case PPC_ID_VSX_XVRDPIZ: return "xvrdpiz"; - case PPC_ID_VSX_XVREDP: return "xvredp"; - case PPC_ID_VSX_XVRESP: return "xvresp"; - case PPC_ID_VSX_XVRSPI: return "xvrspi"; - case PPC_ID_VSX_XVRSPIC: return "xvrspic"; - case PPC_ID_VSX_XVRSPIM: return "xvrspim"; - case PPC_ID_VSX_XVRSPIP: return "xvrspip"; - case PPC_ID_VSX_XVRSPIZ: return "xvrspiz"; - case PPC_ID_VSX_XVRSQRTEDP: return "xvrsqrtedp"; - case PPC_ID_VSX_XVRSQRTESP: return "xvrsqrtesp"; - case PPC_ID_VSX_XVSQRTDP: return "xvsqrtdp"; - case PPC_ID_VSX_XVSQRTSP: return "xvsqrtsp"; - case PPC_ID_VSX_XVSUBSP: return "xvsubsp"; - case PPC_ID_VSX_XVSUBDP: return "xvsubdp"; - case PPC_ID_VSX_XVTDIVDP: return "xvtdivdp"; - case PPC_ID_VSX_XVTDIVSP: return "xvtdivsp"; - case PPC_ID_VSX_XVTSQRTDP: return "xvtsqrtdp"; - case PPC_ID_VSX_XVTSQRTSP: return "xvtsqrtsp"; - case PPC_ID_VSX_XVTSTDCDP: return "xvtstdcdp"; - case PPC_ID_VSX_XVTSTDCSP: return "xvtstdcsp"; - case PPC_ID_VSX_XVXEXPDP: return "xvxexpdp"; - case PPC_ID_VSX_XVXEXPSP: return "xvxexpsp"; - case PPC_ID_VSX_XVXSIGDP: return "xvxsigdp"; - case PPC_ID_VSX_XVXSIGSP: return "xvxsigsp"; - case PPC_ID_VSX_XXBRD: return "xxbrd"; - case PPC_ID_VSX_XXBRH: return "xxbrh"; - case PPC_ID_VSX_XXBRQ: return "xxbrq"; - case PPC_ID_VSX_XXBRW: return "xxbrw"; - case PPC_ID_VSX_XXEXTRACTUW: return "xxextractuw"; - case PPC_ID_VSX_XXINSERTW: return "xxinsertw"; - case PPC_ID_VSX_XXLAND: return "xxland"; - case PPC_ID_VSX_XXLANDC: return "xxlandc"; - case PPC_ID_VSX_XXLEQV: return "xxleqv"; - case PPC_ID_VSX_XXLNAND: return "xxlnand"; - case PPC_ID_VSX_XXLNOR: return "xxlnor"; - case PPC_ID_VSX_XXLORC: return "xxlorc"; - case PPC_ID_VSX_XXMRGHD: return "xxmrghd"; - case PPC_ID_VSX_XXMRGHW: return "xxmrghw"; - case PPC_ID_VSX_XXMRGLD: return "xxmrgld"; - case PPC_ID_VSX_XXMRGLW: return "xxmrglw"; - case PPC_ID_VSX_XXLOR: return "xxlor"; - case PPC_ID_VSX_XXLXOR: return "xxlxor"; - case PPC_ID_VSX_XXPERM: return "xxperm"; - case PPC_ID_VSX_XXPERMDI: return "xxpermdi"; - case PPC_ID_VSX_XXPERMR: return "xxpermr"; - case PPC_ID_VSX_XXSEL: return "xxsel"; - case PPC_ID_VSX_XXSLDWI: return "xxsldwi"; - case PPC_ID_VSX_XXSPLTD: return "xxspltd"; - case PPC_ID_VSX_XXSPLTIB: return "xxspltib"; - case PPC_ID_VSX_XXSPLTW: return "xxspltw"; - case PPC_ID_VSX_XXSWAPD: return "xxswapd"; - - case PPC_ID_PSQ_L: return "psq_l"; - case PPC_ID_PSQ_LU: return "psq_lu"; - case PPC_ID_PSQ_LUX: return "psq_lux"; - case PPC_ID_PSQ_LX: return "psq_lx"; - case PPC_ID_PSQ_ST: return "psq_st"; - case PPC_ID_PSQ_STU: return "psq_stu"; - case PPC_ID_PSQ_STUX: return "psq_stux"; - case PPC_ID_PSQ_STX: return "psq_stx"; - - case PPC_ID_SPE_BRINC: return "brinc"; - case PPC_ID_SPE_EFDABS: return "efdabs"; - case PPC_ID_SPE_EFDADD: return "efdadd"; - case PPC_ID_SPE_EFDCFS: return "efdcfs"; - case PPC_ID_SPE_EFDCFSF: return "efdcfsf"; - case PPC_ID_SPE_EFDCFSI: return "efdcfsi"; - case PPC_ID_SPE_EFDCFSID: return "efdcfsid"; - case PPC_ID_SPE_EFDCFUF: return "efdcfuf"; - case PPC_ID_SPE_EFDCFUI: return "efdcfui"; - case PPC_ID_SPE_EFDCFUID: return "efdcfuid"; - case PPC_ID_SPE_EFDCMPEQ: return "efdcmpeq"; - case PPC_ID_SPE_EFDCMPGT: return "efdcmpgt"; - case PPC_ID_SPE_EFDCMPLT: return "efdcmplt"; - case PPC_ID_SPE_EFDCTSF: return "efdctsf"; - case PPC_ID_SPE_EFDCTSI: return "efdctsi"; - case PPC_ID_SPE_EFDCTSIDZ: return "efdctsidz"; - case PPC_ID_SPE_EFDCTSIZ: return "efdctsiz"; - case PPC_ID_SPE_EFDCTUF: return "efdctuf"; - case PPC_ID_SPE_EFDCTUI: return "efdctui"; - case PPC_ID_SPE_EFDCTUIDZ: return "efdctuidz"; - case PPC_ID_SPE_EFDCTUIZ: return "efdctuiz"; - case PPC_ID_SPE_EFDDIV: return "efddiv"; - case PPC_ID_SPE_EFDMUL: return "efdmul"; - case PPC_ID_SPE_EFDNABS: return "efdnabs"; - case PPC_ID_SPE_EFDNEG: return "efdneg"; - case PPC_ID_SPE_EFDSUB: return "efdsub"; - case PPC_ID_SPE_EFDTSTEQ: return "efdtsteq"; - case PPC_ID_SPE_EFDTSTGT: return "efdtstgt"; - case PPC_ID_SPE_EFDTSTLT: return "efdtstlt"; - case PPC_ID_SPE_EFSABS: return "efsabs"; - case PPC_ID_SPE_EFSADD: return "efsadd"; - case PPC_ID_SPE_EFSCFD: return "efscfd"; - case PPC_ID_SPE_EFSCFSF: return "efscfsf"; - case PPC_ID_SPE_EFSCFSI: return "efscfsi"; - case PPC_ID_SPE_EFSCFUF: return "efscfuf"; - case PPC_ID_SPE_EFSCFUI: return "efscfui"; - case PPC_ID_SPE_EFSCMPEQ: return "efscmpeq"; - case PPC_ID_SPE_EFSCMPGT: return "efscmpgt"; - case PPC_ID_SPE_EFSCMPLT: return "efscmplt"; - case PPC_ID_SPE_EFSCTSF: return "efsctsf"; - case PPC_ID_SPE_EFSCTSI: return "efsctsi"; - case PPC_ID_SPE_EFSCTSIZ: return "efsctsiz"; - case PPC_ID_SPE_EFSCTUF: return "efsctuf"; - case PPC_ID_SPE_EFSCTUI: return "efsctui"; - case PPC_ID_SPE_EFSCTUIZ: return "efsctuiz"; - case PPC_ID_SPE_EFSDIV: return "efsdiv"; - case PPC_ID_SPE_EFSMUL: return "efsmul"; - case PPC_ID_SPE_EFSNABS: return "efsnabs"; - case PPC_ID_SPE_EFSNEG: return "efsneg"; - case PPC_ID_SPE_EFSSUB: return "efssub"; - case PPC_ID_SPE_EFSTSTEQ: return "efststeq"; - case PPC_ID_SPE_EFSTSTGT: return "efststgt"; - case PPC_ID_SPE_EFSTSTLT: return "efststlt"; - case PPC_ID_SPE_EVABS: return "evabs"; - case PPC_ID_SPE_EVADDIW: return "evaddiw"; - case PPC_ID_SPE_EVADDSMIAAW: return "evaddsmiaaw"; - case PPC_ID_SPE_EVADDSSIAAW: return "evaddssiaaw"; - case PPC_ID_SPE_EVADDUMIAAW: return "evaddumiaaw"; - case PPC_ID_SPE_EVADDUSIAAW: return "evaddusiaaw"; - case PPC_ID_SPE_EVADDW: return "evaddw"; - case PPC_ID_SPE_EVAND: return "evand"; - case PPC_ID_SPE_EVANDC: return "evandc"; - case PPC_ID_SPE_EVCMPEQ: return "evcmpeq"; - case PPC_ID_SPE_EVCMPGTS: return "evcmpgts"; - case PPC_ID_SPE_EVCMPGTU: return "evcmpgtu"; - case PPC_ID_SPE_EVCMPLTS: return "evcmplts"; - case PPC_ID_SPE_EVCMPLTU: return "evcmpltu"; - case PPC_ID_SPE_EVCNTLSW: return "evcntlsw"; - case PPC_ID_SPE_EVCNTLZW: return "evcntlzw"; - case PPC_ID_SPE_EVDIVWS: return "evdivws"; - case PPC_ID_SPE_EVDIVWU: return "evdivwu"; - case PPC_ID_SPE_EVEQV: return "eveqv"; - case PPC_ID_SPE_EVEXTSB: return "evextsb"; - case PPC_ID_SPE_EVEXTSH: return "evextsh"; - case PPC_ID_SPE_EVFSABS: return "evfsabs"; - case PPC_ID_SPE_EVFSADD: return "evfsadd"; - case PPC_ID_SPE_EVFSCFSF: return "evfscfsf"; - case PPC_ID_SPE_EVFSCFSI: return "evfscfsi"; - case PPC_ID_SPE_EVFSCFUF: return "evfscfuf"; - case PPC_ID_SPE_EVFSCFUI: return "evfscfui"; - case PPC_ID_SPE_EVSCFUI: return "evscfui"; - case PPC_ID_SPE_EVFSCMPEQ: return "evfscmpeq"; - case PPC_ID_SPE_EVFSCMPGT: return "evfscmpgt"; - case PPC_ID_SPE_EVFSCMPLT: return "evfscmplt"; - case PPC_ID_SPE_EVFSCTSF: return "evfsctsf"; - case PPC_ID_SPE_EVFSCTSI: return "evfsctsi"; - case PPC_ID_SPE_EVFSCTSIZ: return "evfsctsiz"; - case PPC_ID_SPE_EVFSCTUF: return "evfsctuf"; - case PPC_ID_SPE_EVFSCTUI: return "evfsctui"; - case PPC_ID_SPE_EVFSCTUIZ: return "evfsctuiz"; - case PPC_ID_SPE_EVFSDIV: return "evfsdiv"; - case PPC_ID_SPE_EVFSMUL: return "evfsmul"; - case PPC_ID_SPE_EVFSNABS: return "evfsnabs"; - case PPC_ID_SPE_EVFSNEG: return "evfsneg"; - case PPC_ID_SPE_EVFSSUB: return "evfssub"; - case PPC_ID_SPE_EVFSTSTEQ: return "evfststeq"; - case PPC_ID_SPE_EVFSTSTGT: return "evfststgt"; - case PPC_ID_SPE_EVFSTSTLT: return "evfststlt"; - case PPC_ID_SPE_EVLDD: return "evldd"; - case PPC_ID_SPE_EVLDDX: return "evlddx"; - case PPC_ID_SPE_EVLDH: return "evldh"; - case PPC_ID_SPE_EVLDHX: return "evldhx"; - case PPC_ID_SPE_EVLDW: return "evldw"; - case PPC_ID_SPE_EVLDWX: return "evldwx"; - case PPC_ID_SPE_EVLHHESPLAT: return "evlhhesplat"; - case PPC_ID_SPE_EVLHHESPLATX: return "evlhhesplatx"; - case PPC_ID_SPE_EVLHHOSSPLAT: return "evlhhossplat"; - case PPC_ID_SPE_EVLHHOSSPLATX: return "evlhhossplatx"; - case PPC_ID_SPE_EVLHHOUSPLAT: return "evlhhousplat"; - case PPC_ID_SPE_EVLHHOUSPLATX: return "evlhhousplatx"; - case PPC_ID_SPE_EVLWHE: return "evlwhe"; - case PPC_ID_SPE_EVLWHEX: return "evlwhex"; - case PPC_ID_SPE_EVLWHOS: return "evlwhos"; - case PPC_ID_SPE_EVLWHOSX: return "evlwhosx"; - case PPC_ID_SPE_EVLWHOU: return "evlwhou"; - case PPC_ID_SPE_EVLWHOUX: return "evlwhoux"; - case PPC_ID_SPE_EVLWHSPLAT: return "evlwhsplat"; - case PPC_ID_SPE_EVLWHSPLATX: return "evlwhsplatx"; - case PPC_ID_SPE_EVLWWSPLAT: return "evlwwsplat"; - case PPC_ID_SPE_EVLWWSPLATX: return "evlwwsplatx"; - case PPC_ID_SPE_EVMERGEHI: return "evmergehi"; - case PPC_ID_SPE_EVMERGEHILO: return "evmergehilo"; - case PPC_ID_SPE_EVMERGELO: return "evmergelo"; - case PPC_ID_SPE_EVMERGELOHI: return "evmergelohi"; - case PPC_ID_SPE_EVMHEGSMFAA: return "evmhegsmfaa"; - case PPC_ID_SPE_EVMHEGSMFAN: return "evmhegsmfan"; - case PPC_ID_SPE_EVMHEGSMIAA: return "evmhegsmiaa"; - case PPC_ID_SPE_EVMHEGSMIAN: return "evmhegsmian"; - case PPC_ID_SPE_EVMHEGUMIAA: return "evmhegumiaa"; - case PPC_ID_SPE_EVMHEGUMIAN: return "evmhegumian"; - case PPC_ID_SPE_EVMHESMF: return "evmhesmf"; - case PPC_ID_SPE_EVMHESMFA: return "evmhesmfa"; - case PPC_ID_SPE_EVMHESMFAAW: return "evmhesmfaaw"; - case PPC_ID_SPE_EVMHESMFANW: return "evmhesmfanw"; - case PPC_ID_SPE_EVMHESMI: return "evmhesmi"; - case PPC_ID_SPE_EVMHESMIA: return "evmhesmia"; - case PPC_ID_SPE_EVMHESMIAAW: return "evmhesmiaaw"; - case PPC_ID_SPE_EVMHESMIANW: return "evmhesmianw"; - case PPC_ID_SPE_EVMHESSF: return "evmhessf"; - case PPC_ID_SPE_EVMHESSFA: return "evmhessfa"; - case PPC_ID_SPE_EVMHESSFAAW: return "evmhessfaaw"; - case PPC_ID_SPE_EVMHESSFANW: return "evmhessfanw"; - case PPC_ID_SPE_EVMHESSIAAW: return "evmhessiaaw"; - case PPC_ID_SPE_EVMHESSIANW: return "evmhessianw"; - case PPC_ID_SPE_EVMHEUMI: return "evmheumi"; - case PPC_ID_SPE_EVMHEUMIA: return "evmheumia"; - case PPC_ID_SPE_EVMHEUMIAAW: return "evmheumiaaw"; - case PPC_ID_SPE_EVMHEUMIANW: return "evmheumianw"; - case PPC_ID_SPE_EVMHEUSIAAW: return "evmheusiaaw"; - case PPC_ID_SPE_EVMHEUSIANW: return "evmheusianw"; - case PPC_ID_SPE_EVMHOGSMFAA: return "evmhogsmfaa"; - case PPC_ID_SPE_EVMHOGSMFAN: return "evmhogsmfan"; - case PPC_ID_SPE_EVMHOGSMIAA: return "evmhogsmiaa"; - case PPC_ID_SPE_EVMHOGSMIAN: return "evmhogsmian"; - case PPC_ID_SPE_EVMHOGUMIAA: return "evmhogumiaa"; - case PPC_ID_SPE_EVMHOGUMIAN: return "evmhogumian"; - case PPC_ID_SPE_EVMHOSMF: return "evmhosmf"; - case PPC_ID_SPE_EVMHOSMFA: return "evmhosmfa"; - case PPC_ID_SPE_EVMHOSMFAAW: return "evmhosmfaaw"; - case PPC_ID_SPE_EVMHOSMFANW: return "evmhosmfanw"; - case PPC_ID_SPE_EVMHOSMI: return "evmhosmi"; - case PPC_ID_SPE_EVMHOSMIA: return "evmhosmia"; - case PPC_ID_SPE_EVMHOSMIAAW: return "evmhosmiaaw"; - case PPC_ID_SPE_EVMHOSMIANW: return "evmhosmianw"; - case PPC_ID_SPE_EVMHOSSF: return "evmhossf"; - case PPC_ID_SPE_EVMHOSSFA: return "evmhossfa"; - case PPC_ID_SPE_EVMHOSSFAAW: return "evmhossfaaw"; - case PPC_ID_SPE_EVMHOSSFANW: return "evmhossfanw"; - case PPC_ID_SPE_EVMHOSSIAAW: return "evmhossiaaw"; - case PPC_ID_SPE_EVMHOSSIANW: return "evmhossianw"; - case PPC_ID_SPE_EVMHOUMI: return "evmhoumi"; - case PPC_ID_SPE_EVMHOUMIA: return "evmhoumia"; - case PPC_ID_SPE_EVMHOUMIAAW: return "evmhoumiaaw"; - case PPC_ID_SPE_EVMHOUMIANW: return "evmhoumianw"; - case PPC_ID_SPE_EVMHOUSIAAW: return "evmhousiaaw"; - case PPC_ID_SPE_EVMHOUSIANW: return "evmhousianw"; - case PPC_ID_SPE_EVMR: return "evmr"; - case PPC_ID_SPE_EVMRA: return "evmra"; - case PPC_ID_SPE_EVMWHSMF: return "evmwhsmf"; - case PPC_ID_SPE_EVMWHSMFA: return "evmwhsmfa"; - case PPC_ID_SPE_EVMWHSMI: return "evmwhsmi"; - case PPC_ID_SPE_EVMWHSMIA: return "evmwhsmia"; - case PPC_ID_SPE_EVMWHSSF: return "evmwhssf"; - case PPC_ID_SPE_EVMWHSSFA: return "evmwhssfa"; - case PPC_ID_SPE_EVMWHUMI: return "evmwhumi"; - case PPC_ID_SPE_EVMWHUMIA: return "evmwhumia"; - case PPC_ID_SPE_EVMWHUSIAAW: return "evmwhusiaaw"; - case PPC_ID_SPE_EVMWHUSIANW: return "evmwhusianw"; - case PPC_ID_SPE_EVMWLSMIAAW: return "evmwlsmiaaw"; - case PPC_ID_SPE_EVMWLSMIANW: return "evmwlsmianw"; - case PPC_ID_SPE_EVMWLSSIANW: return "evmwlssianw"; - case PPC_ID_SPE_EVMWLSSIAAW: return "evmwlssiaaw"; - case PPC_ID_SPE_EVMWLUMI: return "evmwlumi"; - case PPC_ID_SPE_EVMWLUMIA: return "evmwlumia"; - case PPC_ID_SPE_EVMWLUMIAAW: return "evmwlumiaaw"; - case PPC_ID_SPE_EVMWLUMIANW: return "evmwlumianw"; - case PPC_ID_SPE_EVMWLUSIAAW: return "evmwlusiaaw"; - case PPC_ID_SPE_EVMWLUSIANW: return "evmwlusianw"; - case PPC_ID_SPE_EVMWSMF: return "evmwsmf"; - case PPC_ID_SPE_EVMWSMFA: return "evmwsmfa"; - case PPC_ID_SPE_EVMWSMFAA: return "evmwsmfaa"; - case PPC_ID_SPE_EVMWSMFAN: return "evmwsmfan"; - case PPC_ID_SPE_EVMWSMI: return "evmwsmi"; - case PPC_ID_SPE_EVMWSMIA: return "evmwsmia"; - case PPC_ID_SPE_EVMWSMIAA: return "evmwsmiaa"; - case PPC_ID_SPE_EVMWSMIAN: return "evmwsmian"; - case PPC_ID_SPE_EVMWSSF: return "evmwssf"; - case PPC_ID_SPE_EVMWSSFA: return "evmwssfa"; - case PPC_ID_SPE_EVMWSSFAA: return "evmwssfaa"; - case PPC_ID_SPE_EVMWSSFAN: return "evmwssfan"; - case PPC_ID_SPE_EVMWUMI: return "evmwumi"; - case PPC_ID_SPE_EVMWUMIA: return "evmwumia"; - case PPC_ID_SPE_EVMWUMIAA: return "evmwumiaa"; - case PPC_ID_SPE_EVMWUMIAN: return "evmwumian"; - case PPC_ID_SPE_EVNAND: return "evnand"; - case PPC_ID_SPE_EVNEG: return "evneg"; - case PPC_ID_SPE_EVNOR: return "evnor"; - case PPC_ID_SPE_EVNOT: return "evnot"; - case PPC_ID_SPE_EVOR: return "evor"; - case PPC_ID_SPE_EVORC: return "evorc"; - case PPC_ID_SPE_EVRLW: return "evrlw"; - case PPC_ID_SPE_EVRLWI: return "evrlwi"; - case PPC_ID_SPE_EVRNDW: return "evrndw"; - case PPC_ID_SPE_EVSEL: return "evsel"; - case PPC_ID_SPE_EVSLW: return "evslw"; - case PPC_ID_SPE_EVSLWI: return "evslwi"; - case PPC_ID_SPE_EVSPLATFI: return "evsplatfi"; - case PPC_ID_SPE_EVSPLATI: return "evsplati"; - case PPC_ID_SPE_EVSRWIS: return "evsrwis"; - case PPC_ID_SPE_EVSRWIU: return "evsrwiu"; - case PPC_ID_SPE_EVSRWS: return "evsrws"; - case PPC_ID_SPE_EVSRWU: return "evsrwu"; - case PPC_ID_SPE_EVSTDD: return "evstdd"; - case PPC_ID_SPE_EVSTDDX: return "evstddx"; - case PPC_ID_SPE_EVSTDH: return "evstdh"; - case PPC_ID_SPE_EVSTDHX: return "evstdhx"; - case PPC_ID_SPE_EVSTDW: return "evstdw"; - case PPC_ID_SPE_EVSTDWX: return "evstdwx"; - case PPC_ID_SPE_EVSTWHE: return "evstwhe"; - case PPC_ID_SPE_EVSTWHEX: return "evstwhex"; - case PPC_ID_SPE_EVSTWHO: return "evstwho"; - case PPC_ID_SPE_EVSTWHOX: return "evstwhox"; - case PPC_ID_SPE_EVSTWWE: return "evstwwe"; - case PPC_ID_SPE_EVSTWWEX: return "evstwwex"; - case PPC_ID_SPE_EVSTWWO: return "evstwwo"; - case PPC_ID_SPE_EVSTWWOX: return "evstwwox"; - case PPC_ID_SPE_EVSUBFSMIAAW: return "evsubfsmiaaw"; - case PPC_ID_SPE_EVSUBFSSIAAW: return "evsubfssiaaw"; - case PPC_ID_SPE_EVSUBFUMIAAW: return "evsubfumiaaw"; - case PPC_ID_SPE_EVSUBFUSIAAW: return "evsubfusiaaw"; - case PPC_ID_SPE_EVSUBFW: return "evsubfw"; - case PPC_ID_SPE_EVSUBIFW: return "evsubifw"; - case PPC_ID_SPE_EVXOR: return "evxor"; - - default: return NULL; - } -} - - -bool Decompose(Instruction* instruction, uint32_t word32, uint64_t address, uint32_t flags) -{ - memset(instruction, 0, sizeof *instruction); - - instruction->id = Decode(word32, flags); - if (instruction->id == PPC_ID_INVALID) - return false; + instruction->id = Decode(word32, flags); + if (instruction->id == PPC_ID_INVALID) + return false; FillOperands(instruction, word32, address); return true; } - -const char* PowerPCRegisterName(uint32_t regId) -{ - switch (regId) - { - case PPC_REG_GPR0: return "r0"; - case PPC_REG_GPR1: return "r1"; - case PPC_REG_GPR2: return "r2"; - case PPC_REG_GPR3: return "r3"; - case PPC_REG_GPR4: return "r4"; - case PPC_REG_GPR5: return "r5"; - case PPC_REG_GPR6: return "r6"; - case PPC_REG_GPR7: return "r7"; - case PPC_REG_GPR8: return "r8"; - case PPC_REG_GPR9: return "r9"; - case PPC_REG_GPR10: return "r10"; - case PPC_REG_GPR11: return "r11"; - case PPC_REG_GPR12: return "r12"; - case PPC_REG_GPR13: return "r13"; - case PPC_REG_GPR14: return "r14"; - case PPC_REG_GPR15: return "r15"; - case PPC_REG_GPR16: return "r16"; - case PPC_REG_GPR17: return "r17"; - case PPC_REG_GPR18: return "r18"; - case PPC_REG_GPR19: return "r19"; - case PPC_REG_GPR20: return "r20"; - case PPC_REG_GPR21: return "r21"; - case PPC_REG_GPR22: return "r22"; - case PPC_REG_GPR23: return "r23"; - case PPC_REG_GPR24: return "r24"; - case PPC_REG_GPR25: return "r25"; - case PPC_REG_GPR26: return "r26"; - case PPC_REG_GPR27: return "r27"; - case PPC_REG_GPR28: return "r28"; - case PPC_REG_GPR29: return "r29"; - case PPC_REG_GPR30: return "r30"; - case PPC_REG_GPR31: return "r31"; - - case PPC_REG_XER: return "xer"; - case PPC_REG_LR: return "lr"; - case PPC_REG_CTR: return "ctr"; - - case PPC_REG_FR0: return "f0"; - case PPC_REG_FR1: return "f1"; - case PPC_REG_FR2: return "f2"; - case PPC_REG_FR3: return "f3"; - case PPC_REG_FR4: return "f4"; - case PPC_REG_FR5: return "f5"; - case PPC_REG_FR6: return "f6"; - case PPC_REG_FR7: return "f7"; - case PPC_REG_FR8: return "f8"; - case PPC_REG_FR9: return "f9"; - case PPC_REG_FR10: return "f10"; - case PPC_REG_FR11: return "f11"; - case PPC_REG_FR12: return "f12"; - case PPC_REG_FR13: return "f13"; - case PPC_REG_FR14: return "f14"; - case PPC_REG_FR15: return "f15"; - case PPC_REG_FR16: return "f16"; - case PPC_REG_FR17: return "f17"; - case PPC_REG_FR18: return "f18"; - case PPC_REG_FR19: return "f19"; - case PPC_REG_FR20: return "f20"; - case PPC_REG_FR21: return "f21"; - case PPC_REG_FR22: return "f22"; - case PPC_REG_FR23: return "f23"; - case PPC_REG_FR24: return "f24"; - case PPC_REG_FR25: return "f25"; - case PPC_REG_FR26: return "f26"; - case PPC_REG_FR27: return "f27"; - case PPC_REG_FR28: return "f28"; - case PPC_REG_FR29: return "f29"; - case PPC_REG_FR30: return "f30"; - case PPC_REG_FR31: return "f31"; - - case PPC_REG_CRF0: return "cr0"; - case PPC_REG_CRF1: return "cr1"; - case PPC_REG_CRF2: return "cr2"; - case PPC_REG_CRF3: return "cr3"; - case PPC_REG_CRF4: return "cr4"; - case PPC_REG_CRF5: return "cr5"; - case PPC_REG_CRF6: return "cr6"; - case PPC_REG_CRF7: return "cr7"; - - case PPC_REG_AV_VR0: return "v0"; - case PPC_REG_AV_VR1: return "v1"; - case PPC_REG_AV_VR2: return "v2"; - case PPC_REG_AV_VR3: return "v3"; - case PPC_REG_AV_VR4: return "v4"; - case PPC_REG_AV_VR5: return "v5"; - case PPC_REG_AV_VR6: return "v6"; - case PPC_REG_AV_VR7: return "v7"; - case PPC_REG_AV_VR8: return "v8"; - case PPC_REG_AV_VR9: return "v9"; - case PPC_REG_AV_VR10: return "v10"; - case PPC_REG_AV_VR11: return "v11"; - case PPC_REG_AV_VR12: return "v12"; - case PPC_REG_AV_VR13: return "v13"; - case PPC_REG_AV_VR14: return "v14"; - case PPC_REG_AV_VR15: return "v15"; - case PPC_REG_AV_VR16: return "v16"; - case PPC_REG_AV_VR17: return "v17"; - case PPC_REG_AV_VR18: return "v18"; - case PPC_REG_AV_VR19: return "v19"; - case PPC_REG_AV_VR20: return "v20"; - case PPC_REG_AV_VR21: return "v21"; - case PPC_REG_AV_VR22: return "v22"; - case PPC_REG_AV_VR23: return "v23"; - case PPC_REG_AV_VR24: return "v24"; - case PPC_REG_AV_VR25: return "v25"; - case PPC_REG_AV_VR26: return "v26"; - case PPC_REG_AV_VR27: return "v27"; - case PPC_REG_AV_VR28: return "v28"; - case PPC_REG_AV_VR29: return "v29"; - case PPC_REG_AV_VR30: return "v30"; - case PPC_REG_AV_VR31: return "v31"; - - case PPC_REG_VSX_VR0: return "vs0"; - case PPC_REG_VSX_VR1: return "vs1"; - case PPC_REG_VSX_VR2: return "vs2"; - case PPC_REG_VSX_VR3: return "vs3"; - case PPC_REG_VSX_VR4: return "vs4"; - case PPC_REG_VSX_VR5: return "vs5"; - case PPC_REG_VSX_VR6: return "vs6"; - case PPC_REG_VSX_VR7: return "vs7"; - case PPC_REG_VSX_VR8: return "vs8"; - case PPC_REG_VSX_VR9: return "vs9"; - case PPC_REG_VSX_VR10: return "vs10"; - case PPC_REG_VSX_VR11: return "vs11"; - case PPC_REG_VSX_VR12: return "vs12"; - case PPC_REG_VSX_VR13: return "vs13"; - case PPC_REG_VSX_VR14: return "vs14"; - case PPC_REG_VSX_VR15: return "vs15"; - case PPC_REG_VSX_VR16: return "vs16"; - case PPC_REG_VSX_VR17: return "vs17"; - case PPC_REG_VSX_VR18: return "vs18"; - case PPC_REG_VSX_VR19: return "vs19"; - case PPC_REG_VSX_VR20: return "vs20"; - case PPC_REG_VSX_VR21: return "vs21"; - case PPC_REG_VSX_VR22: return "vs22"; - case PPC_REG_VSX_VR23: return "vs23"; - case PPC_REG_VSX_VR24: return "vs24"; - case PPC_REG_VSX_VR25: return "vs25"; - case PPC_REG_VSX_VR26: return "vs26"; - case PPC_REG_VSX_VR27: return "vs27"; - case PPC_REG_VSX_VR28: return "vs28"; - case PPC_REG_VSX_VR29: return "vs29"; - case PPC_REG_VSX_VR30: return "vs30"; - case PPC_REG_VSX_VR31: return "vs31"; - case PPC_REG_VSX_VR32: return "vs32"; - case PPC_REG_VSX_VR33: return "vs33"; - case PPC_REG_VSX_VR34: return "vs34"; - case PPC_REG_VSX_VR35: return "vs35"; - case PPC_REG_VSX_VR36: return "vs36"; - case PPC_REG_VSX_VR37: return "vs37"; - case PPC_REG_VSX_VR38: return "vs38"; - case PPC_REG_VSX_VR39: return "vs39"; - case PPC_REG_VSX_VR40: return "vs40"; - case PPC_REG_VSX_VR41: return "vs41"; - case PPC_REG_VSX_VR42: return "vs42"; - case PPC_REG_VSX_VR43: return "vs43"; - case PPC_REG_VSX_VR44: return "vs44"; - case PPC_REG_VSX_VR45: return "vs45"; - case PPC_REG_VSX_VR46: return "vs46"; - case PPC_REG_VSX_VR47: return "vs47"; - case PPC_REG_VSX_VR48: return "vs48"; - case PPC_REG_VSX_VR49: return "vs49"; - case PPC_REG_VSX_VR50: return "vs50"; - case PPC_REG_VSX_VR51: return "vs51"; - case PPC_REG_VSX_VR52: return "vs52"; - case PPC_REG_VSX_VR53: return "vs53"; - case PPC_REG_VSX_VR54: return "vs54"; - case PPC_REG_VSX_VR55: return "vs55"; - case PPC_REG_VSX_VR56: return "vs56"; - case PPC_REG_VSX_VR57: return "vs57"; - case PPC_REG_VSX_VR58: return "vs58"; - case PPC_REG_VSX_VR59: return "vs59"; - case PPC_REG_VSX_VR60: return "vs60"; - case PPC_REG_VSX_VR61: return "vs61"; - case PPC_REG_VSX_VR62: return "vs62"; - case PPC_REG_VSX_VR63: return "vs63"; - - case PPC_REG_GQR0: return "gqr0"; - case PPC_REG_GQR1: return "gqr1"; - case PPC_REG_GQR2: return "gqr2"; - case PPC_REG_GQR3: return "gqr3"; - case PPC_REG_GQR4: return "gqr4"; - case PPC_REG_GQR5: return "gqr5"; - case PPC_REG_GQR6: return "gqr6"; - case PPC_REG_GQR7: return "gqr7"; - - default: return NULL; - } -} - -const char* OperandClassName(uint32_t cls) -{ - switch (cls) - { - case PPC_OP_NONE: return ""; - case PPC_OP_UIMM: return "UIMM"; - case PPC_OP_SIMM: return "SIMM"; - case PPC_OP_LABEL: return "LABEL"; - case PPC_OP_MEM_RA: return "MEM(RA)"; - - case PPC_OP_REG_RA: return "RA"; - case PPC_OP_REG_RB: return "RB"; - case PPC_OP_REG_RC: return "RC"; - case PPC_OP_REG_RD: return "RD"; - case PPC_OP_REG_RS: return "RS"; - - case PPC_OP_REG_FRA: return "FRA"; - case PPC_OP_REG_FRB: return "FRB"; - case PPC_OP_REG_FRC: return "FRC"; - case PPC_OP_REG_FRD: return "FRD"; - case PPC_OP_REG_FRS: return "FRS"; - - case PPC_OP_REG_CRFD: return "CRFD"; - case PPC_OP_REG_CRFD_IMPLY0: return "CRFD"; - case PPC_OP_REG_CRFS: return "CRFS"; - case PPC_OP_CRBIT: return "CRBIT"; - case PPC_OP_CRBIT_A: return "CRBIT_A"; - case PPC_OP_CRBIT_B: return "CRBIT_B"; - case PPC_OP_CRBIT_D: return "CRBIT_C"; - - case PPC_OP_REG_AV_VA: return "ALTIVEC_VA"; - case PPC_OP_REG_AV_VB: return "ALTIVEC_VB"; - case PPC_OP_REG_AV_VC: return "ALTIVEC_VC"; - case PPC_OP_REG_AV_VD: return "ALTIVEC_VD"; - case PPC_OP_REG_AV_VS: return "ALTIVEC_VS"; - - case PPC_OP_REG_VSX_RA: return "VSX_RA"; - case PPC_OP_REG_VSX_RA_DWORD0: return "VSX_RA0"; - - case PPC_OP_REG_VSX_RB: return "VSX_RB"; - case PPC_OP_REG_VSX_RB_DWORD0: return "VSX_RB0"; - - case PPC_OP_REG_VSX_RC: return "VSX_RC"; - case PPC_OP_REG_VSX_RC_DWORD0: return "VSX_RC0"; - - case PPC_OP_REG_VSX_RD: return "VSX_RD"; - case PPC_OP_REG_VSX_RD_DWORD0: return "VSX_RD0"; - - case PPC_OP_REG_VSX_RS: return "VSX_RS"; - case PPC_OP_REG_VSX_RS_DWORD0: return "VSX_RS0"; - - default: - return "???"; - } -} - -// These match the names in the "Condition Register" section -const char* GetCRBitName(uint32_t crbit) -{ - switch (crbit) - { - case 0: return "lt"; - case 1: return "gt"; - case 2: return "eq"; - case 3: return "so"; - case 4: return "cr1lt"; - case 5: return "cr1gt"; - case 6: return "cr1eq"; - case 7: return "cr1so"; - case 8: return "cr2lt"; - case 9: return "cr2gt"; - case 10: return "cr2eq"; - case 11: return "cr2so"; - case 12: return "cr3lt"; - case 13: return "cr3gt"; - case 14: return "cr3eq"; - case 15: return "cr3so"; - case 16: return "cr4lt"; - case 17: return "cr4gt"; - case 18: return "cr4eq"; - case 19: return "cr4so"; - case 20: return "cr5lt"; - case 21: return "cr5gt"; - case 22: return "cr5eq"; - case 23: return "cr5so"; - case 24: return "cr6lt"; - case 25: return "cr6gt"; - case 26: return "cr6eq"; - case 27: return "cr6so"; - case 28: return "cr7lt"; - case 29: return "cr7gt"; - case 30: return "cr7eq"; - case 31: return "cr7so"; - default: - return NULL; - } -} diff --git a/arch/powerpc/decode/decode.h b/arch/powerpc/decode/decode.h index 78ce1858e..4809e4d64 100644 --- a/arch/powerpc/decode/decode.h +++ b/arch/powerpc/decode/decode.h @@ -5,6 +5,16 @@ #include #include +// Procedure for adding a new instruction: +// * Add its enum to the InstructionId in this file (decode.h) +// * Add logic to convert instruction bits to the new instruction in decode.c +// * Add its mnemonic in `GetMnemonic` in `mnemonic.c` +// * Add its operands in `FillOperands` in `operands.c` +// +// This only handles instruction decoding (going from bits --> a powerpc +// instruction), and not anything like lifting or the behavior of the +// instruction itself. + #define DECODE_FLAGS_PPC64 0x01 #define DECODE_FLAGS_ALTIVEC 0x02 #define DECODE_FLAGS_VSX 0x04 diff --git a/arch/powerpc/decode/mnemonic.c b/arch/powerpc/decode/mnemonic.c new file mode 100644 index 000000000..8148d5837 --- /dev/null +++ b/arch/powerpc/decode/mnemonic.c @@ -0,0 +1,1851 @@ +#include "decode.h" + +// the hope is to avoid having to manipulate strings in something that's +// somewhat hot, so we create a bunch of lookup tables for each mnemonic + +// for "OP" and "OP." +#define DEFINE_SUBMNEM_RC(_identifier, base) \ + const char* _identifier[2] = \ + { \ + base, \ + base ".", \ + }; + +// for "OP", "OP.", "OPo", and "OPo." +#define DEFINE_SUBMNEM_OE_RC(_identifier, base) \ + const char* _identifier[4] = \ + { \ + base, \ + base ".", \ + base "o", \ + base "o.", \ + }; + +// for "OP" and "OPl" +#define DEFINE_SUBMNEM_LK(_identifier, base) \ + const char* _identifier[2] = \ + { \ + base, \ + base "l", \ + }; + +// for "OP" and "OPl" and +/- hints +#define DEFINE_SUBMNEM_LK_HINT(_identifier, base) \ + const char* _identifier[8] = \ + { \ + base, \ + base "l", \ + base, \ + base "l", \ + base "-", \ + base "l-", \ + base "+", \ + base "l+", \ + }; + +// for "OP", "OPl", "OPa", and "OPla" +#define DEFINE_SUBMNEM_AA_LK(_identifier, base) \ + const char* _identifier[4] = \ + { \ + base, \ + base "l", \ + base "a", \ + base "la", \ + }; + +// for "OP", "OPl", "OPa", "OPla" and +/- hints +#define DEFINE_SUBMNEM_AA_LK_HINT(_identifier, base) \ + const char* _identifier[16] = \ + { \ + base, \ + base "l", \ + base "a", \ + base "la", \ + base, \ + base "l", \ + base "a", \ + base "la", \ + base "-", \ + base "l-", \ + base "a-", \ + base "la-", \ + base "+", \ + base "l+", \ + base "a+", \ + base "la+" \ + }; + +#define DEFINE_SUBMNEM_ROUND2ODD(_identifier, base) \ + const char* _identifier[2] = \ + { \ + base, \ + base "o", \ + }; + +#define DEFINE_SUBMNEM_INEXACT(_identifier, base) \ + const char* _identifier[2] = \ + { \ + base, \ + base "x", \ + }; + +DEFINE_SUBMNEM_OE_RC(SubMnemADDx, "add") +DEFINE_SUBMNEM_OE_RC(SubMnemADDCx, "addc") +DEFINE_SUBMNEM_OE_RC(SubMnemADDEx, "adde") +DEFINE_SUBMNEM_RC(SubMnemADDICx, "addic") +DEFINE_SUBMNEM_OE_RC(SubMnemADDMEx, "addme") +DEFINE_SUBMNEM_OE_RC(SubMnemADDZEx, "addze") +DEFINE_SUBMNEM_RC(SubMnemANDx, "and") +DEFINE_SUBMNEM_RC(SubMnemANDCx, "andc") +DEFINE_SUBMNEM_AA_LK(SubMnemBx, "b") +DEFINE_SUBMNEM_AA_LK(SubMnemBCx, "bc") +DEFINE_SUBMNEM_LK(SubMnemBCTRx, "bctr") +DEFINE_SUBMNEM_LK(SubMnemBCCTRx, "bcctr") +DEFINE_SUBMNEM_LK(SubMnemBCLRx, "bclr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBDZx, "bdz") +DEFINE_SUBMNEM_LK_HINT(SubMnemBDZLRx, "bdzlr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBDNZx, "bdnz") +DEFINE_SUBMNEM_LK_HINT(SubMnemBDNZLRx, "bdnzlr") +DEFINE_SUBMNEM_AA_LK(SubMnemBDNZFx, "bdnzf") +DEFINE_SUBMNEM_LK(SubMnemBDNZFLRx, "bdnzflr") +DEFINE_SUBMNEM_AA_LK(SubMnemBDNZTx, "bdnzt") +DEFINE_SUBMNEM_LK(SubMnemBDNZTLRx, "bdnztlr") +DEFINE_SUBMNEM_AA_LK(SubMnemBDZFx, "bdzf") +DEFINE_SUBMNEM_LK(SubMnemBDZFLRx, "bdzflr") +DEFINE_SUBMNEM_LK(SubMnemBDFLRx, "bdzlr") +DEFINE_SUBMNEM_AA_LK(SubMnemBDZTx, "bdzt") +DEFINE_SUBMNEM_LK(SubMnemBDZTLRx, "bdztlr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBEQx, "beq") +DEFINE_SUBMNEM_LK_HINT(SubMnemBEQCTRx, "beqctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBEQLRx, "beqlr") +DEFINE_SUBMNEM_AA_LK(SubMnemBFx, "bf") +DEFINE_SUBMNEM_AA_LK(SubMnemBFLRx, "bflr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBGEx, "bge") +DEFINE_SUBMNEM_LK_HINT(SubMnemBGECTRx, "bgectr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBGELRx, "bgelr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBGTx, "bgt") +DEFINE_SUBMNEM_LK_HINT(SubMnemBGTCTRx, "bgtctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBGTLRx, "bgtlr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBLEx, "ble") +DEFINE_SUBMNEM_LK_HINT(SubMnemBLECTRx, "blectr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBLELRx, "blelr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBLTx, "blt") +DEFINE_SUBMNEM_LK_HINT(SubMnemBLTCTRx, "bltctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBLTLRx, "bltlr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBLRx, "blr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBNEx, "bne") +DEFINE_SUBMNEM_LK_HINT(SubMnemBNECTRx, "bnectr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBNELRx, "bnelr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBNSx, "bns") +DEFINE_SUBMNEM_LK_HINT(SubMnemBNSCTRx, "bnsctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBNSLRx, "bnslr") +DEFINE_SUBMNEM_AA_LK_HINT(SubMnemBSOx, "bso") +DEFINE_SUBMNEM_LK_HINT(SubMnemBSOCTRx, "bsoctr") +DEFINE_SUBMNEM_LK_HINT(SubMnemBSOLRx, "bsolr") +DEFINE_SUBMNEM_AA_LK(SubMnemBTx, "bt") +DEFINE_SUBMNEM_AA_LK(SubMnemBTLRx, "btlr") +DEFINE_SUBMNEM_RC(SubMnemCLRLDIx, "clrldi") +DEFINE_SUBMNEM_RC(SubMnemCLRLWIx, "clrlwi") +DEFINE_SUBMNEM_RC(SubMnemCLRRWIx, "clrrwi") +DEFINE_SUBMNEM_RC(SubMnemCNTLZDx, "cntlzd") +DEFINE_SUBMNEM_RC(SubMnemCNTLZWx, "cntlzw") +DEFINE_SUBMNEM_RC(SubMnemCNTTZDx, "cnttzd") +DEFINE_SUBMNEM_RC(SubMnemCNTTZWx, "cnttzw") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVDx, "divd") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVDEx, "divde") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVDEUx, "divdeu") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVDUx, "divdu") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVWx, "divw") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVWEx, "divwe") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVWEUx, "divweu") +DEFINE_SUBMNEM_OE_RC(SubMnemDIVWUx, "divwu") +DEFINE_SUBMNEM_RC(SubMnemEQVx, "eqv") +DEFINE_SUBMNEM_RC(SubMnemEXTSBx, "extsb") +DEFINE_SUBMNEM_RC(SubMnemEXTSHx, "extsh") +DEFINE_SUBMNEM_RC(SubMnemEXTSWx, "extsw") +DEFINE_SUBMNEM_RC(SubMnemEXTSWSLIx, "extswsli") +DEFINE_SUBMNEM_RC(SubMnemFABSx, "fabs") +DEFINE_SUBMNEM_RC(SubMnemFADDx, "fadd") +DEFINE_SUBMNEM_RC(SubMnemFADDSx, "fadds") +DEFINE_SUBMNEM_RC(SubMnemFCFIDx, "fcfid") +DEFINE_SUBMNEM_RC(SubMnemFCFIDSx, "fcfids") +DEFINE_SUBMNEM_RC(SubMnemFCFIDUx, "fcfidu") +DEFINE_SUBMNEM_RC(SubMnemFCFIDUSx, "fcfidus") +DEFINE_SUBMNEM_RC(SubMnemFCPSGNx, "fcpsgn") +DEFINE_SUBMNEM_RC(SubMnemFCTIDx, "fctid") +DEFINE_SUBMNEM_RC(SubMnemFCTIDUx, "fctidu") +DEFINE_SUBMNEM_RC(SubMnemFCTIDUZx, "fctiduz") +DEFINE_SUBMNEM_RC(SubMnemFCTIDZx, "fctidz") +DEFINE_SUBMNEM_RC(SubMnemFCTIWx, "fctiw") +DEFINE_SUBMNEM_RC(SubMnemFCTIWUx, "fctiwu") +DEFINE_SUBMNEM_RC(SubMnemFCTIWUZx, "fctiwuz") +DEFINE_SUBMNEM_RC(SubMnemFCTIWZx, "fctiwz") +DEFINE_SUBMNEM_RC(SubMnemFDIVx, "fdiv") +DEFINE_SUBMNEM_RC(SubMnemFDIVSx, "fdivs") +DEFINE_SUBMNEM_RC(SubMnemFMADDx, "fmadd") +DEFINE_SUBMNEM_RC(SubMnemFMADDSx, "fmadds") +DEFINE_SUBMNEM_RC(SubMnemFMRx, "fmr") +DEFINE_SUBMNEM_RC(SubMnemFMSUBx, "fmsub") +DEFINE_SUBMNEM_RC(SubMnemFMSUBSx, "fmsubs") +DEFINE_SUBMNEM_RC(SubMnemFMULx, "fmul") +DEFINE_SUBMNEM_RC(SubMnemFMULSx, "fmuls") +DEFINE_SUBMNEM_RC(SubMnemFNABSx, "fnabs") +DEFINE_SUBMNEM_RC(SubMnemFNEGx, "fneg") +DEFINE_SUBMNEM_RC(SubMnemFNMADDx, "fnmadd") +DEFINE_SUBMNEM_RC(SubMnemFNMADDSx, "fnmadds") +DEFINE_SUBMNEM_RC(SubMnemFNMSUBx, "fnmsub") +DEFINE_SUBMNEM_RC(SubMnemFNMSUBSx, "fnmsubs") +DEFINE_SUBMNEM_RC(SubMnemFREx, "fre") +DEFINE_SUBMNEM_RC(SubMnemFRESx, "fres") +DEFINE_SUBMNEM_RC(SubMnemFRIMx, "frim") +DEFINE_SUBMNEM_RC(SubMnemFRINx, "frin") +DEFINE_SUBMNEM_RC(SubMnemFRIPx, "frip") +DEFINE_SUBMNEM_RC(SubMnemFRIZx, "friz") +DEFINE_SUBMNEM_RC(SubMnemFRSPx, "frsp") +DEFINE_SUBMNEM_RC(SubMnemFRSQRTEx, "frsqrte") +DEFINE_SUBMNEM_RC(SubMnemFRSQRTESx, "frsqrtes") +DEFINE_SUBMNEM_RC(SubMnemFSELx, "fsel") +DEFINE_SUBMNEM_RC(SubMnemFSQRTx, "fsqrt") +DEFINE_SUBMNEM_RC(SubMnemFSQRTSx, "fsqrts") +DEFINE_SUBMNEM_RC(SubMnemFSUBx, "fsub") +DEFINE_SUBMNEM_RC(SubMnemFSUBSx, "fsubs") +DEFINE_SUBMNEM_RC(SubMnemMFFSx, "mffs") +DEFINE_SUBMNEM_RC(SubMnemMTFSB0x, "mtfsb0") +DEFINE_SUBMNEM_RC(SubMnemMTFSB1x, "mtfsb1") +DEFINE_SUBMNEM_RC(SubMnemMTFSFx, "mtfsf") +DEFINE_SUBMNEM_RC(SubMnemMTFSFIx, "mtfsfi") +DEFINE_SUBMNEM_RC(SubMnemMRx, "mr") +DEFINE_SUBMNEM_RC(SubMnemMULHDx, "mulhd") +DEFINE_SUBMNEM_RC(SubMnemMULHDUx, "mulhdu") +DEFINE_SUBMNEM_RC(SubMnemMULHWx, "mulhw") +DEFINE_SUBMNEM_RC(SubMnemMULHWUx, "mulhwu") +DEFINE_SUBMNEM_OE_RC(SubMnemMULLDx, "mulld") +DEFINE_SUBMNEM_OE_RC(SubMnemMULLWx, "mullw") +DEFINE_SUBMNEM_RC(SubMnemNANDx, "nand") +DEFINE_SUBMNEM_OE_RC(SubMnemNEGx, "neg") +DEFINE_SUBMNEM_RC(SubMnemNORx, "nor") +DEFINE_SUBMNEM_RC(SubMnemORx, "or") +DEFINE_SUBMNEM_RC(SubMnemORCx, "orc") +DEFINE_SUBMNEM_RC(SubMnemRLDICLx, "rldicl") +DEFINE_SUBMNEM_RC(SubMnemRLDICRx, "rldicr") +DEFINE_SUBMNEM_RC(SubMnemRLDICx, "rldic") +DEFINE_SUBMNEM_RC(SubMnemRLDIMIx, "rldimi") +DEFINE_SUBMNEM_RC(SubMnemRLDCLx, "rldcl") +DEFINE_SUBMNEM_RC(SubMnemRLDCRx, "rldcr") +DEFINE_SUBMNEM_RC(SubMnemRLWIMIx, "rlwimi") +DEFINE_SUBMNEM_RC(SubMnemRLWINMx, "rlwinm") +DEFINE_SUBMNEM_RC(SubMnemRLWNMx, "rlwnm") +DEFINE_SUBMNEM_RC(SubMnemROTLDx, "rotld") +DEFINE_SUBMNEM_RC(SubMnemROTLDIx, "rotldi") +DEFINE_SUBMNEM_RC(SubMnemROTLWx, "rotlw") +DEFINE_SUBMNEM_RC(SubMnemROTLWIx, "rotlwi") +DEFINE_SUBMNEM_RC(SubMnemSLDx, "sld") +DEFINE_SUBMNEM_RC(SubMnemSLDIx, "sldi") +DEFINE_SUBMNEM_RC(SubMnemSLWx, "slw") +DEFINE_SUBMNEM_RC(SubMnemSLWIx, "slwi") +DEFINE_SUBMNEM_RC(SubMnemSRADx, "srad") +DEFINE_SUBMNEM_RC(SubMnemSRADIx, "sradi") +DEFINE_SUBMNEM_RC(SubMnemSRAWx, "sraw") +DEFINE_SUBMNEM_RC(SubMnemSRAWIx, "srawi") +DEFINE_SUBMNEM_RC(SubMnemSRDx, "srd") +DEFINE_SUBMNEM_RC(SubMnemSRDIx, "srdi") +DEFINE_SUBMNEM_RC(SubMnemSRWx, "srw") +DEFINE_SUBMNEM_RC(SubMnemSRWIx, "srwi") +DEFINE_SUBMNEM_OE_RC(SubMnemSUBFx, "subf") +DEFINE_SUBMNEM_OE_RC(SubMnemSUBFCx, "subfc") +DEFINE_SUBMNEM_OE_RC(SubMnemSUBFEx, "subfe") +DEFINE_SUBMNEM_OE_RC(SubMnemSUBFMEx, "subfme") +DEFINE_SUBMNEM_OE_RC(SubMnemSUBFZEx, "subfze") +DEFINE_SUBMNEM_RC(SubMnemXORx, "xor") + +// ALTIVEC MNEMONICS +DEFINE_SUBMNEM_RC(SubMnemVCMPBFPx, "vcmpbfp"); +DEFINE_SUBMNEM_RC(SubMnemVCMPEQFPx, "vcmpeqfp"); +DEFINE_SUBMNEM_RC(SubMnemVCMPEQUBx, "vcmpequb"); +DEFINE_SUBMNEM_RC(SubMnemVCMPEQUDx, "vcmpequd"); +DEFINE_SUBMNEM_RC(SubMnemVCMPEQUHx, "vcmpequh"); +DEFINE_SUBMNEM_RC(SubMnemVCMPEQUWx, "vcmpequw"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGEFPx, "vcmpgefp"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTFPx, "vcmpgtfp"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTSBx, "vcmpgtsb"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTSDx, "vcmpgtsd"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTSHx, "vcmpgtsh"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTSWx, "vcmpgtsw"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTUBx, "vcmpgtub"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTUDx, "vcmpgtud"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTUHx, "vcmpgtuh"); +DEFINE_SUBMNEM_RC(SubMnemVCMPGTUWx, "vcmpgtuw"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEBx, "vcmpneb"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEHx, "vcmpneh"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEWx, "vcmpnew"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEZBx, "vcmpnezb"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEZHx, "vcmpnezh"); +DEFINE_SUBMNEM_RC(SubMnemVCMPNEZWx, "vcmpnezw"); + +// VSX MNEMONICS +DEFINE_SUBMNEM_RC(SubMnemXVCMPEQDPx, "xvcmpeqdp"); +DEFINE_SUBMNEM_RC(SubMnemXVCMPEQSPx, "xvcmpeqsp"); +DEFINE_SUBMNEM_RC(SubMnemXVCMPGEDPx, "xvcmpgedp"); +DEFINE_SUBMNEM_RC(SubMnemXVCMPGESPx, "xvcmpgesp"); +DEFINE_SUBMNEM_RC(SubMnemXVCMPGTDPx, "xvcmpgtdp"); +DEFINE_SUBMNEM_RC(SubMnemXVCMPGTSPx, "xvcmpgtsp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSADDQPx, "xsaddqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSCVQPDPx, "xscvqpdp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSDIVQPx, "xsdivqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSMADDQPx, "xsmaddqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSMULQPx, "xsmulqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSMSUBQPx, "xsmsubqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSNMADDQPx, "xsnmaddqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSNMSUBQPx, "xsnmsubqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSSQRTQPx, "xssqrtqp"); +DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSSUBQPx, "xssubqp"); +DEFINE_SUBMNEM_INEXACT(SubMnemXSRQPIx, "xsrqpi"); + +static const char* RcMnemonic(const Instruction* instruction, const char* names[2]) +{ + return names[instruction->flags.rc]; +} + +static const char* OeRcMnemonic(const Instruction* instruction, const char* names[4]) +{ + return names[2*instruction->flags.oe + instruction->flags.rc]; +} + +static const char* LkMnemonic(const Instruction* instruction, const char* names[2]) +{ + return names[instruction->flags.lk]; +} + +static const char* LkHintMnemonic(const Instruction* instruction, const char* names[8]) +{ + return names[2*instruction->flags.branchLikelyHint + instruction->flags.lk]; +} + +static const char* AaLkMnemonic(const Instruction* instruction, const char* names[4]) +{ + return names[2*instruction->flags.aa + instruction->flags.lk]; +} + +static const char* AaLkHintMnemonic(const Instruction* instruction, const char* names[16]) +{ + return names[4*instruction->flags.branchLikelyHint + 2*instruction->flags.aa + instruction->flags.lk]; +} + +static const char* Round2OddMnemonic(const Instruction* instruction, const char* names[2]) +{ + return names[instruction->flags.round2odd]; +} + +static const char* InexactMnemonic(const Instruction* instruction, const char* names[2]) +{ + return names[instruction->flags.inexact]; +} + +const char* GetMnemonic(const Instruction* instruction) +{ + switch (instruction->id) + { + case PPC_ID_ADDx: return OeRcMnemonic(instruction, SubMnemADDx); + case PPC_ID_ADDCx: return OeRcMnemonic(instruction, SubMnemADDCx); + case PPC_ID_ADDEx: return OeRcMnemonic(instruction, SubMnemADDEx); + case PPC_ID_ADDI: return "addi"; + case PPC_ID_ADDICx: return RcMnemonic(instruction, SubMnemADDICx); + case PPC_ID_ADDIS: return "addis"; + case PPC_ID_ADDMEx: return OeRcMnemonic(instruction, SubMnemADDMEx); + case PPC_ID_ADDPCIS: return "addpcis"; + case PPC_ID_ADDZEx: return OeRcMnemonic(instruction, SubMnemADDZEx); + case PPC_ID_ANDx: return RcMnemonic(instruction, SubMnemANDx); + case PPC_ID_ANDCx: return RcMnemonic(instruction, SubMnemANDCx); + case PPC_ID_ANDI: return "andi."; + case PPC_ID_ANDIS: return "andis."; + case PPC_ID_ATTN: return "attn"; + case PPC_ID_Bx: return AaLkMnemonic(instruction, SubMnemBx); + case PPC_ID_BCx: + { + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + const char** mnemonics = NULL; + const char** mnemonicsHint = NULL; + + // mask away the "y" bit + switch (bo & 0x1e) + { + case 0: + mnemonics = SubMnemBDNZFx; + break; + + case 2: + mnemonics = SubMnemBDZFx; + break; + + case 4: + case 6: + switch (bi & 0x3) + { + case 0: + mnemonicsHint = SubMnemBGEx; + break; + case 1: + mnemonicsHint = SubMnemBLEx; + break; + case 2: + mnemonicsHint = SubMnemBNEx; + break; + case 3: + mnemonicsHint = SubMnemBNSx; + break; + + // should be unreachable + default: + return NULL; + } + + break; + + case 8: + mnemonics = SubMnemBDNZTx; + break; + + case 10: + mnemonics = SubMnemBDZTx; + break; + + case 12: + case 14: + switch (bi & 0x3) + { + case 0: + mnemonicsHint = SubMnemBLTx; + break; + + case 1: + mnemonicsHint = SubMnemBGTx; + break; + + case 2: + mnemonicsHint = SubMnemBEQx; + break; + + case 3: + mnemonicsHint = SubMnemBSOx; + break; + + // should be unreachable + default: + return NULL; + } + break; + + // technically these aren't terribly well defined + // when BI != 0, since these BOs don't involve + // a condition bit to test in BI to test against + case 16: + case 24: + mnemonicsHint = SubMnemBDNZx; + break; + + // these represent "branch always" in the BO field, so it's + // not super clear why these disassemble to bdnz + case 20: + case 28: + mnemonicsHint = SubMnemBDNZx; + break; + + case 18: + case 22: + case 26: + mnemonicsHint = SubMnemBDZx; + break; + + // these represent "branch always" in the BO field, so it's + // not super clear why these disassemble to bdz + case 30: + mnemonicsHint = SubMnemBDZx; + break; + + default: + mnemonics = SubMnemBCx; + } + + if (mnemonicsHint) + return AaLkHintMnemonic(instruction, mnemonicsHint); + + if (mnemonics) + return AaLkMnemonic(instruction, mnemonics); + + // should be unreachable + return NULL; + } + + case PPC_ID_BCCTRx: + { + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + // mask away the "y" bit + switch (bo & 0x1e) + { + case 4: + case 6: + switch (bi & 0x3) + { + case 0: return LkHintMnemonic(instruction, SubMnemBGECTRx); + case 1: return LkHintMnemonic(instruction, SubMnemBLECTRx); + case 2: return LkHintMnemonic(instruction, SubMnemBNECTRx); + case 3: return LkHintMnemonic(instruction, SubMnemBNSCTRx); + + // should be unreachable + default: return NULL; + } + + break; + + case 12: + case 14: + switch (bi & 0x3) + { + case 0: return LkHintMnemonic(instruction, SubMnemBLTCTRx); + case 1: return LkHintMnemonic(instruction, SubMnemBGTCTRx); + case 2: return LkHintMnemonic(instruction, SubMnemBEQCTRx); + case 3: return LkHintMnemonic(instruction, SubMnemBSOCTRx); + + // should be unreachable + default: return NULL; + } + + break; + + case 20: + return LkMnemonic(instruction, SubMnemBCTRx); + + default: + return LkMnemonic(instruction, SubMnemBCCTRx); + } + } + + case PPC_ID_BCLRx: + { + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + // mask away the "y" bit + switch (bo & 0x1e) + { + case 0: + return LkMnemonic(instruction, SubMnemBDNZFLRx); + + case 2: + return LkMnemonic(instruction, SubMnemBDZFLRx); + + case 4: + case 6: + switch (bi & 0x3) + { + case 0: return LkHintMnemonic(instruction, SubMnemBGELRx); + case 1: return LkHintMnemonic(instruction, SubMnemBLELRx); + case 2: return LkHintMnemonic(instruction, SubMnemBNELRx); + case 3: return LkHintMnemonic(instruction, SubMnemBNSLRx); + + // should be unreachable + default: return NULL; + } + + case 8: + return LkMnemonic(instruction, SubMnemBDNZTLRx); + + case 10: + return LkMnemonic(instruction, SubMnemBDZTLRx); + + case 12: + case 14: + switch (bi & 0x3) + { + case 0: return LkHintMnemonic(instruction, SubMnemBLTLRx); + case 1: return LkHintMnemonic(instruction, SubMnemBGTLRx); + case 2: return LkHintMnemonic(instruction, SubMnemBEQLRx); + case 3: return LkHintMnemonic(instruction, SubMnemBSOLRx); + + // should be unreachable + default: return NULL; + } + + // technically these aren't terribly well defined + // when BI != 0, since these BOs don't involve + // a condition bit to test in BI to test against + case 16: + case 24: + return LkHintMnemonic(instruction, SubMnemBDNZLRx); + + case 18: + case 26: + return LkHintMnemonic(instruction, SubMnemBDZLRx); + + case 20: + return LkHintMnemonic(instruction, SubMnemBLRx); + + default: + return LkMnemonic(instruction, SubMnemBCLRx); + } + } + + case PPC_ID_BPERMD: return "bpermd"; + case PPC_ID_CLRBHRB: return "clrbhrb"; + case PPC_ID_CLRLDIx: return RcMnemonic(instruction, SubMnemCLRLDIx); + case PPC_ID_CLRLWIx: return RcMnemonic(instruction, SubMnemCLRLWIx); + case PPC_ID_CLRRWIx: return RcMnemonic(instruction, SubMnemCLRRWIx); + case PPC_ID_CMPB: return "cmpb"; + case PPC_ID_CMPD: return "cmpd"; + case PPC_ID_CMPDI: return "cmpdi"; + case PPC_ID_CMPEQB: return "cmpeqb"; + case PPC_ID_CMPRB: return "cmprb"; + case PPC_ID_CMPW: return "cmpw"; + case PPC_ID_CMPWI: return "cmpwi"; + case PPC_ID_CMPLD: return "cmpld"; + case PPC_ID_CMPLDI: return "cmpldi"; + case PPC_ID_CMPLW: return "cmplw"; + case PPC_ID_CMPLWI: return "cmplwi"; + case PPC_ID_CNTLZDx: return RcMnemonic(instruction, SubMnemCNTLZDx); + case PPC_ID_CNTLZWx: return RcMnemonic(instruction, SubMnemCNTLZWx); + case PPC_ID_CNTTZDx: return RcMnemonic(instruction, SubMnemCNTTZDx); + case PPC_ID_CNTTZWx: return RcMnemonic(instruction, SubMnemCNTTZWx); + case PPC_ID_COPY: return "copy"; + case PPC_ID_CP_ABORT: return "cp_abort"; + case PPC_ID_CRAND: return "crand"; + case PPC_ID_CRANDC: return "crandc"; + case PPC_ID_CRCLR: return "crclr"; + case PPC_ID_CREQV: return "creqv"; + case PPC_ID_CRMOVE: return "crmove"; + case PPC_ID_CRNAND: return "crnand"; + case PPC_ID_CRNOR: return "crnor"; + case PPC_ID_CRNOT: return "crnot"; + case PPC_ID_CROR: return "cror"; + case PPC_ID_CRORC: return "crorc"; + case PPC_ID_CRSET: return "crset"; + case PPC_ID_CRXOR: return "crxor"; + case PPC_ID_DARN: return "darn"; + case PPC_ID_DCBA: return "dcba"; + case PPC_ID_DCBF: return "dcbf"; + case PPC_ID_DCBFEP: return "dcbfep"; + case PPC_ID_DCBFL: return "dcbfl"; + case PPC_ID_DCBFLP: return "dcbflp"; + case PPC_ID_DCBI: return "dcbi"; + case PPC_ID_DCBST: return "dcbst"; + case PPC_ID_DCBSTEP: return "dcbstep"; + case PPC_ID_DCBT: return "dcbt"; + case PPC_ID_DCBTT: return "dcbtt"; + case PPC_ID_DCBTEP: return "dcbtep"; + case PPC_ID_DCBTST: return "dcbtst"; + case PPC_ID_DCBTSTEP: return "dcbtstep"; + case PPC_ID_DCBTSTT: return "dcbtstt"; + case PPC_ID_DCBZ: return "dcbz"; + case PPC_ID_DCBZEP: return "dcbzep"; + case PPC_ID_DCBZL: return "dcbzl"; + case PPC_ID_DCCCI: return "dccci"; + case PPC_ID_DCI: return "dci"; + case PPC_ID_DIVDx: return OeRcMnemonic(instruction, SubMnemDIVDx); + case PPC_ID_DIVDEx: return OeRcMnemonic(instruction, SubMnemDIVDEx); + case PPC_ID_DIVDEUx: return OeRcMnemonic(instruction, SubMnemDIVDEUx); + case PPC_ID_DIVDUx: return OeRcMnemonic(instruction, SubMnemDIVDUx); + case PPC_ID_DIVWx: return OeRcMnemonic(instruction, SubMnemDIVWx); + case PPC_ID_DIVWEx: return OeRcMnemonic(instruction, SubMnemDIVWEx); + case PPC_ID_DIVWEUx: return OeRcMnemonic(instruction, SubMnemDIVWEUx); + case PPC_ID_DIVWUx: return OeRcMnemonic(instruction, SubMnemDIVWUx); + case PPC_ID_ECIWX: return "eciwx"; + case PPC_ID_ECOWX: return "ecowx"; + case PPC_ID_EIEIO: return "eieio"; + case PPC_ID_EQVx: return RcMnemonic(instruction, SubMnemEQVx); + case PPC_ID_EXTSBx: return RcMnemonic(instruction, SubMnemEXTSBx); + case PPC_ID_EXTSHx: return RcMnemonic(instruction, SubMnemEXTSHx); + case PPC_ID_EXTSWx: return RcMnemonic(instruction, SubMnemEXTSWx); + case PPC_ID_EXTSWSLIx: return RcMnemonic(instruction, SubMnemEXTSWSLIx); + case PPC_ID_FABSx: return RcMnemonic(instruction, SubMnemFABSx); + case PPC_ID_FADDx: return RcMnemonic(instruction, SubMnemFADDx); + case PPC_ID_FADDSx: return RcMnemonic(instruction, SubMnemFADDSx); + case PPC_ID_FCFIDx: return RcMnemonic(instruction, SubMnemFCFIDx); + case PPC_ID_FCFIDSx: return RcMnemonic(instruction, SubMnemFCFIDSx); + case PPC_ID_FCFIDUx: return RcMnemonic(instruction, SubMnemFCFIDUx); + case PPC_ID_FCFIDUSx: return RcMnemonic(instruction, SubMnemFCFIDUSx); + case PPC_ID_FCMPO: return "fcmpo"; + case PPC_ID_FCMPU: return "fcmpu"; + case PPC_ID_FCPSGNx: return RcMnemonic(instruction, SubMnemFCPSGNx); + case PPC_ID_FCTIDx: return RcMnemonic(instruction, SubMnemFCTIDx); + case PPC_ID_FCTIDUx: return RcMnemonic(instruction, SubMnemFCTIDUx); + case PPC_ID_FCTIDUZx: return RcMnemonic(instruction, SubMnemFCTIDUZx); + case PPC_ID_FCTIDZx: return RcMnemonic(instruction, SubMnemFCTIDZx); + case PPC_ID_FCTIWx: return RcMnemonic(instruction, SubMnemFCTIWx); + case PPC_ID_FCTIWUx: return RcMnemonic(instruction, SubMnemFCTIWUx); + case PPC_ID_FCTIWUZx: return RcMnemonic(instruction, SubMnemFCTIWUZx); + case PPC_ID_FCTIWZx: return RcMnemonic(instruction, SubMnemFCTIWZx); + case PPC_ID_FDIVx: return RcMnemonic(instruction, SubMnemFDIVx); + case PPC_ID_FDIVSx: return RcMnemonic(instruction, SubMnemFDIVSx); + case PPC_ID_FMADDx: return RcMnemonic(instruction, SubMnemFMADDx); + case PPC_ID_FMADDSx: return RcMnemonic(instruction, SubMnemFMADDSx); + case PPC_ID_FMRx: return RcMnemonic(instruction, SubMnemFMRx); + case PPC_ID_FMSUBx: return RcMnemonic(instruction, SubMnemFMSUBx); + case PPC_ID_FMSUBSx: return RcMnemonic(instruction, SubMnemFMSUBSx); + case PPC_ID_FMULx: return RcMnemonic(instruction, SubMnemFMULx); + case PPC_ID_FMULSx: return RcMnemonic(instruction, SubMnemFMULSx); + case PPC_ID_FNABSx: return RcMnemonic(instruction, SubMnemFNABSx); + case PPC_ID_FNEGx: return RcMnemonic(instruction, SubMnemFNEGx); + case PPC_ID_FNMADDx: return RcMnemonic(instruction, SubMnemFNMADDx); + case PPC_ID_FNMADDSx: return RcMnemonic(instruction, SubMnemFNMADDSx); + case PPC_ID_FNMSUBx: return RcMnemonic(instruction, SubMnemFNMSUBx); + case PPC_ID_FNMSUBSx: return RcMnemonic(instruction, SubMnemFNMSUBSx); + case PPC_ID_FREx: return RcMnemonic(instruction, SubMnemFREx); + case PPC_ID_FRESx: return RcMnemonic(instruction, SubMnemFRESx); + case PPC_ID_FRIMx: return RcMnemonic(instruction, SubMnemFRIMx); + case PPC_ID_FRINx: return RcMnemonic(instruction, SubMnemFRINx); + case PPC_ID_FRIPx: return RcMnemonic(instruction, SubMnemFRIPx); + case PPC_ID_FRIZx: return RcMnemonic(instruction, SubMnemFRIZx); + case PPC_ID_FRSPx: return RcMnemonic(instruction, SubMnemFRSPx); + case PPC_ID_FRSQRTEx: return RcMnemonic(instruction, SubMnemFRSQRTEx); + case PPC_ID_FRSQRTESx: return RcMnemonic(instruction, SubMnemFRSQRTESx); + case PPC_ID_FSELx: return RcMnemonic(instruction, SubMnemFSELx); + case PPC_ID_FSQRTx: return RcMnemonic(instruction, SubMnemFSQRTx); + case PPC_ID_FSQRTSx: return RcMnemonic(instruction, SubMnemFSQRTSx); + case PPC_ID_FSUBx: return RcMnemonic(instruction, SubMnemFSUBx); + case PPC_ID_FSUBSx: return RcMnemonic(instruction, SubMnemFSUBSx); + case PPC_ID_FTDIV: return "ftdiv"; + case PPC_ID_FTSQRT: return "ftsqrt"; + case PPC_ID_ICBI: return "icbi"; + case PPC_ID_ICBIEP: return "icbiep"; + case PPC_ID_ICBLC: return "icblc"; + case PPC_ID_ICBLQ: return "icblq."; + case PPC_ID_ICBT: return "icbt"; + case PPC_ID_ICBTLS: return "icbtls"; + case PPC_ID_ICCCI: return "iccci"; + case PPC_ID_ICI: return "ici"; + case PPC_ID_ISEL: return "isel"; + case PPC_ID_ISYNC: return "isync"; + case PPC_ID_LBARX: return "lbarx"; + case PPC_ID_LBEPX: return "lbepx"; + case PPC_ID_LBZ: return "lbz"; + case PPC_ID_LBZCIX: return "lbzcix"; + case PPC_ID_LBZU: return "lbzu"; + case PPC_ID_LBZUX: return "lbzux"; + case PPC_ID_LBZX: return "lbzx"; + case PPC_ID_LDARX: return "ldarx"; + case PPC_ID_LDAT: return "ldat"; + case PPC_ID_LDBRX: return "ldbrx"; + case PPC_ID_LDCIX: return "ldcix"; + case PPC_ID_LD: return "ld"; + case PPC_ID_LDU: return "ldu"; + case PPC_ID_LDUX: return "ldux"; + case PPC_ID_LDX: return "ldx"; + case PPC_ID_LFD: return "lfd"; + case PPC_ID_LFDEPX: return "lfdepx"; + case PPC_ID_LFDU: return "lfdu"; + case PPC_ID_LFDUX: return "lfdux"; + case PPC_ID_LFDX: return "lfdx"; + case PPC_ID_LFIWAX: return "lfiwax"; + case PPC_ID_LFIWZX: return "lfiwzx"; + case PPC_ID_LFS: return "lfs"; + case PPC_ID_LFSU: return "lfsu"; + case PPC_ID_LFSUX: return "lfsux"; + case PPC_ID_LFSX: return "lfsx"; + case PPC_ID_LHA: return "lha"; + case PPC_ID_LHARX: return "lharx"; + case PPC_ID_LHAU: return "lhau"; + case PPC_ID_LHAUX: return "lhaux"; + case PPC_ID_LHAX: return "lhax"; + case PPC_ID_LHBRX: return "lhbrx"; + case PPC_ID_LHEPX: return "lhepx"; + case PPC_ID_LHZ: return "lhz"; + case PPC_ID_LHZCIX: return "lhzcix"; + case PPC_ID_LHZU: return "lhzu"; + case PPC_ID_LHZUX: return "lhzux"; + case PPC_ID_LHZX: return "lhzx"; + case PPC_ID_LI: return "li"; + case PPC_ID_LIS: return "lis"; + case PPC_ID_LMW: return "lmw"; + case PPC_ID_LNIA: return "lnia"; + case PPC_ID_LSWI: return "lswi"; + case PPC_ID_LSWX: return "lswx"; + case PPC_ID_LWA: return "lwa"; + case PPC_ID_LWAT: return "lwat"; + case PPC_ID_LWAX: return "lwax"; + case PPC_ID_LWARX: return "lwarx"; + case PPC_ID_LWAUX: return "lwaux"; + case PPC_ID_LWBRX: return "lwbrx"; + case PPC_ID_LWEPX: return "lwepx"; + case PPC_ID_LWSYNC: return "lwsync"; + case PPC_ID_LWZ: return "lwz"; + case PPC_ID_LWZCIX: return "lwzcix"; + case PPC_ID_LWZU: return "lwzu"; + case PPC_ID_LWZUX: return "lwzux"; + case PPC_ID_LWZX: return "lwzx"; + case PPC_ID_MBAR: return "mbar"; + case PPC_ID_MCRF: return "mcrf"; + case PPC_ID_MCRFS: return "mcrfs"; + case PPC_ID_MCRXR: return "mcrxr"; + case PPC_ID_MCRXRX: return "mcrxrx"; + case PPC_ID_MFBHRBE: return "mfbhrbe"; + case PPC_ID_MFBR0: return "mfbr0"; + case PPC_ID_MFBR1: return "mfbr1"; + case PPC_ID_MFBR2: return "mfbr2"; + case PPC_ID_MFBR3: return "mfbr3"; + case PPC_ID_MFBR4: return "mfbr4"; + case PPC_ID_MFBR5: return "mfbr5"; + case PPC_ID_MFBR6: return "mfbr6"; + case PPC_ID_MFBR7: return "mfbr7"; + case PPC_ID_MFCR: return "mfcr"; + case PPC_ID_MFCTR: return "mfctr"; + case PPC_ID_MFDCR: return "mfdcr"; + case PPC_ID_MFDCRUX: return "mfdcrux"; + case PPC_ID_MFDCRX: return "mfdcrx"; + case PPC_ID_MFFSx: return RcMnemonic(instruction, SubMnemMFFSx); + case PPC_ID_MFFSCDRN: return "mffscdrn"; + case PPC_ID_MFFSCDRNI: return "mffscdrni"; + case PPC_ID_MFFSCE: return "mffsce"; + case PPC_ID_MFFSCRN: return "mffscrn"; + case PPC_ID_MFFSCRNI: return "mffscrni"; + case PPC_ID_MFFSL: return "mffsl"; + case PPC_ID_MFLR: return "mflr"; + case PPC_ID_MFMSR: return "mfmsr"; + case PPC_ID_MFOCRF: return "mfocrf"; + case PPC_ID_MFPMR: return "mfpmr"; + case PPC_ID_MFSPR: return "mfspr"; + case PPC_ID_MFSR: return "mfsr"; + case PPC_ID_MFSRIN: return "mfsrin"; + case PPC_ID_MFTB: return "mftb"; + case PPC_ID_MFTBU: return "mftbu"; + case PPC_ID_MFXER: return "mfxer"; + case PPC_ID_MRx: return RcMnemonic(instruction, SubMnemMRx); + case PPC_ID_MSGSYNC: return "msgsync"; + case PPC_ID_MTAMR: return "mtamr"; + case PPC_ID_MTBR0: return "mtbr0"; + case PPC_ID_MTBR1: return "mtbr1"; + case PPC_ID_MTBR2: return "mtbr2"; + case PPC_ID_MTBR3: return "mtbr3"; + case PPC_ID_MTBR4: return "mtbr4"; + case PPC_ID_MTBR5: return "mtbr5"; + case PPC_ID_MTBR6: return "mtbr6"; + case PPC_ID_MTBR7: return "mtbr7"; + case PPC_ID_MTCRF: return "mtcrf"; + case PPC_ID_MTCTR: return "mtctr"; + case PPC_ID_MTDCR: return "mtdcr"; + case PPC_ID_MTDCRUX: return "mtdcrux"; + case PPC_ID_MTDCRX: return "mtdcrx"; + case PPC_ID_MTFSB0x: return RcMnemonic(instruction, SubMnemMTFSB0x); + case PPC_ID_MTFSB1x: return RcMnemonic(instruction, SubMnemMTFSB1x); + case PPC_ID_MTFSFx: return RcMnemonic(instruction, SubMnemMTFSFx); + case PPC_ID_MTFSFIx: return RcMnemonic(instruction, SubMnemMTFSFIx); + case PPC_ID_MODSD: return "modsd"; + case PPC_ID_MODSW: return "modsw"; + case PPC_ID_MODUD: return "modud"; + case PPC_ID_MODUW: return "moduw"; + case PPC_ID_MTLR: return "mtlr"; + case PPC_ID_MTMSR: return "mtmsr"; + case PPC_ID_MTMSRD: return "mtmsrd"; + case PPC_ID_MTOCRF: return "mtocrf"; + case PPC_ID_MTPMR: return "mtpmr"; + case PPC_ID_MTSPR: return "mtspr"; + case PPC_ID_MTSR: return "mtsr"; + case PPC_ID_MTSRIN: return "mtsrin"; + case PPC_ID_MTXER: return "mtxer"; + case PPC_ID_MULHDx: return RcMnemonic(instruction, SubMnemMULHDx); + case PPC_ID_MULHDUx: return RcMnemonic(instruction, SubMnemMULHDUx); + case PPC_ID_MULHWx: return RcMnemonic(instruction, SubMnemMULHWx); + case PPC_ID_MULHWUx: return RcMnemonic(instruction, SubMnemMULHWUx); + case PPC_ID_MULLI: return "mulli"; + case PPC_ID_MULLDx: return OeRcMnemonic(instruction, SubMnemMULLDx); + case PPC_ID_MULLWx: return OeRcMnemonic(instruction, SubMnemMULLWx); + case PPC_ID_NANDx: return RcMnemonic(instruction, SubMnemNANDx); + case PPC_ID_NEGx: return OeRcMnemonic(instruction, SubMnemNEGx); + case PPC_ID_NOP: return "nop"; + case PPC_ID_NORx: return RcMnemonic(instruction, SubMnemNORx); + case PPC_ID_ORx: return RcMnemonic(instruction, SubMnemORx); + case PPC_ID_ORCx: return RcMnemonic(instruction, SubMnemORCx); + case PPC_ID_ORI: return "ori"; + case PPC_ID_ORIS: return "oris"; + case PPC_ID_PASTE: return "paste."; + case PPC_ID_POPCNTB: return "popcntb"; + case PPC_ID_POPCNTD: return "popcntd"; + case PPC_ID_POPCNTW: return "popcntw"; + case PPC_ID_PTESYNC: return "ptesync"; + case PPC_ID_RFCI: return "rfci"; + case PPC_ID_RFDI: return "rfdi"; + case PPC_ID_RFI: return "rfi"; + case PPC_ID_RFID: return "rfid"; + case PPC_ID_RFMCI: return "rfmci"; + case PPC_ID_RLDICLx: return RcMnemonic(instruction, SubMnemRLDICLx); + case PPC_ID_RLDICRx: return RcMnemonic(instruction, SubMnemRLDICRx); + case PPC_ID_RLDICx: return RcMnemonic(instruction, SubMnemRLDICx); + case PPC_ID_RLDIMIx: return RcMnemonic(instruction, SubMnemRLDIMIx); + case PPC_ID_RLDCLx: return RcMnemonic(instruction, SubMnemRLDCLx); + case PPC_ID_RLDCRx: return RcMnemonic(instruction, SubMnemRLDCRx); + case PPC_ID_RLWIMIx: return RcMnemonic(instruction, SubMnemRLWIMIx); + case PPC_ID_RLWINMx: return RcMnemonic(instruction, SubMnemRLWINMx); + case PPC_ID_RLWNMx: return RcMnemonic(instruction, SubMnemRLWNMx); + case PPC_ID_ROTLDx: return RcMnemonic(instruction, SubMnemROTLDx); + case PPC_ID_ROTLDIx: return RcMnemonic(instruction, SubMnemROTLDIx); + case PPC_ID_ROTLWx: return RcMnemonic(instruction, SubMnemROTLWx); + case PPC_ID_ROTLWIx: return RcMnemonic(instruction, SubMnemROTLWIx); + case PPC_ID_SC: return "sc"; + case PPC_ID_SETB: return "setb"; + case PPC_ID_SLBIA: return "slbia"; + case PPC_ID_SLBIE: return "slbie"; + case PPC_ID_SLBIEG: return "slbieg"; + case PPC_ID_SLBMFEE: return "slbmfee"; + case PPC_ID_SLBMFEV: return "slbmfev"; + case PPC_ID_SLBMTE: return "slbmte"; + case PPC_ID_SLBSYNC: return "slbsync"; + case PPC_ID_SLDx: return RcMnemonic(instruction, SubMnemSLDx); + case PPC_ID_SLDIx: return RcMnemonic(instruction, SubMnemSLDIx); + case PPC_ID_SLWx: return RcMnemonic(instruction, SubMnemSLWx); + case PPC_ID_SLWIx: return RcMnemonic(instruction, SubMnemSLWIx); + case PPC_ID_SRADx: return RcMnemonic(instruction, SubMnemSRADx); + case PPC_ID_SRADIx: return RcMnemonic(instruction, SubMnemSRADIx); + case PPC_ID_SRAWx: return RcMnemonic(instruction, SubMnemSRAWx); + case PPC_ID_SRAWIx: return RcMnemonic(instruction, SubMnemSRAWIx); + case PPC_ID_SRDx: return RcMnemonic(instruction, SubMnemSRDx); + case PPC_ID_SRDIx: return RcMnemonic(instruction, SubMnemSRDIx); + case PPC_ID_SRWx: return RcMnemonic(instruction, SubMnemSRWx); + case PPC_ID_SRWIx: return RcMnemonic(instruction, SubMnemSRWIx); + case PPC_ID_STB: return "stb"; + case PPC_ID_STBCIX: return "stbcix"; + case PPC_ID_STBCX: return "stbcx."; + case PPC_ID_STBEPX: return "stbepx"; + case PPC_ID_STBU: return "stbu"; + case PPC_ID_STBUX: return "stbux"; + case PPC_ID_STBX: return "stbx"; + case PPC_ID_STD: return "std"; + case PPC_ID_STDAT: return "stdat"; + case PPC_ID_STDBRX: return "stdbrx"; + case PPC_ID_STDCIX: return "stdcix"; + case PPC_ID_STDCX: return "stdcx."; + case PPC_ID_STDEPX: return "stdepx"; + case PPC_ID_STDU: return "stdu"; + case PPC_ID_STDUX: return "stdux"; + case PPC_ID_STDX: return "stdx"; + case PPC_ID_STFD: return "stfd"; + case PPC_ID_STFDEPX: return "stfdepx"; + case PPC_ID_STFDU: return "stfdu"; + case PPC_ID_STFDUX: return "stfdux"; + case PPC_ID_STFDX: return "stfdx"; + case PPC_ID_STFIWX: return "stfiwx"; + case PPC_ID_STFS: return "stfs"; + case PPC_ID_STFSU: return "stfsu"; + case PPC_ID_STFSUX: return "stfsux"; + case PPC_ID_STFSX: return "stfsx"; + case PPC_ID_STH: return "sth"; + case PPC_ID_STHBRX: return "sthbrx"; + case PPC_ID_STHCIX: return "sthcix"; + case PPC_ID_STHCX: return "sthcx."; + case PPC_ID_STHEPX: return "sthepx"; + case PPC_ID_STHU: return "sthu"; + case PPC_ID_STHUX: return "sthux"; + case PPC_ID_STHX: return "sthx"; + case PPC_ID_STMW: return "stmw"; + case PPC_ID_STSWI: return "stswi"; + case PPC_ID_STSWX: return "stswx"; + case PPC_ID_STW: return "stw"; + case PPC_ID_STWAT: return "stwat"; + case PPC_ID_STWBRX: return "stwbrx"; + case PPC_ID_STWCIX: return "stwcix"; + case PPC_ID_STWCX: return "stwcx."; + case PPC_ID_STWEPX: return "stwepx"; + case PPC_ID_STWU: return "stwu"; + case PPC_ID_STWUX: return "stwux"; + case PPC_ID_STWX: return "stwx"; + case PPC_ID_SUBFx: return OeRcMnemonic(instruction, SubMnemSUBFx); + case PPC_ID_SUBFCx: return OeRcMnemonic(instruction, SubMnemSUBFCx); + case PPC_ID_SUBFEx: return OeRcMnemonic(instruction, SubMnemSUBFEx); + case PPC_ID_SUBFIC: return "subfic"; + case PPC_ID_SUBFMEx: return OeRcMnemonic(instruction, SubMnemSUBFMEx); + case PPC_ID_SUBFZEx: return OeRcMnemonic(instruction, SubMnemSUBFZEx); + case PPC_ID_SYNC: return "sync"; + case PPC_ID_TABORT: return "tabort."; + case PPC_ID_TABORTDC: return "tabortdc."; + case PPC_ID_TABORTDCI: return "tabortdci."; + case PPC_ID_TABORTWC: return "tabortwc."; + case PPC_ID_TABORTWCI: return "tabortwci."; + case PPC_ID_TBEGIN: return "tbegin."; + case PPC_ID_TCHECK: return "tcheck"; + case PPC_ID_TD: return "td"; + case PPC_ID_TDEQ: return "tdeq"; + case PPC_ID_TDEQI: return "tdeqi"; + case PPC_ID_TDGT: return "tdgt"; + case PPC_ID_TDGTI: return "tdgti"; + case PPC_ID_TDI: return "tdi"; + case PPC_ID_TDLGT: return "tdlgt"; + case PPC_ID_TDLGTI: return "tdlgti"; + case PPC_ID_TDLLT: return "tdllt"; + case PPC_ID_TDLLTI: return "tdllti"; + case PPC_ID_TDLT: return "tdlt"; + case PPC_ID_TDLTI: return "tdlti"; + case PPC_ID_TDNE: return "tdne"; + case PPC_ID_TDNEI: return "tdnei"; + case PPC_ID_TDU: return "tdu"; + case PPC_ID_TDUI: return "tdui"; + case PPC_ID_TEND: return "tend."; + case PPC_ID_TLBIA: return "tlbia"; + case PPC_ID_TLBIE: return "tlbie"; + case PPC_ID_TLBIEL: return "tlbiel"; + case PPC_ID_TLBIVAX: return "tlbivax"; + case PPC_ID_TLBLI: return "tlbli"; + case PPC_ID_TLBSX: return "tlbsx"; + case PPC_ID_TLBSYNC: return "tlbsync"; + case PPC_ID_TLBRE: return "tlbre"; + case PPC_ID_TLBRELO: return "tlbrehi"; + case PPC_ID_TLBREHI: return "tlbrelo"; + case PPC_ID_TLBWE: return "tlbwe"; + case PPC_ID_TLBWEHI: return "tlbwehi"; + case PPC_ID_TLBWELO: return "tlbwelo"; + case PPC_ID_TRAP: return "trap"; + case PPC_ID_TRECHKPT: return "trechkpt."; + case PPC_ID_TRECLAIM: return "treclaim."; + case PPC_ID_TSR: return "tsr."; + case PPC_ID_TW: return "tw"; + case PPC_ID_TWEQ: return "tweq"; + case PPC_ID_TWEQI: return "tweqi"; + case PPC_ID_TWGT: return "twgt"; + case PPC_ID_TWGTI: return "twgti"; + case PPC_ID_TWGEI: return "twgei"; + case PPC_ID_TWI: return "twi"; + case PPC_ID_TWLEI: return "twlei"; + case PPC_ID_TWLLEI: return "twllei"; + case PPC_ID_TWLGT: return "twlgt"; + case PPC_ID_TWLGTI: return "twlgti"; + case PPC_ID_TWLLT: return "twllt"; + case PPC_ID_TWLLTI: return "twllti"; + case PPC_ID_TWLT: return "twlt"; + case PPC_ID_TWLTI: return "twlti"; + case PPC_ID_TWNE: return "twne"; + case PPC_ID_TWNEI: return "twnei"; + case PPC_ID_TWU: return "twu"; + case PPC_ID_TWUI: return "twui"; + case PPC_ID_WAIT: return "wait"; + case PPC_ID_WAITIMPL: return "waitimpl"; + case PPC_ID_WAITRSV: return "waitrsv"; + case PPC_ID_WRTEE: return "wrtee"; + case PPC_ID_WRTEEI: return "wrteei"; + case PPC_ID_XNOP: return "xnop"; + case PPC_ID_XORx: return RcMnemonic(instruction, SubMnemXORx); + case PPC_ID_XORI: return "xori"; + case PPC_ID_XORIS: return "xoris"; + + case PPC_ID_AV_VABSDUB: return "vabsdub"; + case PPC_ID_AV_VABSDUH: return "vabsduh"; + case PPC_ID_AV_VABSDUW: return "vabsduw"; + case PPC_ID_AV_VADDUQM: return "vadduqm"; + case PPC_ID_AV_VADDCUQ: return "vaddcuq"; + case PPC_ID_AV_BCDADD: return "bcdadd."; + case PPC_ID_AV_BCDCFN: return "bcdcfn."; + case PPC_ID_AV_BCDCFSQ: return "bcdcfsq."; + case PPC_ID_AV_BCDCFZ: return "bcdcfz."; + case PPC_ID_AV_BCDCPSGN: return "bcdcpsgn."; + case PPC_ID_AV_BCDCTN: return "bcdctn."; + case PPC_ID_AV_BCDCTSQ: return "bcdctsq."; + case PPC_ID_AV_BCDCTZ: return "bcdctz."; + case PPC_ID_AV_BCDS: return "bcds."; + case PPC_ID_AV_BCDSETSGN: return "bcdsetsgn."; + case PPC_ID_AV_BCDSR: return "bcdsr."; + case PPC_ID_AV_BCDSUB: return "bcdsub."; + case PPC_ID_AV_BCDTRUNC: return "bcdtrunc."; + case PPC_ID_AV_BCDUS: return "bcdus."; + case PPC_ID_AV_BCDUTRUNC: return "bcdutrunc."; + case PPC_ID_AV_DSS: return "dss"; + case PPC_ID_AV_DSSALL: return "dssall"; + case PPC_ID_AV_DST: return "dst"; + case PPC_ID_AV_DSTST: return "dstst"; + case PPC_ID_AV_DSTSTT: return "dststt"; + case PPC_ID_AV_DSTT: return "dstt"; + case PPC_ID_AV_LVEBX: return "lvebx"; + case PPC_ID_AV_LVEHX: return "lvehx"; + case PPC_ID_AV_LVEWX: return "lvewx"; + case PPC_ID_AV_LVSL: return "lvsl"; + case PPC_ID_AV_LVSR: return "lvsr"; + case PPC_ID_AV_LVX: return "lvx"; + case PPC_ID_AV_LVXL: return "lvxl"; + case PPC_ID_AV_MADDHD: return "maddhd"; + case PPC_ID_AV_MADDHDU: return "maddhdu"; + case PPC_ID_AV_MADDLD: return "maddld"; + case PPC_ID_AV_MFVSCR: return "mfvscr"; + case PPC_ID_AV_MTVSCR: return "mtvscr"; + case PPC_ID_AV_STVEBX: return "stvebx"; + case PPC_ID_AV_STVEHX: return "stvehx"; + case PPC_ID_AV_STVEWX: return "stvewx"; + case PPC_ID_AV_STVX: return "stvx"; + case PPC_ID_AV_STVXL: return "stvxl"; + case PPC_ID_AV_VADDCUW: return "vaddcuw"; + case PPC_ID_AV_VADDECUQ: return "vaddecuq"; + case PPC_ID_AV_VADDEUQM: return "vaddeuqm"; + case PPC_ID_AV_VADDFP: return "vaddfp"; + case PPC_ID_AV_VADDSBS: return "vaddsbs"; + case PPC_ID_AV_VADDSHS: return "vaddshs"; + case PPC_ID_AV_VADDSWS: return "vaddsws"; + case PPC_ID_AV_VADDUBM: return "vaddubm"; + case PPC_ID_AV_VADDUBS: return "vaddubs"; + case PPC_ID_AV_VADDUDM: return "vaddudm"; + case PPC_ID_AV_VADDUHM: return "vadduhm"; + case PPC_ID_AV_VADDUHS: return "vadduhs"; + case PPC_ID_AV_VADDUWM: return "vadduwm"; + case PPC_ID_AV_VADDUWS: return "vadduws"; + case PPC_ID_AV_VAND: return "vand"; + case PPC_ID_AV_VANDC: return "vandc"; + case PPC_ID_AV_VAVGSB: return "vavgsb"; + case PPC_ID_AV_VAVGSH: return "vavgsh"; + case PPC_ID_AV_VAVGSW: return "vavgsw"; + case PPC_ID_AV_VAVGUB: return "vavgub"; + case PPC_ID_AV_VAVGUH: return "vavguh"; + case PPC_ID_AV_VAVGUW: return "vavguw"; + case PPC_ID_AV_VBPERMD: return "vbpermd"; + case PPC_ID_AV_VBPERMQ: return "vbpermq"; + case PPC_ID_AV_VCFSX: return "vcfsx"; + case PPC_ID_AV_VCFUX: return "vcfux"; + case PPC_ID_AV_VCIPHER: return "vcipher"; + case PPC_ID_AV_VCIPHERLAST: return "vcipherlast"; + case PPC_ID_AV_VCLZB: return "vclzb"; + case PPC_ID_AV_VCLZD: return "vclzd"; + case PPC_ID_AV_VCLZH: return "vclzh"; + case PPC_ID_AV_VCLZLSBB: return "vclzlsbb"; + case PPC_ID_AV_VCLZW: return "vclzw"; + case PPC_ID_AV_VCMPBFPx: return RcMnemonic(instruction, SubMnemVCMPBFPx); + case PPC_ID_AV_VCMPEQFPx: return RcMnemonic(instruction, SubMnemVCMPEQFPx); + case PPC_ID_AV_VCMPEQUBx: return RcMnemonic(instruction, SubMnemVCMPEQUBx); + case PPC_ID_AV_VCMPEQUDx: return RcMnemonic(instruction, SubMnemVCMPEQUDx); + case PPC_ID_AV_VCMPEQUHx: return RcMnemonic(instruction, SubMnemVCMPEQUHx); + case PPC_ID_AV_VCMPEQUWx: return RcMnemonic(instruction, SubMnemVCMPEQUWx); + case PPC_ID_AV_VCMPGEFPx: return RcMnemonic(instruction, SubMnemVCMPGEFPx); + case PPC_ID_AV_VCMPGTFPx: return RcMnemonic(instruction, SubMnemVCMPGTFPx); + case PPC_ID_AV_VCMPGTSBx: return RcMnemonic(instruction, SubMnemVCMPGTSBx); + case PPC_ID_AV_VCMPGTSDx: return RcMnemonic(instruction, SubMnemVCMPGTSDx); + case PPC_ID_AV_VCMPGTSHx: return RcMnemonic(instruction, SubMnemVCMPGTSHx); + case PPC_ID_AV_VCMPGTSWx: return RcMnemonic(instruction, SubMnemVCMPGTSWx); + case PPC_ID_AV_VCMPGTUBx: return RcMnemonic(instruction, SubMnemVCMPGTUBx); + case PPC_ID_AV_VCMPGTUDx: return RcMnemonic(instruction, SubMnemVCMPGTUDx); + case PPC_ID_AV_VCMPGTUHx: return RcMnemonic(instruction, SubMnemVCMPGTUHx); + case PPC_ID_AV_VCMPGTUWx: return RcMnemonic(instruction, SubMnemVCMPGTUWx); + case PPC_ID_AV_VCMPNEBx: return RcMnemonic(instruction, SubMnemVCMPNEBx); + case PPC_ID_AV_VCMPNEHx: return RcMnemonic(instruction, SubMnemVCMPNEHx); + case PPC_ID_AV_VCMPNEWx: return RcMnemonic(instruction, SubMnemVCMPNEWx); + case PPC_ID_AV_VCMPNEZBx: return RcMnemonic(instruction, SubMnemVCMPNEZBx); + case PPC_ID_AV_VCMPNEZHx: return RcMnemonic(instruction, SubMnemVCMPNEZHx); + case PPC_ID_AV_VCMPNEZWx: return RcMnemonic(instruction, SubMnemVCMPNEZWx); + case PPC_ID_AV_VCTSXS: return "vctsxs"; + case PPC_ID_AV_VCTUXS: return "vctuxs"; + case PPC_ID_AV_VCTZB: return "vctzb"; + case PPC_ID_AV_VCTZD: return "vctzd"; + case PPC_ID_AV_VCTZH: return "vctzh"; + case PPC_ID_AV_VCTZLSBB: return "vctzlsbb"; + case PPC_ID_AV_VCTZW: return "vctzw"; + case PPC_ID_AV_VEQV: return "veqv"; + case PPC_ID_AV_VEXPTEFP: return "vexptefp"; + case PPC_ID_AV_VEXTRACTD: return "vextractd"; + case PPC_ID_AV_VEXTRACTUB: return "vextractub"; + case PPC_ID_AV_VEXTRACTUH: return "vextractuh"; + case PPC_ID_AV_VEXTRACTUW: return "vextractuw"; + case PPC_ID_AV_VEXTSB2D: return "vextsb2d"; + case PPC_ID_AV_VEXTSB2W: return "vextsb2w"; + case PPC_ID_AV_VEXTSH2D: return "vextsh2d"; + case PPC_ID_AV_VEXTSH2W: return "vextsh2w"; + case PPC_ID_AV_VEXTSW2D: return "vextsw2d"; + case PPC_ID_AV_VEXTUBLX: return "vextublx"; + case PPC_ID_AV_VEXTUHLX: return "vextuhlx"; + case PPC_ID_AV_VEXTUWLX: return "vextuwlx"; + case PPC_ID_AV_VEXTUBRX: return "vextubrx"; + case PPC_ID_AV_VEXTUHRX: return "vextuhrx"; + case PPC_ID_AV_VEXTUWRX: return "vextuwrx"; + case PPC_ID_AV_VGBBD: return "vgbbd"; + case PPC_ID_AV_VINSERTB: return "vinsertb"; + case PPC_ID_AV_VINSERTD: return "vinsertd"; + case PPC_ID_AV_VINSERTH: return "vinserth"; + case PPC_ID_AV_VINSERTW: return "vinsertw"; + case PPC_ID_AV_VLOGEFP: return "vlogefp"; + case PPC_ID_AV_VMADDFP: return "vmaddfp"; + case PPC_ID_AV_VMAXFP: return "vmaxfp"; + case PPC_ID_AV_VMAXSB: return "vmaxsb"; + case PPC_ID_AV_VMAXSD: return "vmaxsd"; + case PPC_ID_AV_VMAXSH: return "vmaxsh"; + case PPC_ID_AV_VMAXSW: return "vmaxsw"; + case PPC_ID_AV_VMAXUB: return "vmaxub"; + case PPC_ID_AV_VMAXUD: return "vmaxud"; + case PPC_ID_AV_VMAXUH: return "vmaxuh"; + case PPC_ID_AV_VMAXUW: return "vmaxuw"; + case PPC_ID_AV_VMHADDSHS: return "vmhaddshs"; + case PPC_ID_AV_VMHRADDSHS: return "vmhraddshs"; + case PPC_ID_AV_VMINFP: return "vminfp"; + case PPC_ID_AV_VMINSB: return "vminsb"; + case PPC_ID_AV_VMINSD: return "vminsd"; + case PPC_ID_AV_VMINSH: return "vminsh"; + case PPC_ID_AV_VMINSW: return "vminsw"; + case PPC_ID_AV_VMINUB: return "vminub"; + case PPC_ID_AV_VMINUD: return "vminud"; + case PPC_ID_AV_VMINUH: return "vminuh"; + case PPC_ID_AV_VMINUW: return "vminuw"; + case PPC_ID_AV_VMLADDUHM: return "vmladduhm"; + case PPC_ID_AV_VMR: return "vmr"; + case PPC_ID_AV_VMRGEW: return "vmrgew"; + case PPC_ID_AV_VMRGHB: return "vmrghb"; + case PPC_ID_AV_VMRGHH: return "vmrghh"; + case PPC_ID_AV_VMRGHW: return "vmrghw"; + case PPC_ID_AV_VMRGLB: return "vmrglb"; + case PPC_ID_AV_VMRGLH: return "vmrglh"; + case PPC_ID_AV_VMRGLW: return "vmrglw"; + case PPC_ID_AV_VMRGOW: return "vmrgow"; + case PPC_ID_AV_VMSUMMBM: return "vmsummbm"; + case PPC_ID_AV_VMSUMSHM: return "vmsumshm"; + case PPC_ID_AV_VMSUMSHS: return "vmsumshs"; + case PPC_ID_AV_VMSUMUBM: return "vmsumubm"; + case PPC_ID_AV_VMSUMUHM: return "vmsumuhm"; + case PPC_ID_AV_VMSUMUHS: return "vmsumuhs"; + case PPC_ID_AV_VMUL10CUQ: return "vmul10cuq"; + case PPC_ID_AV_VMUL10EUQ: return "vmul10euq"; + case PPC_ID_AV_VMUL10ECUQ: return "vmul10ecuq"; + case PPC_ID_AV_VMUL10UQ: return "vmul10uq"; + case PPC_ID_AV_VMULESB: return "vmulesb"; + case PPC_ID_AV_VMULESH: return "vmulesh"; + case PPC_ID_AV_VMULESW: return "vmulesw"; + case PPC_ID_AV_VMULEUB: return "vmuleub"; + case PPC_ID_AV_VMULEUH: return "vmuleuh"; + case PPC_ID_AV_VMULEUW: return "vmuleuw"; + case PPC_ID_AV_VMULOSB: return "vmulosb"; + case PPC_ID_AV_VMULOSH: return "vmulosh"; + case PPC_ID_AV_VMULOSW: return "vmulosw"; + case PPC_ID_AV_VMULOUB: return "vmuloub"; + case PPC_ID_AV_VMULOUH: return "vmulouh"; + case PPC_ID_AV_VMULOUW: return "vmulouw"; + case PPC_ID_AV_VMULUWM: return "vmuluwm"; + case PPC_ID_AV_VNAND: return "vnand"; + case PPC_ID_AV_VNCIPHER: return "vncipher"; + case PPC_ID_AV_VNCIPHERLAST: return "vncipherlast"; + case PPC_ID_AV_VNMSUBFP: return "vnmsubfp"; + case PPC_ID_AV_VNEGD: return "vnegd"; + case PPC_ID_AV_VNEGW: return "vnegw"; + case PPC_ID_AV_VNOR: return "vnor"; + case PPC_ID_AV_VNOT: return "vnot"; + case PPC_ID_AV_VOR: return "vor"; + case PPC_ID_AV_VORC: return "vorc"; + case PPC_ID_AV_VPERM: return "vperm"; + case PPC_ID_AV_VPERMR: return "vpermr"; + case PPC_ID_AV_VPERMXOR: return "vpermxor"; + case PPC_ID_AV_VPKPX: return "vpkpx"; + case PPC_ID_AV_VPKSDSS: return "vpksdss"; + case PPC_ID_AV_VPKSDUS: return "vpksdus"; + case PPC_ID_AV_VPKSHSS: return "vpkshss"; + case PPC_ID_AV_VPKSHUS: return "vpkshus"; + case PPC_ID_AV_VPKSWSS: return "vpkswss"; + case PPC_ID_AV_VPKSWUS: return "vpkswus"; + case PPC_ID_AV_VPKUDUM: return "vpkudum"; + case PPC_ID_AV_VPKUDUS: return "vpkudus"; + case PPC_ID_AV_VPKUHUM: return "vpkuhum"; + case PPC_ID_AV_VPKUHUS: return "vpkuhus"; + case PPC_ID_AV_VPKUWUM: return "vpkuwum"; + case PPC_ID_AV_VPKUWUS: return "vpkuwus"; + case PPC_ID_AV_VPMSUMB: return "vpmsumb"; + case PPC_ID_AV_VPMSUMD: return "vpmsumd"; + case PPC_ID_AV_VPMSUMH: return "vpmsumh"; + case PPC_ID_AV_VPMSUMW: return "vpmsumw"; + case PPC_ID_AV_VPOPCNTB: return "vpopcntb"; + case PPC_ID_AV_VPOPCNTD: return "vpopcntd"; + case PPC_ID_AV_VPOPCNTH: return "vpopcnth"; + case PPC_ID_AV_VPOPCNTW: return "vpopcntw"; + case PPC_ID_AV_VPRTYBD: return "vprtybd"; + case PPC_ID_AV_VPRTYBQ: return "vprtybq"; + case PPC_ID_AV_VPRTYBW: return "vprtybw"; + case PPC_ID_AV_VREFP: return "vrefp"; + case PPC_ID_AV_VRFIM: return "vrfim"; + case PPC_ID_AV_VRFIN: return "vrfin"; + case PPC_ID_AV_VRFIP: return "vrfip"; + case PPC_ID_AV_VRFIZ: return "vrfiz"; + case PPC_ID_AV_VRLB: return "vrlb"; + case PPC_ID_AV_VRLD: return "vrld"; + case PPC_ID_AV_VRLDNM: return "vrldnm"; + case PPC_ID_AV_VRLDMI: return "vrldmi"; + case PPC_ID_AV_VRLH: return "vrlh"; + case PPC_ID_AV_VRLW: return "vrlw"; + case PPC_ID_AV_VRLWMI: return "vrlwmi"; + case PPC_ID_AV_VRLWNM: return "vrlwnm"; + case PPC_ID_AV_VRSQRTEFP: return "vrsqrtefp"; + case PPC_ID_AV_VSBOX: return "vsbox"; + case PPC_ID_AV_VSEL: return "vsel"; + case PPC_ID_AV_VSHASIGMAD: return "vshasigmad"; + case PPC_ID_AV_VSHASIGMAW: return "vshasigmaw"; + case PPC_ID_AV_VSL: return "vsl"; + case PPC_ID_AV_VSLB: return "vslb"; + case PPC_ID_AV_VSLD: return "vsld"; + case PPC_ID_AV_VSLDOI: return "vsldoi"; + case PPC_ID_AV_VSLH: return "vslh"; + case PPC_ID_AV_VSLO: return "vslo"; + case PPC_ID_AV_VSLV: return "vslv"; + case PPC_ID_AV_VSLW: return "vslw"; + case PPC_ID_AV_VSPLTB: return "vspltb"; + case PPC_ID_AV_VSPLTH: return "vsplth"; + case PPC_ID_AV_VSPLTISB: return "vspltisb"; + case PPC_ID_AV_VSPLTISH: return "vspltish"; + case PPC_ID_AV_VSPLTISW: return "vspltisw"; + case PPC_ID_AV_VSPLTW: return "vspltw"; + case PPC_ID_AV_VSR: return "vsr"; + case PPC_ID_AV_VSRAB: return "vsrab"; + case PPC_ID_AV_VSRAD: return "vsrad"; + case PPC_ID_AV_VSRAH: return "vsrah"; + case PPC_ID_AV_VSRAW: return "vsraw"; + case PPC_ID_AV_VSRB: return "vsrb"; + case PPC_ID_AV_VSRD: return "vsrd"; + case PPC_ID_AV_VSRH: return "vsrh"; + case PPC_ID_AV_VSRO: return "vsro"; + case PPC_ID_AV_VSRV: return "vsrv"; + case PPC_ID_AV_VSRW: return "vsrw"; + case PPC_ID_AV_VSUBCUQ: return "vsubcuq"; + case PPC_ID_AV_VSUBCUW: return "vsubcuw"; + case PPC_ID_AV_VSUBECUQ: return "vsubecuq"; + case PPC_ID_AV_VSUBEUQM: return "vsubeuqm"; + case PPC_ID_AV_VSUBFP: return "vsubfp"; + case PPC_ID_AV_VSUBSBS: return "vsubsbs"; + case PPC_ID_AV_VSUBSHS: return "vsubshs"; + case PPC_ID_AV_VSUBSWS: return "vsubsws"; + case PPC_ID_AV_VSUBUBM: return "vsububm"; + case PPC_ID_AV_VSUBUBS: return "vsububs"; + case PPC_ID_AV_VSUBUDM: return "vsubudm"; + case PPC_ID_AV_VSUBUHM: return "vsubuhm"; + case PPC_ID_AV_VSUBUHS: return "vsubuhs"; + case PPC_ID_AV_VSUBUQM: return "vsubuqm"; + case PPC_ID_AV_VSUBUWM: return "vsubuwm"; + case PPC_ID_AV_VSUBUWS: return "vsubuws"; + case PPC_ID_AV_VSUMSWS: return "vsumsws"; + case PPC_ID_AV_VSUM2SWS: return "vsum2sws"; + case PPC_ID_AV_VSUM4SBS: return "vsum4sbs"; + case PPC_ID_AV_VSUM4SHS: return "vsum4shs"; + case PPC_ID_AV_VSUM4UBS: return "vsum4ubs"; + case PPC_ID_AV_VUPKHPX: return "vupkhpx"; + case PPC_ID_AV_VUPKHSB: return "vupkhsb"; + case PPC_ID_AV_VUPKHSH: return "vupkhsh"; + case PPC_ID_AV_VUPKHSW: return "vupkhsw"; + case PPC_ID_AV_VUPKLPX: return "vupklpx"; + case PPC_ID_AV_VUPKLSB: return "vupklsb"; + case PPC_ID_AV_VUPKLSH: return "vupklsh"; + case PPC_ID_AV_VUPKLSW: return "vupklsw"; + case PPC_ID_AV_VXOR: return "vxor"; + + case PPC_ID_VSX_LXSDX: return "lxsdx"; + case PPC_ID_VSX_LXSIBZX: return "lxsibzx"; + case PPC_ID_VSX_LXSIHZX: return "lxsihzx"; + case PPC_ID_VSX_LXSIWAX: return "lxsiwax"; + case PPC_ID_VSX_LXSIWZX: return "lxsiwzx"; + case PPC_ID_VSX_LXSSPX: return "lxsspx"; + case PPC_ID_VSX_LXV: return "lxv"; + case PPC_ID_VSX_LXVB16X: return "lxvb16x"; + case PPC_ID_VSX_LXVD2X: return "lxvd2x"; + case PPC_ID_VSX_LXVDSX: return "lxvdsx"; + case PPC_ID_VSX_LXVH8X: return "lxvh8x"; + case PPC_ID_VSX_LXVL: return "lxvl"; + case PPC_ID_VSX_LXVLL: return "lxvll"; + case PPC_ID_VSX_LXVW4X: return "lxvw4x"; + case PPC_ID_VSX_LXVWSX: return "lxvwsx"; + case PPC_ID_VSX_LXVX: return "lxvx"; + case PPC_ID_VSX_MFFPRD: return "mffprd"; + case PPC_ID_VSX_MFVSRD: return "mfvsrd"; + case PPC_ID_VSX_MFVSRLD: return "mfvsrld"; + case PPC_ID_VSX_MFVSRWZ: return "mfvsrwz"; + case PPC_ID_VSX_MTVSRD: return "mtvsrd"; + case PPC_ID_VSX_MTVSRDD: return "mtvsrdd"; + case PPC_ID_VSX_MTVSRWA: return "mtvsrwa"; + case PPC_ID_VSX_MTVSRWS: return "mtvsrws"; + case PPC_ID_VSX_MTVSRWZ: return "mtvsrwz"; + case PPC_ID_VSX_STXSD: return "stxsd"; + case PPC_ID_VSX_STXSDX: return "stxsdx"; + case PPC_ID_VSX_STXSIBX: return "stxsibx"; + case PPC_ID_VSX_STXSIHX: return "stxsihx"; + case PPC_ID_VSX_STXSIWX: return "stxsiwx"; + case PPC_ID_VSX_STXSSP: return "stxssp"; + case PPC_ID_VSX_STXSSPX: return "stxsspx"; + case PPC_ID_VSX_STXVB16X: return "stxvb16x"; + case PPC_ID_VSX_STXVD2X: return "stxvd2x"; + case PPC_ID_VSX_STXVH8X: return "stxvh8x"; + case PPC_ID_VSX_STXV: return "stxv"; + case PPC_ID_VSX_STXVL: return "stxvl"; + case PPC_ID_VSX_STXVLL: return "stxvll"; + case PPC_ID_VSX_STXVW4X: return "stxvw4x"; + case PPC_ID_VSX_STXVX: return "stxvx"; + case PPC_ID_VSX_XSABSDP: return "xsabsdp"; + case PPC_ID_VSX_XSABSQP: return "xsabsqp"; + case PPC_ID_VSX_XSADDDP: return "xsadddp"; + case PPC_ID_VSX_XSADDSP: return "xsaddsp"; + case PPC_ID_VSX_XSADDQPx: return Round2OddMnemonic(instruction, SubMnemXSADDQPx); + case PPC_ID_VSX_XSCMPEQDP: return "xscmpeqdp"; + case PPC_ID_VSX_XSCMPEXPDP: return "xscmpexpdp"; + case PPC_ID_VSX_XSCMPEXPQP: return "xscmpexpqp"; + case PPC_ID_VSX_XSCMPGEDP: return "xscmpgedp"; + case PPC_ID_VSX_XSCMPGTDP: return "xscmpgtdp"; + case PPC_ID_VSX_XSCMPODP: return "xscmpodp"; + case PPC_ID_VSX_XSCMPOQP: return "xscmpoqp"; + case PPC_ID_VSX_XSCMPUDP: return "xscmpudp"; + case PPC_ID_VSX_XSCMPUQP: return "xscmpuqp"; + case PPC_ID_VSX_XSCPSGNDP: return "xscpsgndp"; + case PPC_ID_VSX_XSCPSGNQP: return "xscpsgnqp"; + case PPC_ID_VSX_XSCVDPHP: return "xscvdphp"; + case PPC_ID_VSX_XSCVDPQP: return "xscvdpqp"; + case PPC_ID_VSX_XSCVDPSP: return "xscvdpsp"; + case PPC_ID_VSX_XSCVDPSPN: return "xscvdpspn"; + case PPC_ID_VSX_XSCVDPSXDS: return "xscvdpsxds"; + case PPC_ID_VSX_XSCVDPSXWS: return "xscvdpsxws"; + case PPC_ID_VSX_XSCVDPUXDS: return "xscvdpuxds"; + case PPC_ID_VSX_XSCVDPUXWS: return "xscvdpuxws"; + case PPC_ID_VSX_XSCVHPDP: return "xscvhpdp"; + case PPC_ID_VSX_XSCVQPDPx: return Round2OddMnemonic(instruction, SubMnemXSCVQPDPx); + case PPC_ID_VSX_XSCVQPSDZ: return "xscvqpsdz"; + case PPC_ID_VSX_XSCVQPSWZ: return "xscvqpswz"; + case PPC_ID_VSX_XSCVQPUDZ: return "xscvqpudz"; + case PPC_ID_VSX_XSCVQPUWZ: return "xscvqpuwz"; + case PPC_ID_VSX_XSCVSDQP: return "xscvsdqp"; + case PPC_ID_VSX_XSCVSPDP: return "xscvspdp"; + case PPC_ID_VSX_XSCVSPDPN: return "xscvspdpn"; + case PPC_ID_VSX_XSCVSXDDP: return "xscvsxddp"; + case PPC_ID_VSX_XSCVSXDSP: return "xscvsxdsp"; + case PPC_ID_VSX_XSCVUDQP: return "xscvudqp"; + case PPC_ID_VSX_XSCVUXDDP: return "xscvuxddp"; + case PPC_ID_VSX_XSCVUXDSP: return "xscvuxdsp"; + case PPC_ID_VSX_XSDIVDP: return "xsdivdp"; + case PPC_ID_VSX_XSDIVSP: return "xsdivsp"; + case PPC_ID_VSX_XSDIVQPx: return Round2OddMnemonic(instruction, SubMnemXSDIVQPx); + case PPC_ID_VSX_XSIEXPDP: return "xsiexpdp"; + case PPC_ID_VSX_XSIEXPQP: return "xsiexpqp"; + case PPC_ID_VSX_XSMADDADP: return "xsmaddadp"; + case PPC_ID_VSX_XSMADDASP: return "xsmaddasp"; + case PPC_ID_VSX_XSMADDMDP: return "xsmaddmdp"; + case PPC_ID_VSX_XSMADDMSP: return "xsmaddmsp"; + case PPC_ID_VSX_XSMADDQPx: return Round2OddMnemonic(instruction, SubMnemXSMADDQPx); + case PPC_ID_VSX_XSMAXCDP: return "xsmaxcdp"; + case PPC_ID_VSX_XSMAXDP: return "xsmaxdp"; + case PPC_ID_VSX_XSMAXJDP: return "xsmaxjdp"; + case PPC_ID_VSX_XSMINDP: return "xsmindp"; + case PPC_ID_VSX_XSMINCDP: return "xsmincdp"; + case PPC_ID_VSX_XSMINJDP: return "xsminjdp"; + case PPC_ID_VSX_XSMSUBADP: return "xsmsubadp"; + case PPC_ID_VSX_XSMSUBASP: return "xsmsubasp"; + case PPC_ID_VSX_XSMSUBMDP: return "xsmsubmdp"; + case PPC_ID_VSX_XSMSUBMSP: return "xsmsubmsp"; + case PPC_ID_VSX_XSMSUBQPx: return Round2OddMnemonic(instruction, SubMnemXSMSUBQPx); + case PPC_ID_VSX_XSMULDP: return "xsmuldp"; + case PPC_ID_VSX_XSMULSP: return "xsmulsp"; + case PPC_ID_VSX_XSMULQPx: return Round2OddMnemonic(instruction, SubMnemXSMULQPx); + case PPC_ID_VSX_XSNABSDP: return "xsnabsdp"; + case PPC_ID_VSX_XSNABSQP: return "xsnabsqp"; + case PPC_ID_VSX_XSNEGDP: return "xsnegdp"; + case PPC_ID_VSX_XSNEGQP: return "xsnegqp"; + case PPC_ID_VSX_XSNMADDADP: return "xsnmaddadp"; + case PPC_ID_VSX_XSNMADDASP: return "xsnmaddasp"; + case PPC_ID_VSX_XSNMADDQPx: return Round2OddMnemonic(instruction, SubMnemXSNMADDQPx); + case PPC_ID_VSX_XSNMADDMDP: return "xsnmaddmdp"; + case PPC_ID_VSX_XSNMADDMSP: return "xsnmaddmsp"; + case PPC_ID_VSX_XSNMSUBADP: return "xsnmsubadp"; + case PPC_ID_VSX_XSNMSUBASP: return "xsnmsubasp"; + case PPC_ID_VSX_XSNMSUBMDP: return "xsnmsubmdp"; + case PPC_ID_VSX_XSNMSUBMSP: return "xsnmsubmsp"; + case PPC_ID_VSX_XSNMSUBQPx: return Round2OddMnemonic(instruction, SubMnemXSNMSUBQPx); + case PPC_ID_VSX_XSRDPI: return "xsrdpi"; + case PPC_ID_VSX_XSRDPIC: return "xsrdpic"; + case PPC_ID_VSX_XSRDPIM: return "xsrdpim"; + case PPC_ID_VSX_XSRDPIP: return "xsrdpip"; + case PPC_ID_VSX_XSRDPIZ: return "xsrdpiz"; + case PPC_ID_VSX_XSREDP: return "xsredp"; + case PPC_ID_VSX_XSRESP: return "xsresp"; + case PPC_ID_VSX_XSRSP: return "xsrsp"; + case PPC_ID_VSX_XSRSQRTEDP: return "xsrsqrtedp"; + case PPC_ID_VSX_XSRSQRTESP: return "xsrsqrtesp"; + case PPC_ID_VSX_XSSQRTDP: return "xssqrtdp"; + case PPC_ID_VSX_XSSQRTQPx: return Round2OddMnemonic(instruction, SubMnemXSSQRTQPx); + case PPC_ID_VSX_XSSQRTSP: return "xssqrtsp"; + case PPC_ID_VSX_XSSUBDP: return "xssubdp"; + case PPC_ID_VSX_XSSUBSP: return "xssubsp"; + case PPC_ID_VSX_XSSUBQPx: return Round2OddMnemonic(instruction, SubMnemXSSUBQPx); + case PPC_ID_VSX_XSRQPIx: return InexactMnemonic(instruction, SubMnemXSRQPIx); + case PPC_ID_VSX_XSRQPXP: return "xsrqpxp"; + case PPC_ID_VSX_XSTDIVDP: return "xstdivdp"; + case PPC_ID_VSX_XSTDIVSP: return "xstdivsp"; + case PPC_ID_VSX_XSTSTDCDP: return "xststdcdp"; + case PPC_ID_VSX_XSTSTDCQP: return "xststdcqp"; + case PPC_ID_VSX_XSTSTDCSP: return "xststdcsp"; + case PPC_ID_VSX_XSTSQRTDP: return "xstsqrtdp"; + case PPC_ID_VSX_XSXEXPDP: return "xsxexpdp"; + case PPC_ID_VSX_XSXEXPQP: return "xsxexpqp"; + case PPC_ID_VSX_XSXSIGDP: return "xsxsigdp"; + case PPC_ID_VSX_XSXSIGQP: return "xsxsigqp"; + case PPC_ID_VSX_XVABSSP: return "xvabssp"; + case PPC_ID_VSX_XVABSDP: return "xvabsdp"; + case PPC_ID_VSX_XVADDSP: return "xvaddsp"; + case PPC_ID_VSX_XVADDDP: return "xvadddp"; + case PPC_ID_VSX_XVCMPEQDPx: return RcMnemonic(instruction, SubMnemXVCMPEQDPx); + case PPC_ID_VSX_XVCMPEQSPx: return RcMnemonic(instruction, SubMnemXVCMPEQSPx); + case PPC_ID_VSX_XVCMPGEDPx: return RcMnemonic(instruction, SubMnemXVCMPGEDPx); + case PPC_ID_VSX_XVCMPGESPx: return RcMnemonic(instruction, SubMnemXVCMPGESPx); + case PPC_ID_VSX_XVCMPGTDPx: return RcMnemonic(instruction, SubMnemXVCMPGTDPx); + case PPC_ID_VSX_XVCMPGTSPx: return RcMnemonic(instruction, SubMnemXVCMPGTSPx); + case PPC_ID_VSX_XVCPSGNDP: return "xvcpsgndp"; + case PPC_ID_VSX_XVCPSGNSP: return "xvcpsgnsp"; + case PPC_ID_VSX_XVCVDPSP: return "xvcvdpsp"; + case PPC_ID_VSX_XVCVDPSXDS: return "xvcvdpsxds"; + case PPC_ID_VSX_XVCVDPSXWS: return "xvcvdpsxws"; + case PPC_ID_VSX_XVCVDPUXDS: return "xvcvdpuxds"; + case PPC_ID_VSX_XVCVDPUXWS: return "xvcvdpuxws"; + case PPC_ID_VSX_XVCVHPSP: return "xvcvhpsp"; + case PPC_ID_VSX_XVCVSPDP: return "xvcvspdp"; + case PPC_ID_VSX_XVCVSPHP: return "xvcvsphp"; + case PPC_ID_VSX_XVCVSPSXDS: return "xvcvspsxds"; + case PPC_ID_VSX_XVCVSPSXWS: return "xvcvspsxws"; + case PPC_ID_VSX_XVCVSPUXDS: return "xvcvspuxds"; + case PPC_ID_VSX_XVCVSPUXWS: return "xvcvspuxws"; + case PPC_ID_VSX_XVCVSXDDP: return "xvcvsxddp"; + case PPC_ID_VSX_XVCVSXDSP: return "xvcvsxdsp"; + case PPC_ID_VSX_XVCVSXWDP: return "xvcvsxwdp"; + case PPC_ID_VSX_XVCVSXWSP: return "xvcvsxwsp"; + case PPC_ID_VSX_XVCVUXDDP: return "xvcvuxddp"; + case PPC_ID_VSX_XVCVUXDSP: return "xvcvuxdsp"; + case PPC_ID_VSX_XVCVUXWDP: return "xvcvuxwdp"; + case PPC_ID_VSX_XVCVUXWSP: return "xvcvuxwsp"; + case PPC_ID_VSX_XVDIVDP: return "xvdivdp"; + case PPC_ID_VSX_XVDIVSP: return "xvdivsp"; + case PPC_ID_VSX_XVIEXPDP: return "xviexpdp"; + case PPC_ID_VSX_XVIEXPSP: return "xviexpsp"; + case PPC_ID_VSX_XVMADDADP: return "xvmaddadp"; + case PPC_ID_VSX_XVMADDASP: return "xvmaddasp"; + case PPC_ID_VSX_XVMADDMDP: return "xvmaddmdp"; + case PPC_ID_VSX_XVMADDMSP: return "xvmaddmsp"; + case PPC_ID_VSX_XVMAXDP: return "xvmaxdp"; + case PPC_ID_VSX_XVMAXSP: return "xvmaxsp"; + case PPC_ID_VSX_XVMINDP: return "xvmindp"; + case PPC_ID_VSX_XVMINSP: return "xvminsp"; + case PPC_ID_VSX_XVMOVDP: return "xvmovdp"; + case PPC_ID_VSX_XVMOVSP: return "xvmovsp"; + case PPC_ID_VSX_XVMSUBADP: return "xvmsubadp"; + case PPC_ID_VSX_XVMSUBASP: return "xvmsubasp"; + case PPC_ID_VSX_XVMSUBMDP: return "xvmsubmdp"; + case PPC_ID_VSX_XVMSUBMSP: return "xvmsubmsp"; + case PPC_ID_VSX_XVMULSP: return "xvmulsp"; + case PPC_ID_VSX_XVMULDP: return "xvmuldp"; + case PPC_ID_VSX_XVNABSDP: return "xvnabsdp"; + case PPC_ID_VSX_XVNABSSP: return "xvnabssp"; + case PPC_ID_VSX_XVNMADDADP: return "xvnmaddadp"; + case PPC_ID_VSX_XVNMADDASP: return "xvnmaddasp"; + case PPC_ID_VSX_XVNMADDMDP: return "xvnmaddmdp"; + case PPC_ID_VSX_XVNMADDMSP: return "xvnmaddmsp"; + case PPC_ID_VSX_XVNEGDP: return "xvnegdp"; + case PPC_ID_VSX_XVNEGSP: return "xvnegsp"; + case PPC_ID_VSX_XVNMSUBADP: return "xvnmsubadp"; + case PPC_ID_VSX_XVNMSUBASP: return "xvnmsubasp"; + case PPC_ID_VSX_XVNMSUBMSP: return "xvnmsubmsp"; + case PPC_ID_VSX_XVNMSUBMDP: return "xvnmsubmdp"; + case PPC_ID_VSX_XVRDPI: return "xvrdpi"; + case PPC_ID_VSX_XVRDPIC: return "xvrdpic"; + case PPC_ID_VSX_XVRDPIM: return "xvrdpim"; + case PPC_ID_VSX_XVRDPIP: return "xvrdpip"; + case PPC_ID_VSX_XVRDPIZ: return "xvrdpiz"; + case PPC_ID_VSX_XVREDP: return "xvredp"; + case PPC_ID_VSX_XVRESP: return "xvresp"; + case PPC_ID_VSX_XVRSPI: return "xvrspi"; + case PPC_ID_VSX_XVRSPIC: return "xvrspic"; + case PPC_ID_VSX_XVRSPIM: return "xvrspim"; + case PPC_ID_VSX_XVRSPIP: return "xvrspip"; + case PPC_ID_VSX_XVRSPIZ: return "xvrspiz"; + case PPC_ID_VSX_XVRSQRTEDP: return "xvrsqrtedp"; + case PPC_ID_VSX_XVRSQRTESP: return "xvrsqrtesp"; + case PPC_ID_VSX_XVSQRTDP: return "xvsqrtdp"; + case PPC_ID_VSX_XVSQRTSP: return "xvsqrtsp"; + case PPC_ID_VSX_XVSUBSP: return "xvsubsp"; + case PPC_ID_VSX_XVSUBDP: return "xvsubdp"; + case PPC_ID_VSX_XVTDIVDP: return "xvtdivdp"; + case PPC_ID_VSX_XVTDIVSP: return "xvtdivsp"; + case PPC_ID_VSX_XVTSQRTDP: return "xvtsqrtdp"; + case PPC_ID_VSX_XVTSQRTSP: return "xvtsqrtsp"; + case PPC_ID_VSX_XVTSTDCDP: return "xvtstdcdp"; + case PPC_ID_VSX_XVTSTDCSP: return "xvtstdcsp"; + case PPC_ID_VSX_XVXEXPDP: return "xvxexpdp"; + case PPC_ID_VSX_XVXEXPSP: return "xvxexpsp"; + case PPC_ID_VSX_XVXSIGDP: return "xvxsigdp"; + case PPC_ID_VSX_XVXSIGSP: return "xvxsigsp"; + case PPC_ID_VSX_XXBRD: return "xxbrd"; + case PPC_ID_VSX_XXBRH: return "xxbrh"; + case PPC_ID_VSX_XXBRQ: return "xxbrq"; + case PPC_ID_VSX_XXBRW: return "xxbrw"; + case PPC_ID_VSX_XXEXTRACTUW: return "xxextractuw"; + case PPC_ID_VSX_XXINSERTW: return "xxinsertw"; + case PPC_ID_VSX_XXLAND: return "xxland"; + case PPC_ID_VSX_XXLANDC: return "xxlandc"; + case PPC_ID_VSX_XXLEQV: return "xxleqv"; + case PPC_ID_VSX_XXLNAND: return "xxlnand"; + case PPC_ID_VSX_XXLNOR: return "xxlnor"; + case PPC_ID_VSX_XXLORC: return "xxlorc"; + case PPC_ID_VSX_XXMRGHD: return "xxmrghd"; + case PPC_ID_VSX_XXMRGHW: return "xxmrghw"; + case PPC_ID_VSX_XXMRGLD: return "xxmrgld"; + case PPC_ID_VSX_XXMRGLW: return "xxmrglw"; + case PPC_ID_VSX_XXLOR: return "xxlor"; + case PPC_ID_VSX_XXLXOR: return "xxlxor"; + case PPC_ID_VSX_XXPERM: return "xxperm"; + case PPC_ID_VSX_XXPERMDI: return "xxpermdi"; + case PPC_ID_VSX_XXPERMR: return "xxpermr"; + case PPC_ID_VSX_XXSEL: return "xxsel"; + case PPC_ID_VSX_XXSLDWI: return "xxsldwi"; + case PPC_ID_VSX_XXSPLTD: return "xxspltd"; + case PPC_ID_VSX_XXSPLTIB: return "xxspltib"; + case PPC_ID_VSX_XXSPLTW: return "xxspltw"; + case PPC_ID_VSX_XXSWAPD: return "xxswapd"; + + case PPC_ID_PSQ_L: return "psq_l"; + case PPC_ID_PSQ_LU: return "psq_lu"; + case PPC_ID_PSQ_LUX: return "psq_lux"; + case PPC_ID_PSQ_LX: return "psq_lx"; + case PPC_ID_PSQ_ST: return "psq_st"; + case PPC_ID_PSQ_STU: return "psq_stu"; + case PPC_ID_PSQ_STUX: return "psq_stux"; + case PPC_ID_PSQ_STX: return "psq_stx"; + + case PPC_ID_SPE_BRINC: return "brinc"; + case PPC_ID_SPE_EFDABS: return "efdabs"; + case PPC_ID_SPE_EFDADD: return "efdadd"; + case PPC_ID_SPE_EFDCFS: return "efdcfs"; + case PPC_ID_SPE_EFDCFSF: return "efdcfsf"; + case PPC_ID_SPE_EFDCFSI: return "efdcfsi"; + case PPC_ID_SPE_EFDCFSID: return "efdcfsid"; + case PPC_ID_SPE_EFDCFUF: return "efdcfuf"; + case PPC_ID_SPE_EFDCFUI: return "efdcfui"; + case PPC_ID_SPE_EFDCFUID: return "efdcfuid"; + case PPC_ID_SPE_EFDCMPEQ: return "efdcmpeq"; + case PPC_ID_SPE_EFDCMPGT: return "efdcmpgt"; + case PPC_ID_SPE_EFDCMPLT: return "efdcmplt"; + case PPC_ID_SPE_EFDCTSF: return "efdctsf"; + case PPC_ID_SPE_EFDCTSI: return "efdctsi"; + case PPC_ID_SPE_EFDCTSIDZ: return "efdctsidz"; + case PPC_ID_SPE_EFDCTSIZ: return "efdctsiz"; + case PPC_ID_SPE_EFDCTUF: return "efdctuf"; + case PPC_ID_SPE_EFDCTUI: return "efdctui"; + case PPC_ID_SPE_EFDCTUIDZ: return "efdctuidz"; + case PPC_ID_SPE_EFDCTUIZ: return "efdctuiz"; + case PPC_ID_SPE_EFDDIV: return "efddiv"; + case PPC_ID_SPE_EFDMUL: return "efdmul"; + case PPC_ID_SPE_EFDNABS: return "efdnabs"; + case PPC_ID_SPE_EFDNEG: return "efdneg"; + case PPC_ID_SPE_EFDSUB: return "efdsub"; + case PPC_ID_SPE_EFDTSTEQ: return "efdtsteq"; + case PPC_ID_SPE_EFDTSTGT: return "efdtstgt"; + case PPC_ID_SPE_EFDTSTLT: return "efdtstlt"; + case PPC_ID_SPE_EFSABS: return "efsabs"; + case PPC_ID_SPE_EFSADD: return "efsadd"; + case PPC_ID_SPE_EFSCFD: return "efscfd"; + case PPC_ID_SPE_EFSCFSF: return "efscfsf"; + case PPC_ID_SPE_EFSCFSI: return "efscfsi"; + case PPC_ID_SPE_EFSCFUF: return "efscfuf"; + case PPC_ID_SPE_EFSCFUI: return "efscfui"; + case PPC_ID_SPE_EFSCMPEQ: return "efscmpeq"; + case PPC_ID_SPE_EFSCMPGT: return "efscmpgt"; + case PPC_ID_SPE_EFSCMPLT: return "efscmplt"; + case PPC_ID_SPE_EFSCTSF: return "efsctsf"; + case PPC_ID_SPE_EFSCTSI: return "efsctsi"; + case PPC_ID_SPE_EFSCTSIZ: return "efsctsiz"; + case PPC_ID_SPE_EFSCTUF: return "efsctuf"; + case PPC_ID_SPE_EFSCTUI: return "efsctui"; + case PPC_ID_SPE_EFSCTUIZ: return "efsctuiz"; + case PPC_ID_SPE_EFSDIV: return "efsdiv"; + case PPC_ID_SPE_EFSMUL: return "efsmul"; + case PPC_ID_SPE_EFSNABS: return "efsnabs"; + case PPC_ID_SPE_EFSNEG: return "efsneg"; + case PPC_ID_SPE_EFSSUB: return "efssub"; + case PPC_ID_SPE_EFSTSTEQ: return "efststeq"; + case PPC_ID_SPE_EFSTSTGT: return "efststgt"; + case PPC_ID_SPE_EFSTSTLT: return "efststlt"; + case PPC_ID_SPE_EVABS: return "evabs"; + case PPC_ID_SPE_EVADDIW: return "evaddiw"; + case PPC_ID_SPE_EVADDSMIAAW: return "evaddsmiaaw"; + case PPC_ID_SPE_EVADDSSIAAW: return "evaddssiaaw"; + case PPC_ID_SPE_EVADDUMIAAW: return "evaddumiaaw"; + case PPC_ID_SPE_EVADDUSIAAW: return "evaddusiaaw"; + case PPC_ID_SPE_EVADDW: return "evaddw"; + case PPC_ID_SPE_EVAND: return "evand"; + case PPC_ID_SPE_EVANDC: return "evandc"; + case PPC_ID_SPE_EVCMPEQ: return "evcmpeq"; + case PPC_ID_SPE_EVCMPGTS: return "evcmpgts"; + case PPC_ID_SPE_EVCMPGTU: return "evcmpgtu"; + case PPC_ID_SPE_EVCMPLTS: return "evcmplts"; + case PPC_ID_SPE_EVCMPLTU: return "evcmpltu"; + case PPC_ID_SPE_EVCNTLSW: return "evcntlsw"; + case PPC_ID_SPE_EVCNTLZW: return "evcntlzw"; + case PPC_ID_SPE_EVDIVWS: return "evdivws"; + case PPC_ID_SPE_EVDIVWU: return "evdivwu"; + case PPC_ID_SPE_EVEQV: return "eveqv"; + case PPC_ID_SPE_EVEXTSB: return "evextsb"; + case PPC_ID_SPE_EVEXTSH: return "evextsh"; + case PPC_ID_SPE_EVFSABS: return "evfsabs"; + case PPC_ID_SPE_EVFSADD: return "evfsadd"; + case PPC_ID_SPE_EVFSCFSF: return "evfscfsf"; + case PPC_ID_SPE_EVFSCFSI: return "evfscfsi"; + case PPC_ID_SPE_EVFSCFUF: return "evfscfuf"; + case PPC_ID_SPE_EVFSCFUI: return "evfscfui"; + case PPC_ID_SPE_EVSCFUI: return "evscfui"; + case PPC_ID_SPE_EVFSCMPEQ: return "evfscmpeq"; + case PPC_ID_SPE_EVFSCMPGT: return "evfscmpgt"; + case PPC_ID_SPE_EVFSCMPLT: return "evfscmplt"; + case PPC_ID_SPE_EVFSCTSF: return "evfsctsf"; + case PPC_ID_SPE_EVFSCTSI: return "evfsctsi"; + case PPC_ID_SPE_EVFSCTSIZ: return "evfsctsiz"; + case PPC_ID_SPE_EVFSCTUF: return "evfsctuf"; + case PPC_ID_SPE_EVFSCTUI: return "evfsctui"; + case PPC_ID_SPE_EVFSCTUIZ: return "evfsctuiz"; + case PPC_ID_SPE_EVFSDIV: return "evfsdiv"; + case PPC_ID_SPE_EVFSMUL: return "evfsmul"; + case PPC_ID_SPE_EVFSNABS: return "evfsnabs"; + case PPC_ID_SPE_EVFSNEG: return "evfsneg"; + case PPC_ID_SPE_EVFSSUB: return "evfssub"; + case PPC_ID_SPE_EVFSTSTEQ: return "evfststeq"; + case PPC_ID_SPE_EVFSTSTGT: return "evfststgt"; + case PPC_ID_SPE_EVFSTSTLT: return "evfststlt"; + case PPC_ID_SPE_EVLDD: return "evldd"; + case PPC_ID_SPE_EVLDDX: return "evlddx"; + case PPC_ID_SPE_EVLDH: return "evldh"; + case PPC_ID_SPE_EVLDHX: return "evldhx"; + case PPC_ID_SPE_EVLDW: return "evldw"; + case PPC_ID_SPE_EVLDWX: return "evldwx"; + case PPC_ID_SPE_EVLHHESPLAT: return "evlhhesplat"; + case PPC_ID_SPE_EVLHHESPLATX: return "evlhhesplatx"; + case PPC_ID_SPE_EVLHHOSSPLAT: return "evlhhossplat"; + case PPC_ID_SPE_EVLHHOSSPLATX: return "evlhhossplatx"; + case PPC_ID_SPE_EVLHHOUSPLAT: return "evlhhousplat"; + case PPC_ID_SPE_EVLHHOUSPLATX: return "evlhhousplatx"; + case PPC_ID_SPE_EVLWHE: return "evlwhe"; + case PPC_ID_SPE_EVLWHEX: return "evlwhex"; + case PPC_ID_SPE_EVLWHOS: return "evlwhos"; + case PPC_ID_SPE_EVLWHOSX: return "evlwhosx"; + case PPC_ID_SPE_EVLWHOU: return "evlwhou"; + case PPC_ID_SPE_EVLWHOUX: return "evlwhoux"; + case PPC_ID_SPE_EVLWHSPLAT: return "evlwhsplat"; + case PPC_ID_SPE_EVLWHSPLATX: return "evlwhsplatx"; + case PPC_ID_SPE_EVLWWSPLAT: return "evlwwsplat"; + case PPC_ID_SPE_EVLWWSPLATX: return "evlwwsplatx"; + case PPC_ID_SPE_EVMERGEHI: return "evmergehi"; + case PPC_ID_SPE_EVMERGEHILO: return "evmergehilo"; + case PPC_ID_SPE_EVMERGELO: return "evmergelo"; + case PPC_ID_SPE_EVMERGELOHI: return "evmergelohi"; + case PPC_ID_SPE_EVMHEGSMFAA: return "evmhegsmfaa"; + case PPC_ID_SPE_EVMHEGSMFAN: return "evmhegsmfan"; + case PPC_ID_SPE_EVMHEGSMIAA: return "evmhegsmiaa"; + case PPC_ID_SPE_EVMHEGSMIAN: return "evmhegsmian"; + case PPC_ID_SPE_EVMHEGUMIAA: return "evmhegumiaa"; + case PPC_ID_SPE_EVMHEGUMIAN: return "evmhegumian"; + case PPC_ID_SPE_EVMHESMF: return "evmhesmf"; + case PPC_ID_SPE_EVMHESMFA: return "evmhesmfa"; + case PPC_ID_SPE_EVMHESMFAAW: return "evmhesmfaaw"; + case PPC_ID_SPE_EVMHESMFANW: return "evmhesmfanw"; + case PPC_ID_SPE_EVMHESMI: return "evmhesmi"; + case PPC_ID_SPE_EVMHESMIA: return "evmhesmia"; + case PPC_ID_SPE_EVMHESMIAAW: return "evmhesmiaaw"; + case PPC_ID_SPE_EVMHESMIANW: return "evmhesmianw"; + case PPC_ID_SPE_EVMHESSF: return "evmhessf"; + case PPC_ID_SPE_EVMHESSFA: return "evmhessfa"; + case PPC_ID_SPE_EVMHESSFAAW: return "evmhessfaaw"; + case PPC_ID_SPE_EVMHESSFANW: return "evmhessfanw"; + case PPC_ID_SPE_EVMHESSIAAW: return "evmhessiaaw"; + case PPC_ID_SPE_EVMHESSIANW: return "evmhessianw"; + case PPC_ID_SPE_EVMHEUMI: return "evmheumi"; + case PPC_ID_SPE_EVMHEUMIA: return "evmheumia"; + case PPC_ID_SPE_EVMHEUMIAAW: return "evmheumiaaw"; + case PPC_ID_SPE_EVMHEUMIANW: return "evmheumianw"; + case PPC_ID_SPE_EVMHEUSIAAW: return "evmheusiaaw"; + case PPC_ID_SPE_EVMHEUSIANW: return "evmheusianw"; + case PPC_ID_SPE_EVMHOGSMFAA: return "evmhogsmfaa"; + case PPC_ID_SPE_EVMHOGSMFAN: return "evmhogsmfan"; + case PPC_ID_SPE_EVMHOGSMIAA: return "evmhogsmiaa"; + case PPC_ID_SPE_EVMHOGSMIAN: return "evmhogsmian"; + case PPC_ID_SPE_EVMHOGUMIAA: return "evmhogumiaa"; + case PPC_ID_SPE_EVMHOGUMIAN: return "evmhogumian"; + case PPC_ID_SPE_EVMHOSMF: return "evmhosmf"; + case PPC_ID_SPE_EVMHOSMFA: return "evmhosmfa"; + case PPC_ID_SPE_EVMHOSMFAAW: return "evmhosmfaaw"; + case PPC_ID_SPE_EVMHOSMFANW: return "evmhosmfanw"; + case PPC_ID_SPE_EVMHOSMI: return "evmhosmi"; + case PPC_ID_SPE_EVMHOSMIA: return "evmhosmia"; + case PPC_ID_SPE_EVMHOSMIAAW: return "evmhosmiaaw"; + case PPC_ID_SPE_EVMHOSMIANW: return "evmhosmianw"; + case PPC_ID_SPE_EVMHOSSF: return "evmhossf"; + case PPC_ID_SPE_EVMHOSSFA: return "evmhossfa"; + case PPC_ID_SPE_EVMHOSSFAAW: return "evmhossfaaw"; + case PPC_ID_SPE_EVMHOSSFANW: return "evmhossfanw"; + case PPC_ID_SPE_EVMHOSSIAAW: return "evmhossiaaw"; + case PPC_ID_SPE_EVMHOSSIANW: return "evmhossianw"; + case PPC_ID_SPE_EVMHOUMI: return "evmhoumi"; + case PPC_ID_SPE_EVMHOUMIA: return "evmhoumia"; + case PPC_ID_SPE_EVMHOUMIAAW: return "evmhoumiaaw"; + case PPC_ID_SPE_EVMHOUMIANW: return "evmhoumianw"; + case PPC_ID_SPE_EVMHOUSIAAW: return "evmhousiaaw"; + case PPC_ID_SPE_EVMHOUSIANW: return "evmhousianw"; + case PPC_ID_SPE_EVMR: return "evmr"; + case PPC_ID_SPE_EVMRA: return "evmra"; + case PPC_ID_SPE_EVMWHSMF: return "evmwhsmf"; + case PPC_ID_SPE_EVMWHSMFA: return "evmwhsmfa"; + case PPC_ID_SPE_EVMWHSMI: return "evmwhsmi"; + case PPC_ID_SPE_EVMWHSMIA: return "evmwhsmia"; + case PPC_ID_SPE_EVMWHSSF: return "evmwhssf"; + case PPC_ID_SPE_EVMWHSSFA: return "evmwhssfa"; + case PPC_ID_SPE_EVMWHUMI: return "evmwhumi"; + case PPC_ID_SPE_EVMWHUMIA: return "evmwhumia"; + case PPC_ID_SPE_EVMWHUSIAAW: return "evmwhusiaaw"; + case PPC_ID_SPE_EVMWHUSIANW: return "evmwhusianw"; + case PPC_ID_SPE_EVMWLSMIAAW: return "evmwlsmiaaw"; + case PPC_ID_SPE_EVMWLSMIANW: return "evmwlsmianw"; + case PPC_ID_SPE_EVMWLSSIANW: return "evmwlssianw"; + case PPC_ID_SPE_EVMWLSSIAAW: return "evmwlssiaaw"; + case PPC_ID_SPE_EVMWLUMI: return "evmwlumi"; + case PPC_ID_SPE_EVMWLUMIA: return "evmwlumia"; + case PPC_ID_SPE_EVMWLUMIAAW: return "evmwlumiaaw"; + case PPC_ID_SPE_EVMWLUMIANW: return "evmwlumianw"; + case PPC_ID_SPE_EVMWLUSIAAW: return "evmwlusiaaw"; + case PPC_ID_SPE_EVMWLUSIANW: return "evmwlusianw"; + case PPC_ID_SPE_EVMWSMF: return "evmwsmf"; + case PPC_ID_SPE_EVMWSMFA: return "evmwsmfa"; + case PPC_ID_SPE_EVMWSMFAA: return "evmwsmfaa"; + case PPC_ID_SPE_EVMWSMFAN: return "evmwsmfan"; + case PPC_ID_SPE_EVMWSMI: return "evmwsmi"; + case PPC_ID_SPE_EVMWSMIA: return "evmwsmia"; + case PPC_ID_SPE_EVMWSMIAA: return "evmwsmiaa"; + case PPC_ID_SPE_EVMWSMIAN: return "evmwsmian"; + case PPC_ID_SPE_EVMWSSF: return "evmwssf"; + case PPC_ID_SPE_EVMWSSFA: return "evmwssfa"; + case PPC_ID_SPE_EVMWSSFAA: return "evmwssfaa"; + case PPC_ID_SPE_EVMWSSFAN: return "evmwssfan"; + case PPC_ID_SPE_EVMWUMI: return "evmwumi"; + case PPC_ID_SPE_EVMWUMIA: return "evmwumia"; + case PPC_ID_SPE_EVMWUMIAA: return "evmwumiaa"; + case PPC_ID_SPE_EVMWUMIAN: return "evmwumian"; + case PPC_ID_SPE_EVNAND: return "evnand"; + case PPC_ID_SPE_EVNEG: return "evneg"; + case PPC_ID_SPE_EVNOR: return "evnor"; + case PPC_ID_SPE_EVNOT: return "evnot"; + case PPC_ID_SPE_EVOR: return "evor"; + case PPC_ID_SPE_EVORC: return "evorc"; + case PPC_ID_SPE_EVRLW: return "evrlw"; + case PPC_ID_SPE_EVRLWI: return "evrlwi"; + case PPC_ID_SPE_EVRNDW: return "evrndw"; + case PPC_ID_SPE_EVSEL: return "evsel"; + case PPC_ID_SPE_EVSLW: return "evslw"; + case PPC_ID_SPE_EVSLWI: return "evslwi"; + case PPC_ID_SPE_EVSPLATFI: return "evsplatfi"; + case PPC_ID_SPE_EVSPLATI: return "evsplati"; + case PPC_ID_SPE_EVSRWIS: return "evsrwis"; + case PPC_ID_SPE_EVSRWIU: return "evsrwiu"; + case PPC_ID_SPE_EVSRWS: return "evsrws"; + case PPC_ID_SPE_EVSRWU: return "evsrwu"; + case PPC_ID_SPE_EVSTDD: return "evstdd"; + case PPC_ID_SPE_EVSTDDX: return "evstddx"; + case PPC_ID_SPE_EVSTDH: return "evstdh"; + case PPC_ID_SPE_EVSTDHX: return "evstdhx"; + case PPC_ID_SPE_EVSTDW: return "evstdw"; + case PPC_ID_SPE_EVSTDWX: return "evstdwx"; + case PPC_ID_SPE_EVSTWHE: return "evstwhe"; + case PPC_ID_SPE_EVSTWHEX: return "evstwhex"; + case PPC_ID_SPE_EVSTWHO: return "evstwho"; + case PPC_ID_SPE_EVSTWHOX: return "evstwhox"; + case PPC_ID_SPE_EVSTWWE: return "evstwwe"; + case PPC_ID_SPE_EVSTWWEX: return "evstwwex"; + case PPC_ID_SPE_EVSTWWO: return "evstwwo"; + case PPC_ID_SPE_EVSTWWOX: return "evstwwox"; + case PPC_ID_SPE_EVSUBFSMIAAW: return "evsubfsmiaaw"; + case PPC_ID_SPE_EVSUBFSSIAAW: return "evsubfssiaaw"; + case PPC_ID_SPE_EVSUBFUMIAAW: return "evsubfumiaaw"; + case PPC_ID_SPE_EVSUBFUSIAAW: return "evsubfusiaaw"; + case PPC_ID_SPE_EVSUBFW: return "evsubfw"; + case PPC_ID_SPE_EVSUBIFW: return "evsubifw"; + case PPC_ID_SPE_EVXOR: return "evxor"; + + default: return NULL; + } +} diff --git a/arch/powerpc/decode/names.c b/arch/powerpc/decode/names.c new file mode 100644 index 000000000..e6acd702d --- /dev/null +++ b/arch/powerpc/decode/names.c @@ -0,0 +1,293 @@ +#include "decode.h" + +const char* PowerPCRegisterName(uint32_t regId) +{ + switch (regId) + { + case PPC_REG_GPR0: return "r0"; + case PPC_REG_GPR1: return "r1"; + case PPC_REG_GPR2: return "r2"; + case PPC_REG_GPR3: return "r3"; + case PPC_REG_GPR4: return "r4"; + case PPC_REG_GPR5: return "r5"; + case PPC_REG_GPR6: return "r6"; + case PPC_REG_GPR7: return "r7"; + case PPC_REG_GPR8: return "r8"; + case PPC_REG_GPR9: return "r9"; + case PPC_REG_GPR10: return "r10"; + case PPC_REG_GPR11: return "r11"; + case PPC_REG_GPR12: return "r12"; + case PPC_REG_GPR13: return "r13"; + case PPC_REG_GPR14: return "r14"; + case PPC_REG_GPR15: return "r15"; + case PPC_REG_GPR16: return "r16"; + case PPC_REG_GPR17: return "r17"; + case PPC_REG_GPR18: return "r18"; + case PPC_REG_GPR19: return "r19"; + case PPC_REG_GPR20: return "r20"; + case PPC_REG_GPR21: return "r21"; + case PPC_REG_GPR22: return "r22"; + case PPC_REG_GPR23: return "r23"; + case PPC_REG_GPR24: return "r24"; + case PPC_REG_GPR25: return "r25"; + case PPC_REG_GPR26: return "r26"; + case PPC_REG_GPR27: return "r27"; + case PPC_REG_GPR28: return "r28"; + case PPC_REG_GPR29: return "r29"; + case PPC_REG_GPR30: return "r30"; + case PPC_REG_GPR31: return "r31"; + + case PPC_REG_XER: return "xer"; + case PPC_REG_LR: return "lr"; + case PPC_REG_CTR: return "ctr"; + + case PPC_REG_FR0: return "f0"; + case PPC_REG_FR1: return "f1"; + case PPC_REG_FR2: return "f2"; + case PPC_REG_FR3: return "f3"; + case PPC_REG_FR4: return "f4"; + case PPC_REG_FR5: return "f5"; + case PPC_REG_FR6: return "f6"; + case PPC_REG_FR7: return "f7"; + case PPC_REG_FR8: return "f8"; + case PPC_REG_FR9: return "f9"; + case PPC_REG_FR10: return "f10"; + case PPC_REG_FR11: return "f11"; + case PPC_REG_FR12: return "f12"; + case PPC_REG_FR13: return "f13"; + case PPC_REG_FR14: return "f14"; + case PPC_REG_FR15: return "f15"; + case PPC_REG_FR16: return "f16"; + case PPC_REG_FR17: return "f17"; + case PPC_REG_FR18: return "f18"; + case PPC_REG_FR19: return "f19"; + case PPC_REG_FR20: return "f20"; + case PPC_REG_FR21: return "f21"; + case PPC_REG_FR22: return "f22"; + case PPC_REG_FR23: return "f23"; + case PPC_REG_FR24: return "f24"; + case PPC_REG_FR25: return "f25"; + case PPC_REG_FR26: return "f26"; + case PPC_REG_FR27: return "f27"; + case PPC_REG_FR28: return "f28"; + case PPC_REG_FR29: return "f29"; + case PPC_REG_FR30: return "f30"; + case PPC_REG_FR31: return "f31"; + + case PPC_REG_CRF0: return "cr0"; + case PPC_REG_CRF1: return "cr1"; + case PPC_REG_CRF2: return "cr2"; + case PPC_REG_CRF3: return "cr3"; + case PPC_REG_CRF4: return "cr4"; + case PPC_REG_CRF5: return "cr5"; + case PPC_REG_CRF6: return "cr6"; + case PPC_REG_CRF7: return "cr7"; + + case PPC_REG_AV_VR0: return "v0"; + case PPC_REG_AV_VR1: return "v1"; + case PPC_REG_AV_VR2: return "v2"; + case PPC_REG_AV_VR3: return "v3"; + case PPC_REG_AV_VR4: return "v4"; + case PPC_REG_AV_VR5: return "v5"; + case PPC_REG_AV_VR6: return "v6"; + case PPC_REG_AV_VR7: return "v7"; + case PPC_REG_AV_VR8: return "v8"; + case PPC_REG_AV_VR9: return "v9"; + case PPC_REG_AV_VR10: return "v10"; + case PPC_REG_AV_VR11: return "v11"; + case PPC_REG_AV_VR12: return "v12"; + case PPC_REG_AV_VR13: return "v13"; + case PPC_REG_AV_VR14: return "v14"; + case PPC_REG_AV_VR15: return "v15"; + case PPC_REG_AV_VR16: return "v16"; + case PPC_REG_AV_VR17: return "v17"; + case PPC_REG_AV_VR18: return "v18"; + case PPC_REG_AV_VR19: return "v19"; + case PPC_REG_AV_VR20: return "v20"; + case PPC_REG_AV_VR21: return "v21"; + case PPC_REG_AV_VR22: return "v22"; + case PPC_REG_AV_VR23: return "v23"; + case PPC_REG_AV_VR24: return "v24"; + case PPC_REG_AV_VR25: return "v25"; + case PPC_REG_AV_VR26: return "v26"; + case PPC_REG_AV_VR27: return "v27"; + case PPC_REG_AV_VR28: return "v28"; + case PPC_REG_AV_VR29: return "v29"; + case PPC_REG_AV_VR30: return "v30"; + case PPC_REG_AV_VR31: return "v31"; + + case PPC_REG_VSX_VR0: return "vs0"; + case PPC_REG_VSX_VR1: return "vs1"; + case PPC_REG_VSX_VR2: return "vs2"; + case PPC_REG_VSX_VR3: return "vs3"; + case PPC_REG_VSX_VR4: return "vs4"; + case PPC_REG_VSX_VR5: return "vs5"; + case PPC_REG_VSX_VR6: return "vs6"; + case PPC_REG_VSX_VR7: return "vs7"; + case PPC_REG_VSX_VR8: return "vs8"; + case PPC_REG_VSX_VR9: return "vs9"; + case PPC_REG_VSX_VR10: return "vs10"; + case PPC_REG_VSX_VR11: return "vs11"; + case PPC_REG_VSX_VR12: return "vs12"; + case PPC_REG_VSX_VR13: return "vs13"; + case PPC_REG_VSX_VR14: return "vs14"; + case PPC_REG_VSX_VR15: return "vs15"; + case PPC_REG_VSX_VR16: return "vs16"; + case PPC_REG_VSX_VR17: return "vs17"; + case PPC_REG_VSX_VR18: return "vs18"; + case PPC_REG_VSX_VR19: return "vs19"; + case PPC_REG_VSX_VR20: return "vs20"; + case PPC_REG_VSX_VR21: return "vs21"; + case PPC_REG_VSX_VR22: return "vs22"; + case PPC_REG_VSX_VR23: return "vs23"; + case PPC_REG_VSX_VR24: return "vs24"; + case PPC_REG_VSX_VR25: return "vs25"; + case PPC_REG_VSX_VR26: return "vs26"; + case PPC_REG_VSX_VR27: return "vs27"; + case PPC_REG_VSX_VR28: return "vs28"; + case PPC_REG_VSX_VR29: return "vs29"; + case PPC_REG_VSX_VR30: return "vs30"; + case PPC_REG_VSX_VR31: return "vs31"; + case PPC_REG_VSX_VR32: return "vs32"; + case PPC_REG_VSX_VR33: return "vs33"; + case PPC_REG_VSX_VR34: return "vs34"; + case PPC_REG_VSX_VR35: return "vs35"; + case PPC_REG_VSX_VR36: return "vs36"; + case PPC_REG_VSX_VR37: return "vs37"; + case PPC_REG_VSX_VR38: return "vs38"; + case PPC_REG_VSX_VR39: return "vs39"; + case PPC_REG_VSX_VR40: return "vs40"; + case PPC_REG_VSX_VR41: return "vs41"; + case PPC_REG_VSX_VR42: return "vs42"; + case PPC_REG_VSX_VR43: return "vs43"; + case PPC_REG_VSX_VR44: return "vs44"; + case PPC_REG_VSX_VR45: return "vs45"; + case PPC_REG_VSX_VR46: return "vs46"; + case PPC_REG_VSX_VR47: return "vs47"; + case PPC_REG_VSX_VR48: return "vs48"; + case PPC_REG_VSX_VR49: return "vs49"; + case PPC_REG_VSX_VR50: return "vs50"; + case PPC_REG_VSX_VR51: return "vs51"; + case PPC_REG_VSX_VR52: return "vs52"; + case PPC_REG_VSX_VR53: return "vs53"; + case PPC_REG_VSX_VR54: return "vs54"; + case PPC_REG_VSX_VR55: return "vs55"; + case PPC_REG_VSX_VR56: return "vs56"; + case PPC_REG_VSX_VR57: return "vs57"; + case PPC_REG_VSX_VR58: return "vs58"; + case PPC_REG_VSX_VR59: return "vs59"; + case PPC_REG_VSX_VR60: return "vs60"; + case PPC_REG_VSX_VR61: return "vs61"; + case PPC_REG_VSX_VR62: return "vs62"; + case PPC_REG_VSX_VR63: return "vs63"; + + case PPC_REG_GQR0: return "gqr0"; + case PPC_REG_GQR1: return "gqr1"; + case PPC_REG_GQR2: return "gqr2"; + case PPC_REG_GQR3: return "gqr3"; + case PPC_REG_GQR4: return "gqr4"; + case PPC_REG_GQR5: return "gqr5"; + case PPC_REG_GQR6: return "gqr6"; + case PPC_REG_GQR7: return "gqr7"; + + default: return NULL; + } +} + +const char* OperandClassName(uint32_t cls) +{ + switch (cls) + { + case PPC_OP_NONE: return ""; + case PPC_OP_UIMM: return "UIMM"; + case PPC_OP_SIMM: return "SIMM"; + case PPC_OP_LABEL: return "LABEL"; + case PPC_OP_MEM_RA: return "MEM(RA)"; + + case PPC_OP_REG_RA: return "RA"; + case PPC_OP_REG_RB: return "RB"; + case PPC_OP_REG_RC: return "RC"; + case PPC_OP_REG_RD: return "RD"; + case PPC_OP_REG_RS: return "RS"; + + case PPC_OP_REG_FRA: return "FRA"; + case PPC_OP_REG_FRB: return "FRB"; + case PPC_OP_REG_FRC: return "FRC"; + case PPC_OP_REG_FRD: return "FRD"; + case PPC_OP_REG_FRS: return "FRS"; + + case PPC_OP_REG_CRFD: return "CRFD"; + case PPC_OP_REG_CRFD_IMPLY0: return "CRFD"; + case PPC_OP_REG_CRFS: return "CRFS"; + case PPC_OP_CRBIT: return "CRBIT"; + case PPC_OP_CRBIT_A: return "CRBIT_A"; + case PPC_OP_CRBIT_B: return "CRBIT_B"; + case PPC_OP_CRBIT_D: return "CRBIT_C"; + + case PPC_OP_REG_AV_VA: return "ALTIVEC_VA"; + case PPC_OP_REG_AV_VB: return "ALTIVEC_VB"; + case PPC_OP_REG_AV_VC: return "ALTIVEC_VC"; + case PPC_OP_REG_AV_VD: return "ALTIVEC_VD"; + case PPC_OP_REG_AV_VS: return "ALTIVEC_VS"; + + case PPC_OP_REG_VSX_RA: return "VSX_RA"; + case PPC_OP_REG_VSX_RA_DWORD0: return "VSX_RA0"; + + case PPC_OP_REG_VSX_RB: return "VSX_RB"; + case PPC_OP_REG_VSX_RB_DWORD0: return "VSX_RB0"; + + case PPC_OP_REG_VSX_RC: return "VSX_RC"; + case PPC_OP_REG_VSX_RC_DWORD0: return "VSX_RC0"; + + case PPC_OP_REG_VSX_RD: return "VSX_RD"; + case PPC_OP_REG_VSX_RD_DWORD0: return "VSX_RD0"; + + case PPC_OP_REG_VSX_RS: return "VSX_RS"; + case PPC_OP_REG_VSX_RS_DWORD0: return "VSX_RS0"; + + default: + return "???"; + } +} + +// These match the names in the "Condition Register" section +const char* GetCRBitName(uint32_t crbit) +{ + switch (crbit) + { + case 0: return "lt"; + case 1: return "gt"; + case 2: return "eq"; + case 3: return "so"; + case 4: return "cr1lt"; + case 5: return "cr1gt"; + case 6: return "cr1eq"; + case 7: return "cr1so"; + case 8: return "cr2lt"; + case 9: return "cr2gt"; + case 10: return "cr2eq"; + case 11: return "cr2so"; + case 12: return "cr3lt"; + case 13: return "cr3gt"; + case 14: return "cr3eq"; + case 15: return "cr3so"; + case 16: return "cr4lt"; + case 17: return "cr4gt"; + case 18: return "cr4eq"; + case 19: return "cr4so"; + case 20: return "cr5lt"; + case 21: return "cr5gt"; + case 22: return "cr5eq"; + case 23: return "cr5so"; + case 24: return "cr6lt"; + case 25: return "cr6gt"; + case 26: return "cr6eq"; + case 27: return "cr6so"; + case 28: return "cr7lt"; + case 29: return "cr7gt"; + case 30: return "cr7eq"; + case 31: return "cr7so"; + default: + return NULL; + } +} diff --git a/arch/powerpc/decode/operands.c b/arch/powerpc/decode/operands.c new file mode 100644 index 000000000..48b695037 --- /dev/null +++ b/arch/powerpc/decode/operands.c @@ -0,0 +1,3081 @@ +#include + +#include "decode.h" +#include "priv.h" + +// see stanford bit twiddling hacks +static int32_t sign_extend(uint32_t x, unsigned numBits) +{ + int32_t const m = 1U << (numBits - 1); + + x = x & ((1U << numBits) - 1); + return (x ^ m) - m; +} + +static void CopyOperand(Operand* dst, const Operand* src) +{ + memcpy(dst, src, sizeof *dst); +} + +static Register Gpr(uint32_t value) +{ + return PPC_REG_GPR0 + value; +} + +static Register Fr(uint32_t value) +{ + return PPC_REG_FR0 + value; +} + +static Register Crf(uint32_t value) +{ + return PPC_REG_CRF0 + value; +} + +static Register AltivecVr(uint32_t value) +{ + return PPC_REG_AV_VR0 + value; +} + +static Register VsxVr(uint32_t value) +{ + return PPC_REG_VSX_VR0 + value; +} + +static Register VsxVrHi(uint32_t value) +{ + return PPC_REG_VSX_VR0 + value + 32; +} + +static void PushUIMMValue(Instruction* instruction, uint32_t uimm) +{ + instruction->operands[instruction->numOperands].cls = PPC_OP_UIMM; + instruction->operands[instruction->numOperands].uimm = uimm; + ++instruction->numOperands; +} + +static void PushSIMMValue(Instruction* instruction, int32_t simm) +{ + instruction->operands[instruction->numOperands].cls = PPC_OP_SIMM; + instruction->operands[instruction->numOperands].simm = simm; + ++instruction->numOperands; +} + +static void PushRegister(Instruction* instruction, OperandClass cls, Register reg) +{ + instruction->operands[instruction->numOperands].cls = cls; + instruction->operands[instruction->numOperands].reg = reg; + ++instruction->numOperands; +} + +static uint64_t ComputeBranchTarget(Instruction* instruction, uint64_t address, uint32_t word32) +{ + int32_t bd = (int32_t)((int16_t)(word32 & 0xfffc)); + + return instruction->flags.aa ? bd : address + bd; +} + +static void PushLabel(Instruction* instruction, uint64_t address) +{ + instruction->operands[instruction->numOperands].cls = PPC_OP_LABEL; + instruction->operands[instruction->numOperands].label = address; + ++instruction->numOperands; +} + +// this assumes that instruction->flags.aa has been properly set! +static void PushBranchTarget(Instruction* instruction, uint64_t address, uint32_t word32) +{ + PushLabel(instruction, ComputeBranchTarget(instruction, address, word32)); +} + +static void PushRA(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_RA, Gpr(GetA(word32))); +} + +static void PushRAor0(Instruction* instruction, uint32_t word32) +{ + uint32_t ra = GetA(word32); + + if (ra == 0) + PushUIMMValue(instruction, 0); + else + PushRegister(instruction, PPC_OP_REG_RA, Gpr(ra)); +} + +static void PushRB(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_RB, Gpr(GetB(word32))); +} + +static void PushRC(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_RC, Gpr(GetC(word32))); +} + +static void PushRD(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_RD, Gpr(GetD(word32))); +} + +static void PushRS(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_RS, Gpr(GetS(word32))); +} + +static void PushFRA(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_FRA, Fr(GetA(word32))); +} + +static void PushFRB(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_FRB, Fr(GetB(word32))); +} + +static void PushFRC(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_FRC, Fr(GetC(word32))); +} + +static void PushFRD(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_FRD, Fr(GetD(word32))); +} + +static void PushFRS(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_FRS, Fr(GetS(word32))); +} + +static void PushCRFD(Instruction* instruction, uint32_t word32) +{ + uint32_t crfd = (word32 >> 23) & 0x7; + PushRegister(instruction, PPC_OP_REG_CRFD, Crf(crfd)); +} + +static void PushCRFDImplyCR0(Instruction* instruction, uint32_t word32) +{ + uint32_t crfd = (word32 >> 23) & 0x7; + + PushRegister(instruction, PPC_OP_REG_CRFD_IMPLY0, Crf(crfd)); +} + +static void PushCRFS(Instruction* instruction, uint32_t word32) +{ + uint32_t crfs = (word32 >> 18) & 0x7; + PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crfs)); +} + +static void PushCRBitA(Instruction* instruction, uint32_t word32) +{ + instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_A; + instruction->operands[instruction->numOperands].crbit = GetA(word32); + ++instruction->numOperands; +} + +static void PushCRBitB(Instruction* instruction, uint32_t word32) +{ + instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_B; + instruction->operands[instruction->numOperands].crbit = GetB(word32); + ++instruction->numOperands; +} + +static void PushCRBitD(Instruction* instruction, uint32_t word32) +{ + instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_D; + instruction->operands[instruction->numOperands].crbit = GetD(word32); + ++instruction->numOperands; +} + +static void PushMem(Instruction* instruction, OperandClass cls, Register reg, int32_t offset) +{ + instruction->operands[instruction->numOperands].cls = cls; + instruction->operands[instruction->numOperands].mem.reg = reg; + instruction->operands[instruction->numOperands].mem.offset = offset; + ++instruction->numOperands; +} + +static void FillBranchLikelyHint(Instruction* instruction, uint32_t word32) +{ + uint32_t bo = GetBO(word32); + + switch (bo >> 2) + { + // 001at + // 011at + case 1: + case 3: + instruction->flags.branchLikelyHint = bo & 0x3; + break; + + // 1a00t + // 1a01t + case 4: + case 6: + instruction->flags.branchLikelyHint = ((bo >> 2) & 0x2) | (bo & 0x1); + break; + + // all others don't have hints + default: + instruction->flags.branchLikelyHint = 0; + } +} + +static void PushMemRA(Instruction* instruction, uint32_t word32) +{ + int32_t offset = (int32_t)((int16_t)(word32 & 0xffff)); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), offset); +} + +static void PushVsxA(Instruction* instruction, uint32_t word32, VsxWidth width) +{ + PushRegister(instruction, + width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RA : PPC_OP_REG_VSX_RA_DWORD0, + VsxVr(GetVsxA(word32))); +} + +static void PushVsxHiA(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_VSX_RA, VsxVrHi(GetA(word32))); +} + +static void PushVsxB(Instruction* instruction, uint32_t word32, VsxWidth width) +{ + PushRegister(instruction, + width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RB : PPC_OP_REG_VSX_RB_DWORD0, + VsxVr(GetVsxB(word32))); +} + +static void PushVsxHiB(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_VSX_RB, VsxVrHi(GetB(word32))); +} + +static void PushVsxC(Instruction* instruction, uint32_t word32, VsxWidth width) +{ + PushRegister(instruction, + width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RC : PPC_OP_REG_VSX_RC_DWORD0, + VsxVr(GetVsxC(word32))); +} + +static void PushVsxD(Instruction* instruction, uint32_t word32, VsxWidth width) +{ + PushRegister(instruction, + width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RD : PPC_OP_REG_VSX_RD_DWORD0, + VsxVr(GetVsxD(word32))); +} + +static void PushVsxHiD(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_VSX_RD, VsxVrHi(GetD(word32))); +} + +static void PushVsxS(Instruction* instruction, uint32_t word32, VsxWidth width) +{ + uint32_t sx = word32 & 0x1; + uint32_t s = (word32 >> 21) & 0x1f; + PushRegister(instruction, + width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RS : PPC_OP_REG_VSX_RS_DWORD0, + VsxVr((sx << 5) | s)); +} + +static void PushAltivecVA(Instruction* instruction, uint32_t word32) +{ + uint32_t va = (word32 >> 16) & 0x1f; + PushRegister(instruction, PPC_OP_REG_AV_VA, AltivecVr(va)); +} + +static void PushAltivecVB(Instruction* instruction, uint32_t word32) +{ + uint32_t vb = (word32 >> 11) & 0x1f; + PushRegister(instruction, PPC_OP_REG_AV_VB, AltivecVr(vb)); +} + +static void PushAltivecVC(Instruction* instruction, uint32_t word32) +{ + uint32_t vc = (word32 >> 6) & 0x1f; + PushRegister(instruction, PPC_OP_REG_AV_VC, AltivecVr(vc)); +} + +static void PushAltivecVD(Instruction* instruction, uint32_t word32) +{ + uint32_t vd = (word32 >> 21) & 0x1f; + PushRegister(instruction, PPC_OP_REG_AV_VD, AltivecVr(vd)); +} + +static void PushAltivecVS(Instruction* instruction, uint32_t word32) +{ + uint32_t vs = (word32 >> 21) & 0x1f; + PushRegister(instruction, PPC_OP_REG_AV_VS, AltivecVr(vs)); +} + +void FillOperands(Instruction* instruction, uint32_t word32, uint64_t address) +{ + switch (instruction->id) + { + // instructions with no operands + case PPC_ID_ATTN: + case PPC_ID_CP_ABORT: + case PPC_ID_DCCCI: + case PPC_ID_ICCCI: + case PPC_ID_ISYNC: + case PPC_ID_LWSYNC: + case PPC_ID_MSGSYNC: + case PPC_ID_NOP: + case PPC_ID_PTESYNC: + case PPC_ID_RFCI: + case PPC_ID_RFDI: + case PPC_ID_RFI: + case PPC_ID_RFID: + case PPC_ID_RFMCI: + case PPC_ID_SYNC: + case PPC_ID_TLBIA: + case PPC_ID_TLBSYNC: + case PPC_ID_TRAP: + case PPC_ID_TRECHKPT: + case PPC_ID_SLBIA: + case PPC_ID_SLBSYNC: + case PPC_ID_XNOP: + case PPC_ID_WAITIMPL: + case PPC_ID_WAITRSV: + case PPC_ID_AV_DSSALL: + break; + + // rD + case PPC_ID_LNIA: + case PPC_ID_MFBR0: + case PPC_ID_MFBR1: + case PPC_ID_MFBR2: + case PPC_ID_MFBR3: + case PPC_ID_MFBR4: + case PPC_ID_MFBR5: + case PPC_ID_MFBR6: + case PPC_ID_MFBR7: + case PPC_ID_MFCR: + case PPC_ID_MFCTR: + case PPC_ID_MFLR: + case PPC_ID_MFMSR: + case PPC_ID_MFTBU: + case PPC_ID_MFXER: + PushRD(instruction, word32); + break; + + // rS + case PPC_ID_MTBR0: + case PPC_ID_MTBR1: + case PPC_ID_MTBR2: + case PPC_ID_MTBR3: + case PPC_ID_MTBR4: + case PPC_ID_MTBR5: + case PPC_ID_MTBR6: + case PPC_ID_MTBR7: + case PPC_ID_MTCTR: + case PPC_ID_MTLR: + case PPC_ID_MTMSR: + case PPC_ID_MTMSRD: + case PPC_ID_MTXER: + case PPC_ID_WRTEE: + PushRS(instruction, word32); + break; + + // rA + case PPC_ID_TABORT: + case PPC_ID_TRECLAIM: + PushRA(instruction, word32); + break; + + // rB + case PPC_ID_TLBIEL: + case PPC_ID_TLBLI: + case PPC_ID_SLBIE: + PushRB(instruction, word32); + break; + + // [.] rD, rA (arithmetic) + case PPC_ID_NEGx: + case PPC_ID_SUBFZEx: + case PPC_ID_ADDZEx: + case PPC_ID_SUBFMEx: + case PPC_ID_ADDMEx: + PushRD(instruction, word32); + PushRA(instruction, word32); + + // some of these instructions don't have an "oe" flag, + // but we rely on the fact that those instructions have + // bitmask 0x400 clear in the switch statement on the + instruction->flags.rc = word32 & 0x1; + instruction->flags.oe = (word32 & 0x400) != 0; + break; + + // [.] rD, rA, rB (arithmetic) + case PPC_ID_ADDx: + case PPC_ID_ADDCx: + case PPC_ID_ADDEx: + case PPC_ID_DIVDx: + case PPC_ID_DIVDEx: + case PPC_ID_DIVDEUx: + case PPC_ID_DIVDUx: + case PPC_ID_DIVWx: + case PPC_ID_DIVWEx: + case PPC_ID_DIVWEUx: + case PPC_ID_DIVWUx: + case PPC_ID_MODSD: + case PPC_ID_MODSW: + case PPC_ID_MODUD: + case PPC_ID_MODUW: + case PPC_ID_MULHDx: + case PPC_ID_MULHDUx: + case PPC_ID_MULHWx: + case PPC_ID_MULHWUx: + case PPC_ID_MULLDx: + case PPC_ID_MULLWx: + case PPC_ID_SUBFx: + case PPC_ID_SUBFCx: + case PPC_ID_SUBFEx: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + + // some of these instructions don't have an "oe" flag, + // but we rely on the fact that those instructions have + // bitmask 0x400 clear in the switch statement on the + // 0x7ff mask + instruction->flags.rc = word32 & 0x1; + instruction->flags.oe = (word32 & 0x400) != 0; + break; + + + // [.] rA, rS (logical) + case PPC_ID_CNTLZWx: + case PPC_ID_CNTLZDx: + case PPC_ID_CNTTZWx: + case PPC_ID_CNTTZDx: + case PPC_ID_POPCNTB: + case PPC_ID_POPCNTD: + case PPC_ID_POPCNTW: + case PPC_ID_EXTSHx: + case PPC_ID_EXTSBx: + case PPC_ID_EXTSWx: + PushRA(instruction, word32); + PushRS(instruction, word32); + + // not all of these have RC bits, but it gets filtered + // at subop decode step + instruction->flags.rc = word32 & 0x1; + break; + + // [.] rA, rS, rB + case PPC_ID_ANDx: + case PPC_ID_ANDCx: + case PPC_ID_BPERMD: + case PPC_ID_CMPB: + case PPC_ID_ECIWX: + case PPC_ID_ECOWX: + case PPC_ID_EQVx: + case PPC_ID_NANDx: + case PPC_ID_NORx: + case PPC_ID_ORx: + case PPC_ID_ORCx: + case PPC_ID_ROTLWx: + case PPC_ID_ROTLDx: + case PPC_ID_SLDx: + case PPC_ID_SLWx: + case PPC_ID_SRADx: + case PPC_ID_SRAWx: + case PPC_ID_SRDx: + case PPC_ID_SRWx: + case PPC_ID_XORx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushRB(instruction, word32); + + // not all of these have an rc bit, but they just don't + // get recognized at the switch statement with &0x7ff + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_ROTLWIx: + case PPC_ID_SLWIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_CLRLWIx: + case PPC_ID_SRWIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetMB(word32)); + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_CLRRWIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + + // me = 31 - n --> n = 31 - me + PushUIMMValue(instruction, 31 - GetME(word32)); + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_RLDCLx: + case PPC_ID_RLDCRx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushRB(instruction, word32); + PushUIMMValue(instruction, GetMX64(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_RLDICx: + case PPC_ID_RLDICLx: + case PPC_ID_RLDICRx: + case PPC_ID_RLDIMIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH64(word32)); + PushUIMMValue(instruction, GetMX64(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_CLRLDIx: + case PPC_ID_SRDIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetMX64(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_ROTLDIx: + case PPC_ID_SLDIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH64(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_BCx: + { + uint32_t bo = GetBO(word32); + uint32_t bi = GetBI(word32); + + instruction->flags.lk = word32 & 0x1; + instruction->flags.aa = (word32 & 0x2) != 0; + + // not all BCx have hints, but if they don't, then those + // hints won't be read by anything anyways + FillBranchLikelyHint(instruction, word32); + + PushUIMMValue(instruction, bo); + PushUIMMValue(instruction, bi); + PushBranchTarget(instruction, address, word32); + + break; + } + + // crfD, rA, rB + case PPC_ID_CMPD: + case PPC_ID_CMPEQB: + case PPC_ID_CMPW: + case PPC_ID_CMPLD: + case PPC_ID_CMPLW: + PushCRFDImplyCR0(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // crfD, rA, SIMM + case PPC_ID_CMPDI: + case PPC_ID_CMPWI: + { + int32_t simm = (int32_t)((int16_t)(word32 & 0xffff)); + + PushCRFDImplyCR0(instruction, word32); + PushRA(instruction, word32); + PushSIMMValue(instruction, simm); + break; + } + + // crfD, rA, UIMM + case PPC_ID_CMPLDI: + case PPC_ID_CMPLWI: + { + uint32_t uimm = word32 & 0xffff; + + PushCRFDImplyCR0(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, uimm); + break; + } + + // rA, rB + case PPC_ID_COPY: + case PPC_ID_PASTE: + case PPC_ID_TDEQ: + case PPC_ID_TDGT: + case PPC_ID_TDLGT: + case PPC_ID_TDLLT: + case PPC_ID_TDLT: + case PPC_ID_TDNE: + case PPC_ID_TDU: + case PPC_ID_TLBSX: + case PPC_ID_TWEQ: + case PPC_ID_TWGT: + case PPC_ID_TWLGT: + case PPC_ID_TWLLT: + case PPC_ID_TWLT: + case PPC_ID_TWNE: + case PPC_ID_TWU: + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // TO, rA, rB + case PPC_ID_TD: + case PPC_ID_TW: + case PPC_ID_TABORTDC: + case PPC_ID_TABORTWC: + { + uint32_t to = (word32 >> 21) & 0x1f; + + PushUIMMValue(instruction, to); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + } + + // rA, SIMM + case PPC_ID_TDEQI: + case PPC_ID_TDGTI: + case PPC_ID_TDLGTI: + case PPC_ID_TDLLTI: + case PPC_ID_TDLTI: + case PPC_ID_TDNEI: + case PPC_ID_TDUI: + case PPC_ID_TWEQI: + case PPC_ID_TWGTI: + case PPC_ID_TWLGTI: + case PPC_ID_TWLLTI: + case PPC_ID_TWLTI: + case PPC_ID_TWNEI: + case PPC_ID_TWUI: + { + int32_t simm = (int32_t)((int16_t)(word32 & 0xffff)); + + PushRA(instruction, word32); + PushSIMMValue(instruction, simm); + break; + } + + // TO, rA, SIMM + case PPC_ID_TDI: + case PPC_ID_TWI: + { + uint32_t to = (word32 >> 21) & 0x1f; + int32_t simm = (int32_t)((int16_t)(word32 & 0xffff)); + + PushUIMMValue(instruction, to); + PushRA(instruction, word32); + PushSIMMValue(instruction, simm); + break; + } + + // TO, rA, SIMM + case PPC_ID_TABORTDCI: + case PPC_ID_TABORTWCI: + { + uint32_t to = (word32 >> 21) & 0x1f; + int32_t simm = sign_extend((word32 >> 11) & 0x1f, 5); + + PushUIMMValue(instruction, to); + PushRA(instruction, word32); + PushSIMMValue(instruction, simm); + break; + } + + // rD, rA, SIMM + case PPC_ID_ADDI: + case PPC_ID_MULLI: + case PPC_ID_SUBFIC: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); + break; + + // rA, rS, UIMM + case PPC_ID_ORI: + case PPC_ID_XORI: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, word32 & 0xffff); + break; + + // differentiated in case it makes sense to use the shifted value as an operand + // (which we do for now since it matches capstone) + // rA, rS, UIMM + case PPC_ID_ORIS: + case PPC_ID_XORIS: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, word32 & 0xffff); + break; + + // rD, d(rA) + case PPC_ID_LBZ: + case PPC_ID_LBZU: + case PPC_ID_LHA: + case PPC_ID_LHAU: + case PPC_ID_LHZ: + case PPC_ID_LHZU: + case PPC_ID_LMW: + case PPC_ID_LWZ: + case PPC_ID_LWZU: + PushRD(instruction, word32); + PushMemRA(instruction, word32); + break; + + // rD, d(rA) (64-bit) + case PPC_ID_LD: + case PPC_ID_LDU: + case PPC_ID_LWA: + { + PushRD(instruction, word32); + + int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); + break; + } + + // rD, rA, rB (indexed load) + case PPC_ID_LBEPX: + case PPC_ID_LBZCIX: + case PPC_ID_LBZUX: + case PPC_ID_LBZX: + case PPC_ID_LDBRX: + case PPC_ID_LDCIX: + case PPC_ID_LDUX: + case PPC_ID_LDX: + case PPC_ID_LHAUX: + case PPC_ID_LHAX: + case PPC_ID_LHBRX: + case PPC_ID_LHEPX: + case PPC_ID_LHZCIX: + case PPC_ID_LHZX: + case PPC_ID_LHZUX: + case PPC_ID_LSWX: + case PPC_ID_LWAX: + case PPC_ID_LWAUX: + case PPC_ID_LWBRX: + case PPC_ID_LWEPX: + case PPC_ID_LWZCIX: + case PPC_ID_LWZUX: + case PPC_ID_LWZX: + PushRD(instruction, word32); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // rD, rA, rB, [EH if nonzero] (indexed load) + case PPC_ID_LBARX: + case PPC_ID_LDARX: + case PPC_ID_LHARX: + case PPC_ID_LWARX: + { + PushRD(instruction, word32); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + uint32_t eh = word32 & 0x1; + // NOTE: this breaks with convention by only + // conditionally including EH + if (eh) + PushUIMMValue(instruction, word32 & 0x1); + break; + } + + // rD, rA, FC + case PPC_ID_LDAT: + case PPC_ID_LWAT: + { + uint32_t fc = (word32 >> 11) & 0x1f; + PushRD(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, fc); + break; + } + + // rS, rA, FC + case PPC_ID_STDAT: + case PPC_ID_STWAT: + { + uint32_t fc = (word32 >> 11) & 0x1f; + PushRS(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, fc); + break; + } + + + // rS, d(RA) + case PPC_ID_STB: + case PPC_ID_STBU: + case PPC_ID_STH: + case PPC_ID_STHU: + case PPC_ID_STMW: + case PPC_ID_STW: + case PPC_ID_STWU: + PushRS(instruction, word32); + PushMemRA(instruction, word32); + break; + + // rS, d(RA) (64-bit) + case PPC_ID_STD: + case PPC_ID_STDU: + { + PushRS(instruction, word32); + + int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); + break; + } + + // rS, rA, rB (indexed store) + case PPC_ID_STBCX: + case PPC_ID_STBCIX: + case PPC_ID_STBEPX: + case PPC_ID_STBUX: + case PPC_ID_STBX: + case PPC_ID_STDBRX: + case PPC_ID_STDCIX: + case PPC_ID_STDEPX: + case PPC_ID_STDUX: + case PPC_ID_STDX: + case PPC_ID_STHBRX: + case PPC_ID_STHCIX: + case PPC_ID_STHCX: + case PPC_ID_STHEPX: + case PPC_ID_STHUX: + case PPC_ID_STHX: + case PPC_ID_STSWX: + case PPC_ID_STWBRX: + case PPC_ID_STWCIX: + case PPC_ID_STWEPX: + case PPC_ID_STWUX: + case PPC_ID_STWX: + PushRS(instruction, word32); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // . rS, rA, rB (indexed store with reserve) + case PPC_ID_STDCX: + case PPC_ID_STWCX: + PushRS(instruction, word32); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + instruction->flags.rc = 1; + break; + + // frD, d(rA) + case PPC_ID_LFD: + case PPC_ID_LFDU: + case PPC_ID_LFS: + case PPC_ID_LFSU: + PushFRD(instruction, word32); + PushMemRA(instruction, word32); + break; + + // frD, rA, rB + case PPC_ID_LFDEPX: + case PPC_ID_LFDUX: + case PPC_ID_LFDX: + case PPC_ID_LFIWAX: + case PPC_ID_LFIWZX: + case PPC_ID_LFSUX: + case PPC_ID_LFSX: + PushFRD(instruction, word32); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // frS, d(rA) + case PPC_ID_STFD: + case PPC_ID_STFDU: + case PPC_ID_STFS: + case PPC_ID_STFSU: + PushFRS(instruction, word32); + PushMemRA(instruction, word32); + break; + + // frS, rA, rB + case PPC_ID_STFDEPX: + case PPC_ID_STFDUX: + case PPC_ID_STFDX: + case PPC_ID_STFIWX: + case PPC_ID_STFSUX: + case PPC_ID_STFSX: + PushFRS(instruction, word32); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // crfD, crfS + case PPC_ID_MCRF: + case PPC_ID_MCRFS: + PushCRFD(instruction, word32); + PushCRFS(instruction, word32); + break; + + // crbD, crbA + case PPC_ID_CRMOVE: + case PPC_ID_CRNOT: + PushCRBitD(instruction, word32); + PushCRBitA(instruction, word32); + break; + + // crbD, crbA, crbB + case PPC_ID_CRAND: + case PPC_ID_CRANDC: + case PPC_ID_CREQV: + case PPC_ID_CRNAND: + case PPC_ID_CRNOR: + case PPC_ID_CROR: + case PPC_ID_CRORC: + case PPC_ID_CRXOR: + PushCRBitD(instruction, word32); + PushCRBitA(instruction, word32); + PushCRBitB(instruction, word32); + break; + + // crbD + case PPC_ID_CRCLR: + case PPC_ID_CRSET: + PushCRBitD(instruction, word32); + break; + + // crfS + case PPC_ID_MCRXRX: + case PPC_ID_TCHECK: + PushCRFD(instruction, word32); + break; + + // conditional branches to registers + case PPC_ID_BCLRx: + case PPC_ID_BCCTRx: + // not all BCx have hints, but if they don't, then those + // hints won't be read by anything anyways + FillBranchLikelyHint(instruction, word32); + + PushUIMMValue(instruction, GetBO(word32)); + PushUIMMValue(instruction, GetBI(word32)); + + instruction->flags.lk = word32 & 0x1; + break; + + // frD, frA, frB + case PPC_ID_FADDx: + case PPC_ID_FADDSx: + case PPC_ID_FCPSGNx: + case PPC_ID_FDIVx: + case PPC_ID_FDIVSx: + case PPC_ID_FSUBx: + case PPC_ID_FSUBSx: + PushFRD(instruction, word32); + PushFRA(instruction, word32); + PushFRB(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + // [.] frD, frA, frC + case PPC_ID_FMULx: + case PPC_ID_FMULSx: + PushFRD(instruction, word32); + PushFRA(instruction, word32); + PushFRC(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + // [.] frD, frA, frC, frB + case PPC_ID_FMADDx: + case PPC_ID_FMADDSx: + case PPC_ID_FMSUBx: + case PPC_ID_FMSUBSx: + case PPC_ID_FNMADDx: + case PPC_ID_FNMADDSx: + case PPC_ID_FNMSUBx: + case PPC_ID_FNMSUBSx: + case PPC_ID_FSELx: + PushFRD(instruction, word32); + PushFRA(instruction, word32); + PushFRC(instruction, word32); + PushFRB(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + // [.] frD, frB + case PPC_ID_FABSx: + case PPC_ID_FCFIDx: + case PPC_ID_FCFIDSx: + case PPC_ID_FCFIDUx: + case PPC_ID_FCFIDUSx: + case PPC_ID_FCTIDx: + case PPC_ID_FCTIDUx: + case PPC_ID_FCTIDUZx: + case PPC_ID_FCTIDZx: + case PPC_ID_FCTIWx: + case PPC_ID_FCTIWUx: + case PPC_ID_FCTIWUZx: + case PPC_ID_FCTIWZx: + case PPC_ID_FMRx: + case PPC_ID_FNABSx: + case PPC_ID_FNEGx: + case PPC_ID_FREx: + case PPC_ID_FRESx: + case PPC_ID_FRIMx: + case PPC_ID_FRINx: + case PPC_ID_FRIPx: + case PPC_ID_FRIZx: + case PPC_ID_FRSPx: + case PPC_ID_FRSQRTEx: + case PPC_ID_FRSQRTESx: + case PPC_ID_FSQRTx: + case PPC_ID_FSQRTSx: + PushFRD(instruction, word32); + PushFRB(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + + case PPC_ID_FCMPO: + case PPC_ID_FCMPU: + PushCRFD(instruction, word32); + PushFRA(instruction, word32); + PushFRB(instruction, word32); + break; + + // rD, UIMM (special register) + case PPC_ID_MFDCR: + case PPC_ID_MFPMR: + case PPC_ID_MFSPR: + case PPC_ID_MFTB: + { + uint32_t special = GetSpecialRegisterCommon(word32); + + PushRD(instruction, word32); + PushUIMMValue(instruction, special); + break; + } + + // UIMM, rS (special register) + case PPC_ID_MTDCR: + case PPC_ID_MTPMR: + case PPC_ID_MTSPR: + { + uint32_t special = GetSpecialRegisterCommon(word32); + + PushUIMMValue(instruction, special); + PushRS(instruction, word32); + break; + } + + // rA, rB (cache-related) + case PPC_ID_DCBA: + case PPC_ID_DCBST: + case PPC_ID_DCBSTEP: + case PPC_ID_DCBFL: + case PPC_ID_DCBFLP: + case PPC_ID_DCBI: + case PPC_ID_DCBTSTT: + case PPC_ID_DCBTT: + case PPC_ID_DCBZ: + case PPC_ID_DCBZEP: + case PPC_ID_DCBZL: + case PPC_ID_ICBI: + case PPC_ID_ICBIEP: + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // CT (cache-related) + case PPC_ID_DCI: + case PPC_ID_ICI: + { + uint32_t ct = (word32 >> 21) & 0xf; + + PushUIMMValue(instruction, ct); + break; + } + + // CT, rA, rB (cache-related) + case PPC_ID_ICBLC: + case PPC_ID_ICBLQ: + case PPC_ID_ICBTLS: + uint32_t ct = (word32 >> 21) & 0xf; + + PushUIMMValue(instruction, ct); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // TH, rA, rB (cache-related) + case PPC_ID_DCBTEP: + case PPC_ID_DCBTSTEP: + { + uint32_t th = (word32 >> 21) & 0x1f; + PushUIMMValue(instruction, th); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + } + + // rA, rB, TH + case PPC_ID_DCBT: + { + PushRAor0(instruction, word32); + PushRB(instruction, word32); + uint32_t th = (word32 >> 21) & 0x1f; + if (th != 0) + PushUIMMValue(instruction, th); + break; + } + + case PPC_ID_DCBTST: + { + PushRAor0(instruction, word32); + PushRB(instruction, word32); + uint32_t th = (word32 >> 21) & 0x1f; + if (th != 0) + PushUIMMValue(instruction, th); + break; + } + + case PPC_ID_MTFSB0x: + case PPC_ID_MTFSB1x: + { + uint32_t bt = (word32 >> 21) & 0x1f; + + PushUIMMValue(instruction, bt); + instruction->flags.rc = word32 & 0x1; + break; + } + + case PPC_ID_TLBREHI: + case PPC_ID_TLBRELO: + // TODO: this is how capstone disassembles these + // instructions, but some architectures have no + // operands and this is just "tlbre" + PushRD(instruction, word32); + PushRA(instruction, word32); + + break; + + case PPC_ID_TLBWEHI: + case PPC_ID_TLBWELO: + // TODO: this is how capstone disassembles these + // instructions, but some architectures have no + // operands and this is just "tlbwe" + PushRS(instruction, word32); + PushRA(instruction, word32); + + break; + + // one-off instructions + case PPC_ID_ADDICx: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); + + instruction->flags.rc = (word32 >> 26) == 0x0d; + break; + + case PPC_ID_ADDIS: + // different from other shifted immediates because signed imm + PushRD(instruction, word32); + PushRA(instruction, word32); + PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); + break; + + case PPC_ID_ADDPCIS: + { + PushRD(instruction, word32); + uint64_t d1 = (word32 >> 16) & 0x1f; + uint64_t d0 = (word32 >> 6) & 0x3ff; + uint64_t d2 = word32 & 0x1; + uint64_t d = (d0 << 6) | (d1 << 1) | d2; + PushUIMMValue(instruction, d); + break; + } + + case PPC_ID_ANDI: + // different from other logical immediates because of rc bit + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, word32 & 0xffff); + instruction->flags.rc = 1; + break; + + case PPC_ID_ANDIS: + // different from other logical shifted immediates because of rc bit + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, word32 & 0xffff); + + instruction->flags.rc = 1; + break; + + case PPC_ID_Bx: + { + instruction->flags.lk = word32 & 0x1; + instruction->flags.aa = (word32 & 0x2) != 0; + + uint64_t li = word32 & 0x03fffffc; + li = (uint64_t)(int64_t)sign_extend(li, 26); + uint64_t target = instruction->flags.aa ? li : address + li; + + PushLabel(instruction, target); + + break; + } + + case PPC_ID_CMPRB: + { + PushCRFD(instruction, word32); + + uint32_t l = (word32 >> 21) & 0x1; + PushUIMMValue(instruction, l); + + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + } + + case PPC_ID_DARN: + { + uint32_t l = (word32 >> 16) & 0x3; + PushRD(instruction, word32); + PushUIMMValue(instruction, l); + break; + } + + case PPC_ID_DCBF: + case PPC_ID_DCBFEP: + { + uint32_t l = (word32 >> 21) & 0x3; + PushRAor0(instruction, word32); + PushRB(instruction, word32); + if (l != 0) + PushUIMMValue(instruction, l); + + break; + } + + case PPC_ID_EXTSWSLIx: + { + PushRA(instruction, word32); + PushRS(instruction, word32); + uint32_t sh5 = (word32 >> 1) & 0x1; + uint32_t sh0_4 = (word32 >> 11) & 0x1f; + PushUIMMValue(instruction, (sh5 << 5) | sh0_4); + + instruction->flags.rc = word32 & 0x1; + break; + } + + case PPC_ID_FTDIV: + PushCRFD(instruction, word32); + PushFRA(instruction, word32); + PushFRB(instruction, word32); + break; + + case PPC_ID_FTSQRT: + PushCRFD(instruction, word32); + PushFRB(instruction, word32); + break; + + case PPC_ID_MFBHRBE: + { + uint32_t bhrbe = (word32 >> 11) & 0x3ff; + PushRD(instruction, word32); + PushUIMMValue(instruction, bhrbe); + break; + } + + case PPC_ID_MFOCRF: + { + uint32_t fxm = (word32 >> 12) & 0xff; + + PushRD(instruction, word32); + PushUIMMValue(instruction, fxm); + break; + } + + + case PPC_ID_ICBT: + { + uint32_t ct = (word32 >> 21) & 0xf; + + PushUIMMValue(instruction, ct); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + + break; + } + + case PPC_ID_ISEL: + { + uint32_t bc = (word32 >> 6) & 0x1f; + + PushRD(instruction, word32); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + PushUIMMValue(instruction, bc); + break; + } + + case PPC_ID_LI: + PushRD(instruction, word32); + PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff))); + break; + + case PPC_ID_LIS: + { + PushRD(instruction, word32); + PushSIMMValue(instruction, (int32_t)(word32 & 0xffff)); + break; + } + + case PPC_ID_LSWI: + { + uint32_t nb = (word32 >> 11) & 0x1f; + + PushRD(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, nb); + break; + } + + case PPC_ID_MBAR: + { + uint32_t mo = (word32 >> 21) & 0x1f; + PushUIMMValue(instruction, mo); + break; + } + + case PPC_ID_MFFSx: + case PPC_ID_MFFSCE: + case PPC_ID_MFFSL: + PushFRD(instruction, word32); + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_MFFSCDRN: + case PPC_ID_MFFSCRN: + PushFRD(instruction, word32); + PushFRB(instruction, word32); + break; + + case PPC_ID_MFFSCDRNI: + { + uint32_t drm = (word32 >> 11) & 0x7; + PushFRD(instruction, word32); + PushUIMMValue(instruction, drm); + break; + } + + case PPC_ID_MFFSCRNI: + { + uint32_t rm = (word32 >> 11) & 0x3; + PushFRD(instruction, word32); + PushUIMMValue(instruction, rm); + break; + } + + case PPC_ID_MFSR: + { + uint32_t sr = (word32 >> 16) & 0xf; + + PushRD(instruction, word32); + PushUIMMValue(instruction, sr); + break; + } + + case PPC_ID_MFSRIN: + PushRD(instruction, word32); + PushRB(instruction, word32); + break; + + + case PPC_ID_MRx: + PushRA(instruction, word32); + PushRS(instruction, word32); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_MTCRF: + { + uint32_t crm = (word32 >> 12) & 0xff; + + PushUIMMValue(instruction, crm); + PushRS(instruction, word32); + break; + } + + case PPC_ID_MTFSFx: + { + uint32_t w = (word32 >> 16) & 0x1; + uint32_t l = (word32 >> 25) & 0x1; + uint32_t flm = (word32 >> 17) & 0xff; + + PushUIMMValue(instruction, flm); + PushFRB(instruction, word32); + + if (w != 0 || l != 0) + { + PushUIMMValue(instruction, l); + PushUIMMValue(instruction, w); + } + + instruction->flags.rc = word32 & 0x1; + break; + } + + case PPC_ID_MTFSFIx: + { + uint32_t u = (word32 >> 12) & 0xf; + uint32_t w = (word32 >> 16) & 0x1; + + PushCRFD(instruction, word32); + PushUIMMValue(instruction, u); + if (w != 0) + PushUIMMValue(instruction, w); + + instruction->flags.rc = word32 & 0x1; + break; + } + + case PPC_ID_MTOCRF: + { + uint32_t fxm = (word32 >> 12) & 0xff; + + PushRS(instruction, word32); + PushUIMMValue(instruction, fxm); + break; + } + + case PPC_ID_MTSR: + { + uint32_t sr = (word32 >> 16) & 0xf; + + PushUIMMValue(instruction, sr); + PushRS(instruction, word32); + + break; + } + + case PPC_ID_MTSRIN: + PushRS(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_RLWIMIx: + case PPC_ID_RLWINMx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH(word32)); + PushUIMMValue(instruction, GetMB(word32)); + PushUIMMValue(instruction, GetME(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_RLWNMx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushRB(instruction, word32); + PushUIMMValue(instruction, GetMB(word32)); + PushUIMMValue(instruction, GetME(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_SC: + { + uint32_t lev = (word32 >> 5) & 0x7f; + if (lev != 0) + PushUIMMValue(instruction, lev); + + break; + } + + case PPC_ID_SETB: + PushRD(instruction, word32); + PushCRFS(instruction, word32); + break; + + case PPC_ID_SLBMFEE: + case PPC_ID_SLBMFEV: + PushRD(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_SLBMTE: + case PPC_ID_SLBIEG: + PushRS(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_SRADIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH64(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_SRAWIx: + PushRA(instruction, word32); + PushRS(instruction, word32); + PushUIMMValue(instruction, GetSH(word32)); + + instruction->flags.rc = word32 & 0x1; + break; + + case PPC_ID_STSWI: + { + uint32_t nb = (word32 >> 11) & 0x1f; + + PushRS(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, nb); + break; + } + + case PPC_ID_TBEGIN: + { + uint32_t r = (word32 >> 21) & 0x1; + + PushUIMMValue(instruction, r); + break; + } + + case PPC_ID_TEND: + { + uint32_t a = (word32 >> 25) & 0x1; + + PushUIMMValue(instruction, a); + break; + } + + case PPC_ID_TLBIE: + PushRB(instruction, word32); + PushRS(instruction, word32); + break; + + case PPC_ID_TLBIVAX: + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_TSR: + { + uint32_t l = (word32 >> 21) & 0x1; + + PushUIMMValue(instruction, l); + break; + } + + case PPC_ID_WAIT: + { + uint32_t wc = (word32 >> 21) & 0x3; + + if (wc != 0) + PushUIMMValue(instruction, wc); + + break; + } + + case PPC_ID_WRTEEI: + { + uint32_t e = (word32 & 0x00008000) != 0; + + PushUIMMValue(instruction, e); + break; + } + + // ALTIVEC INSTRUCTIONS + + // vD, vA, vB, vC + case PPC_ID_AV_VADDECUQ: + case PPC_ID_AV_VADDEUQM: + case PPC_ID_AV_VMHADDSHS: + case PPC_ID_AV_VMHRADDSHS: + case PPC_ID_AV_VMLADDUHM: + case PPC_ID_AV_VSUBECUQ: + case PPC_ID_AV_VSUBEUQM: + case PPC_ID_AV_VMSUMMBM: + case PPC_ID_AV_VMSUMUBM: + case PPC_ID_AV_VMSUMSHM: + case PPC_ID_AV_VMSUMSHS: + case PPC_ID_AV_VMSUMUHM: + case PPC_ID_AV_VMSUMUHS: + case PPC_ID_AV_VPERM: + case PPC_ID_AV_VPERMR: + case PPC_ID_AV_VPERMXOR: + case PPC_ID_AV_VSEL: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVB(instruction, word32); + PushAltivecVC(instruction, word32); + break; + + // vD, vA, vC, vB (note swapped vC, vB) + case PPC_ID_AV_VMADDFP: + case PPC_ID_AV_VNMSUBFP: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVC(instruction, word32); + PushAltivecVB(instruction, word32); + break; + + // vD, vA, vB + case PPC_ID_AV_VABSDUB: + case PPC_ID_AV_VABSDUH: + case PPC_ID_AV_VABSDUW: + case PPC_ID_AV_VADDUQM: + case PPC_ID_AV_VADDCUQ: + case PPC_ID_AV_BCDUS: + case PPC_ID_AV_BCDUTRUNC: + case PPC_ID_AV_BCDCPSGN: + case PPC_ID_AV_VADDCUW: + case PPC_ID_AV_VADDFP: + case PPC_ID_AV_VADDSBS: + case PPC_ID_AV_VADDSHS: + case PPC_ID_AV_VADDSWS: + case PPC_ID_AV_VADDUBM: + case PPC_ID_AV_VADDUBS: + case PPC_ID_AV_VADDUDM: + case PPC_ID_AV_VADDUHM: + case PPC_ID_AV_VADDUHS: + case PPC_ID_AV_VADDUWM: + case PPC_ID_AV_VADDUWS: + case PPC_ID_AV_VAND: + case PPC_ID_AV_VANDC: + case PPC_ID_AV_VAVGSB: + case PPC_ID_AV_VAVGSH: + case PPC_ID_AV_VAVGSW: + case PPC_ID_AV_VAVGUB: + case PPC_ID_AV_VAVGUH: + case PPC_ID_AV_VAVGUW: + case PPC_ID_AV_VBPERMD: + case PPC_ID_AV_VBPERMQ: + case PPC_ID_AV_VCIPHER: + case PPC_ID_AV_VCIPHERLAST: + case PPC_ID_AV_VEQV: + case PPC_ID_AV_VMAXFP: + case PPC_ID_AV_VMAXSB: + case PPC_ID_AV_VMAXSD: + case PPC_ID_AV_VMAXSH: + case PPC_ID_AV_VMAXSW: + case PPC_ID_AV_VMAXUB: + case PPC_ID_AV_VMAXUD: + case PPC_ID_AV_VMAXUH: + case PPC_ID_AV_VMAXUW: + case PPC_ID_AV_VMINFP: + case PPC_ID_AV_VMINUB: + case PPC_ID_AV_VMINUD: + case PPC_ID_AV_VMINUH: + case PPC_ID_AV_VMINUW: + case PPC_ID_AV_VMINSB: + case PPC_ID_AV_VMINSD: + case PPC_ID_AV_VMINSH: + case PPC_ID_AV_VMINSW: + case PPC_ID_AV_VMRGEW: + case PPC_ID_AV_VMRGHB: + case PPC_ID_AV_VMRGHH: + case PPC_ID_AV_VMRGHW: + case PPC_ID_AV_VMRGLB: + case PPC_ID_AV_VMRGLH: + case PPC_ID_AV_VMRGLW: + case PPC_ID_AV_VMRGOW: + case PPC_ID_AV_VMUL10EUQ: + case PPC_ID_AV_VMUL10ECUQ: + case PPC_ID_AV_VMULESB: + case PPC_ID_AV_VMULESH: + case PPC_ID_AV_VMULESW: + case PPC_ID_AV_VMULEUB: + case PPC_ID_AV_VMULEUH: + case PPC_ID_AV_VMULEUW: + case PPC_ID_AV_VMULOSB: + case PPC_ID_AV_VMULOSH: + case PPC_ID_AV_VMULOSW: + case PPC_ID_AV_VMULOUB: + case PPC_ID_AV_VMULOUH: + case PPC_ID_AV_VMULOUW: + case PPC_ID_AV_VMULUWM: + case PPC_ID_AV_VNAND: + case PPC_ID_AV_VNCIPHER: + case PPC_ID_AV_VNCIPHERLAST: + case PPC_ID_AV_VNOR: + case PPC_ID_AV_VOR: + case PPC_ID_AV_VORC: + case PPC_ID_AV_VPKPX: + case PPC_ID_AV_VPKSDSS: + case PPC_ID_AV_VPKSDUS: + case PPC_ID_AV_VPKSHSS: + case PPC_ID_AV_VPKSHUS: + case PPC_ID_AV_VPKSWSS: + case PPC_ID_AV_VPKSWUS: + case PPC_ID_AV_VPKUDUM: + case PPC_ID_AV_VPKUDUS: + case PPC_ID_AV_VPKUHUM: + case PPC_ID_AV_VPKUHUS: + case PPC_ID_AV_VPKUWUM: + case PPC_ID_AV_VPKUWUS: + case PPC_ID_AV_VPMSUMB: + case PPC_ID_AV_VPMSUMD: + case PPC_ID_AV_VPMSUMH: + case PPC_ID_AV_VPMSUMW: + case PPC_ID_AV_VRLB: + case PPC_ID_AV_VRLD: + case PPC_ID_AV_VRLDMI: + case PPC_ID_AV_VRLDNM: + case PPC_ID_AV_VRLH: + case PPC_ID_AV_VRLW: + case PPC_ID_AV_VRLWMI: + case PPC_ID_AV_VRLWNM: + case PPC_ID_AV_VSL: + case PPC_ID_AV_VSLB: + case PPC_ID_AV_VSLD: + case PPC_ID_AV_VSLH: + case PPC_ID_AV_VSLO: + case PPC_ID_AV_VSLV: + case PPC_ID_AV_VSLW: + case PPC_ID_AV_VSR: + case PPC_ID_AV_VSRAB: + case PPC_ID_AV_VSRAD: + case PPC_ID_AV_VSRAH: + case PPC_ID_AV_VSRAW: + case PPC_ID_AV_VSRB: + case PPC_ID_AV_VSRD: + case PPC_ID_AV_VSRH: + case PPC_ID_AV_VSRO: + case PPC_ID_AV_VSRV: + case PPC_ID_AV_VSRW: + case PPC_ID_AV_VSUBCUQ: + case PPC_ID_AV_VSUBCUW: + case PPC_ID_AV_VSUBFP: + case PPC_ID_AV_VSUBSBS: + case PPC_ID_AV_VSUBSHS: + case PPC_ID_AV_VSUBSWS: + case PPC_ID_AV_VSUBUBS: + case PPC_ID_AV_VSUBUHS: + case PPC_ID_AV_VSUBUQM: + case PPC_ID_AV_VSUBUWS: + case PPC_ID_AV_VSUBUBM: + case PPC_ID_AV_VSUBUDM: + case PPC_ID_AV_VSUBUHM: + case PPC_ID_AV_VSUBUWM: + case PPC_ID_AV_VSUM2SWS: + case PPC_ID_AV_VSUM4SBS: + case PPC_ID_AV_VSUM4SHS: + case PPC_ID_AV_VSUM4UBS: + case PPC_ID_AV_VSUMSWS: + case PPC_ID_AV_VXOR: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVB(instruction, word32); + break; + + // [.] vD, vA, vB + case PPC_ID_AV_VCMPBFPx: + case PPC_ID_AV_VCMPEQFPx: + case PPC_ID_AV_VCMPGEFPx: + case PPC_ID_AV_VCMPEQUBx: + case PPC_ID_AV_VCMPEQUDx: + case PPC_ID_AV_VCMPEQUHx: + case PPC_ID_AV_VCMPEQUWx: + case PPC_ID_AV_VCMPGTFPx: + case PPC_ID_AV_VCMPGTSBx: + case PPC_ID_AV_VCMPGTSDx: + case PPC_ID_AV_VCMPGTSHx: + case PPC_ID_AV_VCMPGTSWx: + case PPC_ID_AV_VCMPGTUBx: + case PPC_ID_AV_VCMPGTUDx: + case PPC_ID_AV_VCMPGTUHx: + case PPC_ID_AV_VCMPGTUWx: + case PPC_ID_AV_VCMPNEBx: + case PPC_ID_AV_VCMPNEHx: + case PPC_ID_AV_VCMPNEWx: + case PPC_ID_AV_VCMPNEZBx: + case PPC_ID_AV_VCMPNEZHx: + case PPC_ID_AV_VCMPNEZWx: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVB(instruction, word32); + + instruction->flags.rc = (word32 >> 10) & 0x1; + break; + + // vD, vA + case PPC_ID_AV_VMUL10CUQ: + case PPC_ID_AV_VMUL10UQ: + case PPC_ID_AV_VSBOX: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + break; + + // vD, vB + case PPC_ID_AV_BCDCTN: + case PPC_ID_AV_BCDCTSQ: + case PPC_ID_AV_VCLZB: + case PPC_ID_AV_VCLZD: + case PPC_ID_AV_VCLZH: + case PPC_ID_AV_VCLZW: + case PPC_ID_AV_VCTZB: + case PPC_ID_AV_VCTZD: + case PPC_ID_AV_VCTZH: + case PPC_ID_AV_VCTZW: + case PPC_ID_AV_VEXPTEFP: + case PPC_ID_AV_VEXTSB2D: + case PPC_ID_AV_VEXTSB2W: + case PPC_ID_AV_VEXTSH2D: + case PPC_ID_AV_VEXTSH2W: + case PPC_ID_AV_VEXTSW2D: + case PPC_ID_AV_VGBBD: + case PPC_ID_AV_VLOGEFP: + case PPC_ID_AV_VMR: + case PPC_ID_AV_VNEGD: + case PPC_ID_AV_VNEGW: + case PPC_ID_AV_VNOT: + case PPC_ID_AV_VPOPCNTB: + case PPC_ID_AV_VPOPCNTD: + case PPC_ID_AV_VPOPCNTH: + case PPC_ID_AV_VPOPCNTW: + case PPC_ID_AV_VPRTYBD: + case PPC_ID_AV_VPRTYBQ: + case PPC_ID_AV_VPRTYBW: + case PPC_ID_AV_VREFP: + case PPC_ID_AV_VRFIM: + case PPC_ID_AV_VRFIN: + case PPC_ID_AV_VRFIP: + case PPC_ID_AV_VRFIZ: + case PPC_ID_AV_VRSQRTEFP: + case PPC_ID_AV_VUPKHPX: + case PPC_ID_AV_VUPKHSB: + case PPC_ID_AV_VUPKHSH: + case PPC_ID_AV_VUPKHSW: + case PPC_ID_AV_VUPKLPX: + case PPC_ID_AV_VUPKLSB: + case PPC_ID_AV_VUPKLSH: + case PPC_ID_AV_VUPKLSW: + PushAltivecVD(instruction, word32); + PushAltivecVB(instruction, word32); + break; + + // vD, vB, UIMM + case PPC_ID_AV_VCFSX: + case PPC_ID_AV_VCFUX: + case PPC_ID_AV_VCTSXS: + case PPC_ID_AV_VCTUXS: + case PPC_ID_AV_VSPLTB: + case PPC_ID_AV_VSPLTH: + case PPC_ID_AV_VSPLTW: + PushAltivecVD(instruction, word32); + PushAltivecVB(instruction, word32); + PushUIMMValue(instruction, (word32 >> 16) & 0x1f); + break; + + // vD, SIMM + case PPC_ID_AV_VSPLTISB: + case PPC_ID_AV_VSPLTISH: + case PPC_ID_AV_VSPLTISW: + { + PushAltivecVD(instruction, word32); + + int32_t simm = sign_extend((word32 >> 16) & 0x1f, 5); + PushSIMMValue(instruction, simm); + break; + } + + // vD, d(rA) + case PPC_ID_AV_LVEBX: + case PPC_ID_AV_LVEHX: + case PPC_ID_AV_LVEWX: + case PPC_ID_AV_LVSL: + case PPC_ID_AV_LVSR: + case PPC_ID_AV_LVX: + case PPC_ID_AV_LVXL: + PushAltivecVD(instruction, word32); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // vS, d(rA) + case PPC_ID_AV_STVEBX: + case PPC_ID_AV_STVEHX: + case PPC_ID_AV_STVEWX: + case PPC_ID_AV_STVX: + case PPC_ID_AV_STVXL: + PushAltivecVS(instruction, word32); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_AV_DST: + case PPC_ID_AV_DSTST: + case PPC_ID_AV_DSTSTT: + case PPC_ID_AV_DSTT: + { + uint32_t strm = (word32 >> 21) & 0x3; + + PushRA(instruction, word32); + PushRB(instruction, word32); + PushUIMMValue(instruction, strm); + break; + } + + case PPC_ID_AV_DSS: + { + uint32_t strm = (word32 >> 21) & 0x3; + PushUIMMValue(instruction, strm); + break; + } + + case PPC_ID_AV_MFVSCR: + // mfvscr vD + PushAltivecVD(instruction, word32); + break; + + case PPC_ID_AV_MTVSCR: + // mtvscr vB + PushAltivecVB(instruction, word32); + break; + + case PPC_ID_AV_VSLDOI: + // vsldoi vD, vA, vB, UIMM + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVB(instruction, word32); + PushUIMMValue(instruction, (word32 >> 6) & 0xf); + break; + + // rD, rA, rB, rC (normal registers) + case PPC_ID_AV_MADDHD: + case PPC_ID_AV_MADDHDU: + case PPC_ID_AV_MADDLD: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + PushRC(instruction, word32); + break; + + // vrD, vrA, vrB, ps + case PPC_ID_AV_BCDADD: + case PPC_ID_AV_BCDSUB: + case PPC_ID_AV_BCDS: + case PPC_ID_AV_BCDSR: + case PPC_ID_AV_BCDTRUNC: + { + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushAltivecVB(instruction, word32); + uint32_t ps = (word32 & 0x200) != 0; + PushUIMMValue(instruction, ps); + break; + } + + + // vrD, vrB, ps + case PPC_ID_AV_BCDCFN: + case PPC_ID_AV_BCDCFZ: + case PPC_ID_AV_BCDCTZ: + case PPC_ID_AV_BCDCFSQ: + case PPC_ID_AV_BCDSETSGN: + // PS isn't in all of these instructions, but it gets + // filtered out in subop decode + PushAltivecVD(instruction, word32); + PushAltivecVB(instruction, word32); + uint32_t ps = (word32 & 0x200) != 0; + PushUIMMValue(instruction, ps); + break; + + + // vrD, vrB, UIM + case PPC_ID_AV_VEXTRACTD: + case PPC_ID_AV_VEXTRACTUB: + case PPC_ID_AV_VEXTRACTUH: + case PPC_ID_AV_VEXTRACTUW: + case PPC_ID_AV_VINSERTB: + case PPC_ID_AV_VINSERTD: + case PPC_ID_AV_VINSERTH: + case PPC_ID_AV_VINSERTW: + PushAltivecVD(instruction, word32); + PushAltivecVB(instruction, word32); + PushUIMMValue(instruction, (word32 >> 16) & 0xf); + break; + + // rD, rA, vB + case PPC_ID_AV_VEXTUBLX: + case PPC_ID_AV_VEXTUHLX: + case PPC_ID_AV_VEXTUWLX: + case PPC_ID_AV_VEXTUBRX: + case PPC_ID_AV_VEXTUHRX: + case PPC_ID_AV_VEXTUWRX: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushAltivecVB(instruction, word32); + break; + + // vD, vA, ST, SIX + case PPC_ID_AV_VSHASIGMAD: + case PPC_ID_AV_VSHASIGMAW: + PushAltivecVD(instruction, word32); + PushAltivecVA(instruction, word32); + PushUIMMValue(instruction, (word32 >> 15) & 0x1); + PushUIMMValue(instruction, (word32 >> 11) & 0xf); + break; + + // rD, vB + case PPC_ID_AV_VCLZLSBB: + case PPC_ID_AV_VCTZLSBB: + PushRD(instruction, word32); + PushAltivecVB(instruction, word32); + break; + + // VSX INSTRUCTIONS + + // vrD, vrA, vrB + case PPC_ID_VSX_XVADDDP: + case PPC_ID_VSX_XVADDSP: + case PPC_ID_VSX_XVCPSGNDP: + case PPC_ID_VSX_XVCPSGNSP: + case PPC_ID_VSX_XVDIVDP: + case PPC_ID_VSX_XVDIVSP: + case PPC_ID_VSX_XVIEXPDP: + case PPC_ID_VSX_XVIEXPSP: + case PPC_ID_VSX_XVMADDADP: + case PPC_ID_VSX_XVMADDASP: + case PPC_ID_VSX_XVMADDMDP: + case PPC_ID_VSX_XVMADDMSP: + case PPC_ID_VSX_XVMAXDP: + case PPC_ID_VSX_XVMAXSP: + case PPC_ID_VSX_XVMINDP: + case PPC_ID_VSX_XVMINSP: + case PPC_ID_VSX_XVMSUBADP: + case PPC_ID_VSX_XVMSUBMDP: + case PPC_ID_VSX_XVMSUBASP: + case PPC_ID_VSX_XVMSUBMSP: + case PPC_ID_VSX_XVMULDP: + case PPC_ID_VSX_XVMULSP: + case PPC_ID_VSX_XVNMADDADP: + case PPC_ID_VSX_XVNMADDASP: + case PPC_ID_VSX_XVNMADDMDP: + case PPC_ID_VSX_XVNMADDMSP: + case PPC_ID_VSX_XVNMSUBADP: + case PPC_ID_VSX_XVNMSUBASP: + case PPC_ID_VSX_XVNMSUBMDP: + case PPC_ID_VSX_XVNMSUBMSP: + case PPC_ID_VSX_XVSUBDP: + case PPC_ID_VSX_XVSUBSP: + case PPC_ID_VSX_XXLAND: + case PPC_ID_VSX_XXLANDC: + case PPC_ID_VSX_XXLEQV: + case PPC_ID_VSX_XXLOR: + case PPC_ID_VSX_XXLNAND: + case PPC_ID_VSX_XXLNOR: + case PPC_ID_VSX_XXLORC: + case PPC_ID_VSX_XXLXOR: + case PPC_ID_VSX_XXMRGHD: + case PPC_ID_VSX_XXMRGHW: + case PPC_ID_VSX_XXMRGLD: + case PPC_ID_VSX_XXMRGLW: + case PPC_ID_VSX_XXPERM: + case PPC_ID_VSX_XXPERMR: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + break; + + // [.] vrD, rA, vrB + case PPC_ID_VSX_XVCMPEQDPx: + case PPC_ID_VSX_XVCMPEQSPx: + case PPC_ID_VSX_XVCMPGEDPx: + case PPC_ID_VSX_XVCMPGESPx: + case PPC_ID_VSX_XVCMPGTDPx: + case PPC_ID_VSX_XVCMPGTSPx: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + instruction->flags.rc = (word32 & 0x400) != 0; + break; + + // vrD, vrA, vrB + case PPC_ID_VSX_XSADDSP: + case PPC_ID_VSX_XSADDDP: + case PPC_ID_VSX_XSCMPEQDP: + case PPC_ID_VSX_XSCMPGEDP: + case PPC_ID_VSX_XSCMPGTDP: + case PPC_ID_VSX_XSCPSGNDP: + case PPC_ID_VSX_XSDIVDP: + case PPC_ID_VSX_XSDIVSP: + case PPC_ID_VSX_XSMADDADP: + case PPC_ID_VSX_XSMADDMDP: + case PPC_ID_VSX_XSMADDASP: + case PPC_ID_VSX_XSMADDMSP: + case PPC_ID_VSX_XSMAXCDP: + case PPC_ID_VSX_XSMAXDP: + case PPC_ID_VSX_XSMAXJDP: + case PPC_ID_VSX_XSMINCDP: + case PPC_ID_VSX_XSMINDP: + case PPC_ID_VSX_XSMINJDP: + case PPC_ID_VSX_XSMSUBADP: + case PPC_ID_VSX_XSMSUBASP: + case PPC_ID_VSX_XSMSUBMDP: + case PPC_ID_VSX_XSMSUBMSP: + case PPC_ID_VSX_XSMULDP: + case PPC_ID_VSX_XSMULSP: + case PPC_ID_VSX_XSNMADDADP: + case PPC_ID_VSX_XSNMADDASP: + case PPC_ID_VSX_XSNMADDMDP: + case PPC_ID_VSX_XSNMADDMSP: + case PPC_ID_VSX_XSNMSUBADP: + case PPC_ID_VSX_XSNMSUBASP: + case PPC_ID_VSX_XSNMSUBMDP: + case PPC_ID_VSX_XSNMSUBMSP: + case PPC_ID_VSX_XSSUBDP: + case PPC_ID_VSX_XSSUBSP: + PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); + PushVsxA(instruction, word32, VSX_WIDTH_DWORD0); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + break; + + // vrD, vrB + case PPC_ID_VSX_XVABSDP: + case PPC_ID_VSX_XVABSSP: + case PPC_ID_VSX_XVCVDPSP: + case PPC_ID_VSX_XVCVDPSXDS: + case PPC_ID_VSX_XVCVDPSXWS: + case PPC_ID_VSX_XVCVDPUXDS: + case PPC_ID_VSX_XVCVDPUXWS: + case PPC_ID_VSX_XVCVSPDP: + case PPC_ID_VSX_XVCVSPSXDS: + case PPC_ID_VSX_XVCVSPSXWS: + case PPC_ID_VSX_XVCVSPUXDS: + case PPC_ID_VSX_XVCVSPUXWS: + case PPC_ID_VSX_XVCVSXDDP: + case PPC_ID_VSX_XVCVSXDSP: + case PPC_ID_VSX_XVCVSXWDP: + case PPC_ID_VSX_XVCVSXWSP: + case PPC_ID_VSX_XVCVUXDDP: + case PPC_ID_VSX_XVCVUXDSP: + case PPC_ID_VSX_XVCVUXWDP: + case PPC_ID_VSX_XVCVUXWSP: + case PPC_ID_VSX_XVNABSDP: + case PPC_ID_VSX_XVNABSSP: + case PPC_ID_VSX_XVNEGDP: + case PPC_ID_VSX_XVNEGSP: + case PPC_ID_VSX_XVRDPI: + case PPC_ID_VSX_XVRDPIC: + case PPC_ID_VSX_XVRDPIM: + case PPC_ID_VSX_XVRDPIP: + case PPC_ID_VSX_XVRDPIZ: + case PPC_ID_VSX_XVREDP: + case PPC_ID_VSX_XVRESP: + case PPC_ID_VSX_XVRSPI: + case PPC_ID_VSX_XVRSPIC: + case PPC_ID_VSX_XVRSPIM: + case PPC_ID_VSX_XVRSPIP: + case PPC_ID_VSX_XVRSPIZ: + case PPC_ID_VSX_XVRSQRTEDP: + case PPC_ID_VSX_XVRSQRTESP: + case PPC_ID_VSX_XVSQRTSP: + case PPC_ID_VSX_XVSQRTDP: + case PPC_ID_VSX_XVMOVDP: + case PPC_ID_VSX_XVMOVSP: + case PPC_ID_VSX_XVXEXPDP: + case PPC_ID_VSX_XVXEXPSP: + case PPC_ID_VSX_XVXSIGDP: + case PPC_ID_VSX_XVXSIGSP: + case PPC_ID_VSX_XXBRD: + case PPC_ID_VSX_XXBRH: + case PPC_ID_VSX_XXBRQ: + case PPC_ID_VSX_XXBRW: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + break; + + // vrD, vrB + case PPC_ID_VSX_XSABSDP: + case PPC_ID_VSX_XSCVDPHP: + case PPC_ID_VSX_XSCVDPSXDS: + case PPC_ID_VSX_XSCVDPSP: + case PPC_ID_VSX_XSCVDPSPN: + case PPC_ID_VSX_XSCVDPSXWS: + case PPC_ID_VSX_XSCVDPUXDS: + case PPC_ID_VSX_XSCVDPUXWS: + case PPC_ID_VSX_XSCVSPDP: + case PPC_ID_VSX_XSCVHPDP: + case PPC_ID_VSX_XSCVSPDPN: + case PPC_ID_VSX_XSCVSXDDP: + case PPC_ID_VSX_XSCVSXDSP: + case PPC_ID_VSX_XSCVUXDDP: + case PPC_ID_VSX_XSCVUXDSP: + case PPC_ID_VSX_XSNABSDP: + case PPC_ID_VSX_XSNEGDP: + case PPC_ID_VSX_XSRDPI: + case PPC_ID_VSX_XSRDPIC: + case PPC_ID_VSX_XSRDPIM: + case PPC_ID_VSX_XSRDPIP: + case PPC_ID_VSX_XSRDPIZ: + case PPC_ID_VSX_XSREDP: + case PPC_ID_VSX_XSRESP: + case PPC_ID_VSX_XSRSP: + case PPC_ID_VSX_XSRSQRTESP: + case PPC_ID_VSX_XSRSQRTEDP: + case PPC_ID_VSX_XSSQRTDP: + case PPC_ID_VSX_XSSQRTSP: + case PPC_ID_VSX_XVCVHPSP: + case PPC_ID_VSX_XVCVSPHP: + PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + break; + + // vrD, vrA, vrB, + case PPC_ID_VSX_XXPERMDI: + case PPC_ID_VSX_XXSLDWI: + { + uint32_t uimm = (word32 >> 8) & 0x3; + + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + PushUIMMValue(instruction, uimm); + break; + } + + // vrD, rA, rB + case PPC_ID_VSX_MTVSRDD: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // vrD, rA, rB (load indexed) + case PPC_ID_VSX_LXVB16X: + case PPC_ID_VSX_LXVD2X: + case PPC_ID_VSX_LXVDSX: + case PPC_ID_VSX_LXVH8X: + case PPC_ID_VSX_LXVL: + case PPC_ID_VSX_LXVLL: + case PPC_ID_VSX_LXVW4X: + case PPC_ID_VSX_LXVWSX: + case PPC_ID_VSX_LXVX: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_VSX_LXSDX: + case PPC_ID_VSX_LXSIBZX: + case PPC_ID_VSX_LXSIHZX: + case PPC_ID_VSX_LXSIWAX: + case PPC_ID_VSX_LXSIWZX: + case PPC_ID_VSX_LXSSPX: + PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // vrS, rA, rB (store indexed) + case PPC_ID_VSX_STXVB16X: + case PPC_ID_VSX_STXVD2X: + case PPC_ID_VSX_STXVH8X: + case PPC_ID_VSX_STXVL: + case PPC_ID_VSX_STXVLL: + case PPC_ID_VSX_STXVW4X: + case PPC_ID_VSX_STXVX: + PushVsxS(instruction, word32, VSX_WIDTH_FULL); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + case PPC_ID_VSX_STXSDX: + case PPC_ID_VSX_STXSIBX: + case PPC_ID_VSX_STXSIHX: + case PPC_ID_VSX_STXSIWX: + case PPC_ID_VSX_STXSSPX: + PushVsxS(instruction, word32, VSX_WIDTH_DWORD0); + PushRAor0(instruction, word32); + PushRB(instruction, word32); + break; + + // crfD, vrA, vrB + case PPC_ID_VSX_XSCMPEXPDP: + case PPC_ID_VSX_XSCMPODP: + case PPC_ID_VSX_XSCMPUDP: + case PPC_ID_VSX_XSTDIVDP: + PushCRFD(instruction, word32); + PushVsxA(instruction, word32, VSX_WIDTH_DWORD0); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + break; + + // crfD, vrA, vrB + case PPC_ID_VSX_XVTDIVDP: + case PPC_ID_VSX_XVTDIVSP: + PushCRFD(instruction, word32); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + break; + + // crfD, vrB + case PPC_ID_VSX_XVTSQRTSP: + case PPC_ID_VSX_XVTSQRTDP: + PushCRFD(instruction, word32); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + break; + + case PPC_ID_VSX_XSTSQRTDP: + PushCRFD(instruction, word32); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + break; + + // vrD, rA + case PPC_ID_VSX_MTVSRWS: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushRA(instruction, word32); + break; + + case PPC_ID_VSX_MTVSRD: + case PPC_ID_VSX_MTVSRWA: + case PPC_ID_VSX_MTVSRWZ: + PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); + PushRA(instruction, word32); + break; + + // rA, vrS + case PPC_ID_VSX_MFVSRLD: + PushRA(instruction, word32); + PushVsxS(instruction, word32, VSX_WIDTH_FULL); + break; + + case PPC_ID_VSX_MFFPRD: + case PPC_ID_VSX_MFVSRWZ: + case PPC_ID_VSX_MFVSRD: + PushRA(instruction, word32); + PushVsxS(instruction, word32, VSX_WIDTH_DWORD0); + break; + + // vrD, vrB, UIM + case PPC_ID_VSX_XXINSERTW: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + PushUIMMValue(instruction, (word32 >> 16) & 0xf); + break; + + case PPC_ID_VSX_XXEXTRACTUW: + PushVsxD(instruction, word32, VSX_WIDTH_DWORD0); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + PushUIMMValue(instruction, (word32 >> 16) & 0xf); + break; + + case PPC_ID_VSX_LXV: + { + uint32_t dx = (word32 >> 3) & 0x1; + uint32_t d = GetD(word32); + uint32_t vsxd = (dx << 5) | d; + + PushRegister(instruction, PPC_OP_REG_VSX_RD, VsxVr(vsxd)); + + uint32_t dq = (int32_t)((int16_t)(word32 & 0xfff0)); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), dq); + + break; + } + + case PPC_ID_VSX_STXV: + { + uint32_t sx = (word32 >> 3) & 0x1; + uint32_t s = GetS(word32); + uint32_t vsxs = (sx << 5) | s; + + PushRegister(instruction, PPC_OP_REG_VSX_RS, VsxVr(vsxs)); + + int32_t dq = (int32_t)((int16_t)(word32 & 0xfff0)); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), dq); + + break; + } + + case PPC_ID_VSX_STXSD: + case PPC_ID_VSX_STXSSP: + { + uint32_t xs = GetS(word32) + 32; + PushRegister(instruction, PPC_OP_REG_VSX_RS, VsxVr(xs)); + + int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); + break; + } + + // [o] vrdHi, vraHi, vrbHi + case PPC_ID_VSX_XSADDQPx: + case PPC_ID_VSX_XSCPSGNQP: + case PPC_ID_VSX_XSDIVQPx: + case PPC_ID_VSX_XSIEXPQP: + case PPC_ID_VSX_XSMADDQPx: + case PPC_ID_VSX_XSMSUBQPx: + case PPC_ID_VSX_XSMULQPx: + case PPC_ID_VSX_XSNMADDQPx: + case PPC_ID_VSX_XSNMSUBQPx: + case PPC_ID_VSX_XSSUBQPx: + { + PushVsxHiD(instruction, word32); + PushVsxHiA(instruction, word32); + PushVsxHiB(instruction, word32); + + instruction->flags.round2odd = word32 & 0x1; + break; + } + + case PPC_ID_VSX_XSABSQP: + case PPC_ID_VSX_XSCVQPUWZ: + case PPC_ID_VSX_XSCVUDQP: + case PPC_ID_VSX_XSNABSQP: + case PPC_ID_VSX_XSCVDPQP: + case PPC_ID_VSX_XSCVQPDPx: + case PPC_ID_VSX_XSCVQPSDZ: + case PPC_ID_VSX_XSCVQPSWZ: + case PPC_ID_VSX_XSCVQPUDZ: + case PPC_ID_VSX_XSCVSDQP: + case PPC_ID_VSX_XSNEGQP: + case PPC_ID_VSX_XSSQRTQPx: + case PPC_ID_VSX_XSXEXPQP: + case PPC_ID_VSX_XSXSIGQP: + { + PushVsxHiD(instruction, word32); + PushVsxHiB(instruction, word32); + + instruction->flags.round2odd = word32 & 0x1; + break; + } + + case PPC_ID_VSX_XSCMPEXPQP: + case PPC_ID_VSX_XSCMPOQP: + case PPC_ID_VSX_XSCMPUQP: + PushCRFD(instruction, word32); + PushVsxHiA(instruction, word32); + PushVsxHiB(instruction, word32); + + break; + + case PPC_ID_VSX_XSTSTDCQP: + { + uint32_t dcmx = (word32 >> 16) & 0x7f; + PushCRFD(instruction, word32); + PushVsxHiB(instruction, word32); + PushUIMMValue(instruction, dcmx); + break; + } + + // one-off VSX instructions + case PPC_ID_VSX_XSIEXPDP: + { + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + } + + case PPC_ID_VSX_XSRQPIx: + case PPC_ID_VSX_XSRQPXP: + { + uint32_t r = (word32 >> 16) & 0x1; + PushUIMMValue(instruction, r); + PushVsxHiD(instruction, word32); + PushVsxHiB(instruction, word32); + + uint32_t rmc = (word32 >> 9) & 0x3; + PushUIMMValue(instruction, rmc); + + instruction->flags.inexact = word32 & 0x1; + break; + } + + case PPC_ID_VSX_XSTSTDCDP: + case PPC_ID_VSX_XSTSTDCSP: + { + uint32_t dcmx = (word32 >> 16) & 0x7f; + PushCRFD(instruction, word32); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + PushUIMMValue(instruction, dcmx); + break; + } + + case PPC_ID_VSX_XSXEXPDP: + case PPC_ID_VSX_XSXSIGDP: + PushRD(instruction, word32); + PushVsxB(instruction, word32, VSX_WIDTH_DWORD0); + break; + + case PPC_ID_VSX_XVTSTDCDP: + case PPC_ID_VSX_XVTSTDCSP: + { + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + uint32_t dm = (word32 >> 2) & 0x1; + uint32_t dc = (word32 >> 6) & 0x1; + uint32_t dx = (word32 >> 16) & 0x1f; + uint32_t dcmx = (dc << 6) | (dm << 5) | dx; + PushUIMMValue(instruction, dcmx); + break; + } + + + case PPC_ID_VSX_XXSPLTD: + { + uint32_t uimm = (word32 >> 8) & 0x3; + + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + + if (uimm == 3) + PushUIMMValue(instruction, 1); + else + PushUIMMValue(instruction, 0); + + break; + } + + case PPC_ID_VSX_XXSPLTIB: + { + uint32_t uimm8 = (word32 >> 11) & 0xff; + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushUIMMValue(instruction, uimm8); + break; + } + + case PPC_ID_VSX_XXSPLTW: + { + uint32_t um = (word32 >> 16) & 0x3; + + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + PushUIMMValue(instruction, um); + break; + } + + case PPC_ID_VSX_XXSWAPD: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + break; + + case PPC_ID_VSX_XXSEL: + PushVsxD(instruction, word32, VSX_WIDTH_FULL); + PushVsxA(instruction, word32, VSX_WIDTH_FULL); + PushVsxB(instruction, word32, VSX_WIDTH_FULL); + PushVsxC(instruction, word32, VSX_WIDTH_FULL); + break; + + // SPE INSTRUCTIONS + + // SPE rD, rA, rB + case PPC_ID_SPE_BRINC: + case PPC_ID_SPE_EFDADD: + case PPC_ID_SPE_EFDDIV: + case PPC_ID_SPE_EFDMUL: + case PPC_ID_SPE_EFDSUB: + case PPC_ID_SPE_EFSADD: + case PPC_ID_SPE_EFSDIV: + case PPC_ID_SPE_EFSMUL: + case PPC_ID_SPE_EFSSUB: + case PPC_ID_SPE_EVADDW: + case PPC_ID_SPE_EVAND: + case PPC_ID_SPE_EVANDC: + case PPC_ID_SPE_EVDIVWS: + case PPC_ID_SPE_EVDIVWU: + case PPC_ID_SPE_EVEQV: + case PPC_ID_SPE_EVFSADD: + case PPC_ID_SPE_EVFSDIV: + case PPC_ID_SPE_EVFSMUL: + case PPC_ID_SPE_EVFSSUB: + case PPC_ID_SPE_EVLDDX: + case PPC_ID_SPE_EVLDHX: + case PPC_ID_SPE_EVLDWX: + case PPC_ID_SPE_EVLHHESPLATX: + case PPC_ID_SPE_EVLHHOSSPLATX: + case PPC_ID_SPE_EVLHHOUSPLATX: + case PPC_ID_SPE_EVLWHEX: + case PPC_ID_SPE_EVLWHOSX: + case PPC_ID_SPE_EVLWHOUX: + case PPC_ID_SPE_EVLWHSPLATX: + case PPC_ID_SPE_EVLWWSPLATX: + case PPC_ID_SPE_EVMERGEHI: + case PPC_ID_SPE_EVMERGEHILO: + case PPC_ID_SPE_EVMERGELO: + case PPC_ID_SPE_EVMERGELOHI: + case PPC_ID_SPE_EVMHEGSMFAA: + case PPC_ID_SPE_EVMHEGSMFAN: + case PPC_ID_SPE_EVMHEGSMIAA: + case PPC_ID_SPE_EVMHEGSMIAN: + case PPC_ID_SPE_EVMHEGUMIAA: + case PPC_ID_SPE_EVMHEGUMIAN: + case PPC_ID_SPE_EVMHESMF: + case PPC_ID_SPE_EVMHESMFA: + case PPC_ID_SPE_EVMHESMFAAW: + case PPC_ID_SPE_EVMHESMFANW: + case PPC_ID_SPE_EVMHESMI: + case PPC_ID_SPE_EVMHESMIA: + case PPC_ID_SPE_EVMHESMIAAW: + case PPC_ID_SPE_EVMHESMIANW: + case PPC_ID_SPE_EVMHESSF: + case PPC_ID_SPE_EVMHESSFA: + case PPC_ID_SPE_EVMHESSFAAW: + case PPC_ID_SPE_EVMHESSFANW: + case PPC_ID_SPE_EVMHESSIAAW: + case PPC_ID_SPE_EVMHESSIANW: + case PPC_ID_SPE_EVMHEUMI: + case PPC_ID_SPE_EVMHEUMIA: + case PPC_ID_SPE_EVMHEUMIAAW: + case PPC_ID_SPE_EVMHEUMIANW: + case PPC_ID_SPE_EVMHEUSIAAW: + case PPC_ID_SPE_EVMHEUSIANW: + case PPC_ID_SPE_EVMHOGSMFAA: + case PPC_ID_SPE_EVMHOGSMFAN: + case PPC_ID_SPE_EVMHOGSMIAA: + case PPC_ID_SPE_EVMHOGSMIAN: + case PPC_ID_SPE_EVMHOGUMIAA: + case PPC_ID_SPE_EVMHOGUMIAN: + case PPC_ID_SPE_EVMHOSMF: + case PPC_ID_SPE_EVMHOSMFA: + case PPC_ID_SPE_EVMHOSMFAAW: + case PPC_ID_SPE_EVMHOSMFANW: + case PPC_ID_SPE_EVMHOSMI: + case PPC_ID_SPE_EVMHOSMIA: + case PPC_ID_SPE_EVMHOSMIAAW: + case PPC_ID_SPE_EVMHOSMIANW: + case PPC_ID_SPE_EVMHOSSF: + case PPC_ID_SPE_EVMHOSSFA: + case PPC_ID_SPE_EVMHOSSFAAW: + case PPC_ID_SPE_EVMHOSSFANW: + case PPC_ID_SPE_EVMHOSSIAAW: + case PPC_ID_SPE_EVMHOSSIANW: + case PPC_ID_SPE_EVMHOUMI: + case PPC_ID_SPE_EVMHOUMIA: + case PPC_ID_SPE_EVMHOUMIAAW: + case PPC_ID_SPE_EVMHOUMIANW: + case PPC_ID_SPE_EVMHOUSIAAW: + case PPC_ID_SPE_EVMHOUSIANW: + case PPC_ID_SPE_EVMWHSMF: + case PPC_ID_SPE_EVMWHSMFA: + case PPC_ID_SPE_EVMWHSMI: + case PPC_ID_SPE_EVMWHSMIA: + case PPC_ID_SPE_EVMWHSSF: + case PPC_ID_SPE_EVMWHSSFA: + case PPC_ID_SPE_EVMWLSMIAAW: + case PPC_ID_SPE_EVMWLSMIANW: + case PPC_ID_SPE_EVMWLSSIAAW: + case PPC_ID_SPE_EVMWLSSIANW: + case PPC_ID_SPE_EVMWHUMI: + case PPC_ID_SPE_EVMWHUMIA: + case PPC_ID_SPE_EVMWHUSIAAW: + case PPC_ID_SPE_EVMWHUSIANW: + case PPC_ID_SPE_EVMWLUMI: + case PPC_ID_SPE_EVMWLUMIA: + case PPC_ID_SPE_EVMWLUMIAAW: + case PPC_ID_SPE_EVMWLUMIANW: + case PPC_ID_SPE_EVMWLUSIAAW: + case PPC_ID_SPE_EVMWLUSIANW: + case PPC_ID_SPE_EVMWSMF: + case PPC_ID_SPE_EVMWSMFA: + case PPC_ID_SPE_EVMWSMFAA: + case PPC_ID_SPE_EVMWSMFAN: + case PPC_ID_SPE_EVMWSMI: + case PPC_ID_SPE_EVMWSMIA: + case PPC_ID_SPE_EVMWSMIAA: + case PPC_ID_SPE_EVMWSMIAN: + case PPC_ID_SPE_EVMWSSF: + case PPC_ID_SPE_EVMWSSFA: + case PPC_ID_SPE_EVMWSSFAA: + case PPC_ID_SPE_EVMWSSFAN: + case PPC_ID_SPE_EVMWUMI: + case PPC_ID_SPE_EVMWUMIA: + case PPC_ID_SPE_EVMWUMIAA: + case PPC_ID_SPE_EVMWUMIAN: + case PPC_ID_SPE_EVNAND: + case PPC_ID_SPE_EVNOR: + case PPC_ID_SPE_EVOR: + case PPC_ID_SPE_EVORC: + case PPC_ID_SPE_EVRLW: + case PPC_ID_SPE_EVSLW: + case PPC_ID_SPE_EVSRWS: + case PPC_ID_SPE_EVSRWU: + case PPC_ID_SPE_EVSUBFW: + case PPC_ID_SPE_EVXOR: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // rD, rA, /// + case PPC_ID_SPE_EFDABS: + case PPC_ID_SPE_EFDNABS: + case PPC_ID_SPE_EFDNEG: + case PPC_ID_SPE_EFSABS: + case PPC_ID_SPE_EFSNABS: + case PPC_ID_SPE_EFSNEG: + case PPC_ID_SPE_EVABS: + case PPC_ID_SPE_EVADDSMIAAW: + case PPC_ID_SPE_EVADDSSIAAW: + case PPC_ID_SPE_EVADDUMIAAW: + case PPC_ID_SPE_EVADDUSIAAW: + case PPC_ID_SPE_EVCNTLSW: + case PPC_ID_SPE_EVCNTLZW: + case PPC_ID_SPE_EVEXTSB: + case PPC_ID_SPE_EVEXTSH: + case PPC_ID_SPE_EVFSABS: + case PPC_ID_SPE_EVFSNABS: + case PPC_ID_SPE_EVFSNEG: + case PPC_ID_SPE_EVMRA: + case PPC_ID_SPE_EVNEG: + case PPC_ID_SPE_EVSUBFSMIAAW: + case PPC_ID_SPE_EVSUBFSSIAAW: + case PPC_ID_SPE_EVSUBFUMIAAW: + case PPC_ID_SPE_EVSUBFUSIAAW: + PushRD(instruction, word32); + PushRA(instruction, word32); + break; + + // rD, ///, rB + case PPC_ID_SPE_EFDCFS: + case PPC_ID_SPE_EFDCFSF: + case PPC_ID_SPE_EFDCFSI: + case PPC_ID_SPE_EFDCFSID: + case PPC_ID_SPE_EFDCFUF: + case PPC_ID_SPE_EFDCFUI: + case PPC_ID_SPE_EFDCFUID: + case PPC_ID_SPE_EFDCTSF: + case PPC_ID_SPE_EFDCTSI: + case PPC_ID_SPE_EFDCTSIDZ: + case PPC_ID_SPE_EFDCTSIZ: + case PPC_ID_SPE_EFDCTUF: + case PPC_ID_SPE_EFDCTUI: + case PPC_ID_SPE_EFDCTUIDZ: + case PPC_ID_SPE_EFDCTUIZ: + case PPC_ID_SPE_EFSCFD: + case PPC_ID_SPE_EFSCFSF: + case PPC_ID_SPE_EFSCFSI: + case PPC_ID_SPE_EFSCFUF: + case PPC_ID_SPE_EFSCFUI: + case PPC_ID_SPE_EFSCTSF: + case PPC_ID_SPE_EFSCTSI: + case PPC_ID_SPE_EFSCTSIZ: + case PPC_ID_SPE_EFSCTUF: + case PPC_ID_SPE_EFSCTUI: + case PPC_ID_SPE_EFSCTUIZ: + case PPC_ID_SPE_EVFSCFSF: + case PPC_ID_SPE_EVFSCFSI: + case PPC_ID_SPE_EVFSCFUF: + case PPC_ID_SPE_EVFSCFUI: + case PPC_ID_SPE_EVFSCTSF: + case PPC_ID_SPE_EVFSCTSI: + case PPC_ID_SPE_EVFSCTSIZ: + case PPC_ID_SPE_EVFSCTUF: + case PPC_ID_SPE_EVFSCTUI: + case PPC_ID_SPE_EVFSCTUIZ: + PushRD(instruction, word32); + PushRA(instruction, word32); + break; + + // crfD//, rA, rB + case PPC_ID_SPE_EFDCMPEQ: + case PPC_ID_SPE_EFDCMPGT: + case PPC_ID_SPE_EFDCMPLT: + case PPC_ID_SPE_EFDTSTEQ: + case PPC_ID_SPE_EFDTSTGT: + case PPC_ID_SPE_EFDTSTLT: + case PPC_ID_SPE_EFSCMPEQ: + case PPC_ID_SPE_EFSCMPGT: + case PPC_ID_SPE_EFSCMPLT: + case PPC_ID_SPE_EFSTSTEQ: + case PPC_ID_SPE_EFSTSTGT: + case PPC_ID_SPE_EFSTSTLT: + case PPC_ID_SPE_EVCMPEQ: + case PPC_ID_SPE_EVCMPGTS: + case PPC_ID_SPE_EVCMPGTU: + case PPC_ID_SPE_EVCMPLTS: + case PPC_ID_SPE_EVCMPLTU: + case PPC_ID_SPE_EVFSCMPEQ: + case PPC_ID_SPE_EVFSCMPGT: + case PPC_ID_SPE_EVFSCMPLT: + case PPC_ID_SPE_EVFSTSTEQ: + case PPC_ID_SPE_EVFSTSTGT: + case PPC_ID_SPE_EVFSTSTLT: + PushCRFDImplyCR0(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + break; + + // rD, UIMM, rB + case PPC_ID_SPE_EVADDIW: + case PPC_ID_SPE_EVSUBIFW: + PushRD(instruction, word32); + PushUIMMValue(instruction, (word32 >> 16) & 0x1f); + PushRB(instruction, word32); + break; + + // rD, SIMM, /// + case PPC_ID_SPE_EVSPLATFI: + case PPC_ID_SPE_EVSPLATI: + { + int32_t simm = sign_extend((word32 >> 16) & 0x1f, 5); + PushRD(instruction, word32); + PushSIMMValue(instruction, simm); + break; + } + + // rD, rA, UIMM (SPE) + case PPC_ID_SPE_EVRLWI: + case PPC_ID_SPE_EVSLWI: + case PPC_ID_SPE_EVSRWIS: + case PPC_ID_SPE_EVSRWIU: + PushRD(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, (word32 >> 11) & 0x1f); + break; + + // rD, rA, UIMM (SPE loads) + case PPC_ID_SPE_EVLDD: + case PPC_ID_SPE_EVLDH: + case PPC_ID_SPE_EVLDW: + case PPC_ID_SPE_EVLHHESPLAT: + case PPC_ID_SPE_EVLHHOSSPLAT: + case PPC_ID_SPE_EVLHHOUSPLAT: + case PPC_ID_SPE_EVLWHE: + case PPC_ID_SPE_EVLWHOS: + case PPC_ID_SPE_EVLWHOU: + case PPC_ID_SPE_EVLWHSPLAT: + case PPC_ID_SPE_EVLWWSPLAT: + PushRD(instruction, word32); + PushRAor0(instruction, word32); + PushUIMMValue(instruction, (word32 >> 11) & 0x1f); + break; + + // rS, rA, UIMM (SPE) + case PPC_ID_SPE_EVSTDD: + case PPC_ID_SPE_EVSTDH: + case PPC_ID_SPE_EVSTDW: + case PPC_ID_SPE_EVSTWHE: + case PPC_ID_SPE_EVSTWHO: + case PPC_ID_SPE_EVSTWWE: + case PPC_ID_SPE_EVSTWWO: + PushRS(instruction, word32); + PushRAor0(instruction, word32); + PushUIMMValue(instruction, (word32 >> 11) & 0x1f); + break; + + // rS, rA, rB (SPE store-indexed) + case PPC_ID_SPE_EVSTDDX: + case PPC_ID_SPE_EVSTDHX: + case PPC_ID_SPE_EVSTDWX: + case PPC_ID_SPE_EVSTWHEX: + case PPC_ID_SPE_EVSTWHOX: + case PPC_ID_SPE_EVSTWWEX: + case PPC_ID_SPE_EVSTWWOX: + PushRS(instruction, word32); + PushRA(instruction, word32); + PushUIMMValue(instruction, (word32 >> 11) & 0x1f); + break; + + // rD, rA + case PPC_ID_SPE_EVMR: + case PPC_ID_SPE_EVNOT: + case PPC_ID_SPE_EVRNDW: + PushRD(instruction, word32); + PushRA(instruction, word32); + break; + + // rD, rA, rB, crfS + case PPC_ID_SPE_EVSEL: + { + PushRD(instruction, word32); + PushRA(instruction, word32); + PushRB(instruction, word32); + uint32_t crfs = word32 & 0x7; + PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crfs)); + break; + } + + default: + break; + } +} + +void FillBcxOperands(OperandsList* bcx, const Instruction* instruction) +{ + memset(bcx, 0, sizeof *bcx); + + if (instruction->id != PPC_ID_BCx) + return; + + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + switch (bo & 0x1e) + { + // copy BI, target + case 0: + case 2: + case 8: + case 10: + CopyOperand(&bcx->operands[0], &instruction->operands[1]); + CopyOperand(&bcx->operands[1], &instruction->operands[2]); + bcx->numOperands = 2; + break; + + // copy BI, target + case 4: + case 6: + case 12: + case 14: + { + uint32_t crn = bi >> 2; + + bcx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0; + bcx->operands[0].reg = Crf(crn); + CopyOperand(&bcx->operands[1], &instruction->operands[2]); + bcx->numOperands = 2; + break; + } + + // just copy target + case 16: + case 18: + case 20: + case 22: + case 24: + case 26: + case 28: + case 30: + CopyOperand(&bcx->operands[0], &instruction->operands[2]); + bcx->numOperands = 1; + break; + + // copy BO, BI, target + default: + CopyOperand(&bcx->operands[0], &instruction->operands[0]); + CopyOperand(&bcx->operands[1], &instruction->operands[1]); + CopyOperand(&bcx->operands[2], &instruction->operands[2]); + bcx->numOperands = 3; + + break; + } +} + +void FillBcctrxOperands(OperandsList* bcctrx, const Instruction* instruction) +{ + memset(bcctrx, 0, sizeof *bcctrx); + + if (instruction->id != PPC_ID_BCCTRx) + return; + + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + switch (bo & 0x1e) + { + // copy BI --> crn + case 4: + case 6: + case 12: + case 14: + { + uint32_t crn = bi >> 2; + + bcctrx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0; + bcctrx->operands[0].reg = Crf(crn); + bcctrx->numOperands = 1; + break; + } + + // no ops (BCTR, BCTRL) + case 20: + break; + + // copy BO, BI + default: + CopyOperand(&bcctrx->operands[0], &instruction->operands[0]); + CopyOperand(&bcctrx->operands[1], &instruction->operands[1]); + bcctrx->numOperands = 2; + + break; + } + +} + +void FillBclrxOperands(OperandsList* bclrx, const Instruction* instruction) +{ + memset(bclrx, 0, sizeof *bclrx); + + if (instruction->id != PPC_ID_BCLRx) + return; + + uint32_t bo = instruction->operands[0].uimm; + uint32_t bi = instruction->operands[1].uimm; + + switch (bo & 0x1e) + { + // copy BI + case 0: + case 2: + case 8: + case 10: + CopyOperand(&bclrx->operands[0], &instruction->operands[1]); + bclrx->operands[0].cls = PPC_OP_CRBIT; + bclrx->operands[0].crbit = (uint32_t)instruction->operands[1].uimm; + bclrx->numOperands = 1; + break; + + // copy BI --> crn + case 4: + case 6: + case 12: + case 14: + { + uint32_t crn = bi >> 2; + + bclrx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0; + bclrx->operands[0].reg = Crf(crn); + bclrx->numOperands = 1; + break; + } + + // no ops (decrement CTR, compare to 0, but no condition check) + case 16: + case 18: + case 24: + case 26: + + // no ops (BLR, BLRL) + case 20: + break; + + // copy BO, BI + default: + CopyOperand(&bclrx->operands[0], &instruction->operands[0]); + CopyOperand(&bclrx->operands[1], &instruction->operands[1]); + bclrx->numOperands = 2; + + break; + } +} diff --git a/arch/powerpc/decode/priv.c b/arch/powerpc/decode/priv.c new file mode 100644 index 000000000..c2a9091e5 --- /dev/null +++ b/arch/powerpc/decode/priv.c @@ -0,0 +1,109 @@ +#include "priv.h" + +uint32_t GetA(uint32_t word32) +{ + return (word32 >> 16) & 0x1f; +} + +uint32_t GetB(uint32_t word32) +{ + return (word32 >> 11) & 0x1f; +} + +uint32_t GetC(uint32_t word32) +{ + return (word32 >> 6) & 0x1f; +} + +uint32_t GetD(uint32_t word32) +{ + return (word32 >> 21) & 0x1f; +} + +uint32_t GetS(uint32_t word32) +{ + return (word32 >> 21) & 0x1f; +} + +uint32_t GetBI(uint32_t word32) +{ + return (word32 >> 16) & 0x1f; +} + +uint32_t GetBO(uint32_t word32) +{ + return (word32 >> 21) & 0x1f; +} + +uint32_t GetVsxA(uint32_t word32) +{ + uint32_t ax = (word32 >> 2) & 0x1; + uint32_t a = (word32 >> 16) & 0x1f; + + return (ax << 5) | a; +} + +uint32_t GetVsxB(uint32_t word32) +{ + uint32_t bx = (word32 >> 1) & 0x1; + uint32_t b = (word32 >> 11) & 0x1f; + + return (bx << 5) | b; +} + +uint32_t GetVsxC(uint32_t word32) +{ + uint32_t cx = (word32 >> 3) & 0x1; + uint32_t c = (word32 >> 6) & 0x1f; + + return (cx << 5) | c; +} + +uint32_t GetVsxD(uint32_t word32) +{ + uint32_t dx = word32 & 0x1; + uint32_t d = (word32 >> 21) & 0x1f; + + return (dx << 5) | d; +} + +uint32_t GetSpecialRegisterCommon(uint32_t word32) +{ + uint32_t xr5_9 = (word32 >> 16) & 0x1f; + uint32_t xr0_4 = (word32 >> 11) & 0x1f; + uint32_t xr = (xr0_4 << 5) | xr5_9; + + return xr; +} + +uint32_t GetME(uint32_t word32) +{ + return (word32 >> 1) & 0x1f; +} + +uint32_t GetMB(uint32_t word32) +{ + return (word32 >> 6) & 0x1f; +} + +uint32_t GetSH(uint32_t word32) +{ + return (word32 >> 11) & 0x1f; +} + +uint32_t GetSH64(uint32_t word32) +{ + uint32_t sh5 = (word32 >> 1) & 0x1; + uint32_t sh4_0 = (word32 >> 11) & 0x1f; + + return (sh5 << 5) | sh4_0; +} + +uint32_t GetMX64(uint32_t word32) +{ + uint32_t mx = (word32 >> 5) & 0x3f; + + // x <- mx5 || mx[0:5] in powerpc's stupid bit order + return ((mx & 0x1) << 5) | (mx >> 1); +} + diff --git a/arch/powerpc/decode/priv.h b/arch/powerpc/decode/priv.h new file mode 100644 index 000000000..2dafe9c9b --- /dev/null +++ b/arch/powerpc/decode/priv.h @@ -0,0 +1,27 @@ +#include + +#include "decode.h" + +uint32_t GetA(uint32_t word32); +uint32_t GetB(uint32_t word32); +uint32_t GetC(uint32_t word32); +uint32_t GetD(uint32_t word32); +uint32_t GetS(uint32_t word32); + +uint32_t GetBI(uint32_t word32); +uint32_t GetBO(uint32_t word32); + +uint32_t GetVsxA(uint32_t word32); +uint32_t GetVsxB(uint32_t word32); +uint32_t GetVsxC(uint32_t word32); +uint32_t GetVsxD(uint32_t word32); + +uint32_t GetSpecialRegisterCommon(uint32_t word32); + +uint32_t GetME(uint32_t word32); +uint32_t GetMB(uint32_t word32); +uint32_t GetSH(uint32_t word32); +uint32_t GetSH64(uint32_t word32); +uint32_t GetMX64(uint32_t word32); + +void FillOperands(Instruction* instruction, uint32_t word32, uint64_t address); From 4be6588aa8e3374e2c3222a6033bdad7be65366f Mon Sep 17 00:00:00 2001 From: noone Date: Mon, 30 Dec 2024 09:03:59 -0800 Subject: [PATCH 11/19] Add notion of instruction length --- arch/powerpc/arch_ppc.cpp | 63 +++++++++++++++++++--------------- arch/powerpc/decode/decode.c | 17 ++++++--- arch/powerpc/decode/decode.h | 5 ++- arch/powerpc/decode/operands.c | 2 +- arch/powerpc/decode/priv.h | 2 +- 5 files changed, 54 insertions(+), 35 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 3819ebd91..a5e4fb3eb 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -340,12 +340,22 @@ class PowerpcArchitecture: public Architecture bool FillInstruction(Instruction* instruction, const uint8_t* data, size_t length, uint64_t address) { - uint32_t word32 = *(const uint32_t *) data; + switch (length) + { + case 4: + { + uint32_t word32 = *(const uint32_t *) data; - if (endian == BigEndian) - word32 = bswap32(word32); + if (endian == BigEndian) + word32 = bswap32(word32); - return Decompose(instruction, word32, address, decodeFlags); + return Decompose32(instruction, word32, address, decodeFlags); + } + + default: + MYLOG("FillInstruction: unrecognized length %d", length); + return false; + } } /* think "GetInstructionBranchBehavior()" @@ -361,17 +371,17 @@ class PowerpcArchitecture: public Architecture virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override { - Instruction instruction; - - if (maxLen < 4) + size_t instructionLength = GetInstructionLength(data, maxLen, decodeFlags); + if (instructionLength == 0) { - MYLOG("ERROR: need at least 4 bytes\n"); + MYLOG("ERROR: not enough bytes for instruction\n"); return false; } - result.length = 4; + result.length = instructionLength; - if (!FillInstruction(&instruction, data, maxLen, addr)) + Instruction instruction; + if (!FillInstruction(&instruction, data, instructionLength, addr)) { MYLOG("ERROR: FillInstruction()\n"); return false; @@ -540,15 +550,15 @@ class PowerpcArchitecture: public Architecture const char* mnemonic = NULL; //MYLOG("%s()\n", __func__); - - if (len < 4) + size_t instructionLength = GetInstructionLength(data, len, decodeFlags); + if (instructionLength == 0) { - MYLOG("ERROR: need at least 4 bytes\n"); + MYLOG("ERROR: not enough bytes for instruction\n"); return false; } - len = 4; - if (!FillInstruction(&instruction, data, len, addr)) + len = instructionLength; + if (!FillInstruction(&instruction, data, instructionLength, addr)) { MYLOG("ERROR: FillInstruction()\n"); return false; @@ -740,27 +750,24 @@ class PowerpcArchitecture: public Architecture virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override { - Instruction instruction; - bool rc = false; - - if (len < 4) + size_t instructionLength = GetInstructionLength(data, len, decodeFlags); + if (instructionLength == 0) { - MYLOG("ERROR: need at least 4 bytes\n"); - goto cleanup; + MYLOG("ERROR: not enough bytes for instruction\n"); + return false; } - if (!FillInstruction(&instruction, data, len, addr)) + len = instructionLength; + + Instruction instruction; + if (!FillInstruction(&instruction, data, instructionLength, addr)) { MYLOG("ERROR: FillInstruction()\n"); il.AddInstruction(il.Undefined()); - goto cleanup; + return false; } - rc = GetLowLevelILForPPCInstruction(this, il, &instruction, addr); - len = 4; - - cleanup: - return rc; + return GetLowLevelILForPPCInstruction(this, il, &instruction, addr); } virtual size_t GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c index 1b3b128ee..5cede1acc 100644 --- a/arch/powerpc/decode/decode.c +++ b/arch/powerpc/decode/decode.c @@ -9,6 +9,15 @@ // Implementations of the PowerPC^TM Architecture" by Freescale/NXP // +size_t GetInstructionLength(const uint8_t* data, size_t data_length, uint32_t decodeFlags) +{ + (void)data; + (void)data_length; + (void)decodeFlags; + + return 4; +} + static InstructionId DecodeAltivec0x04(uint32_t word32, uint32_t decodeFlags) { uint32_t subop = word32 & 0x3f; @@ -5429,7 +5438,7 @@ static InstructionId Decode0x3F(uint32_t word32, uint32_t flags) return true; } -static InstructionId Decode(uint32_t word32, uint32_t decodeFlags) +static InstructionId Decode32(uint32_t word32, uint32_t decodeFlags) { uint32_t a = GetA(word32); @@ -5754,14 +5763,14 @@ static InstructionId Decode(uint32_t word32, uint32_t decodeFlags) } } -bool Decompose(Instruction* instruction, uint32_t word32, uint64_t address, uint32_t flags) +bool Decompose32(Instruction* instruction, uint32_t word32, uint64_t address, uint32_t flags) { memset(instruction, 0, sizeof *instruction); - instruction->id = Decode(word32, flags); + instruction->id = Decode32(word32, flags); if (instruction->id == PPC_ID_INVALID) return false; - FillOperands(instruction, word32, address); + FillOperands32(instruction, word32, address); return true; } diff --git a/arch/powerpc/decode/decode.h b/arch/powerpc/decode/decode.h index 4809e4d64..1d1fd7957 100644 --- a/arch/powerpc/decode/decode.h +++ b/arch/powerpc/decode/decode.h @@ -1647,7 +1647,10 @@ extern "C" { typedef struct Instruction Instruction; #endif - bool Decompose(Instruction* instruction, uint32_t word32, uint64_t address, uint32_t flags); + // returns 0 if data_length is too small to tell + size_t GetInstructionLength(const uint8_t* data, size_t data_length, uint32_t flags); + + bool Decompose32(Instruction* instruction, uint32_t word32, uint64_t address, uint32_t flags); void FillBcxOperands(OperandsList* bcx, const Instruction* instruction); void FillBcctrxOperands(OperandsList* bcctrx, const Instruction* instruction); void FillBclrxOperands(OperandsList* bclrx, const Instruction* instruction); diff --git a/arch/powerpc/decode/operands.c b/arch/powerpc/decode/operands.c index 48b695037..aca81918b 100644 --- a/arch/powerpc/decode/operands.c +++ b/arch/powerpc/decode/operands.c @@ -310,7 +310,7 @@ static void PushAltivecVS(Instruction* instruction, uint32_t word32) PushRegister(instruction, PPC_OP_REG_AV_VS, AltivecVr(vs)); } -void FillOperands(Instruction* instruction, uint32_t word32, uint64_t address) +void FillOperands32(Instruction* instruction, uint32_t word32, uint64_t address) { switch (instruction->id) { diff --git a/arch/powerpc/decode/priv.h b/arch/powerpc/decode/priv.h index 2dafe9c9b..f3916343e 100644 --- a/arch/powerpc/decode/priv.h +++ b/arch/powerpc/decode/priv.h @@ -24,4 +24,4 @@ uint32_t GetSH(uint32_t word32); uint32_t GetSH64(uint32_t word32); uint32_t GetMX64(uint32_t word32); -void FillOperands(Instruction* instruction, uint32_t word32, uint64_t address); +void FillOperands32(Instruction* instruction, uint32_t word32, uint64_t address); From 67b4daaabae0a3b3c0c6de8bcffeebd7475b2e29 Mon Sep 17 00:00:00 2001 From: noone Date: Tue, 31 Dec 2024 15:14:43 -0800 Subject: [PATCH 12/19] Clean up some last discrepancies --- arch/powerpc/decode/decode.c | 50 ++++++++++++++++++++++++++++++++-- arch/powerpc/decode/decode.h | 6 ++++ arch/powerpc/decode/mnemonic.c | 6 ++++ arch/powerpc/decode/operands.c | 25 +++++++++++++++-- 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c index 5cede1acc..535062118 100644 --- a/arch/powerpc/decode/decode.c +++ b/arch/powerpc/decode/decode.c @@ -2139,8 +2139,14 @@ static InstructionId Decode0x13(uint32_t word32, uint32_t decodeFlags) case 0x102: return PPC_ID_CRANDC; + case 0x124: + if ((word32 & 0x03fff000) != 0) + return PPC_ID_INVALID; + + return PPC_ID_RFEBB; + case 0x12c: - if ((word32 & 0x3fff800) != 0) + if ((word32 & 0x03fff800) != 0) return PPC_ID_INVALID; return PPC_ID_ISYNC; @@ -2157,15 +2163,33 @@ static InstructionId Decode0x13(uint32_t word32, uint32_t decodeFlags) case 0x202: return PPC_ID_CRAND; + case 0x224: + if ((word32 & 0x03fff801) != 0) + return PPC_ID_INVALID; + + return PPC_ID_HRFID; + case 0x242: if (d == a && d == b) return PPC_ID_CRSET; else return PPC_ID_CREQV; + case 0x2e4: + if ((word32 & 0x03fff801) != 0) + return PPC_ID_INVALID; + + return PPC_ID_STOP; + case 0x342: return PPC_ID_CRORC; + case 0x364: + if ((word32 & 0x03fff801) != 0) + return PPC_ID_INVALID; + + return PPC_ID_NAP; + case 0x382: if (a == b) return PPC_ID_CRMOVE; @@ -3407,7 +3431,7 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return PPC_ID_VSX_STXSSPX; case 0x51d: - if ((word32 & 0x03eff800) != 0) + if ((word32 & 0x01dff800) != 0) return PPC_ID_INVALID; return PPC_ID_TBEGIN; @@ -3829,6 +3853,22 @@ static InstructionId Decode0x1F(uint32_t word32, uint32_t decodeFlags) return true; } +static InstructionId DecodeVsx0x39(uint32_t word32, uint32_t flags) +{ + uint32_t subop = word32 & 0x3; + switch (subop) + { + case 2: + return PPC_ID_VSX_LXSD; + + case 3: + return PPC_ID_VSX_LXSSP; + + default: + return PPC_ID_INVALID; + } +} + static InstructionId Decode0x3B(uint32_t word32, uint32_t flags) { uint32_t a = GetA(word32); @@ -5717,6 +5757,12 @@ static InstructionId Decode32(uint32_t word32, uint32_t decodeFlags) case 0x37: return PPC_ID_STFDU; + case 0x39: + if ((decodeFlags & DECODE_FLAGS_VSX) != 0) + return DecodeVsx0x39(word32, decodeFlags); + else + return PPC_ID_INVALID; + case 0x3a: if ((decodeFlags & DECODE_FLAGS_PPC64) == 0) return PPC_ID_INVALID; diff --git a/arch/powerpc/decode/decode.h b/arch/powerpc/decode/decode.h index 1d1fd7957..f5cd82746 100644 --- a/arch/powerpc/decode/decode.h +++ b/arch/powerpc/decode/decode.h @@ -467,6 +467,7 @@ extern "C" { PPC_ID_FSUBSx, PPC_ID_FTDIV, PPC_ID_FTSQRT, + PPC_ID_HRFID, PPC_ID_ICBI, PPC_ID_ICBIEP, PPC_ID_ICBLC, @@ -619,6 +620,7 @@ extern "C" { PPC_ID_MULLDx, PPC_ID_MULLI, PPC_ID_MULLWx, + PPC_ID_NAP, PPC_ID_NANDx, PPC_ID_NEGx, PPC_ID_NOP, @@ -634,6 +636,7 @@ extern "C" { PPC_ID_PTESYNC, PPC_ID_RFCI, PPC_ID_RFDI, + PPC_ID_RFEBB, PPC_ID_RFI, PPC_ID_RFID, PPC_ID_RFMCI, @@ -706,6 +709,7 @@ extern "C" { PPC_ID_STHUX, PPC_ID_STHX, PPC_ID_STMW, + PPC_ID_STOP, PPC_ID_STSWI, PPC_ID_STSWX, PPC_ID_STW, @@ -1089,11 +1093,13 @@ extern "C" { PPC_ID_AV_VXOR, // VSX instructions + PPC_ID_VSX_LXSD, PPC_ID_VSX_LXSDX, PPC_ID_VSX_LXSIBZX, PPC_ID_VSX_LXSIHZX, PPC_ID_VSX_LXSIWAX, PPC_ID_VSX_LXSIWZX, + PPC_ID_VSX_LXSSP, PPC_ID_VSX_LXSSPX, PPC_ID_VSX_LXV, PPC_ID_VSX_LXVB16X, diff --git a/arch/powerpc/decode/mnemonic.c b/arch/powerpc/decode/mnemonic.c index 8148d5837..45bbea921 100644 --- a/arch/powerpc/decode/mnemonic.c +++ b/arch/powerpc/decode/mnemonic.c @@ -708,6 +708,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_FSUBSx: return RcMnemonic(instruction, SubMnemFSUBSx); case PPC_ID_FTDIV: return "ftdiv"; case PPC_ID_FTSQRT: return "ftsqrt"; + case PPC_ID_HRFID: return "hrfid"; case PPC_ID_ICBI: return "icbi"; case PPC_ID_ICBIEP: return "icbiep"; case PPC_ID_ICBLC: return "icblc"; @@ -852,6 +853,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_MULLDx: return OeRcMnemonic(instruction, SubMnemMULLDx); case PPC_ID_MULLWx: return OeRcMnemonic(instruction, SubMnemMULLWx); case PPC_ID_NANDx: return RcMnemonic(instruction, SubMnemNANDx); + case PPC_ID_NAP: return "nap"; case PPC_ID_NEGx: return OeRcMnemonic(instruction, SubMnemNEGx); case PPC_ID_NOP: return "nop"; case PPC_ID_NORx: return RcMnemonic(instruction, SubMnemNORx); @@ -866,6 +868,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_PTESYNC: return "ptesync"; case PPC_ID_RFCI: return "rfci"; case PPC_ID_RFDI: return "rfdi"; + case PPC_ID_RFEBB: return "rfebb"; case PPC_ID_RFI: return "rfi"; case PPC_ID_RFID: return "rfid"; case PPC_ID_RFMCI: return "rfmci"; @@ -938,6 +941,7 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_STHUX: return "sthux"; case PPC_ID_STHX: return "sthx"; case PPC_ID_STMW: return "stmw"; + case PPC_ID_STOP: return "stop"; case PPC_ID_STSWI: return "stswi"; case PPC_ID_STSWX: return "stswx"; case PPC_ID_STW: return "stw"; @@ -1319,11 +1323,13 @@ const char* GetMnemonic(const Instruction* instruction) case PPC_ID_AV_VUPKLSW: return "vupklsw"; case PPC_ID_AV_VXOR: return "vxor"; + case PPC_ID_VSX_LXSD: return "lxsd"; case PPC_ID_VSX_LXSDX: return "lxsdx"; case PPC_ID_VSX_LXSIBZX: return "lxsibzx"; case PPC_ID_VSX_LXSIHZX: return "lxsihzx"; case PPC_ID_VSX_LXSIWAX: return "lxsiwax"; case PPC_ID_VSX_LXSIWZX: return "lxsiwzx"; + case PPC_ID_VSX_LXSSP: return "lxssp"; case PPC_ID_VSX_LXSSPX: return "lxsspx"; case PPC_ID_VSX_LXV: return "lxv"; case PPC_ID_VSX_LXVB16X: return "lxvb16x"; diff --git a/arch/powerpc/decode/operands.c b/arch/powerpc/decode/operands.c index aca81918b..cca497d18 100644 --- a/arch/powerpc/decode/operands.c +++ b/arch/powerpc/decode/operands.c @@ -280,6 +280,11 @@ static void PushVsxS(Instruction* instruction, uint32_t word32, VsxWidth width) VsxVr((sx << 5) | s)); } +static void PushVsxHiS(Instruction* instruction, uint32_t word32) +{ + PushRegister(instruction, PPC_OP_REG_VSX_RS, VsxVrHi(GetS(word32))); +} + static void PushAltivecVA(Instruction* instruction, uint32_t word32) { uint32_t va = (word32 >> 16) & 0x1f; @@ -318,10 +323,12 @@ void FillOperands32(Instruction* instruction, uint32_t word32, uint64_t address) case PPC_ID_ATTN: case PPC_ID_CP_ABORT: case PPC_ID_DCCCI: + case PPC_ID_HRFID: case PPC_ID_ICCCI: case PPC_ID_ISYNC: case PPC_ID_LWSYNC: case PPC_ID_MSGSYNC: + case PPC_ID_NAP: case PPC_ID_NOP: case PPC_ID_PTESYNC: case PPC_ID_RFCI: @@ -329,6 +336,7 @@ void FillOperands32(Instruction* instruction, uint32_t word32, uint64_t address) case PPC_ID_RFI: case PPC_ID_RFID: case PPC_ID_RFMCI: + case PPC_ID_STOP: case PPC_ID_SYNC: case PPC_ID_TLBIA: case PPC_ID_TLBSYNC: @@ -1488,6 +1496,10 @@ void FillOperands32(Instruction* instruction, uint32_t word32, uint64_t address) PushRB(instruction, word32); break; + case PPC_ID_RFEBB: + PushUIMMValue(instruction, (word32 >> 11) & 0x1); + break; + case PPC_ID_RLWIMIx: case PPC_ID_RLWINMx: PushRA(instruction, word32); @@ -2389,6 +2401,16 @@ void FillOperands32(Instruction* instruction, uint32_t word32, uint64_t address) PushUIMMValue(instruction, (word32 >> 16) & 0xf); break; + case PPC_ID_VSX_LXSD: + case PPC_ID_VSX_LXSSP: + { + PushVsxHiD(instruction, word32); + + int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); + PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); + break; + } + case PPC_ID_VSX_LXV: { uint32_t dx = (word32 >> 3) & 0x1; @@ -2420,8 +2442,7 @@ void FillOperands32(Instruction* instruction, uint32_t word32, uint64_t address) case PPC_ID_VSX_STXSD: case PPC_ID_VSX_STXSSP: { - uint32_t xs = GetS(word32) + 32; - PushRegister(instruction, PPC_OP_REG_VSX_RS, VsxVr(xs)); + PushVsxHiS(instruction, word32); int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc)); PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds); From a7b9d06d9f633bf606a1feb4a6fa4e0495c25826 Mon Sep 17 00:00:00 2001 From: noone Date: Tue, 31 Dec 2024 15:17:27 -0800 Subject: [PATCH 13/19] Add capstone comparison test --- arch/powerpc/build_capstone_compare.sh | 2 + arch/powerpc/capstone_compare_test.c | 1875 ++++++++++++++++++++++++ 2 files changed, 1877 insertions(+) create mode 100755 arch/powerpc/build_capstone_compare.sh create mode 100644 arch/powerpc/capstone_compare_test.c diff --git a/arch/powerpc/build_capstone_compare.sh b/arch/powerpc/build_capstone_compare.sh new file mode 100755 index 000000000..ed806267b --- /dev/null +++ b/arch/powerpc/build_capstone_compare.sh @@ -0,0 +1,2 @@ +#!/bin/sh +gcc -I decode decode/decode.c decode/mnemonic.c decode/names.c decode/operands.c decode/priv.c capstone_compare_test.c -l capstone -g -Wall -O3 -o capstone_compare.bin diff --git a/arch/powerpc/capstone_compare_test.c b/arch/powerpc/capstone_compare_test.c new file mode 100644 index 000000000..0c64c0eb2 --- /dev/null +++ b/arch/powerpc/capstone_compare_test.c @@ -0,0 +1,1875 @@ +#include +#include +#include + +#include "capstone/capstone.h" + +#include "decode/decode.h" + +bool crbit_equal(ppc_reg cs_reg, uint32_t crbit) +{ + if (crbit >= 32) + { + printf("invalid new crbit %d\n", crbit); + return false; + } + + if (cs_reg < PPC_REG_CR0EQ || cs_reg > PPC_REG_CR7UN) + { + printf("invalid cs crbit cs reg %d\n", cs_reg); + return false; + } + + uint32_t crn = 0; + uint32_t bit = 0; + if (PPC_REG_CR0EQ <= cs_reg && cs_reg <= PPC_REG_CR7EQ) + { + crn = cs_reg - PPC_REG_CR0EQ; + bit = 2; + } + else if (PPC_REG_CR0GT <= cs_reg && cs_reg <= PPC_REG_CR7GT) + { + crn = cs_reg - PPC_REG_CR0GT; + bit = 1; + } + else if (PPC_REG_CR0LT <= cs_reg && cs_reg <= PPC_REG_CR7LT) + { + crn = cs_reg - PPC_REG_CR0LT; + bit = 0; + } else { + // PPC_REG_CR0UN <= cs_reg && cs_reg <= PPC_REG_CR7UN + crn = cs_reg - PPC_REG_CR0UN; + bit = 3; + } + + uint32_t cs_equivalent = 4*crn + bit; + return crbit == cs_equivalent; +} + +bool ops_equal(csh handle, const cs_ppc_op* capstone_op, const Operand* new_op) +{ + switch (new_op->cls) + { + case PPC_OP_NONE: return capstone_op->type == PPC_OP_INVALID; + + case PPC_OP_UIMM: + { + // handle RA|0 + if (capstone_op->type == PPC_OP_REG) + { + if (capstone_op->reg == PPC_REG_INVALID) + { + if (new_op->uimm != 0) + { + printf("new operand is UIMM %ld != 0, when capstone is PPC_REG_INVALID\n", + new_op->uimm); + + return false; + } + + return true; + } + + printf("new operand is UIMM %ld, capstone is REG %d != PPC_REG_INVALID\n", + new_op->uimm, capstone_op->reg); + return false; + } + + if (capstone_op->type != PPC_OP_IMM) + { + printf("new operand is UIMM, but capstone is %d\n", capstone_op->type); + return false; + } + + int64_t capstone_imm = capstone_op->imm; + int64_t new_imm = new_op->uimm; + + if (capstone_imm != new_imm) + { + printf("new operand UIMM is %#lx, capstone imm is %#lx\n", + new_imm, capstone_imm); + return false; + } + + return true; + } + + case PPC_OP_SIMM: + { + if (capstone_op->type != PPC_OP_IMM) + { + printf("new operand is SIMM, but capstone is %d\n", capstone_op->type); + return false; + } + + int64_t capstone_imm = capstone_op->imm; + int64_t new_imm = new_op->simm; + + if (capstone_imm != new_imm) + { + printf("new operand SIMM is %#lx, capstone imm is %#lx\n", + new_imm, capstone_imm); + return false; + } + + return true; + } + + case PPC_OP_REG_RA: + case PPC_OP_REG_RB: + case PPC_OP_REG_RC: + case PPC_OP_REG_RD: + case PPC_OP_REG_RS: + { + if (capstone_op->type != PPC_OP_REG) + { + printf("new operand is register, but capstone is %d\n", capstone_op->type); + return false; + } + + int capstone_reg = capstone_op->reg - PPC_REG_R0; + int new_reg = new_op->reg - NUPPC_REG_GPR0; + + if (capstone_reg != new_reg) + { + printf("new operand register %d, capstone register %d\n", + new_reg, capstone_reg); + + return false; + } + + return true; + } + + case PPC_OP_REG_FRA: + case PPC_OP_REG_FRB: + case PPC_OP_REG_FRC: + case PPC_OP_REG_FRD: + case PPC_OP_REG_FRS: + { + if (capstone_op->type != PPC_OP_REG) + { + printf("new operand is register, but capstone is %d\n", capstone_op->type); + return false; + } + + int capstone_reg = capstone_op->reg - PPC_REG_F0; + int new_reg = new_op->reg - NUPPC_REG_FR0; + + if (capstone_reg != new_reg) + { + printf("new operand register %d, capstone register %d\n", + new_reg, capstone_reg); + + return false; + } + + return true; + } + + case PPC_OP_REG_CRFD: + case PPC_OP_REG_CRFD_IMPLY0: + case PPC_OP_REG_CRFS: + { + if (capstone_op->type != PPC_OP_REG) + { + printf("new operand is CR, but capstone is %d\n", capstone_op->type); + return false; + } + + int capstone_reg = capstone_op->reg - PPC_REG_CR0; + int new_reg = new_op->reg - NUPPC_REG_CRF0; + + if (capstone_reg != new_reg) + { + printf("new operand CR %d, capstone CR register %d\n", + new_reg, capstone_reg); + + return false; + } + + return true; + } + + case PPC_OP_CRBIT_A: + case PPC_OP_CRBIT_B: + case PPC_OP_CRBIT_D: + { + if (capstone_op->type != PPC_OP_REG) + { + printf("new operand is CRbit, but capstone is %d\n", capstone_op->type); + return false; + } + + const char* capstone_name = cs_reg_name(handle, capstone_op->reg); + + if (!crbit_equal(capstone_op->reg, new_op->crbit)) + { + printf("new operand CR %d, capstone CR register %d (%s)\n", + new_op->crbit, capstone_op->reg, capstone_name); + + return false; + } + + return true; + } + + case PPC_OP_REG_AV_VA: + case PPC_OP_REG_AV_VB: + case PPC_OP_REG_AV_VC: + case PPC_OP_REG_AV_VD: + case PPC_OP_REG_AV_VS: + { + if (capstone_op->type != PPC_OP_REG) + { + printf("new operand is altivec register, but capstone is %d\n", capstone_op->type); + return false; + } + + int capstone_reg = capstone_op->reg - PPC_REG_V0; + int new_reg = new_op->reg - NUPPC_REG_AV_VR0; + + if (capstone_reg != new_reg) + { + printf("new operand altivec register %d, capstone altivec register %d\n", + new_reg, capstone_reg); + + return false; + } + + return true; + } + + case PPC_OP_REG_VSX_RA: + case PPC_OP_REG_VSX_RB: + case PPC_OP_REG_VSX_RC: + case PPC_OP_REG_VSX_RD: + case PPC_OP_REG_VSX_RS: + { + if (capstone_op->type != PPC_OP_REG) + { + printf("new operand is vsx (full) register, but capstone is %d\n", capstone_op->type); + return false; + } + + const char* capstone_name = cs_reg_name(handle, capstone_op->reg); + int new_reg = new_op->reg - NUPPC_REG_VSX_VR0; + int capstone_reg; + if (PPC_REG_VS0 <= capstone_op->reg && capstone_op->reg <= PPC_REG_VS63) + capstone_reg = capstone_op->reg - PPC_REG_VS0; + else if (PPC_REG_V0 <= capstone_op->reg && capstone_op->reg <= PPC_REG_V31) + capstone_reg = capstone_op->reg - PPC_REG_V0 + 32; + else + { + printf("new operand vsx (full) register %d, capstone register %d (%s) isn't any kind of vector\n", new_reg, capstone_op->reg, capstone_name); + + return false; + } + + if (capstone_reg != new_reg) + { + printf("new operand vsx (full) register %d, capstone vsx register %d (%s)\n", + new_reg, capstone_reg, capstone_name); + + return false; + } + + return true; + } + + case PPC_OP_REG_VSX_RA_DWORD0: + case PPC_OP_REG_VSX_RB_DWORD0: + case PPC_OP_REG_VSX_RC_DWORD0: + case PPC_OP_REG_VSX_RD_DWORD0: + case PPC_OP_REG_VSX_RS_DWORD0: + { + if (capstone_op->type != PPC_OP_REG) + { + printf("new operand is vsx (dword0) register, but capstone is %d\n", capstone_op->type); + return false; + } + + const char* capstone_name = cs_reg_name(handle, capstone_op->reg); + int new_reg = new_op->reg - NUPPC_REG_VSX_VR0; + int capstone_reg; + if (PPC_REG_VS0 <= capstone_op->reg && capstone_op->reg <= PPC_REG_VS63) + capstone_reg = capstone_op->reg - PPC_REG_VS0; + else if (PPC_REG_V0 <= capstone_op->reg && capstone_op->reg <= PPC_REG_V31) + capstone_reg = capstone_op->reg - PPC_REG_V0 + 32; + else if (PPC_REG_F0 <= capstone_op->reg && capstone_op->reg <= PPC_REG_F31) + capstone_reg = capstone_op->reg - PPC_REG_F0; + else + { + printf("new operand vsx (dword0) register %d, capstone register %d (%s) isn't any kind of vector\n", new_reg, capstone_op->reg, capstone_name); + + return false; + } + + + if (capstone_reg != new_reg) + { + printf("new operand vsx (dword0) register %d, capstone vsx register %d (%s)\n", + new_reg, capstone_reg, capstone_name); + + return false; + } + + return true; + } + + case PPC_OP_MEM_RA: + { + if (capstone_op->type != PPC_OP_MEM) + { + printf("new operand is memory, but capstone is %d\n", capstone_op->type); + return false; + } + + // memory are of the form RA|0 + int new_reg = new_op->mem.reg - NUPPC_REG_GPR0; + if (new_reg == 0) + { + if (capstone_op->mem.base != PPC_REG_INVALID) + { + printf("new operand mem reg is r0, capstone mem reg is %d != invalid\n", + capstone_op->mem.base); + return false; + } + } + else + { + int capstone_reg = capstone_op->mem.base - PPC_REG_R0; + if (capstone_reg != new_reg) + { + printf("new operand mem reg is %d, capstone mem reg is %d\n", + new_reg, capstone_reg); + return false; + } + } + + int capstone_offset = capstone_op->mem.disp; + int new_offset = new_op->mem.offset; + + if (capstone_offset != new_offset) + { + printf("new operand mem offset is %d, capstone mem offset is %d\n", + new_offset, capstone_offset); + + return false; + } + + return true; + } + + default: + printf("unhandled class %d\n", new_op->cls); + return false; + } + +} + +uint32_t bc_to_bi(ppc_bc bc) +{ + switch (bc) + { + case PPC_BC_LT: return 0; + case PPC_BC_GT: return 1; + case PPC_BC_EQ: return 2; + case PPC_BC_SO: return 3; + default: return 0xffffffff; + } +} + +uint32_t crx_to_bi(const ppc_op_crx* crx) +{ + uint32_t crn = (crx->reg - PPC_REG_CR0); + uint32_t extra = 0; + switch (crx->cond) + { + case PPC_BC_LT: extra = 0; break; + case PPC_BC_GT: extra = 1; break; + case PPC_BC_EQ: extra = 2; break; + case PPC_BC_SO: extra = 3; break; + + default: + printf("bcx capstone op 0 cond is weird %d\n", + crx->cond); + return 0xffffffff; + } + + return crx->scale*crn + extra; +} + +// compare bcx