Instrument FP emulation traps.

This commit is contained in:
thorpej 2002-11-24 17:34:06 +00:00
parent 3d64e26035
commit 0eb35ef834

View File

@ -1,4 +1,4 @@
/* $NetBSD: fpu_emu.c,v 1.3 2001/07/22 11:29:44 wiz Exp $ */
/* $NetBSD: fpu_emu.c,v 1.4 2002/11/24 17:34:06 thorpej Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@ -87,6 +87,7 @@
#include <sys/systm.h>
#include <sys/syslog.h>
#include <sys/signalvar.h>
#include <sys/device.h> /* for evcnt */
#include <powerpc/instr.h>
#include <machine/reg.h>
@ -95,6 +96,45 @@
#include <powerpc/fpu/fpu_emu.h>
#include <powerpc/fpu/fpu_extern.h>
#define FPU_EMU_EVCNT_DECL(name) \
static struct evcnt fpu_emu_ev_##name = \
EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "fpemu", #name); \
EVCNT_ATTACH_STATIC(fpu_emu_ev_##name)
#define FPU_EMU_EVCNT_INCR(name) \
fpu_emu_ev_##name##.ev_count++
FPU_EMU_EVCNT_DECL(stfiwx);
FPU_EMU_EVCNT_DECL(fpstore);
FPU_EMU_EVCNT_DECL(fpload);
FPU_EMU_EVCNT_DECL(fcmpu);
FPU_EMU_EVCNT_DECL(frsp);
FPU_EMU_EVCNT_DECL(fctiw);
FPU_EMU_EVCNT_DECL(fcmpo);
FPU_EMU_EVCNT_DECL(mtfsb1);
FPU_EMU_EVCNT_DECL(fnegabs);
FPU_EMU_EVCNT_DECL(mcrfs);
FPU_EMU_EVCNT_DECL(mtfsb0);
FPU_EMU_EVCNT_DECL(fmr);
FPU_EMU_EVCNT_DECL(mtfsfi);
FPU_EMU_EVCNT_DECL(fnabs);
FPU_EMU_EVCNT_DECL(fabs);
FPU_EMU_EVCNT_DECL(mffs);
FPU_EMU_EVCNT_DECL(mtfsf);
FPU_EMU_EVCNT_DECL(fctid);
FPU_EMU_EVCNT_DECL(fcfid);
FPU_EMU_EVCNT_DECL(fdiv);
FPU_EMU_EVCNT_DECL(fsub);
FPU_EMU_EVCNT_DECL(fadd);
FPU_EMU_EVCNT_DECL(fsqrt);
FPU_EMU_EVCNT_DECL(fsel);
FPU_EMU_EVCNT_DECL(fpres);
FPU_EMU_EVCNT_DECL(fmul);
FPU_EMU_EVCNT_DECL(frsqrte);
FPU_EMU_EVCNT_DECL(fmulsub);
FPU_EMU_EVCNT_DECL(fmuladd);
FPU_EMU_EVCNT_DECL(fnmsub);
FPU_EMU_EVCNT_DECL(fnmadd);
/* FPSR exception masks */
#define FPSR_EX_MSK (FPSCR_VX|FPSCR_OX|FPSCR_UX|FPSCR_ZX| \
@ -280,6 +320,8 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
if (instr.i_any.i_opcd == OPC_integer_31) {
if (instr.i_x.i_xo == OPC31_STFIWX) {
FPU_EMU_EVCNT_INCR(stfiwx);
/* Store as integer */
ra = instr.i_x.i_ra;
rb = instr.i_x.i_rb;
@ -342,6 +384,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
if (store) {
/* Store */
FPU_EMU_EVCNT_INCR(fpstore);
if (type != FTYPE_DBL) {
DPRINTF(FPE_INSN,
("fpu_execute: Store SNG at %p\n",
@ -359,6 +402,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
}
} else {
/* Load */
FPU_EMU_EVCNT_INCR(fpload);
DPRINTF(FPE_INSN, ("fpu_execute: Load from %p\n",
(void *)addr));
if (copyin((const void *)addr, &fs->fpreg[rt], size))
@ -393,6 +437,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
/* One of the special opcodes.... */
switch (instr.i_x.i_xo) {
case OPC63_FCMPU:
FPU_EMU_EVCNT_INCR(fcmpu);
DPRINTF(FPE_INSN, ("fpu_execute: FCMPU\n"));
rt >>= 2;
fpu_explode(fe, &fe->fe_f1, type, ra);
@ -414,6 +459,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
* but values in registers are always
* stored in double precision format.
*/
FPU_EMU_EVCNT_INCR(frsp);
DPRINTF(FPE_INSN, ("fpu_execute: FRSP\n"));
fpu_explode(fe, fp = &fe->fe_f1, FTYPE_DBL, rb);
fpu_implode(fe, fp, FTYPE_SNG,
@ -423,11 +469,13 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
break;
case OPC63_FCTIW:
case OPC63_FCTIWZ:
FPU_EMU_EVCNT_INCR(fctiw);
DPRINTF(FPE_INSN, ("fpu_execute: FCTIW\n"));
fpu_explode(fe, fp = &fe->fe_f1, type, rb);
type = FTYPE_INT;
break;
case OPC63_FCMPO:
FPU_EMU_EVCNT_INCR(fcmpo);
DPRINTF(FPE_INSN, ("fpu_execute: FCMPO\n"));
rt >>= 2;
fpu_explode(fe, &fe->fe_f1, type, ra);
@ -440,11 +488,13 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
setcr = 1;
break;
case OPC63_MTFSB1:
FPU_EMU_EVCNT_INCR(mtfsb1);
DPRINTF(FPE_INSN, ("fpu_execute: MTFSB1\n"));
fe->fe_fpscr |=
(~(FPSCR_VX|FPSR_EX) & (1<<(31-rt)));
break;
case OPC63_FNEG:
FPU_EMU_EVCNT_INCR(fnegabs);
DPRINTF(FPE_INSN, ("fpu_execute: FNEGABS\n"));
memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
sizeof(double));
@ -452,6 +502,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
*a ^= (1 << 31);
break;
case OPC63_MCRFS:
FPU_EMU_EVCNT_INCR(mcrfs);
DPRINTF(FPE_INSN, ("fpu_execute: MCRFS\n"));
cond = 0;
rt &= 0x1c;
@ -467,16 +518,19 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
tf->cr |= (mask << (28 - rt));
break;
case OPC63_MTFSB0:
FPU_EMU_EVCNT_INCR(mtfsb0);
DPRINTF(FPE_INSN, ("fpu_execute: MTFSB0\n"));
fe->fe_fpscr &=
((FPSCR_VX|FPSR_EX) & ~(1<<(31-rt)));
break;
case OPC63_FMR:
FPU_EMU_EVCNT_INCR(fmr);
DPRINTF(FPE_INSN, ("fpu_execute: FMR\n"));
memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
sizeof(double));
break;
case OPC63_MTFSFI:
FPU_EMU_EVCNT_INCR(mtfsfi);
DPRINTF(FPE_INSN, ("fpu_execute: MTFSFI\n"));
rb >>= 1;
rt &= 0x1c; /* Already left-shifted 4 */
@ -487,6 +541,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
/* XXX weird stuff about OX, FX, FEX, and VX should be handled */
break;
case OPC63_FNABS:
FPU_EMU_EVCNT_INCR(fnabs);
DPRINTF(FPE_INSN, ("fpu_execute: FABS\n"));
memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
sizeof(double));
@ -494,6 +549,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
*a |= (1 << 31);
break;
case OPC63_FABS:
FPU_EMU_EVCNT_INCR(fabs);
DPRINTF(FPE_INSN, ("fpu_execute: FABS\n"));
memcpy(&fs->fpreg[rt], &fs->fpreg[rb],
sizeof(double));
@ -501,11 +557,13 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
*a &= ~(1 << 31);
break;
case OPC63_MFFS:
FPU_EMU_EVCNT_INCR(mffs);
DPRINTF(FPE_INSN, ("fpu_execute: MFFS\n"));
memcpy(&fs->fpreg[rt], &fs->fpscr,
sizeof(fs->fpscr));
break;
case OPC63_MTFSF:
FPU_EMU_EVCNT_INCR(mtfsf);
DPRINTF(FPE_INSN, ("fpu_execute: MTFSF\n"));
if ((rt = instr.i_xfl.i_flm) == -1)
mask = -1;
@ -524,11 +582,13 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
break;
case OPC63_FCTID:
case OPC63_FCTIDZ:
FPU_EMU_EVCNT_INCR(fctid);
DPRINTF(FPE_INSN, ("fpu_execute: FCTID\n"));
fpu_explode(fe, fp = &fe->fe_f1, type, rb);
type = FTYPE_LNG;
break;
case OPC63_FCFID:
FPU_EMU_EVCNT_INCR(fcfid);
DPRINTF(FPE_INSN, ("fpu_execute: FCFID\n"));
type = FTYPE_LNG;
fpu_explode(fe, fp = &fe->fe_f1, type, rb);
@ -550,29 +610,34 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
type = FTYPE_DBL;
switch ((unsigned int)instr.i_a.i_xo) {
case OPC59_FDIVS:
FPU_EMU_EVCNT_INCR(fdiv);
DPRINTF(FPE_INSN, ("fpu_execute: FDIV\n"));
fpu_explode(fe, &fe->fe_f1, type, ra);
fpu_explode(fe, &fe->fe_f2, type, rb);
fp = fpu_div(fe);
break;
case OPC59_FSUBS:
FPU_EMU_EVCNT_INCR(fsub);
DPRINTF(FPE_INSN, ("fpu_execute: FSUB\n"));
fpu_explode(fe, &fe->fe_f1, type, ra);
fpu_explode(fe, &fe->fe_f2, type, rb);
fp = fpu_sub(fe);
break;
case OPC59_FADDS:
FPU_EMU_EVCNT_INCR(fadd);
DPRINTF(FPE_INSN, ("fpu_execute: FADD\n"));
fpu_explode(fe, &fe->fe_f1, type, ra);
fpu_explode(fe, &fe->fe_f2, type, rb);
fp = fpu_add(fe);
break;
case OPC59_FSQRTS:
FPU_EMU_EVCNT_INCR(fsqrt);
DPRINTF(FPE_INSN, ("fpu_execute: FSQRT\n"));
fpu_explode(fe, &fe->fe_f1, type, rb);
fp = fpu_sqrt(fe);
break;
case OPC63M_FSEL:
FPU_EMU_EVCNT_INCR(fsel);
DPRINTF(FPE_INSN, ("fpu_execute: FSEL\n"));
a = (int *)&fe->fe_fpstate->fpreg[ra];
if ((*a & 0x80000000) && (*a & 0x7fffffff))
@ -583,6 +648,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
sizeof(double));
break;
case OPC59_FRES:
FPU_EMU_EVCNT_INCR(fpres);
DPRINTF(FPE_INSN, ("fpu_execute: FPRES\n"));
fpu_explode(fe, &fe->fe_f1, type, rb);
fp = fpu_sqrt(fe);
@ -592,6 +658,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
fpu_div(fe);
break;
case OPC59_FMULS:
FPU_EMU_EVCNT_INCR(fmul);
DPRINTF(FPE_INSN, ("fpu_execute: FMUL\n"));
fpu_explode(fe, &fe->fe_f1, type, ra);
fpu_explode(fe, &fe->fe_f2, type, rc);
@ -599,6 +666,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
break;
case OPC63M_FRSQRTE:
/* Reciprocal sqrt() estimate */
FPU_EMU_EVCNT_INCR(frsqrte);
DPRINTF(FPE_INSN, ("fpu_execute: FRSQRTE\n"));
fpu_explode(fe, &fe->fe_f1, type, rb);
fe->fe_f2 = *fp;
@ -608,6 +676,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
fpu_div(fe);
break;
case OPC59_FMSUBS:
FPU_EMU_EVCNT_INCR(fmulsub);
DPRINTF(FPE_INSN, ("fpu_execute: FMULSUB\n"));
fpu_explode(fe, &fe->fe_f1, type, ra);
fpu_explode(fe, &fe->fe_f2, type, rc);
@ -617,6 +686,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
fp = fpu_sub(fe);
break;
case OPC59_FMADDS:
FPU_EMU_EVCNT_INCR(fmuladd);
DPRINTF(FPE_INSN, ("fpu_execute: FMULADD\n"));
fpu_explode(fe, &fe->fe_f1, type, ra);
fpu_explode(fe, &fe->fe_f2, type, rc);
@ -626,6 +696,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
fp = fpu_add(fe);
break;
case OPC59_FNMSUBS:
FPU_EMU_EVCNT_INCR(fnmsub);
DPRINTF(FPE_INSN, ("fpu_execute: FNMSUB\n"));
fpu_explode(fe, &fe->fe_f1, type, ra);
fpu_explode(fe, &fe->fe_f2, type, rc);
@ -637,6 +708,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn)
fp->fp_sign ^= 1;
break;
case OPC59_FNMADDS:
FPU_EMU_EVCNT_INCR(fnmadd);
DPRINTF(FPE_INSN, ("fpu_execute: FNMADD\n"));
fpu_explode(fe, &fe->fe_f1, type, ra);
fpu_explode(fe, &fe->fe_f2, type, rc);