Implement missing PPU instructions.

This commit is contained in:
Andrew Church 2015-01-18 07:00:58 +09:00
parent 692502b177
commit ae4420e604
7 changed files with 179 additions and 80 deletions

View File

@ -1675,6 +1675,10 @@ private:
{
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)
{
DisAsm_R3("swswx", rs, ra, rb);

View File

@ -226,6 +226,9 @@ namespace PPU_instr
#define bind_instr(list, name, ...) \
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, TWI, TO, RA, simm16);
@ -456,9 +459,9 @@ namespace PPU_instr
/*0x004*/bind_instr(g1f_list, TW, TO, RA, RB);
/*0x006*/bind_instr(g1f_list, LVSL, 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);
/*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);
/*0x013*/bind_instr(g1f_list, MFOCRF, L_11, RD, CRM);
/*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);
/*0x026*/bind_instr(g1f_list, LVSR, 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);
/*0x036*/bind_instr(g1f_list, DCBST, 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);
/*0x057*/bind_instr(g1f_list, LBZX, RD, 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);
/*0x07c*/bind_instr(g1f_list, NOR, RA, RS, RB, RC);
/*0x087*/bind_instr(g1f_list, STVEBX, VS, RA, RB);
/*0x088*/bind_instr(g1f_list, SUBFE, RD, RA, RB, OE, RC);
/*0x08a*/bind_instr(g1f_list, ADDE, RD, RA, RB, OE, RC);
/*0x088*/bind_instr_oe(g1f_list, SUBFE, 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);
/*0x095*/bind_instr(g1f_list, STDX, 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);
/*0x0b7*/bind_instr(g1f_list, STWUX, RS, RA, RB);
/*0x0c7*/bind_instr(g1f_list, STVEWX, VS, RA, RB);
/*0x0c8*/bind_instr(g1f_list, SUBFZE, RD, RA, OE, RC);
/*0x0ca*/bind_instr(g1f_list, ADDZE, RD, RA, OE, RC);
/*0x0c8*/bind_instr_oe(g1f_list, SUBFZE, RD, RA, OE, RC);
/*0x0ca*/bind_instr_oe(g1f_list, ADDZE, RD, RA, OE, RC);
/*0x0d6*/bind_instr(g1f_list, STDCX_, RS, RA, RB);
/*0x0d7*/bind_instr(g1f_list, STBX, RS, RA, RB);
/*0x0e7*/bind_instr(g1f_list, STVX, VS, RA, RB);
/*0x0e8*/bind_instr(g1f_list, SUBFME, RD, RA, OE, RC);
/*0x0e9*/bind_instr(g1f_list, MULLD, RD, RA, RB, OE, RC);
/*0x0ea*/bind_instr(g1f_list, ADDME, RD, RA, OE, RC);
/*0x0eb*/bind_instr(g1f_list, MULLW, RD, RA, RB, OE, RC);
/*0x0e8*/bind_instr_oe(g1f_list, SUBFME, RD, RA, OE, RC);
/*0x0e9*/bind_instr_oe(g1f_list, MULLD, RD, RA, RB, OE, RC);
/*0x0ea*/bind_instr_oe(g1f_list, ADDME, RD, RA, OE, RC);
/*0x0eb*/bind_instr_oe(g1f_list, MULLW, RD, RA, RB, OE, RC);
/*0x0f6*/bind_instr(g1f_list, DCBTST, RA, RB, TH);
/*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);
/*0x117*/bind_instr(g1f_list, LHZX, RD, RA, RB);
/*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);
/*0x1b7*/bind_instr(g1f_list, STHUX, RS, RA, RB);
/*0x1bc*/bind_instr(g1f_list, OR, RA, RS, RB, RC);
/*0x1c9*/bind_instr(g1f_list, DIVDU, RD, RA, RB, OE, RC);
/*0x1cb*/bind_instr(g1f_list, DIVWU, RD, RA, RB, OE, RC);
/*0x1c9*/bind_instr_oe(g1f_list, DIVDU, 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);
/*0x1d6*///DCBI
/*0x1dc*/bind_instr(g1f_list, NAND, RA, RS, RB, RC);
/*0x1e7*/bind_instr(g1f_list, STVXL, VS, RA, RB);
/*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC);
/*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC);
/*0x1e9*/bind_instr_oe(g1f_list, DIVD, 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);
// 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);
/*0x215*/bind_instr(g1f_list, LSWX, 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);
/*0x227*/bind_instr(g1f_list, LVRX, VD, 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);
/*0x256*/bind_instr(g1f_list, SYNC, L_9_10);
/*0x257*/bind_instr(g1f_list, LFDX, FRD, RA, RB);
/*0x277*/bind_instr(g1f_list, LFDUX, FRD, 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, STWBRX, RS, RA, RB);
/*0x297*/bind_instr(g1f_list, STFSX, FRS, RA, RB);
@ -657,4 +669,4 @@ namespace PPU_instr
using namespace lists;
using namespace implicts;
#undef bind_instr
};
};

View File

@ -2381,16 +2381,16 @@ private:
const u64 RB = CPU.GPR[rb];
CPU.GPR[rd] = ~RA + RB + 1;
CPU.XER.CA = CPU.IsCarry(~RA, RB, 1);
if(oe) throw "SUBFC(): subfco";
if(oe) CPU.SetOV((~RA>>63 == RB>>63) && (~RA>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void ADDC(u32 rd, u32 ra, u32 rb, u32 oe, bool rc)
{
const s64 RA = CPU.GPR[ra];
const s64 RB = CPU.GPR[rb];
const u64 RA = CPU.GPR[ra];
const u64 RB = CPU.GPR[rb];
CPU.GPR[rd] = RA + RB;
CPU.XER.CA = CPU.IsCarry(RA, RB);
if(oe) throw "ADDC(): addco";
if(oe) CPU.SetOV((RA>>63 == RB>>63) && (RA>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void MULHDU(u32 rd, u32 ra, u32 rb, bool rc)
@ -2526,8 +2526,10 @@ private:
}
void SUBF(u32 rd, u32 ra, u32 rb, u32 oe, bool rc)
{
CPU.GPR[rd] = CPU.GPR[rb] - CPU.GPR[ra];
if(oe) throw "SUBF(): subfo";
const u64 RA = CPU.GPR[ra];
const u64 RB = CPU.GPR[rb];
CPU.GPR[rd] = RB - RA;
if(oe) CPU.SetOV((~RA>>63 == RB>>63) && (~RA>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void LDUX(u32 rd, u32 ra, u32 rb)
@ -2605,8 +2607,9 @@ private:
}
void NEG(u32 rd, u32 ra, u32 oe, bool rc)
{
CPU.GPR[rd] = 0-CPU.GPR[ra];
if(oe) throw "NEG(): nego";
const u64 RA = CPU.GPR[ra];
CPU.GPR[rd] = 0 - RA;
if(oe) CPU.SetOV((~RA>>63 == 0) && (~RA>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void LBZUX(u32 rd, u32 ra, u32 rb)
@ -2634,8 +2637,8 @@ private:
const u64 RB = CPU.GPR[rb];
CPU.GPR[rd] = ~RA + RB + CPU.XER.CA;
CPU.XER.CA = CPU.IsCarry(~RA, RB, CPU.XER.CA);
if(oe) CPU.SetOV((~RA>>63 == RB>>63) && (~RA>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
if(oe) throw "SUBFE(): subfeo";
}
void ADDE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc)
{
@ -2659,8 +2662,8 @@ private:
CPU.GPR[rd] = RA + RB;
CPU.XER.CA = CPU.IsCarry(RA, RB);
}
if(oe) CPU.SetOV((RA>>63 == RB>>63) && (RA>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
if(oe) throw "ADDE(): addeo";
}
void MTOCRF(u32 l, u32 crm, u32 rs)
{
@ -2748,7 +2751,7 @@ private:
const u64 RA = CPU.GPR[ra];
CPU.GPR[rd] = RA + CPU.XER.CA;
CPU.XER.CA = CPU.IsCarry(RA, CPU.XER.CA);
if(oe) LOG_WARNING(PPU, "addzeo");
if(oe) CPU.SetOV((RA>>63 == 0) && (RA>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void SUBFZE(u32 rd, u32 ra, u32 oe, bool rc)
@ -2756,8 +2759,8 @@ private:
const u64 RA = CPU.GPR[ra];
CPU.GPR[rd] = ~RA + CPU.XER.CA;
CPU.XER.CA = CPU.IsCarry(~RA, CPU.XER.CA);
if (oe) LOG_WARNING(PPU, "subfzeo");
if (rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
if(oe) CPU.SetOV((~RA>>63 == 0) && (~RA>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void STDCX_(u32 rs, u32 ra, u32 rb)
{
@ -2787,14 +2790,20 @@ private:
const u64 RA = CPU.GPR[ra];
CPU.GPR[rd] = ~RA + CPU.XER.CA + ~0ULL;
CPU.XER.CA = CPU.IsCarry(~RA, CPU.XER.CA, ~0ULL);
if (oe) LOG_WARNING(PPU, "subfmeo");
if (rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
if(oe) CPU.SetOV((~RA>>63 == 1) && (~RA>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void MULLD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc)
{
CPU.GPR[rd] = (s64)((s64)CPU.GPR[ra] * (s64)CPU.GPR[rb]);
const s64 RA = CPU.GPR[ra];
const s64 RB = CPU.GPR[rb];
CPU.GPR[rd] = (s64)(RA * RB);
if(oe)
{
const s64 high = __mulh(RA, RB);
CPU.SetOV(high != s64(CPU.GPR[rd]) >> 63);
}
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
if(oe) throw "MULLD(): mulldo";
}
void ADDME(u32 rd, u32 ra, u32 oe, bool rc)
{
@ -2802,14 +2811,14 @@ private:
CPU.GPR[rd] = RA + CPU.XER.CA - 1;
CPU.XER.CA |= RA != 0;
if(oe) throw "ADDME(): addmeo";
if(oe) CPU.SetOV((u64(RA)>>63 == 1) && (u64(RA)>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void MULLW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc)
{
CPU.GPR[rd] = (s64)((s64)(s32)CPU.GPR[ra] * (s64)(s32)CPU.GPR[rb]);
if(oe) CPU.SetOV(s64(CPU.GPR[rd]) < s64(-1)<<31 || s64(CPU.GPR[rd]) >= s64(1)<<31);
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
if(oe) throw "MULLW(): mullwo";
}
void DCBTST(u32 ra, u32 rb, u32 th)
{
@ -2825,7 +2834,7 @@ private:
const u64 RA = CPU.GPR[ra];
const u64 RB = CPU.GPR[rb];
CPU.GPR[rd] = RA + RB;
if(oe) throw "ADD(): addo";
if(oe) CPU.SetOV((RA>>63 == RB>>63) && (RA>>63 != CPU.GPR[rd]>>63));
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[rd]);
}
void DCBT(u32 ra, u32 rb, u32 th)
@ -2940,11 +2949,12 @@ private:
if(RB == 0)
{
if(oe) throw "DIVDU(): divduo";
if(oe) CPU.SetOV(true);
CPU.GPR[rd] = 0;
}
else
{
if(oe) CPU.SetOV(false);
CPU.GPR[rd] = RA / RB;
}
@ -2957,11 +2967,12 @@ private:
if(RB == 0)
{
if(oe) throw "DIVWU(): divwuo";
if(oe) CPU.SetOV(true);
CPU.GPR[rd] = 0;
}
else
{
if(oe) CPU.SetOV(false);
CPU.GPR[rd] = RA / RB;
}
@ -2991,11 +3002,12 @@ private:
if (RB == 0 || ((u64)RA == (1ULL << 63) && RB == -1))
{
if(oe) throw "DIVD(): divdo";
if(oe) CPU.SetOV(true);
CPU.GPR[rd] = /*(((u64)RA & (1ULL << 63)) && RB == 0) ? -1 :*/ 0;
}
else
{
if(oe) CPU.SetOV(false);
CPU.GPR[rd] = RA / RB;
}
@ -3008,11 +3020,12 @@ private:
if (RB == 0 || ((u32)RA == (1 << 31) && RB == -1))
{
if(oe) throw "DIVW(): divwo";
if(oe) CPU.SetOV(true);
CPU.GPR[rd] = /*(((u32)RA & (1 << 31)) && RB == 0) ? -1 :*/ 0;
}
else
{
if(oe) CPU.SetOV(false);
CPU.GPR[rd] = (u32)(RA / RB);
}
@ -3033,7 +3046,22 @@ private:
}
void LSWX(u32 rd, u32 ra, u32 rb)
{
throw "LSWX()";
u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
u32 count = CPU.XER.XER & 0x7F;
for (; count >= 4; count -= 4, addr += 4, rd = (rd+1) & 31)
{
CPU.GPR[rd] = vm::get_ref<be_t<u32>>(vm::cast(addr));
}
if (count)
{
u32 value = 0;
for (u32 byte = 0; byte < count; byte++)
{
u32 byte_value = vm::get_ref<u8>(vm::cast(addr+byte));
value |= byte_value << ((3^byte)*8);
}
CPU.GPR[rd] = value;
}
}
void LWBRX(u32 rd, u32 ra, u32 rb)
{
@ -3129,9 +3157,28 @@ private:
for (u32 i = 0; i < 16u - eb; ++i) vm::write8(vm::cast(addr + i), CPU.VPR[vs]._u8[15 - i]);
}
void STDBRX(u32 rs, u32 ra, u32 rb)
{
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
vm::get_ref<u64>(vm::cast(addr)) = CPU.GPR[rs];
}
void STSWX(u32 rs, u32 ra, u32 rb)
{
throw "STSWX()";
u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
u32 count = CPU.XER.XER & 0x7F;
for (; count >= 4; count -= 4, addr += 4, rs = (rs+1) & 31)
{
vm::write32(vm::cast(addr), (u32)CPU.GPR[rs]);
}
if (count)
{
u32 value = (u32)CPU.GPR[rs];
for (u32 byte = 0; byte < count; byte++)
{
u32 byte_value = (u8)(value >> ((3^byte)*8));
vm::write8(vm::cast(addr+byte), byte_value);
}
}
}
void STWBRX(u32 rs, u32 ra, u32 rb)
{
@ -3520,25 +3567,25 @@ private:
}
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FDIVS(): fdivs.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FSUBS(u32 frd, u32 fra, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] - CPU.FPR[frb]);
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FSUBS(): fsubs.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FADDS(u32 frd, u32 fra, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] + CPU.FPR[frb]);
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FADDS(): fadds.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FSQRTS(u32 frd, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(sqrt(CPU.FPR[frb]));
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FSQRTS(): fsqrts.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FRES(u32 frd, u32 frb, bool rc)
{
@ -3547,7 +3594,7 @@ private:
CPU.SetFPSCRException(FPSCR_ZX);
}
CPU.FPR[frd] = static_cast<float>(1.0 / CPU.FPR[frb]);
if(rc) throw "FRES(): fres.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FMULS(u32 frd, u32 fra, u32 frc, bool rc)
{
@ -3555,31 +3602,31 @@ private:
CPU.FPSCR.FI = 0;
CPU.FPSCR.FR = 0;
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FMULS(): fmuls.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb]);
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FMADDS(): fmadds.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb]);
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FMSUBS(): fmsubs.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FNMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(-(CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb]));
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FNMSUBS(): fnmsubs.";////CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FNMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = static_cast<float>(-(CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb]));
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FNMADDS(): fnmadds.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void STD(u32 rs, u32 ra, s32 d)
{
@ -3599,7 +3646,7 @@ private:
if ((crbd == 29) && !CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode enabled");
CPU.FPSCR.FPSCR |= mask;
if(rc) throw "MTFSB1(): mtfsb1.";
if(rc) CPU.UpdateCR1();
}
void MCRFS(u32 crbd, u32 crbs)
{
@ -3632,7 +3679,7 @@ private:
if ((crbd == 29) && !CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode disabled");
CPU.FPSCR.FPSCR &= ~mask;
if(rc) throw "MTFSB0(): mtfsb0.";
if(rc) CPU.UpdateCR1();
}
void MTFSFI(u32 crfd, u32 i, bool rc)
{
@ -3650,12 +3697,12 @@ private:
LOG_WARNING(PPU, "Non-IEEE mode enabled");
}
if(rc) throw "MTFSFI(): mtfsfi.";
if(rc) CPU.UpdateCR1();
}
void MFFS(u32 frd, bool rc)
{
(u64&)CPU.FPR[frd] = CPU.FPSCR.FPSCR;
if(rc) throw "MFFS(): mffs.";
if(rc) CPU.UpdateCR1();
}
void MTFSF(u32 flm, u32 frb, bool rc)
{
@ -3674,7 +3721,7 @@ private:
else
LOG_WARNING(PPU, "Non-IEEE mode enabled");
}
if(rc) throw "MTFSF(): mtfsf.";
if(rc) CPU.UpdateCR1();
}
void FCMPU(u32 crfd, u32 fra, u32 frb)
{
@ -3762,7 +3809,7 @@ private:
}
(u64&)CPU.FPR[frd] = r;
if(rc) throw "FCTIW(): fctiw.";
if(rc) CPU.UpdateCR1();
}
void FCTIWZ(u32 frd, u32 frb, bool rc)
{
@ -3800,7 +3847,7 @@ private:
}
(u64&)CPU.FPR[frd] = (u64)value;
if(rc) throw "FCTIWZ(): fctiwz.";
if(rc) CPU.UpdateCR1();
}
void FDIV(u32 frd, u32 fra, u32 frb, bool rc)
{
@ -3843,30 +3890,30 @@ private:
CPU.FPR[frd] = res;
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FDIV(): fdiv.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FSUB(u32 frd, u32 fra, u32 frb, bool rc)
{
CPU.FPR[frd] = CPU.FPR[fra] - CPU.FPR[frb];
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FSUB(): fsub.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FADD(u32 frd, u32 fra, u32 frb, bool rc)
{
CPU.FPR[frd] = CPU.FPR[fra] + CPU.FPR[frb];
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FASS(): fadd.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FSQRT(u32 frd, u32 frb, bool rc)
{
CPU.FPR[frd] = sqrt(CPU.FPR[frb]);
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FSQRT(): fsqrt.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FSEL(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = CPU.FPR[fra] >= 0.0 ? CPU.FPR[frc] : CPU.FPR[frb];
if(rc) throw "FSEL(): fsel.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FMUL(u32 frd, u32 fra, u32 frc, bool rc)
{
@ -3889,7 +3936,7 @@ private:
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
}
if(rc) throw "FMUL(): fmul.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FRSQRTE(u32 frd, u32 frb, bool rc)
{
@ -3898,31 +3945,31 @@ private:
CPU.SetFPSCRException(FPSCR_ZX);
}
CPU.FPR[frd] = 1.0 / sqrt(CPU.FPR[frb]);
if(rc) throw "FRSQRTE(): frsqrte.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb];
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FMSUB(): fmsub.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb];
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FMADD(): fmadd.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FNMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = -(CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb]);
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FNMSUB(): fnmsub.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FNMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc)
{
CPU.FPR[frd] = -(CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb]);
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FNMADD(): fnmadd.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FCMPO(u32 crfd, u32 fra, u32 frb)
{
@ -3949,22 +3996,22 @@ private:
void FNEG(u32 frd, u32 frb, bool rc)
{
CPU.FPR[frd] = -CPU.FPR[frb];
if(rc) throw "FNEG(): fneg.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FMR(u32 frd, u32 frb, bool rc)
{
CPU.FPR[frd] = CPU.FPR[frb];
if(rc) throw "FMR(): fmr.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FNABS(u32 frd, u32 frb, bool rc)
{
CPU.FPR[frd] = -fabs(CPU.FPR[frb]);
if(rc) throw "FNABS(): fnabs.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FABS(u32 frd, u32 frb, bool rc)
{
CPU.FPR[frd] = fabs(CPU.FPR[frb]);
if(rc) throw "FABS(): fabs.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void FCTID(u32 frd, u32 frb, bool rc)
{
@ -4023,7 +4070,7 @@ private:
}
(u64&)CPU.FPR[frd] = r;
if(rc) throw "FCTID(): fctid.";
if(rc) CPU.UpdateCR1();
}
void FCTIDZ(u32 frd, u32 frb, bool rc)
{
@ -4061,7 +4108,7 @@ private:
}
(u64&)CPU.FPR[frd] = r;
if(rc) throw "FCTIDZ(): fctidz.";
if(rc) CPU.UpdateCR1();
}
void FCFID(u32 frd, u32 frb, bool rc)
{
@ -4083,7 +4130,7 @@ private:
CPU.FPR[frd] = bf;
CPU.FPSCR.FPRF = CPU.FPR[frd].GetType();
if(rc) throw "FCFID(): fcfid.";//CPU.UpdateCR1(CPU.FPR[frd]);
if(rc) CPU.UpdateCR1();
}
void UNK(const u32 code, const u32 opcode, const u32 gcode)

View File

@ -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));
}
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) {
CompilationError("STSWX");
}

View File

@ -598,6 +598,7 @@ namespace ppu_recompiler_llvm {
void LFDX(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 STDBRX(u32 rd, u32 ra, u32 rb) override;
void STSWX(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;

View File

@ -344,6 +344,8 @@ namespace PPU_opcodes
DIVD = 0x1e9,
DIVW = 0x1eb,
LVLX = 0x207, //Load Vector Left Indexed
SUBFCO = 0x208,
ADDCO = 0x20a,
LDBRX = 0x214,
LSWX = 0x215,
LWBRX = 0x216,
@ -351,21 +353,33 @@ namespace PPU_opcodes
SRW = 0x218,
SRD = 0x21b,
LVRX = 0x227, //Load Vector Right Indexed
SUBFO = 0x228,
LFSUX = 0x237,
LSWI = 0x255,
SYNC = 0x256,
LFDX = 0x257,
NEGO = 0x268,
LFDUX = 0x277,
STVLX = 0x287, //Store Vector Left Indexed
SUBFEO = 0x288,
ADDEO = 0x28a,
STDBRX = 0x294,
STSWX = 0x295,
STWBRX = 0x296,
STFSX = 0x297,
STVRX = 0x2a7, //Store Vector Right Indexed
STFSUX = 0x2b7,
SUBFZEO= 0x2c8,
ADDZEO = 0x2ca,
STSWI = 0x2d5,
STFDX = 0x2d7, //Store Floating-Point Double Indexed
SUBFMEO= 0x2e8,
MULLDO = 0x2e9,
ADDMEO = 0x2ea,
MULLWO = 0x2eb,
STFDUX = 0x2f7,
LVLXL = 0x307, //Load Vector Left Indexed Last
ADDO = 0x30a,
LHBRX = 0x316,
SRAW = 0x318,
SRAD = 0x31a,
@ -380,9 +394,13 @@ namespace PPU_opcodes
EXTSH = 0x39a,
STVRXL = 0x3a7, //Store Vector Right Indexed Last
EXTSB = 0x3ba,
DIVDUO = 0x3c9,
DIVWUO = 0x3cb,
STFIWX = 0x3d7,
EXTSW = 0x3da,
ICBI = 0x3d6, //Instruction Cache Block Invalidate
DIVDO = 0x3e9,
DIVWO = 0x3eb,
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 LFDUX(u32 frd, 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 STWBRX(u32 rs, u32 ra, u32 rb) = 0;
virtual void STFSX(u32 frs, u32 ra, u32 rb) = 0;

View File

@ -652,7 +652,7 @@ public:
UpdateCRn<T>(0, val, 0);
}
template<typename T> void UpdateCR1()
void UpdateCR1()
{
SetCR_LT(1, FPSCR.FX);
SetCR_GT(1, FPSCR.FEX);
@ -670,6 +670,12 @@ public:
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); }
void SetOV(const bool set)
{
XER.OV = set;
XER.SO |= set;
}
void SetFPSCRException(const FPSCR_EXP mask)
{
if ((FPSCR.FPSCR & mask) != mask) FPSCR.FX = 1;