summaryrefslogtreecommitdiff
path: root/arch/powerpc/decode/decode.c
diff options
context:
space:
mode:
authorGalen Williamson <galen@vector35.com>2025-06-29 11:23:58 -0400
committerGalen Williamson <galen@vector35.com>2025-06-29 18:28:48 -0400
commite8206bc27e1633c7e4c99907f43bf67d2f200cd5 (patch)
tree2315bec284e9bb692a0eb8986578fe18e2289d23 /arch/powerpc/decode/decode.c
parent91f1eccb6c41a7ef60fd66387ffae075f88141a4 (diff)
[powerpc] Full merge of PowerPC disassembler PRs, including:
* Remove dependency on capstone for PowerPC disassembly #6292 * Add support for PowerPC VLE instruction set #6740 * Add support for paired-single instructions #6821 * Various post-merge fixes and tweaks to disassembly and lifting * Removal of dependence on capstone for assembler's scoring mechanism (capstone currently disabled, but not removed from codebase yet)
Diffstat (limited to 'arch/powerpc/decode/decode.c')
-rw-r--r--arch/powerpc/decode/decode.c6110
1 files changed, 6110 insertions, 0 deletions
diff --git a/arch/powerpc/decode/decode.c b/arch/powerpc/decode/decode.c
new file mode 100644
index 00000000..fc5dc9d5
--- /dev/null
+++ b/arch/powerpc/decode/decode.c
@@ -0,0 +1,6110 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "decode.h"
+#include "priv.h"
+
+// Documentation:
+// * [ProgrammingEnvironments32]: "Programming Environments Manual for 32-bit
+// Implementations of the PowerPC^TM Architecture" by Freescale/NXP
+//
+
+size_t
+GetInstructionLength(const uint8_t* data, size_t data_length, uint32_t decodeFlags)
+{
+ size_t instruction_length = 0;
+ if ((decodeFlags & DECODE_FLAGS_VLE) != 0)
+ {
+ instruction_length = VleGetInstructionLength(data, data_length, decodeFlags);
+ }
+ else
+ {
+ // All other powerpc flavors have fixed 32-bit instructions
+ instruction_length = 4;
+ }
+
+ if (data_length < instruction_length)
+ return 0;
+
+ return instruction_length;
+}
+
+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 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:
+ ;
+ }
+
+ subop = word32 & 0x7ff;
+ switch (subop)
+ {
+ 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;
+
+ case 0x004:
+ return PPC_ID_AV_VRLB;
+
+
+ case 0x006:
+ case 0x406:
+ return PPC_ID_AV_VCMPEQUBx;
+
+ case 0x007:
+ case 0x407:
+ return PPC_ID_AV_VCMPNEBx;
+
+ 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 0x041:
+ return PPC_ID_AV_VMUL10ECUQ;
+
+ case 0x042:
+ return PPC_ID_AV_VMAXUH;
+
+ case 0x044:
+ return PPC_ID_AV_VRLH;
+
+
+ case 0x046:
+ case 0x446:
+ return PPC_ID_AV_VCMPEQUHx;
+
+ case 0x047:
+ case 0x447:
+ return PPC_ID_AV_VCMPNEHx;
+
+ 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 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;
+
+ 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 0x0c5:
+ return PPC_ID_AV_VRLDMI;
+
+ 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 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;
+
+ 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 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;
+
+ 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 0x185:
+ return PPC_ID_AV_VRLWNM;
+
+ case 0x187:
+ case 0x587:
+ return PPC_ID_AV_VCMPNEZWx;
+
+ 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 0x1c5:
+ return PPC_ID_AV_VRLDNM;
+
+ 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 0x201:
+ if (b != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_AV_VMUL10UQ;
+
+ 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 0x20d:
+ if ((word32 & 0x00100000) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_AV_VEXTRACTUB;
+
+ case 0x20e:
+ if (a != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_AV_VUPKHSB;
+
+ case 0x240:
+ return PPC_ID_AV_VADDUHS;
+
+ case 0x241:
+ return PPC_ID_AV_VMUL10EUQ;
+
+ 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 0x24d:
+ if ((word32 & 0x00100000) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_AV_VEXTRACTUH;
+
+ 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 0x28d:
+ if ((word32 & 0x00100000) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_AV_VEXTRACTUW;
+
+ 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 0x2cd:
+ if ((word32 & 0x00100000) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_AV_VEXTRACTD;
+
+ 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 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;
+
+ 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 0x34d:
+ if ((word32 & 0x00100000) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_AV_VINSERTH;
+
+ 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 0x38d:
+ if ((word32 & 0x00100000) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_AV_VINSERTW;
+
+ 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 0x3cd:
+ if ((word32 & 0x00100000) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_AV_VINSERTD;
+
+ case 0x3ce:
+ if (a != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_AV_VUPKLPX;
+
+ 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;
+
+ case 0x40c:
+ return PPC_ID_AV_VSLO;
+
+ 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:
+ 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:
+ 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;
+
+ 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;
+
+ 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 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;
+
+ 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 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;
+
+ 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 0x744:
+ return PPC_ID_AV_VSLV;
+
+ case 0x74d:
+ return PPC_ID_AV_VEXTUHRX;
+
+ 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 0x78c:
+ return PPC_ID_AV_VMRGEW;
+
+ case 0x78d:
+ return PPC_ID_AV_VEXTUWRX;
+
+ 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 DecodeSpe0x04(uint32_t word32, uint32_t decodeFlags)
+{
+ uint32_t a = GetA(word32);
+ uint32_t b = GetB(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 DecodePairedSingle0x04(uint32_t word32, uint32_t decodeFlags)
+{
+ uint32_t a = GetA(word32);
+ uint32_t b = GetB(word32);
+ uint32_t c = GetC(word32);
+ uint32_t d = GetD(word32);
+
+ // see IBM Broadway RISC Microprocessor User's Manual,
+ // Tables A-30, A-31, and A-32
+ uint32_t subop = (word32 >> 1) & 0x1f;
+ switch (subop)
+ {
+ case 10:
+ return PPC_ID_PAIREDSINGLE_PS_SUM0x;
+
+ case 11:
+ return PPC_ID_PAIREDSINGLE_PS_SUM1x;
+
+ case 12:
+ if (b != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_MULS0x;
+
+ case 13:
+ if (b != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_MULS1x;
+
+ case 14:
+ return PPC_ID_PAIREDSINGLE_PS_MADDS0x;
+
+ case 15:
+ return PPC_ID_PAIREDSINGLE_PS_MADDS1x;
+
+ case 18:
+ if (c != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_DIVx;
+
+ case 20:
+ if (c != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_SUBx;
+
+ case 21:
+ if (c != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_ADDx;
+
+ case 23:
+ return PPC_ID_PAIREDSINGLE_PS_SELx;
+
+ case 24:
+ if ((a != 0) || (c != 0))
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_RESx;
+
+ case 25:
+ if (b != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_MULx;
+
+ case 26:
+ if ((a != 0) || (c != 0))
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_RSQRTEx;
+
+ case 28:
+ return PPC_ID_PAIREDSINGLE_PS_MSUBx;
+
+ case 29:
+ return PPC_ID_PAIREDSINGLE_PS_MADDx;
+
+ case 30:
+ return PPC_ID_PAIREDSINGLE_PS_NMSUBx;
+
+ case 31:
+ return PPC_ID_PAIREDSINGLE_PS_NMADDx;
+
+ default:
+ ;
+ }
+
+ subop = (word32 >> 1) & 0x3f;
+ switch (subop)
+ {
+ case 6:
+ if ((word32 & 0x1) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PSQ_LX;
+
+ case 7:
+ if ((word32 & 0x1) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PSQ_STX;
+
+ case 38:
+ if ((word32 & 0x1) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PSQ_LUX;
+
+ case 39:
+ if ((word32 & 0x1) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PSQ_STUX;
+
+ default:
+ ;
+ }
+
+ subop = (word32 >> 1) & 0x3ff;
+ switch (subop)
+ {
+ case 0:
+ if ((word32 & 0x00600001) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_CMPU0;
+
+ case 32:
+ if ((word32 & 0x00600001) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_CMPO0;
+
+ case 40:
+ if (a != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_NEGx;
+
+ case 64:
+ if ((word32 & 0x00600001) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_CMPU1;
+
+ case 72:
+ if (a != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_MRx;
+
+ case 96:
+ if ((word32 & 0x00600001) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_CMPO1;
+
+ case 136:
+ if (a != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_NABSx;
+
+ case 264:
+ if (a != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_PS_ABSx;
+
+ case 528:
+ return PPC_ID_PAIREDSINGLE_PS_MERGE00x;
+
+ case 560:
+ return PPC_ID_PAIREDSINGLE_PS_MERGE01x;
+
+ case 592:
+ return PPC_ID_PAIREDSINGLE_PS_MERGE10x;
+
+ case 624:
+ return PPC_ID_PAIREDSINGLE_PS_MERGE11x;
+
+ case 1014:
+ if ((d != 0) || ((word32 & 0x1) != 0))
+ return PPC_ID_INVALID;
+
+ return PPC_ID_PAIREDSINGLE_DCBZ_L;
+
+ 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 >> 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:
+ 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;
+
+ 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 0x124:
+ if ((word32 & 0x03fff000) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_RFEBB;
+
+ case 0x12c:
+ if ((word32 & 0x03fff800) != 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 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;
+ else
+ return PPC_ID_CROR;
+
+ 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;
+
+ 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)
+ {
+ // PPC_ID_RLDICLx
+ case 0x0:
+ case 0x1:
+ // EXTRDIx: n = sh > 0
+ if (mx == 0)
+ return PPC_ID_ROTLDIx;
+ // Encoding of ROTRDIx is impossible to distinguish from ROTLDIx:
+ // return PPC_ID_ROTRDIx;
+ else if (sh + mx == 64)
+ return PPC_ID_SRDIx;
+ else if (sh == 0)
+ return PPC_ID_CLRLDIx;
+ // else if (sh > 0)
+ // return PPC_ID_EXTRDIx;
+ else
+ return PPC_ID_RLDICLx;
+
+ // PPC_ID_RLDICRx
+ case 0x2:
+ case 0x3:
+ // EXTLDIx: n = sh > 0
+ if (sh + mx == 63)
+ return PPC_ID_SLDIx;
+ else if (sh == 0)
+ return PPC_ID_CLRRDIx;
+ // else if (sh > 0)
+ // return PPC_ID_EXTLDIx;
+ // else
+ 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;
+ }
+}
+
+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:
+ {
+ if ((GetA(word32) == 0) && (GetB(word32) == 0))
+ return PPC_ID_TRAP;
+
+ 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 0x018:
+ case 0x019:
+ return PPC_ID_VSX_LXSIWZX;
+
+ 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:
+ case 0x029:
+ return PPC_ID_LWARX;
+
+ case 0x02a:
+ return PPC_ID_LDX;
+
+ case 0x02c:
+ 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 0x03e:
+ return PPC_ID_LWEPX;
+
+ 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 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;
+
+ 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 0x07e:
+ if (d != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_DCBSTEP;
+
+ case 0x03c:
+ {
+ 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 0x098:
+ case 0x099:
+ return PPC_ID_VSX_LXSIWAX;
+
+ case 0x0a6:
+ if ((a != 0) || (b != 0))
+ return PPC_ID_INVALID;
+
+ return PPC_ID_MFMSR;
+
+ case 0x0a8:
+ case 0x0a9:
+ return PPC_ID_LDARX;
+
+ case 0x0ac:
+ {
+ if ((word32 & 0x03800000) != 0)
+ return PPC_ID_INVALID;
+
+ 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;
+
+ return PPC_ID_INVALID;
+
+ case 0x0d0:
+ case 0x0d1:
+ case 0x4d0:
+ case 0x4d1:
+ if (b != 0)
+ return PPC_ID_INVALID;
+
+ 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:
+ // TODO: PPC_ID_NOTx pseudo-instruction
+ 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;
+
+ 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 0x118:
+ case 0x119:
+ return PPC_ID_VSX_STXSIWX;
+
+ 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 0x13a:
+ return PPC_ID_STDEPX;
+
+ case 0x13e:
+ return PPC_ID_STWEPX;
+
+ 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 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 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;
+
+ 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 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;
+
+ 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 0x1e6:
+ case 0x1e7:
+ if (b != 0)
+ return PPC_ID_INVALID;
+
+ 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;
+
+ return PPC_ID_TLBIEL;
+
+ case 0x22c:
+ {
+ uint32_t th = (word32 >> 21) & 0x1f;
+ if (th == 0x10)
+ return PPC_ID_DCBTT;
+ else
+ return PPC_ID_DCBT;
+ }
+
+ case 0x22e:
+ return PPC_ID_LHZX;
+
+ case 0x238:
+ 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;
+
+ case 0x26e:
+ return PPC_ID_LHZUX;
+
+ case 0x278:
+ case 0x279:
+ return PPC_ID_XORx;
+
+ case 0x27e:
+ return PPC_ID_DCBTEP;
+
+ 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 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);
+
+ // there are a bunch of other MF<some specific SPR>
+ // 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 0x2d8:
+ case 0x2d9:
+ return PPC_ID_VSX_LXVWSX;
+
+ 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 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;
+
+ case 0x338:
+ 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;
+
+ 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 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);
+
+ switch (spr)
+ {
+ // there are a bunch of other MF<some specific SPR>
+ // 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 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;
+
+ 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 0x418:
+ case 0x419:
+ return PPC_ID_VSX_LXSSPX;
+
+ 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 0x434:
+ case 0x435:
+ if (b != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_CNTTZWx;
+
+ 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 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)
+ 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 0x4be:
+ return PPC_ID_LFDEPX;
+
+ case 0x4cc:
+ return PPC_ID_LDAT;
+
+ case 0x4ee:
+ return PPC_ID_LFDUX;
+
+ case 0x4e4:
+ if ((word32 & 0x03fff800) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_TLBIA;
+
+ case 0x518:
+ case 0x519:
+ return PPC_ID_VSX_STXSSPX;
+
+ case 0x51d:
+ if ((word32 & 0x01dff800) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_TBEGIN;
+
+ 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 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)
+ return PPC_ID_INVALID;
+
+ 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;
+
+ return PPC_ID_DCBA;
+
+ 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)
+ return PPC_ID_INVALID;
+
+ 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;
+
+ 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 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;
+
+ 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 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)
+ return PPC_ID_INVALID;
+
+ 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;
+
+ 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 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:
+ if ((decodeFlags & DECODE_FLAGS_VSX) == 0)
+ return PPC_ID_INVALID;
+
+ 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;
+
+ 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 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;
+ 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 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;
+
+ // 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;
+ }
+
+ case 0x7fe:
+ if (d != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_DCBZEP;
+
+ default:
+ return PPC_ID_INVALID;
+ }
+
+ 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);
+ 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 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 >> 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;
+
+ 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 0x0a5:
+ if ((word32 & 0x00100000) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_VSX_XXEXTRACTUW;
+
+ 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 0x0aa:
+ 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 0x0b5:
+ if ((word32 & 0x00100000) != 0)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_VSX_XXINSERTW;
+
+ 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 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;
+
+ return PPC_ID_VSX_XSCVDPUXDS;
+
+ case 0x149:
+ if ((word32 & 0x001f0000) != 0x0)
+ return PPC_ID_INVALID;
+
+ 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;
+
+ return PPC_ID_VSX_XSCVDPSXDS;
+
+ case 0x159:
+ if ((word32 & 0x001f0000) != 0x0)
+ return PPC_ID_INVALID;
+
+ 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;
+
+ return PPC_ID_VSX_XSCVUXDDP;
+
+ case 0x169:
+ if ((word32 & 0x001f0000) != 0x0)
+ return PPC_ID_INVALID;
+
+ 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;
+
+ 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 0x1db:
+ {
+ uint32_t subsubop = (word32 >> 16) & 0x1f;
+ switch (subsubop)
+ {
+ case 0x00:
+ return PPC_ID_VSX_XVXEXPDP;
+
+ case 0x01:
+ return PPC_ID_VSX_XVXSIGDP;
+
+ case 0x07:
+ return PPC_ID_VSX_XXBRH;
+
+ case 0x08:
+ return PPC_ID_VSX_XVXEXPSP;
+
+ 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;
+
+ 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:
+ return PPC_ID_VSX_XSADDSP;
+
+ case 0x01:
+ return PPC_ID_VSX_XSMADDASP;
+
+ case 0x02:
+ case 0x22:
+ case 0x42:
+ 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:
+ 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 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;
+
+ 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 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;
+
+ 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 0x80:
+ return PPC_ID_VSX_XSMAXCDP;
+
+ case 0x81:
+ return PPC_ID_VSX_XSNMADDASP;
+
+ case 0x82:
+ return PPC_ID_VSX_XXLAND;
+
+ case 0x88:
+ return PPC_ID_VSX_XSMINCDP;
+
+ case 0x89:
+ 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;
+
+ 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 0xd5:
+ case 0xdd:
+ return PPC_ID_VSX_XVTSTDCSP;
+
+ case 0xd8:
+ return PPC_ID_VSX_XVIEXPSP;
+
+ 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 0xf5:
+ case 0xfd:
+ return PPC_ID_VSX_XVTSTDCDP;
+
+ case 0xf8:
+ return PPC_ID_VSX_XVIEXPDP;
+
+ case 0xf9:
+ return PPC_ID_VSX_XVNMSUBMDP;
+
+ default:
+ return PPC_ID_INVALID;
+ }
+}
+
+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);
+ 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 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;
+
+ 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 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 0x040:
+ if ((word32 & 0x00600000) != 0)
+ return PPC_ID_INVALID;
+
+ 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))
+ 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 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)
+ return PPC_ID_INVALID;
+
+ return PPC_ID_MTFSFIx;
+
+ case 0x110:
+ case 0x111:
+ if (a != 0)
+ return PPC_ID_INVALID;
+
+ 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)
+ return PPC_ID_INVALID;
+
+ 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)
+ return PPC_ID_INVALID;
+
+ 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)
+ return PPC_ID_INVALID;
+
+ 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)
+ return PPC_ID_INVALID;
+
+ 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)
+ return PPC_ID_INVALID;
+
+ 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)
+ return PPC_ID_INVALID;
+
+ 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:
+ {
+ 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;
+ }
+
+ 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:
+ return PPC_ID_INVALID;
+ }
+ }
+ else
+ {
+ return PPC_ID_INVALID;
+ }
+
+ 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 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)
+ return PPC_ID_INVALID;
+
+ 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)
+ 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;
+}
+
+InstructionId Decode0x04(uint32_t word32, uint32_t decodeFlags)
+{
+ if ((decodeFlags & DECODE_FLAGS_ALTIVEC))
+ return DecodeAltivec0x04(word32, decodeFlags);
+ else if ((decodeFlags & DECODE_FLAGS_SPE))
+ return DecodeSpe0x04(word32, decodeFlags);
+ else if ((decodeFlags & DECODE_FLAGS_PS))
+ return DecodePairedSingle0x04(word32, decodeFlags);
+ else
+ return PPC_ID_INVALID;
+}
+
+static InstructionId Decode32(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:
+ {
+ return Decode0x04(word32, decodeFlags);
+ }
+
+ case 0x07:
+ return PPC_ID_MULLI;
+
+ case 0x08:
+ return PPC_ID_SUBFICx;
+
+
+ case 0x0a:
+ if ((word32 & 0x00400000) == 0)
+ {
+ if ((word32 & 0x00200000) != 0)
+ {
+ if ((decodeFlags & DECODE_FLAGS_PPC64) != 0)
+ return PPC_ID_CMPLDI;
+ else
+ return PPC_ID_INVALID;
+ }
+ 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_CMPDI;
+ else
+ return PPC_ID_INVALID;
+
+ }
+ 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_ADDIx;
+
+ case 0x0f:
+ if (a == 0)
+ return PPC_ID_LIS;
+ else
+ return PPC_ID_ADDIS;
+
+ case 0x10:
+ 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_ORIx;
+
+ case 0x19:
+ return PPC_ID_ORIS;
+
+ case 0x1a:
+ if (word32 == 0x68000000)
+ return PPC_ID_XNOP;
+ else
+ return PPC_ID_XORIx;
+
+ case 0x1b:
+ return PPC_ID_XORIS;
+
+ case 0x1c:
+ return PPC_ID_ANDIx;
+
+ 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 0x38:
+ if ((decodeFlags & DECODE_FLAGS_PS) != 0)
+ return PPC_ID_PAIREDSINGLE_PSQ_L;
+ else
+ return PPC_ID_INVALID;
+
+ case 0x39:
+ if ((decodeFlags & DECODE_FLAGS_VSX) != 0)
+ return DecodeVsx0x39(word32, decodeFlags);
+ else if ((decodeFlags & DECODE_FLAGS_PS) != 0)
+ return PPC_ID_PAIREDSINGLE_PSQ_LU;
+ else
+ return PPC_ID_INVALID;
+
+ 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 DecodeVsx0x3C(word32, decodeFlags);
+ else if ((decodeFlags & DECODE_FLAGS_PS) != 0)
+ return PPC_ID_PAIREDSINGLE_PSQ_ST;
+ else
+ return PPC_ID_INVALID;
+
+ case 0x3d:
+ if ((decodeFlags & DECODE_FLAGS_VSX) != 0)
+ return DecodeVsx0x3D(word32, decodeFlags);
+ else if ((decodeFlags & DECODE_FLAGS_PS) != 0)
+ return PPC_ID_PAIREDSINGLE_PSQ_STU;
+ else
+ return PPC_ID_INVALID;
+
+ 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;
+ }
+}
+
+bool Decompose16(Instruction* instruction, uint16_t word16, uint64_t address, uint32_t flags)
+{
+ size_t numBytes = instruction->numBytes;
+ memset(instruction, 0, sizeof *instruction);
+ instruction->numBytes = numBytes;
+ if ((flags & DECODE_FLAGS_VLE) != 0)
+ return Decompose16Vle(instruction, word16, address, flags);
+ else
+ return false;
+}
+
+bool Decompose32(Instruction* instruction, uint32_t word32, uint64_t address, uint32_t flags)
+{
+ size_t numBytes = instruction->numBytes;
+ memset(instruction, 0, sizeof *instruction);
+ instruction->numBytes = numBytes;
+
+ if ((flags & DECODE_FLAGS_VLE) != 0)
+ return Decompose32Vle(instruction, word32, address, flags);
+
+ instruction->id = Decode32(word32, flags);
+ if (instruction->id == PPC_ID_INVALID)
+ return false;
+
+ FillOperands32(instruction, word32, address);
+ return true;
+}
+
+size_t VleGetInstructionLength(const uint8_t* data, size_t data_length, uint32_t decodeFlags)
+{
+ if (data_length == 0)
+ return 0;
+
+ switch (data[0] & 0xfc)
+ {
+ case 0x10:
+ case 0x18:
+ case 0x1c:
+ case 0x30:
+ case 0x34:
+ case 0x38:
+ case 0x50:
+ case 0x54:
+ case 0x58:
+ case 0x5c:
+ case 0x70:
+ case 0x74:
+ case 0x78:
+ case 0x7c:
+ return 4;
+
+ default:
+ return 2;
+ }
+}
+