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,

Thomas
diff --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);

Reply via email to