home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / DRI-archive / roche / FLTARITH.ASM < prev    next >
Assembly Source File  |  2009-12-11  |  19KB  |  912 lines

  1. ; FLTARITH.ASM
  2. ; ------------
  3. ;
  4. ; See FALCONER.WS4 for doc.
  5. ;
  6. ; (Retyped by Emmanuel ROCHE.)
  7. ;
  8. ;--------------------------------
  9. ; External routines required
  10. ;
  11.     extrn    aerc        ; Arithmetic error trap
  12. ;
  13. ;--------------------------------
  14. ; External routine in INTARITH.ASM
  15. ;
  16.     extrn    c1de,c2bc,c2de,derc,dhlz
  17.     extrn    idiv,imul,stadr
  18. ;
  19. ;--------------------------------
  20. ; Allowable entry points
  21. ;
  22. ; Data manipulation
  23. ;
  24.     entry    hlrd,fxchg
  25. ;
  26. ; Memory addressing
  27. ;
  28.     entry    lfds,lfbs,fload,fstor
  29.     entry    lfbis,lfdis,sfdis
  30. ;
  31. ; Arithmetic operators
  32. ;
  33.     entry    fmult,fdivt,fmul
  34.     entry    fdiv,fdivr,frcip
  35.     entry    fadd,fsub,fsubr
  36. ;
  37. ; Testing, integer extraction
  38. ;
  39.     entry    fcmp,fint
  40. ;
  41. ; Format conversion
  42. ;
  43.     entry    flota,flotp,flotd,flot
  44.     entry    fixt,fixr
  45. ;
  46. ;--------------------------------
  47. ; Macro definitions
  48. ;--------------------------------
  49. ;
  50. ; Change sign of real operand B or D
  51. ;
  52. fsign    macro    reg
  53. bc.l    equ    b
  54. de.h    equ    d
  55.     if    reg*(reg-d)
  56.     error    "R"
  57.     endif
  58.     mov    a,reg
  59.     xri    80H
  60.     mov    reg,a
  61.     endm
  62. ;
  63. ; Load (& pop) real (reg) from TOS, stored by SFTS macro
  64. ;
  65. lfts    macro    reg
  66. bc.l    equ    b
  67. de.h    equ    d
  68.     pop    reg
  69.     mov    5-reg/2,reg
  70.     pop    reg
  71.     if    reg*(reg-d)
  72.     error    "R"
  73.     endif
  74.     endm
  75. ;
  76. ; Load (reg) from TOS & leave on stack (reg)
  77. ;
  78. ltos    macro    reg
  79.     pop    reg
  80.     push    reg
  81.     endm
  82. ;
  83. ; Move operation on register pair B, D, or H
  84. ;
  85. movd    macro    r1,r2
  86.     if    ((r1-d)*(r1-h)*r1) OR ((r2-d)*(r2-h)*r2)
  87.     error    "R"
  88.     endif
  89.     mov    r1,r2
  90.     mov    r1+1,r2+1
  91.     endm
  92. ;
  93. ; Move floating operand from Reg1 to Reg2
  94. ;
  95. movf    macro    r2,r1
  96. bc.l    equ    b
  97. de.h    equ    d
  98.     if    (r1*(r1-d)) OR (r2*(r2-d))
  99.     error    "R"
  100.     endif
  101.     mov    r2,r1
  102.     mov    r2+1,r1+1
  103.     mov    5-r2/2,5-r1/2
  104.     endm
  105. ;
  106. ; Reload (BC.L), stored by PUSH B, PUSH H sequence
  107. ;
  108. reload    macro    reg
  109. bc.l    equ    b
  110.     if    reg-B
  111.     error    "R"
  112.     db    0,0,0
  113.     endif
  114.     if    reg-b=0        ; Was IFZ
  115.     pop    b
  116.     mov    l,c
  117.     pop    b
  118.     endif
  119.     endm
  120. ;
  121. ; "Return" and check stack level zero
  122. ;
  123. rtn    macro
  124.     if    .lvl
  125.     error    "0"+.lvl
  126. .lvl    set    0
  127.     endif
  128.     ret
  129.     endm
  130. ;
  131. ; Save (BC.L), to be restored by RELOAD BC.L later
  132. ;
  133. save    macro    reg
  134. bc.l    equ    b
  135.     if    reg-b
  136.     error    'R'
  137.     db    0,0
  138.     endif
  139.     if    reg-b=0        ; Was IFZ
  140.     push    b
  141.     push    h
  142.     endif
  143.     endm
  144. ;
  145. ; Store real value on top of stack; note SFTS B affects (A)
  146. ;
  147. sfts    macro    r
  148. bc.l    equ    b
  149. de.h    equ    d
  150.     if    r*(r-d)
  151.     error    'R'
  152.     endif
  153.     if    r=0        ; Was IFZ
  154.     mov    a,l
  155.     endif
  156.     push    r
  157.     push    psw-r
  158.     endm
  159. ;
  160. ;--------------------------------
  161. ; Auxiliary routines
  162. ;--------------------------------
  163. ;
  164. ; Normalize the 32 bit value in (DEHL) left
  165. ; and round to 16 bits. Discard the high order
  166. ; bit. (B) returns shift count (in offset binary).
  167. ; Return Carry for value zero.
  168. ; A,F,B,D,E,H,L
  169. ;
  170. hlrd:    mvi    b,80H        ; 
  171.     mov    a,d        ; 
  172.     ora    a        ; 
  173.     jm    hlrd2        ; Normalized
  174.     ora    e        ; 
  175.     ora    h        ; 
  176.     ora    l        ; 
  177.     stc            ; 
  178.     rz            ; Zero value
  179. hlrd1:    dcr    b        ; 
  180.     call    dhlz        ; Left shift
  181.     jp    hlrd1        ; 
  182. hlrd2:    ani    7FH        ; 
  183.     mov    d,a        ; Discard high order bit
  184.     mov    a,h        ; 
  185.     ora    a        ; Check for rounding
  186.     rp            ; Not needed
  187.     inr    e        ; Round up
  188.     rnz            ; No Carry
  189.     inr    d        ; 
  190.     rp            ; No overflow
  191.     inr    b        ; Modify shift count
  192.     mov    d,e        ; Set result
  193.     rtn            ; 
  194. ;
  195. ; Set the high order bits in (BC) and (DE) for
  196. ; arithmetic operations. Discard original signs.
  197. ; Reset Carry.
  198. ; A,F,B,D
  199. ;
  200. sethi:    mov    a,b        ; 
  201.     ori    80H        ; 
  202.     mov    b,a        ; 
  203.     mov    a,d        ; 
  204.     ori    80H        ; 
  205.     mov    d,a        ; 
  206.     rtn            ; 
  207. ;
  208. ; Exchange floating operands
  209. ; A,B<=>D,C<=>E,H<=>L
  210. ;
  211. fxchg:    mov    a,b        ; 
  212.     mov    b,d        ; 
  213.     mov    d,a        ; 
  214.     mov    a,c        ; 
  215.     mov    c,e        ; 
  216.     mov    e,a        ; 
  217.     mov    a,l        ; 
  218.     mov    l,h        ; 
  219.     mov    h,a        ; 
  220.     rtn            ; 
  221. ;
  222. ; Load (DE.H) from stack level (A)
  223. ; Value was stored with PUSH D, PUSH H sequence.
  224. ; A,F,D,E,H
  225. ;
  226. lfds:    push    h        ; 
  227.     call    stadr        ; Get abs address
  228.     inx    h        ; 
  229.     mov    a,m        ; Get exponent
  230.     inx    h        ; 
  231.     mov    e,m        ; 
  232.     inx    h        ; 
  233.     mov    d,m        ; Get mantissa
  234.     pop    h        ; 
  235.     mov    h,a        ; 
  236.     rtn            ; 
  237. ;
  238. ; Load (BC.L) from stack level (A)
  239. ; Value was stored by PUSH D, PUSH H sequence.
  240. ; A,F,B,C,L
  241. ;
  242. lfbs:    push    h        ; 
  243.     call    stadr        ; Get abs address
  244.     inx    h        ; 
  245.     mov    a,m        ; Get exponent
  246.     inx    h        ; 
  247.     mov    c,m        ; Get mantissa
  248.     inx    h        ; 
  249.     mov    b,m        ; 
  250.     pop    h        ; 
  251.     mov    l,a        ; 
  252.     rtn            ; 
  253. ;
  254. ; Load indirect (BC.L) via stack level (A) ptr
  255. ; A,F,B,C,L
  256. ;
  257. lfbis:    push    h        ; 
  258.     call    stadr        ; Form abs address
  259.     mov    a,m        ; LS mem address
  260.     inx    h        ; 
  261.     mov    h,m        ; MS mem address
  262.     mov    l,a        ; 
  263.     mov    a,m        ; Get exponent
  264.     inx    h        ; 
  265.     mov    c,m        ; 
  266.     inx    h        ; 
  267.     mov    b,m        ; Get mantissa
  268.     pop    h        ; 
  269.     mov    l,a        ; 
  270.     rtn            ; 
  271. ;
  272. ; Load indirect (DE.H) via stack level (A) ptr
  273. ; A,F,D,E,H
  274. ;
  275. lfdis:    push    h        ; 
  276.     call    stadr        ; Form abs address
  277.     mov    a,m        ; LS mem address
  278.     inx    h        ; 
  279.     mov    h,m        ; MS mem address
  280.     mov    l,a        ; 
  281.     mov    a,m        ; Get exponent
  282.     inx    h        ; 
  283.     mov    e,m        ; 
  284.     inx    h        ; 
  285.     mov    d,m        ; Get mantissa
  286.     pop    h        ; 
  287.     mov    h,a        ; 
  288.     rtn            ; 
  289. ;
  290. ; Store (DE.D) indirect via stack level (A) ptr
  291. ; A,F
  292. ;
  293. sfdis:    push    h        ; 
  294.     push    b        ; 
  295.     mov    c,m        ; Keep exponent
  296.     inr    a        ; Allow for PUSH B
  297.     call    stadr        ; Get abs address
  298.     mov    a,m        ; 
  299.     inx    h        ; 
  300.     mov    h,m        ; 
  301.     mov    l,a        ; Get pointer
  302.     mov    m,c        ; Store exponent
  303.     inx    h        ; 
  304.     mov    m,e        ; 
  305.     inx    h        ; 
  306.     mov    m,d        ; Store mantissa
  307.     pop    b        ; 
  308.     pop    h        ; 
  309.     rtn            ; 
  310. ;
  311. ; Load (DE.H) via pointer (BC); advance (BC)
  312. ; B,C,D,E,H
  313. ;
  314. fload:    push    psw        ; 
  315.     ldax    b        ; 
  316.     mov    m,a        ; 
  317.     inx    b        ; 
  318.     ldax    b        ; 
  319.     mov    e,a        ; Mantissa
  320.     inx    b        ; 
  321.     ldax    b        ; 
  322.     mov    d,a        ; Exponent
  323.     inx    b        ; Setup for next time
  324.     pop    psw        ; 
  325.     rtn            ; 
  326. ;
  327. ; Store (DE.H) via pointer (BC); advance (BC)
  328. ; B,C
  329. ;
  330. fstor:    push    psw        ; 
  331.     mov    a,h        ; 
  332.     stax    b        ; 
  333.     inx    b        ; 
  334.     mov    a,e        ; 
  335.     stax    b        ; 
  336.     inx    b        ; 
  337.     mov    a,d        ; 
  338.     stax    b        ; 
  339.     inx    b        ; Setup for next time
  340.     pop    psw        ; 
  341.     rtn            ; 
  342. ;
  343. ;--------------------------------
  344. ; Floating point arithmetic system for YALE 8080-based
  345. ; computers -- by Charles B. FALCONER, April 1976
  346. ;
  347. ; Real representation can express values in the absolute value
  348. ; range 0.29388 * 10^-38 through 1.7018 * 10^+38, and zero,
  349. ; together with sign, with approximately 4.8 decimal digit
  350. ; accuracy. The resolution of a value between 1 and 2 is
  351. ; approximately 0.00003. The system is designed to maximize
  352. ; register (as opposed to memory) use during computation.
  353. ;
  354. ; A real (floating point) value is represented by a unipolar
  355. ; 16 bit mantissa, whose value is in the range 1.0 > mantissa
  356. ; > -1.0. The mantissa absolute value is always >= 0.5.
  357. ; Thus, the high order bit of the mantissa is always a "one",
  358. ; and is replaced by a sign bit in internal representation.
  359. ; A "one" sign bit represents negative values.
  360. ;
  361. ; Real values are stored in 3 adjacent memory bytes:
  362. ;   Lowest address: exponent
  363. ;     Next address: least significant byte of mantissa
  364. ;  Highest address: most  significant byte of mantissa
  365. ;
  366. ; Real operands can appear in either of two 8080 internal
  367. ; register configurations. The normal position (considered
  368. ; the real accumulator) is the DE.H register, in which the
  369. ; D and E registers hold the mantissa (sign bit in D), and
  370. ; the M register holds the exponent. A second operand may
  371. ; be held in the BC.L register, where the B and C registers
  372. ; hold the mantissa, and the L register holds the exponent.
  373. ;
  374. ; Note the storage and load macros SFTS and LFTS above for
  375. ; stacking and unstacking floating values. Also note that
  376. ; "SFTS B" will disturb the A and F registers,
  377. ; while "SFTS D" will not.
  378. ;
  379. ; The SAVE and RELOAD macros above do not use the standard
  380. ; memory format, and operate only on the BC.L internal
  381. ; register group.
  382. ;
  383. ;--------------------------------
  384. ; Code for the arithmetic system proper
  385. ;--------------------------------
  386. ;
  387. ; Flating multiply by 10; (DE.H) := 10 * (DE.H)
  388. ; Carry for overflow, returns max value
  389. ; A,F,D,E,H
  390. ;
  391. fmult:    save    bc.l        ; 
  392.     lxi    b,2000H        ; 10.0
  393.     mvi    l,84H        ; 
  394.     call    fmul        ; 
  395.     reload    fmul        ; 
  396.     rtn            ; 
  397. ;
  398. ; Floating div by 10; (DE.H) := (DE.H) * 0.10000
  399. ; Carry for underflow, returns zero
  400. ; A,F,D,E,H
  401. ;
  402. fdivt:    save    bc.l        ; 
  403.     lxi    b,4CCDH        ; 0.10000
  404.     mvi    l,80H-3        ; 
  405.     call    fmul        ; 
  406.     reload    bc.l        ; 
  407.     rtn            ; 
  408. ;
  409. ; Floating multiply (DE.H) := (DE.H) * (BC.L)
  410. ; Carry for overflow or underflow, when
  411. ; maximum or zero values are returned.
  412. ; A,F,D,E,H
  413. ;
  414. fmul:    mov    a,h        ; 
  415.     ora    a        ; 
  416.     rz            ; Acc zero, return same
  417.     mov    a,l        ; 
  418.     ora    a        ; 
  419.     jnz    fmul1        ; (BC.L) not zero
  420.     mov    h,l        ; (BC.L) zero, return zero
  421.     rtn            ; 
  422. fmul1:    mov    a,d        ; 
  423.     xra    b        ; Form result sign
  424.     push    b        ; 
  425.     push    h        ; Save (BC.L)
  426.     push    psw        ; Save result sign
  427.     call    sethi        ; Set hi order operand bit
  428.     call    imul        ; Perform multiplication
  429.     call    hlrd        ; Normalize and round
  430.     pop    psw        ; 
  431.     ani    80H        ; Result sign
  432.     ora    d        ; 
  433.     mov    d,a        ; Set result sign
  434.     mov    a,b        ; Shift count
  435.     pop    h        ; Original exponents
  436.     pop    b        ; Original BC
  437. ;
  438. ; Add exponents H := H + L + A; all in offset code
  439. ; Carry for overflow, when set extremes in (DE.H)
  440. ; A,F,H (DE)
  441. ;
  442. addx:    add    h        ; 
  443.     push    psw        ; Save Carry
  444.     add    l        ; 
  445.     mov    h,a        ; Result
  446.     jc    addx1        ; One overflow required
  447. @01    set    .lvl        ; 
  448.     pop    psw        ; 
  449.     cmc            ; 
  450.     rnc            ; In range
  451.     mvi    h,00H        ; Underflow
  452.     rtn            ; 
  453. .lvl    set    @01        ; 
  454. addx1:    pop    psw        ; Had 1st Carry
  455.     rnc            ; In range
  456. ;
  457. ; Set max value for exponent overflow
  458. ; A,F,D,E,H
  459. ;
  460. ovex:    mvi    h,0FFH        ; Overflow, set max
  461.     mov    e,h        ;   and mantissa
  462.     mov    a,d        ; 
  463.     ori    7FH        ; Prserve result sign
  464.     mov    d,a        ; 
  465.     stc            ; Mark overflow
  466.     rtn            ; 
  467. ;
  468. ; Floating divide (DE.H) := (DE.H) / (BC.L)
  469. ; Carry for overflow or underflow when
  470. ; maximum or zero values are returned.
  471. ; Division by zero causes a system trap.
  472. ; A,F,D,E,H
  473. ;
  474. fdiv:    mov    a,l        ; 
  475.     ora    a        ; 
  476.     cz    aerc        ; Division by zero, fatal
  477.     rc            ; 
  478. fdiv1:    mov    a,h        ; 
  479.     ora    a        ; 
  480.     rz            ; 0/non-zero=0
  481.     mov    a,d        ; 
  482.     xra    b        ; Form result sign
  483.     push    b        ; 
  484.     push    h        ; 
  485.     push    psw        ; 
  486.     call    sethi        ; 
  487.     call    derc        ; Extend and position dividend
  488.     mvi    l,0        ; 
  489.     mov    a,l        ; 
  490.     rar            ; Last bit
  491.     mov    h,a        ; 
  492.     call    idiv        ; Returns 15 or 16 bits
  493.     push    d        ; Save quotient
  494.     mxi    d,0        ; 
  495.     call    c2bc        ; 
  496.     mvi    a,-2        ; Need 2 more bits for rounding
  497. fdiv2:    push    psw        ; Save iterations count
  498.     dad    h        ; Left shift (HLDE)
  499.     rar            ; Save Carry out
  500.     xchg            ; 
  501.     dad    h        ; 
  502.     xchg            ; 
  503.     jnc    fdiv3        ; No Carry into L
  504.     inx    h        ; 
  505. fdiv3:    ral            ; Regain Carry from H
  506.     jc    fdiv4        ; Yes, generate quotient bit
  507.     mov    a,l        ; 
  508.     add    c        ; Test for quotient bit
  509.     mov    a,h        ; 
  510.     adc    b        ; 
  511.     jnc    fdiv5        ; No bit
  512. fdiv4:    dad    b        ; Subtract
  513.     inx    d        ; Insert quotient bit
  514. fdiv5:    pop    psw        ; Get iteration count
  515.     inr    a        ; 
  516.     jn    fdiv2        ; Not done
  517.     mov    a,e        ; 
  518.     rrc            ; 
  519.     rrc            ; 
  520.     mov    h,a        ; Extend quotient
  521.     pop    d        ; Restore quotient
  522.     call    hlrd        ; Normalize and round
  523.     inr    b        ; Correct bin point
  524.     pop    psw        ; 
  525.     ltos    h        ; Original exponent
  526.     ani    80H        ; 
  527.     ora    d        ; 
  528.     mov    d,a        ; Form result sign
  529.     mov    a,l        ; 
  530.     cma            ; 
  531.     inr    a        ; Complement divisor exponent
  532.     mov    l,b        ; Shift count
  533.     call    addx        ; Form result exponent
  534.     mov    a,h        ; 
  535.     pop    h        ; Original exponent
  536.     mov    h,a        ; 
  537.     pop    b        ; 
  538.     rtn            ; With any addx Carry
  539. ;
  540. ; Floating reverse div (DE.H) := (BC.L) / (DE.H)
  541. ; Carry for overflow or underflow when
  542. ; maximum or zero values are returned.
  543. ; Division by zero causes a system trap.
  544. ; A,F,D,E,H
  545. ;
  546. fdivr:    save    bc.l        ; 
  547.     call    fxchg        ; 
  548.     call    fdiv        ; 
  549.     reload    bc.l        ; 
  550.     rtn            ; 
  551. ;
  552. ; Floating reciprocal (DE.H) := 1.0 / (DE.H)
  553. ; Division by zero (orig (DE.H) causes system trap
  554. ; A,F,D,E,H
  555. ;
  556. frcip:    save    bc.l        ; 
  557.     movf    b,d        ; 
  558.     lxi    d,0        ; 
  559.     mvi    h,81H        ; Floating 1.0
  560.     call    fdiv        ; 
  561.     reload    bc.l        ; 
  562.     rtn            ; 
  563. ;
  564. ; Align operands for add
  565. ; Returns two 24 bit values in (BC.L) and (DE.H)
  566. ; with binary points aligned. The actual binary
  567. ; point is that of the larger (on input) magnitude
  568. ; plus 1; i.e., right shifted one place. This allows
  569. ; space for overflows on addition.
  570. ; A,F,B,C,D,E,H,L
  571. ;
  572. alin:    mov    a,h        ; 
  573.     sub    l        ; 
  574.     ora    a        ; Reset any Carry
  575.     push    psw        ; Relative magnitudes
  576.     mov    a,b        ; BC.L := (BC OR 8000H) SHR 1
  577.     ori    80H        ; 
  578.     rar            ; 
  579.     mov    b,a        ; 
  580.     mov    a,c        ; 
  581.     rar            ; 
  582.     mov    c,a        ; 
  583.     mov    a,0        ; 
  584.     rar            ; 
  585.     mov    l,a        ; 
  586.     mov    a,d        ; DE := (DE OR 8000H) SHR 1
  587.     ori    80H        ; 
  588.     rar            ; 
  589.     mov    d,a        ; 
  590.     mov    a,e        ; 
  591.     rar            ; 
  592.     mov    e,a        ; 
  593.     mov    a,0        ; 
  594.     rar            ; 
  595.     mov    h,a        ; 
  596. alin1:    pop    psw        ; 
  597.     rz            ; Aligned
  598.     jp    alin2        ; DE mag > BC mag
  599.     inr    a        ; BC mag > DE mag
  600.     push    psw        ; Save rel mag
  601.     mov    a,d        ; Shift DE.H right, 0 in
  602.     rar            ; 
  603.     mov    d,a        ; 
  604.     mov    a,e        ; 
  605.     rar            ; 
  606.     mov    e,a        ; 
  607.     mov    a,h        ; 
  608.     rar            ; 
  609.     mov    h,a        ; 
  610.     jmp    alin1        ; Now test
  611. .lvl    set    .lvl-1        ; 
  612. alin2:    dcr    a        ; 
  613.     push    psw        ; 
  614.     mov    a,b        ; Shift BC.L right, 0 in
  615.     rar            ; 
  616.     mov    b,a        ; 
  617.     mov    a,c        ; 
  618.     rar            ; 
  619.     mov    c,a        ; 
  620.     mov    a,l        ; 
  621.     rar            ; 
  622.     mov    l,a        ; 
  623.     jmp    .lvl-1        ; 
  624. .lvl    set    .lvl-1        ; 
  625. ;
  626. ; Floating reverse subtract (DE.H) := (BC.L) - (DE.H)
  627. ; Carry for over/underflow, sets extreme value
  628. ; A,F,D,E,H
  629. ;
  630. fsubr:    fsign    d        ; Change D sign
  631. ;
  632. ; Floating add (DE.H) := (DE.H) + (BC.L)
  633. ; Carry for over/underflow, sets extreme value
  634. ; A,F,D,E,H
  635. ;
  636. fadd:    mov    a,l        ; 
  637.     ora    a        ; 
  638.     rz            ; BC.L = 0
  639.     mov    a,h        ; 
  640.     ora    a        ; 
  641.     jnz    fadd2        ; DE.H <> 0
  642. fadd1:    movf    d,b        ; DE.H << BC.L
  643.     rtn            ; 
  644. fadd2:    sub    l        ; 
  645.     jc    fadd3        ; BC mag > DE mag
  646.     cpi    16+1        ; 
  647.     rnc            ; BC.L << DE.H
  648.     mov    a,h        ; Will be result magnitude
  649.     jmp    fadd4        ; 
  650. fadd3:    cpi    -16        ; 
  651.     cmc            ; 
  652.     jnc    fadd1        ; DE.H << BC.L
  653.     mov    a,l        ; Will be result magnitude
  654. fadd4:    save    bc.l        ; 
  655.     push    psw        ; Save result magnitude
  656.     mov    a,b        ; 
  657.     xra    d        ; 
  658.     mov    a,b        ; 
  659.     jp    fadd5        ; Signs same
  660. @01    set    .lvl        ; 
  661.     ana    b        ; Signs different
  662.     cp    fxchg        ; DE.H neg, BC.L pos
  663.     call    alin        ; Now, DE.H pos and BC.L neg
  664.     mov    a,h        ; 
  665.     sub    l        ; 
  666.     mov    h,a        ; 
  667.     mov    a,e        ; 
  668.     sbb    c        ; Perform subtraction
  669.     mov    e,a        ; 
  670.     mov    a,d        ; 
  671.     sbb    b        ; 
  672.     mov    d,a        ; 
  673.     push    psw        ; Save result sign
  674.     jp    fadd6        ; No complement needed
  675.     call    c1de        ; 
  676.     mov    a,h        ; 
  677.     cma            ; 
  678.     inr    a        ; 
  679.     mov    h,a        ; 
  680.     jnz    fadd6        ; No propagation
  681.     inx    d        ; 
  682.     jmp    fadd6        ; Now magnitude, sign is stacked
  683. .lvl    set    @01        ; 
  684. fadd5:    push    psw        ; Result sign
  685.     call    alin        ; 
  686.     mov    a,h        ; 
  687.     add    l        ; 
  688.     mov    h,a        ; Add mantissa
  689.     mov    a,e        ; 
  690.     adc    c        ; 
  691.     mov    e,a        ; 
  692.     mov    a,d        ; 
  693.     adc    b        ; 
  694.     mov    d,a        ; 
  695. fadd6:    xra    a        ; 
  696.     mov    l,a        ; 
  697.     ora    d        ; 
  698.     ora    e        ; 
  699.     ora    m        ; 
  700. @01     set     .lvl        ; 
  701.     jnz    fadd7        ; Result not zero
  702.     pop    psw        ; Purge sign
  703.     pop    psw        ; Purge magnitude
  704.     ora    a        ; Reset any Carry
  705.     jmp    fadd8        ; 
  706. .lvl    set    @01        ; 
  707. fadd7:    call    hlrd        ; 
  708.     pop    psw        ; 
  709.     ani    80H        ; 
  710.     ora    d        ; 
  711.     mov    d,a        ; Set result sign
  712.     mov    h,b        ; 
  713.     mvi    l,81H        ; 
  714.     pop    psw        ; Saved result magnitude
  715.     call    addx        ; Set result magnitude
  716. fadd8:    reload    bc.l        ; 
  717.     rtn            ; With addx Carry if overflow
  718. ;
  719. ; Floating subtract (DE.H) := (DE.H) - (BC.L)
  720. ; Carry for over/underflow, sets extreme value
  721. ; A,F,D,E,H
  722. ;
  723. fsub:    save    bc.l        ; 
  724.     fsign    b        ; Change B sign
  725.     call    fadd        ; 
  726.     reload    bc.l        ; 
  727.     rtn            ; 
  728. ;
  729. ; Floating compare, set flags for (DE.H) - (BC.L)
  730. ;  Zero flag if equal
  731. ;  Plus flag if (DE.H) >= (BC.L)
  732. ; Minus falg if (DE.H) <  (BC.L)
  733. ; A,F
  734. ;
  735. fcmp:    mov    a,l        ; 
  736.     ora    a        ; 
  737.     jnz    fcmp1        ; BC.L <> zero
  738.     mov    a,h        ; 
  739.     ora    a        ; 
  740.     rz            ; Both zero
  741.     mov    a,d        ; 
  742.     ori    l        ; Set flags according to DE.H
  743.     rtn            ;   sign.
  744. fcmp1:    mov    a,h        ; 
  745.     ora    a        ; 
  746.     jz    fcmp2        ; (DE.H) = 0, flags inverse
  747.     sub    l        ;   of (BC.L) sign.
  748.     jz    fcmp4        ; Magnitude same
  749.     mov    a,d        ; 
  750.     jp    fcmp3        ; DE.H controlling magnitude
  751. fcmp2:    mov    a,b        ; BC.L controlling magnitude
  752.     cma            ; 
  753. fcmp3:    ori    01H        ; Set flags via appropriate
  754.     rtn            ;   operand sign.
  755. fcmp4:    ora    b        ; Check signs
  756.     jm    fcmp5        ; (BC.L) < 0
  757.     ora    d        ; (BC.L) > 0, check (DE.H)
  758.     rn            ; (DE.H) < 0
  759.     mov    a,e        ; Both >= 0
  760.     sub    c        ; 
  761.     mov    a,d        ; 
  762.     sbb    b        ; 
  763.     rtn            ; 
  764. fcmp5:    mov    a,d        ; 
  765.     ori    01H        ; 
  766.     rp            ; (DE.H) > 0 and (BC.L) < 0
  767.     mov    a,c        ; 
  768.     sub    e        ; Both < 0
  769.     mov    a,b        ; 
  770.     sbb    d        ; 
  771.     rtn            ; 
  772. ;
  773. ; Convert signed integer (A) to real DE.H)
  774. ; A,F,D,E,H
  775. ;
  776. flota:    ora    a        ; 
  777.     mov    h,a        ; 
  778.     rz            ; Zero
  779.     mov    d,a        ; 
  780.     mvi    e,00H        ; 
  781.     ani    80H        ; 
  782. flot5:    push    psw        ; Save sign
  783.     mvi    h,80H        ; Binary point
  784.     mov    a,d        ; 
  785.     jp    flot2        ; 
  786.     cma            ; 
  787.     inr    a        ; 
  788.     mov    d,a        ; 
  789.     jmp    flot2        ; -ve input
  790. .lvl    set    .lvl-1        ; 
  791. ;
  792. ; Convert positive integer (A) to real (DE.H)
  793. ; A,F,D,E,H
  794. ;
  795. flotp:    ora    a        ; 
  796.     mov    h,a        ; 
  797.     rz            ; Zero
  798.     mov    d,a        ; 
  799.     xra    a        ; 
  800.     mov    e,a        ; 
  801.     jmp    flot5        ; 
  802. ;
  803. ; Convert positive integer (DE) to real (DE.H)
  804. ; A,F,D,E,H
  805. ;
  806. flotd:    xra    a        ; 
  807.     mov    h,a        ; 
  808.     jmp    flot1        ; 
  809. ;
  810. ; Extract integer portion of (DE.H) in real form
  811. ; A,F,D,E,H
  812. ;
  813. fint:    call    fixt        ; Convert to integer
  814.     cnc            ; 
  815.     rnc            ; Already integer
  816. ;
  817. ; Convert signed integer (DE) to real (DE.H)
  818. ; A,F,D,E,H
  819. ;
  820. flot:    mvi    h,00H        ; 
  821.     mov    a,d        ; 
  822.     ani    80H        ; 
  823. flot1:    push    psw        ; Save sign
  824.     cm    c2de        ; Magnitude
  825.     mov    a,d        ; 
  826.     ora    e        ; 
  827.     jz    flot3        ; Zero value
  828.     mvi    h,90H        ; Binary point
  829. flot2:    mov    a,d        ; 
  830.     ora    a        ; 
  831.     jp    flot4        ; Further normalizing
  832.     ani    7FH        ; 
  833.     mov    d,a        ; 
  834. flot3:    pop    psw        ; Get sign
  835.     ora    d        ; 
  836.     mov    d,a        ; 
  837.     rtn            ; 
  838. flot4:    xchg            ; 
  839.     dad    h        ; Left sign
  840.     xchg            ; 
  841.     dcr    h        ; Adjust binary point
  842.     jmp    flot2        ; 
  843. ;
  844. ; Convert real (DE.H) to signed integer (truncate)
  845. ; (DE.H) := signed integer result, truncated.
  846. ; Carry if not 32767 >= value >= -32768, unconverted.
  847. ; A,F,D,E,H
  848. ;
  849. fixt:    mov    a,h        ; 
  850.     ora    a        ; 
  851.     jnz    fixt2        ; Non-zero
  852. fixt1:    xra    a        ; 
  853.     mov    d,a        ; Zero integer part
  854.     mov    e,a        ; 
  855.     rtn            ; 
  856. fixt2:    jp    fixt1        ; No integer part
  857.     sui    81H        ; 
  858.     jm    fixt1        ; No integer part
  859.     sui    15        ; 
  860.     jnz    fixt3        ; Magnitude < 32768
  861.     mov    a,d        ; 
  862.     sui    80H        ; 
  863.     stc            ; 
  864.     rnz            ; Not -32768
  865.     ora    e        ; 
  866.     rz            ; Exactly -32768
  867.     stc            ; 
  868.     rtn            ; Oversize
  869. fixt3:    cnc            ; 
  870.     rc            ; Oversize
  871.     mov    h,a        ; Binary point 0 for 1 to 2
  872.     mov    a,d        ; 
  873.     push    psw        ; 
  874.     ori    80H        ; 
  875.     mov    d,a        ; 
  876. fixt4:    ora    a        ; 
  877.     call    derc        ; Right shift, 0 in
  878.     inr    h        ; 
  879.     jm    fixt4        ; 
  880.     pop    psw        ; 
  881.     ora    a        ; 
  882.     rp            ; Positive
  883.     jmp    c2de        ; Insert sign
  884. ;
  885. ; Fix and round (DE.H) to signed integer in (DE)
  886. ; Return Carry if mag > 32767, without converting
  887. ; A,F,D,E,H
  888. ;
  889. fixr:    save    bc.l        ; 
  890.     sfts    d        ; Save in case of error
  891.     lxi    b,7FFFH        ; 
  892.     mov    l,b        ; 0.49999 to prevent FADD
  893.     mov    a,d        ;   roundup.
  894.     ora    a        ; 
  895.     jp    fixr1        ; (DE.H) > 0
  896.     fsign    b        ; 
  897. fixr1:    call    fadd        ; Round
  898.     call    fixt        ; Fix
  899. @01    set    .lvl        ; 
  900.     jc    fixr2        ; Overflow error
  901.     pop    b        ; Purge original argument
  902.     pop    b        ; 
  903.     jmp    fixr3        ; Restore BC.L
  904. .lvl    set    @01        ; 
  905. fixr2:    lfts    d        ; Restore argument
  906. fixr3:    reload    bc.l        ; 
  907.     rtn            ; 
  908. ;
  909. ;--------------------------------
  910. ;
  911.     end            ; of FLTARITH.ASM
  912.