Files
PSPRecomp/profiles/vcs/host/vcs_tier2_cluster_physics.cpp
Jessica_Natalia b87c41da5d otimizações round 14 (severo), radio fix
otimizações round 14 (severo), radio fix
2026-08-18 18:15:20 -03:00

348 lines
15 KiB
C++

// AUTO-GENERATED by profiles/vcs/tools/build_tier2_superblocks.py.
// Tier-2 SUPERBLOCK V4 150FPS cluster: physics
#include "vcs_tier2_superblocks.hpp"
#include "psprecomp/runtime.hpp"
#include "generated_units.hpp"
#include "vcs_fast_paths.hpp"
#include "vcs_tier2_direct_memory.hpp"
#include <cstdint>
namespace vcs {
using namespace psprecomp;
void tier2_superblock_physics(psprecomp::Runtime &rt,
psprecomp::AllegrexContext &ctx,
psprecomp::GuestMemory::AotFastView &aot_mem,
std::uint32_t entry_pc) {
tier2_detail::SampleScope tier2_scope(Tier2ClusterId::Physics);
auto &tier2_stats = tier2_scope.stats();
Tier2DirectMemoryView tier2_mem(rt.memory().direct_fastmem_base_address());
constexpr std::uint32_t kTier2ReturnCapacity = 32u;
std::uint32_t tier2_pending_transfers = 0u;
std::uint32_t tier2_return_depth = 0u;
std::uint32_t tier2_return_pc[kTier2ReturnCapacity];
std::uint32_t tier2_return_unit[kTier2ReturnCapacity];
std::uint32_t tier2_return_pending_base[kTier2ReturnCapacity];
std::uint32_t tier2_resume_pc = 0u;
std::uint32_t tier2_resume_unit = 0u;
std::uint32_t jump_target = 0u;
std::uint32_t local_pc = 0u;
std::uint32_t local_transfers = 0u;
std::uint32_t entry_id = 0u;
bool tier2_gpr_shadow_valid = true;
#define TIER2_GPR_SYNC_OUT() do {} while (false)
#define TIER2_GPR_SYNC_IN() do {} while (false)
#define TIER2_GPR_BEFORE_COLD() do { tier2_gpr_shadow_valid = false; } while (false)
auto tier2_complete_shadow = [&](std::uint32_t count) -> bool {
TIER2_GPR_SYNC_OUT();
const bool same = rt.tier2_complete_fused_transfers(ctx, count);
if (!same) tier2_gpr_shadow_valid = false;
return same;
};
#define TIER2_SB_RETURN() do { TIER2_GPR_SYNC_OUT(); tier2_scope.finish(); /* Unwind every logical invoke_chained_direct frame in true LIFO order. Tail frames created inside a fused JAL unwind before that JAL; outer JAL frames are also released after context invalidation. */ while (tier2_return_depth != 0u) { std::uint32_t tier2_base_ = tier2_return_pending_base[tier2_return_depth - 1u]; if (tier2_base_ > tier2_pending_transfers) { ++tier2_stats.fallbacks; tier2_base_ = tier2_pending_transfers; } const std::uint32_t tier2_tail_count_ = tier2_pending_transfers - tier2_base_; tier2_pending_transfers = tier2_base_; if (tier2_tail_count_ != 0u) (void)tier2_complete_shadow(tier2_tail_count_); --tier2_return_depth; (void)tier2_complete_shadow(1u); } if (tier2_pending_transfers != 0u) { (void)tier2_complete_shadow(tier2_pending_transfers); tier2_pending_transfers = 0u; } return; } while (false)
goto TIER2_ENTRY_DISPATCH;
TIER2_FUSED_RETURN_DISPATCH:
switch (tier2_resume_pc) {
case 0x08A094D8u: goto SB_L_08A094D8;
case 0x08A094E0u: goto SB_L_08A094E0;
case 0x08A09524u: goto SB_L_08A09524;
case 0x08A09574u: goto SB_L_08A09574;
case 0x08A0958Cu: goto SB_L_08A0958C;
case 0x08A09B2Cu: goto SB_L_08A09B2C;
case 0x08A09BE4u: goto SB_L_08A09BE4;
case 0x08A09C10u: goto SB_L_08A09C10;
case 0x08A09C1Cu: goto SB_L_08A09C1C;
case 0x08A09C44u: goto SB_L_08A09C44;
case 0x08A09C4Cu: goto SB_L_08A09C4C;
case 0x08A09C64u: goto SB_L_08A09C64;
case 0x08A09C9Cu: goto SB_L_08A09C9C;
case 0x08A09CA4u: goto SB_L_08A09CA4;
case 0x08A09CBCu: goto SB_L_08A09CBC;
default: break;
}
switch (tier2_resume_unit) {
default: break;
}
ctx.pc = tier2_resume_pc;
TIER2_SB_RETURN();
TIER2_LOCAL_DISPATCH_U0129:
if (tier2_return_depth != 0u && local_pc == tier2_return_pc[tier2_return_depth - 1u]) {
tier2_resume_pc = local_pc;
tier2_resume_unit = tier2_return_unit[tier2_return_depth - 1u];
// Match invoke_chained_direct(): when the callee has returned, ctx.pc
// already contains the caller continuation before any starvation
// boundary/accounting can run. A scheduler switch here must never see
// the stale callee PC.
ctx.pc = local_pc;
const std::uint32_t tier2_pending_base =
tier2_return_pending_base[tier2_return_depth - 1u];
bool tier2_same_context = true;
if (tier2_pending_transfers < tier2_pending_base) {
++tier2_stats.fallbacks;
ctx.pc = local_pc;
TIER2_SB_RETURN();
}
const std::uint32_t tier2_nested_tail =
tier2_pending_transfers - tier2_pending_base;
if (tier2_nested_tail != 0u) {
tier2_pending_transfers = tier2_pending_base;
if (!tier2_complete_shadow(tier2_nested_tail))
tier2_same_context = false;
}
--tier2_return_depth;
if (!tier2_complete_shadow(1u))
tier2_same_context = false;
if (!tier2_same_context) TIER2_SB_RETURN();
goto TIER2_FUSED_RETURN_DISPATCH;
}
switch (local_pc) {
case 0x08A094D8u: goto SB_L_08A094D8;
case 0x08A094E0u: goto SB_L_08A094E0;
case 0x08A09524u: goto SB_L_08A09524;
case 0x08A09574u: goto SB_L_08A09574;
case 0x08A0958Cu: goto SB_L_08A0958C;
case 0x08A09B2Cu: goto SB_L_08A09B2C;
case 0x08A09BE4u: goto SB_L_08A09BE4;
case 0x08A09C10u: goto SB_L_08A09C10;
case 0x08A09C1Cu: goto SB_L_08A09C1C;
case 0x08A09C44u: goto SB_L_08A09C44;
case 0x08A09C4Cu: goto SB_L_08A09C4C;
case 0x08A09C64u: goto SB_L_08A09C64;
case 0x08A09C9Cu: goto SB_L_08A09C9C;
case 0x08A09CA4u: goto SB_L_08A09CA4;
case 0x08A09CBCu: goto SB_L_08A09CBC;
default:
ctx.pc = local_pc;
TIER2_SB_RETURN();
}
TIER2_ENTRY_DISPATCH:
switch (entry_pc) {
case 0x08A09B2Cu: goto SB_L_08A09B2C;
default:
ctx.pc = entry_pc;
++tier2_stats.fallbacks;
TIER2_SB_RETURN();
}
// TIER2_GPR_BODY_BEGIN
SB_L_08A094D8:
{ const bool branch_taken = ctx.gpr[5] == 0u;
ctx.gpr[6] = (ctx.gpr[6] & 1u);
if (branch_taken) {
goto SB_L_08A0958C;
}
goto SB_L_08A094E0;
}
SB_L_08A094E0:
ctx.gpr[6] = (ctx.gpr[6] & 255u);
ctx.gpr[7] = (39680u << 16u);
ctx.gpr[6] = (ctx.gpr[6] | ctx.gpr[7]);
ctx.gpr[7] = (2236u << 16u);
ctx.gpr[8] = (tier2_mem.aot_load32(ctx.gpr[7] + static_cast<std::uint32_t>(29552)));
tier2_mem.aot_store32(ctx.gpr[8] + static_cast<std::uint32_t>(0), ctx.gpr[6]);
ctx.gpr[6] = (tier2_mem.aot_load32(ctx.gpr[7] + static_cast<std::uint32_t>(29552)));
ctx.gpr[8] = (4608u << 16u);
ctx.gpr[6] = (ctx.gpr[6] + static_cast<std::uint32_t>(4));
tier2_mem.aot_store32(ctx.gpr[7] + static_cast<std::uint32_t>(29552), ctx.gpr[6]);
ctx.gpr[8] = (ctx.gpr[8] + static_cast<std::uint32_t>(277));
tier2_mem.aot_store32(ctx.gpr[6] + static_cast<std::uint32_t>(0), ctx.gpr[8]);
ctx.gpr[6] = (tier2_mem.aot_load32(ctx.gpr[7] + static_cast<std::uint32_t>(29552)));
ctx.gpr[5] = (ctx.gpr[5] + static_cast<std::uint32_t>(2));
ctx.gpr[6] = (ctx.gpr[6] + static_cast<std::uint32_t>(4));
{ const bool branch_taken = ctx.gpr[4] == 0u;
tier2_mem.aot_store32(ctx.gpr[7] + static_cast<std::uint32_t>(29552), ctx.gpr[6]);
if (branch_taken) {
goto SB_L_08A09574;
}
goto SB_L_08A09524;
}
SB_L_08A09524:
ctx.gpr[8] = (ctx.gpr[4] >> 8u);
ctx.gpr[9] = (15u << 16u);
ctx.gpr[8] = (ctx.gpr[8] & ctx.gpr[9]);
ctx.gpr[9] = (ctx.gpr[7] + static_cast<std::uint32_t>(29552));
tier2_mem.aot_store32(ctx.gpr[9] + static_cast<std::uint32_t>(20), ctx.gpr[8]);
ctx.gpr[9] = (4096u << 16u);
ctx.gpr[8] = (ctx.gpr[8] | ctx.gpr[9]);
tier2_mem.aot_store32(ctx.gpr[6] + static_cast<std::uint32_t>(0), ctx.gpr[8]);
ctx.gpr[8] = (256u << 16u);
ctx.gpr[6] = (tier2_mem.aot_load32(ctx.gpr[7] + static_cast<std::uint32_t>(29552)));
ctx.gpr[8] = (ctx.gpr[8] + static_cast<std::uint32_t>(-1));
ctx.gpr[4] = (ctx.gpr[4] & ctx.gpr[8]);
ctx.gpr[6] = (ctx.gpr[6] + static_cast<std::uint32_t>(4));
ctx.gpr[8] = (256u << 16u);
tier2_mem.aot_store32(ctx.gpr[7] + static_cast<std::uint32_t>(29552), ctx.gpr[6]);
ctx.gpr[4] = (ctx.gpr[4] | ctx.gpr[8]);
tier2_mem.aot_store32(ctx.gpr[6] + static_cast<std::uint32_t>(0), ctx.gpr[4]);
ctx.gpr[6] = tier2_mem.aot_advance32(ctx.gpr[7] + static_cast<std::uint32_t>(29552));
goto SB_L_08A09574;
SB_L_08A09574:
ctx.gpr[4] = (1028u << 16u);
ctx.gpr[4] = (ctx.gpr[5] | ctx.gpr[4]);
tier2_mem.aot_store32(ctx.gpr[6] + static_cast<std::uint32_t>(0), ctx.gpr[4]);
ctx.gpr[4] = tier2_mem.aot_advance32(ctx.gpr[7] + static_cast<std::uint32_t>(29552));
goto SB_L_08A0958C;
SB_L_08A0958C:
jump_target = ctx.gpr[31];
// nop
local_pc = jump_target;
goto TIER2_LOCAL_DISPATCH_U0129;
SB_L_08A09B2C:
ctx.gpr[29] = (ctx.gpr[29] + static_cast<std::uint32_t>(-16));
{ const std::uint32_t tier2_words[4]{ctx.gpr[16], ctx.gpr[17], ctx.gpr[18], ctx.gpr[19]};
tier2_mem.aot_store32_block(ctx.gpr[29] + static_cast<std::uint32_t>(0), tier2_words); }
// PSP CACHE is a no-op in coherent host memory.
ctx.set_vfpu_scalar_bits_ct<30u>(ctx.gpr[16]);
ctx.set_vfpu_scalar_bits_ct<62u>(ctx.gpr[17]);
ctx.set_vfpu_scalar_bits_ct<94u>(ctx.gpr[18]);
ctx.set_vfpu_scalar_bits_ct<126u>(ctx.gpr[31]);
ctx.gpr[29] = (ctx.gpr[29] + static_cast<std::uint32_t>(-16));
tier2_mem.aot_store32(ctx.gpr[29] + static_cast<std::uint32_t>(0), ctx.gpr[19]);
ctx.gpr[19] = (0u | 0u);
ctx.gpr[8] = (static_cast<std::uint32_t>(static_cast<std::int32_t>(static_cast<std::int16_t>(tier2_mem.aot_load16(ctx.gpr[4] + static_cast<std::uint32_t>(4))))));
ctx.gpr[9] = (static_cast<std::uint32_t>(static_cast<std::int32_t>(static_cast<std::int16_t>(tier2_mem.aot_load16(ctx.gpr[4] + static_cast<std::uint32_t>(6))))));
ctx.gpr[10] = (static_cast<std::uint32_t>(static_cast<std::int32_t>(static_cast<std::int16_t>(tier2_mem.aot_load16(ctx.gpr[4] + static_cast<std::uint32_t>(8))))));
ctx.set_vfpu_scalar_bits_ct<29u>(ctx.gpr[8]);
ctx.set_vfpu_scalar_bits_ct<61u>(ctx.gpr[9]);
ctx.set_vfpu_scalar_bits_ct<93u>(ctx.gpr[10]);
ctx.execute_vfpu_vi2f_ct<29u, 29u, 3u, 15u>();
ctx.execute_vfpu_vtfm_ct<12u, 48u, 29u, 4u, 3u>();
ctx.execute_vfpu_vcmp_ct<12u, 31u, 4u, 7u>();
// vflush: architectural no-op that retains VFPU prefixes
ctx.gpr[11] = (ctx.vfpu_scalar_bits_ct<131u>());
ctx.gpr[11] = (ctx.gpr[11] & 15u);
ctx.gpr[11] = (ctx.gpr[11] << 16u);
ctx.gpr[8] = (static_cast<std::uint32_t>(static_cast<std::int32_t>(static_cast<std::int16_t>(tier2_mem.aot_load16(ctx.gpr[4] + static_cast<std::uint32_t>(14))))));
ctx.gpr[9] = (static_cast<std::uint32_t>(static_cast<std::int32_t>(static_cast<std::int16_t>(tier2_mem.aot_load16(ctx.gpr[4] + static_cast<std::uint32_t>(16))))));
ctx.gpr[10] = (static_cast<std::uint32_t>(static_cast<std::int32_t>(static_cast<std::int16_t>(tier2_mem.aot_load16(ctx.gpr[4] + static_cast<std::uint32_t>(18))))));
ctx.set_vfpu_scalar_bits_ct<28u>(ctx.gpr[8]);
ctx.set_vfpu_scalar_bits_ct<60u>(ctx.gpr[9]);
ctx.set_vfpu_scalar_bits_ct<92u>(ctx.gpr[10]);
ctx.execute_vfpu_vi2f_ct<28u, 28u, 3u, 15u>();
ctx.execute_vfpu_vtfm_ct<12u, 48u, 28u, 4u, 3u>();
ctx.execute_vfpu_vcmp_ct<12u, 31u, 4u, 7u>();
// vflush: architectural no-op that retains VFPU prefixes
ctx.gpr[12] = (ctx.vfpu_scalar_bits_ct<131u>());
ctx.gpr[12] = (ctx.gpr[12] & 15u);
ctx.gpr[12] = (ctx.gpr[12] << 8u);
if (!ctx.execute_signed_add(5u, 5u, 5u)) { rt.arithmetic_overflow(0x08A09BC8u, 0x00A52820u); TIER2_SB_RETURN(); }
ctx.gpr[8] = (ctx.gpr[5] << 2u);
if (!ctx.execute_signed_add(5u, 5u, 8u)) { rt.arithmetic_overflow(0x08A09BD0u, 0x00A82820u); TIER2_SB_RETURN(); }
if (!ctx.execute_signed_add(18u, 4u, 5u)) { rt.arithmetic_overflow(0x08A09BD4u, 0x00859020u); TIER2_SB_RETURN(); }
ctx.gpr[16] = (ctx.gpr[11] | ctx.gpr[12]);
ctx.gpr[17] = (ctx.gpr[4] + static_cast<std::uint32_t>(20));
ctx.gpr[5] = (0u + static_cast<std::uint32_t>(0));
goto SB_L_08A09BE4;
SB_L_08A09BE4:
// PSP CACHE is a no-op in coherent host memory.
ctx.gpr[8] = (static_cast<std::uint32_t>(static_cast<std::int32_t>(static_cast<std::int16_t>(tier2_mem.aot_load16(ctx.gpr[17] + static_cast<std::uint32_t>(4))))));
ctx.gpr[9] = (static_cast<std::uint32_t>(static_cast<std::int32_t>(static_cast<std::int16_t>(tier2_mem.aot_load16(ctx.gpr[17] + static_cast<std::uint32_t>(6))))));
ctx.gpr[10] = (static_cast<std::uint32_t>(static_cast<std::int32_t>(static_cast<std::int16_t>(tier2_mem.aot_load16(ctx.gpr[17] + static_cast<std::uint32_t>(8))))));
ctx.set_vfpu_scalar_bits_ct<15u>(ctx.gpr[8]);
ctx.set_vfpu_scalar_bits_ct<47u>(ctx.gpr[9]);
ctx.set_vfpu_scalar_bits_ct<79u>(ctx.gpr[10]);
ctx.execute_vfpu_vi2f_ct<15u, 15u, 3u, 15u>();
ctx.execute_vfpu_vcmp_ct<15u, 28u, 3u, 1u>();
if (((ctx.vfpu_ctrl[3] >> 5u) & 1u) != 0u) {
ctx.gpr[11] = ((ctx.gpr[16] >> 8u) & 0x000000FFu);
goto SB_L_08A09C9C;
}
goto SB_L_08A09C10;
SB_L_08A09C10:
ctx.execute_vfpu_vcmp_ct<15u, 29u, 3u, 1u>();
if (((ctx.vfpu_ctrl[3] >> 5u) & 1u) != 0u) {
ctx.gpr[11] = ((ctx.gpr[16] >> 16u) & 0x000000FFu);
goto SB_L_08A09C9C;
}
goto SB_L_08A09C1C;
SB_L_08A09C1C:
ctx.execute_vfpu_vtfm_ct<12u, 48u, 15u, 4u, 3u>();
ctx.execute_vfpu_vcmp_ct<12u, 31u, 4u, 7u>();
// vflush: architectural no-op that retains VFPU prefixes
ctx.gpr[11] = (ctx.vfpu_scalar_bits_ct<131u>());
ctx.gpr[11] = (ctx.gpr[11] & 15u);
ctx.gpr[16] = (ctx.gpr[16] | ctx.gpr[11]);
ctx.gpr[16] = (ctx.gpr[16] << 8u);
ctx.execute_vfpu_vcmp_ct<28u, 29u, 3u, 1u>();
{ const bool branch_taken = ((ctx.vfpu_ctrl[3] >> 5u) & 1u) != 0u;
// nop
if (branch_taken) {
goto SB_L_08A09CA4;
}
goto SB_L_08A09C44;
}
SB_L_08A09C44:
{ const bool branch_taken = ctx.gpr[16] == 0u;
ctx.gpr[11] = (ctx.gpr[16] | 0u);
if (branch_taken) {
goto SB_L_08A09CA4;
}
goto SB_L_08A09C4C;
}
SB_L_08A09C4C:
ctx.gpr[11] = (ctx.gpr[11] >> 8u);
ctx.gpr[11] = (ctx.gpr[11] & ctx.gpr[16]);
ctx.gpr[11] = (ctx.gpr[11] >> 8u);
ctx.gpr[11] = (ctx.gpr[11] & ctx.gpr[16]);
{ const bool branch_taken = ctx.gpr[11] != 0u;
// nop
if (branch_taken) {
goto SB_L_08A09CA4;
}
goto SB_L_08A09C64;
}
SB_L_08A09C64:
ctx.gpr[31] = (0x08A09C6Cu);
ctx.gpr[6] = (ctx.gpr[19] ^ ctx.gpr[5]);
goto SB_L_08A094D8;
SB_L_08A09C9C:
ctx.gpr[16] = (ctx.gpr[16] | ctx.gpr[11]);
ctx.gpr[16] = (ctx.gpr[16] << 8u);
goto SB_L_08A09CA4;
SB_L_08A09CA4:
ctx.gpr[19] = (ctx.gpr[19] ^ 1u);
ctx.gpr[17] = (ctx.gpr[17] + static_cast<std::uint32_t>(10));
ctx.gpr[5] = (ctx.gpr[5] + static_cast<std::uint32_t>(1));
ctx.execute_vfpu_unary_ct<29u, 28u, 3u, 0u>();
if (ctx.gpr[17] != ctx.gpr[18]) {
ctx.execute_vfpu_unary_ct<28u, 15u, 3u, 0u>();
goto SB_L_08A09BE4;
}
goto SB_L_08A09CBC;
SB_L_08A09CBC:
ctx.gpr[31] = (0x08A09CC4u);
ctx.gpr[6] = (ctx.gpr[19] ^ ctx.gpr[5]);
goto SB_L_08A094D8;
// TIER2_GPR_BODY_END
#undef TIER2_SB_RETURN
#undef TIER2_GPR_BEFORE_COLD
#undef TIER2_GPR_SYNC_IN
#undef TIER2_GPR_SYNC_OUT
}
} // namespace vcs