home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-01-15 | 12.1 KB | 624 lines | [TEXT/KAHL] |
- MACHINE MC68020
- MC68881
-
- BLANKS ON
- CASE ON
- STRING ASIS
-
- ; Assembly source for the Math881 math library.
- ; Version 3.0
- ; by Rich Siegel (with assistance from Steve Stein)
- ; ⌐1988 Symantec Corp.
-
- ;
- ; LightspeedC pushes the parameters in reverse order; also, the first parameter
- ; pushed is a hidden argument that contains the address of the function
- ; result.
- ;
- ; Floating-point arguments are pushed by value.
- ;
- ;
- ; The one-argument transcendentals follow a common template: simply
- ; evaluate what's on the stack with FP0 as the destination, load the
- ; function result address into A0, and then do a FMOVE.X FP0, (A0)
- ; to store the function result.
- ;
- ; Since none of the floating-point registers are scratch, these
- ; routines preserve the registers that they use.
- ;
-
- ; in Math881.a the function names begin with the underscore character;
- ; this is useful when the _ERRORCHECK_ symbol is defined in <Math881.h>.
- ; the user can call an underscore directly, or he can call the function
- ; as it's defined in Math881.c, and get the full benefit of the standard
- ; C error checking. For example, using tan() or _tan().
- ;
- ; When _ERRORCHECK_ is not defined, the library calls are simply macros
- ; to call the underscore functions.
-
- ;
- ; int abs(int i);
- ;
- ; stack:
- ; 4 byte return address
- ; i is at 4(a7)
-
- abs proc export
- move.w 4(a7), d0
- bge.s @1
- neg.w d0
-
- @1 rts
-
- ;
- ; double acos(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _acos proc export
-
- fmovem fp0, -(a7) ; preserve registers
- facos.x 20(a7), fp0 ; arccos
- movea.l 16(a7), a0 ; load address of result
- fmove.x fp0, (a0) ; load result
- fmovem (a7)+, fp0 ; restore registers
- rts
-
- ;
- ; double asin(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _asin proc export
-
- fmovem fp0, -(a7)
- fasin.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double atan(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _atan proc export
-
- fmovem fp0, -(a7)
- fatan.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double atan2(double y, double x);
- ;
-
- _atan2 proc export
-
- fmovem fp0/fp1, -(a7) ; preserve fp0 and fp1
- movea.l 28(a7), a0 ; load address of result
- fmove.x 32(a7), fp0 ; load y
- fmove.x 44(a7), fp1 ; load x (we'll use it later)
- fdiv.x fp1, fp0 ; divide by x
- fatan.x fp0 ; arctan
-
- fcmp.w #0, fp1 ; is x < zero?
- fbge @1
-
- fmove.x 32(a7), fp1 ; put a fresh copy of y into fp1
- fcmp.w #0, fp1 ; is y < zero?
- fbge @2
- fmovecr #0, fp1 ; if it is, subtract pi from result.
- fsub.x fp1, fp0
- bra.s @1 ; ...and go home.
-
- @2 fmovecr #0, fp1 ; otherwise, add pi to result.
- fadd.x fp1, fp0
-
- @1 fmove.x fp0, (a0) ; store result
- fmovem (a7)+, fp0/fp1 ; restore registers
-
- rts
-
- ;
- ; double ceil(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _ceil proc export
- fmovem fp0, -(a7) ; preserve fp0
-
- fmove.l fpcr, d0 ; fetch the 68881 control register
- move.l d0, d1 ; save a copy in D1
-
- ori.l #$0030, d0 ; OR in the rounding control
- fmove.l d0, fpcr ; set up the FPCR
-
- fint.x 20(a7), fp0 ; calculate nearest integer of arg
-
- fmove.l d1, fpcr ; restore the fpcr from the copy
-
- movea.l 16(a7), a0 ; load addr of result, and...
- fmove.x fp0, (a0) ; ...load the result
-
- fmovem (a7)+, fp0 ; restore registers
- rts
-
- ;
- ; double cos(double x); /* same schema as acos, asin, atan */
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _cos proc export
-
- fmovem fp0, -(a7)
- fcos.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double cosh(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _cosh proc export
-
- fmovem fp0, -(a7)
- fcosh.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double exp(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _exp proc export
-
- fmovem fp0, -(a7)
- fetox.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double fabs(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _fabs proc export
-
- fmovem fp0, -(a7)
- FABS.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double floor(double x);
- ;
- ; this function works the same as ceil(), except that the value to OR in
- ; is $20 instead of $30.
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _floor proc export
- fmovem fp0, -(a7)
-
- fmove.l fpcr, d0
- move.l d0, d1
-
- ori.l #$0020, d0
- fmove.l d0, fpcr
-
- fint.x 20(a7), fp0
-
- fmove.l d1, fpcr
-
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
-
- rts
-
- ;
- ; double fmod(double y, double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 32
- ; y equ 20
- ; result equ 16
-
- _fmod proc export
- fmovem fp0, -(a7) ; save the registers
- fmove.x 20(a7), fp0 ; load Y
- fmod.x 32(a7), fp0 ; call the '881's FMOD
- movea.l 16(a7), a0 ; load address of result
- fmove.x fp0, (a0) ; load result
- fmovem (a7)+, fp0 ; restore registers
- rts
-
- ;
- ; double frexp(double x, int *nptr);
- ;
- ; This function is machine-dependent, and relies on the internal representation
- ; of the double floating-point data type.
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; nptr equ 32
- ; x equ 20
- ; result equ 16
-
- _frexp proc export
- fmovem fp0, -(a7)
-
- movea.l 16(a7), a0 ; load result address
- movea.l 32(a7), a1 ; load nptr
- fmove.x 20(a7), fp0 ; fetch X
-
- fcmp.w #0, fp0 ; if X is zero, then
- fbne @2
- move.w #0, (a1) ; both parts of result are zero
- fmove.x fp0, (a0) ; return x (since it is also zero)
- bra.s @3 ; goodbye...
-
- @2 move.w 20(a7), d0 ; get the exponent of X
- move.w d0, d1 ; keep a copy
- bge.s @1
- andi.w #$7FFF, d0 ; mask off the mantissa sign bit
-
- @1 subi.w #$3FFE, d0 ; subtract the exponent bias (less one)
-
- andi.w #$8000, d1 ; preserve mantissa's sign bit
- ori.w #$3FFE, d1 ; put in an exponent of (-1)
- move.w d1, 20(a7) ; and smash that over X's old exponent
-
- fmove.x 20(a7), fp0 ; fetch X (again)
- fmove.x fp0, (a0) ; store it in result
- move.w d0, (a1) ; and store *nptr
-
- @3 fmovem (a7)+, fp0
- rts
-
- ;
- ; long labs(long l);
- ;
- ; stack:
- ; 4 byte return address
- ; l is at 4(a7)
-
- labs proc export
- move.l 4(a7), d0
- bge.s @1
- neg.l d0
-
- @1 rts
-
- ;
- ; double ldexp(double x, int n);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; n equ 32
- ; x equ 20
- ; result equ 16
-
- _ldexp proc export
- fmovem fp0, -(a7)
-
- movea.l 16(a7), a0 ; load result address
- fmove.w 32(a7), fp0 ; load N into a float register
- ftwotox fp0 ; raise two to that power.
- fmul.x 20(a7), fp0 ; multiply by X
-
- fmove.x fp0, (a0) ; load result
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double log(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _log proc export
-
- fmovem fp0, -(a7)
- flogn.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double log10(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _log10 proc export
-
- fmovem fp0, -(a7)
- flog10.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double modf(double x, double *ip);
- ;
-
- ; stack frame:
- ; 24 bytes of saved registers
- ; 4 bytes return addr
- ; result equ 28
- ; x equ 32
- ; ip equ 44
-
- _modf proc export
-
- fmovem fp0/fp1, -(a7)
-
- movea.l 28(a7), a0 ; address of result
- movea.l 44(a7), a1 ; address of int part
- fmove.x 32(a7), fp0 ; argument
-
- fintrz.x fp0, fp1 ; leaves integer part in fp1
- fmove.x fp1, (a1) ; store integer part
- fsub.x fp1, fp0
-
- fmove.x fp0, (a0) ; store function result
-
- fmovem (a7)+, fp0/fp1
- rts
-
-
- ;
- ; double pow(double x, double y);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; y equ 32
- ; x equ 20
- ; result equ 16
-
- _pow proc export
- link a6, #0
- fmovem fp0/fp1, -(a7)
-
- fmove.x 12(a6), fp0 ; load x
- fmove.x 24(a6), fp1 ; load y
-
- fcmp.w #0, fp1 ; if y is zero then
- fbne @6
- fcmp.w #0, fp0
- fbeq @error ; zero to the zeroth power is bad.
- fmove.w #1, fp0
- bra @store ; store one as the result.
-
- @6 fcmp.w #0, fp0 ; is x greater than zero?
- fbgt @1
-
- fbne @2 ; if x is zero, then
- fcmp.w #0, fp1
- fble @error ; if y is greater than zero,
- fmove.w #0, fp0 ; then return zero.
- bra.s @store
-
- @2 fint.x fp1 ; round y.
- fcmp.x 24(a6), fp1 ; is y integral? if not,
- fbne @error ; return some error
-
- fmove.x fp1, fp0 ; save a copy of y
- fdiv.w #2, fp1 ; test if y is odd
- fdiv.w #2, fp0
- fint.x fp1
- fcmp.x fp0, fp1 ; if round(fp1) <> fp0
- ; before we branch on this test,
- ; do the operations that both
- ; conditions require.
- ; (in fact, the only thing different
- ; is that the result gets negated
- ; if y is odd.
-
- fmove.l fpsr, d0 ; save the FPSR so we can branch on it later.
- fmove.x 12(a6), fp0 ; re-fetch the arguments
- fmove.x 24(a6), fp1
-
- fneg.x fp0
- flogn.x fp0
- fmul.x fp1, fp0
- fetox.x fp0
-
- fmove.l d0, fpsr ; restore the FPSR
- fbne @5 ; and branch on it.
-
- bra.s @store ; since y is even, do nothing else
-
- @5 fneg.x fp0 ; since y is odd, negate the result.
- bra.s @store
-
- @1 flogn.x fp0 ; x > 0, therefore
- fmul.x fp1, fp0
- fetox.x fp0 ; pow(x, y) = exp(y * ln(x))
- bra.s @store
-
- @error fmove.x #"NAN", fp0
-
- @store movea.l 8(a6), a0
- fmove.x fp0, (a0)
-
- fmovem (a7)+, fp0/fp1
- unlk a6
- rts
-
- ; double sin(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _sin proc export
-
- fmovem fp0, -(a7)
- fsin.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double sinh(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _sinh proc export
-
- fmovem fp0, -(a7)
- fsinh.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double sqrt(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _sqrt proc export
-
- fmovem fp0, -(a7)
- fsqrt.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double tan(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _tan proc export
-
- fmovem fp0, -(a7)
- ftan.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; double tanh(double x);
- ;
- ; stack frame:
- ; 12 bytes saved registers
- ; 4 byte return address
- ; x equ 20
- ; result equ 16
-
- _tanh proc export
-
- fmovem fp0, -(a7)
- ftanh.x 20(a7), fp0
- movea.l 16(a7), a0
- fmove.x fp0, (a0)
- fmovem (a7)+, fp0
- rts
-
- ;
- ; long GetState()
- ;
- ; GetState() simply returns the contents of the 68881's status register.
- ;
- GetState proc export
- fmove.l fpsr, d0
- rts
-
- ;
- ; void ClearExceptions()
- ;
- ; ClearExceptions() clears the exception byte of the 68881 status
- ; register.
- ;
- ClearExceptions proc export
- fmove.l fpsr, d0
- andi.l #$FFFF00FF, d0
- fmove.l d0, fpsr
- rts
-
- end
-