早期freebsd实现

源代码在线查看: fpe.c

软件大小: 40554 K
上传用户: luyibo54618
关键词: freebsd
下载地址: 免注册下载 普通下载 VIP

相关代码

				/*-				 * Copyright (c) 1985 The Regents of the University of California.				 * All rights reserved.				 *				 * This code is derived from software contributed to Berkeley by				 * Computer Consoles Inc.				 *				 * 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 University of				 *	California, Berkeley and its contributors.				 * 4. Neither the name of the University nor the names of its contributors				 *    may be used to endorse or promote products derived from this software				 *    without specific prior written permission.				 *				 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.				 *				 *	@(#)fpe.c	7.1 (Berkeley) 12/6/90				 */								#include "../include/psl.h"				#include "../include/reg.h"				#include "../include/pte.h"				#include "../include/mtpr.h"				#include "../math/Kfp.h"								#include "sys/param.h"				#include "sys/systm.h"				#include "sys/user.h"				#include "sys/proc.h"				#include "sys/seg.h"				#include "sys/acct.h"				#include "sys/kernel.h"								/*				 * Floating point emulation support.				 */				extern	float Kcvtlf(), Kaddf(), Ksubf(), Kmulf(), Kdivf();				extern	double Kcvtld(), Kaddd(), Ksubd(), Kmuld(), Kdivd();				extern	float Ksinf(), Kcosf(), Katanf(), Klogf(), Ksqrtf(), Kexpf();								#define	OP(dop)		((dop) &~ 01)	/* precision-less version of opcode */				#define	isdouble(op)	((op) & 01)	/* is opcode double or float */								struct	fpetab {					int	fpe_op;		/* base opcode emulating */					float	(*fpe_ffunc)();	/* float version of op */					double	(*fpe_dfunc)();	/* double version of op */				} fpetab[] = {					{ OP(CVLD),	Kcvtlf,	Kcvtld },					{ OP(ADDD),	Kaddf,	Kaddd },					{ OP(SUBD),	Ksubf,	Ksubd },					{ OP(MULD),	Kmulf,	Kmuld },					{ OP(DIVD),	Kdivf,	Kdivd },					{ SINF,		Ksinf,	0 },					{ COSF,		Kcosf,	0 },					{ ATANF,	Katanf,	0 },					{ LOGF,		Klogf,	0 },					{ SQRTF,	Ksqrtf,	0 },					{ EXPF,		Kexpf,	0 },				};				#define	NFPETAB	(sizeof (fpetab) / sizeof (fpetab[0]))								/*				 * Emulate the FP opcode. Update psl as necessary.				 * If OK, set opcode to 0, else to the FP exception #.				 * Not all parameter longwords are relevant, depends on opcode.				 *				 * The entry mask is set by locore.s so ALL registers are saved.				 * This enables FP opcodes to change user registers on return.				 */				/* WARNING!!!! THIS CODE MUST NOT PRODUCE ANY FLOATING POINT EXCEPTIONS */				/*ARGSUSED*/				fpemulate(hfsreg, acc_most, acc_least, dbl, op_most, op_least, opcode, pc, psl)				{					int r0, r1;			/* must reserve space */					register int *locr0 = ((int *)&psl)-PS;					register struct fpetab *fp;					int hfs = 0; 			/* returned data about exceptions */					int type;			/* opcode type, FLOAT or DOUBLE */					union { float ff; int fi; } f_res;					union { double dd; int di[2]; } d_res;					int error = 0;								#ifdef lint					r0 = 0; r0 = r0; r1 = 0; r1 = r1;				#endif					type = isdouble(opcode) ? DOUBLE : FLOAT;					for (fp = fpetab; fp < &fpetab[NFPETAB]; fp++)						if ((opcode & 0xfe) == fp->fpe_op)							break;					if (type == DOUBLE) {						if (fp->fpe_dfunc == 0)							fp = &fpetab[NFPETAB];						else							locr0[PS] &= ~PSL_DBL;					}					if (fp >= &fpetab[NFPETAB]) {						opcode = DIV0_EXC;	/* generate SIGILL - XXX */						return (0);					}					switch (type) {									case DOUBLE:						d_res.dd = (*fp->fpe_dfunc)(acc_most, acc_least, op_most,						    op_least, &hfs);						if (d_res.di[0] == 0 && d_res.di[1] == 0)							locr0[PS] |= PSL_Z;						if (d_res.di[0] < 0)							locr0[PS] |= PSL_N;						break;									case FLOAT:						f_res.ff = (*fp->fpe_ffunc)(acc_most, acc_least, op_most,						    op_least, &hfs);						if (f_res.fi == 0)							locr0[PS] |= PSL_Z;						if (f_res.fi ==  0)							locr0[PS] |= PSL_N;						break;					}					if (hfs & HFS_OVF) {						locr0[PS] |= PSL_V;	/* turn on overflow bit */				#ifdef notdef						if (locr0[PS] & PSL_IV)   {  /* overflow enabled? */				#endif							opcode = OVF_EXC;							return ((hfs & HFS_DOM) ? EDOM : ERANGE);				#ifdef notdef						}				#endif					} else if (hfs & HFS_UNDF) {						if (locr0[PS] &  PSL_FU) {  /* underflow enabled? */							opcode = UNDF_EXC;							return ((hfs & HFS_DOM) ? EDOM : ERANGE);						} 					} else if (hfs & HFS_DIVZ) {						opcode = DIV0_EXC;						return (0);					} else if (hfs & HFS_DOM)						error = EDOM;					else if (hfs & HFS_RANGE)						error = ERANGE;					switch (type) {									case DOUBLE:						if (hfs & (HFS_OVF|HFS_UNDF)) {							d_res.dd = 0.0;							locr0[PS] |= PSL_Z;						}						mvtodacc(d_res.di[0], d_res.di[1], &acc_most);						break;									case FLOAT:						if (hfs & (HFS_OVF|HFS_UNDF)) {							f_res.ff = 0.0;							locr0[PS] |= PSL_Z;						}						mvtofacc(f_res.ff, &acc_most);						break;					}					opcode = 0;					return (error);				}							

相关资源