home *** CD-ROM | disk | FTP | other *** search
- /* unfl.c
- *
- * Purpose: to demonstrate the principles used in creating a
- * user-written numeric exception handler.
- * To compile for an 80287:
- * cc unfl.c -DNDP287=1 -n0
- * To compile for an 80387:
- * cc unfl.c -DNDP387=1 -n2
- * To compile for an mW1167:
- * cc unfl.c -DNDP1167=1 -n4
- */
-
- #include <stdio.h>
- #include <dos.h>
-
- #define NONE 0
- #define mW1167 1
- #define i80387 2
- #define i80287 3
- #define EVAL 0xffffffff /* error value returned */
- /* by enab_ex_() */
- #define TRUE 1
- #define FALSE 0
-
- extern void exit();
- extern void bcopy();
- extern double temp_dbl();
-
- void n_ex_hdl(); /* New exception handler. */
- int display_ndp(); /* display NDP state after */
- /* calling stndpenv_() */
-
- double d1, d2 = 2.0e-150, d3 = 2.0e-151, d4= 2.0e-15;
-
-
- #if NDP287==1
- struct excep287 buff; /* used for 80287. See DOS.H */
- #endif
-
- #if NDP387==1
- struct excep buff; /* used for 80387. See DOS.H */
- #endif
-
- #if NDP1167==1
- struct wexcep buff; /* used for mW1167. See DOS.H */
- #endif
-
- unsigned type;
- main()
-
- {
- unsigned save_cw, emask;
- int okay;
-
- type = ndptype_(); /* get type of NDP */
- if (type == NONE) {
- printf ("No NDP present. Exiting\n\n");
- putchar('\7'); /* beep */
- exit(1);
- }
-
- init_ndp_(); /* Initialize the NDP. Masks all */
- /* errors except invalid operations */
-
- type = stndpenv_(&buff); /* Dump NDP numeric and */
- /* environment registers */
- /* into buffer */
-
- okay = display_ndp(); /* display contents of NDP */
- if (!okay) {
- exit(1);
- }
- /*Set up new exception handler*/
- if (!set_ex_hdl_(n_ex_hdl)) {
- printf("\nCan't set up new exception handler.\n");
- putchar('\7'); /* beep */
- exit(1);
- }
-
- emask = UM;
- save_cw = enab_ex_(&emask); /* enable underflow */
- /* exception trap */
- if (save_cw == EVAL) {
- printf("\nProblem in enab_ex()\n");
- putchar('\7'); /* beep */
- exit(1);
- }
-
- d1 = d2 * d3 * d4; /* Force underflow */
-
- printf ("The product is %20.14e\n",d1);
-
- } /* end of main */
-
- #include "\\c200src\\dispndp.c"
-
-
- /* New exception handler. */
-
- void n_ex_hdl()
-
- /* Control branches to this routine (after it is installed)
- * anytime an NDP exception occurs and that exception has
- * been unmasked in the control word.
- */
-
- {
- int i;
- unsigned type;
- char *poperand;
-
- /* The following code initializes the new value. Each byte
- * is initialized separately so that this code may be
- * adapted for any hexadecimal values
- */
-
- static char new_value [] = {
- 0x00,
- 0x00,
- 0x00,
- 0x00,
- 0x00,
- 0x00,
- 0x00,
- 0x00
- };
-
-
- printf("\nAn NDP exception has just occurred.\n\n");
-
- /* On entry the one or more error bits in the NDP status
- * word are on. The error handler calls stndpenv_() to dump
- * NDP numeric and environment registers into the buffer.
- * A side effect of this is that the chip is
- * reinitialized, with all exceptions masked and all error
- * bits cleared.
- */
- type = stndpenv_(&buff);
-
- display_ndp(); /* Display NDP state. */
-
- /* The default (masked) response of the 80387 to an
- * underflow is to return a denormal if possible or,
- * failing that, zero. In this case, the programmer has
- * decided that it would be better if the program
- * would always return zero. The code below tests the
- * underflow error bit in the status word. If this is indeed
- * the current error, the program moves zero into the memory
- * area whose address is in the operand offset field of the
- * 80387. It then calls init_ndp_() which reinitializes
- * the 80387, clearing the error bits in the status word,
- * otherwise another interrupt would happen immediately.
- *
- */
-
- #if NDP387==1
- poperand = (char *) buff.data_off;
- if (buff.sw & UM) {
- bcopy (&new_value[0], poperand,
- (sizeof(new_value)/sizeof(char)));
- }
-
- init_ndp_(); /* initialize the NDP */
- /* This function clears the error bits */
- /* in status word lest an NDP exception */
- /* immediately recur */
- #endif
-
- /* Control now returns to the main program, right after
- * the instruction which caused the underflow.
- */
-
- }
-
-