ibmruntimes / v8ppc

Port of Google V8 javascript engine to PowerPC®
Other
94 stars 20 forks source link

PowerMac G4 hitting illegal instruction #97

Open andrewlow opened 10 years ago

andrewlow commented 10 years ago

The following hits an illegal instruction

./out/ppc.debug/d8  --allow-natives-syntax ./test/mjsunit/mjsunit.js ./test/mjsunit/regress/regress-sqrt.js

Seems to be a problem with fsqrt

Program received signal SIGILL, Illegal instruction.
0x4e943b28 in ?? ()
(gdb) x/20i $pc
=> 0x4e943b28:  fsqrt   f1,f1
tunniclm commented 10 years ago

The instructions the G4 processor does not implement are described in the manual http://www.freescale.com/files/32bit/doc/ref_manual/MPC7410UM.pdf

Of these, our 32-bit build uses: fsqrt, fcfid

tio00 commented 10 years ago

Hi all,

Noob here. I'm continuing from this thread: https://groups.google.com/forum/#!topic/nodejs/ivGMr-C_m1Y

As mentioned there, I have a Titanium Powerbook G4 with Linux MintPPC 11 set up with the code and have also identified some fcfid calls. I would like to help with this, and at this point I'm wondering what the accepted method is to add exceptions for the G4.

Since I snagged the fcfid instruction first, and after some googling, I was wondering if fctiw would be a place to start.

Anyway any pointers on doing this the correct way would be great, Thanks!

andrewlow commented 10 years ago

@Mike - as you've got some in progress changes to support the G4 just go ahead and make a branch in this repo. We can merge once you've for the bugs worked out.

tunniclm commented 10 years ago

I have added the branch g4compat

andrewlow commented 10 years ago

I spent a bit of time today looking at the v8 build on a G4 running Ubuntu. There are only 3 failures in the test suite run and all 3 are related to Math.sqrt(0.01);

$ ./out/ppc.debug/d8
V8 version 3.14.5 (candidate) [console: dumb]
d8> Math.sqrt(0.01)
0.09999999999999999
d8>

Writing a simple C program:

main()
{
printf("%f\n", sqrt(0.01));
}

proves that the basic math library is sane, so I'm guessing the issue is around conversion of then number / rounding - but I haven't put my finger on the exact problem yet.

Given that Mike was 'hacking' in the branch https://github.com/andrewlow/v8ppc/tree/g4compat there might be a bit of work to merge this without breaking things.

tunniclm commented 10 years ago

@andrewlow Be careful that printf() isn't rounding the answer in your C program. Try this to check:

#include <math.h>
#include <stdio.h>
main() {
  printf("sqrt(0.01)=%a\n", sqrt(0.01));
  printf("0.1=%a\n", 0.1);
  printf("sqrt(0.01)%s0.1\n", 0.1==sqrt(0.01) ? "==" : "!=");
}

Here we can compare the precise hexadecimal representation of 0.1 and sqrt(0.01) and see by eye any difference. This is actually not so easy to do (particularly with confidence) when using a decimal representation.

andrewlow commented 10 years ago

@tunniclm good point

One of our Power7 Linux machines

$ ./a.out
sqrt(0.01)=0x1.999999999999ap-4
0.1=0x1.999999999999ap-4
sqrt(0.01)==0.1

The G4

$ ./a.out
sqrt(0.01)=0x1.999999999999ap-4
0.1=0x1.999999999999ap-4
sqrt(0.01)==0.1
andrewlow commented 10 years ago

I've done more digging - I think the C program is mis-leading us.

In JS the Math.sqrt() calls maps down to a call v8::internal::fast_sqrt, which in turn is a call to the C library sqrt().

On Power7 the object that comes back has this hex value for the double:

0x3fb99999      0x9999999a

on the G4

0x3fb99999      0x99999999

I'm starting to wonder if we've left the FPSCR state in the wrong mode? Power7

fpscr          0xa6064100

G4

fpscr          0xa6024100 

It appears the difference between the two registers is the FR bit ( "Floating-point fraction rounded. The last arithmetic or rounding and conversion instruction that rounded the intermediate result incremented the fraction." ) This makes sense as the Power7 result has been rounded and the FR bit is set appropriately.

I think this is proof the C math library is giving us an unexpected answer, looking at the state of FPSCR prior to making the call to the C math library, we're using the same RN (rounding mode) of 00. (round to nearest)

andrewlow commented 10 years ago

I modified the simple C program above to demonstrate the issue we're seeing. (don't forget to link the math library with -lm)

#include <math.h>
#include <stdio.h>
main() {
  double z = 0.01;
  double x;
  int *p = &x;
  x = sqrt(z);
  printf("%08x, %08x\n", p[0], p[1]);
  printf("sqrt(0.01)=%a constant\n", sqrt(0.01));
  printf("sqrt(0.01)=%a variable\n", sqrt(z));
  printf("0.1=%a\n", 0.1);
  printf("sqrt(0.01)%s0.1\n", 0.1==sqrt(0.01) ? "==" : "!=");
}

Power7

$ ./a.out
3fb99999, 9999999a
sqrt(0.01)=0x1.999999999999ap-4 constant
sqrt(0.01)=0x1.999999999999ap-4 variable
0.1=0x1.999999999999ap-4
sqrt(0.01)==0.1

G4

$ ./a.out
3fb99999, 99999999
sqrt(0.01)=0x1.999999999999ap-4 constant
sqrt(0.01)=0x1.9999999999999p-4 variable
0.1=0x1.999999999999ap-4
sqrt(0.01)==0.1

When we pass in the 0.01 value in a double (as a variable) the G4 doesn't round it correctly (where correctly is defined as how the V8 tests expect it to work).