Compare commits

..

1 Commits

Author SHA1 Message Date
patchzyy 6488b7fe70 Split PSQ fallbacks and add PSQ ISA tests 2026-09-30 22:26:48 +02:00
9 changed files with 495 additions and 108 deletions
+34
View File
@@ -22,6 +22,7 @@ if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
endif() endif()
option(MKW_BUILD_PRODUCTS "Build translated WiiCompiled product targets" ON) option(MKW_BUILD_PRODUCTS "Build translated WiiCompiled product targets" ON)
option(MKW_BUILD_PSQ_TESTS "Build focused PSQ ISA tests" OFF)
# Preprocessor definitions that belong to this project's own code (the runtime, # Preprocessor definitions that belong to this project's own code (the runtime,
# the translated shards and the product glue) and to nothing else. They are # the translated shards and the product glue) and to nothing else. They are
@@ -162,6 +163,18 @@ set(MKW_AURORA_DIR "${CMAKE_CURRENT_LIST_DIR}/../aurora-main")
# Fast-math may erase them and change guest-visible integer conversions. # Fast-math may erase them and change guest-visible integer conversions.
set(MKW_TRANSLATED_PPC_FP_OPTIONS -fno-fast-math -ffp-contract=off) set(MKW_TRANSLATED_PPC_FP_OPTIONS -fno-fast-math -ffp-contract=off)
set(MKW_PPC_SEMANTIC_RUNTIME_SOURCES
"${CMAKE_CURRENT_LIST_DIR}/src/ppc_helpers.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/fpu_helpers.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/ppc_quantized.cpp")
set_source_files_properties(${MKW_PPC_SEMANTIC_RUNTIME_SOURCES} PROPERTIES
SKIP_UNITY_BUILD_INCLUSION ON
SKIP_PRECOMPILE_HEADERS ON
COMPILE_OPTIONS "${MKW_TRANSLATED_PPC_FP_OPTIONS}")
# Match the optimization policy of the translated callers as well as their FP policy.
set_property(SOURCE "${CMAKE_CURRENT_LIST_DIR}/src/ppc_quantized.cpp" APPEND PROPERTY
COMPILE_OPTIONS -O2 -fno-slp-vectorize)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# Third-party: aurora-main (provides SDL3 + GPU backends) # Third-party: aurora-main (provides SDL3 + GPU backends)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
@@ -310,6 +323,27 @@ set_target_properties(mkw_platform PROPERTIES UNITY_BUILD OFF)
# Keep these independent from Aurora's BUILD_TESTING option: they validate the # Keep these independent from Aurora's BUILD_TESTING option: they validate the
# project's host-platform contracts, not Aurora's third-party test suite. # project's host-platform contracts, not Aurora's third-party test suite.
enable_testing() enable_testing()
if(MKW_BUILD_PSQ_TESTS)
add_executable(mkw_psq_helpers_tests
"${CMAKE_CURRENT_LIST_DIR}/tests/psq_helpers_tests.cpp"
"${CMAKE_CURRENT_LIST_DIR}/src/ppc_quantized.cpp")
target_include_directories(mkw_psq_helpers_tests PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/tests/psq_memory"
"${CMAKE_CURRENT_LIST_DIR}/include/isa"
"${CMAKE_CURRENT_LIST_DIR}/include")
target_compile_features(mkw_psq_helpers_tests PRIVATE cxx_std_17)
target_compile_options(mkw_psq_helpers_tests PRIVATE
-O2 ${MKW_TRANSLATED_PPC_FP_OPTIONS} -fno-slp-vectorize)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(AMD64|amd64|x86_64|X86_64)$")
target_compile_options(mkw_psq_helpers_tests PRIVATE -march=x86-64-v3)
endif()
set_target_properties(mkw_psq_helpers_tests PROPERTIES UNITY_BUILD OFF)
add_test(NAME mkw_psq_helpers_tests COMMAND mkw_psq_helpers_tests)
add_test(NAME mkw_psq_reserved_tests COMMAND "${CMAKE_COMMAND}"
"-DPSQ_TEST_EXECUTABLE=$<TARGET_FILE:mkw_psq_helpers_tests>"
-P "${CMAKE_CURRENT_LIST_DIR}/tests/psq_reserved_tests.cmake")
endif()
add_executable(mkw_platform_paths_tests "${CMAKE_CURRENT_LIST_DIR}/tests/platform_paths_tests.cpp") add_executable(mkw_platform_paths_tests "${CMAKE_CURRENT_LIST_DIR}/tests/platform_paths_tests.cpp")
target_link_libraries(mkw_platform_paths_tests PRIVATE mkw_platform) target_link_libraries(mkw_platform_paths_tests PRIVATE mkw_platform)
target_compile_features(mkw_platform_paths_tests PRIVATE cxx_std_17) target_compile_features(mkw_platform_paths_tests PRIVATE cxx_std_17)
+1 -10
View File
@@ -118,16 +118,7 @@ foreach(source IN LISTS SOURCES)
endif() endif()
set_source_files_properties("${source}" PROPERTIES UNITY_GROUP "${runtime_group}") set_source_files_properties("${source}" PROPERTIES UNITY_GROUP "${runtime_group}")
endforeach() endforeach()
# These translation units implement guest-visible floating-point bit # PPC semantic sources are excluded from unity/PCH and configured in CMakeLists.txt.
# semantics. Keep them out of the fast-math runtime unity groups and apply
# the same contraction/rounding policy as translated PPC shards.
set(MKW_PPC_SEMANTIC_RUNTIME_SOURCES
"${MKW_RUNTIME_SOURCE_DIR}/src/ppc_helpers.cpp"
"${MKW_RUNTIME_SOURCE_DIR}/src/fpu_helpers.cpp")
set_source_files_properties(${MKW_PPC_SEMANTIC_RUNTIME_SOURCES} PROPERTIES
SKIP_UNITY_BUILD_INCLUSION ON
SKIP_PRECOMPILE_HEADERS ON
COMPILE_OPTIONS "${MKW_TRANSLATED_PPC_FP_OPTIONS}")
set_target_properties(mkw_runtime_common PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE GROUP) set_target_properties(mkw_runtime_common PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE GROUP)
target_precompile_headers(mkw_runtime_common PRIVATE "${MKW_RUNTIME_SOURCE_DIR}/include/mkw_pch.h") target_precompile_headers(mkw_runtime_common PRIVATE "${MKW_RUNTIME_SOURCE_DIR}/include/mkw_pch.h")
mkw_apply_common_compile_options(mkw_runtime_common) mkw_apply_common_compile_options(mkw_runtime_common)
+64 -94
View File
@@ -1385,37 +1385,13 @@ MKW_PPC_FORCE_INLINE void PPC_PsqStStackInline(uint32_t addr, double value)
// Context-free PSQ entries for translated regions which own GQR state as an // Context-free PSQ entries for translated regions which own GQR state as an
// ordinary native value. All architecturally valid quantization encodings are // ordinary native value. All architecturally valid quantization encodings are
// handled directly; reserved encodings retain the generic helper's abort. // handled directly; reserved encodings retain the generic helper's abort.
template <uint32_t W, uint32_t I, bool Stack> template <uint32_t W, bool Stack>
MKW_PPC_NO_INLINE MKW_PPC_COLD inline double PPC_PsqLStateFallback(uint32_t gqr, uint32_t addr) MKW_PPC_NO_INLINE MKW_PPC_COLD double PPC_PsqLStateFallback(uint32_t gqr, uint32_t addr);
{
static_assert(W <= 1u && I < 8u); extern template double PPC_PsqLStateFallback<0u, false>(uint32_t, uint32_t);
const uint32_t type = (gqr >> 16) & 0x7u; extern template double PPC_PsqLStateFallback<0u, true>(uint32_t, uint32_t);
const uint32_t scale = (gqr >> 24) & 0x3Fu; extern template double PPC_PsqLStateFallback<1u, false>(uint32_t, uint32_t);
if constexpr (W == 0u) extern template double PPC_PsqLStateFallback<1u, true>(uint32_t, uint32_t);
{
switch (type)
{
case 0u: return Stack ? PpcLoadPairPsqFloatStackInline(addr) : PpcLoadPairPsqFloatFastInline(addr);
case 4u: return Stack ? PpcLoadPairPsqIntegerStackInline<uint8_t>(addr, scale) : PpcLoadPairPsqIntegerFastInline<uint8_t>(addr, scale);
case 5u: return Stack ? PpcLoadPairPsqIntegerStackInline<uint16_t>(addr, scale) : PpcLoadPairPsqIntegerFastInline<uint16_t>(addr, scale);
case 6u: return Stack ? PpcLoadPairPsqIntegerStackInline<int8_t>(addr, scale) : PpcLoadPairPsqIntegerFastInline<int8_t>(addr, scale);
case 7u: return Stack ? PpcLoadPairPsqIntegerStackInline<int16_t>(addr, scale) : PpcLoadPairPsqIntegerFastInline<int16_t>(addr, scale);
default: std::abort();
}
}
else
{
switch (type)
{
case 0u: return Stack ? PpcLoadSinglePsqFloatStackInline(addr) : PpcLoadSinglePsqFloatFastInline(addr);
case 4u: return Stack ? PpcLoadSinglePsqQuantizedStackInline<uint8_t>(addr, scale) : PpcLoadSinglePsqQuantizedFastInline<uint8_t>(addr, scale);
case 5u: return Stack ? PpcLoadSinglePsqQuantizedStackInline<uint16_t>(addr, scale) : PpcLoadSinglePsqQuantizedFastInline<uint16_t>(addr, scale);
case 6u: return Stack ? PpcLoadSinglePsqQuantizedStackInline<int8_t>(addr, scale) : PpcLoadSinglePsqQuantizedFastInline<int8_t>(addr, scale);
case 7u: return Stack ? PpcLoadSinglePsqQuantizedStackInline<int16_t>(addr, scale) : PpcLoadSinglePsqQuantizedFastInline<int16_t>(addr, scale);
default: std::abort();
}
}
}
// Keep the normal explicit-state path small and directly optimizable. Exact // Keep the normal explicit-state path small and directly optimizable. Exact
// unscaled encodings cover the SDK's common GQR setup; scaled and reserved // unscaled encodings cover the SDK's common GQR setup; scaled and reserved
@@ -1442,41 +1418,17 @@ MKW_PPC_FORCE_INLINE double PPC_PsqLStateInline(uint32_t gqr, uint32_t addr)
if constexpr (W == 0u) return Stack ? PpcLoadPairPsqIntegerStackInline<int16_t>(addr, 0u) : PpcLoadPairPsqIntegerFastInline<int16_t>(addr, 0u); if constexpr (W == 0u) return Stack ? PpcLoadPairPsqIntegerStackInline<int16_t>(addr, 0u) : PpcLoadPairPsqIntegerFastInline<int16_t>(addr, 0u);
else return Stack ? PpcLoadSinglePsqQuantizedStackInline<int16_t>(addr, 0u) : PpcLoadSinglePsqQuantizedFastInline<int16_t>(addr, 0u); else return Stack ? PpcLoadSinglePsqQuantizedStackInline<int16_t>(addr, 0u) : PpcLoadSinglePsqQuantizedFastInline<int16_t>(addr, 0u);
default: default:
return PPC_PsqLStateFallback<W, I, Stack>(gqr, addr); return PPC_PsqLStateFallback<W, Stack>(gqr, addr);
} }
} }
template <uint32_t W, uint32_t I, bool Stack> template <uint32_t W, bool Stack>
MKW_PPC_NO_INLINE MKW_PPC_COLD inline void PPC_PsqStStateFallback(uint32_t gqr, uint32_t addr, double value) MKW_PPC_NO_INLINE MKW_PPC_COLD void PPC_PsqStStateFallback(uint32_t gqr, uint32_t addr, double value);
{
static_assert(W <= 1u && I < 8u); extern template void PPC_PsqStStateFallback<0u, false>(uint32_t, uint32_t, double);
const uint32_t type = gqr & 0x7u; extern template void PPC_PsqStStateFallback<0u, true>(uint32_t, uint32_t, double);
const uint32_t scale = (gqr >> 8) & 0x3Fu; extern template void PPC_PsqStStateFallback<1u, false>(uint32_t, uint32_t, double);
if constexpr (W == 0u) extern template void PPC_PsqStStateFallback<1u, true>(uint32_t, uint32_t, double);
{
switch (type)
{
case 0u: Stack ? PpcStorePairPsqFloatStackInline(addr, value) : PpcStorePairPsqFloatFastInline(addr, value); return;
case 4u: if constexpr (Stack) PpcStorePairPsqQuantizedStackInline<uint8_t>(addr, value, scale); else PpcStorePairPsqQuantizedFastInline<uint8_t>(addr, value, scale); return;
case 5u: if constexpr (Stack) PpcStorePairPsqQuantizedStackInline<uint16_t>(addr, value, scale); else PpcStorePairPsqQuantizedFastInline<uint16_t>(addr, value, scale); return;
case 6u: if constexpr (Stack) PpcStorePairPsqQuantizedStackInline<int8_t>(addr, value, scale); else PpcStorePairPsqQuantizedFastInline<int8_t>(addr, value, scale); return;
case 7u: if constexpr (Stack) PpcStorePairPsqQuantizedStackInline<int16_t>(addr, value, scale); else PpcStorePairPsqQuantizedFastInline<int16_t>(addr, value, scale); return;
default: std::abort();
}
}
else
{
switch (type)
{
case 0u: if constexpr (Stack) PpcStoreSinglePsqFloatStackInline(addr, value); else PpcStoreSinglePsqFloatFastInline(addr, value); return;
case 4u: if constexpr (Stack) PpcStoreSinglePsqQuantizedStackInline<uint8_t>(addr, value, scale); else PpcStoreSinglePsqQuantizedFastInline<uint8_t>(addr, value, scale); return;
case 5u: if constexpr (Stack) PpcStoreSinglePsqQuantizedStackInline<uint16_t>(addr, value, scale); else PpcStoreSinglePsqQuantizedFastInline<uint16_t>(addr, value, scale); return;
case 6u: if constexpr (Stack) PpcStoreSinglePsqQuantizedStackInline<int8_t>(addr, value, scale); else PpcStoreSinglePsqQuantizedFastInline<int8_t>(addr, value, scale); return;
case 7u: if constexpr (Stack) PpcStoreSinglePsqQuantizedStackInline<int16_t>(addr, value, scale); else PpcStoreSinglePsqQuantizedFastInline<int16_t>(addr, value, scale); return;
default: std::abort();
}
}
}
template <uint32_t W, uint32_t I, bool Stack> template <uint32_t W, uint32_t I, bool Stack>
MKW_PPC_FORCE_INLINE void PPC_PsqStStateInline(uint32_t gqr, uint32_t addr, double value) MKW_PPC_FORCE_INLINE void PPC_PsqStStateInline(uint32_t gqr, uint32_t addr, double value)
@@ -1505,11 +1457,18 @@ MKW_PPC_FORCE_INLINE void PPC_PsqStStateInline(uint32_t gqr, uint32_t addr, doub
else { if constexpr (Stack) PpcStoreSinglePsqQuantizedStackInline<int16_t>(addr, value, 0u); else PpcStoreSinglePsqQuantizedFastInline<int16_t>(addr, value, 0u); } else { if constexpr (Stack) PpcStoreSinglePsqQuantizedStackInline<int16_t>(addr, value, 0u); else PpcStoreSinglePsqQuantizedFastInline<int16_t>(addr, value, 0u); }
return; return;
default: default:
PPC_PsqStStateFallback<W, I, Stack>(gqr, addr, value); PPC_PsqStStateFallback<W, Stack>(gqr, addr, value);
return; return;
} }
} }
template <uint32_t W>
MKW_PPC_NO_INLINE MKW_PPC_COLD double PPC_PsqLResolvedStateFallback(
uint32_t gqr, uint8_t* resolvedHost, uint32_t offset, uint32_t addr);
extern template double PPC_PsqLResolvedStateFallback<0u>(uint32_t, uint8_t*, uint32_t, uint32_t);
extern template double PPC_PsqLResolvedStateFallback<1u>(uint32_t, uint8_t*, uint32_t, uint32_t);
template <uint32_t W, uint32_t I> template <uint32_t W, uint32_t I>
MKW_PPC_FORCE_INLINE double PPC_PsqLResolvedStateInline( MKW_PPC_FORCE_INLINE double PPC_PsqLResolvedStateInline(
uint32_t gqr, uint8_t* resolvedHost, uint32_t offset, uint32_t addr) uint32_t gqr, uint8_t* resolvedHost, uint32_t offset, uint32_t addr)
@@ -1517,33 +1476,41 @@ MKW_PPC_FORCE_INLINE double PPC_PsqLResolvedStateInline(
static_assert(W <= 1u && I < 8u); static_assert(W <= 1u && I < 8u);
if (!resolvedHost) [[unlikely]] return PPC_PsqLStateInline<W, I, false>(gqr, addr); if (!resolvedHost) [[unlikely]] return PPC_PsqLStateInline<W, I, false>(gqr, addr);
const uint32_t type = (gqr >> 16) & 0x7u; const uint32_t type = (gqr >> 16) & 0x7u;
const uint32_t scale = (gqr >> 24) & 0x3Fu; if (type == 0u) {
if constexpr (W == 0u) return PpcLoadPairPsqFloatResolvedInline(resolvedHost, offset, addr);
else return PpcLoadSinglePsqFloatResolvedInline(resolvedHost, offset, addr);
}
if constexpr (W == 0u) if constexpr (W == 0u)
{ {
switch (type) switch (gqr & 0x3F070000u)
{ {
case 0u: return PpcLoadPairPsqFloatResolvedInline(resolvedHost, offset, addr); case 0x00040000u: return PpcLoadPairPsqIntegerResolvedInline<uint8_t>(resolvedHost, offset, addr, 0u);
case 4u: return PpcLoadPairPsqIntegerResolvedInline<uint8_t>(resolvedHost, offset, addr, scale); case 0x00050000u: return PpcLoadPairPsqIntegerResolvedInline<uint16_t>(resolvedHost, offset, addr, 0u);
case 5u: return PpcLoadPairPsqIntegerResolvedInline<uint16_t>(resolvedHost, offset, addr, scale); case 0x00060000u: return PpcLoadPairPsqIntegerResolvedInline<int8_t>(resolvedHost, offset, addr, 0u);
case 6u: return PpcLoadPairPsqIntegerResolvedInline<int8_t>(resolvedHost, offset, addr, scale); case 0x00070000u: return PpcLoadPairPsqIntegerResolvedInline<int16_t>(resolvedHost, offset, addr, 0u);
case 7u: return PpcLoadPairPsqIntegerResolvedInline<int16_t>(resolvedHost, offset, addr, scale); default: return PPC_PsqLResolvedStateFallback<W>(gqr, resolvedHost, offset, addr);
default: std::abort();
} }
} }
else else
{ {
switch (type) switch (gqr & 0x3F070000u)
{ {
case 0u: return PpcLoadSinglePsqFloatResolvedInline(resolvedHost, offset, addr); case 0x00040000u: return PpcLoadSinglePsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, 0u);
case 4u: return PpcLoadSinglePsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, scale); case 0x00050000u: return PpcLoadSinglePsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, 0u);
case 5u: return PpcLoadSinglePsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, scale); case 0x00060000u: return PpcLoadSinglePsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, 0u);
case 6u: return PpcLoadSinglePsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, scale); case 0x00070000u: return PpcLoadSinglePsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, 0u);
case 7u: return PpcLoadSinglePsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, scale); default: return PPC_PsqLResolvedStateFallback<W>(gqr, resolvedHost, offset, addr);
default: std::abort();
} }
} }
} }
template <uint32_t W>
MKW_PPC_NO_INLINE MKW_PPC_COLD void PPC_PsqStResolvedStateFallback(
uint32_t gqr, uint8_t* resolvedHost, uint32_t offset, uint32_t addr, double value);
extern template void PPC_PsqStResolvedStateFallback<0u>(uint32_t, uint8_t*, uint32_t, uint32_t, double);
extern template void PPC_PsqStResolvedStateFallback<1u>(uint32_t, uint8_t*, uint32_t, uint32_t, double);
template <uint32_t W, uint32_t I> template <uint32_t W, uint32_t I>
MKW_PPC_FORCE_INLINE void PPC_PsqStResolvedStateInline( MKW_PPC_FORCE_INLINE void PPC_PsqStResolvedStateInline(
uint32_t gqr, uint8_t* resolvedHost, uint32_t offset, uint32_t addr, double value) uint32_t gqr, uint8_t* resolvedHost, uint32_t offset, uint32_t addr, double value)
@@ -1555,29 +1522,32 @@ MKW_PPC_FORCE_INLINE void PPC_PsqStResolvedStateInline(
return; return;
} }
const uint32_t type = gqr & 0x7u; const uint32_t type = gqr & 0x7u;
const uint32_t scale = (gqr >> 8) & 0x3Fu; if (type == 0u) {
if constexpr (W == 0u) PpcStorePairPsqFloatResolvedInline(resolvedHost, offset, addr, value);
else PpcStoreSinglePsqFloatResolvedInline(resolvedHost, offset, addr, value);
return;
}
if constexpr (W == 0u) if constexpr (W == 0u)
{ {
switch (type) switch (gqr & 0x3F07u)
{ {
case 0u: PpcStorePairPsqFloatResolvedInline(resolvedHost, offset, addr, value); return; case 0x3D04u: PpcStorePairPsqU8Scale61ResolvedInline(resolvedHost, offset, addr, value); return;
case 4u: PpcStorePairPsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, value, scale); return; case 4u: PpcStorePairPsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, value, 0u); return;
case 5u: PpcStorePairPsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, value, scale); return; case 5u: PpcStorePairPsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, value, 0u); return;
case 6u: PpcStorePairPsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, value, scale); return; case 6u: PpcStorePairPsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, value, 0u); return;
case 7u: PpcStorePairPsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, value, scale); return; case 7u: PpcStorePairPsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, value, 0u); return;
default: std::abort(); default: PPC_PsqStResolvedStateFallback<W>(gqr, resolvedHost, offset, addr, value); return;
} }
} }
else else
{ {
switch (type) switch (gqr & 0x3F07u)
{ {
case 0u: PpcStoreSinglePsqFloatResolvedInline(resolvedHost, offset, addr, value); return; case 4u: PpcStoreSinglePsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, value, 0u); return;
case 4u: PpcStoreSinglePsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, value, scale); return; case 5u: PpcStoreSinglePsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, value, 0u); return;
case 5u: PpcStoreSinglePsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, value, scale); return; case 6u: PpcStoreSinglePsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, value, 0u); return;
case 6u: PpcStoreSinglePsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, value, scale); return; case 7u: PpcStoreSinglePsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, value, 0u); return;
case 7u: PpcStoreSinglePsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, value, scale); return; default: PPC_PsqStResolvedStateFallback<W>(gqr, resolvedHost, offset, addr, value); return;
default: std::abort();
} }
} }
} }
+4 -4
View File
@@ -833,8 +833,8 @@ extern "C" double PPC_PsqL(uint32_t addr, uint32_t w, uint32_t i)
} }
const uint32_t gqr = cpu->gqr[i & 7]; const uint32_t gqr = cpu->gqr[i & 7];
return w == 0 ? PPC_PsqLStateFallback<0u, 0u, false>(gqr, addr) return w == 0 ? PPC_PsqLStateFallback<0u, false>(gqr, addr)
: PPC_PsqLStateFallback<1u, 0u, false>(gqr, addr); : PPC_PsqLStateFallback<1u, false>(gqr, addr);
} }
extern "C" void PPC_PsqSt(uint32_t addr, double value, uint32_t w, uint32_t i) extern "C" void PPC_PsqSt(uint32_t addr, double value, uint32_t w, uint32_t i)
@@ -848,11 +848,11 @@ extern "C" void PPC_PsqSt(uint32_t addr, double value, uint32_t w, uint32_t i)
const uint32_t gqr = cpu->gqr[i & 7]; const uint32_t gqr = cpu->gqr[i & 7];
if (w == 0) if (w == 0)
{ {
PPC_PsqStStateFallback<0u, 0u, false>(gqr, addr, value); PPC_PsqStStateFallback<0u, false>(gqr, addr, value);
} }
else else
{ {
PPC_PsqStStateFallback<1u, 0u, false>(gqr, addr, value); PPC_PsqStStateFallback<1u, false>(gqr, addr, value);
} }
} }
+154
View File
@@ -0,0 +1,154 @@
#include "isa/ppc_isa_quantized.h"
#if defined(__FAST_MATH__) || __FINITE_MATH_ONLY__
#error "PSQ helpers require strict PPC floating-point options"
#endif
template <uint32_t W, bool Stack>
MKW_PPC_NO_INLINE MKW_PPC_COLD double PPC_PsqLStateFallback(uint32_t gqr, uint32_t addr)
{
static_assert(W <= 1u);
const uint32_t type = (gqr >> 16) & 0x7u;
const uint32_t scale = (gqr >> 24) & 0x3Fu;
if constexpr (W == 0u)
{
switch (type)
{
case 0u: return Stack ? PpcLoadPairPsqFloatStackInline(addr) : PpcLoadPairPsqFloatFastInline(addr);
case 4u: return Stack ? PpcLoadPairPsqIntegerStackInline<uint8_t>(addr, scale) : PpcLoadPairPsqIntegerFastInline<uint8_t>(addr, scale);
case 5u: return Stack ? PpcLoadPairPsqIntegerStackInline<uint16_t>(addr, scale) : PpcLoadPairPsqIntegerFastInline<uint16_t>(addr, scale);
case 6u: return Stack ? PpcLoadPairPsqIntegerStackInline<int8_t>(addr, scale) : PpcLoadPairPsqIntegerFastInline<int8_t>(addr, scale);
case 7u: return Stack ? PpcLoadPairPsqIntegerStackInline<int16_t>(addr, scale) : PpcLoadPairPsqIntegerFastInline<int16_t>(addr, scale);
default: std::abort();
}
}
else
{
switch (type)
{
case 0u: return Stack ? PpcLoadSinglePsqFloatStackInline(addr) : PpcLoadSinglePsqFloatFastInline(addr);
case 4u: return Stack ? PpcLoadSinglePsqQuantizedStackInline<uint8_t>(addr, scale) : PpcLoadSinglePsqQuantizedFastInline<uint8_t>(addr, scale);
case 5u: return Stack ? PpcLoadSinglePsqQuantizedStackInline<uint16_t>(addr, scale) : PpcLoadSinglePsqQuantizedFastInline<uint16_t>(addr, scale);
case 6u: return Stack ? PpcLoadSinglePsqQuantizedStackInline<int8_t>(addr, scale) : PpcLoadSinglePsqQuantizedFastInline<int8_t>(addr, scale);
case 7u: return Stack ? PpcLoadSinglePsqQuantizedStackInline<int16_t>(addr, scale) : PpcLoadSinglePsqQuantizedFastInline<int16_t>(addr, scale);
default: std::abort();
}
}
}
template <uint32_t W, bool Stack>
MKW_PPC_NO_INLINE MKW_PPC_COLD void PPC_PsqStStateFallback(uint32_t gqr, uint32_t addr, double value)
{
static_assert(W <= 1u);
const uint32_t type = gqr & 0x7u;
const uint32_t scale = (gqr >> 8) & 0x3Fu;
if constexpr (W == 0u)
{
switch (type)
{
case 0u: Stack ? PpcStorePairPsqFloatStackInline(addr, value) : PpcStorePairPsqFloatFastInline(addr, value); return;
case 4u: if constexpr (Stack) PpcStorePairPsqQuantizedStackInline<uint8_t>(addr, value, scale); else PpcStorePairPsqQuantizedFastInline<uint8_t>(addr, value, scale); return;
case 5u: if constexpr (Stack) PpcStorePairPsqQuantizedStackInline<uint16_t>(addr, value, scale); else PpcStorePairPsqQuantizedFastInline<uint16_t>(addr, value, scale); return;
case 6u: if constexpr (Stack) PpcStorePairPsqQuantizedStackInline<int8_t>(addr, value, scale); else PpcStorePairPsqQuantizedFastInline<int8_t>(addr, value, scale); return;
case 7u: if constexpr (Stack) PpcStorePairPsqQuantizedStackInline<int16_t>(addr, value, scale); else PpcStorePairPsqQuantizedFastInline<int16_t>(addr, value, scale); return;
default: std::abort();
}
}
else
{
switch (type)
{
case 0u: if constexpr (Stack) PpcStoreSinglePsqFloatStackInline(addr, value); else PpcStoreSinglePsqFloatFastInline(addr, value); return;
case 4u: if constexpr (Stack) PpcStoreSinglePsqQuantizedStackInline<uint8_t>(addr, value, scale); else PpcStoreSinglePsqQuantizedFastInline<uint8_t>(addr, value, scale); return;
case 5u: if constexpr (Stack) PpcStoreSinglePsqQuantizedStackInline<uint16_t>(addr, value, scale); else PpcStoreSinglePsqQuantizedFastInline<uint16_t>(addr, value, scale); return;
case 6u: if constexpr (Stack) PpcStoreSinglePsqQuantizedStackInline<int8_t>(addr, value, scale); else PpcStoreSinglePsqQuantizedFastInline<int8_t>(addr, value, scale); return;
case 7u: if constexpr (Stack) PpcStoreSinglePsqQuantizedStackInline<int16_t>(addr, value, scale); else PpcStoreSinglePsqQuantizedFastInline<int16_t>(addr, value, scale); return;
default: std::abort();
}
}
}
template <uint32_t W>
MKW_PPC_NO_INLINE MKW_PPC_COLD double PPC_PsqLResolvedStateFallback(
uint32_t gqr, uint8_t* resolvedHost, uint32_t offset, uint32_t addr)
{
static_assert(W <= 1u);
if (!resolvedHost) [[unlikely]] return PPC_PsqLStateInline<W, 0u, false>(gqr, addr);
const uint32_t type = (gqr >> 16) & 0x7u;
const uint32_t scale = (gqr >> 24) & 0x3Fu;
if constexpr (W == 0u)
{
switch (type)
{
case 0u: return PpcLoadPairPsqFloatResolvedInline(resolvedHost, offset, addr);
case 4u: return PpcLoadPairPsqIntegerResolvedInline<uint8_t>(resolvedHost, offset, addr, scale);
case 5u: return PpcLoadPairPsqIntegerResolvedInline<uint16_t>(resolvedHost, offset, addr, scale);
case 6u: return PpcLoadPairPsqIntegerResolvedInline<int8_t>(resolvedHost, offset, addr, scale);
case 7u: return PpcLoadPairPsqIntegerResolvedInline<int16_t>(resolvedHost, offset, addr, scale);
default: std::abort();
}
}
else
{
switch (type)
{
case 0u: return PpcLoadSinglePsqFloatResolvedInline(resolvedHost, offset, addr);
case 4u: return PpcLoadSinglePsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, scale);
case 5u: return PpcLoadSinglePsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, scale);
case 6u: return PpcLoadSinglePsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, scale);
case 7u: return PpcLoadSinglePsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, scale);
default: std::abort();
}
}
}
template <uint32_t W>
MKW_PPC_NO_INLINE MKW_PPC_COLD void PPC_PsqStResolvedStateFallback(
uint32_t gqr, uint8_t* resolvedHost, uint32_t offset, uint32_t addr, double value)
{
static_assert(W <= 1u);
if (!resolvedHost) [[unlikely]]
{
PPC_PsqStStateInline<W, 0u, false>(gqr, addr, value);
return;
}
const uint32_t type = gqr & 0x7u;
const uint32_t scale = (gqr >> 8) & 0x3Fu;
if constexpr (W == 0u)
{
switch (type)
{
case 0u: PpcStorePairPsqFloatResolvedInline(resolvedHost, offset, addr, value); return;
case 4u: PpcStorePairPsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, value, scale); return;
case 5u: PpcStorePairPsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, value, scale); return;
case 6u: PpcStorePairPsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, value, scale); return;
case 7u: PpcStorePairPsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, value, scale); return;
default: std::abort();
}
}
else
{
switch (type)
{
case 0u: PpcStoreSinglePsqFloatResolvedInline(resolvedHost, offset, addr, value); return;
case 4u: PpcStoreSinglePsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, value, scale); return;
case 5u: PpcStoreSinglePsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, value, scale); return;
case 6u: PpcStoreSinglePsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, value, scale); return;
case 7u: PpcStoreSinglePsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, value, scale); return;
default: std::abort();
}
}
}
template double PPC_PsqLStateFallback<0u, false>(uint32_t, uint32_t);
template void PPC_PsqStStateFallback<0u, false>(uint32_t, uint32_t, double);
template double PPC_PsqLStateFallback<0u, true>(uint32_t, uint32_t);
template void PPC_PsqStStateFallback<0u, true>(uint32_t, uint32_t, double);
template double PPC_PsqLResolvedStateFallback<0u>(uint32_t, uint8_t*, uint32_t, uint32_t);
template void PPC_PsqStResolvedStateFallback<0u>(uint32_t, uint8_t*, uint32_t, uint32_t, double);
template double PPC_PsqLStateFallback<1u, false>(uint32_t, uint32_t);
template void PPC_PsqStStateFallback<1u, false>(uint32_t, uint32_t, double);
template double PPC_PsqLStateFallback<1u, true>(uint32_t, uint32_t);
template void PPC_PsqStStateFallback<1u, true>(uint32_t, uint32_t, double);
template double PPC_PsqLResolvedStateFallback<1u>(uint32_t, uint8_t*, uint32_t, uint32_t);
template void PPC_PsqStResolvedStateFallback<1u>(uint32_t, uint8_t*, uint32_t, uint32_t, double);
+140
View File
@@ -0,0 +1,140 @@
#include "isa/ppc_isa_quantized.h"
#include <csignal>
#include <iostream>
#include <stdexcept>
#include <string>
static uint64_t checksum = 0;
static unsigned checks = 0;
static void Require(bool condition, const char* message) {
++checks;
if (!condition) throw std::runtime_error(message);
}
static void Hash(uint64_t value) { checksum = (checksum ^ value) * 1099511628211ull; }
template <uint32_t W> static double ReferenceLoad(uint32_t type, uint32_t scale, uint32_t addr) {
if constexpr (W == 0u) {
switch (type) {
case 0: return PpcLoadPairPsqFloatFastInline(addr);
case 4: return PpcLoadPairPsqIntegerFastInline<uint8_t>(addr, scale);
case 5: return PpcLoadPairPsqIntegerFastInline<uint16_t>(addr, scale);
case 6: return PpcLoadPairPsqIntegerFastInline<int8_t>(addr, scale);
case 7: return PpcLoadPairPsqIntegerFastInline<int16_t>(addr, scale);
}
} else {
switch (type) {
case 0: return PpcLoadSinglePsqFloatFastInline(addr);
case 4: return PpcLoadSinglePsqQuantizedFastInline<uint8_t>(addr, scale);
case 5: return PpcLoadSinglePsqQuantizedFastInline<uint16_t>(addr, scale);
case 6: return PpcLoadSinglePsqQuantizedFastInline<int8_t>(addr, scale);
case 7: return PpcLoadSinglePsqQuantizedFastInline<int16_t>(addr, scale);
}
}
std::abort();
}
template <uint32_t W> static void ReferenceStore(uint32_t type, uint32_t scale, uint32_t addr, double value) {
if constexpr (W == 0u) {
switch (type) {
case 0: PpcStorePairPsqFloatFastInline(addr, value); return;
case 4: PpcStorePairPsqQuantizedFastInline<uint8_t>(addr, value, scale); return;
case 5: PpcStorePairPsqQuantizedFastInline<uint16_t>(addr, value, scale); return;
case 6: PpcStorePairPsqQuantizedFastInline<int8_t>(addr, value, scale); return;
case 7: PpcStorePairPsqQuantizedFastInline<int16_t>(addr, value, scale); return;
}
} else {
switch (type) {
case 0: PpcStoreSinglePsqFloatFastInline(addr, value); return;
case 4: PpcStoreSinglePsqQuantizedFastInline<uint8_t>(addr, value, scale); return;
case 5: PpcStoreSinglePsqQuantizedFastInline<uint16_t>(addr, value, scale); return;
case 6: PpcStoreSinglePsqQuantizedFastInline<int8_t>(addr, value, scale); return;
case 7: PpcStoreSinglePsqQuantizedFastInline<int16_t>(addr, value, scale); return;
}
}
std::abort();
}
template <uint32_t W, uint32_t I> static void Check() {
constexpr uint32_t edges[] = {
0, 0x80000000u, 1, 0x80000001u, 0x007FFFFFu, 0x00800000u,
0x3F000000u, 0xBF000000u, 0x3F800000u, 0xBF800000u,
0x437F0000u, 0x477FFF00u, 0xC7000000u, 0x7F7FFFFFu,
0x7F800000u, 0xFF800000u, 0x7F800001u, 0x7FC01234u, 0xFFC01234u
};
for (uint32_t type : {0u, 4u, 5u, 6u, 7u}) for (uint32_t scale = 0; scale < 64; ++scale)
for (unsigned n = 0; n < std::size(edges); ++n) {
// Include ignored GQR bits and a different type/scale in the unused half.
const uint32_t half = (scale << 8) | type | 0xC0F8u;
const uint32_t loadGqr = (half << 16) | 0x2105u;
const uint32_t storeGqr = half | 0x21050000u;
const uint64_t raw = (uint64_t(edges[n]) << 32) | edges[(n + 7) % std::size(edges)];
const double value = PpcBitCastToDoubleInline(raw);
for (unsigned mode = 0; mode < 5; ++mode) {
const uint32_t addr = mode == 0 ? 32u : mode == 1 ? 0xCC008000u : mode == 2 ? 0u : 0xFFFFFF00u;
constexpr uint32_t offset = 17;
PsqTestMemory::directStack = mode == 4;
PsqTestMemory::bytes.fill(0xCD);
BigEndian::Write64(PsqTestMemory::Pointer(addr), raw);
const auto expected = PpcBitCastToU64Inline(ReferenceLoad<W>(type, scale, addr));
PsqTestMemory::accesses = 0;
double loaded;
if (mode == 0) loaded = PPC_PsqLResolvedStateInline<W, I>(loadGqr, PsqTestMemory::Pointer(addr) - offset, offset, addr);
else if (mode == 1) loaded = PPC_PsqLResolvedStateInline<W, I>(loadGqr, nullptr, offset, addr);
else if (mode == 2) loaded = PPC_PsqLStateInline<W, I, false>(loadGqr, addr);
else loaded = PPC_PsqLStateInline<W, I, true>(loadGqr, addr);
Require(PpcBitCastToU64Inline(loaded) == expected, "load bits / lane order");
Hash(expected);
const size_t width = (type == 0 ? 4u : (type == 4 || type == 6) ? 1u : 2u) * (2u - W);
Require(PsqTestMemory::accesses == ((mode == 0 || mode == 4) ? 0u : 1u), "load route");
if (PsqTestMemory::accesses) Require(PsqTestMemory::address == addr && PsqTestMemory::width == width, "load slow address / width");
PsqTestMemory::bytes.fill(0xCD);
ReferenceStore<W>(type, scale, addr, value);
const auto expectedBytes = PsqTestMemory::bytes;
PsqTestMemory::bytes.fill(0xCD);
PsqTestMemory::accesses = 0;
if (mode == 0) PPC_PsqStResolvedStateInline<W, I>(storeGqr, PsqTestMemory::Pointer(addr) - offset, offset, addr, value);
else if (mode == 1) PPC_PsqStResolvedStateInline<W, I>(storeGqr, nullptr, offset, addr, value);
else if (mode == 2) PPC_PsqStStateInline<W, I, false>(storeGqr, addr, value);
else PPC_PsqStStateInline<W, I, true>(storeGqr, addr, value);
Require(PsqTestMemory::bytes == expectedBytes, "store bits / untouched lanes");
Hash(PsqTestMemory::ReadHost<uint64_t>(PsqTestMemory::Pointer(addr)));
Require(PsqTestMemory::accesses == ((mode == 0 || mode == 4) ? 0u : 1u), "store route");
if (PsqTestMemory::accesses) Require(PsqTestMemory::address == addr && PsqTestMemory::width == width, "store slow address / width");
}
}
}
int main(int argc, char** argv) {
try {
if (argc > 1) {
std::signal(SIGABRT, [](int) { std::_Exit(86); });
const uint32_t type = static_cast<uint32_t>(std::stoul(argv[2]));
const bool single = std::string(argv[3]) == "1";
uint8_t* host = std::string(argv[4]) == "resolved" ? PsqTestMemory::bytes.data() : nullptr;
if (std::string(argv[1]) == "load") {
if (single) PPC_PsqLResolvedStateInline<1, 7>(type << 16, host, 0, 0);
else PPC_PsqLResolvedStateInline<0, 7>(type << 16, host, 0, 0);
} else {
if (single) PPC_PsqStResolvedStateInline<1, 7>(type, host, 0, 0, 0);
else PPC_PsqStResolvedStateInline<0, 7>(type, host, 0, 0, 0);
}
return 0;
}
const auto saved = MkwGetHostFpControl();
CpuContext ctx{};
for (uint32_t ni : {0u, 4u}) for (uint32_t rounding = 0; rounding < 4; ++rounding) {
ctx.fpscr = ni;
CpuContextScope scope(&ctx);
#if defined(__x86_64__)
MkwSetHostFpControl((MkwGetHostFpControl() & ~(3u << 13)) | (rounding << 13));
#endif
Check<0, 0>(); Check<1, 0>(); Check<0, 7>(); Check<1, 7>();
}
MkwRestoreHostMxcsr(saved);
std::cout << "passed " << checks << " checks, checksum " << std::hex << checksum << '\n';
} catch (const std::exception& error) {
std::cerr << error.what() << '\n';
return 1;
}
}
+83
View File
@@ -0,0 +1,83 @@
#pragma once
// Instrumented ISA memory seam: no guest VM reservation or GPU is needed.
#include "big_endian.h"
#include <array>
#include <cstdint>
#include <cstring>
namespace PsqTestMemory {
inline std::array<uint8_t, 512> bytes{};
inline uint32_t address = 0;
inline size_t width = 0;
inline unsigned accesses = 0;
inline bool directStack = false;
inline uint8_t* Pointer(uint32_t addr) { return bytes.data() + (addr & 255u); }
inline void Record(uint32_t addr, size_t size) { address = addr; width = size; ++accesses; }
template <typename T> T ReadHost(const uint8_t* host) {
if constexpr (sizeof(T) == 1) return *host;
else if constexpr (sizeof(T) == 2) return BigEndian::Read16(host);
else if constexpr (sizeof(T) == 4) return BigEndian::Read32(host);
else return (uint64_t(BigEndian::Read32(host)) << 32) | BigEndian::Read32(host + 4);
}
template <typename T> void WriteHost(uint8_t* host, T value) {
if constexpr (sizeof(T) == 1) *host = value;
else if constexpr (sizeof(T) == 2) BigEndian::Write16(host, value);
else if constexpr (sizeof(T) == 4) BigEndian::Write32(host, value);
else BigEndian::Write64(host, value);
}
template <typename T> T Read(uint32_t addr) {
Record(addr, sizeof(T)); return ReadHost<T>(Pointer(addr));
}
template <typename T> void Write(uint32_t addr, T value) {
Record(addr, sizeof(T)); WriteHost(Pointer(addr), value);
}
}
namespace GuestFlat {
inline bool RequiresCheckedAccess() noexcept { return true; }
}
#define MKW_FLAT_GUEST_BASE (PsqTestMemory::bytes.data())
class Memory {
public:
static uint8_t Read8(uint32_t a) { return PsqTestMemory::Read<uint8_t>(a); }
static uint16_t Read16(uint32_t a) { return PsqTestMemory::Read<uint16_t>(a); }
static uint32_t Read32(uint32_t a) { return PsqTestMemory::Read<uint32_t>(a); }
static uint64_t Read64(uint32_t a) { return PsqTestMemory::Read<uint64_t>(a); }
static void Write8(uint32_t a, uint8_t v) { PsqTestMemory::Write(a, v); }
static void Write16(uint32_t a, uint16_t v) { PsqTestMemory::Write(a, v); }
static void Write32(uint32_t a, uint32_t v) { PsqTestMemory::Write(a, v); }
static void Write64(uint32_t a, uint64_t v) { PsqTestMemory::Write(a, v); }
};
namespace MemoryInline {
inline bool FlatWriteNeedsPolicy(uint32_t) { return true; }
inline bool TryGetPointerFast(uint32_t a, size_t, uint8_t*& host) {
host = PsqTestMemory::directStack ? PsqTestMemory::Pointer(a) : nullptr;
return host != nullptr;
}
inline bool TryGetWritablePointerFast(uint32_t a, size_t n, uint8_t*& host) {
return TryGetPointerFast(a, n, host);
}
template <typename T> T ReadResolvedFallback(uint32_t a) { return PsqTestMemory::Read<T>(a); }
template <typename T> void WriteResolvedFallback(uint32_t a, T v) { PsqTestMemory::Write(a, v); }
template <typename T> T ReadResolved(uint8_t* host, uint32_t o, uint32_t a) {
return host ? PsqTestMemory::ReadHost<T>(host + o) : ReadResolvedFallback<T>(a);
}
template <typename T> void WriteResolved(uint8_t* host, uint32_t o, uint32_t a, T v) {
if (host) PsqTestMemory::WriteHost(host + o, v); else WriteResolvedFallback(a, v);
}
#define PSQ_TEST_MEMORY_WIDTH(Bits, Type) \
inline Type ReadStack##Bits(uint32_t a) { \
return PsqTestMemory::directStack ? PsqTestMemory::ReadHost<Type>(PsqTestMemory::Pointer(a)) : PsqTestMemory::Read<Type>(a); } \
inline void WriteStack##Bits(uint32_t a, Type v) { \
if (PsqTestMemory::directStack) PsqTestMemory::WriteHost(PsqTestMemory::Pointer(a), v); else PsqTestMemory::Write(a, v); } \
inline Type ReadResolved##Bits(uint8_t* h, uint32_t o, uint32_t a) { return ReadResolved<Type>(h, o, a); } \
inline void WriteResolved##Bits(uint8_t* h, uint32_t o, uint32_t a, Type v) { WriteResolved(h, o, a, v); }
PSQ_TEST_MEMORY_WIDTH(8, uint8_t)
PSQ_TEST_MEMORY_WIDTH(16, uint16_t)
PSQ_TEST_MEMORY_WIDTH(32, uint32_t)
PSQ_TEST_MEMORY_WIDTH(64, uint64_t)
#undef PSQ_TEST_MEMORY_WIDTH
}
+13
View File
@@ -0,0 +1,13 @@
foreach(operation load store)
foreach(type 1 2 3)
foreach(lanes 0 1)
foreach(route resolved null)
execute_process(COMMAND "${PSQ_TEST_EXECUTABLE}" ${operation} ${type} ${lanes} ${route}
RESULT_VARIABLE result OUTPUT_VARIABLE output ERROR_VARIABLE error)
if(NOT result EQUAL 86)
message(FATAL_ERROR "Reserved PSQ ${operation}/${type}/${lanes}/${route}: ${result} ${output} ${error}")
endif()
endforeach()
endforeach()
endforeach()
endforeach()
@@ -15,6 +15,7 @@ internal static class TranslatorCppTestHarness
Path.Combine("runtime", "src", "fpu_helpers.cpp"), Path.Combine("runtime", "src", "fpu_helpers.cpp"),
Path.Combine("runtime", "src", "memory.cpp"), Path.Combine("runtime", "src", "memory.cpp"),
Path.Combine("runtime", "src", "ppc_helpers.cpp"), Path.Combine("runtime", "src", "ppc_helpers.cpp"),
Path.Combine("runtime", "src", "ppc_quantized.cpp"),
}; };
public static string BuildCompileArguments( public static string BuildCompileArguments(
@@ -31,6 +32,7 @@ internal static class TranslatorCppTestHarness
args.Append("-std=c++17 "); args.Append("-std=c++17 ");
args.Append("-D_CRT_SECURE_NO_WARNINGS "); args.Append("-D_CRT_SECURE_NO_WARNINGS ");
args.Append("-march=x86-64-v3 "); args.Append("-march=x86-64-v3 ");
args.Append("-fno-fast-math -ffp-contract=off ");
if (!RuntimeHeadersDefineRestrictMacro(repoRoot)) if (!RuntimeHeadersDefineRestrictMacro(repoRoot))
{ {
// Fallback for the window between an emitter change using MKW_RESTRICT and the runtime // Fallback for the window between an emitter change using MKW_RESTRICT and the runtime