Le jeudi 17 janvier 2013 15:40:31, vous avez écrit :
> Package: tcc
> Version: 0.9.26~git20120612.ad5f375-6
> Severity: normal
Hi Vincent,
sorry for answering so late.
>
> TCC doesn't set the FE_INVALID flag on comparison with NAN (<=, >=, <, >),
> at least on amd64, e.g. with:
>
> #include <stdio.h>
> #include <math.h>
> #include <fenv.h>
>
> #pragma STDC FENV_ACCESS ON
>
> int main (void)
> {
> double d = NAN;
> volatile double v = NAN;
> int err = 0;
>
> feclearexcept (FE_INVALID);
> if (d <= 0.0)
> {
> printf ("NAN comparison is wrong (1)\n");
> err = 1;
> }
> if (! fetestexcept(FE_INVALID))
> {
> printf ("The FE_INVALID flag is not set (1)\n");
> err = 1;
> }
>
> feclearexcept (FE_INVALID);
> if (v <= 0.0)
> {
> printf ("NAN comparison is wrong (2)\n");
> err = 1;
> }
> if (! fetestexcept(FE_INVALID))
> {
> printf ("The FE_INVALID flag is not set (2)\n");
> err = 1;
> }
>
> feclearexcept (FE_INVALID);
> v <= 0.0;
> if (! fetestexcept(FE_INVALID))
> {
> printf ("The FE_INVALID flag is not set (3)\n");
> err = 1;
> }
>
> return err;
> }
>
> I get:
>
> $ tcc nancmp.c -o nancmp -lm
> $ ./nancmp
> The FE_INVALID flag is not set (1)
> The FE_INVALID flag is not set (2)
> The FE_INVALID flag is not set (3)
>
> Like GCC (which is affected by the same bug), the problem is that
> tcc uses ucomisd instead of comisd for <=, >=, <, >.
>
This seems like an easy bug to fix, especially with the precise information you
gave as to the reason. Unfortunately I don't have any x86 machine to test the
fix, would you mind compiling upstream tcc on your own with the attached patch
applied?
Best regards,
Thomasdiff --git a/i386-gen.c b/i386-gen.c
index b26b844..5f0c0f4 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -895,7 +895,7 @@ ST_FUNC void gen_opf(int op)
swapped = 0;
if (swapped)
o(0xc9d9); /* fxch %st(1) */
- o(0xe9da); /* fucompp */
+ o(0xd9de); /* fcompp */
o(0xe0df); /* fnstsw %ax */
if (op == TOK_EQ) {
o(0x45e480); /* and $0x45, %ah */
diff --git a/x86_64-gen.c b/x86_64-gen.c
index 0962056..dc2ced1 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -1792,7 +1792,7 @@ void gen_opf(int op)
swapped = 0;
if (swapped)
o(0xc9d9); /* fxch %st(1) */
- o(0xe9da); /* fucompp */
+ o(0xd9de); /* fcompp */
o(0xe0df); /* fnstsw %ax */
if (op == TOK_EQ) {
o(0x45e480); /* and $0x45, %ah */
@@ -1876,7 +1876,7 @@ void gen_opf(int op)
if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
o(0x66);
- o(0x2e0f); /* ucomisd */
+ o(0x2f0f); /* comisd */
if (vtop->r & VT_LVAL) {
gen_modrm(vtop[-1].r, r, vtop->sym, fc);