NetBSD/sys/arch/mac68k/mac68k/fpu.c

283 lines
8.9 KiB
C

/* $NetBSD: fpu.c,v 1.4 1994/10/26 08:47:01 cgd Exp $ */
/*-
* Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
* Michael L. Finch, Bradley A. Grantham, and
* Lawrence A. Kesteloot
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Alice Group.
* 4. The names of the Alice Group or any of its members may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
/*#include <sys/seg.h>*/
#include <sys/acct.h>
#include <sys/kernel.h>
#include <sys/signalvar.h>
#include <sys/resourcevar.h>
#include <sys/syslog.h>
#include <sys/user.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
#define PRINTF(x)
int fancy (unsigned short buf[])
{
int is, iis, wl, bdsize;
int advance;
if ((buf[2] & 0x0100) == 0) { /* Brief format extention word */
advance = 2;
} else { /* Full format extention word(s) */
advance = 2;
is = (buf[2] >> 6) & 0x1;
iis = buf[2] & 0x7;
switch (iis & 0x3) { /* Advance for outer displacement */
case 0: advance += 0; break;
case 1: advance += 0; break;
case 2: advance += 2; break;
case 3: advance += 4; break;
}
bdsize = (buf[2] >> 4) & 0x3;
switch (bdsize) { /* Advance for base displacement */
case 0: advance += 0; break;
case 1: advance += 0; break;
case 2: advance += 2; break;
case 3: advance += 4; break;
}
}
return advance;
}
int opsize (int rm, int mode, int reg, int src, unsigned short buf[])
{
int len;
if (rm == 0) {
/* Register-to-register */
return 0;
}
len = 0;
switch (src) {
case 0: len = 4; break; /* Int */
case 1: len = 4; break; /* Single */
case 2: len = 10; break; /* Extended */
case 3: len = 12; break; /* Packed BCD */
case 4: len = 2; break; /* Word */
case 5: len = 8; break; /* Double */
case 6: len = 2; break; /* Byte */
case 7: len = 0; break; /* Unknown */
}
switch (mode) {
case 0: return 0;
case 1: return 0;
case 2: return 0;
case 3: return 0;
case 4: return 0;
case 5: return 2; /* 16-bit indirect */
case 6: /* 1, 2, 3, 4, or 5 */
return fancy (buf);
case 7: /* 1, 2, 3, 4, or 5 */
switch (reg) {
case 0: return 2; /* Word address */
case 1: return 4; /* Long address */
case 2: return 2; /* 16-bit PC offset */
case 3: return fancy (buf); /* Fancy shmancy addressing */
case 4: return len; /* Immediate */
}
printf ("Invalid register value: %d\n", reg);
return 0;
}
printf ("Invalid mode: %d\n", mode);
return 0;
}
FPUemul(frame)
struct frame frame;
{
unsigned short buf[16];
int advance, mode, reg, source, dest, rm, coid, type, inst, id, misc;
advance = 0;
PRINTF ( ("FPUemul() - "));
copyin ((char *)frame.f_pc, buf, sizeof (buf));
PRINTF ( ("Word 0: %x, ", (int)buf[0]));
PRINTF ( ("Word 1: %x, ", (int)buf[1]));
/* Check co-processor ID. FPU is 1. (MMU is 0.) */
id = (int)((buf[0] >> 9) & 0x7);
if (id != 1) {
printf ("Unsupported co-processor (%d).\n", id);
#ifdef DDB
Debugger();
#endif
return;
}
type = (buf[0] >> 6) & 0x7;
mode = (buf[0] >> 3) & 0x7;
reg = buf[0] & 0x7;
source = (buf[1] >> 10) & 0x7;
dest = (buf[1] >> 7) & 0x7;
rm = (buf[1] >> 14) & 0x1;
misc = (buf[1] >> 13) & 0x1;
inst = buf[1] & 0x7F;
switch (type) {
case 0:
if ((buf[1] & 0x8000) == 0) {
if (mode == 0 && reg == 0 && source == 7 && rm == 1 && misc == 0) {
PRINTF (("FMOVECR (constant %d)\n", inst));
advance = 4;
} else if (rm == 1 && misc == 1) {
PRINTF (("FMOVE from FPn\n"));
advance = 4 + opsize (rm, mode, reg, source, buf);
} else {
/* Most instructions fall in this category... */
switch (inst) {
case 0: PRINTF ( ("FMOVE to FPn\n")); break;
case 1: PRINTF ( ("FINT\n")); break;
case 2: PRINTF ( ("FSINH\n")); break;
case 3: PRINTF ( ("FINTRZ\n")); break;
case 4: PRINTF ( ("FSQRT\n")); break;
case 6: PRINTF ( ("FLOGNP1\n")); break;
case 8: PRINTF ( ("FETOXM1\n")); break;
case 9: PRINTF ( ("FTANH\n")); break;
case 10: PRINTF ( ("FATAN\n")); break;
case 12: PRINTF ( ("FASIN\n")); break;
case 13: PRINTF ( ("FATANH\n")); break;
case 14: PRINTF ( ("FSIN\n")); break;
case 15: PRINTF ( ("FTAN\n")); break;
case 16: PRINTF ( ("FETOX\n")); break;
case 17: PRINTF ( ("FTWOTOX\n")); break;
case 18: PRINTF ( ("FTENTOX\n")); break;
case 20: PRINTF ( ("FLOGN\n")); break;
case 21: PRINTF ( ("FLOG10\n")); break;
case 22: PRINTF ( ("FLOG2\n")); break;
case 24: PRINTF ( ("FABS\n")); break;
case 25: PRINTF ( ("FCOSH\n")); break;
case 26: PRINTF ( ("FNEG\n")); break;
case 28: PRINTF ( ("FACOS\n")); break;
case 29: PRINTF ( ("FCOS\n")); break;
case 30: PRINTF ( ("FGETEXP\n")); break;
case 31: PRINTF ( ("FGETMAN\n")); break;
case 32: PRINTF ( ("FDIV\n")); break;
case 33: PRINTF ( ("FMOD\n")); break;
case 34: PRINTF ( ("FADD\n")); break;
case 35: PRINTF ( ("FMUL\n")); break;
case 36: PRINTF ( ("FSGLDIV\n")); break;
case 37: PRINTF ( ("FREM\n")); break;
case 38: PRINTF ( ("FSCALE\n")); break;
case 39: PRINTF ( ("FSGLMUL\n")); break;
case 40: PRINTF ( ("FSUB\n")); break;
case 48:
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55: PRINTF ( ("FSINCOS\n")); break;
case 56: PRINTF ( ("FCMP\n")); break;
case 58: PRINTF ( ("FTST\n")); break;
default: PRINTF ( ("Unknown instruction %d.\n", inst)); break;
}
advance = 4 + opsize (rm, mode, reg, source, buf);
}
} else {
if (rm) {
PRINTF ( ("FMOVE[M] FPn\n"));
advance = 4 + opsize (rm, mode, reg, source, buf);
} else {
PRINTF ( ("FMOVE[M] FPcm\n"));
advance = 4 + opsize (rm, mode, reg, source, buf);
}
}
break;
case 1:
if (mode == 1) {
PRINTF ( ("FDBcc\n"));
advance = 6;
} else {
if (mode == 7 && reg > 1) {
PRINTF ( ("FTRAPcc\n"));
switch (reg) {
case 2: advance = 6; break;
case 3: advance = 8; break;
case 4: advance = 4; break;
default: printf ("Unknown reg: %d\n", reg); break;
}
} else {
PRINTF ( ("FScc\n"));
advance = 4 + opsize (rm, mode, reg, source, buf);
}
}
break;
case 2:
case 3:
if (mode == 0 && reg == 0 && source == 0 && dest == 0) {
PRINTF ( ("FNOP\n"));
advance = 4;
} else {
PRINTF ( ("FBcc\n"));
if (type == 2) {
advance = 4;
} else {
advance = 6;
}
}
break;
case 4:
PRINTF ( ("FSAVE\n"));
advance = 2 + opsize (rm, mode, reg, source, buf);
break;
case 5:
PRINTF ( ("FRESTORE\n"));
advance = 2 + opsize (rm, mode, reg, source, buf);
break;
case 6:
case 7:
printf ("Unknown type: %d\n", type);
advance = 2;
break;
}
PRINTF ( ("Exiting FPUemul() (%d)\n", advance));
frame.f_pc += advance;
}