⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fpi_sigfpe.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic char *sccsid = "@(#)fpi_sigfpe.c	4.1	(ULTRIX)	7/3/90";#endif not lint/* ------------------------------------------------------------------ *//* | Copyright Unpublished, MIPS Computer Systems, Inc.  All Rights | *//* | Reserved.  This software contains proprietary and confidential | *//* | information of MIPS and its suppliers.  Use, disclosure or     | *//* | reproduction is prohibited without the prior express written   | *//* | consent of MIPS.                                               | *//* ------------------------------------------------------------------ *//* $Header: fpi_sigfpe.c,v 1.3 87/08/20 14:50:59 dce Exp $ *//* * THIS FILE MUST BE COMPILED WITH THE -float COMPILER OPTION!! */#include <sys/param.h>#if defined(BSD) || defined(ultrix)#include <mips/cpu.h>#include <mips/fpu.h>#include <mips/inst.h>#else#include <sys/sbd.h>#include <sys/fpu.h>#include <sys/inst.h>#endif#include <fpi.h>#include <fp_class.h>#include <signal.h>#include <stdio.h>extern char *sys_errlist[];extern int errno;char *fpi_list[] = {	"source signaling NaN",	"source quiet NaN",	"source denormalized value",	"move of zero",	"negate of zero",	"implemented only in software",	"invalid operation",	"divide by zero",	"destination overflow",	"destination underflow"};/* The counters */int fpi_counts[FPI_SIZE];/* * fpi() is called to setup the signal hander and do the system call. * fpi_() is the fortran wrapper. */voidfpi_(){	fpi();}voidfpi(){    void fpi_sigfpe();#ifdef BSD	signal(SIGFPE, fpi_sigfpe);#else	sigset(SIGFPE, fpi_sigfpe);#endif	if(fp_sigintr(1) == -1){	    fprintf(stderr,		   "fpi(): Error: system call fp_sigintr(1) failed (%s)\n",		   sys_errlist[errno]);	    exit(1);	}}/* * printfpi_counts() is used to print the counts.  printfpi_counts_() is the * fortran wrapper. */voidprintfpi_counts_(){	printfpi_counts();}voidprintfpi_counts(){    int i;	for(i = 0 ; i < FPI_SIZE; i++)		fprintf(stderr, "%s = %d\n", fpi_list[i], fpi_counts[i]);}static int counted;static void source_class();static unsigned long instr;static void help();/* routines to execute single instructions (all in fp_instr.s) */extern float sqrtf_instr(float x);extern double sqrtd_instr(double x);extern float absf_instr(float x);extern double absd_instr(double x);extern void cmpf_instr(float src1, float src2, long index);extern void cmpd_instr(double src1, double src2, long index);extern long cvtw_f_instr(float x);extern long cvtw_d_instr(double x);union value {	struct {	    unsigned long v0,v1,v2,v3;	} v;		/* four words for the value */	long w;		/* word */	float f;	/* single floating point */	double d;	/* double floating point */};/* * fpi_sigfpe() is used to handle the SIGFPE caused by the fp_sigintr() * system call and count the reasons why floating-point interrupts occured. */voidfpi_sigfpe(sig, code, scp)int sig, code;struct sigcontext *scp;{    union fpc_irr fpc_irr;    union fpu_instr fpu_instr;    unsigned long reg, fmt, func;    union value src1, src2, dest;    int src1_class, src2_class, dest_class;    int src1_fmt, src2_fmt, dest_fmt;    union fpc_csr fpc_csr;    int error;	counted = 0;	error = 0;	if(fp_sigintr(0) == -1){	    fprintf(stderr,		   "sigfpe(): Error: system call fp_sigintr(0) failed (%s)\n",		   sys_errlist[errno]);	    exit(1);	}	/*	 * Get the floating point instruction.  If the floating point unit	 * is the board implementation it's in the fpc_eir.  Else it is at	 * the exception program counter as modified by the branch delay	 * bit in the cause register.	 */	fpc_irr.fi_word = get_fpc_irr();	if(fpc_irr.fi_struct.implementation == IMPLEMENTATION_R2360)	    fpu_instr.instr = scp->sc_fpc_eir;	else	    if(scp->sc_cause & CAUSE_BD)		fpu_instr.instr = *(unsigned long *)(scp->sc_pc + 4);	    else		fpu_instr.instr = *(unsigned long *)(scp->sc_pc);	instr = fpu_instr.instr;	/*	 * To get here and have the instruction not be a floating-point	 * instruction is an error.	 */	if(fpu_instr.rtype.op != cop1_op){	    fprintf(stderr, "sigfpe(): Error: reached with a non-floating-point instruction\n");	    exit(1);	}	/*	 * Get the format of the source operand(s) from the (fmt) field of	 * the floating-point instruction.	 */	fmt = fpu_instr.rtype.fmt;	src1_fmt = fmt;	src2_fmt = fmt;	/*	 * Get src1's (rs) value from the value saved in the signal context.	 */	reg = fpu_instr.rtype.rs;	switch(fmt){	case FMT_WORD:	    src1.v.v0 = scp->sc_fpregs[reg];	    src1_class = -1;	    break;	case FMT_SINGLE:	    src1.v.v0 = scp->sc_fpregs[reg];	    src1_class = fp_class_f(src1.f);	    break;	case FMT_DOUBLE:#ifdef MIPSEL	    src1.v.v0 = scp->sc_fpregs[reg];	    src1.v.v1 = scp->sc_fpregs[reg+1];#endif MIPSEL#ifdef MIPSEB	    src1.v.v0 = scp->sc_fpregs[reg+1];	    src1.v.v1 = scp->sc_fpregs[reg];#endif MIPSEB	    src1_class = fp_class_d(src1.d);	    break;	default:	    fprintf(stderr, "sigfpe(): Error: reached with a floating-point instruction with an unsupported format\n");	    error = 1;	}	/*	 * If there is a src2 (rt) get it's value from the value saved in the	 * signal context.	 */	func = fpu_instr.rtype.func;	reg = fpu_instr.rtype.rt;	switch(fmt){	case FMT_WORD:	    src2.v.v0 = scp->sc_fpregs[reg];	    src2_class = -1;	    break;	case FMT_SINGLE:	    src2.v.v0 = scp->sc_fpregs[reg];	    src2_class = fp_class_f(src2.f);	    break;	case FMT_DOUBLE:#ifdef MIPSEL	    src2.v.v0 = scp->sc_fpregs[reg];	    src2.v.v1 = scp->sc_fpregs[reg+1];#endif MIPSEL#ifdef MIPSEB	    src2.v.v0 = scp->sc_fpregs[reg+1];	    src2.v.v1 = scp->sc_fpregs[reg];#endif MIPSEB	    src2_class = fp_class_d(src2.d);	    break;	}	/*	 * Clear out the sticky exception bits so they can be used to tell	 * what happened in creating the destination.	 */	fpc_csr.fc_word = get_fpc_csr();	fpc_csr.fc_struct.se_invalid = 0;	fpc_csr.fc_struct.se_divide0 = 0;	fpc_csr.fc_struct.se_underflow = 0;	fpc_csr.fc_struct.se_overflow = 0;	set_fpc_csr(fpc_csr.fc_word);	dest_fmt = fmt;	switch(func){	case FUNC_CVTS:	    src2_class = -1;	    src2_fmt = -1;	    dest_fmt = FMT_SINGLE;	    switch(fmt){	    case FMT_WORD:		dest.f = src1.w;		dest_class = fp_class_f(dest.f);		break;	    case FMT_DOUBLE:		dest.f = src1.d;		dest_class = fp_class_f(dest.f);		break;	    default:		error = 1;		break;	    }	    break;	case FUNC_CVTD:	    src2_class = -1;	    src2_fmt = -1;	    dest_fmt = FMT_DOUBLE;	    switch(fmt){	    case FMT_WORD:		dest.d = src1.w;		dest_class = fp_class_d(dest.d);		break;	    case FMT_SINGLE:		dest.d = src1.f;		dest_class = fp_class_d(dest.d);		break;	    default:		error = 1;		break;	    }	    break;	case FUNC_CVTW:	    src2_class = -1;	    src2_fmt = -1;	    dest_fmt = FMT_WORD;	    dest_class = -1;	    switch(fmt){	    case FMT_SINGLE:		dest.w = cvtw_f_instr(src1.f);		break;	    case FMT_DOUBLE:		dest.w = cvtw_d_instr(src1.d);		break;	    default:		error = 1;		break;	    }	    break;	case FUNC_ADD:	    switch(fmt){	    case FMT_SINGLE:		dest.f = src1.f + src2.f;		dest_class = fp_class_f(dest.f);		break;	    case FMT_DOUBLE:		dest.d = src1.d + src2.d;		dest_class = fp_class_d(dest.d);		break;	    default:		error = 1;		break;	    }	    break;	case FUNC_SUB:	    switch(fmt){	    case FMT_SINGLE:		dest.f = src1.f - src2.f;		dest_class = fp_class_f(dest.f);		break;	    case FMT_DOUBLE:		dest.d = src1.d - src2.d;		dest_class = fp_class_d(dest.d);		break;	    default:		error = 1;		break;	    }	    break;	case FUNC_MUL:	    switch(fmt){	    case FMT_SINGLE:		dest.f = src1.f * src2.f;		dest_class = fp_class_f(dest.f);		break;	    case FMT_DOUBLE:		dest.d = src1.d * src2.d;		dest_class = fp_class_d(dest.d);		break;	    default:		error = 1;		break;	    }	    break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -