Switch for under- or overflow in Fortran on 3100 ???
Roger Masse
roj at dodads.dco.dec.com
Thu Oct 4 04:34:44 AEST 1990
In article <1990Oct3.081355.19910 at portia.Stanford.EDU>,
buc at jessica.stanford.edu (Robert Richards) writes:
|> Is there any way to turn off the IEEE floating point over and underflow
|> when running a fortran program on decstation 3100 ?
|>
> There is no "built in" facility for doing this, though the hardware and
> ULTRIX support intercepting such exceptions in user code and dealing with
> it there.
> Srini Uppungunduri of Mike Greenfield's group has written a set of
> routines designed to ignore the floating point 'inexact' exception, and
> catch and "fix up" the floating point 'underflow' and integer 'divide
> by zero' exceptions (yes, these are the routines you forwarded me,
> Tom). The user must add calls to the approriate routines to set things
> up, and link in the [C] routines, to get the behavior desired.
> In the case of floating point underflow, the exception is caught, and
> the floating point result is set to 0.0, and execution continues.
> The package of routines follows. Instructions for their use are
> included in the comments. Thanks, Tom (and Srini!), for them.
Regards,
Roger Masse'
8301 Professional Place Digital Equipment Corporation
Landover, Maryland, 20785 Washington ULTRIX Resource Center
Internet: roj at dco.dec.com uucp: decvax!decuac!roj
Disclaimer: My opinions do not necessarily represent anything.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/************************************************************************
* *
* Copyright (c) 1989 by *
* Digital Equipment Corporation, Maynard, MA *
* All rights reserved. *
* *
* This software is furnished under a license and may be used and *
* copied only in accordance with the terms of such license and *
* with the inclusion of the above copyright notice. This *
* software or any other copies thereof may not be provided or *
* otherwise made available to any other person. No title to and *
* ownership of the software is hereby transferred. *
* *
* The information in this software is subject to change without *
* notice and should not be construed as a commitment by Digital *
* Equipment Corporation. *
* *
* Digital assumes no responsibility for the use or reliability *
* of its software on equipment which is not supplied by Digital. *
* *
************************************************************************
* intr_handl.c
*
* Trap and correct floating point and integer exceptions :
* _______________________________________________________
*
* This file contains the following routines
*
* stp_int_handl : Routine to set up integer exception handler
* (only handles integer divide by zero's now)
* stp_flt_handl : Routine to set up floating point exception
* handler
* handl_flt_intr: Handler for floating point interrupts
* handl_int_intr: Handler for integer divide by zero exceptions
* stp_int_handl_: F77 wrapper for stp_int_handl
* stp_flt_handl_: F77 wrapper for stp_flt_handl
* rls_flt_handl : Return to default action for floating point interrupt
* handling
* rls_int_handl : Return to default action for integer interrupt
* handling
* rls_int_handl_: F77 wrapper for rls_int_handl
* rls_flt_handl_: F77 wrapper for rls_flt_handl
*
* Compiler switches:
* _________________
*
* The file can be compiled with two switches -DINEXACT and -DERROR_MSG
*
* -DERROR_MSG: This will print a message indicating the type of excpt.
* encountered every time a exception is encountered
* -DINEXACT : This causes the inexact exception not to be trapped --
* if you donot compile with this flag serious performance
* problems can result. Inexact operations are triggered due
* to several reasons
*
* It is suggested that you compile as
* cc -c -DINEXACT -DERROR_MSG -float intr_handl.c
* as a first pass and then turn off error reporting
*
* For a FORTRAN program after linking the routines in, to set up the
* handlers include the following statements in your source
* CALL STP_FLT_HANDL()
* CALL STP_INT_HANDL()
*
* Srini Uppugunduri 05/09/89
* Updated to rectify only underflows on 07/17/90
*/
#include <mips/cpu.h>
#include <mips/fpu.h>
#include <sys/sysmips.h>
#include <mips/cachectl.h>
#include <mips/inst.h>
#include <fp_class.h>
#include <signal.h>
#include <stdio.h>
extern int fp_class_f(float x); /* will show up in fp_class.h soon */
static unsigned long save_csr_state; /* need this variable to */
/* save the csr state which is used*/
/* in the rls_flt_handl routine */
static unsigned long instr;
/*
* stp_int_handl() sets up the signal handler for the integer
* divide by zero which in normal cases causes a Trace/BPT trap
*/
void stp_int_handl()
{
void handl_int_intr();
signal(SIGTRAP, handl_int_intr);
}
void rls_int_handl()
{
signal(SIGTRAP, SIG_DFL);
}
/*
* stp_flt_handl() sets up the signal handler and enables the
* floating point exceptions. Refer to /usr/include/mips/fpu.h
* for a detailed description of the structures
*/
void stp_flt_handl()
{
union fpc_csr fpc_csr;
void handl_flt_intr();
/*
* The next line sets up the signal handler routine
*/
signal(SIGFPE, handl_flt_intr);
/* The next few lines set up the fpc_csr structure to trap
* for floating interrupts and blanks out inexact floating
* point interrupts which are generated often and cause a
* a serious performance degradation
*/
fpc_csr.fc_word = save_csr_state = get_fpc_csr();
/* Look at the /usr/include/mips/fpu.h to understand the next
few lines
*/
fpc_csr.fc_word |= 0x00000f80;
/* comment out the next few lines if you prefer to trap inexact
floating point exceptions
*/
fpc_csr.fc_struct.ex_inexact = 0;
fpc_csr.fc_struct.en_inexact = 0;
fpc_csr.fc_struct.se_inexact = 0;
/* The next call ensures that a SIGFPE is generated for every
floating point interrupt.
*/
set_fpc_csr(fpc_csr.fc_word);
}
void rls_flt_handl()
{
union fpc_csr fpc_csr;
/* Return the csr to intial state - dont need to trap floating
point interrupts any longer
*/
fpc_csr.fc_word = save_csr_state;
set_fpc_csr(fpc_csr.fc_word);
signal(SIGFPE, SIG_DFL);
}
/*
* stp_int_handl_ and stp_flt_handl_ are the F77 wrappers for setting up
* the integer and floating point interrupt handlers
* rls_flt_handl_ and rls_int_handl_ are the F77 wrappers for releasing
* the signal handlers
*/
void stp_int_handl_()
{
stp_int_handl();
}
void stp_flt_handl_()
{
stp_flt_handl();
}
void rls_int_handl_()
{
rls_int_handl();
}
void rls_flt_handl_()
{
rls_flt_handl();
}
/*
* stp_flt_handl() is the signal handler for SIGFPE (floating point
* interrupts).
* Branch-delay-set will cause a emulate branch based on the branch
* instruction
*/
void handl_flt_intr(sig, code, scp)
int sig, code;
struct sigcontext *scp;
{
union fpc_csr fpc_csr;
union fpu_instr fpu_instr;
union fpc_irr fpc_irr;
unsigned long branch_instruction;
unsigned long dreg, sreg1, sreg2, fmt, func;
fpc_csr.fc_word = scp->sc_fpc_csr;
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;
/*Destination Register */
dreg = fpu_instr.rtype.rd;
/*Source Register 1 */
sreg1 = fpu_instr.rtype.rs;
/*Source Register 2 */
sreg2 = fpu_instr.rtype.rt;
#ifdef ERROR_MSG
if (fpc_csr.fc_struct.ex_invalid)
{
printf("\nFloating point interrupt: Invalid Operation \n");
}
if (fpc_csr.fc_struct.ex_divide0)
{
printf("\nFloating point interrupt: Divide by Zero Operation \n");
}
if (fpc_csr.fc_struct.ex_underflow)
{
printf("\nFloating point interrupt: Underflow Operation \n");
}
if (fpc_csr.fc_struct.ex_overflow)
{
printf("\nFloating point interrupt: Overflow Operation \n");
}
if (fpc_csr.fc_struct.ex_inexact)
{
printf("\nFloating point interrupt: Inexact Operation \n");
}
if (fpc_csr.fc_struct.ex_unimplemented)
{
printf("\nFloating point interrupt: Unimplemented Operation \n");
}
#endif
/*
* Modify the saved PC so that there is no attempt to re-execute
* the floating point instruction that caused the initial
* exception.
*/
if (scp->sc_cause & CAUSE_BD) {
branch_instruction = *(unsigned long *)(scp->sc_pc);
/*
* Look at signal(3) for more details of this step
* Emulate the branch instruction found on the stack
*/
emulate_branch(scp, branch_instruction);
}
else
scp->sc_pc += 4;
/* Modify values in the destination register; if this were big
endian we would need to modify dreg-1 instead of dreg+1 */
if (fpc_csr.fc_struct.ex_underflow)
{
scp->sc_fpregs[dreg] = 0 ;
scp->sc_fpregs[dreg+1] = 0 ;
}
sigreturn(scp);
}
/* Signal Handler for the integer divide by zero operation */
void handl_int_intr(sig, code, scp)
int sig, code;
struct sigcontext *scp;
{
union fpu_instr exception_instruction;
unsigned long branch_instruction, rsreg, rtreg;
/* Check if the SIGTRAP was a divide by zero and
* set the appropriate register to give a zero result
*/
if (scp->sc_cause & CAUSE_BD) {
branch_instruction = *(unsigned long *)(scp->sc_pc);
/*
* Look in signal(3) for details of this step
* emulate_branch(scp,branch_instruction);
*/
exception_instruction.instr =
*(unsigned long *)(scp->sc_pc + 4);
emulate_branch(scp, branch_instruction);
}
else {
exception_instruction.instr =
*(unsigned long *)(scp->sc_pc);
scp->sc_pc += 4;
}
if (code == BRK_DIVZERO)
{
#ifdef ERROR_MSG
printf("\nInteger Interrupt : Divide By zero operation\n");
#endif
rsreg = exception_instruction.itype.base;
rtreg = exception_instruction.itype.rt;
scp->sc_regs[rsreg] = 0;
scp->sc_regs[rtreg] = 1;
scp->sc_mdlo = 0;
scp->sc_mdhi = 0;
}
sigreturn(scp);
}
cacheflush(addr, nbytes, cache)
char *addr;
int nbytes, cache;
{
int status;
status = syscall(151,MIPS_CACHEFLUSH,addr,nbytes,cache);
if (status == -1 ) return(status) ;
else
return(0);
}
Regards,
Roger Masse'
8301 Professional Place Digital Equipment Corporation
Landover, Maryland, 20785 Washington ULTRIX Resource Center
Internet: roj at dco.dec.com uucp: decvax!decuac!roj
Disclaimer: My opinions do not necessarily represent anything.
More information about the Comp.unix.ultrix
mailing list