mirror of
https://github.com/patchzyy/wiicompiled
synced 2026-10-01 16:01:23 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7caee02c74 |
@@ -152,8 +152,7 @@ if ($Profile -ne 'both' -and -not [string]::IsNullOrWhiteSpace($BaseOutputDirect
|
||||
}
|
||||
$realWorkspace = $Workspace.TrimEnd('\')
|
||||
$Workspace = Get-MkwBuildSafePath $realWorkspace 'workspace' 'runtime\CMakeLists.txt'
|
||||
# A selected package inside the install may also name the same Code.pul through the real path.
|
||||
# Give it the workspace spelling before comparing it with the staged copy.
|
||||
# One spelling of the workspace, so the staged Code.pul check below can't copy a file onto itself.
|
||||
if (-not [string]::IsNullOrWhiteSpace($RetroRewindPackageDirectory) -and
|
||||
$RetroRewindPackageDirectory.StartsWith($realWorkspace + '\', [StringComparison]::OrdinalIgnoreCase)) {
|
||||
$RetroRewindPackageDirectory = $Workspace + $RetroRewindPackageDirectory.Substring($realWorkspace.Length)
|
||||
|
||||
@@ -42,9 +42,10 @@ function Get-MkwToolchainPath([string]$ToolchainRoot) {
|
||||
|
||||
function Get-MkwBuildSafePath([string]$Path, [string]$Kind, [string]$MarkerFile) {
|
||||
<#
|
||||
The Windows native build passes workspace paths through CMake, Ninja response files and
|
||||
clang, which do not all interpret quotes the same way. Keep those paths plain even when the
|
||||
user's install directory contains an apostrophe, ampersand or other punctuation.
|
||||
$Path, or a junction to it whose path is plain ASCII. cmd.exe, Ninja response files and the
|
||||
compiler each have their own quoting rules, so a path outside this allowlist ('&', '%', an
|
||||
apostrophe, non-ASCII...) is never handed to the native build at all. $MarkerFile is a file
|
||||
that must exist under a live junction.
|
||||
#>
|
||||
if ([string]::IsNullOrWhiteSpace($Path)) { throw "A $Kind path is required." }
|
||||
$full = [IO.Path]::GetFullPath($Path)
|
||||
@@ -52,8 +53,6 @@ function Get-MkwBuildSafePath([string]$Path, [string]$Kind, [string]$MarkerFile)
|
||||
if ($full -ne [IO.Path]::GetPathRoot($full)) { $full = $full.TrimEnd('\') }
|
||||
if ($full -cmatch '^[A-Za-z0-9 ._\\:-]+$') { return $full }
|
||||
|
||||
Assert-File (Join-Path $full $MarkerFile) "$Kind marker"
|
||||
|
||||
$sha = [Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
$bytes = $sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($full.ToLowerInvariant()))
|
||||
@@ -66,29 +65,23 @@ function Get-MkwBuildSafePath([string]$Path, [string]$Kind, [string]$MarkerFile)
|
||||
$link = Join-Path (Join-Path $base 'WiiCompiled') $linkName
|
||||
try {
|
||||
[IO.Directory]::CreateDirectory((Split-Path -Parent $link)) | Out-Null
|
||||
$existing = Get-Item -LiteralPath $link -Force -ErrorAction SilentlyContinue
|
||||
if ($null -ne $existing) {
|
||||
# Never trust a directory just because it has the marker: it could point at a
|
||||
# different installation. Nor may we remove a directory we did not create.
|
||||
if ($existing.LinkType -ne 'Junction' -or
|
||||
@($existing.Target).Count -ne 1 -or
|
||||
-not [string]::Equals([IO.Path]::GetFullPath(@($existing.Target)[0]),
|
||||
$full, [StringComparison]::OrdinalIgnoreCase)) {
|
||||
throw "An existing path is not the expected junction: $link"
|
||||
}
|
||||
} else {
|
||||
# The name already identifies the target, so an existing junction that still resolves is
|
||||
# this one; only a broken leftover is replaced. Directory.Delete removes the reparse
|
||||
# point itself, where Remove-Item -Recurse would delete the tree it points at.
|
||||
if (-not (Test-Path -LiteralPath (Join-Path $link $MarkerFile) -PathType Leaf)) {
|
||||
if (Test-Path -LiteralPath $link) { [IO.Directory]::Delete($link) }
|
||||
New-Item -ItemType Junction -Path $link -Target $full -ErrorAction Stop | Out-Null
|
||||
}
|
||||
Assert-File (Join-Path $link $MarkerFile) "$Kind junction marker"
|
||||
Write-Host "MKWCBUILD: Building the $Kind through $link, because $full contains characters the native build cannot quote reliably"
|
||||
return $link
|
||||
} catch {
|
||||
$failures += "$link ($($_.Exception.Message))"
|
||||
}
|
||||
}
|
||||
throw ("The $Kind path $full cannot be passed safely to the native build, and no junction " +
|
||||
'to it could be created: ' + ($failures -join '; ') + '. Install to a path of plain ' +
|
||||
'letters, digits and spaces, or make a safe junction location available.')
|
||||
Write-Host ("MKWCBUILD: Warning: no junction to $full could be created (" + ($failures -join '; ') +
|
||||
'); building from the original path, which may fail. Installing to a path of plain ' +
|
||||
'letters, digits and spaces avoids this.')
|
||||
return $full
|
||||
}
|
||||
|
||||
function Get-MkwProjectPins([string]$ProjectFile) {
|
||||
|
||||
@@ -82,9 +82,9 @@ $packages = @(
|
||||
Pins = @(@{ File = $auroraExtern; Text = 'https://github.com/wolfpld/tracy/archive/a64b9a20294d59421a2f57aeca3c6383d8c48169.tar.gz' })
|
||||
},
|
||||
[pscustomobject]@{
|
||||
Name = 'xxhash'; File = 'xxHash-0.8.4.tar.gz'
|
||||
Uris = @('https://github.com/Cyan4973/xxHash/archive/refs/tags/v0.8.4.tar.gz')
|
||||
Pins = @(@{ File = $auroraExtern; Text = 'https://github.com/Cyan4973/xxHash/archive/refs/tags/v0.8.4.tar.gz' })
|
||||
Name = 'xxhash'; File = 'xxHash-0.8.3.tar.gz'
|
||||
Uris = @('https://github.com/Cyan4973/xxHash/archive/refs/tags/v0.8.3.tar.gz')
|
||||
Pins = @(@{ File = $auroraExtern; Text = 'https://github.com/Cyan4973/xxHash/archive/refs/tags/v0.8.3.tar.gz' })
|
||||
},
|
||||
[pscustomobject]@{
|
||||
Name = 'zlib'; File = 'zlib-1.3.2.tar.gz'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# Builds the redistributable precompiled aurora + third-party package for native Linux: aurora
|
||||
# (~43% of local build CPU time per Prepare-NativePrebuilt.ps1), Crypto++ and mbed TLS are identical
|
||||
# (~43% of local build CPU time per Prepare-NativePrebuilt.ps1) and vendored Crypto++ are identical
|
||||
# for every user under the pinned toolchain prepare-portable-tools.sh bundles, so this configures
|
||||
# runtime/ against that toolchain, builds just that closure, and harvests the archives plus a
|
||||
# generated CMake description into an output package - the Linux counterpart to
|
||||
@@ -22,17 +22,11 @@ workspace=$(cd "$script_dir/.." && pwd)
|
||||
|
||||
arch=""
|
||||
output_dir=""
|
||||
toolchain_dir=""
|
||||
ninja_bin=""
|
||||
cmake_bin=""
|
||||
llvm_dir=""
|
||||
sysroot=""
|
||||
stage_dir="$workspace/build/native-prebuilt-stage"
|
||||
keep_stage=0
|
||||
reuse_stage=0
|
||||
parallel=0
|
||||
print_fingerprint_only=0
|
||||
disconnected=0
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
@@ -45,7 +39,8 @@ Usage: Prepare-NativePrebuilt.sh --arch {x86_64|aarch64} [options]
|
||||
--reuse-stage Reuse an existing staging build directory (maintainer iteration aid: a
|
||||
re-harvest does not recompile aurora from scratch)
|
||||
--parallel N Ninja build parallelism (default: nproc)
|
||||
--print-fingerprint-only Print the provenance inputs as "key=value" lines and
|
||||
--print-fingerprint-only Print the four provenance inputs (compiler_sha256, flag_fingerprint,
|
||||
aurora_fingerprint, third_party_fingerprint) as "key=value" lines and
|
||||
exit, without configuring/building/harvesting anything - lets a caller
|
||||
(build-appimage.sh) decide whether an existing package is still current
|
||||
without paying for a full aurora rebuild just to find out.
|
||||
@@ -61,12 +56,6 @@ while [[ $# -gt 0 ]]; do
|
||||
--reuse-stage) reuse_stage=1; shift ;;
|
||||
--parallel) parallel=$2; shift 2 ;;
|
||||
--print-fingerprint-only) print_fingerprint_only=1; shift ;;
|
||||
--toolchain-dir) toolchain_dir=$2; shift 2 ;;
|
||||
--ninja-bin) ninja_bin=$2; shift 2 ;;
|
||||
--cmake-bin) cmake_bin=$2; shift 2 ;;
|
||||
--llvm-dir) llvm_dir=$2; shift 2 ;;
|
||||
--sysroot) sysroot=$2; shift 2 ;;
|
||||
--disconnected) disconnected=1; shift ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) echo "Prepare-NativePrebuilt.sh: unknown argument: $1" >&2; exit 1 ;;
|
||||
esac
|
||||
@@ -83,22 +72,14 @@ assert_dir() { [[ -d "$1" ]] || fail "$2 is missing: $1"; }
|
||||
sha256_of() { sha256sum "$1" | awk '{print $1}'; }
|
||||
normalize() { readlink -f "$1"; }
|
||||
|
||||
# Environment check: Ensure the `SOURCE_DATE_EPOCH` value is not invalid
|
||||
# before trying to build anything (fail-fast)
|
||||
if [[ -n "${SOURCE_DATE_EPOCH:-}" ]] && ! python3 -c \
|
||||
'import datetime, os; datetime.datetime.fromtimestamp(int(os.environ.get("SOURCE_DATE_EPOCH")), datetime.timezone.utc)'
|
||||
then
|
||||
fail "SOURCE_DATE_EPOCH must be a valid UNIX timestamp"
|
||||
fi
|
||||
|
||||
[[ -n "$output_dir" ]] || output_dir="$script_dir/artifacts/native-prebuilt-$arch"
|
||||
[[ "$stage_dir" = /* ]] || stage_dir="$workspace/$stage_dir"
|
||||
|
||||
toolchain_dir="${toolchain_dir:-$script_dir/artifacts/portable-tools/toolchain-$arch}"
|
||||
cc="${llvm_dir:-$toolchain_dir}/bin/clang"
|
||||
cxx="${llvm_dir:-$toolchain_dir}/bin/clang++"
|
||||
cmake_bin="${cmake_bin:-$toolchain_dir/bin/cmake}"
|
||||
ninja_bin="${ninja_bin:-$toolchain_dir/bin/ninja}"
|
||||
toolchain_dir="$script_dir/artifacts/portable-tools/toolchain-$arch"
|
||||
cc="$toolchain_dir/bin/clang"
|
||||
cxx="$toolchain_dir/bin/clang++"
|
||||
cmake_bin="$toolchain_dir/bin/cmake"
|
||||
ninja_bin="$toolchain_dir/bin/ninja"
|
||||
runtime_source="$workspace/runtime"
|
||||
aurora_source="$workspace/aurora-main"
|
||||
|
||||
@@ -107,7 +88,7 @@ assert_file "$ninja_bin" "Portable Ninja"
|
||||
assert_file "$cc" "Portable C compiler"
|
||||
assert_file "$cxx" "Portable C++ compiler"
|
||||
assert_dir "$aurora_source" "aurora-main source tree"
|
||||
clang_binary=$(normalize "${llvm_dir:-$toolchain_dir}/bin/clang-22")
|
||||
clang_binary=$(normalize "$toolchain_dir/bin/clang-22")
|
||||
assert_file "$clang_binary" "Portable clang driver binary"
|
||||
|
||||
(( parallel > 0 )) || parallel=$(nproc)
|
||||
@@ -150,8 +131,6 @@ fixed_configure_flags=(
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_absl=ON
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_PNG=ON
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_Freetype=ON
|
||||
-DUSE_STATIC_MBEDTLS_LIBRARY=ON
|
||||
-DUSE_SHARED_MBEDTLS_LIBRARY=OFF
|
||||
# Freetype's own vendored CMakeLists.txt separately probes for system BZip2 (optional
|
||||
# bzip2-compressed-font support aurora-main never asked for) regardless of the Freetype
|
||||
# find_package disable above, since that only stops aurora's own outer find_package(Freetype)
|
||||
@@ -162,16 +141,6 @@ fixed_configure_flags=(
|
||||
-DFT_DISABLE_BZIP2=ON
|
||||
-DCMAKE_POLICY_DEFAULT_CMP0168=NEW
|
||||
)
|
||||
if [[ "$disconnected" -eq 1 ]]; then
|
||||
fixed_configure_flags+=(
|
||||
-DFETCHCONTENT_FULLY_DISCONNECTED=ON
|
||||
)
|
||||
fi
|
||||
if [[ -n "$sysroot" ]]; then
|
||||
fixed_configure_flags+=(
|
||||
-DCMAKE_SYSROOT="$sysroot"
|
||||
)
|
||||
fi
|
||||
flag_fingerprint=$(printf '%s\n' "${fixed_configure_flags[@]}" | sha256sum | awk '{print $1}')
|
||||
|
||||
# extern/ is excluded because the payload ships that tree separately (aurora-main/extern is bundled
|
||||
@@ -179,24 +148,19 @@ flag_fingerprint=$(printf '%s\n' "${fixed_configure_flags[@]}" | sha256sum | awk
|
||||
aurora_fingerprint=$(fingerprint_tree "$aurora_source" extern build)
|
||||
[[ -n "$aurora_fingerprint" ]] || fail "The aurora source tree could not be fingerprinted: $aurora_source"
|
||||
|
||||
# The harvested Crypto++ archive is consumed against this tree's headers, so it is fingerprinted.
|
||||
# The harvested Crypto++ archive is consumed against this tree's headers, so it is fingerprinted
|
||||
# for the same reason as aurora above. No exclusions: unlike aurora's extern/, nothing under
|
||||
# runtime/third_party is shipped separately.
|
||||
third_party_fingerprint=$(fingerprint_tree "$runtime_source/third_party")
|
||||
[[ -n "$third_party_fingerprint" ]] || fail "The vendored third-party tree could not be fingerprinted: $runtime_source/third_party"
|
||||
mbedtls_fingerprint=$(sha256_of "$runtime_source/cmake/MbedTLSPin.cmake")
|
||||
|
||||
compiler_sha256=$(sha256_of "$cc")
|
||||
cxx_sha256=$(sha256_of "$cxx")
|
||||
# Append the CXX SHA256 if it doesn't match the hash of CC
|
||||
if [[ "${cxx_sha256}" != "${compiler_sha256}" ]]; then
|
||||
compiler_sha256="${compiler_sha256}:${cxx_sha256}"
|
||||
fi
|
||||
compiler_sha256=$(sha256_of "$clang_binary")
|
||||
|
||||
if [[ "$print_fingerprint_only" -eq 1 ]]; then
|
||||
printf 'compiler_sha256=%s\n' "$compiler_sha256"
|
||||
printf 'flag_fingerprint=%s\n' "$flag_fingerprint"
|
||||
printf 'aurora_fingerprint=%s\n' "$aurora_fingerprint"
|
||||
printf 'third_party_fingerprint=%s\n' "$third_party_fingerprint"
|
||||
printf 'mbedtls_fingerprint=%s\n' "$mbedtls_fingerprint"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -397,21 +361,6 @@ while IFS='|' read -r name type file linkerfile; do
|
||||
linker_file_to_reference["$linkerfile"]="@PKG@/$relative_linker"
|
||||
fi
|
||||
done < "$targets_txt"
|
||||
mbedtls_refs=()
|
||||
mbedtls_txt="$export_dir/mbedtls.txt"
|
||||
assert_file "$mbedtls_txt" "Mbed TLS export targets list"
|
||||
while IFS='|' read -r name linkerfile; do
|
||||
[[ -n "$name" ]] || continue
|
||||
linkerfile=$(normalize "$linkerfile")
|
||||
ref=${linker_file_to_reference["$linkerfile"]:-}
|
||||
[[ -n "$ref" ]] || fail "Mbed TLS archive was not harvested: $name ($linkerfile)"
|
||||
mbedtls_refs+=("$ref")
|
||||
done < "$mbedtls_txt"
|
||||
[[ ${#mbedtls_refs[@]} -ge 3 ]] || fail "Expected at least three Mbed TLS archives, got ${#mbedtls_refs[@]}"
|
||||
mbedtls_source_dir=$(get_meta mbedtls_source_dir)
|
||||
assert_dir "$mbedtls_source_dir/include/mbedtls" "Mbed TLS headers"
|
||||
mkdir -p "$output_dir/include/mbedtls"
|
||||
cp -a "$mbedtls_source_dir/include/." "$output_dir/include/mbedtls/"
|
||||
# Unlike Windows (SDL/zlib/libpng ship as DLLs by default), everything here was forced static above
|
||||
# and Dawn's own Linux package (verified directly) ships libwebgpu_dawn.a, also static - so zero
|
||||
# shared imports is the expected, normal outcome, not a failure.
|
||||
@@ -477,9 +426,6 @@ for item in "${link_items[@]}"; do
|
||||
if [[ "$item" = /* ]]; then item_abs=$(normalize "$item"); else item_abs=$(normalize "$stage_dir/$item"); fi
|
||||
ref=${linker_file_to_reference["$item_abs"]:-}
|
||||
if [[ -n "$ref" ]]; then
|
||||
for mbedtls_ref in "${mbedtls_refs[@]}"; do
|
||||
[[ "$ref" == "$mbedtls_ref" ]] && continue 2
|
||||
done
|
||||
package_link_items+=("$ref")
|
||||
continue
|
||||
fi
|
||||
@@ -559,9 +505,6 @@ generated_cmake="$output_dir/native_prebuilt.cmake"
|
||||
format_cmake_block MKW_NP_COMPILE_DEFINITIONS "${package_definitions[@]}"
|
||||
format_cmake_block MKW_NP_COMPILE_OPTIONS "${package_compile_options[@]}"
|
||||
format_cmake_block MKW_NP_LINK_LIBRARIES "${package_link_items[@]}"
|
||||
format_cmake_block MKW_NP_MBEDTLS_LIBRARIES "${mbedtls_refs[@]}"
|
||||
echo 'set(MKW_NP_MBEDTLS_INCLUDE_DIR "@PKG@/include/mbedtls")'
|
||||
printf 'set(MKW_NP_MBEDTLS_FINGERPRINT "%s")\n' "$mbedtls_fingerprint"
|
||||
format_cmake_block MKW_NP_AURORA_TARGETS "aurora::gx" "aurora::pad" "aurora::si" "aurora::vi" "aurora::mtx"
|
||||
echo ""
|
||||
printf 'set(MKW_NP_DAWN_CONFIG_DIR "%s")\n' "$dawn_config_token"
|
||||
@@ -597,12 +540,12 @@ harvested_count=${#linker_file_to_reference[@]}
|
||||
|
||||
python3 - "$output_dir" "$compiler_sha256" "$compiler_version" "$flag_fingerprint" \
|
||||
"$dawn_version" "$dawn_runtime_sha256" "$aurora_fingerprint" "$third_party_fingerprint" \
|
||||
"$sdl3_target" "$harvested_count" "$mbedtls_fingerprint" <<'PY'
|
||||
"$sdl3_target" "$harvested_count" <<'PY'
|
||||
import hashlib, json, os, sys, datetime
|
||||
|
||||
(output_dir, compiler_sha256, compiler_version, flag_fingerprint, dawn_version,
|
||||
dawn_runtime_sha256, aurora_fingerprint, third_party_fingerprint, sdl3_target,
|
||||
harvested_count, mbedtls_fingerprint) = sys.argv[1:]
|
||||
harvested_count) = sys.argv[1:]
|
||||
|
||||
contents = []
|
||||
for root, dirs, files in os.walk(output_dir):
|
||||
@@ -617,21 +560,9 @@ for root, dirs, files in os.walk(output_dir):
|
||||
contents.append({"Path": rel, "Bytes": os.path.getsize(path), "Sha256": digest})
|
||||
contents.sort(key=lambda c: c["Path"])
|
||||
|
||||
source_date_epoch = os.environ.get("SOURCE_DATE_EPOCH") or None
|
||||
utc = datetime.timezone.utc
|
||||
if source_date_epoch is not None:
|
||||
built_utc = datetime.datetime.fromtimestamp(
|
||||
int(source_date_epoch),
|
||||
utc
|
||||
)
|
||||
else:
|
||||
built_utc = datetime.datetime.now(utc)
|
||||
|
||||
built_utc = built_utc.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
|
||||
|
||||
provenance = {
|
||||
"SchemaVersion": 1,
|
||||
"BuiltUtc": built_utc,
|
||||
"BuiltUtc": datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z",
|
||||
"CompilerSha256": compiler_sha256,
|
||||
"CompilerVersion": compiler_version,
|
||||
"FlagFingerprint": flag_fingerprint,
|
||||
@@ -639,7 +570,6 @@ provenance = {
|
||||
"DawnRuntimeSha256": dawn_runtime_sha256,
|
||||
"AuroraSourceFingerprint": aurora_fingerprint,
|
||||
"ThirdPartySourceFingerprint": third_party_fingerprint,
|
||||
"MbedTlsFingerprint": mbedtls_fingerprint,
|
||||
"Sdl3Target": sdl3_target,
|
||||
"HarvestedLibraryCount": int(harvested_count),
|
||||
"Contents": contents,
|
||||
|
||||
@@ -127,40 +127,19 @@ internal static class Program
|
||||
string? retroWfcOfflineDir = null;
|
||||
if (downloadPayload)
|
||||
{
|
||||
// Reused if a previous install already downloaded and it's still valid - matches
|
||||
// Windows's own reuse-if-valid behavior instead of re-downloading on every install.
|
||||
var cacheDir = Path.Combine(workspace, "generated", "retro-wfc-payload");
|
||||
reporter.Progress(InstallStages.Validate,
|
||||
"Downloading the current Retro-WFC payload", 1);
|
||||
reporter.Progress(InstallStages.Validate, "Preparing the Retro-WFC payload", 1);
|
||||
try
|
||||
{
|
||||
// A valid signature authenticates a payload, but does not prove it is the latest
|
||||
// signed revision. Always ask the fixed endpoint for the current snapshot; the
|
||||
// downloader verifies it before atomically replacing the cache.
|
||||
RetroWfcPayload.ValidateStagedRetroWfcPayloadDirectory(cacheDir);
|
||||
}
|
||||
catch (InvalidDataException)
|
||||
{
|
||||
await RetroWfcPayload.DownloadRetroWfcPayloadAsync(
|
||||
RetroWfcPayload.CurrentRetroWfcPayloadUri, cacheDir, token);
|
||||
}
|
||||
catch (Exception downloadFailure) when (!token.IsCancellationRequested &&
|
||||
downloadFailure is HttpRequestException or TimeoutException
|
||||
or IOException)
|
||||
{
|
||||
// Offline installs may continue with a previously authenticated snapshot. Do not
|
||||
// use this path for a newly downloaded payload that failed signature validation:
|
||||
// that must remain a hard failure instead of hiding possible endpoint tampering.
|
||||
try
|
||||
{
|
||||
RetroWfcPayload.ValidateStagedRetroWfcPayloadDirectory(cacheDir);
|
||||
}
|
||||
catch (Exception cacheFailure) when (cacheFailure is IOException or
|
||||
UnauthorizedAccessException or InvalidDataException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"The current Retro-WFC payload could not be downloaded and no valid cached " +
|
||||
$"payload is available ({cacheFailure.Message.TrimEnd('.')}).", downloadFailure);
|
||||
}
|
||||
|
||||
reporter.Diagnostic(
|
||||
"The current Retro-WFC payload could not be downloaded; using the previously " +
|
||||
$"verified cached payload instead ({downloadFailure.Message.TrimEnd('.')}).");
|
||||
}
|
||||
retroWfcOfflineDir = cacheDir;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,8 @@ internal sealed class ProductRepairService
|
||||
InputValidation.CurrentRetroWfcPayloadUri, payloadScratch, cancellationToken);
|
||||
}
|
||||
catch (Exception ex) when (!cancellationToken.IsCancellationRequested &&
|
||||
ex is HttpRequestException or TimeoutException or IOException)
|
||||
ex is HttpRequestException or IOException or InvalidDataException
|
||||
or InvalidOperationException or OperationCanceledException)
|
||||
{
|
||||
payloadSnapshot = RecoverInstalledRetroWfcPayload(toolkitFingerprint,
|
||||
Path.Combine(scratchRoot, "retro-wfc-payload-recovered"), ex, cancellationToken);
|
||||
|
||||
@@ -128,9 +128,9 @@ cp -a "$workspace/Launcher/artifacts/portable-tools/toolchain-$appimagetool_arch
|
||||
|
||||
# Precompiled aurora + third-party package (see Prepare-NativePrebuilt.sh) so a user's own
|
||||
# local-build.sh never has to compile aurora itself (~43% of local build CPU time). Re-harvesting
|
||||
# recompiles the aurora/Crypto++/mbed TLS closure with the toolchain above, so this is skipped unless
|
||||
# recompiles the whole aurora/Crypto++ closure with the toolchain above, so this is skipped unless
|
||||
# --print-fingerprint-only (a fast, build-free check) says the existing package no longer matches
|
||||
# the current compiler, flags, source trees or mbed TLS pin.
|
||||
# the current compiler/flags/aurora/third_party sources.
|
||||
native_prebuilt_dir="$workspace/Launcher/artifacts/native-prebuilt-$appimagetool_arch"
|
||||
echo "Checking whether the precompiled aurora + third-party package ($appimagetool_arch) is current..."
|
||||
current_fingerprint=$(bash "$script_dir/Prepare-NativePrebuilt.sh" --arch "$appimagetool_arch" --print-fingerprint-only)
|
||||
@@ -148,7 +148,6 @@ fields = {
|
||||
"flag_fingerprint": "FlagFingerprint",
|
||||
"aurora_fingerprint": "AuroraSourceFingerprint",
|
||||
"third_party_fingerprint": "ThirdPartySourceFingerprint",
|
||||
"mbedtls_fingerprint": "MbedTlsFingerprint",
|
||||
}
|
||||
print(1 if all(provenance.get(v) == current.get(k) for k, v in fields.items()) else 0)
|
||||
PY
|
||||
|
||||
@@ -77,40 +77,26 @@ if [[ -n "$retro_dir" ]]; then
|
||||
# verify its pinned signature before publishing it into the local cache.
|
||||
retro_wfc_dir="$support_root/RetroWfcPayload"
|
||||
retro_wfc_payload="$retro_wfc_dir/binary/payload.RMCPD00.bin"
|
||||
cached_payload_valid=0
|
||||
if [[ -f "$retro_wfc_payload" ]]; then
|
||||
if "$translator" validate-retro-wfc-payload --directory "$retro_wfc_dir"; then
|
||||
cached_payload_valid=1
|
||||
else
|
||||
printf 'Discarding an invalid cached Retro-WFC payload...\n' >&2
|
||||
rm -f "$retro_wfc_payload"
|
||||
fi
|
||||
if [[ -f "$retro_wfc_payload" ]] && ! "$translator" validate-retro-wfc-payload --directory "$retro_wfc_dir"; then
|
||||
printf 'Discarding an invalid cached Retro-WFC payload...\n' >&2
|
||||
rm -f "$retro_wfc_payload"
|
||||
fi
|
||||
|
||||
# A signed cache may still be an older vulnerable revision, so always attempt to replace it
|
||||
# with the current signed snapshot. A transport failure may fall back to the verified cache;
|
||||
# a downloaded snapshot with an invalid signature remains a hard failure.
|
||||
printf 'Downloading the current Retro-WFC payload needed for online play...\n'
|
||||
mkdir -p "$retro_wfc_dir"
|
||||
payload_stage=$(mktemp -d "$retro_wfc_dir/.payload-download.XXXXXX")
|
||||
temporary_payload="$payload_stage/binary/payload.RMCPD00.bin"
|
||||
mkdir -p "$(dirname "$temporary_payload")"
|
||||
trap 'rm -rf "$payload_stage"' EXIT
|
||||
if /usr/bin/curl --fail --silent --show-error --connect-timeout 10 --max-time 30 \
|
||||
--retry 1 --output "$temporary_payload" \
|
||||
'https://rwfc.net/api/wfc/payload?g=RMCPD00'; then
|
||||
if [[ ! -f "$retro_wfc_payload" ]]; then
|
||||
printf 'Downloading the Retro-WFC payload needed for online play...\n'
|
||||
mkdir -p "$retro_wfc_dir"
|
||||
payload_stage=$(mktemp -d "$retro_wfc_dir/.payload-download.XXXXXX")
|
||||
temporary_payload="$payload_stage/binary/payload.RMCPD00.bin"
|
||||
mkdir -p "$(dirname "$temporary_payload")"
|
||||
trap 'rm -rf "$payload_stage"' EXIT
|
||||
/usr/bin/curl --fail --silent --show-error --connect-timeout 10 --max-time 30 \
|
||||
--retry 1 --output "$temporary_payload" \
|
||||
'https://rwfc.net/api/wfc/payload?g=RMCPD00' || fail 'could not download the Retro-WFC payload needed for online play'
|
||||
"$translator" validate-retro-wfc-payload --directory "$payload_stage" || \
|
||||
fail 'downloaded Retro-WFC payload failed signature validation'
|
||||
mkdir -p "$retro_wfc_dir/binary"
|
||||
mv "$temporary_payload" "$retro_wfc_payload"
|
||||
rmdir "$payload_stage/binary" "$payload_stage"
|
||||
trap - EXIT
|
||||
elif (( cached_payload_valid )); then
|
||||
printf 'Could not download the current Retro-WFC payload; using the previously verified cached payload.\n' >&2
|
||||
rm -rf "$payload_stage"
|
||||
trap - EXIT
|
||||
else
|
||||
fail 'could not download the current Retro-WFC payload and no valid cached payload is available'
|
||||
fi
|
||||
build_args+=(--profile both --base-output-dir "$products" --retro-rewind-package-dir "$retro_dir" --retro-wfc-offline-dir "$retro_wfc_dir")
|
||||
fi
|
||||
|
||||
@@ -225,7 +225,7 @@ EOF
|
||||
# clang++ invocation above would not catch a broken CMAKE_ROOT (Modules/Templates) or a Ninja that
|
||||
# can't find the compiler.
|
||||
cat > "$test_dir/CMakeLists.txt" <<'EOF'
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(test CXX)
|
||||
add_executable(test t.cpp)
|
||||
EOF
|
||||
|
||||
@@ -132,7 +132,7 @@ trees themselves (fetched by `Launcher/Prepare-Dependencies.ps1`) so end-user bu
|
||||
| Abseil | LTS 20240722.0 | Apache-2.0 | <https://github.com/abseil/abseil-cpp> |
|
||||
| Dear ImGui | 1.91.9b-docking | MIT | <https://github.com/ocornut/imgui> |
|
||||
| {fmt} | 11.1.4 | MIT | <https://github.com/fmtlib/fmt> |
|
||||
| xxHash | 0.8.4 | BSD-2-Clause | <https://github.com/Cyan4973/xxHash> |
|
||||
| xxHash | 0.8.3 | BSD-2-Clause | <https://github.com/Cyan4973/xxHash> |
|
||||
| zlib | 1.3.2 | zlib | <https://github.com/madler/zlib> |
|
||||
| libpng | 1.6.58 | PNG Reference Library License v2 | <https://github.com/pnggroup/libpng> |
|
||||
| FreeType | 2.14.3 | **FreeType License (FTL)** - see below | <https://freetype.org/> |
|
||||
|
||||
@@ -101,7 +101,7 @@ if (_aurora_dawn_provider STREQUAL "vendor")
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(dawn
|
||||
URL "https://github.com/google/dawn/archive/refs/tags/${AURORA_DAWN_VERSION}.tar.gz"
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(dawn)
|
||||
@@ -194,7 +194,7 @@ elseif (_aurora_dawn_provider STREQUAL "package")
|
||||
FetchContent_Declare(dawn_prebuilt
|
||||
URL "${AURORA_DAWN_PACKAGE_URL}"
|
||||
${_dawn_prebuilt_hash_argument}
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
)
|
||||
FetchContent_MakeAvailable(dawn_prebuilt)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(libusb
|
||||
URL "https://github.com/libusb/libusb/releases/download/v${AURORA_LIBUSB_VERSION}/libusb-${AURORA_LIBUSB_VERSION}.tar.bz2"
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
)
|
||||
# Upstream ships no CMakeLists.txt, so this only populates the source tree.
|
||||
FetchContent_MakeAvailable(libusb)
|
||||
|
||||
@@ -120,7 +120,7 @@ elseif (_aurora_nod_provider STREQUAL "package")
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(nod_prebuilt
|
||||
URL "${AURORA_NOD_PACKAGE_URL}"
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(nod_prebuilt)
|
||||
|
||||
@@ -92,7 +92,7 @@ elseif (_aurora_sdl3_provider STREQUAL "package")
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(sdl3_prebuilt
|
||||
URL "${AURORA_SDL3_PACKAGE_URL}"
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
)
|
||||
FetchContent_MakeAvailable(sdl3_prebuilt)
|
||||
|
||||
@@ -145,7 +145,7 @@ elseif (_aurora_sdl3_provider STREQUAL "vendor")
|
||||
endif ()
|
||||
FetchContent_Declare(SDL
|
||||
URL "https://github.com/libsdl-org/SDL/releases/download/release-${AURORA_SDL3_VERSION}/SDL3-${AURORA_SDL3_VERSION}.tar.gz"
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
PATCH_COMMAND "${CMAKE_COMMAND}" -DSDL_SOURCE_DIR=<SOURCE_DIR> -P "${_aurora_sdl3_patches}"
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
|
||||
Vendored
+13
-13
@@ -38,7 +38,7 @@ else ()
|
||||
set(ABSL_PROPAGATE_CXX_STD ON)
|
||||
FetchContent_Declare(abseil-cpp
|
||||
URL https://github.com/abseil/abseil-cpp/archive/refs/tags/20240722.0.tar.gz
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(abseil-cpp)
|
||||
@@ -52,10 +52,10 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/AuroraSDL3Provider.cmake)
|
||||
if (NOT TARGET xxhash)
|
||||
message(STATUS "aurora: Fetching xxhash")
|
||||
FetchContent_Declare(xxhash
|
||||
URL https://github.com/Cyan4973/xxHash/archive/refs/tags/v0.8.4.tar.gz
|
||||
URL_HASH SHA256=5738270935e7c3d38a79b3adf7c9692566ce7895a25f67de43ad52ab504acd32
|
||||
SOURCE_SUBDIR build/cmake
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
URL https://github.com/Cyan4973/xxHash/archive/refs/tags/v0.8.3.tar.gz
|
||||
URL_HASH SHA256=aae608dfe8213dfd05d909a57718ef82f30722c392344583d3f39050c7f29a80
|
||||
SOURCE_SUBDIR cmake_unofficial
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
set(XXHASH_BUILD_XXHSUM OFF CACHE INTERNAL "Build the xxhsum binary")
|
||||
@@ -78,7 +78,7 @@ if (NOT TARGET fmt)
|
||||
FetchContent_Declare(fmt
|
||||
URL https://github.com/fmtlib/fmt/archive/refs/tags/11.1.4.tar.gz
|
||||
URL_HASH SHA256=ac366b7b4c2e9f0dde63a59b3feb5ee59b67974b14ee5dc9ea8ad78aa2c1ee1e
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(fmt)
|
||||
@@ -116,7 +116,7 @@ if (AURORA_ENABLE_GX)
|
||||
ZLIB
|
||||
URL https://github.com/madler/zlib/releases/download/v1.3.2/zlib-1.3.2.tar.gz
|
||||
URL_HASH SHA256=bb329a0a2cd0274d05519d61c667c062e06990d72e125ee2dfa8de64f0119d16
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(ZLIB)
|
||||
@@ -152,7 +152,7 @@ if (AURORA_ENABLE_GX)
|
||||
PNG
|
||||
URL https://github.com/pnggroup/libpng/archive/refs/tags/v1.6.58.tar.gz
|
||||
URL_HASH SHA256=A9D4DF463D36A6E5F9C29BD6F4967312D17E996C1854F3511F833924EB1993CF
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(PNG)
|
||||
@@ -176,7 +176,7 @@ if (AURORA_ENABLE_GX)
|
||||
FetchContent_Declare(Freetype
|
||||
URL https://files.twilitrealm.dev/freetype-2.14.3.tar.gz
|
||||
URL_HASH SHA256=e61b31ab26358b946e767ed7eb7f4bb2e507da1cfefeb7a8861ace7fd5c899a1
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(Freetype)
|
||||
@@ -190,7 +190,7 @@ if (AURORA_ENABLE_GX)
|
||||
FetchContent_Declare(imgui
|
||||
URL https://github.com/ocornut/imgui/archive/refs/tags/v1.91.9b-docking.tar.gz
|
||||
URL_HASH SHA256=466fdef9b18de15f0bb6e288e3d00ffa3d82200ec458ce5e4f724a161d9528a5
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(imgui)
|
||||
@@ -235,7 +235,7 @@ if (AURORA_ENABLE_GX)
|
||||
FetchContent_Declare(sqlite3
|
||||
URL https://sqlite.org/2026/sqlite-amalgamation-3510300.zip
|
||||
URL_HASH SHA256=acb1e6f5d832484bf6d32b681e858c38add8b2acdfd42ac5df24b8afb46552b4
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(sqlite3)
|
||||
@@ -278,7 +278,7 @@ if (AURORA_ENABLE_GX)
|
||||
FetchContent_Declare(zstd
|
||||
URL https://github.com/facebook/zstd/releases/download/v1.5.7/zstd-1.5.7.tar.gz
|
||||
URL_HASH SHA256=eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
SOURCE_SUBDIR build/cmake
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
@@ -299,7 +299,7 @@ if (NOT TARGET TracyClient)
|
||||
tracy
|
||||
URL https://github.com/wolfpld/tracy/archive/a64b9a20294d59421a2f57aeca3c6383d8c48169.tar.gz
|
||||
URL_HASH SHA256=24d342b5127d7f659dc3cf94f24347b348cc736f25b17a691fd7f69541937658
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(tracy)
|
||||
|
||||
@@ -5,7 +5,7 @@ if (NOT TARGET gtest)
|
||||
FetchContent_Declare(googletest
|
||||
URL https://github.com/google/googletest/archive/refs/tags/v1.17.0.tar.gz
|
||||
URL_HASH SHA256=65fab701d9829d38cb77c14acdc431d2108bfdbf8979e40eb8ae567edf10b27c
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
+27
-55
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(mkw_recompiled)
|
||||
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(Clang|AppleClang)$" OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
@@ -21,8 +21,14 @@ if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
message(FATAL_ERROR "WiiCompiled only supports Release builds")
|
||||
endif()
|
||||
|
||||
# Ninja writes Windows-quoted response files; the GNU clang driver otherwise reads them POSIX-style.
|
||||
if(CMAKE_HOST_WIN32)
|
||||
foreach(_mkw_lang C CXX)
|
||||
set(CMAKE_${_mkw_lang}_RESPONSE_FILE_LINK_FLAG "--rsp-quoting=windows @")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
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,
|
||||
# the translated shards and the product glue) and to nothing else. They are
|
||||
@@ -114,10 +120,11 @@ endif()
|
||||
# compiles cleanly for Android with nothing beyond a plain C toolchain (no perl/asm build-script
|
||||
# dependency the way OpenSSL's build has), matching how this project already prefers toolchain-
|
||||
# simple libraries (see Crypto++ above, similarly stripped of ASM/SIMD for portability).
|
||||
# The from-source build fetches a pinned upstream tarball with a checked SHA-256.
|
||||
# The Linux native prebuilt package instead ships its compiled archives and headers.
|
||||
# Bump both values in cmake/MbedTLSPin.cmake when updating; the hash comes from
|
||||
# upstream's signed `mbedtls-<version>-sha256sum.txt` release asset.
|
||||
# Fetched at build time from a pinned upstream release tarball with a checked SHA-256, the same way
|
||||
# aurora-main's own dependencies (SDL, zlib, etc.) are pulled in - not committed as a vendored
|
||||
# source tree, so the repository ships the compiled dependency rather than ~280 tracked upstream
|
||||
# files. Bump MKW_MBEDTLS_VERSION/MKW_MBEDTLS_SHA256 together when updating; the hash comes from
|
||||
# upstream's own signed `mbedtls-<version>-sha256sum.txt` release asset.
|
||||
#
|
||||
# The alias exists on every platform so the link lines in cmake/PublicProducts.cmake stay
|
||||
# platform-independent, but it is only populated where network_ssl.cpp actually compiles the mbed
|
||||
@@ -128,22 +135,20 @@ endif()
|
||||
add_library(mkw_mbedtls INTERFACE)
|
||||
add_library(mkw::mbedtls ALIAS mkw_mbedtls)
|
||||
if(NOT MKW_PLATFORM_WINDOWS)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/cmake/MbedTLSPin.cmake")
|
||||
if(NOT MKW_NATIVE_PREBUILT_DIR)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(mkw_mbedtls_upstream
|
||||
URL "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${MKW_MBEDTLS_VERSION}/mbedtls-${MKW_MBEDTLS_VERSION}.tar.bz2"
|
||||
URL_HASH SHA256=${MKW_MBEDTLS_SHA256}
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
||||
)
|
||||
# Subproject mode already disables testing and codegen; it still enables programs.
|
||||
set(ENABLE_PROGRAMS OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_TESTING OFF CACHE BOOL "" FORCE)
|
||||
set(MBEDTLS_FATAL_WARNINGS OFF CACHE BOOL "" FORCE)
|
||||
set(DISABLE_PACKAGE_CONFIG_AND_INSTALL ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(mkw_mbedtls_upstream)
|
||||
target_link_libraries(mkw_mbedtls INTERFACE MbedTLS::mbedtls MbedTLS::mbedx509 MbedTLS::mbedcrypto)
|
||||
endif()
|
||||
include(FetchContent)
|
||||
set(MKW_MBEDTLS_VERSION "3.6.7")
|
||||
set(MKW_MBEDTLS_SHA256 "a7e8bcbec0e6f761b4af24f25677626b35f762f68eef79c08677a363212d11f6")
|
||||
FetchContent_Declare(mkw_mbedtls_upstream
|
||||
URL "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${MKW_MBEDTLS_VERSION}/mbedtls-${MKW_MBEDTLS_VERSION}.tar.bz2"
|
||||
URL_HASH SHA256=${MKW_MBEDTLS_SHA256})
|
||||
# Subproject mode already defaults ENABLE_TESTING off and skips codegen (GEN_FILES), but
|
||||
# ENABLE_PROGRAMS defaults on and installation/package-config isn't wanted for a linked-in copy.
|
||||
set(ENABLE_PROGRAMS OFF CACHE BOOL "" FORCE)
|
||||
set(ENABLE_TESTING OFF CACHE BOOL "" FORCE)
|
||||
set(MBEDTLS_FATAL_WARNINGS OFF CACHE BOOL "" FORCE)
|
||||
set(DISABLE_PACKAGE_CONFIG_AND_INSTALL ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(mkw_mbedtls_upstream)
|
||||
target_link_libraries(mkw_mbedtls INTERFACE MbedTLS::mbedtls MbedTLS::mbedx509 MbedTLS::mbedcrypto)
|
||||
endif()
|
||||
|
||||
set(MKW_TRANSLATED_COMPILE_JOBS 0 CACHE STRING
|
||||
@@ -163,18 +168,6 @@ set(MKW_AURORA_DIR "${CMAKE_CURRENT_LIST_DIR}/../aurora-main")
|
||||
# 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_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)
|
||||
# ----------------------------------------------------------------------
|
||||
@@ -323,27 +316,6 @@ set_target_properties(mkw_platform PROPERTIES UNITY_BUILD OFF)
|
||||
# Keep these independent from Aurora's BUILD_TESTING option: they validate the
|
||||
# project's host-platform contracts, not Aurora's third-party test suite.
|
||||
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")
|
||||
target_link_libraries(mkw_platform_paths_tests PRIVATE mkw_platform)
|
||||
target_compile_features(mkw_platform_paths_tests PRIVATE cxx_std_17)
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Keep the release and verified archive hash together. The Linux native prebuilt
|
||||
# fingerprint includes this file, so changing either value forces a new harvest.
|
||||
set(MKW_MBEDTLS_VERSION "3.6.7")
|
||||
set(MKW_MBEDTLS_SHA256 "a7e8bcbec0e6f761b4af24f25677626b35f762f68eef79c08677a363212d11f6")
|
||||
@@ -42,28 +42,6 @@ endfunction()
|
||||
mkw_np_resolve(_mkw_np_includes ${MKW_NP_INCLUDE_DIRECTORIES})
|
||||
mkw_np_resolve(_mkw_np_links ${MKW_NP_LINK_LIBRARIES})
|
||||
mkw_np_resolve(_mkw_np_dawn_config ${MKW_NP_DAWN_CONFIG_DIR})
|
||||
if(NOT MKW_PLATFORM_WINDOWS)
|
||||
if(NOT MKW_NP_MBEDTLS_LIBRARIES OR NOT MKW_NP_MBEDTLS_INCLUDE_DIR)
|
||||
message(FATAL_ERROR
|
||||
"The Linux native prebuilt package has no Mbed TLS archives; regenerate it with Prepare-NativePrebuilt.sh")
|
||||
endif()
|
||||
file(SHA256 "${CMAKE_CURRENT_LIST_DIR}/MbedTLSPin.cmake" _mkw_np_current_mbedtls_fingerprint)
|
||||
if(NOT MKW_NP_MBEDTLS_FINGERPRINT STREQUAL _mkw_np_current_mbedtls_fingerprint)
|
||||
message(FATAL_ERROR "The native prebuilt Mbed TLS version differs from this workspace; regenerate the package")
|
||||
endif()
|
||||
mkw_np_resolve(_mkw_np_mbedtls_links ${MKW_NP_MBEDTLS_LIBRARIES})
|
||||
mkw_np_resolve(_mkw_np_mbedtls_include ${MKW_NP_MBEDTLS_INCLUDE_DIR})
|
||||
foreach(_archive IN LISTS _mkw_np_mbedtls_links)
|
||||
if(NOT EXISTS "${_archive}")
|
||||
message(FATAL_ERROR "The native prebuilt package is missing Mbed TLS archive: ${_archive}")
|
||||
endif()
|
||||
endforeach()
|
||||
if(NOT IS_DIRECTORY "${_mkw_np_mbedtls_include}")
|
||||
message(FATAL_ERROR "The native prebuilt package is missing Mbed TLS headers: ${_mkw_np_mbedtls_include}")
|
||||
endif()
|
||||
target_include_directories(mkw_mbedtls SYSTEM INTERFACE "${_mkw_np_mbedtls_include}")
|
||||
target_link_libraries(mkw_mbedtls INTERFACE ${_mkw_np_mbedtls_links})
|
||||
endif()
|
||||
|
||||
foreach(_dir IN LISTS _mkw_np_includes)
|
||||
if(NOT IS_DIRECTORY "${_dir}")
|
||||
|
||||
@@ -77,9 +77,6 @@ target_compile_features(mkw_np_probe PRIVATE cxx_std_20)
|
||||
target_link_libraries(mkw_np_probe PRIVATE
|
||||
aurora::gx aurora::pad aurora::si aurora::vi aurora::mtx
|
||||
mkw::cryptopp)
|
||||
if(NOT MKW_PLATFORM_WINDOWS)
|
||||
target_link_libraries(mkw_np_probe PRIVATE mkw::mbedtls)
|
||||
endif()
|
||||
|
||||
get_filename_component(_mkw_np_aurora_dir "${MKW_AURORA_DIR}" ABSOLUTE)
|
||||
mkw_collect_buildsystem_targets("${_mkw_np_aurora_dir}" _mkw_np_all_targets)
|
||||
@@ -87,25 +84,6 @@ mkw_collect_buildsystem_targets("${_mkw_np_aurora_dir}" _mkw_np_all_targets)
|
||||
# the scan above cannot see it; it is appended explicitly. The type and closure
|
||||
# checks below still apply to it.
|
||||
list(APPEND _mkw_np_all_targets "mkw_cryptopp")
|
||||
if(NOT MKW_PLATFORM_WINDOWS)
|
||||
set(_mkw_np_mbedtls_targets mbedtls mbedx509 mbedcrypto)
|
||||
# mbedcrypto links these third-party archives when upstream defines them.
|
||||
# Keep dependencies after mbedcrypto for static linking on the consumer side.
|
||||
foreach(_t everest p256m)
|
||||
if(TARGET ${_t})
|
||||
list(APPEND _mkw_np_mbedtls_targets ${_t})
|
||||
endif()
|
||||
endforeach()
|
||||
list(APPEND _mkw_np_all_targets ${_mkw_np_mbedtls_targets})
|
||||
# Keep the complete TLS archive set separate from aurora's aggregate link interface.
|
||||
set(_mkw_np_mbedtls_lines "")
|
||||
foreach(_t IN LISTS _mkw_np_mbedtls_targets)
|
||||
string(APPEND _mkw_np_mbedtls_lines
|
||||
"${_t}|$<TARGET_LINKER_FILE:${_t}>\n")
|
||||
endforeach()
|
||||
file(GENERATE OUTPUT "${MKW_NATIVE_PREBUILT_EXPORT_DIR}/mbedtls.txt"
|
||||
CONTENT "${_mkw_np_mbedtls_lines}")
|
||||
endif()
|
||||
if(NOT _mkw_np_all_targets)
|
||||
message(FATAL_ERROR "No buildsystem targets were found under ${_mkw_np_aurora_dir}")
|
||||
endif()
|
||||
@@ -158,7 +136,6 @@ string(REPLACE ";" "," _mkw_np_lib_targets_csv "${_mkw_np_lib_targets}")
|
||||
file(WRITE "${MKW_NATIVE_PREBUILT_EXPORT_DIR}/meta.txt"
|
||||
"aurora_dir=${_mkw_np_aurora_dir}\n"
|
||||
"runtime_dir=${CMAKE_CURRENT_SOURCE_DIR}\n"
|
||||
"mbedtls_source_dir=${mkw_mbedtls_upstream_SOURCE_DIR}\n"
|
||||
"binary_dir=${CMAKE_BINARY_DIR}\n"
|
||||
"dawn_config_dir=${_mkw_np_dawn_config_dir}\n"
|
||||
"dawn_prebuilt_source_dir=${dawn_prebuilt_SOURCE_DIR}\n"
|
||||
|
||||
@@ -118,7 +118,16 @@ foreach(source IN LISTS SOURCES)
|
||||
endif()
|
||||
set_source_files_properties("${source}" PROPERTIES UNITY_GROUP "${runtime_group}")
|
||||
endforeach()
|
||||
# PPC semantic sources are excluded from unity/PCH and configured in CMakeLists.txt.
|
||||
# These translation units implement guest-visible floating-point bit
|
||||
# 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)
|
||||
target_precompile_headers(mkw_runtime_common PRIVATE "${MKW_RUNTIME_SOURCE_DIR}/include/mkw_pch.h")
|
||||
mkw_apply_common_compile_options(mkw_runtime_common)
|
||||
|
||||
@@ -294,7 +294,7 @@ inline double PpcLoadPairPsqFloatFastInline(uint32_t addr)
|
||||
return PpcLoadPairPsqFloatFromHostInline(host);
|
||||
}
|
||||
return PpcBitCastToDoubleInline(
|
||||
PpcLoadPairPsqFloatBitsPackedInline(Memory::Read64(addr)));
|
||||
PpcLoadPairPsqFloatBitsPackedInline(MemoryInline::Read64Slow(addr)));
|
||||
}
|
||||
|
||||
inline double PpcLoadSinglePsqFloatFastInline(uint32_t addr)
|
||||
@@ -349,7 +349,7 @@ inline void PpcStorePairPsqFloatFastInline(uint32_t addr, double value)
|
||||
PpcStorePairPsqFloatToHostInline(host, value);
|
||||
return;
|
||||
}
|
||||
Memory::Write64(
|
||||
MemoryInline::Write64Slow(
|
||||
addr, PpcStorePairPsqFloatBitsPackedInline(PpcBitCastToU64Inline(value)));
|
||||
}
|
||||
|
||||
@@ -1385,13 +1385,37 @@ 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
|
||||
// ordinary native value. All architecturally valid quantization encodings are
|
||||
// handled directly; reserved encodings retain the generic helper's abort.
|
||||
template <uint32_t W, bool Stack>
|
||||
MKW_PPC_NO_INLINE MKW_PPC_COLD double PPC_PsqLStateFallback(uint32_t gqr, uint32_t addr);
|
||||
|
||||
extern template double PPC_PsqLStateFallback<0u, false>(uint32_t, uint32_t);
|
||||
extern template double PPC_PsqLStateFallback<0u, true>(uint32_t, uint32_t);
|
||||
extern template double PPC_PsqLStateFallback<1u, false>(uint32_t, uint32_t);
|
||||
extern template double PPC_PsqLStateFallback<1u, true>(uint32_t, uint32_t);
|
||||
template <uint32_t W, uint32_t I, bool Stack>
|
||||
MKW_PPC_NO_INLINE MKW_PPC_COLD inline double PPC_PsqLStateFallback(uint32_t gqr, uint32_t addr)
|
||||
{
|
||||
static_assert(W <= 1u && I < 8u);
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the normal explicit-state path small and directly optimizable. Exact
|
||||
// unscaled encodings cover the SDK's common GQR setup; scaled and reserved
|
||||
@@ -1418,17 +1442,41 @@ 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);
|
||||
else return Stack ? PpcLoadSinglePsqQuantizedStackInline<int16_t>(addr, 0u) : PpcLoadSinglePsqQuantizedFastInline<int16_t>(addr, 0u);
|
||||
default:
|
||||
return PPC_PsqLStateFallback<W, Stack>(gqr, addr);
|
||||
return PPC_PsqLStateFallback<W, I, Stack>(gqr, addr);
|
||||
}
|
||||
}
|
||||
|
||||
template <uint32_t W, bool Stack>
|
||||
MKW_PPC_NO_INLINE MKW_PPC_COLD void PPC_PsqStStateFallback(uint32_t gqr, uint32_t addr, double value);
|
||||
|
||||
extern template void PPC_PsqStStateFallback<0u, false>(uint32_t, uint32_t, double);
|
||||
extern template void PPC_PsqStStateFallback<0u, true>(uint32_t, uint32_t, double);
|
||||
extern template void PPC_PsqStStateFallback<1u, false>(uint32_t, uint32_t, double);
|
||||
extern template void PPC_PsqStStateFallback<1u, true>(uint32_t, uint32_t, double);
|
||||
template <uint32_t W, uint32_t I, bool Stack>
|
||||
MKW_PPC_NO_INLINE MKW_PPC_COLD inline void PPC_PsqStStateFallback(uint32_t gqr, uint32_t addr, double value)
|
||||
{
|
||||
static_assert(W <= 1u && I < 8u);
|
||||
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, uint32_t I, bool Stack>
|
||||
MKW_PPC_FORCE_INLINE void PPC_PsqStStateInline(uint32_t gqr, uint32_t addr, double value)
|
||||
@@ -1457,18 +1505,11 @@ 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); }
|
||||
return;
|
||||
default:
|
||||
PPC_PsqStStateFallback<W, Stack>(gqr, addr, value);
|
||||
PPC_PsqStStateFallback<W, I, Stack>(gqr, addr, value);
|
||||
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>
|
||||
MKW_PPC_FORCE_INLINE double PPC_PsqLResolvedStateInline(
|
||||
uint32_t gqr, uint8_t* resolvedHost, uint32_t offset, uint32_t addr)
|
||||
@@ -1476,41 +1517,33 @@ MKW_PPC_FORCE_INLINE double PPC_PsqLResolvedStateInline(
|
||||
static_assert(W <= 1u && I < 8u);
|
||||
if (!resolvedHost) [[unlikely]] return PPC_PsqLStateInline<W, I, false>(gqr, addr);
|
||||
const uint32_t type = (gqr >> 16) & 0x7u;
|
||||
if (type == 0u) {
|
||||
if constexpr (W == 0u) return PpcLoadPairPsqFloatResolvedInline(resolvedHost, offset, addr);
|
||||
else return PpcLoadSinglePsqFloatResolvedInline(resolvedHost, offset, addr);
|
||||
}
|
||||
const uint32_t scale = (gqr >> 24) & 0x3Fu;
|
||||
if constexpr (W == 0u)
|
||||
{
|
||||
switch (gqr & 0x3F070000u)
|
||||
switch (type)
|
||||
{
|
||||
case 0x00040000u: return PpcLoadPairPsqIntegerResolvedInline<uint8_t>(resolvedHost, offset, addr, 0u);
|
||||
case 0x00050000u: return PpcLoadPairPsqIntegerResolvedInline<uint16_t>(resolvedHost, offset, addr, 0u);
|
||||
case 0x00060000u: return PpcLoadPairPsqIntegerResolvedInline<int8_t>(resolvedHost, offset, addr, 0u);
|
||||
case 0x00070000u: return PpcLoadPairPsqIntegerResolvedInline<int16_t>(resolvedHost, offset, addr, 0u);
|
||||
default: return PPC_PsqLResolvedStateFallback<W>(gqr, resolvedHost, offset, addr);
|
||||
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 (gqr & 0x3F070000u)
|
||||
switch (type)
|
||||
{
|
||||
case 0x00040000u: return PpcLoadSinglePsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, 0u);
|
||||
case 0x00050000u: return PpcLoadSinglePsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, 0u);
|
||||
case 0x00060000u: return PpcLoadSinglePsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, 0u);
|
||||
case 0x00070000u: return PpcLoadSinglePsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, 0u);
|
||||
default: return PPC_PsqLResolvedStateFallback<W>(gqr, resolvedHost, offset, addr);
|
||||
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);
|
||||
|
||||
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>
|
||||
MKW_PPC_FORCE_INLINE void PPC_PsqStResolvedStateInline(
|
||||
uint32_t gqr, uint8_t* resolvedHost, uint32_t offset, uint32_t addr, double value)
|
||||
@@ -1522,32 +1555,29 @@ MKW_PPC_FORCE_INLINE void PPC_PsqStResolvedStateInline(
|
||||
return;
|
||||
}
|
||||
const uint32_t type = gqr & 0x7u;
|
||||
if (type == 0u) {
|
||||
if constexpr (W == 0u) PpcStorePairPsqFloatResolvedInline(resolvedHost, offset, addr, value);
|
||||
else PpcStoreSinglePsqFloatResolvedInline(resolvedHost, offset, addr, value);
|
||||
return;
|
||||
}
|
||||
const uint32_t scale = (gqr >> 8) & 0x3Fu;
|
||||
if constexpr (W == 0u)
|
||||
{
|
||||
switch (gqr & 0x3F07u)
|
||||
switch (type)
|
||||
{
|
||||
case 0x3D04u: PpcStorePairPsqU8Scale61ResolvedInline(resolvedHost, offset, addr, value); return;
|
||||
case 4u: PpcStorePairPsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, value, 0u); return;
|
||||
case 5u: PpcStorePairPsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, value, 0u); return;
|
||||
case 6u: PpcStorePairPsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, value, 0u); return;
|
||||
case 7u: PpcStorePairPsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, value, 0u); return;
|
||||
default: PPC_PsqStResolvedStateFallback<W>(gqr, resolvedHost, offset, addr, value); return;
|
||||
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 (gqr & 0x3F07u)
|
||||
switch (type)
|
||||
{
|
||||
case 4u: PpcStoreSinglePsqQuantizedResolvedInline<uint8_t>(resolvedHost, offset, addr, value, 0u); return;
|
||||
case 5u: PpcStoreSinglePsqQuantizedResolvedInline<uint16_t>(resolvedHost, offset, addr, value, 0u); return;
|
||||
case 6u: PpcStoreSinglePsqQuantizedResolvedInline<int8_t>(resolvedHost, offset, addr, value, 0u); return;
|
||||
case 7u: PpcStoreSinglePsqQuantizedResolvedInline<int16_t>(resolvedHost, offset, addr, value, 0u); return;
|
||||
default: PPC_PsqStResolvedStateFallback<W>(gqr, resolvedHost, offset, addr, value); return;
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,9 +132,8 @@ using CryptoEcdsa = CryptoPP::ECDSA<CryptoPP::EC2N, CryptoPP::SHA1>;
|
||||
|
||||
inline CryptoEcdsa::PrivateKey MakePrivateKey(const uint8_t* key) {
|
||||
CryptoPP::DL_GroupParameters_EC<CryptoPP::EC2N> parameters(CryptoPP::ASN1::sect233r1());
|
||||
// Wii keys need not be canonical scalars; reduction preserves their public key.
|
||||
const CryptoPP::Integer exponent = CryptoPP::Integer(key, 30) % parameters.GetSubgroupOrder();
|
||||
if (exponent == CryptoPP::Integer::Zero()) {
|
||||
const CryptoPP::Integer exponent(key, 30);
|
||||
if (exponent <= CryptoPP::Integer::Zero() || exponent >= parameters.GetSubgroupOrder()) {
|
||||
throw std::invalid_argument("Wii ES private key is outside the sect233r1 subgroup");
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
return w == 0 ? PPC_PsqLStateFallback<0u, false>(gqr, addr)
|
||||
: PPC_PsqLStateFallback<1u, false>(gqr, addr);
|
||||
return w == 0 ? PPC_PsqLStateFallback<0u, 0u, false>(gqr, addr)
|
||||
: PPC_PsqLStateFallback<1u, 0u, false>(gqr, addr);
|
||||
}
|
||||
|
||||
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];
|
||||
if (w == 0)
|
||||
{
|
||||
PPC_PsqStStateFallback<0u, false>(gqr, addr, value);
|
||||
PPC_PsqStStateFallback<0u, 0u, false>(gqr, addr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
PPC_PsqStStateFallback<1u, false>(gqr, addr, value);
|
||||
PPC_PsqStStateFallback<1u, 0u, false>(gqr, addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
#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);
|
||||
@@ -1,140 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
#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
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
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()
|
||||
@@ -18,7 +18,7 @@ entry point, decodes every reachable function, and emits C++ (plus JSON metadata
|
||||
what was emitted).
|
||||
|
||||
2. **`generate-data-init --project <manifest>`** - writes the embedded `.data`/`.rodata`/`.sdata`
|
||||
section initializer and `RuntimeConfig.h`.
|
||||
section initializer and `RuntimeConfig.h`.
|
||||
|
||||
3. **`emit-build-shards --project <manifest>`** - emits the CMake build graph (`shards.cmake`)
|
||||
covering both generated sources and `runtime/src`.
|
||||
@@ -36,7 +36,7 @@ See `projects/examples/generic-dol.yml` for a minimal manifest driven by `RECOMP
|
||||
| Tool | Notes |
|
||||
| --- | --- |
|
||||
| .NET 8 SDK | Builds and runs the translator. |
|
||||
| CMake ≥ 3.25 and Ninja | Configures and drives the native build. |
|
||||
| CMake ≥ 3.16 and Ninja | Configures and drives the native build. |
|
||||
| Clang / LLVM | The shipped build uses LLVM-MinGW targeting `x86-64-v3`. MSVC is not the tested path. |
|
||||
|
||||
Build the CLI once and invoke the assembly directly:
|
||||
|
||||
@@ -15,7 +15,6 @@ internal static class TranslatorCppTestHarness
|
||||
Path.Combine("runtime", "src", "fpu_helpers.cpp"),
|
||||
Path.Combine("runtime", "src", "memory.cpp"),
|
||||
Path.Combine("runtime", "src", "ppc_helpers.cpp"),
|
||||
Path.Combine("runtime", "src", "ppc_quantized.cpp"),
|
||||
};
|
||||
|
||||
public static string BuildCompileArguments(
|
||||
@@ -32,7 +31,6 @@ internal static class TranslatorCppTestHarness
|
||||
args.Append("-std=c++17 ");
|
||||
args.Append("-D_CRT_SECURE_NO_WARNINGS ");
|
||||
args.Append("-march=x86-64-v3 ");
|
||||
args.Append("-fno-fast-math -ffp-contract=off ");
|
||||
if (!RuntimeHeadersDefineRestrictMacro(repoRoot))
|
||||
{
|
||||
// Fallback for the window between an emitter change using MKW_RESTRICT and the runtime
|
||||
|
||||
Reference in New Issue
Block a user