home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / forth / compiler / fpc / source / sfloat1.seq < prev    next >
Text File  |  1990-08-20  |  44KB  |  1,253 lines

  1. \ Software Floating Point Package for FORTH  -- Forward, sequential version.
  2. \ SFLOAT1.SEQ  The first of three files for SFLOAT
  3. CR .( Copyright 1989 by R. L. Smith ) \ Software Floating Point Package for FORTH  -- Forward, sequential version.
  4. CR .( Version 2.21   RLS    08/20/90 10:31:00.69 )
  5. CR
  6. \
  7. \          (c) Copyright 1989  by Robert L. Smith
  8. \                  2300 St. Francis Dr.
  9. \                  Palo Alto, CA 94303
  10. \
  11. \  Permission to use this package or its derivatives is granted for private
  12. \  use with Forth systems.  For permission to use in programs or packages
  13. \  sold for profit, or use with other languages, please contact the author.
  14. \
  15. DEFINED NOFLOATING NIP #IF NOFLOATING #THEN
  16.  
  17. ANEW FPPACKAGE
  18. PREFIX
  19. \ LOADED,
  20. DECIMAL
  21. 6 CONSTANT F#BYTES              \ Number of bytes for a floating point number
  22. CREATE FPSTAT 0 , 0 ,           \ Holds error information
  23.  
  24. ALSO HIDDEN DEFINITIONS
  25. 40 F#BYTES * CONSTANT FPSSIZE   \ Size of floating point stack
  26. CREATE FPSTACK   FPSSIZE ALLOT  \ Floating Point Stack is separate
  27. PREVIOUS DEFINITIONS
  28.  
  29. HERE 12 ALLOT                   \ Leave a little room for underflow
  30. CONSTANT FSP0                   \ Point to base of stack.
  31. CREATE FSP   FSP0 ,             \ Points to top of stack
  32.  
  33. HEX
  34.  
  35. : FDEPTHB   ( -- n )             \ Depth of floating point stack in bytes.
  36.         FSP0 FSP @ - ;
  37.  
  38. : FDEPTH   ( -- n )             \ Depth of floating point stack in FP words.
  39.         FDEPTHB 6 / ;
  40.  
  41. : FCLEAR   ( -- )                 \ Clear Floating Point Stack.
  42.         FSP0 FSP ! ;
  43.  
  44. CODE AND!   ( n addr -- )       \ Logical AND of contents at addr with n
  45.         POP     BX
  46.         POP     AX
  47.         AND     0 [BX], AX
  48.         NEXT
  49.         END-CODE
  50.  
  51. CODE OR!   ( n addr -- )        \ Logical OR of contents at addr with n
  52.         POP     BX
  53.         POP     AX
  54.         OR      0 [BX], AX
  55.         NEXT
  56.         END-CODE
  57.  
  58. CODE FPOP   ( F: r -- ; -- d n )   \ Pop floating number from f-stack to
  59.         MOV     BX, FSP            \ parameter stack.
  60.         PUSH    4 [BX]
  61.         PUSH    2 [BX]
  62.         PUSH    0 [BX]
  63.         ADD     BX, # 6
  64.         MOV     FSP BX
  65.         NEXT
  66.         END-CODE
  67.  
  68. CODE FPUSH   ( F: -- r ; d n -- )    \ Push floating number from parameter
  69.         MOV     BX, FSP              \ stack to floating stack.
  70.         SUB     BX, # 6
  71.         MOV     FSP BX
  72.         POP     0 [BX]
  73.         POP     2 [BX]
  74.         POP     4 [BX]
  75.         NEXT
  76.         END-CODE
  77.  
  78. CODE FPCOPY  ( F r -- r ; -- d n )      \ Get a copy of the floating number
  79.         MOV     BX, FSP                 \ at top of floating stack.
  80.         PUSH    4 [BX]
  81.         PUSH    2 [BX]
  82.         PUSH    0 [BX]
  83.         NEXT
  84.         END-CODE
  85.  
  86. CODE FPFRACT  ( F: r -- r ; -- d )
  87.         MOV     BX, FSP
  88.         PUSH    4 [BX]
  89.         PUSH    2 [BX]
  90.         NEXT
  91.         END-CODE
  92.  
  93. CODE FPSEXP  ( F: r -- r ; -- n )
  94.         MOV     BX, FSP
  95.         PUSH    0 [BX]
  96.         NEXT
  97.         END-CODE
  98.  
  99. : 2/?   ( n1 -- n2 n3 )         \ n2 is n1 shifted right by 1.
  100.                                 \ n3 is least significant bit of n1 .
  101.         DUP >R 2/ 7FFF AND R> 1 AND ;
  102.  
  103. : .NAME     ( n1 -- )
  104.         >NAME .ID ;
  105.  
  106. DEFER FPERR
  107.  
  108. ALSO HIDDEN DEFINITIONS
  109.  
  110. : .FP.    ( -- )   ." Floating Point " ;
  111.  
  112. : (FPERR)    ( F: r -- r ; n1 n2 --  )       \ n1 is CFA, n2 is error flag.
  113.         DUP FPSTAT OR!  CR  BELL EMIT
  114.  ( 1 )  2/? IF  DROP .FP. ." Division by zero in "          .NAME EXIT THEN
  115.  ( 2 )  2/? IF  DROP .FP. ." Overflow in "                  .NAME EXIT THEN
  116.  ( 4 )  2/? IF  DROP .FP. ." argument is negative for "     .NAME EXIT THEN
  117.  ( 8 )  2/? IF  DROP .FP. ." argument is zero for "         .NAME EXIT THEN
  118. ( 10 )  2/? IF  DROP .FP. ." argument is out of range for " .NAME EXIT THEN
  119. ( 20 )  2/? IF  DROP .FP. ." Overflow for Input in "        .NAME EXIT THEN
  120. ( 40 )  2/? IF  DROP .FP. ." Overflow for Output in "       .NAME EXIT THEN
  121. ( 80 )  2/? IF  DROP ." Integer overflow for "              .NAME EXIT THEN
  122. ( 100)  2/? IF  DROP .FP. ." Underflow in "                 .NAME EXIT THEN
  123. ( 200)  2/? IF  DROP .FP. ." argument inaccurate for "      .NAME EXIT THEN
  124. ( 400)  2/? IF  DROP .FP. ." Underflow for Input in "       .NAME EXIT THEN
  125. ( 800)  2/? IF  DROP .FP. ." Underflow for Ouput in "       .NAME EXIT THEN
  126. ( 1000) 2/? IF  DROP .FP. ." results inaccurate for "       .NAME EXIT THEN
  127.         IF ." Unspecified Error " THEN
  128.         DROP QUIT ;
  129.  
  130. ' (FPERR) IS FPERR
  131.  
  132. LABEL DENORM    \ CX = count, BX = Hi, DX = LO, AX = Guard, Round, & Sticky.
  133.         CLEAR_LABELS
  134.         XOR     AX, AX          \ Clear GRS bits
  135.         CMP     CX, # 10        \ Check size of shift
  136.         JL      7 $             \ Branch if shift less than 16
  137.         CMP     CX, # 18        \ Cnt >= 16.  Compare with 24.
  138.         JGE     1 $             \ Branch if shift >= 24
  139.         SUB     CX, # 10        \ 16 <= cnt < 24.  Subtract 16 from cnt.
  140.         MOV     AX, DX          \ Shift by one word.
  141.         MOV     DX, BX
  142.         XOR     BX, BX          \ Clear MS word.
  143.         AND     AL, AL          \ Don't miss any sticky bits.
  144.         JZ      8 $
  145.         OR      AH, # 2         \ Set a sticky bit.
  146.         JMP     8 $             \ Shift from 0 to 7 bits.
  147.  
  148. 1 $:    CMP     CX, # 20        \ Cnt >= 24.  Compare with 32.
  149.         JGE     3 $             \ Branch if shift >= 32.
  150.         MOV     AH, BL          \ 24 <= cnt < 32, so shift by 3 bytes.
  151.         MOV     AL, DH
  152.         OR      AL, DL          \ OR in the sticky bits.
  153.         JZ      2 $             \ Shall we set a sticky bit?
  154.         OR      AH, # 2         \ Yes.
  155. 2 $:    MOV     DL, BH          \ Continue the 3-byte shift.
  156.         XOR     DH, DH          \ Clear the high 3 bytes.
  157.         XOR     BX, BX
  158.         SUB     CX, # 18        \ Adjust the shift counter.
  159.         JMP     8 $             \ Shift remaining 0 to 7 places.
  160.  
  161. 3 $:    CMP     CX, # 28        \ Cnt >= 32.  Check against 40.
  162.         JGE     5 $             \ Branch if shift count > 40.
  163.         MOV     AX, BX          \ 32 <= cnt < 40.  Do a 2 word shift.
  164.         OR      AL, DH          \ Check the sticky bits.
  165.         OR      AL, DL
  166.         JZ      4 $             \ If sticky byte not zero,
  167.         OR      AH, # 2         \  then set sticky bit.
  168. 4 $:    XOR     BX, BX          \ Clear high and low words.
  169.         XOR     DX, DX
  170.         SUB     CX, # 20        \ Adjust shift counter.
  171.         JMP     8 $             \ Go to final shift area.
  172.  
  173. 5 $:    OR      BX, DX          \ Shift count >= 40
  174.         JZ      0A $            \ In theory, this should never jump.
  175.         MOV     AH, # 2         \ So set a sticky bit.
  176.         XOR     BX, BX          \ Clear all the rest.
  177.         XOR     DX, DX
  178.         RET
  179.  
  180. 7 $:    CMP     CX, # 8         \ Count < 16.  See if less than 8.
  181.         JL      8 $
  182.         MOV     AH, DL          \ 8 <= cnt < 16.
  183.         MOV     DL, DH          \ Move by one byte.
  184.         MOV     DH, BL
  185.         MOV     BL, BH
  186.         XOR     BH, BH          \ Clear high byte.
  187.         SUB     CX, # 8         \ Adjust shift count.
  188. 8 $:    AND     CX, CX          \ Test for zero count.
  189.         JZ      0A $
  190. 9 $:    SHR     BX, # 1         \ Shift right by one bit.
  191.         RCR     DX, # 1
  192.         RCR     AX, # 1
  193.         LOOP    9 $             \ Loop until count is 0.
  194. 0A $:   RET
  195.  
  196.         END-CODE
  197.  
  198. PREVIOUS DEFINITIONS
  199. \ F+ and F-
  200.  
  201. HEX
  202.  
  203. CODE F-     ( F: r1 r2 -- r3 )
  204.         CLEAR_LABELS
  205.         PUSH    BP
  206.         MOV     BP, FSP
  207.         XOR     WORD 0 [BP], # 8000  \ For subtraction, reverse sign and add.
  208.         JMP     1 $
  209.         END-CODE
  210.  
  211. CODE F\-   ( F: r1 r2 -- r3 )     \ Reverse subtraction
  212.         PUSH    BP
  213.         MOV     BP, FSP
  214.         XOR     WORD 6 [BP], # 8000
  215.         JMP     1 $
  216.         END-CODE
  217.  
  218. ALSO HIDDEN
  219.  
  220. CODE F+     ( F: r1 r2 -- r3 )    \ Timing: 174 usec.
  221.         PUSH    BP
  222. 1 $:    MOV     BP, FSP
  223.         MOV     AX, 0 [BP]      \ Get SX2  ( Sign and biased exponent )
  224.         MOV     BX, 2 [BP]      \ Hi2
  225.         MOV     DX, 4 [BP]      \ Lo2
  226.         ADD     BP, # 6
  227.         MOV     FSP BP          \ Update Floating Stack Pointer
  228.         OR      BH, BH          \ Check if normalized number.
  229.         JNS     3 $             \ Branch if m.s. bit of Hi2 not set.
  230.         MOV     CX, 0 [BP]      \ SX1.
  231.         MOV     DI, 2 [BP]      \ Hi1
  232.         OR      DI, DI          \ Check if Hi1 is normal.
  233.         JNS     4 $             \ Jump if m.s. bit not set.
  234.         CMP     AX, CX          \ Check if signs and exponents the same.
  235.         JNE     5 $             \ Branch if not the same.
  236.         AND     AX, # 7FFF
  237.         CMP     AX, # 7FFE
  238.         JGE     0F $            \ Overflow check.
  239.         MOV     AX, 4 [BP]      \ Equal exponents: Add magnitudes.
  240.         ADD     AX, DX          \ Lo1 + Lo2
  241.         ADC     BX, DI          \ Hi1 + Hi2
  242.         RCR     BX              \ Carry must have been generated.
  243.         RCR     AX
  244.         JNC     2 $             \ Check guard bit.
  245.         ADD     AX, # 1         \ Round result.
  246.         ADC     BX, # 0         \ No carry-out
  247.         AND     AX, # FFFE      \ Round to even.
  248. 2 $:    INC     CX              \ Add to exponent.  Could check for overflow.
  249.         MOV     4 [BP], AX      \ Push results
  250.         MOV     2 [BP], BX
  251.         MOV     0 [BP], CX
  252. 3 $:    POP     BP
  253.         NEXT
  254.  
  255. 4 $:                            \ Treat 2nd operand as zero.
  256.         MOV     4 [BP], DX      \ Push 1st operand.
  257.         MOV     2 [BP], BX
  258.         MOV     0 [BP], AX
  259.         POP     BP
  260.         NEXT
  261.  
  262. 0F $:   MOV     CX, # 2         \ Report an overflow
  263. 0E $:   MOV     BX, # LAST @ NAME>
  264.         POP     BP
  265.         PUSH    BX
  266.         PUSH    CX
  267.         MOV     AX, # ' FPERR
  268.         JMP     AX
  269.  
  270. 5 $:                            \ Unequal exponents.
  271.         PUSH    SI              \ Save SI
  272.         MOV     SI, 4 [BP]      \ Get Lo1.
  273.         OR      AH, AH          \ Test for negative sign of F2.
  274.         JS      0B $            \ If F2 negative, branch to neg F2 case.
  275.         OR      CH, CH          \ Test for negative F1.
  276.         JS      0C $            \ Branch if F1 is negative.
  277. 6 $:    CMP     AX, CX          \ Add magnitudes.  Find smaller exponent.
  278.         JB      7 $             \ Branch if F2 is smaller.
  279.         XCHG    AX, CX          \ Swap F1 and F2.
  280.         XCHG    BX, DI
  281.         XCHG    DX, SI
  282. 7 $:    PUSH    CX              \ Save CX
  283.         SUB     CX, AX          \ Set CX to exponent difference.
  284.         CALL    DENORM          \ Denormalize the smaller number.
  285.         POP     CX              \ Restore CX
  286.         ADD     DX, SI          \ Add low parts.
  287.         ADC     BX, DI          \ Add high parts.
  288.         JNC     8 $             \ Branch if no carry out.
  289.         INC     CX              \ Increment exponent of sum
  290.         RCR     BX              \ Shift result right by 1.
  291.         RCR     DX
  292.         RCR     AX
  293. 8 $:    ADD     AX, # 8000      \ Round result
  294.         ADC     DX, # 0
  295.         ADC     BX, # 0
  296.         JNC     0A $            \ Branch if no carry out.
  297.         INC     CX              \ Else increment exponent
  298.         RCR     BX              \ Shift the mantissa right
  299.         RCR     DX
  300. 9 $:    POP     SI              \ Restore SI
  301.         MOV     4 [BP], DX
  302.         MOV     2 [BP], BX
  303.         MOV     0 [BP], CX
  304.         TEST    CX, # 7FFE      \ Test for overflow
  305.         JZ      0F $
  306.         POP     BP
  307.         NEXT
  308.  
  309. 0A $:   OR      AX, AX          \ Should we round to even?
  310.         JNE     9 $
  311.         AND     DL, # 0FE       \ Yes, round to even.
  312.         JMP     9 $
  313.  
  314. 0B $:   OR      CH, CH          \ F2 is negative.  Test F1.
  315.         JS      6 $             \ If F1 is negative, add magnitudes.
  316. 0C $:   XOR     AH, # 80        \ Subtract magnitudes.  Flip sign of F2.
  317.         CMP     AX, CX          \ Are exponents now equal?
  318.         JNE     10 $            \ Branch if not equal.
  319.         SUB     SI, DX          \ Subtract F1 - F2.
  320.         SBB     DI, BX
  321.         JA      12 $            \ Branch if F1 > F2 with non-zero high part.
  322.         JC      1C $            \ Branch if F1 < F2
  323.         OR      SI, SI
  324.         JNZ     12 $            \ Branch if F1 > F2 , non-zero low part.
  325. 1C $:   XOR     CH, # 80        \ Otherwise, change sign of result,
  326.         NEG     SI              \  and negate the mantissa.
  327.         JZ      0D $            \ Branch on low part = 0.
  328.         NOT     DI              \ Usually DI is just complemented.
  329.         JMP     12 $            \ Join common code.
  330.  
  331. 0D $:   NEG     DI              \ Finish negating high part.
  332.         JNZ     12 $            \ If non-zero, join common code.
  333. 1F $:   XOR     BX, BX          \ Otherwise result is zero.
  334.         XOR     DX, DX
  335.         XOR     CX, CX
  336.         JMP     15 $
  337.  
  338. 10 $:   JB      11 $            \ Jump if no swap required.
  339.         XOR     AH, # 80
  340.         XCHG    AX, CX          \ Exchange F1 and F2.
  341.         XCHG    BX, DI
  342.         XCHG    DX, SI
  343.         XOR     AH, # 80
  344. 11 $:   PUSH    CX              \ Save CX
  345.         SUB     CX, AX          \ CX = exponent difference.  (Underflow?)
  346.         CALL    DENORM          \ Denormalize the smaller.
  347.         POP     CX              \ Restore CX
  348.         NEG     AX              \ Subtract GRS
  349.         SBB     SI, DX          \ Low part of difference.
  350.         SBB     DI, BX          \ High part of difference.
  351. 12 $:   JZ      16 $            \ If high word is 0, branch to word shift.
  352.         TEST    CX, # 7FC0      \ Check for "Near Underflow"
  353.         JZ      1F $
  354.         MOV     BX, DI          \ Put high part of result in BX
  355.         OR      BH, BH          \ Test high byte.
  356.         JZ      17 $            \ If zero, branch to byte shift.
  357.         JS      1A $            \ If sign bit set, branch to rounding.
  358.         SHL     AX              \ Shift left by 1 bit.
  359.         RCL     SI
  360.         RCL     BX
  361.         DEC     CX              \ Adjust exponent.   (Underflow?)
  362.         AND     BH, BH          \ Test sign bit.
  363.         JS      1A $            \ Go to rounding if sign bit set.
  364. 13 $:   SHL     SI              \ Shift until m.s. bit set.
  365.         RCL     BX
  366.         DEC     CX              \ (Underflow?)
  367. 1D $:   AND     BH, BH
  368. 14 $:   JNS     13 $            \ Branch back until m.s. bit is set.
  369. 15 $:   MOV     DX, SI
  370.         POP     SI              \ Restore SI
  371.         MOV     4 [BP], DX
  372.         MOV     2 [BP], BX
  373.         MOV     0 [BP], CX
  374.         POP     BP
  375.         NEXT
  376.  
  377. 16 $:   MOV     BX, SI          \ Shift by one word.
  378.         MOV     SI, AX
  379.         XOR     AX, AX          \ The rounding and sticky bits are 0.
  380.         CMP     CX, # 7FC0      \ Test for "Near Overflow"
  381.         JZ      1F $
  382.         SUB     CX, # 10        \ Subtract 16 from exponent.
  383.         OR      BX, BX          \ Check if high part is zero.
  384.         JZ      18 $            \ Branch if high = 0.
  385.         OR      BH, BH          \ Check if shift by a byte.
  386.         JNZ     13 $            \ Branch if shift less than 8 bits.
  387. 17 $:   XCHG    CX, SI          \ Do a shift by a byte.
  388.         MOV     BH, BL
  389.         MOV     BL, CH
  390.         MOV     CH, CL
  391.         MOV     CL, AH
  392.         XOR     AX, AX
  393.         XCHG    CX, SI
  394.         SUB     CX, # 8         \ Adjust exponent.
  395.         JMP     1D $            \ Jump to finish shifts.
  396.  
  397. 18 $:   OR      SI, SI          \ Second shift by a word.
  398.         JZ      19 $            \ Branch if total result is zero.
  399.         MOV     BX, SI          \ Move in guard bit.
  400.         XOR     SI, SI
  401.         SUB     CX, # 10        \ Adjust exponent
  402.         OR      BH, BH
  403.         JNZ     14 $            \ Test byte shift.
  404.         JMP     17 $            \ Check remaining shifts.
  405.  
  406. 19 $:   POP     SI              \ Restore SI
  407.         XOR     CX, CX
  408.         MOV     4 [BP], CX
  409.         MOV     2 [BP], CX
  410.         MOV     0 [BP], CX
  411.         POP     BP
  412.         NEXT
  413.  
  414. 1A $:   ADD     AX, # 8000      \ Round result
  415.         ADC     SI, # 0
  416.         ADC     BX, # 0
  417.         JC      1B $            \ Branch if Carry-out generated.
  418.         OR      AX, AX          \ Check if round to even required.
  419.         JNZ     15 $            \ Branch if not.
  420.         AND     SI, # FFFE      \ Round to even.
  421.         JMP     15 $            \ Push results.
  422.  
  423. 1B $:   RCR     BX              \ Carry-out was generated.
  424.         RCR     SI
  425.         INC     CX              \ Adjust exponent.
  426.         JMP     15 $            \ Push results.
  427.  
  428.         END-CODE
  429.  
  430. \ Floating Point Multiply.
  431.  
  432. HEX
  433.  
  434. CODE F*   ( F: r1 r2 -- r3 )      \ Time: 256 usec.
  435.         CLEAR_LABELS
  436.         PUSH    BP
  437.         MOV     BP, FSP
  438.         MOV     AX, 0 [BP]      \ SX2
  439.         MOV     DI, 2 [BP]      \ A
  440.         MOV     BX, 4 [BP]      \ B
  441.         ADD     BP, # 6
  442.         MOV     FSP BP
  443.         MOV     CX, 0 [BP]      \ SX1
  444.         MOV     DX, AX          \ SX2
  445.         XOR     DX, CX          \ Get Sign of product
  446.         AND     DX, # 8000      \ Isolate the sign.
  447.         AND     AX, # 7FFF
  448.         AND     CX, # 7FFF
  449.         ADD     AX, CX          \ Add the exponents,
  450.         SUB     AX, # 3FFF      \ Adjust for the bias.
  451.         JS      6 $             \ Jump if Overflow or Underflow
  452.         AND     AX, # 7FFF      \ Isolate exponent of product,
  453.         OR      AX, DX          \ then join sign and exponent.
  454.         MOV     CX, 2 [BP]      \ C
  455.         MOV     DX, 4 [BP]      \ D
  456.         PUSH    SI
  457.         PUSH    AX              \ Temporarily save product SX
  458.         OR      DI, DI          \ Check if F2 is normal.
  459.         JNS     4 $             \ If not normal, treat as zero.
  460.         OR      CH, CH          \ Check if F1 is normal.
  461.         JNS     4 $             \ If not normal, treat as zero.
  462.         OR      DX, DX          \ Check for low parts = zero.
  463.         JZ      7 $
  464.         OR      BX, BX
  465.         JZ      8 $
  466.         MOV     SI, DX          \ D
  467.         MOV     AX, BX          \ B
  468.         MUL     DX              \ BD to (DX, AX)
  469.         PUSH    AX              \ Save BDL
  470.         MOV     AX, SI          \ D
  471.         MOV     SI, DX          \ BDH to SI
  472.         MUL     DI              \ AD to (DX,AX)
  473.         ADD     SI, AX          \ ADL+BDH to SI
  474.         ADC     DX, # 0         \ ADH
  475.         MOV     AX, BX          \ B
  476.         MOV     BX, DX          \ ADH to BX
  477.         MUL     CX              \ BC to (DX,AX)
  478.         ADD     AX, SI          \ BCL+ADL+BDH to AX
  479.         ADC     BX, DX          \ BCH+ADH
  480.         SBB     SI, SI          \ Set SI to carry-out
  481.         POP     DX              \ BDL
  482.         OR      DX, DX
  483.         JZ      1 $
  484.         OR      AX, # 1         \ In case we need it for rounding!
  485. 1 $:    NEG     SI
  486. 2 $:    XCHG    AX, DI          \ A to AX, PROD1 to DI
  487.         MUL     CX              \ AC to (DX,AX)
  488.         ADD     AX, BX          \ ACL+BCH+ADH
  489.         ADC     DX, SI          \ ACH+carry
  490.         POP     BX              \ SX of product.
  491.         JS      3 $             \ Branch if m.s. bit set
  492.         SHL     DI              \ Otherwise, shift left by 1 bit.
  493.         RCL     AX
  494.         RCL     DX
  495.         DEC     BX              \ Adjust exponent.  (Underflow?)
  496. 3 $:    ADD     DI, # 8000      \ Round result.
  497.         ADC     AX, # 0
  498.         ADC     DX, # 0
  499.         JC      13 $            \ If carry set, re-normalize.
  500.         OR      DI, DI
  501.         JNZ     0C $            \ Branch if round to even is NOT required.
  502.         AND     AX, # FFFE      \ Round to even!
  503.         JMP     0C $            \ Push results.
  504.  
  505. 4 $:    JMP     14 $            \ Needed because of limited jumps
  506.  
  507. 6 $:    JMP     16 $            \ Needed because of limited jumps
  508.  
  509. 7 $:    OR      BX, BX          \ D=0 case.
  510.         JZ      0A $
  511.         MOV     AX, BX
  512.         MUL     CX              \ AC
  513.         MOV     BX, DX          \ ACH
  514.         XOR     SI, SI
  515.         JMP     2 $
  516.  
  517. 8 $:    MOV     AX, DI          \ B=0 case.
  518.         MUL     DX
  519.         MOV     BX, DX
  520.         XOR     SI, SI
  521.         JMP     2 $
  522.  
  523. 9 $:    POP     SI
  524.         JMP     5 $
  525.  
  526. 0A $:   MOV     AX, DI          \ B = D = 0 case.
  527.         XOR     DI, DI
  528.         MUL     CX
  529.         POP     BX
  530.         OR      DX, DX
  531.         JS      0C $
  532.         TEST    BX, # 7FFF      \ Check for underflow
  533.         JZ      9 $
  534.         DEC     BX
  535. 0B $:   RCL     AX              \ Re-normalize.
  536.         RCL     DX
  537. 0C $:   POP     SI
  538.         MOV     4 [BP], AX      \ Push results.
  539.         MOV     2 [BP], DX
  540.         MOV     0 [BP], BX
  541.         POP     BP
  542.         NEXT
  543.  
  544. 13 $:   RCR     DX
  545.         INC     BX
  546.         JMP     0C $
  547.  
  548. 14 $:   XOR     AX, AX          \ Send zero results.
  549.         ADD     SP, # 2
  550.         POP     SI              \ Restore SI
  551. 15 $:   XOR     AX, AX          \ Send zero result
  552.         MOV     4 [BP], AX      \ Push zero result.
  553.         MOV     2 [BP], AX
  554.         MOV     0 [BP], AX
  555.         POP     BP
  556.         NEXT
  557.  
  558. 16 $:                           \ Overflow or Underflow
  559.         CMP     AX, # C000
  560.         JA      15 $            \ Return zero for Underflow case.
  561.         MOV     BX, # -1        \ Overflow case
  562.         MOV     4 [BP], BX
  563.         MOV     2 [BP], BX
  564.         MOV     BX, # 7FFF
  565.         MOV     0 [BP], BX
  566.         POP     BP
  567.         MOV     BX, # LAST @ NAME>
  568.         MOV     CX, # 2
  569.         PUSH    BX
  570.         PUSH    CX
  571.         MOV     AX, # ' FPERR
  572.         JMP     AX
  573.  
  574.         END-CODE
  575.  
  576. PREVIOUS
  577.  
  578. \ Floating division.
  579. \    The division routine that follows is based on the work of Roedy Green,
  580. \    the author of BBL/Abundance.
  581. \    The speed on a standard XT-PC clone is about 290 micro-seconds.
  582.  
  583. CODE F/    ( F: r1 r2 -- r3 )     \ Time: 290 usec.
  584.         CLEAR_LABELS
  585.         PUSH    BP
  586.         MOV     BP, FSP
  587.         MOV     AX, 0 [BP]      \ SX2
  588.         MOV     CX, 2 [BP]      \ Hi2
  589.         MOV     BX, 4 [BP]      \ Lo2
  590.         ADD     BP, # 6
  591.         MOV     FSP BP
  592.         MOV     DX, 0 [BP]      \ SX1
  593.         MOV     DI, DX
  594.         XOR     DI, AX
  595.         AND     DI, # 8000      \ Get sign of result.
  596.         AND     DX, # 7FFF
  597.         AND     AX, # 7FFF
  598.         SUB     DX, AX          \ Difference of biased exponents.
  599.         ADD     DX, # 3FFF      \ Re-bias the exponent.
  600.         CMP     DX, # 7FFD      \ Check for near overflow.
  601.         JAE     0 $             \ Jump if nearly overflow.
  602.         OR      DI, DX          \ Join with the sign of the quotient.
  603.         OR      CH, CH          \ Check for unnormalized (zero) divisor.
  604.         JNS     2 $             \ Branch to Divide by zero routine.
  605.         MOV     DX, 2 [BP]      \ Hi1
  606.         OR      DH, DH          \ Check for unnormalized numerator.
  607.         JNS     3 $             \ Branch to zero case, if unnormalized.
  608.         MOV     AX, 4 [BP]      \ Lo1
  609.         PUSH    BP              \ Save FSP
  610.         PUSH    SI              \ Save SI
  611.         XOR     BP, BP          \ Zero out BP
  612.         CMP     DX, CX          \ Compare numerator with denominator.
  613.         JB      4 $             \ If num < den, begin division process.
  614.         JA      1 $             \ If num > den, shift numerator right by 1.
  615.         CMP     AX, BX          \ If high parts equal, check low parts.
  616.         JAE     1 $             \ If num >= den, shift num right by 1.
  617.         MOV     SI, # FFFF      \ MS num = MS den.  Start with trial g0 = s-1
  618.         MOV     BP, AX
  619.         SUB     BP, BX          \ midnum - lsden
  620.         MOV     AX, BX
  621.         ADD     BP, CX          \ msnum + (midnum-lsnum)
  622.         JC      7 $             \ Good quotient if Carry is set
  623.         JMP     1 $             \ Otherwise, correct result
  624.  
  625. 0 $:    OR      CX, CX          \ Overflow or Underflow
  626.         JNS     2 $             \ Check for Divide by zero.
  627.         MOV     AX, 2 [BP]
  628.         OR      AH, AH
  629.         JNS     3 $             \ Jump if numerator is unnormalized (zero)
  630.         CMP     DX, # C000
  631.         JAE     3 $             \ For underflow, treat as zero
  632.         OR      DI, # 7FFF
  633.         MOV     CX, # 2         \ Overflow flag
  634.         JMP     11 $
  635.  
  636. 1 $:                            \ Num >= Den
  637.         INC     DI              \ Increment exponent of quotient.  (OVFL?)
  638.         SHR     DX, # 1         \ Shift accum right by 1
  639.         RCR     AX, # 1
  640.         JNC     4 $             \ If low bit clear, join normal sequence.
  641.         DIV     CX              \ Initial approximation.
  642.         MOV     SI, AX          \ quotient g0
  643.         MOV     BP, DX          \ remainder r0
  644.         MUL     BX              \ g0 * denlo
  645.         NOT     AX              \ Negate low part of correction factor
  646.         SUB     AX, # 7FFF      \ Adjust for carry from shift.
  647.         JMP     5 $             \ Join rest of main code.
  648.  
  649. 2 $:    AND     DI, # 8000      \ Divide by zero case.
  650.         OR      DI, # 7FFF      \ Set exponent bits to 1.
  651.         MOV     CX, # 1         \ Set flag for divide by zero
  652. 11 $:   MOV     AX, # -1        \ Set largest possible number.
  653.         MOV     2 [BP], AX
  654.         MOV     4 [BP], AX
  655.         MOV     0 [BP], DI
  656.         POP     BP
  657.         MOV     BX, # LAST @ NAME>      \ Point to this routine.
  658.         PUSH    BX
  659.         PUSH    CX
  660.         MOV     AX, # ' FPERR
  661.         JMP     AX
  662.  
  663. 3 $:                            \ Numerator is zero.  Give 0 result.
  664.         XOR     AX, AX
  665.         MOV     0 [BP], AX
  666.         MOV     2 [BP], AX
  667.         MOV     4 [BP], AX
  668.         POP     BP
  669.         NEXT
  670.  
  671. 4 $:    DIV     CX              \ Initial approximation. Divide by denhi.
  672.         MOV     SI, AX          \ Save initial quotient estimate = g0
  673.         MOV     BP, DX          \ Save r0
  674.         MUL     BX              \ Correction factor = g0 * denlo
  675.         NEG     AX
  676. 5 $:    SBB     BP, DX          \ r1 = s * r0 - g0 * denlo
  677.         JNC     7 $             \ Jump if r1 >= 0   (no borrow)
  678. 6 $:    DEC     SI              \ Decrement g by 1, at least.
  679.         ADD     AX, BX          \ r2 = r1 + den
  680.         ADC     BP, CX
  681.         JC      7 $             \ Jump if r2 >= 0   ( no carry)
  682.         DEC     SI              \ Decrement g by 1 for last time.
  683.         ADD     AX, BX
  684.         ADC     BP, CX          \ r3 = r2 + den
  685. 7 $:    MOV     DX, BP
  686.         PUSH    SI              \ Save MS quotient
  687.         CMP     DX, CX
  688.         JAE     0E $
  689.         DIV     CX              \ Approximate LS part of quotient.
  690.         MOV     SI, AX
  691.         MOV     BP, DX
  692.         MUL     BX              \ Correction factor
  693.         NEG     AX
  694.         SBB     BP, DX
  695.         JNC     9 $             \ Jump if no borrow
  696. 8 $:    DEC     SI              \ Decrement g1 by 1
  697.         ADD     AX, BX          \ Add denominator back in to remainder
  698.         ADC     BP, CX
  699.         JC      9 $             \ Jump if no carry
  700.         DEC     SI              \ Decrement g1 again
  701.         ADD     AX, BX          \ Add denominator again
  702.         ADC     BP, CX
  703. 9 $:    POP     DX              \ Get MS part of quotient.
  704.         SHL     AX, # 1         \ Shift remainder left by 1
  705.         RCL     BP, # 1
  706.         JC      0A $            \ If ms bit was set, jump.
  707.         CMP     BP, CX          \ Compare MS 2*remainder with denhi
  708.         JB      0B $            \ If 2*rem < den, jump to no rounding
  709.         JA      0A $            \ If 2*rem > den, jump to rounding case
  710.         CMP     AX, BX          \ If MS parts are equal, compare LS parts
  711.         JB      0B $            \ If 2*rem < den, jump to no rounding
  712.         JE      10 $            \ If 2*rem > den, jump to rounding case
  713. 0A $:   ADD     SI, # 1         \ Round up, for sure.
  714.         ADC     DX, # 0
  715.         JC      0F $
  716. 0B $:   MOV     AX, SI          \ Put ls part of quotient in AX
  717.         POP     SI              \ Restore SI and BP registers
  718.         POP     BP              \ Restore Floating Stack Pointer
  719.         MOV     4 [BP], AX      \ Push results and return.
  720.         MOV     2 [BP], DX
  721.         MOV     0 [BP], DI
  722.         POP     BP              \ Restore original BP
  723.         NEXT
  724.  
  725. 0E $:   MOV     SI, # FFFF      \ MS num = MS den.  Start with trial g0 = s-1
  726.         MOV     BP, AX
  727.         SUB     BP, BX          \ midnum - lsden
  728.         MOV     AX, BX
  729.         ADD     BP, CX          \ msnum + (midnum-lsnum)
  730.         JC      9 $             \ Good quotient if Carry is set
  731.         JMP     8 $             \ Otherwise, correct result
  732.  
  733. 0F $:   RCR     DX, # 1         \ Oops!  We overflowed available bits.
  734.         RCR     SI, # 1         \ So shift right and adjust the exponent.
  735.         INC     DI              \ (Overflow?)
  736.         JMP     0B $
  737.  
  738. 10 $:   ADD     SI, # 1         \ Round to even.
  739.         ADC     DX, # 0
  740.         JC      0F $            \ In rare cases we will get a carry-out.
  741.         AND     SI, # FFFE      \ Otherwise, round to even
  742.         JMP     0B $
  743.  
  744.         END-CODE
  745.  
  746.  
  747. \  End of basic 4-functions.
  748.  
  749. \  Floating Square Root
  750.  
  751. DECIMAL
  752.  
  753. CODE FSQRT    ( F: r1 -- r2 )
  754.         CLEAR_LABELS            \ Clear the local label table.
  755.         PUSH    BP
  756.         MOV     BP, FSP
  757.         MOV     DI, 0 [BP]      \ SEXP  ( Sign and exponent of f1 )
  758.         MOV     BX, 2 [BP]      \ MS part of f1.  Num-hi.
  759.         MOV     DX, 4 [BP]      \ LS part of f1.  Num-low.
  760.         XOR     AX, AX
  761.         OR      BX, BX
  762.         JNS     2 $             \ If MS bit not set, treat as zero.
  763.         OR      DI, DI
  764.         JNS     0 $
  765.         XOR     AX, AX          \ Negative argument to square root
  766.         MOV     2 [BP], AX
  767.         MOV     4 [BP], AX
  768.         MOV     AX, # -1
  769.         MOV     0 [BP], AX
  770.         MOV     AX, # LAST @ NAME>
  771.         POP     BP
  772.         PUSH    AX
  773.         MOV     AX, # 4         \ Negative argument flag
  774.         PUSH    AX
  775.         MOV     AX, # ' FPERR
  776.         JMP     AX
  777.  
  778. 0 $:    PUSH    SI              \ Save some registers.
  779.         PUSH    BP
  780.         XOR     SI, SI          \ Clear Subtractor-hi.
  781.         XOR     BP, BP          \ Clear Subtractor-lo.
  782.         MOV     CX, # 13        \ Set count of 13.
  783.         SHL     DX              \ Shift numerator left by 1.
  784.         RCL     BX
  785.         RCL     AX
  786.         TEST    DI, # 1         \ Do we need another shift?
  787.         JZ      1 $
  788.         SHL     DX              \ Yes.
  789.         RCL     BX
  790.         RCL     AX
  791. 1 $:    SAR     DI              \ Calculate new exponent.
  792.         ADD     DI, # 8192      \ = 2000 in hex.
  793.         JMP     4 $             \ Enter loop in the middle.
  794.  
  795. 2 $:    MOV     0 [BP], AX      \ Zero result case.
  796.         MOV     2 [BP], AX
  797.         MOV     4 [BP], AX
  798.         POP     BP
  799.         NEXT
  800.  
  801. 3 $:    SHL     SI              \ Shift left Subtractor by 1.
  802.         CMP     AX, SI
  803.         JBE     5 $             \ Jump if Num <= Sub.
  804. 4 $:    STC
  805.         SBB     AX, SI          \ Num - Sub -1 -> Num.
  806.         ADD     SI, # 2         \ Put new bit into subtractor.
  807. 5 $:    SHL     DX              \ Shift Num left twice.
  808.         RCL     BX
  809.         RCL     AX
  810.         SHL     DX
  811.         RCL     BX
  812.         RCL     AX
  813.         LOOP    3 $             \ Repeat first iteration 13 times.
  814.         MOV     CX, # 16
  815. 6 $:    SHL     SI              \ Shift subtractor left by 1.
  816.         RCL     BP
  817.         CMP     DX, BP          \ Compare MS parts.
  818.         JA      7 $             \ If Num > Sub, then subtract.
  819.         JB      8 $             \ If Num < Sub, go to shift.
  820.         CMP     AX, SI          \ Compare LS parts.
  821.         JBE     8 $
  822. 7 $:    STC                     \ Subtract case.
  823.         SBB     AX, SI          \ Num - Sub - 1 -> Num.
  824.         SBB     DX, BP
  825.         ADD     SI, # 2         \ Put in new quotient bit.
  826.         ADC     BP, # 0
  827. 8 $:    SHL     BX              \ Shift Num left by 2 places.
  828.         RCL     AX
  829.         RCL     DX
  830.         SHL     BX
  831.         RCL     AX
  832.         RCL     DX
  833.         LOOP    6 $             \ Repeat 16 times.
  834. \ For final iterations, use triple precision.
  835. \ ( BH, DX, AX ) is Num.   ( BL, BP, SI ) is Subtractor.
  836.         MOV     CX, # 4
  837. 9 $:    SHL     SI              \ Shift Subtractor left by 1.
  838.         RCL     BP
  839.         RCL     BL
  840.         CMP     BH, BL          \ Compare MS part.
  841.         JA      10 $
  842.         JB      11 $
  843.         CMP     DX, BP          \ Compare middle part.
  844.         JA      10 $
  845.         JB      11 $
  846.         CMP     AX, SI          \ Compare LS part.
  847.         JBE     11 $
  848. 10 $:   STC
  849.         SBB     AX, SI          \ Num - Sub - 1 -> Num.
  850.         SBB     DX, BP
  851.         SBB     BH, BL
  852.         ADD     SI, # 2
  853.         ADC     BP, # 0
  854.         ADC     BL, # 0
  855. 11 $:   SHL     AX              \ Shift Num left 2 places.
  856.         RCL     DX
  857.         RCL     BH
  858.         SHL     AX
  859.         RCL     DX
  860.         RCL     BH
  861.         LOOP    9 $             \ Iterate 4 times.
  862. \ Main iterations finished.  Now shift answer right by 2 and round.
  863.         SHR     BL
  864.         RCR     BP
  865.         RCR     SI
  866.         SHR     BL
  867.         RCR     BP
  868.         RCR     SI
  869.         JNC     13 $
  870.         TEST    SI, # 1         \ Check LS bit.
  871.         JNZ     12 $
  872.         OR      BH, BH          \ Round to even check.
  873.         JNZ     12 $
  874.         OR      DX, AX
  875.         JZ      13 $
  876. 12 $:   ADD     SI, # 1
  877.         ADC     BP, # 0
  878.         JNC     13 $
  879.         RCR     BP
  880.         RCR     SI
  881.         INC     DI
  882. 13 $:   MOV     AX, BP
  883.         MOV     BX, SI
  884.         POP     BP
  885.         POP     SI
  886.         MOV     4 [BP], BX      \ Push LS part of root.
  887.         MOV     2 [BP], AX      \ Push MS part of root.
  888.         MOV     0 [BP], DI      \ Push Sign+Exponent.
  889.         POP     BP              \ Restore original BP
  890.         NEXT
  891.         END-CODE
  892.  
  893. \ End of Square-root code.
  894.  
  895. HEX
  896. CODE FDUP   ( F: r -- r r )
  897.         MOV     BX, FSP
  898.         MOV     CX, 0 [BX]
  899.         SUB     BX, # 6
  900.         MOV     FSP BX
  901.         MOV     0 [BX], CX
  902.         MOV     CX, 8 [BX]
  903.         MOV     2 [BX], CX
  904.         MOV     CX, 0A [BX]
  905.         MOV     4 [BX], CX
  906.         NEXT
  907.         END-CODE
  908.  
  909. CODE FDROP   ( F: r1 -- )
  910.         ADD     WORD FSP # 6
  911.         NEXT
  912.         END-CODE
  913.  
  914. CODE F2DROP   ( F: r1 r2 -- )
  915.         ADD     WORD FSP # 0C
  916.         NEXT
  917.         END-CODE
  918.  
  919. CODE FNIP   ( F: r1 r2 -- r2 )
  920.         MOV     BX, FSP
  921.         MOV     AX, 0 [BX]
  922.         MOV     6 [BX], AX
  923.         MOV     AX, 2 [BX]
  924.         MOV     8 [BX], AX
  925.         MOV     AX, 4 [BX]
  926.         MOV     0A [BX], AX
  927.         ADD     BX, # 6
  928.         MOV     FSP BX
  929.         NEXT
  930.         END-CODE
  931.  
  932. CODE FOVER   ( F: r1 r2 -- r1 r2 r1 )
  933.         MOV     BX, FSP
  934.         SUB     BX, # 6
  935.         MOV     FSP BX
  936.         MOV     AX, 0C [BX]
  937.         MOV     0 [BX], AX
  938.         MOV     AX, 0E [BX]
  939.         MOV     2 [BX], AX
  940.         MOV     AX, 10 [BX]
  941.         MOV     4 [BX], AX
  942.         NEXT
  943.         END-CODE
  944.  
  945. : F2DUP   ( F: r1 r2 -- r1 r2 r1 r2 )
  946.         FOVER FOVER ;
  947.  
  948. CODE FSWAP   ( F: r1 r2 -- r2 r1 )
  949.         CLEAR_LABELS
  950.         MOV     BX, FSP
  951.         MOV     AX, 0 [BX]
  952.         XCHG    AX, 6 [BX]
  953.         MOV     0 [BX], AX
  954.         MOV     AX, 2 [BX]
  955.         XCHG    AX, 8 [BX]
  956.         MOV     2 [BX], AX
  957.         MOV     AX, 4 [BX]
  958.         XCHG    AX, 0A [BX]
  959.         MOV     4 [BX], AX
  960.         NEXT
  961.         END-CODE
  962.  
  963. CODE FROT   ( F: r1 r2 r3 -- r2 r3 r1 )
  964.         MOV     BX, FSP
  965.         MOV     AX, 0 [BX]
  966.         XCHG    AX, 6 [BX]
  967.         XCHG    AX, 0C [BX]
  968.         MOV     0 [BX], AX
  969.         MOV     AX, 2 [BX]
  970.         XCHG    AX, 8 [BX]
  971.         XCHG    AX, 0E [BX]
  972.         MOV     2 [BX], AX
  973.         MOV     AX, 4 [BX]
  974.         XCHG    AX, 0A [BX]
  975.         XCHG    AX, 10 [BX]
  976.         MOV     4 [BX], AX
  977.         NEXT
  978.         END-CODE
  979.  
  980. CODE F-ROT   ( F: r1 r2 r3 -- r3 r1 r2 )
  981.         MOV     BX, FSP
  982.         MOV     AX, 0 [BX]
  983.         XCHG    AX, 0C [BX]
  984.         XCHG    AX, 6 [BX]
  985.         MOV     0 [BX], AX
  986.         MOV     AX, 2 [BX]
  987.         XCHG    AX, 0E [BX]
  988.         XCHG    AX, 8 [BX]
  989.         MOV     2 [BX], AX
  990.         MOV     AX, 4 [BX]
  991.         XCHG    AX, 10 [BX]
  992.         XCHG    AX, 0A [BX]
  993.         MOV     4 [BX], AX
  994.         NEXT
  995.         END-CODE
  996.  
  997. CODE FPICK  ( F: rn rn-1 ... r0 -- rn rn-1 ... r0 rn ; n -- )
  998.         POP     DI
  999.         ADD     DI, # 1
  1000.         MOV     BX, DI
  1001.         SHL     DI, # 1
  1002.         ADD     DI, BX
  1003.         SHL     DI, # 1
  1004.         MOV     BX, FSP
  1005.         SUB     BX, # 6
  1006.         MOV     FSP BX
  1007.         MOV     AX, 0 [BX+DI]
  1008.         MOV     0 [BX], AX
  1009.         MOV     AX, 2 [BX+DI]
  1010.         MOV     2 [BX], AX
  1011.         MOV     AX, 4 [BX+DI]
  1012.         MOV     4 [BX], AX
  1013.         NEXT
  1014.         END-CODE
  1015.  
  1016. CODE FNSWAP   ( F: rn rn-1 ... r0 -- r0 rn-1 ... r1 rn ; n -- )
  1017.         POP     DI
  1018.         SHL     DI, # 1
  1019.         MOV     BX, DI
  1020.         SHL     DI, # 1
  1021.         ADD     DI, BX          \ n*6
  1022.         MOV     BX, FSP
  1023.         MOV     AX, 0 [BX]
  1024.         XCHG    AX, 0 [BX+DI]
  1025.         MOV     0 [BX], AX
  1026.         ADD     BX, # 2
  1027.         MOV     AX, 0 [BX]
  1028.         XCHG    AX, 0 [BX+DI]
  1029.         MOV     0 [BX], AX
  1030.         ADD     BX, # 2
  1031.         MOV     AX, 0 [BX]
  1032.         XCHG    AX, 0 [BX+DI]
  1033.         MOV     0 [BX], AX
  1034.         NEXT
  1035.         END-CODE
  1036.  
  1037. CODE F0<   ( F: r -- ; -- flag )
  1038.         CLEAR_LABELS
  1039.         MOV     BX, FSP
  1040.         MOV     AX, 0 [BX]
  1041.         MOV     CX, 2 [BX]
  1042.         ADD     BX, # 6
  1043.         MOV     FSP BX
  1044. 0 $:    OR      CX, CX          \ Test for zero
  1045.         JNS     1 $
  1046.         OR      AX, AX
  1047.         JNS     1 $
  1048. 2 $:    MOV     AX, # -1
  1049.         PUSH    AX
  1050.         NEXT
  1051. 1 $:    XOR     AX, AX
  1052.         PUSH    AX
  1053.         NEXT
  1054.         END-CODE
  1055.  
  1056. CODE FDUP0<   ( F: r1 -- r1 ; -- flag )
  1057.         MOV     BX, FSP
  1058.         MOV     AX, 0 [BX]
  1059.         MOV     CX, 2 [BX]
  1060.         JMP     0 $
  1061.         END-CODE
  1062.  
  1063. CODE F0>   ( F: r -- ; -- flag )
  1064.         MOV     BX, FSP
  1065.         MOV     AX, 0 [BX]
  1066.         MOV     CX, 2 [BX]
  1067.         ADD     BX, # 6
  1068.         MOV     FSP BX
  1069.         OR      CX, CX
  1070.         JNS     1 $
  1071.         OR      AX, AX
  1072.         JS      1 $
  1073.         JMP     2 $
  1074.         END-CODE
  1075.  
  1076. CODE F0=   ( F: r -- ; -- flag )
  1077.         MOV     BX, FSP
  1078.         MOV     AX, 2 [BX]
  1079.         ADD     BX, # 6
  1080.         MOV     FSP BX
  1081.         OR      AX, AX
  1082.         JNS     2 $
  1083.         JMP     1 $
  1084.         END-CODE
  1085.  
  1086. CODE FDUP0=   ( F: r -- r ; -- flag )
  1087.         MOV     BX, FSP
  1088.         MOV     AX, 2 [BX]
  1089.         OR      AX, AX
  1090.         JNS     2 $
  1091.         JMP     1 $
  1092.         END-CODE
  1093.  
  1094. CODE F=    ( F: r1 r2 -- ; -- flag )
  1095.         CLEAR_LABELS
  1096.         MOV     BX, FSP
  1097.         MOV     AX, 2 [BX]      \ Get MS fraction of top f.p. number
  1098.         MOV     DX, 8 [BX]      \ Get MS fraction of second f.p. number
  1099.         MOV     CX, AX
  1100.         OR      AX, DX
  1101.         JNS     1 $             \ Jump if r1 and r2 are both zero
  1102.         XOR     DX, CX
  1103.         MOV     AX, 0 [BX]      \ Get Sign and Exponent of top f.p. number
  1104.         XOR     AX, 6 [BX]      \ This code is fairly fast because
  1105.         OR      DX, AX          \ it avoids most conditional branches.
  1106.         MOV     AX, 4 [BX]
  1107.         XOR     AX, 0A [BX]
  1108.         OR      DX, AX
  1109.         XOR     AX, AX
  1110.         ADD     DX, # -1
  1111.         SBB     AX, # 0
  1112.         NOT     AX
  1113.         PUSH    AX
  1114.         ADD     BX, # 0C
  1115.         MOV     FSP BX
  1116.         NEXT
  1117.  
  1118. 1 $:    MOV     AX, # -1
  1119.         PUSH    AX
  1120.         ADD     BX, # 0C
  1121.         MOV     FSP BX
  1122.         NEXT
  1123.  
  1124.         END-CODE
  1125.  
  1126. CODE F2DUP>   ( F: r1 r2 -- ; -- flag )
  1127.         CLEAR_LABELS
  1128.         MOV     BX, FSP
  1129.         MOV     DI, 2 [BX]      \ MS fract of r2
  1130.         OR      DI, DI
  1131.         JNS     1 $             \ Jump if r2 = 0
  1132.         MOV     CX, 8 [BX]      \ MS fract of r1
  1133.         OR      CH, CH
  1134.         JNS     2 $             \ Jump if r1 = 0
  1135.         MOV     AX, 0 [BX]      \ SX of r2
  1136.         OR      AH, AH
  1137.         JS      3 $             \ Jump if r2 < 0
  1138.         MOV     DX, 6 [BX]      \ SX of r1
  1139.         OR      DH, DH
  1140.         JS      5 $             \ Jump if (r1 < 0) and (r2 > 0)
  1141. 8 $:    CMP     DX, AX          \ Signs are positive.
  1142.         JA      7 $             \ Jump if Exponent of r1 > Exponent of r2
  1143.         JB      5 $             \ Jump if Exponent of r1 < Exponent of r2
  1144.         CMP     CX, DI          \ Exponents are equal.  Check MS parts
  1145.         JA      7 $             \ Jump if MS part of r1 > MS part of r2
  1146.         JB      5 $             \ Jump if MS part of r1 < MS part of r2
  1147.         MOV     CX, 0A [BX]     \ LS part of r1
  1148.         CMP     CX, 4 [BX]      \ Compare with LS part of r2
  1149.         JA      7 $
  1150.         JMP     5 $
  1151.  
  1152. 1 $:    MOV     AX, 8 [BX]      \ r2 = 0 case.  Check r1.
  1153.         OR      AH, AH
  1154.         JNS     5 $             \ Jump if r1 = r2 = 0
  1155.         MOV     DX, 6 [BX]
  1156.         OR      DH, DH
  1157.         JNS     7 $             \ Jump if r1 > 0
  1158. 5 $:    XOR     AX, AX          \ Push a false flag.
  1159.         PUSH    AX
  1160.         NEXT
  1161.  
  1162. 2 $:    MOV     AX, 0 [BX]      \ r1 = 0 case.  Test r2.
  1163.         OR      AX, AX
  1164.         JNS     5 $
  1165. 7 $:    MOV     AX, # -1        \ Push a true flag
  1166.         PUSH    AX
  1167.         NEXT
  1168.  
  1169. 3 $:    MOV     DX, 6 [BX]      \ r2 < 0 case.  Get SX of r1
  1170.         OR      DX, DX
  1171.         JNS     7 $
  1172. 9 $:    CMP     DX, AX          \ r1 and r2 both negative case.
  1173.         JB      7 $
  1174.         JA      5 $
  1175.         CMP     CX, DI          \ exp1 = exp2 and signs both negative.
  1176.         JB      7 $             \ Check MS part of fraction.
  1177.         JA      5 $
  1178.         MOV     CX, 4 [BX]      \ MS parts are equal.  Check LS parts
  1179.         MOV     DI, 0A [BX]
  1180.         CMP     DI, CX
  1181.         JB      7 $
  1182.         JMP     5 $
  1183.         END-CODE
  1184.  
  1185. CODE F2DUP<   ( F: r1 r2 -- ; -- flag )
  1186.         MOV     BX, FSP
  1187.         MOV     DI, 2 [BX]
  1188.         OR      DI, DI
  1189.         JNS     0B $            \ Jump if r2 = 0
  1190.         MOV     CX, 8 [BX]
  1191.         OR      CH, CH
  1192.         JNS     0C $            \ Jump if r1 = 0
  1193.         MOV     AX, 0 [BX]
  1194.         OR      AH, AH
  1195.         JS      0D $            \ Jump if r2 < 0
  1196.         MOV     DX, 6 [BX]
  1197.         OR      DX, DX
  1198.         JS      7 $             \ If r1 < 0, result is true.
  1199.         JMP     9 $
  1200.  
  1201. 0B $:   MOV     AX, 8 [BX]
  1202.         OR      AH, AH          \ r2 = 0 case.  Check r1
  1203.         JNS     5 $             \ If r1 = 0, result is false.
  1204.         MOV     DX, 6 [BX]
  1205.         OR      DH, DH
  1206.         JNS     5 $             \ r2 = 0.  If r1 >0, result is false.
  1207.         JMP     7 $
  1208.  
  1209. 0C $:   MOV     AX, 0 [BX]      \ r1 = 0 case. Check sign of r2.
  1210.         OR      AH, AH
  1211.         JS      5 $             \ If r2 < 0, result is false.
  1212.         JMP     7 $
  1213.  
  1214. 0D $:   MOV     DX, 6 [BX]
  1215.         OR      DX, DX          \ r2 < 0 case.  Check r1.
  1216.         JNS     5 $             \ If r1 > 0, result is false.
  1217.         JMP     8 $
  1218.         END-CODE
  1219.  
  1220. : F<    ( F: r1 r2 -- ; -- flag )
  1221.         F2DUP< F2DROP ;
  1222.  
  1223. : F>    ( F: r1 r2 -- ; -- flag )
  1224.         F2DUP> F2DROP ;
  1225.  
  1226. : F<=   ( F: r1 r2 -- ; -- flag )
  1227.         F2DUP> F2DROP 0= ;
  1228.  
  1229. : F>=   ( F: r1 r2 -- ; -- flag )
  1230.         F2DUP< F2DROP 0= ;
  1231.  
  1232. : FMAX  ( F: r1 r2 -- r3 )
  1233.         F2DUP>  IF  FDROP  ELSE  FNIP  THEN ;
  1234.  
  1235. : FMIN  ( F: r1 r2 -- r3 )
  1236.         F2DUP<  IF  FDROP  ELSE  FNIP  THEN ;
  1237.  
  1238. CODE FABS   ( F: r1 -- r2 )
  1239.         MOV     BX, FSP
  1240.         AND     WORD 0 [BX], # 7FFF
  1241.         NEXT
  1242.         END-CODE
  1243.  
  1244. CODE FNEGATE   ( F: r1 -- r2 )
  1245.         MOV     BX, FSP
  1246.         XOR     WORD 0 [BX], # 8000
  1247.         NEXT
  1248.         END-CODE
  1249.  
  1250. DECIMAL
  1251.  
  1252.  
  1253.