root/kernel/FPU-emu/reg_ld_str.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. reg_load_extended
  2. reg_load_double
  3. reg_load_single
  4. reg_load_int64
  5. reg_load_int32
  6. reg_load_int16
  7. reg_load_bcd
  8. reg_store_extended
  9. reg_store_double
  10. reg_store_single
  11. reg_store_int64
  12. reg_store_int32
  13. reg_store_int16
  14. reg_store_bcd
  15. round_to_int
  16. fldenv
  17. frstor
  18. fstenv
  19. fsave

   1 /*---------------------------------------------------------------------------+
   2  |  reg_ld_str.c                                                             |
   3  |                                                                           |
   4  | All of the functions which transfer data between user memory and FPU_REGs.|
   5  |                                                                           |
   6  | Copyright (C) 1992,1993                                                   |
   7  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
   8  |                       Australia.  E-mail apm233m@vaxc.cc.monash.edu.au    |
   9  |                                                                           |
  10  |                                                                           |
  11  +---------------------------------------------------------------------------*/
  12 
  13 /*---------------------------------------------------------------------------+
  14  | Note:                                                                     |
  15  |    The file contains code which accesses user memory.                     |
  16  |    Emulator static data may change when user memory is accessed, due to   |
  17  |    other processes using the emulator while swapping is in progress.      |
  18  +---------------------------------------------------------------------------*/
  19 
  20 #include <asm/segment.h>
  21 
  22 #include "fpu_system.h"
  23 #include "exception.h"
  24 #include "reg_constant.h"
  25 #include "fpu_emu.h"
  26 #include "control_w.h"
  27 
  28 
  29 #define EXTENDED_Emax 0x3fff     /* largest valid exponent */
  30 #define EXTENDED_Ebias 0x3fff
  31 #define EXTENDED_Emin (-0x3ffe)  /* smallest valid exponent */
  32 
  33 #define DOUBLE_Emax 1023         /* largest valid exponent */
  34 #define DOUBLE_Ebias 1023
  35 #define DOUBLE_Emin (-1022)      /* smallest valid exponent */
  36 
  37 #define SINGLE_Emax 127          /* largest valid exponent */
  38 #define SINGLE_Ebias 127
  39 #define SINGLE_Emin (-126)       /* smallest valid exponent */
  40 
  41 
  42 FPU_REG FPU_loaded_data;
  43 
  44 
  45 /* Get a long double from user memory */
  46 void reg_load_extended(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48   long double *s = (long double *)FPU_data_address;
  49   unsigned long sigl, sigh, exp;
  50 
  51   RE_ENTRANT_CHECK_OFF
  52   /* Use temporary variables here because FPU_loaded data is
  53      static and hence re-entrancy problems can arise */
  54   sigl = get_fs_long((unsigned long *) s);
  55   sigh = get_fs_long(1 + (unsigned long *) s);
  56   exp = get_fs_word(4 + (unsigned short *) s);
  57   RE_ENTRANT_CHECK_ON
  58 
  59   FPU_loaded_data.sigl = sigl;
  60   FPU_loaded_data.sigh = sigh;
  61   FPU_loaded_data.exp = exp;
  62 
  63   if (FPU_loaded_data.exp & 0x8000)
  64     FPU_loaded_data.sign = SIGN_NEG;
  65   else
  66     FPU_loaded_data.sign = SIGN_POS;
  67   if ( (FPU_loaded_data.exp &= 0x7fff) == 0 )
  68     {
  69       if ( !(FPU_loaded_data.sigl | FPU_loaded_data.sigh) )
  70         {
  71           FPU_loaded_data.tag = TW_Zero;
  72           return;
  73         }
  74       /* The number is de-normal */
  75       /* The default behaviour will take care of this */
  76     }
  77   else if ( FPU_loaded_data.exp == 0x7fff )
  78     {
  79       FPU_loaded_data.exp = EXTENDED_Emax;
  80       if ( (FPU_loaded_data.sigh == 0x80000000)
  81           && (FPU_loaded_data.sigl == 0) )
  82         {
  83           FPU_loaded_data.tag = TW_Infinity;
  84           return;
  85         }
  86       if ( !(FPU_loaded_data.sigh & 0x80000000) )
  87         {
  88           /* Unsupported data type */
  89           EXCEPTION(EX_Invalid);
  90           FPU_loaded_data.tag = TW_NaN;
  91           return;
  92         }
  93       FPU_loaded_data.tag = TW_NaN;
  94       return;
  95     }
  96   FPU_loaded_data.exp = (FPU_loaded_data.exp & 0x7fff) - EXTENDED_Ebias
  97     + EXP_BIAS;
  98   FPU_loaded_data.tag = TW_Valid;
  99 
 100   normalize(&FPU_loaded_data);
 101 }
 102 
 103 
 104 /* Get a double from user memory */
 105 void reg_load_double(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 106 {
 107   double *dfloat = (double *)FPU_data_address;
 108   int exp;
 109   unsigned m64, l64;
 110 
 111   RE_ENTRANT_CHECK_OFF
 112   m64 = get_fs_long(1 + (unsigned long *) dfloat);
 113   l64 = get_fs_long((unsigned long *) dfloat);
 114   RE_ENTRANT_CHECK_ON
 115 
 116   if (m64 & 0x80000000)
 117     FPU_loaded_data.sign = SIGN_NEG;
 118   else
 119     FPU_loaded_data.sign = SIGN_POS;
 120   exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias;
 121   m64 &= 0xfffff;
 122   if (exp > DOUBLE_Emax)
 123     {
 124       /* Infinity or NaN */
 125       if ((m64 == 0) && (l64 == 0))
 126         {
 127           /* +- infinity */
 128           FPU_loaded_data.exp = EXTENDED_Emax;
 129           FPU_loaded_data.tag = TW_Infinity;
 130           return;
 131         }
 132       else
 133         {
 134           /* Must be a signaling or quiet NaN */
 135           FPU_loaded_data.exp = EXTENDED_Emax;
 136           FPU_loaded_data.tag = TW_NaN;
 137           FPU_loaded_data.sigh = (m64 << 11) | 0x80000000;
 138           FPU_loaded_data.sigh |= l64 >> 21;
 139           FPU_loaded_data.sigl = l64 << 11;
 140           return;
 141         }
 142     }
 143   else if ( exp < DOUBLE_Emin )
 144     {
 145       /* Zero or de-normal */
 146       if ((m64 == 0) && (l64 == 0))
 147         {
 148           /* Zero */
 149           int c = FPU_loaded_data.sign;
 150           reg_move(&CONST_Z, &FPU_loaded_data);
 151           FPU_loaded_data.sign = c;
 152           return;
 153         }
 154       else
 155         {
 156           /* De-normal */
 157           FPU_loaded_data.exp = DOUBLE_Emin + EXP_BIAS;
 158           FPU_loaded_data.tag = TW_Valid;
 159           FPU_loaded_data.sigh = m64 << 11;
 160           FPU_loaded_data.sigh |= l64 >> 21;
 161           FPU_loaded_data.sigl = l64 << 11;
 162           normalize(&FPU_loaded_data);
 163           return;
 164         }
 165     }
 166   else
 167     {
 168       FPU_loaded_data.exp = exp + EXP_BIAS;
 169       FPU_loaded_data.tag = TW_Valid;
 170       FPU_loaded_data.sigh = (m64 << 11) | 0x80000000;
 171       FPU_loaded_data.sigh |= l64 >> 21;
 172       FPU_loaded_data.sigl = l64 << 11;
 173 
 174       return;
 175     }
 176 }
 177 
 178 
 179 /* Get a float from user memory */
 180 void reg_load_single(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 181 {
 182   float *single = (float *)FPU_data_address;
 183   unsigned m32;
 184   int exp;
 185 
 186   RE_ENTRANT_CHECK_OFF
 187   m32 = get_fs_long((unsigned long *) single);
 188   RE_ENTRANT_CHECK_ON
 189 
 190   if (m32 & 0x80000000)
 191     FPU_loaded_data.sign = SIGN_NEG;
 192   else
 193     FPU_loaded_data.sign = SIGN_POS;
 194   if (!(m32 & 0x7fffffff))
 195     {
 196       /* Zero */
 197       int c = FPU_loaded_data.sign;
 198       reg_move(&CONST_Z, &FPU_loaded_data);
 199       FPU_loaded_data.sign = c;
 200       return;
 201     }
 202   exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias;
 203   m32 = (m32 & 0x7fffff) << 8;
 204   if ( exp < SINGLE_Emin )
 205     {
 206       /* De-normals */
 207       FPU_loaded_data.exp = SINGLE_Emin + EXP_BIAS;
 208       FPU_loaded_data.tag = TW_Valid;
 209       FPU_loaded_data.sigh = m32;
 210       FPU_loaded_data.sigl = 0;
 211       normalize(&FPU_loaded_data);
 212       return;
 213     }
 214   else if ( exp > SINGLE_Emax )
 215     {
 216     /* Infinity or NaN */
 217       if ( m32 == 0 )
 218         {
 219           /* +- infinity */
 220           FPU_loaded_data.exp = EXTENDED_Emax;
 221           FPU_loaded_data.tag = TW_Infinity;
 222           return;
 223         }
 224       else
 225         {
 226           /* Must be a signaling or quiet NaN */
 227           FPU_loaded_data.exp = EXTENDED_Emax;
 228           FPU_loaded_data.tag = TW_NaN;
 229           FPU_loaded_data.sigh = m32 | 0x80000000;
 230           FPU_loaded_data.sigl = 0;
 231           return;
 232         }
 233     }
 234   else
 235     {
 236       FPU_loaded_data.exp = exp + EXP_BIAS;
 237       FPU_loaded_data.sigh = m32 | 0x80000000;
 238       FPU_loaded_data.sigl = 0;
 239       FPU_loaded_data.tag = TW_Valid;
 240     }
 241 }
 242 
 243 
 244 /* Get a long long from user memory */
 245 void reg_load_int64(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247   long long *_s = (long long *)FPU_data_address;
 248   int e;
 249   long long s;
 250 
 251   RE_ENTRANT_CHECK_OFF
 252   ((unsigned long *)&s)[0] = get_fs_long((unsigned long *) _s);
 253   ((unsigned long *)&s)[1] = get_fs_long(1 + (unsigned long *) _s);
 254   RE_ENTRANT_CHECK_ON
 255 
 256   if (s == 0)
 257     { reg_move(&CONST_Z, &FPU_loaded_data); return; }
 258 
 259   if (s > 0)
 260     FPU_loaded_data.sign = SIGN_POS;
 261   else
 262   {
 263     s = -s;
 264     FPU_loaded_data.sign = SIGN_NEG;
 265   }
 266 
 267   e = EXP_BIAS + 63;
 268   *((long long *)&FPU_loaded_data.sigl) = s;
 269   FPU_loaded_data.exp = e;
 270   FPU_loaded_data.tag = TW_Valid;
 271   normalize(&FPU_loaded_data);
 272 }
 273 
 274 
 275 /* Get a long from user memory */
 276 void reg_load_int32(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 277 {
 278   long *_s = (long *)FPU_data_address;
 279   long s;
 280   int e;
 281 
 282   RE_ENTRANT_CHECK_OFF
 283   s = (long)get_fs_long((unsigned long *) _s);
 284   RE_ENTRANT_CHECK_ON
 285 
 286   if (s == 0)
 287     { reg_move(&CONST_Z, &FPU_loaded_data); return; }
 288 
 289   if (s > 0)
 290     FPU_loaded_data.sign = SIGN_POS;
 291   else
 292   {
 293     s = -s;
 294     FPU_loaded_data.sign = SIGN_NEG;
 295   }
 296 
 297   e = EXP_BIAS + 31;
 298   FPU_loaded_data.sigh = s;
 299   FPU_loaded_data.sigl = 0;
 300   FPU_loaded_data.exp = e;
 301   FPU_loaded_data.tag = TW_Valid;
 302   normalize(&FPU_loaded_data);
 303 }
 304 
 305 
 306 /* Get a short from user memory */
 307 void reg_load_int16(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 308 {
 309   short *_s = (short *)FPU_data_address;
 310   int s, e;
 311 
 312   RE_ENTRANT_CHECK_OFF
 313   s = (int)get_fs_word((unsigned short *) _s);
 314   RE_ENTRANT_CHECK_ON
 315 
 316   if (s == 0)
 317     { reg_move(&CONST_Z, &FPU_loaded_data); return; }
 318 
 319   if (s > 0)
 320     FPU_loaded_data.sign = SIGN_POS;
 321   else
 322   {
 323     s = -s;
 324     FPU_loaded_data.sign = SIGN_NEG;
 325   }
 326 
 327   e = EXP_BIAS + 15;
 328   FPU_loaded_data.sigh = s << 16;
 329 
 330   FPU_loaded_data.sigl = 0;
 331   FPU_loaded_data.exp = e;
 332   FPU_loaded_data.tag = TW_Valid;
 333   normalize(&FPU_loaded_data);
 334 }
 335 
 336 
 337 /* Get a packed bcd array from user memory */
 338 void reg_load_bcd(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 339 {
 340   char *s = (char *)FPU_data_address;
 341   int pos;
 342   unsigned char bcd;
 343   long long l=0;
 344 
 345   for ( pos = 8; pos >= 0; pos--)
 346     {
 347       l *= 10;
 348       RE_ENTRANT_CHECK_OFF
 349       bcd = (unsigned char)get_fs_byte((unsigned char *) s+pos);
 350       RE_ENTRANT_CHECK_ON
 351       l += bcd >> 4;
 352       l *= 10;
 353       l += bcd & 0x0f;
 354     }
 355   
 356   /* Finish all access to user memory before putting stuff into
 357      the static FPU_loaded_data */
 358   RE_ENTRANT_CHECK_OFF
 359   FPU_loaded_data.sign =
 360     ((unsigned char)get_fs_byte((unsigned char *) s+9)) & 0x80 ?
 361       SIGN_NEG : SIGN_POS;
 362   RE_ENTRANT_CHECK_ON
 363 
 364   if (l == 0)
 365     {
 366       char sign = FPU_loaded_data.sign;
 367       reg_move(&CONST_Z, &FPU_loaded_data);
 368       FPU_loaded_data.sign = sign;
 369     }
 370   else
 371     {
 372       *((long long *)&FPU_loaded_data.sigl) = l;
 373       FPU_loaded_data.exp = EXP_BIAS + 63;
 374       FPU_loaded_data.tag = TW_Valid;
 375       normalize(&FPU_loaded_data);
 376     }
 377 }
 378 
 379 /*===========================================================================*/
 380 
 381 /* Put a long double into user memory */
 382 int reg_store_extended(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 383 {
 384   long double *d = (long double *)FPU_data_address;
 385   long e = FPU_st0_ptr->exp - EXP_BIAS + EXTENDED_Ebias;
 386   unsigned short sign = FPU_st0_ptr->sign*0x8000;
 387   unsigned long ls, ms;
 388 
 389 
 390   if ( FPU_st0_tag == TW_Valid )
 391     {
 392       if ( e >= 0x7fff )
 393         {
 394           EXCEPTION(EX_Overflow);  /* Overflow */
 395           /* This is a special case: see sec 16.2.5.1 of the 80486 book */
 396           if ( control_word & EX_Overflow )
 397             {
 398               /* Overflow to infinity */
 399               ls = 0;
 400               ms = 0x80000000;
 401               e = 0x7fff;
 402             }
 403           else
 404             return 0;
 405         }
 406       else if ( e <= 0 )
 407         {
 408           if ( e == 0 )
 409             {
 410               EXCEPTION(EX_Denormal);  /* Pseudo de-normal */
 411               ls = FPU_st0_ptr->sigl;
 412               ms = FPU_st0_ptr->sigh;
 413             }
 414           else if ( e > -64 )
 415             {
 416               /* Make a de-normal */
 417               FPU_REG tmp;
 418               EXCEPTION(EX_Denormal);  /* De-normal */
 419               reg_move(FPU_st0_ptr, &tmp);
 420               tmp.exp += -EXTENDED_Emin + 64;  /* largest exp to be 63 */
 421               round_to_int(&tmp);
 422               e = 0;
 423               ls = tmp.sigl;
 424               ms = tmp.sigh;
 425             }
 426           else
 427             {
 428               EXCEPTION(EX_Underflow);  /* Underflow */
 429               /* This is a special case: see sec 16.2.5.1 of the 80486 book */
 430               if ( control_word & EX_Underflow )
 431                 {
 432                   /* Underflow to zero */
 433                   ls = 0;
 434                   ms = 0;
 435                   e = 0;
 436                 }
 437               else
 438                 return 0;
 439             }
 440         }
 441       else
 442         {
 443           ls = FPU_st0_ptr->sigl;
 444           ms = FPU_st0_ptr->sigh;
 445         }
 446     }
 447   else if ( FPU_st0_tag == TW_Zero )
 448     {
 449       ls = ms = 0;
 450       e = 0;
 451     }
 452   else if ( FPU_st0_tag == TW_Infinity )
 453     {
 454       ls = 0;
 455       ms = 0x80000000;
 456       e = 0x7fff;
 457     }
 458   else if ( FPU_st0_tag == TW_NaN )
 459     {
 460       ls = FPU_st0_ptr->sigl;
 461       ms = FPU_st0_ptr->sigh;
 462       e = 0x7fff;
 463     }
 464   else if ( FPU_st0_tag == TW_Empty )
 465     {
 466       /* Empty register (stack underflow) */
 467       EXCEPTION(EX_StackUnder);
 468       if ( control_word & EX_Invalid )
 469         {
 470           /* The masked response */
 471           /* Put out the QNaN indefinite */
 472           ls = 0;
 473           ms = 0xc0000000;
 474           e = 0xffff;
 475         }
 476       else
 477         return 0;
 478     }
 479   else
 480     {
 481       /* We don't use TW_Denormal yet ... perhaps never! */
 482       EXCEPTION(EX_Invalid);
 483       /* Store a NaN */
 484       e = 0x7fff;
 485       ls = 1;
 486       ms = 0x80000000;
 487     }
 488   RE_ENTRANT_CHECK_OFF
 489   verify_area(VERIFY_WRITE,d,10);
 490   put_fs_long(ls, (unsigned long *) d);
 491   put_fs_long(ms, 1 + (unsigned long *) d);
 492   put_fs_word((unsigned short)e | sign, 4 + (short *) d);
 493   RE_ENTRANT_CHECK_ON
 494 
 495   return 1;
 496 
 497 }
 498 
 499 
 500 /* Put a double into user memory */
 501 int reg_store_double(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 502 {
 503   double *dfloat = (double *)FPU_data_address;
 504   unsigned long l[2];
 505 
 506   if (FPU_st0_tag == TW_Valid)
 507     {
 508       int exp;
 509       FPU_REG tmp;
 510 
 511       reg_move(FPU_st0_ptr, &tmp);
 512 
 513       if ( tmp.sigl & 0x000007ff )
 514         {
 515           unsigned long increment = 0;  /* avoid gcc warnings */
 516           
 517           switch (control_word & CW_RC)
 518             {
 519             case RC_RND:
 520               /* Rounding can get a little messy.. */
 521               increment = ((tmp.sigl & 0x7ff) > 0x400) |      /* nearest */
 522                 ((tmp.sigl & 0xc00) == 0xc00);                /* odd -> even */
 523               break;
 524             case RC_DOWN:   /* towards -infinity */
 525               increment = (tmp.sign == SIGN_POS) ? 0 : tmp.sigl & 0x7ff;
 526               break;
 527             case RC_UP:     /* towards +infinity */
 528               increment = (tmp.sign == SIGN_POS) ? tmp.sigl & 0x7ff : 0;
 529               break;
 530             case RC_CHOP:
 531               increment = 0;
 532               break;
 533             }
 534           
 535           /* Truncate the mantissa */
 536           tmp.sigl &= 0xfffff800;
 537 
 538           if ( increment )
 539             {
 540               if ( tmp.sigl >= 0xfffff800 )
 541                 {
 542                   /* the sigl part overflows */
 543                   if ( tmp.sigh == 0xffffffff )
 544                     {
 545                       /* The sigh part overflows */
 546                       tmp.sigh = 0x80000000;
 547                       tmp.exp++;
 548                       if (tmp.exp >= EXP_OVER)
 549                         goto overflow;
 550                     }
 551                   else
 552                     {
 553                       tmp.sigh ++;
 554                     }
 555                   tmp.sigl = 0x00000000;
 556                 }
 557               else
 558                 {
 559                   /* We only need to increment sigl */
 560                   tmp.sigl += 0x00000800;
 561                 }
 562             }
 563         }
 564 
 565       l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21);
 566       l[1] = ((tmp.sigh >> 11) & 0xfffff);
 567       exp = tmp.exp - EXP_BIAS;
 568 
 569       if ( exp > DOUBLE_Emax )
 570         {
 571         overflow:
 572           EXCEPTION(EX_Overflow);
 573           /* This is a special case: see sec 16.2.5.1 of the 80486 book */
 574           if ( control_word & EX_Overflow )
 575             {
 576               /* Overflow to infinity */
 577               l[0] = 0x00000000;        /* Set to */
 578               l[1] = 0x7ff00000;        /* + INF */
 579             }
 580           else
 581             return 0;
 582         }
 583       else if ( exp < DOUBLE_Emin )
 584         {
 585           if ( exp > DOUBLE_Emin-53 )
 586             {
 587               /* Make a de-normal */
 588               FPU_REG tmp;
 589               EXCEPTION(EX_Denormal);
 590               reg_move(FPU_st0_ptr, &tmp);
 591               tmp.exp += -DOUBLE_Emin + 52;  /* largest exp to be 51 */
 592               round_to_int(&tmp);
 593               l[0] = tmp.sigl;
 594               l[1] = tmp.sigh;
 595             }
 596           else
 597             {
 598               EXCEPTION(EX_Underflow);
 599               /* This is a special case: see sec 16.2.5.1 of the 80486 book */
 600               if ( control_word & EX_Underflow )
 601                 {
 602                   /* Underflow to zero */
 603                   l[0] = l[1] = 0;
 604                 }
 605               else
 606                 return 0;
 607             }
 608         }
 609       else
 610         {
 611           /* Add the exponent */
 612           l[1] |= (((exp+DOUBLE_Ebias) & 0x7ff) << 20);
 613         }
 614     }
 615   else if (FPU_st0_tag == TW_Zero)
 616     {
 617       /* Number is zero */
 618       l[0] = l[1] = 0;
 619     }
 620   else if (FPU_st0_tag == TW_Infinity)
 621     {
 622       l[0] = 0;
 623       l[1] = 0x7ff00000;
 624     }
 625   else if (FPU_st0_tag == TW_NaN)
 626     {
 627       /* See if we can get a valid NaN from the FPU_REG */
 628       l[0] = (FPU_st0_ptr->sigl >> 11) | (FPU_st0_ptr->sigh << 21);
 629       l[1] = ((FPU_st0_ptr->sigh >> 11) & 0xfffff);
 630       if ( !(l[0] | l[1]) )
 631         {
 632           /* This case does not seem to be handled by the 80486 specs */
 633           EXCEPTION(EX_Invalid);
 634           /* Make the quiet NaN "real indefinite" */
 635           goto put_indefinite;
 636         }
 637       l[1] |= 0x7ff00000;
 638     }
 639   else if ( FPU_st0_tag == TW_Empty )
 640     {
 641       /* Empty register (stack underflow) */
 642       EXCEPTION(EX_StackUnder);
 643       if ( control_word & EX_Invalid )
 644         {
 645           /* The masked response */
 646           /* Put out the QNaN indefinite */
 647 put_indefinite:
 648           RE_ENTRANT_CHECK_OFF
 649           verify_area(VERIFY_WRITE,(void *)dfloat,8);
 650           put_fs_long(0, (unsigned long *) dfloat);
 651           put_fs_long(0xfff80000, 1 + (unsigned long *) dfloat);
 652           RE_ENTRANT_CHECK_ON
 653           return 1;
 654         }
 655       else
 656         return 0;
 657     }
 658   else if (FPU_st0_tag == TW_Denormal)
 659     {
 660       /* Extended real -> double real will always underflow */
 661       l[0] = l[1] = 0;
 662       EXCEPTION(EX_Underflow);
 663     }
 664   if (FPU_st0_ptr->sign)
 665     l[1] |= 0x80000000;
 666 
 667   RE_ENTRANT_CHECK_OFF
 668   verify_area(VERIFY_WRITE,(void *)dfloat,8);
 669   put_fs_long(l[0], (unsigned long *)dfloat);
 670   put_fs_long(l[1], 1 + (unsigned long *)dfloat);
 671   RE_ENTRANT_CHECK_ON
 672 
 673   return 1;
 674 }
 675 
 676 
 677 /* Put a float into user memory */
 678 int reg_store_single(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 679 {
 680   float *single = (float *)FPU_data_address;
 681   long templ;
 682 
 683   if (FPU_st0_tag == TW_Valid)
 684     {
 685       int exp;
 686       FPU_REG tmp;
 687 
 688       reg_move(FPU_st0_ptr, &tmp);
 689 
 690       if ( tmp.sigl | (tmp.sigh & 0x000000ff) )
 691         {
 692           unsigned long increment = 0;          /* avoid gcc warnings */
 693           unsigned long sigh = tmp.sigh;
 694           unsigned long sigl = tmp.sigl;
 695           
 696           switch (control_word & CW_RC)
 697             {
 698             case RC_RND:
 699               increment = ((sigh & 0xff) > 0x80)           /* more than half */
 700                 || (((sigh & 0xff) == 0x80) && sigl)       /* more than half */
 701                   || ((sigh & 0x180) == 0x180);            /* round to even */
 702               break;
 703             case RC_DOWN:   /* towards -infinity */
 704               increment = (tmp.sign == SIGN_POS) ? 0 : (sigl | (sigh & 0xff));
 705               break;
 706             case RC_UP:     /* towards +infinity */
 707               increment = (tmp.sign == SIGN_POS) ? (sigl | (sigh & 0xff)) : 0;
 708               break;
 709             case RC_CHOP:
 710               increment = 0;
 711               break;
 712             }
 713           
 714           /* Truncate part of the mantissa */
 715           tmp.sigl = 0;
 716           
 717           if (increment)
 718             {
 719               if ( sigh >= 0xffffff00 )
 720                 {
 721                   /* The sigh part overflows */
 722                   tmp.sigh = 0x80000000;
 723                   tmp.exp++;
 724                   if (tmp.exp >= EXP_OVER)
 725                     goto overflow;
 726                 }
 727               else
 728                 {
 729                   tmp.sigh &= 0xffffff00;
 730                   tmp.sigh += 0x100;
 731                 }
 732             }
 733           else
 734             tmp.sigh &= 0xffffff00;  /* Finish the truncation */
 735         }
 736 
 737       templ = (tmp.sigh >> 8) & 0x007fffff;
 738       exp = tmp.exp - EXP_BIAS;
 739 
 740       if ( exp > SINGLE_Emax )
 741         {
 742         overflow:
 743           EXCEPTION(EX_Overflow);
 744           /* This is a special case: see sec 16.2.5.1 of the 80486 book */
 745           if ( control_word & EX_Overflow )
 746             {
 747               /* Overflow to infinity */
 748               templ = 0x7f800000;
 749             }
 750           else
 751             return 0;
 752         }
 753       else if ( exp < SINGLE_Emin )
 754         {
 755           if ( exp > SINGLE_Emin-24 )
 756             {
 757               /* Make a de-normal */
 758               FPU_REG tmp;
 759               EXCEPTION(EX_Denormal);
 760               reg_move(FPU_st0_ptr, &tmp);
 761               tmp.exp += -SINGLE_Emin + 23;  /* largest exp to be 22 */
 762               round_to_int(&tmp);
 763               templ = tmp.sigl;
 764             }
 765           else
 766             {
 767               EXCEPTION(EX_Underflow);
 768               /* This is a special case: see sec 16.2.5.1 of the 80486 book */
 769               if ( control_word & EX_Underflow )
 770                 {
 771                   /* Underflow to zero */
 772                   templ = 0;
 773                 }
 774               else
 775                 return 0;
 776             }
 777         }
 778       else
 779         templ |= ((exp+SINGLE_Ebias) & 0xff) << 23;
 780     }
 781   else if (FPU_st0_tag == TW_Zero)
 782     {
 783       templ = 0;
 784     }
 785   else if (FPU_st0_tag == TW_Infinity)
 786     {
 787       templ = 0x7f800000;
 788     }
 789   else if (FPU_st0_tag == TW_NaN)
 790     {
 791       /* See if we can get a valid NaN from the FPU_REG */
 792       templ = FPU_st0_ptr->sigh >> 8;
 793       if ( !(templ & 0x3fffff) )
 794         {
 795           /* This case does not seem to be handled by the 80486 specs */
 796           EXCEPTION(EX_Invalid);
 797           /* Make the quiet NaN "real indefinite" */
 798           goto put_indefinite;
 799         }
 800       templ |= 0x7f800000;
 801     }
 802   else if ( FPU_st0_tag == TW_Empty )
 803     {
 804       /* Empty register (stack underflow) */
 805       EXCEPTION(EX_StackUnder);
 806       if ( control_word & EX_Invalid )
 807         {
 808           /* The masked response */
 809           /* Put out the QNaN indefinite */
 810 put_indefinite:
 811           RE_ENTRANT_CHECK_OFF
 812           verify_area(VERIFY_WRITE,(void *)single,4);
 813           put_fs_long(0xffc00000, (unsigned long *) single);
 814           RE_ENTRANT_CHECK_ON
 815           return 1;
 816         }
 817       else
 818         return 0;
 819     }
 820   else if (FPU_st0_tag == TW_Denormal)
 821     {
 822       /* Extended real -> real will always underflow */
 823       templ = 0;
 824       EXCEPTION(EX_Underflow);
 825     }
 826 #ifdef PARANOID
 827   else
 828     {
 829       EXCEPTION(EX_INTERNAL|0x106);
 830       return 0;
 831     }
 832 #endif
 833   if (FPU_st0_ptr->sign)
 834     templ |= 0x80000000;
 835 
 836   RE_ENTRANT_CHECK_OFF
 837   verify_area(VERIFY_WRITE,(void *)single,4);
 838   put_fs_long(templ,(unsigned long *) single);
 839   RE_ENTRANT_CHECK_ON
 840 
 841   return 1;
 842 }
 843 
 844 
 845 /* Put a long long into user memory */
 846 int reg_store_int64(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 847 {
 848   long long *d = (long long *)FPU_data_address;
 849   FPU_REG t;
 850   long long tll;
 851 
 852   if ( FPU_st0_tag == TW_Empty )
 853     {
 854       /* Empty register (stack underflow) */
 855       EXCEPTION(EX_StackUnder);
 856       if ( control_word & EX_Invalid )
 857         {
 858           /* The masked response */
 859           /* Put out the QNaN indefinite */
 860           goto put_indefinite;
 861         }
 862       else
 863         return 0;
 864     }
 865 
 866   reg_move(FPU_st0_ptr, &t);
 867   round_to_int(&t);
 868   ((long *)&tll)[0] = t.sigl;
 869   ((long *)&tll)[1] = t.sigh;
 870   if ( (t.sigh & 0x80000000) &&
 871       !((t.sigh == 0x80000000) && (t.sigl == 0) && (t.sign == SIGN_NEG)) )
 872     {
 873       EXCEPTION(EX_Invalid);
 874       /* This is a special case: see sec 16.2.5.1 of the 80486 book */
 875       if ( control_word & EX_Invalid )
 876         {
 877           /* Produce "indefinite" */
 878 put_indefinite:
 879           ((long *)&tll)[1] = 0x80000000;
 880           ((long *)&tll)[0] = 0;
 881         }
 882       else
 883         return 0;
 884     }
 885   else if ( t.sign )
 886     tll = - tll;
 887 
 888   RE_ENTRANT_CHECK_OFF
 889   verify_area(VERIFY_WRITE,(void *)d,8);
 890   put_fs_long(((long *)&tll)[0],(unsigned long *) d);
 891   put_fs_long(((long *)&tll)[1],1 + (unsigned long *) d);
 892   RE_ENTRANT_CHECK_ON
 893 
 894   return 1;
 895 }
 896 
 897 
 898 /* Put a long into user memory */
 899 int reg_store_int32(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 900 {
 901   long *d = (long *)FPU_data_address;
 902   FPU_REG t;
 903 
 904   if ( FPU_st0_tag == TW_Empty )
 905     {
 906       /* Empty register (stack underflow) */
 907       EXCEPTION(EX_StackUnder);
 908       if ( control_word & EX_Invalid )
 909         {
 910           /* The masked response */
 911           /* Put out the QNaN indefinite */
 912           RE_ENTRANT_CHECK_OFF
 913           verify_area(VERIFY_WRITE,d,4);
 914           put_fs_long(0x80000000, (unsigned long *) d);
 915           RE_ENTRANT_CHECK_ON
 916           return 1;
 917         }
 918       else
 919         return 0;
 920     }
 921 
 922   reg_move(FPU_st0_ptr, &t);
 923   round_to_int(&t);
 924   if (t.sigh ||
 925       ((t.sigl & 0x80000000) &&
 926        !((t.sigl == 0x80000000) && (t.sign == SIGN_NEG))) )
 927     {
 928       EXCEPTION(EX_Invalid);
 929       /* This is a special case: see sec 16.2.5.1 of the 80486 book */
 930       if ( control_word & EX_Invalid )
 931         {
 932           /* Produce "indefinite" */
 933           t.sigl = 0x80000000;
 934         }
 935       else
 936         return 0;
 937     }
 938   else if ( t.sign )
 939     t.sigl = -(long)t.sigl;
 940 
 941   RE_ENTRANT_CHECK_OFF
 942   verify_area(VERIFY_WRITE,d,4);
 943   put_fs_long(t.sigl, (unsigned long *) d);
 944   RE_ENTRANT_CHECK_ON
 945 
 946   return 1;
 947 }
 948 
 949 
 950 /* Put a short into user memory */
 951 int reg_store_int16(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 952 {
 953   short *d = (short *)FPU_data_address;
 954   FPU_REG t;
 955   short ts;
 956 
 957   if ( FPU_st0_tag == TW_Empty )
 958     {
 959       /* Empty register (stack underflow) */
 960       EXCEPTION(EX_StackUnder);
 961       if ( control_word & EX_Invalid )
 962         {
 963           /* The masked response */
 964           /* Put out the QNaN indefinite */
 965           RE_ENTRANT_CHECK_OFF
 966           verify_area(VERIFY_WRITE,d,2);
 967           put_fs_word(0x8000, (unsigned short *) d);
 968           RE_ENTRANT_CHECK_ON
 969           return 1;
 970         }
 971       else
 972         return 0;
 973     }
 974 
 975   reg_move(FPU_st0_ptr, &t);
 976   round_to_int(&t);
 977   if (t.sigh ||
 978       ((t.sigl & 0xffff8000) &&
 979        !((t.sigl == 0x8000) && (t.sign == SIGN_NEG))) )
 980     {
 981       EXCEPTION(EX_Invalid);
 982       /* This is a special case: see sec 16.2.5.1 of the 80486 book */
 983       if ( control_word & EX_Invalid )
 984         {
 985           /* Produce "indefinite" */
 986           ts = 0x8000;
 987         }
 988       else
 989         return 0;
 990     }
 991   else if ( t.sign )
 992     t.sigl = -t.sigl;
 993 
 994   RE_ENTRANT_CHECK_OFF
 995   verify_area(VERIFY_WRITE,d,2);
 996   put_fs_word((short)t.sigl,(short *) d);
 997   RE_ENTRANT_CHECK_ON
 998 
 999   return 1;
1000 }
1001 
1002 
1003 /* Put a packed bcd array into user memory */
1004 int reg_store_bcd(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1005 {
1006   char *d = (char *)FPU_data_address;
1007   FPU_REG t;
1008   long long ll;
1009   unsigned char b;
1010   int i;
1011   unsigned char sign = (FPU_st0_ptr->sign == SIGN_NEG) ? 0x80 : 0;
1012 
1013   if ( FPU_st0_tag == TW_Empty )
1014     {
1015       /* Empty register (stack underflow) */
1016       EXCEPTION(EX_StackUnder);
1017       if ( control_word & EX_Invalid )
1018         {
1019           /* The masked response */
1020           /* Put out the QNaN indefinite */
1021           goto put_indefinite;
1022         }
1023       else
1024         return 0;
1025     }
1026 
1027   reg_move(FPU_st0_ptr, &t);
1028   round_to_int(&t);
1029   ll = *(long long *)(&t.sigl);
1030 
1031   /* Check for overflow, by comparing with 999999999999999999 decimal. */
1032   if ( (t.sigh > 0x0de0b6b3) ||
1033       ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff)) )
1034     {
1035       EXCEPTION(EX_Invalid);
1036       /* This is a special case: see sec 16.2.5.1 of the 80486 book */
1037       if ( control_word & EX_Invalid )
1038         {
1039 put_indefinite:
1040           /* Produce "indefinite" */
1041           RE_ENTRANT_CHECK_OFF
1042           verify_area(VERIFY_WRITE,d,10);
1043           put_fs_byte(0xff,(unsigned char *) d+7);
1044           put_fs_byte(0xff,(unsigned char *) d+8);
1045           put_fs_byte(0xff,(unsigned char *) d+9);
1046           RE_ENTRANT_CHECK_ON
1047           return 1;
1048         }
1049       else
1050         return 0;
1051     }
1052 
1053   verify_area(VERIFY_WRITE,d,10);
1054   for ( i = 0; i < 9; i++)
1055     {
1056       b = div_small(&ll, 10);
1057       b |= (div_small(&ll, 10)) << 4;
1058       RE_ENTRANT_CHECK_OFF
1059       put_fs_byte(b,(unsigned char *) d+i);
1060       RE_ENTRANT_CHECK_ON
1061     }
1062   RE_ENTRANT_CHECK_OFF
1063   put_fs_byte(sign,(unsigned char *) d+9);
1064   RE_ENTRANT_CHECK_ON
1065 
1066   return 1;
1067 }
1068 
1069 /*===========================================================================*/
1070 
1071 /* r gets mangled such that sig is int, sign: 
1072    it is NOT normalized*/
1073 /* Overflow is signalled by a non-zero return value (in eax).
1074    In the case of overflow, the returned significand always has the
1075    the largest possible value */
1076 /* The value returned in eax is never actually needed :-) */
1077 int round_to_int(FPU_REG *r)
     /* [previous][next][first][last][top][bottom][index][help] */
1078 {
1079   char     very_big;
1080   unsigned eax;
1081 
1082   if (r->tag == TW_Zero)
1083     {
1084       /* Make sure that zero is returned */
1085       *(long long *)&r->sigl = 0;
1086       return 0;        /* o.k. */
1087     }
1088   
1089   if (r->exp > EXP_BIAS + 63)
1090     {
1091       r->sigl = r->sigh = ~0;      /* The largest representable number */
1092       return 1;        /* overflow */
1093     }
1094 
1095   eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp);
1096   very_big = !(~(r->sigh) | ~(r->sigl));  /* test for 0xfff...fff */
1097 #define half_or_more    (eax & 0x80000000)
1098 #define frac_part       (eax)
1099 #define more_than_half  ((eax & 0x80000001) == 0x80000001)
1100   switch (control_word & CW_RC)
1101     {
1102     case RC_RND:
1103       if ( more_than_half                       /* nearest */
1104           || (half_or_more && (r->sigl & 1)) )  /* odd -> even */
1105         {
1106           if ( very_big ) return 1;        /* overflow */
1107           (*(long long *)(&r->sigl)) ++;
1108         }
1109       break;
1110     case RC_DOWN:
1111       if (frac_part && r->sign)
1112         {
1113           if ( very_big ) return 1;        /* overflow */
1114           (*(long long *)(&r->sigl)) ++;
1115         }
1116       break;
1117     case RC_UP:
1118       if (frac_part && !r->sign)
1119         {
1120           if ( very_big ) return 1;        /* overflow */
1121           (*(long long *)(&r->sigl)) ++;
1122         }
1123       break;
1124     case RC_CHOP:
1125       break;
1126     }
1127 
1128   return 0;           /* o.k. */
1129 }
1130 
1131 /*===========================================================================*/
1132 
1133 char *fldenv(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1134 {
1135   char *s = (char *)FPU_data_address;
1136   unsigned short tag_word = 0;
1137   unsigned char tag;
1138   int i;
1139 
1140   RE_ENTRANT_CHECK_OFF
1141   control_word = get_fs_word((unsigned short *) s);
1142   status_word = get_fs_word((unsigned short *) (s+4));
1143   tag_word = get_fs_word((unsigned short *) (s+8));
1144   ip_offset = get_fs_long((unsigned long *) (s+0x0c));
1145   cs_selector = get_fs_long((unsigned long *) (s+0x10));
1146   data_operand_offset = get_fs_long((unsigned long *) (s+0x14));
1147   operand_selector = get_fs_long((unsigned long *) (s+0x18));
1148   RE_ENTRANT_CHECK_ON
1149 
1150 
1151   for ( i = 7; i >= 0; i-- )
1152     {
1153       tag = tag_word & 3;
1154       tag_word <<= 2;
1155 
1156       switch ( tag )
1157         {
1158         case 0:
1159           regs[i].tag = TW_Valid;
1160           break;
1161         case 1:
1162           regs[i].tag = TW_Zero;
1163           break;
1164         case 2:
1165           regs[i].tag = TW_NaN;
1166           break;
1167         case 3:
1168           regs[i].tag = TW_Empty;
1169           break;
1170         }
1171     }
1172 
1173   FPU_data_address = (void *)data_operand_offset;  /* We want no net effect */
1174   FPU_entry_eip = ip_offset;               /* We want no net effect */
1175 
1176   return s + 0x1c;
1177 }
1178 
1179 
1180 void frstor(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1181 {
1182   int i;
1183   unsigned char tag;
1184   FPU_REG *s = (FPU_REG *)fldenv();
1185 
1186   for ( i = 0; i < 8; i++ )
1187     {
1188       /* load each register */
1189       FPU_data_address = (void *)&(s[i]);
1190       reg_load_extended();
1191       tag = regs[i].tag;
1192       reg_move(&FPU_loaded_data, &regs[i]);
1193       if ( tag == TW_NaN )
1194         {
1195           unsigned char t = regs[i].tag;
1196           if ( (t == TW_Valid) || (t == TW_Zero) )
1197             regs[i].tag = TW_NaN;
1198         }
1199       else
1200         regs[i].tag = tag;
1201     }
1202 
1203   FPU_data_address = (void *)data_operand_offset;  /* We want no net effect */
1204 }
1205 
1206 
1207 char *fstenv(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1208 {
1209   char *d = (char *)FPU_data_address;
1210   unsigned short tag_word = 0;
1211   unsigned char tag;
1212   int i;
1213 
1214   verify_area(VERIFY_WRITE,d,28);
1215 
1216   for ( i = 7; i >= 0; i-- )
1217     {
1218       switch ( tag = regs[i].tag )
1219         {
1220         case TW_Denormal:
1221         case TW_Infinity:
1222         case TW_NaN:
1223           tag = 2;
1224           break;
1225         case TW_Empty:
1226           tag = 3;
1227           break;
1228           /* TW_Valid and TW_Zero already have the correct value */
1229         }
1230       tag_word <<= 2;
1231       tag_word |= tag;
1232     }
1233 
1234   /* This is not what should be done ... but saves overheads. */
1235   *(unsigned short *)&cs_selector = FPU_CS;
1236   *(unsigned short *)&operand_selector = FPU_DS;
1237 
1238   RE_ENTRANT_CHECK_OFF
1239   put_fs_word(control_word, (unsigned short *) d);
1240   put_fs_word(status_word, (unsigned short *) (d+4));
1241   put_fs_word(tag_word, (unsigned short *) (d+8));
1242   put_fs_long(ip_offset, (unsigned long *) (d+0x0c));
1243   put_fs_long(cs_selector, (unsigned long *) (d+0x10));
1244   put_fs_long(data_operand_offset, (unsigned long *) (d+0x14));
1245   put_fs_long(operand_selector, (unsigned long *) (d+0x18));
1246   RE_ENTRANT_CHECK_ON
1247 
1248   return d + 0x1c;
1249 }
1250 
1251 
1252 void fsave(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1253 {
1254   char *d;
1255   FPU_REG tmp, *rp;
1256   int i;
1257   short e;
1258 
1259   d = fstenv();
1260   verify_area(VERIFY_WRITE,d,80);
1261   for ( i = 0; i < 8; i++ )
1262     {
1263       /* store each register */
1264       rp = &regs[i];
1265 
1266       e = rp->exp - EXP_BIAS + EXTENDED_Ebias;
1267 
1268       if ( rp->tag == TW_Valid )
1269         {
1270           if ( e >= 0x7fff )
1271             {
1272               /* Overflow to infinity */
1273               RE_ENTRANT_CHECK_OFF
1274               put_fs_long(0, (unsigned long *) (d+i*10+2));
1275               put_fs_long(0x80000000, (unsigned long *) (d+i*10+6));
1276               RE_ENTRANT_CHECK_ON
1277               e = 0x7fff;
1278             }
1279           else if ( e <= 0 )
1280             {
1281               if ( e == 0 )
1282                 {
1283                   /* Pseudo de-normal */
1284                   RE_ENTRANT_CHECK_OFF
1285                   put_fs_long(rp->sigl, (unsigned long *) (d+i*10+2));
1286                   put_fs_long(rp->sigh, (unsigned long *) (d+i*10+6));
1287                   RE_ENTRANT_CHECK_ON
1288                 }
1289               else if ( e > -64 )
1290                 {
1291                   /* Make a de-normal */
1292                   reg_move(rp, &tmp);
1293                   tmp.exp += -EXTENDED_Emin + 64;  /* largest exp to be 63 */
1294                   round_to_int(&tmp);
1295                   e = 0;
1296                   RE_ENTRANT_CHECK_OFF
1297                   put_fs_long(tmp.sigl, (unsigned long *) (d+i*10+2));
1298                   put_fs_long(tmp.sigh, (unsigned long *) (d+i*10+6));
1299                   RE_ENTRANT_CHECK_ON
1300                 }
1301               else
1302                 {
1303                   /* Underflow to zero */
1304                   RE_ENTRANT_CHECK_OFF
1305                   put_fs_long(0, (unsigned long *) (d+i*10+2));
1306                   put_fs_long(0, (unsigned long *) (d+i*10+6));
1307                   RE_ENTRANT_CHECK_ON
1308                   e = 0;
1309                 }
1310             }
1311           else
1312             {
1313               RE_ENTRANT_CHECK_OFF
1314               put_fs_long(rp->sigl, (unsigned long *) (d+i*10+2));
1315               put_fs_long(rp->sigh, (unsigned long *) (d+i*10+6));
1316               RE_ENTRANT_CHECK_ON
1317             }
1318         }
1319       else if ( rp->tag == TW_Zero )
1320         {
1321           RE_ENTRANT_CHECK_OFF
1322           put_fs_long(0, (unsigned long *) (d+i*10+2));
1323           put_fs_long(0, (unsigned long *) (d+i*10+6));
1324           RE_ENTRANT_CHECK_ON
1325           e = 0;
1326         }
1327       else if ( rp->tag == TW_Infinity )
1328         {
1329           RE_ENTRANT_CHECK_OFF
1330           put_fs_long(0, (unsigned long *) (d+i*10+2));
1331           put_fs_long(0x80000000, (unsigned long *) (d+i*10+6));
1332           RE_ENTRANT_CHECK_ON
1333           e = 0x7fff;
1334         }
1335       else if ( rp->tag == TW_NaN )
1336         {
1337           RE_ENTRANT_CHECK_OFF
1338           put_fs_long(rp->sigl, (unsigned long *) (d+i*10+2));
1339           put_fs_long(rp->sigh, (unsigned long *) (d+i*10+6));
1340           RE_ENTRANT_CHECK_ON
1341           e = 0x7fff;
1342         }
1343       else if ( rp->tag == TW_Empty )
1344         {
1345           /* just copy the reg */
1346           RE_ENTRANT_CHECK_OFF
1347           put_fs_long(rp->sigl, (unsigned long *) (d+i*10+2));
1348           put_fs_long(rp->sigh, (unsigned long *) (d+i*10+6));
1349           RE_ENTRANT_CHECK_ON
1350         }
1351       RE_ENTRANT_CHECK_OFF
1352       put_fs_word(e, (unsigned short *) (d+i*10));
1353       RE_ENTRANT_CHECK_ON
1354     }
1355 
1356 }
1357 
1358 /*===========================================================================*/

/* [previous][next][first][last][top][bottom][index][help] */