mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-24 08:54:17 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
|
||||
*
|
||||
* Floating Point Arctangen:
|
||||
* Front End to FFP Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* atan(farg)
|
||||
* double farg;
|
||||
*
|
||||
* Returns : negated Floating point number
|
||||
*
|
||||
.globl _atan
|
||||
.globl iefatan
|
||||
.text
|
||||
fpatan:
|
||||
_atan:
|
||||
~~atan:
|
||||
link r14,#-4
|
||||
move.l d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
jsr iefatan
|
||||
move.l r7,r0
|
||||
move.l (sp)+,d7
|
||||
unlk r14
|
||||
rts
|
||||
126
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/orglibe/atof.c
Normal file
126
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/orglibe/atof.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
Copyright 1982, 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*char *version "@(#)atof.c 1.3 12/29/83";*/
|
||||
|
||||
/*
|
||||
* Ascii String to IEEE Floating Point Routine :
|
||||
* IEEE Standard Single Precision Representation Floating Point
|
||||
*
|
||||
* float
|
||||
* atof(buf)
|
||||
* char *buf;
|
||||
*
|
||||
* No more than 9 significant digits are allowed in single precision.
|
||||
* Largest positive number is 3.4 * 10^33 and the smallest positive
|
||||
* number is 1.2 * 10^-38.
|
||||
* Rely's on the fact that a long and a float are both 32 bits.
|
||||
*/
|
||||
|
||||
#define BIAS 127L
|
||||
#define EXPSIZ 4
|
||||
#define FRACSIZ 20
|
||||
|
||||
long fptoieee();
|
||||
float strbin();
|
||||
float power10();
|
||||
|
||||
long
|
||||
atof(buf)
|
||||
char *buf;
|
||||
{
|
||||
char ibuf[FRACSIZ], ebuf[EXPSIZ];
|
||||
register char *ip, *ep;
|
||||
long ieee; /* return value */
|
||||
int dp, esign, isign, ebin, places;
|
||||
float ibin, fp;
|
||||
|
||||
ip = ibuf; ep = ebuf; dp = 0; places = 0L;
|
||||
while (*buf == ' ' || *buf == '\t') /* ignore white spaces */
|
||||
buf++;
|
||||
isign = (*buf == '-');
|
||||
if (*buf == '-' || *buf == '+')
|
||||
buf++;
|
||||
while (*buf && *buf != 'e' && *buf != 'E') {
|
||||
if (*buf == '.')
|
||||
dp++;
|
||||
else { /* digit seen */
|
||||
*ip++ = *buf;
|
||||
if (dp)
|
||||
places++;
|
||||
}
|
||||
buf++;
|
||||
}
|
||||
*ip = 0;
|
||||
if (*buf == 'e' || *buf == 'E') { /* exponent string */
|
||||
buf++;
|
||||
esign = (*buf == '-');
|
||||
if (*buf == '-' || *buf == '+')
|
||||
buf++;
|
||||
while (*buf) /* get exponent string */
|
||||
*ep++ = *buf++;
|
||||
}
|
||||
*ep = 0;
|
||||
ibin = strbin(ibuf);
|
||||
ebin = atoi(ebuf);
|
||||
places = (esign) ? -ebin - places : ebin - places;
|
||||
fp = ibin * power10(places);
|
||||
ieee = fptoieee(fp);
|
||||
if (isign) /* negative float */
|
||||
ieee =| 0x80000000;
|
||||
return( ieee );
|
||||
}
|
||||
|
||||
float
|
||||
power10(pwr) /* 10^pwr */
|
||||
int pwr;
|
||||
{
|
||||
float f;
|
||||
|
||||
if (pwr < 0L) /* negative power */
|
||||
for (f = 1.0; pwr < 0; pwr++)
|
||||
f = f / 10.0;
|
||||
else /* positive power */
|
||||
for (f = 1.0; pwr > 0; pwr--)
|
||||
f = f * 10.0;
|
||||
return(f);
|
||||
}
|
||||
|
||||
long
|
||||
fptoieee(f) /* convert current machine float to ieee rep */
|
||||
float f; /* unsigned float... */
|
||||
{
|
||||
register long exp, l;
|
||||
|
||||
if (f == 0.0)
|
||||
return(0L);
|
||||
exp = 0L;
|
||||
for( ; f >= 2.0; f = f / 2.0)
|
||||
exp++;
|
||||
for( ; f < 1.0; f = f * 2.0)
|
||||
exp--;
|
||||
f = f - 1.0; /* implicit 1, eg. 1.F */
|
||||
if (f != 0.0)
|
||||
f = f * 8388608.0; /* 2 ^ 23 */
|
||||
l = f;
|
||||
exp =+ BIAS;
|
||||
l =| ((exp<<23) & 0x7f800000);
|
||||
return(l);
|
||||
}
|
||||
|
||||
float
|
||||
strbin(p) /* decimal string => binary long */
|
||||
char *p;
|
||||
{
|
||||
float f;
|
||||
|
||||
for (f = 0.0; *p >= '0' && *p <= '9'; p++) {
|
||||
f = f * 10.0;
|
||||
f = f + (*p - '0');
|
||||
}
|
||||
return(f);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
c68 -c -L -e atof.c
|
||||
c68 -c -L -e ceil.c
|
||||
c68 -c -L -e etoa.c
|
||||
c68 -c -L -e fabs.c
|
||||
c68 -c -L -e floor.c
|
||||
c68 -c -L -e fmod.c
|
||||
c68 -c -L -e fprintf.c
|
||||
c68 -c -L -e ftoa.c
|
||||
c68 -c -L -e ftol.c
|
||||
c68 -c -L -e ieeetof.c
|
||||
c68 -c -L -e ltof.c
|
||||
c68 -c -L -e printf.c
|
||||
c68 -c -L -e fscanf.c
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*char *version "@(#)ceil.c 1.2 10/19/83";*/
|
||||
|
||||
/* ceil - returns the smallest integer (as a double precision
|
||||
number) not greater than x. */
|
||||
|
||||
double
|
||||
ceil(x)
|
||||
double x;
|
||||
{
|
||||
register long i;
|
||||
double retval;
|
||||
|
||||
if( x > 0 )
|
||||
x += 0.999999999999;
|
||||
i = x;
|
||||
retval = i;
|
||||
return( retval );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
*
|
||||
* Floating Point Hyperbolic cosine:
|
||||
* Front End to FFP Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* cosh(farg)
|
||||
* double farg;
|
||||
*
|
||||
* Returns : negated Floating point number
|
||||
*
|
||||
.globl _cosh
|
||||
.globl iefcosh
|
||||
.text
|
||||
fpcosh:
|
||||
_cosh:
|
||||
~~cosh:
|
||||
link r14,#-4
|
||||
move.l d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
jsr iefcosh
|
||||
move.l r7,r0
|
||||
move.l (sp)+,d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,61 @@
|
||||
e:vax ATAN.S r
|
||||
e:vax ATOF.C r
|
||||
e:vax BUILDFILE. r
|
||||
e:vax CEIL.C r
|
||||
e:vax COSH.S r
|
||||
e:vax DOWN.SUB r
|
||||
e:vax ETOA.C r
|
||||
e:vax FABS.C r
|
||||
e:vax FFPABS.S r
|
||||
e:vax FFPADD.S r
|
||||
e:vax FFPATAN.S r
|
||||
e:vax FFPCMP.S r
|
||||
e:vax FFPCPYRT.S r
|
||||
e:vax FFPDIV.S r
|
||||
e:vax FFPEXP.S r
|
||||
e:vax FFPHTHET.S r
|
||||
e:vax FFPIEEE.S r
|
||||
e:vax FFPLOG.S r
|
||||
e:vax FFPMUL2.S r
|
||||
e:vax FFPPWR.S r
|
||||
e:vax FFPSIN.S r
|
||||
e:vax FFPSQRT.S r
|
||||
e:vax FFPTHETA.S r
|
||||
e:vax FFPTNORM.S r
|
||||
e:vax FLOOR.C r
|
||||
e:vax FMOD.C r
|
||||
e:vax FPADD.S r
|
||||
e:vax FPCMP.S r
|
||||
e:vax FPCOS.S r
|
||||
e:vax FPDIV.S r
|
||||
e:vax FPEXP.S r
|
||||
e:vax FPLOG.S r
|
||||
e:vax FPMUL.S r
|
||||
e:vax FPNEG.S r
|
||||
e:vax FPPWR.S r
|
||||
e:vax FPRINTF.C r
|
||||
e:vax FPSIN.S r
|
||||
e:vax FPSQRT.S r
|
||||
e:vax FPSUB.S r
|
||||
e:vax FSCANF.C r
|
||||
e:vax FTOA.C r
|
||||
e:vax FTOL.C r
|
||||
e:vax IEEETOF.C r
|
||||
e:vax IEFABS.S r
|
||||
e:vax IEFADD.S r
|
||||
e:vax IEFATAN.S r
|
||||
e:vax IEFBACK.S r
|
||||
e:vax IEFCMP.S r
|
||||
e:vax IEFDIV.S r
|
||||
e:vax IEFEXP.S r
|
||||
e:vax IEFFRONT.S r
|
||||
e:vax IEFLOG.S r
|
||||
e:vax IEFMUL.S r
|
||||
e:vax IEFPWR.S r
|
||||
e:vax IEFSIN.S r
|
||||
e:vax IEFSINH.S r
|
||||
e:vax IEFSQRT.S r
|
||||
e:vax LTOF.C r
|
||||
e:vax PRINTF.C r
|
||||
e:vax SINH.S r
|
||||
e:vax TANH.S r
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
Directory _DRB0:[STEVE.CPM68K.V102A.LIBE]
|
||||
|
||||
ATAN.S;2
|
||||
ATOF.C;2
|
||||
BUILDFILE.;2
|
||||
CEIL.C;2
|
||||
COSH.S;2
|
||||
DOWN.SUB;1
|
||||
ETOA.C;2
|
||||
FABS.C;2
|
||||
FFPABS.S;2
|
||||
FFPADD.S;2
|
||||
FFPATAN.S;2
|
||||
FFPCMP.S;2
|
||||
FFPCPYRT.S;2
|
||||
FFPDIV.S;2
|
||||
FFPEXP.S;2
|
||||
FFPHTHET.S;2
|
||||
FFPIEEE.S;2
|
||||
FFPLOG.S;2
|
||||
FFPMUL2.S;2
|
||||
FFPPWR.S;2
|
||||
FFPSIN.S;2
|
||||
FFPSQRT.S;2
|
||||
FFPTHETA.S;2
|
||||
FFPTNORM.S;2
|
||||
FLOOR.C;2
|
||||
FMOD.C;2
|
||||
FPADD.S;2
|
||||
FPCMP.S;2
|
||||
FPCOS.S;2
|
||||
FPDIV.S;2
|
||||
FPEXP.S;2
|
||||
FPLOG.S;2
|
||||
FPMUL.S;2
|
||||
FPNEG.S;2
|
||||
FPPWR.S;2
|
||||
FPRINTF.C;2
|
||||
FPSIN.S;2
|
||||
FPSQRT.S;2
|
||||
FPSUB.S;2
|
||||
FSCANF.C;2
|
||||
FTOA.C;2
|
||||
FTOL.C;2
|
||||
IEEETOF.C;2
|
||||
IEFABS.S;2
|
||||
IEFADD.S;2
|
||||
IEFATAN.S;2
|
||||
IEFBACK.S;2
|
||||
IEFCMP.S;2
|
||||
IEFDIV.S;2
|
||||
IEFEXP.S;2
|
||||
IEFFRONT.S;2
|
||||
IEFLOG.S;2
|
||||
IEFMUL.S;2
|
||||
IEFPWR.S;2
|
||||
IEFSIN.S;2
|
||||
IEFSINH.S;2
|
||||
IEFSQRT.S;2
|
||||
LTOF.C;2
|
||||
PRINTF.C;2
|
||||
SINH.S;2
|
||||
TANH.S;2
|
||||
|
||||
Total of 61 files.
|
||||
117
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/orglibe/etoa.c
Normal file
117
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/orglibe/etoa.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*char *version "@(#) etoa - jan 24, 1982"; */
|
||||
|
||||
/*
|
||||
* IEEE Floating Point to Ascii String Conversion Routine :
|
||||
* IEEE Standard Single Precision Representation Floating Point
|
||||
*
|
||||
* char *
|
||||
* etoa(f,buf,prec)
|
||||
* float f;
|
||||
* char *buf;
|
||||
* int prec;
|
||||
*
|
||||
* No more than 9 decimal digits are allowed in single precision.
|
||||
* Largest positive number is 3.4 * 10^33 and the smallest positive
|
||||
* number is 1.2 * 10^-38.
|
||||
* Rely's on the fact that a long and a float are both 32 bits.
|
||||
*/
|
||||
|
||||
#define BIAS 127L
|
||||
#ifndef ISIEEE
|
||||
/* if this is compiled or executed with other than ieee fp */
|
||||
float _ieeetof();
|
||||
#else
|
||||
float _efake();
|
||||
#endif
|
||||
|
||||
char *
|
||||
etoa(fl,buf,prec)
|
||||
long fl; /* ieee formatted float */
|
||||
char *buf;
|
||||
int prec;
|
||||
{
|
||||
register char *bp;
|
||||
register int exp, digit;
|
||||
float f;
|
||||
|
||||
prec = (prec <= 0) ? 1 : (prec <= 9) ? prec : 9;
|
||||
bp = buf;
|
||||
if(fl == 0) goto shortcut;
|
||||
if(fl == 0x7f800000) { /* positive infinity */
|
||||
strcpy(bp,"+infinity");
|
||||
return(bp);
|
||||
}
|
||||
if(fl == 0xff800000) { /* negative infinity */
|
||||
strcpy(bp,"-infinity");
|
||||
return(bp);
|
||||
}
|
||||
#ifndef ISIEEE
|
||||
f = _ieeetof(fl); /* get floating point value */
|
||||
#else
|
||||
f = _efake(fl);
|
||||
#endif
|
||||
#ifndef ISIEEE
|
||||
if (f < 0.0) { /* negative float */
|
||||
#else
|
||||
if (fl & 0x80000000) { /* negative float */
|
||||
#endif
|
||||
*bp++ = '-';
|
||||
f = -f; /* make it positive */
|
||||
}
|
||||
#ifndef ISIEEE
|
||||
if (f == 0.0) {
|
||||
#else
|
||||
if (fl == 0) {
|
||||
#endif
|
||||
shortcut:
|
||||
*bp++ = '0'; *bp++ = '.';
|
||||
while (prec--)
|
||||
*bp++ = '0';
|
||||
*bp++ = 'e'; *bp++ = '0'; *bp++ = '0'; *bp = 0;
|
||||
return(buf);
|
||||
}
|
||||
for (exp=0; f < 1.0; f = f * 10.0) /* get negative exp */
|
||||
exp--;
|
||||
for ( ; f >= 1.0; f = f / 10.0) /* 0.XXXXXXE00 * 10^exp */
|
||||
exp++;
|
||||
|
||||
exp--; /* for one explicit digit */
|
||||
f = f * 10.0;
|
||||
digit = f; /* get one digit */
|
||||
f = f - digit;
|
||||
*bp++ = digit + '0';
|
||||
*bp++ = '.';
|
||||
while(prec-- > 0) { /* get prec. decimal places */
|
||||
f = f * 10.0;
|
||||
digit = f;
|
||||
f = f - digit;
|
||||
*bp++ = digit + '0';
|
||||
}
|
||||
*bp++ = 'e';
|
||||
if (exp < 0) {
|
||||
exp = -exp;
|
||||
*bp++ = '-';
|
||||
}
|
||||
*bp++ = (exp / 10) + '0';
|
||||
*bp++ = (exp % 10) + '0';
|
||||
*bp = 0;
|
||||
return(buf);
|
||||
}
|
||||
|
||||
#ifdef ISIEEE
|
||||
/* if these routines are executed on a 68000 using ieee then no need to
|
||||
do a translation !!! */
|
||||
float
|
||||
_efake(lf)
|
||||
float lf;
|
||||
{
|
||||
return(lf);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*char *version "@(#)fabs.c 1.2 10/19/83";*/
|
||||
|
||||
/*
|
||||
* Floating Point Absolute :
|
||||
* Fast Floating Point Package
|
||||
*
|
||||
* double
|
||||
* fabs(farg)
|
||||
* double farg;
|
||||
*
|
||||
* Returns : absolute Floating point number
|
||||
*/
|
||||
|
||||
long
|
||||
fabs(f)
|
||||
long f;
|
||||
{
|
||||
f = f & 0x7fffffff; /* turn off sign bit */
|
||||
return(f);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
ttl fast floating point abs/neg (ffpabs/ffpneg)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************************
|
||||
* ffpabs *
|
||||
* fast floating point absolute value *
|
||||
* *
|
||||
* input: d7 - fast floating point argument *
|
||||
* *
|
||||
* output: d7 - fast floating point absolute value result *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - cleared *
|
||||
* z - set if result is zero *
|
||||
* v - cleared *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
ffpabs idnt 1,1 ffp abs/neg
|
||||
|
||||
xdef ffpabs fast floating point absolute value
|
||||
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
section 9
|
||||
|
||||
******************************
|
||||
* absolute value entry point *
|
||||
******************************
|
||||
ffpabs and.b #$7f,d7 clear the sign bit
|
||||
rts and return to the caller
|
||||
page
|
||||
*************************************************************
|
||||
* ffpneg *
|
||||
* fast floating point negate *
|
||||
* *
|
||||
* input: d7 - fast floating point argument *
|
||||
* *
|
||||
* output: d7 - fast floating point negated result *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - set if result is negative *
|
||||
* z - set if result is zero *
|
||||
* v - cleared *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
xdef ffpneg fast floating point negate
|
||||
|
||||
**********************
|
||||
* negate entry point *
|
||||
**********************
|
||||
ffpneg tst.b d7 ? is argument a zero
|
||||
beq.s ffprtn return if so
|
||||
eor.b #$80,d7 invert the sign bit
|
||||
ffprtn rts and return to caller
|
||||
|
||||
end
|
||||
@@ -0,0 +1,211 @@
|
||||
ttl fast floating point add/subtract (ffpadd/ffpsub)
|
||||
***************************************
|
||||
* (c) copyright 1980 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************************
|
||||
* ffpadd/ffpsub *
|
||||
* fast floating point add/subtract *
|
||||
* *
|
||||
* ffpadd/ffpsub - fast floating point add and subtract *
|
||||
* *
|
||||
* input: *
|
||||
* ffpadd *
|
||||
* d6 - floating point addend *
|
||||
* d7 - floating point adder *
|
||||
* ffpsub *
|
||||
* d6 - floating point subtrahend *
|
||||
* d7 - floating point minuend *
|
||||
* *
|
||||
* output: *
|
||||
* d7 - floating point add result *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - result is negative *
|
||||
* z - result is zero *
|
||||
* v - overflow has occured *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* registers d3 thru d5 are volatile *
|
||||
* *
|
||||
* code size: 228 bytes stack work area: 0 bytes *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) addend/subtrahend unaltered (d6). *
|
||||
* 2) underflow returns zero and is unflagged. *
|
||||
* 3) overflow returns the highest value with the *
|
||||
* correct sign and the 'v' bit set in the ccr. *
|
||||
* *
|
||||
* time: (8 mhz no wait states assumed) *
|
||||
* *
|
||||
* composite average 20.625 microseconds *
|
||||
* *
|
||||
* add: arg1=0 7.75 microseconds *
|
||||
* arg2=0 5.25 microseconds *
|
||||
* *
|
||||
* like signs 14.50 - 26.00 microseconds *
|
||||
* average 18.00 microseconds *
|
||||
* unlike signs 20.13 - 54.38 microceconds *
|
||||
* average 22.00 microseconds *
|
||||
* *
|
||||
* subtract: arg1=0 4.25 microseconds *
|
||||
* arg2=0 9.88 microseconds *
|
||||
* *
|
||||
* like signs 15.75 - 27.25 microseconds *
|
||||
* average 19.25 microseconds *
|
||||
* unlike signs 21.38 - 55.63 microseconds *
|
||||
* average 23.25 microseconds *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
ffpadd idnt 1,1 ffp add/subtract
|
||||
|
||||
xdef ffpadd,ffpsub entry points
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
section 9
|
||||
|
||||
************************
|
||||
* subtract entry point *
|
||||
************************
|
||||
ffpsub move.b d6,d4 test arg1
|
||||
beq.s fpart2 return arg2 if arg1 zero
|
||||
eor.b #$80,d4 invert copied sign of arg1
|
||||
bmi.s fpami1 branch arg1 minus
|
||||
* + arg1
|
||||
move.b d7,d5 copy and test arg2
|
||||
bmi.s fpams branch arg2 minus
|
||||
bne.s fpals branch positive not zero
|
||||
bra.s fpart1 return arg1 since arg2 is zero
|
||||
|
||||
*******************
|
||||
* add entry point *
|
||||
*******************
|
||||
ffpadd move.b d6,d4 test argument1
|
||||
bmi.s fpami1 branch if arg1 minus
|
||||
beq.s fpart2 return arg2 if zero
|
||||
|
||||
* + arg1
|
||||
move.b d7,d5 test argument2
|
||||
bmi.s fpams branch if mixed signs
|
||||
beq.s fpart1 zero so return argument1
|
||||
|
||||
* +arg1 +arg2
|
||||
* -arg1 -arg2
|
||||
fpals sub.b d4,d5 test exponent magnitudes
|
||||
bmi.s fpa2lt branch arg1 greater
|
||||
move.b d7,d4 setup stronger s+exp in d4
|
||||
|
||||
* arg1exp <= arg2exp
|
||||
cmp.b #24,d5 overbearing size
|
||||
bcc.s fpart2 branch yes, return arg2
|
||||
move.l d6,d3 copy arg1
|
||||
clr.b d3 clean off sign+exponent
|
||||
lsr.l d5,d3 shift to same magnitude
|
||||
move.b #$80,d7 force carry if lsb-1 on
|
||||
add.l d3,d7 add arguments
|
||||
bcs.s fpa2gc branch if carry produced
|
||||
fparsr move.b d4,d7 restore sign/exponent
|
||||
rts return to caller
|
||||
|
||||
* add same sign overflow normalization
|
||||
fpa2gc roxr.l #1,d7 shift carry back into result
|
||||
add.b #1,d4 add one to exponent
|
||||
bvs.s fpa2os branch overflow
|
||||
bcc.s fparsr branch if no exponent overflow
|
||||
fpa2os moveq #-1,d7 create all ones
|
||||
sub.b #1,d4 back to highest exponent+sign
|
||||
move.b d4,d7 replace in result
|
||||
* or.b #$02,ccr show overflow occurred
|
||||
dc.l $003c0002 ****assembler error****
|
||||
rts return to caller
|
||||
|
||||
* return argument1
|
||||
fpart1 move.l d6,d7 move in as result
|
||||
move.b d4,d7 move in prepared sign+exponent
|
||||
rts return to caller
|
||||
|
||||
* return argument2
|
||||
fpart2 tst.b d7 test for returned value
|
||||
rts return to caller
|
||||
|
||||
* -arg1exp > -arg2exp
|
||||
* +arg1exp > +arg2exp
|
||||
fpa2lt cmp.b #-24,d5 ? arguments within range
|
||||
ble.s fpart1 nope, return larger
|
||||
neg.b d5 change difference to positive
|
||||
move.l d6,d3 setup larger value
|
||||
clr.b d7 clean off sign+exponent
|
||||
lsr.l d5,d7 shift to same magnitude
|
||||
move.b #$80,d3 force carry if lsb-1 on
|
||||
add.l d3,d7 add arguments
|
||||
bcs.s fpa2gc branch if carry produced
|
||||
move.b d4,d7 restore sign/exponent
|
||||
rts return to caller
|
||||
|
||||
* -arg1
|
||||
fpami1 move.b d7,d5 test arg2's sign
|
||||
bmi.s fpals branch for like signs
|
||||
beq.s fpart1 if zero return argument1
|
||||
|
||||
* -arg1 +arg2
|
||||
* +arg1 -arg2
|
||||
fpams moveq #-128,d3 create a carry mask ($80)
|
||||
eor.b d3,d5 strip sign off arg2 s+exp copy
|
||||
sub.b d4,d5 compare magnitudes
|
||||
beq.s fpaeq branch equal magnitudes
|
||||
bmi.s fpatlt branch if arg1 larger
|
||||
* arg1 <= arg2
|
||||
cmp.b #24,d5 compare magnitude difference
|
||||
bcc.s fpart2 branch arg2 much bigger
|
||||
move.b d7,d4 arg2 s+exp dominates
|
||||
move.b d3,d7 setup carry on arg2
|
||||
move.l d6,d3 copy arg1
|
||||
fpamss clr.b d3 clear extraneous bits
|
||||
lsr.l d5,d3 adjust for magnitude
|
||||
sub.l d3,d7 subtract smaller from larger
|
||||
bmi.s fparsr return final result if no overflow
|
||||
|
||||
* mixed signs normalize
|
||||
fpanor move.b d4,d5 save correct sign
|
||||
fpanrm clr.b d7 clear subtract residue
|
||||
sub.b #1,d4 make up for first shift
|
||||
cmp.l #$00007fff,d7 ? small enough for swap
|
||||
bhi.s fpaxqn branch nope
|
||||
swap.w d7 shift left 16 bits real fast
|
||||
sub.b #16,d4 make up for 16 bit shift
|
||||
fpaxqn add.l d7,d7 shift up one bit
|
||||
dbmi d4,fpaxqn decrement and branch if positive
|
||||
eor.b d4,d5 ? same sign
|
||||
bmi.s fpazro branch underflow to zero
|
||||
move.b d4,d7 restore sign/exponent
|
||||
beq.s fpazro return zero if exponent underflowed
|
||||
rts return to caller
|
||||
|
||||
* exponent underflowed - return zero
|
||||
fpazro moveq.l #0,d7 create a true zero
|
||||
rts return to caller
|
||||
|
||||
* arg1 > arg2
|
||||
fpatlt cmp.b #-24,d5 ? arg1 >> arg2
|
||||
ble.s fpart1 return it if so
|
||||
neg.b d5 absolutize difference
|
||||
move.l d7,d3 move arg2 as lower value
|
||||
move.l d6,d7 set up arg1 as high
|
||||
move.b #$80,d7 setup rounding bit
|
||||
bra.s fpamss perform the addition
|
||||
|
||||
* equal magnitudes
|
||||
fpaeq move.b d7,d5 save arg1 sign
|
||||
exg.l d5,d4 swap arg2 with arg1 s+exp
|
||||
move.b d6,d7 insure same low byte
|
||||
sub.l d6,d7 obtain difference
|
||||
beq.s fpazro return zero if identical
|
||||
bpl.s fpanor branch if arg2 bigger
|
||||
neg.l d7 correct difference to positive
|
||||
move.b d5,d4 use arg2's sign + exponent
|
||||
bra.s fpanrm and go normalize
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
ttl fast floating point arctangent (ffpatan)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* ffpatan *
|
||||
* fast floating point arctangent *
|
||||
* *
|
||||
* input: d7 - input argument *
|
||||
* *
|
||||
* output: d7 - arctangent radian result *
|
||||
* *
|
||||
* all other registers totally transparent *
|
||||
* *
|
||||
* code size: 132 bytes stack work: 32 bytes *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if the result is zero *
|
||||
* n - cleared *
|
||||
* v - cleared *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) spot checks show at least six digit *
|
||||
* precision on all sampled cases. *
|
||||
* *
|
||||
* time: (8mhz no wait states assumed) *
|
||||
* *
|
||||
* the time is very data sensitive with *
|
||||
* sample values ranging from 238 to *
|
||||
* 465 microseconds *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
ffpatan idnt 1,2 ffp arctangent
|
||||
|
||||
opt pcs
|
||||
|
||||
section 9
|
||||
|
||||
xdef ffpatan entry point
|
||||
|
||||
xref ffptheta arctangent table
|
||||
|
||||
xref ffpdiv,ffpsub arithmetic primitives
|
||||
xref ffptnorm transcendental normalize routine
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
piov2 equ $c90fdb41 float pi/2
|
||||
fpone equ $80000041 float 1
|
||||
|
||||
********************
|
||||
* arctangent entry *
|
||||
********************
|
||||
|
||||
* save registers and perform argument reduction
|
||||
ffpatan movem.l d1-d6/a0,-(sp) save caller's registers
|
||||
move.b d7,-(sp) save original sign on stack
|
||||
and.b #$7f,d7 take absolute value of arg
|
||||
* insure less than one for cordic loop
|
||||
move.l #fpone,d6 load up 1
|
||||
clr.b -(sp) default no inverse required
|
||||
cmp.b d6,d7 ? less than one
|
||||
bcs.s fpainrg branch in range
|
||||
bhi.s fpardc higher - must reduce
|
||||
cmp.l d6,d7 ? less or equal to one
|
||||
bls.s fpainrg branch yes, is in range
|
||||
* argument > 1: atan(1/x) = pi/2 - atan(x)
|
||||
fpardc not.b (sp) flag inverse taken
|
||||
exg.l d6,d7 take inverse of argument
|
||||
jsr ffpdiv perform divide
|
||||
|
||||
* perform cordic function
|
||||
* convert to bin(31,29) precision
|
||||
fpainrg sub.b #64+3,d7 adjust exponent
|
||||
neg.b d7 for shift necessary
|
||||
cmp.b #31,d7 ? too small to worry about
|
||||
bls.s fpanotz branch if not too small
|
||||
move.l #0,d6 convert to a zero
|
||||
bra.s fpazro branch if zero
|
||||
fpanotz lsr.l d7,d7 shift to bin(31,29) precision
|
||||
|
||||
*****************************************
|
||||
* cordic calculation registers: *
|
||||
* d1 - loop count a0 - table pointer *
|
||||
* d2 - shift count *
|
||||
* d3 - y' d5 - y *
|
||||
* d4 - x' d6 - z *
|
||||
* d7 - x *
|
||||
*****************************************
|
||||
|
||||
move.l #0,d6 z=0
|
||||
move.l #1<<29,d5 y=1
|
||||
lea ffptheta+4,a0 to arctangent table
|
||||
move.l #24,d1 loop 25 times
|
||||
move.l #1,d2 prime shift counter
|
||||
bra.s cordic enter cordic loop
|
||||
|
||||
* cordic loop
|
||||
fplpls asr.l d2,d4 shift(x')
|
||||
add.l d4,d5 y = y + x'
|
||||
add.l (a0),d6 z = z + arctan(i)
|
||||
cordic move.l d7,d4 x' = x
|
||||
move.l d5,d3 y' = y
|
||||
asr.l d2,d3 shift(y')
|
||||
fplnlp sub.l d3,d7 x = x - y'
|
||||
bpl.s fplpls branch negative
|
||||
move.l d4,d7 restore x
|
||||
add.l #4,a0 to next table entry
|
||||
add.b #1,d2 increment shift count
|
||||
lsr.l #1,d3 shift(y')
|
||||
dbra d1,fplnlp and loop until done
|
||||
|
||||
* now convert to float and reconstruct the result
|
||||
jsr ffptnorm float z
|
||||
fpazro move.l d6,d7 copy answer to d7
|
||||
tst.b (sp)+ ? was inverse taken
|
||||
beq.s fpaninv branch if not
|
||||
move.l #piov2,d7 take away from pi over two
|
||||
jsr ffpsub subtract
|
||||
fpaninv move.b (sp)+,d6 load original sign
|
||||
tst.b d7 ? result zero
|
||||
beq.s fpartn return if so
|
||||
and.b #$80,d6 clear exponent portion
|
||||
or.b d6,d7 if minus, give minus result
|
||||
fpartn movem.l (sp)+,d1-d6/a0 restore caller's registers
|
||||
rts return to caller
|
||||
|
||||
end
|
||||
@@ -0,0 +1,83 @@
|
||||
ttl fast floating point cmp/tst (ffpcmp/ffptst)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************************
|
||||
* ffpcmp *
|
||||
* fast floating point compare *
|
||||
* *
|
||||
* input: d6 - fast floating point argument (source) *
|
||||
* d7 - fast floating point argument (destination) *
|
||||
* *
|
||||
* output: condition code reflecting the following branches *
|
||||
* for the result of comparing the destination *
|
||||
* minus the source: *
|
||||
* *
|
||||
* gt - destination greater *
|
||||
* ge - destination greater or equal to *
|
||||
* eq - destination equal *
|
||||
* ne - destination not equal *
|
||||
* lt - destination less than *
|
||||
* le - destination less than or equal to *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - cleared *
|
||||
* z - set if result is zero *
|
||||
* v - cleared *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
ffpcmp idnt 1,1 ffp cmp/tst
|
||||
|
||||
xdef ffpcmp fast floating point compare
|
||||
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
section 9
|
||||
|
||||
***********************
|
||||
* compare entry point *
|
||||
***********************
|
||||
ffpcmp cmp.b d6,d7 compare sign and exponent only first
|
||||
bne.s ffpcrtn return if that is sufficient
|
||||
cmp.l d6,d7 no, compare full longwords then
|
||||
ffpcrtn rts and return to the caller
|
||||
page
|
||||
*************************************************************
|
||||
* ffptst *
|
||||
* fast floating point test *
|
||||
* *
|
||||
* input: d7 - fast floating point argument *
|
||||
* *
|
||||
* output: condition codes set for the following branches: *
|
||||
* *
|
||||
* eq - argument equals zero *
|
||||
* ne - argument not equal zero *
|
||||
* pl - argument is positive (includes zero)*
|
||||
* mi - argument is negative *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - set if result is negative *
|
||||
* z - set if result is zero *
|
||||
* v - cleared *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
xdef ffptst fast floating point test
|
||||
|
||||
********************
|
||||
* test entry point *
|
||||
********************
|
||||
ffptst tst.b d7 return tested condition code
|
||||
rts to caller
|
||||
|
||||
end
|
||||
@@ -0,0 +1,29 @@
|
||||
ttl mc68343 fast floating point copyright notice (ffpcpyrt)
|
||||
ffpcpyrt idnt 1,1 ffp copyright notice
|
||||
|
||||
*************************************
|
||||
* ffp library copyright notice stub *
|
||||
* *
|
||||
* this module is included by all *
|
||||
* link edits with the ffplib.ro *
|
||||
* library to protect motorola's *
|
||||
* copyright status. *
|
||||
* *
|
||||
* code: 67 bytes *
|
||||
* *
|
||||
* note: this module must reside *
|
||||
* last in the library as it is *
|
||||
* referenced by all other mc68343 *
|
||||
* modules. *
|
||||
*************************************
|
||||
|
||||
section 9
|
||||
|
||||
xdef ffpcpyrt
|
||||
|
||||
|
||||
ffpcpyrt equ *
|
||||
dc.b 'mc68343 floating point firmware '
|
||||
dc.b '(c) copyright 1981 by motorola inc.'
|
||||
|
||||
end
|
||||
@@ -0,0 +1,166 @@
|
||||
ttl fast floating point divide (ffpdiv)
|
||||
*****************************************
|
||||
* (c) copyright 1980 by motorola inc. *
|
||||
*****************************************
|
||||
|
||||
********************************************
|
||||
* ffpdiv subroutine *
|
||||
* *
|
||||
* input: *
|
||||
* d6 - floating point divisor *
|
||||
* d7 - floating point dividend *
|
||||
* *
|
||||
* output: *
|
||||
* d7 - floating point quotient *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - set if result negative *
|
||||
* z - set if result zero *
|
||||
* v - set if result overflowed *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* registers d3 thru d5 volatile *
|
||||
* *
|
||||
* code: 150 bytes stack work: 0 bytes *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) divisor is unaltered (d6). *
|
||||
* 2) underflows return zero without *
|
||||
* any indicators set. *
|
||||
* 3) overflows return the highest value *
|
||||
* with the proper sign and the 'v' *
|
||||
* bit set in the ccr. *
|
||||
* 4) if a divide by zero is attempted *
|
||||
* the divide by zero exception trap *
|
||||
* is forced by this code with the *
|
||||
* original arguments intact. if the *
|
||||
* exception returns with the denom- *
|
||||
* inator altered the divide operation *
|
||||
* continues, otherwise an overflow *
|
||||
* is forced with the proper sign. *
|
||||
* the floating divide by zero can be *
|
||||
* distinguished from true zero divide *
|
||||
* by the fact that it is an immediate *
|
||||
* zero dividing into register d7. *
|
||||
* *
|
||||
* time: (8 mhz no wait states assumed) *
|
||||
* dividend zero 5.250 microseconds *
|
||||
* minimum time others 72.750 microseconds *
|
||||
* maximum time others 85.000 microseconds *
|
||||
* average others 76.687 microseconds *
|
||||
* *
|
||||
********************************************
|
||||
page
|
||||
ffpdiv idnt 1,1 ffp divide
|
||||
|
||||
xdef ffpdiv entry point
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
section 9
|
||||
|
||||
* divide by zero exit
|
||||
fpddzr divu.w #0,d7 **force divide by zero **
|
||||
|
||||
* if the exception returns with altered denominator - continue divide
|
||||
tst.l d6 ? exception alter the zero
|
||||
bne.s ffpdiv branch if so to continue
|
||||
* setup maximum number for divide overflow
|
||||
fpdovf or.l #$ffffff7f,d7 maximize with proper sign
|
||||
tst.b d7 set condition code for sign
|
||||
* or.w #$02,ccr set overflow bit
|
||||
dc.l $003c0002 ******sick assembler******
|
||||
fpdrtn rts return to caller
|
||||
|
||||
* over or underflow detected
|
||||
fpdov2 swap.w d6 restore arg1
|
||||
swap.w d7 restore arg2 for sign
|
||||
fpdovfs eor.b d6,d7 setup correct sign
|
||||
bra.s fpdovf and enter overflow handling
|
||||
fpdouf bmi.s fpdovfs branch if overflow
|
||||
fpdund move.l #0,d7 underflow to zero
|
||||
rts and return to caller
|
||||
|
||||
***************
|
||||
* entry point *
|
||||
***************
|
||||
|
||||
* first subtract exponents
|
||||
ffpdiv move.b d6,d5 copy arg1 (divisor)
|
||||
beq.s fpddzr branch if divide by zero
|
||||
move.l d7,d4 copy arg2 (dividend)
|
||||
beq.s fpdrtn return zero if dividend zero
|
||||
moveq #-128,d3 setup sign mask
|
||||
add.w d5,d5 isolate arg1 sign from exponent
|
||||
add.w d4,d4 isolate arg2 sign from exponent
|
||||
eor.b d3,d5 adjust arg1 exponent to binary
|
||||
eor.b d3,d4 adjust arg2 exponent to binary
|
||||
sub.b d5,d4 subtract exponents
|
||||
bvs.s fpdouf branch if overflow/underflow
|
||||
clr.b d7 clear arg2 s+exp
|
||||
swap.w d7 prepare high 16 bit compare
|
||||
swap.w d6 against arg1 and arg2
|
||||
cmp.w d6,d7 ? check if overflow will occur
|
||||
bmi.s fpdnov branch if not
|
||||
* adjust for fixed point divide overflow
|
||||
add.b #2,d4 adjust exponent up one
|
||||
bvs.s fpdov2 branch overflow here
|
||||
ror.l #1,d7 shift down by power of two
|
||||
fpdnov swap.w d7 correct arg2
|
||||
move.b d3,d5 move $80 into d5.b
|
||||
eor.w d5,d4 create sign and absolutize exponent
|
||||
lsr.w #1,d4 d4.b now has sign+exponent of result
|
||||
|
||||
* now divide just using 16 bits into 24
|
||||
move.l d7,d3 copy arg1 for initial divide
|
||||
divu.w d6,d3 obtain test quotient
|
||||
move.w d3,d5 save test quotient
|
||||
|
||||
* now multiply 16-bit divide result times full 24 bit divisor and compare
|
||||
* with the dividend. multiplying back out with the full 24-bits allows
|
||||
* us to see if the result was too large due to the 8 missing divisor bits
|
||||
* used in the hardware divide. the result can only be too large by 1 unit.
|
||||
mulu.w d6,d3 high divisor x quotient
|
||||
sub.l d3,d7 d7=partial subtraction
|
||||
swap.w d7 to low divisor
|
||||
swap.w d6 rebuild arg1 to normal
|
||||
move.w d6,d3 setup arg1 for product
|
||||
clr.b d3 zero low byte
|
||||
mulu.w d5,d3 find remaining product
|
||||
sub.l d3,d7 now have full subtraction
|
||||
bcc.s fpdqok branch first 16 bits correct
|
||||
|
||||
* estimate too high, decrement quotient by one
|
||||
move.l d6,d3 rebuild divisor
|
||||
clr.b d3 reverse halves
|
||||
add.l d3,d7 add another divisor
|
||||
sub.w #1,d5 decrement quotient
|
||||
|
||||
* compute last 8 bits with another divide. the exact remainder from the
|
||||
* multiply and compare above is divided again by a 16-bit only divisor.
|
||||
* however, this time we require only 9 bits of accuracy in the result
|
||||
* (8 to make 24 bits total and 1 extra bit for rounding purposes) and this
|
||||
* divide always returns a precision of at least 9 bits.
|
||||
fpdqok move.l d6,d3 copy arg1 again
|
||||
swap.w d3 first 16 bits divisor in d3.w
|
||||
clr.w d7 into first 16 bits of dividend
|
||||
divu.w d3,d7 obtain final 16 bit result
|
||||
swap.w d5 first 16 quotient to high half
|
||||
bmi.s fpdisn branch if normalized
|
||||
* rare occurrance - unnormalized
|
||||
* happends when mantissa arg1 < arg2 and they differ only in last 8 bits
|
||||
move.w d7,d5 insert low word of quotient
|
||||
add.l d5,d5 shift mantissa left one
|
||||
sub.b #1,d4 adjust exponent down (cannot zero)
|
||||
move.w d5,d7 cancel next instruction
|
||||
|
||||
* rebuild our final result and return
|
||||
fpdisn move.w d7,d5 append next 16 bits
|
||||
add.l #$80,d5 round to 24 bits (cannot overflow)
|
||||
move.l d5,d7 return in d7
|
||||
move.b d4,d7 finish result with sign+exponent
|
||||
beq.s fpdund underflow if zero exponent
|
||||
rts return result to caller
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,203 @@
|
||||
ttl fast floating point exponent (ffpexp)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* ffpexp *
|
||||
* fast floating point exponent *
|
||||
* *
|
||||
* input: d7 - input argument *
|
||||
* *
|
||||
* output: d7 - exponential result *
|
||||
* *
|
||||
* all other registers are transparent *
|
||||
* *
|
||||
* code size: 256 bytes stack work: 34 bytes *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if result in d7 is zero *
|
||||
* n - cleared *
|
||||
* v - set if overlow occurred *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) an overflow returns the largest *
|
||||
* magnitude number. *
|
||||
* 2) spot checks show at least 6.8 digit *
|
||||
* accuracy for all abs(arg) < 30. *
|
||||
* *
|
||||
* time: (8mhz no wait states assumed) *
|
||||
* *
|
||||
* 488 microseconds *
|
||||
* *
|
||||
* logic: 1) find n = int(arg/ln 2). this is *
|
||||
* added to the mantissa at the end.*
|
||||
* 3) reduce argument to range by *
|
||||
* finding arg = mod(arg, ln 2). *
|
||||
* 4) derive exp(arg) with cordic loop.*
|
||||
* 5) add n to exponent giving result. *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
ffpexp idnt 1,2 ffp exp
|
||||
|
||||
opt pcs
|
||||
|
||||
section 9
|
||||
|
||||
xdef ffpexp entry point
|
||||
|
||||
xref ffphthet hypertangent table
|
||||
|
||||
xref ffpmul2,ffpsub arithmetic primitives
|
||||
xref ffptnorm transcendental normalize routine
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
ln2 equ $b1721840 ln 2 (base e) .693147180
|
||||
ln2inv equ $b8aa3b41 inverse of ln 2 (base e) 1.44269504
|
||||
cnjkhinv equ $9a8f4441 floating conjugate of k inverse
|
||||
* corrected for the extra convergence
|
||||
* during shifts for 4 and 13
|
||||
kfctseed equ $26a3d100 k cordic seed
|
||||
|
||||
|
||||
* overflow - return zero or highest value and "v" bit
|
||||
fpeovflw move.w (sp)+,d6 load sign word and work off stack
|
||||
tst.b d6 ? was argument negative
|
||||
bpl.s fpovnzro no, continue
|
||||
move.l #0,d7 return a zero
|
||||
bra.s fpovrtn as result is too small
|
||||
fpovnzro move.l #-1,d7 set all zeroes
|
||||
lsr.b #1,d7 zero sign bit
|
||||
* or.b #$02,ccr set overflow bit
|
||||
dc.l $003c0002 ***assembler error***
|
||||
fpovrtn movem.l (sp)+,d1-d6/a0 restore registers
|
||||
rts return to caller
|
||||
|
||||
* return one for zero argument
|
||||
ffpe1 move.l #$80000041,d7 return a true one
|
||||
lea 7*4+2(sp),sp ignore stack saves
|
||||
tst.b d7 set condition code properly
|
||||
rts return to caller
|
||||
|
||||
**************
|
||||
* exp entry *
|
||||
**************
|
||||
|
||||
* save work registers and insure positive argument
|
||||
ffpexp movem.l d1-d6/a0,-(sp) save all work registers
|
||||
move.w d7,-(sp) save sign in low order byte for later
|
||||
beq.s ffpe1 return a true one for zero exponent
|
||||
and.b #$7f,d7 take absolute value
|
||||
|
||||
* divide by log 2 base e for partial result
|
||||
fpepos move.l d7,d2 save original argument
|
||||
move.l #ln2inv,d6 load inverse to multiply (faster)
|
||||
jsr ffpmul2 obtain division thru multiply
|
||||
bvs fpeovflw branch if too large
|
||||
* convert quotient to both fixed and float integer
|
||||
move.b d7,d5 copy exponent over
|
||||
move.b d7,d6 copy exponent over
|
||||
sub.b #64+32,d5 find non-fractional precision
|
||||
neg.b d5 make positive
|
||||
cmp.b #24,d5 ? insure not too large
|
||||
ble.s fpeovflw branch too large
|
||||
cmp.b #32,d5 ? test upper range
|
||||
bge.s fpesml branch less than one
|
||||
lsr.l d5,d7 shift to integer
|
||||
move.b d7,(sp) place adjusted exponent with sign byte
|
||||
lsl.l d5,d7 back to normal without fraction
|
||||
move.b d6,d7 re-insert sign+exponent
|
||||
move.l #ln2,d6 multiply by ln2 to find residue
|
||||
jsr ffpmul2 multiply back out
|
||||
move.l d7,d6 setup to subtract multiple of ln 2
|
||||
move.l d2,d7 move argument in
|
||||
jsr ffpsub find remainder of ln 2 divide
|
||||
move.l d7,d2 copy float argument
|
||||
bra.s fpeadj adjust to fixed
|
||||
|
||||
* multiple less than one
|
||||
fpesml clr.b (sp) default initial multiply to zero
|
||||
move.l d2,d7 back to original argument
|
||||
|
||||
* convert argument to binary(31,29) precision
|
||||
fpeadj clr.b d7 clear sign and exponent
|
||||
sub.b #64+3,d2 obtain shift value
|
||||
neg.b d2 for 2 non-fraction bits
|
||||
cmp.b #31,d2 insure not too small
|
||||
bls.s fpeshf branch to shift if ok
|
||||
move.l #0,d7 force to zero
|
||||
fpeshf lsr.l d2,d7 convert to fixed point
|
||||
|
||||
*****************************************
|
||||
* cordic calculation registers: *
|
||||
* d1 - loop count a0 - table pointer *
|
||||
* d2 - shift count *
|
||||
* d3 - y' d5 - y *
|
||||
* d4 - x' d6 - x *
|
||||
* d7 - test argument *
|
||||
*****************************************
|
||||
|
||||
* input within range, now start cordic setup
|
||||
fpecom move.l #0,d5 y=0
|
||||
move.l #kfctseed,d6 x=1 with jkhinverse factored out
|
||||
lea ffphthet,a0 point to hperbolic tangent table
|
||||
move.l #0,d2 prime shift counter
|
||||
|
||||
* perform cordic loop repeating shifts 4 and 13 to guarantee convergence
|
||||
* (ref. "a unified algorithm for elementary functions" j.s.walther
|
||||
* pg. 380 spring joint computer conference 1971)
|
||||
move.l #3,d1 do shifts 1 thru 4
|
||||
bsr.s cordic first cordic loops
|
||||
sub.l #4,a0 redo table entry
|
||||
sub.w #1,d2 redo shift count
|
||||
move.l #9,d1 do four through 13
|
||||
bsr.s cordic second cordic loops
|
||||
sub.l #4,a0 back to entry 13
|
||||
sub.w #1,d2 redo shift for 13
|
||||
move.l #10,d1 now 13 through 23
|
||||
bsr.s cordic and finish up
|
||||
|
||||
* now finalize the result
|
||||
tst.b 1(sp) test original sign
|
||||
bpl.s fsepos branch positive argument
|
||||
neg.l d5 change y for subtraction
|
||||
neg.b (sp) negate adjusted exponent to subtract
|
||||
fsepos add.l d5,d6 add or subtract y to/from x
|
||||
jsr ffptnorm float x
|
||||
move.l d6,d7 setup result
|
||||
* add ln2 factor integer to the exponent
|
||||
add.b (sp),d7 add to exponent
|
||||
bmi fpeovflw branch if too large
|
||||
beq fpeovflw branch if too small
|
||||
add.l #2,sp rid work data off stack
|
||||
movem.l (sp)+,d1-d6/a0 restore registers
|
||||
rts return to caller
|
||||
|
||||
*************************
|
||||
* cordic loop subroutine*
|
||||
*************************
|
||||
cordic add.w #1,d2 increment shift count
|
||||
move.l d5,d3 copy y
|
||||
move.l d6,d4 copy x
|
||||
asr.l d2,d3 shift for y'
|
||||
asr.l d2,d4 shift for x'
|
||||
tst.l d7 test arg value
|
||||
bmi.s febmi branch minus test
|
||||
add.l d4,d5 y=y+x'
|
||||
add.l d3,d6 x=x+y'
|
||||
sub.l (a0)+,d7 arg=arg-table(n)
|
||||
dbra d1,cordic loop until done
|
||||
rts return
|
||||
|
||||
febmi sub.l d4,d5 y=y-x'
|
||||
sub.l d3,d6 x=x-y'
|
||||
add.l (a0)+,d7 arg=arg+table(n)
|
||||
dbra d1,cordic loop until done
|
||||
rts return
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,48 @@
|
||||
ttl fast floating point cordic hyperbolic table (ffphthet)
|
||||
ffphthet idnt 1,1 ffp inverse hyperbolic table
|
||||
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
section 9
|
||||
|
||||
xdef ffphthet external definition
|
||||
|
||||
*********************************************************
|
||||
* inverse hyperbolic tangent table for cordic *
|
||||
* *
|
||||
* the following table is used during cordic *
|
||||
* transcendental evaluations for log and exp. it has *
|
||||
* inverse hyperbolic tangent for 2**-n where n ranges *
|
||||
* from 1 to 24. the format is binary(31,29) *
|
||||
* precision (i.e. the binary point is assumed between *
|
||||
* bits 27 and 28 with three leading non-fraction bits.) *
|
||||
*********************************************************
|
||||
|
||||
ffphthet dc.l $1193ea7a $8c9f53d0>>3 harctan(2**-1) .549306144
|
||||
dc.l $4162bbe8>>3 harctan(2**-2) .255412812
|
||||
dc.l $202b1238>>3 harctan(2**-3)
|
||||
dc.l $10055888>>3 harctan(2**-4)
|
||||
dc.l $0800aac0>>3 harctan(2**-5)
|
||||
dc.l $04001550>>3 harctan(2**-6)
|
||||
dc.l $020002a8>>3 harctan(2**-7)
|
||||
dc.l $01000050>>3 harctan(2**-8)
|
||||
dc.l $00800008>>3 harctan(2**-9)
|
||||
dc.l $00400000>>3 harctan(2**-10)
|
||||
dc.l $00200000>>3 harctan(2**-11)
|
||||
dc.l $00100000>>3 harctan(2**-12)
|
||||
dc.l $00080000>>3 harctan(2**-13)
|
||||
dc.l $00040000>>3 harctan(2**-14)
|
||||
dc.l $00020000>>3 harctan(2**-15)
|
||||
dc.l $00010000>>3 harctan(2**-16)
|
||||
dc.l $00008000>>3 harctan(2**-17)
|
||||
dc.l $00004000>>3 harctan(2**-18)
|
||||
dc.l $00002000>>3 harctan(2**-19)
|
||||
dc.l $00001000>>3 harctan(2**-20)
|
||||
dc.l $00000800>>3 harctan(2**-21)
|
||||
dc.l $00000400>>3 harctan(2**-22)
|
||||
dc.l $00000200>>3 harctan(2**-23)
|
||||
dc.l $00000100>>3 harctan(2**-24)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,220 @@
|
||||
ttl ffpieee conversions to/from ffp (ffptieee,ffpfieee)
|
||||
******************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
******************************************
|
||||
|
||||
****************************************************
|
||||
* ffptieee and ffpfieee subroutines *
|
||||
* *
|
||||
* this module contains single-precision *
|
||||
* conversion routines for ieee format floating *
|
||||
* point (draft 8.0) to and from motorola fast *
|
||||
* floating point (ffp) values. *
|
||||
* these can be used when large groups of numbers *
|
||||
* need to be converted between formats. see *
|
||||
* the mc68344 user's guide for a fuller *
|
||||
* explanation of the various methods for ieee *
|
||||
* format support. *
|
||||
* *
|
||||
* the fast floating point (non-ieee format) *
|
||||
* provides results as precise as those required *
|
||||
* by the ieee specification. however, this *
|
||||
* format has some minor differences: *
|
||||
* 1) if the true result of an operation *
|
||||
* is exactly between representable *
|
||||
* values, the ffp round-to-nearest *
|
||||
* function may round to either even or odd. *
|
||||
* 2) the ffp exponent allows half of the range *
|
||||
* that the single-precision ieee format *
|
||||
* provides (approx. 10 to the +-19 decimal). *
|
||||
* 3) the ieee format specifies infinity, *
|
||||
* not-a-number, and denormalized data *
|
||||
* types that are not directly supported *
|
||||
* by the ffp format. however, they may be *
|
||||
* added via customizing or used via the ieee *
|
||||
* format equivalent compatible calls *
|
||||
* described in the mc68344 user's guide. *
|
||||
* 4) all zeroes are considered positive *
|
||||
* in ffp format. *
|
||||
* 5) the slightly higher precision multiply *
|
||||
* routine "ffpmul2" should be substituted *
|
||||
* for the default routine "ffpmul" for *
|
||||
* completely equivalent precision. *
|
||||
* *
|
||||
****************************************************
|
||||
page
|
||||
ffpieee idnt 1,1 ffp conversions to/from ieee format
|
||||
|
||||
section 9
|
||||
|
||||
xdef ffptieee,ffpfieee
|
||||
|
||||
****************************************************
|
||||
* ffptieee *
|
||||
* *
|
||||
* fast floating point to ieee format *
|
||||
* *
|
||||
* input: d7 - fast floating point value *
|
||||
* *
|
||||
* output: d7 - ieee format floating point value *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - set if the result is negative *
|
||||
* z - set if the result is zero *
|
||||
* v - undefined *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) no work storage or registers required. *
|
||||
* 2) all zeroes will be converted positive. *
|
||||
* 3) no not-a-number, inifinity, denormalized, *
|
||||
* or indefinites generated. (unless *
|
||||
* user customized.) *
|
||||
* *
|
||||
* times (assuming in-line code): *
|
||||
* value zero 18 cycles *
|
||||
* value not zero 66 cycles *
|
||||
* *
|
||||
****************************************************
|
||||
|
||||
ffptieee equ *
|
||||
|
||||
add.l d7,d7 delete mantissa high bit
|
||||
beq.s done1 branch zero as finished
|
||||
eor.b #$80,d7 to twos complement exponent
|
||||
asr.b #1,d7 form 8-bit exponent
|
||||
sub.b #$82,d7 adjust 64 to 127 and excessize
|
||||
swap.w d7 swap for high byte placement
|
||||
rol.l #7,d7 set sign+exp in high byte
|
||||
done1 equ *
|
||||
|
||||
rts return to caller
|
||||
page
|
||||
************************************************************
|
||||
* ffpfieee *
|
||||
* fast floating point from ieee format *
|
||||
* *
|
||||
* input: d7 - ieee format floating point value *
|
||||
* output: d7 - ffp format floating point value *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - undefined *
|
||||
* z - set if the result is zero *
|
||||
* v - set if result overflowed ffp format *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) register d5 is used for work storage and not *
|
||||
* transparent. *
|
||||
* 2) not-a-number, inifinity, and denormalized *
|
||||
* types as well as an exponent outside of ffp range *
|
||||
* generate a branch to a specific part of the *
|
||||
* routine. customizing may easily be done there. *
|
||||
* *
|
||||
* the default actions for the various types are: *
|
||||
* label type default substitution *
|
||||
* ----- ---- -------------------- *
|
||||
* nan not-a-number zero *
|
||||
* inf infinity largest ffp value same sign *
|
||||
* ("v" set in ccr) *
|
||||
* denor denormalized zero *
|
||||
* exphi exp too large largest ffp value same sign *
|
||||
* ("v" set in ccr) *
|
||||
* explo exp too small zero *
|
||||
* *
|
||||
* times (assuming in-line code): *
|
||||
* value zero 78 cycles *
|
||||
* value not zero 72 cycles *
|
||||
* *
|
||||
************************************************************
|
||||
|
||||
vbit equ $02 condition code register "v" bit mask
|
||||
|
||||
ffpfieee equ *
|
||||
|
||||
swap.w d7 swap word halves
|
||||
ror.l #7,d7 exponent to low byte
|
||||
move.l #-128,d5 load $80 mask in work register
|
||||
eor.b d5,d7 convert from excess 127 to two's-complement
|
||||
add.b d7,d7 from 8 to 7 bit exponent
|
||||
bvs.s ffpovf branch will not fit
|
||||
add.b #2<<1+1,d7 adjust excess 127 to 64 and set mantissa high bit
|
||||
bvs.s exphi branch exponent too large (overflow)
|
||||
eor.b d5,d7 back to excess 64
|
||||
ror.l #1,d7 to fast float representation ("v" cleared)
|
||||
done2 equ *
|
||||
|
||||
rts return to caller
|
||||
page
|
||||
* overflow detected - caused by one of the following:
|
||||
* - false overflow due to difference between excess 127 and 64 format
|
||||
* - exponent too high or low to fit in 7 bits (exponent over/underflow)
|
||||
* - an exponent of $ff representing an infinity
|
||||
* - an exponent of $00 representing a zero, nan, or denormalized value
|
||||
ffpovf bcc.s ffpovlw branch if overflow (exponent $ff or too large)
|
||||
* overflow - check for possible false overflow due to different excess formats
|
||||
cmp.b #$7c,d7 ? was original argument really in range
|
||||
beq.s ffpovfls yes, branch false overflow
|
||||
cmp.b #$7e,d7 ? was original argument really in range
|
||||
bne.s ffptovf no, branch true overflow
|
||||
ffpovfls add.b #$80+2<<1+1,d7 excess 64 adjustment and mantissa high bit
|
||||
ror.l #1,d7 finalize to fast floating point format
|
||||
tst.b d7 insure no illegal zero sign+exponent byte
|
||||
bne.s done2 done if does not set s+exp all zeroes
|
||||
bra.s explo treat as underflowed exponent otherwise
|
||||
* exponent low - check for zero, denormalized value, or too small an exponent
|
||||
ffptovf and.w #$feff,d7 clear sign bit out
|
||||
tst.l d7 ? entire value now zero
|
||||
beq.s done2 branch if value is zero
|
||||
tst.b d7 ? denormalized number (significant#0, exp=0)
|
||||
beq.s denor branch if denormalized
|
||||
|
||||
***************
|
||||
*****explo - exponent to small for ffp format
|
||||
***************
|
||||
* the sign bit will be bit 8.
|
||||
explo move.l #0,d7 default zero for this case ("v" cleared)
|
||||
bra.s done2 return to mainline
|
||||
|
||||
***************
|
||||
*****denor - denormalized number
|
||||
***************
|
||||
denor move.l #0,d7 default is to return a zero ("v" cleared)
|
||||
bra.s done2 return to mainline
|
||||
|
||||
* exponent high - check for exponent too high, infinity, or nan
|
||||
ffpovlw cmp.b #$fe,d7 ? was original exponent $ff
|
||||
bne.s exphi no, branch exponent too large
|
||||
lsr.l #8,d7 shift out exponent
|
||||
lsr.l #1,d7 shift out sign
|
||||
bne.s nan branch not-a-number
|
||||
|
||||
***************
|
||||
*****inf - infinity
|
||||
***************
|
||||
* the carry and x bit represent the sign
|
||||
inf move.l #-1,d7 setup maximum ffp value
|
||||
roxr.b #1,d7 shift in sign
|
||||
or.b #vbit,ccr show overflow occured [clh] was sr
|
||||
bra.s done2 return with maximum same sign to mainline
|
||||
|
||||
***************
|
||||
*****exphi - exponent to large for ffp format
|
||||
***************
|
||||
* the sign bit will be bit 8.
|
||||
exphi lsl.w #8,d7 set x bit to sign
|
||||
move.l #-1,d7 setup maximum number
|
||||
roxr.b #1,d7 shift in sign
|
||||
or.b #vbit,ccr show overflow ocurred [vlh] was sr
|
||||
bra.s done2 return maximum same sign to mainline
|
||||
|
||||
***************
|
||||
*****nan - not-a-number
|
||||
***************
|
||||
* bits 0 thru 22 contain the nan data field
|
||||
nan move.l #0,d7 default to a zero ("v" bit cleared)
|
||||
bra.s done2 return to mainline
|
||||
|
||||
end
|
||||
@@ -0,0 +1,161 @@
|
||||
ttl fast floating point log (ffplog)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* ffplog *
|
||||
* fast floating point logorithm *
|
||||
* *
|
||||
* input: d7 - input argument *
|
||||
* *
|
||||
* output: d7 - logorithmic result to base e *
|
||||
* *
|
||||
* all other registers totally transparent *
|
||||
* *
|
||||
* code size: 184 bytes stack work: 38 bytes *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if the result is zero *
|
||||
* n - set if result in is negative *
|
||||
* v - set if invalid negative argument *
|
||||
* or zero argument *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) spot checks show errors bounded by *
|
||||
* 5 x 10**-8. *
|
||||
* 2) negative arguments are illegal and cause*
|
||||
* the "v" bit to be set and the absolute *
|
||||
* value used instead. *
|
||||
* 3) a zero argument returns the largest *
|
||||
* negative value possible with the "v" bit*
|
||||
* set. *
|
||||
* *
|
||||
* time: (8mhz no wait states assumed) *
|
||||
* *
|
||||
* times are very data sensitive with *
|
||||
* samples ranging from 170 to 556 *
|
||||
* microseconds *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
ffplog idnt 1,2 ffp log
|
||||
|
||||
opt pcs
|
||||
section 9
|
||||
|
||||
xdef ffplog entry point
|
||||
|
||||
xref ffphthet hypertangent table
|
||||
xref ffpadd,ffpdiv,ffpsub,ffpmul2 arithmetic primitives
|
||||
xref ffptnorm transcendental normalize routine
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
fpone equ $80000041 floating value for one
|
||||
log2 equ $b1721840 log(2) = .6931471805
|
||||
|
||||
**************
|
||||
* log entry *
|
||||
**************
|
||||
|
||||
* insure argument positive
|
||||
ffplog tst.b d7 ? test sign
|
||||
beq.s fplzro branch argument zero
|
||||
bpl.s fplok branch alright
|
||||
|
||||
* argument is negative - use the absolute value and set the "v" bit
|
||||
and.b #$7f,d7 take absolute value
|
||||
bsr.s fplok find log(abs(x))
|
||||
*psetv or.b #$02,ccr set overflow bit
|
||||
fpsetv dc.l $003c0002 ***assembler error***
|
||||
rts return to caller
|
||||
|
||||
* argument is zero - return largest negative number with "v" bit
|
||||
fplzro move.l #-1,d7 return largest negative
|
||||
jmp fpsetv return with "v" bit set
|
||||
|
||||
* save work registers and strip exponent off
|
||||
fplok movem.l d1-d6/a0,-(sp) save all work registers
|
||||
move.b d7,-(sp) save original exponent
|
||||
move.b #64+1,d7 force between 1 and 2
|
||||
move.l #fpone,d6 load up a one
|
||||
move.l d7,d2 copy argument
|
||||
jsr ffpadd create arg+1
|
||||
exg.l d7,d2 swap result with argument
|
||||
jsr ffpsub create arg-1
|
||||
move.l d2,d6 prepare for divide
|
||||
jsr ffpdiv result is (arg-1)/(arg+1)
|
||||
beq.s fplnocr zero so cordic not needed
|
||||
* convert to bin(31,29) precision
|
||||
sub.b #64+3,d7 adjust exponent
|
||||
neg.b d7 for shift necessary
|
||||
cmp.b #31,d7 ? insure not too small
|
||||
bls.s fplshf no, go shift
|
||||
move.l #0,d7 force to zero
|
||||
fplshf lsr.l d7,d7 shift to bin(31,29) precision
|
||||
|
||||
*****************************************
|
||||
* cordic calculation registers: *
|
||||
* d1 - loop count a0 - table pointer *
|
||||
* d2 - shift count *
|
||||
* d3 - y' d5 - y *
|
||||
* d4 - x' d6 - z *
|
||||
* d7 - x *
|
||||
*****************************************
|
||||
|
||||
move.l #0,d6 z=0
|
||||
move.l #1<<29,d5 y=1
|
||||
lea ffphthet,a0 to inverse hyperbolic tangent table
|
||||
move.l #22,d1 loop 23 times
|
||||
move.l #1,d2 prime shift counter
|
||||
bra.s cordic enter cordic loop
|
||||
|
||||
* cordic loop
|
||||
fplpls asr.l d2,d4 shift(x')
|
||||
sub.l d4,d5 y = y - x'
|
||||
add.l (a0),d6 z = z + hypertan(i)
|
||||
cordic move.l d7,d4 x' = x
|
||||
move.l d5,d3 y' = y
|
||||
asr.l d2,d3 shift(y')
|
||||
fplnlp sub.l d3,d7 x = x - y'
|
||||
bpl.s fplpls branch negative
|
||||
move.l d4,d7 restore x
|
||||
add.l #4,a0 to next table entry
|
||||
add.b #1,d2 increment shift count
|
||||
lsr.l #1,d3 shift(y')
|
||||
dbra d1,fplnlp and loop until done
|
||||
|
||||
* now convert to float and add exponent*log(2) for final result
|
||||
move.l #0,d7 default zero if too small
|
||||
jsr ffptnorm float z
|
||||
beq.s fplnocr branch if too small
|
||||
add.b #1,d6 times two
|
||||
move.l d6,d7 setup in d7 in case exp=0
|
||||
fplnocr move.l d7,d2 save result
|
||||
move.l #0,d6 prepare original exponent load
|
||||
move.b (sp)+,d6 load it back
|
||||
sub.b #64+1,d6 convert exponent to binary
|
||||
beq.s fplzpr branch zero partial here
|
||||
move.b d6,d1 save sign byte
|
||||
bpl.s fplpos branch positive value
|
||||
neg.b d6 force positive
|
||||
fplpos ror.l #8,d6 prepare to convert to integer
|
||||
move.l #$47,d5 setup exponent mask
|
||||
fplnorm add.l d6,d6 shift to left
|
||||
dbmi d5,fplnorm exp-1 and branch if not normalized
|
||||
move.b d5,d6 fix in exponent
|
||||
and.b #$80,d1 extract sign
|
||||
or.b d1,d6 insert sign in
|
||||
move.l #log2,d7 multiply exponent by log(2)
|
||||
jsr ffpmul2 multiply d6 and d7
|
||||
move.l d2,d6 now add cordic result
|
||||
jsr ffpadd for final answer
|
||||
|
||||
fplzpr movem.l (sp)+,d1-d6/a0 restore registers
|
||||
rts return to caller
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,132 @@
|
||||
ttl fast floating point precise multiply (ffpmul2)
|
||||
*******************************************
|
||||
* (c) copyright 1980 by motorola inc. *
|
||||
*******************************************
|
||||
|
||||
********************************************
|
||||
* ffpmul2 subroutine *
|
||||
* *
|
||||
* this module is the second of the *
|
||||
* multiply routines. it is 18% slower *
|
||||
* but provides the highest accuracy *
|
||||
* possible. the error is exactly .5 *
|
||||
* least significant bit versus an error *
|
||||
* in the high-speed default routine of *
|
||||
* .50390625 least significant bit due *
|
||||
* to truncation. *
|
||||
* *
|
||||
* input: *
|
||||
* d6 - floating point multiplier *
|
||||
* d7 - floating point multiplican *
|
||||
* *
|
||||
* output: *
|
||||
* d7 - floating point result *
|
||||
* *
|
||||
* registers d3 thru d5 are volatile *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - set if result negative *
|
||||
* z - set if result is zero *
|
||||
* v - set if overflow occurred *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* code: 134 bytes stack work: 0 bytes *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) multipier unaltered (d6). *
|
||||
* 2) underflows return zero with no *
|
||||
* indicator set. *
|
||||
* 3) overflows will return the maximum *
|
||||
* value with the proper sign and the *
|
||||
* 'v' bit set in the ccr. *
|
||||
* *
|
||||
* times: (8mhz no wait states assumed) *
|
||||
* arg1 zero 5.750 microseconds *
|
||||
* arg2 zero 3.750 microseconds *
|
||||
* minimum time others 45.750 microseconds *
|
||||
* maximum time others 61.500 microseconds *
|
||||
* average others 52.875 microseconds *
|
||||
* *
|
||||
********************************************
|
||||
page
|
||||
ffpmul2 idnt 1,1 ffp high-precision multiply
|
||||
|
||||
xdef ffpmul2 entry point
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
section 9
|
||||
|
||||
|
||||
* ffpmul2 subroutine entry point
|
||||
ffpmul2 move.b d7,d5 prepare sign/exponent work 4
|
||||
beq.s ffmrtn return if result already zero 8/10
|
||||
move.b d6,d4 copy arg1 sign/exponent 4
|
||||
beq.s ffmrt0 return zero if arg1=0 8/10
|
||||
add.w d5,d5 shift left by one 4
|
||||
add.w d4,d4 shift left by one 4
|
||||
moveq #-128,d3 prepare exponent modifier ($80) 4
|
||||
eor.b d3,d4 adjust arg1 exponent to binary 4
|
||||
eor.b d3,d5 adjust arg2 exponent to binary 4
|
||||
add.b d4,d5 add exponents 4
|
||||
bvs.s ffmouf branch if overflow/underflow 8/10
|
||||
move.b d3,d4 overlay $80 constant into d4 4
|
||||
eor.w d4,d5 d5 now has sign and exponent 4
|
||||
ror.w #1,d5 move to low 8 bits 8
|
||||
swap.w d5 save final s+exp in high word 4
|
||||
move.w d6,d5 copy arg1 low byte 4
|
||||
clr.b d7 clear s+exp out of arg2 4
|
||||
clr.b d5 clear s+exp out of arg1 low byte 4
|
||||
move.w d5,d4 prepare arg1lowb for multiply 4
|
||||
mulu.w d7,d4 d4 = arg2lowb x arg1lowb 38-54 (46)
|
||||
swap.w d4 place result in low word 4
|
||||
move.l d7,d3 copy arg2 4
|
||||
swap.w d3 to arg2highw 4
|
||||
mulu.w d5,d3 d3 = arg1lowb x arg2highw 38-54 (46)
|
||||
add.l d3,d4 d4 = partial product (no carry) 8
|
||||
swap.w d6 to arg1 high two bytes 4
|
||||
move.l d6,d3 copy arg1highw over 4
|
||||
mulu.w d7,d3 d3 = arg2lowb x arg1highw 38-54 (46)
|
||||
add.l d3,d4 d4 = partial product 8
|
||||
clr.w d4 clear low end runoff 4
|
||||
addx.b d4,d4 shift in carry if any 4
|
||||
swap.w d4 put carry into high word 4
|
||||
swap.w d7 now top of arg2 4
|
||||
mulu.w d6,d7 d7 = arg1highw x arg2highw 40-70 (54)
|
||||
swap.w d6 restore arg1 4
|
||||
swap.w d5 restore s+exp to low word
|
||||
add.l d4,d7 add partial products 8
|
||||
bpl ffmnor branch if must normalize 8/10
|
||||
add.l #$80,d7 round up (cannot overflow) 16
|
||||
move.b d5,d7 insert sign and exponent 4
|
||||
beq.s ffmrt0 return zero if zero exponent 8/10
|
||||
ffmrtn rts return to caller 16
|
||||
|
||||
* must normalize result
|
||||
ffmnor sub.b #1,d5 bump exponent down by one 4
|
||||
bvs.s ffmrt0 return zero if underflow 8/10
|
||||
bcs.s ffmrt0 return zero if sign inverted 8/10
|
||||
moveq #$40,d4 rounding factor 4
|
||||
add.l d4,d7 add in rounding factor 8
|
||||
add.l d7,d7 shift to normalize 8
|
||||
bcc.s ffmcln return normalized number 8/10
|
||||
roxr.l #1,d7 rounding forced carry in top bit 10
|
||||
add.b #1,d5 undo normalize attempt 4
|
||||
ffmcln move.b d5,d7 insert sign and exponent 4
|
||||
beq.s ffmrt0 return zero if exponent zero 8/10
|
||||
rts return to caller 16
|
||||
|
||||
* arg1 zero
|
||||
ffmrt0 move.l #0,d7 return zero 4
|
||||
rts return to caller 16
|
||||
|
||||
* overflow or underflow exponent
|
||||
ffmouf bpl.s ffmrt0 branch if underflow to give zero 8/10
|
||||
eor.b d6,d7 calculate proper sign 4
|
||||
or.l #$ffffff7f,d7 force highest value possible 16
|
||||
tst.b d7 set sign in return code
|
||||
* ori.b #$02,ccr set overflow bit
|
||||
dc.l $003c0002 ****sick assembler**** 20
|
||||
rts return to caller 16
|
||||
|
||||
end
|
||||
@@ -0,0 +1,80 @@
|
||||
ttl fast floating point power (ffppwr)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* ffppwr *
|
||||
* fast floating point power function *
|
||||
* *
|
||||
* input: d6 - floating point exponent value *
|
||||
* d7 - floating point argument value *
|
||||
* *
|
||||
* output: d7 - result of the value taken to *
|
||||
* the power specified *
|
||||
* *
|
||||
* all registers but d7 are transparent *
|
||||
* *
|
||||
* code size: 36 bytes stack work: 42 bytes *
|
||||
* *
|
||||
* calls subroutines: ffplog, ffpexp and ffpmul2 *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if the result is zero *
|
||||
* n - cleared *
|
||||
* v - set if overflow occurred or base *
|
||||
* value argument was negative *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) a negative base value will force the use*
|
||||
* if its absolute value. the "v" bit will*
|
||||
* be set upon function return. *
|
||||
* 2) if the result overflows then the *
|
||||
* maximum size value is returned with the *
|
||||
* "v" bit set in the condition code. *
|
||||
* 3) spot checks show at least six digit *
|
||||
* precision for 80 percent of the cases. *
|
||||
* *
|
||||
* time: (8mhz no wait states assumed) *
|
||||
* *
|
||||
* the timing is very data sensitive with *
|
||||
* test samples ranging from 720 to *
|
||||
* 1206 microseconds *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
ffppwr idnt 1,1 ffp power
|
||||
|
||||
opt pcs
|
||||
|
||||
section 9
|
||||
|
||||
xdef ffppwr entry point
|
||||
|
||||
xref ffplog,ffpexp exponent and log functions
|
||||
xref ffpmul2 multiply function
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
*****************
|
||||
* power entry *
|
||||
*****************
|
||||
|
||||
* take the logorithm of the base value
|
||||
ffppwr tst.b d7 ? negative base value
|
||||
bpl.s fpppos branch positive
|
||||
and.b #$7f,d7 take absolute value
|
||||
bsr.s fpppos find result using that
|
||||
* or.b #$02,ccr force "v" bit on for negative argument
|
||||
dc.l $003c0002 *****assembler error*****
|
||||
rts return to caller
|
||||
|
||||
fpppos jsr ffplog find log of the number to be used
|
||||
movem.l d3-d5,-(sp) save multiply work registers
|
||||
jsr ffpmul2 multiply by the exponent
|
||||
movem.l (sp)+,d3-d5 restore multiply work registers
|
||||
* if overflowed, ffpexp will set "v" bit and return desired result anyway
|
||||
jmp ffpexp result is exponent
|
||||
|
||||
end
|
||||
@@ -0,0 +1,283 @@
|
||||
ttl ffp sine cosine tangent (ffpsin/ffpcos/ffptan/ffpsincs)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* ffpsin ffpcos ffptan ffpsincs *
|
||||
* fast floating point sine/cosine/tangent *
|
||||
* *
|
||||
* input: d7 - input argument (radian) *
|
||||
* *
|
||||
* output: d7 - function result *
|
||||
* (ffpsincs also returns d6) *
|
||||
* *
|
||||
* all other registers totally transparent *
|
||||
* *
|
||||
* code size: 334 bytes stack work: 38 bytes *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if result in d7 is zero *
|
||||
* n - set if result in d7 is negative *
|
||||
* c - undefined *
|
||||
* v - set if result is meaningless *
|
||||
* (input magnitude too large) *
|
||||
* x - undefined *
|
||||
* *
|
||||
* functions: *
|
||||
* ffpsin - sine result *
|
||||
* ffpcos - cosine result *
|
||||
* ffptan - tangent result *
|
||||
* ffpsincs - both sine and cosine *
|
||||
* d6 - sin, d7 - cosine *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) input values are in radians. *
|
||||
* 2) function ffpsincs returns both sine *
|
||||
* and cosine twice as fast as calculating *
|
||||
* the two functions independently for *
|
||||
* the same value. this is handy for *
|
||||
* graphics processing. *
|
||||
* 2) input arguments larger than two pi *
|
||||
* suffer reduced precision. the larger *
|
||||
* the argument, the smaller the precision.*
|
||||
* excessively large arguments which have *
|
||||
* less than 5 bits of precision are *
|
||||
* returned unchanged with the "v" bit set.*
|
||||
* 3) for tangent angles of infinite value *
|
||||
* the largest possible positive number *
|
||||
* is returned ($ffffff7f). this still *
|
||||
* gives results well within single *
|
||||
* precision calculation. *
|
||||
* 4) spot checks show errors bounded by *
|
||||
* 4 x 10**-7 but for arguments close to *
|
||||
* pi/2 intervals where 10**-5 is seen. *
|
||||
* *
|
||||
* time: (8mhz no wait states and argument *
|
||||
* assumed within +-pi) *
|
||||
* *
|
||||
* ffpsin 413 microseconds *
|
||||
* ffpcos 409 microseconds *
|
||||
* ffptan 501 microseconds *
|
||||
* ffpsincs 420 microseconds *
|
||||
*************************************************
|
||||
page
|
||||
ffpsin idnt 1,2 ffp sine cosine tangent
|
||||
|
||||
opt pcs
|
||||
|
||||
section 9
|
||||
|
||||
xdef ffpsin,ffpcos,ffptan,ffpsincs entry points
|
||||
|
||||
xref ffptheta inverse tangent table
|
||||
|
||||
xref ffpmul2,ffpdiv,ffpsub multiply, divide and subtract
|
||||
xref ffptnorm transcendental normalize routine
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
pi equ $c90fdb42 floating constant pi
|
||||
fixedpi equ $c90fdaa2 pi skeleton to 32 bits precision
|
||||
inv2pi equ $a2f9833e inverse of two-pi
|
||||
kinv equ $9b74ee40 floating k inverse
|
||||
nkfact equ $ec916240 negative k inverse
|
||||
|
||||
********************************************
|
||||
* entry for returning both sine and cosine *
|
||||
********************************************
|
||||
ffpsincs move.w #-2,-(sp) flag both sine and cosine wanted
|
||||
bra.s fpscom enter common code
|
||||
|
||||
**********************
|
||||
* tangent entry point*
|
||||
**********************
|
||||
ffptan move.w #-1,-(sp) flag tangent with minus value
|
||||
bra.s fpschl check very small values
|
||||
|
||||
**************************
|
||||
* cosine only entry point*
|
||||
**************************
|
||||
ffpcos move.w #1,-(sp) flag cosine with positive value
|
||||
bra.s fpscom enter common code
|
||||
|
||||
* negative sine/tangent small value check
|
||||
fpschm cmp.b #$80+$40-8,d7 ? less or same as -2**-9
|
||||
bhi.s fpscom continue if not too small
|
||||
* return argument
|
||||
fpsrti add.l #2,sp rid internal parameter
|
||||
tst.b d7 set condition codes
|
||||
rts return to caller
|
||||
|
||||
************************
|
||||
* sine only entry point*
|
||||
************************
|
||||
ffpsin clr.w -(sp) flag sine with zero
|
||||
* sine and tangent values < 2**-9 return identities
|
||||
fpschl tst.b d7 test sign
|
||||
bmi.s fpschm branch minus
|
||||
cmp.b #$40-8,d7 ? less or same than 2**-9
|
||||
bls.s fpsrti return identity
|
||||
|
||||
* save registers and insure input within + or - pi range
|
||||
fpscom movem.l d1-d6/a0,-(sp) save all work registers
|
||||
move.l d7,d2 copy input over
|
||||
add.b d7,d7 rid sign bit
|
||||
cmp.b #(64+5)<<1,d7 ? abs(arg) < 2**6 (32)
|
||||
bls.s fpsnlr branch yes, not too large
|
||||
* argument is too large to subtract to within range
|
||||
cmp.b #(64+20)<<1,d7 ? test excessive size (>2**20)
|
||||
bls.s fpsgpr no, go ahead and use
|
||||
* error - argument so large result has no precision
|
||||
* or.b #$02,ccr force v bit on
|
||||
dc.l $003c0002 *****assembler error*****
|
||||
movem.l (sp)+,d1-d6/a0 restore registers
|
||||
add.l #2,sp clean internal argument off stack
|
||||
rts return to caller
|
||||
|
||||
* we must find mod(arg,twopi) since argument is too large for subtractions
|
||||
fpsgpr move.l #inv2pi,d6 load up 2*pi inverse constant
|
||||
move.l d2,d7 copy over input argument
|
||||
jsr ffpmul2 divide by 2pi (via multiply inverse)
|
||||
* convert quotient to float integer
|
||||
move.b d7,d5 copy exponent over
|
||||
and.b #$7f,d5 rid sign from exponent
|
||||
sub.b #64+24,d5 find fractional precision
|
||||
neg.b d5 make positive
|
||||
move.l #-1,d4 setup mask of all ones
|
||||
clr.b d4 start zeroes at low byte
|
||||
lsl.l d5,d4 shift zeroes into fractional part
|
||||
or.b #$ff,d4 do not remove sign and exponent
|
||||
and.l d4,d7 strip fractional bits entirely
|
||||
move.l #pi+1,d6 load up 2*pi constant
|
||||
jsr ffpmul2 multiply back out
|
||||
move.l d7,d6 setup to subtract multiple of twopi
|
||||
move.l d2,d7 move argument in
|
||||
jsr ffpsub find remainder of twopi divide
|
||||
move.l d7,d2 use it as new input argument
|
||||
|
||||
* convert argument to binary(31,26) precision for reduction within +-pi
|
||||
fpsnlr move.l #$0c90fdaa,d4 fixedpi>>4 load pi
|
||||
move.l d2,d7 copy float argument
|
||||
clr.b d7 clear sign and exponent
|
||||
tst.b d2 test sign
|
||||
bmi.s fpsnmi branch negative
|
||||
sub.b #64+6,d2 obtain shift value
|
||||
neg.b d2 for 5 bit non-fraction bits
|
||||
cmp.b #31,d2 ? very small number
|
||||
bls.s fpssh1 no, go ahead and shift
|
||||
move.l #0,d7 force to zero
|
||||
fpssh1 lsr.l d2,d7 convert to fixed point
|
||||
* force to +pi or below
|
||||
fpspck cmp.l d4,d7 ? greater than pi
|
||||
ble.s fpsckm branch not
|
||||
sub.l d4,d7 subtract
|
||||
sub.l d4,d7 . twopi
|
||||
bra.s fpspck and check again
|
||||
|
||||
fpsnmi sub.b #$80+64+6,d2 rid sign and get shift value
|
||||
neg.b d2 for 5 non-fractional bits
|
||||
cmp.b #31,d2 ? very small number
|
||||
bls.s fpssh2 no, go ahead and shift
|
||||
move.l #0,d7 force to zero
|
||||
fpssh2 lsr.l d2,d7 convert to fixed point
|
||||
neg.l d7 make negative
|
||||
neg.l d4 make -pi
|
||||
* force to -pi or above
|
||||
fpsnck cmp.l d4,d7 ? less than -pi
|
||||
bge.s fpsckm branch not
|
||||
sub.l d4,d7 add
|
||||
sub.l d4,d7 . twopi
|
||||
bra.s fpsnck and check again
|
||||
|
||||
*****************************************
|
||||
* cordic calculation registers: *
|
||||
* d1 - loop count a0 - table pointer *
|
||||
* d2 - shift count *
|
||||
* d3 - x' d5 - x *
|
||||
* d4 - y' d6 - y *
|
||||
* d7 - test argument *
|
||||
*****************************************
|
||||
|
||||
* input within range, now start cordic setup
|
||||
fpsckm move.l #0,d5 x=0
|
||||
move.l #nkfact,d6 y=negative inverse k factor seed
|
||||
move.l #$3243f6a8,d4 fixedpi>>2, setup fixed pi/2 constant
|
||||
asl.l #3,d7 now to binary(31,29) precision
|
||||
bmi.s fpsap2 branch if minus to add pi/2
|
||||
neg.l d6 y=positive inverse k factor seed
|
||||
neg.l d4 subtract pi/2 for positive argument
|
||||
fpsap2 add.l d4,d7 add constant
|
||||
lea ffptheta,a0 load arctangent table
|
||||
move.l #23,d1 loop 24 times
|
||||
move.l #-1,d2 prime shift counter
|
||||
* cordic loop
|
||||
fsinlp add.w #1,d2 increment shift count
|
||||
move.l d5,d3 copy x
|
||||
move.l d6,d4 copy y
|
||||
asr.l d2,d3 shift for x'
|
||||
asr.l d2,d4 shift for y'
|
||||
tst.l d7 test arg value
|
||||
bmi.s fsbmi branch minus test
|
||||
sub.l d4,d5 x=x-y'
|
||||
add.l d3,d6 y=y+x'
|
||||
sub.l (a0)+,d7 arg=arg-table(n)
|
||||
dbra d1,fsinlp loop until done
|
||||
bra.s fscom enter common code
|
||||
fsbmi add.l d4,d5 x=x+y'
|
||||
sub.l d3,d6 y=y-x'
|
||||
add.l (a0)+,d7 arg=arg+table(n)
|
||||
dbra d1,fsinlp loop until done
|
||||
|
||||
* now split up tangent and ffpsincs from sine and cosine
|
||||
fscom move.w 7*4(sp),d1 reload internal parameter
|
||||
bpl.s fssincos branch for sine or cosine
|
||||
|
||||
add.b #1,d1 see if was -1 for tangent
|
||||
bne.s fsdual no, must be both sin and cosine
|
||||
* tangent finish
|
||||
bsr.s fsfloat float y (sin)
|
||||
move.l d6,d7 setup for divide into
|
||||
move.l d5,d6 prepare x
|
||||
bsr.s fsfloat float x (cos)
|
||||
beq.s fstinf branch infinite result
|
||||
jsr ffpdiv tangent = sin/cos
|
||||
fsinfrt movem.l (sp)+,d1-d6/a0 restore registers
|
||||
add.l #2,sp delete internal parameter
|
||||
rts return to caller
|
||||
* tangent is infinite. return maximum positive number.
|
||||
fstinf move.l #$ffffff7f,d7 largest ffp number
|
||||
bra.s fsinfrt and clean up
|
||||
|
||||
* sine and cosine
|
||||
fssincos beq.s fssine branch if sine
|
||||
move.l d5,d6 use x for cosine
|
||||
fssine bsr.s fsfloat convert to float
|
||||
move.l d6,d7 return result
|
||||
tst.b d7 and condition code test
|
||||
movem.l (sp)+,d1-d6/a0 restore registers
|
||||
add.l #2,sp delete internal parameter
|
||||
rts return to caller
|
||||
|
||||
* both sine and cosine
|
||||
fsdual move.l d5,-(sp) save cosine derivitive
|
||||
bsr.s fsfloat convert sine derivitive to float
|
||||
move.l d6,6*4(sp) place sine into saved d6
|
||||
move.l (sp)+,d6 restore cosine derivitive
|
||||
bra.s fssine and continue restoring sine on the sly
|
||||
|
||||
* fsfloat - float internal precision but truncate to zero if < 2**-21
|
||||
fsfloat move.l d6,d4 copy internal precision value
|
||||
bmi.s fsfneg branch negative
|
||||
cmp.l #$000000ff,d6 ? test magnitude
|
||||
bhi dobranch ffptnorm normalize if not too small
|
||||
fsfzro move.l #0,d6 return a zero
|
||||
rts return to caller
|
||||
fsfneg asr.l #8,d4 see if all ones bits 8-31
|
||||
add.l #1,d4 ? goes to zero
|
||||
bne dobranch ffptnorm normalize if not too small
|
||||
bra.s fsfzro return zero
|
||||
dobranch:
|
||||
jmp ffptnorm for loader problem
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,112 @@
|
||||
ttl fast floating point square root (ffpsqrt)
|
||||
*******************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
*******************************************
|
||||
|
||||
********************************************
|
||||
* ffpsqrt subroutine *
|
||||
* *
|
||||
* input: *
|
||||
* d7 - floating point argument *
|
||||
* *
|
||||
* output: *
|
||||
* d7 - floating point square root *
|
||||
* *
|
||||
* condition codes: *
|
||||
* *
|
||||
* n - cleared *
|
||||
* z - set if result is zero *
|
||||
* v - set if argument was negative*
|
||||
* c - cleared *
|
||||
* x - undefined *
|
||||
* *
|
||||
* registers d3 thru d6 are volatile *
|
||||
* *
|
||||
* code: 194 bytes stack work: 4 bytes *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) no overflows or underflows can *
|
||||
* occur. *
|
||||
* 2) a negative argument causes the *
|
||||
* absolute value to be used and the *
|
||||
* "v" bit set to indicate that a *
|
||||
* negative square root was attempted. *
|
||||
* *
|
||||
* times: *
|
||||
* argument zero 3.50 microseconds *
|
||||
* minimum time > 0 187.50 microseconds *
|
||||
* average time > 0 193.75 microseconds *
|
||||
* maximum time > 0 200.00 microseconds *
|
||||
********************************************
|
||||
page
|
||||
ffpsqrt idnt 1,1 ffp square root
|
||||
|
||||
section 9
|
||||
|
||||
xdef ffpsqrt entry point
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
* negative argument handler
|
||||
fpsinv and.b #$7f,d7 take absolute value
|
||||
bsr.s ffpsqrt find sqrt(abs(x))
|
||||
* or.b $02,ccr set "v" bit
|
||||
dc.l $003c0002 **assembler error**
|
||||
rts return to caller
|
||||
|
||||
*********************
|
||||
* square root entry *
|
||||
*********************
|
||||
ffpsqrt move.b d7,d3 copy s+exponent over
|
||||
beq.s fpsrtn return zero if zero argument
|
||||
bmi.s fpsinv negative, reject with special condition codes
|
||||
lsr.b #1,d3 divide exponent by two
|
||||
bcc.s fpseven branch exponent was even
|
||||
add.b #1,d3 adjust odd values up by one
|
||||
lsr.l #1,d7 offset odd exponent's mantissa one bit
|
||||
fpseven add.b #$20,d3 renormalize exponent
|
||||
swap.w d3 save result s+exp for final move
|
||||
move.w #23,d3 setup loop for 24 bit generation
|
||||
lsr.l #7,d7 prepare first test value
|
||||
move.l d7,d4 d4 - previous value during loop
|
||||
move.l d7,d5 d5 - new test value during loop
|
||||
move.l a0,d6 save address register
|
||||
lea fpstbl(pc),a0 load table address
|
||||
move.l #$00800000,d7 d7 - initial result (must be a one)
|
||||
sub.l d7,d4 preset old value in case zero bit next
|
||||
sub.l #$01200000,d5 combine first loop calculations
|
||||
bra.s fpsent go enter loop calculations
|
||||
|
||||
* square root calculation
|
||||
* this is an optimized scheme for the recursive square root algorithm:
|
||||
*
|
||||
* step n+1:
|
||||
* test value <= .0 0 0 r r r 0 1 then generate a one in result r
|
||||
* n 2 1 n 2 1 else a zero in result r n+1
|
||||
* n+1
|
||||
* precalculations are done such that the entry is midway into step 2
|
||||
|
||||
fpsone bset d3,d7 insert a one into this position
|
||||
move.l d5,d4 update new test value
|
||||
fpszero add.l d4,d4 multiply test result by two
|
||||
move.l d4,d5 copy in case next bit zero
|
||||
sub.l (a0)+,d5 subtract the '01' ending pattern
|
||||
sub.l d7,d5 subtract result bits collected so far
|
||||
fpsent dbmi d3,fpsone branch if a one generated in the result
|
||||
dbpl d3,fpszero branch if a zero generated
|
||||
|
||||
* all 24 bits calculated. now test result of 25th bit
|
||||
bls.s fpsfin branch next bit zero, no rounding
|
||||
add.l #1,d7 round up (cannot overflow)
|
||||
fpsfin lsl.l #8,d7 normalize result
|
||||
move.l d6,a0 restore address register
|
||||
swap.w d3 restore s+exp save
|
||||
move.b d3,d7 move in final sign+exponent
|
||||
fpsrtn rts return to caller
|
||||
|
||||
* table to furnish '01' shifts during the algorithm loop
|
||||
fpstbl dc.l 1<<20,1<<19,1<<18,1<<17,1<<16,1<<15
|
||||
dc.l 1<<14,1<<13,1<<12,1<<11,1<<10,1<<9,1<<8
|
||||
dc.l 1<<7,1<<6,1<<5,1<<4,1<<3,1<<2,1<<1,1<<0
|
||||
dc.l 0,0
|
||||
|
||||
end
|
||||
@@ -0,0 +1,50 @@
|
||||
ttl arctangent cordic table - ffptheta
|
||||
ffptheta idnt 1,1 ffp arctangent table
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
section 9
|
||||
|
||||
xdef ffptheta external definition
|
||||
|
||||
*********************************************************
|
||||
* arctangent table for cordic *
|
||||
* *
|
||||
* the following table is used during cordic *
|
||||
* transcendental evaluations for sine, cosine, and *
|
||||
* tangent and represents arctangent values 2**-n where *
|
||||
* n ranges from 0 to 24. the format is binary(31,29) *
|
||||
* precision (i.e. the binary point is between bits *
|
||||
* 28 and 27 giving two leading non-fraction bits.) *
|
||||
*********************************************************
|
||||
|
||||
ffptheta dc.l $1921fb54 $c90fdaa2>>3 arctan(2**0)
|
||||
dc.l $76b19c15>>3 arctan(2**-1)
|
||||
dc.l $3eb6ebf2>>3 arctan(2**-2)
|
||||
dc.l $1fd5ba9a>>3 arctan(2**-3)
|
||||
dc.l $0ffaaddb>>3 arctan(2**-4)
|
||||
dc.l $07ff556e>>3 arctan(2**-5)
|
||||
dc.l $03ffeaab>>3 arctan(2**-6)
|
||||
dc.l $01fffd55>>3 arctan(2**-7)
|
||||
dc.l $00ffffaa>>3 arctan(2**-8)
|
||||
dc.l $007ffff5>>3 arctan(2**-9)
|
||||
dc.l $003ffffe>>3 arctan(2**-10)
|
||||
dc.l $001fffff>>3 arctan(2**-11)
|
||||
dc.l $000fffff>>3 arctan(2**-12)
|
||||
dc.l $0007ffff>>3 arctan(2**-13)
|
||||
dc.l $0003ffff>>3 arctan(2**-14)
|
||||
dc.l $0001ffff>>3 arctan(2**-15)
|
||||
dc.l $0000ffff>>3 arctan(2**-16)
|
||||
dc.l $00007fff>>3 arctan(2**-17)
|
||||
dc.l $00003fff>>3 arctan(2**-18)
|
||||
dc.l $00001fff>>3 arctan(2**-19)
|
||||
dc.l $00000fff>>3 arctan(2**-20)
|
||||
dc.l $000007ff>>3 arctan(2**-21)
|
||||
dc.l $000003ff>>3 arctan(2**-22)
|
||||
dc.l $000001ff>>3 arctan(2**-23)
|
||||
dc.l $000000ff>>3 arctan(2**-24)
|
||||
dc.l $0000007f>>3 arctan(2**-25)
|
||||
dc.l $0000003f>>3 arctan(2**-26)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,51 @@
|
||||
ttl ffp transcendental normalize internal routine (ffptnorm)
|
||||
ffptnorm idnt 1,2 ffp transcendental internal normalize
|
||||
|
||||
xdef ffptnorm
|
||||
section 9
|
||||
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
******************************
|
||||
* ffptnorm *
|
||||
* normalize bin(29,31) value *
|
||||
* and convert to float *
|
||||
* *
|
||||
* input: d6 - internal fixed *
|
||||
* output: d6 - ffp float *
|
||||
* cc - reflect value *
|
||||
* notes: *
|
||||
* 1) d4 is destroyed. *
|
||||
* *
|
||||
* time: (8mhz no wait state) *
|
||||
* zero 4.0 microsec. *
|
||||
* avg else 17.0 microsec. *
|
||||
* *
|
||||
******************************
|
||||
|
||||
|
||||
ffptnorm move.l #$42,d4 setup initial exponent
|
||||
tst.l d6 test for non-negative
|
||||
beq.s fsfrtn return if zero
|
||||
bpl.s fsfpls branch is >= 0
|
||||
neg.l d6 absolutize input
|
||||
move.b #$c2,d4 setup initial negative exponent
|
||||
fsfpls cmp.l #$00007fff,d6 test for a small number
|
||||
bhi.s fsfcont branch if not small
|
||||
swap.w d6 swap halves
|
||||
sub.b #16,d4 offset by 16 shifts
|
||||
fsfcont add.l d6,d6 shift another bit
|
||||
dbmi d4,fsfcont shift left until normalized
|
||||
tst.b d6 ? should we round up
|
||||
bpl.s fsfnrm no, branch rounded
|
||||
add.l #$100,d6 round up
|
||||
bcc.s fsfnrm branch no overflow
|
||||
roxr.l #1,d6 adjust back for bit in 31
|
||||
add.b #1,d4 make up for last shift right
|
||||
fsfnrm move.b d4,d6 insert sign+exponent
|
||||
fsfrtn rts return to caller
|
||||
|
||||
|
||||
end
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*char *version "@(#)floor.c 1.2 10/19/83";
|
||||
|
||||
/* floor - returns the largest integer (as a double precision
|
||||
number) not greater than x. */
|
||||
|
||||
double
|
||||
floor(x)
|
||||
double x;
|
||||
{
|
||||
register long i;
|
||||
double retval;
|
||||
|
||||
if ( x < 0 )
|
||||
x -= 0.99999999999999;
|
||||
i = x;
|
||||
retval = i;
|
||||
return( retval );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*char *version "@(#)fmod.c 1.2 10/19/83";
|
||||
|
||||
/* fmod - returns the number f such that x = iy + f, and
|
||||
0 <= f <= y. */
|
||||
|
||||
double
|
||||
fmod(x,y)
|
||||
double x;
|
||||
double y;
|
||||
{
|
||||
double z;
|
||||
double retval;
|
||||
register long i;
|
||||
double fabs();
|
||||
double absx;
|
||||
double absy;
|
||||
|
||||
absx = fabs(x);
|
||||
absy = fabs(y);
|
||||
for(z = absx; z - absy >= 0. ; z -= absy)
|
||||
;
|
||||
i = z;
|
||||
if( x < 0.0 )
|
||||
i *= -1;
|
||||
retval = i;
|
||||
return( retval );
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
*
|
||||
* Floating Point Addition :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* fpadd(addend,adder)
|
||||
* double addend, adder;
|
||||
*
|
||||
* Returns : Sum of two floating point numbers
|
||||
*
|
||||
.globl fpadd
|
||||
.globl _fpadd
|
||||
.globl iefadd
|
||||
.text
|
||||
fpadd:
|
||||
_fpadd:
|
||||
~~fpadd:
|
||||
link r14,#-4
|
||||
movem.l d6-d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
move.l 12(r14),r6
|
||||
jsr iefadd
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d6-d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,25 @@
|
||||
*
|
||||
* Floating Point Compare :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* fpcmp(source,dest)
|
||||
* double source, dest;
|
||||
*
|
||||
* Returns : Condition codes based on Floating Point Compare
|
||||
* in the Condition code register
|
||||
*
|
||||
.globl fpcmp
|
||||
.globl _fpcmp
|
||||
.globl iefcmp
|
||||
.text
|
||||
fpcmp:
|
||||
_fpcmp:
|
||||
~~fpcmp:
|
||||
link r14,#-4
|
||||
movem.l d6-d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
move.l 12(r14),r6
|
||||
jsr iefcmp
|
||||
movem.l (sp)+,d6-d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,26 @@
|
||||
*
|
||||
* Floating Point Cosine :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* cos(farg)
|
||||
* double farg;
|
||||
*
|
||||
* Input : in radians
|
||||
* Returns : cosine of Floating point number
|
||||
*
|
||||
.globl cos
|
||||
.globl _cos
|
||||
.globl iefcos
|
||||
.text
|
||||
cos:
|
||||
_cos:
|
||||
~~cos:
|
||||
link r14,#-4
|
||||
movem.l d3-d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
jsr iefcos
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d3-d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,26 @@
|
||||
*
|
||||
* Floating Point Division :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* fpdiv(divisor,dividend)
|
||||
* double divisor, dividend;
|
||||
*
|
||||
* Return : Floating Point Quotient
|
||||
*
|
||||
.globl fpdiv
|
||||
.globl _fpdiv
|
||||
.globl iefdiv
|
||||
.text
|
||||
fpdiv:
|
||||
_fpdiv:
|
||||
~~fpdiv:
|
||||
link r14,#-4
|
||||
movem.l d6-d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
move.l 12(r14),r6
|
||||
jsr iefdiv
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d6-d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,25 @@
|
||||
*
|
||||
* Floating Point Exponent :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* exp(x)
|
||||
* double x;
|
||||
*
|
||||
* Returns : e ^ x (where e = 2.718...)
|
||||
*
|
||||
.globl exp
|
||||
.globl _exp
|
||||
.globl iefexp
|
||||
.text
|
||||
exp:
|
||||
_exp:
|
||||
~~exp:
|
||||
link r14,#-4
|
||||
movem.l d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
jsr iefexp
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,25 @@
|
||||
*
|
||||
* Floating Point Logarithm :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* log(x)
|
||||
* double x;
|
||||
*
|
||||
* Returns : the floating point logarithm
|
||||
*
|
||||
.globl log
|
||||
.globl _log
|
||||
.globl ieflog
|
||||
.text
|
||||
log:
|
||||
_log:
|
||||
~~log:
|
||||
link r14,#-4
|
||||
movem.l d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
jsr ieflog
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,30 @@
|
||||
*
|
||||
* Floating Point Multiplication :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* fpmul(multiplier,multiplicand)
|
||||
* double multiplier, multiplicand;
|
||||
*
|
||||
* Return : Result of Floating Point Multiply
|
||||
*
|
||||
.globl fpmul
|
||||
.globl _fpmul
|
||||
.globl fpmult
|
||||
.globl _fpmult
|
||||
.globl iefmul
|
||||
.text
|
||||
fpmult:
|
||||
_fpmult:
|
||||
fpmul:
|
||||
_fpmul:
|
||||
~~fpmul:
|
||||
link r14,#-4
|
||||
movem.l d6-d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
move.l 12(r14),r6
|
||||
jsr iefmul
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d6-d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,25 @@
|
||||
*
|
||||
* Floating Point Negation :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* fpneg(farg)
|
||||
* double farg;
|
||||
*
|
||||
* Returns : negated Floating point number
|
||||
*
|
||||
.globl fpneg
|
||||
.globl _fpneg
|
||||
.globl iefneg
|
||||
.text
|
||||
fpneg:
|
||||
_fpneg:
|
||||
~~fpneg:
|
||||
link r14,#-4
|
||||
movem.l d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
jsr iefneg
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,26 @@
|
||||
*
|
||||
* Floating Point Power :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* pow(x,y)
|
||||
* double x, y;
|
||||
*
|
||||
* Returns : x ^ y
|
||||
*
|
||||
.globl pow
|
||||
.globl _pow
|
||||
.globl iefpwr
|
||||
.text
|
||||
pow:
|
||||
_pow:
|
||||
~~pow:
|
||||
link r14,#-4
|
||||
movem.l d3-d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
move.l 12(r14),r6
|
||||
jsr iefpwr
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d3-d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/**
|
||||
** formated print
|
||||
**/
|
||||
|
||||
/*char *version "@(#)fprintf - jan 24, 1982";*/
|
||||
#include <stdio.h>
|
||||
#define BUFSIZ 80
|
||||
|
||||
char *ftoa();
|
||||
char *etoa();
|
||||
char *petoa();
|
||||
char *pftoa();
|
||||
|
||||
static char *__str;
|
||||
FILE *__stream;
|
||||
static char **_p;
|
||||
|
||||
fprintf(fp, plist)
|
||||
FILE *fp;
|
||||
char *plist;
|
||||
{
|
||||
if (!fp->_flag & _WMODE) return;
|
||||
|
||||
__stream = fp;
|
||||
_p = &plist;
|
||||
__doprintf(0);
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
sprintf(s, plist)
|
||||
char *s, *plist;
|
||||
{
|
||||
__str = s;
|
||||
_p = &plist;
|
||||
__doprint(1);
|
||||
*__str = NULL;
|
||||
}
|
||||
|
||||
__doprint(mode)
|
||||
int mode;
|
||||
{
|
||||
register char *fmt, c;
|
||||
char buf[BUFSIZ];
|
||||
extern char *__prtshort(), *__prtld();
|
||||
register int *pi;
|
||||
int width, prec;
|
||||
int left, longf;
|
||||
char padchar;
|
||||
char *s;
|
||||
int n;
|
||||
auto (*fn)();
|
||||
int len;
|
||||
|
||||
fmt = *_p++;
|
||||
|
||||
pi = _p;
|
||||
while (c = *fmt++)
|
||||
{
|
||||
_p = pi;
|
||||
if (c != '%')
|
||||
{
|
||||
__putch(mode, c);
|
||||
continue;
|
||||
}
|
||||
left = 0;
|
||||
if ((c = *fmt++) == '-')
|
||||
{
|
||||
c = *fmt++;
|
||||
left++;
|
||||
}
|
||||
padchar = ' ';
|
||||
if (c == '0')
|
||||
{
|
||||
padchar = c;
|
||||
c = *fmt++;
|
||||
}
|
||||
width = -1;
|
||||
while (c >= '0' && c <= '9')
|
||||
{
|
||||
if (width < 0)
|
||||
width = 0;
|
||||
width = width * 10 + (c - '0');
|
||||
c = *fmt++;
|
||||
}
|
||||
prec = -1;
|
||||
if (c == '.')
|
||||
{
|
||||
prec = 0;
|
||||
c = *fmt++;
|
||||
}
|
||||
while (c >= '0' && c <= '9')
|
||||
{
|
||||
prec = prec * 10 + (c - '0');
|
||||
c = *fmt++;
|
||||
}
|
||||
longf = 0;
|
||||
if (c == 'l')
|
||||
{
|
||||
longf++;
|
||||
c = *fmt++;
|
||||
}
|
||||
/*
|
||||
* we now have all the prelims out of the way;
|
||||
* let's see what we want to print
|
||||
*/
|
||||
s = buf;
|
||||
switch (c)
|
||||
{
|
||||
|
||||
case 'd': /* decimal signed */
|
||||
case 'D':
|
||||
if (longf)
|
||||
fn = __prtld;
|
||||
else
|
||||
fn = __prtshort;
|
||||
__prtint(pi++, buf, 10, 1, fn, 0);
|
||||
if (longf)
|
||||
pi++;
|
||||
break;
|
||||
|
||||
case 'u': /* decimal unsigned */
|
||||
case 'U':
|
||||
__prtint(pi++, buf, 10, 0, __prtshort, 0);
|
||||
break;
|
||||
|
||||
case 'o': /* octal unsigned */
|
||||
case 'O':
|
||||
if (longf)
|
||||
fn = __prtld;
|
||||
else
|
||||
fn = __prtshort;
|
||||
__prtint(pi++, buf, 8, 0, fn, 0);
|
||||
if (longf)
|
||||
pi++;
|
||||
break;
|
||||
|
||||
case 'x': /* hexadecimal unsigned */
|
||||
case 'X':
|
||||
if (longf)
|
||||
fn = __prtld;
|
||||
else
|
||||
fn = __prtshort;
|
||||
__prtint(pi++, buf, 16, 0, fn, c == 'X');
|
||||
if (longf)
|
||||
pi++;
|
||||
break;
|
||||
|
||||
case 's': /* string */
|
||||
case 'S':
|
||||
s = *_p++;
|
||||
pi = _p;
|
||||
break;
|
||||
|
||||
case 'c': /* character */
|
||||
case 'C':
|
||||
n = *pi++;
|
||||
buf[0] = n;
|
||||
buf[1] = '\0';
|
||||
break;
|
||||
|
||||
case 'e': /* exponential */
|
||||
case 'E':
|
||||
petoa(pi, buf, prec);
|
||||
pi =+ 2;
|
||||
prec = -1;
|
||||
break;
|
||||
|
||||
case 'f': /* floating */
|
||||
case 'F':
|
||||
pftoa(pi, buf, prec);
|
||||
pi =+ 2;
|
||||
prec = -1;
|
||||
break;
|
||||
|
||||
case 'g': /* e or f */
|
||||
case 'G':
|
||||
pftoa(pi, buf, prec);
|
||||
if (strlen(buf) > (7 + prec)) /* smallest fp string */
|
||||
petoa(pi, buf, prec);
|
||||
pi =+ 2;
|
||||
prec = -1;
|
||||
break;
|
||||
|
||||
default: /* just print the character */
|
||||
__putch(mode, c);
|
||||
continue;
|
||||
|
||||
}
|
||||
len = __length(s);
|
||||
if (prec < len && prec >= 0)
|
||||
len = prec;
|
||||
n = width - len;
|
||||
if (!left)
|
||||
{
|
||||
if (padchar != ' ' && *s == '-')
|
||||
{
|
||||
len--;
|
||||
__putch(mode, *s); s++;
|
||||
}
|
||||
while (n-- > 0)
|
||||
__putch(mode, padchar);
|
||||
}
|
||||
while (len--) {
|
||||
__putch(mode, *s); s++;
|
||||
}
|
||||
while (n-- > 0)
|
||||
__putch(mode, padchar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__putch(mode, c)
|
||||
int mode;
|
||||
char c;
|
||||
{
|
||||
if (mode)
|
||||
*__str++ = c;
|
||||
else
|
||||
putc(c,__stream);
|
||||
return (c);
|
||||
}
|
||||
|
||||
char *
|
||||
pftoa(addr,buf,prec)
|
||||
float *addr;
|
||||
char *buf;
|
||||
int prec;
|
||||
{
|
||||
float fp;
|
||||
|
||||
if (prec<0)
|
||||
prec = 6;
|
||||
fp = *addr;
|
||||
return( ftoa(fp, buf, prec) );
|
||||
}
|
||||
|
||||
char *
|
||||
petoa(addr,buf,prec)
|
||||
float *addr;
|
||||
char *buf;
|
||||
int prec;
|
||||
{
|
||||
float fp;
|
||||
|
||||
if (prec<0)
|
||||
prec = 6;
|
||||
fp = *addr;
|
||||
return( etoa(fp, buf, prec) );
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
*
|
||||
* Floating Point Sine :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* sin(farg)
|
||||
* double farg;
|
||||
*
|
||||
* Input : in radians
|
||||
* Returns : sine of Floating point number
|
||||
*
|
||||
.globl sin
|
||||
.globl _sin
|
||||
.globl iefsin
|
||||
.text
|
||||
sin:
|
||||
_sin:
|
||||
~~sin:
|
||||
link r14,#-4
|
||||
movem.l d3-d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
jsr iefsin
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d3-d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,26 @@
|
||||
*
|
||||
* Floating Point Square Root :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* sqrt(farg)
|
||||
* double farg;
|
||||
*
|
||||
* Input : in radians
|
||||
* Returns : square root of Floating point number
|
||||
*
|
||||
.globl sqrt
|
||||
.globl _sqrt
|
||||
.globl iefsqrt
|
||||
.text
|
||||
sqrt:
|
||||
_sqrt:
|
||||
~~sqrt:
|
||||
link r14,#-4
|
||||
movem.l d3-d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
jsr iefsqrt
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d3-d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,26 @@
|
||||
*
|
||||
* Floating Point Subtraction :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* fpsub(subtrahend,minuend)
|
||||
* double subtrahend, minuend;
|
||||
*
|
||||
* Returns : Floating point subtraction result
|
||||
*
|
||||
.globl fpsub
|
||||
.globl _fpsub
|
||||
.globl iefsub
|
||||
.text
|
||||
fpsub:
|
||||
_fpsub:
|
||||
~~fpsub:
|
||||
link r14,#-4
|
||||
movem.l d6-d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
move.l 12(r14),r6
|
||||
jsr iefsub
|
||||
move.l r7,r0
|
||||
movem.l (sp)+,d6-d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,529 @@
|
||||
/*
|
||||
Copyright 1982, 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
|
||||
@(#)fscanf.c 1.1 11/9/83
|
||||
*/
|
||||
|
||||
/*
|
||||
** formatted read routine
|
||||
**
|
||||
** functionally equivalent to scanf in portable C library
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Delimiters */
|
||||
|
||||
#define NEWLINE '\n'
|
||||
#define TAB '\t'
|
||||
#define SPACE ' '
|
||||
#define NULL '\0'
|
||||
|
||||
/* returns from __next() */
|
||||
|
||||
#define CHAR 0
|
||||
#define NOT_WHT -1
|
||||
#define NOT_WHT_NL 1
|
||||
|
||||
/* returns from __scan() */
|
||||
|
||||
#define NORETURN 0
|
||||
#define VALID 1
|
||||
#define NOMATCH -1
|
||||
#define AT_EOF -2
|
||||
#define ERROR -3
|
||||
|
||||
FILE *__stream;
|
||||
char **_p, *__sstr, __holdch;
|
||||
int __smode, __hold;
|
||||
|
||||
scanf(parlist)
|
||||
char *parlist;
|
||||
{
|
||||
__smode = 0;
|
||||
_p = &parlist;
|
||||
return(__doscanf());
|
||||
}
|
||||
|
||||
fscanf(stream,parlist)
|
||||
FILE *stream;
|
||||
char *parlist;
|
||||
{
|
||||
if( (stream->_flag&(_RMODE|_UPDATE)) == 0 || feof(stream) )
|
||||
return(EOF);
|
||||
|
||||
__smode = 1;
|
||||
__stream = stream;
|
||||
_p = &parlist;
|
||||
return(__doscanf());
|
||||
}
|
||||
|
||||
sscanf(s,parlist)
|
||||
char *s, *parlist;
|
||||
{
|
||||
__smode = 2;
|
||||
__sstr = s;
|
||||
_p = &parlist;
|
||||
return(__doscanf());
|
||||
}
|
||||
|
||||
__doscanf()
|
||||
{
|
||||
register int nmatch;
|
||||
register char ch;
|
||||
char *format;
|
||||
register char match_ch;
|
||||
|
||||
nmatch = __hold = 0;
|
||||
format = *_p++;
|
||||
while( 1 ) {
|
||||
switch (ch = *format++) {
|
||||
|
||||
case NULL:
|
||||
return(nmatch);
|
||||
|
||||
case '%':
|
||||
if( *format != '%' ) {
|
||||
switch (__scan(&format, *_p)) {
|
||||
|
||||
case VALID: /* good return*/
|
||||
_p++;
|
||||
nmatch++;
|
||||
case NORETURN: /* no return*/
|
||||
break;
|
||||
|
||||
case NOMATCH: /* no match */
|
||||
return(nmatch);
|
||||
|
||||
case AT_EOF: /* end of file */
|
||||
return(nmatch ? nmatch : NOMATCH);
|
||||
|
||||
default: /* syntax error */
|
||||
return(NOMATCH);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
format++;
|
||||
|
||||
default:
|
||||
match_ch = __next(CHAR);
|
||||
if( ch != match_ch ) {
|
||||
__unget(match_ch);
|
||||
return(nmatch ? nmatch : AT_EOF);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* main scan routine -- look at characters in the conversion string
|
||||
* and do their bidding
|
||||
*/
|
||||
__scan(spec, result)
|
||||
char **spec;
|
||||
char *result;
|
||||
{
|
||||
register int longf, length;
|
||||
register char ch;
|
||||
extern int __strend(), __splend();
|
||||
|
||||
longf = length = 0;
|
||||
while( 1 ) {
|
||||
switch (ch = *(*spec)++) {
|
||||
case '*':
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
length = length * 10 + ch - '0';
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if( longf )
|
||||
return(ERROR);
|
||||
longf = 1;
|
||||
break;
|
||||
|
||||
case 'h': /* short */
|
||||
if( longf )
|
||||
return(ERROR);
|
||||
longf = NOMATCH;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 'O':
|
||||
return(__dec(result, length ? length : 100, 8, longf));
|
||||
|
||||
case 'd':
|
||||
case 'D':
|
||||
return(__dec(result, length ? length : 100, 10, longf));
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
return(__dec(result, length ? length : 100, 16, longf));
|
||||
|
||||
case 'c':
|
||||
case 'C':
|
||||
if( longf )
|
||||
return(ERROR);
|
||||
return(__char(result, length ? length : 1));
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
if( longf )
|
||||
return(ERROR);
|
||||
return(__strx(result, length ? length : 100, __strend));
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
if( longf )
|
||||
return(ERROR);
|
||||
return(__float(result, length ? length : 100));
|
||||
/*return(ERROR); /* not yet implemented */
|
||||
|
||||
case '[':
|
||||
if( longf )
|
||||
return(ERROR);
|
||||
if( __inits(spec) )
|
||||
return(ERROR);
|
||||
return(__strx(result, length ? length : 100, __splend));
|
||||
|
||||
default:
|
||||
return(ERROR);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get a constant -- octal, decimal, or hex depending on base
|
||||
*/
|
||||
__dec(result, length, base, longf)
|
||||
register int *result;
|
||||
int length;
|
||||
int base;
|
||||
int longf;
|
||||
{
|
||||
register char ch;
|
||||
register int val;
|
||||
register int ndigit;
|
||||
register long *lresult;
|
||||
register long lres;
|
||||
register int ires;
|
||||
register int minus, ok;
|
||||
|
||||
ires = 0;
|
||||
lres = 0;
|
||||
ndigit = minus = 0;
|
||||
switch (ch = __next(NOT_WHT_NL)) {
|
||||
|
||||
case NULL:
|
||||
case EOF:
|
||||
return(AT_EOF);
|
||||
|
||||
case '-':
|
||||
minus = 1;
|
||||
case '+':
|
||||
ndigit++;
|
||||
ch = __next(NOT_WHT);
|
||||
}
|
||||
ok = 0;
|
||||
while( (val = __digit(ch, base)) >= 0 && ndigit++ < length ) {
|
||||
ok++;
|
||||
if( longf )
|
||||
lres = lres * base + val;
|
||||
else
|
||||
ires = ires * base + val;
|
||||
ch = __next(CHAR);
|
||||
}
|
||||
__unget(ch);
|
||||
if( !ok )
|
||||
return(NOMATCH);
|
||||
if( !result )
|
||||
return(NORETURN);
|
||||
if( minus )
|
||||
if( longf )
|
||||
lres = -lres;
|
||||
else
|
||||
ires = -ires;
|
||||
if( longf ) {
|
||||
lresult = result;
|
||||
*lresult = lres;
|
||||
}
|
||||
else
|
||||
*result = ires;
|
||||
return(VALID);
|
||||
}
|
||||
|
||||
/*
|
||||
* get a floating point constant
|
||||
*/
|
||||
__float(result, length)
|
||||
register double *result;
|
||||
int length;
|
||||
{
|
||||
char buffer[100];
|
||||
double val;
|
||||
int ret, ch;
|
||||
|
||||
ret = __strx(buffer, 100, __strend);
|
||||
val = atof(buffer);
|
||||
*result = val;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
__next(mode)
|
||||
int mode;
|
||||
{
|
||||
/*
|
||||
* mode -1: get next non-space or non-tab
|
||||
* mode 0: get next character
|
||||
* mode 1: get next non-space, non-tab, or non-newline
|
||||
*/
|
||||
register int ch;
|
||||
|
||||
if( (ch = __getch()) == EOF )
|
||||
return(EOF);
|
||||
if( mode == 0 )
|
||||
return(ch);
|
||||
while( ch == SPACE || ch == TAB || ch == NEWLINE ) {
|
||||
if( ch == NEWLINE && mode < 0 )
|
||||
break;
|
||||
ch = __getch();
|
||||
}
|
||||
return(ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* check an input character for a valid constant digit (octal, decimal,
|
||||
* or hex) if found, return the proper numeric value. Negative results
|
||||
* indicate error.
|
||||
*/
|
||||
__digit(ch, base)
|
||||
register char ch;
|
||||
register int base;
|
||||
{
|
||||
register int n;
|
||||
|
||||
if( ch < '0' )
|
||||
return(NOMATCH);
|
||||
if( ch <= '7' )
|
||||
return(ch - '0');
|
||||
if( base == 8 )
|
||||
return(NOMATCH);
|
||||
if( ch <= '9' )
|
||||
return(ch - '0');
|
||||
if( base == 10 || ch < 'A' )
|
||||
return(NOMATCH);
|
||||
if( ch <= 'F' )
|
||||
return(ch - 'A' + 10);
|
||||
if( ch < 'a' || ch > 'f' )
|
||||
return(NOMATCH);
|
||||
return(ch - 'a' + 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* check for an end of string delimiter
|
||||
*/
|
||||
__strend(cha)
|
||||
char cha;
|
||||
{
|
||||
register char ch;
|
||||
|
||||
if( (ch = cha) == EOF )
|
||||
return(EOF);
|
||||
if( ch == SPACE || ch == TAB || ch == NEWLINE || ch == NULL )
|
||||
return(VALID);
|
||||
return(NORETURN);
|
||||
}
|
||||
|
||||
char __splset[128];
|
||||
|
||||
/*
|
||||
* check for the occurrance of any character in the set which
|
||||
* the user wants to be end-of-string delimiters
|
||||
*/
|
||||
__splend(ch)
|
||||
char ch;
|
||||
{
|
||||
if( ch == EOF )
|
||||
return(EOF);
|
||||
return(__splset[ch]);
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize the array which inidcates the special chars which the user
|
||||
* wants to be included (or not included) in strings.
|
||||
*/
|
||||
__inits(spec)
|
||||
register char **spec;
|
||||
{
|
||||
register char ch;
|
||||
register int i;
|
||||
register int val;
|
||||
|
||||
ch = *(*spec)++;
|
||||
if( ch == '^' ) {
|
||||
val = 0;
|
||||
ch = *(*spec)++;
|
||||
}
|
||||
else
|
||||
val = 1;
|
||||
for (i = 1; i < 128; i++)
|
||||
__splset[i] = val;
|
||||
val = 1 - val;
|
||||
while( ch != ']' ) {
|
||||
if( ch == 0 )
|
||||
return(NOMATCH);
|
||||
__splset[ch & 0177] = val;
|
||||
ch = *(*spec)++;
|
||||
}
|
||||
__splset[0] = 1;
|
||||
return(NORETURN);
|
||||
}
|
||||
|
||||
/*
|
||||
* getting a string
|
||||
*/
|
||||
__strx(result, length, endfn)
|
||||
register char *result;
|
||||
register int length;
|
||||
register int (*endfn)();
|
||||
{
|
||||
register char ch;
|
||||
extern int __splend();
|
||||
register int imode, notok;
|
||||
|
||||
notok = 1;
|
||||
imode = (endfn != __splend);
|
||||
if (imode) {
|
||||
ch = __next(NOT_WHT_NL);
|
||||
__unget(ch); /* bypass tab or space... */
|
||||
}
|
||||
while( !(*endfn)( (ch = __next(imode)) ) && length-- > 0 ) {
|
||||
if( result )
|
||||
*result++ = ch;
|
||||
imode = notok = 0;
|
||||
}
|
||||
__unget(ch);
|
||||
if( notok )
|
||||
return(ch == EOF ? AT_EOF : NOMATCH);
|
||||
if( !result )
|
||||
return(NORETURN);
|
||||
*result = 0;
|
||||
return(VALID);
|
||||
}
|
||||
|
||||
/*
|
||||
* getting a character constant
|
||||
*/
|
||||
__char(result, length)
|
||||
register char *result;
|
||||
register int length;
|
||||
{
|
||||
register char *r, ch;
|
||||
register int l;
|
||||
|
||||
r = result;
|
||||
l = length;
|
||||
|
||||
while( l-- ) {
|
||||
if( (ch = __next(CHAR)) <= 0 ) {
|
||||
if( l + 1 == length )
|
||||
return(ch == EOF ? AT_EOF : NOMATCH);
|
||||
else
|
||||
return(result != 0);
|
||||
}
|
||||
if( result )
|
||||
*result++ = ch;
|
||||
}
|
||||
return(result != 0);
|
||||
}
|
||||
|
||||
__getch()
|
||||
{
|
||||
switch(__smode) {
|
||||
case 0:
|
||||
return(__gstdi());
|
||||
case 1:
|
||||
return(getc(__stream));
|
||||
case 2:
|
||||
return(__gs());
|
||||
}
|
||||
}
|
||||
|
||||
__unget(ch)
|
||||
char ch;
|
||||
{
|
||||
switch(__smode) {
|
||||
case 0:
|
||||
__ugstdi(ch);
|
||||
break;
|
||||
case 1:
|
||||
ungetc(ch,__stream);
|
||||
break;
|
||||
case 2:
|
||||
__ungs(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* return the next char pointed to by *s
|
||||
*/
|
||||
__gs()
|
||||
{
|
||||
register char c;
|
||||
|
||||
c = *__sstr;
|
||||
if( c )
|
||||
__sstr++;
|
||||
else
|
||||
return(EOF);
|
||||
return(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* put back a char for further scanning
|
||||
*/
|
||||
__ungs(c)
|
||||
char c;
|
||||
{
|
||||
if( c )
|
||||
__sstr--;
|
||||
}
|
||||
|
||||
__gstdi()
|
||||
{
|
||||
if( !__hold)
|
||||
return(getchar());
|
||||
else {
|
||||
__hold = 0;
|
||||
return(__holdch);
|
||||
}
|
||||
}
|
||||
|
||||
__ugstdi(ch)
|
||||
char ch;
|
||||
{
|
||||
__hold = 1;
|
||||
__holdch = ch;
|
||||
}
|
||||
121
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/orglibe/ftoa.c
Normal file
121
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102a/orglibe/ftoa.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright 1982, 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*char *version "@(#)ftoa.c 1.4 12/29/83";*/
|
||||
|
||||
/*
|
||||
* IEEE Floating Point to Ascii String Conversion Routine :
|
||||
* IEEE Standard Single Precision Representation Floating Point
|
||||
*
|
||||
* char *
|
||||
* ftoa(f,buf,prec)
|
||||
* float f;
|
||||
* char *buf;
|
||||
* int prec;
|
||||
*
|
||||
* No more than 9 decimal digits are allowed in single precision.
|
||||
* Largest positive number is 3.4 * 10^33 and the smallest positive
|
||||
* number is 1.2 * 10^-38.
|
||||
* Rely's on the fact that a long and a float are both 32 bits.
|
||||
* 29 dec 83 - allow 0 decimal places !!!
|
||||
*/
|
||||
|
||||
#define BIAS 127L
|
||||
|
||||
#ifdef ISIEEE
|
||||
float _ffake();
|
||||
#else
|
||||
float _ieeetof();
|
||||
#endif
|
||||
|
||||
char *
|
||||
ftoa(fl,buf,prec)
|
||||
long fl; /* ieee formatted float */
|
||||
char *buf;
|
||||
int prec;
|
||||
{
|
||||
register char *bp;
|
||||
register int exp, digit;
|
||||
float f;
|
||||
|
||||
prec = (prec <= 0) ? 0 : (prec <= 9) ? prec : 9;
|
||||
bp = buf;
|
||||
if(fl == 0) goto shortcut;
|
||||
if(fl == 0x7f800000) { /* positive infinity */
|
||||
strcpy(bp,"+infinity");
|
||||
return(bp);
|
||||
}
|
||||
if(fl == 0xff800000) { /* negative infinity */
|
||||
strcpy(bp,"-infinity");
|
||||
return(bp);
|
||||
}
|
||||
#ifndef ISIEEE
|
||||
f = _ieeetof(fl); /* get floating point value */
|
||||
#else
|
||||
f = _ffake(fl);
|
||||
#endif
|
||||
#ifndef ISIEEE
|
||||
if (f < 0.0) { /* negative float */
|
||||
#else
|
||||
if (fl & 0x80000000) { /* negative float */
|
||||
#endif
|
||||
*bp++ = '-';
|
||||
f = -f; /* make it positive */
|
||||
}
|
||||
#ifndef ISIEEE
|
||||
if (f == 0.0) {
|
||||
#else
|
||||
if (fl == 0) {
|
||||
#endif
|
||||
shortcut:
|
||||
*bp++ = '0';
|
||||
if(prec) {
|
||||
*bp++ = '.';
|
||||
while (prec--)
|
||||
*bp++ = '0';
|
||||
}
|
||||
*bp = 0;
|
||||
return(buf);
|
||||
}
|
||||
for (exp=0; f < 1.0; f = f * 10.0) /* get negative exp */
|
||||
exp--;
|
||||
for ( ; f >= 1.0; f = f / 10.0) /* 0.XXXXXXE00 * 10^exp */
|
||||
exp++;
|
||||
|
||||
if (exp<=0) /* one significant digit */
|
||||
*bp++ = '0';
|
||||
for ( ; exp>0; exp--) { /* get significant digits */
|
||||
f = f * 10.0;
|
||||
digit = f; /* get one digit */
|
||||
f = f - digit;
|
||||
*bp++ = digit + '0';
|
||||
}
|
||||
if(prec) {
|
||||
*bp++ = '.';
|
||||
for( ; exp<0 && prec; prec--, exp++) /* exp < 0 ? */
|
||||
*bp++ = '0';
|
||||
while(prec-- > 0) {
|
||||
f = f * 10.0;
|
||||
digit = f; /* get one digit */
|
||||
f = f - digit;
|
||||
*bp++ = digit + '0';
|
||||
}
|
||||
}
|
||||
*bp = 0;
|
||||
return(buf);
|
||||
}
|
||||
|
||||
#ifdef ISIEEE
|
||||
/* if these routines are executed on a 68000 using ieee then no need to
|
||||
do a translation !!! */
|
||||
float
|
||||
_ffake(lf)
|
||||
float lf;
|
||||
{
|
||||
return(lf);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/* char *version "@(#)ftol.c 1.2 10/19/83"; */
|
||||
|
||||
/*
|
||||
* Floating Point Float to Long Routine :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* long
|
||||
* fpftol(fparg)
|
||||
* double fparg;
|
||||
*
|
||||
* Return : Fixed Point representation of Floating Point Number
|
||||
*/
|
||||
|
||||
#define BIAS 127L
|
||||
|
||||
long
|
||||
fpftol(f)
|
||||
long f;
|
||||
{
|
||||
register long l;
|
||||
register int exp, sign;
|
||||
|
||||
l = (f & 0x7f800000) >> 23;
|
||||
exp = l - BIAS;
|
||||
if (f == 0L || exp < 0) /* underflow or 0 */
|
||||
return(0L);
|
||||
sign = (f < 0L);
|
||||
if (exp > 31) /* overflow */
|
||||
return( (sign) ? 0x80000000 : 0x7fffffff);
|
||||
exp =- 23;
|
||||
l = (f & 0x7fffff) | 0x800000; /* 1.F */
|
||||
for( ; exp < 0 ; exp++)
|
||||
l =>> 1;
|
||||
for( ; exp > 0; exp--)
|
||||
l =<< 1;
|
||||
if (sign)
|
||||
l = -l;
|
||||
return(l);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*char *version "@(#) _ieeetof - dec 29, 1982"; */
|
||||
|
||||
/*
|
||||
* IEEE Floating Point Representation to Internal Representation :
|
||||
* IEEE Standard Single Precision Representation Floating Point
|
||||
*
|
||||
* float
|
||||
* _ieeetof(lf)
|
||||
* long lf;
|
||||
*
|
||||
* Largest positive number is 3.4 * 10^33 and the smallest positive
|
||||
* number is 1.2 * 10^-38.
|
||||
* Rely's on the fact that a long and a float are both 32 bits.
|
||||
*/
|
||||
|
||||
#define BIAS 127L
|
||||
|
||||
float
|
||||
_ieeetof(lf)
|
||||
long lf;
|
||||
{
|
||||
register long exp;
|
||||
register int count, fsign;
|
||||
float f;
|
||||
|
||||
if (lf == 0L)
|
||||
return(0.0);
|
||||
if (lf < 0L) {
|
||||
fsign = 1;
|
||||
lf =& 0x7fffffff; /* mask MSB (sign) */
|
||||
}
|
||||
else
|
||||
fsign = 0;
|
||||
exp = (lf >> 23) & 0xff; /* biased ieee exponent */
|
||||
exp =- BIAS;
|
||||
lf =& 0x7fffff; /* 23 bits of fraction */
|
||||
f = lf;
|
||||
if (lf != 0) /* don't need to do floating point test !!! */
|
||||
f = f / 8388608.0; /* 2 ^ 23 */
|
||||
f = f + 1.0; /* ieee fraction : 1.F */
|
||||
while (exp < 0) { /* negative exp : 2^-? */
|
||||
f = f / 2.0;
|
||||
exp++;
|
||||
}
|
||||
while (exp > 0) { /* positive exp : 2^+? */
|
||||
f = f * 2.0;
|
||||
exp--;
|
||||
}
|
||||
if (fsign)
|
||||
f = -f;
|
||||
return(f);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
ttl ieee format equivalent abs and neg (iefabs/iefneg)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************************
|
||||
* iefabs *
|
||||
* fast floating point ieee format equivalent absolute value*
|
||||
* *
|
||||
* input: d7 - ieee format number argument *
|
||||
* *
|
||||
* output: d7 - ieee format number absolute value result *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - cleared *
|
||||
* z - set if result is zero *
|
||||
* v - set if result is nan (not-a-number) *
|
||||
* (occurs only if input argument is nan) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
* maximum stack used: 24 bytes *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) this routine properly handles all ieee floating *
|
||||
* point values and number types. *
|
||||
* 2) if the input argument is a nan (not-a-number) then *
|
||||
* it will be returned as the result with the "v" bit *
|
||||
* set in the condition code register. *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
iefabs idnt 1,1 ieee format equivalent abs and neg
|
||||
|
||||
opt pcs
|
||||
|
||||
xdef iefabs ieee format absolute value
|
||||
|
||||
xref iefsop single argument conversion routine
|
||||
xref iefrtod7 return caller's original d7 as result
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
section 9
|
||||
|
||||
******************************
|
||||
* absolute value entry point *
|
||||
******************************
|
||||
iefabs jsr iefsop direct return to caller if nan encountered
|
||||
nop +0 normalized return (or zero or denormalized)
|
||||
* +2 infinity return
|
||||
|
||||
* all values may be absolutized by forcing a plus sign on the original value
|
||||
bclr.b #7,16(sp) clear sign bit of original value
|
||||
jmp iefrtod7 and return original value altered a wee bit
|
||||
page
|
||||
*************************************************************
|
||||
* iefneg *
|
||||
* fast floating point ieee format equivalent negate *
|
||||
* *
|
||||
* input: d7 - ieee format number argument *
|
||||
* *
|
||||
* output: d7 - ieee format number negated result *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - set if result is negative *
|
||||
* z - set if result is zero *
|
||||
* v - set if result is nan (not-a-number) *
|
||||
* (occurs only if input argument is nan) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
* maximum stack used: 24 bytes *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) this routine properly handles all ieee floating *
|
||||
* point values and number types. *
|
||||
* 2) if the input argument is a nan (not-a-number) then *
|
||||
* it will be returned as the result with the "v" bit *
|
||||
* set in the condition code register. *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
xdef iefneg ieee format negate
|
||||
|
||||
**********************
|
||||
* negate entry point *
|
||||
**********************
|
||||
iefneg jsr iefsop direct return to caller if nan encountered
|
||||
nop +0 normalized return (or zero or denormalized)
|
||||
* +6 both infinity return
|
||||
|
||||
* all values may be negated by inverting the sign bit of the original value
|
||||
bchg.b #7,16(sp) negate original sign bit
|
||||
jmp iefrtod7 and return this modified original register
|
||||
|
||||
end
|
||||
@@ -0,0 +1,122 @@
|
||||
ttl ieee format equivalent add/subtract (iefadd/iefsub)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************************
|
||||
* iefadd/iefsub *
|
||||
* fast floating point ieee format equivalent add/subtract *
|
||||
* *
|
||||
* iefadd - ieee format equivalent floating point addition *
|
||||
* *
|
||||
* input: d6 - ieee format number addend (source) *
|
||||
* d7 - ieee format number adder (destination) *
|
||||
* *
|
||||
* iefsub - ieee format equivalent floating point subtract *
|
||||
* *
|
||||
* input: d6 - ieee format number subtrahend (source) *
|
||||
* d7 - ieee format number minuend (destination) *
|
||||
* *
|
||||
* output: d7 - ieee format floating result of register d6 *
|
||||
* added or subtracted from register d7 *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - result is negative *
|
||||
* z - result is zero *
|
||||
* v - result is nan (not-a-number) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
* maximum used stack: 28 bytes *
|
||||
* *
|
||||
* result matrix: arg 2 *
|
||||
* others +inf -inf nan *
|
||||
* arg 1 **************************************** *
|
||||
* others * a * b * c * f * *
|
||||
* +infinity * b * b * d * f * *
|
||||
* -infinity * c * d * c * f * *
|
||||
* nan * e * e * e * f * *
|
||||
* **************************************** *
|
||||
* a = return addition or subtraction result, *
|
||||
* overflowing to infinity, underflowing to zero *
|
||||
* b = return plus infinity *
|
||||
* c = return minus infinity *
|
||||
* d = return newly created nan (not-a-number) *
|
||||
* e = return arg1 (nan) unchanged *
|
||||
* f = return arg2 (nan) unchanged *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) for subtraction, the sign of the source is *
|
||||
* inverted and then the operation is treated as *
|
||||
* an addition using the decision matrix above. *
|
||||
* 2) see the mc68344 user's guide for a description of *
|
||||
* the possible differences between the results *
|
||||
* returned here versus those required by the *
|
||||
* ieee standard. *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
iefadd idnt 1,1 ieee format equivalent add/subtract
|
||||
|
||||
opt pcs
|
||||
|
||||
xdef iefadd ieee format addition
|
||||
xdef iefsub ieee format subtraction
|
||||
|
||||
xref iefdop double argument conversion routine
|
||||
xref iefrtnan create and return nan result routine
|
||||
xref iefrtd7 return contents of d7 as the result
|
||||
xref iefrtsz return signed zero with sign of d7
|
||||
xref ieftieee return and convert back to ieee format
|
||||
xref ffpadd reference fast floating point add routine
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
section 9
|
||||
|
||||
************************
|
||||
* subtract entry point *
|
||||
************************
|
||||
iefsub bchg.l #31,d6 invert sign of second argument for subtract
|
||||
jsr iefadd and call add routine
|
||||
move.w sr,-(sp) save ccr of result on the stack [vlh] was sr
|
||||
bchg.l #31,d6 revert sign back to original condition
|
||||
rtr return with result and condition codes
|
||||
|
||||
*******************
|
||||
* add entry point *
|
||||
*******************
|
||||
iefadd jsr iefdop decode both operands
|
||||
jmp iefnrm +0 branch normalized
|
||||
jmp iefinf2 +2 branch arg2 infinity
|
||||
jmp iefinf1 +4 branch arg1 infinity
|
||||
* test for opposite signs +6 both are infinity
|
||||
eor.l d6,d7 exclusive or signs
|
||||
* bmi iefrtnan opposite signs - go return a nan
|
||||
bmi GOTHERE
|
||||
jmp iefinf1
|
||||
GOTHERE jmp iefrtnan * loader problem
|
||||
|
||||
* otherwise both same and return same
|
||||
|
||||
* arg1 infinity - return it
|
||||
iefinf1 move.l d6,d7 return arg1
|
||||
* arg2 infinity - return it (already in d7)
|
||||
iefinf2 jmp iefrtd7 return d7 as our result
|
||||
|
||||
* normalized numbers - do the addition
|
||||
iefnrm jsr ffpadd do fast floating point add
|
||||
* bne ieftieee convert result back to ieee format
|
||||
bne DOIT
|
||||
jmp NOPE
|
||||
DOIT jmp ieftieee
|
||||
* the above few lines had to be changed because of the loader problem
|
||||
|
||||
* result is zero - return with proper sign for rn (round-to-nearest)
|
||||
NOPE
|
||||
movem.l (sp),d3-d7 reload arguments (and rest of registers)
|
||||
and.l d6,d7 return minus only if both minus
|
||||
jmp iefrtsz return signed zero with sign of d7
|
||||
|
||||
end
|
||||
@@ -0,0 +1,66 @@
|
||||
ttl ieee format equivalent arctangent (iefatan)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* iefatan *
|
||||
* ieee format equivalent arctangent *
|
||||
* *
|
||||
* input: d7 - ieee format argument *
|
||||
* *
|
||||
* output: d7 - ieee format arctangent radian *
|
||||
* result *
|
||||
* *
|
||||
* all other registers totally transparent *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if result is zero *
|
||||
* n - cleared *
|
||||
* v - set if result is nan (not-a-number)*
|
||||
* (set if the input argument was nan)
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all other registers transparent *
|
||||
* *
|
||||
* maximum stack used: 54 bytes *
|
||||
* *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) see the mc68344 user's guide for details*
|
||||
* on ieee format range limitations. *
|
||||
* 2) spot checks show at least six digit *
|
||||
* precision on all sampled cases. *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
iefatan idnt 1,1 ieee format equivalent arctangent
|
||||
|
||||
opt pcs
|
||||
|
||||
section 9
|
||||
|
||||
xdef iefatan entry point
|
||||
|
||||
xref ffpatan fast floating point arctangent
|
||||
xref iefsop front-end single operand convert
|
||||
xref ieftieee back-end return ieee format
|
||||
xref ffpfieee ffp to ieee convert routine
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
********************
|
||||
* arctangent entry *
|
||||
********************
|
||||
|
||||
* save registers and convert argument
|
||||
iefatan jsr iefsop convert the single argument
|
||||
bra.s iefnrm +0 branch normalized
|
||||
* argument was infinite +2 infinity
|
||||
jsr ffpfieee convert to maximum values allowed in ffp format
|
||||
|
||||
* argument was normalized
|
||||
iefnrm jsr ffpatan call ffp arctangent routine
|
||||
jmp ieftieee return in ieee format
|
||||
|
||||
end
|
||||
@@ -0,0 +1,186 @@
|
||||
ttl ieee format equivalent back-end routines (iefback)
|
||||
iefback idnt 1,1 ieee format equivalent back-end routines
|
||||
******************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
******************************************
|
||||
|
||||
section 9
|
||||
|
||||
****************************************************************
|
||||
* iefrtnan (internal routine) *
|
||||
* ieee format equivalent fast floating point return nan *
|
||||
* *
|
||||
* input: sp -> +0 original callers d3-d7 registers *
|
||||
* +20 original callers return address *
|
||||
* *
|
||||
* output: d7 - a newly created nan (not-a-number) *
|
||||
* ccr - the "v" bit is forced on *
|
||||
* *
|
||||
* and direct return to the original caller *
|
||||
* *
|
||||
* purpose: called whenever the result of an operation *
|
||||
* is illegal or undefined and a nan result must *
|
||||
* be generated as the final result. *
|
||||
* *
|
||||
* the ieee format defined nan is determined by an exponent *
|
||||
* of all one's and a non-zero significand. the sign bit *
|
||||
* is a don't care. the ieee standard leaves up to each *
|
||||
* implementation what is placed in the significand. here *
|
||||
* we will generate the low order 23 bits of the original *
|
||||
* caller's return address. however, this may not be *
|
||||
* sufficient - if all 23 bits happen to be zero or the *
|
||||
* address is larger than 23 bits this would lead to an *
|
||||
* incorrect result. therfore, if this happens only the low *
|
||||
* order significand bit is set on with the rest zeroes. *
|
||||
* this represents an odd address (illegal with current m68000*
|
||||
* instruction alignment restrictions) and any interested *
|
||||
* party can tell if such a substitution has taken place. *
|
||||
* also, if this was illegally assumed to be an address and *
|
||||
* used, an address exception trap would ensue thus not *
|
||||
* allowing its use as a valid address. *
|
||||
* *
|
||||
****************************************************************
|
||||
|
||||
signmsk equ $80000000 ieee format sign isolation mask
|
||||
expmsk equ $7f800000 ieee format exponent mask
|
||||
vbit equ $0002 condition code "v" bit mask
|
||||
zbit equ $0004 condition code "z" bit mask
|
||||
|
||||
xdef iefrtnan return nan result routine
|
||||
|
||||
iefrtnan movem.l (sp)+,d3-d7 restore callers registers
|
||||
move.l (sp),d7 load up return address
|
||||
and.l #signmsk+expmsk,d7 verify not larger than 23 bits
|
||||
bne.s iefnone it is, cannot use it - return a one
|
||||
move.l (sp),d7 load up return address
|
||||
and.l #$007fffff,d7 isolate address bits required
|
||||
bne.s iefnzro branch if not zero
|
||||
iefnone move.l #1,d7 set only low bit on
|
||||
iefnzro or.l #expmsk,d7 force exponent all ones
|
||||
or.b #vbit,ccr return with "v" bit set [vlh]
|
||||
rts return to original caller
|
||||
page
|
||||
**********************************************************
|
||||
* ieftieee (internal subroutine) *
|
||||
* ieee format compatible convert ffp to ieee format *
|
||||
* *
|
||||
* input: d7 - result of fast floating point operation *
|
||||
* ccr - set for above result *
|
||||
* sp -> +0 original callers saved d3-d7 *
|
||||
* +20 original callers return address *
|
||||
* *
|
||||
* output: d7 - ieee format equivalent of the result *
|
||||
* *
|
||||
* condition code: *
|
||||
* *
|
||||
* n - set if the result is negative *
|
||||
* z - set if the result is zero *
|
||||
* v - cleared (not nan) *
|
||||
* c - cleared *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all fast floating point numbers have an exact *
|
||||
* ieee format representation. since the fast *
|
||||
* floating point routines always set the "v" bit *
|
||||
* for overflows and returns the proper sign, we *
|
||||
* can easily change the result to an ieee infinity *
|
||||
* and unflag the "v" bit. *
|
||||
* *
|
||||
**********************************************************
|
||||
|
||||
xdef ieftieee return ieee result to original caller
|
||||
|
||||
ieftieee bvs.s iefvset branch if overflow ffp result
|
||||
add.l d7,d7 delete mantissa high bit
|
||||
beq.s ieftrtn branch zero as finished
|
||||
eor.b #$80,d7 to twos complement exponent
|
||||
asr.b #1,d7 form 8-bit exponent
|
||||
sub.b #$82,d7 adjust 64 to 127 and excessize
|
||||
swap.w d7 swap for high byte placement
|
||||
rol.l #7,d7 set sign+exp in high byte
|
||||
ieftrtn tst.l d7 test "z" and "n", clear "v" and "c" in ccr
|
||||
movem.l (sp)+,d3-d6 restore d3 thru d6 callers registers
|
||||
add.l #4,sp skip original d7
|
||||
rts return to original caller with result
|
||||
|
||||
* overflow - set to proper ieee format infinity
|
||||
iefvset add.b d7,d7 save sign bit in "x"
|
||||
move.l #expmsk<<1,d7 set exponent of ones shifted left
|
||||
roxr.l #1,d7 insert proper sign
|
||||
jmp ieftrtn and return to original caller
|
||||
page
|
||||
*******************************************************************
|
||||
* general purpose return routines *
|
||||
* *
|
||||
* the following routines return a specific final result *
|
||||
* to the original caller with the proper condition codes *
|
||||
* set as follows: *
|
||||
* *
|
||||
* n - the result is negative *
|
||||
* z - the result is a zero *
|
||||
* v - cleared (not a nan) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* the routines are as follows: *
|
||||
* *
|
||||
* iefrtd7 - return the current contents of d7 *
|
||||
* iefrtod7 - return the original contents of d7 *
|
||||
* iefrtsz - return a signed zero (sign is bit 31 of d7) *
|
||||
* iefrtie - return infinity with sign exclusive or of *
|
||||
* original argument signs *
|
||||
* iefrtsze - return signed zero with sign exclusiv or *
|
||||
* of original argument signs *
|
||||
* *
|
||||
*******************************************************************
|
||||
|
||||
xdef iefrtd7,iefrtsz,iefrtod7,iefrtie,iefrtsze
|
||||
|
||||
**********************
|
||||
* return original d7 *
|
||||
* (cant be neg zero) *
|
||||
**********************
|
||||
iefrtod7 move.l 16(sp),d7 load original d7 into d7
|
||||
|
||||
*********************
|
||||
* return current d7 *
|
||||
* (cant be neg zero)*
|
||||
*********************
|
||||
iefrtd7 movem.l (sp)+,d3-d6 load all but d7 registers back up
|
||||
add.l #4,sp skip original d7 on stack
|
||||
add.l d7,d7 check for signed zero
|
||||
beq.s iefwasz branch if was a zero
|
||||
roxr.l #1,d7 value back into position set ccr ("v" clear)
|
||||
rts return to caller with ccr and result
|
||||
|
||||
**************************************
|
||||
* return signed zero with sign being *
|
||||
* eor of the original operands *
|
||||
**************************************
|
||||
iefrtsze movem.l 12(sp),d6-d7 load original arguments
|
||||
eor.l d6,d7 produce proper sign
|
||||
|
||||
**********************
|
||||
* return signed zero *
|
||||
* d7 bit31 has sign *
|
||||
**********************
|
||||
iefrtsz movem.l (sp)+,d3-d6 load all but d7 back up
|
||||
add.l #4,sp skip original d7 on stack
|
||||
add.l d7,d7 set sign bit into carry
|
||||
move.l #0,d7 zero d7
|
||||
iefwasz roxr.l #1,d7 set sign bit back in ("v" cleared)
|
||||
or.b #zbit,ccr force zero bit on in ccr [vlh]
|
||||
rts
|
||||
|
||||
*********************************
|
||||
* return infinity with eor sign *
|
||||
* of original arguments *
|
||||
*********************************
|
||||
iefrtie movem.l (sp)+,d3-d7 restore original arguments
|
||||
eor.l d6,d7 produce proper sign
|
||||
add.l d7,d7 shift sign out
|
||||
move.l #expmsk<<1,d7 setup infinity (exponent all ones)
|
||||
roxr.l #1,d7 set sign back in ("v" cleared)
|
||||
rts return with result and ccr set
|
||||
|
||||
end
|
||||
@@ -0,0 +1,182 @@
|
||||
ttl ieee format equivalent compare and test (iefcmp/ieftst)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************************
|
||||
* iefcmp *
|
||||
* fast floating point ieee format equivalent compare *
|
||||
* *
|
||||
* (result is test of destination - source) *
|
||||
* *
|
||||
* input: d6 - ieee format number (source) *
|
||||
* d7 - ieee format number (destination) *
|
||||
* *
|
||||
* output: the condition code register is set to directly *
|
||||
* reflect the following results of the test: *
|
||||
* *
|
||||
* eq equal *
|
||||
* ne not equal *
|
||||
* gt greater than *
|
||||
* ge greater than or equal *
|
||||
* lt less than *
|
||||
* le less than or equal *
|
||||
* cc ordered *
|
||||
* cs unordered *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - set for proper arithmetic tests *
|
||||
* z - set if result is zero *
|
||||
* v - set for proper arithmetic tests *
|
||||
* c - set if result is unordered *
|
||||
* (not-a-number operand) *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
* maximum stack usage: 32 bytes *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) the unordered condition results whenever any *
|
||||
* argument is a nan (not-a-number). the carry bit *
|
||||
* will be returned on if this occurs. this is *
|
||||
* different from most of the other mc68344 ieee format*
|
||||
* equivalent operations in that they return the "v" *
|
||||
* bit set which is handy for use of the "trapv" *
|
||||
* instruction. however, "v" must be used here for the*
|
||||
* signed arithmetic comparisons. *
|
||||
* 2) iefcmp recognizes and properly handles all single- *
|
||||
* precision ieee format values and data types. *
|
||||
* 3) infinities are handled in affine mode (plus and *
|
||||
* minus infinities are allowed and operate with non- *
|
||||
* infinities). *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
|
||||
iefcmp idnt 1,1 ieee format equivalent compare/test
|
||||
|
||||
opt pcs
|
||||
|
||||
xref iefdop double argument conversion routine
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
section 9
|
||||
xdef iefcmp ieee format compare
|
||||
|
||||
ccrcbit equ $01 condition code register "c" bit mask
|
||||
|
||||
***********************
|
||||
* compare entry point *
|
||||
***********************
|
||||
iefcmp move.l d7,-(sp) save callers original d7
|
||||
jsr iefcall call internal routine (nans will return here)
|
||||
* if control returns here it will be from iefdopt detecting a nan
|
||||
move.l (sp)+,d7 restore original d7 in case arg1 nan and not arg2
|
||||
or #ccrcbit,ccr set c-bit for unordered nan encntrd [vlh]
|
||||
rts return to caller with "c" set
|
||||
|
||||
* internal subroutine. split nan's away via call to iefdop. iefdop will
|
||||
* directly return to the code above if it detects either operand to be a nan.
|
||||
iefcall jsr iefdop decode both operands
|
||||
jmp iefnrm +0 normalized return (or zero or denormalized)
|
||||
jmp iefinf2 +2 arg2 infnity return
|
||||
jmp iefinf1 +4 arg1 infnity return
|
||||
* +6 both infinity return
|
||||
|
||||
* both values are infinity. we can substitute +1 and -1 values for plus and
|
||||
* minus infinity respectively, and continue with a straight arithmetic compare.
|
||||
move.l #30,d5 setup shift count for sign propagation
|
||||
asr.l d5,d7 change to plus or minus one
|
||||
asr.l d5,d6 change to plus or minus one
|
||||
jmp iefdocmp now finish with standard arithmetic compare
|
||||
|
||||
* arg2 is infinity and not arg1 - substitute $80000000 (lowest binary value)
|
||||
* for negative infinity to force proper compare
|
||||
iefinf2 tst.l d7 ? was this minus infinity
|
||||
bpl.s iefinf2p branch if ok to compare
|
||||
lsl.l #8,d7 change to smallest negative number for compare
|
||||
iefinf2p jsr ieffix1 reload and fix arg1 negative zeroes
|
||||
jmp iefdocmp now finish with compare
|
||||
|
||||
* arg1 is infinity and not arg2 - substitude $80000000 (lowest binary value)
|
||||
* for negative infinity to force proper compare
|
||||
iefinf1 tst.l d6 ? was this minus infinity
|
||||
bpl.s iefdarg2 branch if not, ok to use
|
||||
lsl.l #8,d6 set to smallest negative value
|
||||
jmp iefdarg2 reload and fix arg2 negative zeroes
|
||||
|
||||
* all normalized, denormalized, or zeroes return here.
|
||||
* except for minus zeroes, a simple arithmetic compare can be
|
||||
* done directly on the original ieee arguments. minus zeroes are
|
||||
* changed to true arithmetic zeroes.
|
||||
iefnrm jsr ieffix1 load and fix negative zeroes for first argument
|
||||
iefdarg2 move.l 16(sp),d7 reload arg2
|
||||
add.l d7,d7 test for plus or minus zero
|
||||
beq.s iefdocmp br zero, use true zero for compare
|
||||
move.l 16(sp),d7 reload and use original value
|
||||
iefdocmp cmp.l d6,d7 perform the compare (destination minus source)
|
||||
and #$7f-ccrcbit,ccr force c-bit off for ordered cmpr [vlh]
|
||||
movem.l (sp)+,d3-d7 restore callers original registers
|
||||
add.l #8,sp skip over internal return address and saved d7
|
||||
rts return with arithmetic compare condition code
|
||||
|
||||
* load and fix argument 1 for negative zeroes
|
||||
ieffix1 move.l 12+4(sp),d6 reload it back
|
||||
add.l d6,d6 check for plus or minus zero
|
||||
beq.s ieffixr return if zero to use true zero
|
||||
move.l 12+4(sp),d6 reload and use original value
|
||||
ieffixr rts return to caller
|
||||
page
|
||||
*************************************************************
|
||||
* ieftst *
|
||||
* fast floating point ieee format equivalent test *
|
||||
* *
|
||||
* (result is test of destination minus zero) *
|
||||
* *
|
||||
* input: d7 - ieee format number (destination) *
|
||||
* *
|
||||
* output: the condition code register is set to directly *
|
||||
* reflect the following results of the test: *
|
||||
* *
|
||||
* eq equal zero *
|
||||
* ne not equal zero *
|
||||
* pl positive value *
|
||||
* mi negative value *
|
||||
* vc not a nan (not-a-number) *
|
||||
* vs nan (not-a-number) *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - set if negative *
|
||||
* z - set if zero *
|
||||
* v - set if nan (not-a-number) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
* total stack usage: 24 bytes *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) iefcmp recognizes and properly handles all single- *
|
||||
* precision ieee format values and data types. *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
|
||||
xref iefsop single argument conversion routine
|
||||
xref iefrtod7 return original d7 to caller as result
|
||||
|
||||
xdef ieftst ieee format test
|
||||
|
||||
********************
|
||||
* test entry point *
|
||||
********************
|
||||
ieftst jsr iefsop separate out nans back to caller
|
||||
nop +0 normalized zero or denormalized
|
||||
* +2 argument was infinity
|
||||
|
||||
* merely return with d7 as the result. ccr will be set properly
|
||||
jmp iefrtod7 return old original d7
|
||||
|
||||
end
|
||||
@@ -0,0 +1,99 @@
|
||||
ttl ieee format equivalent divide (iefdiv)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************************
|
||||
* iefdiv *
|
||||
* fast floating point ieee format equivalent divide *
|
||||
* *
|
||||
* input: d6 - ieee format number divisor (source) *
|
||||
* d7 - ieee format number dividend (destination) *
|
||||
* *
|
||||
* output: d7 - ieee format floating result of register d6 *
|
||||
* divided into register d7 *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - result is negative *
|
||||
* z - result is zero *
|
||||
* v - result is nan (not-a-number) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
* maximum stack usage: 24 bytes *
|
||||
* *
|
||||
* result matrix: arg 2 *
|
||||
* others zero infinity nan *
|
||||
* arg 1 **************************************** *
|
||||
* others * a * b * c * f * *
|
||||
* zero * c * d * c * f * *
|
||||
* infinity * b * b * d * f * *
|
||||
* nan * e * e * e * f * *
|
||||
* **************************************** *
|
||||
* a = return divide result, overflowing to infinity, *
|
||||
* underflowing to zero with proper sign *
|
||||
* b = return zero with proper sign *
|
||||
* c = return infinity with proper sign *
|
||||
* d = return newly created nan (not-a-number) *
|
||||
* e = return arg1 (nan) unchanged *
|
||||
* f = return arg2 (nan) unchanged *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) see the mc68344 user's guide for a description of *
|
||||
* the possible differences between the results *
|
||||
* returned here versus those required by the *
|
||||
* ieee standard. *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
iefdiv idnt 1,1 ieee format equivalent divide
|
||||
|
||||
opt pcs
|
||||
|
||||
xdef iefdiv ieee format equivalent divide
|
||||
|
||||
xref iefdop double argument conversion routine
|
||||
xref iefrtnan create and return nan result routine
|
||||
xref ieftieee return and convert back to ieee format
|
||||
xref iefrtsze return signed zero with exclusive or signs
|
||||
xref iefrtie return infinity with exclusive or signs
|
||||
xref ffpdiv reference fast floating point divide routine
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
section 9
|
||||
|
||||
**********************
|
||||
* divide entry point *
|
||||
**********************
|
||||
iefdiv jsr iefdop decode both operands
|
||||
jmp iefnrm +0 branch normalized
|
||||
jmp iefrtinf +2 branch arg2 infinity
|
||||
jmp iefrtzro +4 branch arg1 infinity
|
||||
* both are infinity - return a nan +6 both are infinity
|
||||
jmp iefrtnan return a nan for infinity into infinity
|
||||
|
||||
* arg1 infinity - return zero with proper sign
|
||||
iefrtzro jmp iefrtsze return zero with exclusive or'ed sign
|
||||
|
||||
* arg2 infinity but not arg1 - return infinity with proper sign
|
||||
iefrtinf jmp iefrtie return infinity with exclusive or'ed sign
|
||||
|
||||
* normalized numbers - test for zeroes
|
||||
iefnrm tst.l d7 ? dividend zero (arg2)
|
||||
bne.s ief2nz no, go test divisor for zero
|
||||
tst.l d6 ? are both zero
|
||||
bne.s iefrtzro no, just dividend - return a zero
|
||||
jmp iefrtnan return a nan for zero into zero
|
||||
|
||||
* dividend (arg2) not zero
|
||||
ief2nz tst.l d6 ? divisor zero (arg1) but not dividend (arg2)
|
||||
beq.s iefrtinf yes, return infinity with proper sign
|
||||
|
||||
* both arguments non zero and normalized - do the divide
|
||||
jsr ffpdiv do fast floating point divide
|
||||
beq iefrtzro if result is zero return a proper sign zero
|
||||
jmp ieftieee convert result back to ieee format
|
||||
|
||||
end
|
||||
@@ -0,0 +1,67 @@
|
||||
ttl ieee format equivalent exponent (iefexp)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* iefexp *
|
||||
* ieee format equivalent exponent function *
|
||||
* *
|
||||
* input: d7 - ieee floating point argument *
|
||||
* *
|
||||
* output: d7 - ieee floating point exponential*
|
||||
* result *
|
||||
* *
|
||||
* all other registers are transparent *
|
||||
* *
|
||||
* maximum stack used: 54 bytes *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if result in d7 is zero *
|
||||
* n - cleared *
|
||||
* v - set if result is nan (not-a-number)*
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) if the input argument is a nan (not-a- *
|
||||
* number) then the "v" bit will be set *
|
||||
* and the argument unchanged upon return. *
|
||||
* 2) see the mc68344 user's guide for details*
|
||||
* on the range of ieee normalized values *
|
||||
* supported. *
|
||||
* 2) spot checks show at least 6.8 digit *
|
||||
* accuracy for all abs(arg) < 30. *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
iefexp idnt 1,1 ieee format equivalent exp
|
||||
|
||||
opt pcs
|
||||
|
||||
section 9
|
||||
|
||||
xdef iefexp entry point
|
||||
|
||||
xref ffpexp fast floating point exponent
|
||||
xref iefsop front-end single argument routine
|
||||
xref ieftieee back-end return to ieee format
|
||||
xref iefrtd7 return to caller argument in d7
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
************************
|
||||
* exponent entry point *
|
||||
************************
|
||||
iefexp jsr iefsop convert argument to ffp format
|
||||
bra.s iefnrm branch normalized
|
||||
* argument is an infinity
|
||||
bpl.s iefdrtn branch if plus - return itself
|
||||
move.l #0,d7 return plus zero if was negative infinity
|
||||
iefdrtn jmp iefrtd7 return the result that is in d7
|
||||
|
||||
* argument is normalized
|
||||
iefnrm jsr ffpexp call fast floating point exponent function
|
||||
jmp ieftieee and return in ieee format
|
||||
|
||||
end
|
||||
@@ -0,0 +1,292 @@
|
||||
ttl ieee format front-end routines (ieffront)
|
||||
ieffront idnt 1,1 ieee format equivalent front-end routines
|
||||
******************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
******************************************
|
||||
|
||||
*******************************************************
|
||||
* idfsop (internal subroutine) *
|
||||
* ieee format equivalent process single operand *
|
||||
* *
|
||||
* input: d7 - ieee format number argument2 *
|
||||
* sp -> +0 return address to caller *
|
||||
* +4 original caller's return address *
|
||||
* *
|
||||
* output: d6 converted to fast floating point *
|
||||
* format with user's original registers *
|
||||
* d3-d7 stacked or a direct return bypassing*
|
||||
* the first-line routine if either *
|
||||
* parameter was a nan *
|
||||
* *
|
||||
* *
|
||||
* return is via vectored branch with offset added *
|
||||
* to the address on the stack. this allows easy *
|
||||
* type descrimination by the caller for selected *
|
||||
* data types: *
|
||||
* *
|
||||
* return +0 if the argument is normalized *
|
||||
* (including zero and denormalized) *
|
||||
* +2 if argument is an infinity *
|
||||
* *
|
||||
* the stack appears: s+0 original d3-d7 upon entry*
|
||||
* s+20 original caller's return *
|
||||
* *
|
||||
* condition codes: *
|
||||
* *
|
||||
* (only if bypassed return done) *
|
||||
* *
|
||||
* n - undefined *
|
||||
* z - cleared *
|
||||
* v - set (result is a nan) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* (only if return to immediate caller) *
|
||||
* *
|
||||
* n - set if value is negative *
|
||||
* z - set if value is a zero *
|
||||
* v - undeinfed *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* this routine is a front end for the ieee format *
|
||||
* capatible routines (ief routines). it may *
|
||||
* bypass the caller to directly return to the user *
|
||||
* code if the argument is a nan (not-a-number) *
|
||||
* since the result must be a nan (the same). *
|
||||
* the call to this routine must be the *
|
||||
* first instruction of the level-1 ief routine, *
|
||||
* since it may return directly to the original *
|
||||
* caller. also registers must be unaltered before *
|
||||
* the call. *
|
||||
* *
|
||||
* logic: the following decision tree shows the *
|
||||
* processing for this routine and what *
|
||||
* values are returned for the argument *
|
||||
* *
|
||||
* if arg is nan then *
|
||||
* set the "v" bit in the ccr and bypass the *
|
||||
* caller returning with arg (d7) unchanged *
|
||||
* *
|
||||
* if arg is an infinity then adjust return address *
|
||||
* and return with ccr set for plus or minus *
|
||||
* at offset +2 *
|
||||
* *
|
||||
* if arg is denormalized then set it to zero *
|
||||
* else it is normalized - convert to ffp format*
|
||||
* *
|
||||
* return to caller at +0 offset *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) during the conversion of normalized ieee format *
|
||||
* numbers to ffp format, the exponent may be too *
|
||||
* large for ffp magnitudes. when this is true *
|
||||
* then the value is converted to an infinity with *
|
||||
* the proper sign. if the exponent is too small *
|
||||
* than a zero is returned. see the mc68344 user's*
|
||||
* guide for complete details of the range handling*
|
||||
* of the fast floating point format conversion. *
|
||||
* 2) all zeroes are treated as positive values. *
|
||||
* 3) denormalized values are treated as zeroes. *
|
||||
* *
|
||||
*******************************************************
|
||||
|
||||
section 9
|
||||
|
||||
xdef iefsop single operand convert
|
||||
|
||||
expmsk equ $7f800000 ieee format exponent mask
|
||||
vbit equ $0002 condition code "v" bit mask
|
||||
cbit equ $0001 condition code "c" bit mask
|
||||
|
||||
* call internal subroutine to parse argument (d7)
|
||||
iefsop lea -16(sp),sp adjust stack for new return address position
|
||||
move.l 16(sp),-(sp) move return address to new location
|
||||
movem.l d3-d7,4(sp) save original caller's registers
|
||||
bsr.s iefprse convert argument two
|
||||
bcc.s iefargs branch not infinity
|
||||
move.w sr,d5 save ccr [vlh] was sr
|
||||
add.l #2,(sp) adjust return address
|
||||
move.w d5,ccr restore ccr
|
||||
iefargs rts return to caller at proper offset
|
||||
page
|
||||
*******************************************************
|
||||
* idfdop (internal subroutine) *
|
||||
* ieee format equivalent process double operand *
|
||||
* *
|
||||
* input: d6 - ieee format number argument1 *
|
||||
* d7 - ieee format number argument2 *
|
||||
* sp -> +0 return address to caller *
|
||||
* +4 original caller's return address *
|
||||
* *
|
||||
* output: d6/d7 converted to fast floating point *
|
||||
* format with user's original registers *
|
||||
* d3-d7 stacked or a direct return bypassing*
|
||||
* the first-line routine if either *
|
||||
* parameter was a nan *
|
||||
* *
|
||||
* *
|
||||
* return is via vectored branch with offset added *
|
||||
* to the address on the stack. this allows easy *
|
||||
* type descrimination by the caller for selected *
|
||||
* data types: *
|
||||
* *
|
||||
* return +0 if both arguments normalized *
|
||||
* (including zero and denormalized) *
|
||||
* +2 if arg2 is an infinity *
|
||||
* +4 if arg1 is an infinity *
|
||||
* +6 if both arguments are infinities *
|
||||
* *
|
||||
* the stack appears: s+0 original d3-d7 upon entry*
|
||||
* s+20 original caller's return *
|
||||
* *
|
||||
* condition codes: *
|
||||
* *
|
||||
* (only if bypassed return done) *
|
||||
* *
|
||||
* n - undefined *
|
||||
* z - cleared *
|
||||
* v - set (result is a nan) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* (only if return directly to immediate caller) *
|
||||
* *
|
||||
* n - set if arg1 is negative *
|
||||
* z - set if arg1 is zero *
|
||||
* v - undefined *
|
||||
* c - set if arg1 is an infinity *
|
||||
* x - undefined *
|
||||
* *
|
||||
* this routine is a front end for the ieee format *
|
||||
* capatible routines (ief routines). it may *
|
||||
* bypass the caller to directly return to the user *
|
||||
* code if an argument is a nan (not-a-number) *
|
||||
* since the result must be a nan. it must be the *
|
||||
* first instruction of the level-1 ief routine, *
|
||||
* since it may return directly to the original *
|
||||
* caller. also registers must be unaltered before *
|
||||
* the call. *
|
||||
* *
|
||||
* logic: the following decision tree shows the *
|
||||
* processing for this routine and what *
|
||||
* values are returned for arg1 and arg2 *
|
||||
* *
|
||||
* if arg2 is nan then *
|
||||
* set the "v" bit in the ccr and bypass the *
|
||||
* caller returning with arg2 (d7) unchanged *
|
||||
* *
|
||||
* if arg1 is nan then *
|
||||
* set the "v" bit in the ccr and bypass the *
|
||||
* caller returning with arg1 copied to arg2 *
|
||||
* *
|
||||
* if arg2 is an infinity then adjust return address *
|
||||
* *
|
||||
* if arg1 is an infinity then adjust return address *
|
||||
* *
|
||||
* if arg2 is denormalized then set it to zero *
|
||||
* else it is normalized - convert to ffp format*
|
||||
* *
|
||||
* if arg1 is denormalized then set it to zero *
|
||||
* else it is normalized - convert to ffp format*
|
||||
* *
|
||||
* return to caller at proper offset *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) during the conversion of normalized ieee format *
|
||||
* numbers to ffp format, the exponent may be too *
|
||||
* large for ffp magnitudes. when this is true *
|
||||
* then the value is converted to an infinity with *
|
||||
* the proper sign. if the exponent is too small *
|
||||
* than a zero is returned. see the mc68344 user's*
|
||||
* guide for complete details of the range *
|
||||
* treatment by the fast floating point conversion.*
|
||||
* 2) all zeroes are treated as positive values. *
|
||||
* 3) denormalized values are treated as zeroes. *
|
||||
* *
|
||||
*******************************************************
|
||||
|
||||
section 9
|
||||
|
||||
xdef iefdop dual operand convert
|
||||
|
||||
* call internal subroutine to parse argument 2 (d7)
|
||||
iefdop lea -16(sp),sp reset stack for register storage
|
||||
move.l 16(sp),-(sp) move return address to new bottom of stack
|
||||
movem.l d3-d7,4(sp) save original registers above return address
|
||||
bsr.s iefprse convert argument two
|
||||
bcc.s iefarg2 branch not infinity
|
||||
add.l #2,(sp) adjust return address
|
||||
iefarg2 exg.l d6,d7 swap arguments to convert arg1 (nan returns arg1)
|
||||
bsr.s iefprse convert second argument
|
||||
bcc.s iefnoti branch not infinity
|
||||
move.w sr,d5 save ccr [vlh] was sr
|
||||
add.l #4,(sp) adjust return address
|
||||
move.w d5,ccr restore ccr
|
||||
iefnoti exg.l d6,d7 swap arguments back into place
|
||||
rts return to caller
|
||||
page
|
||||
*
|
||||
* internal convert subroutine
|
||||
* convert the argument in d7 to fast floating point format and return
|
||||
* ccr set for test against sign and zero
|
||||
*
|
||||
* output:
|
||||
* if nan - direct return bypassing caller with nan in d7 and "v" set
|
||||
* else return with converted value and "c" bit if is an infnity
|
||||
*
|
||||
iefprse move.l d7,d5 save original argument
|
||||
swap.w d7 swap word halves
|
||||
ror.l #7,d7 exponent to low byte
|
||||
eor.b #$80,d7 convert from excess 127 to two's-complement
|
||||
add.b d7,d7 from 8 to 7 bit exponent
|
||||
bvs.s iefovf branch will not fit
|
||||
add.b #2<<1+1,d7 adjust excess 127 to 64 and set mantissa high bit
|
||||
bvs.s iefexh branch exponent too large (overflow)
|
||||
eor.b #$80,d7 back to excess 64
|
||||
ror.l #1,d7 to fast float representation
|
||||
tst.b d7 clear carry
|
||||
rts return to caller
|
||||
|
||||
* overflow detected - caused by one of the following:
|
||||
* - false exponent overflow due to difference in excess notations
|
||||
* - exponent too high or low to fit in 7 bits (exponent over/underflow)
|
||||
* - an exponent of $ff representing an infinity
|
||||
* - an exponent of $00 representing a zero, nan, or denormalized value
|
||||
iefovf bcc.s iefovlw branch if overflow (exponent $ff or too large)
|
||||
* check for false overflow
|
||||
cmp.b #$7c,d7 ? will corrected value be ok
|
||||
beq.s ieffov yes, branch if false overflow
|
||||
cmp.b #$7e,d7 ? will corrected value be in range
|
||||
bne.s iefnotf no, branch not false overflow
|
||||
ieffov add.b #$80+2<<1+1,d7 back to excess 64 and set mantissa high bit
|
||||
ror.l #1,d7 to fast floating point representation
|
||||
tst.b d7 insure not illegal zero sign+exponent byte
|
||||
bne.s iefcrt no, is ok so return "c" cleared
|
||||
* exponent low - is zero, denormalized value, or too small an exponent
|
||||
iefnotf move.l #0,d7 return zero for all of these cases ("c" cleared)
|
||||
iefcrt rts return to caller
|
||||
|
||||
* exponent high - check for exponent too high, infinity, or nan
|
||||
iefovlw cmp.b #$fe,d7 ? was original exponent $ff
|
||||
bne.s iefexh no, branch exponent too large
|
||||
lsr.l #8,d7 shift out exponent
|
||||
lsr.l #1,d7 shift sign out into "x" bit
|
||||
beq.s iefexhi branch if true infinity
|
||||
|
||||
* arg2 is a nan - bypass caller and return as the result with "v" bit set
|
||||
move.l d5,d7 return original argument
|
||||
add.l #8,sp skip internal and caller return addresses
|
||||
movem.l (sp)+,d3-d6 return registers intact
|
||||
add.l #4,sp skip original d7
|
||||
or.b #vbit,ccr set v bit on [vlh]
|
||||
rts return to original caller
|
||||
|
||||
* arg2 is infinity or exponent too large so force to infinity (sign is bit 8)
|
||||
iefexh lsl.w #8,d7 set "x" ccr bit same as sign
|
||||
iefexhi move.l #expmsk<<1,d7 set exponent all ones for infinity and over 1
|
||||
roxr.l #1,d7 shift sign and and finished result
|
||||
or.b #cbit,ccr set "c" bit on for infinity notice [vlh]
|
||||
rts return to conversion routine
|
||||
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
ttl ieee format equivalent log (ieflog)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* ieflog *
|
||||
* fast floating point logorithm *
|
||||
* *
|
||||
* input: d7 - ieee format input argument *
|
||||
* *
|
||||
* output: d7 - ieee format logorithmic result *
|
||||
* *
|
||||
* all other registers totally transparent *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if result is zero *
|
||||
* n - set if result is negative *
|
||||
* v - set if result is nan (not-a-number)*
|
||||
* (negative or nan argument) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all other registers transparent *
|
||||
* *
|
||||
* maximum stack used: 54 bytes *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) see the mc68344 user's guide for details*
|
||||
* concerning ieee format normalized range *
|
||||
* support limitations. *
|
||||
* 2) spot checks show relative errors bounded*
|
||||
* by 5 x 10**-8. *
|
||||
* 2) negative arguments are illegal and cause*
|
||||
* a nan (not-a-number) to be returned. *
|
||||
* 3) a zero argument returns minus infinity. *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
ieflog idnt 1,1 ieee format equivalent logorithm
|
||||
|
||||
opt pcs
|
||||
section 9
|
||||
|
||||
xdef ieflog entry point
|
||||
|
||||
xref ffplog ffp logorithm routine
|
||||
xref iefsop front-end operand conversion routine
|
||||
xref ieftieee back-end convert to ieee and return
|
||||
xref iefrtnan back-end return nan routine
|
||||
xref iefrtod7 return original d7 from the caller
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
**************
|
||||
* log entry *
|
||||
**************
|
||||
ieflog jsr iefsop convert the operand
|
||||
bra.s iefnrm +0 branch normalized value
|
||||
* input argument is infinity +8
|
||||
bmi iefrtnan return a nan for a negative argument
|
||||
jmp iefrtod7 return plus infinity as the result
|
||||
|
||||
* argument is normalized
|
||||
iefnrm bmi iefrtnan return a nan if argument is negative
|
||||
jsr ffplog call fast floating point log routine
|
||||
jmp ieftieee and return result in ieee format
|
||||
|
||||
end
|
||||
@@ -0,0 +1,102 @@
|
||||
|
||||
ttl ieee format equivalent multiply (iefmul)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************************
|
||||
* iefmul *
|
||||
* fast floating point ieee format equivalent multiply *
|
||||
* *
|
||||
* iefmul - ieee format equivalent floating point multiply *
|
||||
* *
|
||||
* input: d6 - ieee format number multiplier (source) *
|
||||
* d7 - ieee format number multiplican (destination)*
|
||||
* *
|
||||
* output: d7 - ieee format floating result of register d6 *
|
||||
* multiplied by register d7 *
|
||||
* *
|
||||
* condition codes: *
|
||||
* n - result is negative *
|
||||
* z - result is zero *
|
||||
* v - result is nan (not-a-number) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers transparent *
|
||||
* *
|
||||
* maximum stack used: 24 bytes *
|
||||
* *
|
||||
* result matrix: arg 2 *
|
||||
* normalized zero inf nan *
|
||||
* arg 1 **************************************** *
|
||||
* normalized * a * b * c * f * *
|
||||
* zero * b * b * d * f * *
|
||||
* infinity * c * d * c * f * *
|
||||
* nan * e * e * e * f * *
|
||||
* **************************************** *
|
||||
* (denormalized values are treated as zeroes) *
|
||||
* a = return multiply result, overflow to infinity, *
|
||||
* underflow to zero *
|
||||
* b = return zero *
|
||||
* c = return infinity *
|
||||
* d = return newly created nan (not-a-number) for *
|
||||
* illegal operation
|
||||
* e = return arg1 (nan) unchanged *
|
||||
* f = return arg2 (nan) unchanged *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) zeroes and infinities are returned with proper *
|
||||
* sign (exclusive or of input argument sign bits). *
|
||||
* 2) see the mc68344 user's guide for a description of *
|
||||
* the possible differences between the results *
|
||||
* returned here versus those required by the *
|
||||
* ieee standard. *
|
||||
* *
|
||||
*************************************************************
|
||||
page
|
||||
iefmul idnt 1,1 ieee format equivalent multiply
|
||||
|
||||
opt pcs
|
||||
|
||||
xdef iefmul ieee format equivalent multiply
|
||||
|
||||
xref iefdop double argument conversion routine
|
||||
xref iefrtnan create and return nan result routine
|
||||
xref ieftieee return and convert back to ieee format
|
||||
xref iefrtie return signed infinity exclusive or'ed
|
||||
xref iefrtsze return signed zero exclusive or'ed
|
||||
xref ffpmul2 reference ffp perfect precision mult routine
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
section 9
|
||||
|
||||
***********************************************
|
||||
* ieee format equivalent multiply entry point *
|
||||
***********************************************
|
||||
iefmul jsr iefdop decode both operands
|
||||
jmp iefnrm +0 branch normalized
|
||||
jmp iefinf2 +2 branch only arg2 infinity
|
||||
jmp iefinf1 +4 branch only arg1 infinity
|
||||
* both infinity, return proper sign +6 both are infinity
|
||||
iefrtinf jmp iefrtie returne infinity with proper sign
|
||||
|
||||
* arg1 infinity - swap arguments and treat as arg2
|
||||
iefinf1 exg.l d6,d7 swap for next code portion
|
||||
|
||||
* arg2 infinity - if opposite argument is zero than illegal and return nan
|
||||
iefinf2 tst.l d6 ? is opposite argument a zero
|
||||
bne.s iefrtinf no, go return infinity with proper sign
|
||||
jmp iefrtnan yes, return a nan for this illegal operation
|
||||
|
||||
* normalized numbers(or zero) - do the multiply
|
||||
iefnrm jsr ffpmul2 do fast floating point add
|
||||
* bne ieftieee convert result back to ieee format
|
||||
bne DOIT
|
||||
jmp NOPE
|
||||
DOIT jmp ieftieee * loader problems again
|
||||
|
||||
* result is zero so return zero with proper sign
|
||||
NOPE jmp iefrtsze return zero with exclusively or'ed signed
|
||||
|
||||
end
|
||||
@@ -0,0 +1,60 @@
|
||||
ttl ieee format equivalent power function(iefpwr)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* iefpwr *
|
||||
* ieee format equivalent power function *
|
||||
* *
|
||||
* input: d6 - ieee format exponent value *
|
||||
* d7 - ieee format argument value *
|
||||
* *
|
||||
* output: d7 - result of the value taken to *
|
||||
* the power specified *
|
||||
* *
|
||||
* all registers are transparent *
|
||||
* *
|
||||
* maximum stack used: 52 bytes *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if result is zero *
|
||||
* n - cleared *
|
||||
* v - set if result is nan (not-a-number)*
|
||||
* (input argument negative or nan) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) see the mc68344 user's guide for details*
|
||||
* concerning limitations on normalized *
|
||||
* argument ranges. *
|
||||
* 2) a negative base value, or zero to a *
|
||||
* negative power is invalid and returns *
|
||||
* a nan with the "v" bit set. *
|
||||
* 3) spot checks show at least six digit *
|
||||
* precision for 80 percent of the cases. *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
iefpwr idnt 1,1 ieee format equivalent power function
|
||||
|
||||
opt pcs
|
||||
|
||||
section 9
|
||||
|
||||
xdef iefpwr entry point
|
||||
|
||||
xref ieflog ieee log function
|
||||
xref iefmul ieee multiply routine
|
||||
xref iefexp ieee exponent function
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
*****************
|
||||
* power entry *
|
||||
*****************
|
||||
iefpwr jsr ieflog find low of base value
|
||||
jsr iefmul multiply by the power
|
||||
jmp iefexp finish with exponent result
|
||||
|
||||
end
|
||||
@@ -0,0 +1,110 @@
|
||||
ttl ieee format equivalent (iefsin/iefcos/ieftan)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* iefsin iefcos ieftan *
|
||||
* ieee format equivalent sine/cosine/tangent *
|
||||
* *
|
||||
* input: d7 - ieee format argument (radians) *
|
||||
* *
|
||||
* output: d7 - ieee format function result *
|
||||
* *
|
||||
* all other registers totally transparent *
|
||||
* *
|
||||
* maximum stack used: 54 bytes *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if result in d7 is zero *
|
||||
* n - set if result in d7 is negative *
|
||||
* c - undefined *
|
||||
* v - set if result is nan (not-a-number)*
|
||||
* (input magnitude too large or nan) *
|
||||
* x - undefined *
|
||||
* *
|
||||
* functions: *
|
||||
* iefsin - sine result *
|
||||
* iefcos - cosine result *
|
||||
* ieftan - tangent result *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) input values are in radians. *
|
||||
* 2) input arguments larger than two pi *
|
||||
* suffer reduced precision. the larger *
|
||||
* the argument, the smaller the precision.*
|
||||
* excessively large arguments which have *
|
||||
* less than 5 bits of precision are *
|
||||
* returned as a nan with the "v" bit set. *
|
||||
* 3) the sign of tangents with infinite *
|
||||
* value is undefined, however we return *
|
||||
* a positive infinity. *
|
||||
* 4) spot checks show relative errors bounded*
|
||||
* by 4 x 10**-7 but for arguments close to*
|
||||
* pi/2 intervals where 10**-5 is seen. *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
iefsin idnt 1,1 ieee format equivalent sine/cosine/tangent
|
||||
|
||||
opt pcs
|
||||
|
||||
section 9
|
||||
|
||||
xdef iefsin,iefcos,ieftan entry points
|
||||
|
||||
xref ffpsin,ffpcos,ffptan ffp transcendentals
|
||||
xref iefsop single operand front-ender
|
||||
xref ieftieee back-end convert back to ieee format
|
||||
xref iefrtnan back-end return ieee nan routine
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
vbit equ $0002 condition code register "v" bit mask
|
||||
ffpsign equ.b $80 sign in fast floating point value
|
||||
|
||||
***********************
|
||||
* tangent entry point *
|
||||
***********************
|
||||
ieftan jsr iefsop parse the operand
|
||||
bra.s ieftnrm +0 branch not infinity or nan
|
||||
jmp iefrtnan +2 return nan for infinity
|
||||
|
||||
* perform tangent function with normalized number
|
||||
ieftnrm jsr ffptan find tangent
|
||||
bra.s iefcmn enter common exit code
|
||||
|
||||
**********************
|
||||
* cosine entry point *
|
||||
**********************
|
||||
iefcos jsr iefsop parse the operand
|
||||
bra.s iefcnrm +0 branch not infinity or nan
|
||||
jmp iefrtnan +2 return nan for infinity
|
||||
|
||||
* perform cosine function with normalized number
|
||||
iefcnrm jsr ffpcos find cosine
|
||||
bra.s iefcmn enter common exit code
|
||||
|
||||
********************
|
||||
* sine entry point *
|
||||
********************
|
||||
iefsin jsr iefsop parse the operand
|
||||
bra.s iefsnrm +0 branch not infinity or nan
|
||||
jmp iefrtnan +2 return nan for infinity
|
||||
|
||||
* perform sine function with normalized number
|
||||
iefsnrm jsr ffpsin find sine
|
||||
iefcmn bvc ieftieee return if had enough precision
|
||||
* overflow can mean true infinity result or not enough precision
|
||||
* we can test for not enough precision by checking for largest possible value
|
||||
move.l d7,d5 copy over ffp format result
|
||||
or.b #ffpsign,d5 set sign bit to a one
|
||||
sub.l #1,d5 test for all one bits
|
||||
* bne iefrtnan no, not enough precision, return a nan
|
||||
bne dobranch for 16-bit non-MMU problem
|
||||
tst.b d7 reset ccr as it was
|
||||
or.b #vbit,ccr and show overflow occured
|
||||
jmp ieftieee restore with infinity of proper sign
|
||||
dobranch:
|
||||
jmp iefrtnan
|
||||
|
||||
end
|
||||
@@ -0,0 +1,134 @@
|
||||
ttl ieee format equivalent hyperbolics (iefsinh)
|
||||
***************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
***************************************
|
||||
|
||||
*************************************************
|
||||
* iefsinh/iefcosh/ieftanh *
|
||||
* ieee equivalent floating point hyperbolics *
|
||||
* *
|
||||
* input: d7 - ieee format argument *
|
||||
* *
|
||||
* output: d7 - ieee format hyperbolic result *
|
||||
* *
|
||||
* all other registers are transparent *
|
||||
* *
|
||||
* maximum stack useage: 54 bytes *
|
||||
* *
|
||||
* calls: iefexp, iefdiv, iefadd and iefsub *
|
||||
* *
|
||||
* condition codes: *
|
||||
* z - set if result is zero *
|
||||
* n - set if result is negative *
|
||||
* v - set if result is nan (not-a-number)*
|
||||
* (returned if input was nan) *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) see the mc68344 user's guide for the *
|
||||
* limitations on ieee format normalized *
|
||||
* values. *
|
||||
* 2) if the input argument is a nan, it will *
|
||||
* be returned with the "v" bit set. *
|
||||
* 3) spot checks show at least seven digit *
|
||||
* precision. *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
iefsinh idnt 1,1 ieee format equivalent hyperbolics
|
||||
|
||||
opt pcs
|
||||
|
||||
section 9
|
||||
|
||||
xdef iefsinh,iefcosh,ieftanh entry points
|
||||
|
||||
xref iefexp,iefmul,iefdiv,iefadd,iefsub called
|
||||
xref ffpcpyrt copyright stub
|
||||
|
||||
fpone equ $3f800000 floating one
|
||||
fptwo equ $40000000 floating two
|
||||
|
||||
**********************************
|
||||
* iefcosh *
|
||||
* this function is defined as *
|
||||
* x -x *
|
||||
* e + e *
|
||||
* -------- *
|
||||
* 2 *
|
||||
* we evaluate exactly as defined *
|
||||
**********************************
|
||||
|
||||
iefcosh move.l d6,-(sp) save our work register
|
||||
jsr iefexp evaluate e to the x
|
||||
move.l d7,-(sp) save result
|
||||
move.l d7,d6 setup for divide into one
|
||||
move.l #fpone,d7 load floating point one
|
||||
jsr iefdiv compute e to -x as the inverse
|
||||
move.l (sp)+,d6 prepare to add together
|
||||
jsr iefadd create the numerator
|
||||
move.l #fptwo,d6 prepare to divide by two
|
||||
jsr iefdiv divide by two
|
||||
movem.l (sp)+,d6 restore work register
|
||||
rts return to caller
|
||||
page
|
||||
**********************************
|
||||
* iefsinh *
|
||||
* this function is defined as *
|
||||
* x -x *
|
||||
* e - e *
|
||||
* -------- *
|
||||
* 2 *
|
||||
* we evaluate exactly as defined *
|
||||
**********************************
|
||||
|
||||
iefsinh move.l d6,-(sp) save our work register
|
||||
jsr iefexp evaluate e to the x
|
||||
move.l d7,-(sp) save result
|
||||
move.l d7,d6 setup for divide into one
|
||||
move.l #fpone,d7 load floating point one
|
||||
jsr iefdiv compute e to -x as the inverse
|
||||
move.l d7,d6 prepare to subtract
|
||||
move.l (sp)+,d7 from first calculation
|
||||
jsr iefsub create the numerator
|
||||
move.l #fptwo,d6 prepare to divide by two
|
||||
jsr iefdiv divide by two
|
||||
movem.l (sp)+,d6 restore work register
|
||||
rts return to caller
|
||||
page
|
||||
**********************************
|
||||
* ieftanh *
|
||||
* this function is defined as *
|
||||
* sinh/cosh which reduces to: *
|
||||
* 2x *
|
||||
* e - 1 *
|
||||
* ------ *
|
||||
* 2x *
|
||||
* e + 1 *
|
||||
* *
|
||||
* which we evaluate. *
|
||||
**********************************
|
||||
|
||||
ieftanh move.l d6,-(sp) save our one work register
|
||||
move.l #fptwo,d6 prepare to multiply times two
|
||||
jsr iefmul get argument times two
|
||||
jsr iefexp evaluate e to the 2x
|
||||
move.l d7,-(sp) save result
|
||||
move.l #fpone,d6 load floating point one
|
||||
jsr iefadd add 1 to e**2x
|
||||
move.l d7,-(sp) save denominator
|
||||
move.l 4(sp),d7 now prepare to subtract
|
||||
jsr iefsub create numerator
|
||||
movem.l (sp)+,d6 restore denominator (keep ccr same)
|
||||
bvs.s ieftrtn branch if nan here
|
||||
cmp.l d6,d7 ***allow infinity by infinity to be one***
|
||||
bne.s ieftdod branch to do divide if not same value
|
||||
move.l #fpone,d7 result is a one
|
||||
bra.s ieftrtn and return
|
||||
ieftdod jsr iefdiv create result
|
||||
ieftrtn add.l #4,sp free e**2x off of stack
|
||||
movem.l (sp)+,d6 restore our work register
|
||||
rts return to caller with answer and ccr set
|
||||
|
||||
end
|
||||
@@ -0,0 +1,86 @@
|
||||
ttl ieee format equivalent square root (iefsqrt)
|
||||
*******************************************
|
||||
* (c) copyright 1981 by motorola inc. *
|
||||
*******************************************
|
||||
|
||||
*************************************************
|
||||
* iefsqrt *
|
||||
* ieee format equivalent square root *
|
||||
* *
|
||||
* input: *
|
||||
* d7 - ieee format argument *
|
||||
* *
|
||||
* output: *
|
||||
* d7 - ieee format square root *
|
||||
* *
|
||||
* condition codes: *
|
||||
* *
|
||||
* if the result is valid - *
|
||||
* n - cleared *
|
||||
* z - set if result is zero *
|
||||
* v - cleared *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* if the result is invalid due to a *
|
||||
* negative non-zero or nan input argument- *
|
||||
* n - undefined *
|
||||
* z - cleared *
|
||||
* v - set *
|
||||
* c - undefined *
|
||||
* x - undefined *
|
||||
* *
|
||||
* all registers are transparent *
|
||||
* *
|
||||
* maximum stack used: 24 bytes *
|
||||
* *
|
||||
* notes: *
|
||||
* 1) valid results are obtained unless *
|
||||
* the input argument was a negative *
|
||||
* non-zero number or nan (not-a- *
|
||||
* number) which can be determined by *
|
||||
* the "v" bit setting in the ccr. *
|
||||
* 2) see the mc68344 user's guide for *
|
||||
* details on the ranges handled by *
|
||||
* the fast floating point equivalent *
|
||||
* routines. *
|
||||
* *
|
||||
*************************************************
|
||||
page
|
||||
iefsqrt idnt 1,1 ieee format equivalent square root
|
||||
|
||||
section 9
|
||||
|
||||
xdef iefsqrt entry point
|
||||
|
||||
xref ffpsqrt fast floating point square root routine
|
||||
xref iefsop single operand front-end handler
|
||||
xref ieftieee back-end handler to return ieee format
|
||||
xref iefrtnan error handler to return a nan (not-a-number)
|
||||
xref iefrtod7 return original caller's d7
|
||||
xref ffpcpyrt copyright notice
|
||||
|
||||
*********************
|
||||
* square root entry *
|
||||
*********************
|
||||
iefsqrt jsr iefsop convert the operand
|
||||
bra.s iefnrm branch both normalized
|
||||
* argument was infinity - return a nan if minus
|
||||
* bmi iefrtnan return nan if it is minus infinity
|
||||
bmi dobranch
|
||||
jmp iefrtod7 just return input argument if plus infinity
|
||||
|
||||
* argument was normalized
|
||||
* iefnrm bmi iefrtnan return nan for invalid negative argument
|
||||
iefnrm bmi dobranch
|
||||
move.l 16(sp),d5 insure was not a negative very small number
|
||||
bpl.s iefsdoit branch was positive
|
||||
add.l d5,d5 rid sign byte to check if was negative zero
|
||||
* bne iefrtnan return nan for very small negative numbers also
|
||||
bne dobranch
|
||||
iefsdoit jsr ffpsqrt perform square root
|
||||
jmp ieftieee and return ieee format back to caller
|
||||
dobranch:
|
||||
jmp iefrtnan 16-bit no MMU stuff
|
||||
|
||||
end
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/*char *version "@(#)ltof.c 1.2 10/19/83"; */
|
||||
|
||||
/*
|
||||
* Floating Point Long to Float Routine :
|
||||
* Front End to IEEE Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* fpltof(larg)
|
||||
* long larg;
|
||||
*
|
||||
* Return : Floating Point representation of Long Fixed point integer
|
||||
*/
|
||||
|
||||
#define BIAS 127L
|
||||
|
||||
long
|
||||
fpltof(l)
|
||||
long l;
|
||||
{
|
||||
register long exp;
|
||||
register int sign;
|
||||
|
||||
if (l < 0L) { /* signed ?? */
|
||||
sign = 1;
|
||||
l = -l;
|
||||
}
|
||||
else
|
||||
sign = 0;
|
||||
if (l == 0L)
|
||||
return(0L);
|
||||
exp = 23L;
|
||||
for( ; l & 0x7f000000; exp++) /* something in upper 7 bits */
|
||||
l =>> 1;
|
||||
for( ; !(l & 0x00800000); exp--) /* get mantissa : 1.F */
|
||||
l =<< 1;
|
||||
l =& 0x007fffff; /* reduce to .F in 23 bits */
|
||||
if (sign)
|
||||
l =| 0x80000000;
|
||||
exp = (exp + BIAS)<<23;
|
||||
l =| exp;
|
||||
return(l);
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
Copyright 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
|
||||
@(#)printf.c 1.2 10/19/83
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
struct {
|
||||
int word0;
|
||||
int word1;
|
||||
};
|
||||
|
||||
#define BUFSIZ 80
|
||||
|
||||
FILE *__stream;
|
||||
static char *__str;
|
||||
static char **_p;
|
||||
|
||||
extern char *__prtshort(), *__prtld();
|
||||
|
||||
char *etoa();
|
||||
char *ftoa();
|
||||
char *petoa();
|
||||
char *pftoa();
|
||||
|
||||
printf(arg1,arg2,arg3)
|
||||
char *arg1, *arg2, *arg3;
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if( arg1 == -1 ) {
|
||||
/*
|
||||
* printf( ((char *)-1), buf, fmt...) is sprintf(buf, fmt...)
|
||||
*/
|
||||
__str = arg2;
|
||||
_p = &arg3;
|
||||
*__str = NULL;
|
||||
__doprint(1);
|
||||
*__str = NULL;
|
||||
}
|
||||
else if( arg1 < _NUFILE ) {
|
||||
/*
|
||||
* printf( ((char *)fd), fmt...) is fprintf( fd to fp, fmt,...)
|
||||
*/
|
||||
fp = fdopen( (arg1).word1 , "w");
|
||||
__stream = fp;
|
||||
_p = &arg2;
|
||||
__doprintf(0);
|
||||
fflush(fp);
|
||||
fp->_flag = 0;
|
||||
fp->_nextp = fp->_base = NULL;
|
||||
}
|
||||
else {
|
||||
__stream = stdout;
|
||||
_p = &arg1;
|
||||
__doprintf(0);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fp, plist)
|
||||
FILE *fp;
|
||||
char *plist;
|
||||
{
|
||||
if( (fp->_flag&(_WMODE|_UPDATE|_APPEND)) == 0 )
|
||||
return;
|
||||
|
||||
__stream = fp;
|
||||
_p = &plist;
|
||||
__doprintf(0);
|
||||
}
|
||||
|
||||
sprintf(s, plist)
|
||||
char *s, *plist;
|
||||
{
|
||||
__str = s;
|
||||
_p = &plist;
|
||||
__doprint(1);
|
||||
*__str = NULL;
|
||||
}
|
||||
|
||||
__doprint(mode)
|
||||
int mode;
|
||||
{
|
||||
register char *fmt, c;
|
||||
register int *pi;
|
||||
char buf[BUFSIZ];
|
||||
int width, prec, left, longf, n, len, prepend;
|
||||
char padchar;
|
||||
char *s;
|
||||
auto (*fn)();
|
||||
|
||||
fmt = *_p++;
|
||||
|
||||
pi = _p;
|
||||
while( c = *fmt++ ) {
|
||||
_p = pi;
|
||||
if( c != '%' ) {
|
||||
__putch(mode, c);
|
||||
continue;
|
||||
}
|
||||
prepend = left = 0;
|
||||
if( (c = *fmt++) == '-' ) {
|
||||
c = *fmt++;
|
||||
left++;
|
||||
}
|
||||
if (c == '#') { /* [vlh] 26 jul 83 */
|
||||
c = *fmt++;
|
||||
prepend++;
|
||||
}
|
||||
padchar = ' ';
|
||||
if( c == '0' ) {
|
||||
padchar = c;
|
||||
c = *fmt++;
|
||||
}
|
||||
width = -1;
|
||||
while( c >= '0' && c <= '9' ) {
|
||||
if( width < 0 )
|
||||
width = 0;
|
||||
width = width * 10 + (c - '0');
|
||||
c = *fmt++;
|
||||
}
|
||||
if (c == '*') { /* [vlh] 26 jul 83 */
|
||||
c = *fmt++;
|
||||
width = *pi++;
|
||||
}
|
||||
prec = -1;
|
||||
if( c == '.' ) {
|
||||
prec = 0;
|
||||
c = *fmt++;
|
||||
}
|
||||
while( c >= '0' && c <= '9' ) {
|
||||
prec = prec * 10 + (c - '0');
|
||||
c = *fmt++;
|
||||
}
|
||||
if (c == '*') { /* [vlh] 26 jul 83 */
|
||||
c = *fmt++;
|
||||
prec = *pi++;
|
||||
}
|
||||
longf = 0;
|
||||
if( c == 'l' ) {
|
||||
longf++;
|
||||
c = *fmt++;
|
||||
}
|
||||
/*
|
||||
* we now have all the prelims out of the way;
|
||||
* let's see what we want to print
|
||||
*/
|
||||
s = buf;
|
||||
switch (c) {
|
||||
|
||||
case 'd': /* decimal signed */
|
||||
case 'D':
|
||||
if( longf )
|
||||
fn = __prtld;
|
||||
else
|
||||
fn = __prtshort;
|
||||
__prtint(pi++, buf, 10, 1, fn, 0);
|
||||
if( longf )
|
||||
pi++;
|
||||
break;
|
||||
|
||||
case 'u': /* decimal unsigned */
|
||||
case 'U':
|
||||
__prtint(pi++, buf, 10, 0, __prtshort, 0);
|
||||
break;
|
||||
|
||||
case 'o': /* octal unsigned */
|
||||
case 'O':
|
||||
if (prepend) /* [vlh] 26 jul 83 */
|
||||
__putch(mode, '0');
|
||||
if( longf )
|
||||
fn = __prtld;
|
||||
else
|
||||
fn = __prtshort;
|
||||
__prtint(pi++, buf, 8, 0, fn, 0);
|
||||
if( longf )
|
||||
pi++;
|
||||
break;
|
||||
|
||||
case 'x': /* hexadecimal unsigned */
|
||||
case 'X':
|
||||
if (prepend) { /* [vlh] 26 jul 83 */
|
||||
__putch(mode, '0');
|
||||
__putch(mode, 'x');
|
||||
}
|
||||
if( longf )
|
||||
fn = __prtld;
|
||||
else
|
||||
fn = __prtshort;
|
||||
__prtint(pi++, buf, 16, 0, fn, c == 'X');
|
||||
if( longf )
|
||||
pi++;
|
||||
break;
|
||||
|
||||
case 's': /* string */
|
||||
case 'S':
|
||||
s = *_p++;
|
||||
pi = _p;
|
||||
break;
|
||||
|
||||
case 'c': /* character */
|
||||
case 'C':
|
||||
n = *pi++;
|
||||
buf[0] = n;
|
||||
buf[1] = '\0';
|
||||
break;
|
||||
|
||||
case 'e': /* exponential */
|
||||
case 'E':
|
||||
petoa(pi, buf, prec);
|
||||
pi += 2;
|
||||
prec = -1;
|
||||
break;
|
||||
|
||||
case 'f': /* floating */
|
||||
case 'F':
|
||||
pftoa(pi, buf, prec);
|
||||
pi += 2;
|
||||
prec = -1;
|
||||
break;
|
||||
|
||||
case 'g': /* e or f */
|
||||
case 'G':
|
||||
pftoa(pi, buf, prec);
|
||||
if (strlen(buf) > (7 + prec) ) /* smallest fp string */
|
||||
petoa(pi, buf, prec);
|
||||
pi += 2;
|
||||
prec = -1;
|
||||
break;
|
||||
|
||||
default: /* just print the character */
|
||||
__putch(mode, c);
|
||||
continue;
|
||||
|
||||
}
|
||||
len = __length(s);
|
||||
if( prec < len && prec >= 0 )
|
||||
len = prec;
|
||||
n = width - len;
|
||||
if( !left ) {
|
||||
if( padchar != ' ' && *s == '-' ) {
|
||||
len--;
|
||||
__putch(mode, *s++);
|
||||
}
|
||||
while( n-- > 0 )
|
||||
__putch(mode, padchar);
|
||||
}
|
||||
while( len-- )
|
||||
__putch(mode, *s++);
|
||||
|
||||
while( n-- > 0 )
|
||||
__putch(mode, padchar);
|
||||
}
|
||||
if( mode == 0 && (__stream->_flag&_UNBUF) )
|
||||
fflush(__stream);
|
||||
}
|
||||
|
||||
__putch(mode, c)
|
||||
int mode;
|
||||
char c;
|
||||
{
|
||||
if( mode )
|
||||
*__str++ = c;
|
||||
else
|
||||
putc(c,__stream);
|
||||
return (c);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
pftoa(addr,buf,prec)
|
||||
float *addr;
|
||||
char *buf;
|
||||
int prec;
|
||||
{
|
||||
float fp;
|
||||
|
||||
if (prec<0)
|
||||
prec = 6;
|
||||
fp = *addr;
|
||||
return( ftoa(fp, buf, prec) );
|
||||
}
|
||||
|
||||
char *
|
||||
petoa(addr,buf,prec)
|
||||
float *addr;
|
||||
char *buf;
|
||||
int prec;
|
||||
{
|
||||
float fp;
|
||||
|
||||
if (prec<0)
|
||||
prec = 6;
|
||||
fp = *addr;
|
||||
return( etoa(fp, buf, prec) );
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
*
|
||||
* Floating Point Hyperbolic sine:
|
||||
* Front End to FFP Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* sinh(farg)
|
||||
* double farg;
|
||||
*
|
||||
* Returns : negated Floating point number
|
||||
*
|
||||
.globl _sinh
|
||||
.globl iefsinh
|
||||
.text
|
||||
fpsinh:
|
||||
_sinh:
|
||||
~~sinh:
|
||||
link r14,#-4
|
||||
move.l d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
jsr iefsinh
|
||||
move.l r7,r0
|
||||
move.l (sp)+,d7
|
||||
unlk r14
|
||||
rts
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
*
|
||||
* Floating Point Hyperbolic tangent:
|
||||
* Front End to FFP Floating Point Package.
|
||||
*
|
||||
* double
|
||||
* tanh(farg)
|
||||
* double farg;
|
||||
*
|
||||
* Returns : negated Floating point number
|
||||
*
|
||||
.globl _tanh
|
||||
.globl ieftanh
|
||||
.text
|
||||
fptanh:
|
||||
_tanh:
|
||||
~~tanh:
|
||||
link r14,#-4
|
||||
move.l d7,-(sp)
|
||||
move.l 8(r14),r7
|
||||
jsr ieftanh
|
||||
move.l r7,r0
|
||||
move.l (sp)+,d7
|
||||
unlk r14
|
||||
rts
|
||||
Reference in New Issue
Block a user