CPU/PGXP: Identifier name consistency

This commit is contained in:
Stenzek 2024-08-20 20:43:21 +10:00
parent dadf388657
commit d4d813f043
No known key found for this signature in database
4 changed files with 168 additions and 199 deletions

View File

@ -50,7 +50,7 @@ union CacheControl
BitField<u32, bool, 11, 1> icache_enable;
};
struct PGXP_value
struct PGXPValue
{
float x;
float y;
@ -118,9 +118,9 @@ struct State
void* fastmem_base = nullptr;
void** memory_handlers = nullptr;
PGXP_value pgxp_gpr[static_cast<u8>(Reg::count)] = {};
PGXP_value pgxp_cop0[32] = {};
PGXP_value pgxp_gte[64] = {};
PGXPValue pgxp_gpr[static_cast<u8>(Reg::count)] = {};
PGXPValue pgxp_cop0[32] = {};
PGXPValue pgxp_gte[64] = {};
std::array<u32, ICACHE_LINES> icache_tags = {};
std::array<u8, ICACHE_SIZE> icache_data = {};

View File

@ -1,5 +1,9 @@
// SPDX-FileCopyrightText: 2016 iCatButler, 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: GPL-2.0+
//
// This file has been completely rewritten over the years compared to the original PCSXR-PGXP release.
// No original code remains. The original copyright notice is included above for historical purposes.
//
#include "cpu_pgxp.h"
#include "bus.h"
@ -65,43 +69,42 @@ static double f16Sign(double val);
static double f16Unsign(double val);
static double f16Overflow(double val);
static void CacheVertex(u32 value, const PGXP_value& vertex);
static PGXP_value* GetCachedVertex(u32 value);
static void CacheVertex(u32 value, const PGXPValue& vertex);
static PGXPValue* GetCachedVertex(u32 value);
static float TruncateVertexPosition(float p);
static bool IsWithinTolerance(float precise_x, float precise_y, int int_x, int int_y);
static PGXP_value& GetRdValue(Instruction instr);
static PGXP_value& GetRtValue(Instruction instr);
static PGXP_value& ValidateAndGetRtValue(Instruction instr, u32 rtVal);
static PGXP_value& ValidateAndGetRsValue(Instruction instr, u32 rsVal);
static void SetRtValue(Instruction instr, const PGXP_value& val);
static void SetRtValue(Instruction instr, const PGXP_value& val, u32 rtVal);
static PGXP_value& GetSXY0();
static PGXP_value& GetSXY1();
static PGXP_value& GetSXY2();
static PGXP_value& PushSXY();
static PGXPValue& GetRdValue(Instruction instr);
static PGXPValue& GetRtValue(Instruction instr);
static PGXPValue& ValidateAndGetRtValue(Instruction instr, u32 rtVal);
static PGXPValue& ValidateAndGetRsValue(Instruction instr, u32 rsVal);
static void SetRtValue(Instruction instr, const PGXPValue& val);
static void SetRtValue(Instruction instr, const PGXPValue& val, u32 rtVal);
static PGXPValue& GetSXY0();
static PGXPValue& GetSXY1();
static PGXPValue& GetSXY2();
static PGXPValue& PushSXY();
static PGXP_value* GetPtr(u32 addr);
static PGXPValue* GetPtr(u32 addr);
static const PGXPValue& ValidateAndLoadMem(u32 addr, u32 value);
static void ValidateAndLoadMem16(PGXPValue& dest, u32 addr, u32 value, bool sign);
static const PGXP_value& ValidateAndLoadMem(u32 addr, u32 value);
static void ValidateAndLoadMem16(PGXP_value& dest, u32 addr, u32 value, bool sign);
static void CPU_MTC2(u32 reg, const PGXP_value& value, u32 val);
static void CPU_MTC2(u32 reg, const PGXPValue& value, u32 val);
static void CPU_BITWISE(Instruction instr, u32 rdVal, u32 rsVal, u32 rtVal);
static void CPU_SLL(Instruction instr, u32 rtVal, u32 sh);
static void CPU_SRx(Instruction instr, u32 rtVal, u32 sh, bool sign, bool is_variable);
static void WriteMem(u32 addr, const PGXP_value& value);
static void WriteMem16(u32 addr, const PGXP_value& value);
static void WriteMem(u32 addr, const PGXPValue& value);
static void WriteMem16(u32 addr, const PGXPValue& value);
static void CopyZIfMissing(PGXP_value& dst, const PGXP_value& src);
static void SelectZ(float& dst_z, u32& dst_flags, const PGXP_value& src1, const PGXP_value& src2);
static void CopyZIfMissing(PGXPValue& dst, const PGXPValue& src);
static void SelectZ(float& dst_z, u32& dst_flags, const PGXPValue& src1, const PGXPValue& src2);
#ifdef LOG_VALUES
static void LogInstruction(u32 pc, Instruction instr);
static void LogValue(const char* name, u32 rval, const PGXP_value* val);
static void LogValueStr(SmallStringBase& str, const char* name, u32 rval, const PGXP_value* val);
static void LogValue(const char* name, u32 rval, const PGXPValue* val);
static void LogValueStr(SmallStringBase& str, const char* name, u32 rval, const PGXPValue* val);
// clang-format off
#define LOG_VALUES_NV() do { LogInstruction(CPU::g_state.current_instruction_pc, instr); } while (0)
@ -120,11 +123,10 @@ static void LogValueStr(SmallStringBase& str, const char* name, u32 rval, const
#endif
// clang-format on
static constexpr PGXP_value PGXP_value_invalid = {0.f, 0.f, 0.f, 0, 0};
static constexpr PGXP_value PGXP_value_zero = {0.f, 0.f, 0.f, 0, VALID_XY};
static constexpr const PGXPValue INVALID_VALUE = {};
static PGXP_value* s_mem = nullptr;
static PGXP_value* s_vertex_cache = nullptr;
static PGXPValue* s_mem = nullptr;
static PGXPValue* s_vertex_cache = nullptr;
#ifdef LOG_VALUES
static std::FILE* s_log;
@ -139,14 +141,14 @@ void CPU::PGXP::Initialize()
if (!s_mem)
{
s_mem = static_cast<PGXP_value*>(std::calloc(PGXP_MEM_SIZE, sizeof(PGXP_value)));
s_mem = static_cast<PGXPValue*>(std::calloc(PGXP_MEM_SIZE, sizeof(PGXPValue)));
if (!s_mem)
Panic("Failed to allocate PGXP memory");
}
if (g_settings.gpu_pgxp_vertex_cache && !s_vertex_cache)
{
s_vertex_cache = static_cast<PGXP_value*>(std::calloc(VERTEX_CACHE_SIZE, sizeof(PGXP_value)));
s_vertex_cache = static_cast<PGXPValue*>(std::calloc(VERTEX_CACHE_SIZE, sizeof(PGXPValue)));
if (!s_vertex_cache)
{
ERROR_LOG("Failed to allocate memory for vertex cache, disabling.");
@ -155,7 +157,7 @@ void CPU::PGXP::Initialize()
}
if (s_vertex_cache)
std::memset(s_vertex_cache, 0, sizeof(PGXP_value) * VERTEX_CACHE_SIZE);
std::memset(s_vertex_cache, 0, sizeof(PGXPValue) * VERTEX_CACHE_SIZE);
}
void CPU::PGXP::Reset()
@ -165,10 +167,10 @@ void CPU::PGXP::Reset()
std::memset(g_state.pgxp_gte, 0, sizeof(g_state.pgxp_gte));
if (s_mem)
std::memset(s_mem, 0, sizeof(PGXP_value) * PGXP_MEM_SIZE);
std::memset(s_mem, 0, sizeof(PGXPValue) * PGXP_MEM_SIZE);
if (g_settings.gpu_pgxp_vertex_cache && s_vertex_cache)
std::memset(s_vertex_cache, 0, sizeof(PGXP_value) * VERTEX_CACHE_SIZE);
std::memset(s_vertex_cache, 0, sizeof(PGXPValue) * VERTEX_CACHE_SIZE);
}
void CPU::PGXP::Shutdown()
@ -205,65 +207,65 @@ ALWAYS_INLINE_RELEASE double CPU::PGXP::f16Overflow(double val)
return static_cast<double>(static_cast<s64>(val) >> 16);
}
ALWAYS_INLINE CPU::PGXP_value& CPU::PGXP::GetRdValue(Instruction instr)
ALWAYS_INLINE CPU::PGXPValue& CPU::PGXP::GetRdValue(Instruction instr)
{
return g_state.pgxp_gpr[static_cast<u8>(instr.r.rd.GetValue())];
}
ALWAYS_INLINE CPU::PGXP_value& CPU::PGXP::GetRtValue(Instruction instr)
ALWAYS_INLINE CPU::PGXPValue& CPU::PGXP::GetRtValue(Instruction instr)
{
return g_state.pgxp_gpr[static_cast<u8>(instr.r.rt.GetValue())];
}
ALWAYS_INLINE CPU::PGXP_value& CPU::PGXP::ValidateAndGetRtValue(Instruction instr, u32 rtVal)
ALWAYS_INLINE CPU::PGXPValue& CPU::PGXP::ValidateAndGetRtValue(Instruction instr, u32 rtVal)
{
PGXP_value& ret = g_state.pgxp_gpr[static_cast<u8>(instr.r.rt.GetValue())];
PGXPValue& ret = g_state.pgxp_gpr[static_cast<u8>(instr.r.rt.GetValue())];
ret.Validate(rtVal);
return ret;
}
ALWAYS_INLINE CPU::PGXP_value& CPU::PGXP::ValidateAndGetRsValue(Instruction instr, u32 rsVal)
ALWAYS_INLINE CPU::PGXPValue& CPU::PGXP::ValidateAndGetRsValue(Instruction instr, u32 rsVal)
{
PGXP_value& ret = g_state.pgxp_gpr[static_cast<u8>(instr.r.rs.GetValue())];
PGXPValue& ret = g_state.pgxp_gpr[static_cast<u8>(instr.r.rs.GetValue())];
ret.Validate(rsVal);
return ret;
}
ALWAYS_INLINE void CPU::PGXP::SetRtValue(Instruction instr, const PGXP_value& val)
ALWAYS_INLINE void CPU::PGXP::SetRtValue(Instruction instr, const PGXPValue& val)
{
g_state.pgxp_gpr[static_cast<u8>(instr.r.rt.GetValue())] = val;
}
ALWAYS_INLINE void CPU::PGXP::SetRtValue(Instruction instr, const PGXP_value& val, u32 rtVal)
ALWAYS_INLINE void CPU::PGXP::SetRtValue(Instruction instr, const PGXPValue& val, u32 rtVal)
{
PGXP_value& prtVal = g_state.pgxp_gpr[static_cast<u8>(instr.r.rt.GetValue())];
PGXPValue& prtVal = g_state.pgxp_gpr[static_cast<u8>(instr.r.rt.GetValue())];
prtVal = val;
prtVal.value = rtVal;
}
ALWAYS_INLINE CPU::PGXP_value& CPU::PGXP::GetSXY0()
ALWAYS_INLINE CPU::PGXPValue& CPU::PGXP::GetSXY0()
{
return g_state.pgxp_gte[12];
}
ALWAYS_INLINE CPU::PGXP_value& CPU::PGXP::GetSXY1()
ALWAYS_INLINE CPU::PGXPValue& CPU::PGXP::GetSXY1()
{
return g_state.pgxp_gte[13];
}
ALWAYS_INLINE CPU::PGXP_value& CPU::PGXP::GetSXY2()
ALWAYS_INLINE CPU::PGXPValue& CPU::PGXP::GetSXY2()
{
return g_state.pgxp_gte[14];
}
ALWAYS_INLINE CPU::PGXP_value& CPU::PGXP::PushSXY()
ALWAYS_INLINE CPU::PGXPValue& CPU::PGXP::PushSXY()
{
g_state.pgxp_gte[12] = g_state.pgxp_gte[13];
g_state.pgxp_gte[13] = g_state.pgxp_gte[14];
return g_state.pgxp_gte[14];
}
ALWAYS_INLINE_RELEASE CPU::PGXP_value* CPU::PGXP::GetPtr(u32 addr)
ALWAYS_INLINE_RELEASE CPU::PGXPValue* CPU::PGXP::GetPtr(u32 addr)
{
#if 0
if ((addr & CPU::PHYSICAL_MEMORY_ADDRESS_MASK) >= 0x0017A2B4 &&
@ -281,22 +283,22 @@ ALWAYS_INLINE_RELEASE CPU::PGXP_value* CPU::PGXP::GetPtr(u32 addr)
return nullptr;
}
ALWAYS_INLINE_RELEASE const CPU::PGXP_value& CPU::PGXP::ValidateAndLoadMem(u32 addr, u32 value)
ALWAYS_INLINE_RELEASE const CPU::PGXPValue& CPU::PGXP::ValidateAndLoadMem(u32 addr, u32 value)
{
PGXP_value* pMem = GetPtr(addr);
PGXPValue* pMem = GetPtr(addr);
if (!pMem) [[unlikely]]
return PGXP_value_invalid;
return INVALID_VALUE;
pMem->Validate(value);
return *pMem;
}
ALWAYS_INLINE_RELEASE void CPU::PGXP::ValidateAndLoadMem16(PGXP_value& dest, u32 addr, u32 value, bool sign)
ALWAYS_INLINE_RELEASE void CPU::PGXP::ValidateAndLoadMem16(PGXPValue& dest, u32 addr, u32 value, bool sign)
{
PGXP_value* pMem = GetPtr(addr);
PGXPValue* pMem = GetPtr(addr);
if (!pMem) [[unlikely]]
{
dest = PGXP_value_invalid;
dest = INVALID_VALUE;
return;
}
@ -333,9 +335,9 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::ValidateAndLoadMem16(PGXP_value& dest, u32
dest.value = value;
}
ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem(u32 addr, const PGXP_value& value)
ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem(u32 addr, const PGXPValue& value)
{
PGXP_value* pMem = GetPtr(addr);
PGXPValue* pMem = GetPtr(addr);
if (!pMem) [[unlikely]]
return;
@ -343,9 +345,9 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem(u32 addr, const PGXP_value& value
pMem->flags |= VALID_LOWZ | VALID_HIGHZ;
}
ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem16(u32 addr, const PGXP_value& value)
ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem16(u32 addr, const PGXPValue& value)
{
PGXP_value* dest = GetPtr(addr);
PGXPValue* dest = GetPtr(addr);
if (!dest) [[unlikely]]
return;
@ -380,14 +382,14 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem16(u32 addr, const PGXP_value& val
}
}
ALWAYS_INLINE_RELEASE void CPU::PGXP::CopyZIfMissing(PGXP_value& dst, const PGXP_value& src)
ALWAYS_INLINE_RELEASE void CPU::PGXP::CopyZIfMissing(PGXPValue& dst, const PGXPValue& src)
{
dst.z = dst.HasValid(COMP_Z) ? dst.z : src.z;
dst.flags |= (src.flags & VALID_Z);
}
ALWAYS_INLINE_RELEASE void CPU::PGXP::SelectZ(float& dst_z, u32& dst_flags, const PGXP_value& src1,
const PGXP_value& src2)
ALWAYS_INLINE_RELEASE void CPU::PGXP::SelectZ(float& dst_z, u32& dst_flags, const PGXPValue& src1,
const PGXPValue& src2)
{
// Prefer src2 if src1 is missing Z, or is potentially an imprecise value, when src2 is precise.
dst_z = (!(src1.flags & VALID_Z) ||
@ -415,7 +417,7 @@ void CPU::PGXP::LogInstruction(u32 pc, Instruction instr)
std::fprintf(s_log, "%08X %08X %-20s", pc, instr.bits, str.c_str());
}
void CPU::PGXP::LogValue(const char* name, u32 rval, const PGXP_value* val)
void CPU::PGXP::LogValue(const char* name, u32 rval, const PGXPValue* val)
{
if (!s_log) [[unlikely]]
return;
@ -425,7 +427,7 @@ void CPU::PGXP::LogValue(const char* name, u32 rval, const PGXP_value* val)
std::fprintf(s_log, " %s", str.c_str());
}
void CPU::PGXP::LogValueStr(SmallStringBase& str, const char* name, u32 rval, const PGXP_value* val)
void CPU::PGXP::LogValueStr(SmallStringBase& str, const char* name, u32 rval, const PGXPValue* val)
{
str.append_format("{}=[{:08X}", name, rval);
if (!val)
@ -461,7 +463,7 @@ void CPU::PGXP::LogValueStr(SmallStringBase& str, const char* name, u32 rval, co
void CPU::PGXP::GTE_RTPS(float x, float y, float z, u32 value)
{
PGXP_value& pvalue = PushSXY();
PGXPValue& pvalue = PushSXY();
pvalue.x = x;
pvalue.y = y;
pvalue.z = z;
@ -472,13 +474,13 @@ void CPU::PGXP::GTE_RTPS(float x, float y, float z, u32 value)
CacheVertex(value, pvalue);
}
int CPU::PGXP::GTE_NCLIP_valid(u32 sxy0, u32 sxy1, u32 sxy2)
bool CPU::PGXP::GTE_HasPreciseVertices(u32 sxy0, u32 sxy1, u32 sxy2)
{
PGXP_value& SXY0 = GetSXY0();
PGXPValue& SXY0 = GetSXY0();
SXY0.Validate(sxy0);
PGXP_value& SXY1 = GetSXY1();
PGXPValue& SXY1 = GetSXY1();
SXY1.Validate(sxy1);
PGXP_value& SXY2 = GetSXY2();
PGXPValue& SXY2 = GetSXY2();
SXY2.Validate(sxy2);
// Don't use accurate clipping for game-constructed values, which don't have a valid Z.
@ -487,9 +489,9 @@ int CPU::PGXP::GTE_NCLIP_valid(u32 sxy0, u32 sxy1, u32 sxy2)
float CPU::PGXP::GTE_NCLIP()
{
const PGXP_value& SXY0 = GetSXY0();
const PGXP_value& SXY1 = GetSXY1();
const PGXP_value& SXY2 = GetSXY2();
const PGXPValue& SXY0 = GetSXY0();
const PGXPValue& SXY1 = GetSXY1();
const PGXPValue& SXY2 = GetSXY2();
float nclip = ((SXY0.x * SXY1.y) + (SXY1.x * SXY2.y) + (SXY2.x * SXY0.y) - (SXY0.x * SXY2.y) - (SXY1.x * SXY0.y) -
(SXY2.x * SXY1.y));
@ -501,14 +503,14 @@ float CPU::PGXP::GTE_NCLIP()
return nclip;
}
ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_MTC2(u32 reg, const PGXP_value& value, u32 val)
ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_MTC2(u32 reg, const PGXPValue& value, u32 val)
{
switch (reg)
{
case 15:
{
// push FIFO
PGXP_value& SXY2 = PushSXY();
PGXPValue& SXY2 = PushSXY();
SXY2 = value;
return;
}
@ -522,7 +524,7 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_MTC2(u32 reg, const PGXP_value& value,
default:
{
PGXP_value& gteVal = g_state.pgxp_gte[reg];
PGXPValue& gteVal = g_state.pgxp_gte[reg];
gteVal = value;
gteVal.value = val;
return;
@ -530,17 +532,13 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_MTC2(u32 reg, const PGXP_value& value,
}
}
////////////////////////////////////
// Data transfer tracking
////////////////////////////////////
void CPU::PGXP::CPU_MFC2(Instruction instr, u32 rdVal)
{
// CPU[Rt] = GTE_D[Rd]
const u32 idx = instr.cop.Cop2Index();
LOG_VALUES_1(CPU::GetGTERegisterName(idx), rdVal, &g_state.pgxp_gte[idx]);
PGXP_value& prdVal = g_state.pgxp_gte[idx];
PGXPValue& prdVal = g_state.pgxp_gte[idx];
prdVal.Validate(rdVal);
SetRtValue(instr, prdVal, rdVal);
}
@ -551,19 +549,16 @@ void CPU::PGXP::CPU_MTC2(Instruction instr, u32 rtVal)
const u32 idx = instr.cop.Cop2Index();
LOG_VALUES_C1(instr.r.rt.GetValue(), rtVal);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
CPU_MTC2(idx, prtVal, rtVal);
}
////////////////////////////////////
// Memory Access
////////////////////////////////////
void CPU::PGXP::CPU_LWC2(Instruction instr, u32 addr, u32 rtVal)
{
// GTE_D[Rt] = Mem[addr]
LOG_VALUES_LOAD(addr, rtVal);
const PGXP_value& pMem = ValidateAndLoadMem(addr, rtVal);
const PGXPValue& pMem = ValidateAndLoadMem(addr, rtVal);
CPU_MTC2(static_cast<u32>(instr.r.rt.GetValue()), pMem, rtVal);
}
@ -571,7 +566,7 @@ void CPU::PGXP::CPU_SWC2(Instruction instr, u32 addr, u32 rtVal)
{
// Mem[addr] = GTE_D[Rt]
const u32 idx = static_cast<u32>(instr.r.rt.GetValue());
PGXP_value& prtVal = g_state.pgxp_gte[idx];
PGXPValue& prtVal = g_state.pgxp_gte[idx];
#ifdef LOG_VALUES
LOG_VALUES_1(CPU::GetGTERegisterName(idx), rtVal, &prtVal);
std::fprintf(s_log, " addr=%08X", addr);
@ -580,7 +575,7 @@ void CPU::PGXP::CPU_SWC2(Instruction instr, u32 addr, u32 rtVal)
WriteMem(addr, prtVal);
}
ALWAYS_INLINE_RELEASE void CPU::PGXP::CacheVertex(u32 value, const PGXP_value& vertex)
ALWAYS_INLINE_RELEASE void CPU::PGXP::CacheVertex(u32 value, const PGXPValue& vertex)
{
const s16 sx = static_cast<s16>(value & 0xFFFFu);
const s16 sy = static_cast<s16>(value >> 16);
@ -588,7 +583,7 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::CacheVertex(u32 value, const PGXP_value& v
s_vertex_cache[(sy + 1024) * VERTEX_CACHE_WIDTH + (sx + 1024)] = vertex;
}
ALWAYS_INLINE_RELEASE CPU::PGXP_value* CPU::PGXP::GetCachedVertex(u32 value)
ALWAYS_INLINE_RELEASE CPU::PGXPValue* CPU::PGXP::GetCachedVertex(u32 value)
{
const s16 sx = static_cast<s16>(value & 0xFFFFu);
const s16 sy = static_cast<s16>(value >> 16);
@ -617,7 +612,7 @@ ALWAYS_INLINE_RELEASE bool CPU::PGXP::IsWithinTolerance(float precise_x, float p
bool CPU::PGXP::GetPreciseVertex(u32 addr, u32 value, int x, int y, int xOffs, int yOffs, float* out_x, float* out_y,
float* out_w)
{
const PGXP_value* vert = GetPtr(addr);
const PGXPValue* vert = GetPtr(addr);
if (vert && ((vert->flags & VALID_XY) == VALID_XY) && (vert->value == value))
{
// There is a value here with valid X and Y coordinates
@ -669,7 +664,7 @@ void CPU::PGXP::CPU_LW(Instruction instr, u32 addr, u32 rtVal)
void CPU::PGXP::CPU_LBx(Instruction instr, u32 addr, u32 rtVal)
{
LOG_VALUES_LOAD(addr, rtVal);
SetRtValue(instr, PGXP_value_invalid);
SetRtValue(instr, INVALID_VALUE);
}
void CPU::PGXP::CPU_LH(Instruction instr, u32 addr, u32 rtVal)
@ -689,13 +684,13 @@ void CPU::PGXP::CPU_LHU(Instruction instr, u32 addr, u32 rtVal)
void CPU::PGXP::CPU_SB(Instruction instr, u32 addr, u32 rtVal)
{
LOG_VALUES_STORE(instr.r.rt.GetValue(), rtVal, addr);
WriteMem(addr, PGXP_value_invalid);
WriteMem(addr, INVALID_VALUE);
}
void CPU::PGXP::CPU_SH(Instruction instr, u32 addr, u32 rtVal)
{
LOG_VALUES_STORE(instr.r.rt.GetValue(), rtVal, addr);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
WriteMem16(addr, prtVal);
}
@ -703,7 +698,7 @@ void CPU::PGXP::CPU_SW(Instruction instr, u32 addr, u32 rtVal)
{
// Mem[Rs + Im] = Rt
LOG_VALUES_STORE(instr.r.rt.GetValue(), rtVal, addr);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
WriteMem(addr, prtVal);
}
@ -720,7 +715,7 @@ void CPU::PGXP::CPU_MOVE(u32 Rd, u32 Rs, u32 rsVal)
const Instruction instr = {0};
LOG_VALUES_C1(Rs, rsVal);
#endif
PGXP_value& prsVal = g_state.pgxp_gpr[Rs];
PGXPValue& prsVal = g_state.pgxp_gpr[Rs];
prsVal.Validate(rsVal);
g_state.pgxp_gpr[Rd] = prsVal;
}
@ -730,11 +725,11 @@ void CPU::PGXP::CPU_ADDI(Instruction instr, u32 rsVal)
LOG_VALUES_C1(instr.i.rs.GetValue(), rsVal);
// Rt = Rs + Imm (signed)
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
const u32 immVal = instr.i.imm_sext32();
PGXP_value& prtVal = GetRtValue(instr);
PGXPValue& prtVal = GetRtValue(instr);
prtVal = prsVal;
if (immVal == 0)
@ -773,8 +768,8 @@ void CPU::PGXP::CPU_ANDI(Instruction instr, u32 rsVal)
// Rt = Rs & Imm
const u32 imm = instr.i.imm_zext32();
const u32 rtVal = rsVal & imm;
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& prtVal = GetRtValue(instr);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prtVal = GetRtValue(instr);
// remove upper 16-bits
prtVal.y = 0.0f;
@ -817,8 +812,8 @@ void CPU::PGXP::CPU_ORI(Instruction instr, u32 rsVal)
const u32 imm = instr.i.imm_zext32();
const u32 rtVal = rsVal | imm;
PGXP_value& pRsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& pRtVal = GetRtValue(instr);
PGXPValue& pRsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& pRtVal = GetRtValue(instr);
pRtVal = pRsVal;
pRtVal.value = rtVal;
@ -842,8 +837,8 @@ void CPU::PGXP::CPU_XORI(Instruction instr, u32 rsVal)
const u32 imm = instr.i.imm_zext32();
const u32 rtVal = rsVal ^ imm;
PGXP_value& pRsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& pRtVal = GetRtValue(instr);
PGXPValue& pRsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& pRtVal = GetRtValue(instr);
pRtVal = pRsVal;
pRtVal.value = rtVal;
@ -865,12 +860,12 @@ void CPU::PGXP::CPU_SLTI(Instruction instr, u32 rsVal)
// Rt = Rs < Imm (signed)
const s32 imm = instr.i.imm_s16();
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
const float fimmx = static_cast<float>(imm);
const float fimmy = fimmx < 0.0f ? -1.0f : 0.0f;
PGXP_value& prtVal = GetRtValue(instr);
PGXPValue& prtVal = GetRtValue(instr);
prtVal.x = (prsVal.GetValidY(rsVal) < fimmy || prsVal.GetValidX(rsVal) < fimmx) ? 1.0f : 0.0f;
prtVal.y = 0.0f;
prtVal.z = prsVal.z;
@ -884,12 +879,12 @@ void CPU::PGXP::CPU_SLTIU(Instruction instr, u32 rsVal)
// Rt = Rs < Imm (Unsigned)
const u32 imm = instr.i.imm_u16();
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
const float fimmx = static_cast<float>(static_cast<s16>(imm)); // deliberately signed
const float fimmy = fimmx < 0.0f ? -1.0f : 0.0f;
PGXP_value& prtVal = GetRtValue(instr);
PGXPValue& prtVal = GetRtValue(instr);
prtVal.x =
(f16Unsign(prsVal.GetValidY(rsVal)) < f16Unsign(fimmy) || f16Unsign(prsVal.GetValidX(rsVal)) < fimmx) ? 1.0f : 0.0f;
prtVal.y = 0.0f;
@ -898,33 +893,27 @@ void CPU::PGXP::CPU_SLTIU(Instruction instr, u32 rsVal)
prtVal.value = BoolToUInt32(rsVal < imm);
}
////////////////////////////////////
// Load Upper
////////////////////////////////////
void CPU::PGXP::CPU_LUI(Instruction instr)
{
LOG_VALUES_NV();
// Rt = Imm << 16
PGXP_value& pRtVal = GetRtValue(instr);
pRtVal = PGXP_value_zero;
PGXPValue& pRtVal = GetRtValue(instr);
pRtVal.x = 0.0f;
pRtVal.y = static_cast<float>(instr.i.imm_s16());
pRtVal.z = 0.0f;
pRtVal.value = instr.i.imm_zext32() << 16;
pRtVal.flags = VALID_XY;
}
////////////////////////////////////
// Register Arithmetic
////////////////////////////////////
void CPU::PGXP::CPU_ADD(Instruction instr, u32 rsVal, u32 rtVal)
{
LOG_VALUES_C2(instr.r.rs.GetValue(), rsVal, instr.r.rt.GetValue(), rtVal);
// Rd = Rs + Rt (signed)
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXP_value& prdVal = GetRdValue(instr);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prdVal = GetRdValue(instr);
if (rtVal == 0)
{
@ -962,9 +951,9 @@ void CPU::PGXP::CPU_SUB(Instruction instr, u32 rsVal, u32 rtVal)
LOG_VALUES_C2(instr.r.rs.GetValue(), rsVal, instr.r.rt.GetValue(), rtVal);
// Rd = Rs - Rt (signed)
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXP_value& prdVal = GetRdValue(instr);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prdVal = GetRdValue(instr);
if (rtVal == 0)
{
@ -995,8 +984,8 @@ void CPU::PGXP::CPU_SUB(Instruction instr, u32 rsVal, u32 rtVal)
ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_BITWISE(Instruction instr, u32 rdVal, u32 rsVal, u32 rtVal)
{
// Rd = Rs & Rt
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
float x, y;
if (LOWORD_U16(rdVal) == 0)
@ -1019,7 +1008,7 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_BITWISE(Instruction instr, u32 rdVal,
// Why not write directly to prdVal? Because it might be the same as the source.
u32 flags = ((prsVal.flags | prtVal.flags) & VALID_XY) ? (VALID_XY | VALID_TAINTED_Z) : 0;
PGXP_value& prdVal = GetRdValue(instr);
PGXPValue& prdVal = GetRdValue(instr);
SelectZ(prdVal.z, flags, prsVal, prtVal);
prdVal.x = x;
prdVal.y = y;
@ -1068,9 +1057,9 @@ void CPU::PGXP::CPU_SLT(Instruction instr, u32 rsVal, u32 rtVal)
LOG_VALUES_C2(instr.r.rs.GetValue(), rsVal, instr.r.rt.GetValue(), rtVal);
// Rd = Rs < Rt (signed)
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXP_value& prdVal = GetRdValue(instr);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prdVal = GetRdValue(instr);
prdVal.x = (prsVal.GetValidY(rsVal) < prtVal.GetValidY(rtVal) ||
f16Unsign(prsVal.GetValidX(rsVal)) < f16Unsign(prtVal.GetValidX(rtVal))) ?
1.0f :
@ -1086,9 +1075,9 @@ void CPU::PGXP::CPU_SLTU(Instruction instr, u32 rsVal, u32 rtVal)
LOG_VALUES_C2(instr.r.rs.GetValue(), rsVal, instr.r.rt.GetValue(), rtVal);
// Rd = Rs < Rt (unsigned)
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXP_value& prdVal = GetRdValue(instr);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prdVal = GetRdValue(instr);
prdVal.x = (f16Unsign(prsVal.GetValidY(rsVal)) < f16Unsign(prtVal.GetValidY(rtVal)) ||
f16Unsign(prsVal.GetValidX(rsVal)) < f16Unsign(prtVal.GetValidX(rtVal))) ?
1.0f :
@ -1099,20 +1088,16 @@ void CPU::PGXP::CPU_SLTU(Instruction instr, u32 rsVal, u32 rtVal)
prdVal.value = BoolToUInt32(rsVal < rtVal);
}
////////////////////////////////////
// Register mult/div
////////////////////////////////////
void CPU::PGXP::CPU_MULT(Instruction instr, u32 rsVal, u32 rtVal)
{
LOG_VALUES_C2(instr.r.rs.GetValue(), rsVal, instr.r.rt.GetValue(), rtVal);
// Hi/Lo = Rs * Rt (signed)
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXP_value& ploVal = g_state.pgxp_gpr[static_cast<u8>(Reg::lo)];
PGXP_value& phiVal = g_state.pgxp_gpr[static_cast<u8>(Reg::hi)];
PGXPValue& ploVal = g_state.pgxp_gpr[static_cast<u8>(Reg::lo)];
PGXPValue& phiVal = g_state.pgxp_gpr[static_cast<u8>(Reg::hi)];
ploVal = prsVal;
CopyZIfMissing(ploVal, prsVal);
@ -1154,11 +1139,11 @@ void CPU::PGXP::CPU_MULTU(Instruction instr, u32 rsVal, u32 rtVal)
LOG_VALUES_C2(instr.r.rs.GetValue(), rsVal, instr.r.rt.GetValue(), rtVal);
// Hi/Lo = Rs * Rt (unsigned)
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXP_value& ploVal = g_state.pgxp_gpr[static_cast<u8>(Reg::lo)];
PGXP_value& phiVal = g_state.pgxp_gpr[static_cast<u8>(Reg::hi)];
PGXPValue& ploVal = g_state.pgxp_gpr[static_cast<u8>(Reg::lo)];
PGXPValue& phiVal = g_state.pgxp_gpr[static_cast<u8>(Reg::hi)];
ploVal = prsVal;
CopyZIfMissing(ploVal, prsVal);
@ -1201,11 +1186,11 @@ void CPU::PGXP::CPU_DIV(Instruction instr, u32 rsVal, u32 rtVal)
// Lo = Rs / Rt (signed)
// Hi = Rs % Rt (signed)
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXP_value& ploVal = g_state.pgxp_gpr[static_cast<u8>(Reg::lo)];
PGXP_value& phiVal = g_state.pgxp_gpr[static_cast<u8>(Reg::hi)];
PGXPValue& ploVal = g_state.pgxp_gpr[static_cast<u8>(Reg::lo)];
PGXPValue& phiVal = g_state.pgxp_gpr[static_cast<u8>(Reg::hi)];
ploVal = prsVal;
CopyZIfMissing(ploVal, prsVal);
@ -1251,11 +1236,11 @@ void CPU::PGXP::CPU_DIVU(Instruction instr, u32 rsVal, u32 rtVal)
// Lo = Rs / Rt (unsigned)
// Hi = Rs % Rt (unsigned)
PGXP_value& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prsVal = ValidateAndGetRsValue(instr, rsVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXP_value& ploVal = g_state.pgxp_gpr[static_cast<u8>(Reg::lo)];
PGXP_value& phiVal = g_state.pgxp_gpr[static_cast<u8>(Reg::hi)];
PGXPValue& ploVal = g_state.pgxp_gpr[static_cast<u8>(Reg::lo)];
PGXPValue& phiVal = g_state.pgxp_gpr[static_cast<u8>(Reg::hi)];
ploVal = prsVal;
CopyZIfMissing(ploVal, prsVal);
@ -1290,15 +1275,11 @@ void CPU::PGXP::CPU_DIVU(Instruction instr, u32 rsVal, u32 rtVal)
}
}
////////////////////////////////////
// Shift operations (sa)
////////////////////////////////////
ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_SLL(Instruction instr, u32 rtVal, u32 sh)
{
const u32 rdVal = rtVal << sh;
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXP_value& prdVal = GetRdValue(instr);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prdVal = GetRdValue(instr);
prdVal.z = prtVal.z;
prdVal.value = rdVal;
@ -1358,7 +1339,7 @@ void CPU::PGXP::CPU_SLLV(Instruction instr, u32 rtVal, u32 rsVal)
ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_SRx(Instruction instr, u32 rtVal, u32 sh, bool sign, bool is_variable)
{
const u32 rdVal = sign ? static_cast<u32>(static_cast<s32>(rtVal) >> sh) : (rtVal >> sh);
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
double x = prtVal.x;
double y = sign ? prtVal.y : f16Unsign(prtVal.y);
@ -1398,7 +1379,7 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_SRx(Instruction instr, u32 rtVal, u32
else
y = y / static_cast<double>(1 << sh);
PGXP_value& prdVal = GetRdValue(instr);
PGXPValue& prdVal = GetRdValue(instr);
// Use low precision/rounded values when we're not shifting an entire component,
// and it's not originally from a 3D value. Too many false positives in P2/etc.
@ -1461,13 +1442,13 @@ void CPU::PGXP::CPU_SRAV(Instruction instr, u32 rtVal, u32 rsVal)
void CPU::PGXP::CPU_MFC0(Instruction instr, u32 rdVal)
{
const u32 idx = static_cast<u8>(instr.r.rd.GetValue());
PGXP_value& prdVal = g_state.pgxp_cop0[idx];
LOG_VALUES_1(TinyString::from_format("cop0_{}", idx).c_str(), rdVal, &prdVal);
LOG_VALUES_1(TinyString::from_format("cop0_{}", idx).c_str(), rdVal, &g_state.pgxp_cop0[idx]);
// CPU[Rt] = CP0[Rd]
PGXPValue& prdVal = g_state.pgxp_cop0[idx];
prdVal.Validate(rdVal);
PGXP_value& prtVal = GetRtValue(instr);
PGXPValue& prtVal = GetRtValue(instr);
prtVal = prdVal;
prtVal.value = rdVal;
}
@ -1477,8 +1458,8 @@ void CPU::PGXP::CPU_MTC0(Instruction instr, u32 rdVal, u32 rtVal)
LOG_VALUES_C1(instr.r.rt.GetValue(), rtVal);
// CP0[Rd] = CPU[Rt]
PGXP_value& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXP_value& prdVal = g_state.pgxp_cop0[static_cast<u8>(instr.r.rd.GetValue())];
PGXPValue& prtVal = ValidateAndGetRtValue(instr, rtVal);
PGXPValue& prdVal = g_state.pgxp_cop0[static_cast<u8>(instr.r.rd.GetValue())];
prdVal = prtVal;
prtVal.value = rdVal;
}

View File

@ -6,27 +6,27 @@
namespace CPU::PGXP {
/// State management.
void Initialize();
void Reset();
void Shutdown();
// -- GTE functions
// Transforms
void GTE_RTPS(float x, float y, float z, u32 value);
int GTE_NCLIP_valid(u32 sxy0, u32 sxy1, u32 sxy2);
float GTE_NCLIP();
// Data transfer tracking
void CPU_MFC2(Instruction instr, u32 rdVal); // copy GTE data reg to GPR reg (MFC2)
void CPU_MTC2(Instruction instr, u32 rtVal); // copy GPR reg to GTE data reg (MTC2)
// Memory Access
void CPU_LWC2(Instruction instr, u32 addr, u32 rtVal); // copy memory to GTE reg
void CPU_SWC2(Instruction instr, u32 addr, u32 rtVal); // copy GTE reg to memory
/// Vertex lookup from GPU side.
bool GetPreciseVertex(u32 addr, u32 value, int x, int y, int xOffs, int yOffs, float* out_x, float* out_y,
float* out_w);
// -- CPU functions
// GTE instruction hooks.
void GTE_RTPS(float x, float y, float z, u32 value);
bool GTE_HasPreciseVertices(u32 sxy0, u32 sxy1, u32 sxy2);
float GTE_NCLIP();
// CPU instruction implementations.
void CPU_MFC2(Instruction instr, u32 rdVal);
void CPU_MTC2(Instruction instr, u32 rtVal);
void CPU_LWC2(Instruction instr, u32 addr, u32 rtVal);
void CPU_SWC2(Instruction instr, u32 addr, u32 rtVal);
void CPU_LW(Instruction instr, u32 addr, u32 rtVal);
void CPU_LH(Instruction instr, u32 addr, u32 rtVal);
void CPU_LHU(Instruction instr, u32 addr, u32 rtVal);
@ -35,25 +35,14 @@ void CPU_SB(Instruction instr, u32 addr, u32 rtVal);
void CPU_SH(Instruction instr, u32 addr, u32 rtVal);
void CPU_SW(Instruction instr, u32 addr, u32 rtVal);
void CPU_MOVE(u32 Rd, u32 Rs, u32 rsVal);
ALWAYS_INLINE static u32 PackMoveArgs(Reg rd, Reg rs)
{
return (static_cast<u32>(rd) << 8) | static_cast<u32>(rs);
}
void CPU_MOVE_Packed(u32 rd_and_rs, u32 rsVal);
// Arithmetic with immediate value
void CPU_ADDI(Instruction instr, u32 rsVal);
void CPU_ANDI(Instruction instr, u32 rsVal);
void CPU_ORI(Instruction instr, u32 rsVal);
void CPU_XORI(Instruction instr, u32 rsVal);
void CPU_SLTI(Instruction instr, u32 rsVal);
void CPU_SLTIU(Instruction instr, u32 rsVal);
// Load Upper
void CPU_LUI(Instruction instr);
// Register Arithmetic
void CPU_ADD(Instruction instr, u32 rsVal, u32 rtVal);
void CPU_SUB(Instruction instr, u32 rsVal, u32 rtVal);
void CPU_AND_(Instruction instr, u32 rsVal, u32 rtVal);
@ -62,27 +51,26 @@ void CPU_XOR_(Instruction instr, u32 rsVal, u32 rtVal);
void CPU_NOR(Instruction instr, u32 rsVal, u32 rtVal);
void CPU_SLT(Instruction instr, u32 rsVal, u32 rtVal);
void CPU_SLTU(Instruction instr, u32 rsVal, u32 rtVal);
// Register mult/div
void CPU_MULT(Instruction instr, u32 rsVal, u32 rtVal);
void CPU_MULTU(Instruction instr, u32 rsVal, u32 rtVal);
void CPU_DIV(Instruction instr, u32 rsVal, u32 rtVal);
void CPU_DIVU(Instruction instr, u32 rsVal, u32 rtVal);
// Shift operations (sa)
void CPU_SLL(Instruction instr, u32 rtVal);
void CPU_SRL(Instruction instr, u32 rtVal);
void CPU_SRA(Instruction instr, u32 rtVal);
// Shift operations variable
void CPU_SLLV(Instruction instr, u32 rtVal, u32 rsVal);
void CPU_SRLV(Instruction instr, u32 rtVal, u32 rsVal);
void CPU_SRAV(Instruction instr, u32 rtVal, u32 rsVal);
// CP0 Data transfer tracking
void CPU_MFC0(Instruction instr, u32 rdVal);
void CPU_MTC0(Instruction instr, u32 rdVal, u32 rtVal);
// Utility functions.
ALWAYS_INLINE static u32 PackMoveArgs(Reg rd, Reg rs)
{
return (static_cast<u32>(rd) << 8) | static_cast<u32>(rs);
}
ALWAYS_INLINE void TryMove(Reg rd, Reg rs, Reg rt)
{
u32 src;

View File

@ -849,7 +849,7 @@ void GTE::Execute_NCLIP(Instruction inst)
void GTE::Execute_NCLIP_PGXP(Instruction inst)
{
if (CPU::PGXP::GTE_NCLIP_valid(REGS.dr32[12], REGS.dr32[13], REGS.dr32[14]))
if (CPU::PGXP::GTE_HasPreciseVertices(REGS.dr32[12], REGS.dr32[13], REGS.dr32[14]))
{
REGS.FLAG.Clear();
REGS.MAC0 = static_cast<s32>(CPU::PGXP::GTE_NCLIP());