home *** CD-ROM | disk | FTP | other *** search
- /*
- * divz.c
- *
- * Purpose: demonstrates principles used in creating a
- * user-written numeric exception handler.
- * To compile for an 80287:
- * cc divz.c -DNDP287=1 -n0
- * To compile for an 80387:
- * cc divz.c -DNDP387=1 -n2
- * To compile for an mW1167:
- * cc divz.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 = 1.0, d3 = 0.0;
-
- #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 = ZM;
- save_cw = enab_ex_(&emask); /* enable zero divide */
- /* exception trap */
- if (save_cw == EVAL) {
- printf("\nProblem in enab_ex()\n");
- putchar('\7'); /* beep */
- exit(1);
- }
-
- d1 = d2/d3; /* Force division by zero */
-
- printf ("The quotient 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;
-
- static char large_value [] = {
- 0xff,
- 0xff,
- 0xff,
- 0xff,
- 0xff,
- 0xff,
- 0xff,
- 0xff,
- 0xfb,
- 0x43
- };
-
-
- 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 a division
- * by zero is to return an infinity whose sign is the
- * exclusive OR of the signs of the two operands. The
- * programmer has decided that it would be better if the
- * program would return a very large positive number. The
- * code below tests the zero divide bit in the status word.
- * If this is indeed the current error, the program moves a
- * very large value into the memory area for ST0 (the lowest
- * 80387 numeric register) and then calls ldndpenv_()
- * which reloads the buffer into the 80387 and clears the
- * error bits in the status word, otherwise another
- * interrupt would happen immediately.
- * Note that ldndpenv_() will NOT work with an 80287,
- * because of a bug in the interface between a protected
- * mode 80386 and an 80287.
- *
- */
-
- #if NDP387==1 || NDP287==1
- if (buff.sw & ZM) {
- bcopy (&large_value[0], &buff.st0[0], 10);
- }
-
- ldndpenv_(&buff); /* load buffer back into NDP. */
- /* This function clears the */
- /* error bits in the status word */
- /* lest an NDP exception */
- /* immediately recur */
- #endif
-
- /* Control now returns to the main program, right after
- * the instruction which caused the division by zero.
- */
-
- }
-