Annotation of 42BSD/usr.lib/libF77/trpfpe_.c, revision 1.1.1.1

1.1       root        1: /* #define     OLD_BSD         if you're running < 4.2bsd */
                      2: /*
                      3: char   id_trpfpe[] = "@(#)trpfpe_.c    1.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:  *     David Wasley, UCBerkeley, June 1983.
                     21:  */
                     22: 
                     23: 
                     24: #include <stdio.h>
                     25: #include <signal.h>
                     26: #include "opcodes.h"
                     27: #include "operand.h"
                     28: #include "../libI77/fiodefs.h"
                     29: 
                     30: #define        SIG_VAL         int (*)()
                     31: 
                     32: #if    vax             /* only works on VAXen */
                     33: 
                     34: struct arglist {               /* what AP points to */
                     35:        long    al_numarg;      /* only true in CALLS format */
                     36:        long    al_arg[256];
                     37: };
                     38: 
                     39: struct cframe {                        /* VAX call frame */
                     40:        long            cf_handler;
                     41:        unsigned short  cf_psw;
                     42:        unsigned short  cf_mask;
                     43:        struct arglist  *cf_ap;
                     44:        struct cframe   *cf_fp;
                     45:        char            *cf_pc;
                     46: };
                     47: 
                     48: /*
                     49:  * bits in the PSW
                     50:  */
                     51: #define        PSW_V   0x2
                     52: #define        PSW_FU  0x40
                     53: #define        PSW_IV  0x20
                     54: 
                     55: /*
                     56:  * where the registers are stored as we see them in the handler
                     57:  */
                     58: struct reg0_6 {
                     59:        long    reg[7];
                     60: };
                     61: 
                     62: struct reg7_11 {
                     63:        long    reg[5];
                     64: };
                     65: 
                     66: #define        iR0     reg0_6->reg[0]
                     67: #define        iR1     reg0_6->reg[1]
                     68: #define        iR2     reg0_6->reg[2]
                     69: #define        iR3     reg0_6->reg[3]
                     70: #define        iR4     reg0_6->reg[4]
                     71: #define        iR5     reg0_6->reg[5]
                     72: #define        iR6     reg0_6->reg[6]
                     73: #define        iR7     reg7_11->reg[0]
                     74: #define        iR8     reg7_11->reg[1]
                     75: #define        iR9     reg7_11->reg[2]
                     76: #define        iR10    reg7_11->reg[3]
                     77: #define        iR11    reg7_11->reg[4]
                     78: 
                     79: union objects {                /* for load/store */
                     80:        char    ua_byte;
                     81:        short   ua_word;
                     82:        long    ua_long;
                     83:        float   ua_float;
                     84:        double  ua_double;
                     85:        union objects   *ua_anything;
                     86: };
                     87: 
                     88: typedef union objects  anything;
                     89: enum object_type { BYTE, WORD, LONG, FLOAT, QUAD, DOUBLE, UNKNOWN };
                     90: 
                     91: 
                     92: /*
                     93:  * assembly language assist
                     94:  * There are some things you just can't do in C
                     95:  */
                     96: asm(".text");
                     97: 
                     98: struct cframe  *myfp();
                     99: asm("_myfp: .word 0x0");
                    100:        asm("movl 12(fp),r0");
                    101:        asm("ret");
                    102: 
                    103: struct arglist *myap();
                    104: asm("_myap: .word 0x0");
                    105:        asm("movl 8(fp),r0");
                    106:        asm("ret");
                    107: 
                    108: char   *mysp();
                    109: asm("_mysp: .word 0x0");
                    110:        asm("extzv $30,$2,4(fp),r0");
                    111:        asm("addl2 ap,r0");     /* SP in caller is AP+4 here + SPA bits! */
                    112:        asm("addl2 $4,r0");
                    113:        asm("ret");
                    114: 
                    115: char   *mypc();
                    116: asm("_mypc: .word 0x0");
                    117:        asm("movl 16(fp),r0");
                    118:        asm("ret");
                    119: 
                    120: asm(".data");
                    121: 
                    122: 
                    123: /*
                    124:  * Where interrupted objects are
                    125:  */
                    126: static struct cframe   **ifp;  /* addr of saved FP */
                    127: static struct arglist  **iap;  /* addr of saved AP */
                    128: static char             *isp;  /* value of interrupted SP */
                    129: static char            **ipc;  /* addr of saved PC */
                    130: static struct reg0_6   *reg0_6;/* registers 0-6 are saved on the exception */
                    131: static struct reg7_11  *reg7_11;/* we save 7-11 by our entry mask */
                    132: static anything                *result_addr;   /* where the dummy result goes */
                    133: static enum object_type         result_type;   /* what kind of object it is */
                    134: 
                    135: /*
                    136:  * some globals
                    137:  */
                    138: static union {
                    139:        long    rv_long[2];
                    140:        float   rv_float;
                    141:        double  rv_double;
                    142:                        } retval; /* the user specified dummy result */
                    143: static int     max_messages    = 1;            /* the user can tell us */
                    144: static int     fpe_count       = 0;            /* how bad is it ? */
                    145:        long    fpeflt_         = 0;    /* fortran "common /fpeflt/ flag" */
                    146: static int     (*sigfpe_dfl)() = SIG_DFL;      /* if we can't fix it ... */
                    147: 
                    148: /*
                    149:  * The fortran unit control table
                    150:  */
                    151: extern unit units[];
                    152: 
                    153: /*
                    154:  * Fortran message table is in main
                    155:  */
                    156: struct msgtbl {
                    157:        char    *mesg;
                    158:        int     dummy;
                    159: };
                    160: extern struct msgtbl   act_fpe[];
                    161: 
                    162: 
                    163: /*
                    164:  * Get the address of the (saved) next operand & update saved PC.
                    165:  * The major purpose of this is to determine where to store the result.
                    166:  * There is one case we can't deal with: -(SP) or (SP)+
                    167:  * since we can't change the size of the stack.
                    168:  * Let's just hope compilers don't generate that for results.
                    169:  */
                    170: 
                    171: anything *
                    172: get_operand (oper_size)
                    173:        int     oper_size;      /* size of operand we expect */
                    174: {
                    175:        register int    regnum;
                    176:        register int    operand_code;
                    177:        int             index;
                    178:        anything        *oper_addr;
                    179:        anything        *reg_addr;
                    180: 
                    181:        regnum = (**ipc & 0xf);
                    182:        if (regnum == PC)
                    183:                operand_code = (*(*ipc)++ & 0xff);
                    184:        else
                    185:                operand_code = (*(*ipc)++ & 0xf0);
                    186:        if (regnum <= R6)
                    187:                reg_addr = (anything *)&reg0_6->reg[regnum];
                    188:        else if (regnum <= R11)
                    189:                reg_addr = (anything *)&reg7_11->reg[regnum];
                    190:        else if (regnum == AP)
                    191:                reg_addr = (anything *)iap;
                    192:        else if (regnum == FP)
                    193:                reg_addr = (anything *)ifp;
                    194:        else if (regnum == SP)
                    195:                reg_addr = (anything *)&isp;    /* We saved this ourselves */
                    196:        else if (regnum == PC)
                    197:                reg_addr = (anything *)ipc;
                    198: 
                    199: 
                    200:        switch (operand_code)
                    201:        {
                    202:                case IMMEDIATE:
                    203:                        oper_addr = (anything *)(*ipc);
                    204:                        *ipc += oper_size;
                    205:                        return(oper_addr);
                    206: 
                    207:                case ABSOLUTE:
                    208:                        oper_addr = (anything *)(**ipc);
                    209:                        *ipc += sizeof (anything *);
                    210:                        return(oper_addr);
                    211: 
                    212:                case LITERAL0:
                    213:                case LITERAL1:
                    214:                case LITERAL2:
                    215:                case LITERAL3:
                    216:                        /* we don't care about the address of these */
                    217:                        return((anything *)0);
                    218: 
                    219:                case INDEXED:
                    220:                        index = reg_addr->ua_long * oper_size;
                    221:                        oper_addr = (anything *)(get_operand(sizeof (long))->ua_long + index);
                    222:                        return(oper_addr);
                    223: 
                    224:                case REGISTER:
                    225:                        return(reg_addr);
                    226: 
                    227:                case REGDEFERED:
                    228:                        return(reg_addr->ua_anything);
                    229: 
                    230:                case AUTODEC:
                    231:                        if (regnum == SP)
                    232:                        {
                    233:                                fprintf(stderr, "trp: can't fix -(SP) operand\n");
                    234:                                exit(1);
                    235:                        }
                    236:                        reg_addr->ua_long -= oper_size;
                    237:                        oper_addr = reg_addr->ua_anything;
                    238:                        return(oper_addr);
                    239: 
                    240:                case AUTOINC:
                    241:                        if (regnum == SP)
                    242:                        {
                    243:                                fprintf(stderr, "trp: can't fix (SP)+ operand\n");
                    244:                                exit(1);
                    245:                        }
                    246:                        oper_addr = reg_addr->ua_anything;
                    247:                        reg_addr->ua_long += oper_size;
                    248:                        return(oper_addr);
                    249: 
                    250:                case AUTOINCDEF:
                    251:                        if (regnum == SP)
                    252:                        {
                    253:                                fprintf(stderr, "trp: can't fix @(SP)+ operand\n");
                    254:                                exit(1);
                    255:                        }
                    256:                        oper_addr = (reg_addr->ua_anything)->ua_anything;
                    257:                        reg_addr->ua_long += sizeof (anything *);
                    258:                        return(oper_addr);
                    259: 
                    260:                case BYTEDISP:
                    261:                case BYTEREL:
                    262:                        index = ((anything *)(*ipc))->ua_byte;
                    263:                        *ipc += sizeof (char);  /* do it now in case reg==PC */
                    264:                        oper_addr = (anything *)(index + reg_addr->ua_long);
                    265:                        return(oper_addr);
                    266: 
                    267:                case BYTEDISPDEF:
                    268:                case BYTERELDEF:
                    269:                        index = ((anything *)(*ipc))->ua_byte;
                    270:                        *ipc += sizeof (char);  /* do it now in case reg==PC */
                    271:                        oper_addr = (anything *)(index + reg_addr->ua_long);
                    272:                        oper_addr = oper_addr->ua_anything;
                    273:                        return(oper_addr);
                    274: 
                    275:                case WORDDISP:
                    276:                case WORDREL:
                    277:                        index = ((anything *)(*ipc))->ua_word;
                    278:                        *ipc += sizeof (short); /* do it now in case reg==PC */
                    279:                        oper_addr = (anything *)(index + reg_addr->ua_long);
                    280:                        return(oper_addr);
                    281: 
                    282:                case WORDDISPDEF:
                    283:                case WORDRELDEF:
                    284:                        index = ((anything *)(*ipc))->ua_word;
                    285:                        *ipc += sizeof (short); /* do it now in case reg==PC */
                    286:                        oper_addr = (anything *)(index + reg_addr->ua_long);
                    287:                        oper_addr = oper_addr->ua_anything;
                    288:                        return(oper_addr);
                    289: 
                    290:                case LONGDISP:
                    291:                case LONGREL:
                    292:                        index = ((anything *)(*ipc))->ua_long;
                    293:                        *ipc += sizeof (long);  /* do it now in case reg==PC */
                    294:                        oper_addr = (anything *)(index + reg_addr->ua_long);
                    295:                        return(oper_addr);
                    296: 
                    297:                case LONGDISPDEF:
                    298:                case LONGRELDEF:
                    299:                        index = ((anything *)(*ipc))->ua_long;
                    300:                        *ipc += sizeof (long);  /* do it now in case reg==PC */
                    301:                        oper_addr = (anything *)(index + reg_addr->ua_long);
                    302:                        oper_addr = oper_addr->ua_anything;
                    303:                        return(oper_addr);
                    304: 
                    305:                /* NOTREACHED */
                    306:        }
                    307: }
                    308: 
                    309: /*
                    310:  * Trap & repair floating exceptions so that a program may proceed.
                    311:  * There is no notion of "correctness" here; just the ability to continue.
                    312:  *
                    313:  * The on_fpe() routine first checks the type code to see if the
                    314:  * exception is repairable. If so, it checks the opcode to see if
                    315:  * it is one that it knows. If this is true, it then simulates the
                    316:  * VAX cpu in retrieving operands in order to increment iPC correctly.
                    317:  * It notes where the result of the operation would have been stored
                    318:  * and substitutes a previously supplied value.
                    319:  */
                    320: 
                    321: #ifdef OLD_BSD
                    322: on_fpe(signo, code, myaddr, pc, ps)
                    323:        int signo, code, ps;
                    324:        char *myaddr, *pc;
                    325: #else
                    326: on_fpe(signo, code, sc, grbg)
                    327:        int signo, code;
                    328:        struct sigcontext *sc;
                    329: #endif
                    330: {
                    331:        /*
                    332:         * There must be at least 5 register variables here
                    333:         * so our entry mask will save R11-R7.
                    334:         */
                    335:        register long   *stk;
                    336:        register long   *sp;
                    337:        register struct arglist *ap;
                    338:        register struct cframe  *fp;
                    339:        register FILE   *ef;
                    340: 
                    341:        ef = units[STDERR].ufd;         /* fortran error stream */
                    342: 
                    343:        switch (code)
                    344:        {
                    345:                case FPE_INTOVF_TRAP:   /* integer overflow */
                    346:                case FPE_INTDIV_TRAP:   /* integer divide by zero */
                    347:                case FPE_FLTOVF_TRAP:   /* floating overflow */
                    348:                case FPE_FLTDIV_TRAP:   /* floating/decimal divide by zero */
                    349:                case FPE_FLTUND_TRAP:   /* floating underflow */
                    350:                case FPE_DECOVF_TRAP:   /* decimal overflow */
                    351:                case FPE_SUBRNG_TRAP:   /* subscript out of range */
                    352:                default:
                    353: cant_fix:
                    354:                        if (sigfpe_dfl > (SIG_VAL)7)    /* user specified */
                    355: #ifdef OLD_BSD
                    356:                                return((*sigfpe_dfl)(signo, code, myaddr, pc, ps));
                    357: #else
                    358:                                return((*sigfpe_dfl)(signo, code, sc, grbg));
                    359: #endif
                    360:                        else
                    361: #ifdef OLD_BSD
                    362:                                sigdie(signo, code, myaddr, pc, ps);
                    363: #else
                    364:                                sigdie(signo, code, sc, grbg);
                    365: #endif
                    366:                        /* NOTREACHED */
                    367: 
                    368:                case FPE_FLTOVF_FAULT:  /* floating overflow fault */
                    369:                case FPE_FLTDIV_FAULT:  /* divide by zero floating fault */
                    370:                case FPE_FLTUND_FAULT:  /* floating underflow fault */
                    371:                        if (++fpe_count <= max_messages) {
                    372:                                fprintf(ef, "trpfpe: %s",
                    373:                                        act_fpe[code-1].mesg);
                    374:                                if (fpe_count == max_messages)
                    375:                                        fprintf(ef, ": No more messages will be printed.\n");
                    376:                                else
                    377:                                        fputc('\n', ef);
                    378:                        }
                    379:                        fpeflt_ = -1;
                    380:                        break;
                    381:        }
                    382: 
                    383:        ap = myap();                    /* my arglist pointer */
                    384:        fp = myfp();                    /* my frame pointer */
                    385:        ifp = &(fp->cf_fp)->cf_fp;      /* user's stored in next frame back */
                    386:        iap = &(fp->cf_fp)->cf_ap;
                    387:        /*
                    388:         * these are likely to be system dependent
                    389:         */
                    390:        reg0_6 = (struct reg0_6 *)((char *)fp->cf_fp + sizeof (struct cframe));
                    391:        reg7_11 = (struct reg7_11 *)((char *)fp->cf_fp - sizeof (struct reg7_11));
                    392: 
                    393: #ifdef OLD_BSD
                    394:        ipc = &pc;
                    395:        isp = (char *)&ap->al_arg[ap->al_numarg + 2];   /* assumes 2 dummys */
                    396:        ps &= ~(PSW_V|PSW_FU);
                    397: #else
                    398:        ipc = (char **)&sc->sc_pc;
                    399:        isp = (char *)sc + sizeof (struct sigcontext);
                    400:        sc->sc_ps &= ~(PSW_V|PSW_FU);
                    401: #endif
                    402: 
                    403: 
                    404:        switch (*(*ipc)++)
                    405:        {
                    406:                case ADDD3:
                    407:                case DIVD3:
                    408:                case MULD3:
                    409:                case SUBD3:
                    410:                        (void) get_operand(sizeof (double));
                    411:                        /* intentional fall-thru */
                    412: 
                    413:                case ADDD2:
                    414:                case DIVD2:
                    415:                case MULD2:
                    416:                case SUBD2:
                    417:                case MNEGD:
                    418:                case MOVD:
                    419:                        (void) get_operand(sizeof (double));
                    420:                        result_addr = get_operand(sizeof (double));
                    421:                        result_type = DOUBLE;
                    422:                        break;
                    423: 
                    424:                case ADDF3:
                    425:                case DIVF3:
                    426:                case MULF3:
                    427:                case SUBF3:
                    428:                        (void) get_operand(sizeof (float));
                    429:                        /* intentional fall-thru */
                    430: 
                    431:                case ADDF2:
                    432:                case DIVF2:
                    433:                case MULF2:
                    434:                case SUBF2:
                    435:                case MNEGF:
                    436:                case MOVF:
                    437:                        (void) get_operand(sizeof (float));
                    438:                        result_addr = get_operand(sizeof (float));
                    439:                        result_type = FLOAT;
                    440:                        break;
                    441: 
                    442:                case CVTDF:
                    443:                        (void) get_operand(sizeof (double));
                    444:                        result_addr = get_operand(sizeof (float));
                    445:                        result_type = FLOAT;
                    446:                        break;
                    447: 
                    448:                case CVTFD:
                    449:                        (void) get_operand(sizeof (float));
                    450:                        result_addr = get_operand(sizeof (double));
                    451:                        result_type = DOUBLE;
                    452:                        break;
                    453: 
                    454:                case EMODF:
                    455:                case EMODD:
                    456:                        fprintf(ef, "trpfpe: can't fix emod yet\n");
                    457:                        goto cant_fix;
                    458: 
                    459:                case POLYF:
                    460:                case POLYD:
                    461:                        fprintf(ef, "trpfpe: can't fix poly yet\n");
                    462:                        goto cant_fix;
                    463: 
                    464:                case ACBD:
                    465:                case ACBF:
                    466:                case CMPD:
                    467:                case CMPF:
                    468:                case TSTD:
                    469:                case TSTF:
                    470:                case CVTDB:
                    471:                case CVTDL:
                    472:                case CVTDW:
                    473:                case CVTFB:
                    474:                case CVTFL:
                    475:                case CVTFW:
                    476:                case CVTRDL:
                    477:                case CVTRFL:
                    478:                        /* These can generate only reserved operand faults */
                    479:                        /* They are shown here for completeness */
                    480: 
                    481:                default:
                    482:                        fprintf(stderr, "trp: opcode 0x%02x unknown\n",
                    483:                                *(--(*ipc)) & 0xff);
                    484:                        goto cant_fix;
                    485:                        /* NOTREACHED */
                    486:        }
                    487: 
                    488:        if (result_type == FLOAT)
                    489:                result_addr->ua_float = retval.rv_float;
                    490:        else
                    491:        {
                    492:                if (result_addr == (anything *)&iR6)
                    493:                {       /*
                    494:                         * special case - the R6/R7 pair is stored apart
                    495:                         */
                    496:                        result_addr->ua_long = retval.rv_long[0];
                    497:                        ((anything *)&iR7)->ua_long = retval.rv_long[1];
                    498:                }
                    499:                else
                    500:                        result_addr->ua_double = retval.rv_double;
                    501:        }
                    502:        signal(SIGFPE, on_fpe);
                    503: }
                    504: #endif vax
                    505: 
                    506: trpfpe_ (count, rval)
                    507:        long    *count; /* how many to announce */
                    508:        double  *rval;  /* dummy return value */
                    509: {
                    510: #if    vax
                    511:        max_messages = *count;
                    512:        retval.rv_double = *rval;
                    513:        sigfpe_dfl = signal(SIGFPE, on_fpe);
                    514:        fpe_count = 0;
                    515: #endif
                    516: }
                    517: 
                    518: long
                    519: fpecnt_ ()
                    520: {
                    521: #if    vax
                    522:        return (fpe_count);
                    523: #else
                    524:        return (0L);
                    525: #endif
                    526: }
                    527: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.