Initial Alloy implementation.
This is a regression in functionality and performance, but a much better foundation for the future of the project (I think). It can run basic apps under an SSA interpreter but doesn't support some of the features required to do real 360 apps yet.
This commit is contained in:
@@ -1,42 +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 XENIA_CPU_PPC_DISASM_H_
|
||||
#define XENIA_CPU_PPC_DISASM_H_
|
||||
|
||||
#include <xenia/cpu/ppc/instr.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace ppc {
|
||||
|
||||
|
||||
void RegisterDisasmCategoryAltivec();
|
||||
void RegisterDisasmCategoryALU();
|
||||
void RegisterDisasmCategoryControl();
|
||||
void RegisterDisasmCategoryFPU();
|
||||
void RegisterDisasmCategoryMemory();
|
||||
|
||||
|
||||
#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 cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_PPC_DISASM_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,728 +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 <xenia/cpu/ppc/disasm.h>
|
||||
|
||||
|
||||
using namespace xe::cpu::ppc;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
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("no-op", "OR Immediate", 0);
|
||||
} 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 cpu
|
||||
} // namespace xe
|
||||
@@ -1,276 +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 <xenia/cpu/ppc/disasm.h>
|
||||
|
||||
|
||||
using namespace xe::cpu::ppc;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
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 = XEEXTS26(i.I.LI << 2);
|
||||
} else {
|
||||
nia = 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);
|
||||
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 cpu
|
||||
} // namespace xe
|
||||
@@ -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 <xenia/cpu/ppc/disasm.h>
|
||||
|
||||
|
||||
using namespace xe::cpu::ppc;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
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 cpu
|
||||
} // namespace xe
|
||||
@@ -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 <xenia/cpu/ppc/disasm.h>
|
||||
|
||||
|
||||
using namespace xe::cpu::ppc;
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
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 cpu
|
||||
} // namespace xe
|
||||
@@ -1,502 +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 <xenia/cpu/ppc/instr.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <xenia/cpu/ppc/instr_tables.h>
|
||||
|
||||
|
||||
using namespace xe::cpu::ppc;
|
||||
|
||||
|
||||
void InstrOperand::Dump(std::string& out_str) {
|
||||
if (display) {
|
||||
out_str += display;
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[32];
|
||||
const size_t max_count = XECOUNT(buffer);
|
||||
switch (type) {
|
||||
case InstrOperand::kRegister:
|
||||
switch (reg.set) {
|
||||
case InstrRegister::kXER:
|
||||
xesnprintfa(buffer, max_count, "XER");
|
||||
break;
|
||||
case InstrRegister::kLR:
|
||||
xesnprintfa(buffer, max_count, "LR");
|
||||
break;
|
||||
case InstrRegister::kCTR:
|
||||
xesnprintfa(buffer, max_count, "CTR");
|
||||
break;
|
||||
case InstrRegister::kCR:
|
||||
xesnprintfa(buffer, max_count, "CR%d", reg.ordinal);
|
||||
break;
|
||||
case InstrRegister::kFPSCR:
|
||||
xesnprintfa(buffer, max_count, "FPSCR");
|
||||
break;
|
||||
case InstrRegister::kGPR:
|
||||
xesnprintfa(buffer, max_count, "r%d", reg.ordinal);
|
||||
break;
|
||||
case InstrRegister::kFPR:
|
||||
xesnprintfa(buffer, max_count, "f%d", reg.ordinal);
|
||||
break;
|
||||
case InstrRegister::kVMX:
|
||||
xesnprintfa(buffer, max_count, "vr%d", reg.ordinal);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case InstrOperand::kImmediate:
|
||||
switch (imm.width) {
|
||||
case 1:
|
||||
if (imm.is_signed) {
|
||||
xesnprintfa(buffer, max_count, "%d", (int32_t)(int8_t)imm.value);
|
||||
} else {
|
||||
xesnprintfa(buffer, max_count, "0x%.2X", (uint8_t)imm.value);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (imm.is_signed) {
|
||||
xesnprintfa(buffer, max_count, "%d", (int32_t)(int16_t)imm.value);
|
||||
} else {
|
||||
xesnprintfa(buffer, max_count, "0x%.4X", (uint16_t)imm.value);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (imm.is_signed) {
|
||||
xesnprintfa(buffer, max_count, "%d", (int32_t)imm.value);
|
||||
} else {
|
||||
xesnprintfa(buffer, max_count, "0x%.8X", (uint32_t)imm.value);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (imm.is_signed) {
|
||||
xesnprintfa(buffer, max_count, "%lld", (int64_t)imm.value);
|
||||
} else {
|
||||
xesnprintfa(buffer, max_count, "0x%.16llX", imm.value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
out_str += buffer;
|
||||
}
|
||||
|
||||
|
||||
void InstrAccessBits::Clear() {
|
||||
spr = cr = gpr = fpr = 0;
|
||||
}
|
||||
|
||||
void InstrAccessBits::Extend(InstrAccessBits& other) {
|
||||
spr |= other.spr;
|
||||
cr |= other.cr;
|
||||
gpr |= other.gpr;
|
||||
fpr |= other.fpr;
|
||||
vr31_0 |= other.vr31_0;
|
||||
vr63_32 |= other.vr63_32;
|
||||
vr95_64 |= other.vr95_64;
|
||||
vr127_96 |= other.vr127_96;
|
||||
}
|
||||
|
||||
void InstrAccessBits::MarkAccess(InstrRegister& reg) {
|
||||
uint64_t bits = 0;
|
||||
if (reg.access & InstrRegister::kRead) {
|
||||
bits |= 0x1;
|
||||
}
|
||||
if (reg.access & InstrRegister::kWrite) {
|
||||
bits |= 0x2;
|
||||
}
|
||||
|
||||
switch (reg.set) {
|
||||
case InstrRegister::kXER:
|
||||
spr |= bits << (2 * 0);
|
||||
break;
|
||||
case InstrRegister::kLR:
|
||||
spr |= bits << (2 * 1);
|
||||
break;
|
||||
case InstrRegister::kCTR:
|
||||
spr |= bits << (2 * 2);
|
||||
break;
|
||||
case InstrRegister::kCR:
|
||||
cr |= bits << (2 * reg.ordinal);
|
||||
break;
|
||||
case InstrRegister::kFPSCR:
|
||||
spr |= bits << (2 * 3);
|
||||
break;
|
||||
case InstrRegister::kGPR:
|
||||
gpr |= bits << (2 * reg.ordinal);
|
||||
break;
|
||||
case InstrRegister::kFPR:
|
||||
fpr |= bits << (2 * reg.ordinal);
|
||||
break;
|
||||
case InstrRegister::kVMX:
|
||||
if (reg.ordinal < 32) {
|
||||
vr31_0 |= bits << (2 * reg.ordinal);
|
||||
} else if (reg.ordinal < 64) {
|
||||
vr63_32 |= bits << (2 * (reg.ordinal - 32));
|
||||
} else if (reg.ordinal < 96) {
|
||||
vr95_64 |= bits << (2 * (reg.ordinal - 64));
|
||||
} else {
|
||||
vr127_96 |= bits << (2 * (reg.ordinal - 96));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
XEASSERTALWAYS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InstrAccessBits::Dump(std::string& out_str) {
|
||||
std::stringstream str;
|
||||
if (spr) {
|
||||
uint64_t spr_t = spr;
|
||||
if (spr_t & 0x3) {
|
||||
str << "XER [";
|
||||
str << ((spr_t & 1) ? "R" : " ");
|
||||
str << ((spr_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
spr_t >>= 2;
|
||||
if (spr_t & 0x3) {
|
||||
str << "LR [";
|
||||
str << ((spr_t & 1) ? "R" : " ");
|
||||
str << ((spr_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
spr_t >>= 2;
|
||||
if (spr_t & 0x3) {
|
||||
str << "CTR [";
|
||||
str << ((spr_t & 1) ? "R" : " ");
|
||||
str << ((spr_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
spr_t >>= 2;
|
||||
if (spr_t & 0x3) {
|
||||
str << "FPCSR [";
|
||||
str << ((spr_t & 1) ? "R" : " ");
|
||||
str << ((spr_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
spr_t >>= 2;
|
||||
}
|
||||
|
||||
if (cr) {
|
||||
uint64_t cr_t = cr;
|
||||
for (size_t n = 0; n < 8; n++) {
|
||||
if (cr_t & 0x3) {
|
||||
str << "cr" << n << " [";
|
||||
str << ((cr_t & 1) ? "R" : " ");
|
||||
str << ((cr_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
cr_t >>= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpr) {
|
||||
uint64_t gpr_t = gpr;
|
||||
for (size_t n = 0; n < 32; n++) {
|
||||
if (gpr_t & 0x3) {
|
||||
str << "r" << n << " [";
|
||||
str << ((gpr_t & 1) ? "R" : " ");
|
||||
str << ((gpr_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
gpr_t >>= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (fpr) {
|
||||
uint64_t fpr_t = fpr;
|
||||
for (size_t n = 0; n < 32; n++) {
|
||||
if (fpr_t & 0x3) {
|
||||
str << "f" << n << " [";
|
||||
str << ((fpr_t & 1) ? "R" : " ");
|
||||
str << ((fpr_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
fpr_t >>= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (vr31_0) {
|
||||
uint64_t vr31_0_t = vr31_0;
|
||||
for (size_t n = 0; n < 32; n++) {
|
||||
if (vr31_0_t & 0x3) {
|
||||
str << "vr" << n << " [";
|
||||
str << ((vr31_0_t & 1) ? "R" : " ");
|
||||
str << ((vr31_0_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
vr31_0_t >>= 2;
|
||||
}
|
||||
}
|
||||
if (vr63_32) {
|
||||
uint64_t vr63_32_t = vr63_32;
|
||||
for (size_t n = 0; n < 32; n++) {
|
||||
if (vr63_32_t & 0x3) {
|
||||
str << "vr" << (n + 32) << " [";
|
||||
str << ((vr63_32_t & 1) ? "R" : " ");
|
||||
str << ((vr63_32_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
vr63_32_t >>= 2;
|
||||
}
|
||||
}
|
||||
if (vr95_64) {
|
||||
uint64_t vr95_64_t = vr95_64;
|
||||
for (size_t n = 0; n < 32; n++) {
|
||||
if (vr95_64_t & 0x3) {
|
||||
str << "vr" << (n + 64) << " [";
|
||||
str << ((vr95_64_t & 1) ? "R" : " ");
|
||||
str << ((vr95_64_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
vr95_64_t >>= 2;
|
||||
}
|
||||
}
|
||||
if (vr127_96) {
|
||||
uint64_t vr127_96_t = vr127_96;
|
||||
for (size_t n = 0; n < 32; n++) {
|
||||
if (vr127_96_t & 0x3) {
|
||||
str << "vr" << (n + 96) << " [";
|
||||
str << ((vr127_96_t & 1) ? "R" : " ");
|
||||
str << ((vr127_96_t & 2) ? "W" : " ");
|
||||
str << "] ";
|
||||
}
|
||||
vr127_96_t >>= 2;
|
||||
}
|
||||
}
|
||||
|
||||
out_str = str.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;
|
||||
}
|
||||
|
||||
void InstrDisasm::Dump(std::string& out_str, size_t pad) {
|
||||
out_str = name;
|
||||
if (flags & InstrDisasm::kOE) {
|
||||
out_str += "o";
|
||||
}
|
||||
if (flags & InstrDisasm::kRc) {
|
||||
out_str += ".";
|
||||
}
|
||||
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 += ", ";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
InstrType* xe::cpu::ppc::GetInstrType(uint32_t code) {
|
||||
// Fast lookup via tables.
|
||||
InstrType* slot = NULL;
|
||||
switch (code >> 26) {
|
||||
case 4:
|
||||
// Opcode = 4, index = bits 10-0 (10)
|
||||
slot = xe::cpu::ppc::tables::instr_table_4[XESELECTBITS(code, 0, 10)];
|
||||
break;
|
||||
case 19:
|
||||
// Opcode = 19, index = bits 10-1 (10)
|
||||
slot = xe::cpu::ppc::tables::instr_table_19[XESELECTBITS(code, 1, 10)];
|
||||
break;
|
||||
case 30:
|
||||
// Opcode = 30, index = bits 4-1 (4)
|
||||
// Special cased to an uber instruction.
|
||||
slot = xe::cpu::ppc::tables::instr_table_30[XESELECTBITS(code, 0, 0)];
|
||||
// slot = &xe::cpu::ppc::tables::instr_table_30[XESELECTBITS(code, 1, 4)];
|
||||
break;
|
||||
case 31:
|
||||
// Opcode = 31, index = bits 10-1 (10)
|
||||
slot = xe::cpu::ppc::tables::instr_table_31[XESELECTBITS(code, 1, 10)];
|
||||
break;
|
||||
case 58:
|
||||
// Opcode = 58, index = bits 1-0 (2)
|
||||
slot = xe::cpu::ppc::tables::instr_table_58[XESELECTBITS(code, 0, 1)];
|
||||
break;
|
||||
case 59:
|
||||
// Opcode = 59, index = bits 5-1 (5)
|
||||
slot = xe::cpu::ppc::tables::instr_table_59[XESELECTBITS(code, 1, 5)];
|
||||
break;
|
||||
case 62:
|
||||
// Opcode = 62, index = bits 1-0 (2)
|
||||
slot = xe::cpu::ppc::tables::instr_table_62[XESELECTBITS(code, 0, 1)];
|
||||
break;
|
||||
case 63:
|
||||
// Opcode = 63, index = bits 10-1 (10)
|
||||
slot = xe::cpu::ppc::tables::instr_table_63[XESELECTBITS(code, 1, 10)];
|
||||
break;
|
||||
default:
|
||||
slot = xe::cpu::ppc::tables::instr_table[XESELECTBITS(code, 26, 31)];
|
||||
break;
|
||||
}
|
||||
if (slot && slot->opcode) {
|
||||
return slot;
|
||||
}
|
||||
|
||||
// Slow lookup via linear scan.
|
||||
// This is primarily due to laziness. It could be made fast like the others.
|
||||
for (size_t n = 0; n < XECOUNT(xe::cpu::ppc::tables::instr_table_scan);
|
||||
n++) {
|
||||
slot = &(xe::cpu::ppc::tables::instr_table_scan[n]);
|
||||
if (slot->opcode == (code & slot->opcode_mask)) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int xe::cpu::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 xe::cpu::ppc::RegisterInstrEmit(uint32_t code, InstrEmitFn emit) {
|
||||
InstrType* instr_type = GetInstrType(code);
|
||||
XEASSERTNOTNULL(instr_type);
|
||||
if (!instr_type) {
|
||||
return 1;
|
||||
}
|
||||
XEASSERTNULL(instr_type->emit);
|
||||
instr_type->emit = emit;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,531 +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 XENIA_CPU_PPC_INSTR_H_
|
||||
#define XENIA_CPU_PPC_INSTR_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace ppc {
|
||||
|
||||
|
||||
// TODO(benvanik): rename these
|
||||
typedef enum {
|
||||
kXEPPCInstrFormatI = 0,
|
||||
kXEPPCInstrFormatB = 1,
|
||||
kXEPPCInstrFormatSC = 2,
|
||||
kXEPPCInstrFormatD = 3,
|
||||
kXEPPCInstrFormatDS = 4,
|
||||
kXEPPCInstrFormatX = 5,
|
||||
kXEPPCInstrFormatXL = 6,
|
||||
kXEPPCInstrFormatXFX = 7,
|
||||
kXEPPCInstrFormatXFL = 8,
|
||||
kXEPPCInstrFormatXS = 9,
|
||||
kXEPPCInstrFormatXO = 10,
|
||||
kXEPPCInstrFormatA = 11,
|
||||
kXEPPCInstrFormatM = 12,
|
||||
kXEPPCInstrFormatMD = 13,
|
||||
kXEPPCInstrFormatMDS = 14,
|
||||
kXEPPCInstrFormatVXA = 15,
|
||||
kXEPPCInstrFormatVX = 16,
|
||||
kXEPPCInstrFormatVXR = 17,
|
||||
kXEPPCInstrFormatVX128 = 18,
|
||||
kXEPPCInstrFormatVX128_1 = 19,
|
||||
kXEPPCInstrFormatVX128_2 = 20,
|
||||
kXEPPCInstrFormatVX128_3 = 21,
|
||||
kXEPPCInstrFormatVX128_4 = 22,
|
||||
kXEPPCInstrFormatVX128_5 = 23,
|
||||
kXEPPCInstrFormatVX128_P = 24,
|
||||
kXEPPCInstrFormatVX128_R = 25,
|
||||
kXEPPCInstrFormatXDSS = 26,
|
||||
} xe_ppc_instr_format_e;
|
||||
|
||||
typedef enum {
|
||||
kXEPPCInstrMaskVXR = 0xFC0003FF,
|
||||
kXEPPCInstrMaskVXA = 0xFC00003F,
|
||||
kXEPPCInstrMaskVX128 = 0xFC0003D0,
|
||||
kXEPPCInstrMaskVX128_1 = 0xFC0007F3,
|
||||
kXEPPCInstrMaskVX128_2 = 0xFC000210,
|
||||
kXEPPCInstrMaskVX128_3 = 0xFC0007F0,
|
||||
kXEPPCInstrMaskVX128_4 = 0xFC000730,
|
||||
kXEPPCInstrMaskVX128_5 = 0xFC000010,
|
||||
kXEPPCInstrMaskVX128_P = 0xFC000630,
|
||||
kXEPPCInstrMaskVX128_R = 0xFC000390,
|
||||
} xe_ppc_instr_mask_e;
|
||||
|
||||
typedef enum {
|
||||
kXEPPCInstrTypeGeneral = (1 << 0),
|
||||
kXEPPCInstrTypeBranch = (1 << 1),
|
||||
kXEPPCInstrTypeBranchCond = kXEPPCInstrTypeBranch | (1 << 2),
|
||||
kXEPPCInstrTypeBranchAlways = kXEPPCInstrTypeBranch | (1 << 3),
|
||||
kXEPPCInstrTypeSyscall = (1 << 4),
|
||||
} xe_ppc_instr_type_e;
|
||||
|
||||
typedef enum {
|
||||
kXEPPCInstrFlagReserved = 0,
|
||||
} xe_ppc_instr_flag_e;
|
||||
|
||||
|
||||
class InstrType;
|
||||
|
||||
|
||||
static inline int32_t XEEXTS16(uint32_t v) {
|
||||
return (int32_t)((int16_t)v);
|
||||
}
|
||||
static inline int32_t XEEXTS26(uint32_t v) {
|
||||
return v & 0x02000000 ? (int32_t)v | 0xFC000000 : (int32_t)(v);
|
||||
}
|
||||
static inline uint32_t XEEXTZ16(uint32_t v) {
|
||||
return (uint32_t)((uint16_t)v);
|
||||
}
|
||||
static inline uint64_t XEMASK(uint32_t mstart, uint32_t mstop) {
|
||||
// if mstart ≤ mstop then
|
||||
// mask[mstart:mstop] = ones
|
||||
// mask[all other bits] = zeros
|
||||
// else
|
||||
// mask[mstart:63] = ones
|
||||
// mask[0:mstop] = ones
|
||||
// mask[all other bits] = zeros
|
||||
mstart &= 0x3F;
|
||||
mstop &= 0x3F;
|
||||
uint64_t value =
|
||||
(UINT64_MAX >> mstart) ^ ((mstop >= 63) ? 0 : UINT64_MAX >> (mstop + 1));
|
||||
return mstart <= mstop ? value : ~value;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
InstrType* type;
|
||||
uint32_t address;
|
||||
|
||||
union {
|
||||
uint32_t code;
|
||||
|
||||
// kXEPPCInstrFormatI
|
||||
struct {
|
||||
uint32_t LK : 1;
|
||||
uint32_t AA : 1;
|
||||
uint32_t LI : 24;
|
||||
uint32_t : 6;
|
||||
} I;
|
||||
// kXEPPCInstrFormatB
|
||||
struct {
|
||||
uint32_t LK : 1;
|
||||
uint32_t AA : 1;
|
||||
uint32_t BD : 14;
|
||||
uint32_t BI : 5;
|
||||
uint32_t BO : 5;
|
||||
uint32_t : 6;
|
||||
} B;
|
||||
|
||||
// kXEPPCInstrFormatSC
|
||||
// kXEPPCInstrFormatD
|
||||
struct {
|
||||
uint32_t DS : 16;
|
||||
uint32_t RA : 5;
|
||||
uint32_t RT : 5;
|
||||
uint32_t : 6;
|
||||
} D;
|
||||
// kXEPPCInstrFormatDS
|
||||
struct {
|
||||
uint32_t : 2;
|
||||
uint32_t DS : 14;
|
||||
uint32_t RA : 5;
|
||||
uint32_t RT : 5;
|
||||
uint32_t : 6;
|
||||
} DS;
|
||||
// kXEPPCInstrFormatX
|
||||
struct {
|
||||
uint32_t Rc : 1;
|
||||
uint32_t : 10;
|
||||
uint32_t RB : 5;
|
||||
uint32_t RA : 5;
|
||||
uint32_t RT : 5;
|
||||
uint32_t : 6;
|
||||
} X;
|
||||
// kXEPPCInstrFormatXL
|
||||
struct {
|
||||
uint32_t LK : 1;
|
||||
uint32_t : 10;
|
||||
uint32_t BB : 5;
|
||||
uint32_t BI : 5;
|
||||
uint32_t BO : 5;
|
||||
uint32_t : 6;
|
||||
} XL;
|
||||
// kXEPPCInstrFormatXFX
|
||||
struct {
|
||||
uint32_t : 1;
|
||||
uint32_t : 10;
|
||||
uint32_t spr : 10;
|
||||
uint32_t RT : 5;
|
||||
uint32_t : 6;
|
||||
} XFX;
|
||||
// kXEPPCInstrFormatXFL
|
||||
struct {
|
||||
uint32_t Rc : 1;
|
||||
uint32_t : 10;
|
||||
uint32_t RB : 5;
|
||||
uint32_t : 1;
|
||||
uint32_t FM : 8;
|
||||
uint32_t : 1;
|
||||
uint32_t : 6;
|
||||
} XFL;
|
||||
// kXEPPCInstrFormatXS
|
||||
struct {
|
||||
uint32_t Rc : 1;
|
||||
uint32_t SH5 : 1;
|
||||
uint32_t : 9;
|
||||
uint32_t SH : 5;
|
||||
uint32_t RA : 5;
|
||||
uint32_t RT : 5;
|
||||
uint32_t : 6;
|
||||
} XS;
|
||||
// kXEPPCInstrFormatXO
|
||||
struct {
|
||||
uint32_t Rc : 1;
|
||||
uint32_t : 9;
|
||||
uint32_t OE : 1;
|
||||
uint32_t RB : 5;
|
||||
uint32_t RA : 5;
|
||||
uint32_t RT : 5;
|
||||
uint32_t : 6;
|
||||
} XO;
|
||||
// kXEPPCInstrFormatA
|
||||
struct {
|
||||
uint32_t Rc : 1;
|
||||
uint32_t XO : 5;
|
||||
uint32_t FRC : 5;
|
||||
uint32_t FRB : 5;
|
||||
uint32_t FRA : 5;
|
||||
uint32_t FRT : 5;
|
||||
uint32_t : 6;
|
||||
} A;
|
||||
// kXEPPCInstrFormatM
|
||||
struct {
|
||||
uint32_t Rc : 1;
|
||||
uint32_t ME : 5;
|
||||
uint32_t MB : 5;
|
||||
uint32_t SH : 5;
|
||||
uint32_t RA : 5;
|
||||
uint32_t RT : 5;
|
||||
uint32_t : 6;
|
||||
} M;
|
||||
// kXEPPCInstrFormatMD
|
||||
struct {
|
||||
uint32_t Rc : 1;
|
||||
uint32_t SH5 : 1;
|
||||
uint32_t idx : 3;
|
||||
uint32_t MB5 : 1;
|
||||
uint32_t MB : 5;
|
||||
uint32_t SH : 5;
|
||||
uint32_t RA : 5;
|
||||
uint32_t RT : 5;
|
||||
uint32_t : 6;
|
||||
} MD;
|
||||
// kXEPPCInstrFormatMDS
|
||||
struct {
|
||||
uint32_t Rc : 1;
|
||||
uint32_t idx : 4;
|
||||
uint32_t MB5 : 1;
|
||||
uint32_t MB : 5;
|
||||
uint32_t RB : 5;
|
||||
uint32_t RA : 5;
|
||||
uint32_t RT : 5;
|
||||
uint32_t : 6;
|
||||
} MDS;
|
||||
// kXEPPCInstrFormatVXA
|
||||
struct {
|
||||
uint32_t : 6;
|
||||
uint32_t VC : 5;
|
||||
uint32_t VB : 5;
|
||||
uint32_t VA : 5;
|
||||
uint32_t VD : 5;
|
||||
uint32_t : 6;
|
||||
} VXA;
|
||||
// kXEPPCInstrFormatVX
|
||||
struct {
|
||||
uint32_t : 11;
|
||||
uint32_t VB : 5;
|
||||
uint32_t VA : 5;
|
||||
uint32_t VD : 5;
|
||||
uint32_t : 6;
|
||||
} VX;
|
||||
// kXEPPCInstrFormatVXR
|
||||
struct {
|
||||
uint32_t : 10;
|
||||
uint32_t Rc : 1;
|
||||
uint32_t VB : 5;
|
||||
uint32_t VA : 5;
|
||||
uint32_t VD : 5;
|
||||
uint32_t : 6;
|
||||
} VXR;
|
||||
// kXEPPCInstrFormatVX128
|
||||
struct {
|
||||
// VD128 = VD128l | (VD128h << 5)
|
||||
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
||||
// VB128 = VB128l | (VB128h << 5)
|
||||
uint32_t VB128h : 2;
|
||||
uint32_t VD128h : 2;
|
||||
uint32_t : 1;
|
||||
uint32_t VA128h : 1;
|
||||
uint32_t : 4;
|
||||
uint32_t VA128H : 1;
|
||||
uint32_t VB128l : 5;
|
||||
uint32_t VA128l : 5;
|
||||
uint32_t VD128l : 5;
|
||||
uint32_t : 6;
|
||||
} VX128;
|
||||
// kXEPPCInstrFormatVX128_1
|
||||
struct {
|
||||
// VD128 = VD128l | (VD128h << 5)
|
||||
uint32_t : 2;
|
||||
uint32_t VD128h : 2;
|
||||
uint32_t : 7;
|
||||
uint32_t RB : 5;
|
||||
uint32_t RA : 5;
|
||||
uint32_t VD128l : 5;
|
||||
uint32_t : 6;
|
||||
} VX128_1;
|
||||
// kXEPPCInstrFormatVX128_2
|
||||
struct {
|
||||
// VD128 = VD128l | (VD128h << 5)
|
||||
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
||||
// VB128 = VB128l | (VB128h << 5)
|
||||
uint32_t VB128h : 2;
|
||||
uint32_t VD128h : 2;
|
||||
uint32_t : 1;
|
||||
uint32_t VA128h : 1;
|
||||
uint32_t VC : 3;
|
||||
uint32_t : 1;
|
||||
uint32_t VA128H : 1;
|
||||
uint32_t VB128l : 5;
|
||||
uint32_t VA128l : 5;
|
||||
uint32_t VD128l : 5;
|
||||
uint32_t : 6;
|
||||
} VX128_2;
|
||||
// kXEPPCInstrFormatVX128_3
|
||||
struct {
|
||||
// VD128 = VD128l | (VD128h << 5)
|
||||
// VB128 = VB128l | (VB128h << 5)
|
||||
uint32_t VB128h : 2;
|
||||
uint32_t VD128h : 2;
|
||||
uint32_t : 7;
|
||||
uint32_t VB128l : 5;
|
||||
uint32_t IMM : 5;
|
||||
uint32_t VD128l : 5;
|
||||
uint32_t : 6;
|
||||
} VX128_3;
|
||||
// kXEPPCInstrFormatVX128_4
|
||||
struct {
|
||||
// VD128 = VD128l | (VD128h << 5)
|
||||
// VB128 = VB128l | (VB128h << 5)
|
||||
uint32_t VB128h : 2;
|
||||
uint32_t VD128h : 2;
|
||||
uint32_t : 2;
|
||||
uint32_t z : 2;
|
||||
uint32_t : 3;
|
||||
uint32_t VB128l : 5;
|
||||
uint32_t IMM : 5;
|
||||
uint32_t VD128l : 5;
|
||||
uint32_t : 6;
|
||||
} VX128_4;
|
||||
// kXEPPCInstrFormatVX128_5
|
||||
struct {
|
||||
// VD128 = VD128l | (VD128h << 5)
|
||||
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
||||
// VB128 = VB128l | (VB128h << 5)
|
||||
uint32_t VB128h : 2;
|
||||
uint32_t VD128h : 2;
|
||||
uint32_t : 1;
|
||||
uint32_t VA128h : 1;
|
||||
uint32_t SH : 4;
|
||||
uint32_t VA128H : 1;
|
||||
uint32_t VB128l : 5;
|
||||
uint32_t VA128l : 5;
|
||||
uint32_t VD128l : 5;
|
||||
uint32_t : 6;
|
||||
} VX128_5;
|
||||
// kXEPPCInstrFormatVX128_P
|
||||
struct {
|
||||
// VD128 = VD128l | (VD128h << 5)
|
||||
// VB128 = VB128l | (VB128h << 5)
|
||||
// PERM = PERMl | (PERMh << 5)
|
||||
uint32_t VB128h : 2;
|
||||
uint32_t VD128h : 2;
|
||||
uint32_t : 2;
|
||||
uint32_t PERMh : 3;
|
||||
uint32_t : 2;
|
||||
uint32_t VB128l : 5;
|
||||
uint32_t PERMl : 5;
|
||||
uint32_t VD128l : 5;
|
||||
uint32_t : 6;
|
||||
} VX128_P;
|
||||
// kXEPPCInstrFormatVX128_R
|
||||
struct {
|
||||
// VD128 = VD128l | (VD128h << 5)
|
||||
// VA128 = VA128l | (VA128h << 5) | (VA128H << 6)
|
||||
// VB128 = VB128l | (VB128h << 5)
|
||||
uint32_t VB128h : 2;
|
||||
uint32_t VD128h : 2;
|
||||
uint32_t : 1;
|
||||
uint32_t VA128h : 1;
|
||||
uint32_t Rc : 1;
|
||||
uint32_t : 3;
|
||||
uint32_t VA128H : 1;
|
||||
uint32_t VB128l : 5;
|
||||
uint32_t VA128l : 5;
|
||||
uint32_t VD128l : 5;
|
||||
uint32_t : 6;
|
||||
} VX128_R;
|
||||
// kXEPPCInstrFormatXDSS
|
||||
struct {
|
||||
} XDSS;
|
||||
};
|
||||
} InstrData;
|
||||
|
||||
|
||||
typedef struct {
|
||||
enum RegisterSet {
|
||||
kXER,
|
||||
kLR,
|
||||
kCTR,
|
||||
kCR, // 0-7
|
||||
kFPSCR,
|
||||
kGPR, // 0-31
|
||||
kFPR, // 0-31
|
||||
kVMX, // 0-127
|
||||
};
|
||||
|
||||
enum Access {
|
||||
kRead = 1 << 0,
|
||||
kWrite = 1 << 1,
|
||||
kReadWrite = kRead | kWrite,
|
||||
};
|
||||
|
||||
RegisterSet set;
|
||||
uint32_t ordinal;
|
||||
Access access;
|
||||
} InstrRegister;
|
||||
|
||||
|
||||
typedef struct {
|
||||
enum OperandType {
|
||||
kRegister,
|
||||
kImmediate,
|
||||
};
|
||||
|
||||
OperandType type;
|
||||
const char* display;
|
||||
union {
|
||||
InstrRegister reg;
|
||||
struct {
|
||||
bool is_signed;
|
||||
uint64_t value;
|
||||
size_t width;
|
||||
} imm;
|
||||
};
|
||||
|
||||
void Dump(std::string& out_str);
|
||||
} InstrOperand;
|
||||
|
||||
|
||||
class InstrAccessBits {
|
||||
public:
|
||||
InstrAccessBits() :
|
||||
spr(0), cr(0), gpr(0), fpr(0),
|
||||
vr31_0(0), vr63_32(0), vr95_64(0), vr127_96(0) {
|
||||
}
|
||||
|
||||
// Bitmasks derived from the accesses to registers.
|
||||
// Format is 2 bits for each register, even bits indicating reads and odds
|
||||
// indicating writes.
|
||||
uint64_t spr; // fpcsr/ctr/lr/xer
|
||||
uint64_t cr; // cr7/6/5/4/3/2/1/0
|
||||
uint64_t gpr; // r31-0
|
||||
uint64_t fpr; // f31-0
|
||||
uint64_t vr31_0;
|
||||
uint64_t vr63_32;
|
||||
uint64_t vr95_64;
|
||||
uint64_t vr127_96;
|
||||
|
||||
void Clear();
|
||||
void Extend(InstrAccessBits& other);
|
||||
void MarkAccess(InstrRegister& reg);
|
||||
void Dump(std::string& out_str);
|
||||
};
|
||||
|
||||
|
||||
class InstrDisasm {
|
||||
public:
|
||||
enum Flags {
|
||||
kOE = 1 << 0,
|
||||
kRc = 1 << 1,
|
||||
kCA = 1 << 2,
|
||||
kLR = 1 << 4,
|
||||
kFP = 1 << 5,
|
||||
kVMX = 1 << 6,
|
||||
};
|
||||
|
||||
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);
|
||||
void AddCTR(InstrRegister::Access access);
|
||||
void AddCR(uint32_t bf, InstrRegister::Access access);
|
||||
void AddFPSCR(InstrRegister::Access access);
|
||||
void AddRegOperand(InstrRegister::RegisterSet set, uint32_t ordinal,
|
||||
InstrRegister::Access access, const char* display = NULL);
|
||||
void AddSImmOperand(uint64_t value, size_t width, const char* display = NULL);
|
||||
void AddUImmOperand(uint64_t value, size_t width, const char* display = NULL);
|
||||
int Finish();
|
||||
|
||||
void Dump(std::string& out_str, size_t pad = 13);
|
||||
};
|
||||
|
||||
|
||||
typedef int (*InstrDisassembleFn)(InstrData& i, InstrDisasm& d);
|
||||
typedef void* InstrEmitFn;
|
||||
|
||||
|
||||
class InstrType {
|
||||
public:
|
||||
uint32_t opcode;
|
||||
uint32_t opcode_mask; // Only used for certain opcodes (altivec, etc).
|
||||
uint32_t format; // xe_ppc_instr_format_e
|
||||
uint32_t type; // xe_ppc_instr_type_e
|
||||
uint32_t flags; // xe_ppc_instr_flag_e
|
||||
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);
|
||||
|
||||
|
||||
} // namespace ppc
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_PPC_INSTR_H_
|
||||
|
||||
@@ -1,643 +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 XENIA_CPU_PPC_INSTR_TABLE_H_
|
||||
#define XENIA_CPU_PPC_INSTR_TABLE_H_
|
||||
|
||||
#include <xenia/cpu/ppc/instr.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace ppc {
|
||||
namespace tables {
|
||||
|
||||
|
||||
static InstrType** instr_table_prep(
|
||||
InstrType* unprep, int unprep_count, int a, int b) {
|
||||
int prep_count = (int)pow(2.0, b - a + 1);
|
||||
InstrType** prep = (InstrType**)xe_calloc(prep_count * sizeof(void*));
|
||||
for (int n = 0; n < unprep_count; n++) {
|
||||
int ordinal = XESELECTBITS(unprep[n].opcode, a, b);
|
||||
prep[ordinal] = &unprep[n];
|
||||
}
|
||||
return prep;
|
||||
}
|
||||
|
||||
static InstrType** instr_table_prep_63(
|
||||
InstrType* unprep, int unprep_count, int a, int b) {
|
||||
// Special handling for A format instructions.
|
||||
int prep_count = (int)pow(2.0, b - a + 1);
|
||||
InstrType** prep = (InstrType**)xe_calloc(prep_count * sizeof(void*));
|
||||
for (int n = 0; n < unprep_count; n++) {
|
||||
int ordinal = XESELECTBITS(unprep[n].opcode, a, b);
|
||||
if (unprep[n].format == kXEPPCInstrFormatA) {
|
||||
// Must splat this into all of the slots that it could be in.
|
||||
for (int m = 0; m < 32; m++) {
|
||||
prep[ordinal + (m << 5)] = &unprep[n];
|
||||
}
|
||||
} else {
|
||||
prep[ordinal] = &unprep[n];
|
||||
}
|
||||
}
|
||||
return prep;
|
||||
}
|
||||
|
||||
|
||||
#define EMPTY(slot) {0}
|
||||
#define INSTRUCTION(name, opcode, format, type, flag) { \
|
||||
opcode, \
|
||||
0, \
|
||||
kXEPPCInstrFormat##format, \
|
||||
kXEPPCInstrType##type, \
|
||||
flag, \
|
||||
#name, \
|
||||
}
|
||||
#define FLAG(t) kXEPPCInstrFlag##t
|
||||
|
||||
|
||||
// This table set is constructed from:
|
||||
// pem_64bit_v3.0.2005jul15.pdf, A.2
|
||||
// PowerISA_V2.06B_V2_PUBLIC.pdf
|
||||
|
||||
// Opcode = 4, index = bits 11-0 (6)
|
||||
static InstrType instr_table_4_unprep[] = {
|
||||
// TODO: all of the vector ops
|
||||
INSTRUCTION(mfvscr, 0x10000604, VX , General , 0),
|
||||
INSTRUCTION(mtvscr, 0x10000644, VX , General , 0),
|
||||
INSTRUCTION(vaddcuw, 0x10000180, VX , General , 0),
|
||||
INSTRUCTION(vaddfp, 0x1000000A, VX , General , 0),
|
||||
INSTRUCTION(vaddsbs, 0x10000300, VX , General , 0),
|
||||
INSTRUCTION(vaddshs, 0x10000340, VX , General , 0),
|
||||
INSTRUCTION(vaddsws, 0x10000380, VX , General , 0),
|
||||
INSTRUCTION(vaddubm, 0x10000000, VX , General , 0),
|
||||
INSTRUCTION(vaddubs, 0x10000200, VX , General , 0),
|
||||
INSTRUCTION(vadduhm, 0x10000040, VX , General , 0),
|
||||
INSTRUCTION(vadduhs, 0x10000240, VX , General , 0),
|
||||
INSTRUCTION(vadduwm, 0x10000080, VX , General , 0),
|
||||
INSTRUCTION(vadduws, 0x10000280, VX , General , 0),
|
||||
INSTRUCTION(vand, 0x10000404, VX , General , 0),
|
||||
INSTRUCTION(vandc, 0x10000444, VX , General , 0),
|
||||
INSTRUCTION(vavgsb, 0x10000502, VX , General , 0),
|
||||
INSTRUCTION(vavgsh, 0x10000542, VX , General , 0),
|
||||
INSTRUCTION(vavgsw, 0x10000582, VX , General , 0),
|
||||
INSTRUCTION(vavgub, 0x10000402, VX , General , 0),
|
||||
INSTRUCTION(vavguh, 0x10000442, VX , General , 0),
|
||||
INSTRUCTION(vavguw, 0x10000482, VX , General , 0),
|
||||
INSTRUCTION(vcfsx, 0x1000034A, VX , General , 0),
|
||||
INSTRUCTION(vcfux, 0x1000030A, VX , General , 0),
|
||||
INSTRUCTION(vctsxs, 0x100003CA, VX , General , 0),
|
||||
INSTRUCTION(vctuxs, 0x1000038A, VX , General , 0),
|
||||
INSTRUCTION(vexptefp, 0x1000018A, VX , General , 0),
|
||||
INSTRUCTION(vlogefp, 0x100001CA, VX , General , 0),
|
||||
INSTRUCTION(vmaxfp, 0x1000040A, VX , General , 0),
|
||||
INSTRUCTION(vmaxsb, 0x10000102, VX , General , 0),
|
||||
INSTRUCTION(vmaxsh, 0x10000142, VX , General , 0),
|
||||
INSTRUCTION(vmaxsw, 0x10000182, VX , General , 0),
|
||||
INSTRUCTION(vmaxub, 0x10000002, VX , General , 0),
|
||||
INSTRUCTION(vmaxuh, 0x10000042, VX , General , 0),
|
||||
INSTRUCTION(vmaxuw, 0x10000082, VX , General , 0),
|
||||
INSTRUCTION(vminfp, 0x1000044A, VX , General , 0),
|
||||
INSTRUCTION(vminsb, 0x10000302, VX , General , 0),
|
||||
INSTRUCTION(vminsh, 0x10000342, VX , General , 0),
|
||||
INSTRUCTION(vminsw, 0x10000382, VX , General , 0),
|
||||
INSTRUCTION(vminub, 0x10000202, VX , General , 0),
|
||||
INSTRUCTION(vminuh, 0x10000242, VX , General , 0),
|
||||
INSTRUCTION(vminuw, 0x10000282, VX , General , 0),
|
||||
INSTRUCTION(vmrghb, 0x1000000C, VX , General , 0),
|
||||
INSTRUCTION(vmrghh, 0x1000004C, VX , General , 0),
|
||||
INSTRUCTION(vmrghw, 0x1000008C, VX , General , 0),
|
||||
INSTRUCTION(vmrglb, 0x1000010C, VX , General , 0),
|
||||
INSTRUCTION(vmrglh, 0x1000014C, VX , General , 0),
|
||||
INSTRUCTION(vmrglw, 0x1000018C, VX , General , 0),
|
||||
INSTRUCTION(vmulesb, 0x10000308, VX , General , 0),
|
||||
INSTRUCTION(vmulesh, 0x10000348, VX , General , 0),
|
||||
INSTRUCTION(vmuleub, 0x10000208, VX , General , 0),
|
||||
INSTRUCTION(vmuleuh, 0x10000248, VX , General , 0),
|
||||
INSTRUCTION(vmulosb, 0x10000108, VX , General , 0),
|
||||
INSTRUCTION(vmulosh, 0x10000148, VX , General , 0),
|
||||
INSTRUCTION(vmuloub, 0x10000008, VX , General , 0),
|
||||
INSTRUCTION(vmulouh, 0x10000048, VX , General , 0),
|
||||
INSTRUCTION(vnor, 0x10000504, VX , General , 0),
|
||||
INSTRUCTION(vor, 0x10000484, VX , General , 0),
|
||||
INSTRUCTION(vpkpx, 0x1000030E, VX , General , 0),
|
||||
INSTRUCTION(vpkshss, 0x1000018E, VX , General , 0),
|
||||
INSTRUCTION(vpkshus, 0x1000010E, VX , General , 0),
|
||||
INSTRUCTION(vpkswss, 0x100001CE, VX , General , 0),
|
||||
INSTRUCTION(vpkswus, 0x1000014E, VX , General , 0),
|
||||
INSTRUCTION(vpkuhum, 0x1000000E, VX , General , 0),
|
||||
INSTRUCTION(vpkuhus, 0x1000008E, VX , General , 0),
|
||||
INSTRUCTION(vpkuwum, 0x1000004E, VX , General , 0),
|
||||
INSTRUCTION(vpkuwus, 0x100000CE, VX , General , 0),
|
||||
INSTRUCTION(vrefp, 0x1000010A, VX , General , 0),
|
||||
INSTRUCTION(vrfim, 0x100002CA, VX , General , 0),
|
||||
INSTRUCTION(vrfin, 0x1000020A, VX , General , 0),
|
||||
INSTRUCTION(vrfip, 0x1000028A, VX , General , 0),
|
||||
INSTRUCTION(vrfiz, 0x1000024A, VX , General , 0),
|
||||
INSTRUCTION(vrlb, 0x10000004, VX , General , 0),
|
||||
INSTRUCTION(vrlh, 0x10000044, VX , General , 0),
|
||||
INSTRUCTION(vrlw, 0x10000084, VX , General , 0),
|
||||
INSTRUCTION(vrsqrtefp, 0x1000014A, VX , General , 0),
|
||||
INSTRUCTION(vsl, 0x100001C4, VX , General , 0),
|
||||
INSTRUCTION(vslb, 0x10000104, VX , General , 0),
|
||||
INSTRUCTION(vslh, 0x10000144, VX , General , 0),
|
||||
INSTRUCTION(vslo, 0x1000040C, VX , General , 0),
|
||||
INSTRUCTION(vslw, 0x10000184, VX , General , 0),
|
||||
INSTRUCTION(vspltb, 0x1000020C, VX , General , 0),
|
||||
INSTRUCTION(vsplth, 0x1000024C, VX , General , 0),
|
||||
INSTRUCTION(vspltisb, 0x1000030C, VX , General , 0),
|
||||
INSTRUCTION(vspltish, 0x1000034C, VX , General , 0),
|
||||
INSTRUCTION(vspltisw, 0x1000038C, VX , General , 0),
|
||||
INSTRUCTION(vspltw, 0x1000028C, VX , General , 0),
|
||||
INSTRUCTION(vsr, 0x100002C4, VX , General , 0),
|
||||
INSTRUCTION(vsrab, 0x10000304, VX , General , 0),
|
||||
INSTRUCTION(vsrah, 0x10000344, VX , General , 0),
|
||||
INSTRUCTION(vsraw, 0x10000384, VX , General , 0),
|
||||
INSTRUCTION(vsrb, 0x10000204, VX , General , 0),
|
||||
INSTRUCTION(vsrh, 0x10000244, VX , General , 0),
|
||||
INSTRUCTION(vsro, 0x1000044C, VX , General , 0),
|
||||
INSTRUCTION(vsrw, 0x10000284, VX , General , 0),
|
||||
INSTRUCTION(vsubcuw, 0x10000580, VX , General , 0),
|
||||
INSTRUCTION(vsubfp, 0x1000004A, VX , General , 0),
|
||||
INSTRUCTION(vsubsbs, 0x10000700, VX , General , 0),
|
||||
INSTRUCTION(vsubshs, 0x10000740, VX , General , 0),
|
||||
INSTRUCTION(vsubsws, 0x10000780, VX , General , 0),
|
||||
INSTRUCTION(vsububm, 0x10000400, VX , General , 0),
|
||||
INSTRUCTION(vsububs, 0x10000600, VX , General , 0),
|
||||
INSTRUCTION(vsubuhm, 0x10000440, VX , General , 0),
|
||||
INSTRUCTION(vsubuhs, 0x10000640, VX , General , 0),
|
||||
INSTRUCTION(vsubuwm, 0x10000480, VX , General , 0),
|
||||
INSTRUCTION(vsubuws, 0x10000680, VX , General , 0),
|
||||
INSTRUCTION(vsumsws, 0x10000788, VX , General , 0),
|
||||
INSTRUCTION(vsum2sws, 0x10000688, VX , General , 0),
|
||||
INSTRUCTION(vsum4sbs, 0x10000708, VX , General , 0),
|
||||
INSTRUCTION(vsum4shs, 0x10000648, VX , General , 0),
|
||||
INSTRUCTION(vsum4ubs, 0x10000608, VX , General , 0),
|
||||
INSTRUCTION(vupkhpx, 0x1000034E, VX , General , 0),
|
||||
INSTRUCTION(vupkhsb, 0x1000020E, VX , General , 0),
|
||||
INSTRUCTION(vupkhsh, 0x1000024E, VX , General , 0),
|
||||
INSTRUCTION(vupklpx, 0x100003CE, VX , General , 0),
|
||||
INSTRUCTION(vupklsb, 0x1000028E, VX , General , 0),
|
||||
INSTRUCTION(vupklsh, 0x100002CE, VX , General , 0),
|
||||
INSTRUCTION(vxor, 0x100004C4, VX , General , 0),
|
||||
};
|
||||
static InstrType** instr_table_4 = instr_table_prep(
|
||||
instr_table_4_unprep, XECOUNT(instr_table_4_unprep), 0, 11);
|
||||
|
||||
// Opcode = 19, index = bits 10-1 (10)
|
||||
static InstrType instr_table_19_unprep[] = {
|
||||
INSTRUCTION(mcrf, 0x4C000000, XL , General , 0),
|
||||
INSTRUCTION(bclrx, 0x4C000020, XL , BranchCond , 0),
|
||||
INSTRUCTION(crnor, 0x4C000042, XL , General , 0),
|
||||
INSTRUCTION(crandc, 0x4C000102, XL , General , 0),
|
||||
INSTRUCTION(isync, 0x4C00012C, XL , General , 0),
|
||||
INSTRUCTION(crxor, 0x4C000182, XL , General , 0),
|
||||
INSTRUCTION(crnand, 0x4C0001C2, XL , General , 0),
|
||||
INSTRUCTION(crand, 0x4C000202, XL , General , 0),
|
||||
INSTRUCTION(creqv, 0x4C000242, XL , General , 0),
|
||||
INSTRUCTION(crorc, 0x4C000342, XL , General , 0),
|
||||
INSTRUCTION(cror, 0x4C000382, XL , General , 0),
|
||||
INSTRUCTION(bcctrx, 0x4C000420, XL , BranchCond , 0),
|
||||
};
|
||||
static InstrType** instr_table_19 = instr_table_prep(
|
||||
instr_table_19_unprep, XECOUNT(instr_table_19_unprep), 1, 10);
|
||||
|
||||
// Opcode = 30, index = bits 4-1 (4)
|
||||
static InstrType instr_table_30_unprep[] = {
|
||||
// Decoding these instrunctions in this table is difficult because the
|
||||
// index bits are kind of random. This is special cased by an uber
|
||||
// instruction handler.
|
||||
INSTRUCTION(rld, 0x78000000, MD , General , 0),
|
||||
// INSTRUCTION(rldiclx, 0x78000000, MD , General , 0),
|
||||
// INSTRUCTION(rldicrx, 0x78000004, MD , General , 0),
|
||||
// INSTRUCTION(rldicx, 0x78000008, MD , General , 0),
|
||||
// INSTRUCTION(rldimix, 0x7800000C, MD , General , 0),
|
||||
// INSTRUCTION(rldclx, 0x78000010, MDS, General , 0),
|
||||
// INSTRUCTION(rldcrx, 0x78000012, MDS, General , 0),
|
||||
};
|
||||
static InstrType** instr_table_30 = instr_table_prep(
|
||||
instr_table_30_unprep, XECOUNT(instr_table_30_unprep), 0, 0);
|
||||
|
||||
// Opcode = 31, index = bits 10-1 (10)
|
||||
static InstrType instr_table_31_unprep[] = {
|
||||
INSTRUCTION(cmp, 0x7C000000, X , General , 0),
|
||||
INSTRUCTION(tw, 0x7C000008, X , General , 0),
|
||||
INSTRUCTION(lvsl, 0x7C00000C, X , General , 0),
|
||||
INSTRUCTION(lvebx, 0x7C00000E, X , General , 0),
|
||||
INSTRUCTION(subfcx, 0x7C000010, XO , General , 0),
|
||||
INSTRUCTION(mulhdux, 0x7C000012, XO , General , 0),
|
||||
INSTRUCTION(addcx, 0x7C000014, XO , General , 0),
|
||||
INSTRUCTION(mulhwux, 0x7C000016, XO , General , 0),
|
||||
INSTRUCTION(mfcr, 0x7C000026, X , General , 0),
|
||||
INSTRUCTION(lwarx, 0x7C000028, X , General , 0),
|
||||
INSTRUCTION(ldx, 0x7C00002A, X , General , 0),
|
||||
INSTRUCTION(lwzx, 0x7C00002E, X , General , 0),
|
||||
INSTRUCTION(slwx, 0x7C000030, X , General , 0),
|
||||
INSTRUCTION(cntlzwx, 0x7C000034, X , General , 0),
|
||||
INSTRUCTION(sldx, 0x7C000036, X , General , 0),
|
||||
INSTRUCTION(andx, 0x7C000038, X , General , 0),
|
||||
INSTRUCTION(cmpl, 0x7C000040, X , General , 0),
|
||||
INSTRUCTION(lvsr, 0x7C00004C, X , General , 0),
|
||||
INSTRUCTION(lvehx, 0x7C00004E, X , General , 0),
|
||||
INSTRUCTION(subfx, 0x7C000050, XO , General , 0),
|
||||
INSTRUCTION(ldux, 0x7C00006A, X , General , 0),
|
||||
INSTRUCTION(dcbst, 0x7C00006C, X , General , 0),
|
||||
INSTRUCTION(lwzux, 0x7C00006E, X , General , 0),
|
||||
INSTRUCTION(cntlzdx, 0x7C000074, X , General , 0),
|
||||
INSTRUCTION(andcx, 0x7C000078, X , General , 0),
|
||||
INSTRUCTION(td, 0x7C000088, X , General , 0),
|
||||
INSTRUCTION(lvewx, 0x7C00008E, X , General , 0),
|
||||
INSTRUCTION(mulhdx, 0x7C000092, XO , General , 0),
|
||||
INSTRUCTION(mulhwx, 0x7C000096, XO , General , 0),
|
||||
INSTRUCTION(mfmsr, 0x7C0000A6, X , General , 0),
|
||||
INSTRUCTION(ldarx, 0x7C0000A8, X , General , 0),
|
||||
INSTRUCTION(dcbf, 0x7C0000AC, X , General , 0),
|
||||
INSTRUCTION(lbzx, 0x7C0000AE, X , General , 0),
|
||||
INSTRUCTION(lvx, 0x7C0000CE, X , General , 0),
|
||||
INSTRUCTION(negx, 0x7C0000D0, XO , General , 0),
|
||||
INSTRUCTION(lbzux, 0x7C0000EE, X , General , 0),
|
||||
INSTRUCTION(norx, 0x7C0000F8, X , General , 0),
|
||||
INSTRUCTION(stvebx, 0x7C00010E, X , General , 0),
|
||||
INSTRUCTION(subfex, 0x7C000110, XO , General , 0),
|
||||
INSTRUCTION(addex, 0x7C000114, XO , General , 0),
|
||||
INSTRUCTION(mtcrf, 0x7C000120, XFX, General , 0),
|
||||
INSTRUCTION(mtmsr, 0x7C000124, X , General , 0),
|
||||
INSTRUCTION(stdx, 0x7C00012A, X , General , 0),
|
||||
INSTRUCTION(stwcx, 0x7C00012D, X , General , 0),
|
||||
INSTRUCTION(stwx, 0x7C00012E, X , General , 0),
|
||||
INSTRUCTION(stvehx, 0x7C00014E, X , General , 0),
|
||||
INSTRUCTION(mtmsrd, 0x7C000164, X , General , 0),
|
||||
INSTRUCTION(stdux, 0x7C00016A, X , General , 0),
|
||||
INSTRUCTION(stwux, 0x7C00016E, X , General , 0),
|
||||
INSTRUCTION(stvewx, 0x7C00018E, X , General , 0),
|
||||
INSTRUCTION(subfzex, 0x7C000190, XO , General , 0),
|
||||
INSTRUCTION(addzex, 0x7C000194, XO , General , 0),
|
||||
INSTRUCTION(stdcx, 0x7C0001AD, X , General , 0),
|
||||
INSTRUCTION(stbx, 0x7C0001AE, X , General , 0),
|
||||
INSTRUCTION(stvx, 0x7C0001CE, X , General , 0),
|
||||
INSTRUCTION(subfmex, 0x7C0001D0, XO , General , 0),
|
||||
INSTRUCTION(mulldx, 0x7C0001D2, XO , General , 0),
|
||||
INSTRUCTION(addmex, 0x7C0001D4, XO , General , 0),
|
||||
INSTRUCTION(mullwx, 0x7C0001D6, XO , General , 0),
|
||||
INSTRUCTION(dcbtst, 0x7C0001EC, X , General , 0),
|
||||
INSTRUCTION(stbux, 0x7C0001EE, X , General , 0),
|
||||
INSTRUCTION(addx, 0x7C000214, XO , General , 0),
|
||||
INSTRUCTION(dcbt, 0x7C00022C, X , General , 0),
|
||||
INSTRUCTION(lhzx, 0x7C00022E, X , General , 0),
|
||||
INSTRUCTION(eqvx, 0x7C000238, X , General , 0),
|
||||
INSTRUCTION(eciwx, 0x7C00026C, X , General , 0),
|
||||
INSTRUCTION(lhzux, 0x7C00026E, X , General , 0),
|
||||
INSTRUCTION(xorx, 0x7C000278, X , General , 0),
|
||||
INSTRUCTION(mfspr, 0x7C0002A6, XFX, General , 0),
|
||||
INSTRUCTION(lwax, 0x7C0002AA, X , General , 0),
|
||||
INSTRUCTION(lhax, 0x7C0002AE, X , General , 0),
|
||||
INSTRUCTION(lvxl, 0x7C0002CE, X , General , 0),
|
||||
INSTRUCTION(mftb, 0x7C0002E6, XFX, General , 0),
|
||||
INSTRUCTION(lwaux, 0x7C0002EA, X , General , 0),
|
||||
INSTRUCTION(lhaux, 0x7C0002EE, X , General , 0),
|
||||
INSTRUCTION(sthx, 0x7C00032E, X , General , 0),
|
||||
INSTRUCTION(orcx, 0x7C000338, X , General , 0),
|
||||
INSTRUCTION(ecowx, 0x7C00036C, X , General , 0),
|
||||
INSTRUCTION(sthux, 0x7C00036E, X , General , 0),
|
||||
INSTRUCTION(orx, 0x7C000378, X , General , 0),
|
||||
INSTRUCTION(divdux, 0x7C000392, XO , General , 0),
|
||||
INSTRUCTION(divwux, 0x7C000396, XO , General , 0),
|
||||
INSTRUCTION(mtspr, 0x7C0003A6, XFX, General , 0),
|
||||
INSTRUCTION(nandx, 0x7C0003B8, X , General , 0),
|
||||
INSTRUCTION(stvxl, 0x7C0003CE, X , General , 0),
|
||||
INSTRUCTION(divdx, 0x7C0003D2, XO , General , 0),
|
||||
INSTRUCTION(divwx, 0x7C0003D6, XO , General , 0),
|
||||
INSTRUCTION(lvlx, 0x7C00040E, X , General , 0),
|
||||
INSTRUCTION(ldbrx, 0x7C000428, X , General , 0),
|
||||
INSTRUCTION(lswx, 0x7C00042A, X , General , 0),
|
||||
INSTRUCTION(lwbrx, 0x7C00042C, X , General , 0),
|
||||
INSTRUCTION(lfsx, 0x7C00042E, X , General , 0),
|
||||
INSTRUCTION(srwx, 0x7C000430, X , General , 0),
|
||||
INSTRUCTION(srdx, 0x7C000436, X , General , 0),
|
||||
INSTRUCTION(lfsux, 0x7C00046E, X , General , 0),
|
||||
INSTRUCTION(lswi, 0x7C0004AA, X , General , 0),
|
||||
INSTRUCTION(sync, 0x7C0004AC, X , General , 0),
|
||||
INSTRUCTION(lfdx, 0x7C0004AE, X , General , 0),
|
||||
INSTRUCTION(lfdux, 0x7C0004EE, X , General , 0),
|
||||
INSTRUCTION(stdbrx, 0x7C000528, X , General , 0),
|
||||
INSTRUCTION(stswx, 0x7C00052A, X , General , 0),
|
||||
INSTRUCTION(stwbrx, 0x7C00052C, X , General , 0),
|
||||
INSTRUCTION(stfsx, 0x7C00052E, X , General , 0),
|
||||
INSTRUCTION(stfsux, 0x7C00056E, X , General , 0),
|
||||
INSTRUCTION(stswi, 0x7C0005AA, X , General , 0),
|
||||
INSTRUCTION(stfdx, 0x7C0005AE, X , General , 0),
|
||||
INSTRUCTION(stfdux, 0x7C0005EE, X , General , 0),
|
||||
INSTRUCTION(lhbrx, 0x7C00062C, X , General , 0),
|
||||
INSTRUCTION(srawx, 0x7C000630, X , General , 0),
|
||||
INSTRUCTION(sradx, 0x7C000634, X , General , 0),
|
||||
INSTRUCTION(srawix, 0x7C000670, X , General , 0),
|
||||
INSTRUCTION(sradix, 0x7C000674, XS , General , 0), // TODO
|
||||
INSTRUCTION(eieio, 0x7C0006AC, X , General , 0),
|
||||
INSTRUCTION(sthbrx, 0x7C00072C, X , General , 0),
|
||||
INSTRUCTION(extshx, 0x7C000734, X , General , 0),
|
||||
INSTRUCTION(extsbx, 0x7C000774, X , General , 0),
|
||||
INSTRUCTION(icbi, 0x7C0007AC, X , General , 0),
|
||||
INSTRUCTION(stfiwx, 0x7C0007AE, X , General , 0),
|
||||
INSTRUCTION(extswx, 0x7C0007B4, X , General , 0),
|
||||
INSTRUCTION(dcbz, 0x7C0007EC, X , General , 0), // 0x7C2007EC = DCBZ128
|
||||
INSTRUCTION(dst, 0x7C0002AC, XDSS, General , 0),
|
||||
INSTRUCTION(dstst, 0x7C0002EC, XDSS, General , 0),
|
||||
INSTRUCTION(dss, 0x7C00066C, XDSS, General , 0),
|
||||
INSTRUCTION(lvebx, 0x7C00000E, X , General , 0),
|
||||
INSTRUCTION(lvehx, 0x7C00004E, X , General , 0),
|
||||
INSTRUCTION(lvewx, 0x7C00008E, X , General , 0),
|
||||
INSTRUCTION(lvsl, 0x7C00000C, X , General , 0),
|
||||
INSTRUCTION(lvsr, 0x7C00004C, X , General , 0),
|
||||
INSTRUCTION(lvx, 0x7C0000CE, X , General , 0),
|
||||
INSTRUCTION(lvxl, 0x7C0002CE, X , General , 0),
|
||||
INSTRUCTION(stvebx, 0x7C00010E, X , General , 0),
|
||||
INSTRUCTION(stvehx, 0x7C00014E, X , General , 0),
|
||||
INSTRUCTION(stvewx, 0x7C00018E, X , General , 0),
|
||||
INSTRUCTION(stvx, 0x7C0001CE, X , General , 0),
|
||||
INSTRUCTION(stvxl, 0x7C0003CE, X , General , 0),
|
||||
INSTRUCTION(lvlx, 0x7C00040E, X , General , 0),
|
||||
INSTRUCTION(lvlxl, 0x7C00060E, X , General , 0),
|
||||
INSTRUCTION(lvrx, 0x7C00044E, X , General , 0),
|
||||
INSTRUCTION(lvrxl, 0x7C00064E, X , General , 0),
|
||||
INSTRUCTION(stvlx, 0x7C00050E, X , General , 0),
|
||||
INSTRUCTION(stvlxl, 0x7C00070E, X , General , 0),
|
||||
INSTRUCTION(stvrx, 0x7C00054E, X , General , 0),
|
||||
INSTRUCTION(stvrxl, 0x7C00074E, X , General , 0),
|
||||
};
|
||||
static InstrType** instr_table_31 = instr_table_prep(
|
||||
instr_table_31_unprep, XECOUNT(instr_table_31_unprep), 1, 10);
|
||||
|
||||
// Opcode = 58, index = bits 1-0 (2)
|
||||
static InstrType instr_table_58_unprep[] = {
|
||||
INSTRUCTION(ld, 0xE8000000, DS , General , 0),
|
||||
INSTRUCTION(ldu, 0xE8000001, DS , General , 0),
|
||||
INSTRUCTION(lwa, 0xE8000002, DS , General , 0),
|
||||
};
|
||||
static InstrType** instr_table_58 = instr_table_prep(
|
||||
instr_table_58_unprep, XECOUNT(instr_table_58_unprep), 0, 1);
|
||||
|
||||
// Opcode = 59, index = bits 5-1 (5)
|
||||
static InstrType instr_table_59_unprep[] = {
|
||||
INSTRUCTION(fdivsx, 0xEC000024, A , General , 0),
|
||||
INSTRUCTION(fsubsx, 0xEC000028, A , General , 0),
|
||||
INSTRUCTION(faddsx, 0xEC00002A, A , General , 0),
|
||||
INSTRUCTION(fsqrtsx, 0xEC00002C, A , General , 0),
|
||||
INSTRUCTION(fresx, 0xEC000030, A , General , 0),
|
||||
INSTRUCTION(fmulsx, 0xEC000032, A , General , 0),
|
||||
INSTRUCTION(fmsubsx, 0xEC000038, A , General , 0),
|
||||
INSTRUCTION(fmaddsx, 0xEC00003A, A , General , 0),
|
||||
INSTRUCTION(fnmsubsx, 0xEC00003C, A , General , 0),
|
||||
INSTRUCTION(fnmaddsx, 0xEC00003E, A , General , 0),
|
||||
};
|
||||
static InstrType** instr_table_59 = instr_table_prep(
|
||||
instr_table_59_unprep, XECOUNT(instr_table_59_unprep), 1, 5);
|
||||
|
||||
// Opcode = 62, index = bits 1-0 (2)
|
||||
static InstrType instr_table_62_unprep[] = {
|
||||
INSTRUCTION(std, 0xF8000000, DS , General , 0),
|
||||
INSTRUCTION(stdu, 0xF8000001, DS , General , 0),
|
||||
};
|
||||
static InstrType** instr_table_62 = instr_table_prep(
|
||||
instr_table_62_unprep, XECOUNT(instr_table_62_unprep), 0, 1);
|
||||
|
||||
// Opcode = 63, index = bits 10-1 (10)
|
||||
// NOTE: the A format instructions need some special handling because
|
||||
// they only use 6bits to identify their index.
|
||||
static InstrType instr_table_63_unprep[] = {
|
||||
INSTRUCTION(fcmpu, 0xFC000000, X , General , 0),
|
||||
INSTRUCTION(frspx, 0xFC000018, X , General , 0),
|
||||
INSTRUCTION(fctiwx, 0xFC00001C, X , General , 0),
|
||||
INSTRUCTION(fctiwzx, 0xFC00001E, X , General , 0),
|
||||
INSTRUCTION(fdivx, 0xFC000024, A , General , 0),
|
||||
INSTRUCTION(fsubx, 0xFC000028, A , General , 0),
|
||||
INSTRUCTION(faddx, 0xFC00002A, A , General , 0),
|
||||
INSTRUCTION(fsqrtx, 0xFC00002C, A , General , 0),
|
||||
INSTRUCTION(fselx, 0xFC00002E, A , General , 0),
|
||||
INSTRUCTION(fmulx, 0xFC000032, A , General , 0),
|
||||
INSTRUCTION(frsqrtex, 0xFC000034, A , General , 0),
|
||||
INSTRUCTION(fmsubx, 0xFC000038, A , General , 0),
|
||||
INSTRUCTION(fmaddx, 0xFC00003A, A , General , 0),
|
||||
INSTRUCTION(fnmsubx, 0xFC00003C, A , General , 0),
|
||||
INSTRUCTION(fnmaddx, 0xFC00003E, A , General , 0),
|
||||
INSTRUCTION(fcmpo, 0xFC000040, X , General , 0),
|
||||
INSTRUCTION(mtfsb1x, 0xFC00004C, X , General , 0),
|
||||
INSTRUCTION(fnegx, 0xFC000050, X , General , 0),
|
||||
INSTRUCTION(mcrfs, 0xFC000080, X , General , 0),
|
||||
INSTRUCTION(mtfsb0x, 0xFC00008C, X , General , 0),
|
||||
INSTRUCTION(fmrx, 0xFC000090, X , General , 0),
|
||||
INSTRUCTION(mtfsfix, 0xFC00010C, X , General , 0),
|
||||
INSTRUCTION(fnabsx, 0xFC000110, X , General , 0),
|
||||
INSTRUCTION(fabsx, 0xFC000210, X , General , 0),
|
||||
INSTRUCTION(mffsx, 0xFC00048E, X , General , 0),
|
||||
INSTRUCTION(mtfsfx, 0xFC00058E, XFL, General , 0),
|
||||
INSTRUCTION(fctidx, 0xFC00065C, X , General , 0),
|
||||
INSTRUCTION(fctidzx, 0xFC00065E, X , General , 0),
|
||||
INSTRUCTION(fcfidx, 0xFC00069C, X , General , 0),
|
||||
};
|
||||
static InstrType** instr_table_63 = instr_table_prep_63(
|
||||
instr_table_63_unprep, XECOUNT(instr_table_63_unprep), 1, 10);
|
||||
|
||||
// Main table, index = bits 31-26 (6) : (code >> 26)
|
||||
static InstrType instr_table_unprep[64] = {
|
||||
INSTRUCTION(tdi, 0x08000000, D , General , 0),
|
||||
INSTRUCTION(twi, 0x0C000000, D , General , 0),
|
||||
INSTRUCTION(mulli, 0x1C000000, D , General , 0),
|
||||
INSTRUCTION(subficx, 0x20000000, D , General , 0),
|
||||
INSTRUCTION(cmpli, 0x28000000, D , General , 0),
|
||||
INSTRUCTION(cmpi, 0x2C000000, D , General , 0),
|
||||
INSTRUCTION(addic, 0x30000000, D , General , 0),
|
||||
INSTRUCTION(addicx, 0x34000000, D , General , 0),
|
||||
INSTRUCTION(addi, 0x38000000, D , General , 0),
|
||||
INSTRUCTION(addis, 0x3C000000, D , General , 0),
|
||||
INSTRUCTION(bcx, 0x40000000, B , BranchCond , 0),
|
||||
INSTRUCTION(sc, 0x44000002, SC , Syscall , 0),
|
||||
INSTRUCTION(bx, 0x48000000, I , BranchAlways , 0),
|
||||
INSTRUCTION(rlwimix, 0x50000000, M , General , 0),
|
||||
INSTRUCTION(rlwinmx, 0x54000000, M , General , 0),
|
||||
INSTRUCTION(rlwnmx, 0x5C000000, M , General , 0),
|
||||
INSTRUCTION(ori, 0x60000000, D , General , 0),
|
||||
INSTRUCTION(oris, 0x64000000, D , General , 0),
|
||||
INSTRUCTION(xori, 0x68000000, D , General , 0),
|
||||
INSTRUCTION(xoris, 0x6C000000, D , General , 0),
|
||||
INSTRUCTION(andix, 0x70000000, D , General , 0),
|
||||
INSTRUCTION(andisx, 0x74000000, D , General , 0),
|
||||
INSTRUCTION(lwz, 0x80000000, D , General , 0),
|
||||
INSTRUCTION(lwzu, 0x84000000, D , General , 0),
|
||||
INSTRUCTION(lbz, 0x88000000, D , General , 0),
|
||||
INSTRUCTION(lbzu, 0x8C000000, D , General , 0),
|
||||
INSTRUCTION(stw, 0x90000000, D , General , 0),
|
||||
INSTRUCTION(stwu, 0x94000000, D , General , 0),
|
||||
INSTRUCTION(stb, 0x98000000, D , General , 0),
|
||||
INSTRUCTION(stbu, 0x9C000000, D , General , 0),
|
||||
INSTRUCTION(lhz, 0xA0000000, D , General , 0),
|
||||
INSTRUCTION(lhzu, 0xA4000000, D , General , 0),
|
||||
INSTRUCTION(lha, 0xA8000000, D , General , 0),
|
||||
INSTRUCTION(lhau, 0xAC000000, D , General , 0),
|
||||
INSTRUCTION(sth, 0xB0000000, D , General , 0),
|
||||
INSTRUCTION(sthu, 0xB4000000, D , General , 0),
|
||||
INSTRUCTION(lmw, 0xB8000000, D , General , 0),
|
||||
INSTRUCTION(stmw, 0xBC000000, D , General , 0),
|
||||
INSTRUCTION(lfs, 0xC0000000, D , General , 0),
|
||||
INSTRUCTION(lfsu, 0xC4000000, D , General , 0),
|
||||
INSTRUCTION(lfd, 0xC8000000, D , General , 0),
|
||||
INSTRUCTION(lfdu, 0xCC000000, D , General , 0),
|
||||
INSTRUCTION(stfs, 0xD0000000, D , General , 0),
|
||||
INSTRUCTION(stfsu, 0xD4000000, D , General , 0),
|
||||
INSTRUCTION(stfd, 0xD8000000, D , General , 0),
|
||||
INSTRUCTION(stfdu, 0xDC000000, D , General , 0),
|
||||
};
|
||||
static InstrType** instr_table = instr_table_prep(
|
||||
instr_table_unprep, XECOUNT(instr_table_unprep), 26, 31);
|
||||
|
||||
// Altivec instructions.
|
||||
// TODO(benvanik): build a table like the other instructions.
|
||||
// This table is looked up via linear scan of opcodes.
|
||||
#define SCAN_INSTRUCTION(name, opcode, format, type, flag) { \
|
||||
opcode, \
|
||||
kXEPPCInstrMask##format, \
|
||||
kXEPPCInstrFormat##format, \
|
||||
kXEPPCInstrType##type, \
|
||||
flag, \
|
||||
#name, \
|
||||
}
|
||||
#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_R(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x390))
|
||||
static InstrType instr_table_scan[] = {
|
||||
SCAN_INSTRUCTION(vcmpbfp, 0x100003C6, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpeqfp, 0x100000C6, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpequb, 0x10000006, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpequh, 0x10000046, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpequw, 0x10000086, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpgefp, 0x100001C6, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpgtfp, 0x100002C6, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpgtsb, 0x10000306, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpgtsh, 0x10000346, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpgtsw, 0x10000386, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpgtub, 0x10000206, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpgtuh, 0x10000246, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpgtuw, 0x10000286, VXR , General , 0),
|
||||
SCAN_INSTRUCTION(vmaddfp, 0x1000002E, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vmhaddshs, 0x10000020, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vmhraddshs, 0x10000021, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vmladduhm, 0x10000022, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vmsummbm, 0x10000025, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vmsumshm, 0x10000028, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vmsumshs, 0x10000029, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vmsumubm, 0x10000024, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vmsumuhm, 0x10000026, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vmsumuhs, 0x10000027, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vnmsubfp, 0x1000002F, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vperm, 0x1000002B, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vsel, 0x1000002A, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(vsldoi, 0x1000002C, VXA , General , 0),
|
||||
SCAN_INSTRUCTION(lvsl128, VX128_1(4, 3), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(lvsr128, VX128_1(4, 67), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(lvewx128, VX128_1(4, 131), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(lvx128, VX128_1(4, 195), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(stvewx128, VX128_1(4, 387), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(stvx128, VX128_1(4, 451), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(lvxl128, VX128_1(4, 707), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(stvxl128, VX128_1(4, 963), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(lvlx128, VX128_1(4, 1027), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(lvrx128, VX128_1(4, 1091), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(stvlx128, VX128_1(4, 1283), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(stvrx128, VX128_1(4, 1347), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(lvlxl128, VX128_1(4, 1539), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(lvrxl128, VX128_1(4, 1603), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(stvlxl128, VX128_1(4, 1795), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(stvrxl128, VX128_1(4, 1859), VX128_1 , General , 0),
|
||||
SCAN_INSTRUCTION(vsldoi128, VX128_5(4, 16), VX128_5 , General , 0),
|
||||
SCAN_INSTRUCTION(vperm128, VX128_2(5, 0), VX128_2 , General , 0),
|
||||
SCAN_INSTRUCTION(vaddfp128, VX128(5, 16), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vsubfp128, VX128(5, 80), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vmulfp128, VX128(5, 144), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vmaddfp128, VX128(5, 208), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vmaddcfp128, VX128(5, 272), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vnmsubfp128, VX128(5, 336), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vmsum3fp128, VX128(5, 400), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vmsum4fp128, VX128(5, 464), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vpkshss128, VX128(5, 512), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vand128, VX128(5, 528), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vpkshus128, VX128(5, 576), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vandc128, VX128(5, 592), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vpkswss128, VX128(5, 640), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vnor128, VX128(5, 656), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vpkswus128, VX128(5, 704), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vor128, VX128(5, 720), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vpkuhum128, VX128(5, 768), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vxor128, VX128(5, 784), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vpkuhus128, VX128(5, 832), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vsel128, VX128(5, 848), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vpkuwum128, VX128(5, 896), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vslo128, VX128(5, 912), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vpkuwus128, VX128(5, 960), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vsro128, VX128(5, 976), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vpermwi128, VX128_P(6, 528), VX128_P , General , 0),
|
||||
SCAN_INSTRUCTION(vcfpsxws128, VX128_3(6, 560), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vcfpuxws128, VX128_3(6, 624), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vcsxwfp128, VX128_3(6, 688), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vcuxwfp128, VX128_3(6, 752), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vrfim128, VX128_3(6, 816), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vrfin128, VX128_3(6, 880), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vrfip128, VX128_3(6, 944), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vrfiz128, VX128_3(6, 1008), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vpkd3d128, VX128_4(6, 1552), VX128_4 , General , 0),
|
||||
SCAN_INSTRUCTION(vrefp128, VX128_3(6, 1584), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vrsqrtefp128, VX128_3(6, 1648), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vexptefp128, VX128_3(6, 1712), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vlogefp128, VX128_3(6, 1776), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vrlimi128, VX128_4(6, 1808), VX128_4 , General , 0),
|
||||
SCAN_INSTRUCTION(vspltw128, VX128_3(6, 1840), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vspltisw128, VX128_3(6, 1904), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vupkd3d128, VX128_3(6, 2032), VX128_3 , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpeqfp128, VX128_R(6, 0), VX128_R , General , 0),
|
||||
SCAN_INSTRUCTION(vrlw128, VX128(6, 80), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpgefp128, VX128_R(6, 128), VX128_R , General , 0),
|
||||
SCAN_INSTRUCTION(vslw128, VX128(6, 208), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpgtfp128, VX128_R(6, 256), VX128_R , General , 0),
|
||||
SCAN_INSTRUCTION(vsraw128, VX128(6, 336), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpbfp128, VX128_R(6, 384), VX128_R , General , 0),
|
||||
SCAN_INSTRUCTION(vsrw128, VX128(6, 464), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vcmpequw128, VX128_R(6, 512), VX128_R , General , 0),
|
||||
SCAN_INSTRUCTION(vmaxfp128, VX128(6, 640), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vminfp128, VX128(6, 704), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vmrghw128, VX128(6, 768), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vmrglw128, VX128(6, 832), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vupkhsb128, VX128(6, 896), VX128 , General , 0),
|
||||
SCAN_INSTRUCTION(vupklsb128, VX128(6, 960), VX128 , General , 0),
|
||||
};
|
||||
#undef OP
|
||||
#undef VX128
|
||||
#undef VX128_1
|
||||
#undef VX128_2
|
||||
#undef VX128_3
|
||||
#undef VX128_4
|
||||
#undef VX128_5
|
||||
#undef VX128_P
|
||||
|
||||
|
||||
#undef FLAG
|
||||
#undef INSTRUCTION
|
||||
#undef EMPTY
|
||||
|
||||
|
||||
} // namespace tables
|
||||
} // namespace ppc
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_PPC_INSTR_TABLE_H_
|
||||
@@ -1,40 +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 XENIA_CPU_PPC_REGISTERS_H_
|
||||
#define XENIA_CPU_PPC_REGISTERS_H_
|
||||
|
||||
#include <xenia/common.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace ppc {
|
||||
|
||||
|
||||
typedef bool (*RegisterHandlesCallback)(void* context, uint32_t addr);
|
||||
typedef uint64_t (*RegisterReadCallback)(void* context, uint32_t addr);
|
||||
typedef void (*RegisterWriteCallback)(void* context, uint32_t addr,
|
||||
uint64_t value);
|
||||
|
||||
|
||||
typedef struct {
|
||||
void* context;
|
||||
RegisterHandlesCallback handles;
|
||||
RegisterReadCallback read;
|
||||
RegisterWriteCallback write;
|
||||
} RegisterAccessCallbacks;
|
||||
|
||||
|
||||
} // namespace ppc
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_PPC_REGISTERS_H_
|
||||
@@ -1,17 +0,0 @@
|
||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'disasm.h',
|
||||
'disasm_altivec.cc',
|
||||
'disasm_alu.cc',
|
||||
'disasm_control.cc',
|
||||
'disasm_fpu.cc',
|
||||
'disasm_memory.cc',
|
||||
'instr.cc',
|
||||
'instr.h',
|
||||
'instr_tables.h',
|
||||
'registers.h',
|
||||
'state.cc',
|
||||
'state.h',
|
||||
],
|
||||
}
|
||||
@@ -1,47 +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 <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
#include <xenia/cpu/ppc/state.h>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
uint64_t ParseInt64(const char* value) {
|
||||
return xestrtoulla(value, NULL, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void xe_ppc_state::SetRegFromString(const char* name, const char* value) {
|
||||
int n;
|
||||
if (sscanf(name, "r%d", &n) == 1) {
|
||||
this->r[n] = ParseInt64(value);
|
||||
} else {
|
||||
printf("Unrecognized register name: %s\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
bool xe_ppc_state::CompareRegWithString(
|
||||
const char* name, const char* value,
|
||||
char* out_value, size_t out_value_size) {
|
||||
int n;
|
||||
if (sscanf(name, "r%d", &n) == 1) {
|
||||
uint64_t expected = ParseInt64(value);
|
||||
if (this->r[n] != expected) {
|
||||
xesnprintfa(out_value, out_value_size, "%016llX", this->r[n]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
printf("Unrecognized register name: %s\n", name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,167 +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 XENIA_CPU_PPC_STATE_H_
|
||||
#define XENIA_CPU_PPC_STATE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
XEDECLARECLASS2(xe, cpu, Processor);
|
||||
XEDECLARECLASS2(xe, cpu, ThreadState);
|
||||
|
||||
|
||||
// namespace FPRF {
|
||||
// enum FPRF_e {
|
||||
// QUIET_NAN = 0x00088000,
|
||||
// NEG_INFINITY = 0x00090000,
|
||||
// NEG_NORMALIZED = 0x00010000,
|
||||
// NEG_DENORMALIZED = 0x00018000,
|
||||
// NEG_ZERO = 0x00048000,
|
||||
// POS_ZERO = 0x00040000,
|
||||
// POS_DENORMALIZED = 0x00028000,
|
||||
// POS_NORMALIZED = 0x00020000,
|
||||
// POS_INFINITY = 0x000A0000,
|
||||
// };
|
||||
// } // FPRF
|
||||
|
||||
|
||||
#define kXEPPCRegLR 0xFFFF0001
|
||||
#define kXEPPCRegCTR 0xFFFF0002
|
||||
|
||||
|
||||
typedef struct XECACHEALIGN xe_float4 {
|
||||
union {
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
struct {
|
||||
uint32_t ix;
|
||||
uint32_t iy;
|
||||
uint32_t iz;
|
||||
uint32_t iw;
|
||||
};
|
||||
float f4[4];
|
||||
uint32_t i4[4];
|
||||
struct {
|
||||
uint64_t low;
|
||||
uint64_t high;
|
||||
};
|
||||
};
|
||||
} xe_float4_t;
|
||||
|
||||
|
||||
typedef struct XECACHEALIGN64 xe_ppc_state {
|
||||
uint32_t cia; // Current PC (CIA)
|
||||
uint32_t nia; // Next PC (NIA)
|
||||
uint64_t xer; // XER register
|
||||
uint64_t lr; // Link register
|
||||
uint64_t ctr; // Count register
|
||||
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t lt :1; // Negative (LT) - result is negative
|
||||
uint8_t gt :1; // Positive (GT) - result is positive (and not zero)
|
||||
uint8_t eq :1; // Zero (EQ) - result is zero or a stwcx/stdcx completed successfully
|
||||
uint8_t so :1; // Summary Overflow (SO) - copy of XER[SO]
|
||||
} cr0;
|
||||
struct {
|
||||
uint8_t fx :1; // FP exception summary - copy of FPSCR[FX]
|
||||
uint8_t fex :1; // FP enabled exception summary - copy of FPSCR[FEX]
|
||||
uint8_t vx :1; // FP invalid operation exception summary - copy of FPSCR[VX]
|
||||
uint8_t ox :1; // FP overflow exception - copy of FPSCR[OX]
|
||||
} cr1;
|
||||
struct {
|
||||
uint8_t value :4;
|
||||
} cr2;
|
||||
struct {
|
||||
uint8_t value :4;
|
||||
} cr3;
|
||||
struct {
|
||||
uint8_t value :4;
|
||||
} cr4;
|
||||
struct {
|
||||
uint8_t value :4;
|
||||
} cr5;
|
||||
struct {
|
||||
uint8_t value :4;
|
||||
} cr6;
|
||||
struct {
|
||||
uint8_t value :4;
|
||||
} cr7;
|
||||
} cr; // Condition register
|
||||
|
||||
union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint8_t fx :1; // FP exception summary -- sticky
|
||||
uint8_t fex :1; // FP enabled exception summary
|
||||
uint8_t vx :1; // FP invalid operation exception summary
|
||||
uint8_t ox :1; // FP overflow exception -- sticky
|
||||
uint8_t ux :1; // FP underflow exception -- sticky
|
||||
uint8_t zx :1; // FP zero divide exception -- sticky
|
||||
uint8_t xx :1; // FP inexact exception -- sticky
|
||||
uint8_t vxsnan :1; // FP invalid op exception: SNaN -- sticky
|
||||
uint8_t vxisi :1; // FP invalid op exception: infinity - infinity -- sticky
|
||||
uint8_t vxidi :1; // FP invalid op exception: infinity / infinity -- sticky
|
||||
uint8_t vxzdz :1; // FP invalid op exception: 0 / 0 -- sticky
|
||||
uint8_t vximz :1; // FP invalid op exception: infinity * 0 -- sticky
|
||||
uint8_t vxvc :1; // FP invalid op exception: invalid compare -- sticky
|
||||
uint8_t fr :1; // FP fraction rounded
|
||||
uint8_t fi :1; // FP fraction inexact
|
||||
uint8_t fprf_c :1; // FP result class
|
||||
uint8_t fprf_lt :1; // FP result less than or negative (FL or <)
|
||||
uint8_t fprf_gt :1; // FP result greater than or positive (FG or >)
|
||||
uint8_t fprf_eq :1; // FP result equal or zero (FE or =)
|
||||
uint8_t fprf_un :1; // FP result unordered or NaN (FU or ?)
|
||||
uint8_t reserved :1;
|
||||
uint8_t vxsoft :1; // FP invalid op exception: software request -- sticky
|
||||
uint8_t vxsqrt :1; // FP invalid op exception: invalid sqrt -- sticky
|
||||
uint8_t vxcvi :1; // FP invalid op exception: invalid integer convert -- sticky
|
||||
uint8_t ve :1; // FP invalid op exception enable
|
||||
uint8_t oe :1; // IEEE floating-point overflow exception enable
|
||||
uint8_t ue :1; // IEEE floating-point underflow exception enable
|
||||
uint8_t ze :1; // IEEE floating-point zero divide exception enable
|
||||
uint8_t xe :1; // IEEE floating-point inexact exception enable
|
||||
uint8_t ni :1; // Floating-point non-IEEE mode
|
||||
uint8_t rn :2; // FP rounding control: 00 = nearest
|
||||
// 01 = toward zero
|
||||
// 10 = toward +infinity
|
||||
// 11 = toward -infinity
|
||||
} bits;
|
||||
} fpscr; // Floating-point status and control register
|
||||
|
||||
uint64_t r[32]; // General purpose registers
|
||||
xe_float4_t v[128]; // VMX128 vector registers
|
||||
double f[32]; // Floating-point registers
|
||||
|
||||
// uint32_t get_fprf() {
|
||||
// return fpscr.value & 0x000F8000;
|
||||
// }
|
||||
// void set_fprf(const uint32_t v) {
|
||||
// fpscr.value = (fpscr.value & ~0x000F8000) | v;
|
||||
// }
|
||||
|
||||
// Runtime-specific data pointer. Used on callbacks to get access to the
|
||||
// current runtime and its data.
|
||||
uint8_t* membase;
|
||||
xe::cpu::Processor* processor;
|
||||
xe::cpu::ThreadState* thread_state;
|
||||
|
||||
void SetRegFromString(const char* name, const char* value);
|
||||
bool CompareRegWithString(const char* name, const char* value,
|
||||
char* out_value, size_t out_value_size);
|
||||
} xe_ppc_state_t;
|
||||
|
||||
|
||||
#endif // XENIA_CPU_PPC_STATE_H_
|
||||
Reference in New Issue
Block a user