mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-31 20:41:45 +01:00
ppu interpreter: Improve FPCC field handling
This commit is contained in:
parent
aa44ef1f44
commit
e21504d52d
@ -1,4 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "PPUThread.h"
|
||||
#include "PPUInterpreter.h"
|
||||
@ -22,7 +22,7 @@ inline void ppu_cr_set(ppu_thread& ppu, u32 field, bool le, bool gt, bool eq, bo
|
||||
|
||||
if (UNLIKELY(g_cfg.core.ppu_debug))
|
||||
{
|
||||
*(u32*)(vm::g_stat_addr + ppu.cia) |= *(u32*)(u8*)(ppu.cr + field * 4);
|
||||
*(u32*)(vm::g_stat_addr + ppu.cia) |= *(u32*)(ppu.cr.bits + field * 4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2941,7 +2941,7 @@ bool ppu_interpreter::B(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter::MCRF(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
CHECK_SIZE(ppu_thread::cr, 32);
|
||||
reinterpret_cast<u32*>(ppu.cr)[op.crfd] = reinterpret_cast<u32*>(ppu.cr)[op.crfs];
|
||||
reinterpret_cast<u32*>(+ppu.cr.bits)[op.crfd] = reinterpret_cast<u32*>(+ppu.cr.bits)[op.crfs];
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3237,7 +3237,7 @@ bool ppu_interpreter::MFOCRF(ppu_thread& ppu, ppu_opcode_t op)
|
||||
else
|
||||
{
|
||||
// MFCR
|
||||
auto* lanes = reinterpret_cast<be_t<v128>*>(ppu.cr);
|
||||
auto* lanes = reinterpret_cast<be_t<v128>*>(+ppu.cr.bits);
|
||||
const u32 mh = _mm_movemask_epi8(_mm_slli_epi64(lanes[0].value().vi, 7));
|
||||
const u32 ml = _mm_movemask_epi8(_mm_slli_epi64(lanes[1].value().vi, 7));
|
||||
|
||||
@ -3518,7 +3518,7 @@ bool ppu_interpreter::MTOCRF(ppu_thread& ppu, ppu_opcode_t op)
|
||||
const u32 n = utils::cntlz32(op.crm) & 7;
|
||||
const u32 p = n * 4;
|
||||
const u64 v = (s >> (p ^ 0x1c)) & 0xf;
|
||||
*(u32*)(u8*)(ppu.cr + p) = *(u32*)(s_table + v);
|
||||
*(u32*)(ppu.cr.bits + p) = *(u32*)(s_table + v);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3530,7 +3530,7 @@ bool ppu_interpreter::MTOCRF(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
const u32 p = i * 4;
|
||||
const u64 v = (s >> (p ^ 0x1c)) & 0xf;
|
||||
*(u32*)(u8*)(ppu.cr + p) = *(u32*)(s_table + v);
|
||||
*(u32*)(ppu.cr.bits + p) = *(u32*)(s_table + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4673,28 +4673,46 @@ bool ppu_interpreter::FNMADDS(ppu_thread& ppu, ppu_opcode_t op)
|
||||
|
||||
bool ppu_interpreter::MTFSB1(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
LOG_WARNING(PPU, "MTFSB1");
|
||||
const u32 bit = op.crbd;
|
||||
if (bit < 16 || bit > 19) LOG_WARNING(PPU, "MTFSB1(%d)", bit);
|
||||
ppu.fpscr.bits[bit] = 1;
|
||||
if (UNLIKELY(op.rc)) ppu_cr_set(ppu, 1, ppu.fpscr.fg, ppu.fpscr.fl, ppu.fpscr.fe, ppu.fpscr.fu);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::MCRFS(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
LOG_WARNING(PPU, "MCRFS");
|
||||
ppu_cr_set(ppu, op.crfd, false, false, false, false);
|
||||
if (op.crfs != 4) LOG_WARNING(PPU, "MCRFS(%d)", op.crfs);
|
||||
reinterpret_cast<u32*>(+ppu.cr.bits)[op.crfd] = reinterpret_cast<u32*>(&ppu.fpscr.bits[0])[op.crfs];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::MTFSB0(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
LOG_WARNING(PPU, "MTFSB0");
|
||||
const u32 bit = op.crbd;
|
||||
if (bit < 16 || bit > 19) LOG_WARNING(PPU, "MTFSB0(%d)", bit);
|
||||
ppu.fpscr.bits[bit] = 0;
|
||||
if (UNLIKELY(op.rc)) ppu_cr_set(ppu, 1, ppu.fpscr.fg, ppu.fpscr.fl, ppu.fpscr.fe, ppu.fpscr.fu);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ppu_interpreter::MTFSFI(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
LOG_WARNING(PPU, "MTFSFI");
|
||||
const u32 bf = op.crfd * 4;
|
||||
if (bf != 4 * 4)
|
||||
{
|
||||
// Do nothing on non-FPCC field (TODO)
|
||||
LOG_WARNING(PPU, "MTFSFI(%d)", op.crfd);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 i = op.i;
|
||||
ppu.fpscr.bits[bf + 3] = i & 1; i >>= 1;
|
||||
ppu.fpscr.bits[bf + 2] = i & 1; i >>= 1;
|
||||
ppu.fpscr.bits[bf + 1] = i & 1; i >>= 1;
|
||||
ppu.fpscr.bits[bf + 0] = i & 1;
|
||||
}
|
||||
|
||||
if (UNLIKELY(op.rc)) ppu_cr_set(ppu, 1, ppu.fpscr.fg, ppu.fpscr.fl, ppu.fpscr.fe, ppu.fpscr.fu);
|
||||
return true;
|
||||
}
|
||||
@ -4702,7 +4720,7 @@ bool ppu_interpreter::MTFSFI(ppu_thread& ppu, ppu_opcode_t op)
|
||||
bool ppu_interpreter::MFFS(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
LOG_WARNING(PPU, "MFFS");
|
||||
ppu.fpr[op.frd] = 0.0;
|
||||
(u64&)ppu.fpr[op.frd] = u64{ppu.fpscr.fl} << 15 | u64{ppu.fpscr.fg} << 14 | u64{ppu.fpscr.fe} << 13 | u64{ppu.fpscr.fu} << 12;
|
||||
if (UNLIKELY(op.rc)) ppu_cr_set(ppu, 1, ppu.fpscr.fg, ppu.fpscr.fl, ppu.fpscr.fe, ppu.fpscr.fu);
|
||||
return true;
|
||||
}
|
||||
@ -4718,10 +4736,10 @@ bool ppu_interpreter::FCMPU(ppu_thread& ppu, ppu_opcode_t op)
|
||||
{
|
||||
const f64 a = ppu.fpr[op.fra];
|
||||
const f64 b = ppu.fpr[op.frb];
|
||||
ppu.fpscr.fg = a > b;
|
||||
ppu.fpscr.fl = a < b;
|
||||
ppu.fpscr.fe = a == b;
|
||||
//ppu.fpscr.fu = a != a || b != b;
|
||||
u8 test_fu = ppu.fpscr.fg = a > b;
|
||||
test_fu |= ppu.fpscr.fl = a < b;
|
||||
test_fu |= ppu.fpscr.fe = a == b;
|
||||
(u8&)ppu.fpscr.fu = test_fu ^ 1;
|
||||
ppu_cr_set(ppu, op.crfd, ppu.fpscr.fl, ppu.fpscr.fg, ppu.fpscr.fe, ppu.fpscr.fu);
|
||||
return true;
|
||||
}
|
||||
|
@ -443,7 +443,7 @@ std::string ppu_thread::dump() const
|
||||
for (uint i = 0; i < 32; ++i) fmt::append(ret, "FPR[%d] = %.6G\n", i, fpr[i]);
|
||||
for (uint i = 0; i < 32; ++i) fmt::append(ret, "VR[%d] = %s [x: %g y: %g z: %g w: %g]\n", i, vr[i], vr[i]._f[3], vr[i]._f[2], vr[i]._f[1], vr[i]._f[0]);
|
||||
|
||||
fmt::append(ret, "CR = 0x%08x\n", cr_pack());
|
||||
fmt::append(ret, "CR = 0x%08x\n", cr.pack());
|
||||
fmt::append(ret, "LR = 0x%llx\n", lr);
|
||||
fmt::append(ret, "CTR = 0x%llx\n", ctr);
|
||||
fmt::append(ret, "VRSAVE = 0x%08x\n", vrsave);
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include "../CPU/CPUThread.h"
|
||||
@ -59,47 +59,64 @@ public:
|
||||
f64 fpr[32] = {}; // Floating Point Registers
|
||||
v128 vr[32] = {}; // Vector Registers
|
||||
|
||||
alignas(16) bool cr[32] = {}; // Condition Registers (unpacked)
|
||||
|
||||
alignas(16) struct // Floating-Point Status and Control Register (unpacked)
|
||||
struct cr_bits
|
||||
{
|
||||
// TODO
|
||||
bool _start[16]{};
|
||||
bool fl{}; // FPCC.FL
|
||||
bool fg{}; // FPCC.FG
|
||||
bool fe{}; // FPCC.FE
|
||||
bool fu{}; // FPCC.FU
|
||||
bool _end[12]{};
|
||||
}
|
||||
fpscr;
|
||||
alignas(16) u8 bits[32];
|
||||
|
||||
u64 lr{}; // Link Register
|
||||
u64 ctr{}; // Counter Register
|
||||
u32 vrsave{0xffffffff}; // VR Save Register
|
||||
u32 cia{}; // Current Instruction Address
|
||||
u8& operator [](std::size_t i)
|
||||
{
|
||||
return bits[i];
|
||||
}
|
||||
|
||||
// Pack CR bits
|
||||
u32 cr_pack() const
|
||||
u32 pack() const
|
||||
{
|
||||
u32 result{};
|
||||
|
||||
for (u32 bit : cr)
|
||||
for (u32 bit : bits)
|
||||
{
|
||||
result = (result << 1) | bit;
|
||||
result <<= 1;
|
||||
result |= bit;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Unpack CR bits
|
||||
void cr_unpack(u32 value)
|
||||
void unpack(u32 value)
|
||||
{
|
||||
for (bool& b : cr)
|
||||
for (u8& b : bits)
|
||||
{
|
||||
b = (value & 0x1) != 0;
|
||||
b = value & 0x1;
|
||||
value >>= 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cr_bits cr{}; // Condition Registers (unpacked)
|
||||
|
||||
// Floating-Point Status and Control Register (unpacked)
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
// TODO
|
||||
bool _start[16];
|
||||
bool fl; // FPCC.FL
|
||||
bool fg; // FPCC.FG
|
||||
bool fe; // FPCC.FE
|
||||
bool fu; // FPCC.FU
|
||||
bool _end[12];
|
||||
};
|
||||
|
||||
cr_bits bits;
|
||||
}
|
||||
fpscr{};
|
||||
|
||||
u64 lr{}; // Link Register
|
||||
u64 ctr{}; // Counter Register
|
||||
u32 vrsave{0xffffffff}; // VR Save Register
|
||||
u32 cia{}; // Current Instruction Address
|
||||
|
||||
// Fixed-Point Exception Register (abstract representation)
|
||||
struct
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
#include "register_editor_dialog.h"
|
||||
|
||||
constexpr auto qstr = QString::fromStdString;
|
||||
@ -105,7 +105,7 @@ void register_editor_dialog::updateRegister(const QString& text)
|
||||
if (reg.compare(0, 3, "FPR") == 0) str = fmt::format("%016llx", ppu.fpr[reg_index]);
|
||||
if (reg.compare(0, 2, "VR") == 0) str = fmt::format("%016llx%016llx", ppu.vr[reg_index]._u64[1], ppu.vr[reg_index]._u64[0]);
|
||||
}
|
||||
if (reg == "CR") str = fmt::format("%08x", ppu.cr_pack());
|
||||
if (reg == "CR") str = fmt::format("%08x", ppu.cr.pack());
|
||||
if (reg == "LR") str = fmt::format("%016llx", ppu.lr);
|
||||
if (reg == "CTR") str = fmt::format("%016llx", ppu.ctr);
|
||||
}
|
||||
@ -169,7 +169,7 @@ void register_editor_dialog::OnOkay(const std::shared_ptr<cpu_thread>& _cpu)
|
||||
if (reg == "CR")
|
||||
{
|
||||
const ullong reg_value = std::stoull(value.substr(24, 31), 0, 16);
|
||||
if (reg == "CR") ppu.cr_unpack((u32)reg_value);
|
||||
if (reg == "CR") ppu.cr.unpack((u32)reg_value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user