mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 16:31:28 +12:00
Merge pull request #964 from achurch/ppu-interpreter-fixes
Implement missing and fix broken PPU instructions in the interpreter.
This commit is contained in:
commit
10150957ff
8 changed files with 981 additions and 597 deletions
|
@ -1675,6 +1675,10 @@ private:
|
||||||
{
|
{
|
||||||
DisAsm_V1_R2("stvlx", vs, ra, rb);
|
DisAsm_V1_R2("stvlx", vs, ra, rb);
|
||||||
}
|
}
|
||||||
|
void STDBRX(u32 rs, u32 ra, u32 rb)
|
||||||
|
{
|
||||||
|
DisAsm_R3("stdbrx", rs, ra, rb);
|
||||||
|
}
|
||||||
void STSWX(u32 rs, u32 ra, u32 rb)
|
void STSWX(u32 rs, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
DisAsm_R3("swswx", rs, ra, rb);
|
DisAsm_R3("swswx", rs, ra, rb);
|
||||||
|
|
|
@ -226,6 +226,9 @@ namespace PPU_instr
|
||||||
|
|
||||||
#define bind_instr(list, name, ...) \
|
#define bind_instr(list, name, ...) \
|
||||||
static const auto& name = make_instr<PPU_opcodes::name>(list, #name, &PPUOpcodes::name, ##__VA_ARGS__)
|
static const auto& name = make_instr<PPU_opcodes::name>(list, #name, &PPUOpcodes::name, ##__VA_ARGS__)
|
||||||
|
#define bind_instr_oe(list, name, ...) \
|
||||||
|
bind_instr(list, name, ##__VA_ARGS__); \
|
||||||
|
static const auto& name##O = make_instr<PPU_opcodes::name##O>(list, #name "O", &PPUOpcodes::name, ##__VA_ARGS__)
|
||||||
|
|
||||||
bind_instr(main_list, TDI, TO, RA, simm16);
|
bind_instr(main_list, TDI, TO, RA, simm16);
|
||||||
bind_instr(main_list, TWI, TO, RA, simm16);
|
bind_instr(main_list, TWI, TO, RA, simm16);
|
||||||
|
@ -456,9 +459,9 @@ namespace PPU_instr
|
||||||
/*0x004*/bind_instr(g1f_list, TW, TO, RA, RB);
|
/*0x004*/bind_instr(g1f_list, TW, TO, RA, RB);
|
||||||
/*0x006*/bind_instr(g1f_list, LVSL, VD, RA, RB);
|
/*0x006*/bind_instr(g1f_list, LVSL, VD, RA, RB);
|
||||||
/*0x007*/bind_instr(g1f_list, LVEBX, VD, RA, RB);
|
/*0x007*/bind_instr(g1f_list, LVEBX, VD, RA, RB);
|
||||||
/*0x008*/bind_instr(g1f_list, SUBFC, RD, RA, RB, OE, RC);
|
/*0x008*/bind_instr_oe(g1f_list, SUBFC, RD, RA, RB, OE, RC);
|
||||||
/*0x009*/bind_instr(g1f_list, MULHDU, RD, RA, RB, RC);
|
/*0x009*/bind_instr(g1f_list, MULHDU, RD, RA, RB, RC);
|
||||||
/*0x00a*/bind_instr(g1f_list, ADDC, RD, RA, RB, OE, RC);
|
/*0x00a*/bind_instr_oe(g1f_list, ADDC, RD, RA, RB, OE, RC);
|
||||||
/*0x00b*/bind_instr(g1f_list, MULHWU, RD, RA, RB, RC);
|
/*0x00b*/bind_instr(g1f_list, MULHWU, RD, RA, RB, RC);
|
||||||
/*0x013*/bind_instr(g1f_list, MFOCRF, L_11, RD, CRM);
|
/*0x013*/bind_instr(g1f_list, MFOCRF, L_11, RD, CRM);
|
||||||
/*0x014*/bind_instr(g1f_list, LWARX, RD, RA, RB);
|
/*0x014*/bind_instr(g1f_list, LWARX, RD, RA, RB);
|
||||||
|
@ -471,7 +474,7 @@ namespace PPU_instr
|
||||||
/*0x020*/bind_instr(g1f_list, CMPL, CRFD, L_10, RA, RB);
|
/*0x020*/bind_instr(g1f_list, CMPL, CRFD, L_10, RA, RB);
|
||||||
/*0x026*/bind_instr(g1f_list, LVSR, VD, RA, RB);
|
/*0x026*/bind_instr(g1f_list, LVSR, VD, RA, RB);
|
||||||
/*0x027*/bind_instr(g1f_list, LVEHX, VD, RA, RB);
|
/*0x027*/bind_instr(g1f_list, LVEHX, VD, RA, RB);
|
||||||
/*0x028*/bind_instr(g1f_list, SUBF, RD, RA, RB, OE, RC);
|
/*0x028*/bind_instr_oe(g1f_list, SUBF, RD, RA, RB, OE, RC);
|
||||||
/*0x035*/bind_instr(g1f_list, LDUX, RD, RA, RB);
|
/*0x035*/bind_instr(g1f_list, LDUX, RD, RA, RB);
|
||||||
/*0x036*/bind_instr(g1f_list, DCBST, RA, RB);
|
/*0x036*/bind_instr(g1f_list, DCBST, RA, RB);
|
||||||
/*0x037*/bind_instr(g1f_list, LWZUX, RD, RA, RB);
|
/*0x037*/bind_instr(g1f_list, LWZUX, RD, RA, RB);
|
||||||
|
@ -485,12 +488,12 @@ namespace PPU_instr
|
||||||
/*0x056*/bind_instr(g1f_list, DCBF, RA, RB);
|
/*0x056*/bind_instr(g1f_list, DCBF, RA, RB);
|
||||||
/*0x057*/bind_instr(g1f_list, LBZX, RD, RA, RB);
|
/*0x057*/bind_instr(g1f_list, LBZX, RD, RA, RB);
|
||||||
/*0x067*/bind_instr(g1f_list, LVX, VD, RA, RB);
|
/*0x067*/bind_instr(g1f_list, LVX, VD, RA, RB);
|
||||||
/*0x068*/bind_instr(g1f_list, NEG, RD, RA, OE, RC);
|
/*0x068*/bind_instr_oe(g1f_list, NEG, RD, RA, OE, RC);
|
||||||
/*0x077*/bind_instr(g1f_list, LBZUX, RD, RA, RB);
|
/*0x077*/bind_instr(g1f_list, LBZUX, RD, RA, RB);
|
||||||
/*0x07c*/bind_instr(g1f_list, NOR, RA, RS, RB, RC);
|
/*0x07c*/bind_instr(g1f_list, NOR, RA, RS, RB, RC);
|
||||||
/*0x087*/bind_instr(g1f_list, STVEBX, VS, RA, RB);
|
/*0x087*/bind_instr(g1f_list, STVEBX, VS, RA, RB);
|
||||||
/*0x088*/bind_instr(g1f_list, SUBFE, RD, RA, RB, OE, RC);
|
/*0x088*/bind_instr_oe(g1f_list, SUBFE, RD, RA, RB, OE, RC);
|
||||||
/*0x08a*/bind_instr(g1f_list, ADDE, RD, RA, RB, OE, RC);
|
/*0x08a*/bind_instr_oe(g1f_list, ADDE, RD, RA, RB, OE, RC);
|
||||||
/*0x090*/bind_instr(g1f_list, MTOCRF, L_11, CRM, RS);
|
/*0x090*/bind_instr(g1f_list, MTOCRF, L_11, CRM, RS);
|
||||||
/*0x095*/bind_instr(g1f_list, STDX, RS, RA, RB);
|
/*0x095*/bind_instr(g1f_list, STDX, RS, RA, RB);
|
||||||
/*0x096*/bind_instr(g1f_list, STWCX_, RS, RA, RB);
|
/*0x096*/bind_instr(g1f_list, STWCX_, RS, RA, RB);
|
||||||
|
@ -499,18 +502,18 @@ namespace PPU_instr
|
||||||
/*0x0b5*/bind_instr(g1f_list, STDUX, RS, RA, RB);
|
/*0x0b5*/bind_instr(g1f_list, STDUX, RS, RA, RB);
|
||||||
/*0x0b7*/bind_instr(g1f_list, STWUX, RS, RA, RB);
|
/*0x0b7*/bind_instr(g1f_list, STWUX, RS, RA, RB);
|
||||||
/*0x0c7*/bind_instr(g1f_list, STVEWX, VS, RA, RB);
|
/*0x0c7*/bind_instr(g1f_list, STVEWX, VS, RA, RB);
|
||||||
/*0x0c8*/bind_instr(g1f_list, SUBFZE, RD, RA, OE, RC);
|
/*0x0c8*/bind_instr_oe(g1f_list, SUBFZE, RD, RA, OE, RC);
|
||||||
/*0x0ca*/bind_instr(g1f_list, ADDZE, RD, RA, OE, RC);
|
/*0x0ca*/bind_instr_oe(g1f_list, ADDZE, RD, RA, OE, RC);
|
||||||
/*0x0d6*/bind_instr(g1f_list, STDCX_, RS, RA, RB);
|
/*0x0d6*/bind_instr(g1f_list, STDCX_, RS, RA, RB);
|
||||||
/*0x0d7*/bind_instr(g1f_list, STBX, RS, RA, RB);
|
/*0x0d7*/bind_instr(g1f_list, STBX, RS, RA, RB);
|
||||||
/*0x0e7*/bind_instr(g1f_list, STVX, VS, RA, RB);
|
/*0x0e7*/bind_instr(g1f_list, STVX, VS, RA, RB);
|
||||||
/*0x0e8*/bind_instr(g1f_list, SUBFME, RD, RA, OE, RC);
|
/*0x0e8*/bind_instr_oe(g1f_list, SUBFME, RD, RA, OE, RC);
|
||||||
/*0x0e9*/bind_instr(g1f_list, MULLD, RD, RA, RB, OE, RC);
|
/*0x0e9*/bind_instr_oe(g1f_list, MULLD, RD, RA, RB, OE, RC);
|
||||||
/*0x0ea*/bind_instr(g1f_list, ADDME, RD, RA, OE, RC);
|
/*0x0ea*/bind_instr_oe(g1f_list, ADDME, RD, RA, OE, RC);
|
||||||
/*0x0eb*/bind_instr(g1f_list, MULLW, RD, RA, RB, OE, RC);
|
/*0x0eb*/bind_instr_oe(g1f_list, MULLW, RD, RA, RB, OE, RC);
|
||||||
/*0x0f6*/bind_instr(g1f_list, DCBTST, RA, RB, TH);
|
/*0x0f6*/bind_instr(g1f_list, DCBTST, RA, RB, TH);
|
||||||
/*0x0f7*/bind_instr(g1f_list, STBUX, RS, RA, RB);
|
/*0x0f7*/bind_instr(g1f_list, STBUX, RS, RA, RB);
|
||||||
/*0x10a*/bind_instr(g1f_list, ADD, RD, RA, RB, OE, RC);
|
/*0x10a*/bind_instr_oe(g1f_list, ADD, RD, RA, RB, OE, RC);
|
||||||
/*0x116*/bind_instr(g1f_list, DCBT, RA, RB, TH);
|
/*0x116*/bind_instr(g1f_list, DCBT, RA, RB, TH);
|
||||||
/*0x117*/bind_instr(g1f_list, LHZX, RD, RA, RB);
|
/*0x117*/bind_instr(g1f_list, LHZX, RD, RA, RB);
|
||||||
/*0x11c*/bind_instr(g1f_list, EQV, RA, RS, RB, RC);
|
/*0x11c*/bind_instr(g1f_list, EQV, RA, RS, RB, RC);
|
||||||
|
@ -531,15 +534,21 @@ namespace PPU_instr
|
||||||
/*0x1b6*/bind_instr(g1f_list, ECOWX, RS, RA, RB);
|
/*0x1b6*/bind_instr(g1f_list, ECOWX, RS, RA, RB);
|
||||||
/*0x1b7*/bind_instr(g1f_list, STHUX, RS, RA, RB);
|
/*0x1b7*/bind_instr(g1f_list, STHUX, RS, RA, RB);
|
||||||
/*0x1bc*/bind_instr(g1f_list, OR, RA, RS, RB, RC);
|
/*0x1bc*/bind_instr(g1f_list, OR, RA, RS, RB, RC);
|
||||||
/*0x1c9*/bind_instr(g1f_list, DIVDU, RD, RA, RB, OE, RC);
|
/*0x1c9*/bind_instr_oe(g1f_list, DIVDU, RD, RA, RB, OE, RC);
|
||||||
/*0x1cb*/bind_instr(g1f_list, DIVWU, RD, RA, RB, OE, RC);
|
/*0x1cb*/bind_instr_oe(g1f_list, DIVWU, RD, RA, RB, OE, RC);
|
||||||
/*0x1d3*/bind_instr(g1f_list, MTSPR, SPR, RS);
|
/*0x1d3*/bind_instr(g1f_list, MTSPR, SPR, RS);
|
||||||
/*0x1d6*///DCBI
|
/*0x1d6*///DCBI
|
||||||
/*0x1dc*/bind_instr(g1f_list, NAND, RA, RS, RB, RC);
|
/*0x1dc*/bind_instr(g1f_list, NAND, RA, RS, RB, RC);
|
||||||
/*0x1e7*/bind_instr(g1f_list, STVXL, VS, RA, RB);
|
/*0x1e7*/bind_instr(g1f_list, STVXL, VS, RA, RB);
|
||||||
/*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC);
|
/*0x1e9*/bind_instr_oe(g1f_list, DIVD, RD, RA, RB, OE, RC);
|
||||||
/*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC);
|
/*0x1eb*/bind_instr_oe(g1f_list, DIVW, RD, RA, RB, OE, RC);
|
||||||
/*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB);
|
/*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB);
|
||||||
|
// MULH{D|DU|W|WU} don't use OE, but a real Cell accepts
|
||||||
|
// opcodes with OE=1 and Rc=0, behaving as if OE was not set.
|
||||||
|
// OE=1 and Rc=1 causes an invalid instruction exception, but
|
||||||
|
// we don't worry about that.
|
||||||
|
static const auto& MULHDUO = make_instr<0x209>(g1f_list, "MULHDUO", &PPUOpcodes::MULHDU, RD, RA, RB, RC);
|
||||||
|
static const auto& MULHWUO = make_instr<0x20b>(g1f_list, "MULHWUO", &PPUOpcodes::MULHWU, RD, RA, RB, RC);
|
||||||
/*0x214*/bind_instr(g1f_list, LDBRX, RD, RA, RB);
|
/*0x214*/bind_instr(g1f_list, LDBRX, RD, RA, RB);
|
||||||
/*0x215*/bind_instr(g1f_list, LSWX, RD, RA, RB);
|
/*0x215*/bind_instr(g1f_list, LSWX, RD, RA, RB);
|
||||||
/*0x216*/bind_instr(g1f_list, LWBRX, RD, RA, RB);
|
/*0x216*/bind_instr(g1f_list, LWBRX, RD, RA, RB);
|
||||||
|
@ -548,11 +557,14 @@ namespace PPU_instr
|
||||||
/*0x21b*/bind_instr(g1f_list, SRD, RA, RS, RB, RC);
|
/*0x21b*/bind_instr(g1f_list, SRD, RA, RS, RB, RC);
|
||||||
/*0x227*/bind_instr(g1f_list, LVRX, VD, RA, RB);
|
/*0x227*/bind_instr(g1f_list, LVRX, VD, RA, RB);
|
||||||
/*0x237*/bind_instr(g1f_list, LFSUX, FRD, RA, RB);
|
/*0x237*/bind_instr(g1f_list, LFSUX, FRD, RA, RB);
|
||||||
|
static const auto& MULHDO = make_instr<0x249>(g1f_list, "MULHDO", &PPUOpcodes::MULHD, RD, RA, RB, RC);
|
||||||
|
static const auto& MULHWO = make_instr<0x24b>(g1f_list, "MULHWO", &PPUOpcodes::MULHW, RD, RA, RB, RC);
|
||||||
/*0x255*/bind_instr(g1f_list, LSWI, RD, RA, NB);
|
/*0x255*/bind_instr(g1f_list, LSWI, RD, RA, NB);
|
||||||
/*0x256*/bind_instr(g1f_list, SYNC, L_9_10);
|
/*0x256*/bind_instr(g1f_list, SYNC, L_9_10);
|
||||||
/*0x257*/bind_instr(g1f_list, LFDX, FRD, RA, RB);
|
/*0x257*/bind_instr(g1f_list, LFDX, FRD, RA, RB);
|
||||||
/*0x277*/bind_instr(g1f_list, LFDUX, FRD, RA, RB);
|
/*0x277*/bind_instr(g1f_list, LFDUX, FRD, RA, RB);
|
||||||
/*0x287*/bind_instr(g1f_list, STVLX, VS, RA, RB);
|
/*0x287*/bind_instr(g1f_list, STVLX, VS, RA, RB);
|
||||||
|
/*0x294*/bind_instr(g1f_list, STDBRX, RD, RA, RB);
|
||||||
/*0x296*/bind_instr(g1f_list, STSWX, RS, RA, RB);
|
/*0x296*/bind_instr(g1f_list, STSWX, RS, RA, RB);
|
||||||
/*0x296*/bind_instr(g1f_list, STWBRX, RS, RA, RB);
|
/*0x296*/bind_instr(g1f_list, STWBRX, RS, RA, RB);
|
||||||
/*0x297*/bind_instr(g1f_list, STFSX, FRS, RA, RB);
|
/*0x297*/bind_instr(g1f_list, STFSX, FRS, RA, RB);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3311,7 +3311,7 @@ void Compiler::MFSPR(u32 rd, u32 spr) {
|
||||||
rd_i64 = GetCtr();
|
rd_i64 = GetCtr();
|
||||||
break;
|
break;
|
||||||
case 0x100:
|
case 0x100:
|
||||||
rd_i64 = GetUsprg0();
|
rd_i64 = GetVrsave();
|
||||||
break;
|
break;
|
||||||
case 0x10C:
|
case 0x10C:
|
||||||
rd_i64 = Call<u64>("get_time", get_time);
|
rd_i64 = Call<u64>("get_time", get_time);
|
||||||
|
@ -3503,7 +3503,7 @@ void Compiler::MTSPR(u32 spr, u32 rs) {
|
||||||
SetCtr(rs_i64);
|
SetCtr(rs_i64);
|
||||||
break;
|
break;
|
||||||
case 0x100:
|
case 0x100:
|
||||||
SetUsprg0(rs_i64);
|
SetVrsave(rs_i64);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -3746,6 +3746,16 @@ void Compiler::STVLX(u32 vs, u32 ra, u32 rb) {
|
||||||
addr_i8_ptr, vs_i8_ptr, size_i64, m_ir_builder->getInt32(1), m_ir_builder->getInt1(false));
|
addr_i8_ptr, vs_i8_ptr, size_i64, m_ir_builder->getInt32(1), m_ir_builder->getInt1(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Compiler::STDBRX(u32 rs, u32 ra, u32 rb) {
|
||||||
|
auto addr_i64 = GetGpr(rb);
|
||||||
|
if (ra) {
|
||||||
|
auto ra_i64 = GetGpr(ra);
|
||||||
|
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteMemory(addr_i64, GetGpr(rs), 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
void Compiler::STSWX(u32 rs, u32 ra, u32 rb) {
|
void Compiler::STSWX(u32 rs, u32 ra, u32 rb) {
|
||||||
CompilationError("STSWX");
|
CompilationError("STSWX");
|
||||||
}
|
}
|
||||||
|
@ -5268,17 +5278,19 @@ void Compiler::SetXerSo(Value * so) {
|
||||||
SetXer(xer_i64);
|
SetXer(xer_i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value * Compiler::GetUsprg0() {
|
Value * Compiler::GetVrsave() {
|
||||||
auto usrpg0_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, USPRG));
|
auto vrsave_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VRSAVE));
|
||||||
auto usprg0_i64_ptr = m_ir_builder->CreateBitCast(usrpg0_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
auto vrsave_i32_ptr = m_ir_builder->CreateBitCast(vrsave_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
|
||||||
return m_ir_builder->CreateAlignedLoad(usprg0_i64_ptr, 8);
|
auto val_i32 = m_ir_builder->CreateAlignedLoad(vrsave_i32_ptr, 4);
|
||||||
|
return m_ir_builder->CreateZExtOrTrunc(val_i32, m_ir_builder->getInt64Ty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::SetUsprg0(Value * val_x64) {
|
void Compiler::SetVrsave(Value * val_x64) {
|
||||||
auto val_i64 = m_ir_builder->CreateBitCast(val_x64, m_ir_builder->getInt64Ty());
|
auto val_i64 = m_ir_builder->CreateBitCast(val_x64, m_ir_builder->getInt64Ty());
|
||||||
auto usprg0_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, USPRG));
|
auto val_i32 = m_ir_builder->CreateZExtOrTrunc(val_i64, m_ir_builder->getInt32Ty());
|
||||||
auto usprg0_i64_ptr = m_ir_builder->CreateBitCast(usprg0_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
auto vrsave_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VRSAVE));
|
||||||
m_ir_builder->CreateAlignedStore(val_i64, usprg0_i64_ptr, 8);
|
auto vrsave_i32_ptr = m_ir_builder->CreateBitCast(vrsave_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
|
||||||
|
m_ir_builder->CreateAlignedStore(val_i32, vrsave_i32_ptr, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value * Compiler::GetFpscr() {
|
Value * Compiler::GetFpscr() {
|
||||||
|
|
|
@ -598,6 +598,7 @@ namespace ppu_recompiler_llvm {
|
||||||
void LFDX(u32 frd, u32 ra, u32 rb) override;
|
void LFDX(u32 frd, u32 ra, u32 rb) override;
|
||||||
void LFDUX(u32 frd, u32 ra, u32 rb) override;
|
void LFDUX(u32 frd, u32 ra, u32 rb) override;
|
||||||
void STVLX(u32 vs, u32 ra, u32 rb) override;
|
void STVLX(u32 vs, u32 ra, u32 rb) override;
|
||||||
|
void STDBRX(u32 rd, u32 ra, u32 rb) override;
|
||||||
void STSWX(u32 rs, u32 ra, u32 rb) override;
|
void STSWX(u32 rs, u32 ra, u32 rb) override;
|
||||||
void STWBRX(u32 rs, u32 ra, u32 rb) override;
|
void STWBRX(u32 rs, u32 ra, u32 rb) override;
|
||||||
void STFSX(u32 frs, u32 ra, u32 rb) override;
|
void STFSX(u32 frs, u32 ra, u32 rb) override;
|
||||||
|
@ -859,11 +860,11 @@ namespace ppu_recompiler_llvm {
|
||||||
/// Set the SO bit of XER
|
/// Set the SO bit of XER
|
||||||
void SetXerSo(llvm::Value * so);
|
void SetXerSo(llvm::Value * so);
|
||||||
|
|
||||||
/// Get USPRG0
|
/// Get VRSAVE
|
||||||
llvm::Value * GetUsprg0();
|
llvm::Value * GetVrsave();
|
||||||
|
|
||||||
/// Set USPRG0
|
/// Set VRSAVE
|
||||||
void SetUsprg0(llvm::Value * val_x64);
|
void SetVrsave(llvm::Value * val_x64);
|
||||||
|
|
||||||
/// Load FPSCR
|
/// Load FPSCR
|
||||||
llvm::Value * GetFpscr();
|
llvm::Value * GetFpscr();
|
||||||
|
|
|
@ -344,6 +344,8 @@ namespace PPU_opcodes
|
||||||
DIVD = 0x1e9,
|
DIVD = 0x1e9,
|
||||||
DIVW = 0x1eb,
|
DIVW = 0x1eb,
|
||||||
LVLX = 0x207, //Load Vector Left Indexed
|
LVLX = 0x207, //Load Vector Left Indexed
|
||||||
|
SUBFCO = 0x208,
|
||||||
|
ADDCO = 0x20a,
|
||||||
LDBRX = 0x214,
|
LDBRX = 0x214,
|
||||||
LSWX = 0x215,
|
LSWX = 0x215,
|
||||||
LWBRX = 0x216,
|
LWBRX = 0x216,
|
||||||
|
@ -351,21 +353,33 @@ namespace PPU_opcodes
|
||||||
SRW = 0x218,
|
SRW = 0x218,
|
||||||
SRD = 0x21b,
|
SRD = 0x21b,
|
||||||
LVRX = 0x227, //Load Vector Right Indexed
|
LVRX = 0x227, //Load Vector Right Indexed
|
||||||
|
SUBFO = 0x228,
|
||||||
LFSUX = 0x237,
|
LFSUX = 0x237,
|
||||||
LSWI = 0x255,
|
LSWI = 0x255,
|
||||||
SYNC = 0x256,
|
SYNC = 0x256,
|
||||||
LFDX = 0x257,
|
LFDX = 0x257,
|
||||||
|
NEGO = 0x268,
|
||||||
LFDUX = 0x277,
|
LFDUX = 0x277,
|
||||||
STVLX = 0x287, //Store Vector Left Indexed
|
STVLX = 0x287, //Store Vector Left Indexed
|
||||||
|
SUBFEO = 0x288,
|
||||||
|
ADDEO = 0x28a,
|
||||||
|
STDBRX = 0x294,
|
||||||
STSWX = 0x295,
|
STSWX = 0x295,
|
||||||
STWBRX = 0x296,
|
STWBRX = 0x296,
|
||||||
STFSX = 0x297,
|
STFSX = 0x297,
|
||||||
STVRX = 0x2a7, //Store Vector Right Indexed
|
STVRX = 0x2a7, //Store Vector Right Indexed
|
||||||
STFSUX = 0x2b7,
|
STFSUX = 0x2b7,
|
||||||
|
SUBFZEO= 0x2c8,
|
||||||
|
ADDZEO = 0x2ca,
|
||||||
STSWI = 0x2d5,
|
STSWI = 0x2d5,
|
||||||
STFDX = 0x2d7, //Store Floating-Point Double Indexed
|
STFDX = 0x2d7, //Store Floating-Point Double Indexed
|
||||||
|
SUBFMEO= 0x2e8,
|
||||||
|
MULLDO = 0x2e9,
|
||||||
|
ADDMEO = 0x2ea,
|
||||||
|
MULLWO = 0x2eb,
|
||||||
STFDUX = 0x2f7,
|
STFDUX = 0x2f7,
|
||||||
LVLXL = 0x307, //Load Vector Left Indexed Last
|
LVLXL = 0x307, //Load Vector Left Indexed Last
|
||||||
|
ADDO = 0x30a,
|
||||||
LHBRX = 0x316,
|
LHBRX = 0x316,
|
||||||
SRAW = 0x318,
|
SRAW = 0x318,
|
||||||
SRAD = 0x31a,
|
SRAD = 0x31a,
|
||||||
|
@ -380,9 +394,13 @@ namespace PPU_opcodes
|
||||||
EXTSH = 0x39a,
|
EXTSH = 0x39a,
|
||||||
STVRXL = 0x3a7, //Store Vector Right Indexed Last
|
STVRXL = 0x3a7, //Store Vector Right Indexed Last
|
||||||
EXTSB = 0x3ba,
|
EXTSB = 0x3ba,
|
||||||
|
DIVDUO = 0x3c9,
|
||||||
|
DIVWUO = 0x3cb,
|
||||||
STFIWX = 0x3d7,
|
STFIWX = 0x3d7,
|
||||||
EXTSW = 0x3da,
|
EXTSW = 0x3da,
|
||||||
ICBI = 0x3d6, //Instruction Cache Block Invalidate
|
ICBI = 0x3d6, //Instruction Cache Block Invalidate
|
||||||
|
DIVDO = 0x3e9,
|
||||||
|
DIVWO = 0x3eb,
|
||||||
DCBZ = 0x3f6, //Data Cache Block Set to Zero
|
DCBZ = 0x3f6, //Data Cache Block Set to Zero
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -759,6 +777,7 @@ public:
|
||||||
virtual void LFDX(u32 frd, u32 ra, u32 rb) = 0;
|
virtual void LFDX(u32 frd, u32 ra, u32 rb) = 0;
|
||||||
virtual void LFDUX(u32 frd, u32 ra, u32 rb) = 0;
|
virtual void LFDUX(u32 frd, u32 ra, u32 rb) = 0;
|
||||||
virtual void STVLX(u32 vs, u32 ra, u32 rb) = 0;
|
virtual void STVLX(u32 vs, u32 ra, u32 rb) = 0;
|
||||||
|
virtual void STDBRX(u32 rs, u32 ra, u32 rb) = 0;
|
||||||
virtual void STSWX(u32 rs, u32 ra, u32 rb) = 0;
|
virtual void STSWX(u32 rs, u32 ra, u32 rb) = 0;
|
||||||
virtual void STWBRX(u32 rs, u32 ra, u32 rb) = 0;
|
virtual void STWBRX(u32 rs, u32 ra, u32 rb) = 0;
|
||||||
virtual void STFSX(u32 frs, u32 ra, u32 rb) = 0;
|
virtual void STFSX(u32 frs, u32 ra, u32 rb) = 0;
|
||||||
|
|
|
@ -43,7 +43,6 @@ void PPUThread::DoReset()
|
||||||
memset(FPR, 0, sizeof(FPR));
|
memset(FPR, 0, sizeof(FPR));
|
||||||
memset(GPR, 0, sizeof(GPR));
|
memset(GPR, 0, sizeof(GPR));
|
||||||
memset(SPRG, 0, sizeof(SPRG));
|
memset(SPRG, 0, sizeof(SPRG));
|
||||||
memset(USPRG, 0, sizeof(USPRG));
|
|
||||||
|
|
||||||
CR.CR = 0;
|
CR.CR = 0;
|
||||||
LR = 0;
|
LR = 0;
|
||||||
|
@ -52,6 +51,7 @@ void PPUThread::DoReset()
|
||||||
XER.XER = 0;
|
XER.XER = 0;
|
||||||
FPSCR.FPSCR = 0;
|
FPSCR.FPSCR = 0;
|
||||||
VSCR.VSCR = 0;
|
VSCR.VSCR = 0;
|
||||||
|
VRSAVE = 0;
|
||||||
|
|
||||||
cycle = 0;
|
cycle = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ enum FPSCR_EXP
|
||||||
FPSCR_VXSOFT = 0x00000400,
|
FPSCR_VXSOFT = 0x00000400,
|
||||||
FPSCR_VXSQRT = 0x00000200,
|
FPSCR_VXSQRT = 0x00000200,
|
||||||
FPSCR_VXCVI = 0x00000100,
|
FPSCR_VXCVI = 0x00000100,
|
||||||
|
|
||||||
|
FPSCR_VX_ALL = FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI | FPSCR_VXZDZ | FPSCR_VXIMZ | FPSCR_VXVC | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FPSCR_RN
|
enum FPSCR_RN
|
||||||
|
@ -441,18 +443,22 @@ struct PPCdouble
|
||||||
|
|
||||||
PPCdouble() : _u64(0)
|
PPCdouble() : _u64(0)
|
||||||
{
|
{
|
||||||
|
type = UpdateType();
|
||||||
}
|
}
|
||||||
|
|
||||||
PPCdouble(double val) : _double(val)
|
PPCdouble(double val) : _double(val)
|
||||||
{
|
{
|
||||||
|
type = UpdateType();
|
||||||
}
|
}
|
||||||
|
|
||||||
PPCdouble(u64 val) : _u64(val)
|
PPCdouble(u64 val) : _u64(val)
|
||||||
{
|
{
|
||||||
|
type = UpdateType();
|
||||||
}
|
}
|
||||||
|
|
||||||
PPCdouble(u32 val) : _u64(val)
|
PPCdouble(u32 val) : _u64(val)
|
||||||
{
|
{
|
||||||
|
type = UpdateType();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -531,20 +537,12 @@ public:
|
||||||
u64 LR; //SPR 0x008 : Link Register
|
u64 LR; //SPR 0x008 : Link Register
|
||||||
u64 CTR; //SPR 0x009 : Count Register
|
u64 CTR; //SPR 0x009 : Count Register
|
||||||
|
|
||||||
u64 USPRG[8]; //SPR 0x100 - 0x107: User-SPR General-Purpose Registers
|
u32 VRSAVE; //SPR 0x100: VR Save/Restore Register (32 bits)
|
||||||
|
|
||||||
u64 SPRG[8]; //SPR 0x110 - 0x117 : SPR General-Purpose Registers
|
u64 SPRG[8]; //SPR 0x110 - 0x117 : SPR General-Purpose Registers
|
||||||
|
|
||||||
//TBR : Time-Base Registers
|
//TBR : Time-Base Registers
|
||||||
union
|
u64 TB; //TBR 0x10C - 0x10D
|
||||||
{
|
|
||||||
u64 TB; //TBR 0x10C - 0x10D
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
u32 TBH;
|
|
||||||
u32 TBL;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
u64 cycle;
|
u64 cycle;
|
||||||
|
|
||||||
|
@ -652,7 +650,7 @@ public:
|
||||||
UpdateCRn<T>(0, val, 0);
|
UpdateCRn<T>(0, val, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void UpdateCR1()
|
void UpdateCR1()
|
||||||
{
|
{
|
||||||
SetCR_LT(1, FPSCR.FX);
|
SetCR_LT(1, FPSCR.FX);
|
||||||
SetCR_GT(1, FPSCR.FEX);
|
SetCR_GT(1, FPSCR.FEX);
|
||||||
|
@ -670,10 +668,37 @@ public:
|
||||||
bool IsCarry(const u64 a, const u64 b) { return (a + b) < a; }
|
bool IsCarry(const u64 a, const u64 b) { return (a + b) < a; }
|
||||||
bool IsCarry(const u64 a, const u64 b, const u64 c) { return IsCarry(a, b) || IsCarry(a + b, c); }
|
bool IsCarry(const u64 a, const u64 b, const u64 c) { return IsCarry(a, b) || IsCarry(a + b, c); }
|
||||||
|
|
||||||
|
void SetOV(const bool set)
|
||||||
|
{
|
||||||
|
XER.OV = set;
|
||||||
|
XER.SO |= set;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateFPSCR_FEX()
|
||||||
|
{
|
||||||
|
const u32 exceptions = (FPSCR.FPSCR >> 25) & 0x1F;
|
||||||
|
const u32 enabled = (FPSCR.FPSCR >> 3) & 0x1F;
|
||||||
|
if (exceptions & enabled) FPSCR.FEX = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateFPSCR_VX()
|
||||||
|
{
|
||||||
|
if (FPSCR.FPSCR & FPSCR_VX_ALL) FPSCR.VX = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFPSCR(const u32 val)
|
||||||
|
{
|
||||||
|
FPSCR.FPSCR = val & ~(FPSCR_FEX | FPSCR_VX);
|
||||||
|
UpdateFPSCR_VX();
|
||||||
|
UpdateFPSCR_FEX();
|
||||||
|
}
|
||||||
|
|
||||||
void SetFPSCRException(const FPSCR_EXP mask)
|
void SetFPSCRException(const FPSCR_EXP mask)
|
||||||
{
|
{
|
||||||
if ((FPSCR.FPSCR & mask) != mask) FPSCR.FX = 1;
|
if ((FPSCR.FPSCR & mask) != mask) FPSCR.FX = 1;
|
||||||
FPSCR.FPSCR |= mask;
|
FPSCR.FPSCR |= mask;
|
||||||
|
UpdateFPSCR_VX();
|
||||||
|
UpdateFPSCR_FEX();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFPSCR_FI(const u32 val)
|
void SetFPSCR_FI(const u32 val)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue