Hello everybody

I've done a bit more investigating. I did a VAX-floating point build, 
and it failed in t/op/pack test 39 as well, this time with the exception
code 0000000000000504 %SYSTEM-F-HPARITH, high performance arithmetic 
trap

and not 00000000000005B4 %SYSTEM-F-ILLEGAL_SHADOW, illegal formed trap 
shadow.

t/op/pack test 39 looks as follows 
(pack.t line 180ff, it even wonders whether this makes sense on VMS):

 SKIP: {
    # Is this a stupid thing to do on VMS, VOS and other unusual platforms?
    my $inf = eval '2**10000';

    skip "Couldn't generate infinity - got error '$@'"
      unless defined $inf and $inf == $inf / 2 and $inf + 1 == $inf;

    eval { $x = pack 'w', $inf };
    like ($@, qr/^Cannot compress integer/);
  }

The line, which crashes is 

    eval { $x = pack 'w', $inf };

If I add a simple print statement to output $inf, something like

    print "\$inf = <$inf>\n";

immediately before the 'eval', the crash no longer occurs. This seems to
indicate, that the act of printing the value must somehow change it! On 
the other hand, we are working with infinity, so strange things are
perhaps to be expected. I get the following output:

ok 38
$inf = <Infinity>
not ok 39
# Failed at [.op]pack_jesper.t line 190
#      got 'Can only compress unsigned integers at [.op]pack_jesper.t 
line 189.
# '
# expected /(?-xism:^Cannot compress integer)/

Further investigation shows, that the crash (in the original pack.t, without the 
print) happens in line 2320 of PP_PACK.C, this is where it says

          *--in = (unsigned char)(anv - (next * 128)) | 0x80;

'anv' and 'next' are both NV's (double), 'in' is a char *

I broke up the statement into its individual parts, to find out where it 
fails:

                    printf("PACK test 1\n");
                    ccnt = 1;
      do {
   NV next = Perl_floor(anv / 128);
                        NV t1, t2;
                        unsigned char c1;
                        printf("PACK test loop %d anv %e next %e\n",
                               ccnt,anv,next);
                        DumpBytes( "anv", (unsigned char *)&anv, 8 );
                        DumpBytes( "next", (unsigned char *)&next, 8 );
                        ccnt++;
   if (in <= buf)  /* this cannot happen ;-) */
       Perl_croak(aTHX_ "Cannot compress integer");
                        t1 = next*128;
                        DumpBytes("t1", (unsigned char *)&t1, 8);
                        t2 = anv-t1;
                        DumpBytes("t2", (unsigned char *)&t2, 8);
                        c1 = (unsigned char)t2;
                        printf("c1 %02X\n", c1);
                        c1 = c1 | 0x80;
                        *--in = c1;
/**************
   *--in = (unsigned char)(anv - (next * 128)) | 0x80;
***************/
   anv = next;
      } while (anv > 0);
                    printf("PACK test 2\n");


where DumpBytes is declared as:

void DumpBytes( char *txt, unsigned char *buf, int len )
{
   int i;
   printf("%s %08X:", txt, buf);
   for (i = 0; i < len; i++) {
      printf(" %02X", buf[i]);
   }
   printf("\n");
}

I get the following:

PACK test 1
PACK test loop 1 anv Infinity next Infinity
anv 7AFB94F0: 00 00 00 00 00 00 F0 7F
next 7AFB9560: 00 00 00 00 00 00 F0 7F
t1 7AFB9558: 00 00 00 00 00 00 F0 7F
t2 7AFB9550: 00 00 00 00 00 00 F8 FF
%DEBUG-I-DYNMODSET, setting module PP_PACK
%SYSTEM-F-ILLEGAL_SHADOW, illegal formed trap shadow, Imask=00000000, 
Fmask=0000
0002, summary=03, PC=000000000015CBF4, PS=0000001B
break on unhandled exception preceding PP_PACK\Perl_pack_cat\%LINE 
47230+8
 47230:                         c1 = (unsigned char)t2;

which clearly indicates, that it is the conversion of a 
double (t2) with a questionable value (00 00 00 00 00 00 F8 FF) 
into an unsigned char, which causes the 
trouble.

t2 is the result of subtracting t1 (00 00 00 00 00 00 F0 7F) from
anv (00 00 00 00 00 00 F0 7F). If we assume, that this bit pattern 
represents IEEE floating point Infinity (I haven't checked, maybe I 
should), we should also wonder whether IEEE specifies what the result of 
Infinity minus Infinity should be.

When you think about it, the entire calculation also sounds weird:

Take Infinity (next), multiply by 128, subtract that from Infinity (anv)

After having worked with this now for quite some time, I still have not 
quite understood, what pack.t test 39 is trying to test or achieve. Does 
it make sense at all to run it under VMS?

Another thing, slightly OT: The Alpha Architecture Handbook can be 
downloaded from:

http://www.support.compaq.com/alpha-tools/documentation/current/chip-docs.html#library

On page 293 it describes what 'software completion' is all about. It 
has to do with certain floating point operations, which hardware may not 
be able to complete. In such cases, hardware can raise an exception, and the 
operating system must then be prepared to complete the operation in 
software. It's interesting but quite complicated, and I don't know 
whether it will help us here.


    Best regards
    Jesper Naur

Reply via email to