xref: /plan9/sys/src/cmd/qi/float.c (revision 6891d8578618fb7ccda4a131c122d4d0e6580c4b)
17d9195a7SDavid du Colombier #include <u.h>
27d9195a7SDavid du Colombier #include <libc.h>
37d9195a7SDavid du Colombier #include <bio.h>
47d9195a7SDavid du Colombier #include <mach.h>
57d9195a7SDavid du Colombier #define Extern extern
67d9195a7SDavid du Colombier #include "power.h"
77d9195a7SDavid du Colombier 
87d9195a7SDavid du Colombier ulong	setfpscr(void);
97d9195a7SDavid du Colombier void	setfpcc(double);
107d9195a7SDavid du Colombier void	farith(ulong);
117d9195a7SDavid du Colombier void	farith2(ulong);
127d9195a7SDavid du Colombier void	fariths(ulong);
137d9195a7SDavid du Colombier void	fcmp(ulong);
147d9195a7SDavid du Colombier void	mtfsb1(ulong);
157d9195a7SDavid du Colombier void	mcrfs(ulong);
167d9195a7SDavid du Colombier void	mtfsb0(ulong);
177d9195a7SDavid du Colombier void	mtfsf(ulong);
187d9195a7SDavid du Colombier void	mtfsfi(ulong);
197d9195a7SDavid du Colombier void	mffs(ulong);
207d9195a7SDavid du Colombier void	mtfsf(ulong);
217d9195a7SDavid du Colombier 
227d9195a7SDavid du Colombier Inst	op59[] = {
237d9195a7SDavid du Colombier [18] {fariths, "fdivs", Ifloat},
247d9195a7SDavid du Colombier [20] {fariths, "fsubs", Ifloat},
257d9195a7SDavid du Colombier [21] {fariths, "fadds", Ifloat},
267d9195a7SDavid du Colombier [22] {unimp, "fsqrts", Ifloat},
277d9195a7SDavid du Colombier [24] {unimp, "fres", Ifloat},
287d9195a7SDavid du Colombier [25] {fariths, "fmuls", Ifloat},
297d9195a7SDavid du Colombier [28] {fariths, "fmsubs", Ifloat},
307d9195a7SDavid du Colombier [29] {fariths, "fmadds", Ifloat},
317d9195a7SDavid du Colombier [30] {fariths, "fnmsubs", Ifloat},
327d9195a7SDavid du Colombier [31] {fariths, "fnmadds", Ifloat},
337d9195a7SDavid du Colombier };
347d9195a7SDavid du Colombier 
357d9195a7SDavid du Colombier Inset	ops59 = {op59, nelem(op59)};
367d9195a7SDavid du Colombier 
377d9195a7SDavid du Colombier Inst	op63a[] = {
387d9195a7SDavid du Colombier [12] {farith, "frsp", Ifloat},
397d9195a7SDavid du Colombier [14] {farith, "fctiw", Ifloat},
407d9195a7SDavid du Colombier [15] {farith, "fctiwz", Ifloat},
417d9195a7SDavid du Colombier [18] {farith, "fdiv", Ifloat},
427d9195a7SDavid du Colombier [20] {farith, "fsub", Ifloat},
437d9195a7SDavid du Colombier [21] {farith, "fadd", Ifloat},
447d9195a7SDavid du Colombier [22] {unimp, "frsqrt", Ifloat},
457d9195a7SDavid du Colombier [23] {unimp, "fsel", Ifloat},
467d9195a7SDavid du Colombier [25] {farith, "fmul", Ifloat},
477d9195a7SDavid du Colombier [26] {unimp, "frsqrte", Ifloat},
487d9195a7SDavid du Colombier [28] {farith, "fmsub", Ifloat},
497d9195a7SDavid du Colombier [29] {farith, "fmadd", Ifloat},
507d9195a7SDavid du Colombier [30] {farith, "fnmsub", Ifloat},
517d9195a7SDavid du Colombier [31] {farith, "fnmadd", Ifloat},
527d9195a7SDavid du Colombier };
537d9195a7SDavid du Colombier 
547d9195a7SDavid du Colombier Inset	ops63a= {op63a, nelem(op63a)};
557d9195a7SDavid du Colombier 
567d9195a7SDavid du Colombier Inst	op63b[] = {
577d9195a7SDavid du Colombier [0] {fcmp, "fcmpu", Ifloat},
587d9195a7SDavid du Colombier [32] {fcmp, "fcmpo", Ifloat},
597d9195a7SDavid du Colombier [38] {mtfsb1, "mtfsb1", Ifloat},
607d9195a7SDavid du Colombier [40] {farith2, "fneg", Ifloat},
617d9195a7SDavid du Colombier [64] {mcrfs, "mcrfs", Ifloat},
627d9195a7SDavid du Colombier [70] {mtfsb0, "mtfsb0", Ifloat},
637d9195a7SDavid du Colombier [72] {farith2, "fmr", Ifloat},
647d9195a7SDavid du Colombier [134] {mtfsfi, "mtfsfi", Ifloat},
657d9195a7SDavid du Colombier [136] {farith2, "fnabs", Ifloat},
667d9195a7SDavid du Colombier [264] {farith2, "fabs", Ifloat},
677d9195a7SDavid du Colombier [583] {mffs, "mffs", Ifloat},
687d9195a7SDavid du Colombier [711] {mtfsf, "mtfsf", Ifloat},
697d9195a7SDavid du Colombier };
707d9195a7SDavid du Colombier 
717d9195a7SDavid du Colombier Inset	ops63b = {op63b, nelem(op63b)};
727d9195a7SDavid du Colombier 
737d9195a7SDavid du Colombier void
fpreginit(void)74*6891d857SDavid du Colombier fpreginit(void)
75*6891d857SDavid du Colombier {
76*6891d857SDavid du Colombier 	int i;
77*6891d857SDavid du Colombier 
78*6891d857SDavid du Colombier 	/* Normally initialised by the kernel */
79*6891d857SDavid du Colombier 	reg.fd[27] = 4503601774854144.0;
80*6891d857SDavid du Colombier 	reg.fd[29] = 0.5;
81*6891d857SDavid du Colombier 	reg.fd[28] = 0.0;
82*6891d857SDavid du Colombier 	reg.fd[30] = 1.0;
83*6891d857SDavid du Colombier 	reg.fd[31] = 2.0;
84*6891d857SDavid du Colombier 	for(i = 0; i < 27; i++)
85*6891d857SDavid du Colombier 		reg.fd[i] = reg.fd[28];
86*6891d857SDavid du Colombier }
87*6891d857SDavid du Colombier 
88*6891d857SDavid du Colombier static double
v2fp(uvlong v)89*6891d857SDavid du Colombier v2fp(uvlong v)
90*6891d857SDavid du Colombier {
91*6891d857SDavid du Colombier 	FPdbleword f;
92*6891d857SDavid du Colombier 
93*6891d857SDavid du Colombier 	f.hi = v>>32;
94*6891d857SDavid du Colombier 	f.lo = v;
95*6891d857SDavid du Colombier 	return f.x;
96*6891d857SDavid du Colombier }
97*6891d857SDavid du Colombier 
98*6891d857SDavid du Colombier static uvlong
fp2v(double d)99*6891d857SDavid du Colombier fp2v(double d)
100*6891d857SDavid du Colombier {
101*6891d857SDavid du Colombier 	FPdbleword f;
102*6891d857SDavid du Colombier 
103*6891d857SDavid du Colombier 	f.x = d;
104*6891d857SDavid du Colombier 	return ((uvlong)f.hi<<32) | f.lo;
105*6891d857SDavid du Colombier }
106*6891d857SDavid du Colombier 
107*6891d857SDavid du Colombier void
lfs(ulong ir)1087d9195a7SDavid du Colombier lfs(ulong ir)
1097d9195a7SDavid du Colombier {
1107d9195a7SDavid du Colombier 	ulong ea;
1117d9195a7SDavid du Colombier 	int imm, ra, rd, upd;
1127d9195a7SDavid du Colombier 	union {
1137d9195a7SDavid du Colombier 		ulong	i;
1147d9195a7SDavid du Colombier 		float	f;
1157d9195a7SDavid du Colombier 	} u;
1167d9195a7SDavid du Colombier 
1177d9195a7SDavid du Colombier 	getairr(ir);
1187d9195a7SDavid du Colombier 	ea = imm;
1197d9195a7SDavid du Colombier 	upd = (ir&(1L<<26))!=0;
1207d9195a7SDavid du Colombier 	if(ra) {
1217d9195a7SDavid du Colombier 		ea += reg.r[ra];
1227d9195a7SDavid du Colombier 		if(upd)
1237d9195a7SDavid du Colombier 			reg.r[ra] = ea;
1247d9195a7SDavid du Colombier 	} else {
1257d9195a7SDavid du Colombier 		if(upd)
1267d9195a7SDavid du Colombier 			undef(ir);
1277d9195a7SDavid du Colombier 	}
1287d9195a7SDavid du Colombier 	if(trace)
1297d9195a7SDavid du Colombier 		itrace("%s\tf%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1307d9195a7SDavid du Colombier 
1317d9195a7SDavid du Colombier 	u.i = getmem_w(ea);
1327d9195a7SDavid du Colombier 	reg.fd[rd] = u.f;
1337d9195a7SDavid du Colombier }
1347d9195a7SDavid du Colombier 
1357d9195a7SDavid du Colombier void
lfsx(ulong ir)1367d9195a7SDavid du Colombier lfsx(ulong ir)
1377d9195a7SDavid du Colombier {
1387d9195a7SDavid du Colombier 	ulong ea;
1397d9195a7SDavid du Colombier 	int rd, ra, rb, upd;
1407d9195a7SDavid du Colombier 	union {
1417d9195a7SDavid du Colombier 		ulong	i;
1427d9195a7SDavid du Colombier 		float	f;
1437d9195a7SDavid du Colombier 	} u;
1447d9195a7SDavid du Colombier 
1457d9195a7SDavid du Colombier 	getarrr(ir);
1467d9195a7SDavid du Colombier 	ea = reg.r[rb];
1477d9195a7SDavid du Colombier 	upd = ((ir>>1)&0x3FF)==567;
1487d9195a7SDavid du Colombier 	if(ra){
1497d9195a7SDavid du Colombier 		ea += reg.r[ra];
1507d9195a7SDavid du Colombier 		if(upd)
1517d9195a7SDavid du Colombier 			reg.r[ra] = ea;
1527d9195a7SDavid du Colombier 		if(trace)
1537d9195a7SDavid du Colombier 			itrace("%s\tf%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1547d9195a7SDavid du Colombier 	} else {
1557d9195a7SDavid du Colombier 		if(upd)
1567d9195a7SDavid du Colombier 			undef(ir);
1577d9195a7SDavid du Colombier 		if(trace)
1587d9195a7SDavid du Colombier 			itrace("%s\tf%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1597d9195a7SDavid du Colombier 	}
1607d9195a7SDavid du Colombier 
1617d9195a7SDavid du Colombier 	u.i = getmem_w(ea);
1627d9195a7SDavid du Colombier 	reg.fd[rd] = u.f;
1637d9195a7SDavid du Colombier }
1647d9195a7SDavid du Colombier 
1657d9195a7SDavid du Colombier void
lfd(ulong ir)1667d9195a7SDavid du Colombier lfd(ulong ir)
1677d9195a7SDavid du Colombier {
1687d9195a7SDavid du Colombier 	ulong ea;
1697d9195a7SDavid du Colombier 	int imm, ra, rd, upd;
1707d9195a7SDavid du Colombier 
1717d9195a7SDavid du Colombier 	getairr(ir);
1727d9195a7SDavid du Colombier 	ea = imm;
1737d9195a7SDavid du Colombier 	upd = (ir&(1L<<26))!=0;
1747d9195a7SDavid du Colombier 	if(ra) {
1757d9195a7SDavid du Colombier 		ea += reg.r[ra];
1767d9195a7SDavid du Colombier 		if(upd)
1777d9195a7SDavid du Colombier 			reg.r[ra] = ea;
1787d9195a7SDavid du Colombier 	} else {
1797d9195a7SDavid du Colombier 		if(upd)
1807d9195a7SDavid du Colombier 			undef(ir);
1817d9195a7SDavid du Colombier 	}
1827d9195a7SDavid du Colombier 	if(trace)
1837d9195a7SDavid du Colombier 		itrace("%s\tf%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1847d9195a7SDavid du Colombier 
185*6891d857SDavid du Colombier 	reg.fd[rd] = v2fp(getmem_v(ea));
1867d9195a7SDavid du Colombier }
1877d9195a7SDavid du Colombier 
1887d9195a7SDavid du Colombier void
lfdx(ulong ir)1897d9195a7SDavid du Colombier lfdx(ulong ir)
1907d9195a7SDavid du Colombier {
1917d9195a7SDavid du Colombier 	ulong ea;
1927d9195a7SDavid du Colombier 	int rd, ra, rb, upd;
1937d9195a7SDavid du Colombier 
1947d9195a7SDavid du Colombier 	getarrr(ir);
1957d9195a7SDavid du Colombier 	ea = reg.r[rb];
1967d9195a7SDavid du Colombier 	upd = ((ir>>1)&0x3FF)==631;
1977d9195a7SDavid du Colombier 	if(ra){
1987d9195a7SDavid du Colombier 		ea += reg.r[ra];
1997d9195a7SDavid du Colombier 		if(upd)
2007d9195a7SDavid du Colombier 			reg.r[ra] = ea;
2017d9195a7SDavid du Colombier 		if(trace)
2027d9195a7SDavid du Colombier 			itrace("%s\tf%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
2037d9195a7SDavid du Colombier 	} else {
2047d9195a7SDavid du Colombier 		if(upd)
2057d9195a7SDavid du Colombier 			undef(ir);
2067d9195a7SDavid du Colombier 		if(trace)
2077d9195a7SDavid du Colombier 			itrace("%s\tf%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
2087d9195a7SDavid du Colombier 	}
2097d9195a7SDavid du Colombier 
210*6891d857SDavid du Colombier 	reg.fd[rd] = v2fp(getmem_v(ea));
2117d9195a7SDavid du Colombier }
2127d9195a7SDavid du Colombier 
2137d9195a7SDavid du Colombier void
stfs(ulong ir)2147d9195a7SDavid du Colombier stfs(ulong ir)
2157d9195a7SDavid du Colombier {
2167d9195a7SDavid du Colombier 	ulong ea;
2177d9195a7SDavid du Colombier 	int imm, ra, rd, upd;
2187d9195a7SDavid du Colombier 	union {
2197d9195a7SDavid du Colombier 		float f;
2207d9195a7SDavid du Colombier 		ulong w;
2217d9195a7SDavid du Colombier 	} u;
2227d9195a7SDavid du Colombier 
2237d9195a7SDavid du Colombier 	getairr(ir);
2247d9195a7SDavid du Colombier 	ea = imm;
2257d9195a7SDavid du Colombier 	upd = (ir&(1L<<26))!=0;
2267d9195a7SDavid du Colombier 	if(ra) {
2277d9195a7SDavid du Colombier 		ea += reg.r[ra];
2287d9195a7SDavid du Colombier 		if(upd)
2297d9195a7SDavid du Colombier 			reg.r[ra] = ea;
2307d9195a7SDavid du Colombier 	} else {
2317d9195a7SDavid du Colombier 		if(upd)
2327d9195a7SDavid du Colombier 			undef(ir);
2337d9195a7SDavid du Colombier 	}
2347d9195a7SDavid du Colombier 	if(trace)
2357d9195a7SDavid du Colombier 		itrace("%s\tf%d,%ld(r%d) %lux=%g",
2367d9195a7SDavid du Colombier 					ci->name, rd, imm, ra, ea, reg.fd[rd]);
2377d9195a7SDavid du Colombier 	u.f = reg.fd[rd];	/* BUG: actual PPC conversion is more subtle than this */
2387d9195a7SDavid du Colombier 	putmem_w(ea, u.w);
2397d9195a7SDavid du Colombier }
2407d9195a7SDavid du Colombier 
2417d9195a7SDavid du Colombier void
stfsx(ulong ir)2427d9195a7SDavid du Colombier stfsx(ulong ir)
2437d9195a7SDavid du Colombier {
2447d9195a7SDavid du Colombier 	ulong ea;
2457d9195a7SDavid du Colombier 	int rd, ra, rb, upd;
2467d9195a7SDavid du Colombier 	union {
2477d9195a7SDavid du Colombier 		float	f;
2487d9195a7SDavid du Colombier 		ulong	w;
2497d9195a7SDavid du Colombier 	} u;
2507d9195a7SDavid du Colombier 
2517d9195a7SDavid du Colombier 	getarrr(ir);
2527d9195a7SDavid du Colombier 	ea = reg.r[rb];
2537d9195a7SDavid du Colombier 	upd = getxo(ir)==695;
2547d9195a7SDavid du Colombier 	if(ra){
2557d9195a7SDavid du Colombier 		ea += reg.r[ra];
2567d9195a7SDavid du Colombier 		if(upd)
2577d9195a7SDavid du Colombier 			reg.r[ra] = ea;
2587d9195a7SDavid du Colombier 		if(trace)
2597d9195a7SDavid du Colombier 			itrace("%s\tf%d,(r%d+r%d) %lux=%g", ci->name, rd, ra, rb, ea, (float)reg.fd[rd]);
2607d9195a7SDavid du Colombier 	} else {
2617d9195a7SDavid du Colombier 		if(upd)
2627d9195a7SDavid du Colombier 			undef(ir);
2637d9195a7SDavid du Colombier 		if(trace)
2647d9195a7SDavid du Colombier 			itrace("%s\tf%d,(r%d) %lux=%g", ci->name, rd, rb, ea, (float)reg.fd[rd]);
2657d9195a7SDavid du Colombier 	}
2667d9195a7SDavid du Colombier 
2677d9195a7SDavid du Colombier 	u.f = reg.fd[rd];	/* BUG: actual PPC conversion is more subtle than this */
2687d9195a7SDavid du Colombier 	putmem_w(ea, u.w);
2697d9195a7SDavid du Colombier }
2707d9195a7SDavid du Colombier 
2717d9195a7SDavid du Colombier void
stfd(ulong ir)2727d9195a7SDavid du Colombier stfd(ulong ir)
2737d9195a7SDavid du Colombier {
2747d9195a7SDavid du Colombier 	ulong ea;
2757d9195a7SDavid du Colombier 	int imm, ra, rd, upd;
2767d9195a7SDavid du Colombier 
2777d9195a7SDavid du Colombier 	getairr(ir);
2787d9195a7SDavid du Colombier 	ea = imm;
2797d9195a7SDavid du Colombier 	upd = (ir&(1L<<26))!=0;
2807d9195a7SDavid du Colombier 	if(ra) {
2817d9195a7SDavid du Colombier 		ea += reg.r[ra];
2827d9195a7SDavid du Colombier 		if(upd)
2837d9195a7SDavid du Colombier 			reg.r[ra] = ea;
2847d9195a7SDavid du Colombier 	} else {
2857d9195a7SDavid du Colombier 		if(upd)
2867d9195a7SDavid du Colombier 			undef(ir);
2877d9195a7SDavid du Colombier 	}
2887d9195a7SDavid du Colombier 	if(trace)
2897d9195a7SDavid du Colombier 		itrace("%s\tf%d,%ld(r%d) %lux=%g",
2907d9195a7SDavid du Colombier 					ci->name, rd, imm, ra, ea, reg.fd[rd]);
2917d9195a7SDavid du Colombier 
292*6891d857SDavid du Colombier 	putmem_v(ea, fp2v(reg.fd[rd]));
2937d9195a7SDavid du Colombier }
2947d9195a7SDavid du Colombier 
2957d9195a7SDavid du Colombier void
stfdx(ulong ir)2967d9195a7SDavid du Colombier stfdx(ulong ir)
2977d9195a7SDavid du Colombier {
2987d9195a7SDavid du Colombier 	ulong ea;
2997d9195a7SDavid du Colombier 	int rd, ra, rb, upd;
3007d9195a7SDavid du Colombier 
3017d9195a7SDavid du Colombier 	getarrr(ir);
3027d9195a7SDavid du Colombier 	ea = reg.r[rb];
3037d9195a7SDavid du Colombier 	upd = ((ir>>1)&0x3FF)==759;
3047d9195a7SDavid du Colombier 	if(ra){
3057d9195a7SDavid du Colombier 		ea += reg.r[ra];
3067d9195a7SDavid du Colombier 		if(upd)
3077d9195a7SDavid du Colombier 			reg.r[ra] = ea;
3087d9195a7SDavid du Colombier 		if(trace)
3097d9195a7SDavid du Colombier 			itrace("%s\tf%d,(r%d+r%d) %lux=%g", ci->name, rd, ra, rb, ea, reg.fd[rd]);
3107d9195a7SDavid du Colombier 	} else {
3117d9195a7SDavid du Colombier 		if(upd)
3127d9195a7SDavid du Colombier 			undef(ir);
3137d9195a7SDavid du Colombier 		if(trace)
3147d9195a7SDavid du Colombier 			itrace("%s\tf%d,(r%d) %lux=%g", ci->name, rd, rb, ea, reg.fd[rd]);
3157d9195a7SDavid du Colombier 	}
3167d9195a7SDavid du Colombier 
317*6891d857SDavid du Colombier 	putmem_v(ea, fp2v(reg.fd[rd]));
3187d9195a7SDavid du Colombier }
3197d9195a7SDavid du Colombier 
3207d9195a7SDavid du Colombier void
mcrfs(ulong ir)3217d9195a7SDavid du Colombier mcrfs(ulong ir)
3227d9195a7SDavid du Colombier {
3237d9195a7SDavid du Colombier 	ulong rd, ra, rb;
3247d9195a7SDavid du Colombier 	static ulong fpscr0[] ={
3257d9195a7SDavid du Colombier 		FPS_FX|FPS_OX,
3267d9195a7SDavid du Colombier 		FPS_UX|FPS_ZX|FPS_XX|FPS_VXSNAN,
3277d9195a7SDavid du Colombier 		FPS_VXISI|FPS_VXIDI|FPS_VXZDZ|FPS_VXIMZ,
3287d9195a7SDavid du Colombier 		FPS_VXVC,
3297d9195a7SDavid du Colombier 		0,
3307d9195a7SDavid du Colombier 		FPS_VXCVI,
3317d9195a7SDavid du Colombier 	};
3327d9195a7SDavid du Colombier 
3337d9195a7SDavid du Colombier 	getarrr(ir);
3347d9195a7SDavid du Colombier 	if(rb || ra&3 || rd&3)
3357d9195a7SDavid du Colombier 		undef(ir);
3367d9195a7SDavid du Colombier 	ra >>= 2;
3377d9195a7SDavid du Colombier 	rd >>= 2;
3387d9195a7SDavid du Colombier 	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, getCR(ra, reg.fpscr));
3397d9195a7SDavid du Colombier 	reg.fpscr &= ~fpscr0[ra];
3407d9195a7SDavid du Colombier 	if(trace)
3417d9195a7SDavid du Colombier 		itrace("mcrfs\tcrf%d,crf%d\n", rd, ra);
3427d9195a7SDavid du Colombier }
3437d9195a7SDavid du Colombier 
3447d9195a7SDavid du Colombier void
mffs(ulong ir)3457d9195a7SDavid du Colombier mffs(ulong ir)
3467d9195a7SDavid du Colombier {
3477d9195a7SDavid du Colombier 	int rd, ra, rb;
348*6891d857SDavid du Colombier 	FPdbleword d;
3497d9195a7SDavid du Colombier 
3507d9195a7SDavid du Colombier 	getarrr(ir);
3517d9195a7SDavid du Colombier 	if(ra || rb)
3527d9195a7SDavid du Colombier 		undef(ir);
353*6891d857SDavid du Colombier 	d.hi = 0xFFF80000UL;
354*6891d857SDavid du Colombier 	d.lo = reg.fpscr;
355*6891d857SDavid du Colombier 	reg.fd[rd] = d.x;
3567d9195a7SDavid du Colombier 	/* it's anyone's guess how CR1 should be set when ir&1 */
3577d9195a7SDavid du Colombier 	reg.cr &= ~mkCR(1, 0xE);	/* leave SO, reset others */
3587d9195a7SDavid du Colombier 	if(trace)
3597d9195a7SDavid du Colombier 		itrace("mffs%s\tfr%d\n", ir&1?".":"", rd);
3607d9195a7SDavid du Colombier }
3617d9195a7SDavid du Colombier 
3627d9195a7SDavid du Colombier void
mtfsb1(ulong ir)3637d9195a7SDavid du Colombier mtfsb1(ulong ir)
3647d9195a7SDavid du Colombier {
3657d9195a7SDavid du Colombier 	int rd, ra, rb;
3667d9195a7SDavid du Colombier 
3677d9195a7SDavid du Colombier 	getarrr(ir);
3687d9195a7SDavid du Colombier 	if(ra || rb)
3697d9195a7SDavid du Colombier 		undef(ir);
3707d9195a7SDavid du Colombier 	reg.fpscr |= (1L << (31-rd));
3717d9195a7SDavid du Colombier 	/* BUG: should set summary bits */
3727d9195a7SDavid du Colombier 	if(ir & 1)
3737d9195a7SDavid du Colombier 		reg.cr &= ~mkCR(1, 0xE);	/* BUG: manual unclear: leave SO, reset others? */
3747d9195a7SDavid du Colombier 	if(trace)
3757d9195a7SDavid du Colombier 		itrace("mtfsb1%s\tfr%d\n", ir&1?".":"", rd);
3767d9195a7SDavid du Colombier }
3777d9195a7SDavid du Colombier 
3787d9195a7SDavid du Colombier void
mtfsb0(ulong ir)3797d9195a7SDavid du Colombier mtfsb0(ulong ir)
3807d9195a7SDavid du Colombier {
3817d9195a7SDavid du Colombier 	int rd, ra, rb;
3827d9195a7SDavid du Colombier 
3837d9195a7SDavid du Colombier 	getarrr(ir);
3847d9195a7SDavid du Colombier 	if(ra || rb)
3857d9195a7SDavid du Colombier 		undef(ir);
3867d9195a7SDavid du Colombier 	reg.fpscr &= ~(1L << (31-rd));
3877d9195a7SDavid du Colombier 	if(ir & 1)
3887d9195a7SDavid du Colombier 		reg.cr &= ~mkCR(1, 0xE);		/* BUG: manual unclear: leave SO, reset others? */
3897d9195a7SDavid du Colombier 	if(trace)
3907d9195a7SDavid du Colombier 		itrace("mtfsb0%s\tfr%d\n", ir&1?".":"", rd);
3917d9195a7SDavid du Colombier }
3927d9195a7SDavid du Colombier 
3937d9195a7SDavid du Colombier void
mtfsf(ulong ir)3947d9195a7SDavid du Colombier mtfsf(ulong ir)
3957d9195a7SDavid du Colombier {
3967d9195a7SDavid du Colombier 	int fm, rb, i;
397*6891d857SDavid du Colombier 	FPdbleword d;
3987d9195a7SDavid du Colombier 	ulong v;
3997d9195a7SDavid du Colombier 
4007d9195a7SDavid du Colombier 	if(ir & ((1L << 25)|(1L << 16)))
4017d9195a7SDavid du Colombier 		undef(ir);
4027d9195a7SDavid du Colombier 	rb = (ir >> 11) & 0x1F;
4037d9195a7SDavid du Colombier 	fm = (ir >> 17) & 0xFF;
404*6891d857SDavid du Colombier 	d.x = reg.fd[rb];
405*6891d857SDavid du Colombier 	v = d.lo;
4067d9195a7SDavid du Colombier 	for(i=0; i<8; i++)
4077d9195a7SDavid du Colombier 		if(fm & (1 << (7-i)))
4087d9195a7SDavid du Colombier 			reg.fpscr = (reg.fpscr & ~mkCR(i, 0xF)) | mkCR(i, getCR(i, v));
4097d9195a7SDavid du Colombier 	/* BUG: should set FEX and VX `according to the usual rule' */
4107d9195a7SDavid du Colombier 	if(ir & 1)
4117d9195a7SDavid du Colombier 		reg.cr &= ~mkCR(1, 0xE);		/* BUG: manual unclear: leave SO, reset others? */
4127d9195a7SDavid du Colombier 	if(trace)
4137d9195a7SDavid du Colombier 		itrace("mtfsf%s\t#%.2x,fr%d", ir&1?".":"", fm, rb);
4147d9195a7SDavid du Colombier }
4157d9195a7SDavid du Colombier 
4167d9195a7SDavid du Colombier void
mtfsfi(ulong ir)4177d9195a7SDavid du Colombier mtfsfi(ulong ir)
4187d9195a7SDavid du Colombier {
4197d9195a7SDavid du Colombier 	int imm, rd;
4207d9195a7SDavid du Colombier 
4217d9195a7SDavid du Colombier 	if(ir & ((0x7F << 16)|(1L << 11)))
4227d9195a7SDavid du Colombier 		undef(ir);
4237d9195a7SDavid du Colombier 	rd = (ir >> 23) & 0xF;
4247d9195a7SDavid du Colombier 	imm = (ir >> 12) & 0xF;
4257d9195a7SDavid du Colombier 	reg.fpscr = (reg.fpscr & ~mkCR(rd, 0xF)) | mkCR(rd, imm);
4267d9195a7SDavid du Colombier 	/* BUG: should set FEX and VX `according to the usual rule' */
4277d9195a7SDavid du Colombier 	if(ir & 1)
4287d9195a7SDavid du Colombier 		reg.cr &= ~mkCR(1, 0xE);		/* BUG: manual unclear: leave SO, reset others? */
4297d9195a7SDavid du Colombier 	if(trace)
4307d9195a7SDavid du Colombier 		itrace("mtfsfi%s\tcrf%d,#%x", ir&1?".":"", rd, imm);
4317d9195a7SDavid du Colombier }
4327d9195a7SDavid du Colombier 
4337d9195a7SDavid du Colombier void
fcmp(ulong ir)4347d9195a7SDavid du Colombier fcmp(ulong ir)
4357d9195a7SDavid du Colombier {
4367d9195a7SDavid du Colombier 	int fc, rd, ra, rb;
4377d9195a7SDavid du Colombier 
4387d9195a7SDavid du Colombier 	getarrr(ir);
4397d9195a7SDavid du Colombier 	if(rd & 3)
4407d9195a7SDavid du Colombier 		undef(ir);
4417d9195a7SDavid du Colombier 	rd >>= 2;
4427d9195a7SDavid du Colombier 	SET(fc);
4437d9195a7SDavid du Colombier 	switch(getxo(ir)) {
4447d9195a7SDavid du Colombier 	default:
4457d9195a7SDavid du Colombier 		undef(ir);
4467d9195a7SDavid du Colombier 	case 0:
4477d9195a7SDavid du Colombier 		if(trace)
4487d9195a7SDavid du Colombier 			itrace("fcmpu\tcr%d,f%d,f%d", rd, ra, rb);
4497d9195a7SDavid du Colombier 		if(isNaN(reg.fd[ra]) || isNaN(reg.fd[rb])) {
4507d9195a7SDavid du Colombier 			fc = CRFU;
4517d9195a7SDavid du Colombier 			break;
4527d9195a7SDavid du Colombier 		}
4537d9195a7SDavid du Colombier 		if(reg.fd[ra] == reg.fd[rb]) {
4547d9195a7SDavid du Colombier 			fc = CREQ;
4557d9195a7SDavid du Colombier 			break;
4567d9195a7SDavid du Colombier 		}
4577d9195a7SDavid du Colombier 		if(reg.fd[ra] < reg.fd[rb]) {
4587d9195a7SDavid du Colombier 			fc = CRLT;
4597d9195a7SDavid du Colombier 			break;
4607d9195a7SDavid du Colombier 		}
4617d9195a7SDavid du Colombier 		if(reg.fd[ra] > reg.fd[rb]) {
4627d9195a7SDavid du Colombier 			fc = CRGT;
4637d9195a7SDavid du Colombier 			break;
4647d9195a7SDavid du Colombier 		}
4657d9195a7SDavid du Colombier 		print("qi: fcmp error\n");
4667d9195a7SDavid du Colombier 		break;
4677d9195a7SDavid du Colombier 	case 32:
4687d9195a7SDavid du Colombier 		if(trace)
4697d9195a7SDavid du Colombier 			itrace("fcmpo\tcr%d,f%d,f%d", rd, ra, rb);
4707d9195a7SDavid du Colombier 		if(isNaN(reg.fd[ra]) || isNaN(reg.fd[rb])) {	/* BUG: depends whether quiet or signalling ... */
4717d9195a7SDavid du Colombier 			fc = CRFU;
4727d9195a7SDavid du Colombier 			Bprint(bioout, "invalid_fp_register\n");
4737d9195a7SDavid du Colombier 			longjmp(errjmp, 0);
4747d9195a7SDavid du Colombier 		}
4757d9195a7SDavid du Colombier 		if(reg.fd[ra] == reg.fd[rb]) {
4767d9195a7SDavid du Colombier 			fc = CREQ;
4777d9195a7SDavid du Colombier 			break;
4787d9195a7SDavid du Colombier 		}
4797d9195a7SDavid du Colombier 		if(reg.fd[ra] < reg.fd[rb]) {
4807d9195a7SDavid du Colombier 			fc = CRLT;
4817d9195a7SDavid du Colombier 			break;
4827d9195a7SDavid du Colombier 		}
4837d9195a7SDavid du Colombier 		if(reg.fd[ra] > reg.fd[rb]) {
4847d9195a7SDavid du Colombier 			fc = CRGT;
4857d9195a7SDavid du Colombier 			break;
4867d9195a7SDavid du Colombier 		}
4877d9195a7SDavid du Colombier 		print("qi: fcmp error\n");
4887d9195a7SDavid du Colombier 		break;
4897d9195a7SDavid du Colombier 
4907d9195a7SDavid du Colombier 	}
4917d9195a7SDavid du Colombier 	fc >>= 28;
4927d9195a7SDavid du Colombier 	reg.cr = (reg.cr & ~mkCR(rd,~0)) | mkCR(rd, fc);
4937d9195a7SDavid du Colombier 	reg.fpscr = (reg.fpscr & ~0xF800) | (fc<<11);
4947d9195a7SDavid du Colombier 	/* BUG: update FX, VXSNAN, VXVC */
4957d9195a7SDavid du Colombier }
4967d9195a7SDavid du Colombier 
4977d9195a7SDavid du Colombier /*
4987d9195a7SDavid du Colombier  * the farith functions probably don't produce the right results
4997d9195a7SDavid du Colombier  * in the presence of NaNs, Infs, etc., esp. wrt exception handling,
5007d9195a7SDavid du Colombier  */
5017d9195a7SDavid du Colombier void
fariths(ulong ir)5027d9195a7SDavid du Colombier fariths(ulong ir)
5037d9195a7SDavid du Colombier {
5047d9195a7SDavid du Colombier 	int rd, ra, rb, rc, fmt;
5057d9195a7SDavid du Colombier 	char *cc;
5067d9195a7SDavid du Colombier 	ulong fpscr;
5077d9195a7SDavid du Colombier 
5087d9195a7SDavid du Colombier 	fmt = 0;
5097d9195a7SDavid du Colombier 	rc = (ir>>6)&0x1F;
5107d9195a7SDavid du Colombier 	getarrr(ir);
5117d9195a7SDavid du Colombier 	switch(getxo(ir)&0x1F) {	/* partial XO decode */
5127d9195a7SDavid du Colombier 	default:
5137d9195a7SDavid du Colombier 		undef(ir);
5147d9195a7SDavid du Colombier 	case 18:
5157d9195a7SDavid du Colombier 		if((float)reg.fd[rb] == 0.0) {
5167d9195a7SDavid du Colombier 			Bprint(bioout, "fp_exception ZX\n");
5177d9195a7SDavid du Colombier 			reg.fpscr |= FPS_ZX | FPS_FX;
5187d9195a7SDavid du Colombier 			longjmp(errjmp, 0);
5197d9195a7SDavid du Colombier 		}
5207d9195a7SDavid du Colombier 		reg.fd[rd] = (float)(reg.fd[ra] / reg.fd[rb]);
5217d9195a7SDavid du Colombier 		break;
5227d9195a7SDavid du Colombier 	case 20:
5237d9195a7SDavid du Colombier 		reg.fd[rd] = (float)(reg.fd[ra] - reg.fd[rb]);
5247d9195a7SDavid du Colombier 		break;
5257d9195a7SDavid du Colombier 	case 21:
5267d9195a7SDavid du Colombier 		reg.fd[rd] = (float)(reg.fd[ra] + reg.fd[rb]);
5277d9195a7SDavid du Colombier 		break;
5287d9195a7SDavid du Colombier 	case 25:
5297d9195a7SDavid du Colombier 		reg.fd[rd] = (float)(reg.fd[ra] * reg.fd[rc]);
5307d9195a7SDavid du Colombier 		rb = rc;
5317d9195a7SDavid du Colombier 		break;
5327d9195a7SDavid du Colombier 	case 28:
5337d9195a7SDavid du Colombier 		reg.fd[rd] = (float)((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]);
5347d9195a7SDavid du Colombier 		fmt = 2;
5357d9195a7SDavid du Colombier 		break;
5367d9195a7SDavid du Colombier 	case 29:
5377d9195a7SDavid du Colombier 		reg.fd[rd] = (float)((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]);
5387d9195a7SDavid du Colombier 		fmt = 2;
5397d9195a7SDavid du Colombier 		break;
5407d9195a7SDavid du Colombier 	case 30:
5417d9195a7SDavid du Colombier 		reg.fd[rd] = (float)-((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]);
5427d9195a7SDavid du Colombier 		fmt = 2;
5437d9195a7SDavid du Colombier 		break;
5447d9195a7SDavid du Colombier 	case 31:
5457d9195a7SDavid du Colombier 		reg.fd[rd] = (float)-((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]);
5467d9195a7SDavid du Colombier 		fmt = 2;
5477d9195a7SDavid du Colombier 		break;
5487d9195a7SDavid du Colombier 	}
5497d9195a7SDavid du Colombier 	if(fmt==1 && ra)
5507d9195a7SDavid du Colombier 		undef(ir);
5517d9195a7SDavid du Colombier 	fpscr = setfpscr();
5527d9195a7SDavid du Colombier 	setfpcc(reg.fd[rd]);
5537d9195a7SDavid du Colombier 	cc = "";
5547d9195a7SDavid du Colombier 	if(ir & 1) {
5557d9195a7SDavid du Colombier 		cc = ".";
5567d9195a7SDavid du Colombier 		reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
5577d9195a7SDavid du Colombier 	}
5587d9195a7SDavid du Colombier 	if(trace) {
5597d9195a7SDavid du Colombier 		switch(fmt) {
5607d9195a7SDavid du Colombier 		case 0:
5617d9195a7SDavid du Colombier 			itrace("%s%s\tfr%d,fr%d,fr%d", ci->name, cc, rd, ra, rb);
5627d9195a7SDavid du Colombier 			break;
5637d9195a7SDavid du Colombier 		case 1:
5647d9195a7SDavid du Colombier 			itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb);
5657d9195a7SDavid du Colombier 			break;
5667d9195a7SDavid du Colombier 		case 2:
5677d9195a7SDavid du Colombier 			itrace("%s%s\tfr%d,fr%d,fr%d,fr%d", ci->name, cc, rd, ra, rc, rb);
5687d9195a7SDavid du Colombier 			break;
5697d9195a7SDavid du Colombier 		}
5707d9195a7SDavid du Colombier 	}
5717d9195a7SDavid du Colombier }
5727d9195a7SDavid du Colombier 
5737d9195a7SDavid du Colombier void
farith(ulong ir)5747d9195a7SDavid du Colombier farith(ulong ir)
5757d9195a7SDavid du Colombier {
5767d9195a7SDavid du Colombier 	vlong vl;
5777d9195a7SDavid du Colombier 	int rd, ra, rb, rc, fmt;
5787d9195a7SDavid du Colombier 	char *cc;
5797d9195a7SDavid du Colombier 	ulong fpscr;
5807d9195a7SDavid du Colombier 	int nocc;
5817d9195a7SDavid du Colombier 	double d;
5827d9195a7SDavid du Colombier 
5837d9195a7SDavid du Colombier 	fmt = 0;
5847d9195a7SDavid du Colombier 	nocc = 0;
5857d9195a7SDavid du Colombier 	rc = (ir>>6)&0x1F;
5867d9195a7SDavid du Colombier 	getarrr(ir);
5877d9195a7SDavid du Colombier 	switch(getxo(ir)&0x1F) { /* partial XO decode */
5887d9195a7SDavid du Colombier 	default:
5897d9195a7SDavid du Colombier 		undef(ir);
5907d9195a7SDavid du Colombier 	case 12:	/* frsp */
5917d9195a7SDavid du Colombier 		reg.fd[rd] = (float)reg.fd[rb];
5927d9195a7SDavid du Colombier 		fmt = 1;
5937d9195a7SDavid du Colombier 		break;
5947d9195a7SDavid du Colombier 	case 14:	/* fctiw */	/* BUG: ignores rounding mode */
5957d9195a7SDavid du Colombier 	case 15:	/* fctiwz */
5967d9195a7SDavid du Colombier 		d = reg.fd[rb];
5977d9195a7SDavid du Colombier 		if(d >= 0x7fffffff)
5987d9195a7SDavid du Colombier 			vl = 0x7fffffff;
5997d9195a7SDavid du Colombier 		else if(d < 0x80000000)
6007d9195a7SDavid du Colombier 			vl = 0x80000000;
6017d9195a7SDavid du Colombier 		else
6027d9195a7SDavid du Colombier 			vl = d;
603*6891d857SDavid du Colombier 		reg.fd[rd] = v2fp(vl);
6047d9195a7SDavid du Colombier 		fmt = 1;
6057d9195a7SDavid du Colombier 		nocc = 1;
6067d9195a7SDavid du Colombier 		break;
6077d9195a7SDavid du Colombier 	case 18:
6087d9195a7SDavid du Colombier 		if(reg.fd[rb] == 0.0) {
6097d9195a7SDavid du Colombier 			Bprint(bioout, "fp_exception ZX\n");
6107d9195a7SDavid du Colombier 			reg.fpscr |= FPS_ZX | FPS_FX;
6117d9195a7SDavid du Colombier 			longjmp(errjmp, 0);
6127d9195a7SDavid du Colombier 		}
6137d9195a7SDavid du Colombier 		reg.fd[rd] = reg.fd[ra] / reg.fd[rb];
6147d9195a7SDavid du Colombier 		break;
6157d9195a7SDavid du Colombier 	case 20:
6167d9195a7SDavid du Colombier 		reg.fd[rd] = reg.fd[ra] - reg.fd[rb];
6177d9195a7SDavid du Colombier 		break;
6187d9195a7SDavid du Colombier 	case 21:
6197d9195a7SDavid du Colombier 		reg.fd[rd] = reg.fd[ra] + reg.fd[rb];
6207d9195a7SDavid du Colombier 		break;
6217d9195a7SDavid du Colombier 	case 25:
6227d9195a7SDavid du Colombier 		reg.fd[rd] = reg.fd[ra] * reg.fd[rc];
6237d9195a7SDavid du Colombier 		rb = rc;
6247d9195a7SDavid du Colombier 		break;
6257d9195a7SDavid du Colombier 	case 28:
6267d9195a7SDavid du Colombier 		reg.fd[rd] = (reg.fd[ra] * reg.fd[rc]) - reg.fd[rb];
6277d9195a7SDavid du Colombier 		fmt = 2;
6287d9195a7SDavid du Colombier 		break;
6297d9195a7SDavid du Colombier 	case 29:
6307d9195a7SDavid du Colombier 		reg.fd[rd] = (reg.fd[ra] * reg.fd[rc]) + reg.fd[rb];
6317d9195a7SDavid du Colombier 		fmt = 2;
6327d9195a7SDavid du Colombier 		break;
6337d9195a7SDavid du Colombier 	case 30:
6347d9195a7SDavid du Colombier 		reg.fd[rd] = -((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]);
6357d9195a7SDavid du Colombier 		fmt = 2;
6367d9195a7SDavid du Colombier 		break;
6377d9195a7SDavid du Colombier 	case 31:
6387d9195a7SDavid du Colombier 		reg.fd[rd] = -((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]);
6397d9195a7SDavid du Colombier 		fmt = 2;
6407d9195a7SDavid du Colombier 		break;
6417d9195a7SDavid du Colombier 	}
6427d9195a7SDavid du Colombier 	if(fmt==1 && ra)
6437d9195a7SDavid du Colombier 		undef(ir);
6447d9195a7SDavid du Colombier 	fpscr = setfpscr();
6457d9195a7SDavid du Colombier 	if(nocc == 0)
6467d9195a7SDavid du Colombier 		setfpcc(reg.fd[rd]);
6477d9195a7SDavid du Colombier 	cc = "";
6487d9195a7SDavid du Colombier 	if(ir & 1) {
6497d9195a7SDavid du Colombier 		cc = ".";
6507d9195a7SDavid du Colombier 		reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
6517d9195a7SDavid du Colombier 	}
6527d9195a7SDavid du Colombier 	if(trace) {
6537d9195a7SDavid du Colombier 		switch(fmt) {
6547d9195a7SDavid du Colombier 		case 0:
6557d9195a7SDavid du Colombier 			itrace("%s%s\tfr%d,fr%d,fr%d", ci->name, cc, rd, ra, rb);
6567d9195a7SDavid du Colombier 			break;
6577d9195a7SDavid du Colombier 		case 1:
6587d9195a7SDavid du Colombier 			itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb);
6597d9195a7SDavid du Colombier 			break;
6607d9195a7SDavid du Colombier 		case 2:
6617d9195a7SDavid du Colombier 			itrace("%s%s\tfr%d,fr%d,fr%d,fr%d", ci->name, cc, rd, ra, rc, rb);
6627d9195a7SDavid du Colombier 			break;
6637d9195a7SDavid du Colombier 		}
6647d9195a7SDavid du Colombier 	}
6657d9195a7SDavid du Colombier }
6667d9195a7SDavid du Colombier 
6677d9195a7SDavid du Colombier void
farith2(ulong ir)6687d9195a7SDavid du Colombier farith2(ulong ir)
6697d9195a7SDavid du Colombier {
6707d9195a7SDavid du Colombier 	int rd, ra, rb;
6717d9195a7SDavid du Colombier 	char *cc;
6727d9195a7SDavid du Colombier 	ulong fpscr;
6737d9195a7SDavid du Colombier 
6747d9195a7SDavid du Colombier 	getarrr(ir);
6757d9195a7SDavid du Colombier 	switch(getxo(ir)) { /* full XO decode */
6767d9195a7SDavid du Colombier 	default:
6777d9195a7SDavid du Colombier 		undef(ir);
6787d9195a7SDavid du Colombier 	case 40:
6797d9195a7SDavid du Colombier 		reg.fd[rd] = -reg.fd[rb];
6807d9195a7SDavid du Colombier 		break;
6817d9195a7SDavid du Colombier 	case 72:
6827d9195a7SDavid du Colombier 		reg.fd[rd] = reg.fd[rb];
6837d9195a7SDavid du Colombier 		break;
6847d9195a7SDavid du Colombier 	case 136:
6857d9195a7SDavid du Colombier 		reg.fd[rd] = -fabs(reg.fd[rb]);
6867d9195a7SDavid du Colombier 		break;
6877d9195a7SDavid du Colombier 	case 264:
6887d9195a7SDavid du Colombier 		reg.fd[rd] = fabs(reg.fd[rb]);
6897d9195a7SDavid du Colombier 		break;
6907d9195a7SDavid du Colombier 	}
6917d9195a7SDavid du Colombier 	if(ra)
6927d9195a7SDavid du Colombier 		undef(ir);
6937d9195a7SDavid du Colombier 	fpscr = setfpscr();
6947d9195a7SDavid du Colombier 	setfpcc(reg.fd[rd]);
6957d9195a7SDavid du Colombier 	cc = "";
6967d9195a7SDavid du Colombier 	if(ir & 1) {
6977d9195a7SDavid du Colombier 		cc = ".";
6987d9195a7SDavid du Colombier 		reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
6997d9195a7SDavid du Colombier 	}
7007d9195a7SDavid du Colombier 	if(trace)
7017d9195a7SDavid du Colombier 		itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb);
7027d9195a7SDavid du Colombier }
7037d9195a7SDavid du Colombier 
7047d9195a7SDavid du Colombier ulong
setfpscr(void)7057d9195a7SDavid du Colombier setfpscr(void)
7067d9195a7SDavid du Colombier {
7077d9195a7SDavid du Colombier 	ulong fps, fpscr;
7087d9195a7SDavid du Colombier 
7097d9195a7SDavid du Colombier 	fps = getfsr();
7107d9195a7SDavid du Colombier 	fpscr = reg.fpscr;
7117d9195a7SDavid du Colombier 	if(fps & FPAOVFL)
7127d9195a7SDavid du Colombier 		fpscr |= FPS_OX;
7137d9195a7SDavid du Colombier 	if(fps & FPAINEX)
7147d9195a7SDavid du Colombier 		fpscr |= FPS_XX;
7157d9195a7SDavid du Colombier 	if(fps & FPAUNFL)
7167d9195a7SDavid du Colombier 		fpscr |= FPS_UX;
7177d9195a7SDavid du Colombier 	if(fps & FPAZDIV)
7187d9195a7SDavid du Colombier 		fpscr |= FPS_ZX;
7197d9195a7SDavid du Colombier 	if(fpscr != reg.fpscr) {
7207d9195a7SDavid du Colombier 		fpscr |= FPS_FX;
7217d9195a7SDavid du Colombier 		reg.fpscr = fpscr;
7227d9195a7SDavid du Colombier 	}
7237d9195a7SDavid du Colombier 	return fpscr;
7247d9195a7SDavid du Colombier }
7257d9195a7SDavid du Colombier 
7267d9195a7SDavid du Colombier void
setfpcc(double r)7277d9195a7SDavid du Colombier setfpcc(double r)
7287d9195a7SDavid du Colombier {
7297d9195a7SDavid du Colombier 	int c;
7307d9195a7SDavid du Colombier 
7317d9195a7SDavid du Colombier 	c = 0;
7327d9195a7SDavid du Colombier 	if(r == 0)
7337d9195a7SDavid du Colombier 		c |= 2;
7347d9195a7SDavid du Colombier 	else if(r < 0)
7357d9195a7SDavid du Colombier 		c |= 4;
7367d9195a7SDavid du Colombier 	else
7377d9195a7SDavid du Colombier 		c |= 8;
7387d9195a7SDavid du Colombier 	if(isNaN(r))
7397d9195a7SDavid du Colombier 		c |= 1;
7407d9195a7SDavid du Colombier 	reg.fpscr = (reg.fpscr & ~0xF800) | (0<<15) | (c<<11); /* unsure about class bit */
7417d9195a7SDavid du Colombier }
742