otimizações round 13 (severo)

otimizações round 13 (severo)
This commit is contained in:
Jessica_Natalia
2026-08-18 13:07:44 -03:00
parent d39586741f
commit b8d2bb4f09
235 changed files with 349511 additions and 336749 deletions
+22
View File
@@ -277,6 +277,14 @@ struct alignas(16) AllegrexContext {
PSPRECOMP_CONTEXT_FORCEINLINE void write_vfpu_vector_with_destination_prefix_ct(const float *source) noexcept {
static_assert(Length >= 1u && Length <= 4u);
const std::uint32_t destination_prefix = vfpu_ctrl[2];
// V8.4: the architectural default has no saturation and no lane mask.
// This is by far the common case in geometry code, so bypass the local
// copy, four saturation decodes and four mask tests entirely.
if (destination_prefix == 0u) {
write_vfpu_vector_ct<VectorRegister, Length>(source);
eat_vfpu_prefixes();
return;
}
float value[4]{source[0], Length >= 2u ? source[1] : 0.0f,
Length >= 3u ? source[2] : 0.0f, Length >= 4u ? source[3] : 0.0f};
auto saturate_lane = [&](std::uint32_t i) {
@@ -1666,6 +1674,20 @@ struct alignas(16) AllegrexContext {
float source[16]{};
float target[4]{};
float result[16]{};
// With S/T/D at their architectural defaults VMSCL is exactly a
// matrix-by-scalar multiply. Avoid reading the old destination and all
// prefix/saturation plumbing while retaining the same final prefix eat.
if (vfpu_ctrl[0] == 0xE4u && vfpu_ctrl[1] == 0xE4u && vfpu_ctrl[2] == 0u) {
read_vfpu_matrix_ct<SourceMatrixRegister, Side>(source);
read_vfpu_vector_ct<TargetScalarRegister, 1u>(target);
const float scalar = target[0];
for (std::uint32_t row = 0u; row < Side; ++row)
for (std::uint32_t column = 0u; column < Side; ++column)
result[row * 4u + column] = source[row * 4u + column] * scalar;
write_vfpu_matrix_ct<DestinationMatrixRegister, Side>(result);
eat_vfpu_prefixes();
return;
}
float previous_destination[16]{};
read_vfpu_matrix_ct<SourceMatrixRegister, Side>(source);
read_vfpu_matrix_ct<DestinationMatrixRegister, Side>(previous_destination);
+95
View File
@@ -68,6 +68,83 @@ public:
// GuestMemory and preserve the original validation/watch behavior.
class AotFastView {
public:
// V8.4 production AOT path. VCSNative now treats direct-fastmem as a
// launch requirement, so its generated corpus can call these helpers
// and remove the per-memory-access `fastmem_base_ != nullptr` branch.
// The checked AOT helpers below remain untouched for the generic
// PSPRecomp framework, tests, tools and profiles that need fallback
// memory semantics.
[[nodiscard]] PSPRECOMP_MEMORY_FAST_PATH std::uint8_t aot_direct_load8(std::uint32_t address) const noexcept {
return *fastmem_pointer(fastmem_base_, address);
}
[[nodiscard]] PSPRECOMP_MEMORY_FAST_PATH std::uint16_t aot_direct_load16(std::uint32_t address) const noexcept {
return GuestMemory::read_le16(fastmem_pointer(fastmem_base_, address));
}
[[nodiscard]] PSPRECOMP_MEMORY_FAST_PATH std::uint32_t aot_direct_load32(std::uint32_t address) const noexcept {
return GuestMemory::read_le32(fastmem_pointer(fastmem_base_, address));
}
PSPRECOMP_MEMORY_FAST_PATH void aot_direct_store8(std::uint32_t address, std::uint8_t value) const noexcept {
*fastmem_pointer(fastmem_base_, address) = value;
}
PSPRECOMP_MEMORY_FAST_PATH void aot_direct_store16(std::uint32_t address, std::uint16_t value) const noexcept {
GuestMemory::write_le16(fastmem_pointer(fastmem_base_, address), value);
}
PSPRECOMP_MEMORY_FAST_PATH void aot_direct_store32(std::uint32_t address, std::uint32_t value) const noexcept {
GuestMemory::write_le32(fastmem_pointer(fastmem_base_, address), value);
}
template <std::size_t N>
PSPRECOMP_MEMORY_FAST_PATH void aot_direct_load32_block(
std::uint32_t address, std::uint32_t (&values)[N]) const noexcept {
static_assert(N != 0u);
if constexpr (std::endian::native == std::endian::little) {
std::memcpy(values, fastmem_pointer(fastmem_base_, address), N * sizeof(std::uint32_t));
} else {
for (std::size_t i = 0; i < N; ++i)
values[i] = GuestMemory::read_le32(fastmem_pointer(
fastmem_base_, address + static_cast<std::uint32_t>(i * 4u)));
}
}
template <std::size_t N>
PSPRECOMP_MEMORY_FAST_PATH void aot_direct_store32_block(
std::uint32_t address, const std::uint32_t (&values)[N]) const noexcept {
static_assert(N != 0u);
if constexpr (std::endian::native == std::endian::little) {
std::memcpy(fastmem_pointer(fastmem_base_, address), values, N * sizeof(std::uint32_t));
} else {
for (std::size_t i = 0; i < N; ++i)
GuestMemory::write_le32(fastmem_pointer(
fastmem_base_, address + static_cast<std::uint32_t>(i * 4u)), values[i]);
}
}
[[nodiscard]] PSPRECOMP_MEMORY_FAST_PATH std::uint32_t aot_direct_load_word_left(
std::uint32_t address, std::uint32_t existing) const noexcept {
const std::uint32_t shift = (address & 3u) * 8u;
const std::uint32_t memory_word = aot_direct_load32(address & ~3u);
return (existing & (0x00FFFFFFu >> shift)) | (memory_word << (24u - shift));
}
[[nodiscard]] PSPRECOMP_MEMORY_FAST_PATH std::uint32_t aot_direct_load_word_right(
std::uint32_t address, std::uint32_t existing) const noexcept {
const std::uint32_t shift = (address & 3u) * 8u;
const std::uint32_t memory_word = aot_direct_load32(address & ~3u);
return (existing & (0xFFFFFF00u << (24u - shift))) | (memory_word >> shift);
}
PSPRECOMP_MEMORY_FAST_PATH void aot_direct_store_word_left(
std::uint32_t address, std::uint32_t value) const noexcept {
const std::uint32_t shift = (address & 3u) * 8u;
const std::uint32_t aligned = address & ~3u;
const std::uint32_t memory_word = aot_direct_load32(aligned);
aot_direct_store32(aligned,
(value >> (24u - shift)) | (memory_word & (0xFFFFFF00u << shift)));
}
PSPRECOMP_MEMORY_FAST_PATH void aot_direct_store_word_right(
std::uint32_t address, std::uint32_t value) const noexcept {
const std::uint32_t shift = (address & 3u) * 8u;
const std::uint32_t aligned = address & ~3u;
const std::uint32_t memory_word = aot_direct_load32(aligned);
aot_direct_store32(aligned,
(value << shift) | (memory_word & (0x00FFFFFFu >> (24u - shift))));
}
[[nodiscard]] PSPRECOMP_MEMORY_FAST_PATH std::uint8_t aot_load8(std::uint32_t address) const {
if (fastmem_base_ != nullptr) return *fastmem_pointer(fastmem_base_, address);
const std::uint32_t offset = ram_offset_of_fast(address);
@@ -446,6 +523,24 @@ public:
void aot_store_word_left(std::uint32_t address, std::uint32_t value);
void aot_store_word_right(std::uint32_t address, std::uint32_t value);
// Generic block access used by code generators for LV.Q/SV.Q. Profiles
// with a shared AotFastView lower these calls to their cached/direct view;
// manual generated fixtures retain the exact checked scalar semantics.
template <std::size_t N>
PSPRECOMP_MEMORY_FAST_PATH void aot_load32_block(
std::uint32_t address, std::uint32_t (&values)[N]) const {
static_assert(N != 0u);
for (std::size_t i = 0; i < N; ++i)
values[i] = aot_load32(address + static_cast<std::uint32_t>(i * 4u));
}
template <std::size_t N>
PSPRECOMP_MEMORY_FAST_PATH void aot_store32_block(
std::uint32_t address, const std::uint32_t (&values)[N]) {
static_assert(N != 0u);
for (std::size_t i = 0; i < N; ++i)
aot_store32(address + static_cast<std::uint32_t>(i * 4u), values[i]);
}
// DEFLATE/LZ-style forward overlap copy. Unlike memmove, bytes written at
// the destination become immediately available as source bytes, so a short
// match (for example distance=1) can expand to a long repeated run.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More