summaryrefslogtreecommitdiff
path: root/arch/powerpc/decode/operands.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/operands.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/operands.c')
-rw-r--r--arch/powerpc/decode/operands.c3288
1 files changed, 3288 insertions, 0 deletions
diff --git a/arch/powerpc/decode/operands.c b/arch/powerpc/decode/operands.c
new file mode 100644
index 00000000..15628049
--- /dev/null
+++ b/arch/powerpc/decode/operands.c
@@ -0,0 +1,3288 @@
+#include <string.h>
+
+#include "decode.h"
+#include "priv.h"
+
+// see stanford bit twiddling hacks
+int32_t sign_extend(uint32_t x, unsigned numBits)
+{
+ int32_t const m = 1U << (numBits - 1);
+
+ x = x & ((1U << numBits) - 1);
+ return (x ^ m) - m;
+}
+
+Register Gpr(uint32_t value)
+{
+ return PPC_REG_GPR0 + value;
+}
+
+Register Fr(uint32_t value)
+{
+ return PPC_REG_FR0 + value;
+}
+
+Register Crf(uint32_t value)
+{
+ return PPC_REG_CRF0 + value;
+}
+
+Register AltivecVr(uint32_t value)
+{
+ return PPC_REG_AV_VR0 + value;
+}
+
+Register VsxVr(uint32_t value)
+{
+ return PPC_REG_VSX_VR0 + value;
+}
+
+Register VsxVrHi(uint32_t value)
+{
+ return PPC_REG_VSX_VR0 + value + 32;
+}
+
+void PushUIMMValue(Instruction* instruction, uint64_t uimm)
+{
+ instruction->operands[instruction->numOperands].cls = PPC_OP_UIMM;
+ instruction->operands[instruction->numOperands].uimm = uimm;
+ ++instruction->numOperands;
+}
+
+void PushSIMMValue(Instruction* instruction, int32_t simm)
+{
+ instruction->operands[instruction->numOperands].cls = PPC_OP_SIMM;
+ instruction->operands[instruction->numOperands].simm = simm;
+ ++instruction->numOperands;
+}
+
+void PushRegister(Instruction* instruction, OperandClass cls, Register reg)
+{
+ instruction->operands[instruction->numOperands].cls = cls;
+ instruction->operands[instruction->numOperands].reg = reg;
+ ++instruction->numOperands;
+}
+
+uint64_t ComputeBranchTarget(Instruction* instruction, uint64_t address, uint32_t word32)
+{
+ int32_t bd = (int32_t)((int16_t)(word32 & 0xfffc));
+
+ return instruction->flags.aa ? bd : address + bd;
+}
+
+void PushLabel(Instruction* instruction, uint64_t address)
+{
+ instruction->operands[instruction->numOperands].cls = PPC_OP_LABEL;
+ instruction->operands[instruction->numOperands].label = address;
+ ++instruction->numOperands;
+}
+
+// this assumes that instruction->flags.aa has been properly set!
+void PushBranchTarget(Instruction* instruction, uint64_t address, uint32_t word32)
+{
+ PushLabel(instruction, ComputeBranchTarget(instruction, address, word32));
+}
+
+void PushRA(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_RA, Gpr(GetA(word32)));
+}
+
+void PushRAor0(Instruction* instruction, uint32_t word32)
+{
+ uint32_t ra = GetA(word32);
+
+ if (ra == 0)
+ PushUIMMValue(instruction, 0);
+ else
+ PushRegister(instruction, PPC_OP_REG_RA, Gpr(ra));
+}
+
+void PushRB(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_RB, Gpr(GetB(word32)));
+}
+
+void PushRC(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_RC, Gpr(GetC(word32)));
+}
+
+void PushRD(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_RD, Gpr(GetD(word32)));
+}
+
+void PushRS(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_RS, Gpr(GetS(word32)));
+}
+
+void PushFRA(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_FRA, Fr(GetA(word32)));
+}
+
+void PushFRB(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_FRB, Fr(GetB(word32)));
+}
+
+void PushFRC(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_FRC, Fr(GetC(word32)));
+}
+
+void PushFRD(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_FRD, Fr(GetD(word32)));
+}
+
+void PushFRS(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_FRS, Fr(GetS(word32)));
+}
+
+void PushCRFD(Instruction* instruction, uint32_t word32)
+{
+ uint32_t crfd = (word32 >> 23) & 0x7;
+ PushRegister(instruction, PPC_OP_REG_CRFD, Crf(crfd));
+}
+
+void PushCRFDImplyCR0(Instruction* instruction, uint32_t word32)
+{
+ uint32_t crfd = (word32 >> 23) & 0x7;
+
+ PushRegister(instruction, PPC_OP_REG_CRFD_IMPLY0, Crf(crfd));
+}
+
+void PushCRFS(Instruction* instruction, uint32_t word32)
+{
+ uint32_t crfs = (word32 >> 18) & 0x7;
+ PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crfs));
+}
+
+void PushCRBitA(Instruction* instruction, uint32_t word32)
+{
+ instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_A;
+ instruction->operands[instruction->numOperands].crbit = GetA(word32);
+ ++instruction->numOperands;
+}
+
+void PushCRBitB(Instruction* instruction, uint32_t word32)
+{
+ instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_B;
+ instruction->operands[instruction->numOperands].crbit = GetB(word32);
+ ++instruction->numOperands;
+}
+
+void PushCRBitD(Instruction* instruction, uint32_t word32)
+{
+ instruction->operands[instruction->numOperands].cls = PPC_OP_CRBIT_D;
+ instruction->operands[instruction->numOperands].crbit = GetD(word32);
+ ++instruction->numOperands;
+}
+
+void PushMem(Instruction* instruction, OperandClass cls, Register reg, int32_t offset)
+{
+ instruction->operands[instruction->numOperands].cls = cls;
+ instruction->operands[instruction->numOperands].mem.reg = reg;
+ instruction->operands[instruction->numOperands].mem.offset = offset;
+ ++instruction->numOperands;
+}
+
+void FillBranchLikelyHint(Instruction* instruction, uint32_t word32)
+{
+ uint32_t bo = GetBO(word32);
+
+ switch (bo >> 2)
+ {
+ // 001at
+ // 011at
+ case 1:
+ case 3:
+ instruction->flags.branchLikelyHint = bo & 0x3;
+ break;
+
+ // 1a00t
+ // 1a01t
+ case 4:
+ case 6:
+ instruction->flags.branchLikelyHint = ((bo >> 2) & 0x2) | (bo & 0x1);
+ break;
+
+ // all others don't have hints
+ default:
+ instruction->flags.branchLikelyHint = 0;
+ }
+}
+
+void PushMemRAOffset(Instruction* instruction, uint32_t word32, int32_t offset)
+{
+ PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), offset);
+}
+
+// Default of d=lower 16 bits
+void PushMemRA(Instruction* instruction, uint32_t word32)
+{
+ PushMemRAOffset(instruction, word32, (int32_t)((int16_t)(word32 & 0xffff)));
+}
+
+void PushVsxA(Instruction* instruction, uint32_t word32, VsxWidth width)
+{
+ PushRegister(instruction,
+ width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RA : PPC_OP_REG_VSX_RA_DWORD0,
+ VsxVr(GetVsxA(word32)));
+}
+
+void PushVsxHiA(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_VSX_RA, VsxVrHi(GetA(word32)));
+}
+
+void PushVsxB(Instruction* instruction, uint32_t word32, VsxWidth width)
+{
+ PushRegister(instruction,
+ width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RB : PPC_OP_REG_VSX_RB_DWORD0,
+ VsxVr(GetVsxB(word32)));
+}
+
+void PushVsxHiB(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_VSX_RB, VsxVrHi(GetB(word32)));
+}
+
+void PushVsxC(Instruction* instruction, uint32_t word32, VsxWidth width)
+{
+ PushRegister(instruction,
+ width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RC : PPC_OP_REG_VSX_RC_DWORD0,
+ VsxVr(GetVsxC(word32)));
+}
+
+void PushVsxD(Instruction* instruction, uint32_t word32, VsxWidth width)
+{
+ PushRegister(instruction,
+ width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RD : PPC_OP_REG_VSX_RD_DWORD0,
+ VsxVr(GetVsxD(word32)));
+}
+
+void PushVsxHiD(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_VSX_RD, VsxVrHi(GetD(word32)));
+}
+
+void PushVsxS(Instruction* instruction, uint32_t word32, VsxWidth width)
+{
+ uint32_t sx = word32 & 0x1;
+ uint32_t s = (word32 >> 21) & 0x1f;
+ PushRegister(instruction,
+ width == VSX_WIDTH_FULL ? PPC_OP_REG_VSX_RS : PPC_OP_REG_VSX_RS_DWORD0,
+ VsxVr((sx << 5) | s));
+}
+
+void PushVsxHiS(Instruction* instruction, uint32_t word32)
+{
+ PushRegister(instruction, PPC_OP_REG_VSX_RS, VsxVrHi(GetS(word32)));
+}
+
+void PushAltivecVA(Instruction* instruction, uint32_t word32)
+{
+ uint32_t va = (word32 >> 16) & 0x1f;
+ PushRegister(instruction, PPC_OP_REG_AV_VA, AltivecVr(va));
+}
+
+void PushAltivecVB(Instruction* instruction, uint32_t word32)
+{
+ uint32_t vb = (word32 >> 11) & 0x1f;
+ PushRegister(instruction, PPC_OP_REG_AV_VB, AltivecVr(vb));
+}
+
+void PushAltivecVC(Instruction* instruction, uint32_t word32)
+{
+ uint32_t vc = (word32 >> 6) & 0x1f;
+ PushRegister(instruction, PPC_OP_REG_AV_VC, AltivecVr(vc));
+}
+
+void PushAltivecVD(Instruction* instruction, uint32_t word32)
+{
+ uint32_t vd = (word32 >> 21) & 0x1f;
+ PushRegister(instruction, PPC_OP_REG_AV_VD, AltivecVr(vd));
+}
+
+void PushAltivecVS(Instruction* instruction, uint32_t word32)
+{
+ uint32_t vs = (word32 >> 21) & 0x1f;
+ PushRegister(instruction, PPC_OP_REG_AV_VS, AltivecVr(vs));
+}
+
+void FillOperands32(Instruction* instruction, uint32_t word32, uint64_t address)
+{
+ switch (instruction->id)
+ {
+ // instructions with no operands
+ case PPC_ID_ATTN:
+ case PPC_ID_CP_ABORT:
+ case PPC_ID_DCCCI:
+ case PPC_ID_HRFID:
+ case PPC_ID_ICCCI:
+ case PPC_ID_ISYNC:
+ case PPC_ID_LWSYNC:
+ case PPC_ID_MSGSYNC:
+ case PPC_ID_NAP:
+ case PPC_ID_NOP:
+ case PPC_ID_PTESYNC:
+ case PPC_ID_RFCI:
+ case PPC_ID_RFDI:
+ case PPC_ID_RFI:
+ case PPC_ID_RFID:
+ case PPC_ID_RFMCI:
+ case PPC_ID_STOP:
+ case PPC_ID_SYNC:
+ case PPC_ID_TLBIA:
+ case PPC_ID_TLBSYNC:
+ case PPC_ID_TRAP:
+ case PPC_ID_TRECHKPT:
+ case PPC_ID_SLBIA:
+ case PPC_ID_SLBSYNC:
+ case PPC_ID_XNOP:
+ case PPC_ID_WAITIMPL:
+ case PPC_ID_WAITRSV:
+ case PPC_ID_AV_DSSALL:
+ break;
+
+ // <op> rD
+ case PPC_ID_LNIA:
+ case PPC_ID_MFBR0:
+ case PPC_ID_MFBR1:
+ case PPC_ID_MFBR2:
+ case PPC_ID_MFBR3:
+ case PPC_ID_MFBR4:
+ case PPC_ID_MFBR5:
+ case PPC_ID_MFBR6:
+ case PPC_ID_MFBR7:
+ case PPC_ID_MFCR:
+ case PPC_ID_MFCTR:
+ case PPC_ID_MFLR:
+ case PPC_ID_MFMSR:
+ case PPC_ID_MFTBU:
+ case PPC_ID_MFXER:
+ PushRD(instruction, word32);
+ break;
+
+ // <op> rS
+ case PPC_ID_MTBR0:
+ case PPC_ID_MTBR1:
+ case PPC_ID_MTBR2:
+ case PPC_ID_MTBR3:
+ case PPC_ID_MTBR4:
+ case PPC_ID_MTBR5:
+ case PPC_ID_MTBR6:
+ case PPC_ID_MTBR7:
+ case PPC_ID_MTCTR:
+ case PPC_ID_MTLR:
+ case PPC_ID_MTMSR:
+ case PPC_ID_MTMSRD:
+ case PPC_ID_MTXER:
+ case PPC_ID_WRTEE:
+ PushRS(instruction, word32);
+ break;
+
+ // <op> rA
+ case PPC_ID_TABORT:
+ case PPC_ID_TRECLAIM:
+ PushRA(instruction, word32);
+ break;
+
+ // <op> rB
+ case PPC_ID_TLBIEL:
+ case PPC_ID_TLBLI:
+ case PPC_ID_SLBIE:
+ PushRB(instruction, word32);
+ break;
+
+ // <op>[.] rD, rA (arithmetic)
+ case PPC_ID_NEGx:
+ case PPC_ID_SUBFZEx:
+ case PPC_ID_ADDZEx:
+ case PPC_ID_SUBFMEx:
+ case PPC_ID_ADDMEx:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+
+ // some of these instructions don't have an "oe" flag,
+ // but we rely on the fact that those instructions have
+ // bitmask 0x400 clear in the switch statement on the
+ instruction->flags.rc = word32 & 0x1;
+ instruction->flags.oe = (word32 & 0x400) != 0;
+ break;
+
+ // <op>[.] rD, rA, rB (arithmetic)
+ case PPC_ID_ADDx:
+ case PPC_ID_ADDCx:
+ case PPC_ID_ADDEx:
+ case PPC_ID_DIVDx:
+ case PPC_ID_DIVDEx:
+ case PPC_ID_DIVDEUx:
+ case PPC_ID_DIVDUx:
+ case PPC_ID_DIVWx:
+ case PPC_ID_DIVWEx:
+ case PPC_ID_DIVWEUx:
+ case PPC_ID_DIVWUx:
+ case PPC_ID_MODSD:
+ case PPC_ID_MODSW:
+ case PPC_ID_MODUD:
+ case PPC_ID_MODUW:
+ case PPC_ID_MULHDx:
+ case PPC_ID_MULHDUx:
+ case PPC_ID_MULHWx:
+ case PPC_ID_MULHWUx:
+ case PPC_ID_MULLDx:
+ case PPC_ID_MULLWx:
+ case PPC_ID_SUBFx:
+ case PPC_ID_SUBFCx:
+ case PPC_ID_SUBFEx:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+
+ // some of these instructions don't have an "oe" flag,
+ // but we rely on the fact that those instructions have
+ // bitmask 0x400 clear in the switch statement on the
+ // 0x7ff mask
+ instruction->flags.rc = word32 & 0x1;
+ instruction->flags.oe = (word32 & 0x400) != 0;
+ break;
+
+
+ // <op>[.] rA, rS (logical)
+ case PPC_ID_CNTLZWx:
+ case PPC_ID_CNTLZDx:
+ case PPC_ID_CNTTZWx:
+ case PPC_ID_CNTTZDx:
+ case PPC_ID_POPCNTB:
+ case PPC_ID_POPCNTD:
+ case PPC_ID_POPCNTW:
+ case PPC_ID_EXTSHx:
+ case PPC_ID_EXTSBx:
+ case PPC_ID_EXTSWx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+
+ // not all of these have RC bits, but it gets filtered
+ // at subop decode step
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ // <op>[.] rA, rS, rB
+ case PPC_ID_ANDx:
+ case PPC_ID_ANDCx:
+ case PPC_ID_BPERMD:
+ case PPC_ID_CMPB:
+ case PPC_ID_ECIWX:
+ case PPC_ID_ECOWX:
+ case PPC_ID_EQVx:
+ case PPC_ID_NANDx:
+ case PPC_ID_NORx:
+ case PPC_ID_ORx:
+ case PPC_ID_ORCx:
+ case PPC_ID_ROTLWx:
+ case PPC_ID_ROTLDx:
+ case PPC_ID_SLDx:
+ case PPC_ID_SLWx:
+ case PPC_ID_SRADx:
+ case PPC_ID_SRAWx:
+ case PPC_ID_SRDx:
+ case PPC_ID_SRWx:
+ case PPC_ID_XORx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushRB(instruction, word32);
+
+ // not all of these have an rc bit, but they just don't
+ // get recognized at the switch statement with &0x7ff
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_ROTLWIx:
+ case PPC_ID_SLWIx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, GetSH(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_CLRLWIx:
+ case PPC_ID_SRWIx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, GetMB(word32));
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_CLRRWIx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+
+ // me = 31 - n --> n = 31 - me
+ PushUIMMValue(instruction, 31 - GetME(word32));
+ // PushUIMMValue(instruction, GetME(word32));
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_RLDCLx:
+ case PPC_ID_RLDCRx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushRB(instruction, word32);
+ PushUIMMValue(instruction, GetMX64(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_EXTLDIx:
+ // Decoder will never generate this extended mnemonic, but handle its operands anyway
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+
+ // extldi ra,rs,n,b (n>0) --> rldicr ra,rs,b,n−1
+ PushUIMMValue(instruction, GetMX64(word32));
+ PushUIMMValue(instruction, GetSH64(word32) - 1);
+ // PushUIMMValue(instruction, GetSH64(word32));
+ // PushUIMMValue(instruction, GetMX64(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_EXTRDIx:
+ // Decoder will never generate this extended mnemonic, but handle its operands anyway
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+
+ // extrdi ra,rs,n,b (n>0) --> rldicl ra,rs,b+n,64−n
+ PushUIMMValue(instruction, GetMX64(word32) + GetSH64(word32));
+ PushUIMMValue(instruction, 64 - GetSH64(word32));
+ // PushUIMMValue(instruction, GetSH64(word32));
+ // PushUIMMValue(instruction, GetMX64(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+
+ case PPC_ID_RLDICx:
+ case PPC_ID_RLDICLx:
+ case PPC_ID_RLDICRx:
+ case PPC_ID_RLDIMIx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, GetSH64(word32));
+ PushUIMMValue(instruction, GetMX64(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_CLRLDIx:
+ case PPC_ID_CLRRDIx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ if (instruction->id == PPC_ID_CLRRDIx)
+ PushUIMMValue(instruction, 63 - GetMX64(word32));
+ // PushUIMMValue(instruction, GetMX64(word32));
+ else
+ PushUIMMValue(instruction, GetMX64(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_ROTLDIx:
+ case PPC_ID_ROTRDIx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ if (instruction->id == PPC_ID_ROTRDIx)
+ PushUIMMValue(instruction, 64 - GetSH64(word32));
+ // PushUIMMValue(instruction, GetSH64(word32));
+ else
+ PushUIMMValue(instruction, GetSH64(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_SLDIx:
+ case PPC_ID_SRDIx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, GetSH64(word32));
+ // if (instruction->id == PPC_ID_SRDIx)
+ // PushUIMMValue(instruction, 64 - GetSH64(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_BCx:
+ {
+ uint32_t bo = GetBO(word32);
+ uint32_t bi = GetBI(word32);
+
+ instruction->flags.lk = word32 & 0x1;
+ instruction->flags.aa = (word32 & 0x2) != 0;
+
+ // not all BCx have hints, but if they don't, then those
+ // hints won't be read by anything anyways
+ FillBranchLikelyHint(instruction, word32);
+
+ PushUIMMValue(instruction, bo);
+ PushUIMMValue(instruction, bi);
+ PushBranchTarget(instruction, address, word32);
+
+ break;
+ }
+
+ // <op> crfD, rA, rB
+ case PPC_ID_CMPD:
+ case PPC_ID_CMPEQB:
+ case PPC_ID_CMPW:
+ case PPC_ID_CMPLD:
+ case PPC_ID_CMPLW:
+ PushCRFDImplyCR0(instruction, word32);
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <op> crfD, rA, SIMM
+ case PPC_ID_CMPDI:
+ case PPC_ID_CMPWI:
+ {
+ int32_t simm = (int32_t)((int16_t)(word32 & 0xffff));
+
+ PushCRFDImplyCR0(instruction, word32);
+ PushRA(instruction, word32);
+ PushSIMMValue(instruction, simm);
+ break;
+ }
+
+ // <op> crfD, rA, UIMM
+ case PPC_ID_CMPLDI:
+ case PPC_ID_CMPLWI:
+ {
+ uint32_t uimm = word32 & 0xffff;
+
+ PushCRFDImplyCR0(instruction, word32);
+ PushRA(instruction, word32);
+ PushUIMMValue(instruction, uimm);
+ break;
+ }
+
+ // <op> rA, rB
+ case PPC_ID_COPY:
+ case PPC_ID_PASTE:
+ case PPC_ID_TDEQ:
+ case PPC_ID_TDGT:
+ case PPC_ID_TDLGT:
+ case PPC_ID_TDLLT:
+ case PPC_ID_TDLT:
+ case PPC_ID_TDNE:
+ case PPC_ID_TDU:
+ case PPC_ID_TLBSX:
+ case PPC_ID_TWEQ:
+ case PPC_ID_TWGT:
+ case PPC_ID_TWLGT:
+ case PPC_ID_TWLLT:
+ case PPC_ID_TWLT:
+ case PPC_ID_TWNE:
+ case PPC_ID_TWU:
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <trap> TO, rA, rB
+ case PPC_ID_TD:
+ case PPC_ID_TW:
+ case PPC_ID_TABORTDC:
+ case PPC_ID_TABORTWC:
+ {
+ uint32_t to = (word32 >> 21) & 0x1f;
+
+ PushUIMMValue(instruction, to);
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+ }
+
+ // <trap> rA, SIMM
+ case PPC_ID_TDEQI:
+ case PPC_ID_TDGTI:
+ case PPC_ID_TDLGTI:
+ case PPC_ID_TDLLTI:
+ case PPC_ID_TDLTI:
+ case PPC_ID_TDNEI:
+ case PPC_ID_TDUI:
+ case PPC_ID_TWEQI:
+ case PPC_ID_TWGTI:
+ case PPC_ID_TWLGTI:
+ case PPC_ID_TWLLTI:
+ case PPC_ID_TWLTI:
+ case PPC_ID_TWNEI:
+ case PPC_ID_TWUI:
+ {
+ int32_t simm = (int32_t)((int16_t)(word32 & 0xffff));
+
+ PushRA(instruction, word32);
+ PushSIMMValue(instruction, simm);
+ break;
+ }
+
+ // <trap> TO, rA, SIMM
+ case PPC_ID_TDI:
+ case PPC_ID_TWI:
+ {
+ uint32_t to = (word32 >> 21) & 0x1f;
+ int32_t simm = (int32_t)((int16_t)(word32 & 0xffff));
+
+ PushUIMMValue(instruction, to);
+ PushRA(instruction, word32);
+ PushSIMMValue(instruction, simm);
+ break;
+ }
+
+ // <tabort> TO, rA, SIMM
+ case PPC_ID_TABORTDCI:
+ case PPC_ID_TABORTWCI:
+ {
+ uint32_t to = (word32 >> 21) & 0x1f;
+ int32_t simm = sign_extend((word32 >> 11) & 0x1f, 5);
+
+ PushUIMMValue(instruction, to);
+ PushRA(instruction, word32);
+ PushSIMMValue(instruction, simm);
+ break;
+ }
+
+ // <op> rD, rA, SIMM
+ case PPC_ID_ADDIx:
+ case PPC_ID_MULLI:
+ case PPC_ID_SUBFICx:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff)));
+ break;
+
+ // <op> rA, rS, UIMM
+ case PPC_ID_ORIx:
+ case PPC_ID_XORIx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, word32 & 0xffff);
+
+ instruction->flags.rc = false;
+ break;
+
+ // differentiated in case it makes sense to use the shifted value as an operand
+ // (which we do for now since it matches capstone)
+ // <op> rA, rS, UIMM
+ case PPC_ID_ORIS:
+ case PPC_ID_XORIS:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, word32 & 0xffff);
+ break;
+
+ // <op> rD, d(rA)
+ case PPC_ID_LBZ:
+ case PPC_ID_LBZU:
+ case PPC_ID_LHA:
+ case PPC_ID_LHAU:
+ case PPC_ID_LHZ:
+ case PPC_ID_LHZU:
+ case PPC_ID_LMW:
+ case PPC_ID_LWZ:
+ case PPC_ID_LWZU:
+ PushRD(instruction, word32);
+ PushMemRA(instruction, word32);
+ break;
+
+ // <op> rD, d(rA) (64-bit)
+ case PPC_ID_LD:
+ case PPC_ID_LDU:
+ case PPC_ID_LWA:
+ {
+ PushRD(instruction, word32);
+
+ int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc));
+ PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds);
+ break;
+ }
+
+ // <op> rD, rA, rB (indexed load)
+ case PPC_ID_LBEPX:
+ case PPC_ID_LBZCIX:
+ case PPC_ID_LBZUX:
+ case PPC_ID_LBZX:
+ case PPC_ID_LDBRX:
+ case PPC_ID_LDCIX:
+ case PPC_ID_LDUX:
+ case PPC_ID_LDX:
+ case PPC_ID_LHAUX:
+ case PPC_ID_LHAX:
+ case PPC_ID_LHBRX:
+ case PPC_ID_LHEPX:
+ case PPC_ID_LHZCIX:
+ case PPC_ID_LHZX:
+ case PPC_ID_LHZUX:
+ case PPC_ID_LSWX:
+ case PPC_ID_LWAX:
+ case PPC_ID_LWAUX:
+ case PPC_ID_LWBRX:
+ case PPC_ID_LWEPX:
+ case PPC_ID_LWZCIX:
+ case PPC_ID_LWZUX:
+ case PPC_ID_LWZX:
+ PushRD(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <op> rD, rA, rB, [EH if nonzero] (indexed load)
+ case PPC_ID_LBARX:
+ case PPC_ID_LDARX:
+ case PPC_ID_LHARX:
+ case PPC_ID_LWARX:
+ {
+ PushRD(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ uint32_t eh = word32 & 0x1;
+ // NOTE: this breaks with convention by only
+ // conditionally including EH
+ if (eh)
+ PushUIMMValue(instruction, word32 & 0x1);
+ break;
+ }
+
+ // <op> rD, rA, FC
+ case PPC_ID_LDAT:
+ case PPC_ID_LWAT:
+ {
+ uint32_t fc = (word32 >> 11) & 0x1f;
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushUIMMValue(instruction, fc);
+ break;
+ }
+
+ // <op> rS, rA, FC
+ case PPC_ID_STDAT:
+ case PPC_ID_STWAT:
+ {
+ uint32_t fc = (word32 >> 11) & 0x1f;
+ PushRS(instruction, word32);
+ PushRA(instruction, word32);
+ PushUIMMValue(instruction, fc);
+ break;
+ }
+
+
+ // <op> rS, d(RA)
+ case PPC_ID_STB:
+ case PPC_ID_STBU:
+ case PPC_ID_STH:
+ case PPC_ID_STHU:
+ case PPC_ID_STMW:
+ case PPC_ID_STW:
+ case PPC_ID_STWU:
+ PushRS(instruction, word32);
+ PushMemRA(instruction, word32);
+ break;
+
+ // <op> rS, d(RA) (64-bit)
+ case PPC_ID_STD:
+ case PPC_ID_STDU:
+ {
+ PushRS(instruction, word32);
+
+ int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc));
+ PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds);
+ break;
+ }
+
+ // <op> rS, rA, rB (indexed store)
+ case PPC_ID_STBCX:
+ case PPC_ID_STBCIX:
+ case PPC_ID_STBEPX:
+ case PPC_ID_STBUX:
+ case PPC_ID_STBX:
+ case PPC_ID_STDBRX:
+ case PPC_ID_STDCIX:
+ case PPC_ID_STDEPX:
+ case PPC_ID_STDUX:
+ case PPC_ID_STDX:
+ case PPC_ID_STHBRX:
+ case PPC_ID_STHCIX:
+ case PPC_ID_STHCX:
+ case PPC_ID_STHEPX:
+ case PPC_ID_STHUX:
+ case PPC_ID_STHX:
+ case PPC_ID_STSWX:
+ case PPC_ID_STWBRX:
+ case PPC_ID_STWCIX:
+ case PPC_ID_STWEPX:
+ case PPC_ID_STWUX:
+ case PPC_ID_STWX:
+ PushRS(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <op>. rS, rA, rB (indexed store with reserve)
+ case PPC_ID_STDCX:
+ case PPC_ID_STWCX:
+ PushRS(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ instruction->flags.rc = 1;
+ break;
+
+ // <op> frD, d(rA)
+ case PPC_ID_LFD:
+ case PPC_ID_LFDU:
+ case PPC_ID_LFS:
+ case PPC_ID_LFSU:
+ PushFRD(instruction, word32);
+ PushMemRA(instruction, word32);
+ break;
+
+ // <op> frD, rA, rB
+ case PPC_ID_LFDEPX:
+ case PPC_ID_LFDUX:
+ case PPC_ID_LFDX:
+ case PPC_ID_LFIWAX:
+ case PPC_ID_LFIWZX:
+ case PPC_ID_LFSUX:
+ case PPC_ID_LFSX:
+ PushFRD(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <op> frS, d(rA)
+ case PPC_ID_STFD:
+ case PPC_ID_STFDU:
+ case PPC_ID_STFS:
+ case PPC_ID_STFSU:
+ PushFRS(instruction, word32);
+ PushMemRA(instruction, word32);
+ break;
+
+ // <op> frS, rA, rB
+ case PPC_ID_STFDEPX:
+ case PPC_ID_STFDUX:
+ case PPC_ID_STFDX:
+ case PPC_ID_STFIWX:
+ case PPC_ID_STFSUX:
+ case PPC_ID_STFSX:
+ PushFRS(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <op> crfD, crfS
+ case PPC_ID_MCRF:
+ case PPC_ID_MCRFS:
+ PushCRFD(instruction, word32);
+ PushCRFS(instruction, word32);
+ break;
+
+ // <op> crbD, crbA
+ case PPC_ID_CRMOVE:
+ case PPC_ID_CRNOT:
+ PushCRBitD(instruction, word32);
+ PushCRBitA(instruction, word32);
+ break;
+
+ // <op> crbD, crbA, crbB
+ case PPC_ID_CRAND:
+ case PPC_ID_CRANDC:
+ case PPC_ID_CREQV:
+ case PPC_ID_CRNAND:
+ case PPC_ID_CRNOR:
+ case PPC_ID_CROR:
+ case PPC_ID_CRORC:
+ case PPC_ID_CRXOR:
+ PushCRBitD(instruction, word32);
+ PushCRBitA(instruction, word32);
+ PushCRBitB(instruction, word32);
+ break;
+
+ // <op> crbD
+ case PPC_ID_CRCLR:
+ case PPC_ID_CRSET:
+ PushCRBitD(instruction, word32);
+ break;
+
+ // <op> crfS
+ case PPC_ID_MCRXRX:
+ case PPC_ID_TCHECK:
+ PushCRFD(instruction, word32);
+ break;
+
+ // conditional branches to registers
+ case PPC_ID_BCLRx:
+ case PPC_ID_BCCTRx:
+ // not all BC<reg>x have hints, but if they don't, then those
+ // hints won't be read by anything anyways
+ FillBranchLikelyHint(instruction, word32);
+
+ PushUIMMValue(instruction, GetBO(word32));
+ PushUIMMValue(instruction, GetBI(word32));
+
+ instruction->flags.lk = word32 & 0x1;
+ break;
+
+ // <op> frD, frA, frB
+ case PPC_ID_FADDx:
+ case PPC_ID_FADDSx:
+ case PPC_ID_FCPSGNx:
+ case PPC_ID_FDIVx:
+ case PPC_ID_FDIVSx:
+ case PPC_ID_FSUBx:
+ case PPC_ID_FSUBSx:
+ PushFRD(instruction, word32);
+ PushFRA(instruction, word32);
+ PushFRB(instruction, word32);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ // <op>[.] frD, frA, frC
+ case PPC_ID_FMULx:
+ case PPC_ID_FMULSx:
+ PushFRD(instruction, word32);
+ PushFRA(instruction, word32);
+ PushFRC(instruction, word32);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ // <op>[.] frD, frA, frC, frB
+ case PPC_ID_FMADDx:
+ case PPC_ID_FMADDSx:
+ case PPC_ID_FMSUBx:
+ case PPC_ID_FMSUBSx:
+ case PPC_ID_FNMADDx:
+ case PPC_ID_FNMADDSx:
+ case PPC_ID_FNMSUBx:
+ case PPC_ID_FNMSUBSx:
+ case PPC_ID_FSELx:
+ PushFRD(instruction, word32);
+ PushFRA(instruction, word32);
+ PushFRC(instruction, word32);
+ PushFRB(instruction, word32);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ // <op>[.] frD, frB
+ case PPC_ID_FABSx:
+ case PPC_ID_FCFIDx:
+ case PPC_ID_FCFIDSx:
+ case PPC_ID_FCFIDUx:
+ case PPC_ID_FCFIDUSx:
+ case PPC_ID_FCTIDx:
+ case PPC_ID_FCTIDUx:
+ case PPC_ID_FCTIDUZx:
+ case PPC_ID_FCTIDZx:
+ case PPC_ID_FCTIWx:
+ case PPC_ID_FCTIWUx:
+ case PPC_ID_FCTIWUZx:
+ case PPC_ID_FCTIWZx:
+ case PPC_ID_FMRx:
+ case PPC_ID_FNABSx:
+ case PPC_ID_FNEGx:
+ case PPC_ID_FREx:
+ case PPC_ID_FRESx:
+ case PPC_ID_FRIMx:
+ case PPC_ID_FRINx:
+ case PPC_ID_FRIPx:
+ case PPC_ID_FRIZx:
+ case PPC_ID_FRSPx:
+ case PPC_ID_FRSQRTEx:
+ case PPC_ID_FRSQRTESx:
+ case PPC_ID_FSQRTx:
+ case PPC_ID_FSQRTSx:
+ PushFRD(instruction, word32);
+ PushFRB(instruction, word32);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+
+ case PPC_ID_FCMPO:
+ case PPC_ID_FCMPU:
+ PushCRFD(instruction, word32);
+ PushFRA(instruction, word32);
+ PushFRB(instruction, word32);
+ break;
+
+ // <op> rD, UIMM (special register)
+ case PPC_ID_MFDCR:
+ case PPC_ID_MFPMR:
+ case PPC_ID_MFSPR:
+ case PPC_ID_MFTB:
+ {
+ uint32_t special = GetSpecialRegisterCommon(word32);
+
+ PushRD(instruction, word32);
+ PushUIMMValue(instruction, special);
+ break;
+ }
+
+ // <op> UIMM, rS (special register)
+ case PPC_ID_MTDCR:
+ case PPC_ID_MTPMR:
+ case PPC_ID_MTSPR:
+ {
+ uint32_t special = GetSpecialRegisterCommon(word32);
+
+ PushUIMMValue(instruction, special);
+ PushRS(instruction, word32);
+ break;
+ }
+
+ // <op> rA, rB (cache-related)
+ case PPC_ID_DCBA:
+ case PPC_ID_DCBST:
+ case PPC_ID_DCBSTEP:
+ case PPC_ID_DCBFL:
+ case PPC_ID_DCBFLP:
+ case PPC_ID_DCBI:
+ case PPC_ID_DCBTSTT:
+ case PPC_ID_DCBTT:
+ case PPC_ID_DCBZ:
+ case PPC_ID_DCBZEP:
+ case PPC_ID_DCBZL:
+ case PPC_ID_ICBI:
+ case PPC_ID_ICBIEP:
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <op> CT (cache-related)
+ case PPC_ID_DCI:
+ case PPC_ID_ICI:
+ {
+ uint32_t ct = (word32 >> 21) & 0xf;
+
+ PushUIMMValue(instruction, ct);
+ break;
+ }
+
+ // <op> CT, rA, rB (cache-related)
+ case PPC_ID_ICBLC:
+ case PPC_ID_ICBLQ:
+ case PPC_ID_ICBTLS:
+ {
+ uint32_t ct = (word32 >> 21) & 0xf;
+
+ PushUIMMValue(instruction, ct);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+ }
+
+ // <op> TH, rA, rB (cache-related)
+ case PPC_ID_DCBTEP:
+ case PPC_ID_DCBTSTEP:
+ {
+ uint32_t th = (word32 >> 21) & 0x1f;
+ PushUIMMValue(instruction, th);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+ }
+
+ // <op> rA, rB, TH
+ case PPC_ID_DCBT:
+ {
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ uint32_t th = (word32 >> 21) & 0x1f;
+ if (th != 0)
+ PushUIMMValue(instruction, th);
+ break;
+ }
+
+ case PPC_ID_DCBTST:
+ {
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ uint32_t th = (word32 >> 21) & 0x1f;
+ if (th != 0)
+ PushUIMMValue(instruction, th);
+ break;
+ }
+
+ case PPC_ID_MTFSB0x:
+ case PPC_ID_MTFSB1x:
+ {
+ uint32_t bt = (word32 >> 21) & 0x1f;
+
+ PushUIMMValue(instruction, bt);
+ instruction->flags.rc = word32 & 0x1;
+ break;
+ }
+
+ case PPC_ID_TLBREHI:
+ case PPC_ID_TLBRELO:
+ // TODO: this is how capstone disassembles these
+ // instructions, but some architectures have no
+ // operands and this is just "tlbre"
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+
+ break;
+
+ case PPC_ID_TLBWEHI:
+ case PPC_ID_TLBWELO:
+ // TODO: this is how capstone disassembles these
+ // instructions, but some architectures have no
+ // operands and this is just "tlbwe"
+ PushRS(instruction, word32);
+ PushRA(instruction, word32);
+
+ break;
+
+ // one-off instructions
+ case PPC_ID_ADDICx:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff)));
+
+ instruction->flags.rc = (word32 >> 26) == 0x0d;
+ break;
+
+ case PPC_ID_ADDIS:
+ // different from other shifted immediates because signed imm
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff)));
+ break;
+
+ case PPC_ID_ADDPCIS:
+ {
+ PushRD(instruction, word32);
+ uint64_t d1 = (word32 >> 16) & 0x1f;
+ uint64_t d0 = (word32 >> 6) & 0x3ff;
+ uint64_t d2 = word32 & 0x1;
+ uint64_t d = (d0 << 6) | (d1 << 1) | d2;
+ PushUIMMValue(instruction, d);
+ break;
+ }
+
+ case PPC_ID_ANDIx:
+ // different from other logical immediates because of rc bit
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, word32 & 0xffff);
+ instruction->flags.rc = 1;
+ break;
+
+ case PPC_ID_ANDIS:
+ // different from other logical shifted immediates because of rc bit
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, word32 & 0xffff);
+
+ instruction->flags.rc = 1;
+ break;
+
+ case PPC_ID_Bx:
+ {
+ instruction->flags.lk = word32 & 0x1;
+ instruction->flags.aa = (word32 & 0x2) != 0;
+
+ uint64_t li = word32 & 0x03fffffc;
+ li = (uint64_t)(int64_t)sign_extend(li, 26);
+ uint64_t target = instruction->flags.aa ? li : address + li;
+
+ PushLabel(instruction, target);
+
+ break;
+ }
+
+ case PPC_ID_CMPRB:
+ {
+ PushCRFD(instruction, word32);
+
+ uint32_t l = (word32 >> 21) & 0x1;
+ PushUIMMValue(instruction, l);
+
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+ }
+
+ case PPC_ID_DARN:
+ {
+ uint32_t l = (word32 >> 16) & 0x3;
+ PushRD(instruction, word32);
+ PushUIMMValue(instruction, l);
+ break;
+ }
+
+ case PPC_ID_DCBF:
+ case PPC_ID_DCBFEP:
+ {
+ uint32_t l = (word32 >> 21) & 0x3;
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ if (l != 0)
+ PushUIMMValue(instruction, l);
+
+ break;
+ }
+
+ case PPC_ID_EXTSWSLIx:
+ {
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ uint32_t sh5 = (word32 >> 1) & 0x1;
+ uint32_t sh0_4 = (word32 >> 11) & 0x1f;
+ PushUIMMValue(instruction, (sh5 << 5) | sh0_4);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+ }
+
+ case PPC_ID_FTDIV:
+ PushCRFD(instruction, word32);
+ PushFRA(instruction, word32);
+ PushFRB(instruction, word32);
+ break;
+
+ case PPC_ID_FTSQRT:
+ PushCRFD(instruction, word32);
+ PushFRB(instruction, word32);
+ break;
+
+ case PPC_ID_MFBHRBE:
+ {
+ uint32_t bhrbe = (word32 >> 11) & 0x3ff;
+ PushRD(instruction, word32);
+ PushUIMMValue(instruction, bhrbe);
+ break;
+ }
+
+ case PPC_ID_MFOCRF:
+ {
+ uint32_t fxm = (word32 >> 12) & 0xff;
+
+ PushRD(instruction, word32);
+ PushUIMMValue(instruction, fxm);
+ break;
+ }
+
+
+ case PPC_ID_ICBT:
+ {
+ uint32_t ct = (word32 >> 21) & 0xf;
+
+ PushUIMMValue(instruction, ct);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+
+ break;
+ }
+
+ case PPC_ID_ISEL:
+ {
+ uint32_t bc = (word32 >> 6) & 0x1f;
+
+ PushRD(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ PushUIMMValue(instruction, bc);
+ break;
+ }
+
+ case PPC_ID_LI:
+ PushRD(instruction, word32);
+ PushSIMMValue(instruction, (int32_t)((int16_t)(word32 & 0xffff)));
+ break;
+
+ case PPC_ID_LIS:
+ {
+ PushRD(instruction, word32);
+ PushSIMMValue(instruction, (int32_t)(word32 & 0xffff));
+ break;
+ }
+
+ case PPC_ID_LSWI:
+ {
+ uint32_t nb = (word32 >> 11) & 0x1f;
+
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushUIMMValue(instruction, nb);
+ break;
+ }
+
+ case PPC_ID_MBAR:
+ {
+ uint32_t mo = (word32 >> 21) & 0x1f;
+ PushUIMMValue(instruction, mo);
+ break;
+ }
+
+ case PPC_ID_MFFSx:
+ case PPC_ID_MFFSCE:
+ case PPC_ID_MFFSL:
+ PushFRD(instruction, word32);
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_MFFSCDRN:
+ case PPC_ID_MFFSCRN:
+ PushFRD(instruction, word32);
+ PushFRB(instruction, word32);
+ break;
+
+ case PPC_ID_MFFSCDRNI:
+ {
+ uint32_t drm = (word32 >> 11) & 0x7;
+ PushFRD(instruction, word32);
+ PushUIMMValue(instruction, drm);
+ break;
+ }
+
+ case PPC_ID_MFFSCRNI:
+ {
+ uint32_t rm = (word32 >> 11) & 0x3;
+ PushFRD(instruction, word32);
+ PushUIMMValue(instruction, rm);
+ break;
+ }
+
+ case PPC_ID_MFSR:
+ {
+ uint32_t sr = (word32 >> 16) & 0xf;
+
+ PushRD(instruction, word32);
+ PushUIMMValue(instruction, sr);
+ break;
+ }
+
+ case PPC_ID_MFSRIN:
+ PushRD(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+
+ case PPC_ID_MRx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_MTCRF:
+ {
+ uint32_t crm = (word32 >> 12) & 0xff;
+
+ PushUIMMValue(instruction, crm);
+ PushRS(instruction, word32);
+ break;
+ }
+
+ case PPC_ID_MTFSFx:
+ {
+ uint32_t w = (word32 >> 16) & 0x1;
+ uint32_t l = (word32 >> 25) & 0x1;
+ uint32_t flm = (word32 >> 17) & 0xff;
+
+ PushUIMMValue(instruction, flm);
+ PushFRB(instruction, word32);
+
+ if (w != 0 || l != 0)
+ {
+ PushUIMMValue(instruction, l);
+ PushUIMMValue(instruction, w);
+ }
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+ }
+
+ case PPC_ID_MTFSFIx:
+ {
+ uint32_t u = (word32 >> 12) & 0xf;
+ uint32_t w = (word32 >> 16) & 0x1;
+
+ PushCRFD(instruction, word32);
+ PushUIMMValue(instruction, u);
+ if (w != 0)
+ PushUIMMValue(instruction, w);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+ }
+
+ case PPC_ID_MTOCRF:
+ {
+ uint32_t fxm = (word32 >> 12) & 0xff;
+
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, fxm);
+ break;
+ }
+
+ case PPC_ID_MTSR:
+ {
+ uint32_t sr = (word32 >> 16) & 0xf;
+
+ PushUIMMValue(instruction, sr);
+ PushRS(instruction, word32);
+
+ break;
+ }
+
+ case PPC_ID_MTSRIN:
+ PushRS(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ case PPC_ID_RFEBB:
+ PushUIMMValue(instruction, (word32 >> 11) & 0x1);
+ break;
+
+ case PPC_ID_RLWIMIx:
+ case PPC_ID_RLWINMx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, GetSH(word32));
+ PushUIMMValue(instruction, GetMB(word32));
+ PushUIMMValue(instruction, GetME(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_RLWNMx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushRB(instruction, word32);
+ PushUIMMValue(instruction, GetMB(word32));
+ PushUIMMValue(instruction, GetME(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_SC:
+ {
+ uint32_t lev = (word32 >> 5) & 0x7f;
+ if (lev != 0)
+ PushUIMMValue(instruction, lev);
+
+ break;
+ }
+
+ case PPC_ID_SETB:
+ PushRD(instruction, word32);
+ PushCRFS(instruction, word32);
+ break;
+
+ case PPC_ID_SLBMFEE:
+ case PPC_ID_SLBMFEV:
+ PushRD(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ case PPC_ID_SLBMTE:
+ case PPC_ID_SLBIEG:
+ PushRS(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ case PPC_ID_SRADIx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, GetSH64(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_SRAWIx:
+ PushRA(instruction, word32);
+ PushRS(instruction, word32);
+ PushUIMMValue(instruction, GetSH(word32));
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ case PPC_ID_STSWI:
+ {
+ uint32_t nb = (word32 >> 11) & 0x1f;
+
+ PushRS(instruction, word32);
+ PushRA(instruction, word32);
+ PushUIMMValue(instruction, nb);
+ break;
+ }
+
+ case PPC_ID_TBEGIN:
+ {
+ uint32_t r = (word32 >> 21) & 0x1;
+
+ PushUIMMValue(instruction, r);
+ break;
+ }
+
+ case PPC_ID_TEND:
+ {
+ uint32_t a = (word32 >> 25) & 0x1;
+
+ PushUIMMValue(instruction, a);
+ break;
+ }
+
+ case PPC_ID_TLBIE:
+ PushRB(instruction, word32);
+ PushRS(instruction, word32);
+ break;
+
+ case PPC_ID_TLBIVAX:
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ case PPC_ID_TSR:
+ {
+ uint32_t l = (word32 >> 21) & 0x1;
+
+ PushUIMMValue(instruction, l);
+ break;
+ }
+
+ case PPC_ID_WAIT:
+ {
+ uint32_t wc = (word32 >> 21) & 0x3;
+
+ if (wc != 0)
+ PushUIMMValue(instruction, wc);
+
+ break;
+ }
+
+ case PPC_ID_WRTEEI:
+ {
+ uint32_t e = (word32 & 0x00008000) != 0;
+
+ PushUIMMValue(instruction, e);
+ break;
+ }
+
+ // ALTIVEC INSTRUCTIONS
+
+ // <op> vD, vA, vB, vC
+ case PPC_ID_AV_VADDECUQ:
+ case PPC_ID_AV_VADDEUQM:
+ case PPC_ID_AV_VMHADDSHS:
+ case PPC_ID_AV_VMHRADDSHS:
+ case PPC_ID_AV_VMLADDUHM:
+ case PPC_ID_AV_VSUBECUQ:
+ case PPC_ID_AV_VSUBEUQM:
+ case PPC_ID_AV_VMSUMMBM:
+ case PPC_ID_AV_VMSUMUBM:
+ case PPC_ID_AV_VMSUMSHM:
+ case PPC_ID_AV_VMSUMSHS:
+ case PPC_ID_AV_VMSUMUHM:
+ case PPC_ID_AV_VMSUMUHS:
+ case PPC_ID_AV_VPERM:
+ case PPC_ID_AV_VPERMR:
+ case PPC_ID_AV_VPERMXOR:
+ case PPC_ID_AV_VSEL:
+ PushAltivecVD(instruction, word32);
+ PushAltivecVA(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ PushAltivecVC(instruction, word32);
+ break;
+
+ // <op> vD, vA, vC, vB (note swapped vC, vB)
+ case PPC_ID_AV_VMADDFP:
+ case PPC_ID_AV_VNMSUBFP:
+ PushAltivecVD(instruction, word32);
+ PushAltivecVA(instruction, word32);
+ PushAltivecVC(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ break;
+
+ // <op> vD, vA, vB
+ case PPC_ID_AV_VABSDUB:
+ case PPC_ID_AV_VABSDUH:
+ case PPC_ID_AV_VABSDUW:
+ case PPC_ID_AV_VADDUQM:
+ case PPC_ID_AV_VADDCUQ:
+ case PPC_ID_AV_BCDUS:
+ case PPC_ID_AV_BCDUTRUNC:
+ case PPC_ID_AV_BCDCPSGN:
+ case PPC_ID_AV_VADDCUW:
+ case PPC_ID_AV_VADDFP:
+ case PPC_ID_AV_VADDSBS:
+ case PPC_ID_AV_VADDSHS:
+ case PPC_ID_AV_VADDSWS:
+ case PPC_ID_AV_VADDUBM:
+ case PPC_ID_AV_VADDUBS:
+ case PPC_ID_AV_VADDUDM:
+ case PPC_ID_AV_VADDUHM:
+ case PPC_ID_AV_VADDUHS:
+ case PPC_ID_AV_VADDUWM:
+ case PPC_ID_AV_VADDUWS:
+ case PPC_ID_AV_VAND:
+ case PPC_ID_AV_VANDC:
+ case PPC_ID_AV_VAVGSB:
+ case PPC_ID_AV_VAVGSH:
+ case PPC_ID_AV_VAVGSW:
+ case PPC_ID_AV_VAVGUB:
+ case PPC_ID_AV_VAVGUH:
+ case PPC_ID_AV_VAVGUW:
+ case PPC_ID_AV_VBPERMD:
+ case PPC_ID_AV_VBPERMQ:
+ case PPC_ID_AV_VCIPHER:
+ case PPC_ID_AV_VCIPHERLAST:
+ case PPC_ID_AV_VEQV:
+ case PPC_ID_AV_VMAXFP:
+ case PPC_ID_AV_VMAXSB:
+ case PPC_ID_AV_VMAXSD:
+ case PPC_ID_AV_VMAXSH:
+ case PPC_ID_AV_VMAXSW:
+ case PPC_ID_AV_VMAXUB:
+ case PPC_ID_AV_VMAXUD:
+ case PPC_ID_AV_VMAXUH:
+ case PPC_ID_AV_VMAXUW:
+ case PPC_ID_AV_VMINFP:
+ case PPC_ID_AV_VMINUB:
+ case PPC_ID_AV_VMINUD:
+ case PPC_ID_AV_VMINUH:
+ case PPC_ID_AV_VMINUW:
+ case PPC_ID_AV_VMINSB:
+ case PPC_ID_AV_VMINSD:
+ case PPC_ID_AV_VMINSH:
+ case PPC_ID_AV_VMINSW:
+ case PPC_ID_AV_VMRGEW:
+ case PPC_ID_AV_VMRGHB:
+ case PPC_ID_AV_VMRGHH:
+ case PPC_ID_AV_VMRGHW:
+ case PPC_ID_AV_VMRGLB:
+ case PPC_ID_AV_VMRGLH:
+ case PPC_ID_AV_VMRGLW:
+ case PPC_ID_AV_VMRGOW:
+ case PPC_ID_AV_VMUL10EUQ:
+ case PPC_ID_AV_VMUL10ECUQ:
+ case PPC_ID_AV_VMULESB:
+ case PPC_ID_AV_VMULESH:
+ case PPC_ID_AV_VMULESW:
+ case PPC_ID_AV_VMULEUB:
+ case PPC_ID_AV_VMULEUH:
+ case PPC_ID_AV_VMULEUW:
+ case PPC_ID_AV_VMULOSB:
+ case PPC_ID_AV_VMULOSH:
+ case PPC_ID_AV_VMULOSW:
+ case PPC_ID_AV_VMULOUB:
+ case PPC_ID_AV_VMULOUH:
+ case PPC_ID_AV_VMULOUW:
+ case PPC_ID_AV_VMULUWM:
+ case PPC_ID_AV_VNAND:
+ case PPC_ID_AV_VNCIPHER:
+ case PPC_ID_AV_VNCIPHERLAST:
+ case PPC_ID_AV_VNOR:
+ case PPC_ID_AV_VOR:
+ case PPC_ID_AV_VORC:
+ case PPC_ID_AV_VPKPX:
+ case PPC_ID_AV_VPKSDSS:
+ case PPC_ID_AV_VPKSDUS:
+ case PPC_ID_AV_VPKSHSS:
+ case PPC_ID_AV_VPKSHUS:
+ case PPC_ID_AV_VPKSWSS:
+ case PPC_ID_AV_VPKSWUS:
+ case PPC_ID_AV_VPKUDUM:
+ case PPC_ID_AV_VPKUDUS:
+ case PPC_ID_AV_VPKUHUM:
+ case PPC_ID_AV_VPKUHUS:
+ case PPC_ID_AV_VPKUWUM:
+ case PPC_ID_AV_VPKUWUS:
+ case PPC_ID_AV_VPMSUMB:
+ case PPC_ID_AV_VPMSUMD:
+ case PPC_ID_AV_VPMSUMH:
+ case PPC_ID_AV_VPMSUMW:
+ case PPC_ID_AV_VRLB:
+ case PPC_ID_AV_VRLD:
+ case PPC_ID_AV_VRLDMI:
+ case PPC_ID_AV_VRLDNM:
+ case PPC_ID_AV_VRLH:
+ case PPC_ID_AV_VRLW:
+ case PPC_ID_AV_VRLWMI:
+ case PPC_ID_AV_VRLWNM:
+ case PPC_ID_AV_VSL:
+ case PPC_ID_AV_VSLB:
+ case PPC_ID_AV_VSLD:
+ case PPC_ID_AV_VSLH:
+ case PPC_ID_AV_VSLO:
+ case PPC_ID_AV_VSLV:
+ case PPC_ID_AV_VSLW:
+ case PPC_ID_AV_VSR:
+ case PPC_ID_AV_VSRAB:
+ case PPC_ID_AV_VSRAD:
+ case PPC_ID_AV_VSRAH:
+ case PPC_ID_AV_VSRAW:
+ case PPC_ID_AV_VSRB:
+ case PPC_ID_AV_VSRD:
+ case PPC_ID_AV_VSRH:
+ case PPC_ID_AV_VSRO:
+ case PPC_ID_AV_VSRV:
+ case PPC_ID_AV_VSRW:
+ case PPC_ID_AV_VSUBCUQ:
+ case PPC_ID_AV_VSUBCUW:
+ case PPC_ID_AV_VSUBFP:
+ case PPC_ID_AV_VSUBSBS:
+ case PPC_ID_AV_VSUBSHS:
+ case PPC_ID_AV_VSUBSWS:
+ case PPC_ID_AV_VSUBUBS:
+ case PPC_ID_AV_VSUBUHS:
+ case PPC_ID_AV_VSUBUQM:
+ case PPC_ID_AV_VSUBUWS:
+ case PPC_ID_AV_VSUBUBM:
+ case PPC_ID_AV_VSUBUDM:
+ case PPC_ID_AV_VSUBUHM:
+ case PPC_ID_AV_VSUBUWM:
+ case PPC_ID_AV_VSUM2SWS:
+ case PPC_ID_AV_VSUM4SBS:
+ case PPC_ID_AV_VSUM4SHS:
+ case PPC_ID_AV_VSUM4UBS:
+ case PPC_ID_AV_VSUMSWS:
+ case PPC_ID_AV_VXOR:
+ PushAltivecVD(instruction, word32);
+ PushAltivecVA(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ break;
+
+ // <op>[.] vD, vA, vB
+ case PPC_ID_AV_VCMPBFPx:
+ case PPC_ID_AV_VCMPEQFPx:
+ case PPC_ID_AV_VCMPGEFPx:
+ case PPC_ID_AV_VCMPEQUBx:
+ case PPC_ID_AV_VCMPEQUDx:
+ case PPC_ID_AV_VCMPEQUHx:
+ case PPC_ID_AV_VCMPEQUWx:
+ case PPC_ID_AV_VCMPGTFPx:
+ case PPC_ID_AV_VCMPGTSBx:
+ case PPC_ID_AV_VCMPGTSDx:
+ case PPC_ID_AV_VCMPGTSHx:
+ case PPC_ID_AV_VCMPGTSWx:
+ case PPC_ID_AV_VCMPGTUBx:
+ case PPC_ID_AV_VCMPGTUDx:
+ case PPC_ID_AV_VCMPGTUHx:
+ case PPC_ID_AV_VCMPGTUWx:
+ case PPC_ID_AV_VCMPNEBx:
+ case PPC_ID_AV_VCMPNEHx:
+ case PPC_ID_AV_VCMPNEWx:
+ case PPC_ID_AV_VCMPNEZBx:
+ case PPC_ID_AV_VCMPNEZHx:
+ case PPC_ID_AV_VCMPNEZWx:
+ PushAltivecVD(instruction, word32);
+ PushAltivecVA(instruction, word32);
+ PushAltivecVB(instruction, word32);
+
+ instruction->flags.rc = (word32 >> 10) & 0x1;
+ break;
+
+ // <op> vD, vA
+ case PPC_ID_AV_VMUL10CUQ:
+ case PPC_ID_AV_VMUL10UQ:
+ case PPC_ID_AV_VSBOX:
+ PushAltivecVD(instruction, word32);
+ PushAltivecVA(instruction, word32);
+ break;
+
+ // <op> vD, vB
+ case PPC_ID_AV_BCDCTN:
+ case PPC_ID_AV_BCDCTSQ:
+ case PPC_ID_AV_VCLZB:
+ case PPC_ID_AV_VCLZD:
+ case PPC_ID_AV_VCLZH:
+ case PPC_ID_AV_VCLZW:
+ case PPC_ID_AV_VCTZB:
+ case PPC_ID_AV_VCTZD:
+ case PPC_ID_AV_VCTZH:
+ case PPC_ID_AV_VCTZW:
+ case PPC_ID_AV_VEXPTEFP:
+ case PPC_ID_AV_VEXTSB2D:
+ case PPC_ID_AV_VEXTSB2W:
+ case PPC_ID_AV_VEXTSH2D:
+ case PPC_ID_AV_VEXTSH2W:
+ case PPC_ID_AV_VEXTSW2D:
+ case PPC_ID_AV_VGBBD:
+ case PPC_ID_AV_VLOGEFP:
+ case PPC_ID_AV_VMR:
+ case PPC_ID_AV_VNEGD:
+ case PPC_ID_AV_VNEGW:
+ case PPC_ID_AV_VNOT:
+ case PPC_ID_AV_VPOPCNTB:
+ case PPC_ID_AV_VPOPCNTD:
+ case PPC_ID_AV_VPOPCNTH:
+ case PPC_ID_AV_VPOPCNTW:
+ case PPC_ID_AV_VPRTYBD:
+ case PPC_ID_AV_VPRTYBQ:
+ case PPC_ID_AV_VPRTYBW:
+ case PPC_ID_AV_VREFP:
+ case PPC_ID_AV_VRFIM:
+ case PPC_ID_AV_VRFIN:
+ case PPC_ID_AV_VRFIP:
+ case PPC_ID_AV_VRFIZ:
+ case PPC_ID_AV_VRSQRTEFP:
+ case PPC_ID_AV_VUPKHPX:
+ case PPC_ID_AV_VUPKHSB:
+ case PPC_ID_AV_VUPKHSH:
+ case PPC_ID_AV_VUPKHSW:
+ case PPC_ID_AV_VUPKLPX:
+ case PPC_ID_AV_VUPKLSB:
+ case PPC_ID_AV_VUPKLSH:
+ case PPC_ID_AV_VUPKLSW:
+ PushAltivecVD(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ break;
+
+ // <op> vD, vB, UIMM
+ case PPC_ID_AV_VCFSX:
+ case PPC_ID_AV_VCFUX:
+ case PPC_ID_AV_VCTSXS:
+ case PPC_ID_AV_VCTUXS:
+ case PPC_ID_AV_VSPLTB:
+ case PPC_ID_AV_VSPLTH:
+ case PPC_ID_AV_VSPLTW:
+ PushAltivecVD(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ PushUIMMValue(instruction, (word32 >> 16) & 0x1f);
+ break;
+
+ // <op> vD, SIMM
+ case PPC_ID_AV_VSPLTISB:
+ case PPC_ID_AV_VSPLTISH:
+ case PPC_ID_AV_VSPLTISW:
+ {
+ PushAltivecVD(instruction, word32);
+
+ int32_t simm = sign_extend((word32 >> 16) & 0x1f, 5);
+ PushSIMMValue(instruction, simm);
+ break;
+ }
+
+ // <op> vD, d(rA)
+ case PPC_ID_AV_LVEBX:
+ case PPC_ID_AV_LVEHX:
+ case PPC_ID_AV_LVEWX:
+ case PPC_ID_AV_LVSL:
+ case PPC_ID_AV_LVSR:
+ case PPC_ID_AV_LVX:
+ case PPC_ID_AV_LVXL:
+ PushAltivecVD(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <op> vS, d(rA)
+ case PPC_ID_AV_STVEBX:
+ case PPC_ID_AV_STVEHX:
+ case PPC_ID_AV_STVEWX:
+ case PPC_ID_AV_STVX:
+ case PPC_ID_AV_STVXL:
+ PushAltivecVS(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ case PPC_ID_AV_DST:
+ case PPC_ID_AV_DSTST:
+ case PPC_ID_AV_DSTSTT:
+ case PPC_ID_AV_DSTT:
+ {
+ uint32_t strm = (word32 >> 21) & 0x3;
+
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ PushUIMMValue(instruction, strm);
+ break;
+ }
+
+ case PPC_ID_AV_DSS:
+ {
+ uint32_t strm = (word32 >> 21) & 0x3;
+ PushUIMMValue(instruction, strm);
+ break;
+ }
+
+ case PPC_ID_AV_MFVSCR:
+ // mfvscr vD
+ PushAltivecVD(instruction, word32);
+ break;
+
+ case PPC_ID_AV_MTVSCR:
+ // mtvscr vB
+ PushAltivecVB(instruction, word32);
+ break;
+
+ case PPC_ID_AV_VSLDOI:
+ // vsldoi vD, vA, vB, UIMM
+ PushAltivecVD(instruction, word32);
+ PushAltivecVA(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ PushUIMMValue(instruction, (word32 >> 6) & 0xf);
+ break;
+
+ // rD, rA, rB, rC (normal registers)
+ case PPC_ID_AV_MADDHD:
+ case PPC_ID_AV_MADDHDU:
+ case PPC_ID_AV_MADDLD:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ PushRC(instruction, word32);
+ break;
+
+ // vrD, vrA, vrB, ps
+ case PPC_ID_AV_BCDADD:
+ case PPC_ID_AV_BCDSUB:
+ case PPC_ID_AV_BCDS:
+ case PPC_ID_AV_BCDSR:
+ case PPC_ID_AV_BCDTRUNC:
+ {
+ PushAltivecVD(instruction, word32);
+ PushAltivecVA(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ uint32_t ps = (word32 & 0x200) != 0;
+ PushUIMMValue(instruction, ps);
+ break;
+ }
+
+
+ // vrD, vrB, ps
+ case PPC_ID_AV_BCDCFN:
+ case PPC_ID_AV_BCDCFZ:
+ case PPC_ID_AV_BCDCTZ:
+ case PPC_ID_AV_BCDCFSQ:
+ case PPC_ID_AV_BCDSETSGN:
+ // PS isn't in all of these instructions, but it gets
+ // filtered out in subop decode
+ PushAltivecVD(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ uint32_t ps = (word32 & 0x200) != 0;
+ PushUIMMValue(instruction, ps);
+ break;
+
+
+ // vrD, vrB, UIM
+ case PPC_ID_AV_VEXTRACTD:
+ case PPC_ID_AV_VEXTRACTUB:
+ case PPC_ID_AV_VEXTRACTUH:
+ case PPC_ID_AV_VEXTRACTUW:
+ case PPC_ID_AV_VINSERTB:
+ case PPC_ID_AV_VINSERTD:
+ case PPC_ID_AV_VINSERTH:
+ case PPC_ID_AV_VINSERTW:
+ PushAltivecVD(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ PushUIMMValue(instruction, (word32 >> 16) & 0xf);
+ break;
+
+ // <op> rD, rA, vB
+ case PPC_ID_AV_VEXTUBLX:
+ case PPC_ID_AV_VEXTUHLX:
+ case PPC_ID_AV_VEXTUWLX:
+ case PPC_ID_AV_VEXTUBRX:
+ case PPC_ID_AV_VEXTUHRX:
+ case PPC_ID_AV_VEXTUWRX:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ break;
+
+ // <op> vD, vA, ST, SIX
+ case PPC_ID_AV_VSHASIGMAD:
+ case PPC_ID_AV_VSHASIGMAW:
+ PushAltivecVD(instruction, word32);
+ PushAltivecVA(instruction, word32);
+ PushUIMMValue(instruction, (word32 >> 15) & 0x1);
+ PushUIMMValue(instruction, (word32 >> 11) & 0xf);
+ break;
+
+ // <op> rD, vB
+ case PPC_ID_AV_VCLZLSBB:
+ case PPC_ID_AV_VCTZLSBB:
+ PushRD(instruction, word32);
+ PushAltivecVB(instruction, word32);
+ break;
+
+ // VSX INSTRUCTIONS
+
+ // <op> vrD, vrA, vrB <full width>
+ case PPC_ID_VSX_XVADDDP:
+ case PPC_ID_VSX_XVADDSP:
+ case PPC_ID_VSX_XVCPSGNDP:
+ case PPC_ID_VSX_XVCPSGNSP:
+ case PPC_ID_VSX_XVDIVDP:
+ case PPC_ID_VSX_XVDIVSP:
+ case PPC_ID_VSX_XVIEXPDP:
+ case PPC_ID_VSX_XVIEXPSP:
+ case PPC_ID_VSX_XVMADDADP:
+ case PPC_ID_VSX_XVMADDASP:
+ case PPC_ID_VSX_XVMADDMDP:
+ case PPC_ID_VSX_XVMADDMSP:
+ case PPC_ID_VSX_XVMAXDP:
+ case PPC_ID_VSX_XVMAXSP:
+ case PPC_ID_VSX_XVMINDP:
+ case PPC_ID_VSX_XVMINSP:
+ case PPC_ID_VSX_XVMSUBADP:
+ case PPC_ID_VSX_XVMSUBMDP:
+ case PPC_ID_VSX_XVMSUBASP:
+ case PPC_ID_VSX_XVMSUBMSP:
+ case PPC_ID_VSX_XVMULDP:
+ case PPC_ID_VSX_XVMULSP:
+ case PPC_ID_VSX_XVNMADDADP:
+ case PPC_ID_VSX_XVNMADDASP:
+ case PPC_ID_VSX_XVNMADDMDP:
+ case PPC_ID_VSX_XVNMADDMSP:
+ case PPC_ID_VSX_XVNMSUBADP:
+ case PPC_ID_VSX_XVNMSUBASP:
+ case PPC_ID_VSX_XVNMSUBMDP:
+ case PPC_ID_VSX_XVNMSUBMSP:
+ case PPC_ID_VSX_XVSUBDP:
+ case PPC_ID_VSX_XVSUBSP:
+ case PPC_ID_VSX_XXLAND:
+ case PPC_ID_VSX_XXLANDC:
+ case PPC_ID_VSX_XXLEQV:
+ case PPC_ID_VSX_XXLOR:
+ case PPC_ID_VSX_XXLNAND:
+ case PPC_ID_VSX_XXLNOR:
+ case PPC_ID_VSX_XXLORC:
+ case PPC_ID_VSX_XXLXOR:
+ case PPC_ID_VSX_XXMRGHD:
+ case PPC_ID_VSX_XXMRGHW:
+ case PPC_ID_VSX_XXMRGLD:
+ case PPC_ID_VSX_XXMRGLW:
+ case PPC_ID_VSX_XXPERM:
+ case PPC_ID_VSX_XXPERMR:
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxA(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxB(instruction, word32, VSX_WIDTH_FULL);
+ break;
+
+ // <op>[.] vrD, rA, vrB <full>
+ case PPC_ID_VSX_XVCMPEQDPx:
+ case PPC_ID_VSX_XVCMPEQSPx:
+ case PPC_ID_VSX_XVCMPGEDPx:
+ case PPC_ID_VSX_XVCMPGESPx:
+ case PPC_ID_VSX_XVCMPGTDPx:
+ case PPC_ID_VSX_XVCMPGTSPx:
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxA(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxB(instruction, word32, VSX_WIDTH_FULL);
+ instruction->flags.rc = (word32 & 0x400) != 0;
+ break;
+
+ // <op> vrD, vrA, vrB <dword0>
+ case PPC_ID_VSX_XSADDSP:
+ case PPC_ID_VSX_XSADDDP:
+ case PPC_ID_VSX_XSCMPEQDP:
+ case PPC_ID_VSX_XSCMPGEDP:
+ case PPC_ID_VSX_XSCMPGTDP:
+ case PPC_ID_VSX_XSCPSGNDP:
+ case PPC_ID_VSX_XSDIVDP:
+ case PPC_ID_VSX_XSDIVSP:
+ case PPC_ID_VSX_XSMADDADP:
+ case PPC_ID_VSX_XSMADDMDP:
+ case PPC_ID_VSX_XSMADDASP:
+ case PPC_ID_VSX_XSMADDMSP:
+ case PPC_ID_VSX_XSMAXCDP:
+ case PPC_ID_VSX_XSMAXDP:
+ case PPC_ID_VSX_XSMAXJDP:
+ case PPC_ID_VSX_XSMINCDP:
+ case PPC_ID_VSX_XSMINDP:
+ case PPC_ID_VSX_XSMINJDP:
+ case PPC_ID_VSX_XSMSUBADP:
+ case PPC_ID_VSX_XSMSUBASP:
+ case PPC_ID_VSX_XSMSUBMDP:
+ case PPC_ID_VSX_XSMSUBMSP:
+ case PPC_ID_VSX_XSMULDP:
+ case PPC_ID_VSX_XSMULSP:
+ case PPC_ID_VSX_XSNMADDADP:
+ case PPC_ID_VSX_XSNMADDASP:
+ case PPC_ID_VSX_XSNMADDMDP:
+ case PPC_ID_VSX_XSNMADDMSP:
+ case PPC_ID_VSX_XSNMSUBADP:
+ case PPC_ID_VSX_XSNMSUBASP:
+ case PPC_ID_VSX_XSNMSUBMDP:
+ case PPC_ID_VSX_XSNMSUBMSP:
+ case PPC_ID_VSX_XSSUBDP:
+ case PPC_ID_VSX_XSSUBSP:
+ PushVsxD(instruction, word32, VSX_WIDTH_DWORD0);
+ PushVsxA(instruction, word32, VSX_WIDTH_DWORD0);
+ PushVsxB(instruction, word32, VSX_WIDTH_DWORD0);
+ break;
+
+ // <op> vrD, vrB
+ case PPC_ID_VSX_XVABSDP:
+ case PPC_ID_VSX_XVABSSP:
+ case PPC_ID_VSX_XVCVDPSP:
+ case PPC_ID_VSX_XVCVDPSXDS:
+ case PPC_ID_VSX_XVCVDPSXWS:
+ case PPC_ID_VSX_XVCVDPUXDS:
+ case PPC_ID_VSX_XVCVDPUXWS:
+ case PPC_ID_VSX_XVCVSPDP:
+ case PPC_ID_VSX_XVCVSPSXDS:
+ case PPC_ID_VSX_XVCVSPSXWS:
+ case PPC_ID_VSX_XVCVSPUXDS:
+ case PPC_ID_VSX_XVCVSPUXWS:
+ case PPC_ID_VSX_XVCVSXDDP:
+ case PPC_ID_VSX_XVCVSXDSP:
+ case PPC_ID_VSX_XVCVSXWDP:
+ case PPC_ID_VSX_XVCVSXWSP:
+ case PPC_ID_VSX_XVCVUXDDP:
+ case PPC_ID_VSX_XVCVUXDSP:
+ case PPC_ID_VSX_XVCVUXWDP:
+ case PPC_ID_VSX_XVCVUXWSP:
+ case PPC_ID_VSX_XVNABSDP:
+ case PPC_ID_VSX_XVNABSSP:
+ case PPC_ID_VSX_XVNEGDP:
+ case PPC_ID_VSX_XVNEGSP:
+ case PPC_ID_VSX_XVRDPI:
+ case PPC_ID_VSX_XVRDPIC:
+ case PPC_ID_VSX_XVRDPIM:
+ case PPC_ID_VSX_XVRDPIP:
+ case PPC_ID_VSX_XVRDPIZ:
+ case PPC_ID_VSX_XVREDP:
+ case PPC_ID_VSX_XVRESP:
+ case PPC_ID_VSX_XVRSPI:
+ case PPC_ID_VSX_XVRSPIC:
+ case PPC_ID_VSX_XVRSPIM:
+ case PPC_ID_VSX_XVRSPIP:
+ case PPC_ID_VSX_XVRSPIZ:
+ case PPC_ID_VSX_XVRSQRTEDP:
+ case PPC_ID_VSX_XVRSQRTESP:
+ case PPC_ID_VSX_XVSQRTSP:
+ case PPC_ID_VSX_XVSQRTDP:
+ case PPC_ID_VSX_XVMOVDP:
+ case PPC_ID_VSX_XVMOVSP:
+ case PPC_ID_VSX_XVXEXPDP:
+ case PPC_ID_VSX_XVXEXPSP:
+ case PPC_ID_VSX_XVXSIGDP:
+ case PPC_ID_VSX_XVXSIGSP:
+ case PPC_ID_VSX_XXBRD:
+ case PPC_ID_VSX_XXBRH:
+ case PPC_ID_VSX_XXBRQ:
+ case PPC_ID_VSX_XXBRW:
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxB(instruction, word32, VSX_WIDTH_FULL);
+ break;
+
+ // <op> vrD, vrB
+ case PPC_ID_VSX_XSABSDP:
+ case PPC_ID_VSX_XSCVDPHP:
+ case PPC_ID_VSX_XSCVDPSXDS:
+ case PPC_ID_VSX_XSCVDPSP:
+ case PPC_ID_VSX_XSCVDPSPN:
+ case PPC_ID_VSX_XSCVDPSXWS:
+ case PPC_ID_VSX_XSCVDPUXDS:
+ case PPC_ID_VSX_XSCVDPUXWS:
+ case PPC_ID_VSX_XSCVSPDP:
+ case PPC_ID_VSX_XSCVHPDP:
+ case PPC_ID_VSX_XSCVSPDPN:
+ case PPC_ID_VSX_XSCVSXDDP:
+ case PPC_ID_VSX_XSCVSXDSP:
+ case PPC_ID_VSX_XSCVUXDDP:
+ case PPC_ID_VSX_XSCVUXDSP:
+ case PPC_ID_VSX_XSNABSDP:
+ case PPC_ID_VSX_XSNEGDP:
+ case PPC_ID_VSX_XSRDPI:
+ case PPC_ID_VSX_XSRDPIC:
+ case PPC_ID_VSX_XSRDPIM:
+ case PPC_ID_VSX_XSRDPIP:
+ case PPC_ID_VSX_XSRDPIZ:
+ case PPC_ID_VSX_XSREDP:
+ case PPC_ID_VSX_XSRESP:
+ case PPC_ID_VSX_XSRSP:
+ case PPC_ID_VSX_XSRSQRTESP:
+ case PPC_ID_VSX_XSRSQRTEDP:
+ case PPC_ID_VSX_XSSQRTDP:
+ case PPC_ID_VSX_XSSQRTSP:
+ case PPC_ID_VSX_XVCVHPSP:
+ case PPC_ID_VSX_XVCVSPHP:
+ PushVsxD(instruction, word32, VSX_WIDTH_DWORD0);
+ PushVsxB(instruction, word32, VSX_WIDTH_DWORD0);
+ break;
+
+ // <op> vrD, vrA, vrB, <UIMM>
+ case PPC_ID_VSX_XXPERMDI:
+ case PPC_ID_VSX_XXSLDWI:
+ {
+ uint32_t uimm = (word32 >> 8) & 0x3;
+
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxA(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxB(instruction, word32, VSX_WIDTH_FULL);
+ PushUIMMValue(instruction, uimm);
+ break;
+ }
+
+ // <op> vrD, rA, rB
+ case PPC_ID_VSX_MTVSRDD:
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <op> vrD, rA, rB (load indexed)
+ case PPC_ID_VSX_LXVB16X:
+ case PPC_ID_VSX_LXVD2X:
+ case PPC_ID_VSX_LXVDSX:
+ case PPC_ID_VSX_LXVH8X:
+ case PPC_ID_VSX_LXVL:
+ case PPC_ID_VSX_LXVLL:
+ case PPC_ID_VSX_LXVW4X:
+ case PPC_ID_VSX_LXVWSX:
+ case PPC_ID_VSX_LXVX:
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ case PPC_ID_VSX_LXSDX:
+ case PPC_ID_VSX_LXSIBZX:
+ case PPC_ID_VSX_LXSIHZX:
+ case PPC_ID_VSX_LXSIWAX:
+ case PPC_ID_VSX_LXSIWZX:
+ case PPC_ID_VSX_LXSSPX:
+ PushVsxD(instruction, word32, VSX_WIDTH_DWORD0);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <op> vrS, rA, rB (store indexed)
+ case PPC_ID_VSX_STXVB16X:
+ case PPC_ID_VSX_STXVD2X:
+ case PPC_ID_VSX_STXVH8X:
+ case PPC_ID_VSX_STXVL:
+ case PPC_ID_VSX_STXVLL:
+ case PPC_ID_VSX_STXVW4X:
+ case PPC_ID_VSX_STXVX:
+ PushVsxS(instruction, word32, VSX_WIDTH_FULL);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ case PPC_ID_VSX_STXSDX:
+ case PPC_ID_VSX_STXSIBX:
+ case PPC_ID_VSX_STXSIHX:
+ case PPC_ID_VSX_STXSIWX:
+ case PPC_ID_VSX_STXSSPX:
+ PushVsxS(instruction, word32, VSX_WIDTH_DWORD0);
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // <op> crfD, vrA, vrB <dword0>
+ case PPC_ID_VSX_XSCMPEXPDP:
+ case PPC_ID_VSX_XSCMPODP:
+ case PPC_ID_VSX_XSCMPUDP:
+ case PPC_ID_VSX_XSTDIVDP:
+ PushCRFD(instruction, word32);
+ PushVsxA(instruction, word32, VSX_WIDTH_DWORD0);
+ PushVsxB(instruction, word32, VSX_WIDTH_DWORD0);
+ break;
+
+ // <op> crfD, vrA, vrB <full>
+ case PPC_ID_VSX_XVTDIVDP:
+ case PPC_ID_VSX_XVTDIVSP:
+ PushCRFD(instruction, word32);
+ PushVsxA(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxB(instruction, word32, VSX_WIDTH_FULL);
+ break;
+
+ // <op> crfD, vrB
+ case PPC_ID_VSX_XVTSQRTSP:
+ case PPC_ID_VSX_XVTSQRTDP:
+ PushCRFD(instruction, word32);
+ PushVsxB(instruction, word32, VSX_WIDTH_FULL);
+ break;
+
+ case PPC_ID_VSX_XSTSQRTDP:
+ PushCRFD(instruction, word32);
+ PushVsxB(instruction, word32, VSX_WIDTH_DWORD0);
+ break;
+
+ // <op> vrD, rA
+ case PPC_ID_VSX_MTVSRWS:
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushRA(instruction, word32);
+ break;
+
+ case PPC_ID_VSX_MTVSRD:
+ case PPC_ID_VSX_MTVSRWA:
+ case PPC_ID_VSX_MTVSRWZ:
+ PushVsxD(instruction, word32, VSX_WIDTH_DWORD0);
+ PushRA(instruction, word32);
+ break;
+
+ // <op> rA, vrS
+ case PPC_ID_VSX_MFVSRLD:
+ PushRA(instruction, word32);
+ PushVsxS(instruction, word32, VSX_WIDTH_FULL);
+ break;
+
+ case PPC_ID_VSX_MFFPRD:
+ case PPC_ID_VSX_MFVSRWZ:
+ case PPC_ID_VSX_MFVSRD:
+ PushRA(instruction, word32);
+ PushVsxS(instruction, word32, VSX_WIDTH_DWORD0);
+ break;
+
+ // <op> vrD, vrB, UIM
+ case PPC_ID_VSX_XXINSERTW:
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxB(instruction, word32, VSX_WIDTH_FULL);
+ PushUIMMValue(instruction, (word32 >> 16) & 0xf);
+ break;
+
+ case PPC_ID_VSX_XXEXTRACTUW:
+ PushVsxD(instruction, word32, VSX_WIDTH_DWORD0);
+ PushVsxB(instruction, word32, VSX_WIDTH_DWORD0);
+ PushUIMMValue(instruction, (word32 >> 16) & 0xf);
+ break;
+
+ case PPC_ID_VSX_LXSD:
+ case PPC_ID_VSX_LXSSP:
+ {
+ PushVsxHiD(instruction, word32);
+
+ int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc));
+ PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds);
+ break;
+ }
+
+ case PPC_ID_VSX_LXV:
+ {
+ uint32_t dx = (word32 >> 3) & 0x1;
+ uint32_t d = GetD(word32);
+ uint32_t vsxd = (dx << 5) | d;
+
+ PushRegister(instruction, PPC_OP_REG_VSX_RD, VsxVr(vsxd));
+
+ uint32_t dq = (int32_t)((int16_t)(word32 & 0xfff0));
+ PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), dq);
+
+ break;
+ }
+
+ case PPC_ID_VSX_STXV:
+ {
+ uint32_t sx = (word32 >> 3) & 0x1;
+ uint32_t s = GetS(word32);
+ uint32_t vsxs = (sx << 5) | s;
+
+ PushRegister(instruction, PPC_OP_REG_VSX_RS, VsxVr(vsxs));
+
+ int32_t dq = (int32_t)((int16_t)(word32 & 0xfff0));
+ PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), dq);
+
+ break;
+ }
+
+ case PPC_ID_VSX_STXSD:
+ case PPC_ID_VSX_STXSSP:
+ {
+ PushVsxHiS(instruction, word32);
+
+ int32_t ds = (int32_t)((int16_t)(word32 & 0xfffc));
+ PushMem(instruction, PPC_OP_MEM_RA, Gpr(GetA(word32)), ds);
+ break;
+ }
+
+ // <op>[o] vrdHi, vraHi, vrbHi
+ case PPC_ID_VSX_XSADDQPx:
+ case PPC_ID_VSX_XSCPSGNQP:
+ case PPC_ID_VSX_XSDIVQPx:
+ case PPC_ID_VSX_XSIEXPQP:
+ case PPC_ID_VSX_XSMADDQPx:
+ case PPC_ID_VSX_XSMSUBQPx:
+ case PPC_ID_VSX_XSMULQPx:
+ case PPC_ID_VSX_XSNMADDQPx:
+ case PPC_ID_VSX_XSNMSUBQPx:
+ case PPC_ID_VSX_XSSUBQPx:
+ {
+ PushVsxHiD(instruction, word32);
+ PushVsxHiA(instruction, word32);
+ PushVsxHiB(instruction, word32);
+
+ instruction->flags.round2odd = word32 & 0x1;
+ break;
+ }
+
+ case PPC_ID_VSX_XSABSQP:
+ case PPC_ID_VSX_XSCVQPUWZ:
+ case PPC_ID_VSX_XSCVUDQP:
+ case PPC_ID_VSX_XSNABSQP:
+ case PPC_ID_VSX_XSCVDPQP:
+ case PPC_ID_VSX_XSCVQPDPx:
+ case PPC_ID_VSX_XSCVQPSDZ:
+ case PPC_ID_VSX_XSCVQPSWZ:
+ case PPC_ID_VSX_XSCVQPUDZ:
+ case PPC_ID_VSX_XSCVSDQP:
+ case PPC_ID_VSX_XSNEGQP:
+ case PPC_ID_VSX_XSSQRTQPx:
+ case PPC_ID_VSX_XSXEXPQP:
+ case PPC_ID_VSX_XSXSIGQP:
+ {
+ PushVsxHiD(instruction, word32);
+ PushVsxHiB(instruction, word32);
+
+ instruction->flags.round2odd = word32 & 0x1;
+ break;
+ }
+
+ case PPC_ID_VSX_XSCMPEXPQP:
+ case PPC_ID_VSX_XSCMPOQP:
+ case PPC_ID_VSX_XSCMPUQP:
+ PushCRFD(instruction, word32);
+ PushVsxHiA(instruction, word32);
+ PushVsxHiB(instruction, word32);
+
+ break;
+
+ case PPC_ID_VSX_XSTSTDCQP:
+ {
+ uint32_t dcmx = (word32 >> 16) & 0x7f;
+ PushCRFD(instruction, word32);
+ PushVsxHiB(instruction, word32);
+ PushUIMMValue(instruction, dcmx);
+ break;
+ }
+
+ // one-off VSX instructions
+ case PPC_ID_VSX_XSIEXPDP:
+ {
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+ }
+
+ case PPC_ID_VSX_XSRQPIx:
+ case PPC_ID_VSX_XSRQPXP:
+ {
+ uint32_t r = (word32 >> 16) & 0x1;
+ PushUIMMValue(instruction, r);
+ PushVsxHiD(instruction, word32);
+ PushVsxHiB(instruction, word32);
+
+ uint32_t rmc = (word32 >> 9) & 0x3;
+ PushUIMMValue(instruction, rmc);
+
+ instruction->flags.inexact = word32 & 0x1;
+ break;
+ }
+
+ case PPC_ID_VSX_XSTSTDCDP:
+ case PPC_ID_VSX_XSTSTDCSP:
+ {
+ uint32_t dcmx = (word32 >> 16) & 0x7f;
+ PushCRFD(instruction, word32);
+ PushVsxB(instruction, word32, VSX_WIDTH_DWORD0);
+ PushUIMMValue(instruction, dcmx);
+ break;
+ }
+
+ case PPC_ID_VSX_XSXEXPDP:
+ case PPC_ID_VSX_XSXSIGDP:
+ PushRD(instruction, word32);
+ PushVsxB(instruction, word32, VSX_WIDTH_DWORD0);
+ break;
+
+ case PPC_ID_VSX_XVTSTDCDP:
+ case PPC_ID_VSX_XVTSTDCSP:
+ {
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxB(instruction, word32, VSX_WIDTH_FULL);
+ uint32_t dm = (word32 >> 2) & 0x1;
+ uint32_t dc = (word32 >> 6) & 0x1;
+ uint32_t dx = (word32 >> 16) & 0x1f;
+ uint32_t dcmx = (dc << 6) | (dm << 5) | dx;
+ PushUIMMValue(instruction, dcmx);
+ break;
+ }
+
+
+ case PPC_ID_VSX_XXSPLTD:
+ {
+ uint32_t uimm = (word32 >> 8) & 0x3;
+
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxA(instruction, word32, VSX_WIDTH_FULL);
+
+ if (uimm == 3)
+ PushUIMMValue(instruction, 1);
+ else
+ PushUIMMValue(instruction, 0);
+
+ break;
+ }
+
+ case PPC_ID_VSX_XXSPLTIB:
+ {
+ uint32_t uimm8 = (word32 >> 11) & 0xff;
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushUIMMValue(instruction, uimm8);
+ break;
+ }
+
+ case PPC_ID_VSX_XXSPLTW:
+ {
+ uint32_t um = (word32 >> 16) & 0x3;
+
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxB(instruction, word32, VSX_WIDTH_FULL);
+ PushUIMMValue(instruction, um);
+ break;
+ }
+
+ case PPC_ID_VSX_XXSWAPD:
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxA(instruction, word32, VSX_WIDTH_FULL);
+ break;
+
+ case PPC_ID_VSX_XXSEL:
+ PushVsxD(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxA(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxB(instruction, word32, VSX_WIDTH_FULL);
+ PushVsxC(instruction, word32, VSX_WIDTH_FULL);
+ break;
+
+ // SPE INSTRUCTIONS
+
+ // SPE rD, rA, rB
+ case PPC_ID_SPE_BRINC:
+ case PPC_ID_SPE_EFDADD:
+ case PPC_ID_SPE_EFDDIV:
+ case PPC_ID_SPE_EFDMUL:
+ case PPC_ID_SPE_EFDSUB:
+ case PPC_ID_SPE_EFSADD:
+ case PPC_ID_SPE_EFSDIV:
+ case PPC_ID_SPE_EFSMUL:
+ case PPC_ID_SPE_EFSSUB:
+ case PPC_ID_SPE_EVADDW:
+ case PPC_ID_SPE_EVAND:
+ case PPC_ID_SPE_EVANDC:
+ case PPC_ID_SPE_EVDIVWS:
+ case PPC_ID_SPE_EVDIVWU:
+ case PPC_ID_SPE_EVEQV:
+ case PPC_ID_SPE_EVFSADD:
+ case PPC_ID_SPE_EVFSDIV:
+ case PPC_ID_SPE_EVFSMUL:
+ case PPC_ID_SPE_EVFSSUB:
+ case PPC_ID_SPE_EVLDDX:
+ case PPC_ID_SPE_EVLDHX:
+ case PPC_ID_SPE_EVLDWX:
+ case PPC_ID_SPE_EVLHHESPLATX:
+ case PPC_ID_SPE_EVLHHOSSPLATX:
+ case PPC_ID_SPE_EVLHHOUSPLATX:
+ case PPC_ID_SPE_EVLWHEX:
+ case PPC_ID_SPE_EVLWHOSX:
+ case PPC_ID_SPE_EVLWHOUX:
+ case PPC_ID_SPE_EVLWHSPLATX:
+ case PPC_ID_SPE_EVLWWSPLATX:
+ case PPC_ID_SPE_EVMERGEHI:
+ case PPC_ID_SPE_EVMERGEHILO:
+ case PPC_ID_SPE_EVMERGELO:
+ case PPC_ID_SPE_EVMERGELOHI:
+ case PPC_ID_SPE_EVMHEGSMFAA:
+ case PPC_ID_SPE_EVMHEGSMFAN:
+ case PPC_ID_SPE_EVMHEGSMIAA:
+ case PPC_ID_SPE_EVMHEGSMIAN:
+ case PPC_ID_SPE_EVMHEGUMIAA:
+ case PPC_ID_SPE_EVMHEGUMIAN:
+ case PPC_ID_SPE_EVMHESMF:
+ case PPC_ID_SPE_EVMHESMFA:
+ case PPC_ID_SPE_EVMHESMFAAW:
+ case PPC_ID_SPE_EVMHESMFANW:
+ case PPC_ID_SPE_EVMHESMI:
+ case PPC_ID_SPE_EVMHESMIA:
+ case PPC_ID_SPE_EVMHESMIAAW:
+ case PPC_ID_SPE_EVMHESMIANW:
+ case PPC_ID_SPE_EVMHESSF:
+ case PPC_ID_SPE_EVMHESSFA:
+ case PPC_ID_SPE_EVMHESSFAAW:
+ case PPC_ID_SPE_EVMHESSFANW:
+ case PPC_ID_SPE_EVMHESSIAAW:
+ case PPC_ID_SPE_EVMHESSIANW:
+ case PPC_ID_SPE_EVMHEUMI:
+ case PPC_ID_SPE_EVMHEUMIA:
+ case PPC_ID_SPE_EVMHEUMIAAW:
+ case PPC_ID_SPE_EVMHEUMIANW:
+ case PPC_ID_SPE_EVMHEUSIAAW:
+ case PPC_ID_SPE_EVMHEUSIANW:
+ case PPC_ID_SPE_EVMHOGSMFAA:
+ case PPC_ID_SPE_EVMHOGSMFAN:
+ case PPC_ID_SPE_EVMHOGSMIAA:
+ case PPC_ID_SPE_EVMHOGSMIAN:
+ case PPC_ID_SPE_EVMHOGUMIAA:
+ case PPC_ID_SPE_EVMHOGUMIAN:
+ case PPC_ID_SPE_EVMHOSMF:
+ case PPC_ID_SPE_EVMHOSMFA:
+ case PPC_ID_SPE_EVMHOSMFAAW:
+ case PPC_ID_SPE_EVMHOSMFANW:
+ case PPC_ID_SPE_EVMHOSMI:
+ case PPC_ID_SPE_EVMHOSMIA:
+ case PPC_ID_SPE_EVMHOSMIAAW:
+ case PPC_ID_SPE_EVMHOSMIANW:
+ case PPC_ID_SPE_EVMHOSSF:
+ case PPC_ID_SPE_EVMHOSSFA:
+ case PPC_ID_SPE_EVMHOSSFAAW:
+ case PPC_ID_SPE_EVMHOSSFANW:
+ case PPC_ID_SPE_EVMHOSSIAAW:
+ case PPC_ID_SPE_EVMHOSSIANW:
+ case PPC_ID_SPE_EVMHOUMI:
+ case PPC_ID_SPE_EVMHOUMIA:
+ case PPC_ID_SPE_EVMHOUMIAAW:
+ case PPC_ID_SPE_EVMHOUMIANW:
+ case PPC_ID_SPE_EVMHOUSIAAW:
+ case PPC_ID_SPE_EVMHOUSIANW:
+ case PPC_ID_SPE_EVMWHSMF:
+ case PPC_ID_SPE_EVMWHSMFA:
+ case PPC_ID_SPE_EVMWHSMI:
+ case PPC_ID_SPE_EVMWHSMIA:
+ case PPC_ID_SPE_EVMWHSSF:
+ case PPC_ID_SPE_EVMWHSSFA:
+ case PPC_ID_SPE_EVMWLSMIAAW:
+ case PPC_ID_SPE_EVMWLSMIANW:
+ case PPC_ID_SPE_EVMWLSSIAAW:
+ case PPC_ID_SPE_EVMWLSSIANW:
+ case PPC_ID_SPE_EVMWHUMI:
+ case PPC_ID_SPE_EVMWHUMIA:
+ case PPC_ID_SPE_EVMWHUSIAAW:
+ case PPC_ID_SPE_EVMWHUSIANW:
+ case PPC_ID_SPE_EVMWLUMI:
+ case PPC_ID_SPE_EVMWLUMIA:
+ case PPC_ID_SPE_EVMWLUMIAAW:
+ case PPC_ID_SPE_EVMWLUMIANW:
+ case PPC_ID_SPE_EVMWLUSIAAW:
+ case PPC_ID_SPE_EVMWLUSIANW:
+ case PPC_ID_SPE_EVMWSMF:
+ case PPC_ID_SPE_EVMWSMFA:
+ case PPC_ID_SPE_EVMWSMFAA:
+ case PPC_ID_SPE_EVMWSMFAN:
+ case PPC_ID_SPE_EVMWSMI:
+ case PPC_ID_SPE_EVMWSMIA:
+ case PPC_ID_SPE_EVMWSMIAA:
+ case PPC_ID_SPE_EVMWSMIAN:
+ case PPC_ID_SPE_EVMWSSF:
+ case PPC_ID_SPE_EVMWSSFA:
+ case PPC_ID_SPE_EVMWSSFAA:
+ case PPC_ID_SPE_EVMWSSFAN:
+ case PPC_ID_SPE_EVMWUMI:
+ case PPC_ID_SPE_EVMWUMIA:
+ case PPC_ID_SPE_EVMWUMIAA:
+ case PPC_ID_SPE_EVMWUMIAN:
+ case PPC_ID_SPE_EVNAND:
+ case PPC_ID_SPE_EVNOR:
+ case PPC_ID_SPE_EVOR:
+ case PPC_ID_SPE_EVORC:
+ case PPC_ID_SPE_EVRLW:
+ case PPC_ID_SPE_EVSLW:
+ case PPC_ID_SPE_EVSRWS:
+ case PPC_ID_SPE_EVSRWU:
+ case PPC_ID_SPE_EVSUBFW:
+ case PPC_ID_SPE_EVXOR:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // rD, rA, ///
+ case PPC_ID_SPE_EFDABS:
+ case PPC_ID_SPE_EFDNABS:
+ case PPC_ID_SPE_EFDNEG:
+ case PPC_ID_SPE_EFSABS:
+ case PPC_ID_SPE_EFSNABS:
+ case PPC_ID_SPE_EFSNEG:
+ case PPC_ID_SPE_EVABS:
+ case PPC_ID_SPE_EVADDSMIAAW:
+ case PPC_ID_SPE_EVADDSSIAAW:
+ case PPC_ID_SPE_EVADDUMIAAW:
+ case PPC_ID_SPE_EVADDUSIAAW:
+ case PPC_ID_SPE_EVCNTLSW:
+ case PPC_ID_SPE_EVCNTLZW:
+ case PPC_ID_SPE_EVEXTSB:
+ case PPC_ID_SPE_EVEXTSH:
+ case PPC_ID_SPE_EVFSABS:
+ case PPC_ID_SPE_EVFSNABS:
+ case PPC_ID_SPE_EVFSNEG:
+ case PPC_ID_SPE_EVMRA:
+ case PPC_ID_SPE_EVNEG:
+ case PPC_ID_SPE_EVSUBFSMIAAW:
+ case PPC_ID_SPE_EVSUBFSSIAAW:
+ case PPC_ID_SPE_EVSUBFUMIAAW:
+ case PPC_ID_SPE_EVSUBFUSIAAW:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ break;
+
+ // rD, ///, rB
+ case PPC_ID_SPE_EFDCFS:
+ case PPC_ID_SPE_EFDCFSF:
+ case PPC_ID_SPE_EFDCFSI:
+ case PPC_ID_SPE_EFDCFSID:
+ case PPC_ID_SPE_EFDCFUF:
+ case PPC_ID_SPE_EFDCFUI:
+ case PPC_ID_SPE_EFDCFUID:
+ case PPC_ID_SPE_EFDCTSF:
+ case PPC_ID_SPE_EFDCTSI:
+ case PPC_ID_SPE_EFDCTSIDZ:
+ case PPC_ID_SPE_EFDCTSIZ:
+ case PPC_ID_SPE_EFDCTUF:
+ case PPC_ID_SPE_EFDCTUI:
+ case PPC_ID_SPE_EFDCTUIDZ:
+ case PPC_ID_SPE_EFDCTUIZ:
+ case PPC_ID_SPE_EFSCFD:
+ case PPC_ID_SPE_EFSCFSF:
+ case PPC_ID_SPE_EFSCFSI:
+ case PPC_ID_SPE_EFSCFUF:
+ case PPC_ID_SPE_EFSCFUI:
+ case PPC_ID_SPE_EFSCTSF:
+ case PPC_ID_SPE_EFSCTSI:
+ case PPC_ID_SPE_EFSCTSIZ:
+ case PPC_ID_SPE_EFSCTUF:
+ case PPC_ID_SPE_EFSCTUI:
+ case PPC_ID_SPE_EFSCTUIZ:
+ case PPC_ID_SPE_EVFSCFSF:
+ case PPC_ID_SPE_EVFSCFSI:
+ case PPC_ID_SPE_EVFSCFUF:
+ case PPC_ID_SPE_EVFSCFUI:
+ case PPC_ID_SPE_EVFSCTSF:
+ case PPC_ID_SPE_EVFSCTSI:
+ case PPC_ID_SPE_EVFSCTSIZ:
+ case PPC_ID_SPE_EVFSCTUF:
+ case PPC_ID_SPE_EVFSCTUI:
+ case PPC_ID_SPE_EVFSCTUIZ:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ break;
+
+ // crfD//, rA, rB
+ case PPC_ID_SPE_EFDCMPEQ:
+ case PPC_ID_SPE_EFDCMPGT:
+ case PPC_ID_SPE_EFDCMPLT:
+ case PPC_ID_SPE_EFDTSTEQ:
+ case PPC_ID_SPE_EFDTSTGT:
+ case PPC_ID_SPE_EFDTSTLT:
+ case PPC_ID_SPE_EFSCMPEQ:
+ case PPC_ID_SPE_EFSCMPGT:
+ case PPC_ID_SPE_EFSCMPLT:
+ case PPC_ID_SPE_EFSTSTEQ:
+ case PPC_ID_SPE_EFSTSTGT:
+ case PPC_ID_SPE_EFSTSTLT:
+ case PPC_ID_SPE_EVCMPEQ:
+ case PPC_ID_SPE_EVCMPGTS:
+ case PPC_ID_SPE_EVCMPGTU:
+ case PPC_ID_SPE_EVCMPLTS:
+ case PPC_ID_SPE_EVCMPLTU:
+ case PPC_ID_SPE_EVFSCMPEQ:
+ case PPC_ID_SPE_EVFSCMPGT:
+ case PPC_ID_SPE_EVFSCMPLT:
+ case PPC_ID_SPE_EVFSTSTEQ:
+ case PPC_ID_SPE_EVFSTSTGT:
+ case PPC_ID_SPE_EVFSTSTLT:
+ PushCRFDImplyCR0(instruction, word32);
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ // rD, UIMM, rB
+ case PPC_ID_SPE_EVADDIW:
+ case PPC_ID_SPE_EVSUBIFW:
+ PushRD(instruction, word32);
+ PushUIMMValue(instruction, (word32 >> 16) & 0x1f);
+ PushRB(instruction, word32);
+ break;
+
+ // rD, SIMM, ///
+ case PPC_ID_SPE_EVSPLATFI:
+ case PPC_ID_SPE_EVSPLATI:
+ {
+ int32_t simm = sign_extend((word32 >> 16) & 0x1f, 5);
+ PushRD(instruction, word32);
+ PushSIMMValue(instruction, simm);
+ break;
+ }
+
+ // rD, rA, UIMM (SPE)
+ case PPC_ID_SPE_EVRLWI:
+ case PPC_ID_SPE_EVSLWI:
+ case PPC_ID_SPE_EVSRWIS:
+ case PPC_ID_SPE_EVSRWIU:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushUIMMValue(instruction, (word32 >> 11) & 0x1f);
+ break;
+
+ // rD, rA, UIMM (SPE loads)
+ case PPC_ID_SPE_EVLDD:
+ case PPC_ID_SPE_EVLDH:
+ case PPC_ID_SPE_EVLDW:
+ case PPC_ID_SPE_EVLHHESPLAT:
+ case PPC_ID_SPE_EVLHHOSSPLAT:
+ case PPC_ID_SPE_EVLHHOUSPLAT:
+ case PPC_ID_SPE_EVLWHE:
+ case PPC_ID_SPE_EVLWHOS:
+ case PPC_ID_SPE_EVLWHOU:
+ case PPC_ID_SPE_EVLWHSPLAT:
+ case PPC_ID_SPE_EVLWWSPLAT:
+ PushRD(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushUIMMValue(instruction, (word32 >> 11) & 0x1f);
+ break;
+
+ // rS, rA, UIMM (SPE)
+ case PPC_ID_SPE_EVSTDD:
+ case PPC_ID_SPE_EVSTDH:
+ case PPC_ID_SPE_EVSTDW:
+ case PPC_ID_SPE_EVSTWHE:
+ case PPC_ID_SPE_EVSTWHO:
+ case PPC_ID_SPE_EVSTWWE:
+ case PPC_ID_SPE_EVSTWWO:
+ PushRS(instruction, word32);
+ PushRAor0(instruction, word32);
+ PushUIMMValue(instruction, (word32 >> 11) & 0x1f);
+ break;
+
+ // rS, rA, rB (SPE store-indexed)
+ case PPC_ID_SPE_EVSTDDX:
+ case PPC_ID_SPE_EVSTDHX:
+ case PPC_ID_SPE_EVSTDWX:
+ case PPC_ID_SPE_EVSTWHEX:
+ case PPC_ID_SPE_EVSTWHOX:
+ case PPC_ID_SPE_EVSTWWEX:
+ case PPC_ID_SPE_EVSTWWOX:
+ PushRS(instruction, word32);
+ PushRA(instruction, word32);
+ PushUIMMValue(instruction, (word32 >> 11) & 0x1f);
+ break;
+
+ // rD, rA
+ case PPC_ID_SPE_EVMR:
+ case PPC_ID_SPE_EVNOT:
+ case PPC_ID_SPE_EVRNDW:
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ break;
+
+ // rD, rA, rB, crfS
+ case PPC_ID_SPE_EVSEL:
+ {
+ PushRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ uint32_t crfs = word32 & 0x7;
+ PushRegister(instruction, PPC_OP_REG_CRFS, Crf(crfs));
+ break;
+ }
+
+ // PAIRED-SINGLE INSTRUCTIONS
+
+ // op[.] frD, frA, frB
+ case PPC_ID_PAIREDSINGLE_PS_ADDx:
+ case PPC_ID_PAIREDSINGLE_PS_DIVx:
+ case PPC_ID_PAIREDSINGLE_PS_MERGE00x:
+ case PPC_ID_PAIREDSINGLE_PS_MERGE01x:
+ case PPC_ID_PAIREDSINGLE_PS_MERGE10x:
+ case PPC_ID_PAIREDSINGLE_PS_MERGE11x:
+ case PPC_ID_PAIREDSINGLE_PS_SUBx:
+ PushFRD(instruction, word32);
+ PushFRA(instruction, word32);
+ PushFRB(instruction, word32);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ // op[.] frD, frA, frC
+ case PPC_ID_PAIREDSINGLE_PS_MULx:
+ case PPC_ID_PAIREDSINGLE_PS_MULS0x:
+ case PPC_ID_PAIREDSINGLE_PS_MULS1x:
+ PushFRD(instruction, word32);
+ PushFRA(instruction, word32);
+ PushFRC(instruction, word32);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ // op[.] frD, frB
+ case PPC_ID_PAIREDSINGLE_PS_ABSx:
+ case PPC_ID_PAIREDSINGLE_PS_MRx:
+ case PPC_ID_PAIREDSINGLE_PS_NABSx:
+ case PPC_ID_PAIREDSINGLE_PS_NEGx:
+ case PPC_ID_PAIREDSINGLE_PS_RESx:
+ case PPC_ID_PAIREDSINGLE_PS_RSQRTEx:
+ PushFRD(instruction, word32);
+ PushFRB(instruction, word32);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ // op[.] frD, frA, frC, frB
+ // (take care not to use frD, frA, frB, frC)
+ case PPC_ID_PAIREDSINGLE_PS_MADDx:
+ case PPC_ID_PAIREDSINGLE_PS_MADDS0x:
+ case PPC_ID_PAIREDSINGLE_PS_MADDS1x:
+ case PPC_ID_PAIREDSINGLE_PS_MSUBx:
+ case PPC_ID_PAIREDSINGLE_PS_NMADDx:
+ case PPC_ID_PAIREDSINGLE_PS_NMSUBx:
+ case PPC_ID_PAIREDSINGLE_PS_SELx:
+ case PPC_ID_PAIREDSINGLE_PS_SUM0x:
+ case PPC_ID_PAIREDSINGLE_PS_SUM1x:
+ PushFRD(instruction, word32);
+ PushFRA(instruction, word32);
+ PushFRC(instruction, word32);
+ PushFRB(instruction, word32);
+
+ instruction->flags.rc = word32 & 0x1;
+ break;
+
+ // op crfD, frA, frB
+ case PPC_ID_PAIREDSINGLE_PS_CMPO0:
+ case PPC_ID_PAIREDSINGLE_PS_CMPO1:
+ case PPC_ID_PAIREDSINGLE_PS_CMPU0:
+ case PPC_ID_PAIREDSINGLE_PS_CMPU1:
+ PushCRFDImplyCR0(instruction, word32);
+ PushFRA(instruction, word32);
+ PushFRB(instruction, word32);
+ break;
+
+ // load-stores
+ case PPC_ID_PAIREDSINGLE_PSQ_L:
+ case PPC_ID_PAIREDSINGLE_PSQ_LU:
+ {
+ uint32_t w = (word32 >> 15) & 0x1;
+ uint32_t i = (word32 >> 12) & 0x7;
+ uint32_t d = word32 & 0xfff;
+
+ PushFRD(instruction, word32);
+ PushMemRAOffset(instruction, word32, sign_extend(d, 12));
+ PushUIMMValue(instruction, w);
+ PushUIMMValue(instruction, i);
+ break;
+ }
+
+ case PPC_ID_PAIREDSINGLE_PSQ_LUX:
+ case PPC_ID_PAIREDSINGLE_PSQ_LX:
+ {
+ uint32_t w = (word32 >> 10) & 0x1;
+ uint32_t i = (word32 >> 7) & 0x7;
+
+ PushFRD(instruction, word32);
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ PushUIMMValue(instruction, w);
+ PushUIMMValue(instruction, i);
+ break;
+ }
+
+ case PPC_ID_PAIREDSINGLE_PSQ_ST:
+ case PPC_ID_PAIREDSINGLE_PSQ_STU:
+ {
+ uint32_t w = (word32 >> 15) & 0x1;
+ uint32_t i = (word32 >> 12) & 0x7;
+ uint32_t d = word32 & 0xfff;
+
+ PushFRS(instruction, word32);
+ PushMemRAOffset(instruction, word32, sign_extend(d, 12));
+ PushUIMMValue(instruction, w);
+ PushUIMMValue(instruction, i);
+ break;
+ }
+
+ case PPC_ID_PAIREDSINGLE_PSQ_STX:
+ case PPC_ID_PAIREDSINGLE_PSQ_STUX:
+ {
+ uint32_t w = (word32 >> 10) & 0x1;
+ uint32_t i = (word32 >> 7) & 0x7;
+
+ PushFRS(instruction, word32);
+ PushRA(instruction, word32);
+ PushRB(instruction, word32);
+ PushUIMMValue(instruction, w);
+ PushUIMMValue(instruction, i);
+ break;
+ }
+
+ // dcbz_l rA, rB
+ case PPC_ID_PAIREDSINGLE_DCBZ_L:
+ PushRAor0(instruction, word32);
+ PushRB(instruction, word32);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void FillBcxOperands(OperandsList* bcx, const Instruction* instruction)
+{
+ memset(bcx, 0, sizeof *bcx);
+
+ if (instruction->id != PPC_ID_BCx)
+ return;
+
+ uint32_t bo = instruction->operands[0].uimm;
+ uint32_t bi = instruction->operands[1].uimm;
+
+ switch (bo & 0x1e)
+ {
+ // copy BI, target
+ case 0:
+ case 2:
+ case 8:
+ case 10:
+ CopyOperand(&bcx->operands[0], &instruction->operands[1]);
+ CopyOperand(&bcx->operands[1], &instruction->operands[2]);
+ bcx->numOperands = 2;
+ break;
+
+ // use BI, copy target
+ case 4:
+ case 6:
+ case 12:
+ case 14:
+ {
+ uint32_t crn = bi >> 2;
+
+ bcx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0;
+ bcx->operands[0].reg = Crf(crn);
+ CopyOperand(&bcx->operands[1], &instruction->operands[2]);
+ bcx->numOperands = 2;
+ break;
+ }
+
+ // just copy target
+ case 16:
+ case 18:
+ case 20:
+ case 22:
+ case 24:
+ case 26:
+ case 28:
+ case 30:
+ CopyOperand(&bcx->operands[0], &instruction->operands[2]);
+ bcx->numOperands = 1;
+ break;
+
+ // copy BO, BI, target
+ default:
+ CopyOperand(&bcx->operands[0], &instruction->operands[0]);
+ CopyOperand(&bcx->operands[1], &instruction->operands[1]);
+ CopyOperand(&bcx->operands[2], &instruction->operands[2]);
+ bcx->numOperands = 3;
+
+ break;
+ }
+}
+
+void FillBcctrxOperands(OperandsList* bcctrx, const Instruction* instruction)
+{
+ memset(bcctrx, 0, sizeof *bcctrx);
+
+ if (instruction->id != PPC_ID_BCCTRx)
+ return;
+
+ uint32_t bo = instruction->operands[0].uimm;
+ uint32_t bi = instruction->operands[1].uimm;
+
+ switch (bo & 0x1e)
+ {
+ // copy BI --> crn
+ case 4:
+ case 6:
+ case 12:
+ case 14:
+ {
+ uint32_t crn = bi >> 2;
+
+ bcctrx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0;
+ bcctrx->operands[0].reg = Crf(crn);
+ bcctrx->numOperands = 1;
+ break;
+ }
+
+ // no ops (BCTR, BCTRL)
+ case 20:
+ break;
+
+ // copy BO, BI
+ default:
+ CopyOperand(&bcctrx->operands[0], &instruction->operands[0]);
+ CopyOperand(&bcctrx->operands[1], &instruction->operands[1]);
+ bcctrx->numOperands = 2;
+
+ break;
+ }
+
+}
+
+void FillBclrxOperands(OperandsList* bclrx, const Instruction* instruction)
+{
+ memset(bclrx, 0, sizeof *bclrx);
+
+ if (instruction->id != PPC_ID_BCLRx)
+ return;
+
+ uint32_t bo = instruction->operands[0].uimm;
+ uint32_t bi = instruction->operands[1].uimm;
+
+ switch (bo & 0x1e)
+ {
+ // copy BI
+ case 0:
+ case 2:
+ case 8:
+ case 10:
+ CopyOperand(&bclrx->operands[0], &instruction->operands[1]);
+ bclrx->operands[0].cls = PPC_OP_CRBIT;
+ bclrx->operands[0].crbit = (uint32_t)instruction->operands[1].uimm;
+ bclrx->numOperands = 1;
+ break;
+
+ // copy BI --> crn
+ case 4:
+ case 6:
+ case 12:
+ case 14:
+ {
+ uint32_t crn = bi >> 2;
+
+ bclrx->operands[0].cls = PPC_OP_REG_CRFS_IMPLY0;
+ bclrx->operands[0].reg = Crf(crn);
+ bclrx->numOperands = 1;
+ break;
+ }
+
+ // no ops (decrement CTR, compare to 0, but no condition check)
+ case 16:
+ case 18:
+ case 24:
+ case 26:
+
+ // no ops (BLR, BLRL)
+ case 20:
+ break;
+
+ // copy BO, BI
+ default:
+ CopyOperand(&bclrx->operands[0], &instruction->operands[0]);
+ CopyOperand(&bclrx->operands[1], &instruction->operands[1]);
+ bclrx->numOperands = 2;
+
+ break;
+ }
+}