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