Annotation of coherent/b/kernel/emulator/errors.c, revision 1.1

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: 

unix.superglobalmegacorp.com

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