|
|
1.1 ! root 1: /* ! 2: * @(#)trpfpe_.c 1.1 6/7/85 ! 3: * ! 4: * ! 5: * Fortran floating-point error handler ! 6: * ! 7: * Synopsis: ! 8: * call trpfpe (n, retval) ! 9: * causes floating point faults to be trapped, with the ! 10: * first 'n' errors getting a message printed. ! 11: * 'retval' is put in place of the bad result. ! 12: * k = fpecnt() ! 13: * causes 'k' to get the number of errors since the ! 14: * last call to trpfpe(). ! 15: * ! 16: * common /fpeflt/ fpflag ! 17: * logical fpflag ! 18: * fpflag will become .true. on faults ! 19: * ! 20: * This handler just prints a message. It cannot fix anything ! 21: * on Power6 because of its fpp architecture. In any case, there ! 22: * are no arithmetic faults (only traps) around, so that no instruction ! 23: * is interrupted befor it completes, and PC points to the next floating ! 24: * point instruction (not necessarily next executable instr after the one ! 25: * that got the exception). ! 26: */ ! 27: ! 28: ! 29: #include <stdio.h> ! 30: #include <signal.h> ! 31: #include "../libI77/fiodefs.h" ! 32: ! 33: #define SIG_VAL int (*)() ! 34: ! 35: ! 36: struct arglist { /* what AP points to */ ! 37: long al_arg[256]; ! 38: }; ! 39: ! 40: struct reg0_1 { ! 41: long reg[2]; ! 42: }; ! 43: struct reg2_12 { ! 44: long reg[11]; ! 45: }; ! 46: #include <sys/types.h> ! 47: #include <frame.h> ! 48: #include "sigframe.h" ! 49: ! 50: /* ! 51: * bits in the PSL ! 52: */ ! 53: #include <machine/psl.h> ! 54: ! 55: /* ! 56: * where the registers are stored as we see them in the handler ! 57: */ ! 58: ! 59: ! 60: #define iR0 reg0_1->reg[1] ! 61: #define iR1 reg0_1->reg[0] ! 62: ! 63: #define iR2 reg2_12->reg[0] ! 64: #define iR3 reg2_12->reg[1] ! 65: #define iR4 reg2_12->reg[2] ! 66: #define iR5 reg2_12->reg[3] ! 67: #define iR6 reg2_12->reg[4] ! 68: #define iR7 reg2_12->reg[5] ! 69: #define iR8 reg2_12->reg[6] ! 70: #define iR9 reg2_12->reg[7] ! 71: #define iR10 reg2_12->reg[8] ! 72: #define iR11 reg2_12->reg[9] ! 73: #define iR12 reg2_12->reg[10] ! 74: ! 75: union objects { /* for load/store */ ! 76: char ua_byte; ! 77: short ua_word; ! 78: long ua_long; ! 79: float ua_float; ! 80: double ua_double; ! 81: union objects *ua_anything; ! 82: }; ! 83: ! 84: typedef union objects anything; ! 85: enum object_type { BYTE, WORD, LONG, FLOAT, QUAD, DOUBLE, UNKNOWN }; ! 86: ! 87: ! 88: /* ! 89: * assembly language assist ! 90: * There are some things you just can't do in C ! 91: */ ! 92: asm(".text"); ! 93: ! 94: long *myfp(); ! 95: asm("_myfp: .word 0"); ! 96: asm("movl (fp),r0"); ! 97: asm("ret"); ! 98: ! 99: struct frame *framep(p) ! 100: long *p; ! 101: { ! 102: return((struct frame *)(p-2)); ! 103: } ! 104: ! 105: struct arglist *argp(p) ! 106: long *p; ! 107: { ! 108: return((struct arglist *)(p+1)); ! 109: } ! 110: ! 111: char *mysp(); ! 112: asm("_mysp: .word 0"); ! 113: asm("addl3 $4,fp,r0"); ! 114: asm("ret"); ! 115: ! 116: char *mypc(); ! 117: asm("_mypc: .word 0"); ! 118: asm("movl -8(fp),r0"); ! 119: asm("ret"); ! 120: ! 121: asm(".data"); ! 122: ! 123: ! 124: /* ! 125: * Where interrupted objects are ! 126: */ ! 127: static struct frame *ifp; /* addr of saved FP */ ! 128: static struct arglist *iap; /* addr of saved AP */ ! 129: static char *isp; /* value of interrupted SP */ ! 130: static char **ipc; /* addr of saved PC */ ! 131: static struct reg0_1 *reg0_1;/* registers 0-1 are saved on the exception */ ! 132: static struct reg2_12 *reg2_12;/* we save 2-12 by our entry mask */ ! 133: static anything *result_addr; /* where the dummy result goes */ ! 134: static enum object_type result_type; /* what kind of object it is */ ! 135: ! 136: /* ! 137: * some globals ! 138: */ ! 139: static union { ! 140: long rv_long[2]; ! 141: float rv_float; ! 142: double rv_double; ! 143: } retval; /* the user specified dummy result */ ! 144: static int max_messages = 1; /* the user can tell us */ ! 145: static int fpe_count = 0; /* how bad is it ? */ ! 146: long fpeflt_ = 0; /* fortran "common /fpeflt/ flag" */ ! 147: static int (*sigfpe_dfl)() = SIG_DFL; /* if we can't fix it ... */ ! 148: ! 149: /* ! 150: * The fortran unit control table ! 151: */ ! 152: extern unit units[]; ! 153: ! 154: /* ! 155: * Fortran message table is in main ! 156: */ ! 157: struct msgtbl { ! 158: char *mesg; ! 159: int dummy; ! 160: }; ! 161: extern struct msgtbl act_fpe[]; ! 162: ! 163: ! 164: /* VALID ONLY ON VAX !!! ! 165: * ! 166: * Get the address of the (saved) next operand & update saved PC. ! 167: * The major purpose of this is to determine where to store the result. ! 168: * There is one case we can't deal with: -(SP) or (SP)+ ! 169: * since we can't change the size of the stack. ! 170: * Let's just hope compilers don't generate that for results. ! 171: */ ! 172: ! 173: ! 174: /* ! 175: * Trap & repair floating exceptions so that a program may proceed. ! 176: * There is no notion of "correctness" here; just the ability to continue. ! 177: * ! 178: * The on_fpe() routine first checks the type code to see if the ! 179: * exception is repairable. If so, it checks the opcode to see if ! 180: * it is one that it knows. If this is true, it then simulates the ! 181: * VAX cpu in retrieving operands in order to increment iPC correctly. ! 182: * It notes where the result of the operation would have been stored ! 183: * and substitutes a previously supplied value. ! 184: * DOES NOT REPAIR ON TAHOE !!! ! 185: */ ! 186: ! 187: on_fpe(signo, code, sc) ! 188: int signo, code; ! 189: struct sigcontext *sc; ! 190: { ! 191: /* ! 192: * There must be at least 11 register variables here ! 193: * so our entry mask will save R12-R2. ! 194: */ ! 195: register long *stk; ! 196: register long *sp, *rfp; ! 197: register struct arglist *ap; ! 198: register struct frame *fp; ! 199: register FILE *ef; ! 200: register struct sigframe *sfp; ! 201: register long dmy1, dmy2, dmy3, dmy4; ! 202: ! 203: dmy1 = dmy2 = dmy3 = dmy4 = 0; ! 204: ! 205: ef = units[STDERR].ufd; /* fortran error stream */ ! 206: ! 207: switch (code) ! 208: { ! 209: case FPE_INTOVF_TRAP: /* integer overflow */ ! 210: case FPE_INTDIV_TRAP: /* integer divide by zero */ ! 211: case FPE_FLTOVF_TRAP: /* floating overflow */ ! 212: case FPE_FLTDIV_TRAP: /* floating divide by zero */ ! 213: case FPE_FLTUND_TRAP: /* floating underflow */ ! 214: default: ! 215: cant_fix: ! 216: if (sigfpe_dfl > (SIG_VAL)7) /* user specified */ ! 217: return((*sigfpe_dfl)(signo, code, sc)); ! 218: else ! 219: if (++fpe_count <= max_messages) { ! 220: fprintf(ef, "trpfpe: %s", ! 221: act_fpe[code-1].mesg); ! 222: if (fpe_count == max_messages) ! 223: fprintf(ef, ": No more messages will be printed.\n"); ! 224: else ! 225: fputc('\n', ef); ! 226: } ! 227: fpeflt_ = -1; ! 228: break; ! 229: } ! 230: ! 231: /* ! 232: * Find all the registers just in case something better can be done. ! 233: */ ! 234: ! 235: rfp = myfp(); /* contents of fp register */ ! 236: ap = argp(rfp); /* my arglist pointer */ ! 237: fp = framep(rfp); /* my frame pointer */ ! 238: ifp = framep(*rfp); /* user's stored in next frame back */ ! 239: iap = argp(*rfp); ! 240: ! 241: sfp = (struct sigframe *)ap; /* sigframe contains at its bottom the ! 242: signal handler arguments */ ! 243: ! 244: reg0_1 = (struct reg0_1 *)&sfp->r1; ! 245: reg2_12 = (struct reg2_12 *)((char *)fp - sizeof (struct reg2_12)); ! 246: ! 247: ipc = (char **)&sc->sc_pc; ! 248: isp = (char *)sc + sizeof (struct sigcontext); ! 249: sc->sc_ps &= ~(PSL_V|PSL_FU); ! 250: ! 251: fprintf(ef, "Current PC = %X \n", sc->sc_pc); ! 252: ! 253: signal(SIGFPE, on_fpe); ! 254: sigdie(signo, code, sc); ! 255: } ! 256: ! 257: trpfpe_ (count, rval) ! 258: long *count; /* how many to announce */ ! 259: double *rval; /* dummy return value */ ! 260: { ! 261: max_messages = *count; ! 262: retval.rv_double = *rval; ! 263: sigfpe_dfl = signal(SIGFPE, on_fpe); ! 264: fpe_count = 0; ! 265: } ! 266: ! 267: long ! 268: fpecnt_ () ! 269: { ! 270: return (fpe_count); ! 271: } ! 272:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.