|
|
1.1 ! root 1: /*---------------------------------------------------------------------------+ ! 2: | errors.c | ! 3: | | ! 4: | The error handling functions for wm-FPU-emu | ! 5: | | ! 6: | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | ! 7: | Australia. E-mail [email protected] | ! 8: | | ! 9: | | ! 10: +---------------------------------------------------------------------------*/ ! 11: ! 12: /*---------------------------------------------------------------------------+ ! 13: | Note: | ! 14: | The file contains code which accesses user memory. | ! 15: | Emulator static data may change when user memory is accessed, due to | ! 16: | other processes using the emulator while swapping is in progress. | ! 17: +---------------------------------------------------------------------------*/ ! 18: ! 19: #include <linux/signal.h> ! 20: ! 21: #include <asm/segment.h> ! 22: ! 23: #include "fpu_system.h" ! 24: #include "exception.h" ! 25: #include "fpu_emu.h" ! 26: #include "status_w.h" ! 27: #include "control_w.h" ! 28: #include "reg_constant.h" ! 29: #include "version.h" ! 30: ! 31: /* */ ! 32: #undef PRINT_MESSAGES ! 33: /* */ ! 34: ! 35: void Un_impl(void) ! 36: { ! 37: unsigned char byte1, FPU_modrm; ! 38: ! 39: RE_ENTRANT_CHECK_OFF ! 40: byte1 = get_fs_byte((unsigned char *) FPU_ORIG_EIP); ! 41: FPU_modrm = get_fs_byte(1 + (unsigned char *) FPU_ORIG_EIP); ! 42: ! 43: printf("Unimplemented FPU Opcode at eip=%p : %02x ", ! 44: FPU_ORIG_EIP, byte1); ! 45: ! 46: if (FPU_modrm >= 0300) ! 47: printf("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); ! 48: else ! 49: printf("/%d\n", (FPU_modrm >> 3) & 7); ! 50: RE_ENTRANT_CHECK_ON ! 51: ! 52: EXCEPTION(EX_Invalid); ! 53: ! 54: } ! 55: ! 56: ! 57: ! 58: ! 59: void emu_printall() ! 60: { ! 61: int i; ! 62: static char *tag_desc[] = { "Valid", "Zero", "ERROR", "ERROR", ! 63: "DeNorm", "Inf", "NaN", "Empty" }; ! 64: unsigned char byte1, FPU_modrm; ! 65: ! 66: RE_ENTRANT_CHECK_OFF ! 67: byte1 = get_fs_byte((unsigned char *) FPU_ORIG_EIP); ! 68: FPU_modrm = get_fs_byte(1 + (unsigned char *) FPU_ORIG_EIP); ! 69: ! 70: #ifdef DEBUGGING ! 71: if ( status_word & SW_B ) printf("SW: backward compatibility (=ES)\n"); ! 72: if ( status_word & SW_C3 ) printf("SW: condition bit 3\n"); ! 73: if ( status_word & SW_C2 ) printf("SW: condition bit 2\n"); ! 74: if ( status_word & SW_C1 ) printf("SW: condition bit 1\n"); ! 75: if ( status_word & SW_C0 ) printf("SW: condition bit 0\n"); ! 76: if ( status_word & SW_ES ) printf("SW: exception summary\n"); ! 77: if ( status_word & SW_SF ) printf("SW: stack fault\n"); ! 78: if ( status_word & SW_PE ) printf("SW: loss of precision\n"); ! 79: if ( status_word & SW_UE ) printf("SW: underflow\n"); ! 80: if ( status_word & SW_OE ) printf("SW: overflow\n"); ! 81: if ( status_word & SW_ZE ) printf("SW: divide by zero\n"); ! 82: if ( status_word & SW_DE ) printf("SW: denormalized operand\n"); ! 83: if ( status_word & SW_IE ) printf("SW: invalid operation\n"); ! 84: #endif DEBUGGING ! 85: ! 86: status_word = status_word & ~SW_TOP; ! 87: status_word |= (top&7) << SW_TOPS; ! 88: ! 89: printf("At %p: %02x ", FPU_ORIG_EIP, byte1); ! 90: if (FPU_modrm >= 0300) ! 91: printf("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); ! 92: else ! 93: printf("/%d, mod=%d rm=%d\n", ! 94: (FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7); ! 95: ! 96: printf(" SW: b=%d st=%d es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n", ! 97: status_word & 0x8000 ? 1 : 0, /* busy */ ! 98: (status_word & 0x3800) >> 11, /* stack top pointer */ ! 99: status_word & 0x80 ? 1 : 0, /* Error summary status */ ! 100: status_word & 0x40 ? 1 : 0, /* Stack flag */ ! 101: status_word & SW_C3?1:0, status_word & SW_C2?1:0, /* cc */ ! 102: status_word & SW_C1?1:0, status_word & SW_C0?1:0, /* cc */ ! 103: status_word & SW_PE?1:0, status_word & SW_UE?1:0, /* exception fl */ ! 104: status_word & SW_OE?1:0, status_word & SW_ZE?1:0, /* exception fl */ ! 105: status_word & SW_DE?1:0, status_word & SW_IE?1:0); /* exception fl */ ! 106: ! 107: printf(" CW: ic=%d rc=%d%d pc=%d%d iem=%d ef=%d%d%d%d%d%d\n", ! 108: control_word & 0x1000 ? 1 : 0, ! 109: (control_word & 0x800) >> 11, (control_word & 0x400) >> 10, ! 110: (control_word & 0x200) >> 9, (control_word & 0x100) >> 8, ! 111: control_word & 0x80 ? 1 : 0, ! 112: control_word & SW_PE?1:0, control_word & SW_UE?1:0, /* exception */ ! 113: control_word & SW_OE?1:0, control_word & SW_ZE?1:0, /* exception */ ! 114: control_word & SW_DE?1:0, control_word & SW_IE?1:0); /* exception */ ! 115: ! 116: for ( i = 0; i < 8; i++ ) ! 117: { ! 118: FPU_REG *r = &st(i); ! 119: switch (r->tag) ! 120: { ! 121: case TW_Empty: ! 122: continue; ! 123: break; ! 124: case TW_Zero: ! 125: printf("st(%d) %c .0000 0000 0000 0000 ", ! 126: i, r->sign ? '-' : '+'); ! 127: break; ! 128: case TW_Valid: ! 129: case TW_NaN: ! 130: case TW_Denormal: ! 131: case TW_Infinity: ! 132: printf("st(%d) %c .%04x %04x %04x %04x e%+-6d ", i, ! 133: r->sign ? '-' : '+', ! 134: (long)(r->sigh >> 16), ! 135: (long)(r->sigh & 0xFFFF), ! 136: (long)(r->sigl >> 16), ! 137: (long)(r->sigl & 0xFFFF), ! 138: r->exp - EXP_BIAS + 1); ! 139: break; ! 140: default: ! 141: printf("Whoops! Error in errors.c "); ! 142: break; ! 143: } ! 144: printf("%s\n", tag_desc[(int) (unsigned) r->tag]); ! 145: } ! 146: ! 147: printf("[data] %c .%04x %04x %04x %04x e%+-6d ", ! 148: FPU_loaded_data.sign ? '-' : '+', ! 149: (long)(FPU_loaded_data.sigh >> 16), ! 150: (long)(FPU_loaded_data.sigh & 0xFFFF), ! 151: (long)(FPU_loaded_data.sigl >> 16), ! 152: (long)(FPU_loaded_data.sigl & 0xFFFF), ! 153: FPU_loaded_data.exp - EXP_BIAS + 1); ! 154: printf("%s\n", tag_desc[(int) (unsigned) FPU_loaded_data.tag]); ! 155: RE_ENTRANT_CHECK_ON ! 156: ! 157: } ! 158: ! 159: static struct { ! 160: int type; ! 161: char *name; ! 162: } exception_names[] = { ! 163: { EX_StackOver, "stack overflow" }, ! 164: { EX_StackUnder, "stack underflow" }, ! 165: { EX_Precision, "loss of precision" }, ! 166: { EX_Underflow, "underflow" }, ! 167: { EX_Overflow, "overflow" }, ! 168: { EX_ZeroDiv, "divide by zero" }, ! 169: { EX_Denormal, "denormalized operand" }, ! 170: { EX_Invalid, "invalid operation" }, ! 171: { EX_INTERNAL, "INTERNAL BUG in "FPU_VERSION }, ! 172: { 0, NULL } ! 173: }; ! 174: ! 175: /* ! 176: EX_INTERNAL is always given with a code which indicates where the ! 177: error was detected. ! 178: ! 179: Internal error types: ! 180: 0x14 in e14.c ! 181: 0x1nn in a *.c file: ! 182: 0x101 in reg_add_sub.c ! 183: 0x102 in reg_mul.c ! 184: 0x103 in poly_sin.c ! 185: 0x104 in poly_tan.c ! 186: 0x105 in reg_mul.c ! 187: 0x106 in reg_mov.c ! 188: 0x107 in fpu_trig.c ! 189: 0x108 in reg_compare.c ! 190: 0x109 in reg_compare.c ! 191: 0x110 in reg_add_sub.c ! 192: 0x111 in interface.c ! 193: 0x112 in fpu_trig.c ! 194: 0x113 in reg_add_sub.c ! 195: 0x114 in reg_ld_str.c ! 196: 0x115 in fpu_trig.c ! 197: 0x116 in fpu_trig.c ! 198: 0x117 in fpu_trig.c ! 199: 0x118 in fpu_trig.c ! 200: 0x119 in fpu_trig.c ! 201: 0x120 in poly_atan.c ! 202: 0x121 in reg_compare.c ! 203: 0x122 in reg_compare.c ! 204: 0x123 in reg_compare.c ! 205: 0x2nn in an *.s file: ! 206: 0x201 in reg_u_add.S ! 207: 0x202 in reg_u_div.S ! 208: 0x203 in reg_u_div.S ! 209: 0x204 in reg_u_div.S ! 210: 0x205 in reg_u_mul.S ! 211: 0x206 in reg_u_sub.S ! 212: 0x207 in wm_sqrt.S ! 213: 0x208 in reg_div.S ! 214: 0x209 in reg_u_sub.S ! 215: 0x210 in reg_u_sub.S ! 216: 0x211 in reg_u_sub.S ! 217: 0x212 in reg_u_sub.S ! 218: */ ! 219: ! 220: void exception(int n) ! 221: { ! 222: int i, int_type; ! 223: ! 224: int_type = 0; ! 225: if ( n & EX_INTERNAL ) ! 226: { ! 227: int_type = n - EX_INTERNAL; ! 228: n = EX_INTERNAL; ! 229: /* Set lots of exception bits! */ ! 230: status_word |= (0x3f | EX_ErrorSummary | FPU_BUSY); ! 231: } ! 232: else ! 233: { ! 234: /* Set the corresponding exception bit */ ! 235: status_word |= (n | EX_ErrorSummary | FPU_BUSY); ! 236: if (n == EX_StackUnder) /* Stack underflow */ ! 237: /* This bit distinguishes over- from underflow */ ! 238: status_word &= ~SW_C1; ! 239: } ! 240: ! 241: RE_ENTRANT_CHECK_OFF ! 242: if ( (~control_word & n & CW_EXM) || (n == EX_INTERNAL) ) ! 243: { ! 244: #ifdef PRINT_MESSAGES ! 245: /* My message from the sponsor */ ! 246: printf(FPU_VERSION" "__DATE__" (C) W. Metzenthen.\r\n"); ! 247: #endif PRINT_MESSAGES ! 248: ! 249: /* Get a name string for error reporting */ ! 250: for (i=0; exception_names[i].type; i++) ! 251: if (exception_names[i].type == n) ! 252: break; ! 253: ! 254: if (exception_names[i].type) ! 255: { ! 256: #ifdef PRINT_MESSAGES ! 257: printf("FP Exception: %s!\n", exception_names[i].name); ! 258: #endif PRINT_MESSAGES ! 259: } ! 260: else ! 261: printf("FP emulator: Unknown Exception: 0x%04x!\n", n); ! 262: ! 263: if ( n == EX_INTERNAL ) ! 264: { ! 265: printf("FP emulator: Internal error type 0x%04x\n", int_type); ! 266: emu_printall(); ! 267: } ! 268: #ifdef PRINT_MESSAGES ! 269: else ! 270: emu_printall(); ! 271: #endif PRINT_MESSAGES ! 272: emSendsig(SIGFPE, emCurrent, 1); ! 273: } ! 274: RE_ENTRANT_CHECK_ON ! 275: ! 276: #ifdef __DEBUG__ ! 277: math_abort(FPU_info,SIGFPE); ! 278: #endif __DEBUG__ ! 279: ! 280: /* Cause the look-ahead mechanism to terminate */ ! 281: FPU_lookahead = 0; ! 282: } ! 283: ! 284: ! 285: /* Real operation attempted on two operands, one a NaN */ ! 286: void real_2op_NaN(FPU_REG *a, FPU_REG *b, FPU_REG *dest) ! 287: { ! 288: FPU_REG *x; ! 289: ! 290: x = a; ! 291: if (a->tag == TW_NaN) ! 292: { ! 293: if (b->tag == TW_NaN) ! 294: { ! 295: /* find the "larger" */ ! 296: if ( *(long long *)&(a->sigl) < *(long long *)&(b->sigl) ) ! 297: x = b; ! 298: } ! 299: /* else return the quiet version of the NaN in a */ ! 300: } ! 301: else if (b->tag == TW_NaN) ! 302: { ! 303: x = b; ! 304: } ! 305: #ifdef PARANOID ! 306: else ! 307: { ! 308: EXCEPTION(EX_INTERNAL|0x113); ! 309: x = &CONST_QNaN; ! 310: } ! 311: #endif PARANOID ! 312: ! 313: if ( control_word & EX_Invalid ) ! 314: { ! 315: /* The masked response */ ! 316: reg_move(x, dest); ! 317: /* ensure a Quiet NaN */ ! 318: dest->sigh |= 0x40000000; ! 319: } ! 320: ! 321: EXCEPTION(EX_Invalid); ! 322: ! 323: return; ! 324: } ! 325: ! 326: /* Invalid arith operation on valid registers */ ! 327: void arith_invalid(FPU_REG *dest) ! 328: { ! 329: ! 330: if ( control_word & EX_Invalid ) ! 331: { ! 332: /* The masked response */ ! 333: reg_move(&CONST_QNaN, dest); ! 334: } ! 335: ! 336: EXCEPTION(EX_Invalid); ! 337: ! 338: return; ! 339: ! 340: } ! 341: ! 342: ! 343: /* Divide a finite number by zero */ ! 344: void divide_by_zero(int sign, FPU_REG *dest) ! 345: { ! 346: ! 347: if ( control_word & EX_ZeroDiv ) ! 348: { ! 349: /* The masked response */ ! 350: reg_move(&CONST_INF, dest); ! 351: dest->sign = (unsigned char)sign; ! 352: } ! 353: ! 354: EXCEPTION(EX_ZeroDiv); ! 355: ! 356: return; ! 357: ! 358: } ! 359: ! 360: ! 361: void arith_overflow(FPU_REG *dest) ! 362: { ! 363: ! 364: if ( control_word & EX_Overflow ) ! 365: { ! 366: char sign; ! 367: /* The masked response */ ! 368: sign = dest->sign; ! 369: reg_move(&CONST_INF, dest); ! 370: dest->sign = sign; ! 371: } ! 372: else ! 373: { ! 374: /* Subtract the magic number from the exponent */ ! 375: dest->exp -= (3 * (1 << 13)); ! 376: } ! 377: ! 378: EXCEPTION(EX_Overflow); ! 379: ! 380: return; ! 381: ! 382: } ! 383: ! 384: ! 385: void arith_underflow(FPU_REG *dest) ! 386: { ! 387: ! 388: if ( control_word & EX_Underflow ) ! 389: { ! 390: /* The masked response */ ! 391: if ( dest->exp <= EXP_UNDER - 63 ) ! 392: reg_move(&CONST_Z, dest); ! 393: } ! 394: else ! 395: { ! 396: /* Add the magic number to the exponent */ ! 397: dest->exp += (3 * (1 << 13)); ! 398: } ! 399: ! 400: EXCEPTION(EX_Underflow); ! 401: ! 402: return; ! 403: } ! 404: ! 405: ! 406: void stack_overflow(void) ! 407: { ! 408: ! 409: if ( control_word & EX_Invalid ) ! 410: { ! 411: /* The masked response */ ! 412: top--; ! 413: reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0)); ! 414: } ! 415: ! 416: EXCEPTION(EX_StackOver); ! 417: ! 418: return; ! 419: ! 420: } ! 421: ! 422: ! 423: void stack_underflow(void) ! 424: { ! 425: ! 426: if ( control_word & EX_Invalid ) ! 427: { ! 428: /* The masked response */ ! 429: reg_move(&CONST_QNaN, FPU_st0_ptr); ! 430: } ! 431: ! 432: EXCEPTION(EX_StackUnder); ! 433: ! 434: return; ! 435: ! 436: } ! 437:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.