fpu_simulator.c revision 9d0d62ad2e60e8f742a2e723d06e88352ee6a1f3
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Main procedures for sparc FPU simulator. */
#include <sys/privregs.h>
#include <sys/vis_simulator.h>
#define FPUINFO_KSTAT(opcode) { \
}
if (prec < 2) { \
FPUINFO_KSTAT(kstat_s); \
} else if (prec == 2) { \
FPUINFO_KSTAT(kstat_d); \
} else { \
FPUINFO_KSTAT(kstat_q); \
}
/*
* FPU simulator global kstat data
*/
struct fpuinfo_kstat fpuinfo = {
{ "fpu_sim_fmovs", KSTAT_DATA_UINT64},
{ "fpu_sim_fmovd", KSTAT_DATA_UINT64},
{ "fpu_sim_fmovq", KSTAT_DATA_UINT64},
{ "fpu_sim_fnegs", KSTAT_DATA_UINT64},
{ "fpu_sim_fnegd", KSTAT_DATA_UINT64},
{ "fpu_sim_fnegq", KSTAT_DATA_UINT64},
{ "fpu_sim_fabss", KSTAT_DATA_UINT64},
{ "fpu_sim_fabsd", KSTAT_DATA_UINT64},
{ "fpu_sim_fabsq", KSTAT_DATA_UINT64},
{ "fpu_sim_fsqrts", KSTAT_DATA_UINT64},
{ "fpu_sim_fsqrtd", KSTAT_DATA_UINT64},
{ "fpu_sim_fsqrtq", KSTAT_DATA_UINT64},
{ "fpu_sim_fadds", KSTAT_DATA_UINT64},
{ "fpu_sim_faddd", KSTAT_DATA_UINT64},
{ "fpu_sim_faddq", KSTAT_DATA_UINT64},
{ "fpu_sim_fsubs", KSTAT_DATA_UINT64},
{ "fpu_sim_fsubd", KSTAT_DATA_UINT64},
{ "fpu_sim_fsubq", KSTAT_DATA_UINT64},
{ "fpu_sim_fmuls", KSTAT_DATA_UINT64},
{ "fpu_sim_fmuld", KSTAT_DATA_UINT64},
{ "fpu_sim_fmulq", KSTAT_DATA_UINT64},
{ "fpu_sim_fdivs", KSTAT_DATA_UINT64},
{ "fpu_sim_fdivd", KSTAT_DATA_UINT64},
{ "fpu_sim_fdivq", KSTAT_DATA_UINT64},
{ "fpu_sim_fcmps", KSTAT_DATA_UINT64},
{ "fpu_sim_fcmpd", KSTAT_DATA_UINT64},
{ "fpu_sim_fcmpq", KSTAT_DATA_UINT64},
{ "fpu_sim_fcmpes", KSTAT_DATA_UINT64},
{ "fpu_sim_fcmped", KSTAT_DATA_UINT64},
{ "fpu_sim_fcmpeq", KSTAT_DATA_UINT64},
{ "fpu_sim_fsmuld", KSTAT_DATA_UINT64},
{ "fpu_sim_fdmulx", KSTAT_DATA_UINT64},
{ "fpu_sim_fstox", KSTAT_DATA_UINT64},
{ "fpu_sim_fdtox", KSTAT_DATA_UINT64},
{ "fpu_sim_fqtox", KSTAT_DATA_UINT64},
{ "fpu_sim_fxtos", KSTAT_DATA_UINT64},
{ "fpu_sim_fxtod", KSTAT_DATA_UINT64},
{ "fpu_sim_fxtoq", KSTAT_DATA_UINT64},
{ "fpu_sim_fitos", KSTAT_DATA_UINT64},
{ "fpu_sim_fitod", KSTAT_DATA_UINT64},
{ "fpu_sim_fitoq", KSTAT_DATA_UINT64},
{ "fpu_sim_fstoi", KSTAT_DATA_UINT64},
{ "fpu_sim_fdtoi", KSTAT_DATA_UINT64},
{ "fpu_sim_fqtoi", KSTAT_DATA_UINT64},
{ "fpu_sim_fmovcc", KSTAT_DATA_UINT64},
{ "fpu_sim_fmovr", KSTAT_DATA_UINT64},
{ "fpu_sim_fmadds", KSTAT_DATA_UINT64},
{ "fpu_sim_fmaddd", KSTAT_DATA_UINT64},
{ "fpu_sim_fmsubs", KSTAT_DATA_UINT64},
{ "fpu_sim_fmsubd", KSTAT_DATA_UINT64},
{ "fpu_sim_fnmadds", KSTAT_DATA_UINT64},
{ "fpu_sim_fnmaddd", KSTAT_DATA_UINT64},
{ "fpu_sim_fnmsubs", KSTAT_DATA_UINT64},
{ "fpu_sim_fnmsubd", KSTAT_DATA_UINT64},
{ "fpu_sim_invalid", KSTAT_DATA_UINT64},
};
struct visinfo_kstat visinfo = {
{ "vis_edge8", KSTAT_DATA_UINT64},
{ "vis_edge8n", KSTAT_DATA_UINT64},
{ "vis_edge8l", KSTAT_DATA_UINT64},
{ "vis_edge8ln", KSTAT_DATA_UINT64},
{ "vis_edge16", KSTAT_DATA_UINT64},
{ "vis_edge16n", KSTAT_DATA_UINT64},
{ "vis_edge16l", KSTAT_DATA_UINT64},
{ "vis_edge16ln", KSTAT_DATA_UINT64},
{ "vis_edge32", KSTAT_DATA_UINT64},
{ "vis_edge32n", KSTAT_DATA_UINT64},
{ "vis_edge32l", KSTAT_DATA_UINT64},
{ "vis_edge32ln", KSTAT_DATA_UINT64},
{ "vis_array8", KSTAT_DATA_UINT64},
{ "vis_array16", KSTAT_DATA_UINT64},
{ "vis_array32", KSTAT_DATA_UINT64},
{ "vis_bmask", KSTAT_DATA_UINT64},
{ "vis_fcmple16", KSTAT_DATA_UINT64},
{ "vis_fcmpne16", KSTAT_DATA_UINT64},
{ "vis_fcmpgt16", KSTAT_DATA_UINT64},
{ "vis_fcmpeq16", KSTAT_DATA_UINT64},
{ "vis_fcmple32", KSTAT_DATA_UINT64},
{ "vis_fcmpne32", KSTAT_DATA_UINT64},
{ "vis_fcmpgt32", KSTAT_DATA_UINT64},
{ "vis_fcmpeq32", KSTAT_DATA_UINT64},
{ "vis_fmul8x16", KSTAT_DATA_UINT64},
{ "vis_fmul8x16au", KSTAT_DATA_UINT64},
{ "vis_fmul8x16al", KSTAT_DATA_UINT64},
{ "vis_fmul8sux16", KSTAT_DATA_UINT64},
{ "vis_fmul8ulx16", KSTAT_DATA_UINT64},
{ "vis_fmuld8sux16", KSTAT_DATA_UINT64},
{ "vis_fmuld8ulx16", KSTAT_DATA_UINT64},
{ "vis_fpack16", KSTAT_DATA_UINT64},
{ "vis_fpack32", KSTAT_DATA_UINT64},
{ "vis_fpackfix", KSTAT_DATA_UINT64},
{ "vis_fexpand", KSTAT_DATA_UINT64},
{ "vis_fpmerge", KSTAT_DATA_UINT64},
{ "vis_pdist", KSTAT_DATA_UINT64},
{ "vis_pdistn", KSTAT_DATA_UINT64},
{ "vis_bshuffle", KSTAT_DATA_UINT64},
};
/* PUBLIC FUNCTIONS */
/* ARGSUSED */
static enum ftt_type
{
/*
* Obtain rounding direction and precision
*/
case fmadd:
}
break;
case fmsub:
}
break;
case fnmadd:
}
break;
case fnmsub:
}
}
} else {
return (ftt_unimplemented);
return (ftt_unimplemented);
}
}
/* ibit not valid for fpop1 instructions */
return (ftt_unimplemented);
return (ftt_unimplemented);
}
}
case fmovs: /* also covers fmovd, fmovq */
} else { /* fmovd */
nrs2+2);
} else {
}
}
break;
case fabss: /* also covers fabsd, fabsq */
usr &= 0x7fffffff;
} else { /* fabsd */
lusr &= 0x7fffffffffffffff;
nrs2+2);
} else {
}
}
break;
case fnegs: /* also covers fnegd, fnegq */
usr ^= 0x80000000;
} else { /* fnegd */
lusr ^= 0x8000000000000000;
nrs2+2);
lusr ^= 0x0000000000000000;
} else {
}
}
break;
case fadd:
break;
case fsub:
break;
case fmul:
break;
case fsmuld:
return (ftt_unimplemented);
break;
case fdmulx:
return (ftt_unimplemented);
break;
case fdiv:
break;
case fcmp:
switch (nfcc) {
case fcc_0:
break;
case fcc_1:
break;
case fcc_2:
break;
case fcc_3:
break;
}
break;
case fcmpe:
switch (nfcc) {
case fcc_0:
break;
case fcc_1:
break;
case fcc_2:
break;
case fcc_3:
break;
}
break;
case fsqrt:
break;
case ftoi:
/* Force rounding toward zero. */
break;
case ftoll:
/* Force rounding toward zero. */
break;
case flltos:
break;
case flltod:
break;
case flltox:
break;
case fitos:
break;
case fitod:
break;
case fitox:
break;
default:
return (ftt_unimplemented);
}
}
if (andexcep != 0) { /* Signal an IEEE SIGFPE here. */
} else {
pfpsd->fp_trapcode = 0;
}
return (ftt_ieee);
} else { /* Just set accrued exception field. */
}
return (ftt_none);
}
/*
* fpu_vis_sim simulates fpu and vis instructions;
* It can work with both real and pcb image registers.
*/
enum ftt_type
{
union {
uint32_t i;
} fp;
if (fpu_exists) {
} else {
}
return (ftt);
}
return (ftt);
} else {
return (ftt);
}
}
/*
* fpu_simulator simulates FPU instructions only;
* reads and writes FPU data registers directly.
*/
enum ftt_type
{
union {
uint32_t i;
} fp;
}
/*
* fp_emulator simulates FPU and CPU-FPU instructions; reads and writes FPU
* data registers from image in pfpu.
*/
enum ftt_type
void *prw, /* Pointer to locals and ins. */
{
union {
uint32_t i;
} fp;
return (ftt);
/* Do not retry emulated instruction. */
/*
* Simulation generated an exception of some kind,
* simulate the fp queue for a signal.
*/
}
} else
return (ftt);
/*
* If we are single-stepping, don't emulate any more instructions.
*/
return (ftt);
/*
* now read next instruction and see if it can be emulated
*/
return (ftt);
/* Do not retry emulated instruction. */
/*
* Simulation generated an exception of some kind,
* simulate the fp queue for a signal.
*/
}
} else if (
/* rd %gsr */
/* wr %gsr */
/* movcc */
/* fbpcc */
/* fldst */
/* fbcc */
} else
return (ftt);
return (ftt);
else
goto again;
}
/*
* FPU simulator global kstat data
*/
struct fpustat_kstat fpustat = {
{ "fpu_ieee_traps", KSTAT_DATA_UINT64 },
{ "fpu_unfinished_traps", KSTAT_DATA_UINT64 },
{ "fpu_unimplemented", KSTAT_DATA_UINT64 },
};
void
fp_kstat_init(void)
{
} else {
}
} else {
}
} else {
}
}
void
{
(ftt == ftt_unimplemented));
else if (ftt == ftt_unfinished)
else if (ftt == ftt_unimplemented)
}