home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c329 / 2.img / EXAMPLES / UNFL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-21  |  5.0 KB  |  175 lines

  1. /* unfl.c
  2.  *
  3.  * Purpose: to demonstrate the principles used in creating a
  4.  * user-written numeric exception handler.
  5.  * To compile for an 80287:
  6.  *      cc unfl.c -DNDP287=1 -n0
  7.  * To compile for an 80387:
  8.  *      cc unfl.c -DNDP387=1 -n2
  9.  * To compile for an mW1167:
  10.  *      cc unfl.c -DNDP1167=1 -n4
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <dos.h>
  15.  
  16. #define NONE    0
  17. #define mW1167  1
  18. #define i80387  2
  19. #define i80287  3
  20. #define EVAL    0xffffffff      /* error value returned */
  21.                                 /* by enab_ex_() */
  22. #define TRUE    1
  23. #define FALSE   0
  24.  
  25. extern void     exit();
  26. extern void     bcopy();
  27. extern double   temp_dbl();
  28.  
  29. void    n_ex_hdl();             /* New exception handler. */
  30. int     display_ndp();          /* display NDP state after */
  31.                                 /* calling stndpenv_() */
  32.  
  33. double  d1, d2 = 2.0e-150, d3 = 2.0e-151, d4= 2.0e-15;
  34.  
  35.  
  36. #if NDP287==1
  37. struct excep287 buff;           /* used for 80287. See DOS.H */
  38. #endif
  39.  
  40. #if NDP387==1
  41. struct excep buff;             /* used for 80387. See DOS.H */
  42. #endif
  43.  
  44. #if NDP1167==1
  45. struct wexcep buff;             /* used for mW1167. See DOS.H */
  46. #endif
  47.  
  48. unsigned        type;
  49. main()
  50.  
  51. {
  52.         unsigned        save_cw, emask;
  53.         int             okay;
  54.  
  55.         type = ndptype_();      /* get type of NDP */
  56.         if (type == NONE) {
  57.                 printf ("No NDP present. Exiting\n\n");
  58.                 putchar('\7');  /* beep */
  59.                 exit(1);
  60.         }
  61.  
  62.         init_ndp_();    /* Initialize the NDP. Masks all */
  63.                         /* errors  except invalid operations */
  64.  
  65.         type = stndpenv_(&buff); /* Dump NDP numeric and */
  66.                                 /* environment registers */
  67.                                 /* into buffer */
  68.  
  69.         okay = display_ndp();   /* display contents of NDP */
  70.         if (!okay) {
  71.                 exit(1);
  72.         }
  73.                                 /*Set up new exception handler*/
  74.         if (!set_ex_hdl_(n_ex_hdl)) {
  75.                 printf("\nCan't set up new exception handler.\n");
  76.                 putchar('\7');  /* beep */
  77.                 exit(1);
  78.         }
  79.  
  80.         emask = UM;
  81.         save_cw = enab_ex_(&emask); /* enable underflow */
  82.                                     /* exception trap */
  83.         if (save_cw == EVAL) {
  84.                 printf("\nProblem in enab_ex()\n");
  85.                 putchar('\7');  /* beep */
  86.                 exit(1);
  87.         }
  88.  
  89.         d1 = d2 * d3 * d4;      /* Force underflow */
  90.         
  91.         printf ("The product is %20.14e\n",d1);
  92.         
  93. }       /* end of main */
  94.  
  95. #include "\\c200src\\dispndp.c"
  96.  
  97.  
  98. /* New exception handler. */
  99.  
  100. void    n_ex_hdl()
  101.  
  102. /* Control branches to this routine (after it is installed)
  103.  * anytime an NDP exception occurs and that exception has
  104.  * been unmasked in the control word.
  105.  */
  106.  
  107. {
  108.         int             i;
  109.         unsigned        type;
  110.         char            *poperand;
  111.  
  112. /* The following code initializes the new value. Each byte
  113.  * is initialized separately so that this code may be
  114.  * adapted for any hexadecimal values
  115.  */
  116.  
  117. static  char new_value [] = {
  118.                 0x00,
  119.                 0x00,
  120.                 0x00,
  121.                 0x00,
  122.                 0x00,
  123.                 0x00,
  124.                 0x00,
  125.                 0x00
  126.         };
  127.  
  128.  
  129.         printf("\nAn NDP exception has just occurred.\n\n");
  130.  
  131. /* On entry the one or more error bits in the NDP status
  132.  * word are on. The error handler calls stndpenv_() to dump
  133.  * NDP numeric and environment registers into the buffer.
  134.  * A side effect of this is that the chip is
  135.  * reinitialized, with all exceptions masked and all error
  136.  * bits cleared.
  137.  */
  138.         type = stndpenv_(&buff);
  139.  
  140.         display_ndp();  /* Display NDP state. */
  141.  
  142. /* The default (masked) response of the 80387 to an
  143.  * underflow is to return a denormal if possible or,
  144.  * failing that, zero. In this case, the programmer has
  145.  * decided that it would be better if the program
  146.  * would always return zero. The code below tests the 
  147.  * underflow error bit in the status word. If this is indeed
  148.  * the current error, the program moves zero into the memory
  149.  * area whose address is in the operand offset field of the
  150.  * 80387. It then calls init_ndp_() which reinitializes
  151.  * the 80387, clearing the error bits in the status word,
  152.  * otherwise another interrupt would happen immediately.
  153.  *
  154.  */
  155.  
  156. #if NDP387==1
  157.         poperand = (char *) buff.data_off;
  158.         if (buff.sw & UM) {
  159.                 bcopy (&new_value[0], poperand,
  160.                         (sizeof(new_value)/sizeof(char)));
  161.         }
  162.  
  163.         init_ndp_();    /* initialize the NDP */
  164.                         /* This function clears the error bits */
  165.                         /* in status word lest an NDP exception */
  166.                         /* immediately recur */
  167. #endif
  168.  
  169. /* Control now returns to the main program, right after
  170.  * the instruction which caused the underflow.
  171.  */
  172.  
  173. }
  174.  
  175.