1 /*
2  *  Copyright (C) 2002-2014  The DOSBox Team
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 
20 
FPU_FINIT(void)21 static void FPU_FINIT(void) {
22 	FPU_SetCW(0x37F);
23 	fpu.sw = 0;
24 	TOP=FPU_GET_TOP();
25 	fpu.tags[0] = TAG_Empty;
26 	fpu.tags[1] = TAG_Empty;
27 	fpu.tags[2] = TAG_Empty;
28 	fpu.tags[3] = TAG_Empty;
29 	fpu.tags[4] = TAG_Empty;
30 	fpu.tags[5] = TAG_Empty;
31 	fpu.tags[6] = TAG_Empty;
32 	fpu.tags[7] = TAG_Empty;
33 	fpu.tags[8] = TAG_Valid; // is only used by us
34 }
35 
FPU_FCLEX(void)36 static void FPU_FCLEX(void){
37 	fpu.sw &= 0x7f00;			//should clear exceptions
38 }
39 
FPU_FNOP(void)40 static void FPU_FNOP(void){
41 	return;
42 }
43 
FPU_PREP_PUSH(void)44 static void FPU_PREP_PUSH(void){
45 	TOP = (TOP - 1) &7;
46    //not needed and causing crashes //dosbox-x doesnt have this
47    //if (GCC_UNLIKELY(fpu.tags[TOP] != TAG_Empty)) E_Exit("FPU stack overflow");
48 	fpu.tags[TOP] = TAG_Valid;
49 }
50 
FPU_PUSH(double in)51 static void FPU_PUSH(double in){
52    FPU_PREP_PUSH();
53 	fpu.regs[TOP].d = in;
54 //	LOG(LOG_FPU,LOG_ERROR)("Pushed at %d  %g to the stack",newtop,in);
55 	return;
56 }
57 
FPU_FPOP(void)58 static void FPU_FPOP(void){
59    //not needed and causing crashes  //dosbox-x doesnt have this
60    //if (GCC_UNLIKELY(fpu.tags[TOP] == TAG_Empty)) E_Exit("FPU stack underflow");
61 	fpu.tags[TOP]=TAG_Empty;
62 	//maybe set zero in it as well
63 	TOP = ((TOP+1)&7);
64 //	LOG(LOG_FPU,LOG_ERROR)("popped from %d  %g off the stack",top,fpu.regs[top].d);
65 	return;
66 }
67 
FROUND(double in)68 static double FROUND(double in){
69 	switch(fpu.round){
70 	case ROUND_Nearest:
71 		if (in-floor(in)>0.5) return (floor(in)+1);
72 		else if (in-floor(in)<0.5) return (floor(in));
73 		else return (((static_cast<Bit64s>(floor(in)))&1)!=0)?(floor(in)+1):(floor(in));
74 		break;
75 	case ROUND_Down:
76 		return (floor(in));
77 		break;
78 	case ROUND_Up:
79 		return (ceil(in));
80 		break;
81 	case ROUND_Chop:
82 		return in; //the cast afterwards will do it right maybe cast here
83 		break;
84 	default:
85 		return in;
86 		break;
87 	}
88 }
89 
90 #define BIAS80 16383
91 #define BIAS64 1023
92 
FPU_FLD80(PhysPt addr)93 static Real64 FPU_FLD80(PhysPt addr) {
94 	struct {
95 		Bit16s begin;
96 		FPU_Reg eind;
97 	} test;
98 	test.eind.l.lower = mem_readd(addr);
99 	test.eind.l.upper = mem_readd(addr+4);
100 	test.begin = mem_readw(addr+8);
101 
102 	Bit64s exp64 = (((test.begin&0x7fff) - BIAS80));
103 	Bit64s blah = ((exp64 >0)?exp64:-exp64)&0x3ff;
104 	Bit64s exp64final = ((exp64 >0)?blah:-blah) +BIAS64;
105 
106 	Bit64s mant64 = (test.eind.ll >> 11) & LONGTYPE(0xfffffffffffff);
107 	Bit64s sign = (test.begin&0x8000)?1:0;
108 	FPU_Reg result;
109 	result.ll = (sign <<63)|(exp64final << 52)| mant64;
110 
111 	if(test.eind.l.lower == 0 && test.eind.l.upper == 0x80000000 && (test.begin&0x7fff) == 0x7fff) {
112 		//Detect INF and -INF (score 3.11 when drawing a slur.)
113 		result.d = sign?-HUGE_VAL:HUGE_VAL;
114 	}
115 	return result.d;
116 
117 	//mant64= test.mant80/2***64    * 2 **53
118 }
119 
FPU_ST80(PhysPt addr,Bitu reg)120 static void FPU_ST80(PhysPt addr,Bitu reg) {
121 	struct {
122 		Bit16s begin;
123 		FPU_Reg eind;
124 	} test;
125 	Bit64s sign80 = (fpu.regs[reg].ll&LONGTYPE(0x8000000000000000))?1:0;
126 	Bit64s exp80 =  fpu.regs[reg].ll&LONGTYPE(0x7ff0000000000000);
127 	Bit64s exp80final = (exp80>>52);
128 	Bit64s mant80 = fpu.regs[reg].ll&LONGTYPE(0x000fffffffffffff);
129 	Bit64s mant80final = (mant80 << 11);
130 	if(fpu.regs[reg].d != 0){ //Zero is a special case
131 		// Elvira wants the 8 and tcalc doesn't
132 		mant80final |= LONGTYPE(0x8000000000000000);
133 		//Ca-cyber doesn't like this when result is zero.
134 		exp80final += (BIAS80 - BIAS64);
135 	}
136 	test.begin = (static_cast<Bit16s>(sign80)<<15)| static_cast<Bit16s>(exp80final);
137 	test.eind.ll = mant80final;
138 	mem_writed(addr,test.eind.l.lower);
139 	mem_writed(addr+4,test.eind.l.upper);
140 	mem_writew(addr+8,test.begin);
141 }
142 
143 
FPU_FLD_F32(PhysPt addr,Bitu store_to)144 static void FPU_FLD_F32(PhysPt addr,Bitu store_to) {
145 	union {
146 		float f;
147 		Bit32u l;
148 	}	blah;
149 	blah.l = mem_readd(addr);
150 	fpu.regs[store_to].d = static_cast<Real64>(blah.f);
151 }
152 
FPU_FLD_F64(PhysPt addr,Bitu store_to)153 static void FPU_FLD_F64(PhysPt addr,Bitu store_to) {
154 	fpu.regs[store_to].l.lower = mem_readd(addr);
155 	fpu.regs[store_to].l.upper = mem_readd(addr+4);
156 }
157 
FPU_FLD_F80(PhysPt addr)158 static void FPU_FLD_F80(PhysPt addr) {
159 	fpu.regs[TOP].d = FPU_FLD80(addr);
160 }
161 
FPU_FLD_I16(PhysPt addr,Bitu store_to)162 static void FPU_FLD_I16(PhysPt addr,Bitu store_to) {
163 	Bit16s blah = mem_readw(addr);
164 	fpu.regs[store_to].d = static_cast<Real64>(blah);
165 }
166 
FPU_FLD_I32(PhysPt addr,Bitu store_to)167 static void FPU_FLD_I32(PhysPt addr,Bitu store_to) {
168 	Bit32s blah = mem_readd(addr);
169 	fpu.regs[store_to].d = static_cast<Real64>(blah);
170 }
171 
FPU_FLD_I64(PhysPt addr,Bitu store_to)172 static void FPU_FLD_I64(PhysPt addr,Bitu store_to) {
173 	FPU_Reg blah;
174 	blah.l.lower = mem_readd(addr);
175 	blah.l.upper = mem_readd(addr+4);
176 	fpu.regs[store_to].d = static_cast<Real64>(blah.ll);
177 }
178 
FPU_FBLD(PhysPt addr,Bitu store_to)179 static void FPU_FBLD(PhysPt addr,Bitu store_to) {
180 	Bit64u val = 0;
181 	Bitu in = 0;
182 	Bit64u base = 1;
183 	for(Bitu i = 0;i < 9;i++){
184 		in = mem_readb(addr + i);
185 		val += ( (in&0xf) * base); //in&0xf shouldn't be higher then 9
186 		base *= 10;
187 		val += ((( in>>4)&0xf) * base);
188 		base *= 10;
189 	}
190 
191 	//last number, only now convert to float in order to get
192 	//the best signification
193 	Real64 temp = static_cast<Real64>(val);
194 	in = mem_readb(addr + 9);
195 	temp += ( (in&0xf) * base );
196 	if(in&0x80) temp *= -1.0;
197 	fpu.regs[store_to].d = temp;
198 }
199 
200 
FPU_FLD_F32_EA(PhysPt addr)201 static INLINE void FPU_FLD_F32_EA(PhysPt addr) {
202 	FPU_FLD_F32(addr,8);
203 }
FPU_FLD_F64_EA(PhysPt addr)204 static INLINE void FPU_FLD_F64_EA(PhysPt addr) {
205 	FPU_FLD_F64(addr,8);
206 }
FPU_FLD_I32_EA(PhysPt addr)207 static INLINE void FPU_FLD_I32_EA(PhysPt addr) {
208 	FPU_FLD_I32(addr,8);
209 }
FPU_FLD_I16_EA(PhysPt addr)210 static INLINE void FPU_FLD_I16_EA(PhysPt addr) {
211 	FPU_FLD_I16(addr,8);
212 }
213 
214 
FPU_FST_F32(PhysPt addr)215 static void FPU_FST_F32(PhysPt addr) {
216 	union {
217 		float f;
218 		Bit32u l;
219 	}	blah;
220 	//should depend on rounding method
221 	blah.f = static_cast<float>(fpu.regs[TOP].d);
222 	mem_writed(addr,blah.l);
223 }
224 
FPU_FST_F64(PhysPt addr)225 static void FPU_FST_F64(PhysPt addr) {
226 	mem_writed(addr,fpu.regs[TOP].l.lower);
227 	mem_writed(addr+4,fpu.regs[TOP].l.upper);
228 }
229 
FPU_FST_F80(PhysPt addr)230 static void FPU_FST_F80(PhysPt addr) {
231 	FPU_ST80(addr,TOP);
232 }
233 
FPU_FST_I16(PhysPt addr)234 static void FPU_FST_I16(PhysPt addr) {
235 	mem_writew(addr,static_cast<Bit16s>(FROUND(fpu.regs[TOP].d)));
236 }
237 
FPU_FST_I32(PhysPt addr)238 static void FPU_FST_I32(PhysPt addr) {
239 	mem_writed(addr,static_cast<Bit32s>(FROUND(fpu.regs[TOP].d)));
240 }
241 
FPU_FST_I64(PhysPt addr)242 static void FPU_FST_I64(PhysPt addr) {
243 	FPU_Reg blah;
244 	blah.ll = static_cast<Bit64s>(FROUND(fpu.regs[TOP].d));
245 	mem_writed(addr,blah.l.lower);
246 	mem_writed(addr+4,blah.l.upper);
247 }
248 
FPU_FBST(PhysPt addr)249 static void FPU_FBST(PhysPt addr) {
250 	FPU_Reg val = fpu.regs[TOP];
251 	bool sign = false;
252 	if(fpu.regs[TOP].ll & LONGTYPE(0x8000000000000000)) { //sign
253 		sign=true;
254 		val.d=-val.d;
255 	}
256 	//numbers from back to front
257 	Real64 temp=val.d;
258 	Bitu p;
259 	for(Bitu i=0;i<9;i++){
260 		val.d=temp;
261 		temp = static_cast<Real64>(static_cast<Bit64s>(floor(val.d/10.0)));
262 		p = static_cast<Bitu>(val.d - 10.0*temp);
263 		val.d=temp;
264 		temp = static_cast<Real64>(static_cast<Bit64s>(floor(val.d/10.0)));
265 		p |= (static_cast<Bitu>(val.d - 10.0*temp)<<4);
266 
267 		mem_writeb(addr+i,p);
268 	}
269 	val.d=temp;
270 	temp = static_cast<Real64>(static_cast<Bit64s>(floor(val.d/10.0)));
271 	p = static_cast<Bitu>(val.d - 10.0*temp);
272 	if(sign)
273 		p|=0x80;
274 	mem_writeb(addr+9,p);
275 }
276 
FPU_FADD(Bitu op1,Bitu op2)277 static void FPU_FADD(Bitu op1, Bitu op2){
278 	fpu.regs[op1].d+=fpu.regs[op2].d;
279 	//flags and such :)
280 	return;
281 }
282 
FPU_FSIN(void)283 static void FPU_FSIN(void){
284 	fpu.regs[TOP].d = sin(fpu.regs[TOP].d);
285 	FPU_SET_C2(0);
286 	//flags and such :)
287 	return;
288 }
289 
FPU_FSINCOS(void)290 static void FPU_FSINCOS(void){
291 	Real64 temp = fpu.regs[TOP].d;
292 	fpu.regs[TOP].d = sin(temp);
293 	FPU_PUSH(cos(temp));
294 	FPU_SET_C2(0);
295 	//flags and such :)
296 	return;
297 }
298 
FPU_FCOS(void)299 static void FPU_FCOS(void){
300 	fpu.regs[TOP].d = cos(fpu.regs[TOP].d);
301 	FPU_SET_C2(0);
302 	//flags and such :)
303 	return;
304 }
305 
FPU_FSQRT(void)306 static void FPU_FSQRT(void){
307 	fpu.regs[TOP].d = sqrt(fpu.regs[TOP].d);
308 	//flags and such :)
309 	return;
310 }
FPU_FPATAN(void)311 static void FPU_FPATAN(void){
312 	fpu.regs[STV(1)].d = atan2(fpu.regs[STV(1)].d,fpu.regs[TOP].d);
313 	FPU_FPOP();
314 	//flags and such :)
315 	return;
316 }
FPU_FPTAN(void)317 static void FPU_FPTAN(void){
318 	fpu.regs[TOP].d = tan(fpu.regs[TOP].d);
319 	FPU_PUSH(1.0);
320 	FPU_SET_C2(0);
321 	//flags and such :)
322 	return;
323 }
FPU_FDIV(Bitu st,Bitu other)324 static void FPU_FDIV(Bitu st, Bitu other){
325 	fpu.regs[st].d= fpu.regs[st].d/fpu.regs[other].d;
326 	//flags and such :)
327 	return;
328 }
329 
FPU_FDIVR(Bitu st,Bitu other)330 static void FPU_FDIVR(Bitu st, Bitu other){
331 	fpu.regs[st].d= fpu.regs[other].d/fpu.regs[st].d;
332 	// flags and such :)
333 	return;
334 }
335 
FPU_FMUL(Bitu st,Bitu other)336 static void FPU_FMUL(Bitu st, Bitu other){
337 	fpu.regs[st].d*=fpu.regs[other].d;
338 	//flags and such :)
339 	return;
340 }
341 
FPU_FSUB(Bitu st,Bitu other)342 static void FPU_FSUB(Bitu st, Bitu other){
343 	fpu.regs[st].d = fpu.regs[st].d - fpu.regs[other].d;
344 	//flags and such :)
345 	return;
346 }
347 
FPU_FSUBR(Bitu st,Bitu other)348 static void FPU_FSUBR(Bitu st, Bitu other){
349 	fpu.regs[st].d= fpu.regs[other].d - fpu.regs[st].d;
350 	//flags and such :)
351 	return;
352 }
353 
FPU_FXCH(Bitu st,Bitu other)354 static void FPU_FXCH(Bitu st, Bitu other){
355 	FPU_Tag tag = fpu.tags[other];
356 	FPU_Reg reg = fpu.regs[other];
357 	fpu.tags[other] = fpu.tags[st];
358 	fpu.regs[other] = fpu.regs[st];
359 	fpu.tags[st] = tag;
360 	fpu.regs[st] = reg;
361 }
362 
FPU_FST(Bitu st,Bitu other)363 static void FPU_FST(Bitu st, Bitu other){
364 	fpu.tags[other] = fpu.tags[st];
365 	fpu.regs[other] = fpu.regs[st];
366 }
367 
368 
FPU_FCOM(Bitu st,Bitu other)369 static void FPU_FCOM(Bitu st, Bitu other){
370 	if(((fpu.tags[st] != TAG_Valid) && (fpu.tags[st] != TAG_Zero)) ||
371 		((fpu.tags[other] != TAG_Valid) && (fpu.tags[other] != TAG_Zero))){
372 		FPU_SET_C3(1);FPU_SET_C2(1);FPU_SET_C0(1);return;
373 	}
374 	if(fpu.regs[st].d == fpu.regs[other].d){
375 		FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0);return;
376 	}
377 	if(fpu.regs[st].d < fpu.regs[other].d){
378 		FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C0(1);return;
379 	}
380 	// st > other
381 	FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C0(0);return;
382 }
383 
FPU_FUCOM(Bitu st,Bitu other)384 static void FPU_FUCOM(Bitu st, Bitu other){
385 	//does atm the same as fcom
386 	FPU_FCOM(st,other);
387 }
388 
FPU_FRNDINT(void)389 static void FPU_FRNDINT(void){
390 	Bit64s temp= static_cast<Bit64s>(FROUND(fpu.regs[TOP].d));
391 	fpu.regs[TOP].d=static_cast<double>(temp);
392 }
393 
FPU_FPREM(void)394 static void FPU_FPREM(void){
395 	Real64 valtop = fpu.regs[TOP].d;
396 	Real64 valdiv = fpu.regs[STV(1)].d;
397 	Bit64s ressaved = static_cast<Bit64s>( (valtop/valdiv) );
398 // Some backups
399 //	Real64 res=valtop - ressaved*valdiv;
400 //      res= fmod(valtop,valdiv);
401 	fpu.regs[TOP].d = valtop - ressaved*valdiv;
402 	FPU_SET_C0(static_cast<Bitu>(ressaved&4));
403 	FPU_SET_C3(static_cast<Bitu>(ressaved&2));
404 	FPU_SET_C1(static_cast<Bitu>(ressaved&1));
405 	FPU_SET_C2(0);
406 }
407 
FPU_FPREM1(void)408 static void FPU_FPREM1(void){
409 	Real64 valtop = fpu.regs[TOP].d;
410 	Real64 valdiv = fpu.regs[STV(1)].d;
411 	double quot = valtop/valdiv;
412 	double quotf = floor(quot);
413 	Bit64s ressaved;
414 	if (quot-quotf>0.5) ressaved = static_cast<Bit64s>(quotf+1);
415 	else if (quot-quotf<0.5) ressaved = static_cast<Bit64s>(quotf);
416 	else ressaved = static_cast<Bit64s>((((static_cast<Bit64s>(quotf))&1)!=0)?(quotf+1):(quotf));
417 	fpu.regs[TOP].d = valtop - ressaved*valdiv;
418 	FPU_SET_C0(static_cast<Bitu>(ressaved&4));
419 	FPU_SET_C3(static_cast<Bitu>(ressaved&2));
420 	FPU_SET_C1(static_cast<Bitu>(ressaved&1));
421 	FPU_SET_C2(0);
422 }
423 
FPU_FXAM(void)424 static void FPU_FXAM(void){
425 	if(fpu.regs[TOP].ll & LONGTYPE(0x8000000000000000))	//sign
426 	{
427 		FPU_SET_C1(1);
428 	}
429 	else
430 	{
431 		FPU_SET_C1(0);
432 	}
433 	if(fpu.tags[TOP] == TAG_Empty)
434 	{
435 		FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(1);
436 		return;
437 	}
438 	if(fpu.regs[TOP].d == 0.0)		//zero or normalized number.
439 	{
440 		FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0);
441 	}
442 	else
443 	{
444 		FPU_SET_C3(0);FPU_SET_C2(1);FPU_SET_C0(0);
445 	}
446 }
447 
448 
FPU_F2XM1(void)449 static void FPU_F2XM1(void){
450 	fpu.regs[TOP].d = pow(2.0,fpu.regs[TOP].d) - 1;
451 	return;
452 }
453 
FPU_FYL2X(void)454 static void FPU_FYL2X(void){
455 	fpu.regs[STV(1)].d*=log(fpu.regs[TOP].d)/log(static_cast<Real64>(2.0));
456 	FPU_FPOP();
457 	return;
458 }
459 
FPU_FYL2XP1(void)460 static void FPU_FYL2XP1(void){
461 	fpu.regs[STV(1)].d*=log(fpu.regs[TOP].d+1.0)/log(static_cast<Real64>(2.0));
462 	FPU_FPOP();
463 	return;
464 }
465 
FPU_FSCALE(void)466 static void FPU_FSCALE(void){
467 	fpu.regs[TOP].d *= pow(2.0,static_cast<Real64>(static_cast<Bit64s>(fpu.regs[STV(1)].d)));
468 	return; //2^x where x is chopped.
469 }
470 
FPU_FSTENV(PhysPt addr)471 static void FPU_FSTENV(PhysPt addr){
472 	FPU_SET_TOP(TOP);
473 	if(!cpu.code.big) {
474 		mem_writew(addr+0,static_cast<Bit16u>(fpu.cw));
475 		mem_writew(addr+2,static_cast<Bit16u>(fpu.sw));
476 		mem_writew(addr+4,static_cast<Bit16u>(FPU_GetTag()));
477 	} else {
478 		mem_writed(addr+0,static_cast<Bit32u>(fpu.cw));
479 		mem_writed(addr+4,static_cast<Bit32u>(fpu.sw));
480 		mem_writed(addr+8,static_cast<Bit32u>(FPU_GetTag()));
481 	}
482 }
483 
FPU_FLDENV(PhysPt addr)484 static void FPU_FLDENV(PhysPt addr){
485 	Bit16u tag;
486 	Bit32u tagbig;
487 	Bitu cw;
488 	if(!cpu.code.big) {
489 		cw     = mem_readw(addr+0);
490 		fpu.sw = mem_readw(addr+2);
491 		tag    = mem_readw(addr+4);
492 	} else {
493 		cw     = mem_readd(addr+0);
494 		fpu.sw = (Bit16u)mem_readd(addr+4);
495 		tagbig = mem_readd(addr+8);
496 		tag    = static_cast<Bit16u>(tagbig);
497 	}
498 	FPU_SetTag(tag);
499 	FPU_SetCW(cw);
500 	TOP = FPU_GET_TOP();
501 }
502 
FPU_FSAVE(PhysPt addr)503 static void FPU_FSAVE(PhysPt addr){
504 	FPU_FSTENV(addr);
505 	Bitu start = (cpu.code.big?28:14);
506 	for(Bitu i = 0;i < 8;i++){
507 		FPU_ST80(addr+start,STV(i));
508 		start += 10;
509 	}
510 	FPU_FINIT();
511 }
512 
FPU_FRSTOR(PhysPt addr)513 static void FPU_FRSTOR(PhysPt addr){
514 	FPU_FLDENV(addr);
515 	Bitu start = (cpu.code.big?28:14);
516 	for(Bitu i = 0;i < 8;i++){
517 		fpu.regs[STV(i)].d = FPU_FLD80(addr+start);
518 		start += 10;
519 	}
520 }
521 
FPU_FXTRACT(void)522 static void FPU_FXTRACT(void) {
523 	// function stores real bias in st and
524 	// pushes the significant number onto the stack
525 	// if double ever uses a different base please correct this function
526 
527 	FPU_Reg test = fpu.regs[TOP];
528 	Bit64s exp80 =  test.ll&LONGTYPE(0x7ff0000000000000);
529 	Bit64s exp80final = (exp80>>52) - BIAS64;
530 	Real64 mant = test.d / (pow(2.0,static_cast<Real64>(exp80final)));
531 	fpu.regs[TOP].d = static_cast<Real64>(exp80final);
532 	FPU_PUSH(mant);
533 }
534 
FPU_FCHS(void)535 static void FPU_FCHS(void){
536 	fpu.regs[TOP].d = -1.0*(fpu.regs[TOP].d);
537 }
538 
FPU_FABS(void)539 static void FPU_FABS(void){
540 	fpu.regs[TOP].d = fabs(fpu.regs[TOP].d);
541 }
542 
FPU_FTST(void)543 static void FPU_FTST(void){
544 	fpu.regs[8].d = 0.0;
545 	FPU_FCOM(TOP,8);
546 }
547 
FPU_FLD1(void)548 static void FPU_FLD1(void){
549 	FPU_PREP_PUSH();
550 	fpu.regs[TOP].d = 1.0;
551 }
552 
FPU_FLDL2T(void)553 static void FPU_FLDL2T(void){
554 	FPU_PREP_PUSH();
555 	fpu.regs[TOP].d = L2T;
556 }
557 
FPU_FLDL2E(void)558 static void FPU_FLDL2E(void){
559 	FPU_PREP_PUSH();
560 	fpu.regs[TOP].d = L2E;
561 }
562 
FPU_FLDPI(void)563 static void FPU_FLDPI(void){
564 	FPU_PREP_PUSH();
565 	fpu.regs[TOP].d = PI;
566 }
567 
FPU_FLDLG2(void)568 static void FPU_FLDLG2(void){
569 	FPU_PREP_PUSH();
570 	fpu.regs[TOP].d = LG2;
571 }
572 
FPU_FLDLN2(void)573 static void FPU_FLDLN2(void){
574 	FPU_PREP_PUSH();
575 	fpu.regs[TOP].d = LN2;
576 }
577 
FPU_FLDZ(void)578 static void FPU_FLDZ(void){
579 	FPU_PREP_PUSH();
580 	fpu.regs[TOP].d = 0.0;
581 	fpu.tags[TOP] = TAG_Zero;
582 }
583 
584 
FPU_FADD_EA(Bitu op1)585 static INLINE void FPU_FADD_EA(Bitu op1){
586 	FPU_FADD(op1,8);
587 }
FPU_FMUL_EA(Bitu op1)588 static INLINE void FPU_FMUL_EA(Bitu op1){
589 	FPU_FMUL(op1,8);
590 }
FPU_FSUB_EA(Bitu op1)591 static INLINE void FPU_FSUB_EA(Bitu op1){
592 	FPU_FSUB(op1,8);
593 }
FPU_FSUBR_EA(Bitu op1)594 static INLINE void FPU_FSUBR_EA(Bitu op1){
595 	FPU_FSUBR(op1,8);
596 }
FPU_FDIV_EA(Bitu op1)597 static INLINE void FPU_FDIV_EA(Bitu op1){
598 	FPU_FDIV(op1,8);
599 }
FPU_FDIVR_EA(Bitu op1)600 static INLINE void FPU_FDIVR_EA(Bitu op1){
601 	FPU_FDIVR(op1,8);
602 }
FPU_FCOM_EA(Bitu op1)603 static INLINE void FPU_FCOM_EA(Bitu op1){
604 	FPU_FCOM(op1,8);
605 }
606 
607