From aba52f32b01212a7226dfcbeee9b00387591598e Mon Sep 17 00:00:00 2001 From: Mihawk <163614687+mihawk-99@users.noreply.github.com> Date: Thu, 8 Oct 2026 19:30:16 -0400 Subject: [PATCH] host: preserve IEEE denormal assumptions in compiler wrappers --- host/bin/prospero-clang | 1 + host/bin/prospero-clang++ | 1 + samples/test_denormals/Makefile | 48 +++++++++++++++++++++++++++++++ samples/test_denormals/classify.c | 11 +++++++ samples/test_denormals/main.c | 24 ++++++++++++++++ 5 files changed, 85 insertions(+) create mode 100644 samples/test_denormals/Makefile create mode 100644 samples/test_denormals/classify.c create mode 100644 samples/test_denormals/main.c diff --git a/host/bin/prospero-clang b/host/bin/prospero-clang index 0f91935a..38d79de9 100755 --- a/host/bin/prospero-clang +++ b/host/bin/prospero-clang @@ -75,6 +75,7 @@ exec -a "${SCRIPT_NAME}" "${SCRIPT_DIR}/clang" \ -L "${PS5_PAYLOAD_SDK}/target/lib" \ -L "${PS5_PAYLOAD_HBROOT}/lib" \ -fno-stack-protector -fno-plt -femulated-tls \ + -fdenormal-fp-math=ieee \ $LIBS_C \ --end-no-unused-arguments \ "$@" \ diff --git a/host/bin/prospero-clang++ b/host/bin/prospero-clang++ index 9b698cf0..0ee8a057 100755 --- a/host/bin/prospero-clang++ +++ b/host/bin/prospero-clang++ @@ -80,6 +80,7 @@ exec -a "${SCRIPT_NAME}" "${SCRIPT_DIR}/clang++" \ -L "${PS5_PAYLOAD_SDK}/target/lib" \ -L "${PS5_PAYLOAD_HBROOT}/lib" \ -fno-stack-protector -fno-plt -femulated-tls \ + -fdenormal-fp-math=ieee \ -frtti -fexceptions \ $LIBS_CXX $LIBS_C \ --end-no-unused-arguments \ diff --git a/samples/test_denormals/Makefile b/samples/test_denormals/Makefile new file mode 100644 index 00000000..ab2a2b9e --- /dev/null +++ b/samples/test_denormals/Makefile @@ -0,0 +1,48 @@ +# Copyright (C) 2023 John Törnblom +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not see +# . + +PS5_HOST ?= ps5 +PS5_PORT ?= 9021 + +ifdef PS5_PAYLOAD_SDK + include $(PS5_PAYLOAD_SDK)/toolchain/prospero.mk +else + $(error PS5_PAYLOAD_SDK is undefined) +endif + +ELF := test_denormals.elf + +CFLAGS := -Wall -Werror -g -O2 + +all: $(ELF) + +$(ELF): main.c classify.c + $(CC) $(CFLAGS) -o $@ $^ + +clean: + rm -f $(ELF) + +test: $(ELF) + $(PS5_DEPLOY) -h $(PS5_HOST) -p $(PS5_PORT) $^ + +debug: $(ELF) + gdb-multiarch \ + -ex "set architecture i386:x86-64" \ + -ex "target extended-remote $(PS5_HOST):2159" \ + -ex "file $(ELF)" \ + -ex "remote put $(ELF) /data/$(ELF)" \ + -ex "set remote exec-file /data/$(ELF)" \ + -ex "start" diff --git a/samples/test_denormals/classify.c b/samples/test_denormals/classify.c new file mode 100644 index 00000000..12c6f175 --- /dev/null +++ b/samples/test_denormals/classify.c @@ -0,0 +1,11 @@ +/* Copyright (C) 2026 Mihawk + * SPDX-License-Identifier: GPL-3.0-or-later + */ +#include + +/* A separate translation unit prevents constant folding at the call site. */ +int +classify(float value) { + return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, value); +} diff --git a/samples/test_denormals/main.c b/samples/test_denormals/main.c new file mode 100644 index 00000000..fe521cd1 --- /dev/null +++ b/samples/test_denormals/main.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2026 Mihawk + * SPDX-License-Identifier: GPL-3.0-or-later + */ +#include +#include +#include +#include + +int classify(float value); + +int +main(void) { + unsigned previous, ieee; + uint32_t bits = 1; /* Smallest positive IEEE binary32 subnormal. */ + float value; + memcpy(&value, &bits, sizeof(value)); + __asm__ volatile("stmxcsr %0" : "=m"(previous)); + ieee = previous & ~0x8040u; /* Disable FTZ and DAZ for this test. */ + __asm__ volatile("ldmxcsr %0" : : "m"(ieee) : "memory"); + const int actual = classify(value); + __asm__ volatile("ldmxcsr %0" : : "m"(previous) : "memory"); + printf("classification=%d, expected FP_SUBNORMAL=%d\n", actual, FP_SUBNORMAL); + return actual != FP_SUBNORMAL; +}