home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 171_01 / m8087.mac < prev    next >
Text File  |  1983-11-23  |  29KB  |  818 lines

  1. ;***********************************************************************;
  2. ;                                                                       ;
  3. ;       M8087.MAC - File of macros which provide assembly level         ;
  4. ;                       software support for use of 8087 NDP with       ;
  5. ;                       the IBM personal computer                       ;
  6. ;                                                                       ;
  7. ;       Source: BYTE, August 1983, Vol. 8, No. 8, pp.331-374            ;
  8. ;                                                                       ;
  9. ;       Note - The initial 'if1' and final 'endif' have been removed    ;
  10. ;               from the original BYTE version. My Microsoft 'masm'     ;
  11. ;               balked at the construct hence I dropped it.             ;
  12. ;               Of course the same result is obtained by the statements ;
  13. ;                                                                       ;
  14. ;                       if1                                             ;
  15. ;                               INCLUDE M8087.MAC                       ;
  16. ;                       endif                                           ;
  17. ;                                                                       ;
  18. ;               in your Macro Assembler source, which seems to work.    ;
  19. ;                                                                       ;
  20. ;       The following has not been tested by me, hence use at your own  ;
  21. ;       risk. I hope that this will help stimulate macro development    ;
  22. ;       for Microsoft C in the area of 8087 applications.               ;
  23. ;                                                                       ;
  24. ;***********************************************************************;
  25.  
  26.  
  27.  
  28. ;***********************************************************************;
  29. ;                                                                       ;
  30. ;       ESC_REG - "REG" parameter specifies ESC value.  Issue           ;
  31. ;               proper ESC sequence depending on REQ value.             ;
  32. ;               PARAM is a 6-bit parameter whose upper 3-bits           ;
  33. ;               make up the "xxx" bits in the ESC opcode (11011xxx)     ;
  34. ;               and lower 3-bits make up "yyy" bits in source           ;
  35. ;               byte following (using standard "mod" and "r/m"          ;
  36. ;               designators define byte as "modyyyr/m").                ;
  37. ;                                                                       ;
  38. ;***********************************************************************;
  39.  
  40. ESC_REG macro PARAM,REG
  41.         ;
  42.         ; We need to determine what "reg" field assignment corresponds with
  43.         ; the current value of REG.  This is used as the source for the
  44.         ; ESC operation.  PARAM is used directly in the ESC call
  45.         ;
  46.         ife REG ; Decrement until REG = 0, then issue ESC sequence
  47.           ESC PARAM,AX          ; AX = 000b (see operand summary for 8088)
  48.         else
  49.           REG = REG - 1
  50.           ife REG
  51.             ESC PARAM,CX                ; CX = 001b
  52.           else
  53.             REG = REG - 1
  54.             ife REG
  55.               ESC PARAM,DX              ; DX = 010b
  56.             else
  57.               REG = REG - 1
  58.               ife REG
  59.                 ESC PARAM,BX            ; BX = 011b
  60.               else
  61.                 REG = REG - 1
  62.                 ife REG
  63.                   ESC PARAM,SP          ; SP = 100b
  64.                 else
  65.                   REG = REG - 1
  66.                   ife REG
  67.                     ESC PARAM,BP        ; BP = 101b
  68.                   else
  69.                     REG = REG - 1
  70.                     ife REG
  71.                       ESC PARAM,SI      ; SI = 110b
  72.                     else                ; If REG >= 7, assume 7
  73.                       ESC PARAM,DI      ; DI = 111b
  74.                     endif
  75.                   endif
  76.                 endif
  77.               endif
  78.             endif
  79.           endif
  80.         endif
  81. endm    ; Done with ESC_REG macro
  82.  
  83.  
  84. ;***********************************************************************;
  85. ;                                                                       ;
  86. ;       CHECK_ST - Inputs parameter "ST(i)" and returns with REG=i      ;
  87. ;                                                                       ;
  88. ;***********************************************************************;
  89.  
  90. CHECK_ST macro P_ST
  91.         REG = -1        ; Assume no match is found
  92.         ifidn <&P_ST>,<ST(0)>   ; Is i=0?
  93.           REG = 0
  94.         endif
  95.         ifidn <&P_ST>,<ST(1)>    
  96.           REG = 1
  97.         endif
  98.         ifidn <&P_ST>,<ST(2)>    
  99.           REG = 2
  100.         endif
  101.         ifidn <&P_ST>,<ST(3)>    
  102.           REG = 3
  103.         endif
  104.         ifidn <&P_ST>,<ST(4)>    
  105.           REG = 4
  106.         endif
  107.         ifidn <&P_ST>,<ST(5)>    
  108.           REG = 5
  109.         endif
  110.         ifidn <&P_ST>,<ST(6)>    
  111.           REG = 6
  112.         endif
  113.         ifidn <&P_ST>,<ST(7)>    
  114.           REG = 7
  115.         endif
  116.         ifidn <&P_ST>,<st(0)>   ; Is i=0?        
  117.           REG = 0
  118.         endif
  119.         ifidn <&P_ST>,<st(1)>    
  120.           REG = 1
  121.         endif
  122.         ifidn <&P_ST>,<st(2)>    
  123.           REG = 2
  124.         endif
  125.         ifidn <&P_ST>,<st(3)>    
  126.           REG = 3
  127.         endif
  128.         ifidn <&P_ST>,<st(4)>    
  129.           REG = 4
  130.         endif
  131.         ifidn <&P_ST>,<st(5)>    
  132.           REG = 5
  133.         endif
  134.         ifidn <&P_ST>,<st(6)>    
  135.           REG = 6
  136.         endif
  137.         ifidn <&P_ST>,<st(7)>    
  138.           REG = 7
  139.         endif
  140.         ;
  141.         ; If i not between 0 or 7, see if actually an
  142.         ; "ST(i)" or "ST(I)" string, indicating use of
  143.         ; top of stack element
  144.         ;
  145.         ifidn <&P_ST>,<ST(i)>
  146.           REG = 0
  147.         endif
  148.         ifidn <&P_ST>,<ST(I)>
  149.           REG = 0
  150.         endif
  151.         ifidn <&P_ST>,<st(i)>
  152.           REG = 0
  153.         endif
  154.         ifidn <&P_ST>,<st(I)>
  155.           REG = 0
  156.         endif
  157. endm
  158. ;***********************************************************************;
  159. ;*                                                                      ;
  160. ;*      CHK_CONC - Simple macro that will automatically insert          ;
  161. ;*                      WAIT statements AFTER every 8087 instruction    ;
  162. ;*                      which accesses CPU main memory.  If variable    ;
  163. ;*                      "AUTOSYNC" <> 0, then these WAITs will be       ;
  164. ;*                      inserted (providing no concurrency but relieving;
  165. ;*                      the programmer from worrying about synchronizing;
  166. ;*                      data references. If the user program sets       ;
  167. ;*                      AUTOSYNC to a zero value, then no WAITS         ;
  168. ;*                      are inserted after the instructions and it is   ;
  169. ;*                      the user's responsibility to insure synch-      ;
  170. ;*                      ronization.                                     ;
  171. ;*                                                                      ;
  172. ;***********************************************************************;
  173.  
  174. CHK_CONC macro
  175.  
  176.         if AUTOSYNC
  177.                 WAIT    ; Automatic syncronization
  178.         endif
  179. endm
  180.  
  181.  
  182.  
  183. ;***********************************************************************;
  184. ;                                                                       ;
  185. ;       CHOOSE_4 - Determine which of four parameters (XXX1 to XXX4)    ;
  186. ;                  should be used in ESC sequence, depending on P1      ; 
  187. ;                  and P2 values.  P1 and P@ are parameters passed      ;
  188. ;                  by user in macro call.  XXX1 to XXX4 are macro-      ;
  189. ;                  dependent parameters tacked on to the call to        ;
  190. ;                  CHOOSE_4 by the specific 8087 macro called by the    ;
  191. ;                  user code.                                           ;
  192. ;                                                                       ;
  193. ;***********************************************************************;                                                                       
  194.  
  195. CHOOSE_4 macro P1,P2,XXX1,XXX2,XXX3,XXX4
  196.         ; Initialize variables
  197.         ZERO = 0
  198.         NOTZERO = 0
  199.         REG = 0
  200.         ;
  201.         ; If user passed no parameters, (P1 and P2 are "blank") then
  202.         ; issue a call to ESC_REG macro to set up proper ESC sequence.
  203.         ; An arithmetic instruction with no operands is identical to the
  204.         ; same instruction with the operand form "ST(1),ST".
  205.         ; Example: "FDIV" - Divides second element on stack by first and
  206.         ;              places result in second element on stack.
  207.         ;
  208.         ifb <P1>
  209.                 REG = 1
  210.                 ESC_REG XXX1,REG
  211.         else
  212.           ;
  213.           ; Check to see if first parameter (P1) passed by user is "ST".
  214.           ; If yes, indicates that second parameter (P2) is of form "ST(i)"
  215.           ; so use CHECK_ST macro to determine 'i'.  Then call ESC_REG macro
  216.           ; to issue ESC sequence
  217.           ; Example : "FADD ST,ST(4)" - Adds register four (fifth element on
  218.           ;             8087 stack) to top element and leaves result on top 
  219.           ;             of stack.
  220.           ;
  221.           ifidn <P1>,<ST>
  222.             CHECK_ST P2
  223.             ZERO = REG + 1
  224.             ife ZERO
  225.               REG = 1
  226.             endif
  227.             ESC_REG XXX2,REG
  228.           else
  229.           ifidn <P1>,<st>
  230.             CHECK_ST P2
  231.             ZERO = REG + 1
  232.             ife ZERO
  233.               REG = 1
  234.             endif
  235.             ESC_REG XXX2,REG
  236.           else
  237.             ;
  238.             ; See if P1 is of form "ST(i)".  CHECK_ST returns with REG = -1
  239.             ; if not, else REG = i (i from 0 to 7).  If of ST(i) form, assume
  240.             ; P2 is ST (ie. operands are "ST(i),ST".  Use ESC_REG for ESC
  241.             ; sequence
  242.             ; Example : "FSUB ST(3),ST" - Subtract top of stack from register
  243.             ;           three (the fourth element down the stack) and leave
  244.             ;           result in register 3.
  245.             ;
  246.             CHECK_ST P1
  247.             NOTZERO = REG + 1
  248.             if NOTZERO
  249.                 ESC_REG XXX1,REG
  250.             else
  251.               ;
  252.               ; See if P1 indicates operation is "SHORT" real type.  If so,
  253.               ; then P2 is address of source/destination and xxx3 sets up
  254.               ; SHORT version of operation requested.
  255.               ; Example : "FMUL SHORT VECTOR[SI]" - Multiply 32 bit number
  256.               ;           found in memory at VECTOR offset from DS:SI address
  257.               ;           by top of 8087 stack and leave result on top of stack
  258.               ;
  259.               ifidn <P1>,<SHORT>
  260.                 ESC XXX3,P2
  261.                 CHK_CONC        ; Insert non-concurrent WAIT?
  262.               else
  263.               ifidn <P1>,<short>
  264.                 ESC XXX3,P2
  265.                 CHK_CONC        ; Insert non-concurrent WAIT?
  266.               else
  267.                 ;
  268.                 ; See if P1 indicates a "LONG" real type.  If so, P2 is
  269.                 ; source/destination address and XXX4 is LONG opcode.
  270.                 ; Example : "FDIV LONG [BP].ID_NUMB" - Divide top of stack
  271.                 ;                by 64 bit number found at SS:BP + ID_NUMB
  272.                 ;                in memory.  Leave result on top of 8087 stack
  273.                 ;
  274.                 ifidn <P1>,<LONG>
  275.                   ESC XXX4,P2
  276.                   CHK_CONC       ; Insert non-concurrent WAIT?
  277.                 else
  278.                 ifidn <P1>,<long>
  279.                   ESC XXX4,P2
  280.                   CHK_CONC       ; Insert non-concurrent WAIT?
  281.                 else 
  282.                   ;
  283.                   ; See if P1 indicates "TEMP" real type. If so, P2 is
  284.                   ; source/destination and XXX2 is TEMP opcode.
  285.                   ; Example : "FLD TEMP INTERMEDIATE" - Load 80-bit temporary
  286.                   ;              real number from memory address INTERMEDIATE
  287.                   ;              onto top of 8087 stack
  288.                   ;
  289.                   ifidn <P1>,<TEMP>
  290.                     ESC XXX2,P2
  291.                    CHK_CONC      ; Insert non-concurrent WAIT?
  292.                   else
  293.                   ifidn <P1>,<temp>
  294.                     ESC XXX2,P2
  295.                     CHK_CONC     ; Insert non-concurrent WAIT?
  296.                   else
  297.                     ;
  298.                     ; If none of above, assume operation is of type "ST(i)"
  299.                     ; and take appropriate action
  300.                     ; Example :"FFREE ST(2)" - Free register 2 in 8087
  301.                     ;
  302.                     REG = 1
  303.                     ESC_REG XXX2,REG
  304.                   endif
  305.                 endif
  306.               endif
  307.             endif
  308.           endif
  309.         endif
  310.       endif
  311.     endif
  312.   endif
  313. endif
  314. endm
  315.  
  316.  
  317. ;***********************************************************************;
  318. ;                                                                       ;
  319. ;       INT_SIZE - For all integer operations, determine proper         ;
  320. ;                  parameters to use in ESC sequence                    ;
  321. ;                                                                       ;
  322. ;***********************************************************************;
  323.  
  324. INT_SIZE macro P1,P2,XXX_S,XXX_W,XXX_L
  325.  
  326.         ;
  327.         ; Do :WORD" integer operation.
  328.         ; Example : "FIMUL WORD PULSE_CNT[SI]" - Multiply 16 bit integer
  329.         ;               value found at (DS:SI + PULSE_CNT) by top of stack
  330.         ;               and leave result on top of stack
  331.         ;
  332.         ifidn <P1>,<SHORT>
  333.           ESC XXX_S,P2
  334.         else
  335.         ifidn <P1>,<short>
  336.           ESC XXX_S,P2
  337.         else
  338.           ;
  339.           ; Do "LONG" integer operation.
  340.           ; Example : "FILD LONG POS_LABEL" - Load 64-bit integer onto top
  341.           ;           of stack from main memory at POS_LABEL
  342.           ;
  343.           ifidn <P1>,<LONG>
  344.             ESC XXX_L,P2
  345.           else
  346.           ifidn <P1>,<long>
  347.             ESC XXX_L,P2
  348.           else
  349.             ERROR IN macro !!!
  350.           endif
  351.         endif
  352.       endif
  353.     endif
  354. CHK_CONC        : Insert non-concurrent WAIT?
  355. endm
  356.  
  357. ;***********************************************************************;
  358. ;*                                                                      ;
  359. ;*              DEFINE ALL 8087 MNEMONICS HERE                          ;
  360. ;*                  (In alphabetical order)                             ;
  361. ;*                                                                      ;
  362. ;***********************************************************************;
  363.  
  364.  
  365. FABS    macro           ; Absolute value - No operands
  366.         WAIT            ; Synchronization cmd
  367.         ESC 0CH,CX
  368. endm
  369.  
  370. FADD    macro   P1,P2   ; Add real -//source/destination,source
  371.                         ;       //ST,ST(i)/ST(i),ST/short-real/long-real
  372.         ifb  <P1>       ; If no parameters, classical stack - discard operands
  373.                 FADDP ST(1),ST
  374.         else
  375.                 WAIT    ; Synchronization cmd
  376.                 CHOOSE_4 P1,P2,20H,00H,00H,20H
  377.         endif
  378. endm
  379.  
  380. FADDP   macro   P1,P2   ; Add real and pop - destination,source
  381.                         ;       ST(i),ST
  382.         WAIT            ; Synchronization cmd
  383.         CHOOSE_4 P1,,30H
  384. endm
  385.  
  386. FBLD    macro   P1      ; Packed decimal (BCD) load - source
  387.                         ;       packed-decimal
  388.         WAIT            ; Synchronization cmd
  389.         ESC 3CH,P1
  390. endm
  391.  
  392. FBSTP   macro   P1      ; Packed decimal (BCD) load - source
  393.                         ;       packed-decimal
  394.         WAIT            ; Synchronization cmd
  395.         ESC 3EH,P1
  396. endm
  397.  
  398. FCHS    macro           ; Change sign - No operands
  399.         WAIT            ; Synchronization cmd
  400.         ESC 0CH,AX
  401. endm
  402.  
  403. FCLEX   macro           ; Clear exceptions - No operands
  404.         WAIT            ; Synchronization cmd
  405.         FNCLEX          ;
  406. endm
  407.  
  408. FCOM    macro   P1,P2   ; Compare real - //source
  409.                         ;       //ST(i)/short-real/long-real
  410.         WAIT            ; Synchronization cmd
  411.         CHOOSE_4 P1,P2,02H,,02H,22H
  412. endm
  413.  
  414. FCOMP   macro   P1,P2   ; Compare real and pop - //source
  415.                         ;       //ST(i)/short-real/long-real
  416.         WAIT            ; Synchronization cmd
  417.         CHOOSE_4 P1,P2,03H,,03H,23H
  418. endm
  419.  
  420. FCOMPP  macro   P1,P2   ; Compare real and pop twice - No operands
  421.         WAIT            ; Synchronization cmd
  422.         ESC 33H,CX
  423. endm
  424.  
  425. FDECSTP macro           ; Decrement stack pointer - No operands
  426.         WAIT            ; Synchronization cmd
  427.         ESC 0EH,SI
  428. endm
  429.  
  430. FDISI   macro           ; Disable interrupts - No operands
  431.         WAIT            ; Synchronization cmd
  432.         FNDISI          ;
  433. endm
  434.  
  435. FDIV    macro   P1,P2   ; Divide real - //source/destination,source
  436.                         ;       //ST(i),ST/short-real/long-real
  437.         ifb  <P1>       ; If no parameters, classical stack - discard operands
  438.                 FDIVP ST(1),ST
  439.         else
  440.                 WAIT    ; Synchronization cmd
  441.                 CHOOSE_4 P1,P2,26H,06H,06H,26H
  442.         endif
  443. endm
  444.  
  445. FDIVP   macro   P1,P2   ; Divide real and pop - destination,source
  446.                         ;       ST(i),ST
  447.         WAIT            ; Synchronization cmd
  448.         CHOOSE_4 P1,,36H
  449. endm
  450.  
  451. FDIVR   macro P1,P2     ; Divide real reversed - //source/destination,source
  452.                         ;       //ST,ST(i)/ST(i),ST/short-real/long-real
  453.         ifb  <P1>       ; If no parameters, classical stack - discard operands
  454.                 FDIVRP ST(1),ST
  455.         else
  456.                 WAIT            ; Synchronization cmd
  457.                 CHOOSE_4 P1,P2,27H,07H,07H,27H
  458.         endif
  459. endm
  460.  
  461. FDIVRP  macro   P1,P2   ; Divide real reversed and pop - destination,source
  462.                         ;       ST(i),ST
  463.         WAIT            ; Synchronization cmd
  464.         CHOOSE_4 P1,,37H
  465. endm
  466.  
  467. FENI    macro           ; Enable interrupts - No operands
  468.         WAIT            ; Synchronization cmd
  469.         FNENI           ;
  470. endm
  471.  
  472. FFREE   macro   P1      ; Free register - destination
  473.                         ;       ST(i)
  474.         WAIT            ; Synchronization cmd
  475.         CHOOSE_4 P1,,28H
  476. endm
  477.  
  478. FIADD   macro   P1,P2   ; Integer add - source
  479.                         ;       word-integer/short-integer
  480.         WAIT            ; Synchronization cmd
  481.         INT_SIZE P1,P2,10H,30H
  482. endm
  483.  
  484. FICOM   macro   P1,P2   ; Integer compare - source
  485.                         ;       word-integer/short-integer
  486.         WAIT            ; Synchronization cmd
  487.         INT_SIZE P1,P2,12H,32H
  488. endm
  489.  
  490. FICOMP  macro   P1,P2   ; Integer compare and pop
  491.                         ;       word-integer/short-integer
  492.         WAIT            ; Synchronization cmd
  493.         INT_SIZE P1,P2,13H,33H
  494. endm
  495.  
  496. FIDIV   macro   P1,P2   ; Integer divide - source
  497.                         ;       word-integer/short-integer
  498.         WAIT            ; Synchronization cmd
  499.         INT_SIZE P1,P2,16H,36H
  500. endm
  501.  
  502. FIDIVR  macro   P1,P2   ; Integer divide reversed - source
  503.                         ;       word-integer/short-integer
  504.         WAIT            ; Synchronization cmd
  505.         INT_SIZE P1,P2,17H,37H
  506. endm
  507.  
  508. FILD    macro   P1,P2   ; Integer load - source
  509.                         ;       word-integer/short-integer/long-integer
  510.         WAIT            ; Synchronization cmd
  511.         INT_SIZE P1,P2,18H,38H,3DH
  512. endm
  513.  
  514. FIMUL   macro   P1,P2   ; Integer multiply - source
  515.                         ;       word-integer/short-integer
  516.         WAIT            ; Synchronization cmd
  517.         INT_SIZE P1,P2,11H,31H
  518. endm
  519.  
  520. FINCSTP macro           ; Increment stack pointer - No operands
  521.         WAIT            ; Synchronization cmd
  522.         ESC 0EH,DI
  523. endm
  524.  
  525. FINIT   macro           ; Initialize processor - No operands
  526.         WAIT            ; Synchronization cmd
  527.         FNINIT          ;
  528. endm
  529.  
  530. FIST    macro   P1,P2   ; Integer store - destination
  531.                         ;       word-integer/short-integer
  532.         WAIT            ; Synchronization cmd
  533.         INT_SIZE P1,P2,1AH,3AH
  534. endm
  535.  
  536. FISTP   macro   P1,P2   ; Integer store and pop - destination
  537.                         ;       word-integer/short-integer/long-integer
  538.         WAIT            ; Synchronization cmd
  539.         INT_SIZE P1,P2,1BH,3BH,3FH
  540. endm
  541.  
  542. FISUB   macro   P1,P2   ; Integer subtract - source
  543.                         ;       word-integer/short-integer
  544.         WAIT            ; Synchronization cmd
  545.         INT_SIZE P1,P2,14H,34H
  546. endm
  547.  
  548. FISUBR  macro   P1,P2   ; Integer subtract reversed - source
  549.                         ;       word-integer/short-integer
  550.         WAIT            ; Synchronization cmd
  551.         INT_SIZE P1,P2,15H,35H
  552. endm
  553.  
  554. FLD     macro   P1,P2   ; Load real - source
  555.                         ;       ST(i)/short-real/long-real/temp-real
  556.         WAIT            ; Synchronization cmd
  557.         CHOOSE_4 P1,P2,08H,1DH,08H,28H ; 1DH INDICATES TEMPORARY REAL !!
  558. endm
  559.  
  560. FLDCW   macro   P1      ; Load control word - source
  561.                         ;       2-bytes
  562.         WAIT            ; Synchronization cmd
  563.         ESC 0DH,P1
  564. endm
  565.  
  566. FLDEVN  macro   P1      ; Load environment - source
  567.                         ;       14-bytes
  568.         WAIT            ; Synchronization cmd
  569.         ESC 0CH,P1
  570. endm
  571.  
  572. FLDLG2  macro           ; Load log 2 (base 10) - No operands
  573.         WAIT            ; Synchronization cmd
  574.         ESC 0DH,SP
  575. endm
  576.  
  577. FLDLN2  macro           ; Load log 2 (base e) - No operands
  578.         WAIT            ; Synchronization cmd
  579.         ESC 0DH,BP
  580. endm
  581.  
  582. FLDL2E  macro           ; Load log e (base 2) - No operands
  583.         WAIT            ; Synchronization cmd
  584.         ESC 0DH,DX
  585. endm
  586.  
  587.  
  588. FLDL2T  macro           ; Load log 10 (base 2) - No operands
  589.         WAIT            ; Synchronization cmd
  590.         ESC 0DH,CX
  591. endm
  592.  
  593. FLDPI   macro           ; Load pi - No operands
  594.         WAIT            ; Synchronization cmd
  595.         ESC 0DH,BX
  596. endm
  597.  
  598. FLDZ    macro           ; Load +0.0 - No operands
  599.         WAIT            ; Synchronization cmd
  600.         ESC 0DH,SI
  601. endm
  602.  
  603. FLD1    macro           ; Load +1.0 - No operands
  604.         WAIT            ; Synchronization cmd
  605.         ESC 0DH,AX
  606. endm
  607.  
  608. FMUL    macro P1,P2     ; Multiply real - //source/destination,source
  609.                         ;       //ST(i),ST/ST,ST(i)/short-real/long-real
  610.         ifb  <P1>       ; If no parameters, classical stack - discard operands
  611.                 FMULP ST(1),ST
  612.         else
  613.                 WAIT            ; Synchronization cmd
  614.                 CHOOSE_4 P1,P2,21H,01H,01H,21H
  615.         endif
  616. endm
  617.  
  618. FMULP   macro   P1,P2   ; Multiply real and pop - destination,source
  619.                         ;       ST(i),ST
  620.         WAIT            ; Synchronization cmd
  621.         CHOOSE_4 P1,,31H
  622. endm
  623.  
  624. FNCLEX  macro           ; Clear exceptions - No wait FCLEX
  625.         ESC 1CH,DX      ;
  626. endm
  627.  
  628. FNDISI  macro           ; Disable interrupts - No wait FDISI
  629.         ESC 1CH,CX      ;
  630. endm
  631.  
  632. FNENI   macro           ; Enable interrupts - No wait FENI
  633.         ESC 1CH,AX      ;
  634. endm
  635.  
  636. FNINIT  macro           ; Initialize processor - No wait FINIT
  637.         ESC 1CH,BX      ;
  638. endm
  639.  
  640. FNOP    macro           ; No operation - No operands
  641.         WAIT            ; Synchronization cmd
  642.         ESC 0AH,AX      ;
  643. endm
  644.  
  645. FNSAVE  macro   P1      ; Save state - destination (No wait FSAVE)
  646.                         ;       94-bytes
  647.         ESC 2EH,P1      ;
  648. endm
  649.  
  650. FNSTCW  macro   P1      ; Store control word - destination (No wait FSTCW)
  651.                         ;       2-bytes
  652.         ESC 0FH,P1      ;
  653. endm
  654.  
  655. FNSTENV macro   P1      ; Store environment - destination (No wait FSTENV)
  656.                         ;       14-bytes
  657.         ESC 0EH,P1
  658. endm
  659.  
  660. FNSTSW  macro   P1      ; Store status word - destination (No wait FSTSW)
  661.                         ;       2-bytes
  662.         ESC 2FH,P1
  663. endm
  664.  
  665. FPATAN  macro           ; Partial arctangent - No operands
  666.         WAIT            ; Synchronization cmd
  667.         ESC 0EH,BX
  668. endm
  669.  
  670. FPREM   macro           ; Partial remainder - No operands
  671.         WAIT            ; Synchronization cmd
  672.         ESC 0FH,AX
  673. endm
  674.  
  675. FPTAN   macro           ; Partial tangent - No operands
  676.         WAIT            ; Synchronization cmd
  677.         ESC 0EH,DX
  678. endm
  679.  
  680. FRNDINT macro           ; Round to integer - No operands
  681.         WAIT            ; Synchronization cmd
  682.         ESC 0FH,SP
  683. endm
  684.  
  685. FRSTOR  macro   P1      ; Restore saved state - source
  686.                         ;       94-bytes
  687.         WAIT            ; Synchronization cmd
  688.         ESC 2CH,P1
  689. endm
  690.  
  691. FSAVE   macro   P1      ; Save state - destination
  692.                         ;       94-bytes
  693.         WAIT            ; Synchronization cmd
  694.         FNSAVE P1       ;
  695. endm
  696.  
  697. FSCALE  macro           ; Scale - No operands
  698.         WAIT            ; Synchronization cmd
  699.         ESC 0FH,BP
  700. endm
  701.  
  702. FSQRT   macro           ; Square root - No operands
  703.         WAIT            ; Synchronization cmd
  704.         ESC 0FH,DX
  705. endm
  706.  
  707. FST     macro   P1,P2   ; Store real - destination
  708.                         ;       ST(i)/short-real/long-real
  709.         WAIT            ; Synchronization cmd
  710.         CHOOSE_4 P1,P2,2AH,,0AH,2AH
  711. endm
  712.  
  713. FSTCW   macro   P1      ; Store control word - destination
  714.                         ;       2-bytes
  715.         WAIT            ; Synchronization cmd
  716.         FNSTCW P1       ;
  717. endm
  718.  
  719. FSTENV  macro   P1      ; Store environment - destination
  720.                         ;       14-bytes
  721.         WAIT            ; Synchronization cmd
  722.         FNSTENV P1      ;
  723. endm
  724.  
  725. FSTP    macro   P1,P2   ; Store real and pop - destination
  726.                         ;       ST(i)/short-real/long-real/temp-real
  727.         WAIT            ; Synchronization cmd
  728.         CHOOSE_4 P1,P2,2BH,1FH,0BH,2BH ; 1FH INDICATES TEMPORARY REAL !!
  729. endm
  730.  
  731. FSTSW   macro   P1      ; Store status word - destination 
  732.                         ;       2-bytes
  733.         WAIT            ; Synchronization cmd
  734.         FNSTSW P1       ;
  735. endm
  736.  
  737. FSUB    macro   P1,P2   ; Subtract real - //source/destination,source
  738.                         ;       //ST,ST(i)/ST(i),ST/short-real/long-real
  739.         ifb  <P1>       ; If no parameters, classical stack - discard operands
  740.                 FSUBP ST(1),ST
  741.         else
  742.                 WAIT    ; Synchronization cmd
  743.                 CHOOSE_4 P1,P2,24H,04H,04H,24H
  744.         endif
  745. endm
  746.  
  747. FSUBP   macro   P1,P2   ; Subtract real and pop - destination,source
  748.                         ;       ST(i),ST
  749.         WAIT            ; Synchronization cmd
  750.         CHOOSE_4 P1,,34H
  751. endm
  752.  
  753. FSUBR   macro   P1,P2   ; Subtract real reversed - //source/destination,source
  754.                         ;       //ST,ST(i)/ST(i),ST/short-real/long-real
  755.         ifb  <P1>       ; If no parameters, classical stack - discard operands
  756.                 FSUBRP ST(1),ST
  757.         else
  758.                 WAIT    ; Synchronization cmd
  759.                 CHOOSE_4 P1,P2,25H,05H,05H,25H
  760.         endif
  761. endm
  762.  
  763. FSUBRP  macro   P1,P2   ; Subtract real reversed and pop - destination,source
  764.                         ;       ST(i),ST
  765.         WAIT            ; Synchronization cmd
  766.         CHOOSE_4 P1,,35H
  767. endm
  768.  
  769. FTST    macro           ; Test stack top against +0.0 - No operands
  770.         WAIT            ; Synchronization cmd
  771.         ESC 0CH,SP
  772. endm
  773.  
  774. FWAIT   macro           ; (CPU) Wait while 8087 is busy - No operands
  775.         WAIT            ; NOTE : CPU instruction, not escape code
  776. endm
  777.  
  778. FXAM    macro           ; Examine stack top - No operands
  779.         WAIT            ; Synchronization cmd
  780.         ESC 0CH,BP
  781. endm
  782.  
  783. FXCH    macro   P1      ; Exchange registers - //destination
  784.                         ;       //ST(i)
  785.         WAIT            ; Synchronization cmd
  786.         CHOOSE_4 P1,,09H
  787. endm
  788.  
  789. FXTRACT macro           ; Extract exponent and significand - No operands
  790.         WAIT            ; Synchronization cmd
  791.         ESC 0EH,SP
  792. endm
  793.  
  794. FYL2X   macro           ; Y * log X (base 2) - No operands
  795.         WAIT            ; Synchronization cmd
  796.         ESC 0EH,CX
  797. endm
  798.  
  799. FYL2XP1 macro           ; Y * log (X+1) (base 2) - No operands
  800.         WAIT            ; Synchronization cmd
  801.         ESC 0FH,CX
  802. endm
  803.  
  804. F2XM1   macro           ; (2^^X - 1) - No operands
  805.         WAIT            ; Synchronization cmd
  806.         ESC 0EH,AX
  807. endm
  808.  
  809.  
  810.  
  811. AUTOSYNC=1      ; Initialize M8087 to automatic synchronization
  812.     ; Synchronization cmd
  813.         ESC 0EH,AX
  814. endm
  815.  
  816.  
  817.  
  818. AUTOSYNC