New ppc opcode decoder.

Seems to work and match up with the old decoder (which may be bad).
Old decoder remains until all functionality is replaced.
This commit is contained in:
Ben Vanik 2015-12-27 22:53:05 -08:00
parent ca8d658ffe
commit 990d973c74
15 changed files with 2490 additions and 71 deletions

View File

@ -11,7 +11,7 @@
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/base/string_buffer.h" #include "xenia/cpu/ppc/ppc_instr.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -505,11 +505,15 @@ void Disasm_vspltisw(InstrData* i, StringBuffer* str) {
str->AppendFormat("%-8s v%d, %.8X", i->type->name, i->VX.VD, simm); str->AppendFormat("%-8s v%d, %.8X", i->type->name, i->VX.VD, simm);
} }
int DisasmPPC(InstrData* i, StringBuffer* str) { int DisasmPPC(uint32_t address, uint32_t code, StringBuffer* str) {
if (!i->type) { InstrData i;
i.address = address;
i.code = code;
i.type = GetInstrType(i.code);
if (!i.type) {
str->Append("???"); str->Append("???");
} else { } else {
i->type->disasm(i, str); i.type->disasm(&i, str);
} }
return 0; return 0;
} }

View File

@ -11,13 +11,12 @@
#define XENIA_CPU_PPC_PPC_DISASM_H_ #define XENIA_CPU_PPC_PPC_DISASM_H_
#include "xenia/base/string_buffer.h" #include "xenia/base/string_buffer.h"
#include "xenia/cpu/ppc/ppc_instr.h"
namespace xe { namespace xe {
namespace cpu { namespace cpu {
namespace ppc { namespace ppc {
int DisasmPPC(InstrData* i, StringBuffer* str); int DisasmPPC(uint32_t address, uint32_t code, StringBuffer* str);
} // namespace ppc } // namespace ppc
} // namespace cpu } // namespace cpu

View File

@ -21,6 +21,7 @@
#include "xenia/cpu/ppc/ppc_disasm.h" #include "xenia/cpu/ppc/ppc_disasm.h"
#include "xenia/cpu/ppc/ppc_frontend.h" #include "xenia/cpu/ppc/ppc_frontend.h"
#include "xenia/cpu/ppc/ppc_instr.h" #include "xenia/cpu/ppc/ppc_instr.h"
#include "xenia/cpu/ppc/ppc_opcode_info.h"
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
namespace xe { namespace xe {
@ -84,14 +85,13 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) {
uint32_t start_address = function_->address(); uint32_t start_address = function_->address();
uint32_t end_address = function_->end_address(); uint32_t end_address = function_->end_address();
InstrData i;
for (uint32_t address = start_address, offset = 0; address <= end_address; for (uint32_t address = start_address, offset = 0; address <= end_address;
address += 4, offset++) { address += 4, offset++) {
i.address = address;
i.code = xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
// TODO(benvanik): find a way to avoid using the opcode tables.
i.type = GetInstrType(i.code);
trace_info_.dest_count = 0; trace_info_.dest_count = 0;
uint32_t code =
xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
auto opcode = LookupOpcode(code);
auto& opcode_info = GetOpcodeInfo(opcode);
// Mark label, if we were assigned one earlier on in the walk. // Mark label, if we were assigned one earlier on in the walk.
// We may still get a label, but it'll be inserted by LookupLabel // We may still get a label, but it'll be inserted by LookupLabel
@ -107,15 +107,15 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) {
AnnotateLabel(address, label); AnnotateLabel(address, label);
} }
comment_buffer_.Reset(); comment_buffer_.Reset();
comment_buffer_.AppendFormat("%.8X %.8X ", address, i.code); comment_buffer_.AppendFormat("%.8X %.8X ", address, code);
DisasmPPC(&i, &comment_buffer_); DisasmPPC(address, code, &comment_buffer_);
Comment(comment_buffer_); Comment(comment_buffer_);
first_instr = last_instr(); first_instr = last_instr();
} }
// Mark source offset for debugging. // Mark source offset for debugging.
// We could omit this if we never wanted to debug. // We could omit this if we never wanted to debug.
SourceOffset(i.address); SourceOffset(address);
if (!first_instr) { if (!first_instr) {
first_instr = last_instr(); first_instr = last_instr();
} }
@ -123,8 +123,13 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) {
// Stash instruction offset. It's either the SOURCE_OFFSET or the COMMENT. // Stash instruction offset. It's either the SOURCE_OFFSET or the COMMENT.
instr_offset_list_[offset] = first_instr; instr_offset_list_[offset] = first_instr;
InstrData i;
i.address = address;
i.code = code;
i.type = GetInstrType(code);
if (!i.type) { if (!i.type) {
XELOGE("Invalid instruction %.8llX %.8X", i.address, i.code); XELOGE("Invalid instruction %.8llX %.8X", address, code);
Comment("INVALID!"); Comment("INVALID!");
// TraceInvalidInstruction(i); // TraceInvalidInstruction(i);
continue; continue;
@ -141,7 +146,7 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) {
typedef int (*InstrEmitter)(PPCHIRBuilder& f, InstrData& i); typedef int (*InstrEmitter)(PPCHIRBuilder& f, InstrData& i);
InstrEmitter emit = (InstrEmitter)i.type->emit; InstrEmitter emit = (InstrEmitter)i.type->emit;
if (i.address == FLAGS_break_on_instruction) { if (address == FLAGS_break_on_instruction) {
Comment("--break-on-instruction target"); Comment("--break-on-instruction target");
if (FLAGS_break_condition_gpr < 0) { if (FLAGS_break_condition_gpr < 0) {
@ -158,8 +163,8 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) {
} }
if (!i.type->emit || emit(*this, i)) { if (!i.type->emit || emit(*this, i)) {
XELOGE("Unimplemented instr %.8llX %.8X %s", i.address, i.code, XELOGE("Unimplemented instr %.8llX %.8X %s", address, code,
i.type->name); opcode_info.name);
Comment("UNIMPLEMENTED!"); Comment("UNIMPLEMENTED!");
// DebugBreak(); // DebugBreak();
// TraceInvalidInstruction(i); // TraceInvalidInstruction(i);

View File

@ -0,0 +1,479 @@
// This code was autogenerated by tools/ppc-table-gen.py. Do not modify!
// clang-format off
#ifndef XENIA_CPU_PPC_PPC_OPCODE_H_
#define XENIA_CPU_PPC_PPC_OPCODE_H_
#include <cstdint>
namespace xe {
namespace cpu {
namespace ppc {
// All PPC opcodes in the same order they appear in ppc_instr_table.h:
enum class PPCOpcode : uint32_t {
addcx,
addex,
addi,
addic,
addicx,
addis,
addmex,
addx,
addzex,
andcx,
andisx,
andix,
andx,
bcctrx,
bclrx,
bcx,
bx,
cmp,
cmpi,
cmpl,
cmpli,
cntlzdx,
cntlzwx,
crand,
crandc,
creqv,
crnand,
crnor,
cror,
crorc,
crxor,
dcba,
dcbf,
dcbi,
dcbst,
dcbt,
dcbtst,
dcbz,
dcbz128,
divdux,
divdx,
divwux,
divwx,
eciwx,
ecowx,
eieio,
eqvx,
extsbx,
extshx,
extswx,
fabsx,
faddsx,
faddx,
fcfidx,
fcmpo,
fcmpu,
fctidx,
fctidzx,
fctiwx,
fctiwzx,
fdivsx,
fdivx,
fmaddsx,
fmaddx,
fmrx,
fmsubsx,
fmsubx,
fmulsx,
fmulx,
fnabsx,
fnegx,
fnmaddsx,
fnmaddx,
fnmsubsx,
fnmsubx,
fresx,
frspx,
frsqrtex,
fselx,
fsqrtsx,
fsqrtx,
fsubsx,
fsubx,
icbi,
isync,
lbz,
lbzu,
lbzux,
lbzx,
ld,
ldarx,
ldbrx,
ldu,
ldux,
ldx,
lfd,
lfdu,
lfdux,
lfdx,
lfs,
lfsu,
lfsux,
lfsx,
lha,
lhau,
lhaux,
lhax,
lhbrx,
lhz,
lhzu,
lhzux,
lhzx,
lmw,
lswi,
lswx,
lvebx,
lvehx,
lvewx,
lvewx128,
lvlx,
lvlx128,
lvlxl,
lvlxl128,
lvrx,
lvrx128,
lvrxl,
lvrxl128,
lvsl,
lvsl128,
lvsr,
lvsr128,
lvx,
lvx128,
lvxl,
lvxl128,
lwa,
lwarx,
lwaux,
lwax,
lwbrx,
lwz,
lwzu,
lwzux,
lwzx,
mcrf,
mcrfs,
mcrxr,
mfcr,
mffsx,
mfmsr,
mfspr,
mftb,
mfvscr,
mtcrf,
mtfsb0x,
mtfsb1x,
mtfsfix,
mtfsfx,
mtmsr,
mtmsrd,
mtspr,
mtvscr,
mulhdux,
mulhdx,
mulhwux,
mulhwx,
mulldx,
mulli,
mullwx,
nandx,
negx,
norx,
orcx,
ori,
oris,
orx,
rldclx,
rldcrx,
rldiclx,
rldicrx,
rldicx,
rldimix,
rlwimix,
rlwinmx,
rlwnmx,
sc,
sldx,
slwx,
sradix,
sradx,
srawix,
srawx,
srdx,
srwx,
stb,
stbu,
stbux,
stbx,
std,
stdbrx,
stdcx,
stdu,
stdux,
stdx,
stfd,
stfdu,
stfdux,
stfdx,
stfiwx,
stfs,
stfsu,
stfsux,
stfsx,
sth,
sthbrx,
sthu,
sthux,
sthx,
stmw,
stswi,
stswx,
stvebx,
stvehx,
stvewx,
stvewx128,
stvlx,
stvlx128,
stvlxl,
stvlxl128,
stvrx,
stvrx128,
stvrxl,
stvrxl128,
stvx,
stvx128,
stvxl,
stvxl128,
stw,
stwbrx,
stwcx,
stwu,
stwux,
stwx,
subfcx,
subfex,
subficx,
subfmex,
subfx,
subfzex,
sync,
td,
tdi,
tw,
twi,
vaddcuw,
vaddfp,
vaddfp128,
vaddsbs,
vaddshs,
vaddsws,
vaddubm,
vaddubs,
vadduhm,
vadduhs,
vadduwm,
vadduws,
vand,
vand128,
vandc,
vandc128,
vavgsb,
vavgsh,
vavgsw,
vavgub,
vavguh,
vavguw,
vcfpsxws128,
vcfpuxws128,
vcfsx,
vcfux,
vcmpbfp,
vcmpbfp128,
vcmpeqfp,
vcmpeqfp128,
vcmpequb,
vcmpequh,
vcmpequw,
vcmpequw128,
vcmpgefp,
vcmpgefp128,
vcmpgtfp,
vcmpgtfp128,
vcmpgtsb,
vcmpgtsh,
vcmpgtsw,
vcmpgtub,
vcmpgtuh,
vcmpgtuw,
vcsxwfp128,
vctsxs,
vctuxs,
vcuxwfp128,
vexptefp,
vexptefp128,
vlogefp,
vlogefp128,
vmaddcfp128,
vmaddfp,
vmaddfp128,
vmaxfp,
vmaxfp128,
vmaxsb,
vmaxsh,
vmaxsw,
vmaxub,
vmaxuh,
vmaxuw,
vmhaddshs,
vmhraddshs,
vminfp,
vminfp128,
vminsb,
vminsh,
vminsw,
vminub,
vminuh,
vminuw,
vmladduhm,
vmrghb,
vmrghh,
vmrghw,
vmrghw128,
vmrglb,
vmrglh,
vmrglw,
vmrglw128,
vmsum3fp128,
vmsum4fp128,
vmsummbm,
vmsumshm,
vmsumshs,
vmsumubm,
vmsumuhm,
vmsumuhs,
vmulesb,
vmulesh,
vmuleub,
vmuleuh,
vmulfp128,
vmulosb,
vmulosh,
vmuloub,
vmulouh,
vnmsubfp,
vnmsubfp128,
vnor,
vnor128,
vor,
vor128,
vperm,
vperm128,
vpermwi128,
vpkd3d128,
vpkpx,
vpkshss,
vpkshss128,
vpkshus,
vpkshus128,
vpkswss,
vpkswss128,
vpkswus,
vpkswus128,
vpkuhum,
vpkuhum128,
vpkuhus,
vpkuhus128,
vpkuwum,
vpkuwum128,
vpkuwus,
vpkuwus128,
vrefp,
vrefp128,
vrfim,
vrfim128,
vrfin,
vrfin128,
vrfip,
vrfip128,
vrfiz,
vrfiz128,
vrlb,
vrlh,
vrlimi128,
vrlw,
vrlw128,
vrsqrtefp,
vrsqrtefp128,
vsel,
vsel128,
vsl,
vslb,
vsldoi,
vsldoi128,
vslh,
vslo,
vslo128,
vslw,
vslw128,
vspltb,
vsplth,
vspltisb,
vspltish,
vspltisw,
vspltisw128,
vspltw,
vspltw128,
vsr,
vsrab,
vsrah,
vsraw,
vsraw128,
vsrb,
vsrh,
vsro,
vsro128,
vsrw,
vsrw128,
vsubcuw,
vsubfp,
vsubfp128,
vsubsbs,
vsubshs,
vsubsws,
vsububm,
vsububs,
vsubuhm,
vsubuhs,
vsubuwm,
vsubuws,
vsum2sws,
vsum4sbs,
vsum4shs,
vsum4ubs,
vsumsws,
vupkd3d128,
vupkhpx,
vupkhsb,
vupkhsb128,
vupkhsh,
vupklpx,
vupklsb,
vupklsb128,
vupklsh,
vxor,
vxor128,
xori,
xoris,
xorx,
kInvalid,
};
} // namespace ppc
} // namespace cpu
} // namespace xe
#endif // XENIA_CPU_PPC_PPC_OPCODE_H_

View File

@ -0,0 +1,79 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_PPC_PPC_OPCODE_INFO_H_
#define XENIA_CPU_PPC_PPC_OPCODE_INFO_H_
#include <cstdint>
#include "xenia/cpu/ppc/ppc_opcode.h"
namespace xe {
namespace cpu {
namespace ppc {
enum class PPCOpcodeFormat {
kSC,
kD,
kB,
kI,
kX,
kXL,
kXFX,
kXFL,
kVX,
kVX128,
kVX128_1,
kVX128_2,
kVX128_3,
kVX128_4,
kVX128_5,
kVX128_R,
kVX128_P,
kVC,
kVA,
kXO,
kXW,
kA,
kDS,
kM,
kMD,
kMDS,
kMDSH,
kXS,
kDCBZ,
};
enum class PPCOpcodeGroup {
kInt,
kFp,
kVmx,
};
struct PPCOpcodeInfo {
uint32_t opcode;
const char* name;
PPCOpcodeFormat format;
PPCOpcodeGroup group;
const char* description;
};
PPCOpcode LookupOpcode(uint32_t code);
const PPCOpcodeInfo& GetOpcodeInfo(PPCOpcode opcode);
inline const PPCOpcodeInfo& LookupOpcodeInfo(uint32_t code) {
return GetOpcodeInfo(LookupOpcode(code));
}
} // namespace ppc
} // namespace cpu
} // namespace xe
#endif // XENIA_CPU_PPC_PPC_OPCODE_INFO_H_

View File

@ -0,0 +1,554 @@
// This code was autogenerated by tools/ppc-table-gen.py. Do not modify!
// clang-format off
#include <cstdint>
#include "xenia/base/assert.h"
#include "xenia/cpu/ppc/ppc_opcode.h"
#include "xenia/cpu/ppc/ppc_opcode_info.h"
namespace xe {
namespace cpu {
namespace ppc {
constexpr uint32_t ExtractBits(uint32_t v, uint32_t a, uint32_t b) {
return (v >> (32 - 1 - b)) & ((1 << (b - a + 1)) - 1);
}
#define PPC_DECODER_MISS assert_always(); return PPCOpcode::kInvalid
#define PPC_DECODER_HIT(name) return PPCOpcode::name;
PPCOpcode LookupOpcode(uint32_t code) {
switch (ExtractBits(code, 0, 5)) {
case 2: PPC_DECODER_HIT(tdi);
case 3: PPC_DECODER_HIT(twi);
case 4:
switch ((ExtractBits(code, 21, 27) << 4)|(ExtractBits(code, 30, 31) << 0)) {
case 0b00000000011: PPC_DECODER_HIT(lvsl128);
case 0b00001000011: PPC_DECODER_HIT(lvsr128);
case 0b00010000011: PPC_DECODER_HIT(lvewx128);
case 0b00011000011: PPC_DECODER_HIT(lvx128);
case 0b00110000011: PPC_DECODER_HIT(stvewx128);
case 0b00111000011: PPC_DECODER_HIT(stvx128);
case 0b01011000011: PPC_DECODER_HIT(lvxl128);
case 0b01111000011: PPC_DECODER_HIT(stvxl128);
case 0b10000000011: PPC_DECODER_HIT(lvlx128);
case 0b10001000011: PPC_DECODER_HIT(lvrx128);
case 0b10100000011: PPC_DECODER_HIT(stvlx128);
case 0b10101000011: PPC_DECODER_HIT(stvrx128);
case 0b11000000011: PPC_DECODER_HIT(lvlxl128);
case 0b11001000011: PPC_DECODER_HIT(lvrxl128);
case 0b11100000011: PPC_DECODER_HIT(stvlxl128);
case 0b11101000011: PPC_DECODER_HIT(stvrxl128);
}
switch ((ExtractBits(code, 21, 31) << 0)) {
case 0b00000000000: PPC_DECODER_HIT(vaddubm);
case 0b00000000010: PPC_DECODER_HIT(vmaxub);
case 0b00000000100: PPC_DECODER_HIT(vrlb);
case 0b00000001000: PPC_DECODER_HIT(vmuloub);
case 0b00000001010: PPC_DECODER_HIT(vaddfp);
case 0b00000001100: PPC_DECODER_HIT(vmrghb);
case 0b00000001110: PPC_DECODER_HIT(vpkuhum);
case 0b00001000000: PPC_DECODER_HIT(vadduhm);
case 0b00001000010: PPC_DECODER_HIT(vmaxuh);
case 0b00001000100: PPC_DECODER_HIT(vrlh);
case 0b00001001000: PPC_DECODER_HIT(vmulouh);
case 0b00001001010: PPC_DECODER_HIT(vsubfp);
case 0b00001001100: PPC_DECODER_HIT(vmrghh);
case 0b00001001110: PPC_DECODER_HIT(vpkuwum);
case 0b00010000000: PPC_DECODER_HIT(vadduwm);
case 0b00010000010: PPC_DECODER_HIT(vmaxuw);
case 0b00010000100: PPC_DECODER_HIT(vrlw);
case 0b00010001100: PPC_DECODER_HIT(vmrghw);
case 0b00010001110: PPC_DECODER_HIT(vpkuhus);
case 0b00011001110: PPC_DECODER_HIT(vpkuwus);
case 0b00100000010: PPC_DECODER_HIT(vmaxsb);
case 0b00100000100: PPC_DECODER_HIT(vslb);
case 0b00100001000: PPC_DECODER_HIT(vmulosb);
case 0b00100001010: PPC_DECODER_HIT(vrefp);
case 0b00100001100: PPC_DECODER_HIT(vmrglb);
case 0b00100001110: PPC_DECODER_HIT(vpkshus);
case 0b00101000010: PPC_DECODER_HIT(vmaxsh);
case 0b00101000100: PPC_DECODER_HIT(vslh);
case 0b00101001000: PPC_DECODER_HIT(vmulosh);
case 0b00101001010: PPC_DECODER_HIT(vrsqrtefp);
case 0b00101001100: PPC_DECODER_HIT(vmrglh);
case 0b00101001110: PPC_DECODER_HIT(vpkswus);
case 0b00110000000: PPC_DECODER_HIT(vaddcuw);
case 0b00110000010: PPC_DECODER_HIT(vmaxsw);
case 0b00110000100: PPC_DECODER_HIT(vslw);
case 0b00110001010: PPC_DECODER_HIT(vexptefp);
case 0b00110001100: PPC_DECODER_HIT(vmrglw);
case 0b00110001110: PPC_DECODER_HIT(vpkshss);
case 0b00111000100: PPC_DECODER_HIT(vsl);
case 0b00111001010: PPC_DECODER_HIT(vlogefp);
case 0b00111001110: PPC_DECODER_HIT(vpkswss);
case 0b01000000000: PPC_DECODER_HIT(vaddubs);
case 0b01000000010: PPC_DECODER_HIT(vminub);
case 0b01000000100: PPC_DECODER_HIT(vsrb);
case 0b01000001000: PPC_DECODER_HIT(vmuleub);
case 0b01000001010: PPC_DECODER_HIT(vrfin);
case 0b01000001100: PPC_DECODER_HIT(vspltb);
case 0b01000001110: PPC_DECODER_HIT(vupkhsb);
case 0b01001000000: PPC_DECODER_HIT(vadduhs);
case 0b01001000010: PPC_DECODER_HIT(vminuh);
case 0b01001000100: PPC_DECODER_HIT(vsrh);
case 0b01001001000: PPC_DECODER_HIT(vmuleuh);
case 0b01001001010: PPC_DECODER_HIT(vrfiz);
case 0b01001001100: PPC_DECODER_HIT(vsplth);
case 0b01001001110: PPC_DECODER_HIT(vupkhsh);
case 0b01010000000: PPC_DECODER_HIT(vadduws);
case 0b01010000010: PPC_DECODER_HIT(vminuw);
case 0b01010000100: PPC_DECODER_HIT(vsrw);
case 0b01010001010: PPC_DECODER_HIT(vrfip);
case 0b01010001100: PPC_DECODER_HIT(vspltw);
case 0b01010001110: PPC_DECODER_HIT(vupklsb);
case 0b01011000100: PPC_DECODER_HIT(vsr);
case 0b01011001010: PPC_DECODER_HIT(vrfim);
case 0b01011001110: PPC_DECODER_HIT(vupklsh);
case 0b01100000000: PPC_DECODER_HIT(vaddsbs);
case 0b01100000010: PPC_DECODER_HIT(vminsb);
case 0b01100000100: PPC_DECODER_HIT(vsrab);
case 0b01100001000: PPC_DECODER_HIT(vmulesb);
case 0b01100001010: PPC_DECODER_HIT(vcfux);
case 0b01100001100: PPC_DECODER_HIT(vspltisb);
case 0b01100001110: PPC_DECODER_HIT(vpkpx);
case 0b01101000000: PPC_DECODER_HIT(vaddshs);
case 0b01101000010: PPC_DECODER_HIT(vminsh);
case 0b01101000100: PPC_DECODER_HIT(vsrah);
case 0b01101001000: PPC_DECODER_HIT(vmulesh);
case 0b01101001010: PPC_DECODER_HIT(vcfsx);
case 0b01101001100: PPC_DECODER_HIT(vspltish);
case 0b01101001110: PPC_DECODER_HIT(vupkhpx);
case 0b01110000000: PPC_DECODER_HIT(vaddsws);
case 0b01110000010: PPC_DECODER_HIT(vminsw);
case 0b01110000100: PPC_DECODER_HIT(vsraw);
case 0b01110001010: PPC_DECODER_HIT(vctuxs);
case 0b01110001100: PPC_DECODER_HIT(vspltisw);
case 0b01111001010: PPC_DECODER_HIT(vctsxs);
case 0b01111001110: PPC_DECODER_HIT(vupklpx);
case 0b10000000000: PPC_DECODER_HIT(vsububm);
case 0b10000000010: PPC_DECODER_HIT(vavgub);
case 0b10000000100: PPC_DECODER_HIT(vand);
case 0b10000001010: PPC_DECODER_HIT(vmaxfp);
case 0b10000001100: PPC_DECODER_HIT(vslo);
case 0b10001000000: PPC_DECODER_HIT(vsubuhm);
case 0b10001000010: PPC_DECODER_HIT(vavguh);
case 0b10001000100: PPC_DECODER_HIT(vandc);
case 0b10001001010: PPC_DECODER_HIT(vminfp);
case 0b10001001100: PPC_DECODER_HIT(vsro);
case 0b10010000000: PPC_DECODER_HIT(vsubuwm);
case 0b10010000010: PPC_DECODER_HIT(vavguw);
case 0b10010000100: PPC_DECODER_HIT(vor);
case 0b10011000100: PPC_DECODER_HIT(vxor);
case 0b10100000010: PPC_DECODER_HIT(vavgsb);
case 0b10100000100: PPC_DECODER_HIT(vnor);
case 0b10101000010: PPC_DECODER_HIT(vavgsh);
case 0b10110000000: PPC_DECODER_HIT(vsubcuw);
case 0b10110000010: PPC_DECODER_HIT(vavgsw);
case 0b11000000000: PPC_DECODER_HIT(vsububs);
case 0b11000000100: PPC_DECODER_HIT(mfvscr);
case 0b11000001000: PPC_DECODER_HIT(vsum4ubs);
case 0b11001000000: PPC_DECODER_HIT(vsubuhs);
case 0b11001000100: PPC_DECODER_HIT(mtvscr);
case 0b11001001000: PPC_DECODER_HIT(vsum4shs);
case 0b11010000000: PPC_DECODER_HIT(vsubuws);
case 0b11010001000: PPC_DECODER_HIT(vsum2sws);
case 0b11100000000: PPC_DECODER_HIT(vsubsbs);
case 0b11100001000: PPC_DECODER_HIT(vsum4sbs);
case 0b11101000000: PPC_DECODER_HIT(vsubshs);
case 0b11110000000: PPC_DECODER_HIT(vsubsws);
case 0b11110001000: PPC_DECODER_HIT(vsumsws);
}
switch ((ExtractBits(code, 22, 31) << 0)) {
case 0b0000000110: PPC_DECODER_HIT(vcmpequb);
case 0b0001000110: PPC_DECODER_HIT(vcmpequh);
case 0b0010000110: PPC_DECODER_HIT(vcmpequw);
case 0b0011000110: PPC_DECODER_HIT(vcmpeqfp);
case 0b0111000110: PPC_DECODER_HIT(vcmpgefp);
case 0b1000000110: PPC_DECODER_HIT(vcmpgtub);
case 0b1001000110: PPC_DECODER_HIT(vcmpgtuh);
case 0b1010000110: PPC_DECODER_HIT(vcmpgtuw);
case 0b1011000110: PPC_DECODER_HIT(vcmpgtfp);
case 0b1100000110: PPC_DECODER_HIT(vcmpgtsb);
case 0b1101000110: PPC_DECODER_HIT(vcmpgtsh);
case 0b1110000110: PPC_DECODER_HIT(vcmpgtsw);
case 0b1111000110: PPC_DECODER_HIT(vcmpbfp);
}
switch ((ExtractBits(code, 26, 31) << 0)) {
case 0b100000: PPC_DECODER_HIT(vmhaddshs);
case 0b100001: PPC_DECODER_HIT(vmhraddshs);
case 0b100010: PPC_DECODER_HIT(vmladduhm);
case 0b100100: PPC_DECODER_HIT(vmsumubm);
case 0b100101: PPC_DECODER_HIT(vmsummbm);
case 0b100110: PPC_DECODER_HIT(vmsumuhm);
case 0b100111: PPC_DECODER_HIT(vmsumuhs);
case 0b101000: PPC_DECODER_HIT(vmsumshm);
case 0b101001: PPC_DECODER_HIT(vmsumshs);
case 0b101010: PPC_DECODER_HIT(vsel);
case 0b101011: PPC_DECODER_HIT(vperm);
case 0b101100: PPC_DECODER_HIT(vsldoi);
case 0b101110: PPC_DECODER_HIT(vmaddfp);
case 0b101111: PPC_DECODER_HIT(vnmsubfp);
}
switch ((ExtractBits(code, 27, 27) << 0)) {
case 0b1: PPC_DECODER_HIT(vsldoi128);
}
PPC_DECODER_MISS;
case 5:
switch ((ExtractBits(code, 22, 22) << 5)|(ExtractBits(code, 27, 27) << 0)) {
case 0b000000: PPC_DECODER_HIT(vperm128);
}
switch ((ExtractBits(code, 22, 25) << 2)|(ExtractBits(code, 27, 27) << 0)) {
case 0b000001: PPC_DECODER_HIT(vaddfp128);
case 0b000101: PPC_DECODER_HIT(vsubfp128);
case 0b001001: PPC_DECODER_HIT(vmulfp128);
case 0b001101: PPC_DECODER_HIT(vmaddfp128);
case 0b010001: PPC_DECODER_HIT(vmaddcfp128);
case 0b010101: PPC_DECODER_HIT(vnmsubfp128);
case 0b011001: PPC_DECODER_HIT(vmsum3fp128);
case 0b011101: PPC_DECODER_HIT(vmsum4fp128);
case 0b100000: PPC_DECODER_HIT(vpkshss128);
case 0b100001: PPC_DECODER_HIT(vand128);
case 0b100100: PPC_DECODER_HIT(vpkshus128);
case 0b100101: PPC_DECODER_HIT(vandc128);
case 0b101000: PPC_DECODER_HIT(vpkswss128);
case 0b101001: PPC_DECODER_HIT(vnor128);
case 0b101100: PPC_DECODER_HIT(vpkswus128);
case 0b101101: PPC_DECODER_HIT(vor128);
case 0b110000: PPC_DECODER_HIT(vpkuhum128);
case 0b110001: PPC_DECODER_HIT(vxor128);
case 0b110100: PPC_DECODER_HIT(vpkuhus128);
case 0b110101: PPC_DECODER_HIT(vsel128);
case 0b111000: PPC_DECODER_HIT(vpkuwum128);
case 0b111001: PPC_DECODER_HIT(vslo128);
case 0b111100: PPC_DECODER_HIT(vpkuwus128);
case 0b111101: PPC_DECODER_HIT(vsro128);
}
PPC_DECODER_MISS;
case 6:
switch ((ExtractBits(code, 21, 22) << 5)|(ExtractBits(code, 26, 27) << 0)) {
case 0b0100001: PPC_DECODER_HIT(vpermwi128);
}
switch ((ExtractBits(code, 21, 23) << 4)|(ExtractBits(code, 26, 27) << 0)) {
case 0b1100001: PPC_DECODER_HIT(vpkd3d128);
case 0b1110001: PPC_DECODER_HIT(vrlimi128);
}
switch ((ExtractBits(code, 21, 27) << 0)) {
case 0b0100011: PPC_DECODER_HIT(vcfpsxws128);
case 0b0100111: PPC_DECODER_HIT(vcfpuxws128);
case 0b0101011: PPC_DECODER_HIT(vcsxwfp128);
case 0b0101111: PPC_DECODER_HIT(vcuxwfp128);
case 0b0110011: PPC_DECODER_HIT(vrfim128);
case 0b0110111: PPC_DECODER_HIT(vrfin128);
case 0b0111011: PPC_DECODER_HIT(vrfip128);
case 0b0111111: PPC_DECODER_HIT(vrfiz128);
case 0b1100011: PPC_DECODER_HIT(vrefp128);
case 0b1100111: PPC_DECODER_HIT(vrsqrtefp128);
case 0b1101011: PPC_DECODER_HIT(vexptefp128);
case 0b1101111: PPC_DECODER_HIT(vlogefp128);
case 0b1110011: PPC_DECODER_HIT(vspltw128);
case 0b1110111: PPC_DECODER_HIT(vspltisw128);
case 0b1111111: PPC_DECODER_HIT(vupkd3d128);
}
switch ((ExtractBits(code, 22, 24) << 3)|(ExtractBits(code, 27, 27) << 0)) {
case 0b000000: PPC_DECODER_HIT(vcmpeqfp128);
case 0b001000: PPC_DECODER_HIT(vcmpgefp128);
case 0b010000: PPC_DECODER_HIT(vcmpgtfp128);
case 0b011000: PPC_DECODER_HIT(vcmpbfp128);
case 0b100000: PPC_DECODER_HIT(vcmpequw128);
}
switch ((ExtractBits(code, 22, 25) << 2)|(ExtractBits(code, 27, 27) << 0)) {
case 0b000101: PPC_DECODER_HIT(vrlw128);
case 0b001101: PPC_DECODER_HIT(vslw128);
case 0b010101: PPC_DECODER_HIT(vsraw128);
case 0b011101: PPC_DECODER_HIT(vsrw128);
case 0b101000: PPC_DECODER_HIT(vmaxfp128);
case 0b101100: PPC_DECODER_HIT(vminfp128);
case 0b110000: PPC_DECODER_HIT(vmrghw128);
case 0b110100: PPC_DECODER_HIT(vmrglw128);
case 0b111000: PPC_DECODER_HIT(vupkhsb128);
case 0b111100: PPC_DECODER_HIT(vupklsb128);
}
PPC_DECODER_MISS;
case 7: PPC_DECODER_HIT(mulli);
case 8: PPC_DECODER_HIT(subficx);
case 10: PPC_DECODER_HIT(cmpli);
case 11: PPC_DECODER_HIT(cmpi);
case 12: PPC_DECODER_HIT(addic);
case 13: PPC_DECODER_HIT(addicx);
case 14: PPC_DECODER_HIT(addi);
case 15: PPC_DECODER_HIT(addis);
case 16: PPC_DECODER_HIT(bcx);
case 17: PPC_DECODER_HIT(sc);
case 18: PPC_DECODER_HIT(bx);
case 19:
switch ((ExtractBits(code, 21, 30) << 0)) {
case 0b0000000000: PPC_DECODER_HIT(mcrf);
case 0b0000010000: PPC_DECODER_HIT(bclrx);
case 0b0000100001: PPC_DECODER_HIT(crnor);
case 0b0010000001: PPC_DECODER_HIT(crandc);
case 0b0010010110: PPC_DECODER_HIT(isync);
case 0b0011000001: PPC_DECODER_HIT(crxor);
case 0b0011100001: PPC_DECODER_HIT(crnand);
case 0b0100000001: PPC_DECODER_HIT(crand);
case 0b0100100001: PPC_DECODER_HIT(creqv);
case 0b0110100001: PPC_DECODER_HIT(crorc);
case 0b0111000001: PPC_DECODER_HIT(cror);
case 0b1000010000: PPC_DECODER_HIT(bcctrx);
}
PPC_DECODER_MISS;
case 20: PPC_DECODER_HIT(rlwimix);
case 21: PPC_DECODER_HIT(rlwinmx);
case 23: PPC_DECODER_HIT(rlwnmx);
case 24: PPC_DECODER_HIT(ori);
case 25: PPC_DECODER_HIT(oris);
case 26: PPC_DECODER_HIT(xori);
case 27: PPC_DECODER_HIT(xoris);
case 28: PPC_DECODER_HIT(andix);
case 29: PPC_DECODER_HIT(andisx);
case 30:
switch ((ExtractBits(code, 27, 29) << 0)) {
case 0b000: PPC_DECODER_HIT(rldiclx);
case 0b001: PPC_DECODER_HIT(rldicrx);
case 0b010: PPC_DECODER_HIT(rldicx);
case 0b011: PPC_DECODER_HIT(rldimix);
}
switch ((ExtractBits(code, 27, 30) << 0)) {
case 0b1000: PPC_DECODER_HIT(rldclx);
case 0b1001: PPC_DECODER_HIT(rldcrx);
}
PPC_DECODER_MISS;
case 31:
switch ((ExtractBits(code, 21, 29) << 0)) {
case 0b110011101: PPC_DECODER_HIT(sradix);
}
switch ((ExtractBits(code, 21, 30) << 0)) {
case 0b0000000000: PPC_DECODER_HIT(cmp);
case 0b0000000100: PPC_DECODER_HIT(tw);
case 0b0000000110: PPC_DECODER_HIT(lvsl);
case 0b0000000111: PPC_DECODER_HIT(lvebx);
case 0b0000010011: PPC_DECODER_HIT(mfcr);
case 0b0000010100: PPC_DECODER_HIT(lwarx);
case 0b0000010101: PPC_DECODER_HIT(ldx);
case 0b0000010111: PPC_DECODER_HIT(lwzx);
case 0b0000011000: PPC_DECODER_HIT(slwx);
case 0b0000011010: PPC_DECODER_HIT(cntlzwx);
case 0b0000011011: PPC_DECODER_HIT(sldx);
case 0b0000011100: PPC_DECODER_HIT(andx);
case 0b0000100000: PPC_DECODER_HIT(cmpl);
case 0b0000100110: PPC_DECODER_HIT(lvsr);
case 0b0000100111: PPC_DECODER_HIT(lvehx);
case 0b0000110101: PPC_DECODER_HIT(ldux);
case 0b0000110110: PPC_DECODER_HIT(dcbst);
case 0b0000110111: PPC_DECODER_HIT(lwzux);
case 0b0000111010: PPC_DECODER_HIT(cntlzdx);
case 0b0000111100: PPC_DECODER_HIT(andcx);
case 0b0001000100: PPC_DECODER_HIT(td);
case 0b0001000111: PPC_DECODER_HIT(lvewx);
case 0b0001010011: PPC_DECODER_HIT(mfmsr);
case 0b0001010100: PPC_DECODER_HIT(ldarx);
case 0b0001010110: PPC_DECODER_HIT(dcbf);
case 0b0001010111: PPC_DECODER_HIT(lbzx);
case 0b0001100111: PPC_DECODER_HIT(lvx);
case 0b0001110111: PPC_DECODER_HIT(lbzux);
case 0b0001111100: PPC_DECODER_HIT(norx);
case 0b0010000111: PPC_DECODER_HIT(stvebx);
case 0b0010010000: PPC_DECODER_HIT(mtcrf);
case 0b0010010010: PPC_DECODER_HIT(mtmsr);
case 0b0010010101: PPC_DECODER_HIT(stdx);
case 0b0010010110: PPC_DECODER_HIT(stwcx);
case 0b0010010111: PPC_DECODER_HIT(stwx);
case 0b0010100111: PPC_DECODER_HIT(stvehx);
case 0b0010110010: PPC_DECODER_HIT(mtmsrd);
case 0b0010110101: PPC_DECODER_HIT(stdux);
case 0b0010110111: PPC_DECODER_HIT(stwux);
case 0b0011000111: PPC_DECODER_HIT(stvewx);
case 0b0011010110: PPC_DECODER_HIT(stdcx);
case 0b0011010111: PPC_DECODER_HIT(stbx);
case 0b0011100111: PPC_DECODER_HIT(stvx);
case 0b0011110110: PPC_DECODER_HIT(dcbtst);
case 0b0011110111: PPC_DECODER_HIT(stbux);
case 0b0100010110: PPC_DECODER_HIT(dcbt);
case 0b0100010111: PPC_DECODER_HIT(lhzx);
case 0b0100011100: PPC_DECODER_HIT(eqvx);
case 0b0100110110: PPC_DECODER_HIT(eciwx);
case 0b0100110111: PPC_DECODER_HIT(lhzux);
case 0b0100111100: PPC_DECODER_HIT(xorx);
case 0b0101010011: PPC_DECODER_HIT(mfspr);
case 0b0101010101: PPC_DECODER_HIT(lwax);
case 0b0101010111: PPC_DECODER_HIT(lhax);
case 0b0101100111: PPC_DECODER_HIT(lvxl);
case 0b0101110011: PPC_DECODER_HIT(mftb);
case 0b0101110101: PPC_DECODER_HIT(lwaux);
case 0b0101110111: PPC_DECODER_HIT(lhaux);
case 0b0110010111: PPC_DECODER_HIT(sthx);
case 0b0110011100: PPC_DECODER_HIT(orcx);
case 0b0110110110: PPC_DECODER_HIT(ecowx);
case 0b0110110111: PPC_DECODER_HIT(sthux);
case 0b0110111100: PPC_DECODER_HIT(orx);
case 0b0111010011: PPC_DECODER_HIT(mtspr);
case 0b0111010110: PPC_DECODER_HIT(dcbi);
case 0b0111011100: PPC_DECODER_HIT(nandx);
case 0b0111100111: PPC_DECODER_HIT(stvxl);
case 0b1000000000: PPC_DECODER_HIT(mcrxr);
case 0b1000000111: PPC_DECODER_HIT(lvlx);
case 0b1000010100: PPC_DECODER_HIT(ldbrx);
case 0b1000010101: PPC_DECODER_HIT(lswx);
case 0b1000010110: PPC_DECODER_HIT(lwbrx);
case 0b1000010111: PPC_DECODER_HIT(lfsx);
case 0b1000011000: PPC_DECODER_HIT(srwx);
case 0b1000011011: PPC_DECODER_HIT(srdx);
case 0b1000100111: PPC_DECODER_HIT(lvrx);
case 0b1000110111: PPC_DECODER_HIT(lfsux);
case 0b1001010101: PPC_DECODER_HIT(lswi);
case 0b1001010110: PPC_DECODER_HIT(sync);
case 0b1001010111: PPC_DECODER_HIT(lfdx);
case 0b1001110111: PPC_DECODER_HIT(lfdux);
case 0b1010000111: PPC_DECODER_HIT(stvlx);
case 0b1010010100: PPC_DECODER_HIT(stdbrx);
case 0b1010010101: PPC_DECODER_HIT(stswx);
case 0b1010010110: PPC_DECODER_HIT(stwbrx);
case 0b1010010111: PPC_DECODER_HIT(stfsx);
case 0b1010100111: PPC_DECODER_HIT(stvrx);
case 0b1010110111: PPC_DECODER_HIT(stfsux);
case 0b1011010101: PPC_DECODER_HIT(stswi);
case 0b1011010111: PPC_DECODER_HIT(stfdx);
case 0b1011110110: PPC_DECODER_HIT(dcba);
case 0b1011110111: PPC_DECODER_HIT(stfdux);
case 0b1100000111: PPC_DECODER_HIT(lvlxl);
case 0b1100010110: PPC_DECODER_HIT(lhbrx);
case 0b1100011000: PPC_DECODER_HIT(srawx);
case 0b1100011010: PPC_DECODER_HIT(sradx);
case 0b1100100111: PPC_DECODER_HIT(lvrxl);
case 0b1100111000: PPC_DECODER_HIT(srawix);
case 0b1101010110: PPC_DECODER_HIT(eieio);
case 0b1110000111: PPC_DECODER_HIT(stvlxl);
case 0b1110010110: PPC_DECODER_HIT(sthbrx);
case 0b1110011010: PPC_DECODER_HIT(extshx);
case 0b1110100111: PPC_DECODER_HIT(stvrxl);
case 0b1110111010: PPC_DECODER_HIT(extsbx);
case 0b1111010110: PPC_DECODER_HIT(icbi);
case 0b1111010111: PPC_DECODER_HIT(stfiwx);
case 0b1111011010: PPC_DECODER_HIT(extswx);
}
switch ((ExtractBits(code, 22, 30) << 0)) {
case 0b000001000: PPC_DECODER_HIT(subfcx);
case 0b000001001: PPC_DECODER_HIT(mulhdux);
case 0b000001010: PPC_DECODER_HIT(addcx);
case 0b000001011: PPC_DECODER_HIT(mulhwux);
case 0b000101000: PPC_DECODER_HIT(subfx);
case 0b001001001: PPC_DECODER_HIT(mulhdx);
case 0b001001011: PPC_DECODER_HIT(mulhwx);
case 0b001101000: PPC_DECODER_HIT(negx);
case 0b010001000: PPC_DECODER_HIT(subfex);
case 0b010001010: PPC_DECODER_HIT(addex);
case 0b011001000: PPC_DECODER_HIT(subfzex);
case 0b011001010: PPC_DECODER_HIT(addzex);
case 0b011101000: PPC_DECODER_HIT(subfmex);
case 0b011101001: PPC_DECODER_HIT(mulldx);
case 0b011101010: PPC_DECODER_HIT(addmex);
case 0b011101011: PPC_DECODER_HIT(mullwx);
case 0b100001010: PPC_DECODER_HIT(addx);
case 0b111001001: PPC_DECODER_HIT(divdux);
case 0b111001011: PPC_DECODER_HIT(divwux);
case 0b111101001: PPC_DECODER_HIT(divdx);
case 0b111101011: PPC_DECODER_HIT(divwx);
}
switch ((ExtractBits(code, 6, 10) << 20)|(ExtractBits(code, 21, 30) << 0)) {
case 0b0000000000000001111110110: PPC_DECODER_HIT(dcbz);
case 0b0000100000000001111110110: PPC_DECODER_HIT(dcbz128);
}
PPC_DECODER_MISS;
case 32: PPC_DECODER_HIT(lwz);
case 33: PPC_DECODER_HIT(lwzu);
case 34: PPC_DECODER_HIT(lbz);
case 35: PPC_DECODER_HIT(lbzu);
case 36: PPC_DECODER_HIT(stw);
case 37: PPC_DECODER_HIT(stwu);
case 38: PPC_DECODER_HIT(stb);
case 39: PPC_DECODER_HIT(stbu);
case 40: PPC_DECODER_HIT(lhz);
case 41: PPC_DECODER_HIT(lhzu);
case 42: PPC_DECODER_HIT(lha);
case 43: PPC_DECODER_HIT(lhau);
case 44: PPC_DECODER_HIT(sth);
case 45: PPC_DECODER_HIT(sthu);
case 46: PPC_DECODER_HIT(lmw);
case 47: PPC_DECODER_HIT(stmw);
case 48: PPC_DECODER_HIT(lfs);
case 49: PPC_DECODER_HIT(lfsu);
case 50: PPC_DECODER_HIT(lfd);
case 51: PPC_DECODER_HIT(lfdu);
case 52: PPC_DECODER_HIT(stfs);
case 53: PPC_DECODER_HIT(stfsu);
case 54: PPC_DECODER_HIT(stfd);
case 55: PPC_DECODER_HIT(stfdu);
case 58:
switch ((ExtractBits(code, 30, 31) << 0)) {
case 0b00: PPC_DECODER_HIT(ld);
case 0b01: PPC_DECODER_HIT(ldu);
case 0b10: PPC_DECODER_HIT(lwa);
}
PPC_DECODER_MISS;
case 59:
switch ((ExtractBits(code, 26, 30) << 0)) {
case 0b10010: PPC_DECODER_HIT(fdivsx);
case 0b10100: PPC_DECODER_HIT(fsubsx);
case 0b10101: PPC_DECODER_HIT(faddsx);
case 0b10110: PPC_DECODER_HIT(fsqrtsx);
case 0b11000: PPC_DECODER_HIT(fresx);
case 0b11001: PPC_DECODER_HIT(fmulsx);
case 0b11100: PPC_DECODER_HIT(fmsubsx);
case 0b11101: PPC_DECODER_HIT(fmaddsx);
case 0b11110: PPC_DECODER_HIT(fnmsubsx);
case 0b11111: PPC_DECODER_HIT(fnmaddsx);
}
PPC_DECODER_MISS;
case 62:
switch ((ExtractBits(code, 30, 31) << 0)) {
case 0b00: PPC_DECODER_HIT(std);
case 0b01: PPC_DECODER_HIT(stdu);
}
PPC_DECODER_MISS;
case 63:
switch ((ExtractBits(code, 21, 30) << 0)) {
case 0b0000000000: PPC_DECODER_HIT(fcmpu);
case 0b0000001100: PPC_DECODER_HIT(frspx);
case 0b0000001110: PPC_DECODER_HIT(fctiwx);
case 0b0000001111: PPC_DECODER_HIT(fctiwzx);
case 0b0000100000: PPC_DECODER_HIT(fcmpo);
case 0b0000100110: PPC_DECODER_HIT(mtfsb1x);
case 0b0000101000: PPC_DECODER_HIT(fnegx);
case 0b0001000000: PPC_DECODER_HIT(mcrfs);
case 0b0001000110: PPC_DECODER_HIT(mtfsb0x);
case 0b0001001000: PPC_DECODER_HIT(fmrx);
case 0b0010000110: PPC_DECODER_HIT(mtfsfix);
case 0b0010001000: PPC_DECODER_HIT(fnabsx);
case 0b0100001000: PPC_DECODER_HIT(fabsx);
case 0b1001000111: PPC_DECODER_HIT(mffsx);
case 0b1011000111: PPC_DECODER_HIT(mtfsfx);
case 0b1100101110: PPC_DECODER_HIT(fctidx);
case 0b1100101111: PPC_DECODER_HIT(fctidzx);
case 0b1101001110: PPC_DECODER_HIT(fcfidx);
}
switch ((ExtractBits(code, 26, 30) << 0)) {
case 0b10010: PPC_DECODER_HIT(fdivx);
case 0b10100: PPC_DECODER_HIT(fsubx);
case 0b10101: PPC_DECODER_HIT(faddx);
case 0b10110: PPC_DECODER_HIT(fsqrtx);
case 0b10111: PPC_DECODER_HIT(fselx);
case 0b11001: PPC_DECODER_HIT(fmulx);
case 0b11010: PPC_DECODER_HIT(frsqrtex);
case 0b11100: PPC_DECODER_HIT(fmsubx);
case 0b11101: PPC_DECODER_HIT(fmaddx);
case 0b11110: PPC_DECODER_HIT(fnmsubx);
case 0b11111: PPC_DECODER_HIT(fnmaddx);
}
PPC_DECODER_MISS;
default: PPC_DECODER_MISS;
}
}
} // namespace ppc
} // namespace cpu
} // namespace xe

View File

@ -0,0 +1,482 @@
// This code was autogenerated by tools/ppc-table-gen.py. Do not modify!
// clang-format off
#include <cstdint>
#include "xenia/cpu/ppc/ppc_opcode.h"
#include "xenia/cpu/ppc/ppc_opcode_info.h"
namespace xe {
namespace cpu {
namespace ppc {
#define INSTRUCTION(opcode, mnem, form, subform, group, desc) \
{opcode, mnem, PPCOpcodeFormat::form, PPCOpcodeGroup::group, desc}
PPCOpcodeInfo ppc_opcode_table[] = {
INSTRUCTION(0x7c000014, "addcx" , kXO , D_A_B_OE_Rc , kInt, "Add Carrying" ),
INSTRUCTION(0x7c000114, "addex" , kXO , D_A_B_OE_Rc , kInt, "Add Extended" ),
INSTRUCTION(0x38000000, "addi" , kD , D_A_SIMM , kInt, "Add Immediate" ),
INSTRUCTION(0x30000000, "addic" , kD , D_A_SIMM , kInt, "Add Immediate Carrying" ),
INSTRUCTION(0x34000000, "addicx" , kD , D_A_SIMM , kInt, "Add Immediate Carrying and Record" ),
INSTRUCTION(0x3c000000, "addis" , kD , D_A_SIMM , kInt, "Add Immediate Shifted" ),
INSTRUCTION(0x7c0001d4, "addmex" , kXO , D_A_0_OE_Rc , kInt, "Add to Minus One Extended" ),
INSTRUCTION(0x7c000214, "addx" , kXO , D_A_B_OE_Rc , kInt, "Add" ),
INSTRUCTION(0x7c000194, "addzex" , kXO , D_A_0_OE_Rc , kInt, "Add to Zero Extended" ),
INSTRUCTION(0x7c000078, "andcx" , kX , S_A_B_Rc , kInt, "AND with Complement" ),
INSTRUCTION(0x74000000, "andisx" , kD , S_A_UIMM , kInt, "AND Immediate Shifted" ),
INSTRUCTION(0x70000000, "andix" , kD , S_A_UIMM , kInt, "AND Immediate" ),
INSTRUCTION(0x7c000038, "andx" , kX , S_A_B_Rc , kInt, "AND" ),
INSTRUCTION(0x4c000420, "bcctrx" , kXL , BO_BI_0_LK , kInt, "Branch Conditional to Count Register" ),
INSTRUCTION(0x4c000020, "bclrx" , kXL , BO_BI_0_LK , kInt, "Branch Conditional to Link Register" ),
INSTRUCTION(0x40000000, "bcx" , kB , BO_BI_BD_AA_LK , kInt, "Branch Conditional" ),
INSTRUCTION(0x48000000, "bx" , kI , LI_AA_LK , kInt, "Branch" ),
INSTRUCTION(0x7c000000, "cmp" , kX , crfD_L_A_B , kInt, "Compare" ),
INSTRUCTION(0x2c000000, "cmpi" , kD , crfD_L_A_SIMM , kInt, "Compare Immediate" ),
INSTRUCTION(0x7c000040, "cmpl" , kX , crfD_L_A_B , kInt, "Compare Logical" ),
INSTRUCTION(0x28000000, "cmpli" , kD , crfD_L_A_UIMM , kInt, "Compare Logical Immediate" ),
INSTRUCTION(0x7c000074, "cntlzdx" , kX , S_A_0_Rc , kInt, "Count Leading Zeros Doubleword" ),
INSTRUCTION(0x7c000034, "cntlzwx" , kX , S_A_0_Rc , kInt, "Count Leading Zeros Word" ),
INSTRUCTION(0x4c000202, "crand" , kXL , crbD_crbA_crbB , kInt, "Condition Register AND" ),
INSTRUCTION(0x4c000102, "crandc" , kXL , crbD_crbA_crbB , kInt, "Condition Register AND with Complement" ),
INSTRUCTION(0x4c000242, "creqv" , kXL , crbD_crbA_crbB , kInt, "Condition Register Equivalent" ),
INSTRUCTION(0x4c0001c2, "crnand" , kXL , crbD_crbA_crbB , kInt, "Condition Register NAND" ),
INSTRUCTION(0x4c000042, "crnor" , kXL , crbD_crbA_crbB , kInt, "Condition Register NOR" ),
INSTRUCTION(0x4c000382, "cror" , kXL , crbD_crbA_crbB , kInt, "Condition Register OR" ),
INSTRUCTION(0x4c000342, "crorc" , kXL , crbD_crbA_crbB , kInt, "Condition Register OR with Complement" ),
INSTRUCTION(0x4c000182, "crxor" , kXL , crbD_crbA_crbB , kInt, "Condition Register XOR" ),
INSTRUCTION(0x7c0005ec, "dcba" , kX , _0_A_B , kInt, "Data Cache Block Allocate" ),
INSTRUCTION(0x7c0000ac, "dcbf" , kX , _0_A_B , kInt, "Data Cache Block Flush" ),
INSTRUCTION(0x7c0003ac, "dcbi" , kX , _0_A_B , kInt, "Data Cache Block Invalidate" ),
INSTRUCTION(0x7c00006c, "dcbst" , kX , _0_A_B , kInt, "Data Cache Block Store" ),
INSTRUCTION(0x7c00022c, "dcbt" , kX , _0_A_B , kInt, "Data Cache Block Touch" ),
INSTRUCTION(0x7c0001ec, "dcbtst" , kX , _0_A_B , kInt, "Data Cache Block Touch for Store" ),
INSTRUCTION(0x7c0007ec, "dcbz" , kDCBZ , _0_A_B , kInt, "Data Cache Block Clear to Zero" ),
INSTRUCTION(0x7c2007ec, "dcbz128" , kDCBZ , _0_A_B , kInt, "Data Cache Block Clear to Zero 128" ),
INSTRUCTION(0x7c000392, "divdux" , kXO , D_A_B_OE_Rc , kInt, "Divide Doubleword Unsigned" ),
INSTRUCTION(0x7c0003d2, "divdx" , kXO , D_A_B_OE_Rc , kInt, "Divide Doubleword" ),
INSTRUCTION(0x7c000396, "divwux" , kXO , D_A_B_OE_Rc , kInt, "Divide Word Unsigned" ),
INSTRUCTION(0x7c0003d6, "divwx" , kXO , D_A_B_OE_Rc , kInt, "Divide Word" ),
INSTRUCTION(0x7c00026c, "eciwx" , kX , D_A_B , kInt, "External Control In Word Indexed" ),
INSTRUCTION(0x7c00036c, "ecowx" , kX , S_A_B , kInt, "External Control Out Word Indexed" ),
INSTRUCTION(0x7c0006ac, "eieio" , kX , _0_0_0 , kInt, "Enforce In-Order Execution of I/O" ),
INSTRUCTION(0x7c000238, "eqvx" , kX , S_A_B_Rc , kInt, "Equivalent" ),
INSTRUCTION(0x7c000774, "extsbx" , kX , S_A_0_Rc , kInt, "Extend Sign Byte" ),
INSTRUCTION(0x7c000734, "extshx" , kX , S_A_0_Rc , kInt, "Extend Sign Half Word" ),
INSTRUCTION(0x7c0007b4, "extswx" , kX , S_A_0_Rc , kInt, "Extend Sign Word" ),
INSTRUCTION(0xfc000210, "fabsx" , kX , D_0_B_Rc , kFp , "Floating Absolute Value" ),
INSTRUCTION(0xec00002a, "faddsx" , kA , D_A_B_0_Rc , kFp , "Floating Add Single" ),
INSTRUCTION(0xfc00002a, "faddx" , kA , D_A_B_0_Rc , kFp , "Floating Add" ),
INSTRUCTION(0xfc00069c, "fcfidx" , kX , D_A_B_Rc , kFp , "Floating Convert From Integer Doubleword" ),
INSTRUCTION(0xfc000040, "fcmpo" , kX , crfD_A_B , kFp , "Floating Compare Ordered" ),
INSTRUCTION(0xfc000000, "fcmpu" , kX , crfD_A_B , kFp , "Floating Compare Unordered" ),
INSTRUCTION(0xfc00065c, "fctidx" , kX , D_0_B_Rc , kFp , "Floating Convert to Integer Doubleword" ),
INSTRUCTION(0xfc00065e, "fctidzx" , kX , D_0_B_Rc , kFp , "Floating Convert to Integer Doubleword with Round Toward Zero" ),
INSTRUCTION(0xfc00001c, "fctiwx" , kX , D_0_B_Rc , kFp , "Floating Convert to Integer Word" ),
INSTRUCTION(0xfc00001e, "fctiwzx" , kX , D_0_B_Rc , kFp , "Floating Convert to Integer Word with Round Toward Zero" ),
INSTRUCTION(0xec000024, "fdivsx" , kA , D_A_B_0_Rc , kFp , "Floating Divide Single" ),
INSTRUCTION(0xfc000024, "fdivx" , kA , D_A_B_0_Rc , kFp , "Floating Divide" ),
INSTRUCTION(0xec00003a, "fmaddsx" , kA , D_A_B_C_Rc , kFp , "Floating Multiply-Add Single" ),
INSTRUCTION(0xfc00003a, "fmaddx" , kA , D_A_B_C_Rc , kFp , "Floating Multiply-Add" ),
INSTRUCTION(0xfc000090, "fmrx" , kX , D_0_B_Rc , kFp , "Floating Move Register" ),
INSTRUCTION(0xec000038, "fmsubsx" , kA , D_A_B_C_Rc , kFp , "Floating Multiply-Subtract Single" ),
INSTRUCTION(0xfc000038, "fmsubx" , kA , D_A_B_C_Rc , kFp , "Floating Multiply-Subtract" ),
INSTRUCTION(0xec000032, "fmulsx" , kA , D_A_0_C_Rc , kFp , "Floating Multiply Single" ),
INSTRUCTION(0xfc000032, "fmulx" , kA , D_A_0_C_Rc , kFp , "Floating Multiply" ),
INSTRUCTION(0xfc000110, "fnabsx" , kX , D_0_B_Rc , kFp , "Floating Negative Absolute Value" ),
INSTRUCTION(0xfc000050, "fnegx" , kX , D_0_B_Rc , kFp , "Floating Negate" ),
INSTRUCTION(0xec00003e, "fnmaddsx" , kA , D_A_B_C_Rc , kFp , "Floating Negative Multiply-Add Single" ),
INSTRUCTION(0xfc00003e, "fnmaddx" , kA , D_A_B_C_Rc , kFp , "Floating Negative Multiply-Add" ),
INSTRUCTION(0xec00003c, "fnmsubsx" , kA , D_A_B_C_Rc , kFp , "Floating Negative Multiply-Subtract Single" ),
INSTRUCTION(0xfc00003c, "fnmsubx" , kA , D_A_B_C_Rc , kFp , "Floating Negative Multiply-Subtract" ),
INSTRUCTION(0xec000030, "fresx" , kA , D_0_B_0_Rc , kFp , "Floating Reciprocal Estimate Single" ),
INSTRUCTION(0xfc000018, "frspx" , kX , D_0_B_Rc , kFp , "Floating Round to Single" ),
INSTRUCTION(0xfc000034, "frsqrtex" , kA , D_0_B_0_Rc , kFp , "Floating Reciprocal Square Root Estimate" ),
INSTRUCTION(0xfc00002e, "fselx" , kA , D_A_B_C_Rc , kFp , "Floating Select" ),
INSTRUCTION(0xec00002c, "fsqrtsx" , kA , D_0_B_0_Rc , kFp , "Floating Square Root Single" ),
INSTRUCTION(0xfc00002c, "fsqrtx" , kA , D_0_B_0_Rc , kFp , "Floating Square Root" ),
INSTRUCTION(0xec000028, "fsubsx" , kA , D_A_B_0_Rc , kFp , "Floating Subtract Single" ),
INSTRUCTION(0xfc000028, "fsubx" , kA , D_A_B_0_Rc , kFp , "Floating Subtract" ),
INSTRUCTION(0x7c0007ac, "icbi" , kX , _0_A_B , kInt, "Instruction Cache Block Invalidate" ),
INSTRUCTION(0x4c00012c, "isync" , kXL , _0_0_0 , kInt, "Instruction Synchronize" ),
INSTRUCTION(0x88000000, "lbz" , kD , D_A_d , kInt, "Load Byte and Zero" ),
INSTRUCTION(0x8c000000, "lbzu" , kD , D_A_d , kInt, "Load Byte and Zero with Update" ),
INSTRUCTION(0x7c0000ee, "lbzux" , kX , D_A_B , kInt, "Load Byte and Zero with Update Indexed" ),
INSTRUCTION(0x7c0000ae, "lbzx" , kX , D_A_B , kInt, "Load Byte and Zero Indexed" ),
INSTRUCTION(0xe8000000, "ld" , kDS , D_A_d , kInt, "Load Doubleword" ),
INSTRUCTION(0x7c0000a8, "ldarx" , kX , D_A_B , kInt, "Load Doubleword and Reserve Indexed" ),
INSTRUCTION(0x7c000428, "ldbrx" , kX , D_A_B , kInt, "Load Doubleword Byte-Reverse Indexed" ),
INSTRUCTION(0xe8000001, "ldu" , kDS , D_A_d , kInt, "Load Doubleword with Update" ),
INSTRUCTION(0x7c00006a, "ldux" , kX , D_A_B , kInt, "Load Doubleword with Update Indexed" ),
INSTRUCTION(0x7c00002a, "ldx" , kX , D_A_B , kInt, "Load Doubleword Indexed" ),
INSTRUCTION(0xc8000000, "lfd" , kD , D_A_d , kFp , "Load Floating-Point Double" ),
INSTRUCTION(0xcc000000, "lfdu" , kD , D_A_d , kFp , "Load Floating-Point Double with Update" ),
INSTRUCTION(0x7c0004ee, "lfdux" , kX , D_A_B , kFp , "Load Floating-Point Double with Update Indexed" ),
INSTRUCTION(0x7c0004ae, "lfdx" , kX , D_A_B , kFp , "Load Floating-Point Double Indexed" ),
INSTRUCTION(0xc0000000, "lfs" , kD , D_A_d , kFp , "Load Floating-Point Single" ),
INSTRUCTION(0xc4000000, "lfsu" , kD , D_A_d , kFp , "Load Floating-Point Single with Update" ),
INSTRUCTION(0x7c00046e, "lfsux" , kX , D_A_B , kFp , "Load Floating-Point Single with Update Indexed" ),
INSTRUCTION(0x7c00042e, "lfsx" , kX , D_A_B , kFp , "Load Floating-Point Single Indexed" ),
INSTRUCTION(0xa8000000, "lha" , kD , D_A_d , kInt, "Load Half Word Algebraic" ),
INSTRUCTION(0xac000000, "lhau" , kD , D_A_d , kInt, "Load Half Word Algebraic with Update" ),
INSTRUCTION(0x7c0002ee, "lhaux" , kX , D_A_B , kInt, "Load Half Word Algebraic with Update Indexed" ),
INSTRUCTION(0x7c0002ae, "lhax" , kX , D_A_B , kInt, "Load Half Word Algebraic Indexed" ),
INSTRUCTION(0x7c00062c, "lhbrx" , kX , D_A_B , kInt, "Load Half Word Byte-Reverse Indexed" ),
INSTRUCTION(0xa0000000, "lhz" , kD , D_A_d , kInt, "Load Half Word and Zero" ),
INSTRUCTION(0xa4000000, "lhzu" , kD , D_A_d , kInt, "Load Half Word and Zero with Update" ),
INSTRUCTION(0x7c00026e, "lhzux" , kX , D_A_B , kInt, "Load Half Word and Zero with Update Indexed" ),
INSTRUCTION(0x7c00022e, "lhzx" , kX , D_A_B , kInt, "Load Half Word and Zero Indexed" ),
INSTRUCTION(0xb8000000, "lmw" , kD , D_A_d , kInt, "Load Multiple Word" ),
INSTRUCTION(0x7c0004aa, "lswi" , kX , D_A_NB , kInt, "Load String Word Immediate" ),
INSTRUCTION(0x7c00042a, "lswx" , kX , D_A_B , kInt, "Load String Word Indexed" ),
INSTRUCTION(0x7c00000e, "lvebx" , kX , D_A_B , kVmx, "Load Vector Element Byte Indexed" ),
INSTRUCTION(0x7c00004e, "lvehx" , kX , D_A_B , kVmx, "Load Vector Element Half Word Indexed" ),
INSTRUCTION(0x7c00008e, "lvewx" , kX , D_A_B , kVmx, "Load Vector Element Word Indexed" ),
INSTRUCTION(0x10000083, "lvewx128" , kVX128_1, D_A_B , kVmx, "Load Vector Element Word Indexed 128" ),
INSTRUCTION(0x7c00040e, "lvlx" , kX , D_A_B , kVmx, "Load Vector Left Indexed" ),
INSTRUCTION(0x10000403, "lvlx128" , kVX128_1, D_A_B , kVmx, "Load Vector Left Indexed 128" ),
INSTRUCTION(0x7c00060e, "lvlxl" , kX , D_A_B , kVmx, "Load Vector Left Indexed LRU" ),
INSTRUCTION(0x10000603, "lvlxl128" , kVX128_1, D_A_B , kVmx, "Load Vector Left Indexed LRU 128" ),
INSTRUCTION(0x7c00044e, "lvrx" , kX , D_A_B , kVmx, "Load Vector Right Indexed" ),
INSTRUCTION(0x10000443, "lvrx128" , kVX128_1, D_A_B , kVmx, "Load Vector Right Indexed 128" ),
INSTRUCTION(0x7c00064e, "lvrxl" , kX , D_A_B , kVmx, "Load Vector Right Indexed LRU" ),
INSTRUCTION(0x10000643, "lvrxl128" , kVX128_1, D_A_B , kVmx, "Load Vector Right Indexed LRU 128" ),
INSTRUCTION(0x7c00000c, "lvsl" , kX , D_A_B , kVmx, "Load Vector for Shift Left Indexed" ),
INSTRUCTION(0x10000003, "lvsl128" , kVX128_1, D_A_B , kVmx, "Load Vector for Shift Left Indexed 128" ),
INSTRUCTION(0x7c00004c, "lvsr" , kX , D_A_B , kVmx, "Load Vector for Shift Right Indexed" ),
INSTRUCTION(0x10000043, "lvsr128" , kVX128_1, D_A_B , kVmx, "Load Vector for Shift Right Indexed 128" ),
INSTRUCTION(0x7c0000ce, "lvx" , kX , D_A_B , kVmx, "Load Vector Indexed" ),
INSTRUCTION(0x100000c3, "lvx128" , kVX128_1, D_A_B , kVmx, "Load Vector Indexed 128" ),
INSTRUCTION(0x7c0002ce, "lvxl" , kX , D_A_B , kVmx, "Load Vector Indexed LRU" ),
INSTRUCTION(0x100002c3, "lvxl128" , kVX128_1, D_A_B , kVmx, "Load Vector Indexed LRU 128" ),
INSTRUCTION(0xe8000002, "lwa" , kDS , D_A_d , kInt, "Load Word Algebraic" ),
INSTRUCTION(0x7c000028, "lwarx" , kX , D_A_B , kInt, "Load Word and Reserve Indexed" ),
INSTRUCTION(0x7c0002ea, "lwaux" , kX , D_A_B , kInt, "Load Word Algebraic with Update Indexed" ),
INSTRUCTION(0x7c0002aa, "lwax" , kX , D_A_B , kInt, "Load Word Algebraic Indexed" ),
INSTRUCTION(0x7c00042c, "lwbrx" , kX , D_A_B , kInt, "Load Word Byte-Reverse Indexed" ),
INSTRUCTION(0x80000000, "lwz" , kD , D_A_d , kInt, "Load Word and Zero" ),
INSTRUCTION(0x84000000, "lwzu" , kD , D_A_d , kInt, "Load Word and Zero with Update" ),
INSTRUCTION(0x7c00006e, "lwzux" , kX , D_A_B , kInt, "Load Word and Zero with Update Indexed" ),
INSTRUCTION(0x7c00002e, "lwzx" , kX , D_A_B , kInt, "Load Word and Zero Indexed" ),
INSTRUCTION(0x4c000000, "mcrf" , kXL , crfD_crfS_0 , kInt, "Move Condition Register Field" ),
INSTRUCTION(0xfc000080, "mcrfs" , kX , crfD_crfS_0 , kFp , "Move to Condition Register from FPSCR" ),
INSTRUCTION(0x7c000400, "mcrxr" , kX , crfD_0_0 , kInt, "Move to Condition Register from XER" ),
INSTRUCTION(0x7c000026, "mfcr" , kX , D_0_0 , kInt, "Move from Condition Register" ),
INSTRUCTION(0xfc00048e, "mffsx" , kX , D_0_0_Rc , kFp , "Move from FPSCR" ),
INSTRUCTION(0x7c0000a6, "mfmsr" , kX , D_0_0 , kInt, "Move from Machine State Register" ),
INSTRUCTION(0x7c0002a6, "mfspr" , kXFX , D_spr , kInt, "Move from Special-Purpose Register" ),
INSTRUCTION(0x7c0002e6, "mftb" , kXFX , D_tbr , kInt, "Move from Time Base" ),
INSTRUCTION(0x10000604, "mfvscr" , kVX , D_0_0 , kInt, "Move from VSCR" ),
INSTRUCTION(0x7c000120, "mtcrf" , kXFX , S_CRM , kInt, "Move to Condition Register Fields" ),
INSTRUCTION(0xfc00008c, "mtfsb0x" , kX , crbD_0_0_Rc , kFp , "Move to FPSCR Bit 0" ),
INSTRUCTION(0xfc00004c, "mtfsb1x" , kX , crbD_0_0_Rc , kFp , "Move to FPSCR Bit 1" ),
INSTRUCTION(0xfc00010c, "mtfsfix" , kX , crfD_0_IMM_Rc , kFp , "Move to FPSCR Field Immediate" ),
INSTRUCTION(0xfc00058e, "mtfsfx" , kXFL , FM_B_Rc , kFp , "Move to FPSCR Fields" ),
INSTRUCTION(0x7c000124, "mtmsr" , kX , S_0_0 , kInt, "Move to Machine State Register" ),
INSTRUCTION(0x7c000164, "mtmsrd" , kX , S_0_0 , kInt, "Move to Machine State Register Doubleword" ),
INSTRUCTION(0x7c0003a6, "mtspr" , kXFX , S_spr , kInt, "Move to Special-Purpose Register" ),
INSTRUCTION(0x10000644, "mtvscr" , kVX , S_0_0 , kInt, "Move to VSCR" ),
INSTRUCTION(0x7c000012, "mulhdux" , kXO , D_A_B_Rc , kInt, "Multiply High Doubleword Unsigned" ),
INSTRUCTION(0x7c000092, "mulhdx" , kXO , D_A_B_Rc , kInt, "Multiply High Doubleword" ),
INSTRUCTION(0x7c000016, "mulhwux" , kXO , D_A_B_Rc , kInt, "Multiply High Word Unsigned" ),
INSTRUCTION(0x7c000096, "mulhwx" , kXO , D_A_B_Rc , kInt, "Multiply High Word" ),
INSTRUCTION(0x7c0001d2, "mulldx" , kXO , D_A_B_OE_Rc , kInt, "Multiply Low Doubleword" ),
INSTRUCTION(0x1c000000, "mulli" , kD , D_A_SIMM , kInt, "Multiply Low Immediate" ),
INSTRUCTION(0x7c0001d6, "mullwx" , kXO , D_A_B_OE_Rc , kInt, "Multiply Low Word" ),
INSTRUCTION(0x7c0003b8, "nandx" , kX , S_A_B_Rc , kInt, "NAND" ),
INSTRUCTION(0x7c0000d0, "negx" , kXO , D_A_0_OE_Rc , kInt, "Negate" ),
INSTRUCTION(0x7c0000f8, "norx" , kX , S_A_B_Rc , kInt, "NOR" ),
INSTRUCTION(0x7c000338, "orcx" , kX , S_A_B_Rc , kInt, "OR with Complement" ),
INSTRUCTION(0x60000000, "ori" , kD , S_A_UIMM , kInt, "OR Immediate" ),
INSTRUCTION(0x64000000, "oris" , kD , S_A_UIMM , kInt, "OR Immediate Shifted" ),
INSTRUCTION(0x7c000378, "orx" , kX , S_A_B_Rc , kInt, "OR" ),
INSTRUCTION(0x78000010, "rldclx" , kMDS , S_A_B_MB_ME_Rc , kInt, "Rotate Left Doubleword then Clear Left" ),
INSTRUCTION(0x78000012, "rldcrx" , kMDS , S_A_B_MB_ME_Rc , kInt, "Rotate Left Doubleword then Clear Right" ),
INSTRUCTION(0x78000000, "rldiclx" , kMDSH , S_A_SH_MB_ME_Rc, kInt, "Rotate Left Doubleword Immediate then Clear Left" ),
INSTRUCTION(0x78000004, "rldicrx" , kMDSH , S_A_SH_MB_ME_Rc, kInt, "Rotate Left Doubleword Immediate then Clear Right" ),
INSTRUCTION(0x78000008, "rldicx" , kMDSH , S_A_SH_MB_ME_Rc, kInt, "Rotate Left Doubleword Immediate then Clear" ),
INSTRUCTION(0x7800000c, "rldimix" , kMDSH , S_A_SH_MB_ME_Rc, kInt, "Rotate Left Doubleword Immediate then Mask Insert" ),
INSTRUCTION(0x50000000, "rlwimix" , kM , S_A_SH_MB_ME_Rc, kInt, "Rotate Left Word Immediate then Mask Insert" ),
INSTRUCTION(0x54000000, "rlwinmx" , kM , S_A_SH_MB_ME_Rc, kInt, "Rotate Left Word Immediate then AND with Mask" ),
INSTRUCTION(0x5c000000, "rlwnmx" , kM , S_A_SH_MB_ME_Rc, kInt, "Rotate Left Word then AND with Mask" ),
INSTRUCTION(0x44000002, "sc" , kSC , sc , kInt, "System Call" ),
INSTRUCTION(0x7c000036, "sldx" , kX , S_A_B_Rc , kInt, "Shift Left Doubleword" ),
INSTRUCTION(0x7c000030, "slwx" , kX , S_A_B_Rc , kInt, "Shift Left Word" ),
INSTRUCTION(0x7c000674, "sradix" , kXS , S_A_SH_Rc , kInt, "Shift Right Algebraic Doubleword Immediate" ),
INSTRUCTION(0x7c000634, "sradx" , kX , S_A_B_Rc , kInt, "Shift Right Algebraic Doubleword" ),
INSTRUCTION(0x7c000670, "srawix" , kX , S_A_SH_Rc , kInt, "Shift Right Algebraic Word Immediate" ),
INSTRUCTION(0x7c000630, "srawx" , kX , S_A_B_Rc , kInt, "Shift Right Algebraic Word" ),
INSTRUCTION(0x7c000436, "srdx" , kX , S_A_B_Rc , kInt, "Shift Right Doubleword" ),
INSTRUCTION(0x7c000430, "srwx" , kX , S_A_B_Rc , kInt, "Shift Right Word" ),
INSTRUCTION(0x98000000, "stb" , kD , S_A_d , kInt, "Store Byte" ),
INSTRUCTION(0x9c000000, "stbu" , kD , S_A_d , kInt, "Store Byte with Update" ),
INSTRUCTION(0x7c0001ee, "stbux" , kX , S_A_B , kInt, "Store Byte with Update Indexed" ),
INSTRUCTION(0x7c0001ae, "stbx" , kX , S_A_B , kInt, "Store Byte Indexed" ),
INSTRUCTION(0xf8000000, "std" , kDS , S_A_d , kInt, "Store Doubleword" ),
INSTRUCTION(0x7c000528, "stdbrx" , kX , S_A_B , kInt, "Store Doubleword Byte-Reverse Indexed" ),
INSTRUCTION(0x7c0001ad, "stdcx" , kX , S_A_B_1 , kInt, "Store Doubleword Conditional Indexed" ),
INSTRUCTION(0xf8000001, "stdu" , kDS , S_A_d , kInt, "Store Doubleword with Update" ),
INSTRUCTION(0x7c00016a, "stdux" , kX , S_A_B , kInt, "Store Doubleword with Update Indexed" ),
INSTRUCTION(0x7c00012a, "stdx" , kX , S_A_B , kInt, "Store Doubleword Indexed" ),
INSTRUCTION(0xd8000000, "stfd" , kD , S_A_d , kFp , "Store Floating-Point Double" ),
INSTRUCTION(0xdc000000, "stfdu" , kD , S_A_d , kFp , "Store Floating-Point Double with Update" ),
INSTRUCTION(0x7c0005ee, "stfdux" , kX , S_A_B , kFp , "Store Floating-Point Double with Update Indexed" ),
INSTRUCTION(0x7c0005ae, "stfdx" , kX , S_A_B , kFp , "Store Floating-Point Double Indexed" ),
INSTRUCTION(0x7c0007ae, "stfiwx" , kX , S_A_B , kFp , "Store Floating-Point as Integer Word Indexed" ),
INSTRUCTION(0xd0000000, "stfs" , kD , S_A_d , kFp , "Store Floating-Point Single" ),
INSTRUCTION(0xd4000000, "stfsu" , kD , S_A_d , kFp , "Store Floating-Point Single with Update" ),
INSTRUCTION(0x7c00056e, "stfsux" , kX , S_A_B , kFp , "Store Floating-Point Single with Update Indexed" ),
INSTRUCTION(0x7c00052e, "stfsx" , kX , S_A_B , kFp , "Store Floating-Point Single Indexed" ),
INSTRUCTION(0xb0000000, "sth" , kD , S_A_d , kInt, "Store Half Word" ),
INSTRUCTION(0x7c00072c, "sthbrx" , kX , S_A_B , kInt, "Store Half Word Byte-Reverse Indexed" ),
INSTRUCTION(0xb4000000, "sthu" , kD , S_A_d , kInt, "Store Half Word with Update" ),
INSTRUCTION(0x7c00036e, "sthux" , kX , S_A_B , kInt, "Store Half Word with Update Indexed" ),
INSTRUCTION(0x7c00032e, "sthx" , kX , S_A_B , kInt, "Store Half Word Indexed" ),
INSTRUCTION(0xbc000000, "stmw" , kD , S_A_d , kInt, "Store Multiple Word" ),
INSTRUCTION(0x7c0005aa, "stswi" , kX , S_A_NB , kInt, "Store String Word Immediate" ),
INSTRUCTION(0x7c00052a, "stswx" , kX , S_A_B , kInt, "Store String Word Indexed" ),
INSTRUCTION(0x7c00010e, "stvebx" , kX , S_A_B , kVmx, "Store Vector Element Byte Indexed" ),
INSTRUCTION(0x7c00014e, "stvehx" , kX , S_A_B , kVmx, "Store Vector Element Half Word Indexed" ),
INSTRUCTION(0x7c00018e, "stvewx" , kX , S_A_B , kVmx, "Store Vector Element Word Indexed" ),
INSTRUCTION(0x10000183, "stvewx128" , kVX128_1, S_A_B , kVmx, "Store Vector Element Word Indexed 128" ),
INSTRUCTION(0x7c00050e, "stvlx" , kX , S_A_B , kVmx, "Store Vector Left Indexed" ),
INSTRUCTION(0x10000503, "stvlx128" , kVX128_1, S_A_B , kVmx, "Store Vector Left Indexed 128" ),
INSTRUCTION(0x7c00070e, "stvlxl" , kX , S_A_B , kVmx, "Store Vector Left Indexed LRU" ),
INSTRUCTION(0x10000703, "stvlxl128" , kVX128_1, S_A_B , kVmx, "Store Vector Left Indexed LRU 128" ),
INSTRUCTION(0x7c00054e, "stvrx" , kX , S_A_B , kVmx, "Store Vector Right Indexed" ),
INSTRUCTION(0x10000543, "stvrx128" , kVX128_1, S_A_B , kVmx, "Store Vector Right Indexed 128" ),
INSTRUCTION(0x7c00074e, "stvrxl" , kX , S_A_B , kVmx, "Store Vector Right Indexed LRU" ),
INSTRUCTION(0x10000743, "stvrxl128" , kVX128_1, S_A_B , kVmx, "Store Vector Right Indexed LRU 128" ),
INSTRUCTION(0x7c0001ce, "stvx" , kX , S_A_B , kVmx, "Store Vector Indexed" ),
INSTRUCTION(0x100001c3, "stvx128" , kVX128_1, S_A_B , kVmx, "Store Vector Indexed 128" ),
INSTRUCTION(0x7c0003ce, "stvxl" , kX , S_A_B , kVmx, "Store Vector Indexed LRU" ),
INSTRUCTION(0x100003c3, "stvxl128" , kVX128_1, S_A_B , kVmx, "Store Vector Indexed LRU 128" ),
INSTRUCTION(0x90000000, "stw" , kD , S_A_d , kInt, "Store Word" ),
INSTRUCTION(0x7c00052c, "stwbrx" , kX , S_A_B , kInt, "Store Word Byte-Reverse Indexed" ),
INSTRUCTION(0x7c00012d, "stwcx" , kX , S_A_B_1 , kInt, "Store Word Conditional Indexed" ),
INSTRUCTION(0x94000000, "stwu" , kD , S_A_d , kInt, "Store Word with Update" ),
INSTRUCTION(0x7c00016e, "stwux" , kX , S_A_B , kInt, "Store Word with Update Indexed" ),
INSTRUCTION(0x7c00012e, "stwx" , kX , S_A_B , kInt, "Store Word Indexed" ),
INSTRUCTION(0x7c000010, "subfcx" , kXO , D_A_B_OE_Rc , kInt, "Subtract From Carrying" ),
INSTRUCTION(0x7c000110, "subfex" , kXO , D_A_B_OE_Rc , kInt, "Subtract From Extended" ),
INSTRUCTION(0x20000000, "subficx" , kD , D_A_SIMM , kInt, "Subtract From Immediate Carrying" ),
INSTRUCTION(0x7c0001d0, "subfmex" , kXO , D_A_0_OE_Rc , kInt, "Subtract From Minus One Extended" ),
INSTRUCTION(0x7c000050, "subfx" , kXO , D_A_B_OE_Rc , kInt, "Subtract From" ),
INSTRUCTION(0x7c000190, "subfzex" , kXO , D_A_0_OE_Rc , kInt, "Subtract From Zero Extended" ),
INSTRUCTION(0x7c0004ac, "sync" , kX , _0_0_0 , kInt, "Synchronize" ),
INSTRUCTION(0x7c000088, "td" , kX , TO_A_B , kInt, "Trap Doubleword" ),
INSTRUCTION(0x08000000, "tdi" , kD , TO_A_SIMM , kInt, "Trap Doubleword Immediate" ),
INSTRUCTION(0x7c000008, "tw" , kX , TO_A_B , kInt, "Trap Word" ),
INSTRUCTION(0x0c000000, "twi" , kD , TO_A_SIMM , kInt, "Trap Word Immediate" ),
INSTRUCTION(0x10000180, "vaddcuw" , kVX , D_A_B , kVmx, "Vector Add Carryout Unsigned Word" ),
INSTRUCTION(0x1000000a, "vaddfp" , kVX , D_A_B , kVmx, "Vector Add Floating Point" ),
INSTRUCTION(0x14000010, "vaddfp128" , kVX128 , D_A_B , kVmx, "Vector128 Add Floating Point" ),
INSTRUCTION(0x10000300, "vaddsbs" , kVX , D_A_B , kVmx, "Vector Add Signed Byte Saturate" ),
INSTRUCTION(0x10000340, "vaddshs" , kVX , D_A_B , kVmx, "Vector Add Signed Half Word Saturate" ),
INSTRUCTION(0x10000380, "vaddsws" , kVX , D_A_B , kVmx, "Vector Add Signed Word Saturate" ),
INSTRUCTION(0x10000000, "vaddubm" , kVX , D_A_B , kVmx, "Vector Add Unsigned Byte Modulo" ),
INSTRUCTION(0x10000200, "vaddubs" , kVX , D_A_B , kVmx, "Vector Add Unsigned Byte Saturate" ),
INSTRUCTION(0x10000040, "vadduhm" , kVX , D_A_B , kVmx, "Vector Add Unsigned Half Word Modulo" ),
INSTRUCTION(0x10000240, "vadduhs" , kVX , D_A_B , kVmx, "Vector Add Unsigned Half Word Saturate" ),
INSTRUCTION(0x10000080, "vadduwm" , kVX , D_A_B , kVmx, "Vector Add Unsigned Word Modulo" ),
INSTRUCTION(0x10000280, "vadduws" , kVX , D_A_B , kVmx, "Vector Add Unsigned Word Saturate" ),
INSTRUCTION(0x10000404, "vand" , kVX , D_A_B , kVmx, "Vector Logical AND" ),
INSTRUCTION(0x14000210, "vand128" , kVX128 , D_A_B , kVmx, "Vector128 Logical AND" ),
INSTRUCTION(0x10000444, "vandc" , kVX , D_A_B , kVmx, "Vector Logical AND with Complement" ),
INSTRUCTION(0x14000250, "vandc128" , kVX128 , D_A_B , kVmx, "Vector128 Logical AND with Complement" ),
INSTRUCTION(0x10000502, "vavgsb" , kVX , D_A_B , kVmx, "Vector Average Signed Byte" ),
INSTRUCTION(0x10000542, "vavgsh" , kVX , D_A_B , kVmx, "Vector Average Signed Half Word" ),
INSTRUCTION(0x10000582, "vavgsw" , kVX , D_A_B , kVmx, "Vector Average Signed Word" ),
INSTRUCTION(0x10000402, "vavgub" , kVX , D_A_B , kVmx, "Vector Average Unsigned Byte" ),
INSTRUCTION(0x10000442, "vavguh" , kVX , D_A_B , kVmx, "Vector Average Unsigned Half Word" ),
INSTRUCTION(0x10000482, "vavguw" , kVX , D_A_B , kVmx, "Vector Average Unsigned Word" ),
INSTRUCTION(0x18000230, "vcfpsxws128" , kVX128_3, D_B_SIMM , kVmx, "Vector128 Convert From Floating-Point to Signed Fixed-Point Word Saturate" ),
INSTRUCTION(0x18000270, "vcfpuxws128" , kVX128_3, D_B_UIMM , kVmx, "Vector128 Convert From Floating-Point to Unsigned Fixed-Point Word Saturate"),
INSTRUCTION(0x1000034a, "vcfsx" , kVX , D_A_B , kVmx, "Vector Convert from Signed Fixed-Point Word" ),
INSTRUCTION(0x1000030a, "vcfux" , kVX , D_A_B , kVmx, "Vector Convert from Unsigned Fixed-Point Word" ),
INSTRUCTION(0x100003c6, "vcmpbfp" , kVC , D_A_B , kVmx, "Vector Compare Bounds Floating Point" ),
INSTRUCTION(0x18000180, "vcmpbfp128" , kVX128_R, D_A_B , kVmx, "Vector128 Compare Bounds Floating Point" ),
INSTRUCTION(0x100000c6, "vcmpeqfp" , kVC , D_A_B , kVmx, "Vector Compare Equal-to Floating Point" ),
INSTRUCTION(0x18000000, "vcmpeqfp128" , kVX128_R, D_A_B , kVmx, "Vector128 Compare Equal-to Floating Point" ),
INSTRUCTION(0x10000006, "vcmpequb" , kVC , D_A_B , kVmx, "Vector Compare Equal-to Unsigned Byte" ),
INSTRUCTION(0x10000046, "vcmpequh" , kVC , D_A_B , kVmx, "Vector Compare Equal-to Unsigned Half Word" ),
INSTRUCTION(0x10000086, "vcmpequw" , kVC , D_A_B , kVmx, "Vector Compare Equal-to Unsigned Word" ),
INSTRUCTION(0x18000200, "vcmpequw128" , kVX128_R, D_A_B , kVmx, "Vector128 Compare Equal-to Unsigned Word" ),
INSTRUCTION(0x100001c6, "vcmpgefp" , kVC , D_A_B , kVmx, "Vector Compare Greater-Than-or-Equal-to Floating Point" ),
INSTRUCTION(0x18000080, "vcmpgefp128" , kVX128_R, D_A_B , kVmx, "Vector128 Compare Greater-Than-or-Equal-to Floating Point" ),
INSTRUCTION(0x100002c6, "vcmpgtfp" , kVC , D_A_B , kVmx, "Vector Compare Greater-Than Floating Point" ),
INSTRUCTION(0x18000100, "vcmpgtfp128" , kVX128_R, D_A_B , kVmx, "Vector128 Compare Greater-Than Floating-Point" ),
INSTRUCTION(0x10000306, "vcmpgtsb" , kVC , D_A_B , kVmx, "Vector Compare Greater-Than Signed Byte" ),
INSTRUCTION(0x10000346, "vcmpgtsh" , kVC , D_A_B , kVmx, "Vector Compare Greater-Than Signed Half Word" ),
INSTRUCTION(0x10000386, "vcmpgtsw" , kVC , D_A_B , kVmx, "Vector Compare Greater-Than Signed Word" ),
INSTRUCTION(0x10000206, "vcmpgtub" , kVC , D_A_B , kVmx, "Vector Compare Greater-Than Unsigned Byte" ),
INSTRUCTION(0x10000246, "vcmpgtuh" , kVC , D_A_B , kVmx, "Vector Compare Greater-Than Unsigned Half Word" ),
INSTRUCTION(0x10000286, "vcmpgtuw" , kVC , D_A_B , kVmx, "Vector Compare Greater-Than Unsigned Word" ),
INSTRUCTION(0x180002b0, "vcsxwfp128" , kVX128_3, D_B_SIMM , kVmx, "Vector128 Convert From Signed Fixed-Point Word to Floating-Point" ),
INSTRUCTION(0x100003ca, "vctsxs" , kVX , D_A_B , kVmx, "Vector Convert to Signed Fixed-Point Word Saturate" ),
INSTRUCTION(0x1000038a, "vctuxs" , kVX , D_A_B , kVmx, "Vector Convert to Unsigned Fixed-Point Word Saturate" ),
INSTRUCTION(0x180002f0, "vcuxwfp128" , kVX128_3, D_B_SIMM , kVmx, "Vector128 Convert From Unsigned Fixed-Point Word to Floating-Point" ),
INSTRUCTION(0x1000018a, "vexptefp" , kVX , D_A_B , kVmx, "Vector 2 Raised to the Exponent Estimate Floating Point" ),
INSTRUCTION(0x180006b0, "vexptefp128" , kVX128_3, D_B , kVmx, "Vector128 Log2 Estimate Floating Point" ),
INSTRUCTION(0x100001ca, "vlogefp" , kVX , D_A_B , kVmx, "Vector Log2 Estimate Floating Point" ),
INSTRUCTION(0x180006f0, "vlogefp128" , kVX128_3, D_B , kVmx, "Vector128 Log2 Estimate Floating Point" ),
INSTRUCTION(0x14000110, "vmaddcfp128" , kVX128 , D_A_D_B , kVmx, "Vector128 Multiply Add Floating Point" ),
INSTRUCTION(0x1000002e, "vmaddfp" , kVA , D_A_B_C , kVmx, "Vector Multiply-Add Floating Point" ),
INSTRUCTION(0x140000d0, "vmaddfp128" , kVX128 , D_A_D_B , kVmx, "Vector128 Multiply Add Floating Point" ),
INSTRUCTION(0x1000040a, "vmaxfp" , kVX , D_A_B , kVmx, "Vector Maximum Floating Point" ),
INSTRUCTION(0x18000280, "vmaxfp128" , kVX128 , D_A_B , kVmx, "Vector128 Maximum Floating Point" ),
INSTRUCTION(0x10000102, "vmaxsb" , kVX , D_A_B , kVmx, "Vector Maximum Signed Byte" ),
INSTRUCTION(0x10000142, "vmaxsh" , kVX , D_A_B , kVmx, "Vector Maximum Signed Half Word" ),
INSTRUCTION(0x10000182, "vmaxsw" , kVX , D_A_B , kVmx, "Vector Maximum Signed Word" ),
INSTRUCTION(0x10000002, "vmaxub" , kVX , D_A_B , kVmx, "Vector Maximum Unsigned Byte" ),
INSTRUCTION(0x10000042, "vmaxuh" , kVX , D_A_B , kVmx, "Vector Maximum Unsigned Half Word" ),
INSTRUCTION(0x10000082, "vmaxuw" , kVX , D_A_B , kVmx, "Vector Maximum Unsigned Word" ),
INSTRUCTION(0x10000020, "vmhaddshs" , kVA , D_A_B_C , kVmx, "Vector Multiply-High and Add Signed Signed Half Word Saturate" ),
INSTRUCTION(0x10000021, "vmhraddshs" , kVA , D_A_B_C , kVmx, "Vector Multiply-High Round and Add Signed Signed Half Word Saturate" ),
INSTRUCTION(0x1000044a, "vminfp" , kVX , D_A_B , kVmx, "Vector Minimum Floating Point" ),
INSTRUCTION(0x180002c0, "vminfp128" , kVX128 , D_A_B , kVmx, "Vector128 Minimum Floating Point" ),
INSTRUCTION(0x10000302, "vminsb" , kVX , D_A_B , kVmx, "Vector Minimum Signed Byte" ),
INSTRUCTION(0x10000342, "vminsh" , kVX , D_A_B , kVmx, "Vector Minimum Signed Half Word" ),
INSTRUCTION(0x10000382, "vminsw" , kVX , D_A_B , kVmx, "Vector Minimum Signed Word" ),
INSTRUCTION(0x10000202, "vminub" , kVX , D_A_B , kVmx, "Vector Minimum Unsigned Byte" ),
INSTRUCTION(0x10000242, "vminuh" , kVX , D_A_B , kVmx, "Vector Minimum Unsigned Half Word" ),
INSTRUCTION(0x10000282, "vminuw" , kVX , D_A_B , kVmx, "Vector Minimum Unsigned Word" ),
INSTRUCTION(0x10000022, "vmladduhm" , kVA , D_A_B_C , kVmx, "Vector Multiply-Low and Add Unsigned Half Word Modulo" ),
INSTRUCTION(0x1000000c, "vmrghb" , kVX , D_A_B , kVmx, "Vector Merge High Byte" ),
INSTRUCTION(0x1000004c, "vmrghh" , kVX , D_A_B , kVmx, "Vector Merge High Half Word" ),
INSTRUCTION(0x1000008c, "vmrghw" , kVX , D_A_B , kVmx, "Vector Merge High Word" ),
INSTRUCTION(0x18000300, "vmrghw128" , kVX128 , D_A_B , kVmx, "Vector128 Merge High Word" ),
INSTRUCTION(0x1000010c, "vmrglb" , kVX , D_A_B , kVmx, "Vector Merge Low Byte" ),
INSTRUCTION(0x1000014c, "vmrglh" , kVX , D_A_B , kVmx, "Vector Merge Low Half Word" ),
INSTRUCTION(0x1000018c, "vmrglw" , kVX , D_A_B , kVmx, "Vector Merge Low Word" ),
INSTRUCTION(0x18000340, "vmrglw128" , kVX128 , D_A_B , kVmx, "Vector128 Merge Low Word" ),
INSTRUCTION(0x14000190, "vmsum3fp128" , kVX128 , D_A_B , kVmx, "Vector128 Multiply Sum 3-way Floating Point" ),
INSTRUCTION(0x140001d0, "vmsum4fp128" , kVX128 , D_A_B , kVmx, "Vector128 Multiply Sum 4-way Floating-Point" ),
INSTRUCTION(0x10000025, "vmsummbm" , kVA , D_A_B_C , kVmx, "Vector Multiply-Sum Mixed-Sign Byte Modulo" ),
INSTRUCTION(0x10000028, "vmsumshm" , kVA , D_A_B_C , kVmx, "Vector Multiply-Sum Signed Half Word Modulo" ),
INSTRUCTION(0x10000029, "vmsumshs" , kVA , D_A_B_C , kVmx, "Vector Multiply-Sum Signed Half Word Saturate" ),
INSTRUCTION(0x10000024, "vmsumubm" , kVA , D_A_B_C , kVmx, "Vector Multiply-Sum Unsigned Byte Modulo" ),
INSTRUCTION(0x10000026, "vmsumuhm" , kVA , D_A_B_C , kVmx, "Vector Multiply-Sum Unsigned Half Word Modulo" ),
INSTRUCTION(0x10000027, "vmsumuhs" , kVA , D_A_B_C , kVmx, "Vector Multiply-Sum Unsigned Half Word Saturate" ),
INSTRUCTION(0x10000308, "vmulesb" , kVX , D_A_B , kVmx, "Vector Multiply Even Signed Byte" ),
INSTRUCTION(0x10000348, "vmulesh" , kVX , D_A_B , kVmx, "Vector Multiply Even Signed Half Word" ),
INSTRUCTION(0x10000208, "vmuleub" , kVX , D_A_B , kVmx, "Vector Multiply Even Unsigned Byte" ),
INSTRUCTION(0x10000248, "vmuleuh" , kVX , D_A_B , kVmx, "Vector Multiply Even Unsigned Half Word" ),
INSTRUCTION(0x14000090, "vmulfp128" , kVX128 , D_A_B , kVmx, "Vector128 Multiply Floating-Point" ),
INSTRUCTION(0x10000108, "vmulosb" , kVX , D_A_B , kVmx, "Vector Multiply Odd Signed Byte" ),
INSTRUCTION(0x10000148, "vmulosh" , kVX , D_A_B , kVmx, "Vector Multiply Odd Signed Half Word" ),
INSTRUCTION(0x10000008, "vmuloub" , kVX , D_A_B , kVmx, "Vector Multiply Odd Unsigned Byte" ),
INSTRUCTION(0x10000048, "vmulouh" , kVX , D_A_B , kVmx, "Vector Multiply Odd Unsigned Half Word" ),
INSTRUCTION(0x1000002f, "vnmsubfp" , kVA , D_A_B_C , kVmx, "Vector Negative Multiply-Subtract Floating Point" ),
INSTRUCTION(0x14000150, "vnmsubfp128" , kVX128 , D_A_B , kVmx, "Vector128 Negative Multiply-Subtract Floating Point" ),
INSTRUCTION(0x10000504, "vnor" , kVX , D_A_B , kVmx, "Vector Logical NOR" ),
INSTRUCTION(0x14000290, "vnor128" , kVX128 , D_A_B , kVmx, "Vector128 Logical NOR" ),
INSTRUCTION(0x10000484, "vor" , kVX , D_A_B , kVmx, "Vector Logical OR" ),
INSTRUCTION(0x140002d0, "vor128" , kVX128 , D_A_B , kVmx, "Vector128 Logical OR" ),
INSTRUCTION(0x1000002b, "vperm" , kVA , D_A_B_C , kVmx, "Vector Permute" ),
INSTRUCTION(0x14000000, "vperm128" , kVX128_2, D_A_B_C , kVmx, "Vector128 Permute" ),
INSTRUCTION(0x18000210, "vpermwi128" , kVX128_P, D_A_B_C , kVmx, "Vector128 Permutate Word Immediate" ),
INSTRUCTION(0x18000610, "vpkd3d128" , kVX128_4, D_B , kVmx, "Vector128 Pack D3Dtype, Rotate Left Immediate and Mask Insert" ),
INSTRUCTION(0x1000030e, "vpkpx" , kVX , D_A_B , kVmx, "Vector Pack Pixel" ),
INSTRUCTION(0x1000018e, "vpkshss" , kVX , D_A_B , kVmx, "Vector Pack Signed Half Word Signed Saturate" ),
INSTRUCTION(0x14000200, "vpkshss128" , kVX128 , D_A_B , kVmx, "Vector128 Pack Signed Half Word Signed Saturate" ),
INSTRUCTION(0x1000010e, "vpkshus" , kVX , D_A_B , kVmx, "Vector Pack Signed Half Word Unsigned Saturate" ),
INSTRUCTION(0x14000240, "vpkshus128" , kVX128 , D_A_B , kVmx, "Vector128 Pack Signed Half Word Unsigned Saturate" ),
INSTRUCTION(0x100001ce, "vpkswss" , kVX , D_A_B , kVmx, "Vector Pack Signed Word Signed Saturate" ),
INSTRUCTION(0x14000280, "vpkswss128" , kVX128 , D_A_B , kVmx, "Vector128 Pack Signed Word Signed Saturate" ),
INSTRUCTION(0x1000014e, "vpkswus" , kVX , D_A_B , kVmx, "Vector Pack Signed Word Unsigned Saturate" ),
INSTRUCTION(0x140002c0, "vpkswus128" , kVX128 , D_A_B , kVmx, "Vector128 Pack Signed Word Unsigned Saturate" ),
INSTRUCTION(0x1000000e, "vpkuhum" , kVX , D_A_B , kVmx, "Vector Pack Unsigned Half Word Unsigned Modulo" ),
INSTRUCTION(0x14000300, "vpkuhum128" , kVX128 , D_A_B , kVmx, "Vector128 Pack Unsigned Half Word Unsigned Modulo" ),
INSTRUCTION(0x1000008e, "vpkuhus" , kVX , D_A_B , kVmx, "Vector Pack Unsigned Half Word Unsigned Saturate" ),
INSTRUCTION(0x14000340, "vpkuhus128" , kVX128 , D_A_B , kVmx, "Vector128 Pack Unsigned Half Word Unsigned Saturate" ),
INSTRUCTION(0x1000004e, "vpkuwum" , kVX , D_A_B , kVmx, "Vector Pack Unsigned Word Unsigned Modulo" ),
INSTRUCTION(0x14000380, "vpkuwum128" , kVX128 , D_A_B , kVmx, "Vector128 Pack Unsigned Word Unsigned Modulo" ),
INSTRUCTION(0x100000ce, "vpkuwus" , kVX , D_A_B , kVmx, "Vector Pack Unsigned Word Unsigned Saturate" ),
INSTRUCTION(0x140003c0, "vpkuwus128" , kVX128 , D_A_B , kVmx, "Vector128 Pack Unsigned Word Unsigned Saturate" ),
INSTRUCTION(0x1000010a, "vrefp" , kVX , D_A_B , kVmx, "Vector Reciprocal Estimate Floating Point" ),
INSTRUCTION(0x18000630, "vrefp128" , kVX128_3, D_B , kVmx, "Vector128 Reciprocal Estimate Floating Point" ),
INSTRUCTION(0x100002ca, "vrfim" , kVX , D_A_B , kVmx, "Vector Round to Floating-Point Integer toward -Infinity" ),
INSTRUCTION(0x18000330, "vrfim128" , kVX128_3, D_B , kVmx, "Vector128 Round to Floating-Point Integer toward -Infinity" ),
INSTRUCTION(0x1000020a, "vrfin" , kVX , D_A_B , kVmx, "Vector Round to Floating-Point Integer Nearest" ),
INSTRUCTION(0x18000370, "vrfin128" , kVX128_3, D_B , kVmx, "Vector128 Round to Floating-Point Integer Nearest" ),
INSTRUCTION(0x1000028a, "vrfip" , kVX , D_A_B , kVmx, "Vector Round to Floating-Point Integer toward +Infinity" ),
INSTRUCTION(0x180003b0, "vrfip128" , kVX128_3, D_B , kVmx, "Vector128 Round to Floating-Point Integer toward +Infinity" ),
INSTRUCTION(0x1000024a, "vrfiz" , kVX , D_A_B , kVmx, "Vector Round to Floating-Point Integer toward Zero" ),
INSTRUCTION(0x180003f0, "vrfiz128" , kVX128_3, D_B , kVmx, "Vector128 Round to Floating-Point Integer toward Zero" ),
INSTRUCTION(0x10000004, "vrlb" , kVX , D_A_B , kVmx, "Vector Rotate Left Integer Byte" ),
INSTRUCTION(0x10000044, "vrlh" , kVX , D_A_B , kVmx, "Vector Rotate Left Integer Half Word" ),
INSTRUCTION(0x18000710, "vrlimi128" , kVX128_4, D_B_UIMM , kVmx, "Vector128 Rotate Left Immediate and Mask Insert" ),
INSTRUCTION(0x10000084, "vrlw" , kVX , D_A_B , kVmx, "Vector Rotate Left Integer Word" ),
INSTRUCTION(0x18000050, "vrlw128" , kVX128 , D_A_B , kVmx, "Vector128 Rotate Left Word" ),
INSTRUCTION(0x1000014a, "vrsqrtefp" , kVX , D_A_B , kVmx, "Vector Reciprocal Square Root Estimate Floating Point" ),
INSTRUCTION(0x18000670, "vrsqrtefp128", kVX128_3, D_B , kVmx, "Vector128 Reciprocal Square Root Estimate Floating Point" ),
INSTRUCTION(0x1000002a, "vsel" , kVA , D_A_B_C , kVmx, "Vector Conditional Select" ),
INSTRUCTION(0x14000350, "vsel128" , kVX128 , D_A_B_D , kVmx, "Vector128 Conditional Select" ),
INSTRUCTION(0x100001c4, "vsl" , kVX , D_A_B , kVmx, "Vector Shift Left" ),
INSTRUCTION(0x10000104, "vslb" , kVX , D_A_B , kVmx, "Vector Shift Left Integer Byte" ),
INSTRUCTION(0x1000002c, "vsldoi" , kVA , D_A_B_C , kVmx, "Vector Shift Left Double by Octet Immediate" ),
INSTRUCTION(0x10000010, "vsldoi128" , kVX128_5, D_A_B_I , kVmx, "Vector128 Shift Left Double by Octet Immediate" ),
INSTRUCTION(0x10000144, "vslh" , kVX , D_A_B , kVmx, "Vector Shift Left Integer Half Word" ),
INSTRUCTION(0x1000040c, "vslo" , kVX , D_A_B , kVmx, "Vector Shift Left by Octet" ),
INSTRUCTION(0x14000390, "vslo128" , kVX128 , D_A_B , kVmx, "Vector128 Shift Left Octet" ),
INSTRUCTION(0x10000184, "vslw" , kVX , D_A_B , kVmx, "Vector Shift Left Integer Word" ),
INSTRUCTION(0x180000d0, "vslw128" , kVX128 , D_A_B , kVmx, "Vector128 Shift Left Integer Word" ),
INSTRUCTION(0x1000020c, "vspltb" , kVX , D_A_B , kVmx, "Vector Splat Byte" ),
INSTRUCTION(0x1000024c, "vsplth" , kVX , D_A_B , kVmx, "Vector Splat Half Word" ),
INSTRUCTION(0x1000030c, "vspltisb" , kVX , D_A_B , kVmx, "Vector Splat Immediate Signed Byte" ),
INSTRUCTION(0x1000034c, "vspltish" , kVX , D_A_B , kVmx, "Vector Splat Immediate Signed Half Word" ),
INSTRUCTION(0x1000038c, "vspltisw" , kVX , D_A_B , kVmx, "Vector Splat Immediate Signed Word" ),
INSTRUCTION(0x18000770, "vspltisw128" , kVX128_3, D_B_SIMM , kVmx, "Vector128 Splat Immediate Signed Word" ),
INSTRUCTION(0x1000028c, "vspltw" , kVX , D_A_B , kVmx, "Vector Splat Word" ),
INSTRUCTION(0x18000730, "vspltw128" , kVX128_3, D_B_SIMM , kVmx, "Vector128 Splat Word" ),
INSTRUCTION(0x100002c4, "vsr" , kVX , D_A_B , kVmx, "Vector Shift Right" ),
INSTRUCTION(0x10000304, "vsrab" , kVX , D_A_B , kVmx, "Vector Shift Right Algebraic Byte" ),
INSTRUCTION(0x10000344, "vsrah" , kVX , D_A_B , kVmx, "Vector Shift Right Algebraic Half Word" ),
INSTRUCTION(0x10000384, "vsraw" , kVX , D_A_B , kVmx, "Vector Shift Right Algebraic Word" ),
INSTRUCTION(0x18000150, "vsraw128" , kVX128 , D_A_B , kVmx, "Vector128 Shift Right Arithmetic Word" ),
INSTRUCTION(0x10000204, "vsrb" , kVX , D_A_B , kVmx, "Vector Shift Right Byte" ),
INSTRUCTION(0x10000244, "vsrh" , kVX , D_A_B , kVmx, "Vector Shift Right Half Word" ),
INSTRUCTION(0x1000044c, "vsro" , kVX , D_A_B , kVmx, "Vector Shift Right Octet" ),
INSTRUCTION(0x140003d0, "vsro128" , kVX128 , D_A_B , kVmx, "Vector128 Shift Right Octet" ),
INSTRUCTION(0x10000284, "vsrw" , kVX , D_A_B , kVmx, "Vector Shift Right Word" ),
INSTRUCTION(0x180001d0, "vsrw128" , kVX128 , D_A_B , kVmx, "Vector128 Shift Right Word" ),
INSTRUCTION(0x10000580, "vsubcuw" , kVX , D_A_B , kVmx, "Vector Subtract Carryout Unsigned Word" ),
INSTRUCTION(0x1000004a, "vsubfp" , kVX , D_A_B , kVmx, "Vector Subtract Floating Point" ),
INSTRUCTION(0x14000050, "vsubfp128" , kVX128 , D_A_B , kVmx, "Vector128 Subtract Floating Point" ),
INSTRUCTION(0x10000700, "vsubsbs" , kVX , D_A_B , kVmx, "Vector Subtract Signed Byte Saturate" ),
INSTRUCTION(0x10000740, "vsubshs" , kVX , D_A_B , kVmx, "Vector Subtract Signed Half Word Saturate" ),
INSTRUCTION(0x10000780, "vsubsws" , kVX , D_A_B , kVmx, "Vector Subtract Signed Word Saturate" ),
INSTRUCTION(0x10000400, "vsububm" , kVX , D_A_B , kVmx, "Vector Subtract Unsigned Byte Modulo" ),
INSTRUCTION(0x10000600, "vsububs" , kVX , D_A_B , kVmx, "Vector Subtract Unsigned Byte Saturate" ),
INSTRUCTION(0x10000440, "vsubuhm" , kVX , D_A_B , kVmx, "Vector Subtract Unsigned Half Word Modulo" ),
INSTRUCTION(0x10000640, "vsubuhs" , kVX , D_A_B , kVmx, "Vector Subtract Unsigned Half Word Saturate" ),
INSTRUCTION(0x10000480, "vsubuwm" , kVX , D_A_B , kVmx, "Vector Subtract Unsigned Word Modulo" ),
INSTRUCTION(0x10000680, "vsubuws" , kVX , D_A_B , kVmx, "Vector Subtract Unsigned Word Saturate" ),
INSTRUCTION(0x10000688, "vsum2sws" , kVX , D_A_B , kVmx, "Vector Sum Across Partial (1/2) Signed Word Saturate" ),
INSTRUCTION(0x10000708, "vsum4sbs" , kVX , D_A_B , kVmx, "Vector Sum Across Partial (1/4) Signed Byte Saturate" ),
INSTRUCTION(0x10000648, "vsum4shs" , kVX , D_A_B , kVmx, "Vector Sum Across Partial (1/4) Signed Half Word Saturate" ),
INSTRUCTION(0x10000608, "vsum4ubs" , kVX , D_A_B , kVmx, "Vector Sum Across Partial (1/4) Unsigned Byte Saturate" ),
INSTRUCTION(0x10000788, "vsumsws" , kVX , D_A_B , kVmx, "Vector Sum Across Signed Word Saturate" ),
INSTRUCTION(0x180007f0, "vupkd3d128" , kVX128_3, D_B_SIMM , kVmx, "Vector128 Unpack D3Dtype" ),
INSTRUCTION(0x1000034e, "vupkhpx" , kVX , D_A_B , kVmx, "Vector Unpack High Pixel" ),
INSTRUCTION(0x1000020e, "vupkhsb" , kVX , D_A_B , kVmx, "Vector Unpack High Signed Byte" ),
INSTRUCTION(0x18000380, "vupkhsb128" , kVX128 , D_B , kVmx, "Vector128 Unpack High Signed Byte" ),
INSTRUCTION(0x1000024e, "vupkhsh" , kVX , D_A_B , kVmx, "Vector Unpack High Signed Half Word" ),
INSTRUCTION(0x100003ce, "vupklpx" , kVX , D_A_B , kVmx, "Vector Unpack Low Pixel" ),
INSTRUCTION(0x1000028e, "vupklsb" , kVX , D_A_B , kVmx, "Vector Unpack Low Signed Byte" ),
INSTRUCTION(0x180003c0, "vupklsb128" , kVX128 , D_B , kVmx, "Vector128 Unpack Low Signed Byte" ),
INSTRUCTION(0x100002ce, "vupklsh" , kVX , D_A_B , kVmx, "Vector Unpack Low Signed Half Word" ),
INSTRUCTION(0x100004c4, "vxor" , kVX , D_A_B , kVmx, "Vector Logical XOR" ),
INSTRUCTION(0x14000310, "vxor128" , kVX128 , D_A_B , kVmx, "Vector128 Logical XOR" ),
INSTRUCTION(0x68000000, "xori" , kD , S_A_UIMM , kInt, "XOR Immediate" ),
INSTRUCTION(0x6c000000, "xoris" , kD , S_A_UIMM , kInt, "XOR Immediate Shifted" ),
INSTRUCTION(0x7c000278, "xorx" , kX , S_A_B_Rc , kInt, "XOR" ),
};
static_assert(sizeof(ppc_opcode_table) / sizeof(PPCOpcodeInfo) == static_cast<int>(PPCOpcode::kInvalid), "PPC table mismatch - rerun ppc-table-gen");
const PPCOpcodeInfo& GetOpcodeInfo(PPCOpcode opcode) {
return ppc_opcode_table[static_cast<int>(opcode)];
}
} // namespace ppc
} // namespace cpu
} // namespace xe

View File

@ -17,6 +17,7 @@
#include "xenia/base/profiling.h" #include "xenia/base/profiling.h"
#include "xenia/cpu/ppc/ppc_frontend.h" #include "xenia/cpu/ppc/ppc_frontend.h"
#include "xenia/cpu/ppc/ppc_instr.h" #include "xenia/cpu/ppc/ppc_instr.h"
#include "xenia/cpu/ppc/ppc_opcode_info.h"
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
#if 0 #if 0
@ -63,23 +64,24 @@ bool PPCScanner::Scan(GuestFunction* function, DebugInfo* debug_info) {
size_t blocks_found = 0; size_t blocks_found = 0;
bool in_block = false; bool in_block = false;
bool starts_with_mfspr_lr = false; bool starts_with_mfspr_lr = false;
InstrData i;
while (true) { while (true) {
i.address = address; uint32_t code =
i.code = xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address)); xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
// If we fetched 0 assume that we somehow hit one of the awesome // If we fetched 0 assume that we somehow hit one of the awesome
// 'no really we meant to end after that bl' functions. // 'no really we meant to end after that bl' functions.
if (!i.code) { if (!code) {
LOGPPC("function end %.8X (0x00000000 read)", address); LOGPPC("function end %.8X (0x00000000 read)", address);
// Don't include the 0's. // Don't include the 0's.
address -= 4; address -= 4;
break; break;
} }
// TODO(benvanik): find a way to avoid using the opcode tables. auto opcode = LookupOpcode(code);
// This lookup is *expensive* and should be avoided when scanning.
i.type = GetInstrType(i.code); InstrData i;
i.address = address;
i.code = code;
// TODO(benvanik): switch on instruction metadata. // TODO(benvanik): switch on instruction metadata.
++address_reference_count; ++address_reference_count;
@ -88,7 +90,7 @@ bool PPCScanner::Scan(GuestFunction* function, DebugInfo* debug_info) {
// Check if the function starts with a mfspr lr, as that's a good indication // Check if the function starts with a mfspr lr, as that's a good indication
// of whether or not this is a normal function with a prolog/epilog. // of whether or not this is a normal function with a prolog/epilog.
// Some valid leaf functions won't have this, but most will. // Some valid leaf functions won't have this, but most will.
if (address == start_address && i.type && i.type->opcode == 0x7C0002A6 && if (address == start_address && opcode == PPCOpcode::mfspr &&
(((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F)) == 8) { (((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F)) == 8) {
starts_with_mfspr_lr = true; starts_with_mfspr_lr = true;
} }
@ -100,12 +102,12 @@ bool PPCScanner::Scan(GuestFunction* function, DebugInfo* debug_info) {
bool ends_fn = false; bool ends_fn = false;
bool ends_block = false; bool ends_block = false;
if (!i.type) { if (opcode == PPCOpcode::kInvalid) {
// Invalid instruction. // Invalid instruction.
// We can just ignore it because there's (very little)/no chance it'll // We can just ignore it because there's (very little)/no chance it'll
// affect flow control. // affect flow control.
LOGPPC("Invalid instruction at %.8X: %.8X", address, i.code); LOGPPC("Invalid instruction at %.8X: %.8X", address, code);
} else if (i.code == 0x4E800020) { } else if (code == 0x4E800020) {
// blr -- unconditional branch to LR. // blr -- unconditional branch to LR.
// This is generally a return. // This is generally a return.
if (furthest_target > address) { if (furthest_target > address) {
@ -117,7 +119,7 @@ bool PPCScanner::Scan(GuestFunction* function, DebugInfo* debug_info) {
ends_fn = true; ends_fn = true;
} }
ends_block = true; ends_block = true;
} else if (i.code == 0x4E800420) { } else if (code == 0x4E800420) {
// bctr -- unconditional branch to CTR. // bctr -- unconditional branch to CTR.
// This is generally a jump to a function pointer (non-return). // This is generally a jump to a function pointer (non-return).
// This is almost always a jump table. // This is almost always a jump table.
@ -131,7 +133,7 @@ bool PPCScanner::Scan(GuestFunction* function, DebugInfo* debug_info) {
ends_fn = true; ends_fn = true;
} }
ends_block = true; ends_block = true;
} else if (i.type->opcode == 0x48000000) { } else if (opcode == PPCOpcode::bx) {
// b/ba/bl/bla // b/ba/bl/bla
uint32_t target = uint32_t target =
(uint32_t)XEEXTS26(i.I.LI << 2) + (i.I.AA ? 0 : (int32_t)address); (uint32_t)XEEXTS26(i.I.LI << 2) + (i.I.AA ? 0 : (int32_t)address);
@ -209,7 +211,7 @@ bool PPCScanner::Scan(GuestFunction* function, DebugInfo* debug_info) {
} }
} }
ends_block = true; ends_block = true;
} else if (i.type->opcode == 0x40000000) { } else if (opcode == PPCOpcode::bcx) {
// bc/bca/bcl/bcla // bc/bca/bcl/bcla
uint32_t target = uint32_t target =
(uint32_t)XEEXTS16(i.B.BD << 2) + (i.B.AA ? 0 : (int32_t)address); (uint32_t)XEEXTS16(i.B.BD << 2) + (i.B.AA ? 0 : (int32_t)address);
@ -230,7 +232,7 @@ bool PPCScanner::Scan(GuestFunction* function, DebugInfo* debug_info) {
} }
} }
ends_block = true; ends_block = true;
} else if (i.type->opcode == 0x4C000020) { } else if (opcode == PPCOpcode::bclrx) {
// bclr/bclrl // bclr/bclrl
if (i.XL.LK) { if (i.XL.LK) {
LOGPPC("bclrl %.8X", address); LOGPPC("bclrl %.8X", address);
@ -238,7 +240,7 @@ bool PPCScanner::Scan(GuestFunction* function, DebugInfo* debug_info) {
LOGPPC("bclr %.8X", address); LOGPPC("bclr %.8X", address);
} }
ends_block = true; ends_block = true;
} else if (i.type->opcode == 0x4C000420) { } else if (opcode == PPCOpcode::bcctrx) {
// bcctr/bcctrl // bcctr/bcctrl
if (i.XL.LK) { if (i.XL.LK) {
LOGPPC("bcctrl %.8X", address); LOGPPC("bcctrl %.8X", address);
@ -299,17 +301,13 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(GuestFunction* function) {
uint32_t end_address = function->end_address(); uint32_t end_address = function->end_address();
bool in_block = false; bool in_block = false;
uint32_t block_start = 0; uint32_t block_start = 0;
InstrData i;
for (uint32_t address = start_address; address <= end_address; address += 4) { for (uint32_t address = start_address; address <= end_address; address += 4) {
i.address = address; uint32_t code =
i.code = xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address)); xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
if (!i.code) { if (!code) {
continue; continue;
} }
auto opcode = xe::cpu::ppc::LookupOpcode(code);
// TODO(benvanik): find a way to avoid using the opcode tables.
// This lookup is *expensive* and should be avoided when scanning.
i.type = GetInstrType(i.code);
if (!in_block) { if (!in_block) {
in_block = true; in_block = true;
@ -317,30 +315,28 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(GuestFunction* function) {
} }
bool ends_block = false; bool ends_block = false;
if (!i.type) { if (code == 0x4E800020) {
// Invalid instruction.
} else if (i.code == 0x4E800020) {
// blr -- unconditional branch to LR. // blr -- unconditional branch to LR.
ends_block = true; ends_block = true;
} else if (i.code == 0x4E800420) { } else if (code == 0x4E800420) {
// bctr -- unconditional branch to CTR. // bctr -- unconditional branch to CTR.
// This is almost always a jump table. // This is almost always a jump table.
// TODO(benvanik): decode jump tables. // TODO(benvanik): decode jump tables.
ends_block = true; ends_block = true;
} else if (i.type->opcode == 0x48000000) { } else if (opcode == PPCOpcode::bx) {
// b/ba/bl/bla // b/ba/bl/bla
// uint32_t target = // uint32_t target =
// (uint32_t)XEEXTS26(i.I.LI << 2) + (i.I.AA ? 0 : (int32_t)address); // (uint32_t)XEEXTS26(i.I.LI << 2) + (i.I.AA ? 0 : (int32_t)address);
ends_block = true; ends_block = true;
} else if (i.type->opcode == 0x40000000) { } else if (opcode == PPCOpcode::bcx) {
// bc/bca/bcl/bcla // bc/bca/bcl/bcla
// uint32_t target = // uint32_t target =
// (uint32_t)XEEXTS16(i.B.BD << 2) + (i.B.AA ? 0 : (int32_t)address); // (uint32_t)XEEXTS16(i.B.BD << 2) + (i.B.AA ? 0 : (int32_t)address);
ends_block = true; ends_block = true;
} else if (i.type->opcode == 0x4C000020) { } else if (opcode == PPCOpcode::bclrx) {
// bclr/bclrl // bclr/bclrl
ends_block = true; ends_block = true;
} else if (i.type->opcode == 0x4C000420) { } else if (opcode == PPCOpcode::bcctrx) {
// bcctr/bcctrl // bcctr/bcctrl
ends_block = true; ends_block = true;
} }

View File

@ -219,14 +219,11 @@ void PPCTranslator::DumpSource(GuestFunction* function,
uint32_t start_address = function->address(); uint32_t start_address = function->address();
uint32_t end_address = function->end_address(); uint32_t end_address = function->end_address();
InstrData i;
auto block_it = blocks.begin(); auto block_it = blocks.begin();
for (uint32_t address = start_address, offset = 0; address <= end_address; for (uint32_t address = start_address, offset = 0; address <= end_address;
address += 4, offset++) { address += 4, offset++) {
i.address = address; uint32_t code =
i.code = xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address)); xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
// TODO(benvanik): find a way to avoid using the opcode tables.
i.type = GetInstrType(i.code);
// Check labels. // Check labels.
if (block_it != blocks.end() && block_it->start_address == address) { if (block_it != blocks.end() && block_it->start_address == address) {
@ -235,8 +232,8 @@ void PPCTranslator::DumpSource(GuestFunction* function,
++block_it; ++block_it;
} }
string_buffer->AppendFormat("%.8X %.8X ", address, i.code); string_buffer->AppendFormat("%.8X %.8X ", address, code);
DisasmPPC(&i, string_buffer); DisasmPPC(address, code, string_buffer);
string_buffer->Append('\n'); string_buffer->Append('\n');
} }
} }

View File

@ -30,3 +30,14 @@ test_vcmpxxfp128_3:
#_ REGISTER_OUT v4 [3f800000, 3f800000, 3f800000, 3f800000] #_ REGISTER_OUT v4 [3f800000, 3f800000, 3f800000, 3f800000]
#_ REGISTER_OUT v5 [3f800001, 3f800001, 3f800001, 3f800001] #_ REGISTER_OUT v5 [3f800001, 3f800001, 3f800001, 3f800001]
#_ REGISTER_OUT r3 0x00000020 #_ REGISTER_OUT r3 0x00000020
test_vcmpxxfp128_4:
#_ REGISTER_IN v4 [3f800000, 3f800000, 3f800000, 3f800000]
#_ REGISTER_IN v5 [3f800001, 3f800001, 3f800001, 3f800001]
vcmpgefp128. v3, v4, v5
mfocrf r3, 2 # cr6
blr
#_ REGISTER_OUT v3 [00000000, 00000000, 00000000, 00000000]
#_ REGISTER_OUT v4 [3f800000, 3f800000, 3f800000, 3f800000]
#_ REGISTER_OUT v5 [3f800001, 3f800001, 3f800001, 3f800001]
#_ REGISTER_OUT r3 0x00000020

View File

@ -24,6 +24,7 @@
#include "xenia/cpu/backend/code_cache.h" #include "xenia/cpu/backend/code_cache.h"
#include "xenia/cpu/function.h" #include "xenia/cpu/function.h"
#include "xenia/cpu/ppc/ppc_instr.h" #include "xenia/cpu/ppc/ppc_instr.h"
#include "xenia/cpu/ppc/ppc_opcode_info.h"
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
#include "xenia/cpu/stack_walker.h" #include "xenia/cpu/stack_walker.h"
#include "xenia/emulator.h" #include "xenia/emulator.h"
@ -47,6 +48,7 @@ namespace xe {
namespace debug { namespace debug {
using xe::cpu::ThreadState; using xe::cpu::ThreadState;
using xe::cpu::ppc::PPCOpcode;
using xe::kernel::XObject; using xe::kernel::XObject;
using xe::kernel::XThread; using xe::kernel::XThread;
@ -723,10 +725,8 @@ uint32_t Debugger::CalculateNextGuestInstruction(
i.address = current_pc; i.address = current_pc;
i.code = xe::load_and_swap<uint32_t>( i.code = xe::load_and_swap<uint32_t>(
emulator_->memory()->TranslateVirtual(i.address)); emulator_->memory()->TranslateVirtual(i.address));
i.type = xe::cpu::ppc::GetInstrType(i.code); auto opcode = xe::cpu::ppc::LookupOpcode(i.code);
if (!i.type) { if (i.code == 0x4E800020) {
return current_pc + 4;
} else if (i.code == 0x4E800020) {
// blr -- unconditional branch to LR. // blr -- unconditional branch to LR.
uint32_t target_pc = static_cast<uint32_t>(thread_info->guest_context.lr); uint32_t target_pc = static_cast<uint32_t>(thread_info->guest_context.lr);
return target_pc; return target_pc;
@ -734,13 +734,13 @@ uint32_t Debugger::CalculateNextGuestInstruction(
// bctr -- unconditional branch to CTR. // bctr -- unconditional branch to CTR.
uint32_t target_pc = static_cast<uint32_t>(thread_info->guest_context.ctr); uint32_t target_pc = static_cast<uint32_t>(thread_info->guest_context.ctr);
return target_pc; return target_pc;
} else if (i.type->opcode == 0x48000000) { } else if (opcode == PPCOpcode::bx) {
// b/ba/bl/bla // b/ba/bl/bla
uint32_t target_pc = uint32_t target_pc =
static_cast<uint32_t>(xe::cpu::ppc::XEEXTS26(i.I.LI << 2)) + static_cast<uint32_t>(xe::cpu::ppc::XEEXTS26(i.I.LI << 2)) +
(i.I.AA ? 0u : i.address); (i.I.AA ? 0u : i.address);
return target_pc; return target_pc;
} else if (i.type->opcode == 0x40000000) { } else if (opcode == PPCOpcode::bcx) {
// bc/bca/bcl/bcla // bc/bca/bcl/bcla
uint32_t target_pc = uint32_t target_pc =
static_cast<uint32_t>(xe::cpu::ppc::XEEXTS16(i.B.BD << 2)) + static_cast<uint32_t>(xe::cpu::ppc::XEEXTS16(i.B.BD << 2)) +
@ -748,13 +748,13 @@ uint32_t Debugger::CalculateNextGuestInstruction(
bool test_passed = TestPpcCondition(&thread_info->guest_context, i.B.BO, bool test_passed = TestPpcCondition(&thread_info->guest_context, i.B.BO,
i.B.BI, true, true); i.B.BI, true, true);
return test_passed ? target_pc : current_pc + 4; return test_passed ? target_pc : current_pc + 4;
} else if (i.type->opcode == 0x4C000020) { } else if (opcode == PPCOpcode::bclrx) {
// bclr/bclrl // bclr/bclrl
uint32_t target_pc = static_cast<uint32_t>(thread_info->guest_context.lr); uint32_t target_pc = static_cast<uint32_t>(thread_info->guest_context.lr);
bool test_passed = TestPpcCondition(&thread_info->guest_context, i.XL.BO, bool test_passed = TestPpcCondition(&thread_info->guest_context, i.XL.BO,
i.XL.BI, true, true); i.XL.BI, true, true);
return test_passed ? target_pc : current_pc + 4; return test_passed ? target_pc : current_pc + 4;
} else if (i.type->opcode == 0x4C000420) { } else if (opcode == PPCOpcode::bcctrx) {
// bcctr/bcctrl // bcctr/bcctrl
uint32_t target_pc = static_cast<uint32_t>(thread_info->guest_context.ctr); uint32_t target_pc = static_cast<uint32_t>(thread_info->guest_context.ctr);
bool test_passed = TestPpcCondition(&thread_info->guest_context, i.XL.BO, bool test_passed = TestPpcCondition(&thread_info->guest_context, i.XL.BO,

View File

@ -502,12 +502,10 @@ void DebugWindow::DrawGuestFunctionSource() {
ImGui::Text(" %c ", is_current_instr ? '>' : ' '); ImGui::Text(" %c ", is_current_instr ? '>' : ' ');
ImGui::SameLine(); ImGui::SameLine();
cpu::ppc::InstrData i; uint32_t code =
i.address = address; xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
i.code = xe::load_and_swap<uint32_t>(memory->TranslateVirtual(address)); cpu::ppc::DisasmPPC(address, code, &str);
i.type = cpu::ppc::GetInstrType(i.code); ImGui::Text("%.8X %.8X %s", address, code, str.GetString());
cpu::ppc::DisasmPPC(&i, &str);
ImGui::Text("%.8X %.8X %s", address, i.code, str.GetString());
str.Reset(); str.Reset();
if (is_current_instr) { if (is_current_instr) {

View File

@ -298,6 +298,10 @@ dword_result_t XamShowDeviceSelectorUI(dword_t user_index, dword_t content_type,
case 3: // title/publisher update? case 3: // title/publisher update?
*device_id_ptr = 0xF00D0000 | 0x0003; *device_id_ptr = 0xF00D0000 | 0x0003;
break; break;
default:
assert_unhandled_case(content_type);
*device_id_ptr = 0xF00D0000 | 0x0001;
break;
} }
if (overlapped) { if (overlapped) {

466
tools/ppc-instructions.xml Normal file
View File

@ -0,0 +1,466 @@
<?xml version="1.0" encoding="UTF-8"?>
<root>
<ppc-isa name="6xx_pem">
<insn desc="Add" form="XO" group="int" mnem="addx" opcode="7c000214" sub-form="D-A-B-OE-Rc" />
<insn desc="Add Carrying" form="XO" group="int" mnem="addcx" opcode="7c000014" sub-form="D-A-B-OE-Rc" />
<insn desc="Add Extended" form="XO" group="int" mnem="addex" opcode="7c000114" sub-form="D-A-B-OE-Rc" />
<insn desc="Add Immediate" form="D" group="int" mnem="addi" opcode="38000000" sub-form="D-A-SIMM" />
<insn desc="Add Immediate Carrying" form="D" group="int" mnem="addic" opcode="30000000" sub-form="D-A-SIMM" />
<insn desc="Add Immediate Carrying and Record" form="D" group="int" mnem="addic." opcode="34000000" sub-form="D-A-SIMM" />
<insn desc="Add Immediate Shifted" form="D" group="int" mnem="addis" opcode="3c000000" sub-form="D-A-SIMM" />
<insn desc="Add to Minus One Extended" form="XO" group="int" mnem="addmex" opcode="7c0001d4" sub-form="D-A-0-OE-Rc" />
<insn desc="Add to Zero Extended" form="XO" group="int" mnem="addzex" opcode="7c000194" sub-form="D-A-0-OE-Rc" />
<insn desc="AND" form="X" group="int" mnem="andx" opcode="7c000038" sub-form="S-A-B-Rc" />
<insn desc="AND with Complement" form="X" group="int" mnem="andcx" opcode="7c000078" sub-form="S-A-B-Rc" />
<insn desc="AND Immediate" form="D" group="int" mnem="andi." opcode="70000000" sub-form="S-A-UIMM" />
<insn desc="AND Immediate Shifted" form="D" group="int" mnem="andis." opcode="74000000" sub-form="S-A-UIMM" />
<insn desc="Branch" form="I" group="int" mnem="bx" opcode="48000000" sub-form="LI-AA-LK" />
<insn desc="Branch Conditional" form="B" group="int" mnem="bcx" opcode="40000000" sub-form="BO-BI-BD-AA-LK" />
<insn desc="Branch Conditional to Count Register" form="XL" group="int" mnem="bcctrx" opcode="4c000420" sub-form="BO-BI-0-LK" />
<insn desc="Branch Conditional to Link Register" form="XL" group="int" mnem="bclrx" opcode="4c000020" sub-form="BO-BI-0-LK" />
<insn desc="Compare" form="X" group="int" mnem="cmp" opcode="7c000000" sub-form="crfD-L-A-B" />
<insn desc="Compare Immediate" form="D" group="int" mnem="cmpi" opcode="2c000000" sub-form="crfD-L-A-SIMM" />
<insn desc="Compare Logical" form="X" group="int" mnem="cmpl" opcode="7c000040" sub-form="crfD-L-A-B" />
<insn desc="Compare Logical Immediate" form="D" group="int" mnem="cmpli" opcode="28000000" sub-form="crfD-L-A-UIMM" />
<insn desc="Count Leading Zeros Doubleword" form="X" group="int" mnem="cntlzdx" opcode="7c000074" sub-form="S-A-0-Rc" />
<insn desc="Count Leading Zeros Word" form="X" group="int" mnem="cntlzwx" opcode="7c000034" sub-form="S-A-0-Rc" />
<insn desc="Condition Register AND" form="XL" group="int" mnem="crand" opcode="4c000202" sub-form="crbD-crbA-crbB" />
<insn desc="Condition Register AND with Complement" form="XL" group="int" mnem="crandc" opcode="4c000102" sub-form="crbD-crbA-crbB" />
<insn desc="Condition Register Equivalent" form="XL" group="int" mnem="creqv" opcode="4c000242" sub-form="crbD-crbA-crbB" />
<insn desc="Condition Register NAND" form="XL" group="int" mnem="crnand" opcode="4c0001c2" sub-form="crbD-crbA-crbB" />
<insn desc="Condition Register NOR" form="XL" group="int" mnem="crnor" opcode="4c000042" sub-form="crbD-crbA-crbB" />
<insn desc="Condition Register OR" form="XL" group="int" mnem="cror" opcode="4c000382" sub-form="crbD-crbA-crbB" />
<insn desc="Condition Register OR with Complement" form="XL" group="int" mnem="crorc" opcode="4c000342" sub-form="crbD-crbA-crbB" />
<insn desc="Condition Register XOR" form="XL" group="int" mnem="crxor" opcode="4c000182" sub-form="crbD-crbA-crbB" />
<insn desc="Data Cache Block Allocate" form="X" group="int" mnem="dcba" opcode="7c0005ec" sub-form="0-A-B" />
<insn desc="Data Cache Block Flush" form="X" group="int" mnem="dcbf" opcode="7c0000ac" sub-form="0-A-B" />
<insn desc="Data Cache Block Invalidate" form="X" group="int" mnem="dcbi" opcode="7c0003ac" sub-form="0-A-B" />
<insn desc="Data Cache Block Store" form="X" group="int" mnem="dcbst" opcode="7c00006c" sub-form="0-A-B" />
<insn desc="Data Cache Block Touch" form="X" group="int" mnem="dcbt" opcode="7c00022c" sub-form="0-A-B" />
<insn desc="Data Cache Block Touch for Store" form="X" group="int" mnem="dcbtst" opcode="7c0001ec" sub-form="0-A-B" />
<insn desc="Data Cache Block Clear to Zero" form="DCBZ" group="int" mnem="dcbz" opcode="7c0007ec" sub-form="0-A-B" />
<insn desc="Data Cache Block Clear to Zero 128" form="DCBZ" group="int" mnem="dcbz128" opcode="7c2007ec" sub-form="0-A-B" />
<insn desc="Divide Doubleword" form="XO" group="int" mnem="divdx" opcode="7c0003d2" sub-form="D-A-B-OE-Rc" />
<insn desc="Divide Doubleword Unsigned" form="XO" group="int" mnem="divdux" opcode="7c000392" sub-form="D-A-B-OE-Rc" />
<insn desc="Divide Word" form="XO" group="int" mnem="divwx" opcode="7c0003d6" sub-form="D-A-B-OE-Rc" />
<insn desc="Divide Word Unsigned" form="XO" group="int" mnem="divwux" opcode="7c000396" sub-form="D-A-B-OE-Rc" />
<insn desc="External Control In Word Indexed" form="X" group="int" mnem="eciwx" opcode="7c00026c" sub-form="D-A-B" />
<insn desc="External Control Out Word Indexed" form="X" group="int" mnem="ecowx" opcode="7c00036c" sub-form="S-A-B" />
<insn desc="Enforce In-Order Execution of I/O" form="X" group="int" mnem="eieio" opcode="7c0006ac" sub-form="0-0-0" />
<insn desc="Equivalent" form="X" group="int" mnem="eqvx" opcode="7c000238" sub-form="S-A-B-Rc" />
<insn desc="Extend Sign Byte" form="X" group="int" mnem="extsbx" opcode="7c000774" sub-form="S-A-0-Rc" />
<insn desc="Extend Sign Half Word" form="X" group="int" mnem="extshx" opcode="7c000734" sub-form="S-A-0-Rc" />
<insn desc="Extend Sign Word" form="X" group="int" mnem="extswx" opcode="7c0007B4" sub-form="S-A-0-Rc" />
<insn desc="Floating Absolute Value" form="X" group="fp" mnem="fabsx" opcode="fc000210" sub-form="D-0-B-Rc" />
<insn desc="Floating Add" form="A" group="fp" mnem="faddx" opcode="fc00002a" sub-form="D-A-B-0-Rc" />
<insn desc="Floating Add Single" form="A" group="fp" mnem="faddsx" opcode="ec00002a" sub-form="D-A-B-0-Rc" />
<insn desc="Floating Convert From Integer Doubleword" form="X" group="fp" mnem="fcfidx" opcode="FC00069C" sub-form="D-A-B-Rc" />
<insn desc="Floating Compare Ordered" form="X" group="fp" mnem="fcmpo" opcode="fc000040" sub-form="crfD-A-B" />
<insn desc="Floating Compare Unordered" form="X" group="fp" mnem="fcmpu" opcode="fc000000" sub-form="crfD-A-B" />
<insn desc="Floating Convert to Integer Doubleword" form="X" group="fp" mnem="fctidx" opcode="fc00065c" sub-form="D-0-B-Rc" />
<insn desc="Floating Convert to Integer Doubleword with Round Toward Zero" form="X" group="fp" mnem="fctidzx" opcode="fc00065e" sub-form="D-0-B-Rc" />
<insn desc="Floating Convert to Integer Word" form="X" group="fp" mnem="fctiwx" opcode="fc00001c" sub-form="D-0-B-Rc" />
<insn desc="Floating Convert to Integer Word with Round Toward Zero" form="X" group="fp" mnem="fctiwzx" opcode="fc00001e" sub-form="D-0-B-Rc" />
<insn desc="Floating Divide" form="A" group="fp" mnem="fdivx" opcode="fc000024" sub-form="D-A-B-0-Rc" />
<insn desc="Floating Divide Single" form="A" group="fp" mnem="fdivsx" opcode="ec000024" sub-form="D-A-B-0-Rc" />
<insn desc="Floating Multiply-Add" form="A" group="fp" mnem="fmaddx" opcode="fc00003a" sub-form="D-A-B-C-Rc" />
<insn desc="Floating Multiply-Add Single" form="A" group="fp" mnem="fmaddsx" opcode="ec00003a" sub-form="D-A-B-C-Rc" />
<insn desc="Floating Move Register" form="X" group="fp" mnem="fmrx" opcode="fc000090" sub-form="D-0-B-Rc" />
<insn desc="Floating Multiply-Subtract" form="A" group="fp" mnem="fmsubx" opcode="fc000038" sub-form="D-A-B-C-Rc" />
<insn desc="Floating Multiply-Subtract Single" form="A" group="fp" mnem="fmsubsx" opcode="ec000038" sub-form="D-A-B-C-Rc" />
<insn desc="Floating Multiply" form="A" group="fp" mnem="fmulx" opcode="fc000032" sub-form="D-A-0-C-Rc" />
<insn desc="Floating Multiply Single" form="A" group="fp" mnem="fmulsx" opcode="ec000032" sub-form="D-A-0-C-Rc" />
<insn desc="Floating Negative Absolute Value" form="X" group="fp" mnem="fnabsx" opcode="fc000110" sub-form="D-0-B-Rc" />
<insn desc="Floating Negate" form="X" group="fp" mnem="fnegx" opcode="fc000050" sub-form="D-0-B-Rc" />
<insn desc="Floating Negative Multiply-Add" form="A" group="fp" mnem="fnmaddx" opcode="fc00003e" sub-form="D-A-B-C-Rc" />
<insn desc="Floating Negative Multiply-Add Single" form="A" group="fp" mnem="fnmaddsx" opcode="ec00003e" sub-form="D-A-B-C-Rc" />
<insn desc="Floating Negative Multiply-Subtract" form="A" group="fp" mnem="fnmsubx" opcode="fc00003c" sub-form="D-A-B-C-Rc" />
<insn desc="Floating Negative Multiply-Subtract Single" form="A" group="fp" mnem="fnmsubsx" opcode="ec00003c" sub-form="D-A-B-C-Rc" />
<insn desc="Floating Reciprocal Estimate Single" form="A" group="fp" mnem="fresx" opcode="ec000030" sub-form="D-0-B-0-Rc" />
<insn desc="Floating Round to Single" form="X" group="fp" mnem="frspx" opcode="fc000018" sub-form="D-0-B-Rc" />
<insn desc="Floating Reciprocal Square Root Estimate" form="A" group="fp" mnem="frsqrtex" opcode="fc000034" sub-form="D-0-B-0-Rc" />
<insn desc="Floating Select" form="A" group="fp" mnem="fselx" opcode="fc00002e" sub-form="D-A-B-C-Rc" />
<insn desc="Floating Square Root" form="A" group="fp" mnem="fsqrtx" opcode="fc00002c" sub-form="D-0-B-0-Rc" />
<insn desc="Floating Square Root Single" form="A" group="fp" mnem="fsqrtsx" opcode="ec00002c" sub-form="D-0-B-0-Rc" />
<insn desc="Floating Subtract" form="A" group="fp" mnem="fsubx" opcode="fc000028" sub-form="D-A-B-0-Rc" />
<insn desc="Floating Subtract Single" form="A" group="fp" mnem="fsubsx" opcode="ec000028" sub-form="D-A-B-0-Rc" />
<insn desc="Instruction Cache Block Invalidate" form="X" group="int" mnem="icbi" opcode="7c0007ac" sub-form="0-A-B" />
<insn desc="Instruction Synchronize" form="XL" group="int" mnem="isync" opcode="4c00012c" sub-form="0-0-0" />
<insn desc="Load Byte and Zero" form="D" group="int" mnem="lbz" opcode="88000000" sub-form="D-A-d" />
<insn desc="Load Byte and Zero with Update" form="D" group="int" mnem="lbzu" opcode="8c000000" sub-form="D-A-d" />
<insn desc="Load Byte and Zero with Update Indexed" form="X" group="int" mnem="lbzux" opcode="7c0000ee" sub-form="D-A-B" />
<insn desc="Load Byte and Zero Indexed" form="X" group="int" mnem="lbzx" opcode="7c0000ae" sub-form="D-A-B" />
<insn desc="Load Doubleword" form="DS" group="int" mnem="ld" opcode="E8000000" sub-form="D-A-d" />
<insn desc="Load Doubleword and Reserve Indexed" form="X" group="int" mnem="ldarx" opcode="7C0000A8" sub-form="D-A-B" />
<insn desc="Load Doubleword Byte-Reverse Indexed" form="X" group="int" mnem="ldbrx" opcode="7C000428" sub-form="D-A-B" />
<insn desc="Load Doubleword with Update" form="DS" group="int" mnem="ldu" opcode="E8000001" sub-form="D-A-d" />
<insn desc="Load Doubleword with Update Indexed" form="X" group="int" mnem="ldux" opcode="7c00006a" sub-form="D-A-B" />
<insn desc="Load Doubleword Indexed" form="X" group="int" mnem="ldx" opcode="7c00002a" sub-form="D-A-B" />
<insn desc="Load Floating-Point Double" form="D" group="fp" mnem="lfd" opcode="c8000000" sub-form="D-A-d" />
<insn desc="Load Floating-Point Double with Update" form="D" group="fp" mnem="lfdu" opcode="cc000000" sub-form="D-A-d" />
<insn desc="Load Floating-Point Double with Update Indexed" form="X" group="fp" mnem="lfdux" opcode="7c0004ee" sub-form="D-A-B" />
<insn desc="Load Floating-Point Double Indexed" form="X" group="fp" mnem="lfdx" opcode="7c0004ae" sub-form="D-A-B" />
<insn desc="Load Floating-Point Single" form="D" group="fp" mnem="lfs" opcode="c0000000" sub-form="D-A-d" />
<insn desc="Load Floating-Point Single with Update" form="D" group="fp" mnem="lfsu" opcode="c4000000" sub-form="D-A-d" />
<insn desc="Load Floating-Point Single with Update Indexed" form="X" group="fp" mnem="lfsux" opcode="7c00046e" sub-form="D-A-B" />
<insn desc="Load Floating-Point Single Indexed" form="X" group="fp" mnem="lfsx" opcode="7c00042e" sub-form="D-A-B" />
<insn desc="Load Half Word Algebraic" form="D" group="int" mnem="lha" opcode="a8000000" sub-form="D-A-d" />
<insn desc="Load Half Word Algebraic with Update" form="D" group="int" mnem="lhau" opcode="ac000000" sub-form="D-A-d" />
<insn desc="Load Half Word Algebraic with Update Indexed" form="X" group="int" mnem="lhaux" opcode="7c0002ee" sub-form="D-A-B" />
<insn desc="Load Half Word Algebraic Indexed" form="X" group="int" mnem="lhax" opcode="7c0002ae" sub-form="D-A-B" />
<insn desc="Load Half Word Byte-Reverse Indexed" form="X" group="int" mnem="lhbrx" opcode="7c00062c" sub-form="D-A-B" />
<insn desc="Load Half Word and Zero" form="D" group="int" mnem="lhz" opcode="a0000000" sub-form="D-A-d" />
<insn desc="Load Half Word and Zero with Update" form="D" group="int" mnem="lhzu" opcode="a4000000" sub-form="D-A-d" />
<insn desc="Load Half Word and Zero with Update Indexed" form="X" group="int" mnem="lhzux" opcode="7c00026e" sub-form="D-A-B" />
<insn desc="Load Half Word and Zero Indexed" form="X" group="int" mnem="lhzx" opcode="7c00022e" sub-form="D-A-B" />
<insn desc="Load Multiple Word" form="D" group="int" mnem="lmw" opcode="b8000000" sub-form="D-A-d" />
<insn desc="Load String Word Immediate" form="X" group="int" mnem="lswi" opcode="7c0004aa" sub-form="D-A-NB" />
<insn desc="Load String Word Indexed" form="X" group="int" mnem="lswx" opcode="7c00042a" sub-form="D-A-B" />
<insn desc="Load Vector Element Byte Indexed" form="X" group="vmx" mnem="lvebx" opcode="7c00000e" sub-form="D-A-B" />
<insn desc="Load Vector Element Half Word Indexed" form="X" group="vmx" mnem="lvehx" opcode="7c00004e" sub-form="D-A-B" />
<insn desc="Load Vector Element Word Indexed" form="X" group="vmx" mnem="lvewx" opcode="7c00008e" sub-form="D-A-B" />
<insn desc="Load Vector Element Word Indexed 128" form="VX128_1" group="vmx" mnem="lvewx128" opcode="10000083" sub-form="D-A-B" />
<insn desc="Load Vector for Shift Left Indexed" form="X" group="vmx" mnem="lvsl" opcode="7c00000c" sub-form="D-A-B" />
<insn desc="Load Vector for Shift Left Indexed 128" form="VX128_1" group="vmx" mnem="lvsl128" opcode="10000003" sub-form="D-A-B" />
<insn desc="Load Vector for Shift Right Indexed" form="X" group="vmx" mnem="lvsr" opcode="7c00004c" sub-form="D-A-B" />
<insn desc="Load Vector for Shift Right Indexed 128" form="VX128_1" group="vmx" mnem="lvsr128" opcode="10000043" sub-form="D-A-B" />
<insn desc="Load Vector Indexed" form="X" group="vmx" mnem="lvx" opcode="7c0000ce" sub-form="D-A-B" />
<insn desc="Load Vector Indexed 128" form="VX128_1" group="vmx" mnem="lvx128" opcode="100000C3" sub-form="D-A-B" />
<insn desc="Load Vector Indexed LRU" form="X" group="vmx" mnem="lvxl" opcode="7c0002ce" sub-form="D-A-B" />
<insn desc="Load Vector Indexed LRU 128" form="VX128_1" group="vmx" mnem="lvxl128" opcode="100002C3" sub-form="D-A-B" />
<insn desc="Load Vector Left Indexed" form="X" group="vmx" mnem="lvlx" opcode="7C00040E" sub-form="D-A-B" />
<insn desc="Load Vector Left Indexed 128" form="VX128_1" group="vmx" mnem="lvlx128" opcode="10000403" sub-form="D-A-B" />
<insn desc="Load Vector Left Indexed LRU" form="X" group="vmx" mnem="lvlxl" opcode="7C00060E" sub-form="D-A-B" />
<insn desc="Load Vector Left Indexed LRU 128" form="VX128_1" group="vmx" mnem="lvlxl128" opcode="10000603" sub-form="D-A-B" />
<insn desc="Load Vector Right Indexed" form="X" group="vmx" mnem="lvrx" opcode="7C00044E" sub-form="D-A-B" />
<insn desc="Load Vector Right Indexed 128" form="VX128_1" group="vmx" mnem="lvrx128" opcode="10000443" sub-form="D-A-B" />
<insn desc="Load Vector Right Indexed LRU" form="X" group="vmx" mnem="lvrxl" opcode="7C00064E" sub-form="D-A-B" />
<insn desc="Load Vector Right Indexed LRU 128" form="VX128_1" group="vmx" mnem="lvrxl128" opcode="10000643" sub-form="D-A-B" />
<insn desc="Load Word Algebraic" form="DS" group="int" mnem="lwa" opcode="e8000002" sub-form="D-A-d" />
<insn desc="Load Word and Reserve Indexed" form="X" group="int" mnem="lwarx" opcode="7c000028" sub-form="D-A-B" />
<insn desc="Load Word Algebraic with Update Indexed" form="X" group="int" mnem="lwaux" opcode="7c0002ea" sub-form="D-A-B" />
<insn desc="Load Word Algebraic Indexed" form="X" group="int" mnem="lwax" opcode="7c0002aa" sub-form="D-A-B" />
<insn desc="Load Word Byte-Reverse Indexed" form="X" group="int" mnem="lwbrx" opcode="7c00042c" sub-form="D-A-B" />
<insn desc="Load Word and Zero" form="D" group="int" mnem="lwz" opcode="80000000" sub-form="D-A-d" />
<insn desc="Load Word and Zero with Update" form="D" group="int" mnem="lwzu" opcode="84000000" sub-form="D-A-d" />
<insn desc="Load Word and Zero with Update Indexed" form="X" group="int" mnem="lwzux" opcode="7c00006e" sub-form="D-A-B" />
<insn desc="Load Word and Zero Indexed" form="X" group="int" mnem="lwzx" opcode="7c00002e" sub-form="D-A-B" />
<insn desc="Move Condition Register Field" form="XL" group="int" mnem="mcrf" opcode="4c000000" sub-form="crfD-crfS-0" />
<insn desc="Move to Condition Register from FPSCR" form="X" group="fp" mnem="mcrfs" opcode="fc000080" sub-form="crfD-crfS-0" />
<insn desc="Move to Condition Register from XER" form="X" group="int" mnem="mcrxr" opcode="7c000400" sub-form="crfD-0-0" />
<insn desc="Move from Condition Register" form="X" group="int" mnem="mfcr" opcode="7c000026" sub-form="D-0-0" />
<insn desc="Move from FPSCR" form="X" group="fp" mnem="mffsx" opcode="fc00048e" sub-form="D-0-0-Rc" />
<insn desc="Move from Machine State Register" form="X" group="int" mnem="mfmsr" opcode="7c0000a6" sub-form="D-0-0" />
<insn desc="Move from Special-Purpose Register" form="XFX" group="int" mnem="mfspr" opcode="7c0002a6" sub-form="D-spr" />
<insn desc="Move from Time Base" form="XFX" group="int" mnem="mftb" opcode="7c0002e6" sub-form="D-tbr" />
<insn desc="Move from VSCR" form="VX" group="int" mnem="mfvscr" opcode="10000604" sub-form="D-0-0" />
<insn desc="Move to Condition Register Fields" form="XFX" group="int" mnem="mtcrf" opcode="7c000120" sub-form="S-CRM" />
<insn desc="Move to FPSCR Bit 0" form="X" group="fp" mnem="mtfsb0x" opcode="fc00008c" sub-form="crbD-0-0-Rc" />
<insn desc="Move to FPSCR Bit 1" form="X" group="fp" mnem="mtfsb1x" opcode="fc00004c" sub-form="crbD-0-0-Rc" />
<insn desc="Move to FPSCR Fields" form="XFL" group="fp" mnem="mtfsfx" opcode="fc00058e" sub-form="FM-B-Rc" />
<insn desc="Move to FPSCR Field Immediate" form="X" group="fp" mnem="mtfsfix" opcode="fc00010c" sub-form="crfD-0-IMM-Rc" />
<insn desc="Move to Machine State Register" form="X" group="int" mnem="mtmsr" opcode="7c000124" sub-form="S-0-0" />
<insn desc="Move to Machine State Register Doubleword" form="X" group="int" mnem="mtmsrd" opcode="7c000164" sub-form="S-0-0" />
<insn desc="Move to Special-Purpose Register" form="XFX" group="int" mnem="mtspr" opcode="7c0003a6" sub-form="S-spr" />
<insn desc="Move to VSCR" form="VX" group="int" mnem="mtvscr" opcode="10000644" sub-form="S-0-0" />
<insn desc="Multiply High Doubleword" form="XO" group="int" mnem="mulhdx" opcode="7c000092" sub-form="D-A-B-Rc" />
<insn desc="Multiply High Doubleword Unsigned" form="XO" group="int" mnem="mulhdux" opcode="7c000012" sub-form="D-A-B-Rc" />
<insn desc="Multiply High Word" form="XO" group="int" mnem="mulhwx" opcode="7c000096" sub-form="D-A-B-Rc" />
<insn desc="Multiply High Word Unsigned" form="XO" group="int" mnem="mulhwux" opcode="7c000016" sub-form="D-A-B-Rc" />
<insn desc="Multiply Low Doubleword" form="XO" group="int" mnem="mulldx" opcode="7c0001d2" sub-form="D-A-B-OE-Rc" />
<insn desc="Multiply Low Immediate" form="D" group="int" mnem="mulli" opcode="1c000000" sub-form="D-A-SIMM" />
<insn desc="Multiply Low Word" form="XO" group="int" mnem="mullwx" opcode="7c0001d6" sub-form="D-A-B-OE-Rc" />
<insn desc="NAND" form="X" group="int" mnem="nandx" opcode="7c0003b8" sub-form="S-A-B-Rc" />
<insn desc="Negate" form="XO" group="int" mnem="negx" opcode="7c0000d0" sub-form="D-A-0-OE-Rc" />
<insn desc="NOR" form="X" group="int" mnem="norx" opcode="7c0000f8" sub-form="S-A-B-Rc" />
<insn desc="OR" form="X" group="int" mnem="orx" opcode="7c000378" sub-form="S-A-B-Rc" />
<insn desc="OR with Complement" form="X" group="int" mnem="orcx" opcode="7c000338" sub-form="S-A-B-Rc" />
<insn desc="OR Immediate" form="D" group="int" mnem="ori" opcode="60000000" sub-form="S-A-UIMM" />
<insn desc="OR Immediate Shifted" form="D" group="int" mnem="oris" opcode="64000000" sub-form="S-A-UIMM" />
<insn desc="Rotate Left Doubleword then Clear Left" form="MDS" group="int" mnem="rldclx" opcode="78000010" sub-form="S-A-B-MB-ME-Rc" />
<insn desc="Rotate Left Doubleword then Clear Right" form="MDS" group="int" mnem="rldcrx" opcode="78000012" sub-form="S-A-B-MB-ME-Rc" />
<insn desc="Rotate Left Doubleword Immediate then Clear" form="MDSH" group="int" mnem="rldicx" opcode="78000008" sub-form="S-A-SH-MB-ME-Rc" />
<insn desc="Rotate Left Doubleword Immediate then Clear Left" form="MDSH" group="int" mnem="rldiclx" opcode="78000000" sub-form="S-A-SH-MB-ME-Rc" />
<insn desc="Rotate Left Doubleword Immediate then Clear Right" form="MDSH" group="int" mnem="rldicrx" opcode="78000004" sub-form="S-A-SH-MB-ME-Rc" />
<insn desc="Rotate Left Doubleword Immediate then Mask Insert" form="MDSH" group="int" mnem="rldimix" opcode="7800000C" sub-form="S-A-SH-MB-ME-Rc" />
<insn desc="Rotate Left Word Immediate then Mask Insert" form="M" group="int" mnem="rlwimix" opcode="50000000" sub-form="S-A-SH-MB-ME-Rc" />
<insn desc="Rotate Left Word Immediate then AND with Mask" form="M" group="int" mnem="rlwinmx" opcode="54000000" sub-form="S-A-SH-MB-ME-Rc" />
<insn desc="Rotate Left Word then AND with Mask" form="M" group="int" mnem="rlwnmx" opcode="5c000000" sub-form="S-A-SH-MB-ME-Rc" />
<insn desc="System Call" form="SC" group="int" mnem="sc" opcode="44000002" sub-form="sc" />
<insn desc="Shift Left Doubleword" form="X" group="int" mnem="sldx" opcode="7c000036" sub-form="S-A-B-Rc" />
<insn desc="Shift Left Word" form="X" group="int" mnem="slwx" opcode="7c000030" sub-form="S-A-B-Rc" />
<insn desc="Shift Right Algebraic Doubleword" form="X" group="int" mnem="sradx" opcode="7c000634" sub-form="S-A-B-Rc" />
<insn desc="Shift Right Algebraic Doubleword Immediate" form="XS" group="int" mnem="sradix" opcode="7c000674" sub-form="S-A-SH-Rc" />
<insn desc="Shift Right Algebraic Word" form="X" group="int" mnem="srawx" opcode="7c000630" sub-form="S-A-B-Rc" />
<insn desc="Shift Right Algebraic Word Immediate" form="X" group="int" mnem="srawix" opcode="7c000670" sub-form="S-A-SH-Rc" />
<insn desc="Shift Right Doubleword" form="X" group="int" mnem="srdx" opcode="7c000436" sub-form="S-A-B-Rc" />
<insn desc="Shift Right Word" form="X" group="int" mnem="srwx" opcode="7c000430" sub-form="S-A-B-Rc" />
<insn desc="Store Byte" form="D" group="int" mnem="stb" opcode="98000000" sub-form="S-A-d" />
<insn desc="Store Byte with Update" form="D" group="int" mnem="stbu" opcode="9c000000" sub-form="S-A-d" />
<insn desc="Store Byte with Update Indexed" form="X" group="int" mnem="stbux" opcode="7c0001ee" sub-form="S-A-B" />
<insn desc="Store Byte Indexed" form="X" group="int" mnem="stbx" opcode="7c0001ae" sub-form="S-A-B" />
<insn desc="Store Doubleword" form="DS" group="int" mnem="std" opcode="f8000000" sub-form="S-A-d" />
<insn desc="Store Doubleword Byte-Reverse Indexed" form="X" group="int" mnem="stdbrx" opcode="7c000528" sub-form="S-A-B" />
<insn desc="Store Doubleword Conditional Indexed" form="X" group="int" mnem="stdcx" opcode="7c0001ad" sub-form="S-A-B-1" />
<insn desc="Store Doubleword with Update" form="DS" group="int" mnem="stdu" opcode="f8000001" sub-form="S-A-d" />
<insn desc="Store Doubleword with Update Indexed" form="X" group="int" mnem="stdux" opcode="7c00016a" sub-form="S-A-B" />
<insn desc="Store Doubleword Indexed" form="X" group="int" mnem="stdx" opcode="7c00012a" sub-form="S-A-B" />
<insn desc="Store Floating-Point Double" form="D" group="fp" mnem="stfd" opcode="d8000000" sub-form="S-A-d" />
<insn desc="Store Floating-Point Double with Update" form="D" group="fp" mnem="stfdu" opcode="dc000000" sub-form="S-A-d" />
<insn desc="Store Floating-Point Double with Update Indexed" form="X" group="fp" mnem="stfdux" opcode="7c0005ee" sub-form="S-A-B" />
<insn desc="Store Floating-Point Double Indexed" form="X" group="fp" mnem="stfdx" opcode="7c0005ae" sub-form="S-A-B" />
<insn desc="Store Floating-Point as Integer Word Indexed" form="X" group="fp" mnem="stfiwx" opcode="7c0007ae" sub-form="S-A-B" />
<insn desc="Store Floating-Point Single" form="D" group="fp" mnem="stfs" opcode="d0000000" sub-form="S-A-d" />
<insn desc="Store Floating-Point Single with Update" form="D" group="fp" mnem="stfsu" opcode="d4000000" sub-form="S-A-d" />
<insn desc="Store Floating-Point Single with Update Indexed" form="X" group="fp" mnem="stfsux" opcode="7c00056e" sub-form="S-A-B" />
<insn desc="Store Floating-Point Single Indexed" form="X" group="fp" mnem="stfsx" opcode="7c00052e" sub-form="S-A-B" />
<insn desc="Store Half Word" form="D" group="int" mnem="sth" opcode="b0000000" sub-form="S-A-d" />
<insn desc="Store Half Word Byte-Reverse Indexed" form="X" group="int" mnem="sthbrx" opcode="7c00072c" sub-form="S-A-B" />
<insn desc="Store Half Word with Update" form="D" group="int" mnem="sthu" opcode="b4000000" sub-form="S-A-d" />
<insn desc="Store Half Word with Update Indexed" form="X" group="int" mnem="sthux" opcode="7c00036e" sub-form="S-A-B" />
<insn desc="Store Half Word Indexed" form="X" group="int" mnem="sthx" opcode="7c00032e" sub-form="S-A-B" />
<insn desc="Store Multiple Word" form="D" group="int" mnem="stmw" opcode="bc000000" sub-form="S-A-d" />
<insn desc="Store String Word Immediate" form="X" group="int" mnem="stswi" opcode="7c0005aa" sub-form="S-A-NB" />
<insn desc="Store String Word Indexed" form="X" group="int" mnem="stswx" opcode="7c00052a" sub-form="S-A-B" />
<insn desc="Store Vector Element Byte Indexed" form="X" group="vmx" mnem="stvebx" opcode="7c00010e" sub-form="S-A-B" />
<insn desc="Store Vector Element Half Word Indexed" form="X" group="vmx" mnem="stvehx" opcode="7c00014e" sub-form="S-A-B" />
<insn desc="Store Vector Element Word Indexed" form="X" group="vmx" mnem="stvewx" opcode="7c00018e" sub-form="S-A-B" />
<insn desc="Store Vector Element Word Indexed 128" form="VX128_1" group="vmx" mnem="stvewx128" opcode="10000183" sub-form="S-A-B" />
<insn desc="Store Vector Indexed" form="X" group="vmx" mnem="stvx" opcode="7c0001ce" sub-form="S-A-B" />
<insn desc="Store Vector Indexed 128" form="VX128_1" group="vmx" mnem="stvx128" opcode="100001c3" sub-form="S-A-B" />
<insn desc="Store Vector Indexed LRU" form="X" group="vmx" mnem="stvxl" opcode="7c0003ce" sub-form="S-A-B" />
<insn desc="Store Vector Indexed LRU 128" form="VX128_1" group="vmx" mnem="stvxl128" opcode="100003c3" sub-form="S-A-B" />
<insn desc="Store Vector Left Indexed" form="X" group="vmx" mnem="stvlx" opcode="7c00050e" sub-form="S-A-B" />
<insn desc="Store Vector Left Indexed 128" form="VX128_1" group="vmx" mnem="stvlx128" opcode="10000503" sub-form="S-A-B" />
<insn desc="Store Vector Left Indexed LRU" form="X" group="vmx" mnem="stvlxl" opcode="7c00070e" sub-form="S-A-B" />
<insn desc="Store Vector Left Indexed LRU 128" form="VX128_1" group="vmx" mnem="stvlxl128" opcode="10000703" sub-form="S-A-B" />
<insn desc="Store Vector Right Indexed" form="X" group="vmx" mnem="stvrx" opcode="7c00054e" sub-form="S-A-B" />
<insn desc="Store Vector Right Indexed 128" form="VX128_1" group="vmx" mnem="stvrx128" opcode="10000543" sub-form="S-A-B" />
<insn desc="Store Vector Right Indexed LRU" form="X" group="vmx" mnem="stvrxl" opcode="7c00074e" sub-form="S-A-B" />
<insn desc="Store Vector Right Indexed LRU 128" form="VX128_1" group="vmx" mnem="stvrxl128" opcode="10000743" sub-form="S-A-B" />
<insn desc="Store Word" form="D" group="int" mnem="stw" opcode="90000000" sub-form="S-A-d" />
<insn desc="Store Word Byte-Reverse Indexed" form="X" group="int" mnem="stwbrx" opcode="7c00052c" sub-form="S-A-B" />
<insn desc="Store Word Conditional Indexed" form="X" group="int" mnem="stwcx" opcode="7c00012d" sub-form="S-A-B-1" />
<insn desc="Store Word with Update" form="D" group="int" mnem="stwu" opcode="94000000" sub-form="S-A-d" />
<insn desc="Store Word with Update Indexed" form="X" group="int" mnem="stwux" opcode="7c00016e" sub-form="S-A-B" />
<insn desc="Store Word Indexed" form="X" group="int" mnem="stwx" opcode="7c00012e" sub-form="S-A-B" />
<insn desc="Subtract From" form="XO" group="int" mnem="subfx" opcode="7c000050" sub-form="D-A-B-OE-Rc" />
<insn desc="Subtract From Carrying" form="XO" group="int" mnem="subfcx" opcode="7c000010" sub-form="D-A-B-OE-Rc" />
<insn desc="Subtract From Extended" form="XO" group="int" mnem="subfex" opcode="7c000110" sub-form="D-A-B-OE-Rc" />
<insn desc="Subtract From Immediate Carrying" form="D" group="int" mnem="subficx" opcode="20000000" sub-form="D-A-SIMM" />
<insn desc="Subtract From Minus One Extended" form="XO" group="int" mnem="subfmex" opcode="7c0001d0" sub-form="D-A-0-OE-Rc" />
<insn desc="Subtract From Zero Extended" form="XO" group="int" mnem="subfzex" opcode="7c000190" sub-form="D-A-0-OE-Rc" />
<insn desc="Synchronize" form="X" group="int" mnem="sync" opcode="7c0004ac" sub-form="0-0-0" />
<insn desc="Trap Doubleword" form="X" group="int" mnem="td" opcode="7c000088" sub-form="TO-A-B" />
<insn desc="Trap Doubleword Immediate" form="D" group="int" mnem="tdi" opcode="08000000" sub-form="TO-A-SIMM" />
<insn desc="Trap Word" form="X" group="int" mnem="tw" opcode="7c000008" sub-form="TO-A-B" />
<insn desc="Trap Word Immediate" form="D" group="int" mnem="twi" opcode="0c000000" sub-form="TO-A-SIMM" />
<insn desc="XOR" form="X" group="int" mnem="xorx" opcode="7c000278" sub-form="S-A-B-Rc" />
<insn desc="XOR Immediate" form="D" group="int" mnem="xori" opcode="68000000" sub-form="S-A-UIMM" />
<insn desc="XOR Immediate Shifted" form="D" group="int" mnem="xoris" opcode="6c000000" sub-form="S-A-UIMM" />
</ppc-isa>
<ppc-isa name="vmx">
<insn mnem="vaddcuw" opcode="10000180" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Carryout Unsigned Word" />
<insn mnem="vaddfp" opcode="1000000A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Floating Point" />
<insn mnem="vaddsbs" opcode="10000300" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Signed Byte Saturate" />
<insn mnem="vaddshs" opcode="10000340" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Signed Half Word Saturate" />
<insn mnem="vaddsws" opcode="10000380" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Signed Word Saturate" />
<insn mnem="vaddubm" opcode="10000000" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Unsigned Byte Modulo" />
<insn mnem="vaddubs" opcode="10000200" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Unsigned Byte Saturate" />
<insn mnem="vadduhm" opcode="10000040" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Unsigned Half Word Modulo" />
<insn mnem="vadduhs" opcode="10000240" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Unsigned Half Word Saturate" />
<insn mnem="vadduwm" opcode="10000080" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Unsigned Word Modulo" />
<insn mnem="vadduws" opcode="10000280" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Add Unsigned Word Saturate" />
<insn mnem="vand" opcode="10000404" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Logical AND" />
<insn mnem="vandc" opcode="10000444" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Logical AND with Complement" />
<insn mnem="vavgsb" opcode="10000502" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Average Signed Byte" />
<insn mnem="vavgsh" opcode="10000542" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Average Signed Half Word" />
<insn mnem="vavgsw" opcode="10000582" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Average Signed Word" />
<insn mnem="vavgub" opcode="10000402" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Average Unsigned Byte" />
<insn mnem="vavguh" opcode="10000442" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Average Unsigned Half Word" />
<insn mnem="vavguw" opcode="10000482" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Average Unsigned Word" />
<insn mnem="vcfsx" opcode="1000034A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Convert from Signed Fixed-Point Word" />
<insn mnem="vcfux" opcode="1000030A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Convert from Unsigned Fixed-Point Word" />
<insn mnem="vctsxs" opcode="100003CA" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Convert to Signed Fixed-Point Word Saturate" />
<insn mnem="vctuxs" opcode="1000038A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Convert to Unsigned Fixed-Point Word Saturate" />
<insn mnem="vexptefp" opcode="1000018A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector 2 Raised to the Exponent Estimate Floating Point" />
<insn mnem="vlogefp" opcode="100001CA" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Log2 Estimate Floating Point" />
<insn mnem="vmaxfp" opcode="1000040A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Maximum Floating Point" />
<insn mnem="vmaxsb" opcode="10000102" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Maximum Signed Byte" />
<insn mnem="vmaxsh" opcode="10000142" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Maximum Signed Half Word" />
<insn mnem="vmaxsw" opcode="10000182" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Maximum Signed Word" />
<insn mnem="vmaxub" opcode="10000002" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Maximum Unsigned Byte" />
<insn mnem="vmaxuh" opcode="10000042" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Maximum Unsigned Half Word" />
<insn mnem="vmaxuw" opcode="10000082" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Maximum Unsigned Word" />
<insn mnem="vminfp" opcode="1000044A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Minimum Floating Point" />
<insn mnem="vminsb" opcode="10000302" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Minimum Signed Byte" />
<insn mnem="vminsh" opcode="10000342" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Minimum Signed Half Word" />
<insn mnem="vminsw" opcode="10000382" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Minimum Signed Word" />
<insn mnem="vminub" opcode="10000202" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Minimum Unsigned Byte" />
<insn mnem="vminuh" opcode="10000242" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Minimum Unsigned Half Word" />
<insn mnem="vminuw" opcode="10000282" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Minimum Unsigned Word" />
<insn mnem="vmrghb" opcode="1000000C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Merge High Byte" />
<insn mnem="vmrghh" opcode="1000004C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Merge High Half Word" />
<insn mnem="vmrghw" opcode="1000008C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Merge High Word" />
<insn mnem="vmrglb" opcode="1000010C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Merge Low Byte" />
<insn mnem="vmrglh" opcode="1000014C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Merge Low Half Word" />
<insn mnem="vmrglw" opcode="1000018C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Merge Low Word" />
<insn mnem="vmulesb" opcode="10000308" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Multiply Even Signed Byte" />
<insn mnem="vmulesh" opcode="10000348" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Multiply Even Signed Half Word" />
<insn mnem="vmuleub" opcode="10000208" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Multiply Even Unsigned Byte" />
<insn mnem="vmuleuh" opcode="10000248" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Multiply Even Unsigned Half Word" />
<insn mnem="vmulosb" opcode="10000108" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Multiply Odd Signed Byte" />
<insn mnem="vmulosh" opcode="10000148" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Multiply Odd Signed Half Word" />
<insn mnem="vmuloub" opcode="10000008" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Multiply Odd Unsigned Byte" />
<insn mnem="vmulouh" opcode="10000048" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Multiply Odd Unsigned Half Word" />
<insn mnem="vnor" opcode="10000504" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Logical NOR" />
<insn mnem="vor" opcode="10000484" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Logical OR" />
<insn mnem="vpkpx" opcode="1000030E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Pack Pixel" />
<insn mnem="vpkshss" opcode="1000018E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Pack Signed Half Word Signed Saturate" />
<insn mnem="vpkshus" opcode="1000010E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Pack Signed Half Word Unsigned Saturate" />
<insn mnem="vpkswss" opcode="100001CE" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Pack Signed Word Signed Saturate" />
<insn mnem="vpkswus" opcode="1000014E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Pack Signed Word Unsigned Saturate" />
<insn mnem="vpkuhum" opcode="1000000E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Pack Unsigned Half Word Unsigned Modulo" />
<insn mnem="vpkuhus" opcode="1000008E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Pack Unsigned Half Word Unsigned Saturate" />
<insn mnem="vpkuwum" opcode="1000004E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Pack Unsigned Word Unsigned Modulo" />
<insn mnem="vpkuwus" opcode="100000CE" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Pack Unsigned Word Unsigned Saturate" />
<insn mnem="vrefp" opcode="1000010A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Reciprocal Estimate Floating Point" />
<insn mnem="vrfim" opcode="100002CA" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Round to Floating-Point Integer toward -Infinity" />
<insn mnem="vrfin" opcode="1000020A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Round to Floating-Point Integer Nearest" />
<insn mnem="vrfip" opcode="1000028A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Round to Floating-Point Integer toward +Infinity" />
<insn mnem="vrfiz" opcode="1000024A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Round to Floating-Point Integer toward Zero" />
<insn mnem="vrlb" opcode="10000004" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Rotate Left Integer Byte" />
<insn mnem="vrlh" opcode="10000044" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Rotate Left Integer Half Word" />
<insn mnem="vrlw" opcode="10000084" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Rotate Left Integer Word" />
<insn mnem="vrsqrtefp" opcode="1000014A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Reciprocal Square Root Estimate Floating Point" />
<insn mnem="vsl" opcode="100001C4" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Left" />
<insn mnem="vslb" opcode="10000104" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Left Integer Byte" />
<insn mnem="vslh" opcode="10000144" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Left Integer Half Word" />
<insn mnem="vslo" opcode="1000040C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Left by Octet" />
<insn mnem="vslw" opcode="10000184" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Left Integer Word" />
<insn mnem="vspltb" opcode="1000020C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Splat Byte" />
<insn mnem="vsplth" opcode="1000024C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Splat Half Word" />
<insn mnem="vspltisb" opcode="1000030C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Splat Immediate Signed Byte" />
<insn mnem="vspltish" opcode="1000034C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Splat Immediate Signed Half Word" />
<insn mnem="vspltisw" opcode="1000038C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Splat Immediate Signed Word" />
<insn mnem="vspltw" opcode="1000028C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Splat Word" />
<insn mnem="vsr" opcode="100002C4" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Right" />
<insn mnem="vsrab" opcode="10000304" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Right Algebraic Byte" />
<insn mnem="vsrah" opcode="10000344" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Right Algebraic Half Word" />
<insn mnem="vsraw" opcode="10000384" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Right Algebraic Word" />
<insn mnem="vsrb" opcode="10000204" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Right Byte" />
<insn mnem="vsrh" opcode="10000244" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Right Half Word" />
<insn mnem="vsro" opcode="1000044C" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Right Octet" />
<insn mnem="vsrw" opcode="10000284" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Shift Right Word" />
<insn mnem="vsubcuw" opcode="10000580" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Carryout Unsigned Word" />
<insn mnem="vsubfp" opcode="1000004A" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Floating Point" />
<insn mnem="vsubsbs" opcode="10000700" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Signed Byte Saturate" />
<insn mnem="vsubshs" opcode="10000740" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Signed Half Word Saturate" />
<insn mnem="vsubsws" opcode="10000780" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Signed Word Saturate" />
<insn mnem="vsububm" opcode="10000400" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Unsigned Byte Modulo" />
<insn mnem="vsububs" opcode="10000600" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Unsigned Byte Saturate" />
<insn mnem="vsubuhm" opcode="10000440" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Unsigned Half Word Modulo" />
<insn mnem="vsubuhs" opcode="10000640" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Unsigned Half Word Saturate" />
<insn mnem="vsubuwm" opcode="10000480" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Unsigned Word Modulo" />
<insn mnem="vsubuws" opcode="10000680" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Subtract Unsigned Word Saturate" />
<insn mnem="vsumsws" opcode="10000788" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Sum Across Signed Word Saturate" />
<insn mnem="vsum2sws" opcode="10000688" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Sum Across Partial (1/2) Signed Word Saturate" />
<insn mnem="vsum4sbs" opcode="10000708" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Sum Across Partial (1/4) Signed Byte Saturate" />
<insn mnem="vsum4shs" opcode="10000648" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Sum Across Partial (1/4) Signed Half Word Saturate" />
<insn mnem="vsum4ubs" opcode="10000608" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Sum Across Partial (1/4) Unsigned Byte Saturate" />
<insn mnem="vupkhpx" opcode="1000034E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Unpack High Pixel" />
<insn mnem="vupkhsb" opcode="1000020E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Unpack High Signed Byte" />
<insn mnem="vupkhsh" opcode="1000024E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Unpack High Signed Half Word" />
<insn mnem="vupklpx" opcode="100003CE" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Unpack Low Pixel" />
<insn mnem="vupklsb" opcode="1000028E" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Unpack Low Signed Byte" />
<insn mnem="vupklsh" opcode="100002CE" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Unpack Low Signed Half Word" />
<insn mnem="vxor" opcode="100004C4" form="VX" group="vmx" sub-form="D-A-B" desc="Vector Logical XOR" />
<insn mnem="vcmpbfp" opcode="100003C6" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Bounds Floating Point" />
<insn mnem="vcmpeqfp" opcode="100000C6" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Equal-to Floating Point" />
<insn mnem="vcmpequb" opcode="10000006" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Equal-to Unsigned Byte" />
<insn mnem="vcmpequh" opcode="10000046" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Equal-to Unsigned Half Word" />
<insn mnem="vcmpequw" opcode="10000086" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Equal-to Unsigned Word" />
<insn mnem="vcmpgefp" opcode="100001C6" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Greater-Than-or-Equal-to Floating Point" />
<insn mnem="vcmpgtfp" opcode="100002C6" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Greater-Than Floating Point" />
<insn mnem="vcmpgtsb" opcode="10000306" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Greater-Than Signed Byte" />
<insn mnem="vcmpgtsh" opcode="10000346" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Greater-Than Signed Half Word" />
<insn mnem="vcmpgtsw" opcode="10000386" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Greater-Than Signed Word" />
<insn mnem="vcmpgtub" opcode="10000206" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Greater-Than Unsigned Byte" />
<insn mnem="vcmpgtuh" opcode="10000246" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Greater-Than Unsigned Half Word" />
<insn mnem="vcmpgtuw" opcode="10000286" form="VC" group="vmx" sub-form="D-A-B" desc="Vector Compare Greater-Than Unsigned Word" />
<insn mnem="vmaddfp" opcode="1000002E" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Multiply-Add Floating Point" />
<insn mnem="vmhaddshs" opcode="10000020" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Multiply-High and Add Signed Signed Half Word Saturate" />
<insn mnem="vmhraddshs" opcode="10000021" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Multiply-High Round and Add Signed Signed Half Word Saturate" />
<insn mnem="vmladduhm" opcode="10000022" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Multiply-Low and Add Unsigned Half Word Modulo" />
<insn mnem="vmsummbm" opcode="10000025" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Multiply-Sum Mixed-Sign Byte Modulo" />
<insn mnem="vmsumshm" opcode="10000028" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Multiply-Sum Signed Half Word Modulo" />
<insn mnem="vmsumshs" opcode="10000029" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Multiply-Sum Signed Half Word Saturate" />
<insn mnem="vmsumubm" opcode="10000024" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Multiply-Sum Unsigned Byte Modulo" />
<insn mnem="vmsumuhm" opcode="10000026" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Multiply-Sum Unsigned Half Word Modulo" />
<insn mnem="vmsumuhs" opcode="10000027" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Multiply-Sum Unsigned Half Word Saturate" />
<insn mnem="vnmsubfp" opcode="1000002F" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Negative Multiply-Subtract Floating Point" />
<insn mnem="vperm" opcode="1000002B" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Permute" />
<insn mnem="vsel" opcode="1000002A" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Conditional Select" />
<insn mnem="vsldoi" opcode="1000002C" form="VA" group="vmx" sub-form="D-A-B-C" desc="Vector Shift Left Double by Octet Immediate" />
<insn mnem="vsldoi128" opcode="10000010" form="VX128_5" group="vmx" sub-form="D-A-B-I" desc="Vector128 Shift Left Double by Octet Immediate" />
<insn mnem="vperm128" opcode="14000000" form="VX128_2" group="vmx" sub-form="D-A-B-C" desc="Vector128 Permute" />
<insn mnem="vaddfp128" opcode="14000010" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Add Floating Point" />
<insn mnem="vsubfp128" opcode="14000050" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Subtract Floating Point" />
<insn mnem="vmulfp128" opcode="14000090" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Multiply Floating-Point" />
<insn mnem="vmaddfp128" opcode="140000D0" form="VX128" group="vmx" sub-form="D-A-D-B" desc="Vector128 Multiply Add Floating Point" />
<insn mnem="vmaddcfp128" opcode="14000110" form="VX128" group="vmx" sub-form="D-A-D-B" desc="Vector128 Multiply Add Floating Point" />
<insn mnem="vnmsubfp128" opcode="14000150" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Negative Multiply-Subtract Floating Point" />
<insn mnem="vmsum3fp128" opcode="14000190" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Multiply Sum 3-way Floating Point" />
<insn mnem="vmsum4fp128" opcode="140001D0" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Multiply Sum 4-way Floating-Point" />
<insn mnem="vpkshss128" opcode="14000200" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Pack Signed Half Word Signed Saturate" />
<insn mnem="vand128" opcode="14000210" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Logical AND" />
<insn mnem="vpkshus128" opcode="14000240" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Pack Signed Half Word Unsigned Saturate" />
<insn mnem="vandc128" opcode="14000250" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Logical AND with Complement" />
<insn mnem="vpkswss128" opcode="14000280" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Pack Signed Word Signed Saturate" />
<insn mnem="vnor128" opcode="14000290" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Logical NOR" />
<insn mnem="vpkswus128" opcode="140002C0" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Pack Signed Word Unsigned Saturate" />
<insn mnem="vor128" opcode="140002D0" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Logical OR" />
<insn mnem="vpkuhum128" opcode="14000300" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Pack Unsigned Half Word Unsigned Modulo" />
<insn mnem="vxor128" opcode="14000310" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Logical XOR" />
<insn mnem="vpkuhus128" opcode="14000340" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Pack Unsigned Half Word Unsigned Saturate" />
<insn mnem="vsel128" opcode="14000350" form="VX128" group="vmx" sub-form="D-A-B-D" desc="Vector128 Conditional Select" />
<insn mnem="vpkuwum128" opcode="14000380" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Pack Unsigned Word Unsigned Modulo" />
<insn mnem="vslo128" opcode="14000390" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Shift Left Octet" />
<insn mnem="vpkuwus128" opcode="140003C0" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Pack Unsigned Word Unsigned Saturate" />
<insn mnem="vsro128" opcode="140003D0" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Shift Right Octet" />
<insn mnem="vpermwi128" opcode="18000210" form="VX128_P" group="vmx" sub-form="D-A-B-C" desc="Vector128 Permutate Word Immediate" />
<insn mnem="vcfpsxws128" opcode="18000230" form="VX128_3" group="vmx" sub-form="D-B-SIMM" desc="Vector128 Convert From Floating-Point to Signed Fixed-Point Word Saturate" />
<insn mnem="vcfpuxws128" opcode="18000270" form="VX128_3" group="vmx" sub-form="D-B-UIMM" desc="Vector128 Convert From Floating-Point to Unsigned Fixed-Point Word Saturate" />
<insn mnem="vcsxwfp128" opcode="180002B0" form="VX128_3" group="vmx" sub-form="D-B-SIMM" desc="Vector128 Convert From Signed Fixed-Point Word to Floating-Point" />
<insn mnem="vcuxwfp128" opcode="180002F0" form="VX128_3" group="vmx" sub-form="D-B-SIMM" desc="Vector128 Convert From Unsigned Fixed-Point Word to Floating-Point" />
<insn mnem="vrfim128" opcode="18000330" form="VX128_3" group="vmx" sub-form="D-B" desc="Vector128 Round to Floating-Point Integer toward -Infinity" />
<insn mnem="vrfin128" opcode="18000370" form="VX128_3" group="vmx" sub-form="D-B" desc="Vector128 Round to Floating-Point Integer Nearest" />
<insn mnem="vrfip128" opcode="180003B0" form="VX128_3" group="vmx" sub-form="D-B" desc="Vector128 Round to Floating-Point Integer toward +Infinity" />
<insn mnem="vrfiz128" opcode="180003F0" form="VX128_3" group="vmx" sub-form="D-B" desc="Vector128 Round to Floating-Point Integer toward Zero" />
<insn mnem="vpkd3d128" opcode="18000610" form="VX128_4" group="vmx" sub-form="D-B" desc="Vector128 Pack D3Dtype, Rotate Left Immediate and Mask Insert" />
<insn mnem="vrefp128" opcode="18000630" form="VX128_3" group="vmx" sub-form="D-B" desc="Vector128 Reciprocal Estimate Floating Point" />
<insn mnem="vrsqrtefp128" opcode="18000670" form="VX128_3" group="vmx" sub-form="D-B" desc="Vector128 Reciprocal Square Root Estimate Floating Point" />
<insn mnem="vexptefp128" opcode="180006B0" form="VX128_3" group="vmx" sub-form="D-B" desc="Vector128 Log2 Estimate Floating Point" />
<insn mnem="vlogefp128" opcode="180006F0" form="VX128_3" group="vmx" sub-form="D-B" desc="Vector128 Log2 Estimate Floating Point" />
<insn mnem="vrlimi128" opcode="18000710" form="VX128_4" group="vmx" sub-form="D-B-UIMM" desc="Vector128 Rotate Left Immediate and Mask Insert" />
<insn mnem="vspltw128" opcode="18000730" form="VX128_3" group="vmx" sub-form="D-B-SIMM" desc="Vector128 Splat Word" />
<insn mnem="vspltisw128" opcode="18000770" form="VX128_3" group="vmx" sub-form="D-B-SIMM" desc="Vector128 Splat Immediate Signed Word" />
<insn mnem="vupkd3d128" opcode="180007F0" form="VX128_3" group="vmx" sub-form="D-B-SIMM" desc="Vector128 Unpack D3Dtype" />
<insn mnem="vcmpeqfp128" opcode="18000000" form="VX128_R" group="vmx" sub-form="D-A-B" desc="Vector128 Compare Equal-to Floating Point" />
<insn mnem="vrlw128" opcode="18000050" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Rotate Left Word" />
<insn mnem="vcmpgefp128" opcode="18000080" form="VX128_R" group="vmx" sub-form="D-A-B" desc="Vector128 Compare Greater-Than-or-Equal-to Floating Point" />
<insn mnem="vslw128" opcode="180000D0" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Shift Left Integer Word" />
<insn mnem="vcmpgtfp128" opcode="18000100" form="VX128_R" group="vmx" sub-form="D-A-B" desc="Vector128 Compare Greater-Than Floating-Point" />
<insn mnem="vsraw128" opcode="18000150" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Shift Right Arithmetic Word" />
<insn mnem="vcmpbfp128" opcode="18000180" form="VX128_R" group="vmx" sub-form="D-A-B" desc="Vector128 Compare Bounds Floating Point" />
<insn mnem="vsrw128" opcode="180001D0" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Shift Right Word" />
<insn mnem="vcmpequw128" opcode="18000200" form="VX128_R" group="vmx" sub-form="D-A-B" desc="Vector128 Compare Equal-to Unsigned Word" />
<insn mnem="vmaxfp128" opcode="18000280" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Maximum Floating Point" />
<insn mnem="vminfp128" opcode="180002C0" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Minimum Floating Point" />
<insn mnem="vmrghw128" opcode="18000300" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Merge High Word" />
<insn mnem="vmrglw128" opcode="18000340" form="VX128" group="vmx" sub-form="D-A-B" desc="Vector128 Merge Low Word" />
<insn mnem="vupkhsb128" opcode="18000380" form="VX128" group="vmx" sub-form="D-B" desc="Vector128 Unpack High Signed Byte" />
<insn mnem="vupklsb128" opcode="180003C0" form="VX128" group="vmx" sub-form="D-B" desc="Vector128 Unpack Low Signed Byte" />
</ppc-isa>
</root>

345
tools/ppc-table-gen.py Normal file
View File

@ -0,0 +1,345 @@
#!/usr/bin/env python
# Copyright 2015 Ben Vanik & shuffle2. All Rights Reserved.
"""PPC instruction table generator.
Generates various headers/sources for looking up and handling PPC instructions.
This is based on shuffle2's PPC generator:
https://gist.github.com/shuffle2/10015968
"""
__author__ = 'ben.vanik@gmail.com (Ben Vanik)'
import os
import sys
from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring, dump
self_path = os.path.dirname(os.path.abspath(__file__))
class Insn:
pass
def bit_extract(x, leftmost, rightmost):
return (x >> (32 - 1 - rightmost)) & ((1 << (rightmost - leftmost + 1)) - 1)
extended_opcode_bits = {
'X': [(21, 30)],
'XL': [(21, 30)],
'XFX': [(21, 30)],
'XFL': [(21, 30)],
'VX': [(21, 31)],
'VX128': [(22, 25), (27, 27)],
'VX128_1': [(21, 27), (30, 31)],
'VX128_2': [(22, 22), (27, 27)],
'VX128_3': [(21, 27)],
'VX128_4': [(21, 23), (26, 27)],
'VX128_5': [(27, 27)],
'VX128_R': [(22, 24), (27, 27)],
'VX128_P': [(21, 22), (26, 27)],
'VC': [(22, 31)],
'VA': [(26, 31)],
'XO': [(22, 30)],
'XW': [(25, 30)],
'A': [(26, 30)],
'DS': [(30, 31)],
'MD': [(27, 30)],
'MDS': [(27, 30)],
'MDSH': [(27, 29)],
'XS': [(21, 29)],
'DCBZ': [(6, 10), (21, 30)], # like X
}
def opcode_primary(insn):
return bit_extract(insn, 0, 5)
def opcode_extended(insn, form):
if form in extended_opcode_bits:
parts = extended_opcode_bits[form]
value = 0
shift = 0
for part in parts:
shift = max(shift, part[1])
for part in parts:
part_value = bit_extract(insn, part[0], part[1])
value = value | (part_value << (shift - part[1]))
return value
else:
return -1
def parse_insns(filename):
root = ElementTree(file = filename)
insns = []
# Convert to python types
for e in root.findall('.//insn'):
i = Insn()
i.desc = e.attrib['desc']
i.form = e.attrib['form']
i.group = e.attrib['group']
i.mnem = e.attrib['mnem']
i.opcode = int(e.attrib['opcode'], 16)
i.subform = e.attrib['sub-form']
i.op_primary = opcode_primary(i.opcode)
i.op_extended = opcode_extended(i.opcode, i.form)
insns.append(i)
return insns
def c_mnem(x):
return x.replace('.', 'x')
def c_subform(x):
x = x.replace('-', '_')
if x[0] >= '0' and x[0] <= '9':
x = '_' + x
return x
def c_group(x):
return 'k' + x[0].upper() + x[1:]
def c_bool(x):
return 'true' if x else 'false'
def generate_opcodes(insns):
l = []
TAB = ' ' * 2
def w0(x): l.append(x)
def w1(x): w0(TAB * 1 + x)
def w2(x): w0(TAB * 2 + x)
def w3(x): w0(TAB * 3 + x)
w0('// This code was autogenerated by %s. Do not modify!' % (sys.argv[0]))
w0('// clang-format off')
w0('#ifndef XENIA_CPU_PPC_PPC_OPCODE_H_')
w0('#define XENIA_CPU_PPC_PPC_OPCODE_H_')
w0('')
w0('#include <cstdint>')
w0('')
w0('namespace xe {')
w0('namespace cpu {')
w0('namespace ppc {')
w0('')
for i in insns:
i.mnem = c_mnem(i.mnem)
i.subform = c_subform(i.subform)
insns = sorted(insns, key = lambda i: i.mnem)
w0('// All PPC opcodes in the same order they appear in ppc_instr_table.h:')
w0('enum class PPCOpcode : uint32_t {')
for i in insns:
w1('%s,' % (i.mnem))
w1('kInvalid,')
w0('};')
w0('')
w0('} // namespace ppc')
w0('} // namespace cpu')
w0('} // namespace xe')
w0('')
w0('#endif // XENIA_CPU_PPC_PPC_OPCODE_H_')
w0('')
return '\n'.join(l)
def generate_table(insns):
l = []
TAB = ' ' * 2
def w0(x): l.append(x)
def w1(x): w0(TAB * 1 + x)
def w2(x): w0(TAB * 2 + x)
def w3(x): w0(TAB * 3 + x)
w0('// This code was autogenerated by %s. Do not modify!' % (sys.argv[0]))
w0('// clang-format off')
w0('#include <cstdint>')
w0('')
w0('#include "xenia/cpu/ppc/ppc_opcode.h"')
w0('#include "xenia/cpu/ppc/ppc_opcode_info.h"')
w0('')
w0('namespace xe {')
w0('namespace cpu {')
w0('namespace ppc {')
w0('')
for i in insns:
i.mnem = '"' + c_mnem(i.mnem) + '"'
i.form = c_group(i.form)
i.subform = c_subform(i.subform)
i.desc = '"' + i.desc + '"'
i.group = c_group(i.group)
mnem_len = len(max(insns, key = lambda i: len(i.mnem)).mnem)
form_len = len(max(insns, key = lambda i: len(i.form)).form)
subform_len = len(max(insns, key = lambda i: len(i.subform)).subform)
desc_len = len(max(insns, key = lambda i: len(i.desc)).desc)
group_len = len(max(insns, key = lambda i: len(i.group)).group)
insns = sorted(insns, key = lambda i: i.mnem)
w0('#define INSTRUCTION(opcode, mnem, form, subform, group, desc) \\')
w0(' {opcode, mnem, PPCOpcodeFormat::form, PPCOpcodeGroup::group, desc}')
w0('PPCOpcodeInfo ppc_opcode_table[] = {')
fmt = 'INSTRUCTION(' + ', '.join([
'0x%08x',
'%-' + str(mnem_len) + 's',
'%-' + str(form_len) + 's',
'%-' + str(subform_len) + 's',
'%-' + str(group_len) + 's',
'%-' + str(desc_len) + 's',
]) + '),'
for i in insns:
w1(fmt % (i.opcode, i.mnem, i.form, i.subform, i.group, i.desc))
w0('};')
w0('static_assert(sizeof(ppc_opcode_table) / sizeof(PPCOpcodeInfo) == static_cast<int>(PPCOpcode::kInvalid), "PPC table mismatch - rerun ppc-table-gen");')
w0('')
w0('const PPCOpcodeInfo& GetOpcodeInfo(PPCOpcode opcode) {')
w1('return ppc_opcode_table[static_cast<int>(opcode)];')
w0('}')
w0('')
w0('} // namespace ppc')
w0('} // namespace cpu')
w0('} // namespace xe')
w0('')
return '\n'.join(l)
def generate_lookup(insns):
l = []
TAB = ' ' * 2
def w0(x): l.append(x)
def w1(x): w0(TAB * 1 + x)
def w2(x): w0(TAB * 2 + x)
def w3(x): w0(TAB * 3 + x)
for i in insns:
i.mnem = c_mnem(i.mnem)
w0('// This code was autogenerated by %s. Do not modify!' % (sys.argv[0]))
w0('// clang-format off')
w0('#include <cstdint>')
w0('')
w0('#include "xenia/base/assert.h"')
w0('#include "xenia/cpu/ppc/ppc_opcode.h"')
w0('#include "xenia/cpu/ppc/ppc_opcode_info.h"')
w0('')
w0('namespace xe {')
w0('namespace cpu {')
w0('namespace ppc {')
w0('')
w0('constexpr uint32_t ExtractBits(uint32_t v, uint32_t a, uint32_t b) {')
w0(' return (v >> (32 - 1 - b)) & ((1 << (b - a + 1)) - 1);')
w0('}')
w0('')
w0('#define PPC_DECODER_MISS assert_always(); return PPCOpcode::kInvalid')
w0('#define PPC_DECODER_HIT(name) return PPCOpcode::name;')
w0('')
w0('PPCOpcode LookupOpcode(uint32_t code) {')
w1('switch (ExtractBits(code, 0, 5)) {')
subtables = {}
for i in sorted(insns, key = lambda i: i.op_primary):
if i.op_primary not in subtables: subtables[i.op_primary] = []
subtables[i.op_primary].append(i)
for pri in sorted(subtables.iterkeys()):
# all the extended encodings (which we care about) end with bit 30. So we want to
# do the rest of the seach by bitscanning left from bit 30. This is simulated
# in the C switch-statement by creating leafs for each extended opcode,
# sorted by bitlength shortest to longest.
if len(subtables[pri]) == 1:
for i in subtables[pri]:
# the primary opcode field fully identifies the opcode
w1('case %i: PPC_DECODER_HIT(%s);' % (i.op_primary, i.mnem))
continue
extract_groups = {}
for i in subtables[pri]:
form_parts = extended_opcode_bits[i.form]
shift = 0
for form_part in form_parts:
shift = max(shift, form_part[1])
extract_parts = []
for form_part in form_parts:
extract_parts.append('(ExtractBits(code, %s, %s) << %s)' % (form_part[0], form_part[1], shift - form_part[1]))
extract_expression = '|'.join(extract_parts)
if extract_expression not in extract_groups:
extract_groups[extract_expression] = (i.form, extract_expression, [])
extract_groups[extract_expression][2].append(i)
w1('case %i:' % (pri))
for extract_expression in sorted(extract_groups.iterkeys()):
(form, extract_expression, group_insns) = extract_groups[extract_expression]
bit_span_low = 31
bit_span_high = 0
form_parts = extended_opcode_bits[form]
for form_part in form_parts:
bit_span_low = min(bit_span_low, form_part[0])
bit_span_high = max(bit_span_high, form_part[1])
bit_count = bit_span_high - bit_span_low + 1
w2('switch (%s) {' % (extract_expression))
for i in sorted(group_insns, key=lambda i: i.op_extended):
w3('case 0b%s: PPC_DECODER_HIT(%s);' % (
('{:0'+str(bit_count)+'b}').format(i.op_extended),
i.mnem))
w2('}')
w2('PPC_DECODER_MISS;')
w1('default: PPC_DECODER_MISS;')
w1('}')
w0('}')
w0('')
w0('} // namespace ppc')
w0('} // namespace cpu')
w0('} // namespace xe')
w0('')
# from this we can see some tables have bits which can be used to determine extended opcoded size:
# primary opcode 31:
# 01... = 9 bits (XO form), else 10 bits (X/XFX forms)
# primary opcode 63:
# 1.... = 7 bits (A form), else 10 bits (X/XFL forms)
# primary opcode 4:
# does not have small bit range to determine size, but you can just use the
# low 7 bits in order to "guess" the opcode. if you assume no invalid
# encodings are input, only the sequence ...0001000 actually *needs* the upper
# bits in order to differentiate the opcode (0100001000 = ps_abs, 0010001000 = ps_nabs)
# otherwise, the low 7bits can be used as the determinant, and a second comparison
# can be used against the real length of bits to fully match the extended opcode
#
# this approach can be generalized for all primary opcodes with extended opcodes of varying lengths:
# compare bits of smallest length, fall through to comparing larger sizes until found or failure
# with the optional optimization of discarding further compares for extended opcodes which
# share top bits with any other extended opcode (at the price of failing to detect invalid opcodes)
return '\n'.join(l)
if __name__ == '__main__':
ppc_src_path = os.path.join(self_path, '..', 'src', 'xenia', 'cpu', 'ppc')
insns = parse_insns(os.path.join(self_path, 'ppc-instructions.xml'))
with open(os.path.join(ppc_src_path, 'ppc_opcode.h'), 'w') as f:
f.write(generate_opcodes(insns))
insns = parse_insns(os.path.join(self_path, 'ppc-instructions.xml'))
with open(os.path.join(ppc_src_path, 'ppc_opcode_table.cc'), 'w') as f:
f.write(generate_table(insns))
insns = parse_insns(os.path.join(self_path, 'ppc-instructions.xml'))
with open(os.path.join(ppc_src_path, 'ppc_opcode_lookup.cc'), 'w') as f:
f.write(generate_lookup(insns))