xref: /netbsd/sys/arch/hppa/spmath/fpudispatch.c (revision 82357f6d)
1 /*	$NetBSD: fpudispatch.c,v 1.4 2009/03/14 21:04:10 dsl Exp $	 */
2 
3 /*
4  *  (c) Copyright 1991 HEWLETT-PACKARD COMPANY
5  *
6  *  To anyone who acknowledges that this file is provided "AS IS"
7  *  without any express or implied warranty:
8  *      permission to use, copy, modify, and distribute this file
9  *  for any purpose is hereby granted without fee, provided that
10  *  the above copyright notice and this notice appears in all
11  *  copies, and that the name of Hewlett-Packard Company not be
12  *  used in advertising or publicity pertaining to distribution
13  *  of the software without specific, written prior permission.
14  *  Hewlett-Packard Company makes no representations about the
15  *  suitability of this software for any purpose.
16  */
17 
18 /* Source: /n/schirf/u/baford/CVS/mach4-parisc/kernel/parisc/fpudispatch.c,v
19  * Revision: 1.4 	Author: mike
20  * State: Exp    	Locker:
21  * Date: 1994/07/21 17:36:35
22  */
23 
24 #include <sys/cdefs.h>
25 __KERNEL_RCSID(0, "$NetBSD: fpudispatch.c,v 1.4 2009/03/14 21:04:10 dsl Exp $");
26 
27 #include <sys/types.h>
28 #include <sys/systm.h>
29 
30 #include "../spmath/float.h"
31 /*
32  * XXX fredette - hack to glue the bulk of
33  * the spmath library to this dispatcher.
34  */
35 #define	dbl_integer		unsigned
36 #define	sgl_floating_point	unsigned
37 #define	dbl_floating_point	unsigned
38 #include "../spmath/sgl_float.h"
39 #include "../spmath/dbl_float.h"
40 #include "../spmath/cnv_float.h"
41 #include "../spmath/md.h"
42 #include "../spmath/fpudispatch.h"
43 
44 /*
45  * version of EMULATION software for COPR,0,0 instruction
46  */
47 #define EMULATION_VERSION 3
48 #define COPR_INST 0x30000000
49 
50 /*
51  * definition of extru macro.  If pos and len are constants, the compiler
52  * will generate an extru instruction when optimized
53  */
54 #define extru(r,pos,len)	(((r) >> (31-(pos))) & (( 1 << (len)) - 1))
55 /* definitions of bit field locations in the instruction */
56 #define fpmajorpos 5
57 #define fpr1pos	10
58 #define fpr2pos 15
59 #define fptpos	31
60 #define fpsubpos 18
61 #define fpclass1subpos 16
62 #define fpclasspos 22
63 #define fpfmtpos 20
64 #define fpdfpos 18
65 /*
66  * the following are the extra bits for the 0E major op
67  */
68 #define fpxr1pos 24
69 #define fpxr2pos 19
70 #define fpxtpos 25
71 #define fpxpos 23
72 #define fp0efmtpos 20
73 /*
74  * the following are for the multi-ops
75  */
76 #define fprm1pos 10
77 #define fprm2pos 15
78 #define fptmpos 31
79 #define fprapos 25
80 #define fptapos 20
81 #define fpmultifmt 26
82 
83 /*
84  * offset to constant zero in the FP emulation registers
85  */
86 #define fpzeroreg (32*sizeof(double)/sizeof(unsigned))
87 
88 /*
89  * extract the major opcode from the instruction
90  */
91 #define get_major(op) extru(op,fpmajorpos,6)
92 /*
93  * extract the two bit class field from the FP instruction. The class is at bit
94  * positions 21-22
95  */
96 #define get_class(op) extru(op,fpclasspos,2)
97 /*
98  * extract the 3 bit subop field.  For all but class 1 instructions, it is
99  * located at bit positions 16-18
100  */
101 #define get_subop(op) extru(op,fpsubpos,3)
102 /*
103  * extract the 2 bit subop field from class 1 instructions.  It is located
104  * at bit positions 15-16
105  */
106 #define get_subop1(op) extru(op,fpclass1subpos,2)
107 
108 /* definitions of unimplemented exceptions */
109 #define MAJOR_0C_EXCP	UNIMPLEMENTEDEXCEPTION
110 #define MAJOR_0E_EXCP	UNIMPLEMENTEDEXCEPTION
111 #define MAJOR_06_EXCP	UNIMPLEMENTEDEXCEPTION
112 #define MAJOR_26_EXCP	UNIMPLEMENTEDEXCEPTION
113 #define PA83_UNIMP_EXCP	UNIMPLEMENTEDEXCEPTION
114 
115 int
decode_0c(unsigned ir,unsigned class,unsigned subop,unsigned fpregs[])116 decode_0c(unsigned ir,unsigned class,unsigned subop,unsigned fpregs[])
117 {
118 	unsigned r1,r2,t;	/* operand register offsets */
119 	unsigned fmt;		/* also sf for class 1 conversions */
120 	unsigned  df;		/* for class 1 conversions */
121 	unsigned *status;
122 
123 	if (ir == COPR_INST) {
124 		fpregs[0] = EMULATION_VERSION << 11;
125 		return(NOEXCEPTION);
126 	}
127 	status = &fpregs[0];	/* fp status register */
128 	r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(unsigned);
129 	if (r1 == 0)		/* map fr0 source to constant zero */
130 		r1 = fpzeroreg;
131 	t = extru(ir,fptpos,5) * sizeof(double)/sizeof(unsigned);
132 	if (t == 0 && class != 2)	/* don't allow fr0 as a dest */
133 		return(MAJOR_0C_EXCP);
134 	fmt = extru(ir,fpfmtpos,2);	/* get fmt completer */
135 
136 	switch (class) {
137 	    case 0:
138 		switch (subop) {
139 			case 0:	/* COPR 0,0 emulated above*/
140 			case 1:
141 			case 6:
142 			case 7:
143 				return(MAJOR_0C_EXCP);
144 			case 2:	/* FCPY */
145 				switch (fmt) {
146 				    case 2: /* illegal */
147 					return(MAJOR_0C_EXCP);
148 				    case 3: /* quad */
149 					fpregs[t+3] = fpregs[r1+3];
150 					fpregs[t+2] = fpregs[r1+2];
151 				    case 1: /* double */
152 					fpregs[t+1] = fpregs[r1+1];
153 				    case 0: /* single */
154 					fpregs[t] = fpregs[r1];
155 					return(NOEXCEPTION);
156 				}
157 			case 3: /* FABS */
158 				switch (fmt) {
159 				    case 2: /* illegal */
160 					return(MAJOR_0C_EXCP);
161 				    case 3: /* quad */
162 					fpregs[t+3] = fpregs[r1+3];
163 					fpregs[t+2] = fpregs[r1+2];
164 				    case 1: /* double */
165 					fpregs[t+1] = fpregs[r1+1];
166 				    case 0: /* single */
167 					/* copy and clear sign bit */
168 					fpregs[t] = fpregs[r1] & 0x7fffffff;
169 					return(NOEXCEPTION);
170 				}
171 			case 4: /* FSQRT */
172 				switch (fmt) {
173 				    case 0:
174 					return(sgl_fsqrt(&fpregs[r1],
175 						&fpregs[t],status));
176 				    case 1:
177 					return(dbl_fsqrt(&fpregs[r1],
178 						&fpregs[t],status));
179 				    case 2:
180 				    case 3: /* quad not implemented */
181 					return(MAJOR_0C_EXCP);
182 				}
183 			case 5: /* FRND */
184 				switch (fmt) {
185 				    case 0:
186 					return(sgl_frnd(&fpregs[r1],
187 						&fpregs[t],status));
188 				    case 1:
189 					return(dbl_frnd(&fpregs[r1],
190 						&fpregs[t],status));
191 				    case 2:
192 				    case 3: /* quad not implemented */
193 					return(MAJOR_0C_EXCP);
194 				}
195 		} /* end of switch (subop) */
196 
197 	case 1: /* class 1 */
198 		df = extru(ir,fpdfpos,2); /* get dest format */
199 		if ((df & 2) || (fmt & 2)) {
200 			/*
201 			 * fmt's 2 and 3 are illegal of not implemented
202 			 * quad conversions
203 			 */
204 			return(MAJOR_0C_EXCP);
205 		}
206 		/*
207 		 * encode source and dest formats into 2 bits.
208 		 * high bit is source, low bit is dest.
209 		 * bit = 1 --> double precision
210 		 */
211 		fmt = (fmt << 1) | df;
212 		switch (subop) {
213 			case 0: /* FCNVFF */
214 				switch(fmt) {
215 				    case 0: /* sgl/sgl */
216 					return(MAJOR_0C_EXCP);
217 				    case 1: /* sgl/dbl */
218 					return(sgl_to_dbl_fcnvff(&fpregs[r1],
219 						&fpregs[t],status));
220 				    case 2: /* dbl/sgl */
221 					return(dbl_to_sgl_fcnvff(&fpregs[r1],
222 						&fpregs[t],status));
223 				    case 3: /* dbl/dbl */
224 					return(MAJOR_0C_EXCP);
225 				}
226 			case 1: /* FCNVXF */
227 				switch(fmt) {
228 				    case 0: /* sgl/sgl */
229 					return(sgl_to_sgl_fcnvxf(&fpregs[r1],
230 						&fpregs[t],status));
231 				    case 1: /* sgl/dbl */
232 					return(sgl_to_dbl_fcnvxf(&fpregs[r1],
233 						&fpregs[t],status));
234 				    case 2: /* dbl/sgl */
235 					return(dbl_to_sgl_fcnvxf(&fpregs[r1],
236 						&fpregs[t],status));
237 				    case 3: /* dbl/dbl */
238 					return(dbl_to_dbl_fcnvxf(&fpregs[r1],
239 						&fpregs[t],status));
240 				}
241 			case 2: /* FCNVFX */
242 				switch(fmt) {
243 				    case 0: /* sgl/sgl */
244 					return(sgl_to_sgl_fcnvfx(&fpregs[r1],
245 						&fpregs[t],status));
246 				    case 1: /* sgl/dbl */
247 					return(sgl_to_dbl_fcnvfx(&fpregs[r1],
248 						&fpregs[t],status));
249 				    case 2: /* dbl/sgl */
250 					return(dbl_to_sgl_fcnvfx(&fpregs[r1],
251 						&fpregs[t],status));
252 				    case 3: /* dbl/dbl */
253 					return(dbl_to_dbl_fcnvfx(&fpregs[r1],
254 						&fpregs[t],status));
255 				}
256 			case 3: /* FCNVFXT */
257 				switch(fmt) {
258 				    case 0: /* sgl/sgl */
259 					return(sgl_to_sgl_fcnvfxt(&fpregs[r1],
260 						&fpregs[t],status));
261 				    case 1: /* sgl/dbl */
262 					return(sgl_to_dbl_fcnvfxt(&fpregs[r1],
263 						&fpregs[t],status));
264 				    case 2: /* dbl/sgl */
265 					return(dbl_to_sgl_fcnvfxt(&fpregs[r1],
266 						&fpregs[t],status));
267 				    case 3: /* dbl/dbl */
268 					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],
269 						&fpregs[t],status));
270 				}
271 		} /* end of switch subop */
272 
273 	case 2: /* class 2 */
274 		r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(unsigned);
275 		if (r2 == 0)
276 			r2 = fpzeroreg;
277 		switch (subop) {
278 			case 2:
279 			case 3:
280 			case 4:
281 			case 5:
282 			case 6:
283 			case 7:
284 				return(MAJOR_0C_EXCP);
285 			case 0: /* FCMP */
286 				switch (fmt) {
287 				    case 0:
288 					return(sgl_fcmp(&fpregs[r1],&fpregs[r2],
289 						extru(ir,fptpos,5),status));
290 				    case 1:
291 					return(dbl_fcmp(&fpregs[r1],&fpregs[r2],
292 						extru(ir,fptpos,5),status));
293 				    case 2: /* illegal */
294 				    case 3: /* quad not implemented */
295 					return(MAJOR_0C_EXCP);
296 				}
297 			case 1: /* FTEST */
298 				switch (fmt) {
299 				    case 0:
300 					/*
301 					 * arg0 is not used
302 					 * second param is the t field used for
303 					 * ftest,acc and ftest,rej
304 					 */
305 					/* XXX fredette - broken */
306 #if 0
307 					return(ftest(0,extru(ir,fptpos,5),
308 						&fpregs[0]));
309 #else
310 					panic("ftest");
311 #endif
312 				    case 1:
313 				    case 2:
314 				    case 3:
315 					return(MAJOR_0C_EXCP);
316 				}
317 		} /* end if switch for class 2*/
318 	case 3: /* class 3 */
319 		r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(unsigned);
320 		if (r2 == 0)
321 			r2 = fpzeroreg;
322 		switch (subop) {
323 			case 5:
324 			case 6:
325 			case 7:
326 				return(MAJOR_0C_EXCP);
327 
328 			case 0: /* FADD */
329 				switch (fmt) {
330 				    case 0:
331 					return(sgl_fadd(&fpregs[r1],&fpregs[r2],
332 						&fpregs[t],status));
333 				    case 1:
334 					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
335 						&fpregs[t],status));
336 				    case 2: /* illegal */
337 				    case 3: /* quad not implemented */
338 					return(MAJOR_0C_EXCP);
339 				}
340 			case 1: /* FSUB */
341 				switch (fmt) {
342 				    case 0:
343 					return(sgl_fsub(&fpregs[r1],&fpregs[r2],
344 						&fpregs[t],status));
345 				    case 1:
346 					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
347 						&fpregs[t],status));
348 				    case 2: /* illegal */
349 				    case 3: /* quad not implemented */
350 					return(MAJOR_0C_EXCP);
351 				}
352 			case 2: /* FMPY */
353 				switch (fmt) {
354 				    case 0:
355 					return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
356 						&fpregs[t],status));
357 				    case 1:
358 					return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
359 						&fpregs[t],status));
360 				    case 2: /* illegal */
361 				    case 3: /* quad not implemented */
362 					return(MAJOR_0C_EXCP);
363 				}
364 			case 3: /* FDIV */
365 				switch (fmt) {
366 				    case 0:
367 					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
368 						&fpregs[t],status));
369 				    case 1:
370 					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
371 						&fpregs[t],status));
372 				    case 2: /* illegal */
373 				    case 3: /* quad not implemented */
374 					return(MAJOR_0C_EXCP);
375 				}
376 			case 4: /* FREM */
377 				switch (fmt) {
378 				    case 0:
379 					return(sgl_frem(&fpregs[r1],&fpregs[r2],
380 						&fpregs[t],status));
381 				    case 1:
382 					return(dbl_frem(&fpregs[r1],&fpregs[r2],
383 						&fpregs[t],status));
384 				    case 2: /* illegal */
385 				    case 3: /* quad not implemented */
386 					return(MAJOR_0C_EXCP);
387 				}
388 		} /* end of class 3 switch */
389 	} /* end of switch(class) */
390 	panic("decode_0c");
391 }
392 
393 int
decode_0e(unsigned ir,unsigned class,unsigned subop,unsigned fpregs[])394 decode_0e(unsigned ir,unsigned class,unsigned subop,unsigned fpregs[])
395 {
396 	unsigned r1,r2,t;	/* operand register offsets */
397 	unsigned fmt;		/* also sf for class 1 conversions */
398 	unsigned df;		/* dest format for class 1 conversions */
399 	unsigned *status;
400 
401 	status = &fpregs[0];
402 	r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
403 	if (r1 == 0)
404 		r1 = fpzeroreg;
405 	t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
406 	if (t == 0 && class != 2)
407 		return(MAJOR_0E_EXCP);
408 	if (class < 2)		/* class 0 or 1 has 2 bit fmt */
409 		fmt = extru(ir,fpfmtpos,2);
410 	else			/* class 2 and 3 have 1 bit fmt */
411 		fmt = extru(ir,fp0efmtpos,1);
412 
413 	switch (class) {
414 	    case 0:
415 		switch (subop) {
416 			case 0: /* unimplemented */
417 			case 1:
418 			case 6:
419 			case 7:
420 				return(MAJOR_0E_EXCP);
421 			case 2: /* FCPY */
422 				switch (fmt) {
423 				    case 2:
424 				    case 3:
425 					return(MAJOR_0E_EXCP);
426 				    case 1: /* double */
427 					fpregs[t+1] = fpregs[r1+1];
428 				    case 0: /* single */
429 					fpregs[t] = fpregs[r1];
430 					return(NOEXCEPTION);
431 				}
432 			case 3: /* FABS */
433 				switch (fmt) {
434 				    case 2:
435 				    case 3:
436 					return(MAJOR_0E_EXCP);
437 				    case 1: /* double */
438 					fpregs[t+1] = fpregs[r1+1];
439 				    case 0: /* single */
440 					fpregs[t] = fpregs[r1] & 0x7fffffff;
441 					return(NOEXCEPTION);
442 				}
443 			case 4: /* FSQRT */
444 				switch (fmt) {
445 				    case 0:
446 					return(sgl_fsqrt(&fpregs[r1],
447 						&fpregs[t], status));
448 				    case 1:
449 					return(dbl_fsqrt(&fpregs[r1],
450 						&fpregs[t], status));
451 				    case 2:
452 				    case 3:
453 					return(MAJOR_0E_EXCP);
454 				}
455 			case 5: /* FRMD */
456 				switch (fmt) {
457 				    case 0:
458 					return(sgl_frnd(&fpregs[r1],
459 						&fpregs[t], status));
460 				    case 1:
461 					return(dbl_frnd(&fpregs[r1],
462 						&fpregs[t], status));
463 				    case 2:
464 				    case 3:
465 					return(MAJOR_0E_EXCP);
466 				}
467 		} /* end of switch (subop */
468 
469 	case 1: /* class 1 */
470 		df = extru(ir,fpdfpos,2); /* get dest format */
471 		if ((df & 2) || (fmt & 2))
472 			return(MAJOR_0E_EXCP);
473 
474 		fmt = (fmt << 1) | df;
475 		switch (subop) {
476 			case 0: /* FCNVFF */
477 				switch(fmt) {
478 				    case 0: /* sgl/sgl */
479 					return(MAJOR_0E_EXCP);
480 				    case 1: /* sgl/dbl */
481 					return(sgl_to_dbl_fcnvff(&fpregs[r1],
482 						&fpregs[t],status));
483 				    case 2: /* dbl/sgl */
484 					return(dbl_to_sgl_fcnvff(&fpregs[r1],
485 						&fpregs[t],status));
486 				    case 3: /* dbl/dbl */
487 					return(MAJOR_0E_EXCP);
488 				}
489 			case 1: /* FCNVXF */
490 				switch(fmt) {
491 				    case 0: /* sgl/sgl */
492 					return(sgl_to_sgl_fcnvxf(&fpregs[r1],
493 						&fpregs[t],status));
494 				    case 1: /* sgl/dbl */
495 					return(sgl_to_dbl_fcnvxf(&fpregs[r1],
496 						&fpregs[t],status));
497 				    case 2: /* dbl/sgl */
498 					return(dbl_to_sgl_fcnvxf(&fpregs[r1],
499 						&fpregs[t],status));
500 				    case 3: /* dbl/dbl */
501 					return(dbl_to_dbl_fcnvxf(&fpregs[r1],
502 						&fpregs[t],status));
503 				}
504 			case 2: /* FCNVFX */
505 				switch(fmt) {
506 				    case 0: /* sgl/sgl */
507 					return(sgl_to_sgl_fcnvfx(&fpregs[r1],
508 						&fpregs[t],status));
509 				    case 1: /* sgl/dbl */
510 					return(sgl_to_dbl_fcnvfx(&fpregs[r1],
511 						&fpregs[t],status));
512 				    case 2: /* dbl/sgl */
513 					return(dbl_to_sgl_fcnvfx(&fpregs[r1],
514 						&fpregs[t],status));
515 				    case 3: /* dbl/dbl */
516 					return(dbl_to_dbl_fcnvfx(&fpregs[r1],
517 						&fpregs[t],status));
518 				}
519 			case 3: /* FCNVFXT */
520 				switch(fmt) {
521 				    case 0: /* sgl/sgl */
522 					return(sgl_to_sgl_fcnvfxt(&fpregs[r1],
523 						&fpregs[t],status));
524 				    case 1: /* sgl/dbl */
525 					return(sgl_to_dbl_fcnvfxt(&fpregs[r1],
526 						&fpregs[t],status));
527 				    case 2: /* dbl/sgl */
528 					return(dbl_to_sgl_fcnvfxt(&fpregs[r1],
529 						&fpregs[t],status));
530 				    case 3: /* dbl/dbl */
531 					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],
532 						&fpregs[t],status));
533 				}
534 		} /* end of switch subop */
535 	case 2: /* class 2 */
536 		r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
537 		if (r2 == 0)
538 			r2 = fpzeroreg;
539 		switch (subop) {
540 			case 1:
541 			case 2:
542 			case 3:
543 			case 4:
544 			case 5:
545 			case 6:
546 			case 7:
547 				return(MAJOR_0E_EXCP);
548 			case 0: /* FCMP */
549 				switch (fmt) {
550 				    /*
551 				     * fmt is only 1 bit long
552 				     */
553 				    case 0:
554 					return(sgl_fcmp(&fpregs[r1],&fpregs[r2],
555 						extru(ir,fptpos,5),status));
556 				    case 1:
557 					return(dbl_fcmp(&fpregs[r1],&fpregs[r2],
558 						extru(ir,fptpos,5),status));
559 				}
560 		} /* end of switch for class 2 */
561 	case 3: /* class 3 */
562 		r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
563 		if (r2 == 0)
564 			r2 = fpzeroreg;
565 		switch (subop) {
566 			case 5:
567 			case 6:
568 			case 7:
569 				return(MAJOR_0E_EXCP);
570 
571 			/*
572 			 * Note that fmt is only 1 bit for class 3 */
573 			case 0: /* FADD */
574 				switch (fmt) {
575 				    case 0:
576 					return(sgl_fadd(&fpregs[r1],&fpregs[r2],
577 						&fpregs[t],status));
578 				    case 1:
579 					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
580 						&fpregs[t],status));
581 				}
582 			case 1: /* FSUB */
583 				switch (fmt) {
584 				    case 0:
585 					return(sgl_fsub(&fpregs[r1],&fpregs[r2],
586 						&fpregs[t],status));
587 				    case 1:
588 					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
589 						&fpregs[t],status));
590 				}
591 			case 2: /* FMPY or XMPYU */
592 				/*
593 				 * check for integer multiply (x bit set)
594 				 */
595 				if (extru(ir,fpxpos,1)) {
596 				    /*
597 				     * emulate XMPYU
598 				     */
599 				    switch (fmt) {
600 					case 0:
601 					    /*
602 					     * bad instruction if t specifies
603 					     * the right half of a register
604 					     */
605 					    if (t & 1)
606 						return(MAJOR_0E_EXCP);
607 					    /* XXX fredette - broken. */
608 #if 0
609 					    impyu(&fpregs[r1],&fpregs[r2],
610 						&fpregs[t]);
611 					    return(NOEXCEPTION);
612 #else
613 					    panic("impyu");
614 #endif
615 					case 1:
616 						return(MAJOR_0E_EXCP);
617 				    }
618 				}
619 				else { /* FMPY */
620 				    switch (fmt) {
621 				        case 0:
622 					    return(sgl_fmpy(&fpregs[r1],
623 					       &fpregs[r2],&fpregs[t],status));
624 				        case 1:
625 					    return(dbl_fmpy(&fpregs[r1],
626 					       &fpregs[r2],&fpregs[t],status));
627 				    }
628 				}
629 			case 3: /* FDIV */
630 				switch (fmt) {
631 				    case 0:
632 					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
633 						&fpregs[t],status));
634 				    case 1:
635 					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
636 						&fpregs[t],status));
637 				}
638 			case 4: /* FREM */
639 				switch (fmt) {
640 				    case 0:
641 					return(sgl_frem(&fpregs[r1],&fpregs[r2],
642 						&fpregs[t],status));
643 				    case 1:
644 					return(dbl_frem(&fpregs[r1],&fpregs[r2],
645 						&fpregs[t],status));
646 				}
647 		} /* end of class 3 switch */
648 	} /* end of switch(class) */
649 	panic("decode_0e");
650 }
651 
652 
653 /*
654  * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
655  */
656 int
decode_06(unsigned ir,unsigned fpregs[])657 decode_06(unsigned ir,unsigned fpregs[])
658 {
659 	unsigned rm1, rm2, tm, ra, ta; /* operands */
660 	unsigned fmt;
661 	unsigned error = 0;
662 	unsigned status;
663 	union {
664 		double dbl;
665 		float flt;
666 		struct { unsigned i1; unsigned i2; } ints;
667 	} mtmp, atmp;
668 
669 
670 	status = fpregs[0];		/* use a local copy of status reg */
671 	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */
672 	if (fmt == 0) { /* DBL */
673 		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(unsigned);
674 		if (rm1 == 0)
675 			rm1 = fpzeroreg;
676 		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(unsigned);
677 		if (rm2 == 0)
678 			rm2 = fpzeroreg;
679 		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(unsigned);
680 		if (tm == 0)
681 			return(MAJOR_06_EXCP);
682 		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(unsigned);
683 		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(unsigned);
684 		if (ta == 0)
685 			return(MAJOR_06_EXCP);
686 
687 #ifdef TIMEX
688 		if (ra == 0) {
689 			 /* special case FMPYCFXT */
690 			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
691 					&status))
692 				error = 1;
693 			if (dbl_to_sgl_fcnvfxt(&fpregs[ta],(unsigned *) &atmp,
694 				(unsigned *) &atmp,&status))
695 				error = 1;
696 		}
697 		else {
698 #else
699 		if (ra == 0)
700 			ra = fpzeroreg;
701 #endif
702 
703 			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
704 					&status))
705 				error = 1;
706 			if (dbl_fadd(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
707 					&status))
708 				error = 1;
709 #ifdef TIMEX
710 		}
711 #endif
712 		if (error)
713 			return(MAJOR_06_EXCP);
714 		else {
715 			/* copy results */
716 			fpregs[tm] = mtmp.ints.i1;
717 			fpregs[tm+1] = mtmp.ints.i2;
718 			fpregs[ta] = atmp.ints.i1;
719 			fpregs[ta+1] = atmp.ints.i2;
720 			fpregs[0] = status;
721 			return(NOEXCEPTION);
722 		}
723 	}
724 	else { /* SGL */
725 		/*
726 		 * calculate offsets for single precision numbers
727 		 * See table 6-14 in PA-89 architecture for mapping
728 		 */
729 		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */
730 		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */
731 
732 		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */
733 		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */
734 
735 		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */
736 		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */
737 
738 		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */
739 		ra |= extru(ir,fprapos-4,1);	/* add right word offset */
740 
741 		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */
742 		ta |= extru(ir,fptapos-4,1);	/* add right word offset */
743 
744 		if (ra == 0x20) { /* special case FMPYCFXT (really 0) */
745 			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
746 					&status))
747 				error = 1;
748 			/* XXX fredette - this is broken */
749 #if 0
750 			if (sgl_to_sgl_fcnvfxt(&fpregs[ta],(unsigned *) &atmp,
751 				(unsigned *) &atmp,&status))
752 				error = 1;
753 #else
754 				panic("FMPYADD");
755 #endif
756 		}
757 		else {
758 			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
759 					&status))
760 				error = 1;
761 			if (sgl_fadd(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
762 					&status))
763 				error = 1;
764 		}
765 		if (error)
766 			return(MAJOR_06_EXCP);
767 		else {
768 			/* copy results */
769 			fpregs[tm] = mtmp.ints.i1;
770 			fpregs[ta] = atmp.ints.i1;
771 			fpregs[0] = status;
772 			return(NOEXCEPTION);
773 		}
774 	}
775 }
776 
777 /*
778  * routine to decode the 26 (FMPYSUB) instruction
779  */
780 int
decode_26(unsigned ir,unsigned fpregs[])781 decode_26(unsigned ir,unsigned fpregs[])
782 {
783 	unsigned rm1, rm2, tm, ra, ta; /* operands */
784 	unsigned fmt;
785 	unsigned error = 0;
786 	unsigned status;
787 	union {
788 		double dbl;
789 		float flt;
790 		struct { unsigned i1; unsigned i2; } ints;
791 	} mtmp, atmp;
792 
793 
794 	status = fpregs[0];
795 	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */
796 	if (fmt == 0) { /* DBL */
797 		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(unsigned);
798 		if (rm1 == 0)
799 			rm1 = fpzeroreg;
800 		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(unsigned);
801 		if (rm2 == 0)
802 			rm2 = fpzeroreg;
803 		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(unsigned);
804 		if (tm == 0)
805 			return(MAJOR_26_EXCP);
806 		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(unsigned);
807 		if (ra == 0)
808 			return(MAJOR_26_EXCP);
809 		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(unsigned);
810 		if (ta == 0)
811 			return(MAJOR_26_EXCP);
812 
813 		if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
814 				&status))
815 			error = 1;
816 		if (dbl_fsub(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
817 				&status))
818 			error = 1;
819 		if (error)
820 			return(MAJOR_26_EXCP);
821 		else {
822 			/* copy results */
823 			fpregs[tm] = mtmp.ints.i1;
824 			fpregs[tm+1] = mtmp.ints.i2;
825 			fpregs[ta] = atmp.ints.i1;
826 			fpregs[ta+1] = atmp.ints.i2;
827 			fpregs[0] = status;
828 			return(NOEXCEPTION);
829 		}
830 	}
831 	else { /* SGL */
832 		/*
833 		 * calculate offsets for single precision numbers
834 		 * See table 6-14 in PA-89 architecture for mapping
835 		 */
836 		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */
837 		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */
838 
839 		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */
840 		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */
841 
842 		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */
843 		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */
844 
845 		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */
846 		ra |= extru(ir,fprapos-4,1);	/* add right word offset */
847 
848 		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */
849 		ta |= extru(ir,fptapos-4,1);	/* add right word offset */
850 
851 		if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
852 				&status))
853 			error = 1;
854 		if (sgl_fsub(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
855 				&status))
856 			error = 1;
857 		if (error)
858 			return(MAJOR_26_EXCP);
859 		else {
860 			/* copy results */
861 			fpregs[tm] = mtmp.ints.i1;
862 			fpregs[ta] = atmp.ints.i1;
863 			fpregs[0] = status;
864 			return(NOEXCEPTION);
865 		}
866 	}
867 
868 }
869