home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / gnu / libsrc87 / sflonum.s < prev    next >
Encoding:
Text File  |  1993-07-30  |  8.9 KB  |  431 lines

  1. #
  2. #    Single prec. Floating point support code.  
  3. #
  4. #    A float looks like:
  5. #
  6. #    |S|E.x.p ... |M.a.n.t.i.s.s.a ... |
  7. #    +-+----------+--------------------+
  8. #
  9. #    where s is the sign bit, Exp is 8 bits of exponent, interpreted
  10. #    as E + 126, and Mantissa is 23 bits of fraction, with a
  11. #    hidden bit.  The point is to the left of the hidden bit.
  12. #
  13. #    All these routines have calling sequences like c routines,
  14. #    ie args on stack in backwards order, return values in d0
  15. #
  16.  
  17.  
  18. .text
  19.     .even
  20. .globl ___addsf3
  21. .globl __addsf3
  22. ___addsf3:
  23. __addsf3:
  24.     link    a6,#0        | dont need any locals
  25.     moveml    #0x3F00,sp@-    | save all data registers
  26.     movel    a6@(8),d0    | get a
  27.     beq    addsf_ret_b    |  zero .. just return b
  28.     movel    #23,d6        | shift count
  29.     movel    d0,d2        | get the exponent
  30.     lsrl    d6,d2        | and shift right
  31.     andl    #0xFF,d2    | no sign bit
  32.     subl    #126,d2        | offset the exponent
  33.     movel    a6@(12),d1    | get b
  34.     beq    addsf_ret_a
  35.     movel    d1,d3        | get the exponent for b
  36.     lsrl    d6,d3        | and shift right, with implicit extend
  37.     andl    #0xFF,d3    | make sure we didnt get a sign bit
  38.     subl    #126,d3        | off set this one too
  39.  
  40.     andl    #0x7FFFFF,d0    | mask a for mantissa
  41.     orl    #0x800000,d0    | and put in hidden bit
  42.     tstl    a6@(8)        | test the original value
  43.     bpl    addsf_1        | pos, ok
  44.     negl    d0        | neg, negate the mantissa
  45. addsf_1:
  46.     andl    #0x7FFFFF,d1    | mask b for mantissa
  47.     orl    #0x800000,d1    | ditto
  48.     tstl    a6@(12)        | test ...
  49.     bpl    addsf_2
  50.     negl    d1        | negate this one
  51. addsf_2:
  52.     cmpl    d2,d3        | compare Ea to Eb
  53.     blt    addsf_3        | Ea > Eb
  54.  
  55.     movel    d3,d5        | get Eb
  56.     subl    d2,d5        | subtract Ea
  57.     asrl    d5,d0        |  yielding count to shift Ma right
  58.     movel    d3,d5        | use this as resultant exponent
  59.     bra    addsf_4        | and go rejoin common part
  60. addsf_3:
  61.     movel    d2,d5        | get Ea
  62.     subl    d3,d5        | subtract Eb
  63.     asrl    d5,d1        |  yielding count to shift Mb right
  64.     movel    d2,d5        | use this as resultant exponent
  65.  
  66. addsf_4:
  67.     clrl    d7        | zap sign flag
  68.     addl    d1,d0        | add Mb to Ma
  69.  
  70.  
  71.     beq    addsf_z        | zero? ok, go return zero
  72.     bpl    addsf_5        | positive? ok, go scale it
  73.     negl    d0        | negate Mr
  74.     movel    #1,d7        | remember sign
  75. addsf_5:
  76.     btst    #24,d0        | carry?
  77.     beq    addsf_6        | nope, its ok as is
  78.     asrl    #1,d0        | shift right one
  79.     addql    #1,d5        | inc exp
  80.  
  81. | zzz check for overflow in here someplace
  82.  
  83. addsf_6:
  84.     btst    #23,d0        | got a bit in the right place yet?
  85.     bne    addsf_7        | yes, were done
  86.     lsll    #1,d0        | shift left one
  87.     subql    #1,d5        | dec exponent
  88.     bra    addsf_6
  89. addsf_7:
  90.     andl    #0x7FFFFF,d0    | zap out hidden bit
  91.     addl    #126,d5        | add offset to exp
  92.     andl    #0xFF,d5    | zap to 8 bits
  93.     movel    #23,d6        | shift count
  94.     lsll    d6,d5        | shift the exp up
  95.     orl    d5,d0        | stick the exp in
  96.     tstl    d7        | negative?
  97.     beq    addsf_ret_a
  98.     orl    #0x80000000,d0    | yup, negate it
  99.     bra    addsf_ret_a
  100. addsf_z:
  101.     clrl    d0
  102.     bra    addsf_ret_a
  103. addsf_ret_b:
  104.     movel    a6@(12),d0
  105. addsf_ret_a:
  106.     moveml    sp@+,#0x00FC    | snarf back all regs
  107.     unlk    a6
  108.     rts            | sigh
  109. # #ifdef L_negsf2
  110. # int
  111. # _negsf2 (a)
  112. #      union flt_or_int a;
  113. # {
  114. #   union flt_or_int intify;
  115. #   return INTIFY (-a.f);
  116. # }
  117. # #endif
  118.  
  119. .text
  120.     .even
  121. .globl ___negsf2
  122. .globl __negsf2
  123. ___negsf2:
  124. __negsf2:
  125.     movel    sp@(4),d0
  126.     beq    negsf2_z
  127.     eorl    #0x80000000,d0
  128. negsf2_z:
  129.     rts            | sigh
  130. # #ifdef L_subsf3
  131. # int
  132. # _subsf3 (a, b)
  133. #      union flt_or_int a, b;
  134. # {
  135. #   union flt_or_int intify;
  136. #   return INTIFY (a.f - b.f);
  137. # }
  138. # #endif
  139.  
  140. .text
  141.     .even
  142. .globl ___subsf3
  143. .globl __subsf3
  144. ___subsf3:
  145. __subsf3:
  146.     tstl    sp@(8)        | kludge.  just negate b and add
  147.     beq    subsf_bz    | zero.  dont bother
  148.     eorl    #0x80000000,sp@(8)    | negate it
  149.     jmp    ___addsf3
  150. subsf_bz:
  151.     movel    sp@(4),d0
  152.     rts
  153.  
  154. # #ifdef L_cmpsf2
  155. # int
  156. # _cmpsf2 (a, b)
  157. #      union flt_or_int a, b;
  158. # {
  159. #   union flt_or_int intify;
  160. #   if (a.f > b.f)
  161. #     return 1;
  162. #   else if (a.f < b.f)
  163. #     return -1;
  164. #   return 0;
  165. # }
  166. # #endif
  167.  
  168. .text
  169.     .even
  170. .globl ___cmpsf2
  171. .globl __cmpsf2
  172. ___cmpsf2:
  173. __cmpsf2:
  174.     movel    sp@(4),d0    | get a
  175.     movel    sp@(8),d1    | get b
  176.  
  177.     bpl    cmpsf2_p
  178.     tstl    d0
  179.     bpl    cmpsf2_p
  180.     cmpl    d1,d0
  181.     bgt    cmpsf2_m
  182.     blt    cmpsf2_1
  183. cmpsf2_z:
  184.     clrl    d0
  185.     rts
  186. cmpsf2_p:
  187.     cmpl    d1,d0
  188.     bgt    cmpsf2_1
  189.     beq    cmpsf2_z
  190. cmpsf2_m:
  191.     movel    #-1,d0
  192.     rts
  193. cmpsf2_1:
  194.     movel    #1,d0
  195.     rts            | sigh
  196. # #ifdef L_mulsf3
  197. # int
  198. # _mulsf3 (a, b)
  199. #      union flt_or_int a, b;
  200. # {
  201. #   union flt_or_int intify;
  202. #   return INTIFY (a.f * b.f);
  203. # }
  204. # #endif
  205.  
  206. .text
  207.     .even
  208. .globl ___mulsf3
  209. .globl __mulsf3
  210. ___mulsf3:
  211. __mulsf3:
  212. |
  213. | multiply.  take the numbers apart.  shift each exponent down to
  214. | 16 bits.  unsigned multiply those.  shift that down to 24 bits.
  215. | exponent is Ea + Eb.
  216. |
  217.  
  218.     link    a6,#-8        | 64 bit accum for mult
  219.     moveml    #0x3F00,sp@-    | save all data registers
  220.     movel    a6@(8),d0    | get a
  221.     beq    mulsf3_z
  222.     movel    a6@(12),d1    | get b
  223.     beq    mulsf3_z
  224.     movel    #23,d6        | shift count
  225.     movel    d0,d2        | get the exponent
  226.     lsrl    d6,d2        | and shift right
  227.     andl    #0xFF,d2
  228.     subl    #126,d2        | offset the exponent
  229.     movel    d1,d3        | get the exponent for b
  230.     lsrl    d6,d3        | and shift right
  231.     andl    #0xFF,d2
  232.     subl    #126,d3        | off set this one too
  233.  
  234.     clrl    d7        | negative result flag
  235.     andl    #0x7FFFFF,d0    | mask a for mantissa
  236.     orl    #0x800000,d0    | and put in hidden bit
  237.     tstl    a6@(8)        | test the original value
  238.     bpl    mulsf3_1    | pos, ok
  239.     eorl    #1,d7        | remember negative
  240. mulsf3_1:
  241.     andl    #0x7FFFFF,d1    | mask b for mantissa
  242.     orl    #0x800000,d1    | ditto
  243.     tstl    a6@(12)        | test ...
  244.     bpl    mulsf3_2
  245.     eorl    #1,d7
  246. mulsf3_2:
  247. |    lsrl    #8,d1        | shift this one down
  248. |    lsrl    #8,d0        | this one too...
  249. |    mulu    d1,d0        | do the multiply
  250.  
  251. |    beq    mulsf3_ret    | zero? ok, just return
  252. |    lsrl    #8,d0        | shift right again
  253.  
  254. |
  255. | we have mantissas as follows:
  256. |
  257. |    |...ah...|...al...|    |...bh...|...bl...|
  258. |
  259. | product is composed as:
  260. |
  261. |            |....al * bl....|
  262. |        |....al * bh....|
  263. |        |....ah * bl....|
  264. |    |....ah * bh....|
  265. |
  266. | then take the 24 bit chunk thats 16 bits in.
  267.  
  268.     movel    d0,d4
  269.     andl    #0xFFFF,d4    | al
  270.     movel    d1,d5
  271.     andl    #0xFFFF,d5    | bl
  272.     mulu    d5,d4        | thats al * bl
  273.     movel    d4,a6@(-4)    | into the accum
  274.     clrl    a6@(-8)        | zap the top part
  275.  
  276.     movel    d0,d4
  277.     andl    #0xFFFF,d4    | al
  278.     movel    d1,d5
  279.     movel    #16,d6        | shift count
  280.     lsrl    d6,d5        | bh
  281.     mulu    d5,d4        | al * bh
  282.     addl    d4,a6@(-6)
  283.  
  284.     movel    d0,d4
  285.     lsrl    d6,d4        | ah
  286.     movel    d1,d5
  287.     andl    #0xFFFF,d5    | bl
  288.     mulu    d5,d4        | ah * bl
  289.     addl    d4,a6@(-6)
  290.  
  291.     movel    d0,d4
  292.     lsrl    d6,d4        | ah
  293.     movel    d1,d5
  294.     lsrl    d6,d5        | bh
  295.     mulu    d5,d4        | ah * bh
  296.     addl    d4,a6@(-8)
  297.  
  298.     movel    a6@(-6),d0    | get the relevant part
  299.     lsrl    #8,d0        | and shift it down
  300.  
  301. mulsf3_norm:
  302.     btst    #23,d0        | normalized?
  303.     bne    mulsf3_ok
  304.     lsll    #1,d0
  305.     subql    #1,d2
  306.     bra    mulsf3_norm
  307.  
  308. mulsf3_ok:
  309.     andl    #0x7FFFFF,d0    | zap hidden bit
  310.     addl    d3,d2        | add Eb to Ea
  311.     addl    #126,d2        | fix offset
  312.     andl    #0xFF,d2    | whack to 8 bits
  313.     movel    #23,d6        | shift count
  314.     lsll    d6,d2        | shift up to right place
  315.     orl    d2,d0        | shove it in
  316.     tstl    d7        | sign neg?
  317.     beq    mulsf3_ret
  318.     orl    #0x80000000,d0    | set sign bit
  319.     bra    mulsf3_ret
  320. mulsf3_z:
  321.     clrl    d0
  322. mulsf3_ret:
  323.     moveml    sp@+,#0x00FC    | snarf back all regs
  324.     unlk    a6
  325.     rts            | sigh
  326. # #ifdef L_divsf3
  327. # int
  328. # _divsf3 (a, b)
  329. #      union flt_or_int a, b;
  330. # {
  331. #   union flt_or_int intify;
  332. #   return INTIFY (a.f / b.f);
  333. # }
  334. # #endif
  335.  
  336. .text
  337.     .even
  338. .globl ___divsf3
  339. .globl __divsf3
  340. ___divsf3:
  341. __divsf3:
  342. |
  343. | divide.  sort of like mult, exc we do shifts and subtracts to
  344. | do the division of the mantissa.  resultant exponent is Ea - Eb.
  345. |
  346.  
  347.     link    a6,#0        | dont need any locals
  348.     moveml    #0x3F00,sp@-    | save all data registers
  349.     movel    a6@(8),d0    | get a
  350.     movel    a6@(12),d1    | get b
  351.     movel    #23,d6        | shift count
  352.     movel    d0,d2        | get the exponent
  353.     lsrl    d6,d2        | and shift right
  354.     andl    #0xFF,d2
  355.     subl    #127,d2        | offset the exponent
  356.     movel    d1,d3        | get the exponent for b
  357.     lsrl    d6,d3        | and shift right
  358.     andl    #0xFF,d3
  359.     subl    #127,d3        | off set this one too
  360.  
  361.     clrl    d7        | negative result flag
  362.     andl    #0x7FFFFF,d0    | mask a for mantissa
  363.     orl    #0x800000,d0    | and put in hidden bit
  364.     tstl    a6@(8)        | test the original value
  365.     bpl    divsf3_1    | pos, ok
  366.     eorl    #1,d7        | remember negative
  367. divsf3_1:
  368.     andl    #0x7FFFFF,d1    | mask b for mantissa
  369.     orl    #0x800000,d1    | ditto
  370.     tstl    a6@(12)        | test ...
  371.     bpl    divsf3_2
  372.     eorl    #1,d7
  373. divsf3_2:
  374. |
  375. | for now, kludge.  shift Ma left and Mb right, then do an unsigned divide
  376. | and shift the result left.  Blech
  377. |
  378.  
  379. |    lsrl    #8,d1        | shift this one down
  380. |    lsll    #7,d0        | this one up
  381. |    divu    d1,d0        | do the divide
  382. |    andl    #0xFFFF,d0    | and mask off cruft
  383.  
  384. |    beq    divsf3_ret    | zero? ok, just return
  385. |    lsll    #8,d0        | shift left again
  386.  
  387. | same sort of trick as long divide, exc its easier here, cause
  388. | the numbers (mantissas) are already bit-aligned.
  389.  
  390.     clrl    d4        | accumulator
  391.     movel    #0x800000,d5    | bit
  392.     lsll    #7,d0        | buy a little extra accuracy...
  393.     lsll    #7,d1
  394. divsf3_2a:
  395.     cmpl    d1,d0        | compare dividend to divisor
  396.     bmi    divsf3_2b    | nope, no bit here
  397.     orl    d5,d4        | put in the bit
  398.     subl    d1,d0        | and subtract
  399. divsf3_2b:
  400.     lsrl    #1,d1        | slide divisor down
  401.     lsrl    #1,d5        | slide bit down
  402.     bne    divsf3_2a    | and go round again
  403.     movel    d4,d0        | leave the result here
  404.  
  405. divsf3_3:
  406.     btst    #23,d0        | right place yet?
  407.     bne    divsf3_4
  408.     lsll    #1,d0
  409.     subql    #1,d2
  410.     bra    divsf3_3
  411. divsf3_4:
  412.     andl    #0x7FFFFF,d0    | zap hidden bit
  413.     subl    d3,d2        | sub Eb from Ea
  414.     addl    #127,d2        | fix offset
  415.     andl    #0xFF,d2    | whack to 8 bits
  416.     lsll    d6,d2        | shift up to right place
  417.     orl    d2,d0        | shove it in
  418.     tstl    d7        | sign neg?
  419.     beq    divsf3_ret
  420.     orl    #0x80000000,d0    | set sign bit
  421. divsf3_ret:
  422.     moveml    sp@+,#0x00FC    | snarf back all regs
  423.     unlk    a6
  424.  
  425.     rts            | sigh
  426.