Annotation of coherent/b/kernel/emulator/errors.c, revision 1.1.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.