home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / lang / thinkc30.sit / Math881.a < prev    next >
Text File  |  1989-01-15  |  12KB  |  624 lines

  1.             MACHINE    MC68020
  2.             MC68881
  3.     
  4.             BLANKS    ON
  5.             CASE ON
  6.             STRING    ASIS
  7.  
  8. ; Assembly source for the Math881 math library.
  9. ; Version 3.0
  10. ; by Rich Siegel (with assistance from Steve Stein)
  11. ; ⌐1988 Symantec Corp.
  12.  
  13. ;
  14. ; LightspeedC pushes the parameters in reverse order; also, the first parameter
  15. ; pushed is a hidden argument that contains the address of the function
  16. ; result.
  17. ;
  18. ; Floating-point arguments are pushed by value.
  19. ;
  20. ;    
  21. ;    The one-argument transcendentals follow a common template: simply
  22. ;    evaluate what's on the stack with FP0 as the destination, load the
  23. ;    function result address into A0, and then do a FMOVE.X FP0, (A0)
  24. ;    to store the function result.
  25. ;
  26. ;    Since none of the floating-point registers are scratch, these
  27. ;    routines preserve the registers that they use. 
  28. ;
  29.  
  30. ;    in Math881.a the function names begin with the underscore character;
  31. ; this is useful when the _ERRORCHECK_ symbol is defined in <Math881.h>. 
  32. ; the user can call an underscore directly, or he can call the function
  33. ; as it's defined in Math881.c, and get the full benefit of the standard
  34. ; C error checking. For example, using tan() or _tan().
  35. ;
  36. ;    When _ERRORCHECK_ is not defined, the library calls are simply macros
  37. ; to call the underscore functions.
  38.  
  39. ;
  40. ;    int abs(int i);
  41. ;
  42. ; stack:
  43. ;    4 byte return address
  44. ;    i is at 4(a7)
  45.  
  46. abs            proc export
  47.             move.w    4(a7), d0
  48.             bge.s     @1
  49.             neg.w    d0
  50.             
  51. @1            rts
  52.  
  53. ;        
  54. ;    double acos(double x);
  55. ;
  56. ; stack frame:
  57. ;     12 bytes saved registers
  58. ;    4 byte return address
  59. ;    x        equ    20
  60. ;    result     equ 16
  61.  
  62. _acos        proc export
  63.  
  64.             fmovem         fp0, -(a7)        ; preserve registers
  65.             facos.x     20(a7), fp0        ; arccos
  66.             movea.l     16(a7), a0        ; load address of result
  67.             fmove.x        fp0, (a0)        ; load result
  68.             fmovem        (a7)+, fp0        ; restore registers
  69.             rts
  70.  
  71. ;
  72. ;    double asin(double x);
  73. ;
  74. ; stack frame:
  75. ;     12 bytes saved registers
  76. ;    4 byte return address
  77. ;    x        equ    20
  78. ;    result     equ 16
  79.  
  80. _asin        proc export
  81.  
  82.             fmovem         fp0, -(a7)
  83.             fasin.x     20(a7), fp0
  84.             movea.l     16(a7), a0
  85.             fmove.x        fp0, (a0)
  86.             fmovem        (a7)+, fp0
  87.             rts
  88.             
  89. ;
  90. ;    double atan(double x);
  91. ;
  92. ; stack frame:
  93. ;     12 bytes saved registers
  94. ;    4 byte return address
  95. ;    x        equ    20
  96. ;    result     equ 16
  97.  
  98. _atan        proc export
  99.  
  100.             fmovem         fp0, -(a7)
  101.             fatan.x     20(a7), fp0
  102.             movea.l     16(a7), a0
  103.             fmove.x        fp0, (a0)
  104.             fmovem        (a7)+, fp0
  105.             rts
  106.  
  107. ;
  108. ;    double atan2(double y, double x);
  109. ;
  110.  
  111. _atan2        proc export
  112.  
  113.             fmovem        fp0/fp1, -(a7)        ; preserve fp0 and fp1
  114.             movea.l        28(a7), a0            ; load address of result
  115.             fmove.x        32(a7), fp0            ; load y
  116.             fmove.x        44(a7), fp1            ; load x (we'll use it later)            
  117.             fdiv.x        fp1, fp0            ; divide by x
  118.             fatan.x        fp0                    ; arctan
  119.                         
  120.             fcmp.w        #0, fp1                ; is x < zero?
  121.             fbge        @1
  122.             
  123.             fmove.x        32(a7), fp1            ; put a fresh copy of y into fp1
  124.             fcmp.w        #0, fp1                ; is y < zero?
  125.             fbge        @2                    
  126.             fmovecr        #0, fp1                ; if it is, subtract pi from result.
  127.             fsub.x        fp1, fp0
  128.             bra.s        @1                    ; ...and go home.
  129.             
  130. @2            fmovecr        #0, fp1                ; otherwise, add pi to result.
  131.             fadd.x        fp1, fp0
  132.             
  133. @1            fmove.x        fp0, (a0)            ; store result
  134.             fmovem        (a7)+, fp0/fp1        ; restore registers
  135.  
  136.             rts
  137.             
  138. ;
  139. ;    double ceil(double x);
  140. ;
  141. ; stack frame:
  142. ;     12 bytes saved registers
  143. ;    4 byte return address
  144. ;    x        equ    20
  145. ;    result     equ 16
  146.  
  147. _ceil        proc export
  148.             fmovem        fp0, -(a7)            ; preserve fp0
  149.  
  150.             fmove.l        fpcr, d0            ; fetch the 68881 control register
  151.             move.l        d0, d1                ; save a copy in D1
  152.             
  153.             ori.l        #$0030, d0            ; OR in the rounding control
  154.             fmove.l        d0, fpcr            ; set up the FPCR
  155.             
  156.             fint.x        20(a7), fp0            ; calculate nearest integer of arg
  157.             
  158.             fmove.l        d1, fpcr            ; restore the fpcr from the copy
  159.             
  160.             movea.l        16(a7), a0            ; load addr of result, and...
  161.             fmove.x        fp0, (a0)            ; ...load the result
  162.  
  163.             fmovem        (a7)+, fp0            ; restore registers
  164.             rts
  165.  
  166. ;
  167. ;    double cos(double x); /* same schema as acos, asin, atan */
  168. ;
  169. ; stack frame:
  170. ;     12 bytes saved registers
  171. ;    4 byte return address
  172. ;    x        equ    20
  173. ;    result     equ 16
  174.  
  175. _cos        proc export
  176.  
  177.             fmovem         fp0, -(a7)
  178.             fcos.x         20(a7), fp0
  179.             movea.l     16(a7), a0
  180.             fmove.x        fp0, (a0)
  181.             fmovem        (a7)+, fp0
  182.             rts
  183.             
  184. ;
  185. ;    double cosh(double x);
  186. ;
  187. ; stack frame:
  188. ;     12 bytes saved registers
  189. ;    4 byte return address
  190. ;    x        equ    20
  191. ;    result     equ 16
  192.  
  193. _cosh        proc export
  194.  
  195.             fmovem         fp0, -(a7)
  196.             fcosh.x     20(a7), fp0
  197.             movea.l     16(a7), a0
  198.             fmove.x        fp0, (a0)
  199.             fmovem        (a7)+, fp0
  200.             rts
  201.  
  202. ;
  203. ;     double exp(double x);
  204. ;
  205. ; stack frame:
  206. ;     12 bytes saved registers
  207. ;    4 byte return address
  208. ;    x        equ    20
  209. ;    result     equ 16
  210.  
  211. _exp        proc export
  212.  
  213.             fmovem         fp0, -(a7)
  214.             fetox.x     20(a7), fp0
  215.             movea.l     16(a7), a0
  216.             fmove.x        fp0, (a0)
  217.             fmovem        (a7)+, fp0
  218.             rts
  219.             
  220. ;
  221. ;    double fabs(double x);
  222. ;
  223. ; stack frame:
  224. ;     12 bytes saved registers
  225. ;    4 byte return address
  226. ;    x        equ    20
  227. ;    result     equ 16
  228.  
  229. _fabs        proc export
  230.  
  231.             fmovem         fp0, -(a7)
  232.             FABS.x         20(a7), fp0
  233.             movea.l     16(a7), a0
  234.             fmove.x        fp0, (a0)
  235.             fmovem        (a7)+, fp0
  236.             rts
  237.  
  238. ;
  239. ;    double floor(double x);
  240. ;
  241. ;    this function works the same as ceil(), except that the value to OR in
  242. ;    is $20 instead of $30.
  243. ;
  244. ; stack frame:
  245. ;     12 bytes saved registers
  246. ;    4 byte return address
  247. ;    x        equ    20
  248. ;    result     equ 16
  249.  
  250. _floor        proc export
  251.             fmovem        fp0, -(a7)
  252.  
  253.             fmove.l        fpcr, d0
  254.             move.l        d0, d1
  255.             
  256.             ori.l        #$0020, d0
  257.             fmove.l        d0, fpcr
  258.             
  259.             fint.x        20(a7), fp0
  260.             
  261.             fmove.l        d1, fpcr
  262.             
  263.             movea.l        16(a7), a0
  264.             fmove.x        fp0, (a0)
  265.             fmovem        (a7)+, fp0
  266.  
  267.             rts
  268.             
  269. ;
  270. ;    double fmod(double y, double x);
  271. ;
  272. ; stack frame:
  273. ;     12 bytes saved registers
  274. ;    4 byte return address
  275. ;    x        equ    32
  276. ;    y        equ    20
  277. ;    result     equ 16
  278.  
  279. _fmod        proc export
  280.             fmovem         fp0, -(a7)            ; save the registers
  281.             fmove.x        20(a7), fp0            ; load Y
  282.             fmod.x        32(a7), fp0            ; call the '881's FMOD
  283.             movea.l        16(a7), a0            ; load address of result
  284.             fmove.x        fp0, (a0)            ; load result
  285.             fmovem        (a7)+, fp0            ; restore registers
  286.             rts
  287.             
  288. ;
  289. ;    double frexp(double x, int *nptr);
  290. ;
  291. ;    This function is machine-dependent, and relies on the internal representation
  292. ;    of the double floating-point data type.
  293. ;
  294. ; stack frame:
  295. ;     12 bytes saved registers
  296. ;    4 byte return address
  297. ;    nptr    equ    32
  298. ;    x        equ    20
  299. ;    result     equ 16
  300.  
  301. _frexp        proc export
  302.             fmovem        fp0, -(a7)
  303.  
  304.             movea.l        16(a7), a0            ; load result address
  305.             movea.l        32(a7), a1            ; load nptr
  306.             fmove.x        20(a7), fp0            ; fetch X
  307.  
  308.             fcmp.w        #0, fp0                ; if X is zero, then
  309.             fbne         @2
  310.             move.w        #0, (a1)            ; both parts of result are zero
  311.             fmove.x        fp0, (a0)            ; return x (since it is also zero)
  312.             bra.s        @3                    ; goodbye...
  313.             
  314. @2            move.w        20(a7), d0            ; get the exponent of X
  315.             move.w        d0, d1                ; keep a copy
  316.             bge.s        @1
  317.             andi.w        #$7FFF, d0            ; mask off the mantissa sign bit
  318.             
  319. @1            subi.w        #$3FFE, d0            ; subtract the exponent bias (less one)
  320.             
  321.             andi.w        #$8000, d1            ; preserve mantissa's sign bit
  322.             ori.w        #$3FFE, d1            ; put in an exponent of (-1)
  323.             move.w        d1, 20(a7)            ; and smash that over X's old exponent
  324.             
  325.             fmove.x        20(a7), fp0            ; fetch X (again)
  326.             fmove.x        fp0, (a0)            ; store it in result
  327.             move.w        d0, (a1)            ; and store *nptr
  328.  
  329. @3            fmovem        (a7)+, fp0
  330.             rts
  331.                         
  332. ;
  333. ;    long labs(long l);
  334. ;
  335. ; stack:
  336. ;    4 byte return address
  337. ;    l is at 4(a7)
  338.  
  339. labs        proc export
  340.             move.l    4(a7), d0
  341.             bge.s     @1
  342.             neg.l    d0
  343.             
  344. @1            rts
  345.  
  346. ;
  347. ;    double ldexp(double x, int n);
  348. ;
  349. ; stack frame:
  350. ;     12 bytes saved registers
  351. ;    4 byte return address
  352. ;    n        equ    32
  353. ;    x        equ 20
  354. ;    result     equ 16
  355.  
  356. _ldexp        proc export
  357.             fmovem        fp0, -(a7)
  358.             
  359.             movea.l        16(a7), a0        ; load result address
  360.             fmove.w        32(a7), fp0        ; load N into a float register
  361.             ftwotox        fp0                ; raise two to that power.
  362.             fmul.x        20(a7), fp0        ; multiply by X
  363.  
  364.             fmove.x        fp0, (a0)        ; load result
  365.             fmovem        (a7)+, fp0
  366.             rts
  367.             
  368. ;
  369. ;    double log(double x);
  370. ;
  371. ; stack frame:
  372. ;     12 bytes saved registers
  373. ;    4 byte return address
  374. ;    x        equ    20
  375. ;    result     equ 16
  376.  
  377. _log        proc export
  378.  
  379.             fmovem         fp0, -(a7)
  380.             flogn.x     20(a7), fp0
  381.             movea.l     16(a7), a0
  382.             fmove.x        fp0, (a0)
  383.             fmovem        (a7)+, fp0
  384.             rts
  385.  
  386. ;
  387. ;    double log10(double x);
  388. ;
  389. ; stack frame:
  390. ;     12 bytes saved registers
  391. ;    4 byte return address
  392. ;    x        equ    20
  393. ;    result     equ 16
  394.  
  395. _log10        proc export
  396.  
  397.             fmovem         fp0, -(a7)
  398.             flog10.x     20(a7), fp0
  399.             movea.l     16(a7), a0
  400.             fmove.x        fp0, (a0)
  401.             fmovem        (a7)+, fp0
  402.             rts
  403.  
  404. ;
  405. ;    double modf(double x, double *ip);
  406. ;
  407.  
  408. ; stack frame:
  409. ; 24 bytes of saved registers
  410. ; 4 bytes return addr
  411. ;    result    equ    28
  412. ;    x        equ    32
  413. ;    ip        equ    44
  414.  
  415. _modf        proc export
  416.                         
  417.             fmovem        fp0/fp1, -(a7)
  418.             
  419.             movea.l        28(a7), a0                    ; address of result
  420.             movea.l        44(a7), a1                    ; address of int part
  421.             fmove.x        32(a7), fp0                    ; argument
  422.             
  423.             fintrz.x    fp0, fp1                    ; leaves integer part in fp1
  424.             fmove.x        fp1, (a1)                    ; store integer part
  425.             fsub.x        fp1, fp0
  426.             
  427.             fmove.x        fp0, (a0)                    ; store function result
  428.             
  429.             fmovem        (a7)+, fp0/fp1
  430.             rts
  431.             
  432.  
  433. ;
  434. ;    double pow(double x, double y);
  435. ;
  436. ; stack frame:
  437. ;     12 bytes saved registers
  438. ;    4 byte return address
  439. ;    y        equ    32
  440. ;    x        equ 20
  441. ;    result     equ 16
  442.  
  443. _pow        proc export
  444.             link         a6, #0
  445.             fmovem        fp0/fp1, -(a7)
  446.             
  447.             fmove.x        12(a6), fp0            ; load x
  448.             fmove.x        24(a6), fp1            ; load y
  449.             
  450.             fcmp.w        #0, fp1                ; if y is zero then
  451.             fbne        @6
  452.             fcmp.w        #0, fp0
  453.             fbeq        @error                ; zero to the zeroth power is bad.
  454.             fmove.w        #1, fp0
  455.             bra            @store                ; store one as the result.
  456.             
  457. @6            fcmp.w        #0, fp0                ; is x greater than zero?
  458.             fbgt        @1
  459.             
  460.             fbne        @2                    ; if x is zero, then
  461.             fcmp.w        #0, fp1
  462.             fble        @error                ; if y is greater than zero, 
  463.             fmove.w        #0, fp0                ; then return zero.
  464.             bra.s        @store
  465.             
  466. @2            fint.x        fp1                    ; round y.
  467.             fcmp.x        24(a6), fp1            ; is y integral? if not,
  468.             fbne        @error                ; return some error
  469.             
  470.             fmove.x        fp1, fp0            ; save a copy of y
  471.             fdiv.w        #2, fp1                ; test if y is odd
  472.             fdiv.w        #2, fp0
  473.             fint.x        fp1
  474.             fcmp.x        fp0, fp1            ; if round(fp1) <> fp0
  475.                                             ; before we branch on this test,
  476.                                             ; do the operations that both
  477.                                             ; conditions require.
  478.                                             ; (in fact, the only thing different
  479.                                             ; is that the result gets negated
  480.                                             ; if y is odd.
  481.                                             
  482.             fmove.l        fpsr, d0            ; save the FPSR so we can branch on it later.
  483.             fmove.x        12(a6), fp0            ; re-fetch the arguments
  484.             fmove.x        24(a6), fp1
  485.             
  486.             fneg.x        fp0
  487.             flogn.x        fp0
  488.             fmul.x        fp1, fp0
  489.             fetox.x        fp0
  490.     
  491.             fmove.l        d0, fpsr            ; restore the FPSR
  492.             fbne        @5                    ; and branch on it.
  493.             
  494.             bra.s        @store                ; since y is even, do nothing else
  495.             
  496. @5            fneg.x        fp0                    ; since y is odd, negate the result.
  497.             bra.s        @store
  498.             
  499. @1            flogn.x        fp0                    ; x > 0, therefore 
  500.             fmul.x        fp1, fp0
  501.             fetox.x        fp0                    ; pow(x, y) = exp(y * ln(x))
  502.             bra.s         @store
  503.             
  504. @error        fmove.x        #"NAN", fp0
  505.         
  506. @store        movea.l        8(a6), a0
  507.             fmove.x        fp0, (a0)
  508.  
  509.             fmovem        (a7)+, fp0/fp1
  510.             unlk        a6
  511.             rts
  512.             
  513. ;    double sin(double x);
  514. ;
  515. ; stack frame:
  516. ;     12 bytes saved registers
  517. ;    4 byte return address
  518. ;    x        equ    20
  519. ;    result     equ 16
  520.  
  521. _sin        proc export
  522.  
  523.             fmovem         fp0, -(a7)
  524.             fsin.x         20(a7), fp0
  525.             movea.l     16(a7), a0
  526.             fmove.x        fp0, (a0)
  527.             fmovem        (a7)+, fp0
  528.             rts
  529.  
  530. ;
  531. ;    double sinh(double x);
  532. ;
  533. ; stack frame:
  534. ;     12 bytes saved registers
  535. ;    4 byte return address
  536. ;    x        equ    20
  537. ;    result     equ 16
  538.  
  539. _sinh        proc export
  540.  
  541.             fmovem         fp0, -(a7)
  542.             fsinh.x     20(a7), fp0
  543.             movea.l     16(a7), a0
  544.             fmove.x        fp0, (a0)
  545.             fmovem        (a7)+, fp0
  546.             rts
  547.             
  548. ;
  549. ;    double sqrt(double x);
  550. ;
  551. ; stack frame:
  552. ;     12 bytes saved registers
  553. ;    4 byte return address
  554. ;    x        equ    20
  555. ;    result     equ 16
  556.  
  557. _sqrt        proc export
  558.  
  559.             fmovem         fp0, -(a7)
  560.             fsqrt.x     20(a7), fp0
  561.             movea.l     16(a7), a0
  562.             fmove.x        fp0, (a0)
  563.             fmovem        (a7)+, fp0
  564.             rts
  565.  
  566. ;
  567. ;    double tan(double x);
  568. ;
  569. ; stack frame:
  570. ;     12 bytes saved registers
  571. ;    4 byte return address
  572. ;    x        equ    20
  573. ;    result     equ 16
  574.  
  575. _tan        proc export
  576.  
  577.             fmovem         fp0, -(a7)
  578.             ftan.x         20(a7), fp0
  579.             movea.l     16(a7), a0
  580.             fmove.x        fp0, (a0)
  581.             fmovem        (a7)+, fp0
  582.             rts
  583.  
  584. ;
  585. ;    double tanh(double x);
  586. ;
  587. ; stack frame:
  588. ;     12 bytes saved registers
  589. ;    4 byte return address
  590. ;    x        equ    20
  591. ;    result     equ 16
  592.  
  593. _tanh        proc export
  594.  
  595.             fmovem         fp0, -(a7)
  596.             ftanh.x     20(a7), fp0
  597.             movea.l     16(a7), a0
  598.             fmove.x        fp0, (a0)
  599.             fmovem        (a7)+, fp0
  600.             rts
  601.             
  602. ;
  603. ;    long GetState()
  604. ;
  605. ;    GetState() simply returns the contents of the 68881's status register.
  606. ;
  607. GetState    proc export
  608.             fmove.l    fpsr, d0
  609.             rts
  610.  
  611. ;    
  612. ;    void ClearExceptions()
  613. ;
  614. ;    ClearExceptions() clears the exception byte of the 68881 status
  615. ;    register.
  616. ;
  617. ClearExceptions proc export
  618.             fmove.l fpsr, d0
  619.             andi.l #$FFFF00FF, d0
  620.             fmove.l    d0, fpsr
  621.             rts
  622.  
  623.             end
  624.