Forums » Programming with the ECS » Intermediate Code »
Behaviour of conv
Added by Rochus Keller about 1 year ago
What is the officially expected behaviour when converting a float to an int value?
From the description in the 0.0.41 manual, I can't say if it would truncate or round.
When I compile and run the attached program with 0.0.40, the literal to int assignments in float_convert1 are truncated, but the float to int register conversions in float_convert2 and double_convert) are apparently rounded.
When I compile and run the probram with 0.0.41, all conversions seem to truncate (what I would expect).
Replies (11)
RE: Behaviour of conv - Added by Rochus Keller about 1 year ago
Ok, I see.
I should mention that I used the x86 version of 0.0.40 and the arm64 version of 0.0.41.
Since I assumed that this again is an issue which was fixed from 0.0.40 to 0.0.41, I now updated all used ECS files of my branch to version 0.0.41.
But I still get rounded instead of truncated values (i.e. both a and b in float_convert2 and double_convert become 3)!
I already attached the source in the above comment; here also the generated cod file.
Is this possibly a machine code generator issue, or am I doing something wrong?
convert.cod (9.88 KB) convert.cod |
RE: Behaviour of conv - Added by Florian Negele about 1 year ago
Are you using the legacy FPU or media-float instructions?
RE: Behaviour of conv - Added by Rochus Keller about 1 year ago
I'm using media-float, i.e. in compiler.cpp I set:
#elif defined AMD32BACKEND #include "amd64.hpp" #include "amd64generator.hpp" #define NAMESUFFIX "amd32" static AMD64::Generator generator {diagnostics, stringPool, charset, AMD64::ProtectedMode, true, true};
didn't try yet with the legacy FPU yet; shall I try it?
RE: Behaviour of conv - Added by Florian Negele about 1 year ago
It should work with the legacy FPU which is why I wasn't able to reproduce the problem. Appearently, the media-float instructions require initialisation of the rounding modes as well. The attached patch fixes this oversight for the 64-bit mode. You might have to adapt the code for your specialised 32-bit case. Thanks for reporting.
RE: Behaviour of conv - Added by Rochus Keller about 1 year ago
Thanks for the patch. I applied it to my version of runtime.c and repeated the test with convert.c, but the result is the same (2.7 "truncates" to 3).
Meanwhile I also tried with
AMD64::Generator generator {diagnostics, stringPool, charset, AMD64::ProtectedMode, false, true};
which indeed works correctly, but as we found out it's about factor 10 slower, so I would prefer the "media-float" version.
You might have to adapt the code for your specialised 32-bit case.
What do you mean by that? I have very little experience with i386 nor "media-float".
RE: Behaviour of conv - Added by Florian Negele about 1 year ago
Replace the inline assembler for the 32-bit case with this code:
.initdata _init_fpu .required push dword 00'0111'1111'1000'0000b ldmxcsr dword [esp] pop eax
RE: Behaviour of conv - Added by Rochus Keller about 1 year ago
That's the solution, great, thank you very much!
RE: Behaviour of conv - Added by Florian Negele about 1 year ago
Please note that the generated floating-point conversion to and from unsigned integers don't behave properly in 32-bit mode.
RE: Behaviour of conv - Added by Rochus Keller about 1 year ago
In what respect? I didn's see an issue with unsigned ints for the positive cases in convert.c.
RE: Behaviour of conv - Added by Florian Negele about 1 year ago
Unsigned integer values are basically treated as signed integers during floating-point conversions. There is no problem as long as their representations match.