mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 23:55:40 +00:00
CPU/Recompiler: Read GTE registers directly from struct
This commit is contained in:
parent
b0eb8074f5
commit
37933e9678
|
@ -1509,14 +1509,115 @@ bool CodeGenerator::Compile_cop0(const CodeBlockInstruction& cbi)
|
||||||
Value CodeGenerator::DoGTERegisterRead(u32 index)
|
Value CodeGenerator::DoGTERegisterRead(u32 index)
|
||||||
{
|
{
|
||||||
Value value = m_register_cache.AllocateScratch(RegSize_32);
|
Value value = m_register_cache.AllocateScratch(RegSize_32);
|
||||||
EmitFunctionCallPtr(&value, &Thunks::ReadGTERegister, m_register_cache.GetCPUPtr(), Value::FromConstantU32(index));
|
|
||||||
|
// Most GTE registers can be read directly. Handle the special cases here.
|
||||||
|
if (index == 15) // SXY3
|
||||||
|
{
|
||||||
|
// mirror of SXY2
|
||||||
|
index = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 28: // IRGB
|
||||||
|
case 29: // ORGB
|
||||||
|
{
|
||||||
|
EmitFunctionCallPtr(&value, &Thunks::ReadGTERegister, m_register_cache.GetCPUPtr(),
|
||||||
|
Value::FromConstantU32(index));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
EmitLoadCPUStructField(value.host_reg, RegSize_32, offsetof(Core, m_cop2.m_regs.r32[index]));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenerator::DoGTERegisterWrite(u32 index, const Value& value)
|
void CodeGenerator::DoGTERegisterWrite(u32 index, const Value& value)
|
||||||
{
|
{
|
||||||
EmitFunctionCallPtr(nullptr, &Thunks::WriteGTERegister, m_register_cache.GetCPUPtr(), Value::FromConstantU32(index),
|
switch (index)
|
||||||
value);
|
{
|
||||||
|
case 1: // V0[z]
|
||||||
|
case 3: // V1[z]
|
||||||
|
case 5: // V2[z]
|
||||||
|
case 8: // IR0
|
||||||
|
case 9: // IR1
|
||||||
|
case 10: // IR2
|
||||||
|
case 11: // IR3
|
||||||
|
case 36: // RT33
|
||||||
|
case 44: // L33
|
||||||
|
case 52: // LR33
|
||||||
|
case 58: // H - sign-extended on read but zext on use
|
||||||
|
case 59: // DQA
|
||||||
|
case 61: // ZSF3
|
||||||
|
case 62: // ZSF4
|
||||||
|
{
|
||||||
|
// sign-extend z component of vector registers
|
||||||
|
Value temp = ConvertValueSize(value.ViewAsSize(RegSize_16), RegSize_32, true);
|
||||||
|
EmitStoreCPUStructField(offsetof(Core, m_cop2.m_regs.r32[index]), temp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // OTZ
|
||||||
|
case 16: // SZ0
|
||||||
|
case 17: // SZ1
|
||||||
|
case 18: // SZ2
|
||||||
|
case 19: // SZ3
|
||||||
|
{
|
||||||
|
// zero-extend unsigned values
|
||||||
|
Value temp = ConvertValueSize(value.ViewAsSize(RegSize_16), RegSize_32, false);
|
||||||
|
EmitStoreCPUStructField(offsetof(Core, m_cop2.m_regs.r32[index]), temp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 15: // SXY3
|
||||||
|
{
|
||||||
|
// writing to SXYP pushes to the FIFO
|
||||||
|
Value temp = m_register_cache.AllocateScratch(RegSize_32);
|
||||||
|
|
||||||
|
// SXY0 <- SXY1
|
||||||
|
EmitLoadCPUStructField(temp.host_reg, RegSize_32, offsetof(Core, m_cop2.m_regs.r32[13]));
|
||||||
|
EmitStoreCPUStructField(offsetof(Core, m_cop2.m_regs.r32[12]), temp);
|
||||||
|
|
||||||
|
// SXY1 <- SXY2
|
||||||
|
EmitLoadCPUStructField(temp.host_reg, RegSize_32, offsetof(Core, m_cop2.m_regs.r32[14]));
|
||||||
|
EmitStoreCPUStructField(offsetof(Core, m_cop2.m_regs.r32[13]), temp);
|
||||||
|
|
||||||
|
// SXY2 <- SXYP
|
||||||
|
EmitStoreCPUStructField(offsetof(Core, m_cop2.m_regs.r32[14]), value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 28: // IRGB
|
||||||
|
case 30: // LZCS
|
||||||
|
case 63: // FLAG
|
||||||
|
{
|
||||||
|
EmitFunctionCallPtr(nullptr, &Thunks::WriteGTERegister, m_register_cache.GetCPUPtr(),
|
||||||
|
Value::FromConstantU32(index), value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 29: // ORGB
|
||||||
|
case 31: // LZCR
|
||||||
|
{
|
||||||
|
// read-only registers
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// written as-is, 2x16 or 1x32 bits
|
||||||
|
EmitStoreCPUStructField(offsetof(Core, m_cop2.m_regs.r32[index]), value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CodeGenerator::Compile_cop2(const CodeBlockInstruction& cbi)
|
bool CodeGenerator::Compile_cop2(const CodeBlockInstruction& cbi)
|
||||||
|
|
|
@ -2,11 +2,22 @@
|
||||||
#include "common/state_wrapper.h"
|
#include "common/state_wrapper.h"
|
||||||
#include "gte_types.h"
|
#include "gte_types.h"
|
||||||
|
|
||||||
|
namespace CPU {
|
||||||
|
class Core;
|
||||||
|
|
||||||
|
namespace Recompiler {
|
||||||
|
class CodeGenerator;
|
||||||
|
}
|
||||||
|
} // namespace CPU
|
||||||
|
|
||||||
namespace GTE {
|
namespace GTE {
|
||||||
|
|
||||||
class Core
|
class Core
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
friend CPU::Core;
|
||||||
|
friend CPU::Recompiler::CodeGenerator;
|
||||||
|
|
||||||
Core();
|
Core();
|
||||||
~Core();
|
~Core();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue