1 /* $NetBSD: fpu_emu.c,v 1.7.2.4 2005/11/10 13:58:15 skrll Exp $ */
4 * Copyright 2001 Wasabi Systems, Inc.
7 * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * Copyright (c) 1992, 1993
40 * The Regents of the University of California. All rights reserved.
42 * This software was developed by the Computer Systems Engineering group
43 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
44 * contributed to Berkeley.
46 * All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Lawrence Berkeley Laboratory.
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
54 * 1. Redistributions of source code must retain the above copyright
55 * notice, this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright
57 * notice, this list of conditions and the following disclaimer in the
58 * documentation and/or other materials provided with the distribution.
59 * 3. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
75 * @(#)fpu.c 8.1 (Berkeley) 6/11/93
78 #include <sys/cdefs.h>
79 __KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.7.2.4 2005/11/10 13:58:15 skrll Exp $");
83 #include <sys/param.h>
85 #include <sys/signal.h>
86 #include <sys/systm.h>
87 #include <sys/syslog.h>
88 #include <sys/signalvar.h>
89 #include <sys/device.h> /* for evcnt */
91 #include <powerpc/instr.h>
92 #include <machine/reg.h>
93 #include <machine/fpu.h>
95 #include <powerpc/fpu/fpu_emu.h>
96 #include <powerpc/fpu/fpu_extern.h>
98 #define FPU_EMU_EVCNT_DECL(name) \
99 static struct evcnt fpu_emu_ev_##name = \
100 EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "fpemu", #name); \
101 EVCNT_ATTACH_STATIC(fpu_emu_ev_##name)
103 #define FPU_EMU_EVCNT_INCR(name) \
104 fpu_emu_ev_##name.ev_count++
106 FPU_EMU_EVCNT_DECL(stfiwx
);
107 FPU_EMU_EVCNT_DECL(fpstore
);
108 FPU_EMU_EVCNT_DECL(fpload
);
109 FPU_EMU_EVCNT_DECL(fcmpu
);
110 FPU_EMU_EVCNT_DECL(frsp
);
111 FPU_EMU_EVCNT_DECL(fctiw
);
112 FPU_EMU_EVCNT_DECL(fcmpo
);
113 FPU_EMU_EVCNT_DECL(mtfsb1
);
114 FPU_EMU_EVCNT_DECL(fnegabs
);
115 FPU_EMU_EVCNT_DECL(mcrfs
);
116 FPU_EMU_EVCNT_DECL(mtfsb0
);
117 FPU_EMU_EVCNT_DECL(fmr
);
118 FPU_EMU_EVCNT_DECL(mtfsfi
);
119 FPU_EMU_EVCNT_DECL(fnabs
);
120 FPU_EMU_EVCNT_DECL(fabs
);
121 FPU_EMU_EVCNT_DECL(mffs
);
122 FPU_EMU_EVCNT_DECL(mtfsf
);
123 FPU_EMU_EVCNT_DECL(fctid
);
124 FPU_EMU_EVCNT_DECL(fcfid
);
125 FPU_EMU_EVCNT_DECL(fdiv
);
126 FPU_EMU_EVCNT_DECL(fsub
);
127 FPU_EMU_EVCNT_DECL(fadd
);
128 FPU_EMU_EVCNT_DECL(fsqrt
);
129 FPU_EMU_EVCNT_DECL(fsel
);
130 FPU_EMU_EVCNT_DECL(fpres
);
131 FPU_EMU_EVCNT_DECL(fmul
);
132 FPU_EMU_EVCNT_DECL(frsqrte
);
133 FPU_EMU_EVCNT_DECL(fmulsub
);
134 FPU_EMU_EVCNT_DECL(fmuladd
);
135 FPU_EMU_EVCNT_DECL(fnmsub
);
136 FPU_EMU_EVCNT_DECL(fnmadd
);
138 /* FPSR exception masks */
139 #define FPSR_EX_MSK (FPSCR_VX|FPSCR_OX|FPSCR_UX|FPSCR_ZX| \
140 FPSCR_XX|FPSCR_VXSNAN|FPSCR_VXISI|FPSCR_VXIDI| \
141 FPSCR_VXZDZ|FPSCR_VXIMZ|FPSCR_VXVC|FPSCR_VXSOFT|\
142 FPSCR_VXSQRT|FPSCR_VXCVI)
143 #define FPSR_EX (FPSCR_VE|FPSCR_OE|FPSCR_UE|FPSCR_ZE|FPSCR_XE)
144 #define FPSR_EXOP (FPSR_EX_MSK&(~FPSR_EX))
150 extern vaddr_t
opc_disasm(vaddr_t loc
, int opcode
);
155 * Dump a `fpn' structure.
158 fpu_dumpfpn(struct fpn
*fp
)
160 static const char *class[] = {
161 "SNAN", "QNAN", "ZERO", "NUM", "INF"
164 printf("%s %c.%x %x %x %xE%d", class[fp
->fp_class
+ 2],
165 fp
->fp_sign
? '-' : ' ',
166 fp
->fp_mant
[0], fp
->fp_mant
[1],
167 fp
->fp_mant
[2], fp
->fp_mant
[3],
173 * fpu_execute returns the following error numbers (0 = no error):
175 #define FPE 1 /* take a floating point exception */
176 #define NOTFPU 2 /* not an FPU instruction */
181 * Emulate a floating-point instruction.
182 * Return zero for success, else signal number.
183 * (Typically: zero, SIGFPE, SIGILL, SIGSEGV)
186 fpu_emulate(struct trapframe
*frame
, struct fpreg
*fpf
)
188 static union instr insn
;
189 static struct fpemu fe
;
190 static int lastill
= 0;
193 /* initialize insn.is_datasize to tell it is *not* initialized */
197 /* always set this (to avoid a warning) */
199 if (copyin((void *) (frame
->srr0
), &insn
.i_int
, sizeof (insn
.i_int
))) {
201 printf("fpu_emulate: fault reading opcode\n");
206 DPRINTF(FPE_EX
, ("fpu_emulate: emulating insn %x at %p\n",
207 insn
.i_int
, (void *)frame
->srr0
));
210 if ((insn
.i_any
.i_opcd
== OPC_TWI
) ||
211 ((insn
.i_any
.i_opcd
== OPC_integer_31
) &&
212 (insn
.i_x
.i_xo
== OPC31_TW
))) {
213 /* Check for the two trap insns. */
214 DPRINTF(FPE_EX
, ("fpu_emulate: SIGTRAP\n"));
218 switch (fpu_execute(frame
, &fe
, &insn
)) {
220 DPRINTF(FPE_EX
, ("fpu_emulate: success\n"));
225 DPRINTF(FPE_EX
, ("fpu_emulate: SIGFPE\n"));
230 DPRINTF(FPE_EX
, ("fpu_emulate: SIGSEGV\n"));
236 DPRINTF(FPE_EX
, ("fpu_emulate: SIGILL\n"));
238 if (fpe_debug
& FPE_EX
) {
239 printf("fpu_emulate: illegal insn %x at %p:",
240 insn
.i_int
, (void *) (frame
->srr0
));
241 opc_disasm((vaddr_t
)(frame
->srr0
), insn
.i_int
);
245 * XXXX retry an illegal insn once due to cache issues.
247 if (lastill
== frame
->srr0
) {
250 if (fpe_debug
& FPE_EX
)
254 lastill
= frame
->srr0
;
262 * Execute an FPU instruction (one that runs entirely in the FPU; not
263 * FBfcc or STF, for instance). On return, fe->fe_fs->fs_fsr will be
264 * modified to reflect the setting the hardware would have left.
266 * Note that we do not catch all illegal opcodes, so you can, for instance,
267 * multiply two integers this way.
270 fpu_execute(struct trapframe
*tf
, struct fpemu
*fe
, union instr
*insn
)
273 union instr instr
= *insn
;
276 int ra
, rb
, rc
, rt
, type
, mask
, fsr
, cx
, bf
, setcr
;
283 fe
->fe_fpscr
= ((int *)&fs
->fpscr
)[1];
286 * On PowerPC all floating point values are stored in registers
287 * as doubles, even when used for single precision operations.
290 cond
= instr
.i_any
.i_rc
;
292 bf
= 0; /* XXX gcc */
294 #if defined(DDB) && defined(DEBUG)
295 if (fpe_debug
& FPE_EX
) {
296 vaddr_t loc
= tf
->srr0
;
298 printf("Trying to emulate: %p ", (void *)loc
);
299 opc_disasm(loc
, instr
.i_int
);
304 * `Decode' and execute instruction.
307 if ((instr
.i_any
.i_opcd
>= OPC_LFS
&& instr
.i_any
.i_opcd
<= OPC_STFDU
) ||
308 instr
.i_any
.i_opcd
== OPC_integer_31
) {
310 * Handle load/store insns:
312 * Convert to/from single if needed, calculate addr,
313 * and update index reg if needed.
316 size_t size
= sizeof(float);
319 cond
= 0; /* ld/st never set condition codes */
322 if (instr
.i_any
.i_opcd
== OPC_integer_31
) {
323 if (instr
.i_x
.i_xo
== OPC31_STFIWX
) {
324 FPU_EMU_EVCNT_INCR(stfiwx
);
326 /* Store as integer */
329 DPRINTF(FPE_INSN
, ("reg %d has %lx reg %d has %lx\n",
330 ra
, tf
->fixreg
[ra
], rb
, tf
->fixreg
[rb
]));
332 addr
= tf
->fixreg
[rb
];
334 addr
+= tf
->fixreg
[ra
];
336 a
= (int *)&fs
->fpreg
[rt
];
338 ("fpu_execute: Store INT %x at %p\n",
339 a
[1], (void *)addr
));
340 if (copyout(&a
[1], (void *)addr
, sizeof(int)))
345 if ((instr
.i_x
.i_xo
& OPC31_FPMASK
) != OPC31_FPOP
)
346 /* Not an indexed FP load/store op */
349 store
= (instr
.i_x
.i_xo
& 0x80);
350 if (instr
.i_x
.i_xo
& 0x40)
351 size
= sizeof(double);
354 update
= (instr
.i_x
.i_xo
& 0x20);
356 /* calculate EA of load/store */
359 DPRINTF(FPE_INSN
, ("reg %d has %lx reg %d has %lx\n",
360 ra
, tf
->fixreg
[ra
], rb
, tf
->fixreg
[rb
]));
361 addr
= tf
->fixreg
[rb
];
363 addr
+= tf
->fixreg
[ra
];
366 store
= instr
.i_d
.i_opcd
& 0x4;
367 if (instr
.i_d
.i_opcd
& 0x2)
368 size
= sizeof(double);
371 update
= instr
.i_d
.i_opcd
& 0x1;
373 /* calculate EA of load/store */
375 addr
= instr
.i_d
.i_d
;
376 DPRINTF(FPE_INSN
, ("reg %d has %lx displ %lx\n",
377 ra
, tf
->fixreg
[ra
], addr
));
379 addr
+= tf
->fixreg
[ra
];
383 if (update
&& ra
== 0)
388 FPU_EMU_EVCNT_INCR(fpstore
);
389 if (type
!= FTYPE_DBL
) {
391 ("fpu_execute: Store SNG at %p\n",
393 fpu_explode(fe
, fp
= &fe
->fe_f1
, FTYPE_DBL
, rt
);
394 fpu_implode(fe
, fp
, type
, (void *)&buf
);
395 if (copyout(&buf
, (void *)addr
, size
))
399 ("fpu_execute: Store DBL at %p\n",
401 if (copyout(&fs
->fpreg
[rt
], (void *)addr
, size
))
406 FPU_EMU_EVCNT_INCR(fpload
);
407 DPRINTF(FPE_INSN
, ("fpu_execute: Load from %p\n",
409 if (copyin((const void *)addr
, &fs
->fpreg
[rt
], size
))
411 if (type
!= FTYPE_DBL
) {
412 fpu_explode(fe
, fp
= &fe
->fe_f1
, type
, rt
);
413 fpu_implode(fe
, fp
, FTYPE_DBL
,
414 (u_int
*)&fs
->fpreg
[rt
]);
418 tf
->fixreg
[ra
] = addr
;
422 } else if (instr
.i_any
.i_opcd
== OPC_load_st_62
) {
423 /* These are 64-bit extenstions */
426 } else if (instr
.i_any
.i_opcd
== OPC_sp_fp_59
||
427 instr
.i_any
.i_opcd
== OPC_dp_fp_63
) {
430 if (instr
.i_any
.i_opcd
== OPC_dp_fp_63
&&
431 !(instr
.i_a
.i_xo
& OPC63M_MASK
)) {
438 /* One of the special opcodes.... */
439 switch (instr
.i_x
.i_xo
) {
441 FPU_EMU_EVCNT_INCR(fcmpu
);
442 DPRINTF(FPE_INSN
, ("fpu_execute: FCMPU\n"));
444 fpu_explode(fe
, &fe
->fe_f1
, type
, ra
);
445 fpu_explode(fe
, &fe
->fe_f2
, type
, rb
);
447 /* Make sure we do the condition regs. */
449 /* N.B.: i_rs is already left shifted by two. */
450 bf
= instr
.i_x
.i_rs
& 0xfc;
458 * PowerPC uses this to round a double
459 * precision value to single precision,
460 * but values in registers are always
461 * stored in double precision format.
463 FPU_EMU_EVCNT_INCR(frsp
);
464 DPRINTF(FPE_INSN
, ("fpu_execute: FRSP\n"));
465 fpu_explode(fe
, fp
= &fe
->fe_f1
, FTYPE_DBL
, rb
);
466 fpu_implode(fe
, fp
, FTYPE_SNG
,
467 (u_int
*)&fs
->fpreg
[rt
]);
468 fpu_explode(fe
, fp
= &fe
->fe_f1
, FTYPE_SNG
, rt
);
473 FPU_EMU_EVCNT_INCR(fctiw
);
474 DPRINTF(FPE_INSN
, ("fpu_execute: FCTIW\n"));
475 fpu_explode(fe
, fp
= &fe
->fe_f1
, type
, rb
);
479 FPU_EMU_EVCNT_INCR(fcmpo
);
480 DPRINTF(FPE_INSN
, ("fpu_execute: FCMPO\n"));
482 fpu_explode(fe
, &fe
->fe_f1
, type
, ra
);
483 fpu_explode(fe
, &fe
->fe_f2
, type
, rb
);
485 /* Make sure we do the condition regs. */
487 /* N.B.: i_rs is already left shifted by two. */
488 bf
= instr
.i_x
.i_rs
& 0xfc;
492 FPU_EMU_EVCNT_INCR(mtfsb1
);
493 DPRINTF(FPE_INSN
, ("fpu_execute: MTFSB1\n"));
495 (~(FPSCR_VX
|FPSR_EX
) & (1<<(31-rt
)));
498 FPU_EMU_EVCNT_INCR(fnegabs
);
499 DPRINTF(FPE_INSN
, ("fpu_execute: FNEGABS\n"));
500 memcpy(&fs
->fpreg
[rt
], &fs
->fpreg
[rb
],
502 a
= (int *)&fs
->fpreg
[rt
];
506 FPU_EMU_EVCNT_INCR(mcrfs
);
507 DPRINTF(FPE_INSN
, ("fpu_execute: MCRFS\n"));
511 /* Extract the bits we want */
512 mask
= (fe
->fe_fpscr
>> (28 - ra
)) & 0xf;
513 /* Clear the bits we copied. */
515 (FPSR_EX_MSK
| (0xf << (28 - ra
)));
516 fe
->fe_fpscr
&= fe
->fe_cx
;
517 /* Now shove them in the right part of cr */
518 tf
->cr
&= ~(0xf << (28 - rt
));
519 tf
->cr
|= (mask
<< (28 - rt
));
522 FPU_EMU_EVCNT_INCR(mtfsb0
);
523 DPRINTF(FPE_INSN
, ("fpu_execute: MTFSB0\n"));
525 ((FPSCR_VX
|FPSR_EX
) & ~(1<<(31-rt
)));
528 FPU_EMU_EVCNT_INCR(fmr
);
529 DPRINTF(FPE_INSN
, ("fpu_execute: FMR\n"));
530 memcpy(&fs
->fpreg
[rt
], &fs
->fpreg
[rb
],
534 FPU_EMU_EVCNT_INCR(mtfsfi
);
535 DPRINTF(FPE_INSN
, ("fpu_execute: MTFSFI\n"));
537 rt
&= 0x1c; /* Already left-shifted 4 */
538 fe
->fe_cx
= rb
<< (28 - rt
);
539 mask
= 0xf<<(28 - rt
);
540 fe
->fe_fpscr
= (fe
->fe_fpscr
& ~mask
) |
542 /* XXX weird stuff about OX, FX, FEX, and VX should be handled */
545 FPU_EMU_EVCNT_INCR(fnabs
);
546 DPRINTF(FPE_INSN
, ("fpu_execute: FABS\n"));
547 memcpy(&fs
->fpreg
[rt
], &fs
->fpreg
[rb
],
549 a
= (int *)&fs
->fpreg
[rt
];
553 FPU_EMU_EVCNT_INCR(fabs
);
554 DPRINTF(FPE_INSN
, ("fpu_execute: FABS\n"));
555 memcpy(&fs
->fpreg
[rt
], &fs
->fpreg
[rb
],
557 a
= (int *)&fs
->fpreg
[rt
];
561 FPU_EMU_EVCNT_INCR(mffs
);
562 DPRINTF(FPE_INSN
, ("fpu_execute: MFFS\n"));
563 memcpy(&fs
->fpreg
[rt
], &fs
->fpscr
,
567 FPU_EMU_EVCNT_INCR(mtfsf
);
568 DPRINTF(FPE_INSN
, ("fpu_execute: MTFSF\n"));
569 if ((rt
= instr
.i_xfl
.i_flm
) == -1)
573 /* Convert 1 bit -> 4 bits */
574 for (ra
= 0; ra
< 8; ra
++)
576 mask
|= (0xf<<(4*ra
));
578 a
= (int *)&fs
->fpreg
[rt
];
579 fe
->fe_cx
= mask
& a
[1];
580 fe
->fe_fpscr
= (fe
->fe_fpscr
&~mask
) |
582 /* XXX weird stuff about OX, FX, FEX, and VX should be handled */
586 FPU_EMU_EVCNT_INCR(fctid
);
587 DPRINTF(FPE_INSN
, ("fpu_execute: FCTID\n"));
588 fpu_explode(fe
, fp
= &fe
->fe_f1
, type
, rb
);
592 FPU_EMU_EVCNT_INCR(fcfid
);
593 DPRINTF(FPE_INSN
, ("fpu_execute: FCFID\n"));
595 fpu_explode(fe
, fp
= &fe
->fe_f1
, type
, rb
);
604 rt
= instr
.i_a
.i_frt
;
605 ra
= instr
.i_a
.i_fra
;
606 rb
= instr
.i_a
.i_frb
;
607 rc
= instr
.i_a
.i_frc
;
610 if (instr
.i_any
.i_opcd
& 0x4)
612 switch ((unsigned int)instr
.i_a
.i_xo
) {
614 FPU_EMU_EVCNT_INCR(fdiv
);
615 DPRINTF(FPE_INSN
, ("fpu_execute: FDIV\n"));
616 fpu_explode(fe
, &fe
->fe_f1
, type
, ra
);
617 fpu_explode(fe
, &fe
->fe_f2
, type
, rb
);
621 FPU_EMU_EVCNT_INCR(fsub
);
622 DPRINTF(FPE_INSN
, ("fpu_execute: FSUB\n"));
623 fpu_explode(fe
, &fe
->fe_f1
, type
, ra
);
624 fpu_explode(fe
, &fe
->fe_f2
, type
, rb
);
628 FPU_EMU_EVCNT_INCR(fadd
);
629 DPRINTF(FPE_INSN
, ("fpu_execute: FADD\n"));
630 fpu_explode(fe
, &fe
->fe_f1
, type
, ra
);
631 fpu_explode(fe
, &fe
->fe_f2
, type
, rb
);
635 FPU_EMU_EVCNT_INCR(fsqrt
);
636 DPRINTF(FPE_INSN
, ("fpu_execute: FSQRT\n"));
637 fpu_explode(fe
, &fe
->fe_f1
, type
, rb
);
641 FPU_EMU_EVCNT_INCR(fsel
);
642 DPRINTF(FPE_INSN
, ("fpu_execute: FSEL\n"));
643 a
= (int *)&fe
->fe_fpstate
->fpreg
[ra
];
644 if ((*a
& 0x80000000) && (*a
& 0x7fffffff))
647 DPRINTF(FPE_INSN
, ("f%d => f%d\n", rc
, rt
));
648 memcpy(&fs
->fpreg
[rt
], &fs
->fpreg
[rc
],
652 FPU_EMU_EVCNT_INCR(fpres
);
653 DPRINTF(FPE_INSN
, ("fpu_execute: FPRES\n"));
654 fpu_explode(fe
, &fe
->fe_f1
, type
, rb
);
656 /* now we've gotta overwrite the dest reg */
657 *((int *)&fe
->fe_fpstate
->fpreg
[rt
]) = 1;
658 fpu_explode(fe
, &fe
->fe_f1
, FTYPE_INT
, rt
);
662 FPU_EMU_EVCNT_INCR(fmul
);
663 DPRINTF(FPE_INSN
, ("fpu_execute: FMUL\n"));
664 fpu_explode(fe
, &fe
->fe_f1
, type
, ra
);
665 fpu_explode(fe
, &fe
->fe_f2
, type
, rc
);
669 /* Reciprocal sqrt() estimate */
670 FPU_EMU_EVCNT_INCR(frsqrte
);
671 DPRINTF(FPE_INSN
, ("fpu_execute: FRSQRTE\n"));
672 fpu_explode(fe
, &fe
->fe_f1
, type
, rb
);
675 /* now we've gotta overwrite the dest reg */
676 *((int *)&fe
->fe_fpstate
->fpreg
[rt
]) = 1;
677 fpu_explode(fe
, &fe
->fe_f1
, FTYPE_INT
, rt
);
681 FPU_EMU_EVCNT_INCR(fmulsub
);
682 DPRINTF(FPE_INSN
, ("fpu_execute: FMULSUB\n"));
683 fpu_explode(fe
, &fe
->fe_f1
, type
, ra
);
684 fpu_explode(fe
, &fe
->fe_f2
, type
, rc
);
687 fpu_explode(fe
, &fe
->fe_f2
, type
, rb
);
691 FPU_EMU_EVCNT_INCR(fmuladd
);
692 DPRINTF(FPE_INSN
, ("fpu_execute: FMULADD\n"));
693 fpu_explode(fe
, &fe
->fe_f1
, type
, ra
);
694 fpu_explode(fe
, &fe
->fe_f2
, type
, rc
);
697 fpu_explode(fe
, &fe
->fe_f2
, type
, rb
);
701 FPU_EMU_EVCNT_INCR(fnmsub
);
702 DPRINTF(FPE_INSN
, ("fpu_execute: FNMSUB\n"));
703 fpu_explode(fe
, &fe
->fe_f1
, type
, ra
);
704 fpu_explode(fe
, &fe
->fe_f2
, type
, rc
);
707 fpu_explode(fe
, &fe
->fe_f2
, type
, rb
);
713 FPU_EMU_EVCNT_INCR(fnmadd
);
714 DPRINTF(FPE_INSN
, ("fpu_execute: FNMADD\n"));
715 fpu_explode(fe
, &fe
->fe_f1
, type
, ra
);
716 fpu_explode(fe
, &fe
->fe_f2
, type
, rc
);
719 fpu_explode(fe
, &fe
->fe_f2
, type
, rb
);
734 * ALU operation is complete. Collapse the result and then check
735 * for exceptions. If we got any, and they are enabled, do not
736 * alter the destination register, just stop with an exception.
737 * Otherwise set new current exceptions and accrue.
740 fpu_implode(fe
, fp
, type
, (u_int
*)&fs
->fpreg
[rt
]);
745 if ((cx
^fsr
)&FPSR_EX_MSK
)
747 mask
= fsr
& FPSR_EX
;
751 if (cx
& FPSCR_FPRF
) {
752 /* Need to replace CC */
755 if (cx
& (FPSR_EXOP
))
758 DPRINTF(FPE_INSN
, ("fpu_execute: cx %x, fsr %x\n", cx
, fsr
));
762 cond
= fsr
& 0xf0000000;
763 /* Isolate condition codes */
765 /* Move fpu condition codes to cr[1] */
766 tf
->cr
&= (0x0f000000);
767 tf
->cr
|= (cond
<<24);
768 DPRINTF(FPE_INSN
, ("fpu_execute: cr[1] <= %x\n", cond
));
772 cond
= fsr
& FPSCR_FPCC
;
773 /* Isolate condition codes */
775 /* Move fpu condition codes to cr[1] */
776 tf
->cr
&= ~(0xf0000000>>bf
);
777 tf
->cr
|= (cond
>>bf
);
778 DPRINTF(FPE_INSN
, ("fpu_execute: cr[%d] (cr=%x) <= %x\n", bf
/4, tf
->cr
, cond
));
781 ((int *)&fs
->fpscr
)[1] = fsr
;
784 return (0); /* success */