ptitSeb / box64

Box64 - Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices
https://box86.org
MIT License
3.9k stars 287 forks source link

[RV64_DYNAREC] Clear high 32bits when write back as single #1684

Closed ksco closed 4 months ago

ksco commented 4 months ago

We cannot use FSD here, because RISC-V uses Nan-boxing on single precision floating point values, so if some freg holds a float value, the high 32bits will be all 1s.

ptitSeb commented 4 months ago

We cannot use FSD here, because RISC-V uses Nan-boxing on single precision floating point values, so if some freg holds a float value, the high 32bits will be all 1s.

Not sure I understand. Nan-boxing is the abality to pass a "workload" inside a NAN (fill the mantissa with a speicifc value), and get this value carried away accross operations... What you discribe looks more like the typical sign extension of a 32bits, extended to 64bits, wich might happens with negative values, or x86 NaN (that are negative).

No issue with the code, tho.

ksco commented 4 months ago

It's not a sign extension thing. anyway, the spec explains it well, pasted below:

12.2
 NaN Boxing of Narrower Values
When multiple floating-point precisions are supported, then valid values of narrower n-bit types,
n < FLEN, are represented in the lower n bits of an FLEN-bit NaN value, in a process termed
NaN-boxing. The upper bits of a valid NaN-boxed value must be all 1s. Valid NaN-boxed n-bit
values therefore appear as negative quiet NaNs (qNaNs) when viewed as any wider m-bit value,
n < m ≤ FLEN. Any operation that writes a narrower result to an f register must write all 1s to
the uppermost FLEN−n bits to yield a legal NaN-boxed value.
ptitSeb commented 4 months ago

It's not a sign extension thing. anyway, the spec explains it well, pasted below:

12.2
 NaN Boxing of Narrower Values
When multiple floating-point precisions are supported, then valid values of narrower n-bit types,
n < FLEN, are represented in the lower n bits of an FLEN-bit NaN value, in a process termed
NaN-boxing. The upper bits of a valid NaN-boxed value must be all 1s. Valid NaN-boxed n-bit
values therefore appear as negative quiet NaNs (qNaNs) when viewed as any wider m-bit value,
n < m ≤ FLEN. Any operation that writes a narrower result to an f register must write all 1s to
the uppermost FLEN−n bits to yield a legal NaN-boxed value.

Well, it's still some kind of sign extension, at least, the 32bits upper is filled with 1, like a sign extension, but has a ### "NAN" extension.... Anyway, we don't really care here, we just write using FSW, so no issue, also, I think it's only relevent for 32bits->64bits conversions, it makes no sense for 64bits->32bits conversion

Also also, the upper part is untouched, including the 32-63 interval that might contains upper part of the old 64bits SD value:

CVTSD2SS (128-bit Legacy SSE Version)[ ¶](https://www.felixcloutier.com/x86/cvtsd2ss#cvtsd2ss--128-bit-legacy-sse-version-)
DEST[31:0] := Convert_Double_Precision_To_Single_Precision_Floating_Point(SRC[63:0]);
(* DEST[MAXVL-1:32] Unmodified *)
ksco commented 4 months ago

yeah, I'm working on that.