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