Simplifying disassembler. Much faster than before.

This commit is contained in:
Ben Vanik 2014-01-23 20:31:04 -08:00
parent f36e6cd820
commit 53b9ed5214
17 changed files with 1053 additions and 4864 deletions

View File

@ -25,6 +25,7 @@ which are only documented in a few places (like the gcc source code, etc).
* [PowerPC Vector PEM](https://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/C40E4C6133B31EE8872570B500791108/$file/vector_simd_pem_v_2.07c_26Oct2006_cell.pdf)
* [AltiVec PEM](http://cache.freescale.com/files/32bit/doc/ref_manual/ALTIVECPEM.pdf)
* [VMX128 Opcodes](http://biallas.net/doc/vmx128/vmx128.txt)
* [AltiVec Decoding](https://github.com/kakaroto/ps3ida/blob/master/plugins/PPCAltivec/src/main.cpp)
### x64

View File

@ -1,36 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef ALLOY_FRONTEND_PPC_PPC_DISASM_PRIVATE_H_
#define ALLOY_FRONTEND_PPC_PPC_DISASM_PRIVATE_H_
#include <alloy/frontend/ppc/ppc_disasm.h>
#include <alloy/frontend/ppc/ppc_instr.h>
namespace alloy {
namespace frontend {
namespace ppc {
#define XEDISASMR(name, opcode, format) int InstrDisasm_##name
#define XEREGISTERINSTR(name, opcode) \
RegisterInstrDisassemble(opcode, (InstrDisassembleFn)InstrDisasm_##name);
#define XEINSTRNOTIMPLEMENTED()
//#define XEINSTRNOTIMPLEMENTED XEASSERTALWAYS
} // namespace ppc
} // namespace frontend
} // namespace alloy
#endif // ALLOY_FRONTEND_PPC_PPC_DISASM_PRIVATE_H_

View File

@ -0,0 +1,533 @@
/*
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <alloy/frontend/ppc/ppc_disasm.h>
using namespace alloy::frontend::ppc;
namespace alloy {
namespace frontend {
namespace ppc {
void Disasm_0(InstrData& i, StringBuffer* str) {
str->Append("%-8s ???", i.type->name);
}
void Disasm__(InstrData& i, StringBuffer* str) {
str->Append("%-8s", i.type->name);
}
void Disasm_X_FRT_FRB(InstrData& i, StringBuffer* str) {
str->Append("%*s%s f%d, f%d", i.X.Rc ? -7 : -8, i.type->name, i.X.Rc ? "." : "",
i.X.RT, i.X.RB);
}
void Disasm_A_FRT_FRB(InstrData& i, StringBuffer* str) {
str->Append("%*s%s f%d, f%d", i.A.Rc ? -7 : -8, i.type->name, i.A.Rc ? "." : "",
i.A.FRT, i.A.FRB);
}
void Disasm_A_FRT_FRA_FRB(InstrData& i, StringBuffer* str) {
str->Append("%*s%s f%d, f%d, f%d", i.A.Rc ? -7 : -8, i.type->name, i.A.Rc ? "." : "",
i.A.FRT, i.A.FRA, i.A.FRB);
}
void Disasm_A_FRT_FRA_FRB_FRC(InstrData& i, StringBuffer* str) {
str->Append("%*s%s f%d, f%d, f%d, f%d", i.A.Rc ? -7 : -8, i.type->name, i.A.Rc ? "." : "",
i.A.FRT, i.A.FRA, i.A.FRB, i.A.FRC);
}
void Disasm_X_RT_RA_RB(InstrData& i, StringBuffer* str) {
str->Append("%-8s r%d, r%d, %d", i.type->name,
i.X.RT, i.X.RA, i.X.RB);
}
void Disasm_X_RT_RA0_RB(InstrData& i, StringBuffer* str) {
if (i.X.RA) {
str->Append("%-8s r%d, r%d, %d", i.type->name,
i.X.RT, i.X.RA, i.X.RB);
} else {
str->Append("%-8s r%d, 0, %d", i.type->name,
i.X.RT, i.X.RB);
}
}
void Disasm_X_FRT_RA_RB(InstrData& i, StringBuffer* str) {
str->Append("%-8s f%d, r%d, %d", i.type->name,
i.X.RT, i.X.RA, i.X.RB);
}
void Disasm_X_FRT_RA0_RB(InstrData& i, StringBuffer* str) {
if (i.X.RA) {
str->Append("%-8s f%d, r%d, %d", i.type->name,
i.X.RT, i.X.RA, i.X.RB);
} else {
str->Append("%-8s f%d, 0, %d", i.type->name,
i.X.RT, i.X.RB);
}
}
void Disasm_D_RT_RA_I(InstrData& i, StringBuffer* str) {
str->Append("%-8s r%d, r%d, %d", i.type->name,
i.D.RT, i.D.RA, (int32_t)(int16_t)XEEXTS16(i.D.DS));
}
void Disasm_D_RT_RA0_I(InstrData& i, StringBuffer* str) {
if (i.D.RA) {
str->Append("%-8s r%d, r%d, %d", i.type->name,
i.D.RT, i.D.RA, (int32_t)(int16_t)XEEXTS16(i.D.DS));
} else {
str->Append("%-8s r%d, 0, %d", i.type->name,
i.D.RT, (int32_t)(int16_t)XEEXTS16(i.D.DS));
}
}
void Disasm_D_FRT_RA_I(InstrData& i, StringBuffer* str) {
str->Append("%-8s f%d, r%d, %d", i.type->name,
i.D.RT, i.D.RA, (int32_t)(int16_t)XEEXTS16(i.D.DS));
}
void Disasm_D_FRT_RA0_I(InstrData& i, StringBuffer* str) {
if (i.D.RA) {
str->Append("%-8s f%d, r%d, %d", i.type->name,
i.D.RT, i.D.RA, (int32_t)(int16_t)XEEXTS16(i.D.DS));
} else {
str->Append("%-8s f%d, 0, %d", i.type->name,
i.D.RT, (int32_t)(int16_t)XEEXTS16(i.D.DS));
}
}
void Disasm_DS_RT_RA_I(InstrData& i, StringBuffer* str) {
str->Append("%-8s r%d, r%d, %d", i.type->name,
i.DS.RT, i.DS.RA, (int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
}
void Disasm_DS_RT_RA0_I(InstrData& i, StringBuffer* str) {
if (i.DS.RA) {
str->Append("%-8s r%d, r%d, %d", i.type->name,
i.DS.RT, i.DS.RA, (int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
} else {
str->Append("%-8s r%d, 0, %d", i.type->name,
i.DS.RT, (int32_t)(int16_t)XEEXTS16(i.DS.DS << 2));
}
}
void Disasm_D_RA(InstrData& i, StringBuffer* str) {
str->Append("%-8s r%d", i.type->name,
i.D.RA);
}
void Disasm_X_RA_RB(InstrData& i, StringBuffer* str) {
str->Append("%-8s r%d, r%d", i.type->name,
i.X.RA, i.X.RB);
}
void Disasm_XO_RT_RA_RB(InstrData& i, StringBuffer* str) {
str->Append("%*s%s%s r%d, r%d", i.XO.Rc ? -7 : -8, i.type->name,
i.XO.OE ? "o" : "", i.XO.Rc ? "." : "",
i.XO.RT, i.XO.RA, i.XO.RB);
}
void Disasm_XO_RT_RA(InstrData& i, StringBuffer* str) {
str->Append("%*s%s%s r%d, r%d", i.XO.Rc ? -7 : -8, i.type->name,
i.XO.OE ? "o" : "", i.XO.Rc ? "." : "",
i.XO.RT, i.XO.RA);
}
void Disasm_X_RA_RT_RB(InstrData& i, StringBuffer* str) {
str->Append("%*s%s r%d, r%d, r%d", i.X.Rc ? -7 : -8, i.type->name, i.X.Rc ? "." : "",
i.X.RA, i.X.RT, i.X.RB);
}
void Disasm_D_RA_RT_I(InstrData& i, StringBuffer* str) {
str->Append("%-7s. r%d, r%d, %.4Xh", i.type->name,
i.D.RA, i.D.RT, i.D.DS);
}
void Disasm_X_RA_RT(InstrData& i, StringBuffer* str) {
str->Append("%*s%s r%d, r%d", i.X.Rc ? -7 : -8, i.type->name, i.X.Rc ? "." : "",
i.X.RA, i.X.RT);
}
#define OP(x) ((((uint32_t)(x)) & 0x3f) << 26)
#define VX128(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x3d0))
#define VX128_1(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x7f3))
#define VX128_2(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x210))
#define VX128_3(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x7f0))
#define VX128_4(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x730))
#define VX128_5(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x10))
#define VX128_P(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x630))
#define VX128_VD128 (i.VX128.VD128l | (i.VX128.VD128h << 5))
#define VX128_VA128 (i.VX128.VA128l | (i.VX128.VA128h << 5) | (i.VX128.VA128H << 6))
#define VX128_VB128 (i.VX128.VB128l | (i.VX128.VB128h << 5))
#define VX128_1_VD128 (i.VX128_1.VD128l | (i.VX128_1.VD128h << 5))
#define VX128_2_VD128 (i.VX128_2.VD128l | (i.VX128_2.VD128h << 5))
#define VX128_2_VA128 (i.VX128_2.VA128l | (i.VX128_2.VA128h << 5) | (i.VX128_2.VA128H << 6))
#define VX128_2_VB128 (i.VX128_2.VB128l | (i.VX128_2.VD128h << 5))
#define VX128_2_VC (i.VX128_2.VC)
#define VX128_3_VD128 (i.VX128_3.VD128l | (i.VX128_3.VD128h << 5))
#define VX128_3_VB128 (i.VX128_3.VB128l | (i.VX128_3.VB128h << 5))
#define VX128_3_IMM (i.VX128_3.IMM)
#define VX128_4_VD128 (i.VX128_4.VD128l | (i.VX128_4.VD128h << 5))
#define VX128_4_VB128 (i.VX128_4.VB128l | (i.VX128_4.VB128h << 5))
#define VX128_5_VD128 (i.VX128_5.VD128l | (i.VX128_5.VD128h << 5))
#define VX128_5_VA128 (i.VX128_5.VA128l | (i.VX128_5.VA128h << 5)) | (i.VX128_5.VA128H << 6)
#define VX128_5_VB128 (i.VX128_5.VB128l | (i.VX128_5.VB128h << 5))
#define VX128_5_SH (i.VX128_5.SH)
#define VX128_R_VD128 (i.VX128_R.VD128l | (i.VX128_R.VD128h << 5))
#define VX128_R_VA128 (i.VX128_R.VA128l | (i.VX128_R.VA128h << 5) | (i.VX128_R.VA128H << 6))
#define VX128_R_VB128 (i.VX128_R.VB128l | (i.VX128_R.VB128h << 5))
void Disasm_X_VX_RA0_RB(InstrData& i, StringBuffer* str) {
if (i.X.RA) {
str->Append("%-8s v%d, r%d, r%d", i.type->name,
i.X.RT, i.X.RA, i.X.RB);
} else {
str->Append("%-8s v%d, 0, r%d", i.type->name,
i.X.RT, i.X.RB);
}
}
void Disasm_VX1281_VD_RA0_RB(InstrData& i, StringBuffer* str) {
const uint32_t vd = VX128_1_VD128;
if (i.VX128_1.RA) {
str->Append("%-8s v%d, r%d, r%d", i.type->name,
vd, i.VX128_1.RA, i.VX128_1.RB);
} else {
str->Append("%-8s v%d, 0, r%d", i.type->name,
vd, i.VX128_1.RB);
}
}
void Disasm_VX1283_VD_VB(InstrData& i, StringBuffer* str) {
const uint32_t vd = VX128_3_VD128;
const uint32_t vb = VX128_3_VB128;
str->Append("%-8s v%d, v%d", i.type->name,
vd, vb);
}
void Disasm_VX1283_VD_VB_I(InstrData& i, StringBuffer* str) {
const uint32_t vd = VX128_VD128;
const uint32_t va = VX128_VA128;
const uint32_t uimm = i.VX128_3.IMM;
str->Append("%-8s v%d, v%d, %.2Xh", i.type->name,
vd, va, uimm);
}
void Disasm_VX_VD_VA_VB(InstrData& i, StringBuffer* str) {
str->Append("%-8s v%d, v%d, v%d", i.type->name,
i.VX.VD, i.VX.VA, i.VX.VB);
}
void Disasm_VX128_VD_VA_VB(InstrData& i, StringBuffer* str) {
const uint32_t vd = VX128_VD128;
const uint32_t va = VX128_VA128;
const uint32_t vb = VX128_VB128;
str->Append("%-8s v%d, v%d, v%d", i.type->name,
vd, va, vb);
}
void Disasm_VX128_VD_VA_VD_VB(InstrData& i, StringBuffer* str) {
const uint32_t vd = VX128_VD128;
const uint32_t va = VX128_VA128;
const uint32_t vb = VX128_VB128;
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name,
vd, va, vd, vb);
}
void Disasm_VX1282_VD_VA_VB_VC(InstrData& i, StringBuffer* str) {
const uint32_t vd = VX128_2_VD128;
const uint32_t va = VX128_2_VA128;
const uint32_t vb = VX128_2_VB128;
const uint32_t vc = i.VX128_2.VC;
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name,
vd, va, vb, vc);
}
void Disasm_VXA_VD_VA_VB_VC(InstrData& i, StringBuffer* str) {
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name,
i.VXA.VD, i.VXA.VA, i.VXA.VB, i.VXA.VC);
}
void Disasm_sync(InstrData& i, StringBuffer* str) {
const char* name;
int L = i.X.RT & 3;
switch (L) {
case 0: name = "hwsync"; break;
case 1: name = "lwsync"; break;
default:
case 2:
case 3:
name = "sync";
break;
}
str->Append("%-8s %.2X", name, L);
}
void Disasm_dcbf(InstrData& i, StringBuffer* str) {
const char* name;
switch (i.X.RT & 3) {
case 0: name = "dcbf"; break;
case 1: name = "dcbfl"; break;
case 2: name = "dcbf.RESERVED"; break;
case 3: name = "dcbflp"; break;
}
str->Append("%-8s r%d, r%d", name, i.X.RA, i.X.RB);
}
void Disasm_dcbz(InstrData& i, StringBuffer* str) {
// or dcbz128 0x7C2007EC
if (i.X.RA) {
str->Append("%-8s r%d, r%d", i.type->name, i.X.RA, i.X.RB);
} else {
str->Append("%-8s 0, r%d", i.type->name, i.X.RB);
}
}
void Disasm_fcmp(InstrData& i, StringBuffer* str) {
str->Append("%-8s cr%d, r%d, r%d", i.type->name,
i.X.RT >> 2, i.X.RA, i.X.RB);
}
void Disasm_mffsx(InstrData& i, StringBuffer* str) {
str->Append("%*s%s f%d, FPSCR", i.X.Rc ? -7 : -8, i.type->name, i.X.Rc ? "." : "",
i.X.RT);
}
void Disasm_bx(InstrData& i, StringBuffer* str) {
const char* name = i.I.LK ? "bl" : "b";
uint32_t nia;
if (i.I.AA) {
nia = (uint32_t)XEEXTS26(i.I.LI << 2);
} else {
nia = (uint32_t)(i.address + XEEXTS26(i.I.LI << 2));
}
str->Append("%-8s %.8X", name,
nia);
// TODO(benvanik): resolve target name?
}
void Disasm_bcx(InstrData& i, StringBuffer* str) {
const char* s0 = i.B.LK ? "lr, " : "";
const char* s1;
if (!XESELECTBITS(i.B.BO, 2, 2)) {
s1 = "ctr, ";
} else {
s1 = "";
}
char s2[8] = { 'c', 'r', 0, };
if (!XESELECTBITS(i.B.BO, 4, 4)) {
char* s2a = _itoa(i.B.BI >> 2, s2 + 2, 10);
s2a += xestrlena(s2a);
s2a[0] = ',';
s2a[1] = ' ';
} else {
s2[0] = 0;
}
uint32_t nia;
if (i.B.AA) {
nia = (uint32_t)XEEXTS16(i.B.BD << 2);
} else {
nia = (uint32_t)(i.address + XEEXTS16(i.B.BD << 2));
}
str->Append("%-8s %s%s%s%.8X", i.type->name,
s0, s1, s2, nia);
// TODO(benvanik): resolve target name?
}
void Disasm_bcctrx(InstrData& i, StringBuffer* str) {
// TODO(benvanik): mnemonics
const char* s0 = i.XL.LK ? "lr, " : "";
char s2[8] = { 'c', 'r', 0, };
if (!XESELECTBITS(i.XL.BO, 4, 4)) {
char* s2a = _itoa(i.XL.BI >> 2, s2 + 2, 10);
s2a += xestrlena(s2a);
s2a[0] = ',';
s2a[1] = ' ';
} else {
s2[0] = 0;
}
str->Append("%-8s %s%sctr", i.type->name,
s0, s2);
// TODO(benvanik): resolve target name?
}
void Disasm_bclrx(InstrData& i, StringBuffer* str) {
const char* name = "bclr";
if (i.code == 0x4E800020) {
name = "blr";
}
const char* s1;
if (!XESELECTBITS(i.XL.BO, 2, 2)) {
s1 = "ctr, ";
} else {
s1 = "";
}
char s2[8] = { 'c', 'r', 0, };
if (!XESELECTBITS(i.XL.BO, 4, 4)) {
char* s2a = _itoa(i.XL.BI >> 2, s2 + 2, 10);
s2a += xestrlena(s2a);
s2a[0] = ',';
s2a[1] = ' ';
} else {
s2[0] = 0;
}
str->Append("%-8s %s%s", name,
s1, s2);
}
void Disasm_mfcr(InstrData& i, StringBuffer* str) {
str->Append("%-8s r%d, cr", i.type->name,
i.X.RT);
}
const char* Disasm_spr_name(uint32_t n) {
const char* reg = "???";
switch (n) {
case 1:
reg = "xer";
break;
case 8:
reg = "lr";
break;
case 9:
reg = "ctr";
break;
}
return reg;
}
void Disasm_mfspr(InstrData& i, StringBuffer* str) {
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
const char* reg = Disasm_spr_name(n);
str->Append("%-8s r%d, %s", i.type->name,
i.XFX.RT, reg);
}
void Disasm_mtspr(InstrData& i, StringBuffer* str) {
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
const char* reg = Disasm_spr_name(n);
str->Append("%-8s %s, r%d", i.type->name,
reg, i.XFX.RT);
}
void Disasm_mftb(InstrData& i, StringBuffer* str) {
str->Append("%-8s r%d, tb", i.type->name,
i.XFX.RT);
}
void Disasm_mfmsr(InstrData& i, StringBuffer* str) {
str->Append("%-8s r%d", i.type->name,
i.X.RT);
}
void Disasm_mtmsr(InstrData& i, StringBuffer* str) {
str->Append("%-8s r%d, %d", i.type->name,
i.X.RT, (i.X.RA & 16) ? 1 : 0);
}
void Disasm_cmp(InstrData& i, StringBuffer* str) {
str->Append("%-8s cr%d, %.2X, r%d, r%d", i.type->name,
i.X.RT >> 2, i.X.RT & 1, i.X.RA, i.X.RB);
}
void Disasm_cmpi(InstrData& i, StringBuffer* str) {
str->Append("%-8s cr%d, %.2X, r%d, %d", i.type->name,
i.D.RT >> 2, i.D.RT & 1, i.D.RA, XEEXTS16(i.D.DS));
}
void Disasm_cmpli(InstrData& i, StringBuffer* str) {
str->Append("%-8s cr%d, %.2X, r%d, %.2X", i.type->name,
i.D.RT >> 2, i.D.RT & 1, i.D.RA, XEEXTS16(i.D.DS));
}
void Disasm_rld(InstrData& i, StringBuffer* str) {
if (i.MD.idx == 0) {
// XEDISASMR(rldiclx, 0x78000000, MD )
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicl", i.MD.Rc ? "." : "",
i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH, (i.MD.MB5 << 5) | i.MD.MB);
} else if (i.MD.idx == 1) {
// XEDISASMR(rldicrx, 0x78000004, MD )
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicr", i.MD.Rc ? "." : "",
i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH, (i.MD.MB5 << 5) | i.MD.MB);
} else if (i.MD.idx == 2) {
// XEDISASMR(rldicx, 0x78000008, MD )
uint32_t sh = (i.MD.SH5 << 5) | i.MD.SH;
uint32_t mb = (i.MD.MB5 << 5) | i.MD.MB;
const char* name = (mb == 0x3E) ? "sldi" : "rldic";
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, name, i.MD.Rc ? "." : "",
i.MD.RA, i.MD.RT, sh, mb);
} else if (i.MDS.idx == 8) {
// XEDISASMR(rldclx, 0x78000010, MDS)
str->Append("%*s%s r%d, r%d, %d, %d", i.MDS.Rc ? -7 : -8, "rldcl", i.MDS.Rc ? "." : "",
i.MDS.RA, i.MDS.RT, i.MDS.RB, (i.MDS.MB5 << 5) | i.MDS.MB);
} else if (i.MDS.idx == 9) {
// XEDISASMR(rldcrx, 0x78000012, MDS)
str->Append("%*s%s r%d, r%d, %d, %d", i.MDS.Rc ? -7 : -8, "rldcr", i.MDS.Rc ? "." : "",
i.MDS.RA, i.MDS.RT, i.MDS.RB, (i.MDS.MB5 << 5) | i.MDS.MB);
} else if (i.MD.idx == 3) {
// XEDISASMR(rldimix, 0x7800000C, MD )
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldimi", i.MD.Rc ? "." : "",
i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH, (i.MD.MB5 << 5) | i.MD.MB);
} else {
XEASSERTALWAYS();
}
}
void Disasm_rlwim(InstrData& i, StringBuffer* str) {
str->Append("%*s%s r%d, r%d, %d, %d, %d", i.M.Rc ? -7 : -8, i.type->name, i.M.Rc ? "." : "",
i.M.RA, i.M.RT, i.M.SH, i.M.MB, i.M.ME);
}
void Disasm_rlwnmx(InstrData& i, StringBuffer* str) {
str->Append("%*s%s r%d, r%d, r%d, %d, %d", i.M.Rc ? -7 : -8, i.type->name, i.M.Rc ? "." : "",
i.M.RA, i.M.RT, i.M.SH, i.M.MB, i.M.ME);
}
void Disasm_srawix(InstrData& i, StringBuffer* str) {
str->Append("%*s%s r%d, r%d, %d", i.X.Rc ? -7 : -8, i.type->name, i.X.Rc ? "." : "",
i.X.RA, i.X.RT, i.X.RB);
}
void Disasm_sradix(InstrData& i, StringBuffer* str) {
str->Append("%*s%s r%d, r%d, %d", i.XS.Rc ? -7 : -8, i.type->name, i.XS.Rc ? "." : "",
i.XS.RA, i.XS.RT, (i.XS.SH5 << 5) | i.XS.SH);
}
void Disasm_vpermwi128(InstrData& i, StringBuffer* str) {
const uint32_t vd = i.VX128_P.VD128l | (i.VX128_P.VD128h << 5);
const uint32_t vb = i.VX128_P.VB128l | (i.VX128_P.VB128h << 5);
str->Append("%-8s v%d, v%d, %.2X", i.type->name,
vd, vb, i.VX128_P.PERMl | (i.VX128_P.PERMh << 5));
}
void Disasm_vrfin128(InstrData& i, StringBuffer* str) {
const uint32_t vd = VX128_3_VD128;
const uint32_t vb = VX128_3_VB128;
str->Append("%-8s v%d, v%d", i.type->name,
vd, vb);
}
void Disasm_vrlimi128(InstrData& i, StringBuffer* str) {
const uint32_t vd = VX128_4_VD128;
const uint32_t vb = VX128_4_VB128;
str->Append("%-8s v%d, v%d, %.2X, %.2X", i.type->name,
vd, vb, i.VX128_4.IMM, i.VX128_4.z);
}
void Disasm_vsldoi128(InstrData& i, StringBuffer* str) {
const uint32_t vd = VX128_5_VD128;
const uint32_t va = VX128_5_VA128;
const uint32_t vb = VX128_5_VB128;
const uint32_t sh = i.VX128_5.SH;
str->Append("%-8s v%d, v%d, v%d, %.2X", i.type->name,
vd, va, vb, sh);
}
void Disasm_vspltb(InstrData& i, StringBuffer* str) {
str->Append("%-8s v%d, v%d, %.2X", i.type->name,
i.VX.VD, i.VX.VB, i.VX.VA & 0xF);
}
void Disasm_vsplth(InstrData& i, StringBuffer* str) {
str->Append("%-8s v%d, v%d, %.2X", i.type->name,
i.VX.VD, i.VX.VB, i.VX.VA & 0x7);
}
void Disasm_vspltw(InstrData& i, StringBuffer* str) {
str->Append("%-8s v%d, v%d, %.2X", i.type->name,
i.VX.VD, i.VX.VB, i.VX.VA);
}
void Disasm_vspltisb(InstrData& i, StringBuffer* str) {
// 5bit -> 8bit sign extend
int8_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xF0) : i.VX.VA;
str->Append("%-8s v%d, %.2X", i.type->name,
i.VX.VD, simm);
}
void Disasm_vspltish(InstrData& i, StringBuffer* str) {
// 5bit -> 16bit sign extend
int16_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xFFF0) : i.VX.VA;
str->Append("%-8s v%d, %.4X", i.type->name,
i.VX.VD, simm);
}
void Disasm_vspltisw(InstrData& i, StringBuffer* str) {
// 5bit -> 32bit sign extend
int32_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xFFFFFFF0) : i.VX.VA;
str->Append("%-8s v%d, %.8X", i.type->name,
i.VX.VD, simm);
}
} // namespace ppc
} // namespace frontend
} // namespace alloy
int alloy::frontend::ppc::DisasmPPC(InstrData& i, StringBuffer* str) {
if (!i.type) {
str->Append("???");
} else {
i.type->disasm(i, str);
}
return 0;
}

View File

@ -18,11 +18,7 @@ namespace frontend {
namespace ppc {
void RegisterDisasmCategoryAltivec();
void RegisterDisasmCategoryALU();
void RegisterDisasmCategoryControl();
void RegisterDisasmCategoryFPU();
void RegisterDisasmCategoryMemory();
int DisasmPPC(InstrData& i, StringBuffer* str);
} // namespace ppc

File diff suppressed because it is too large Load Diff

View File

@ -1,729 +0,0 @@
/*
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <alloy/frontend/ppc/ppc_disasm-private.h>
using namespace alloy::frontend::ppc;
namespace alloy {
namespace frontend {
namespace ppc {
// Integer arithmetic (A-3)
XEDISASMR(addx, 0x7C000214, XO )(InstrData& i, InstrDisasm& d) {
d.Init("add", "Add",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(addcx, 0x7C000014, XO )(InstrData& i, InstrDisasm& d) {
d.Init("addc", "Add Carrying",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0) |
InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(addex, 0x7C000114, XO )(InstrData& i, InstrDisasm& d) {
d.Init("adde", "Add Extended",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(addi, 0x38000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("addi", "Add Immediate", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddSImmOperand(0, 4);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(addic, 0x30000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("addic", "Add Immediate Carrying", InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(addicx, 0x34000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("addic", "Add Immediate Carrying and Record",
InstrDisasm::kRc | InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(addis, 0x3C000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("addis", "Add Immediate Shifted", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddSImmOperand(0, 4);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(addmex, 0x7C0001D4, XO )(InstrData& i, InstrDisasm& d) {
d.Init("addme", "Add to Minus One Extended",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0) |
InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(addzex, 0x7C000194, XO )(InstrData& i, InstrDisasm& d) {
d.Init("addze", "Add to Zero Extended",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0) |
InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(divdx, 0x7C0003D2, XO )(InstrData& i, InstrDisasm& d) {
d.Init("divd", "Divide Doubleword",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(divdux, 0x7C000392, XO )(InstrData& i, InstrDisasm& d) {
d.Init("divdu", "Divide Doubleword Unsigned",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(divwx, 0x7C0003D6, XO )(InstrData& i, InstrDisasm& d) {
d.Init("divw", "Divide Word",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(divwux, 0x7C000396, XO )(InstrData& i, InstrDisasm& d) {
d.Init("divwu", "Divide Word Unsigned",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(mulhdx, 0x7C000092, XO )(InstrData& i, InstrDisasm& d) {
d.Init("mulhd", "Multiply High Doubleword", i.XO.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(mulhdux, 0x7C000012, XO )(InstrData& i, InstrDisasm& d) {
d.Init("mulhdu", "Multiply High Doubleword Unsigned",
i.XO.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(mulhwx, 0x7C000096, XO )(InstrData& i, InstrDisasm& d) {
d.Init("mulhw", "Multiply High Word", i.XO.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(mulhwux, 0x7C000016, XO )(InstrData& i, InstrDisasm& d) {
d.Init("mulhwu", "Multiply High Word Unsigned",
i.XO.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(mulldx, 0x7C0001D2, XO )(InstrData& i, InstrDisasm& d) {
d.Init("mulld", "Multiply Low Doubleword",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(mulli, 0x1C000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("mulli", "Multiply Low Immediate", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(mullwx, 0x7C0001D6, XO )(InstrData& i, InstrDisasm& d) {
d.Init("mullw", "Multiply Low Word",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(negx, 0x7C0000D0, XO )(InstrData& i, InstrDisasm& d) {
d.Init("neg", "Negate",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(subfx, 0x7C000050, XO )(InstrData& i, InstrDisasm& d) {
d.Init("subf", "Subtract From",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(subfcx, 0x7C000010, XO )(InstrData& i, InstrDisasm& d) {
d.Init("subfc", "Subtract From Carrying",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0) |
InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(subficx, 0x20000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("subfic", "Subtract From Immediate Carrying", InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(subfex, 0x7C000110, XO )(InstrData& i, InstrDisasm& d) {
d.Init("subfe", "Subtract From Extended",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0) |
InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(subfmex, 0x7C0001D0, XO )(InstrData& i, InstrDisasm& d) {
d.Init("subfme", "Subtract From Minus One Extended",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0) |
InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(subfzex, 0x7C000190, XO )(InstrData& i, InstrDisasm& d) {
d.Init("subfze", "Subtract From Zero Extended",
(i.XO.OE ? InstrDisasm::kOE : 0) | (i.XO.Rc ? InstrDisasm::kRc : 0) |
InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XO.RA, InstrRegister::kRead);
return d.Finish();
}
// Integer compare (A-4)
XEDISASMR(cmp, 0x7C000000, X )(InstrData& i, InstrDisasm& d) {
d.Init("cmp", "Compare", 0);
d.AddCR(i.X.RT >> 2, InstrRegister::kWrite);
d.AddUImmOperand(i.X.RT >> 2, 1);
d.AddUImmOperand(i.X.RT & 1, 1);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(cmpi, 0x2C000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("cmpi", "Compare Immediate", 0);
d.AddCR(i.D.RT >> 2, InstrRegister::kWrite);
d.AddUImmOperand(i.D.RT >> 2, 1);
d.AddUImmOperand(i.D.RT & 1, 1);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(cmpl, 0x7C000040, X )(InstrData& i, InstrDisasm& d) {
d.Init("cmpl", "Compare Logical", 0);
d.AddCR(i.X.RT >> 2, InstrRegister::kWrite);
d.AddUImmOperand(i.X.RT >> 2, 1);
d.AddUImmOperand(i.X.RT & 1, 1);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(cmpli, 0x28000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("cmpli", "Compare Logical Immediate", 0);
d.AddCR(i.D.RT >> 2, InstrRegister::kWrite);
d.AddUImmOperand(i.D.RT >> 2, 1);
d.AddUImmOperand(i.D.RT & 1, 1);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
d.AddSImmOperand(i.D.DS, 2);
return d.Finish();
}
// Integer logical (A-5)
XEDISASMR(andx, 0x7C000038, X )(InstrData& i, InstrDisasm& d) {
d.Init("and", "AND", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(andcx, 0x7C000078, X )(InstrData& i, InstrDisasm& d) {
d.Init("andc", "AND with Complement", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(andix, 0x70000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("andi", "AND Immediate", 0);
d.AddCR(0, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
d.AddUImmOperand(i.D.DS, 2);
return d.Finish();
}
XEDISASMR(andisx, 0x74000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("andi", "AND Immediate Shifted", 0);
d.AddCR(0, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
d.AddUImmOperand(i.D.DS, 2);
return d.Finish();
}
XEDISASMR(cntlzdx, 0x7C000074, X )(InstrData& i, InstrDisasm& d) {
d.Init("cntlzd", "Count Leading Zeros Doubleword",
i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(cntlzwx, 0x7C000034, X )(InstrData& i, InstrDisasm& d) {
d.Init("cntlzw", "Count Leading Zeros Word",
i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(eqvx, 0x7C000238, X )(InstrData& i, InstrDisasm& d) {
d.Init("eqv", "Equivalent", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(extsbx, 0x7C000774, X )(InstrData& i, InstrDisasm& d) {
d.Init("extsb", "Extend Sign Byte", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(extshx, 0x7C000734, X )(InstrData& i, InstrDisasm& d) {
d.Init("extsh", "Extend Sign Halfword", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(extswx, 0x7C0007B4, X )(InstrData& i, InstrDisasm& d) {
d.Init("extsw", "Extend Sign Word", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(nandx, 0x7C0003B8, X )(InstrData& i, InstrDisasm& d) {
d.Init("nand", "NAND", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(norx, 0x7C0000F8, X )(InstrData& i, InstrDisasm& d) {
d.Init("nor", "NOR", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(orx, 0x7C000378, X )(InstrData& i, InstrDisasm& d) {
d.Init("or", "OR", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(orcx, 0x7C000338, X )(InstrData& i, InstrDisasm& d) {
d.Init("orc", "OR with Complement", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(ori, 0x60000000, D )(InstrData& i, InstrDisasm& d) {
if (!i.D.RA && !i.D.RT && !i.D.DS) {
d.Init("nop", "OR Immediate", 0);
return d.Finish();
} else {
d.Init("ori", "OR Immediate", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
d.AddUImmOperand(i.D.DS, 2);
return d.Finish();
}
}
XEDISASMR(oris, 0x64000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("oris", "OR Immediate Shifted", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
d.AddUImmOperand(i.D.DS, 2);
return d.Finish();
}
XEDISASMR(xorx, 0x7C000278, X )(InstrData& i, InstrDisasm& d) {
d.Init("xor", "XOR", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(xori, 0x68000000, D )(InstrData& i, InstrDisasm& d) {
if (!i.D.RA && !i.D.RT && !i.D.DS) {
d.Init("xnop", "XOR Immediate", 0);
} else {
d.Init("xori", "XOR Immediate", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
d.AddUImmOperand(i.D.DS, 2);
}
return d.Finish();
}
XEDISASMR(xoris, 0x6C000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("xoris", "XOR Immediate Shifted", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
d.AddUImmOperand(i.D.DS, 2);
return d.Finish();
}
// Integer rotate (A-6)
XEDISASMR(rld, 0x78000000, MDS)(InstrData& i, InstrDisasm& d) {
if (i.MD.idx == 0) {
// XEDISASMR(rldiclx, 0x78000000, MD )
d.Init("rldicl", "Rotate Left Doubleword Immediate then Clear Left",
i.MD.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.MD.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.MD.RT, InstrRegister::kRead);
d.AddUImmOperand((i.MD.SH5 << 5) | i.MD.SH, 1);
d.AddUImmOperand((i.MD.MB5 << 5) | i.MD.MB, 1);
return d.Finish();
} else if (i.MD.idx == 1) {
// XEDISASMR(rldicrx, 0x78000004, MD )
d.Init("rldicr", "Rotate Left Doubleword Immediate then Clear Right",
i.MD.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.MD.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.MD.RT, InstrRegister::kRead);
d.AddUImmOperand((i.MD.SH5 << 5) | i.MD.SH, 1);
d.AddUImmOperand((i.MD.MB5 << 5) | i.MD.MB, 1);
return d.Finish();
} else if (i.MD.idx == 2) {
// XEDISASMR(rldicx, 0x78000008, MD )
const char* name;
const char* desc;
uint32_t sh = (i.MD.SH5 << 5) | i.MD.SH;
uint32_t mb = (i.MD.MB5 << 5) | i.MD.MB;
if (mb == 0x3E) {
name = "sldi";
desc = "Shift Left Immediate";
} else {
name = "rldic";
desc = "Rotate Left Doubleword Immediate then Clear";
}
d.Init(name, desc,
i.MD.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.MD.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.MD.RT, InstrRegister::kRead);
d.AddUImmOperand(sh, 1);
d.AddUImmOperand(mb, 1);
return d.Finish();
} else if (i.MDS.idx == 8) {
// XEDISASMR(rldclx, 0x78000010, MDS)
d.Init("rldcl", "Rotate Left Doubleword then Clear Left",
i.MDS.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.MDS.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.MDS.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.MDS.RB, InstrRegister::kRead);
d.AddUImmOperand((i.MDS.MB5 << 5) | i.MDS.MB, 1);
return d.Finish();
} else if (i.MDS.idx == 9) {
// XEDISASMR(rldcrx, 0x78000012, MDS)
d.Init("rldcr", "Rotate Left Doubleword then Clear Right",
i.MDS.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.MDS.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.MDS.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.MDS.RB, InstrRegister::kRead);
d.AddUImmOperand((i.MDS.MB5 << 5) | i.MDS.MB, 1);
return d.Finish();
} else if (i.MD.idx == 3) {
// XEDISASMR(rldimix, 0x7800000C, MD )
d.Init("rldimi", "Rotate Left Doubleword Immediate then Mask Insert",
i.MD.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.MD.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.MD.RT, InstrRegister::kRead);
d.AddUImmOperand((i.MD.SH5 << 5) | i.MD.SH, 1);
d.AddUImmOperand((i.MD.MB5 << 5) | i.MD.MB, 1);
return d.Finish();
} else {
XEASSERTALWAYS();
return 1;
}
}
XEDISASMR(rlwimix, 0x50000000, M )(InstrData& i, InstrDisasm& d) {
d.Init("rlwimi", "Rotate Left Word Immediate then Mask Insert",
i.M.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.M.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.M.RT, InstrRegister::kRead);
d.AddUImmOperand(i.M.SH, 1);
d.AddUImmOperand(i.M.MB, 1);
d.AddUImmOperand(i.M.ME, 1);
return d.Finish();
}
XEDISASMR(rlwinmx, 0x54000000, M )(InstrData& i, InstrDisasm& d) {
d.Init("rlwinm", "Rotate Left Word Immediate then AND with Mask",
i.M.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.M.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.M.RT, InstrRegister::kRead);
d.AddUImmOperand(i.M.SH, 1);
d.AddUImmOperand(i.M.MB, 1);
d.AddUImmOperand(i.M.ME, 1);
return d.Finish();
}
XEDISASMR(rlwnmx, 0x5C000000, M )(InstrData& i, InstrDisasm& d) {
d.Init("rlwnm", "Rotate Left Word then AND with Mask",
i.M.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.M.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.M.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.M.SH, InstrRegister::kRead);
d.AddUImmOperand(i.M.MB, 1);
d.AddUImmOperand(i.M.ME, 1);
return d.Finish();
}
// Integer shift (A-7)
XEDISASMR(sldx, 0x7C000036, X )(InstrData& i, InstrDisasm& d) {
d.Init("sld", "Shift Left Doubleword", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(slwx, 0x7C000030, X )(InstrData& i, InstrDisasm& d) {
d.Init("slw", "Shift Left Word", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(sradx, 0x7C000634, X )(InstrData& i, InstrDisasm& d) {
d.Init("srad", "Shift Right Algebraic Doubleword",
i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(sradix, 0x7C000674, XS )(InstrData& i, InstrDisasm& d) {
d.Init("sradi", "Shift Right Algebraic Doubleword Immediate",
(i.XS.Rc ? InstrDisasm::kRc : 0) | InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.XS.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.XS.RT, InstrRegister::kRead);
d.AddUImmOperand((i.XS.SH5 << 5) | i.XS.SH, 1);
return d.Finish();
}
XEDISASMR(srawx, 0x7C000630, X )(InstrData& i, InstrDisasm& d) {
d.Init("sraw", "Shift Right Algebraic Word",
(i.X.Rc ? InstrDisasm::kRc : 0) | InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(srawix, 0x7C000670, X )(InstrData& i, InstrDisasm& d) {
d.Init("srawi", "Shift Right Algebraic Word Immediate",
(i.X.Rc ? InstrDisasm::kRc : 0) | InstrDisasm::kCA);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddUImmOperand(i.X.RB, 1);
return d.Finish();
}
XEDISASMR(srdx, 0x7C000436, X )(InstrData& i, InstrDisasm& d) {
d.Init("srd", "Shift Right Doubleword", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(srwx, 0x7C000430, X )(InstrData& i, InstrDisasm& d) {
d.Init("srw", "Shift Right Word", i.X.Rc ? InstrDisasm::kRc : 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
void RegisterDisasmCategoryALU() {
XEREGISTERINSTR(addx, 0x7C000214);
XEREGISTERINSTR(addcx, 0X7C000014);
XEREGISTERINSTR(addex, 0x7C000114);
XEREGISTERINSTR(addi, 0x38000000);
XEREGISTERINSTR(addic, 0x30000000);
XEREGISTERINSTR(addicx, 0x34000000);
XEREGISTERINSTR(addis, 0x3C000000);
XEREGISTERINSTR(addmex, 0x7C0001D4);
XEREGISTERINSTR(addzex, 0x7C000194);
XEREGISTERINSTR(divdx, 0x7C0003D2);
XEREGISTERINSTR(divdux, 0x7C000392);
XEREGISTERINSTR(divwx, 0x7C0003D6);
XEREGISTERINSTR(divwux, 0x7C000396);
XEREGISTERINSTR(mulhdx, 0x7C000092);
XEREGISTERINSTR(mulhdux, 0x7C000012);
XEREGISTERINSTR(mulhwx, 0x7C000096);
XEREGISTERINSTR(mulhwux, 0x7C000016);
XEREGISTERINSTR(mulldx, 0x7C0001D2);
XEREGISTERINSTR(mulli, 0x1C000000);
XEREGISTERINSTR(mullwx, 0x7C0001D6);
XEREGISTERINSTR(negx, 0x7C0000D0);
XEREGISTERINSTR(subfx, 0x7C000050);
XEREGISTERINSTR(subfcx, 0x7C000010);
XEREGISTERINSTR(subficx, 0x20000000);
XEREGISTERINSTR(subfex, 0x7C000110);
XEREGISTERINSTR(subfmex, 0x7C0001D0);
XEREGISTERINSTR(subfzex, 0x7C000190);
XEREGISTERINSTR(cmp, 0x7C000000);
XEREGISTERINSTR(cmpi, 0x2C000000);
XEREGISTERINSTR(cmpl, 0x7C000040);
XEREGISTERINSTR(cmpli, 0x28000000);
XEREGISTERINSTR(andx, 0x7C000038);
XEREGISTERINSTR(andcx, 0x7C000078);
XEREGISTERINSTR(andix, 0x70000000);
XEREGISTERINSTR(andisx, 0x74000000);
XEREGISTERINSTR(cntlzdx, 0x7C000074);
XEREGISTERINSTR(cntlzwx, 0x7C000034);
XEREGISTERINSTR(eqvx, 0x7C000238);
XEREGISTERINSTR(extsbx, 0x7C000774);
XEREGISTERINSTR(extshx, 0x7C000734);
XEREGISTERINSTR(extswx, 0x7C0007B4);
XEREGISTERINSTR(nandx, 0x7C0003B8);
XEREGISTERINSTR(norx, 0x7C0000F8);
XEREGISTERINSTR(orx, 0x7C000378);
XEREGISTERINSTR(orcx, 0x7C000338);
XEREGISTERINSTR(ori, 0x60000000);
XEREGISTERINSTR(oris, 0x64000000);
XEREGISTERINSTR(xorx, 0x7C000278);
XEREGISTERINSTR(xori, 0x68000000);
XEREGISTERINSTR(xoris, 0x6C000000);
XEREGISTERINSTR(rld, 0x78000000);
// XEREGISTERINSTR(rldclx, 0x78000010);
// XEREGISTERINSTR(rldcrx, 0x78000012);
// XEREGISTERINSTR(rldicx, 0x78000008);
// XEREGISTERINSTR(rldiclx, 0x78000000);
// XEREGISTERINSTR(rldicrx, 0x78000004);
// XEREGISTERINSTR(rldimix, 0x7800000C);
XEREGISTERINSTR(rlwimix, 0x50000000);
XEREGISTERINSTR(rlwinmx, 0x54000000);
XEREGISTERINSTR(rlwnmx, 0x5C000000);
XEREGISTERINSTR(sldx, 0x7C000036);
XEREGISTERINSTR(slwx, 0x7C000030);
XEREGISTERINSTR(sradx, 0x7C000634);
XEREGISTERINSTR(sradix, 0x7C000674);
XEREGISTERINSTR(srawx, 0x7C000630);
XEREGISTERINSTR(srawix, 0x7C000670);
XEREGISTERINSTR(srdx, 0x7C000436);
XEREGISTERINSTR(srwx, 0x7C000430);
}
} // namespace ppc
} // namespace frontend
} // namespace alloy

View File

@ -1,283 +0,0 @@
/*
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <alloy/frontend/ppc/ppc_disasm-private.h>
using namespace alloy::frontend::ppc;
namespace alloy {
namespace frontend {
namespace ppc {
XEDISASMR(bx, 0x48000000, I )(InstrData& i, InstrDisasm& d) {
d.Init("b", "Branch", i.I.LK ? InstrDisasm::kLR : 0);
uint32_t nia;
if (i.I.AA) {
nia = (uint32_t)XEEXTS26(i.I.LI << 2);
} else {
nia = (uint32_t)(i.address + XEEXTS26(i.I.LI << 2));
}
d.AddUImmOperand(nia, 4);
return d.Finish();
}
XEDISASMR(bcx, 0x40000000, B )(InstrData& i, InstrDisasm& d) {
// TODO(benvanik): mnemonics
d.Init("bc", "Branch Conditional", i.B.LK ? InstrDisasm::kLR : 0);
if (!XESELECTBITS(i.B.BO, 2, 2)) {
d.AddCTR(InstrRegister::kReadWrite);
}
if (!XESELECTBITS(i.B.BO, 4, 4)) {
d.AddCR(i.B.BI >> 2, InstrRegister::kRead);
}
d.AddUImmOperand(i.B.BO, 1);
d.AddUImmOperand(i.B.BI, 1);
uint32_t nia;
if (i.B.AA) {
nia = (uint32_t)XEEXTS16(i.B.BD << 2);
} else {
nia = (uint32_t)(i.address + XEEXTS16(i.B.BD << 2));
}
d.AddUImmOperand(nia, 4);
return d.Finish();
}
XEDISASMR(bcctrx, 0x4C000420, XL )(InstrData& i, InstrDisasm& d) {
// TODO(benvanik): mnemonics
d.Init("bcctr", "Branch Conditional to Count Register",
i.XL.LK ? InstrDisasm::kLR : 0);
if (!XESELECTBITS(i.XL.BO, 4, 4)) {
d.AddCR(i.XL.BI >> 2, InstrRegister::kRead);
}
d.AddUImmOperand(i.XL.BO, 1);
d.AddUImmOperand(i.XL.BI, 1);
d.AddCTR(InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(bclrx, 0x4C000020, XL )(InstrData& i, InstrDisasm& d) {
const char* name = "bclr";
if (i.code == 0x4E800020) {
name = "blr";
}
d.Init(name, "Branch Conditional to Link Register",
i.XL.LK ? InstrDisasm::kLR : 0);
if (!XESELECTBITS(i.B.BO, 2, 2)) {
d.AddCTR(InstrRegister::kReadWrite);
}
if (!XESELECTBITS(i.B.BO, 4, 4)) {
d.AddCR(i.B.BI >> 2, InstrRegister::kRead);
}
d.AddUImmOperand(i.XL.BO, 1);
d.AddUImmOperand(i.XL.BI, 1);
d.AddLR(InstrRegister::kRead);
return d.Finish();
}
// Condition register logical (A-23)
XEDISASMR(crand, 0x4C000202, XL )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(crandc, 0x4C000102, XL )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(creqv, 0x4C000242, XL )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(crnand, 0x4C0001C2, XL )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(crnor, 0x4C000042, XL )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(cror, 0x4C000382, XL )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(crorc, 0x4C000342, XL )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(crxor, 0x4C000182, XL )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(mcrf, 0x4C000000, XL )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
// System linkage (A-24)
XEDISASMR(sc, 0x44000002, SC )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
// Trap (A-25)
XEDISASMR(td, 0x7C000088, X )(InstrData& i, InstrDisasm& d) {
d.Init("td", "Trap Doubleword", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(tdi, 0x08000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("tdi", "Trap Doubleword Immediate", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(tw, 0x7C000008, X )(InstrData& i, InstrDisasm& d) {
d.Init("tw", "Trap Word", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(twi, 0x0C000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("twi", "Trap Word Immediate", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
return d.Finish();
}
// Processor control (A-26)
XEDISASMR(mfcr, 0x7C000026, X )(InstrData& i, InstrDisasm& d) {
d.Init("mfcr", "Move From Condition Register", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
for (int n = 0; n < 8; n++) {
d.AddCR(0, InstrRegister::kRead);
}
return d.Finish();
}
XEDISASMR(mfspr, 0x7C0002A6, XFX)(InstrData& i, InstrDisasm& d) {
d.Init("mfspr", "Move From Special Purpose Register", 0);
d.AddRegOperand(InstrRegister::kGPR, i.XFX.RT, InstrRegister::kWrite);
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
switch (n) {
case 1:
d.AddRegOperand(InstrRegister::kXER, 0, InstrRegister::kRead);
break;
case 8:
d.AddRegOperand(InstrRegister::kLR, 0, InstrRegister::kRead);
break;
case 9:
d.AddRegOperand(InstrRegister::kCTR, 0, InstrRegister::kRead);
break;
}
return d.Finish();
}
XEDISASMR(mftb, 0x7C0002E6, XFX)(InstrData& i, InstrDisasm& d) {
d.Init("mftb", "Move From Time Base", 0);
d.AddRegOperand(InstrRegister::kGPR, i.XFX.RT, InstrRegister::kWrite);
return d.Finish();
}
XEDISASMR(mtcrf, 0x7C000120, XFX)(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(mtspr, 0x7C0003A6, XFX)(InstrData& i, InstrDisasm& d) {
d.Init("mtspr", "Move To Special Purpose Register", 0);
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
switch (n) {
case 1:
d.AddRegOperand(InstrRegister::kXER, 0, InstrRegister::kWrite);
break;
case 8:
d.AddRegOperand(InstrRegister::kLR, 0, InstrRegister::kWrite);
break;
case 9:
d.AddRegOperand(InstrRegister::kCTR, 0, InstrRegister::kWrite);
break;
}
d.AddRegOperand(InstrRegister::kGPR, i.XFX.RT, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(mfmsr, 0x7C0000A6, X)(InstrData& i, InstrDisasm& d) {
d.Init("mfmsr", "Move From Machine State Register", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
return d.Finish();
}
XEDISASMR(mtmsr, 0x7C000124, X)(InstrData& i, InstrDisasm& d) {
d.Init("mtmsr", "Move To Machine State Register", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddSImmOperand((i.X.RA & 16) ? 1 : 0, 1);
return d.Finish();
}
XEDISASMR(mtmsrd, 0x7C000164, X)(InstrData& i, InstrDisasm& d) {
d.Init("mtmsrd", "Move To Machine State Register Doubleword", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddSImmOperand((i.X.RA & 16) ? 1 : 0, 1);
return d.Finish();
}
void RegisterDisasmCategoryControl() {
XEREGISTERINSTR(bx, 0x48000000);
XEREGISTERINSTR(bcx, 0x40000000);
XEREGISTERINSTR(bcctrx, 0x4C000420);
XEREGISTERINSTR(bclrx, 0x4C000020);
XEREGISTERINSTR(crand, 0x4C000202);
XEREGISTERINSTR(crandc, 0x4C000102);
XEREGISTERINSTR(creqv, 0x4C000242);
XEREGISTERINSTR(crnand, 0x4C0001C2);
XEREGISTERINSTR(crnor, 0x4C000042);
XEREGISTERINSTR(cror, 0x4C000382);
XEREGISTERINSTR(crorc, 0x4C000342);
XEREGISTERINSTR(crxor, 0x4C000182);
XEREGISTERINSTR(mcrf, 0x4C000000);
XEREGISTERINSTR(sc, 0x44000002);
XEREGISTERINSTR(td, 0x7C000088);
XEREGISTERINSTR(tdi, 0x08000000);
XEREGISTERINSTR(tw, 0x7C000008);
XEREGISTERINSTR(twi, 0x0C000000);
XEREGISTERINSTR(mfcr, 0x7C000026);
XEREGISTERINSTR(mfspr, 0x7C0002A6);
XEREGISTERINSTR(mftb, 0x7C0002E6);
XEREGISTERINSTR(mtcrf, 0x7C000120);
XEREGISTERINSTR(mtspr, 0x7C0003A6);
XEREGISTERINSTR(mfmsr, 0x7C0000A6);
XEREGISTERINSTR(mtmsr, 0x7C000124);
XEREGISTERINSTR(mtmsrd, 0x7C000164);
}
} // namespace ppc
} // namespace frontend
} // namespace alloy

View File

@ -1,413 +0,0 @@
/*
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <alloy/frontend/ppc/ppc_disasm-private.h>
using namespace alloy::frontend::ppc;
namespace alloy {
namespace frontend {
namespace ppc {
// Floating-point arithmetic (A-8)
XEDISASMR(faddx, 0xFC00002A, A )(InstrData& i, InstrDisasm& d) {
d.Init("fadd", "Floating Add [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(faddsx, 0xEC00002A, A )(InstrData& i, InstrDisasm& d) {
d.Init("fadds", "Floating Add [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fdivx, 0xFC000024, A )(InstrData& i, InstrDisasm& d) {
d.Init("fdiv", "Floating Divide [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fdivsx, 0xEC000024, A )(InstrData& i, InstrDisasm& d) {
d.Init("fdivs", "Floating Divide [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fmulx, 0xFC000032, A )(InstrData& i, InstrDisasm& d) {
d.Init("fmul", "Floating Multiply [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fmulsx, 0xEC000032, A )(InstrData& i, InstrDisasm& d) {
d.Init("fmuls", "Floating Multiply [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fresx, 0xEC000030, A )(InstrData& i, InstrDisasm& d) {
d.Init("fres", "Floating Reciprocal Estimate [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(frsqrtex, 0xFC000034, A )(InstrData& i, InstrDisasm& d) {
d.Init("frsqrte", "Floating Reciprocal Square Root Estimate [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fsubx, 0xFC000028, A )(InstrData& i, InstrDisasm& d) {
d.Init("fsub", "Floating Subtract [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fsubsx, 0xEC000028, A )(InstrData& i, InstrDisasm& d) {
d.Init("fsubs", "Floating Subtract [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fselx, 0xFC00002E, A )(InstrData& i, InstrDisasm& d) {
d.Init("fsel", "Floating Select",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fsqrtx, 0xFC00002C, A )(InstrData& i, InstrDisasm& d) {
d.Init("fsqrt", "Floating Square Root [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fsqrtsx, 0xEC00002C, A )(InstrData& i, InstrDisasm& d) {
d.Init("fsqrts", "Floating Square Root [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
return d.Finish();
}
// Floating-point multiply-add (A-9)
XEDISASMR(fmaddx, 0xFC00003A, A )(InstrData& i, InstrDisasm& d) {
d.Init("fmadd", "Floating Multiply-Add [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fmaddsx, 0xEC00003A, A )(InstrData& i, InstrDisasm& d) {
d.Init("fmadds", "Floating Multiply-Add [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fmsubx, 0xFC000038, A )(InstrData& i, InstrDisasm& d) {
d.Init("fmsub", "Floating Multiply-Subtract[Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fmsubsx, 0xEC000038, A )(InstrData& i, InstrDisasm& d) {
d.Init("fmsubs", "Floating Multiply-Subtract [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fnmaddx, 0xFC00003E, A )(InstrData& i, InstrDisasm& d) {
d.Init("fnmadd", "Floating Negative Multiply-Add [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fnmaddsx, 0xEC00003E, A )(InstrData& i, InstrDisasm& d) {
d.Init("fnmadds", "Floating Negative Multiply-Add [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fnmsubx, 0xFC00003C, A )(InstrData& i, InstrDisasm& d) {
d.Init("fnmsub", "Floating Negative Multiply-Subtract [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fnmsubsx, 0xEC00003C, A )(InstrData& i, InstrDisasm& d) {
d.Init("fnmsubs", "Floating Negative Multiply-Add [Single]",
InstrDisasm::kFP | (i.A.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.A.FRT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRB, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.A.FRC, InstrRegister::kRead);
return d.Finish();
}
// Floating-point rounding and conversion (A-10)
XEDISASMR(fcfidx, 0xFC00069C, X )(InstrData& i, InstrDisasm& d) {
d.Init("fcfid", "Floating Convert From Integer Doubleword",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fctidx, 0xFC00065C, X )(InstrData& i, InstrDisasm& d) {
d.Init("fctid", "Floating Convert To Integer Doubleword",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fctidzx, 0xFC00065E, X )(InstrData& i, InstrDisasm& d) {
d.Init("fctidz",
"Floating Convert To Integer Doubleword with round toward Zero",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fctiwx, 0xFC00001C, X )(InstrData& i, InstrDisasm& d) {
d.Init("fctiw", "Floating Convert To Integer Word",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fctiwzx, 0xFC00001E, X )(InstrData& i, InstrDisasm& d) {
d.Init("fctiwz", "Floating Convert To Integer Word with round toward Zero",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(frspx, 0xFC000018, X )(InstrData& i, InstrDisasm& d) {
d.Init("frsp", "Floating Round to Single-Precision",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
// Floating-point compare (A-11)
XEDISASMR(fcmpo, 0xFC000040, X )(InstrData& i, InstrDisasm& d) {
d.Init("fcmpo", "Floating Compare Ordered", 0);
d.AddCR(i.X.RT >> 2, InstrRegister::kWrite);
d.AddUImmOperand(i.X.RT >> 2, 1);
d.AddRegOperand(InstrRegister::kFPR, i.X.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fcmpu, 0xFC000000, X )(InstrData& i, InstrDisasm& d) {
d.Init("fcmpu", "Floating Compare Unordered", 0);
d.AddCR(i.X.RT >> 2, InstrRegister::kWrite);
d.AddUImmOperand(i.X.RT >> 2, 1);
d.AddRegOperand(InstrRegister::kFPR, i.X.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
// Floating-point status and control register (A
XEDISASMR(mcrfs, 0xFC000080, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(mffsx, 0xFC00048E, X )(InstrData& i, InstrDisasm& d) {
d.Init("mffs", "Move from FPSCR",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddFPSCR(InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
return d.Finish();
}
XEDISASMR(mtfsb0x, 0xFC00008C, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(mtfsb1x, 0xFC00004C, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(mtfsfx, 0xFC00058E, XFL)(InstrData& i, InstrDisasm& d) {
d.Init("mtfsf", "Move to FPSCR Fields",
InstrDisasm::kFP | (i.XFL.Rc ? InstrDisasm::kRc : 0));
d.AddFPSCR(InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.XFL.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(mtfsfix, 0xFC00010C, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
// Floating-point move (A-21)
XEDISASMR(fabsx, 0xFC000210, X )(InstrData& i, InstrDisasm& d) {
d.Init("fabs", "Floating Absolute Value",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fmrx, 0xFC000090, X )(InstrData& i, InstrDisasm& d) {
d.Init("fmr", "Floating Move Register",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fnabsx, 0xFC000110, X )(InstrData& i, InstrDisasm& d) {
d.Init("fnabs", "Floating Negative Absolute Value",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(fnegx, 0xFC000050, X )(InstrData& i, InstrDisasm& d) {
d.Init("fneg", "Floating Negate",
InstrDisasm::kFP | (i.X.Rc ? InstrDisasm::kRc : 0));
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kFPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
void RegisterDisasmCategoryFPU() {
XEREGISTERINSTR(faddx, 0xFC00002A);
XEREGISTERINSTR(faddsx, 0xEC00002A);
XEREGISTERINSTR(fdivx, 0xFC000024);
XEREGISTERINSTR(fdivsx, 0xEC000024);
XEREGISTERINSTR(fmulx, 0xFC000032);
XEREGISTERINSTR(fmulsx, 0xEC000032);
XEREGISTERINSTR(fresx, 0xEC000030);
XEREGISTERINSTR(frsqrtex, 0xFC000034);
XEREGISTERINSTR(fsubx, 0xFC000028);
XEREGISTERINSTR(fsubsx, 0xEC000028);
XEREGISTERINSTR(fselx, 0xFC00002E);
XEREGISTERINSTR(fsqrtx, 0xFC00002C);
XEREGISTERINSTR(fsqrtsx, 0xEC00002C);
XEREGISTERINSTR(fmaddx, 0xFC00003A);
XEREGISTERINSTR(fmaddsx, 0xEC00003A);
XEREGISTERINSTR(fmsubx, 0xFC000038);
XEREGISTERINSTR(fmsubsx, 0xEC000038);
XEREGISTERINSTR(fnmaddx, 0xFC00003E);
XEREGISTERINSTR(fnmaddsx, 0xEC00003E);
XEREGISTERINSTR(fnmsubx, 0xFC00003C);
XEREGISTERINSTR(fnmsubsx, 0xEC00003C);
XEREGISTERINSTR(fcfidx, 0xFC00069C);
XEREGISTERINSTR(fctidx, 0xFC00065C);
XEREGISTERINSTR(fctidzx, 0xFC00065E);
XEREGISTERINSTR(fctiwx, 0xFC00001C);
XEREGISTERINSTR(fctiwzx, 0xFC00001E);
XEREGISTERINSTR(frspx, 0xFC000018);
XEREGISTERINSTR(fcmpo, 0xFC000040);
XEREGISTERINSTR(fcmpu, 0xFC000000);
XEREGISTERINSTR(mcrfs, 0xFC000080);
XEREGISTERINSTR(mffsx, 0xFC00048E);
XEREGISTERINSTR(mtfsb0x, 0xFC00008C);
XEREGISTERINSTR(mtfsb1x, 0xFC00004C);
XEREGISTERINSTR(mtfsfx, 0xFC00058E);
XEREGISTERINSTR(mtfsfix, 0xFC00010C);
XEREGISTERINSTR(fabsx, 0xFC000210);
XEREGISTERINSTR(fmrx, 0xFC000090);
XEREGISTERINSTR(fnabsx, 0xFC000110);
XEREGISTERINSTR(fnegx, 0xFC000050);
}
} // namespace ppc
} // namespace frontend
} // namespace alloy

View File

@ -1,930 +0,0 @@
/*
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <alloy/frontend/ppc/ppc_disasm-private.h>
using namespace alloy::frontend::ppc;
namespace alloy {
namespace frontend {
namespace ppc {
// Integer load (A-13)
XEDISASMR(lbz, 0x88000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lbz", "Load Byte and Zero", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lbzu, 0x8C000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lbzu", "Load Byte and Zero with Update", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lbzux, 0x7C0000EE, X )(InstrData& i, InstrDisasm& d) {
d.Init("lbzux", "Load Byte and Zero with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lbzx, 0x7C0000AE, X )(InstrData& i, InstrDisasm& d) {
d.Init("lbzx", "Load Byte and Zero Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(ld, 0xE8000000, DS )(InstrData& i, InstrDisasm& d) {
d.Init("ld", "Load Doubleword", 0);
d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kWrite);
if (i.DS.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.DS.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.DS.DS << 2), 2);
return d.Finish();
}
XEDISASMR(ldu, 0xE8000001, DS )(InstrData& i, InstrDisasm& d) {
d.Init("ldu", "Load Doubleword with Update", 0);
d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.DS.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.DS.DS << 2), 2);
return d.Finish();
}
XEDISASMR(ldux, 0x7C00006A, X )(InstrData& i, InstrDisasm& d) {
d.Init("ldux", "Load Doubleword with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(ldx, 0x7C00002A, X )(InstrData& i, InstrDisasm& d) {
d.Init("ldx", "Load Doubleword Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lha, 0xA8000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lha", "Load Halfword Algebraic", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lhau, 0xAC000000, D )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(lhaux, 0x7C0002EE, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(lhax, 0x7C0002AE, X )(InstrData& i, InstrDisasm& d) {
d.Init("lhax", "Load Halfword Algebraic Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lhz, 0xA0000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lhz", "Load Halfword and Zero", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lhzu, 0xA4000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lhzu", "Load Halfword and Zero with Update", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lhzux, 0x7C00026E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lhzux", "Load Halfword and Zero with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lhzx, 0x7C00022E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lhzx", "Load Halfword and Zero Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lwa, 0xE8000002, DS )(InstrData& i, InstrDisasm& d) {
d.Init("lwa", "Load Word Algebraic", 0);
d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.DS.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.DS.DS << 2), 2);
return d.Finish();
}
XEDISASMR(lwaux, 0x7C0002EA, X )(InstrData& i, InstrDisasm& d) {
d.Init("lwaux", "Load Word Algebraic with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lwax, 0x7C0002AA, X )(InstrData& i, InstrDisasm& d) {
d.Init("lwax", "Load Word Algebraic Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lwz, 0x80000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lwz", "Load Word and Zero", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lwzu, 0x84000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lwzu", "Load Word and Zero with Udpate", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lwzux, 0x7C00006E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lwzux", "Load Word and Zero with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lwzx, 0x7C00002E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lwzx", "Load Word and Zero Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
// Integer store (A-14)
XEDISASMR(stb, 0x98000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stb", "Store Byte", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(stbu, 0x9C000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stbu", "Store Byte with Update", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(stbux, 0x7C0001EE, X )(InstrData& i, InstrDisasm& d) {
d.Init("stbux", "Store Byte with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stbx, 0x7C0001AE, X )(InstrData& i, InstrDisasm& d) {
d.Init("stbx", "Store Byte Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.DS.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(std, 0xF8000000, DS )(InstrData& i, InstrDisasm& d) {
d.Init("std", "Store Doubleword", 0);
d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kRead);
if (i.DS.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.DS.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.DS.DS << 2), 2);
return d.Finish();
}
XEDISASMR(stdu, 0xF8000001, DS )(InstrData& i, InstrDisasm& d) {
d.Init("stdu", "Store Doubleword with Update", 0);
d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.DS.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.DS.DS << 2), 2);
return d.Finish();
}
XEDISASMR(stdux, 0x7C00016A, X )(InstrData& i, InstrDisasm& d) {
d.Init("stdux", "Store Doubleword with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stdx, 0x7C00012A, X )(InstrData& i, InstrDisasm& d) {
d.Init("stdx", "Store Doubleword Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(sth, 0xB0000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("sth", "Store Halfword", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(sthu, 0xB4000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("sthu", "Store Halfword with Update", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(sthux, 0x7C00036E, X )(InstrData& i, InstrDisasm& d) {
d.Init("sthux", "Store Halfword with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(sthx, 0x7C00032E, X )(InstrData& i, InstrDisasm& d) {
d.Init("sth", "Store Halfword Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stw, 0x90000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stw", "Store Word", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(stwu, 0x94000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stwu", "Store Word with Update", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(stwux, 0x7C00016E, X )(InstrData& i, InstrDisasm& d) {
d.Init("stwux", "Store Word with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stwx, 0x7C00012E, X )(InstrData& i, InstrDisasm& d) {
d.Init("stwx", "Store Word Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
// Integer load and store with byte reverse (A-1
XEDISASMR(lhbrx, 0x7C00062C, X )(InstrData& i, InstrDisasm& d) {
d.Init("lhbrx", "Load Halfword Byte-Reverse Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lwbrx, 0x7C00042C, X )(InstrData& i, InstrDisasm& d) {
d.Init("lwbrx", "Load Word Byte-Reverse Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(ldbrx, 0x7C000428, X )(InstrData& i, InstrDisasm& d) {
d.Init("ldbrx", "Load Doubleword Byte-Reverse Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(sthbrx, 0x7C00072C, X )(InstrData& i, InstrDisasm& d) {
d.Init("sthbrx", "Store Halfword Byte-Reverse Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stwbrx, 0x7C00052C, X )(InstrData& i, InstrDisasm& d) {
d.Init("stwbrx", "Store Word Byte-Reverse Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stdbrx, 0x7C000528, X )(InstrData& i, InstrDisasm& d) {
d.Init("stdbrx", "Store Doubleword Byte-Reverse Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
// Integer load and store multiple (A-16)
XEDISASMR(lmw, 0xB8000000, D )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(stmw, 0xBC000000, D )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
// Integer load and store string (A-17)
XEDISASMR(lswi, 0x7C0004AA, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(lswx, 0x7C00042A, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(stswi, 0x7C0005AA, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(stswx, 0x7C00052A, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
// Memory synchronization (A-18)
XEDISASMR(eieio, 0x7C0006AC, X )(InstrData& i, InstrDisasm& d) {
d.Init("eieio", "Enforce In-Order Execution of I/O Instruction", 0);
return d.Finish();
}
XEDISASMR(isync, 0x4C00012C, XL )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(ldarx, 0x7C0000A8, X )(InstrData& i, InstrDisasm& d) {
d.Init("ldarx", "Load Doubleword And Reserve Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lwarx, 0x7C000028, X )(InstrData& i, InstrDisasm& d) {
d.Init("lwarx", "Load Word And Reserve Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stdcx, 0x7C0001AD, X )(InstrData& i, InstrDisasm& d) {
d.Init("stdcx", "Store Doubleword Conditional Indexed",
InstrDisasm::kRc);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stwcx, 0x7C00012D, X )(InstrData& i, InstrDisasm& d) {
d.Init("stwcx", "Store Word Conditional Indexed",
InstrDisasm::kRc);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(sync, 0x7C0004AC, X )(InstrData& i, InstrDisasm& d) {
const char* name;
const char* desc;
int L = i.X.RT & 3;
switch (L) {
case 0:
name = "hwsync";
desc = "Synchronize (heavyweight)";
break;
case 1:
name = "lwsync";
desc = "Synchronize (lightweight)";
break;
default:
case 2:
case 3:
name = "sync";
desc = "Synchronize";
break;
}
d.Init(name, desc, 0);
d.AddUImmOperand(L, 1);
return d.Finish();
}
// Floating-point load (A-19)
XEDISASMR(lfd, 0xC8000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lfd", "Load Floating-Point Double", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lfdu, 0xCC000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lfdu", "Load Floating-Point Double with Update", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lfdux, 0x7C0004EE, X )(InstrData& i, InstrDisasm& d) {
d.Init("lfdux", "Load Floating-Point Double with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lfdx, 0x7C0004AE, X )(InstrData& i, InstrDisasm& d) {
d.Init("lfdx", "Load Floating-Point Double Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lfs, 0xC0000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lfs", "Load Floating-Point Single", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lfsu, 0xC4000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lfsu", "Load Floating-Point Single with Update", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(lfsux, 0x7C00046E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lfsux", "Load Floating-Point Single with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(lfsx, 0x7C00042E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lfsx", "Load Floating-Point Single Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
// Floating-point store (A-20)
XEDISASMR(stfd, 0xD8000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stfd", "Store Floating-Point Double", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(stfdu, 0xDC000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stfdu", "Store Floating-Point Double with Update", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(stfdux, 0x7C0005EE, X )(InstrData& i, InstrDisasm& d) {
d.Init("stfdux", "Store Floating-Point Double with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stfdx, 0x7C0005AE, X )(InstrData& i, InstrDisasm& d) {
d.Init("stfdx", "Store Floating-Point Double Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stfiwx, 0x7C0007AE, X )(InstrData& i, InstrDisasm& d) {
d.Init("stfiwx", "Store Floating-Point as Integer Word Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stfs, 0xD0000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stfs", "Store Floating-Point Single", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(stfsu, 0xD4000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stfsu", "Store Floating-Point Single with Update", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEDISASMR(stfsux, 0x7C00056E, X )(InstrData& i, InstrDisasm& d) {
d.Init("stfsux", "Store Floating-Point Single with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(stfsx, 0x7C00052E, X )(InstrData& i, InstrDisasm& d) {
d.Init("stfsx", "Store Floating-Point Single Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
// Cache management (A-27)
XEDISASMR(dcbf, 0x7C0000AC, X )(InstrData& i, InstrDisasm& d) {
d.Init("dcbf", "Data Cache Block Flush", 0);
/*
switch (i.X.RT & 3)
{
case 0: "dcbf";
case 1: "dcbfl"
case 2: RESERVED
case 3: "dcbflp"
}
*/
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(dcbst, 0x7C00006C, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
XEDISASMR(dcbt, 0x7C00022C, X )(InstrData& i, InstrDisasm& d) {
d.Init("dcbt", "Data Cache Block Touch", 0);
// TODO
return d.Finish();
}
XEDISASMR(dcbtst, 0x7C0001EC, X )(InstrData& i, InstrDisasm& d) {
d.Init("dcbtst", "Data Cache Block Touch for Store", 0);
// TODO
return d.Finish();
}
XEDISASMR(dcbz, 0x7C0007EC, X )(InstrData& i, InstrDisasm& d) {
// or dcbz128 0x7C2007EC
d.Init("dcbz", "Data Cache Block set to Zero", 0);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEDISASMR(icbi, 0x7C0007AC, X )(InstrData& i, InstrDisasm& d) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
void RegisterDisasmCategoryMemory() {
XEREGISTERINSTR(lbz, 0x88000000);
XEREGISTERINSTR(lbzu, 0x8C000000);
XEREGISTERINSTR(lbzux, 0x7C0000EE);
XEREGISTERINSTR(lbzx, 0x7C0000AE);
XEREGISTERINSTR(ld, 0xE8000000);
XEREGISTERINSTR(ldu, 0xE8000001);
XEREGISTERINSTR(ldux, 0x7C00006A);
XEREGISTERINSTR(ldx, 0x7C00002A);
XEREGISTERINSTR(lha, 0xA8000000);
XEREGISTERINSTR(lhau, 0xAC000000);
XEREGISTERINSTR(lhaux, 0x7C0002EE);
XEREGISTERINSTR(lhax, 0x7C0002AE);
XEREGISTERINSTR(lhz, 0xA0000000);
XEREGISTERINSTR(lhzu, 0xA4000000);
XEREGISTERINSTR(lhzux, 0x7C00026E);
XEREGISTERINSTR(lhzx, 0x7C00022E);
XEREGISTERINSTR(lwa, 0xE8000002);
XEREGISTERINSTR(lwaux, 0x7C0002EA);
XEREGISTERINSTR(lwax, 0x7C0002AA);
XEREGISTERINSTR(lwz, 0x80000000);
XEREGISTERINSTR(lwzu, 0x84000000);
XEREGISTERINSTR(lwzux, 0x7C00006E);
XEREGISTERINSTR(lwzx, 0x7C00002E);
XEREGISTERINSTR(stb, 0x98000000);
XEREGISTERINSTR(stbu, 0x9C000000);
XEREGISTERINSTR(stbux, 0x7C0001EE);
XEREGISTERINSTR(stbx, 0x7C0001AE);
XEREGISTERINSTR(std, 0xF8000000);
XEREGISTERINSTR(stdu, 0xF8000001);
XEREGISTERINSTR(stdux, 0x7C00016A);
XEREGISTERINSTR(stdx, 0x7C00012A);
XEREGISTERINSTR(sth, 0xB0000000);
XEREGISTERINSTR(sthu, 0xB4000000);
XEREGISTERINSTR(sthux, 0x7C00036E);
XEREGISTERINSTR(sthx, 0x7C00032E);
XEREGISTERINSTR(stw, 0x90000000);
XEREGISTERINSTR(stwu, 0x94000000);
XEREGISTERINSTR(stwux, 0x7C00016E);
XEREGISTERINSTR(stwx, 0x7C00012E);
XEREGISTERINSTR(lhbrx, 0x7C00062C);
XEREGISTERINSTR(lwbrx, 0x7C00042C);
XEREGISTERINSTR(ldbrx, 0x7C000428);
XEREGISTERINSTR(sthbrx, 0x7C00072C);
XEREGISTERINSTR(stwbrx, 0x7C00052C);
XEREGISTERINSTR(stdbrx, 0x7C000528);
XEREGISTERINSTR(lmw, 0xB8000000);
XEREGISTERINSTR(stmw, 0xBC000000);
XEREGISTERINSTR(lswi, 0x7C0004AA);
XEREGISTERINSTR(lswx, 0x7C00042A);
XEREGISTERINSTR(stswi, 0x7C0005AA);
XEREGISTERINSTR(stswx, 0x7C00052A);
XEREGISTERINSTR(eieio, 0x7C0006AC);
XEREGISTERINSTR(isync, 0x4C00012C);
XEREGISTERINSTR(ldarx, 0x7C0000A8);
XEREGISTERINSTR(lwarx, 0x7C000028);
XEREGISTERINSTR(stdcx, 0x7C0001AD);
XEREGISTERINSTR(stwcx, 0x7C00012D);
XEREGISTERINSTR(sync, 0x7C0004AC);
XEREGISTERINSTR(lfd, 0xC8000000);
XEREGISTERINSTR(lfdu, 0xCC000000);
XEREGISTERINSTR(lfdux, 0x7C0004EE);
XEREGISTERINSTR(lfdx, 0x7C0004AE);
XEREGISTERINSTR(lfs, 0xC0000000);
XEREGISTERINSTR(lfsu, 0xC4000000);
XEREGISTERINSTR(lfsux, 0x7C00046E);
XEREGISTERINSTR(lfsx, 0x7C00042E);
XEREGISTERINSTR(stfd, 0xD8000000);
XEREGISTERINSTR(stfdu, 0xDC000000);
XEREGISTERINSTR(stfdux, 0x7C0005EE);
XEREGISTERINSTR(stfdx, 0x7C0005AE);
XEREGISTERINSTR(stfiwx, 0x7C0007AE);
XEREGISTERINSTR(stfs, 0xD0000000);
XEREGISTERINSTR(stfsu, 0xD4000000);
XEREGISTERINSTR(stfsux, 0x7C00056E);
XEREGISTERINSTR(stfsx, 0x7C00052E);
XEREGISTERINSTR(dcbf, 0x7C0000AC);
XEREGISTERINSTR(dcbst, 0x7C00006C);
XEREGISTERINSTR(dcbt, 0x7C00022C);
XEREGISTERINSTR(dcbtst, 0x7C0001EC);
XEREGISTERINSTR(dcbz, 0x7C0007EC);
XEREGISTERINSTR(icbi, 0x7C0007AC);
}
} // namespace ppc
} // namespace frontend
} // namespace alloy

View File

@ -32,12 +32,6 @@ namespace {
}
has_initialized = true;
RegisterDisasmCategoryAltivec();
RegisterDisasmCategoryALU();
RegisterDisasmCategoryControl();
RegisterDisasmCategoryFPU();
RegisterDisasmCategoryMemory();
RegisterEmitCategoryAltivec();
RegisterEmitCategoryALU();
RegisterEmitCategoryControl();

View File

@ -11,6 +11,7 @@
#include <alloy/frontend/tracing.h>
#include <alloy/frontend/ppc/ppc_context.h>
#include <alloy/frontend/ppc/ppc_disasm.h>
#include <alloy/frontend/ppc/ppc_frontend.h>
#include <alloy/frontend/ppc/ppc_instr.h>
#include <alloy/hir/label.h>
@ -26,9 +27,11 @@ using namespace alloy::runtime;
PPCHIRBuilder::PPCHIRBuilder(PPCFrontend* frontend) :
frontend_(frontend),
HIRBuilder() {
comment_buffer_ = new StringBuffer(4096);
}
PPCHIRBuilder::~PPCHIRBuilder() {
delete comment_buffer_;
}
void PPCHIRBuilder::Reset() {
@ -96,17 +99,9 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, bool with_debug_info) {
if (label) {
AnnotateLabel(address, label);
}
if (!i.type) {
Comment("%.8X %.8X ???", address, i.code);
} else if (i.type->disassemble) {
ppc::InstrDisasm d;
i.type->disassemble(i, d);
std::string disasm;
d.Dump(disasm);
Comment("%.8X %.8X %s", address, i.code, disasm.c_str());
} else {
Comment("%.8X %.8X %s ???", address, i.code, i.type->name);
}
comment_buffer_->Reset();
DisasmPPC(i, comment_buffer_);
Comment("%.8X %.8X %s", address, i.code, comment_buffer_->GetString());
first_instr = last_instr();
}

View File

@ -74,6 +74,9 @@ private:
private:
PPCFrontend* frontend_;
// Reset whenever needed:
StringBuffer* comment_buffer_;
// Reset each Emit:
bool with_debug_info_;
runtime::FunctionInfo* symbol_info_;

View File

@ -283,114 +283,37 @@ void InstrAccessBits::Dump(std::string& out_str) {
void InstrDisasm::Init(const char* name, const char* info, uint32_t flags) {
operands.clear();
special_registers.clear();
access_bits.Clear();
this->name = name;
this->info = info;
this->flags = flags;
if (flags & InstrDisasm::kOE) {
InstrRegister i = {
InstrRegister::kXER, 0, InstrRegister::kReadWrite
};
special_registers.push_back(i);
}
if (flags & InstrDisasm::kRc) {
InstrRegister i = {
InstrRegister::kCR, 0, InstrRegister::kWrite
};
special_registers.push_back(i);
}
if (flags & InstrDisasm::kCA) {
InstrRegister i = {
InstrRegister::kXER, 0, InstrRegister::kReadWrite
};
special_registers.push_back(i);
}
if (flags & InstrDisasm::kLR) {
InstrRegister i = {
InstrRegister::kLR, 0, InstrRegister::kWrite
};
special_registers.push_back(i);
}
}
void InstrDisasm::AddLR(InstrRegister::Access access) {
InstrRegister i = {
InstrRegister::kLR, 0, access
};
special_registers.push_back(i);
}
void InstrDisasm::AddCTR(InstrRegister::Access access) {
InstrRegister i = {
InstrRegister::kCTR, 0, access
};
special_registers.push_back(i);
}
void InstrDisasm::AddCR(uint32_t bf, InstrRegister::Access access) {
InstrRegister i = {
InstrRegister::kCR, bf, access
};
special_registers.push_back(i);
}
void InstrDisasm::AddFPSCR(InstrRegister::Access access) {
InstrRegister i = {
InstrRegister::kFPSCR, 0, access
};
special_registers.push_back(i);
}
void InstrDisasm::AddRegOperand(
InstrRegister::RegisterSet set, uint32_t ordinal,
InstrRegister::Access access, const char* display) {
InstrRegister i = {
set, ordinal, access
};
InstrOperand o;
o.type = InstrOperand::kRegister;
o.reg = i;
o.display = display;
operands.push_back(o);
}
void InstrDisasm::AddSImmOperand(uint64_t value, size_t width,
const char* display) {
InstrOperand o;
o.type = InstrOperand::kImmediate;
o.imm.is_signed = true;
o.imm.value = value;
o.imm.width = width;
o.display = display;
operands.push_back(o);
}
void InstrDisasm::AddUImmOperand(uint64_t value, size_t width,
const char* display) {
InstrOperand o;
o.type = InstrOperand::kImmediate;
o.imm.is_signed = false;
o.imm.value = value;
o.imm.width = width;
o.display = display;
operands.push_back(o);
}
int InstrDisasm::Finish() {
for (std::vector<InstrOperand>::iterator it = operands.begin();
it != operands.end(); ++it) {
if (it->type == InstrOperand::kRegister) {
access_bits.MarkAccess(it->reg);
}
}
for (std::vector<InstrRegister>::iterator it = special_registers.begin();
it != special_registers.end(); ++it) {
access_bits.MarkAccess(*it);
}
return 0;
}
@ -405,19 +328,6 @@ void InstrDisasm::Dump(std::string& out_str, size_t pad) {
if (flags & InstrDisasm::kLR) {
out_str += "l";
}
if (operands.size()) {
if (pad && out_str.size() < pad) {
out_str += std::string(pad - out_str.size(), ' ');
}
for (std::vector<InstrOperand>::iterator it = operands.begin();
it != operands.end(); ++it) {
it->Dump(out_str);
if (it + 1 != operands.end()) {
out_str += ", ";
}
}
}
}
@ -480,18 +390,6 @@ InstrType* alloy::frontend::ppc::GetInstrType(uint32_t code) {
return NULL;
}
int alloy::frontend::ppc::RegisterInstrDisassemble(
uint32_t code, InstrDisassembleFn disassemble) {
InstrType* instr_type = GetInstrType(code);
XEASSERTNOTNULL(instr_type);
if (!instr_type) {
return 1;
}
XEASSERTNULL(instr_type->disassemble);
instr_type->disassemble = disassemble;
return 0;
}
int alloy::frontend::ppc::RegisterInstrEmit(uint32_t code, InstrEmitFn emit) {
InstrType* instr_type = GetInstrType(code);
XEASSERTNOTNULL(instr_type);

View File

@ -481,9 +481,6 @@ public:
const char* name;
const char* info;
uint32_t flags;
std::vector<InstrOperand> operands;
std::vector<InstrRegister> special_registers;
InstrAccessBits access_bits;
void Init(const char* name, const char* info, uint32_t flags);
void AddLR(InstrRegister::Access access);
@ -500,7 +497,7 @@ public:
};
typedef int (*InstrDisassembleFn)(InstrData& i, InstrDisasm& d);
typedef void (*InstrDisasmFn)(InstrData& i, StringBuffer* str);
typedef void* InstrEmitFn;
@ -511,14 +508,13 @@ public:
uint32_t format; // xe_ppc_instr_format_e
uint32_t type; // xe_ppc_instr_type_e
uint32_t flags; // xe_ppc_instr_flag_e
InstrDisasmFn disasm;
char name[16];
InstrDisassembleFn disassemble;
InstrEmitFn emit;
};
InstrType* GetInstrType(uint32_t code);
int RegisterInstrDisassemble(uint32_t code, InstrDisassembleFn disassemble);
int RegisterInstrEmit(uint32_t code, InstrEmitFn emit);

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@
#include <alloy/alloy-private.h>
#include <alloy/compiler/compiler_passes.h>
#include <alloy/frontend/tracing.h>
#include <alloy/frontend/ppc/ppc_disasm.h>
#include <alloy/frontend/ppc/ppc_frontend.h>
#include <alloy/frontend/ppc/ppc_hir_builder.h>
#include <alloy/frontend/ppc/ppc_instr.h>
@ -161,17 +162,8 @@ void PPCTranslator::DumpSource(
++block_it;
}
if (!i.type) {
string_buffer->Append("%.8X %.8X ???", address, i.code);
} else if (i.type->disassemble) {
ppc::InstrDisasm d;
i.type->disassemble(i, d);
std::string disasm;
d.Dump(disasm);
string_buffer->Append("%.8X %.8X %s", address, i.code, disasm.c_str());
} else {
string_buffer->Append("%.8X %.8X %s ???", address, i.code, i.type->name);
}
string_buffer->Append("%.8X %.8X ", address, i.code);
DisasmPPC(i, string_buffer);
string_buffer->Append("\n");
}
}

View File

@ -3,13 +3,8 @@
'sources': [
'ppc_context.cc',
'ppc_context.h',
'ppc_disasm-private.h',
'ppc_disasm.cc',
'ppc_disasm.h',
'ppc_disasm_altivec.cc',
'ppc_disasm_alu.cc',
'ppc_disasm_control.cc',
'ppc_disasm_fpu.cc',
'ppc_disasm_memory.cc',
'ppc_emit-private.h',
'ppc_emit.h',
'ppc_emit_altivec.cc',