fpudispatch.c revision 1.2 1 /* $NetBSD: fpudispatch.c,v 1.2 2003/07/15 02:29:42 lukem 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.2 2003/07/15 02:29:42 lukem 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
116 decode_0c(ir,class,subop,fpregs)
117 unsigned ir,class,subop;
118 unsigned fpregs[];
119 {
120 unsigned r1,r2,t; /* operand register offsets */
121 unsigned fmt; /* also sf for class 1 conversions */
122 unsigned df; /* for class 1 conversions */
123 unsigned *status;
124
125 if (ir == COPR_INST) {
126 fpregs[0] = EMULATION_VERSION << 11;
127 return(NOEXCEPTION);
128 }
129 status = &fpregs[0]; /* fp status register */
130 r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(unsigned);
131 if (r1 == 0) /* map fr0 source to constant zero */
132 r1 = fpzeroreg;
133 t = extru(ir,fptpos,5) * sizeof(double)/sizeof(unsigned);
134 if (t == 0 && class != 2) /* don't allow fr0 as a dest */
135 return(MAJOR_0C_EXCP);
136 fmt = extru(ir,fpfmtpos,2); /* get fmt completer */
137
138 switch (class) {
139 case 0:
140 switch (subop) {
141 case 0: /* COPR 0,0 emulated above*/
142 case 1:
143 case 6:
144 case 7:
145 return(MAJOR_0C_EXCP);
146 case 2: /* FCPY */
147 switch (fmt) {
148 case 2: /* illegal */
149 return(MAJOR_0C_EXCP);
150 case 3: /* quad */
151 fpregs[t+3] = fpregs[r1+3];
152 fpregs[t+2] = fpregs[r1+2];
153 case 1: /* double */
154 fpregs[t+1] = fpregs[r1+1];
155 case 0: /* single */
156 fpregs[t] = fpregs[r1];
157 return(NOEXCEPTION);
158 }
159 case 3: /* FABS */
160 switch (fmt) {
161 case 2: /* illegal */
162 return(MAJOR_0C_EXCP);
163 case 3: /* quad */
164 fpregs[t+3] = fpregs[r1+3];
165 fpregs[t+2] = fpregs[r1+2];
166 case 1: /* double */
167 fpregs[t+1] = fpregs[r1+1];
168 case 0: /* single */
169 /* copy and clear sign bit */
170 fpregs[t] = fpregs[r1] & 0x7fffffff;
171 return(NOEXCEPTION);
172 }
173 case 4: /* FSQRT */
174 switch (fmt) {
175 case 0:
176 return(sgl_fsqrt(&fpregs[r1],
177 &fpregs[t],status));
178 case 1:
179 return(dbl_fsqrt(&fpregs[r1],
180 &fpregs[t],status));
181 case 2:
182 case 3: /* quad not implemented */
183 return(MAJOR_0C_EXCP);
184 }
185 case 5: /* FRND */
186 switch (fmt) {
187 case 0:
188 return(sgl_frnd(&fpregs[r1],
189 &fpregs[t],status));
190 case 1:
191 return(dbl_frnd(&fpregs[r1],
192 &fpregs[t],status));
193 case 2:
194 case 3: /* quad not implemented */
195 return(MAJOR_0C_EXCP);
196 }
197 } /* end of switch (subop) */
198
199 case 1: /* class 1 */
200 df = extru(ir,fpdfpos,2); /* get dest format */
201 if ((df & 2) || (fmt & 2)) {
202 /*
203 * fmt's 2 and 3 are illegal of not implemented
204 * quad conversions
205 */
206 return(MAJOR_0C_EXCP);
207 }
208 /*
209 * encode source and dest formats into 2 bits.
210 * high bit is source, low bit is dest.
211 * bit = 1 --> double precision
212 */
213 fmt = (fmt << 1) | df;
214 switch (subop) {
215 case 0: /* FCNVFF */
216 switch(fmt) {
217 case 0: /* sgl/sgl */
218 return(MAJOR_0C_EXCP);
219 case 1: /* sgl/dbl */
220 return(sgl_to_dbl_fcnvff(&fpregs[r1],
221 &fpregs[t],status));
222 case 2: /* dbl/sgl */
223 return(dbl_to_sgl_fcnvff(&fpregs[r1],
224 &fpregs[t],status));
225 case 3: /* dbl/dbl */
226 return(MAJOR_0C_EXCP);
227 }
228 case 1: /* FCNVXF */
229 switch(fmt) {
230 case 0: /* sgl/sgl */
231 return(sgl_to_sgl_fcnvxf(&fpregs[r1],
232 &fpregs[t],status));
233 case 1: /* sgl/dbl */
234 return(sgl_to_dbl_fcnvxf(&fpregs[r1],
235 &fpregs[t],status));
236 case 2: /* dbl/sgl */
237 return(dbl_to_sgl_fcnvxf(&fpregs[r1],
238 &fpregs[t],status));
239 case 3: /* dbl/dbl */
240 return(dbl_to_dbl_fcnvxf(&fpregs[r1],
241 &fpregs[t],status));
242 }
243 case 2: /* FCNVFX */
244 switch(fmt) {
245 case 0: /* sgl/sgl */
246 return(sgl_to_sgl_fcnvfx(&fpregs[r1],
247 &fpregs[t],status));
248 case 1: /* sgl/dbl */
249 return(sgl_to_dbl_fcnvfx(&fpregs[r1],
250 &fpregs[t],status));
251 case 2: /* dbl/sgl */
252 return(dbl_to_sgl_fcnvfx(&fpregs[r1],
253 &fpregs[t],status));
254 case 3: /* dbl/dbl */
255 return(dbl_to_dbl_fcnvfx(&fpregs[r1],
256 &fpregs[t],status));
257 }
258 case 3: /* FCNVFXT */
259 switch(fmt) {
260 case 0: /* sgl/sgl */
261 return(sgl_to_sgl_fcnvfxt(&fpregs[r1],
262 &fpregs[t],status));
263 case 1: /* sgl/dbl */
264 return(sgl_to_dbl_fcnvfxt(&fpregs[r1],
265 &fpregs[t],status));
266 case 2: /* dbl/sgl */
267 return(dbl_to_sgl_fcnvfxt(&fpregs[r1],
268 &fpregs[t],status));
269 case 3: /* dbl/dbl */
270 return(dbl_to_dbl_fcnvfxt(&fpregs[r1],
271 &fpregs[t],status));
272 }
273 } /* end of switch subop */
274
275 case 2: /* class 2 */
276 r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(unsigned);
277 if (r2 == 0)
278 r2 = fpzeroreg;
279 switch (subop) {
280 case 2:
281 case 3:
282 case 4:
283 case 5:
284 case 6:
285 case 7:
286 return(MAJOR_0C_EXCP);
287 case 0: /* FCMP */
288 switch (fmt) {
289 case 0:
290 return(sgl_fcmp(&fpregs[r1],&fpregs[r2],
291 extru(ir,fptpos,5),status));
292 case 1:
293 return(dbl_fcmp(&fpregs[r1],&fpregs[r2],
294 extru(ir,fptpos,5),status));
295 case 2: /* illegal */
296 case 3: /* quad not implemented */
297 return(MAJOR_0C_EXCP);
298 }
299 case 1: /* FTEST */
300 switch (fmt) {
301 case 0:
302 /*
303 * arg0 is not used
304 * second param is the t field used for
305 * ftest,acc and ftest,rej
306 */
307 /* XXX fredette - broken */
308 #if 0
309 return(ftest(0,extru(ir,fptpos,5),
310 &fpregs[0]));
311 #else
312 panic("ftest");
313 #endif
314 case 1:
315 case 2:
316 case 3:
317 return(MAJOR_0C_EXCP);
318 }
319 } /* end if switch for class 2*/
320 case 3: /* class 3 */
321 r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(unsigned);
322 if (r2 == 0)
323 r2 = fpzeroreg;
324 switch (subop) {
325 case 5:
326 case 6:
327 case 7:
328 return(MAJOR_0C_EXCP);
329
330 case 0: /* FADD */
331 switch (fmt) {
332 case 0:
333 return(sgl_fadd(&fpregs[r1],&fpregs[r2],
334 &fpregs[t],status));
335 case 1:
336 return(dbl_fadd(&fpregs[r1],&fpregs[r2],
337 &fpregs[t],status));
338 case 2: /* illegal */
339 case 3: /* quad not implemented */
340 return(MAJOR_0C_EXCP);
341 }
342 case 1: /* FSUB */
343 switch (fmt) {
344 case 0:
345 return(sgl_fsub(&fpregs[r1],&fpregs[r2],
346 &fpregs[t],status));
347 case 1:
348 return(dbl_fsub(&fpregs[r1],&fpregs[r2],
349 &fpregs[t],status));
350 case 2: /* illegal */
351 case 3: /* quad not implemented */
352 return(MAJOR_0C_EXCP);
353 }
354 case 2: /* FMPY */
355 switch (fmt) {
356 case 0:
357 return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
358 &fpregs[t],status));
359 case 1:
360 return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
361 &fpregs[t],status));
362 case 2: /* illegal */
363 case 3: /* quad not implemented */
364 return(MAJOR_0C_EXCP);
365 }
366 case 3: /* FDIV */
367 switch (fmt) {
368 case 0:
369 return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
370 &fpregs[t],status));
371 case 1:
372 return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
373 &fpregs[t],status));
374 case 2: /* illegal */
375 case 3: /* quad not implemented */
376 return(MAJOR_0C_EXCP);
377 }
378 case 4: /* FREM */
379 switch (fmt) {
380 case 0:
381 return(sgl_frem(&fpregs[r1],&fpregs[r2],
382 &fpregs[t],status));
383 case 1:
384 return(dbl_frem(&fpregs[r1],&fpregs[r2],
385 &fpregs[t],status));
386 case 2: /* illegal */
387 case 3: /* quad not implemented */
388 return(MAJOR_0C_EXCP);
389 }
390 } /* end of class 3 switch */
391 } /* end of switch(class) */
392 panic("decode_0c");
393 }
394
395 int
396 decode_0e(ir,class,subop,fpregs)
397 unsigned ir,class,subop;
398 unsigned fpregs[];
399 {
400 unsigned r1,r2,t; /* operand register offsets */
401 unsigned fmt; /* also sf for class 1 conversions */
402 unsigned df; /* dest format for class 1 conversions */
403 unsigned *status;
404
405 status = &fpregs[0];
406 r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
407 if (r1 == 0)
408 r1 = fpzeroreg;
409 t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
410 if (t == 0 && class != 2)
411 return(MAJOR_0E_EXCP);
412 if (class < 2) /* class 0 or 1 has 2 bit fmt */
413 fmt = extru(ir,fpfmtpos,2);
414 else /* class 2 and 3 have 1 bit fmt */
415 fmt = extru(ir,fp0efmtpos,1);
416
417 switch (class) {
418 case 0:
419 switch (subop) {
420 case 0: /* unimplemented */
421 case 1:
422 case 6:
423 case 7:
424 return(MAJOR_0E_EXCP);
425 case 2: /* FCPY */
426 switch (fmt) {
427 case 2:
428 case 3:
429 return(MAJOR_0E_EXCP);
430 case 1: /* double */
431 fpregs[t+1] = fpregs[r1+1];
432 case 0: /* single */
433 fpregs[t] = fpregs[r1];
434 return(NOEXCEPTION);
435 }
436 case 3: /* FABS */
437 switch (fmt) {
438 case 2:
439 case 3:
440 return(MAJOR_0E_EXCP);
441 case 1: /* double */
442 fpregs[t+1] = fpregs[r1+1];
443 case 0: /* single */
444 fpregs[t] = fpregs[r1] & 0x7fffffff;
445 return(NOEXCEPTION);
446 }
447 case 4: /* FSQRT */
448 switch (fmt) {
449 case 0:
450 return(sgl_fsqrt(&fpregs[r1],
451 &fpregs[t], status));
452 case 1:
453 return(dbl_fsqrt(&fpregs[r1],
454 &fpregs[t], status));
455 case 2:
456 case 3:
457 return(MAJOR_0E_EXCP);
458 }
459 case 5: /* FRMD */
460 switch (fmt) {
461 case 0:
462 return(sgl_frnd(&fpregs[r1],
463 &fpregs[t], status));
464 case 1:
465 return(dbl_frnd(&fpregs[r1],
466 &fpregs[t], status));
467 case 2:
468 case 3:
469 return(MAJOR_0E_EXCP);
470 }
471 } /* end of switch (subop */
472
473 case 1: /* class 1 */
474 df = extru(ir,fpdfpos,2); /* get dest format */
475 if ((df & 2) || (fmt & 2))
476 return(MAJOR_0E_EXCP);
477
478 fmt = (fmt << 1) | df;
479 switch (subop) {
480 case 0: /* FCNVFF */
481 switch(fmt) {
482 case 0: /* sgl/sgl */
483 return(MAJOR_0E_EXCP);
484 case 1: /* sgl/dbl */
485 return(sgl_to_dbl_fcnvff(&fpregs[r1],
486 &fpregs[t],status));
487 case 2: /* dbl/sgl */
488 return(dbl_to_sgl_fcnvff(&fpregs[r1],
489 &fpregs[t],status));
490 case 3: /* dbl/dbl */
491 return(MAJOR_0E_EXCP);
492 }
493 case 1: /* FCNVXF */
494 switch(fmt) {
495 case 0: /* sgl/sgl */
496 return(sgl_to_sgl_fcnvxf(&fpregs[r1],
497 &fpregs[t],status));
498 case 1: /* sgl/dbl */
499 return(sgl_to_dbl_fcnvxf(&fpregs[r1],
500 &fpregs[t],status));
501 case 2: /* dbl/sgl */
502 return(dbl_to_sgl_fcnvxf(&fpregs[r1],
503 &fpregs[t],status));
504 case 3: /* dbl/dbl */
505 return(dbl_to_dbl_fcnvxf(&fpregs[r1],
506 &fpregs[t],status));
507 }
508 case 2: /* FCNVFX */
509 switch(fmt) {
510 case 0: /* sgl/sgl */
511 return(sgl_to_sgl_fcnvfx(&fpregs[r1],
512 &fpregs[t],status));
513 case 1: /* sgl/dbl */
514 return(sgl_to_dbl_fcnvfx(&fpregs[r1],
515 &fpregs[t],status));
516 case 2: /* dbl/sgl */
517 return(dbl_to_sgl_fcnvfx(&fpregs[r1],
518 &fpregs[t],status));
519 case 3: /* dbl/dbl */
520 return(dbl_to_dbl_fcnvfx(&fpregs[r1],
521 &fpregs[t],status));
522 }
523 case 3: /* FCNVFXT */
524 switch(fmt) {
525 case 0: /* sgl/sgl */
526 return(sgl_to_sgl_fcnvfxt(&fpregs[r1],
527 &fpregs[t],status));
528 case 1: /* sgl/dbl */
529 return(sgl_to_dbl_fcnvfxt(&fpregs[r1],
530 &fpregs[t],status));
531 case 2: /* dbl/sgl */
532 return(dbl_to_sgl_fcnvfxt(&fpregs[r1],
533 &fpregs[t],status));
534 case 3: /* dbl/dbl */
535 return(dbl_to_dbl_fcnvfxt(&fpregs[r1],
536 &fpregs[t],status));
537 }
538 } /* end of switch subop */
539 case 2: /* class 2 */
540 r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
541 if (r2 == 0)
542 r2 = fpzeroreg;
543 switch (subop) {
544 case 1:
545 case 2:
546 case 3:
547 case 4:
548 case 5:
549 case 6:
550 case 7:
551 return(MAJOR_0E_EXCP);
552 case 0: /* FCMP */
553 switch (fmt) {
554 /*
555 * fmt is only 1 bit long
556 */
557 case 0:
558 return(sgl_fcmp(&fpregs[r1],&fpregs[r2],
559 extru(ir,fptpos,5),status));
560 case 1:
561 return(dbl_fcmp(&fpregs[r1],&fpregs[r2],
562 extru(ir,fptpos,5),status));
563 }
564 } /* end of switch for class 2 */
565 case 3: /* class 3 */
566 r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
567 if (r2 == 0)
568 r2 = fpzeroreg;
569 switch (subop) {
570 case 5:
571 case 6:
572 case 7:
573 return(MAJOR_0E_EXCP);
574
575 /*
576 * Note that fmt is only 1 bit for class 3 */
577 case 0: /* FADD */
578 switch (fmt) {
579 case 0:
580 return(sgl_fadd(&fpregs[r1],&fpregs[r2],
581 &fpregs[t],status));
582 case 1:
583 return(dbl_fadd(&fpregs[r1],&fpregs[r2],
584 &fpregs[t],status));
585 }
586 case 1: /* FSUB */
587 switch (fmt) {
588 case 0:
589 return(sgl_fsub(&fpregs[r1],&fpregs[r2],
590 &fpregs[t],status));
591 case 1:
592 return(dbl_fsub(&fpregs[r1],&fpregs[r2],
593 &fpregs[t],status));
594 }
595 case 2: /* FMPY or XMPYU */
596 /*
597 * check for integer multiply (x bit set)
598 */
599 if (extru(ir,fpxpos,1)) {
600 /*
601 * emulate XMPYU
602 */
603 switch (fmt) {
604 case 0:
605 /*
606 * bad instruction if t specifies
607 * the right half of a register
608 */
609 if (t & 1)
610 return(MAJOR_0E_EXCP);
611 /* XXX fredette - broken. */
612 #if 0
613 impyu(&fpregs[r1],&fpregs[r2],
614 &fpregs[t]);
615 return(NOEXCEPTION);
616 #else
617 panic("impyu");
618 #endif
619 case 1:
620 return(MAJOR_0E_EXCP);
621 }
622 }
623 else { /* FMPY */
624 switch (fmt) {
625 case 0:
626 return(sgl_fmpy(&fpregs[r1],
627 &fpregs[r2],&fpregs[t],status));
628 case 1:
629 return(dbl_fmpy(&fpregs[r1],
630 &fpregs[r2],&fpregs[t],status));
631 }
632 }
633 case 3: /* FDIV */
634 switch (fmt) {
635 case 0:
636 return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
637 &fpregs[t],status));
638 case 1:
639 return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
640 &fpregs[t],status));
641 }
642 case 4: /* FREM */
643 switch (fmt) {
644 case 0:
645 return(sgl_frem(&fpregs[r1],&fpregs[r2],
646 &fpregs[t],status));
647 case 1:
648 return(dbl_frem(&fpregs[r1],&fpregs[r2],
649 &fpregs[t],status));
650 }
651 } /* end of class 3 switch */
652 } /* end of switch(class) */
653 panic("decode_0e");
654 }
655
656
657 /*
658 * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
659 */
660 int
661 decode_06(ir,fpregs)
662 unsigned ir;
663 unsigned fpregs[];
664 {
665 unsigned rm1, rm2, tm, ra, ta; /* operands */
666 unsigned fmt;
667 unsigned error = 0;
668 unsigned status;
669 union {
670 double dbl;
671 float flt;
672 struct { unsigned i1; unsigned i2; } ints;
673 } mtmp, atmp;
674
675
676 status = fpregs[0]; /* use a local copy of status reg */
677 fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
678 if (fmt == 0) { /* DBL */
679 rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(unsigned);
680 if (rm1 == 0)
681 rm1 = fpzeroreg;
682 rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(unsigned);
683 if (rm2 == 0)
684 rm2 = fpzeroreg;
685 tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(unsigned);
686 if (tm == 0)
687 return(MAJOR_06_EXCP);
688 ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(unsigned);
689 ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(unsigned);
690 if (ta == 0)
691 return(MAJOR_06_EXCP);
692
693 #ifdef TIMEX
694 if (ra == 0) {
695 /* special case FMPYCFXT */
696 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
697 &status))
698 error = 1;
699 if (dbl_to_sgl_fcnvfxt(&fpregs[ta],(unsigned *) &atmp,
700 (unsigned *) &atmp,&status))
701 error = 1;
702 }
703 else {
704 #else
705 if (ra == 0)
706 ra = fpzeroreg;
707 #endif
708
709 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
710 &status))
711 error = 1;
712 if (dbl_fadd(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
713 &status))
714 error = 1;
715 #ifdef TIMEX
716 }
717 #endif
718 if (error)
719 return(MAJOR_06_EXCP);
720 else {
721 /* copy results */
722 fpregs[tm] = mtmp.ints.i1;
723 fpregs[tm+1] = mtmp.ints.i2;
724 fpregs[ta] = atmp.ints.i1;
725 fpregs[ta+1] = atmp.ints.i2;
726 fpregs[0] = status;
727 return(NOEXCEPTION);
728 }
729 }
730 else { /* SGL */
731 /*
732 * calculate offsets for single precision numbers
733 * See table 6-14 in PA-89 architecture for mapping
734 */
735 rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
736 rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
737
738 rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
739 rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
740
741 tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
742 tm |= extru(ir,fptmpos-4,1); /* add right word offset */
743
744 ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
745 ra |= extru(ir,fprapos-4,1); /* add right word offset */
746
747 ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
748 ta |= extru(ir,fptapos-4,1); /* add right word offset */
749
750 if (ra == 0x20) { /* special case FMPYCFXT (really 0) */
751 if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
752 &status))
753 error = 1;
754 /* XXX fredette - this is broken */
755 #if 0
756 if (sgl_to_sgl_fcnvfxt(&fpregs[ta],(unsigned *) &atmp,
757 (unsigned *) &atmp,&status))
758 error = 1;
759 #else
760 panic("FMPYADD");
761 #endif
762 }
763 else {
764 if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
765 &status))
766 error = 1;
767 if (sgl_fadd(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
768 &status))
769 error = 1;
770 }
771 if (error)
772 return(MAJOR_06_EXCP);
773 else {
774 /* copy results */
775 fpregs[tm] = mtmp.ints.i1;
776 fpregs[ta] = atmp.ints.i1;
777 fpregs[0] = status;
778 return(NOEXCEPTION);
779 }
780 }
781 }
782
783 /*
784 * routine to decode the 26 (FMPYSUB) instruction
785 */
786 int
787 decode_26(ir,fpregs)
788 unsigned ir;
789 unsigned fpregs[];
790 {
791 unsigned rm1, rm2, tm, ra, ta; /* operands */
792 unsigned fmt;
793 unsigned error = 0;
794 unsigned status;
795 union {
796 double dbl;
797 float flt;
798 struct { unsigned i1; unsigned i2; } ints;
799 } mtmp, atmp;
800
801
802 status = fpregs[0];
803 fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */
804 if (fmt == 0) { /* DBL */
805 rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(unsigned);
806 if (rm1 == 0)
807 rm1 = fpzeroreg;
808 rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(unsigned);
809 if (rm2 == 0)
810 rm2 = fpzeroreg;
811 tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(unsigned);
812 if (tm == 0)
813 return(MAJOR_26_EXCP);
814 ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(unsigned);
815 if (ra == 0)
816 return(MAJOR_26_EXCP);
817 ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(unsigned);
818 if (ta == 0)
819 return(MAJOR_26_EXCP);
820
821 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
822 &status))
823 error = 1;
824 if (dbl_fsub(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
825 &status))
826 error = 1;
827 if (error)
828 return(MAJOR_26_EXCP);
829 else {
830 /* copy results */
831 fpregs[tm] = mtmp.ints.i1;
832 fpregs[tm+1] = mtmp.ints.i2;
833 fpregs[ta] = atmp.ints.i1;
834 fpregs[ta+1] = atmp.ints.i2;
835 fpregs[0] = status;
836 return(NOEXCEPTION);
837 }
838 }
839 else { /* SGL */
840 /*
841 * calculate offsets for single precision numbers
842 * See table 6-14 in PA-89 architecture for mapping
843 */
844 rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */
845 rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */
846
847 rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */
848 rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */
849
850 tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */
851 tm |= extru(ir,fptmpos-4,1); /* add right word offset */
852
853 ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */
854 ra |= extru(ir,fprapos-4,1); /* add right word offset */
855
856 ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */
857 ta |= extru(ir,fptapos-4,1); /* add right word offset */
858
859 if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp,
860 &status))
861 error = 1;
862 if (sgl_fsub(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp,
863 &status))
864 error = 1;
865 if (error)
866 return(MAJOR_26_EXCP);
867 else {
868 /* copy results */
869 fpregs[tm] = mtmp.ints.i1;
870 fpregs[ta] = atmp.ints.i1;
871 fpregs[0] = status;
872 return(NOEXCEPTION);
873 }
874 }
875
876 }
877