PCem

changeset 6:83ee72aa1453

Fixed value of TOP when using FSAVE/FRSTOR. Infinity and NaN should now be preserved when loading/storing 80-bit floating point.
author TomW
date Sun Jul 07 12:05:53 2013 +0100
parents fe9cf232a465
children 41678958f2e8
files src/x87.c
diffstat 1 files changed, 41 insertions(+), 21 deletions(-) [+]
line diff
     1.1 --- a/src/x87.c	Tue Jun 25 21:46:25 2013 +0100
     1.2 +++ b/src/x87.c	Sun Jul 07 12:05:53 2013 +0100
     1.3 @@ -158,16 +158,22 @@
     1.4  	test.eind.ll |= (uint64_t)readmeml(easeg,eaaddr+4)<<32;
     1.5  	test.begin = readmemw(easeg,eaaddr+8);
     1.6  
     1.7 -	int64_t exp64 = (((test.begin&0x7fff) - BIAS80));
     1.8 -	int64_t blah = ((exp64 >0)?exp64:-exp64)&0x3ff;
     1.9 -	int64_t exp64final = ((exp64 >0)?blah:-blah) +BIAS64;
    1.10 +       	int64_t exp64 = (((test.begin&0x7fff) - BIAS80));
    1.11 +       	int64_t blah = ((exp64 >0)?exp64:-exp64)&0x3ff;
    1.12 +       	int64_t exp64final = ((exp64 >0)?blah:-blah) +BIAS64;
    1.13  
    1.14 -	int64_t mant64 = (test.eind.ll >> 11) & (0xfffffffffffff);
    1.15 -	int64_t sign = (test.begin&0x8000)?1:0;
    1.16 +       	int64_t mant64 = (test.eind.ll >> 11) & (0xfffffffffffff);
    1.17 +       	int64_t sign = (test.begin&0x8000)?1:0;
    1.18  
    1.19 -        if (test.eind.ll&0x400) mant64++;
    1.20 -//        pclog("LD80 %08X %08X\n",test.eind.ll,mant64);
    1.21 -	test.eind.ll = (sign <<63)|(exp64final << 52)| mant64;
    1.22 +        if ((test.begin & 0x7fff) == 0x7fff)
    1.23 +                exp64final = 0x7ff;
    1.24 +        if ((test.begin & 0x7fff) == 0)
    1.25 +                exp64final = 0;
    1.26 +        if (test.eind.ll & 0x400) 
    1.27 +                mant64++;
    1.28 +
    1.29 +        test.eind.ll = (sign <<63)|(exp64final << 52)| mant64;
    1.30 +
    1.31  	return test.eind.d;
    1.32  }
    1.33  
    1.34 @@ -181,20 +187,29 @@
    1.35                          uint64_t ll;
    1.36                  } eind;
    1.37  	} test;
    1.38 +	
    1.39  	test.eind.d=d;
    1.40 -	int64_t sign80 = (test.eind.ll&(0x8000000000000000))?1:0;
    1.41 -	int64_t exp80 =  test.eind.ll&(0x7ff0000000000000);
    1.42 -	int64_t exp80final = (exp80>>52);
    1.43 -	int64_t mant80 = test.eind.ll&(0x000fffffffffffff);
    1.44 -	int64_t mant80final = (mant80 << 11);
    1.45 -	if(d != 0){ //Zero is a special case
    1.46 -		// Elvira wants the 8 and tcalc doesn't
    1.47 -		mant80final |= (0x8000000000000000);
    1.48 -		//Ca-cyber doesn't like this when result is zero.
    1.49 -		exp80final += (BIAS80 - BIAS64);
    1.50 -	}
    1.51 -	test.begin = (((int16_t)sign80)<<15)| (int16_t)exp80final;
    1.52 -	test.eind.ll = mant80final;
    1.53 +	
    1.54 +       	int64_t sign80 = (test.eind.ll&(0x8000000000000000))?1:0;
    1.55 +       	int64_t exp80 =  test.eind.ll&(0x7ff0000000000000);
    1.56 +       	int64_t exp80final = (exp80>>52);
    1.57 +       	int64_t mant80 = test.eind.ll&(0x000fffffffffffff);
    1.58 +       	int64_t mant80final = (mant80 << 11);
    1.59 +
    1.60 +       	if (exp80final == 0x7ff) /*Infinity / Nan*/
    1.61 +       	{
    1.62 +                exp80final = 0x7fff;
    1.63 +                mant80final |= (0x8000000000000000);
    1.64 +        }
    1.65 +       	else if (d != 0){ //Zero is a special case
    1.66 +       		// Elvira wants the 8 and tcalc doesn't
    1.67 +       		mant80final |= (0x8000000000000000);
    1.68 +       		//Ca-cyber doesn't like this when result is zero.
    1.69 +       		exp80final += (BIAS80 - BIAS64);
    1.70 +       	}
    1.71 +       	test.begin = (((int16_t)sign80)<<15)| (int16_t)exp80final;
    1.72 +       	test.eind.ll = mant80final;
    1.73 +
    1.74  	writememl(easeg,eaaddr,test.eind.ll);
    1.75  	writememl(easeg,eaaddr+4,test.eind.ll>>32);
    1.76  	writememw(easeg,eaaddr+8,test.begin);
    1.77 @@ -983,9 +998,14 @@
    1.78                          ST(6)=x87_ld80(); eaaddr+=10;
    1.79                          ST(7)=x87_ld80();
    1.80                          cycles-=(cr0&1)?34:44;
    1.81 +/*                        pclog("new TOP %i\n", TOP);
    1.82 +                        pclog("%04X %04X %04X  %f %f %f %f  %f %f %f %f\n", npxc, npxs, tag, ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7));*/
    1.83                          return;
    1.84                          case 6: /*FSAVE*/
    1.85                          if (fplog) pclog("FSAVE %08X:%08X\n", easeg, eaaddr);
    1.86 +                        npxs = (npxs & ~(7 << 11)) | (TOP << 11);
    1.87 +/*                        pclog("old TOP %i %04X\n", TOP, npxs);
    1.88 +                        pclog("%04X %04X %04X  %f %f %f %f  %f %f %f %f\n", npxc, npxs, tag, ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7));*/
    1.89                          switch ((cr0&1)|(op32&0x100))
    1.90                          {
    1.91                                  case 0x000: /*16-bit real mode*/