xref: /plan9-contrib/sys/src/9/vt4/fpipower.c (revision d6dfd9ef91cf0fa8514a249d5f2a550978c19369)
1*d6dfd9efSDavid du Colombier /*
2*d6dfd9efSDavid du Colombier  * this doesn't attempt to implement Power architecture floating-point properties
3*d6dfd9efSDavid du Colombier  * that aren't visible in the Inferno environment.
4*d6dfd9efSDavid du Colombier  * all arithmetic is done in double precision.
5*d6dfd9efSDavid du Colombier  * the FP trap status isn't updated.
6*d6dfd9efSDavid du Colombier  */
7*d6dfd9efSDavid du Colombier #include	"u.h"
8*d6dfd9efSDavid du Colombier #include	"../port/lib.h"
9*d6dfd9efSDavid du Colombier #include	"mem.h"
10*d6dfd9efSDavid du Colombier #include	"dat.h"
11*d6dfd9efSDavid du Colombier #include	"fns.h"
12*d6dfd9efSDavid du Colombier 
13*d6dfd9efSDavid du Colombier #include	"ureg.h"
14*d6dfd9efSDavid du Colombier 
15*d6dfd9efSDavid du Colombier #include	"fpi.h"
16*d6dfd9efSDavid du Colombier 
17*d6dfd9efSDavid du Colombier #define	REG(x) (*(long*)(((char*)em->ur)+roff[(x)]))
18*d6dfd9efSDavid du Colombier #define	FR(x) (*(Internal*)em->fr[(x)&0x1F])
19*d6dfd9efSDavid du Colombier #define	REGSP	0	/* in Plan 9, the user and kernel stacks are different */
20*d6dfd9efSDavid du Colombier 
21*d6dfd9efSDavid du Colombier #define	getulong(a) (*(ulong*)(a))
22*d6dfd9efSDavid du Colombier 
23*d6dfd9efSDavid du Colombier enum {
24*d6dfd9efSDavid du Colombier 	CRLT = 1<<31,
25*d6dfd9efSDavid du Colombier 	CRGT = 1<<30,
26*d6dfd9efSDavid du Colombier 	CREQ = 1<<29,
27*d6dfd9efSDavid du Colombier 	CRSO = 1<<28,
28*d6dfd9efSDavid du Colombier 	CRFU = CRSO,
29*d6dfd9efSDavid du Colombier 
30*d6dfd9efSDavid du Colombier 	CRFX = 1<<27,
31*d6dfd9efSDavid du Colombier 	CRFEX = 1<<26,
32*d6dfd9efSDavid du Colombier 	CRVX = 1<<25,
33*d6dfd9efSDavid du Colombier 	CROX = 1<<24,
34*d6dfd9efSDavid du Colombier };
35*d6dfd9efSDavid du Colombier 
36*d6dfd9efSDavid du Colombier #define getCR(x,w) (((w)>>(28-(x*4)))&0xF)
37*d6dfd9efSDavid du Colombier #define mkCR(x,v) (((v)&0xF)<<(28-(x*4)))
38*d6dfd9efSDavid du Colombier 
39*d6dfd9efSDavid du Colombier #define simm(xx, ii)	xx = (short)(ii&0xFFFF);
40*d6dfd9efSDavid du Colombier #define getairr(i)	rd = (i>>21)&0x1f; ra = (i>>16)&0x1f; simm(imm,i)
41*d6dfd9efSDavid du Colombier #define getarrr(i)	rd = (i>>21)&0x1f; ra = (i>>16)&0x1f; rb = (i>>11)&0x1f;
42*d6dfd9efSDavid du Colombier #define getop(i) ((i>>26)&0x3F)
43*d6dfd9efSDavid du Colombier #define getxo(i) ((i>>1)&0x3FF)
44*d6dfd9efSDavid du Colombier 
45*d6dfd9efSDavid du Colombier #define	FPS_FX	(1<<31)	/* exception summary (sticky) */
46*d6dfd9efSDavid du Colombier #define	FPS_EX	(1<<30)	/* enabled exception summary */
47*d6dfd9efSDavid du Colombier #define	FPS_VX	(1<<29)	/* invalid operation exception summary */
48*d6dfd9efSDavid du Colombier #define	FPS_OX	(1<<28)	/* overflow exception OX (sticky) */
49*d6dfd9efSDavid du Colombier #define	FPS_UX	(1<<27)	/* underflow exception UX (sticky) */
50*d6dfd9efSDavid du Colombier #define	FPS_ZX	(1<<26)	/* zero divide exception ZX (sticky) */
51*d6dfd9efSDavid du Colombier #define	FPS_XX	(1<<25)	/* inexact exception XX (sticky) */
52*d6dfd9efSDavid du Colombier #define	FPS_VXSNAN (1<<24)	/* invalid operation exception for SNaN (sticky) */
53*d6dfd9efSDavid du Colombier #define	FPS_VXISI	(1<<23)	/* invalid operation exception for ∞-∞ (sticky) */
54*d6dfd9efSDavid du Colombier #define	FPS_VXIDI	(1<<22)	/* invalid operation exception for ∞/∞ (sticky) */
55*d6dfd9efSDavid du Colombier #define	FPS_VXZDZ (1<<21)	/* invalid operation exception for 0/0 (sticky) */
56*d6dfd9efSDavid du Colombier #define	FPS_VXIMZ	(1<<20)	/* invalid operation exception for ∞*0 (sticky) */
57*d6dfd9efSDavid du Colombier #define	FPS_VXVC	(1<<19)	/* invalid operation exception for invalid compare (sticky) */
58*d6dfd9efSDavid du Colombier #define	FPS_FR	(1<<18)	/* fraction rounded */
59*d6dfd9efSDavid du Colombier #define	FPS_FI	(1<<17)	/* fraction inexact */
60*d6dfd9efSDavid du Colombier #define	FPS_FPRF	(1<<16)	/* floating point result class */
61*d6dfd9efSDavid du Colombier #define	FPS_FPCC	(0xF<<12)	/* <, >, =, unordered */
62*d6dfd9efSDavid du Colombier #define	FPS_VXCVI	(1<<8)	/* enable exception for invalid integer convert (sticky) */
63*d6dfd9efSDavid du Colombier #define	FPS_VE	(1<<7)	/* invalid operation exception enable */
64*d6dfd9efSDavid du Colombier #define	FPS_OE	(1<<6)	/* enable overflow exceptions */
65*d6dfd9efSDavid du Colombier #define	FPS_UE	(1<<5)	/* enable underflow */
66*d6dfd9efSDavid du Colombier #define	FPS_ZE	(1<<4)	/* enable zero divide */
67*d6dfd9efSDavid du Colombier #define	FPS_XE	(1<<3)	/* enable inexact exceptions */
68*d6dfd9efSDavid du Colombier #define	FPS_RN	(3<<0)	/* rounding mode */
69*d6dfd9efSDavid du Colombier 
70*d6dfd9efSDavid du Colombier typedef struct Emreg Emreg;
71*d6dfd9efSDavid du Colombier 
72*d6dfd9efSDavid du Colombier struct Emreg {
73*d6dfd9efSDavid du Colombier 	Ureg*	ur;
74*d6dfd9efSDavid du Colombier 	ulong	(*fr)[3];
75*d6dfd9efSDavid du Colombier 	FPsave*	ufp;
76*d6dfd9efSDavid du Colombier 	ulong	ir;
77*d6dfd9efSDavid du Colombier 	char*	name;
78*d6dfd9efSDavid du Colombier };
79*d6dfd9efSDavid du Colombier 
80*d6dfd9efSDavid du Colombier int	fpemudebug = 0;
81*d6dfd9efSDavid du Colombier 
82*d6dfd9efSDavid du Colombier #undef OFR
83*d6dfd9efSDavid du Colombier #define	OFR(X)	((ulong)&((Ureg*)0)->X)
84*d6dfd9efSDavid du Colombier 
85*d6dfd9efSDavid du Colombier static	int	roff[] = {
86*d6dfd9efSDavid du Colombier 	OFR(r0), OFR(r1), OFR(r2), OFR(r3),
87*d6dfd9efSDavid du Colombier 	OFR(r4), OFR(r5), OFR(r6), OFR(r7),
88*d6dfd9efSDavid du Colombier 	OFR(r8), OFR(r9), OFR(r10), OFR(r11),
89*d6dfd9efSDavid du Colombier 	OFR(r12), OFR(r13), OFR(r14), OFR(r15),
90*d6dfd9efSDavid du Colombier 	OFR(r16), OFR(r17), OFR(r18), OFR(r19),
91*d6dfd9efSDavid du Colombier 	OFR(r20), OFR(r21), OFR(r22), OFR(r23),
92*d6dfd9efSDavid du Colombier 	OFR(r24), OFR(r25), OFR(r26), OFR(r27),
93*d6dfd9efSDavid du Colombier 	OFR(r28), OFR(r29), OFR(r30), OFR(r31),
94*d6dfd9efSDavid du Colombier };
95*d6dfd9efSDavid du Colombier 
96*d6dfd9efSDavid du Colombier /*
97*d6dfd9efSDavid du Colombier  * initial FP register values assumed by qc's code
98*d6dfd9efSDavid du Colombier  */
99*d6dfd9efSDavid du Colombier static Internal fpreginit[] = {
100*d6dfd9efSDavid du Colombier 	/* s, e, l, h */
101*d6dfd9efSDavid du Colombier 	{0, 0x400, 0x00000000, 0x08000000},	/* F31=2.0 */
102*d6dfd9efSDavid du Colombier 	{0, 0x3FF, 0x00000000, 0x08000000},	/* F30=1.0 */
103*d6dfd9efSDavid du Colombier 	{0, 0x3FE, 0x00000000, 0x08000000},	/* F29=0.5 */
104*d6dfd9efSDavid du Colombier 	{0, 0x1, 0x00000000, 0x00000000}, /* F28=0.0 */
105*d6dfd9efSDavid du Colombier 	{0, 0x433, 0x00000000, 0x08000040},	/* F27=FREGCVI */
106*d6dfd9efSDavid du Colombier };
107*d6dfd9efSDavid du Colombier 
108*d6dfd9efSDavid du Colombier static void
fadd(Emreg * em,Internal * d,int ra,int rb)109*d6dfd9efSDavid du Colombier fadd(Emreg *em, Internal *d, int ra, int rb)
110*d6dfd9efSDavid du Colombier {
111*d6dfd9efSDavid du Colombier 	Internal a, b;
112*d6dfd9efSDavid du Colombier 
113*d6dfd9efSDavid du Colombier 	a = FR(ra);
114*d6dfd9efSDavid du Colombier 	b = FR(rb);
115*d6dfd9efSDavid du Colombier 	(a.s == b.s? fpiadd: fpisub)(&b, &a, d);
116*d6dfd9efSDavid du Colombier }
117*d6dfd9efSDavid du Colombier 
118*d6dfd9efSDavid du Colombier static void
fsub(Emreg * em,Internal * d,int ra,int rb)119*d6dfd9efSDavid du Colombier fsub(Emreg *em, Internal *d, int ra, int rb)
120*d6dfd9efSDavid du Colombier {
121*d6dfd9efSDavid du Colombier 	Internal a, b;
122*d6dfd9efSDavid du Colombier 
123*d6dfd9efSDavid du Colombier 	a = FR(ra);
124*d6dfd9efSDavid du Colombier 	b = FR(rb);
125*d6dfd9efSDavid du Colombier 	b.s ^= 1;
126*d6dfd9efSDavid du Colombier 	(b.s == a.s? fpiadd: fpisub)(&b, &a, d);
127*d6dfd9efSDavid du Colombier }
128*d6dfd9efSDavid du Colombier 
129*d6dfd9efSDavid du Colombier static void
fmul(Emreg * em,Internal * d,int ra,int rb)130*d6dfd9efSDavid du Colombier fmul(Emreg *em, Internal *d, int ra, int rb)
131*d6dfd9efSDavid du Colombier {
132*d6dfd9efSDavid du Colombier 	Internal a, b;
133*d6dfd9efSDavid du Colombier 
134*d6dfd9efSDavid du Colombier 	a = FR(ra);
135*d6dfd9efSDavid du Colombier 	b = FR(rb);
136*d6dfd9efSDavid du Colombier 	fpimul(&b, &a, d);
137*d6dfd9efSDavid du Colombier }
138*d6dfd9efSDavid du Colombier 
139*d6dfd9efSDavid du Colombier static void
fdiv(Emreg * em,Internal * d,int ra,int rb)140*d6dfd9efSDavid du Colombier fdiv(Emreg *em, Internal *d, int ra, int rb)
141*d6dfd9efSDavid du Colombier {
142*d6dfd9efSDavid du Colombier 	Internal a, b;
143*d6dfd9efSDavid du Colombier 
144*d6dfd9efSDavid du Colombier 	a = FR(ra);
145*d6dfd9efSDavid du Colombier 	b = FR(rb);
146*d6dfd9efSDavid du Colombier 	fpidiv(&b, &a, d);
147*d6dfd9efSDavid du Colombier }
148*d6dfd9efSDavid du Colombier 
149*d6dfd9efSDavid du Colombier static void
fmsub(Emreg * em,Internal * d,int ra,int rc,int rb)150*d6dfd9efSDavid du Colombier fmsub(Emreg *em, Internal *d, int ra, int rc, int rb)
151*d6dfd9efSDavid du Colombier {
152*d6dfd9efSDavid du Colombier 	Internal a, c, b, t;
153*d6dfd9efSDavid du Colombier 
154*d6dfd9efSDavid du Colombier 	a = FR(ra);
155*d6dfd9efSDavid du Colombier 	c = FR(rc);
156*d6dfd9efSDavid du Colombier 	b = FR(rb);
157*d6dfd9efSDavid du Colombier 	fpimul(&a, &c, &t);
158*d6dfd9efSDavid du Colombier 	b.s ^= 1;
159*d6dfd9efSDavid du Colombier 	(b.s == t.s? fpiadd: fpisub)(&b, &t, d);
160*d6dfd9efSDavid du Colombier }
161*d6dfd9efSDavid du Colombier 
162*d6dfd9efSDavid du Colombier static void
fmadd(Emreg * em,Internal * d,int ra,int rc,int rb)163*d6dfd9efSDavid du Colombier fmadd(Emreg *em, Internal *d, int ra, int rc, int rb)
164*d6dfd9efSDavid du Colombier {
165*d6dfd9efSDavid du Colombier 	Internal a, c, b, t;
166*d6dfd9efSDavid du Colombier 
167*d6dfd9efSDavid du Colombier 	a = FR(ra);
168*d6dfd9efSDavid du Colombier 	c = FR(rc);
169*d6dfd9efSDavid du Colombier 	b = FR(rb);
170*d6dfd9efSDavid du Colombier 	fpimul(&a, &c, &t);
171*d6dfd9efSDavid du Colombier 	(t.s == b.s? fpiadd: fpisub)(&b, &t, d);
172*d6dfd9efSDavid du Colombier }
173*d6dfd9efSDavid du Colombier 
174*d6dfd9efSDavid du Colombier static ulong	setfpscr(Emreg*);
175*d6dfd9efSDavid du Colombier static void	setfpcc(Emreg*, int);
176*d6dfd9efSDavid du Colombier 
177*d6dfd9efSDavid du Colombier static void
unimp(Emreg * em,ulong op)178*d6dfd9efSDavid du Colombier unimp(Emreg *em, ulong op)
179*d6dfd9efSDavid du Colombier {
180*d6dfd9efSDavid du Colombier 	char buf[60];
181*d6dfd9efSDavid du Colombier 
182*d6dfd9efSDavid du Colombier 	snprint(buf, sizeof(buf), "sys: fp: pc=%lux unimp fp 0x%.8lux", em->ur->pc, op);
183*d6dfd9efSDavid du Colombier 	if(fpemudebug)
184*d6dfd9efSDavid du Colombier 		print("FPE: %s\n", buf);
185*d6dfd9efSDavid du Colombier 	error(buf);
186*d6dfd9efSDavid du Colombier 	/* no return */
187*d6dfd9efSDavid du Colombier }
188*d6dfd9efSDavid du Colombier 
189*d6dfd9efSDavid du Colombier /*
190*d6dfd9efSDavid du Colombier  * floating load/store
191*d6dfd9efSDavid du Colombier  */
192*d6dfd9efSDavid du Colombier 
193*d6dfd9efSDavid du Colombier static void
fpeairr(Emreg * em,ulong ir,void ** eap,int * rdp)194*d6dfd9efSDavid du Colombier fpeairr(Emreg *em, ulong ir, void **eap, int *rdp)
195*d6dfd9efSDavid du Colombier {
196*d6dfd9efSDavid du Colombier 	ulong ea;
197*d6dfd9efSDavid du Colombier 	long imm;
198*d6dfd9efSDavid du Colombier 	int ra, rd, upd;
199*d6dfd9efSDavid du Colombier 
200*d6dfd9efSDavid du Colombier 	getairr(ir);
201*d6dfd9efSDavid du Colombier 	ea = imm;
202*d6dfd9efSDavid du Colombier 	upd = (ir&(1L<<26))!=0;
203*d6dfd9efSDavid du Colombier 	if(ra) {
204*d6dfd9efSDavid du Colombier 		ea += REG(ra);
205*d6dfd9efSDavid du Colombier 		if(upd){
206*d6dfd9efSDavid du Colombier 			if(REGSP && ra == REGSP)
207*d6dfd9efSDavid du Colombier 				panic("fpemu: r1 update");	/* can't do it because we're running on the same stack */
208*d6dfd9efSDavid du Colombier 			REG(ra) = ea;
209*d6dfd9efSDavid du Colombier 		}
210*d6dfd9efSDavid du Colombier 	} else {
211*d6dfd9efSDavid du Colombier 		if(upd)
212*d6dfd9efSDavid du Colombier 			unimp(em, ir);
213*d6dfd9efSDavid du Colombier 	}
214*d6dfd9efSDavid du Colombier 	*rdp = rd;
215*d6dfd9efSDavid du Colombier 	*eap = (void*)ea;
216*d6dfd9efSDavid du Colombier 	if(fpemudebug)
217*d6dfd9efSDavid du Colombier 		print("%8.8lux %s\tf%d,%ld(r%d) ea=%lux upd=%d\n", em->ur->pc, em->name, rd, imm, ra, ea, upd);
218*d6dfd9efSDavid du Colombier }
219*d6dfd9efSDavid du Colombier 
220*d6dfd9efSDavid du Colombier static void
fpearrr(Emreg * em,ulong ir,int upd,void ** eap,int * rdp)221*d6dfd9efSDavid du Colombier fpearrr(Emreg *em, ulong ir, int upd, void **eap, int *rdp)
222*d6dfd9efSDavid du Colombier {
223*d6dfd9efSDavid du Colombier 	ulong ea;
224*d6dfd9efSDavid du Colombier 	int ra, rb, rd;
225*d6dfd9efSDavid du Colombier 
226*d6dfd9efSDavid du Colombier 	getarrr(ir);
227*d6dfd9efSDavid du Colombier 	ea = REG(rb);
228*d6dfd9efSDavid du Colombier 	if(ra){
229*d6dfd9efSDavid du Colombier 		ea += REG(ra);
230*d6dfd9efSDavid du Colombier 		if(upd){
231*d6dfd9efSDavid du Colombier 			if(REGSP && ra == REGSP)
232*d6dfd9efSDavid du Colombier 				panic("fpemu: r1 update");
233*d6dfd9efSDavid du Colombier 			REG(ra) = ea;
234*d6dfd9efSDavid du Colombier 		}
235*d6dfd9efSDavid du Colombier 		if(fpemudebug)
236*d6dfd9efSDavid du Colombier 			print("%8.8lux %s\tf%d,(r%d+r%d) ea=%lux upd=%d\n", em->ur->pc, em->name, rd, ra, rb, ea, upd);
237*d6dfd9efSDavid du Colombier 	} else {
238*d6dfd9efSDavid du Colombier 		if(upd)
239*d6dfd9efSDavid du Colombier 			unimp(em, ir);
240*d6dfd9efSDavid du Colombier 		if(fpemudebug)
241*d6dfd9efSDavid du Colombier 			print("%8.8lux %s\tf%d,(r%d) ea=%lux\n", em->ur->pc, em->name, rd, rb, ea);
242*d6dfd9efSDavid du Colombier 	}
243*d6dfd9efSDavid du Colombier 	*eap = (void*)ea;
244*d6dfd9efSDavid du Colombier 	*rdp = rd;
245*d6dfd9efSDavid du Colombier }
246*d6dfd9efSDavid du Colombier 
247*d6dfd9efSDavid du Colombier static void
lfs(Emreg * em,ulong ir)248*d6dfd9efSDavid du Colombier lfs(Emreg *em, ulong ir)
249*d6dfd9efSDavid du Colombier {
250*d6dfd9efSDavid du Colombier 	void *ea;
251*d6dfd9efSDavid du Colombier 	int rd;
252*d6dfd9efSDavid du Colombier 
253*d6dfd9efSDavid du Colombier 	em->name = "lfs";
254*d6dfd9efSDavid du Colombier 	fpeairr(em, ir, &ea, &rd);
255*d6dfd9efSDavid du Colombier 	fpis2i(&FR(rd), (void*)ea);
256*d6dfd9efSDavid du Colombier }
257*d6dfd9efSDavid du Colombier 
258*d6dfd9efSDavid du Colombier static void
lfsx(Emreg * em,ulong ir)259*d6dfd9efSDavid du Colombier lfsx(Emreg *em, ulong ir)
260*d6dfd9efSDavid du Colombier {
261*d6dfd9efSDavid du Colombier 	void *ea;
262*d6dfd9efSDavid du Colombier 	int rd;
263*d6dfd9efSDavid du Colombier 
264*d6dfd9efSDavid du Colombier 	em->name = "lfsx";
265*d6dfd9efSDavid du Colombier 	fpearrr(em, ir, ((ir>>1)&0x3FF)==567, &ea, &rd);
266*d6dfd9efSDavid du Colombier 	fpis2i(&FR(rd), (void*)ea);
267*d6dfd9efSDavid du Colombier }
268*d6dfd9efSDavid du Colombier 
269*d6dfd9efSDavid du Colombier static void
lfd(Emreg * em,ulong ir)270*d6dfd9efSDavid du Colombier lfd(Emreg *em, ulong ir)
271*d6dfd9efSDavid du Colombier {
272*d6dfd9efSDavid du Colombier 	void *ea;
273*d6dfd9efSDavid du Colombier 	int rd;
274*d6dfd9efSDavid du Colombier 
275*d6dfd9efSDavid du Colombier 	em->name = "lfd";
276*d6dfd9efSDavid du Colombier 	fpeairr(em, ir, &ea, &rd);
277*d6dfd9efSDavid du Colombier 	fpid2i(&FR(rd), (void*)ea);
278*d6dfd9efSDavid du Colombier }
279*d6dfd9efSDavid du Colombier 
280*d6dfd9efSDavid du Colombier static void
lfdx(Emreg * em,ulong ir)281*d6dfd9efSDavid du Colombier lfdx(Emreg *em, ulong ir)
282*d6dfd9efSDavid du Colombier {
283*d6dfd9efSDavid du Colombier 	void *ea;
284*d6dfd9efSDavid du Colombier 	int rd;
285*d6dfd9efSDavid du Colombier 
286*d6dfd9efSDavid du Colombier 	em->name = "lfdx";
287*d6dfd9efSDavid du Colombier 	fpearrr(em, ir, ((ir>>1)&0x3FF)==631, &ea, &rd);
288*d6dfd9efSDavid du Colombier 	fpid2i(&FR(rd), (void*)ea);
289*d6dfd9efSDavid du Colombier }
290*d6dfd9efSDavid du Colombier 
291*d6dfd9efSDavid du Colombier static void
stfs(Emreg * em,ulong ir)292*d6dfd9efSDavid du Colombier stfs(Emreg *em, ulong ir)
293*d6dfd9efSDavid du Colombier {
294*d6dfd9efSDavid du Colombier 	void *ea;
295*d6dfd9efSDavid du Colombier 	int rd;
296*d6dfd9efSDavid du Colombier 	Internal tmp;
297*d6dfd9efSDavid du Colombier 
298*d6dfd9efSDavid du Colombier 	em->name = "stfs";
299*d6dfd9efSDavid du Colombier 	fpeairr(em, ir, &ea, &rd);
300*d6dfd9efSDavid du Colombier 	tmp = FR(rd);
301*d6dfd9efSDavid du Colombier 	fpii2s(ea, &tmp);
302*d6dfd9efSDavid du Colombier }
303*d6dfd9efSDavid du Colombier 
304*d6dfd9efSDavid du Colombier static void
stfsx(Emreg * em,ulong ir)305*d6dfd9efSDavid du Colombier stfsx(Emreg *em, ulong ir)
306*d6dfd9efSDavid du Colombier {
307*d6dfd9efSDavid du Colombier 	void *ea;
308*d6dfd9efSDavid du Colombier 	int rd;
309*d6dfd9efSDavid du Colombier 	Internal tmp;
310*d6dfd9efSDavid du Colombier 
311*d6dfd9efSDavid du Colombier 	em->name = "stfsx";
312*d6dfd9efSDavid du Colombier 	fpearrr(em, ir, getxo(ir)==695, &ea, &rd);
313*d6dfd9efSDavid du Colombier 	tmp = FR(rd);
314*d6dfd9efSDavid du Colombier 	fpii2s(ea, &tmp);
315*d6dfd9efSDavid du Colombier }
316*d6dfd9efSDavid du Colombier 
317*d6dfd9efSDavid du Colombier static void
stfd(Emreg * em,ulong ir)318*d6dfd9efSDavid du Colombier stfd(Emreg *em, ulong ir)
319*d6dfd9efSDavid du Colombier {
320*d6dfd9efSDavid du Colombier 	void *ea;
321*d6dfd9efSDavid du Colombier 	int rd;
322*d6dfd9efSDavid du Colombier 	Internal tmp;
323*d6dfd9efSDavid du Colombier 
324*d6dfd9efSDavid du Colombier 	em->name = "stfd";
325*d6dfd9efSDavid du Colombier 	fpeairr(em, ir, &ea, &rd);
326*d6dfd9efSDavid du Colombier 	tmp = FR(rd);
327*d6dfd9efSDavid du Colombier 	fpii2d(ea, &tmp);
328*d6dfd9efSDavid du Colombier }
329*d6dfd9efSDavid du Colombier 
330*d6dfd9efSDavid du Colombier static void
stfdx(Emreg * em,ulong ir)331*d6dfd9efSDavid du Colombier stfdx(Emreg *em, ulong ir)
332*d6dfd9efSDavid du Colombier {
333*d6dfd9efSDavid du Colombier 	void *ea;
334*d6dfd9efSDavid du Colombier 	int rd;
335*d6dfd9efSDavid du Colombier 	Internal tmp;
336*d6dfd9efSDavid du Colombier 
337*d6dfd9efSDavid du Colombier 	em->name = "stfdx";
338*d6dfd9efSDavid du Colombier 	fpearrr(em, ir, ((ir>>1)&0x3FF)==759, &ea, &rd);
339*d6dfd9efSDavid du Colombier 	tmp = FR(rd);
340*d6dfd9efSDavid du Colombier 	fpii2d(ea, &tmp);
341*d6dfd9efSDavid du Colombier }
342*d6dfd9efSDavid du Colombier 
343*d6dfd9efSDavid du Colombier static void
mcrfs(Emreg * em,ulong ir)344*d6dfd9efSDavid du Colombier mcrfs(Emreg *em, ulong ir)
345*d6dfd9efSDavid du Colombier {
346*d6dfd9efSDavid du Colombier 	int rd, ra, rb;
347*d6dfd9efSDavid du Colombier 	static ulong fpscr0[] ={
348*d6dfd9efSDavid du Colombier 		FPS_FX|FPS_OX,
349*d6dfd9efSDavid du Colombier 		FPS_UX|FPS_ZX|FPS_XX|FPS_VXSNAN,
350*d6dfd9efSDavid du Colombier 		FPS_VXISI|FPS_VXIDI|FPS_VXZDZ|FPS_VXIMZ,
351*d6dfd9efSDavid du Colombier 		FPS_VXVC,
352*d6dfd9efSDavid du Colombier 		0,
353*d6dfd9efSDavid du Colombier 		FPS_VXCVI,
354*d6dfd9efSDavid du Colombier 	};
355*d6dfd9efSDavid du Colombier 
356*d6dfd9efSDavid du Colombier 	getarrr(ir);
357*d6dfd9efSDavid du Colombier 	if(rb || ra&3 || rd&3)
358*d6dfd9efSDavid du Colombier 		unimp(em, ir);
359*d6dfd9efSDavid du Colombier 	ra >>= 2;
360*d6dfd9efSDavid du Colombier 	rd >>= 2;
361*d6dfd9efSDavid du Colombier 	em->ur->cr = (em->ur->cr & ~mkCR(rd, 0xF)) | mkCR(rd, getCR(ra, em->ufp->fpscr));
362*d6dfd9efSDavid du Colombier 	em->ufp->fpscr &= ~fpscr0[ra];
363*d6dfd9efSDavid du Colombier 	if(fpemudebug)
364*d6dfd9efSDavid du Colombier 		print("%8.8lux mcrfs\tcrf%d,crf%d\n", em->ur->pc, rd, ra);
365*d6dfd9efSDavid du Colombier }
366*d6dfd9efSDavid du Colombier 
367*d6dfd9efSDavid du Colombier static void
mffs(Emreg * em,ulong ir)368*d6dfd9efSDavid du Colombier mffs(Emreg *em, ulong ir)
369*d6dfd9efSDavid du Colombier {
370*d6dfd9efSDavid du Colombier 	int rd, ra, rb;
371*d6dfd9efSDavid du Colombier 	Double dw;
372*d6dfd9efSDavid du Colombier 
373*d6dfd9efSDavid du Colombier 	getarrr(ir);
374*d6dfd9efSDavid du Colombier 	if(ra || rb)
375*d6dfd9efSDavid du Colombier 		unimp(em, ir);
376*d6dfd9efSDavid du Colombier 	dw.h = 0;
377*d6dfd9efSDavid du Colombier 	dw.l = ((uvlong)0xFFF8000L<<16)|em->ufp->fpscr;
378*d6dfd9efSDavid du Colombier 	fpid2i(&FR(rd), &dw);
379*d6dfd9efSDavid du Colombier 	/* it's anyone's guess how CR1 should be set when ir&1 */
380*d6dfd9efSDavid du Colombier 	em->ur->cr &= ~mkCR(1, 0xE);	/* leave SO, reset others */
381*d6dfd9efSDavid du Colombier 	if(fpemudebug)
382*d6dfd9efSDavid du Colombier 		print("%8.8lux mffs%s\tfr%d\n", em->ur->pc, ir&1?".":"", rd);
383*d6dfd9efSDavid du Colombier }
384*d6dfd9efSDavid du Colombier 
385*d6dfd9efSDavid du Colombier static void
mtfsb1(Emreg * em,ulong ir)386*d6dfd9efSDavid du Colombier mtfsb1(Emreg *em, ulong ir)
387*d6dfd9efSDavid du Colombier {
388*d6dfd9efSDavid du Colombier 	int rd, ra, rb;
389*d6dfd9efSDavid du Colombier 
390*d6dfd9efSDavid du Colombier 	getarrr(ir);
391*d6dfd9efSDavid du Colombier 	if(ra || rb)
392*d6dfd9efSDavid du Colombier 		unimp(em, ir);
393*d6dfd9efSDavid du Colombier 	em->ufp->fpscr |= (1L << (31-rd));
394*d6dfd9efSDavid du Colombier 	/* BUG: should set summary bits */
395*d6dfd9efSDavid du Colombier 	if(ir & 1)
396*d6dfd9efSDavid du Colombier 		em->ur->cr &= ~mkCR(1, 0xE);	/* BUG: manual unclear: leave SO, reset others? */
397*d6dfd9efSDavid du Colombier 	if(fpemudebug)
398*d6dfd9efSDavid du Colombier 		print("%8.8lux mtfsb1%s\tfr%d\n", em->ur->pc, ir&1?".":"", rd);
399*d6dfd9efSDavid du Colombier }
400*d6dfd9efSDavid du Colombier 
401*d6dfd9efSDavid du Colombier static void
mtfsb0(Emreg * em,ulong ir)402*d6dfd9efSDavid du Colombier mtfsb0(Emreg *em, ulong ir)
403*d6dfd9efSDavid du Colombier {
404*d6dfd9efSDavid du Colombier 	int rd, ra, rb;
405*d6dfd9efSDavid du Colombier 
406*d6dfd9efSDavid du Colombier 	getarrr(ir);
407*d6dfd9efSDavid du Colombier 	if(ra || rb)
408*d6dfd9efSDavid du Colombier 		unimp(em, ir);
409*d6dfd9efSDavid du Colombier 	em->ufp->fpscr &= ~(1L << (31-rd));
410*d6dfd9efSDavid du Colombier 	if(ir & 1)
411*d6dfd9efSDavid du Colombier 		em->ur->cr &= ~mkCR(1, 0xE);		/* BUG: manual unclear: leave SO, reset others? */
412*d6dfd9efSDavid du Colombier 	if(fpemudebug)
413*d6dfd9efSDavid du Colombier 		print("%8.8lux mtfsb0%s\tfr%d\n", em->ur->pc, ir&1?".":"", rd);
414*d6dfd9efSDavid du Colombier }
415*d6dfd9efSDavid du Colombier 
416*d6dfd9efSDavid du Colombier static void
mtfsf(Emreg * em,ulong ir)417*d6dfd9efSDavid du Colombier mtfsf(Emreg *em, ulong ir)
418*d6dfd9efSDavid du Colombier {
419*d6dfd9efSDavid du Colombier 	int fm, rb, i;
420*d6dfd9efSDavid du Colombier 	ulong v;
421*d6dfd9efSDavid du Colombier 	Internal b;
422*d6dfd9efSDavid du Colombier 	Double db;
423*d6dfd9efSDavid du Colombier 
424*d6dfd9efSDavid du Colombier 	if(ir & ((1L << 25)|(1L << 16)))
425*d6dfd9efSDavid du Colombier 		unimp(em, ir);
426*d6dfd9efSDavid du Colombier 	rb = (ir >> 11) & 0x1F;
427*d6dfd9efSDavid du Colombier 	fm = (ir >> 17) & 0xFF;
428*d6dfd9efSDavid du Colombier 	b = FR(rb);
429*d6dfd9efSDavid du Colombier 	fpii2d(&db, &b);	/* reconstruct hi/lo format to recover low word */
430*d6dfd9efSDavid du Colombier 	v = db.l;
431*d6dfd9efSDavid du Colombier 	for(i=0; i<8; i++)
432*d6dfd9efSDavid du Colombier 		if(fm & (1 << (7-i)))
433*d6dfd9efSDavid du Colombier 			em->ufp->fpscr = (em->ufp->fpscr & ~mkCR(i, 0xF)) | mkCR(i, getCR(i, v));
434*d6dfd9efSDavid du Colombier 	/* BUG: should set FEX and VX `according to the usual rule' */
435*d6dfd9efSDavid du Colombier 	if(ir & 1)
436*d6dfd9efSDavid du Colombier 		em->ur->cr &= ~mkCR(1, 0xE);		/* BUG: manual unclear: leave SO, reset others? */
437*d6dfd9efSDavid du Colombier 	if(fpemudebug)
438*d6dfd9efSDavid du Colombier 		print("%8.8lux mtfsf%s\t#%.2x,fr%d\n", em->ur->pc, ir&1?".":"", fm, rb);
439*d6dfd9efSDavid du Colombier }
440*d6dfd9efSDavid du Colombier 
441*d6dfd9efSDavid du Colombier static void
mtfsfi(Emreg * em,ulong ir)442*d6dfd9efSDavid du Colombier mtfsfi(Emreg *em, ulong ir)
443*d6dfd9efSDavid du Colombier {
444*d6dfd9efSDavid du Colombier 	int imm, rd;
445*d6dfd9efSDavid du Colombier 
446*d6dfd9efSDavid du Colombier 	if(ir & ((0x7F << 16)|(1L << 11)))
447*d6dfd9efSDavid du Colombier 		unimp(em, ir);
448*d6dfd9efSDavid du Colombier 	rd = (ir >> 23) & 0xF;
449*d6dfd9efSDavid du Colombier 	imm = (ir >> 12) & 0xF;
450*d6dfd9efSDavid du Colombier 	em->ufp->fpscr = (em->ufp->fpscr & ~mkCR(rd, 0xF)) | mkCR(rd, imm);
451*d6dfd9efSDavid du Colombier 	/* BUG: should set FEX and VX `according to the usual rule' */
452*d6dfd9efSDavid du Colombier 	if(ir & 1)
453*d6dfd9efSDavid du Colombier 		em->ur->cr &= ~mkCR(1, 0xE);		/* BUG: manual unclear: leave SO, reset others? */
454*d6dfd9efSDavid du Colombier 	if(fpemudebug)
455*d6dfd9efSDavid du Colombier 		print("%8.8lux mtfsfi%s\tcrf%d,#%x\n", em->ur->pc, ir&1?".":"", rd, imm);
456*d6dfd9efSDavid du Colombier }
457*d6dfd9efSDavid du Colombier 
458*d6dfd9efSDavid du Colombier static void
fcmp(Emreg * em,ulong ir)459*d6dfd9efSDavid du Colombier fcmp(Emreg *em, ulong ir)
460*d6dfd9efSDavid du Colombier {
461*d6dfd9efSDavid du Colombier 	int fc, rd, ra, rb, sig, i;
462*d6dfd9efSDavid du Colombier 	Internal a, b;
463*d6dfd9efSDavid du Colombier 
464*d6dfd9efSDavid du Colombier 	getarrr(ir);
465*d6dfd9efSDavid du Colombier 	if(rd & 3)
466*d6dfd9efSDavid du Colombier 		unimp(em, ir);
467*d6dfd9efSDavid du Colombier 	rd >>= 2;
468*d6dfd9efSDavid du Colombier 	sig = 0;
469*d6dfd9efSDavid du Colombier 	switch(getxo(ir)) {
470*d6dfd9efSDavid du Colombier 	default:
471*d6dfd9efSDavid du Colombier 		unimp(em, ir);
472*d6dfd9efSDavid du Colombier 	case 32:
473*d6dfd9efSDavid du Colombier 		if(fpemudebug)
474*d6dfd9efSDavid du Colombier 			print("%8.8lux fcmpo\tcr%d,f%d,f%d\n", em->ur->pc, rd, ra, rb);
475*d6dfd9efSDavid du Colombier 		sig = 1;
476*d6dfd9efSDavid du Colombier 		break;
477*d6dfd9efSDavid du Colombier 	case 0:
478*d6dfd9efSDavid du Colombier 		if(fpemudebug)
479*d6dfd9efSDavid du Colombier 			print("%8.8lux fcmpu\tcr%d,f%d,f%d\n", em->ur->pc, rd, ra, rb);
480*d6dfd9efSDavid du Colombier 		break;
481*d6dfd9efSDavid du Colombier 	}
482*d6dfd9efSDavid du Colombier 	if(IsWeird(&FR(ra)) || IsWeird(&FR(rb))) {
483*d6dfd9efSDavid du Colombier 		if(sig){
484*d6dfd9efSDavid du Colombier 			;	/* BUG: should trap if not masked ... */
485*d6dfd9efSDavid du Colombier 		}
486*d6dfd9efSDavid du Colombier 		fc = CRFU;
487*d6dfd9efSDavid du Colombier 	} else {
488*d6dfd9efSDavid du Colombier 		a = FR(ra);
489*d6dfd9efSDavid du Colombier 		b = FR(rb);
490*d6dfd9efSDavid du Colombier 		fpiround(&a);
491*d6dfd9efSDavid du Colombier 		fpiround(&b);
492*d6dfd9efSDavid du Colombier 		i = fpicmp(&a, &b);
493*d6dfd9efSDavid du Colombier 		if(i > 0)
494*d6dfd9efSDavid du Colombier 			fc = CRGT;
495*d6dfd9efSDavid du Colombier 		else if(i == 0)
496*d6dfd9efSDavid du Colombier 			fc = CREQ;
497*d6dfd9efSDavid du Colombier 		else
498*d6dfd9efSDavid du Colombier 			fc = CRLT;
499*d6dfd9efSDavid du Colombier 	}
500*d6dfd9efSDavid du Colombier 	fc >>= 28;
501*d6dfd9efSDavid du Colombier 	em->ur->cr = (em->ur->cr & ~mkCR(rd,~0)) | mkCR(rd, fc);
502*d6dfd9efSDavid du Colombier 	em->ufp->fpscr = (em->ufp->fpscr & ~0xF800) | (fc<<11);
503*d6dfd9efSDavid du Colombier 	/* BUG: update FX, VXSNAN, VXVC */
504*d6dfd9efSDavid du Colombier }
505*d6dfd9efSDavid du Colombier 
506*d6dfd9efSDavid du Colombier static void
fariths(Emreg * em,ulong ir)507*d6dfd9efSDavid du Colombier fariths(Emreg *em, ulong ir)
508*d6dfd9efSDavid du Colombier {
509*d6dfd9efSDavid du Colombier 	int rd, ra, rb, rc, fmt;
510*d6dfd9efSDavid du Colombier 	char *cc, *n;
511*d6dfd9efSDavid du Colombier 	ulong fpscr;
512*d6dfd9efSDavid du Colombier 	Internal *d;
513*d6dfd9efSDavid du Colombier 
514*d6dfd9efSDavid du Colombier 	fmt = 0;
515*d6dfd9efSDavid du Colombier 	rc = (ir>>6)&0x1F;
516*d6dfd9efSDavid du Colombier 	getarrr(ir);
517*d6dfd9efSDavid du Colombier 	d = &FR(rd);
518*d6dfd9efSDavid du Colombier 	switch(getxo(ir)&0x1F) {	/* partial XO decode */
519*d6dfd9efSDavid du Colombier 	case 22:	/* fsqrts */
520*d6dfd9efSDavid du Colombier 	case 24:	/* fres */
521*d6dfd9efSDavid du Colombier 	default:
522*d6dfd9efSDavid du Colombier 		unimp(em, ir);
523*d6dfd9efSDavid du Colombier 		return;
524*d6dfd9efSDavid du Colombier 	case 18:
525*d6dfd9efSDavid du Colombier 		if(IsZero(&FR(rb))) {
526*d6dfd9efSDavid du Colombier 			em->ufp->fpscr |= FPS_ZX | FPS_FX;
527*d6dfd9efSDavid du Colombier 			error("sys: fp: zero divide");
528*d6dfd9efSDavid du Colombier 		}
529*d6dfd9efSDavid du Colombier 		fdiv(em, d, ra, rb);
530*d6dfd9efSDavid du Colombier 		n = "fdivs";
531*d6dfd9efSDavid du Colombier 		break;
532*d6dfd9efSDavid du Colombier 	case 20:
533*d6dfd9efSDavid du Colombier 		fsub(em, d, ra, rb);
534*d6dfd9efSDavid du Colombier 		n = "fsubs";
535*d6dfd9efSDavid du Colombier 		break;
536*d6dfd9efSDavid du Colombier 	case 21:
537*d6dfd9efSDavid du Colombier 		fadd(em, d, ra, rb);
538*d6dfd9efSDavid du Colombier 		n = "fadds";
539*d6dfd9efSDavid du Colombier 		break;
540*d6dfd9efSDavid du Colombier 	case 25:
541*d6dfd9efSDavid du Colombier 		fmul(em, d, ra, rc);
542*d6dfd9efSDavid du Colombier 		rb = rc;
543*d6dfd9efSDavid du Colombier 		n = "fmuls";
544*d6dfd9efSDavid du Colombier 		break;
545*d6dfd9efSDavid du Colombier 	case 28:
546*d6dfd9efSDavid du Colombier 		fmsub(em, d, ra, rc, rb);
547*d6dfd9efSDavid du Colombier 		fmt = 2;
548*d6dfd9efSDavid du Colombier 		n = "fmsubs";
549*d6dfd9efSDavid du Colombier 		break;
550*d6dfd9efSDavid du Colombier 	case 29:
551*d6dfd9efSDavid du Colombier 		fmadd(em, d, ra, rc, rb);
552*d6dfd9efSDavid du Colombier 		fmt = 2;
553*d6dfd9efSDavid du Colombier 		n = "fmadds";
554*d6dfd9efSDavid du Colombier 		break;
555*d6dfd9efSDavid du Colombier 	case 30:
556*d6dfd9efSDavid du Colombier 		fmsub(em, d, ra, rc, rb);
557*d6dfd9efSDavid du Colombier 		d->s ^= 1;
558*d6dfd9efSDavid du Colombier 		fmt = 2;
559*d6dfd9efSDavid du Colombier 		n = "fnmsubs";
560*d6dfd9efSDavid du Colombier 		break;
561*d6dfd9efSDavid du Colombier 	case 31:
562*d6dfd9efSDavid du Colombier 		fmadd(em, d, ra, rc, rb);
563*d6dfd9efSDavid du Colombier 		d->s ^= 1;
564*d6dfd9efSDavid du Colombier 		fmt = 2;
565*d6dfd9efSDavid du Colombier 		n = "fnmadds";
566*d6dfd9efSDavid du Colombier 		break;
567*d6dfd9efSDavid du Colombier 	}
568*d6dfd9efSDavid du Colombier 	if(fmt==1 && ra)
569*d6dfd9efSDavid du Colombier 		unimp(em, ir);
570*d6dfd9efSDavid du Colombier 	fpscr = setfpscr(em);
571*d6dfd9efSDavid du Colombier 	setfpcc(em, rd);
572*d6dfd9efSDavid du Colombier 	cc = "";
573*d6dfd9efSDavid du Colombier 	if(ir & 1) {
574*d6dfd9efSDavid du Colombier 		cc = ".";
575*d6dfd9efSDavid du Colombier 		em->ur->cr = (em->ur->cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
576*d6dfd9efSDavid du Colombier 	}
577*d6dfd9efSDavid du Colombier 	if(fpemudebug) {
578*d6dfd9efSDavid du Colombier 		switch(fmt) {
579*d6dfd9efSDavid du Colombier 		case 0:
580*d6dfd9efSDavid du Colombier 			print("%8.8lux %s%s\tfr%d,fr%d,fr%d\n", em->ur->pc, n, cc, rd, ra, rb);
581*d6dfd9efSDavid du Colombier 			break;
582*d6dfd9efSDavid du Colombier 		case 1:
583*d6dfd9efSDavid du Colombier 			print("%8.8lux %s%s\tfr%d,fr%d\n", em->ur->pc, n, cc, rd, rb);
584*d6dfd9efSDavid du Colombier 			break;
585*d6dfd9efSDavid du Colombier 		case 2:
586*d6dfd9efSDavid du Colombier 			print("%8.8lux %s%s\tfr%d,fr%d,fr%d,fr%d\n", em->ur->pc, n, cc, rd, ra, rc, rb);
587*d6dfd9efSDavid du Colombier 			break;
588*d6dfd9efSDavid du Colombier 		}
589*d6dfd9efSDavid du Colombier 	}
590*d6dfd9efSDavid du Colombier }
591*d6dfd9efSDavid du Colombier 
592*d6dfd9efSDavid du Colombier static void
farith(Emreg * em,ulong ir)593*d6dfd9efSDavid du Colombier farith(Emreg *em, ulong ir)
594*d6dfd9efSDavid du Colombier {
595*d6dfd9efSDavid du Colombier 	Word w;
596*d6dfd9efSDavid du Colombier 	Double dv;
597*d6dfd9efSDavid du Colombier 	int rd, ra, rb, rc, fmt;
598*d6dfd9efSDavid du Colombier 	char *cc, *n;
599*d6dfd9efSDavid du Colombier 	ulong fpscr;
600*d6dfd9efSDavid du Colombier 	int nocc;
601*d6dfd9efSDavid du Colombier 	Internal *d;
602*d6dfd9efSDavid du Colombier 
603*d6dfd9efSDavid du Colombier 	fmt = 0;
604*d6dfd9efSDavid du Colombier 	nocc = 0;
605*d6dfd9efSDavid du Colombier 	rc = (ir>>6)&0x1F;
606*d6dfd9efSDavid du Colombier 	getarrr(ir);
607*d6dfd9efSDavid du Colombier 	d = &FR(rd);
608*d6dfd9efSDavid du Colombier 	switch(getxo(ir)&0x1F) { /* partial XO decode */
609*d6dfd9efSDavid du Colombier 	case 22:	/* frsqrt */
610*d6dfd9efSDavid du Colombier 	case 23:	/* fsel */
611*d6dfd9efSDavid du Colombier 	case 26:	/* fsqrte */
612*d6dfd9efSDavid du Colombier 	default:
613*d6dfd9efSDavid du Colombier 		unimp(em, ir);
614*d6dfd9efSDavid du Colombier 		return;
615*d6dfd9efSDavid du Colombier 	case 12:	/* frsp */
616*d6dfd9efSDavid du Colombier 		*d = FR(rb);	/* BUG: doesn't round to single precision */
617*d6dfd9efSDavid du Colombier 		fmt = 1;
618*d6dfd9efSDavid du Colombier 		n = "frsp";
619*d6dfd9efSDavid du Colombier 		break;
620*d6dfd9efSDavid du Colombier 	case 14:	/* fctiw */	/* BUG: ignores rounding mode */
621*d6dfd9efSDavid du Colombier 	case 15:	/* fctiwz */
622*d6dfd9efSDavid du Colombier 		fpii2w(&w, &FR(rb));
623*d6dfd9efSDavid du Colombier 		dv.h = 0;
624*d6dfd9efSDavid du Colombier 		dv.l = w;
625*d6dfd9efSDavid du Colombier 		fpid2i(d, &dv);
626*d6dfd9efSDavid du Colombier 		fmt = 1;
627*d6dfd9efSDavid du Colombier 		nocc = 1;
628*d6dfd9efSDavid du Colombier 		n = "fctiw";
629*d6dfd9efSDavid du Colombier 		break;
630*d6dfd9efSDavid du Colombier 	case 18:
631*d6dfd9efSDavid du Colombier 		if(IsZero(&FR(rb))) {
632*d6dfd9efSDavid du Colombier 			em->ufp->fpscr |= FPS_ZX | FPS_FX;
633*d6dfd9efSDavid du Colombier 			error("sys: fp: zero divide");
634*d6dfd9efSDavid du Colombier 		}
635*d6dfd9efSDavid du Colombier 		fdiv(em, d, ra, rb);
636*d6dfd9efSDavid du Colombier 		n = "fdiv";
637*d6dfd9efSDavid du Colombier 		break;
638*d6dfd9efSDavid du Colombier 	case 20:
639*d6dfd9efSDavid du Colombier 		fsub(em, d, ra, rb);
640*d6dfd9efSDavid du Colombier 		n = "fsub";
641*d6dfd9efSDavid du Colombier 		break;
642*d6dfd9efSDavid du Colombier 	case 21:
643*d6dfd9efSDavid du Colombier 		fadd(em, d, ra, rb);
644*d6dfd9efSDavid du Colombier 		n = "fadd";
645*d6dfd9efSDavid du Colombier 		break;
646*d6dfd9efSDavid du Colombier 	case 25:
647*d6dfd9efSDavid du Colombier 		fmul(em, d, ra, rc);
648*d6dfd9efSDavid du Colombier 		rb = rc;
649*d6dfd9efSDavid du Colombier 		n = "fmul";
650*d6dfd9efSDavid du Colombier 		break;
651*d6dfd9efSDavid du Colombier 	case 28:
652*d6dfd9efSDavid du Colombier 		fmsub(em, d, ra, rc, rb);
653*d6dfd9efSDavid du Colombier 		fmt = 2;
654*d6dfd9efSDavid du Colombier 		n = "fmsub";
655*d6dfd9efSDavid du Colombier 		break;
656*d6dfd9efSDavid du Colombier 	case 29:
657*d6dfd9efSDavid du Colombier 		fmadd(em, d, ra, rc, rb);
658*d6dfd9efSDavid du Colombier 		fmt = 2;
659*d6dfd9efSDavid du Colombier 		n = "fmadd";
660*d6dfd9efSDavid du Colombier 		break;
661*d6dfd9efSDavid du Colombier 	case 30:
662*d6dfd9efSDavid du Colombier 		fmsub(em, d, ra, rc, rb);
663*d6dfd9efSDavid du Colombier 		d->s ^= 1;
664*d6dfd9efSDavid du Colombier 		fmt = 2;
665*d6dfd9efSDavid du Colombier 		n = "fnmsub";
666*d6dfd9efSDavid du Colombier 		break;
667*d6dfd9efSDavid du Colombier 	case 31:
668*d6dfd9efSDavid du Colombier 		fmadd(em, d, ra, rc, rb);
669*d6dfd9efSDavid du Colombier 		d->s ^= 1;
670*d6dfd9efSDavid du Colombier 		fmt = 2;
671*d6dfd9efSDavid du Colombier 		n = "fnmadd";
672*d6dfd9efSDavid du Colombier 		break;
673*d6dfd9efSDavid du Colombier 	}
674*d6dfd9efSDavid du Colombier 	if(fmt==1 && ra)
675*d6dfd9efSDavid du Colombier 		unimp(em, ir);
676*d6dfd9efSDavid du Colombier 	fpscr = setfpscr(em);
677*d6dfd9efSDavid du Colombier 	if(nocc == 0)
678*d6dfd9efSDavid du Colombier 		setfpcc(em, rd);
679*d6dfd9efSDavid du Colombier 	cc = "";
680*d6dfd9efSDavid du Colombier 	if(ir & 1) {
681*d6dfd9efSDavid du Colombier 		cc = ".";
682*d6dfd9efSDavid du Colombier 		em->ur->cr = (em->ur->cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
683*d6dfd9efSDavid du Colombier 	}
684*d6dfd9efSDavid du Colombier 	if(fpemudebug) {
685*d6dfd9efSDavid du Colombier 		switch(fmt) {
686*d6dfd9efSDavid du Colombier 		case 0:
687*d6dfd9efSDavid du Colombier 			print("%8.8lux %s%s\tfr%d,fr%d,fr%d\n", em->ur->pc, n, cc, rd, ra, rb);
688*d6dfd9efSDavid du Colombier 			break;
689*d6dfd9efSDavid du Colombier 		case 1:
690*d6dfd9efSDavid du Colombier 			print("%8.8lux %s%s\tfr%d,fr%d\n", em->ur->pc, n, cc, rd, rb);
691*d6dfd9efSDavid du Colombier 			break;
692*d6dfd9efSDavid du Colombier 		case 2:
693*d6dfd9efSDavid du Colombier 			print("%8.8lux %s%s\tfr%d,fr%d,fr%d,fr%d\n", em->ur->pc, n, cc, rd, ra, rc, rb);
694*d6dfd9efSDavid du Colombier 			break;
695*d6dfd9efSDavid du Colombier 		}
696*d6dfd9efSDavid du Colombier 	}
697*d6dfd9efSDavid du Colombier }
698*d6dfd9efSDavid du Colombier 
699*d6dfd9efSDavid du Colombier static void
farith2(Emreg * em,ulong ir)700*d6dfd9efSDavid du Colombier farith2(Emreg *em, ulong ir)
701*d6dfd9efSDavid du Colombier {
702*d6dfd9efSDavid du Colombier 	int rd, ra, rb;
703*d6dfd9efSDavid du Colombier 	char *cc, *n;
704*d6dfd9efSDavid du Colombier 	ulong fpscr;
705*d6dfd9efSDavid du Colombier 	Internal *d, *b;
706*d6dfd9efSDavid du Colombier 
707*d6dfd9efSDavid du Colombier 	getarrr(ir);
708*d6dfd9efSDavid du Colombier 	if(ra)
709*d6dfd9efSDavid du Colombier 		unimp(em, ir);
710*d6dfd9efSDavid du Colombier 	d = &FR(rd);
711*d6dfd9efSDavid du Colombier 	b = &FR(rb);
712*d6dfd9efSDavid du Colombier 	switch(getxo(ir)) { /* full XO decode */
713*d6dfd9efSDavid du Colombier 	default:
714*d6dfd9efSDavid du Colombier 		unimp(em, ir);
715*d6dfd9efSDavid du Colombier 	case 40:
716*d6dfd9efSDavid du Colombier 		*d = *b;
717*d6dfd9efSDavid du Colombier 		d->s ^= 1;
718*d6dfd9efSDavid du Colombier 		n = "fneg";
719*d6dfd9efSDavid du Colombier 		break;
720*d6dfd9efSDavid du Colombier 	case 72:
721*d6dfd9efSDavid du Colombier 		*d = *b;
722*d6dfd9efSDavid du Colombier 		n = "fmr";
723*d6dfd9efSDavid du Colombier 		break;
724*d6dfd9efSDavid du Colombier 	case 136:
725*d6dfd9efSDavid du Colombier 		*d = *b;
726*d6dfd9efSDavid du Colombier 		d->s = 1;
727*d6dfd9efSDavid du Colombier 		n = "fnabs";
728*d6dfd9efSDavid du Colombier 		break;
729*d6dfd9efSDavid du Colombier 	case 264:
730*d6dfd9efSDavid du Colombier 		*d = *b;
731*d6dfd9efSDavid du Colombier 		d->s = 0;
732*d6dfd9efSDavid du Colombier 		n = "fabs";
733*d6dfd9efSDavid du Colombier 		break;
734*d6dfd9efSDavid du Colombier 	}
735*d6dfd9efSDavid du Colombier 	fpscr = setfpscr(em);
736*d6dfd9efSDavid du Colombier 	setfpcc(em, rd);
737*d6dfd9efSDavid du Colombier 	cc = "";
738*d6dfd9efSDavid du Colombier 	if(ir & 1) {
739*d6dfd9efSDavid du Colombier 		cc = ".";
740*d6dfd9efSDavid du Colombier 		em->ur->cr = (em->ur->cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
741*d6dfd9efSDavid du Colombier 	}
742*d6dfd9efSDavid du Colombier 	if(fpemudebug)
743*d6dfd9efSDavid du Colombier 		print("%8.8lux %s%s\tfr%d,fr%d\n", em->ur->pc, n, cc, rd, rb);
744*d6dfd9efSDavid du Colombier }
745*d6dfd9efSDavid du Colombier 
746*d6dfd9efSDavid du Colombier static ulong
setfpscr(Emreg * em)747*d6dfd9efSDavid du Colombier setfpscr(Emreg *em)
748*d6dfd9efSDavid du Colombier {
749*d6dfd9efSDavid du Colombier 	ulong fps, fpscr;
750*d6dfd9efSDavid du Colombier 
751*d6dfd9efSDavid du Colombier 	fps = 0;	/* BUG: getfsr() */
752*d6dfd9efSDavid du Colombier 	fpscr = em->ufp->fpscr;
753*d6dfd9efSDavid du Colombier 	if(fps & FPAOVFL)
754*d6dfd9efSDavid du Colombier 		fpscr |= FPS_OX;
755*d6dfd9efSDavid du Colombier 	if(fps & FPAINEX)
756*d6dfd9efSDavid du Colombier 		fpscr |= FPS_XX;
757*d6dfd9efSDavid du Colombier 	if(fps & FPAUNFL)
758*d6dfd9efSDavid du Colombier 		fpscr |= FPS_UX;
759*d6dfd9efSDavid du Colombier 	if(fps & FPAZDIV)
760*d6dfd9efSDavid du Colombier 		fpscr |= FPS_ZX;
761*d6dfd9efSDavid du Colombier 	if(fpscr != em->ufp->fpscr) {
762*d6dfd9efSDavid du Colombier 		fpscr |= FPS_FX;
763*d6dfd9efSDavid du Colombier 		em->ufp->fpscr = fpscr;
764*d6dfd9efSDavid du Colombier 	}
765*d6dfd9efSDavid du Colombier 	return fpscr;
766*d6dfd9efSDavid du Colombier }
767*d6dfd9efSDavid du Colombier 
768*d6dfd9efSDavid du Colombier static void
setfpcc(Emreg * em,int r)769*d6dfd9efSDavid du Colombier setfpcc(Emreg *em, int r)
770*d6dfd9efSDavid du Colombier {
771*d6dfd9efSDavid du Colombier 	int c;
772*d6dfd9efSDavid du Colombier 	Internal *d;
773*d6dfd9efSDavid du Colombier 
774*d6dfd9efSDavid du Colombier 	d = &FR(r);
775*d6dfd9efSDavid du Colombier 	c = 0;
776*d6dfd9efSDavid du Colombier 	if(IsZero(d))
777*d6dfd9efSDavid du Colombier 		c |= 2;
778*d6dfd9efSDavid du Colombier 	else if(d->s == 1)
779*d6dfd9efSDavid du Colombier 		c |= 4;
780*d6dfd9efSDavid du Colombier 	else
781*d6dfd9efSDavid du Colombier 		c |= 8;
782*d6dfd9efSDavid du Colombier 	if(IsNaN(d))
783*d6dfd9efSDavid du Colombier 		c |= 1;
784*d6dfd9efSDavid du Colombier 	em->ufp->fpscr = (em->ufp->fpscr & ~0xF800) | (0<<15) | (c<<11); /* unsure about class bit */
785*d6dfd9efSDavid du Colombier }
786*d6dfd9efSDavid du Colombier 
787*d6dfd9efSDavid du Colombier static	uchar	op63flag[32] = {
788*d6dfd9efSDavid du Colombier [12] 1, [14] 1, [15] 1, [18] 1, [20] 1, [21] 1, [22] 1,
789*d6dfd9efSDavid du Colombier [23] 1, [25] 1, [26] 1, [28] 1, [29] 1, [30] 1, [31] 1,
790*d6dfd9efSDavid du Colombier };
791*d6dfd9efSDavid du Colombier 
792*d6dfd9efSDavid du Colombier /*
793*d6dfd9efSDavid du Colombier  * returns the number of FP instructions emulated
794*d6dfd9efSDavid du Colombier  */
795*d6dfd9efSDavid du Colombier int
fpipower(Ureg * ur)796*d6dfd9efSDavid du Colombier fpipower(Ureg *ur)
797*d6dfd9efSDavid du Colombier {
798*d6dfd9efSDavid du Colombier 	ulong op;
799*d6dfd9efSDavid du Colombier 	int xo;
800*d6dfd9efSDavid du Colombier 	Emreg emreg, *em;
801*d6dfd9efSDavid du Colombier 	FPsave *ufp;
802*d6dfd9efSDavid du Colombier 	int n;
803*d6dfd9efSDavid du Colombier 
804*d6dfd9efSDavid du Colombier 	ufp = &up->fpsave; /* because all the state is in FPsave, it need not be saved/restored */
805*d6dfd9efSDavid du Colombier 	em = &emreg;
806*d6dfd9efSDavid du Colombier 	em->ur = ur;
807*d6dfd9efSDavid du Colombier 	em->fr = ufp->emreg;
808*d6dfd9efSDavid du Colombier 	em->ufp = ufp;
809*d6dfd9efSDavid du Colombier 	em->name = nil;
810*d6dfd9efSDavid du Colombier 	if(em->ufp->fpistate != FPactive) {
811*d6dfd9efSDavid du Colombier 		em->ufp->fpistate = FPactive;
812*d6dfd9efSDavid du Colombier 		em->ufp->fpscr = 0;	/* TO DO */
813*d6dfd9efSDavid du Colombier 		for(n = 0; n < nelem(fpreginit); n++)
814*d6dfd9efSDavid du Colombier 			FR(31-n) = fpreginit[n];
815*d6dfd9efSDavid du Colombier 	}
816*d6dfd9efSDavid du Colombier 	for(n=0;;n++){
817*d6dfd9efSDavid du Colombier 		validaddr(ur->pc, 4, 0);
818*d6dfd9efSDavid du Colombier 		op = getulong(ur->pc);
819*d6dfd9efSDavid du Colombier 		em->ir = op;
820*d6dfd9efSDavid du Colombier 		if(fpemudebug > 1)
821*d6dfd9efSDavid du Colombier 			print("%8.8lux %8.8lux: ", ur->pc, op);
822*d6dfd9efSDavid du Colombier 		switch(op>>26){
823*d6dfd9efSDavid du Colombier 		default:
824*d6dfd9efSDavid du Colombier 			return n;
825*d6dfd9efSDavid du Colombier 		case 48:	/* lfs */
826*d6dfd9efSDavid du Colombier 		case 49:	/* lfsu */
827*d6dfd9efSDavid du Colombier 			lfs(em, op);
828*d6dfd9efSDavid du Colombier 			break;
829*d6dfd9efSDavid du Colombier 		case 50:	/* lfd */
830*d6dfd9efSDavid du Colombier 		case 51:	/* lfdu */
831*d6dfd9efSDavid du Colombier 			lfd(em, op);
832*d6dfd9efSDavid du Colombier 			break;
833*d6dfd9efSDavid du Colombier 		case 52:	/* stfs */
834*d6dfd9efSDavid du Colombier 		case 53:	/* stfsu */
835*d6dfd9efSDavid du Colombier 			stfs(em, op);
836*d6dfd9efSDavid du Colombier 			break;
837*d6dfd9efSDavid du Colombier 		case 54:	/* stfd */
838*d6dfd9efSDavid du Colombier 		case 55:	/* stfdu */
839*d6dfd9efSDavid du Colombier 			stfd(em, op);
840*d6dfd9efSDavid du Colombier 			break;
841*d6dfd9efSDavid du Colombier 		case 31:	/* indexed load/store */
842*d6dfd9efSDavid du Colombier 			xo = getxo(op);
843*d6dfd9efSDavid du Colombier 			if((xo & 0x300) != 0x200)
844*d6dfd9efSDavid du Colombier 				return n;
845*d6dfd9efSDavid du Colombier 			switch(xo){
846*d6dfd9efSDavid du Colombier 			default:
847*d6dfd9efSDavid du Colombier 				return n;
848*d6dfd9efSDavid du Colombier 			case 535:	/* lfsx */
849*d6dfd9efSDavid du Colombier 			case 567:	/* lfsux */
850*d6dfd9efSDavid du Colombier 				lfsx(em, op);
851*d6dfd9efSDavid du Colombier 				break;
852*d6dfd9efSDavid du Colombier 			case 599:	/* lfdx */
853*d6dfd9efSDavid du Colombier 			case 631:	/* lfdux */
854*d6dfd9efSDavid du Colombier 				lfdx(em, op);
855*d6dfd9efSDavid du Colombier 				break;
856*d6dfd9efSDavid du Colombier 			case 663:	/* stfsx */
857*d6dfd9efSDavid du Colombier 			case 695:	/* stfsux */
858*d6dfd9efSDavid du Colombier 				stfsx(em, op);
859*d6dfd9efSDavid du Colombier 				break;
860*d6dfd9efSDavid du Colombier 			case 727:	/* stfdx */
861*d6dfd9efSDavid du Colombier 			case 759:	/* stfdux */
862*d6dfd9efSDavid du Colombier 				stfdx(em, op);
863*d6dfd9efSDavid du Colombier 				break;
864*d6dfd9efSDavid du Colombier 			}
865*d6dfd9efSDavid du Colombier 			break;
866*d6dfd9efSDavid du Colombier 		case 63:	/* double precision */
867*d6dfd9efSDavid du Colombier 			xo = getxo(op);
868*d6dfd9efSDavid du Colombier 			if(op63flag[xo & 0x1F]){
869*d6dfd9efSDavid du Colombier 				farith(em, op);
870*d6dfd9efSDavid du Colombier 				break;
871*d6dfd9efSDavid du Colombier 			}
872*d6dfd9efSDavid du Colombier 			switch(xo){
873*d6dfd9efSDavid du Colombier 			default:
874*d6dfd9efSDavid du Colombier 				return n;
875*d6dfd9efSDavid du Colombier 			case 0:	/* fcmpu */
876*d6dfd9efSDavid du Colombier 			case 32:	/* fcmpo */
877*d6dfd9efSDavid du Colombier 				fcmp(em, op);
878*d6dfd9efSDavid du Colombier 				break;
879*d6dfd9efSDavid du Colombier 			case 40:	/* fneg */
880*d6dfd9efSDavid du Colombier 			case 72:	/* fmr */
881*d6dfd9efSDavid du Colombier 			case 136:	/* fnabs */
882*d6dfd9efSDavid du Colombier 			case 264:	/* fabs */
883*d6dfd9efSDavid du Colombier 				farith2(em, op);
884*d6dfd9efSDavid du Colombier 				break;
885*d6dfd9efSDavid du Colombier 			case 38:
886*d6dfd9efSDavid du Colombier 				mtfsb1(em, op);
887*d6dfd9efSDavid du Colombier 				break;
888*d6dfd9efSDavid du Colombier 			case 64:
889*d6dfd9efSDavid du Colombier 				mcrfs(em, op);
890*d6dfd9efSDavid du Colombier 				break;
891*d6dfd9efSDavid du Colombier 			case 70:
892*d6dfd9efSDavid du Colombier 				mtfsb0(em, op);
893*d6dfd9efSDavid du Colombier 				break;
894*d6dfd9efSDavid du Colombier 			case 134:
895*d6dfd9efSDavid du Colombier 				mtfsfi(em, op);
896*d6dfd9efSDavid du Colombier 				break;
897*d6dfd9efSDavid du Colombier 			case 583:
898*d6dfd9efSDavid du Colombier 				mffs(em, op);
899*d6dfd9efSDavid du Colombier 				break;
900*d6dfd9efSDavid du Colombier 			case 711:
901*d6dfd9efSDavid du Colombier 				mtfsf(em, op);
902*d6dfd9efSDavid du Colombier 				break;
903*d6dfd9efSDavid du Colombier 			}
904*d6dfd9efSDavid du Colombier 			break;
905*d6dfd9efSDavid du Colombier 		case 59:	/* single precision */
906*d6dfd9efSDavid du Colombier 			fariths(em, op);
907*d6dfd9efSDavid du Colombier 			break;
908*d6dfd9efSDavid du Colombier 		}
909*d6dfd9efSDavid du Colombier 		ur->pc += 4;
910*d6dfd9efSDavid du Colombier 		if(anyhigher())
911*d6dfd9efSDavid du Colombier 			sched();
912*d6dfd9efSDavid du Colombier 	}
913*d6dfd9efSDavid du Colombier }
914*d6dfd9efSDavid du Colombier 
915*d6dfd9efSDavid du Colombier /*
916*d6dfd9efSDavid du Colombier 50:	lfd	frD,d(rA)
917*d6dfd9efSDavid du Colombier 51:	lfdu	frD,d(rA)
918*d6dfd9efSDavid du Colombier 31,631:	lfdux	frD,rA,rB
919*d6dfd9efSDavid du Colombier 31,599:	lfdx	frD,rA,rB
920*d6dfd9efSDavid du Colombier 48:	lfs	frD,d(rA)
921*d6dfd9efSDavid du Colombier 49:	lfsu	frD,d(rA)
922*d6dfd9efSDavid du Colombier 31,567:	lfsux	frD,rA,rB
923*d6dfd9efSDavid du Colombier 31,535:	lfsx	frD,rA,rB
924*d6dfd9efSDavid du Colombier 
925*d6dfd9efSDavid du Colombier 54:	stfd	frS,d(rA)
926*d6dfd9efSDavid du Colombier 55:	stfdu	frS,d(rA)
927*d6dfd9efSDavid du Colombier 31,759:	stfdux	frS,rA,rB
928*d6dfd9efSDavid du Colombier 31,727:	stfdx	frS,rA,rB
929*d6dfd9efSDavid du Colombier 52:	stfs	frS,d(rA)
930*d6dfd9efSDavid du Colombier 53:	stfsu	frS,d(rA)
931*d6dfd9efSDavid du Colombier 31,695:	stfsux	frS,rA,rB
932*d6dfd9efSDavid du Colombier 31,663:	stfsx	frS,rA,rB
933*d6dfd9efSDavid du Colombier 
934*d6dfd9efSDavid du Colombier 63,64:	mcrfs	crfD,crfS
935*d6dfd9efSDavid du Colombier 63,583:	mffs[.]	frD
936*d6dfd9efSDavid du Colombier 63,70:	mtfsb0[.]	crbD
937*d6dfd9efSDavid du Colombier 63,38:	mtfsb1[.]	crbD
938*d6dfd9efSDavid du Colombier 63,711:	mtfsf[.]	FM,frB
939*d6dfd9efSDavid du Colombier 63,134:	mtfsfi[.]	crfD,IMM
940*d6dfd9efSDavid du Colombier */
941*d6dfd9efSDavid du Colombier 
942*d6dfd9efSDavid du Colombier /*
943*d6dfd9efSDavid du Colombier float to int:
944*d6dfd9efSDavid du Colombier 	FMOVD	g+0(SB),F1
945*d6dfd9efSDavid du Colombier 	FCTIWZ	F1,F4
946*d6dfd9efSDavid du Colombier 	FMOVD	F4,.rathole+0(SB)
947*d6dfd9efSDavid du Colombier 	MOVW	.rathole+4(SB),R7
948*d6dfd9efSDavid du Colombier 	MOVW	R7,l+0(SB)
949*d6dfd9efSDavid du Colombier */
950*d6dfd9efSDavid du Colombier 
951*d6dfd9efSDavid du Colombier /*
952*d6dfd9efSDavid du Colombier int to float:
953*d6dfd9efSDavid du Colombier 	MOVW	$1127219200,R9
954*d6dfd9efSDavid du Colombier 	MOVW	l+0(SB),R7
955*d6dfd9efSDavid du Colombier 	MOVW	R9,.rathole+0(SB)
956*d6dfd9efSDavid du Colombier 	XOR	$-2147483648,R7,R6
957*d6dfd9efSDavid du Colombier 	MOVW	R6,.rathole+4(SB)
958*d6dfd9efSDavid du Colombier 	FMOVD	.rathole+0(SB),F0
959*d6dfd9efSDavid du Colombier 	FSUB	F27,F0
960*d6dfd9efSDavid du Colombier 
961*d6dfd9efSDavid du Colombier unsigned to float:
962*d6dfd9efSDavid du Colombier 	MOVW	ul+0(SB),R5
963*d6dfd9efSDavid du Colombier 	MOVW	R9,.rathole+0(SB)
964*d6dfd9efSDavid du Colombier 	XOR	$-2147483648,R5,R4
965*d6dfd9efSDavid du Colombier 	MOVW	R4,.rathole+4(SB)
966*d6dfd9efSDavid du Colombier 	FMOVD	.rathole+0(SB),F3
967*d6dfd9efSDavid du Colombier 	FSUB	F27,F3
968*d6dfd9efSDavid du Colombier 	FCMPU	F3,F28
969*d6dfd9efSDavid du Colombier 	BGE	,3(PC)
970*d6dfd9efSDavid du Colombier 	FMOVD	$4.29496729600000000e+09,F2
971*d6dfd9efSDavid du Colombier 	FADD	F2,F3
972*d6dfd9efSDavid du Colombier 	FMOVD	F3,g+0(SB)
973*d6dfd9efSDavid du Colombier */
974