Skip to content

Commit e754df0

Browse files
committed
[INTERPRETER] Fixes some longdoub / double conversion cases (on nan/infinites/0.0) (backported from Box64)"
1 parent b9d565f commit e754df0

File tree

1 file changed

+39
-50
lines changed

1 file changed

+39
-50
lines changed

src/emu/x87emu_private.c

Lines changed: 39 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -77,53 +77,45 @@ void LD2D(void* ld, void* d)
7777
*(uint64_t*)d = *(uint64_t*)ld;
7878
return;
7979
}
80-
FPU_t result;
80+
FPU_t result;
8181
#pragma pack(push, 1)
82-
struct {
83-
FPU_t f;
84-
int16_t b;
85-
} val;
82+
struct {
83+
FPU_t f;
84+
int16_t b;
85+
} val;
8686
#pragma pack(pop)
8787
#if 1
8888
memcpy(&val, ld, 10);
8989
#else
90-
val.f.ud[0] = *(uint32_t*)ld;
90+
val.f.ud[0] = *(uint32_t*)ld;
9191
val.f.ud[1] = *(uint32_t*)(char*)(ld+4);
92-
val.b = *(int16_t*)((char*)ld+8);
92+
val.b = *(int16_t*)((char*)ld+8);
9393
#endif
94-
int32_t exp64 = (((uint32_t)(val.b&0x7fff) - BIAS80) + BIAS64);
95-
int32_t exp64final = exp64&0x7ff;
9694
// do specific value first (0, infinite...)
9795
// bit 63 is "integer part"
98-
// bit 62 is sign
9996
if((uint32_t)(val.b&0x7fff)==0x7fff) {
10097
// infinity and nans
101-
int t = 0; //nan
102-
switch((val.f.ud[1]>>30)) {
103-
case 0: if((val.f.ud[1]&(1<<29))==0) t = 1;
104-
break;
105-
case 2: if((val.f.ud[1]&(1<<29))==0) t = 1;
106-
break;
107-
}
98+
int t = (val.f.q&0x7fffffffffffffffLL)?0:1;
10899
if(t) { // infinite
109-
result.d = HUGE_VAL;
110-
} else { // NaN
111-
result.ud[1] = 0x7ff << 20;
100+
result.ud[1] = (val.b>>4) << 20;
112101
result.ud[0] = 0;
102+
} else { // NaN
103+
result.ud[1] = (val.b>>4) << 20 | ((val.f.q>>(63-20))&0x000fffff);
104+
result.ud[0] = (val.f.q>>(63-56))&0xffffffff;
105+
if(!(result.q&0x000fffffffffffffLL))
106+
result.q |= 1;
113107
}
114-
if(val.b&0x8000)
115-
result.ud[1] |= 0x80000000;
116108
*(uint64_t*)d = result.q;
117109
return;
118110
}
111+
int32_t exp64 = (((uint32_t)(val.b&0x7fff) - BIAS80) + BIAS64);
112+
int32_t exp64final = exp64&0x7ff;
119113
if(((uint32_t)(val.b&0x7fff)==0) || (exp64<-1074)) {
120-
//if(val.f.ll==0)
114+
//if(val.f.q==0)
121115
// zero
122-
//if(val.f.ll!=0)
116+
//if(val.f.q!=0)
123117
// denormal, but that's to small value for double
124-
uint64_t r = 0;
125-
if(val.b&0x8000)
126-
r |= 0x8000000000000000LL;
118+
uint64_t r = (val.b&0x8000)?0x8000000000000000LL:0LL;
127119
*(uint64_t*)d = r;
128120
return;
129121
}
@@ -149,12 +141,12 @@ void LD2D(void* ld, void* d)
149141
return;
150142
}
151143

152-
uint64_t mant64 = (val.f.q >> 11) & 0xfffffffffffffLL;
153-
uint32_t sign = (val.b&0x8000)?1:0;
144+
uint64_t mant64 = (val.f.q >> 11) & 0xfffffffffffffL;
145+
uint32_t sign = (val.b&0x8000)?1:0;
154146
result.q = mant64;
155-
result.ud[1] |= (sign <<31)|((exp64final&0x7ff) << 20);
147+
result.ud[1] |= (sign <<31)|((exp64final&0x7ff) << 20);
156148

157-
*(uint64_t*)d = result.q;
149+
*(uint64_t*)d = result.q;
158150
}
159151

160152
// double (64bits) -> long double (80bits)
@@ -165,40 +157,37 @@ void D2LD(void* d, void* ld)
165157
return;
166158
}
167159
#pragma pack(push, 1)
168-
struct {
169-
FPU_t f;
170-
int16_t b;
171-
} val;
160+
struct {
161+
FPU_t f;
162+
int16_t b;
163+
} val;
172164
#pragma pack(pop)
173165
FPU_t s;
174166
s.q = *(uint64_t*)d; // use memcpy to avoid risk of Bus Error?
175167
// do special value first
176-
if((s.q&0x7fffffffffffffffLL)==0) {
168+
if((s.q&0x7fffffffffffffffL)==0) {
177169
// zero...
178170
val.f.q = 0;
179-
if(s.ud[1]&0x8000)
180-
val.b = 0x8000;
181-
else
182-
val.b = 0;
171+
val.b = (s.ud[1]&0x80000000)?0x8000:0;
183172
memcpy(ld, &val, 10);
184173
return;
185174
}
186175

187-
int32_t sign80 = (s.ud[1]&0x80000000)?1:0;
188-
int32_t exp80 = s.ud[1]&0x7ff00000;
189-
int32_t exp80final = (exp80>>20);
190-
int64_t mant80 = s.sq&0x000fffffffffffffLL;
191-
int64_t mant80final = (mant80 << 11);
176+
int32_t sign80 = (s.ud[1]&0x80000000)?1:0;
177+
int32_t exp80 = s.ud[1]&0x7ff00000;
178+
int32_t exp80final = (exp80>>20);
179+
uint64_t mant80 = s.q&0x000fffffffffffffL;
180+
uint64_t mant80final = (mant80 << 11);
192181
if(exp80final==0x7ff) {
193182
// NaN and Infinite
194183
exp80final = 0x7fff;
195184
if(mant80==0x0)
196-
mant80final = 0x8000000000000000LL; //infinity
185+
mant80final = 0x8000000000000000L; //infinity
197186
else
198-
mant80final = 0xc000000000000000LL; //(quiet)NaN
187+
mant80final |= 0x8000000000000000L; //(quiet)NaN
199188
} else {
200189
if(exp80!=0){
201-
mant80final |= 0x8000000000000000LL;
190+
mant80final |= 0x8000000000000000L;
202191
exp80final += (BIAS80 - BIAS64);
203192
} else if(mant80final!=0) {
204193
// denormals -> normal
@@ -208,8 +197,8 @@ void D2LD(void* d, void* ld)
208197
mant80final<<=one;
209198
}
210199
}
211-
val.b = ((int16_t)(sign80)<<15)| (int16_t)(exp80final);
212-
val.f.sq = mant80final;
200+
val.b = ((int16_t)(sign80)<<15)| (int16_t)(exp80final);
201+
val.f.q = mant80final;
213202
memcpy(ld, &val, 10);
214203
/*memcpy(ld, &f.ll, 8);
215204
memcpy((char*)ld + 8, &val.b, 2);*/

0 commit comments

Comments
 (0)