|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)trapov_.c 5.5 2/14/90 ! 7: * ! 8: * Fortran/C floating-point overflow handler ! 9: * ! 10: * The idea of these routines is to catch floating-point overflows ! 11: * and print an eror message. When we then get a reserved operand ! 12: * exception, we then fix up the value to the highest possible ! 13: * number. Keen, no? ! 14: * Messy, yes! ! 15: * ! 16: * Synopsis: ! 17: * call trapov(n) ! 18: * causes overflows to be trapped, with the first 'n' ! 19: * overflows getting an "Overflow!" message printed. ! 20: * k = ovcnt(0) ! 21: * causes 'k' to get the number of overflows since the ! 22: * last call to trapov(). ! 23: * ! 24: * Gary Klimowicz, April 17, 1981 ! 25: * Integerated with libF77: David Wasley, UCB, July 1981. ! 26: */ ! 27: ! 28: # include <stdio.h> ! 29: # include <sys/signal.h> ! 30: # include "opcodes.h" ! 31: # include "../libI77/fiodefs.h" ! 32: # define SIG_VAL void (*)() ! 33: ! 34: /* ! 35: * Potential operand values ! 36: */ ! 37: typedef union operand_types { ! 38: char o_byte; ! 39: short o_word; ! 40: long o_long; ! 41: float o_float; ! 42: long o_quad[2]; ! 43: double o_double; ! 44: } anyval; ! 45: ! 46: /* ! 47: * the fortran unit control table ! 48: */ ! 49: extern unit units[]; ! 50: ! 51: /* ! 52: * Fortran message table is in main ! 53: */ ! 54: struct msgtbl { ! 55: char *mesg; ! 56: int dummy; ! 57: }; ! 58: extern struct msgtbl act_fpe[]; ! 59: ! 60: anyval *get_operand_address(), *addr_of_reg(); ! 61: char *opcode_name(); ! 62: ! 63: /* ! 64: * trap type codes ! 65: */ ! 66: # define INT_OVF_T 1 ! 67: # define INT_DIV_T 2 ! 68: # define FLT_OVF_T 3 ! 69: # define FLT_DIV_T 4 ! 70: # define FLT_UND_T 5 ! 71: # define DEC_OVF_T 6 ! 72: # define SUB_RNG_T 7 ! 73: # define FLT_OVF_F 8 ! 74: # define FLT_DIV_F 9 ! 75: # define FLT_UND_F 10 ! 76: ! 77: # define RES_ADR_F 0 ! 78: # define RES_OPC_F 1 ! 79: # define RES_OPR_F 2 ! 80: ! 81: #ifdef vax ! 82: /* ! 83: * Operand modes ! 84: */ ! 85: # define LITERAL0 0x0 ! 86: # define LITERAL1 0x1 ! 87: # define LITERAL2 0x2 ! 88: # define LITERAL3 0x3 ! 89: # define INDEXED 0x4 ! 90: # define REGISTER 0x5 ! 91: # define REG_DEF 0x6 ! 92: # define AUTO_DEC 0x7 ! 93: # define AUTO_INC 0x8 ! 94: # define AUTO_INC_DEF 0x9 ! 95: # define BYTE_DISP 0xa ! 96: # define BYTE_DISP_DEF 0xb ! 97: # define WORD_DISP 0xc ! 98: # define WORD_DISP_DEF 0xd ! 99: # define LONG_DISP 0xe ! 100: # define LONG_DISP_DEF 0xf ! 101: ! 102: /* ! 103: * Operand value types ! 104: */ ! 105: # define F 1 ! 106: # define D 2 ! 107: # define IDUNNO 3 ! 108: ! 109: # define PC 0xf ! 110: # define SP 0xe ! 111: # define FP 0xd ! 112: # define AP 0xc ! 113: ! 114: /* ! 115: * GLOBAL VARIABLES (we need a few) ! 116: * ! 117: * Actual program counter and locations of registers. ! 118: */ ! 119: static char *pc; ! 120: static int *regs0t6; ! 121: static int *regs7t11; ! 122: static int max_messages; ! 123: static int total_overflows; ! 124: static union { ! 125: long v_long[2]; ! 126: double v_double; ! 127: } retrn; ! 128: static sig_t sigill_default = (SIG_VAL)-1; ! 129: static sig_t sigfpe_default; ! 130: ! 131: /* ! 132: * This routine sets up the signal handler for the floating-point ! 133: * and reserved operand interrupts. ! 134: */ ! 135: ! 136: trapov_(count, rtnval) ! 137: int *count; ! 138: double *rtnval; ! 139: { ! 140: void got_overflow(), got_illegal_instruction(); ! 141: ! 142: sigfpe_default = signal(SIGFPE, got_overflow); ! 143: if (sigill_default == (SIG_VAL)-1) ! 144: sigill_default = signal(SIGILL, got_illegal_instruction); ! 145: total_overflows = 0; ! 146: max_messages = *count; ! 147: retrn.v_double = *rtnval; ! 148: } ! 149: ! 150: ! 151: ! 152: /* ! 153: * got_overflow - routine called when overflow occurs ! 154: * ! 155: * This routine just prints a message about the overflow. ! 156: * It is impossible to find the bad result at this point. ! 157: * Instead, we wait until we get the reserved operand exception ! 158: * when we try to use it. This raises the SIGILL signal. ! 159: */ ! 160: ! 161: /*ARGSUSED*/ ! 162: void ! 163: got_overflow(signo, codeword, myaddr, pc, ps) ! 164: char *myaddr, *pc; ! 165: { ! 166: int *sp, i; ! 167: FILE *ef; ! 168: ! 169: signal(SIGFPE, got_overflow); ! 170: ef = units[STDERR].ufd; ! 171: switch (codeword) { ! 172: case INT_OVF_T: ! 173: case INT_DIV_T: ! 174: case FLT_UND_T: ! 175: case DEC_OVF_T: ! 176: case SUB_RNG_T: ! 177: case FLT_OVF_F: ! 178: case FLT_DIV_F: ! 179: case FLT_UND_F: ! 180: if (sigfpe_default > (SIG_VAL)7) ! 181: (*sigfpe_default)(signo, codeword, myaddr, ! 182: pc, ps); ! 183: else ! 184: sigdie(signo, codeword, myaddr, pc, ps); ! 185: /* NOTREACHED */ ! 186: ! 187: case FLT_OVF_T: ! 188: case FLT_DIV_T: ! 189: if (++total_overflows <= max_messages) { ! 190: fprintf(ef, "trapov: %s", ! 191: act_fpe[codeword-1].mesg); ! 192: if (total_overflows == max_messages) ! 193: fprintf(ef, ": No more messages will be printed.\n"); ! 194: else ! 195: fputc('\n', ef); ! 196: } ! 197: return; ! 198: } ! 199: } ! 200: ! 201: int ! 202: ovcnt_() ! 203: { ! 204: return total_overflows; ! 205: } ! 206: ! 207: /* ! 208: * got_illegal_instruction - handle "illegal instruction" signals. ! 209: * ! 210: * This really deals only with reserved operand exceptions. ! 211: * Since there is no way to check this directly, we look at the ! 212: * opcode of the instruction we are executing to see if it is a ! 213: * floating-point operation (with floating-point operands, not ! 214: * just results). ! 215: * ! 216: * This is complicated by the fact that the registers that will ! 217: * eventually be restored are saved in two places. registers 7-11 ! 218: * are saved by this routine, and are in its call frame. (we have ! 219: * to take special care that these registers are specified in ! 220: * the procedure entry mask here.) ! 221: * Registers 0-6 are saved at interrupt time, and are at a offset ! 222: * -8 from the 'signo' parameter below. ! 223: * There is ane extremely inimate connection between the value of ! 224: * the entry mask set by the 'makefile' script, and the constants ! 225: * used in the register offset calculations below. ! 226: * Can someone think of a better way to do this? ! 227: */ ! 228: ! 229: /*ARGSUSED*/ ! 230: void ! 231: got_illegal_instruction(signo, codeword, myaddr, trap_pc, ps) ! 232: char *myaddr, *trap_pc; ! 233: { ! 234: int first_local[1]; /* must be first */ ! 235: int i, opcode, type, o_no, no_reserved; ! 236: anyval *opnd; ! 237: ! 238: regs7t11 = &first_local[0]; ! 239: regs0t6 = &signo - 8; ! 240: pc = trap_pc; ! 241: ! 242: opcode = fetch_byte() & 0xff; ! 243: no_reserved = 0; ! 244: if (codeword != RES_OPR_F || !is_floating_operation(opcode)) { ! 245: if (sigill_default > (SIG_VAL)7) { ! 246: (*sigill_default)(signo, codeword, myaddr, trap_pc, ps); ! 247: return; ! 248: } else ! 249: sigdie(signo, codeword, myaddr, trap_pc, ps); ! 250: /* NOTREACHED */ ! 251: } ! 252: ! 253: if (opcode == POLYD || opcode == POLYF) { ! 254: got_illegal_poly(opcode); ! 255: return; ! 256: } ! 257: ! 258: if (opcode == EMODD || opcode == EMODF) { ! 259: got_illegal_emod(opcode); ! 260: return; ! 261: } ! 262: ! 263: /* ! 264: * This opcode wasn't "unusual". ! 265: * Look at the operands to try and find a reserved operand. ! 266: */ ! 267: for (o_no = 1; o_no <= no_operands(opcode); ++o_no) { ! 268: type = operand_type(opcode, o_no); ! 269: if (type != F && type != D) { ! 270: advance_pc(type); ! 271: continue; ! 272: } ! 273: ! 274: /* F or D operand. Check it out */ ! 275: opnd = get_operand_address(type); ! 276: if (opnd == NULL) { ! 277: fprintf(units[STDERR].ufd, "Can't get operand address: 0x%x, %d\n", ! 278: pc, o_no); ! 279: f77_abort(); ! 280: } ! 281: if (type == F && opnd->o_long == 0x00008000) { ! 282: /* found one */ ! 283: opnd->o_long = retrn.v_long[0]; ! 284: ++no_reserved; ! 285: } else if (type == D && opnd->o_long == 0x00008000) { ! 286: /* found one here, too! */ ! 287: opnd->o_quad[0] = retrn.v_long[0]; ! 288: /* Fix next pointer */ ! 289: if (opnd == addr_of_reg(6)) opnd = addr_of_reg(7); ! 290: else opnd = (anyval *) ((char *) opnd + 4); ! 291: opnd->o_quad[0] = retrn.v_long[1]; ! 292: ++no_reserved; ! 293: } ! 294: ! 295: } ! 296: ! 297: if (no_reserved == 0) { ! 298: fprintf(units[STDERR].ufd, "Can't find any reserved operand!\n"); ! 299: f77_abort(); ! 300: } ! 301: } ! 302: /* ! 303: * is_floating_exception - was the operation code for a floating instruction? ! 304: */ ! 305: ! 306: is_floating_operation(opcode) ! 307: int opcode; ! 308: { ! 309: switch (opcode) { ! 310: case ACBD: case ACBF: case ADDD2: case ADDD3: ! 311: case ADDF2: case ADDF3: case CMPD: case CMPF: ! 312: case CVTDB: case CVTDF: case CVTDL: case CVTDW: ! 313: case CVTFB: case CVTFD: case CVTFL: case CVTFW: ! 314: case CVTRDL: case CVTRFL: case DIVD2: case DIVD3: ! 315: case DIVF2: case DIVF3: case EMODD: case EMODF: ! 316: case MNEGD: case MNEGF: case MOVD: case MOVF: ! 317: case MULD2: case MULD3: case MULF2: case MULF3: ! 318: case POLYD: case POLYF: case SUBD2: case SUBD3: ! 319: case SUBF2: case SUBF3: case TSTD: case TSTF: ! 320: return 1; ! 321: ! 322: default: ! 323: return 0; ! 324: } ! 325: } ! 326: /* ! 327: * got_illegal_poly - handle an illegal POLY[DF] instruction. ! 328: * ! 329: * We don't do anything here yet. ! 330: */ ! 331: ! 332: /*ARGSUSED*/ ! 333: got_illegal_poly(opcode) ! 334: { ! 335: fprintf(units[STDERR].ufd, "Can't do 'poly' instructions yet\n"); ! 336: f77_abort(); ! 337: } ! 338: ! 339: ! 340: ! 341: /* ! 342: * got_illegal_emod - handle illegal EMOD[DF] instruction. ! 343: * ! 344: * We don't do anything here yet. ! 345: */ ! 346: ! 347: /*ARGSUSED*/ ! 348: got_illegal_emod(opcode) ! 349: { ! 350: fprintf(units[STDERR].ufd, "Can't do 'emod' instructions yet\n"); ! 351: f77_abort(); ! 352: } ! 353: ! 354: ! 355: /* ! 356: * no_operands - determine the number of operands in this instruction. ! 357: * ! 358: */ ! 359: ! 360: no_operands(opcode) ! 361: { ! 362: switch (opcode) { ! 363: case ACBD: ! 364: case ACBF: ! 365: return 3; ! 366: ! 367: case MNEGD: ! 368: case MNEGF: ! 369: case MOVD: ! 370: case MOVF: ! 371: case TSTD: ! 372: case TSTF: ! 373: return 1; ! 374: ! 375: default: ! 376: return 2; ! 377: } ! 378: } ! 379: ! 380: ! 381: ! 382: /* ! 383: * operand_type - is the operand a D or an F? ! 384: * ! 385: * We are only descriminating between Floats and Doubles here. ! 386: * Other operands may be possible on exotic instructions. ! 387: */ ! 388: ! 389: /*ARGSUSED*/ ! 390: operand_type(opcode, no) ! 391: { ! 392: if (opcode >= 0x40 && opcode <= 0x56) return F; ! 393: if (opcode >= 0x60 && opcode <= 0x76) return D; ! 394: return IDUNNO; ! 395: } ! 396: ! 397: ! 398: ! 399: /* ! 400: * advance_pc - Advance the program counter past an operand. ! 401: * ! 402: * We just bump the pc by the appropriate values. ! 403: */ ! 404: ! 405: advance_pc(type) ! 406: { ! 407: register int mode, reg; ! 408: ! 409: mode = fetch_byte(); ! 410: reg = mode & 0xf; ! 411: mode = (mode >> 4) & 0xf; ! 412: switch (mode) { ! 413: case LITERAL0: ! 414: case LITERAL1: ! 415: case LITERAL2: ! 416: case LITERAL3: ! 417: return; ! 418: ! 419: case INDEXED: ! 420: advance_pc(type); ! 421: return; ! 422: ! 423: case REGISTER: ! 424: case REG_DEF: ! 425: case AUTO_DEC: ! 426: return; ! 427: ! 428: case AUTO_INC: ! 429: if (reg == PC) { ! 430: if (type == F) (void) fetch_long(); ! 431: else if (type == D) { ! 432: (void) fetch_long(); ! 433: (void) fetch_long(); ! 434: } else { ! 435: fprintf(units[STDERR].ufd, "Bad type %d in advance\n", ! 436: type); ! 437: f77_abort(); ! 438: } ! 439: } ! 440: return; ! 441: ! 442: case AUTO_INC_DEF: ! 443: if (reg == PC) (void) fetch_long(); ! 444: return; ! 445: ! 446: case BYTE_DISP: ! 447: case BYTE_DISP_DEF: ! 448: (void) fetch_byte(); ! 449: return; ! 450: ! 451: case WORD_DISP: ! 452: case WORD_DISP_DEF: ! 453: (void) fetch_word(); ! 454: return; ! 455: ! 456: case LONG_DISP: ! 457: case LONG_DISP_DEF: ! 458: (void) fetch_long(); ! 459: return; ! 460: ! 461: default: ! 462: fprintf(units[STDERR].ufd, "Bad mode 0x%x in op_length()\n", mode); ! 463: f77_abort(); ! 464: } ! 465: } ! 466: ! 467: ! 468: anyval * ! 469: get_operand_address(type) ! 470: { ! 471: register int mode, reg, base; ! 472: ! 473: mode = fetch_byte() & 0xff; ! 474: reg = mode & 0xf; ! 475: mode = (mode >> 4) & 0xf; ! 476: switch (mode) { ! 477: case LITERAL0: ! 478: case LITERAL1: ! 479: case LITERAL2: ! 480: case LITERAL3: ! 481: return NULL; ! 482: ! 483: case INDEXED: ! 484: base = (int) get_operand_address(type); ! 485: if (base == NULL) return NULL; ! 486: base += contents_of_reg(reg)*type_length(type); ! 487: return (anyval *) base; ! 488: ! 489: case REGISTER: ! 490: return addr_of_reg(reg); ! 491: ! 492: case REG_DEF: ! 493: return (anyval *) contents_of_reg(reg); ! 494: ! 495: case AUTO_DEC: ! 496: return (anyval *) (contents_of_reg(reg) ! 497: - type_length(type)); ! 498: ! 499: case AUTO_INC: ! 500: return (anyval *) contents_of_reg(reg); ! 501: ! 502: case AUTO_INC_DEF: ! 503: return (anyval *) * (long *) contents_of_reg(reg); ! 504: ! 505: case BYTE_DISP: ! 506: base = fetch_byte(); ! 507: base += contents_of_reg(reg); ! 508: return (anyval *) base; ! 509: ! 510: case BYTE_DISP_DEF: ! 511: base = fetch_byte(); ! 512: base += contents_of_reg(reg); ! 513: return (anyval *) * (long *) base; ! 514: ! 515: case WORD_DISP: ! 516: base = fetch_word(); ! 517: base += contents_of_reg(reg); ! 518: return (anyval *) base; ! 519: ! 520: case WORD_DISP_DEF: ! 521: base = fetch_word(); ! 522: base += contents_of_reg(reg); ! 523: return (anyval *) * (long *) base; ! 524: ! 525: case LONG_DISP: ! 526: base = fetch_long(); ! 527: base += contents_of_reg(reg); ! 528: return (anyval *) base; ! 529: ! 530: case LONG_DISP_DEF: ! 531: base = fetch_long(); ! 532: base += contents_of_reg(reg); ! 533: return (anyval *) * (long *) base; ! 534: ! 535: default: ! 536: fprintf(units[STDERR].ufd, "Bad mode 0x%x in get_addr()\n", mode); ! 537: f77_abort(); ! 538: } ! 539: return NULL; ! 540: } ! 541: ! 542: ! 543: ! 544: contents_of_reg(reg) ! 545: { ! 546: int value; ! 547: ! 548: if (reg == PC) value = (int) pc; ! 549: else if (reg == SP) value = (int) ®s0t6[6]; ! 550: else if (reg == FP) value = regs0t6[-2]; ! 551: else if (reg == AP) value = regs0t6[-3]; ! 552: else if (reg >= 0 && reg <= 6) value = regs0t6[reg]; ! 553: else if (reg >= 7 && reg <= 11) value = regs7t11[reg]; ! 554: else { ! 555: fprintf(units[STDERR].ufd, "Bad register 0x%x to contents_of()\n", reg); ! 556: f77_abort(); ! 557: value = -1; ! 558: } ! 559: return value; ! 560: } ! 561: ! 562: ! 563: anyval * ! 564: addr_of_reg(reg) ! 565: { ! 566: if (reg >= 0 && reg <= 6) { ! 567: return (anyval *) ®s0t6[reg]; ! 568: } ! 569: if (reg >= 7 && reg <= 11) { ! 570: return (anyval *) ®s7t11[reg]; ! 571: } ! 572: fprintf(units[STDERR].ufd, "Bad reg 0x%x to addr_of()\n", reg); ! 573: f77_abort(); ! 574: return NULL; ! 575: } ! 576: /* ! 577: * fetch_{byte, word, long} - extract values from the PROGRAM area. ! 578: * ! 579: * These routines are used in the operand decoding to extract various ! 580: * fields from where the program counter points. This is because the ! 581: * addressing on the Vax is dynamic: the program counter advances ! 582: * while we are grabbing operands, as well as when we pass instructions. ! 583: * This makes things a bit messy, but I can't help it. ! 584: */ ! 585: fetch_byte() ! 586: { ! 587: return *pc++; ! 588: } ! 589: ! 590: ! 591: ! 592: fetch_word() ! 593: { ! 594: int *old_pc; ! 595: ! 596: old_pc = (int *) pc; ! 597: pc += 2; ! 598: return *old_pc; ! 599: } ! 600: ! 601: ! 602: ! 603: fetch_long() ! 604: { ! 605: long *old_pc; ! 606: ! 607: old_pc = (long *) pc; ! 608: pc += 4; ! 609: return *old_pc; ! 610: } ! 611: ! 612: ! 613: type_length(type) ! 614: { ! 615: if (type == F) return 4; ! 616: if (type == D) return 8; ! 617: fprintf(units[STDERR].ufd, "Bad type 0x%x in type_length()\n", type); ! 618: f77_abort(); ! 619: return -1; ! 620: } ! 621: ! 622: ! 623: ! 624: char *opcode_name(opcode) ! 625: { ! 626: switch (opcode) { ! 627: case ACBD: return "ACBD"; ! 628: case ACBF: return "ACBF"; ! 629: case ADDD2: return "ADDD2"; ! 630: case ADDD3: return "ADDD3"; ! 631: case ADDF2: return "ADDF2"; ! 632: case ADDF3: return "ADDF3"; ! 633: case CMPD: return "CMPD"; ! 634: case CMPF: return "CMPF"; ! 635: case CVTDB: return "CVTDB"; ! 636: case CVTDF: return "CVTDF"; ! 637: case CVTDL: return "CVTDL"; ! 638: case CVTDW: return "CVTDW"; ! 639: case CVTFB: return "CVTFB"; ! 640: case CVTFD: return "CVTFD"; ! 641: case CVTFL: return "CVTFL"; ! 642: case CVTFW: return "CVTFW"; ! 643: case CVTRDL: return "CVTRDL"; ! 644: case CVTRFL: return "CVTRFL"; ! 645: case DIVD2: return "DIVD2"; ! 646: case DIVD3: return "DIVD3"; ! 647: case DIVF2: return "DIVF2"; ! 648: case DIVF3: return "DIVF3"; ! 649: case EMODD: return "EMODD"; ! 650: case EMODF: return "EMODF"; ! 651: case MNEGD: return "MNEGD"; ! 652: case MNEGF: return "MNEGF"; ! 653: case MOVD: return "MOVD"; ! 654: case MOVF: return "MOVF"; ! 655: case MULD2: return "MULD2"; ! 656: case MULD3: return "MULD3"; ! 657: case MULF2: return "MULF2"; ! 658: case MULF3: return "MULF3"; ! 659: case POLYD: return "POLYD"; ! 660: case POLYF: return "POLYF"; ! 661: case SUBD2: return "SUBD2"; ! 662: case SUBD3: return "SUBD3"; ! 663: case SUBF2: return "SUBF2"; ! 664: case SUBF3: return "SUBF3"; ! 665: case TSTD: return "TSTD"; ! 666: case TSTF: return "TSTF"; ! 667: } ! 668: } ! 669: #endif vax ! 670: ! 671: #ifdef tahoe ! 672: /* ! 673: * NO RESERVED OPERAND EXCEPTION ON RESULT OF FP OVERFLOW ON TAHOE. ! 674: * JUST PRINT THE OVERFLOW MESSAGE. RESULT IS 0 (zero). ! 675: */ ! 676: ! 677: /* ! 678: * GLOBAL VARIABLES (we need a few) ! 679: * ! 680: * Actual program counter and locations of registers. ! 681: */ ! 682: static char *pc; ! 683: static int *regs0t1; ! 684: static int *regs2t12; ! 685: static int max_messages; ! 686: static int total_overflows; ! 687: static union { ! 688: long v_long[2]; ! 689: double v_double; ! 690: } retrn; ! 691: static sig_t sigill_default = (SIG_VAL)-1; ! 692: static sig_t sigfpe_default; ! 693: ! 694: ! 695: /* ! 696: * This routine sets up the signal handler for the floating-point ! 697: * and reserved operand interrupts. ! 698: */ ! 699: ! 700: trapov_(count, rtnval) ! 701: int *count; ! 702: double *rtnval; ! 703: { ! 704: void got_overflow(); ! 705: ! 706: sigfpe_default = signal(SIGFPE, got_overflow); ! 707: total_overflows = 0; ! 708: max_messages = *count; ! 709: retrn.v_double = *rtnval; ! 710: } ! 711: ! 712: ! 713: ! 714: /* ! 715: * got_overflow - routine called when overflow occurs ! 716: * ! 717: * This routine just prints a message about the overflow. ! 718: * It is impossible to find the bad result at this point. ! 719: * NEXT 2 LINES DON'T HOLD FOR TAHOE ! ! 720: * Instead, we wait until we get the reserved operand exception ! 721: * when we try to use it. This raises the SIGILL signal. ! 722: */ ! 723: ! 724: /*ARGSUSED*/ ! 725: void ! 726: got_overflow(signo, codeword, sc) ! 727: int signo, codeword; ! 728: struct sigcontext *sc; ! 729: { ! 730: int *sp, i; ! 731: FILE *ef; ! 732: ! 733: signal(SIGFPE, got_overflow); ! 734: ef = units[STDERR].ufd; ! 735: switch (codeword) { ! 736: case INT_OVF_T: ! 737: case INT_DIV_T: ! 738: case FLT_UND_T: ! 739: case FLT_DIV_T: ! 740: if (sigfpe_default > (SIG_VAL)7) ! 741: (*sigfpe_default)(signo, codeword, sc); ! 742: else ! 743: sigdie(signo, codeword, sc); ! 744: /* NOTREACHED */ ! 745: ! 746: case FLT_OVF_T: ! 747: if (++total_overflows <= max_messages) { ! 748: fprintf(ef, "trapov: %s", ! 749: act_fpe[codeword-1].mesg); ! 750: fprintf(ef, ": Current PC = %X", sc->sc_pc); ! 751: if (total_overflows == max_messages) ! 752: fprintf(ef, ": No more messages will be printed.\n"); ! 753: else ! 754: fputc('\n', ef); ! 755: } ! 756: return; ! 757: } ! 758: } ! 759: int ! 760: ovcnt_() ! 761: { ! 762: return total_overflows; ! 763: } ! 764: #endif tahoe
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.