summaryrefslogtreecommitdiff
path: root/sys/src/libc/386
AgeCommit message (Collapse)Author
2022-12-30libc: fix 32-bit arch vlong->double conversion (thans cosa)cinap_lenrek
Cosa wrote: While trying to run kvik's lu9 on ARM, I found that when converting LLONG_MIN to a double on 32bit systems, the result is wrong (positive instead of negative). Given the following test program: void main() { vlong min = LLONG_MIN; double dmin = min; print("minint %lld\n", min); print("minint as double %f\n", dmin); if (dmin > 0.0) { exits("int min as double turned positive"); } exits(0); } The output on x86_64 will be: minint -9223372036854775808 minint as double -9223372036854776400.000000 But on arm or 386 (and I expect also spim, 68000, mips, 68020, sparc, power, since they all use the same _v2d): minint -9223372036854775808 minint as double 9223372036854776400.000000 And the value turned positive in the conversion. The function used for the cast to double is (in /sys/src/libc/arm/vlrt.c): double _v2d(Vlong x) { if(x.hi & SIGN(32)) { if(x.lo) { x.lo = -x.lo; x.hi = ~x.hi; } else x.hi = -x.hi; return -((long)x.hi*4294967296. + x.lo); } return (long)x.hi*4294967296. + x.lo; } If I understand correctly, the issue is that where it tries to flip the sign for x.hi (x.hi = -x.hi), 0x80000000 has no positive, thus stays the same (it stays negative). Then when we get to the negative return, we get a positive out. What came to my mind then, is that in the case that there is no x.lo, we can keep the x.hi sign and cast directly, thus: double _v2d(Vlong x) {     if(!x.lo) {         return (long)x.hi*4294967296.;     }     if(x.hi & SIGN(32)) {         x.lo = -x.lo;         x.hi = ~x.hi;         return -((long)x.hi*4294967296. + x.lo);     }     return (long)x.hi*4294967296. + x.lo; } This looks correct to me, but I don't trust myself to not make mistakes in such critical code, so I would like some feedback on the change. Happy new year in advance, cosa
2016-03-19libc: trailing whitespace cleanupBurnZeZ
2015-10-04libc: add _uv2d()/uv2f() and _vas*d() functions to vlrt.ccinap_lenrek
on 32 bit archs, implement 64 bit vasop with floatingpoint right hand side. also added is uvlong->double conversion function.
2014-02-17prof: properly save and restore RARG for amd64cinap_lenrek
amd64 passes first argument in RARG (BP) register which has the be preserved duing _profin() and _profout() calls. to handle this we introduce _saveret() and _savearg(). _saveret() returns AX, _savearg() returns RARG (BP). for archs other and amd64, _saveret() and _savearg() are the same function, doing nothing. restoing works with dummy function: uintptr _restore(uintptr, uintptr ret) { return ret; } ... ret = _saveret(); arg = _savearg(); ... return _restore(arg, ret); as we pass arg as the first argument, RARG (BP) is restored.
2011-03-30Import sources from 2011-03-30 iso image - libTaru Karttunen
2011-03-30Import sources from 2011-03-30 iso imageTaru Karttunen