4546 lines
72 KiB
Plaintext
4546 lines
72 KiB
Plaintext
asin.c
|
||
#include "math.h"
|
||
#include "errno.h"
|
||
|
||
double arcsine();
|
||
|
||
double asin(x)
|
||
double x;
|
||
{
|
||
return arcsine(x,0);
|
||
}
|
||
|
||
double acos(x)
|
||
double x;
|
||
{
|
||
return arcsine(x,1);
|
||
}
|
||
|
||
#define P1 -0.27368494524164255994e+2
|
||
#define P2 +0.57208227877891731407e+2
|
||
#define P3 -0.39688862997504877339e+2
|
||
#define P4 +0.10152522233806463645e+2
|
||
#define P5 -0.69674573447350646411
|
||
#define Q0 -0.16421096714498560795e+3
|
||
#define Q1 +0.41714430248260412556e+3
|
||
#define Q2 -0.38186303361750149284e+3
|
||
#define Q3 +0.15095270841030604719e+3
|
||
#define Q4 -0.23823859153670238830e+2
|
||
|
||
#define P(g) ((((P5*g P4)*g P3)*g P2)*g P1)
|
||
#define Q(g) (((((g Q4)*g Q3)*g Q2)*g Q1)*g Q0)
|
||
|
||
double arcsine(x,flg)
|
||
double x;
|
||
{
|
||
double y, g, r;
|
||
register int i;
|
||
extern int errno;
|
||
static double a[2] = { 0.0, 0.78539816339744830962 };
|
||
static double b[2] = { 1.57079632679489661923, 0.78539816339744830962 };
|
||
|
||
y = fabs(x);
|
||
i = flg;
|
||
if (y < 2.3e-10)
|
||
r = y;
|
||
else {
|
||
if (y > 0.5) {
|
||
i = 1-i;
|
||
if (y > 1.0) {
|
||
errno = EDOM;
|
||
return 0.0;
|
||
}
|
||
g = (0.5-y)+0.5;
|
||
g = ldexp(g,-1);
|
||
y = sqrt(g);
|
||
y = -(y+y);
|
||
} else
|
||
g = y*y;
|
||
r = y + y*
|
||
((P(g)*g)
|
||
/Q(g));
|
||
}
|
||
if (flg) {
|
||
if (x < 0.0)
|
||
r = (b[i] + r) + b[i];
|
||
else
|
||
r = (a[i] - r) + a[i];
|
||
} else {
|
||
r = (a[i] + r) + a[i];
|
||
if (x < 0.0)
|
||
r = -r;
|
||
}
|
||
return r;
|
||
}
|
||
atan.c
|
||
#include "math.h"
|
||
#include "errno.h"
|
||
|
||
#ifdef MPU8086
|
||
#define MAXEXP 1024
|
||
#define MINEXP -1023
|
||
#else
|
||
#define MAXEXP 504
|
||
#define MINEXP -512
|
||
#endif
|
||
|
||
#define PI 3.14159265358979323846
|
||
#define PIov2 1.57079632679489661923
|
||
|
||
double atan2(v,u)
|
||
double u,v;
|
||
{
|
||
double f, frexp();
|
||
int vexp, uexp;
|
||
extern int flterr;
|
||
extern int errno;
|
||
|
||
if (u == 0.0) {
|
||
if (v == 0.0) {
|
||
errno = EDOM;
|
||
return 0.0;
|
||
} else if (v > 0.0 )
|
||
return PIov2;
|
||
return -PIov2;
|
||
}
|
||
|
||
frexp(v, &vexp);
|
||
frexp(u, &uexp);
|
||
if (vexp-uexp > MAXEXP-3) /* overflow */
|
||
f = PIov2;
|
||
else {
|
||
if (vexp-uexp < MINEXP+3) /* underflow */
|
||
f = 0.0;
|
||
else
|
||
f = atan(fabs(v/u));
|
||
if (u < 0.0)
|
||
f = PI - f;
|
||
}
|
||
if (v < 0.0)
|
||
f = -f;
|
||
return f;
|
||
}
|
||
|
||
#define P0 -0.13688768894191926929e+2
|
||
#define P1 -0.20505855195861651981e+2
|
||
#define P2 -0.84946240351320683534e+1
|
||
#define P3 -0.83758299368150059274e+0
|
||
#define Q0 +0.41066306682575781263e+2
|
||
#define Q1 +0.86157349597130242515e+2
|
||
#define Q2 +0.59578436142597344465e+2
|
||
#define Q3 +0.15024001160028576121e+2
|
||
|
||
#define P(g) (((P3*g P2)*g P1)*g P0)
|
||
#define Q(g) ((((g Q3)*g Q2)*g Q1)*g Q0)
|
||
|
||
double atan(x)
|
||
double x;
|
||
{
|
||
double f, r, g;
|
||
int n;
|
||
static double Avals[4] = {
|
||
0.0,
|
||
0.52359877559829887308,
|
||
1.57079632679489661923,
|
||
1.04719755119659774615
|
||
};
|
||
|
||
n = 0;
|
||
f = fabs(x);
|
||
if (f > 1.0) {
|
||
f = 1.0/f;
|
||
n = 2;
|
||
}
|
||
if (f > 0.26794919243112270647) {
|
||
f = (((0.73205080756887729353*f - 0.5) - 0.5) + f) /
|
||
(1.73205080756887729353 + f);
|
||
++n;
|
||
}
|
||
if (fabs(f) < 2.3e-10)
|
||
r = f;
|
||
else {
|
||
g = f*f;
|
||
r = f + f *
|
||
((P(g)*g)
|
||
/Q(g));
|
||
}
|
||
if (n > 1)
|
||
r = -r;
|
||
r += Avals[n];
|
||
if (x < 0.0)
|
||
r = -r;
|
||
return r;
|
||
}
|
||
exp.c
|
||
#include "math.h"
|
||
#include "errno.h"
|
||
|
||
#define P0 0.25000000000000000000e+0
|
||
#define P1 0.75753180159422776666e-2
|
||
#define P2 0.31555192765684646356e-4
|
||
#define Q0 0.50000000000000000000e+0
|
||
#define Q1 0.56817302698551221787e-1
|
||
#define Q2 0.63121894374398503557e-3
|
||
#define Q3 0.75104028399870046114e-6
|
||
|
||
#define P(z) ((P2*z + P1)*z + P0)
|
||
#define Q(z) (((Q3*z + Q2)*z + Q1)*z + Q0)
|
||
|
||
#define EPS 2.710505e-20
|
||
|
||
double
|
||
exp(x)
|
||
double x;
|
||
{
|
||
int n;
|
||
double xn, g, r, z;
|
||
extern int errno;
|
||
|
||
if (x > LOGHUGE) {
|
||
errno = ERANGE;
|
||
return HUGE_VAL;
|
||
}
|
||
if (x < LOGTINY) {
|
||
errno = ERANGE;
|
||
return 0.0;
|
||
}
|
||
if (fabs(x) < EPS)
|
||
return 1.0;
|
||
n = z = x * 1.4426950408889634074;
|
||
if (n < 0)
|
||
--n;
|
||
if (z-n >= 0.5)
|
||
++n;
|
||
xn = n;
|
||
g = ((x - xn*0.693359375)) + xn*2.1219444005469058277e-4;
|
||
z = g*g;
|
||
r = P(z)*g;
|
||
r = 0.5 + r/(Q(z)-r);
|
||
return ldexp(r,n+1);
|
||
}
|
||
floor.c
|
||
#include "math.h"
|
||
|
||
double floor(d)
|
||
double d;
|
||
{
|
||
if (d < 0.0)
|
||
return -ceil(-d);
|
||
modf(d, &d);
|
||
return d;
|
||
}
|
||
|
||
double ceil(d)
|
||
double d;
|
||
{
|
||
if (d < 0.0)
|
||
return -floor(-d);
|
||
if (modf(d, &d) > 0.0)
|
||
++d;
|
||
return d;
|
||
}
|
||
log.c
|
||
#include "math.h"
|
||
#include "errno.h"
|
||
|
||
double log10(x)
|
||
double x;
|
||
{
|
||
return log(x)*0.43429448190325182765;
|
||
}
|
||
|
||
#define A0 -0.64124943423745581147e+2
|
||
#define A1 +0.16383943563021534222e+2
|
||
#define A2 -0.78956112887491257267e+0
|
||
#define A(w) ((A2*w A1)*w A0)
|
||
|
||
#define B0 -0.76949932108494879777e+3
|
||
#define B1 +0.31203222091924532844e+3
|
||
#define B2 -0.35667977739034646171e+2
|
||
#define B(w) (((w B2)*w B1)*w B0)
|
||
|
||
#define C0 0.70710678118654752440
|
||
#define C1 0.693359375
|
||
#define C2 -2.121944400546905827679e-4
|
||
|
||
double log(x)
|
||
double x;
|
||
{
|
||
double Rz, f, z, w, znum, zden, xn;
|
||
int n;
|
||
extern int errno;
|
||
|
||
if (x <= 0.0) {
|
||
errno = EDOM;
|
||
return -HUGE_VAL;
|
||
}
|
||
f = frexp(x, &n);
|
||
if (f > C0) {
|
||
znum = (znum = f-0.5) - 0.5; /* the assignment prevents const. eval */
|
||
zden = f*0.5 + 0.5;
|
||
} else {
|
||
--n;
|
||
znum = f - 0.5;
|
||
zden = znum*0.5 + 0.5;
|
||
}
|
||
z = znum/zden;
|
||
w = z*z;
|
||
/* the lines below are split up to allow expansion of A(w) and B(w) */
|
||
Rz = z + z * (w *
|
||
A(w)
|
||
/B(w));
|
||
xn = n;
|
||
return (xn*C2 + Rz) + xn*C1;
|
||
}
|
||
pow.c
|
||
#include "math.h"
|
||
#include "errno.h"
|
||
|
||
double pow(a,b)
|
||
double a,b;
|
||
{
|
||
double answer;
|
||
extern int errno;
|
||
register long count;
|
||
char sign, inverse;
|
||
|
||
if (a == 0) {
|
||
if (b <= 0)
|
||
domain: errno = EDOM;
|
||
return 0.0;
|
||
}
|
||
if (b == 0)
|
||
return 1.0; /* anything raised to 0 is 1 */
|
||
inverse = sign = 0;
|
||
if (modf(b,&answer) == 0) {
|
||
if (answer < 0)
|
||
inverse = 1, answer = -answer;
|
||
if ((count = answer) == answer) {
|
||
for (answer = 1.0 ; count ; count >>= 1, a *= a)
|
||
if ((int)count & 1)
|
||
answer *= a;
|
||
if (inverse)
|
||
answer = 1.0/answer;
|
||
return answer;
|
||
}
|
||
if (a < 0)
|
||
sign = 1, a = -a;
|
||
if ((count&1) == 0)
|
||
sign = 0; /* number is even so sign is positive */
|
||
|
||
} else if (a < 0)
|
||
goto domain;
|
||
|
||
answer = exp(log(a)*b);
|
||
return sign ? -answer : answer;
|
||
}
|
||
random.c
|
||
/*
|
||
* Random number generator -
|
||
* adapted from the FORTRAN version
|
||
* in "Software Manual for the Elementary Functions"
|
||
* by W.J. Cody, Jr and William Waite.
|
||
*/
|
||
double ran()
|
||
{
|
||
static long int iy = 100001;
|
||
|
||
iy *= 125;
|
||
iy -= (iy/2796203) * 2796203;
|
||
return (double) iy/ 2796203.0;
|
||
}
|
||
|
||
double randl(x)
|
||
double x;
|
||
{
|
||
double exp();
|
||
|
||
return exp(x*ran());
|
||
}
|
||
sin.c
|
||
#include "math.h"
|
||
#include "errno.h"
|
||
|
||
double cos(x)
|
||
double x;
|
||
{
|
||
double sincos();
|
||
|
||
return sincos(x, fabs(x) + 1.57079632679489661923, 0);
|
||
}
|
||
|
||
double sin(x)
|
||
double x;
|
||
{
|
||
double sincos();
|
||
|
||
if (x < 0.0)
|
||
return sincos(x,-x,1);
|
||
else
|
||
return sincos(x,x,0);
|
||
}
|
||
|
||
#define R1 -0.16666666666666665052e+00
|
||
#define R2 +0.83333333333331650314e-02
|
||
#define R3 -0.19841269841201840457e-03
|
||
#define R4 +0.27557319210152756119e-05
|
||
#define R5 -0.25052106798274584544e-07
|
||
#define R6 +0.16058936490371589114e-09
|
||
#define R7 -0.76429178068910467734e-12
|
||
#define R8 +0.27204790957888846175e-14
|
||
|
||
#define YMAX 6.7465e09
|
||
|
||
static double sincos(x,y,sgn)
|
||
double x,y;
|
||
{
|
||
double f, xn, g;
|
||
extern int errno;
|
||
|
||
if (y >= YMAX) {
|
||
errno = ERANGE;
|
||
return 0.0;
|
||
}
|
||
if (modf(y * 0.31830988618379067154, &xn) >= 0.5)
|
||
++xn;
|
||
if ((int)xn & 1)
|
||
sgn = !sgn;
|
||
if (fabs(x) != y)
|
||
xn -= 0.5;
|
||
g = modf(fabs(x), &x); /* break into fraction and integer parts */
|
||
f = ((x - xn*(3217.0/1024)) + g) - xn*-8.9089102067615373566e-6;
|
||
if (fabs(f) > 2.3283e-10) {
|
||
g = f*f;
|
||
f = (((((((R8*g R7)*g R6)*g R5)*g
|
||
R4)*g R3)*g R2)*g R1)*g*f+f;
|
||
}
|
||
if (sgn)
|
||
f = -f;
|
||
return f;
|
||
}
|
||
sinh.c
|
||
#include "math.h"
|
||
#include "errno.h"
|
||
|
||
extern int errno;
|
||
|
||
#define P0 -0.35181283430177117881e+6
|
||
#define P1 -0.11563521196851768270e+5
|
||
#define P2 -0.16375798202630751372e+3
|
||
#define P3 -0.78966127417357099479e+0
|
||
#define Q0 -0.21108770058106271242e+7
|
||
#define Q1 +0.36162723109421836460e+5
|
||
#define Q2 -0.27773523119650701667e+3
|
||
|
||
#define PS(x) (((P3*x P2)*x P1)*x P0)
|
||
#define QS(x) (((x Q2)*x Q1)*x Q0)
|
||
|
||
double sinh(x)
|
||
double x;
|
||
{
|
||
double y, w, z;
|
||
int sign;
|
||
|
||
y = x;
|
||
sign = 0;
|
||
if (x < 0.0) {
|
||
y = -x;
|
||
sign = 1;
|
||
}
|
||
if (y > 1.0) {
|
||
w = y - 0.6931610107421875000;
|
||
if (w > LOGHUGE) {
|
||
errno = ERANGE;
|
||
z = HUGE_VAL;
|
||
} else {
|
||
z = exp(w);
|
||
if (w < 19.95)
|
||
z -= 0.24999308500451499336 / z;
|
||
z += 0.13830277879601902638e-4 * z;
|
||
}
|
||
if (sign)
|
||
z = -z;
|
||
} else if (y < 2.3e-10)
|
||
z = x;
|
||
else {
|
||
z = x*x;
|
||
z = x + x *
|
||
(z*(PS(z)
|
||
/QS(z)));
|
||
}
|
||
return z;
|
||
}
|
||
|
||
double cosh(x)
|
||
double x;
|
||
{
|
||
double y, w, z;
|
||
|
||
y = fabs(x);
|
||
if (y > 1.0) {
|
||
w = y - 0.6931610107421875000;
|
||
if (w > LOGHUGE) {
|
||
errno = ERANGE;
|
||
return HUGE_VAL;
|
||
}
|
||
z = exp(w);
|
||
if (w < 19.95)
|
||
z += 0.24999308500451499336 / z;
|
||
z += 0.13830277879601902638e-4 * z;
|
||
} else {
|
||
z = exp(y);
|
||
z = z*0.5 + 0.5/z;
|
||
}
|
||
return z;
|
||
}
|
||
sqrt.c
|
||
#include "math.h"
|
||
#include "errno.h"
|
||
|
||
double sqrt(x)
|
||
double x;
|
||
{
|
||
double f, y;
|
||
int n;
|
||
extern int errno;
|
||
|
||
if (x == 0.0)
|
||
return x;
|
||
if (x < 0.0) {
|
||
errno = EDOM;
|
||
return 0.0;
|
||
}
|
||
f = frexp(x, &n);
|
||
y = 0.41731 + 0.59016 * f;
|
||
y = (y + f/y);
|
||
y = ldexp(y,-2) + f/y; /* fast calculation of y2 */
|
||
y = ldexp(y + f/y, -1);
|
||
y = ldexp(y + f/y, -1);
|
||
|
||
if (n&1) {
|
||
y *= 0.70710678118654752440;
|
||
++n;
|
||
}
|
||
return ldexp(y,n/2);
|
||
}
|
||
tan.c
|
||
#include "math.h"
|
||
#include "errno.h"
|
||
|
||
extern int errno;
|
||
|
||
static double tansub();
|
||
|
||
#if MPU8080 || MPUZ80 || MPU6502
|
||
#define TOOSMALL (1.0/HUGE_VAL)
|
||
#else
|
||
#define TOOSMALL TINY_VAL
|
||
#endif
|
||
|
||
double cotan(x)
|
||
double x;
|
||
{
|
||
double y;
|
||
|
||
y = fabs(x);
|
||
if (y < TOOSMALL) {
|
||
errno = ERANGE;
|
||
if (x < 0.0)
|
||
return -HUGE_VAL;
|
||
else
|
||
return HUGE_VAL;
|
||
}
|
||
return tansub(x,y,2);
|
||
}
|
||
|
||
double tan(x)
|
||
double x;
|
||
{
|
||
return tansub(x, fabs(x), 0);
|
||
}
|
||
|
||
#define P1 -0.13338350006421960681e+0
|
||
#define P2 +0.34248878235890589960e-2
|
||
#define P3 -0.17861707342254426711e-4
|
||
#define Q0 +1.0
|
||
#define Q1 -0.46671683339755294240e+0
|
||
#define Q2 +0.25663832289440112864e-1
|
||
#define Q3 -0.31181531907010027307e-3
|
||
#define Q4 +0.49819433993786512270e-6
|
||
|
||
#define P(f,g) (((P3*g P2)*g P1)*g*f + f)
|
||
#define Q(g) ((((Q4*g Q3)*g Q2)*g Q1)*g Q0)
|
||
|
||
#define YMAX 6.74652e09
|
||
|
||
static double tansub(x, y, flag)
|
||
double x,y;
|
||
{
|
||
double f, g, xn;
|
||
double xnum, xden;
|
||
|
||
if (y > YMAX) {
|
||
errno = ERANGE;
|
||
return 0.0;
|
||
}
|
||
if (fabs(modf(x*0.63661977236758134308, &xn)) >= 0.5)
|
||
xn += (x < 0.0) ? -1.0 : 1.0;
|
||
f = modf(x, &g);
|
||
f = ((g - xn*(3217.0/2048)) + f) - xn*-4.454455103380768678308e-6;
|
||
if (fabs(f) < 2.33e-10) {
|
||
xnum = f;
|
||
xden = 1.0;
|
||
} else {
|
||
g = f*f;
|
||
xnum = P(f,g);
|
||
xden = Q(g);
|
||
}
|
||
flag |= ((int)xn & 1);
|
||
switch (flag) {
|
||
case 1: /* A: tan, xn odd */
|
||
xnum = -xnum;
|
||
case 2: /* B: cotan, xn even */
|
||
return xden/xnum;
|
||
|
||
case 3: /* C: cotan, xn odd */
|
||
xnum = -xnum;
|
||
case 0: /* D: tan, xn even */
|
||
return xnum/xden;
|
||
}
|
||
return 0.0;
|
||
}
|
||
tanh.c
|
||
#include "math.h"
|
||
|
||
#define P0 -0.16134119023996228053e+4
|
||
#define P1 -0.99225929672236083313e+2
|
||
#define P2 -0.96437492777225469787e+0
|
||
#define Q0 +0.48402357071988688686e+4
|
||
#define Q1 +0.22337720718962312926e+4
|
||
#define Q2 +0.11274474380534949335e+3
|
||
|
||
#define gP(g) (((P2*g P1)*g P0)*g)
|
||
#define Q(g) (((g Q2)*g Q1)*g Q0)
|
||
|
||
double tanh(x)
|
||
double x;
|
||
{
|
||
double f,g,r;
|
||
|
||
f = fabs(x);
|
||
if (f > 25.3)
|
||
r = 1.0;
|
||
else if (f > 0.54930614433405484570) {
|
||
r = 0.5 - 1.0/(exp(f+f)+1.0);
|
||
r += r;
|
||
} else if (f < 2.3e-10)
|
||
r = f;
|
||
else {
|
||
g = f*f;
|
||
r = f + f*
|
||
(gP(g)
|
||
/Q(g));
|
||
}
|
||
if (x < 0.0)
|
||
r = -r;
|
||
return r;
|
||
}
|
||
atof.asm
|
||
; Copyright (C) 1983 by Manx Software Systems
|
||
;
|
||
;double
|
||
;atof(cp)
|
||
;register char *cp;
|
||
include lmacros.h
|
||
|
||
IFDEF LONGPTR
|
||
cp equ es:byte ptr [di]
|
||
getes macro
|
||
mov es,ss:word ptr acp[2]
|
||
endm
|
||
|
||
ELSE
|
||
|
||
cp equ byte ptr [di]
|
||
getes macro
|
||
;
|
||
endm
|
||
ENDIF
|
||
|
||
procdef atof,<<acp,ptr>>
|
||
sub sp,2
|
||
push di
|
||
push si
|
||
;{
|
||
ifndef LONGPTR
|
||
mov di,ds
|
||
mov es,di
|
||
endif
|
||
ldptr di,acp,es
|
||
; double acc;
|
||
; int msign, esign, dpflg;
|
||
; int i, dexp;
|
||
msign equ byte ptr -1[bp]
|
||
esign equ byte ptr -2[bp] ;these two aren't active at the same time
|
||
dpflg equ byte ptr -2[bp]
|
||
|
||
; while (*cp == ' ' || *cp == '\t')
|
||
; ++cp;
|
||
skiploop:
|
||
mov al,cp
|
||
cmp al,' '
|
||
je skipbl
|
||
cmp al,9
|
||
jne skipdone
|
||
skipbl:
|
||
inc di
|
||
jmp skiploop
|
||
skipdone:
|
||
; if (*cp == '-') {
|
||
cmp al,45
|
||
jne $3
|
||
; ++cp;
|
||
inc di
|
||
; msign = 1;
|
||
mov msign,1
|
||
jmp short $4
|
||
; } else {
|
||
$3:
|
||
; msign = 0;
|
||
mov msign,0
|
||
; if (*cp == '+')
|
||
; ++cp;
|
||
cmp al,43
|
||
jne $4
|
||
inc di
|
||
; }
|
||
$4:
|
||
; dpflg = dexp = 0;
|
||
mov si,0
|
||
mov dpflg,0
|
||
; for (acc = zero ; ; ++cp) {
|
||
call $dlip
|
||
dw 0,0,0,0
|
||
$6:
|
||
; if (isdigit(*cp)) {
|
||
getes
|
||
mov al,cp
|
||
cmp al,'0'
|
||
jb $9
|
||
cmp al,'9'
|
||
ja $9
|
||
; acc *= ten;
|
||
call $dlis
|
||
dw 0,0,0,4024H
|
||
call $dml
|
||
; acc += *cp - '0';
|
||
call $dswap
|
||
getes
|
||
mov al,cp
|
||
cbw
|
||
add ax,-48
|
||
call $itod
|
||
call $dad
|
||
; if (dpflg)
|
||
; --dexp;
|
||
cmp dpflg,0
|
||
je $11
|
||
dec si
|
||
jmp short $11
|
||
; } else if (*cp == '.') {
|
||
$9:
|
||
cmp al,'.'
|
||
jne $8
|
||
; if (dpflg)
|
||
; break;
|
||
cmp dpflg,0
|
||
jne $8
|
||
; dpflg = 1;
|
||
mov dpflg,1
|
||
; } else
|
||
; break;
|
||
$11:
|
||
; }
|
||
inc di
|
||
jmp $6
|
||
$8:
|
||
; if (*cp == 'e' || *cp == 'E') {
|
||
cmp al,101
|
||
je $15
|
||
cmp al,69
|
||
jne $14
|
||
$15:
|
||
; ++cp;
|
||
inc di
|
||
; if (*cp == '-') {
|
||
cmp cp,45
|
||
jne $16
|
||
; ++cp;
|
||
inc di
|
||
; esign = 1;
|
||
mov esign,1
|
||
jmp short $17
|
||
; } else {
|
||
$16:
|
||
; esign = 0;
|
||
mov esign,0
|
||
; if (*cp == '+')
|
||
; ++cp;
|
||
cmp cp,43
|
||
jne $17
|
||
inc di
|
||
; }
|
||
$17:
|
||
; for ( i = 0 ; isdigit(*cp) ; i = i*10 + *cp++ - '0' )
|
||
sub ax,ax
|
||
mov cx,10
|
||
jmp short $20
|
||
$19:
|
||
mul cx
|
||
mov dx,ax
|
||
mov al,cp
|
||
inc di
|
||
cbw
|
||
add ax,dx
|
||
add ax,-48
|
||
$20:
|
||
mov bl,cp
|
||
cmp bl,'0'
|
||
jb $21
|
||
cmp bl,'9'
|
||
jbe $19
|
||
; ;
|
||
$21:
|
||
; if (esign)
|
||
; i = -i;
|
||
cmp esign,0
|
||
je $22
|
||
neg ax
|
||
$22:
|
||
; dexp += i;
|
||
add si,ax
|
||
; }
|
||
; if (dexp < 0) {
|
||
$14:
|
||
call $dlis
|
||
dw 0,0,0,4024H
|
||
test si,si
|
||
jns $23
|
||
; while (dexp++)
|
||
$24:
|
||
; acc /= ten;
|
||
call $ddv
|
||
inc si
|
||
jnz $24
|
||
jmp short $26
|
||
; } else if (dexp > 0) {
|
||
$23:
|
||
jz $26
|
||
; while (dexp--)
|
||
$28:
|
||
; acc *= ten;
|
||
call $dml
|
||
dec si
|
||
jnz $28
|
||
; }
|
||
$26:
|
||
; if (msign)
|
||
; acc = -acc;
|
||
cmp msign,0
|
||
je $30
|
||
call $dng
|
||
; return acc;
|
||
$30:
|
||
pop si
|
||
pop di
|
||
mov sp,bp
|
||
pret
|
||
;}
|
||
pend atof
|
||
ifdef FARPROC
|
||
extrn $dad:far,$dml:far,$ddv:far,$dlip:far,$dlis:far
|
||
extrn $dng:far,$dswap:far,$itod:far
|
||
else
|
||
extrn $dad:near,$dml:near,$ddv:near,$dlip:near,$dlis:near
|
||
extrn $dng:near,$dswap:near,$itod:near
|
||
endif
|
||
finish
|
||
end
|
||
ftoa.asm
|
||
; Copyright (C) 1984 by Manx Software Systems
|
||
;
|
||
include lmacros.h
|
||
;
|
||
;static double round[] = {
|
||
dataseg segment word public 'data'
|
||
round_ equ this word
|
||
; 5.0e+0,
|
||
db 00H,00H,00H,00H,00H,00H,014H,040H
|
||
; 0.5e+0,
|
||
db 00H,00H,00H,00H,00H,00H,0e0H,03fH
|
||
; 0.5e-1,
|
||
db 09aH,099H,099H,099H,099H,099H,0a9H,03fH
|
||
; 0.5e-2,
|
||
db 07bH,014H,0aeH,047H,0e1H,07aH,074H,03fH
|
||
; 0.5e-3,
|
||
db 0fcH,0a9H,0f1H,0d2H,04dH,062H,040H,03fH
|
||
; 0.5e-4,
|
||
db 02dH,043H,01cH,0ebH,0e2H,036H,0aH,03fH
|
||
; 0.5e-5,
|
||
db 0f1H,068H,0e3H,088H,0b5H,0f8H,0d4H,03eH
|
||
; 0.5e-6,
|
||
db 08dH,0edH,0b5H,0a0H,0f7H,0c6H,0a0H,03eH
|
||
; 0.5e-7,
|
||
db 048H,0afH,0bcH,09aH,0f2H,0d7H,06aH,03eH
|
||
; 0.5e-8,
|
||
db 03aH,08cH,030H,0e2H,08eH,079H,035H,03eH
|
||
; 0.5e-9,
|
||
db 095H,0d6H,026H,0e8H,0bH,02eH,01H,03eH
|
||
; 0.5e-10,
|
||
db 0bbH,0bdH,0d7H,0d9H,0dfH,07cH,0cbH,03dH
|
||
; 0.5e-11,
|
||
db 095H,064H,079H,0e1H,07fH,0fdH,095H,03dH
|
||
; 0.5e-12,
|
||
db 011H,0eaH,02dH,081H,099H,097H,061H,03dH
|
||
; 0.5e-13,
|
||
db 082H,076H,049H,068H,0c2H,025H,02cH,03dH
|
||
; 0.5e-14,
|
||
db 09bH,02bH,0a1H,086H,09bH,084H,0f6H,03cH
|
||
; 0.5e-15,
|
||
db 016H,056H,0e7H,09eH,0afH,03H,0c2H,03cH
|
||
; 0.5e-16,
|
||
; db 0bcH,089H,0d8H,097H,0b2H,0d2H,08cH,03cH
|
||
; 0.5e-17,
|
||
; db 097H,0d4H,046H,046H,0f5H,0eH,057H,03cH
|
||
; 0.5e-18,
|
||
; db 0acH,043H,0d2H,0d1H,05dH,072H,022H,03cH
|
||
;};
|
||
dataseg ends
|
||
assume ds:dataseg
|
||
IFDEF LONGPTR
|
||
buffer equ es:byte ptr [di]
|
||
getes macro
|
||
mov es,word ptr abuf[2]
|
||
endm
|
||
ELSE
|
||
|
||
buffer equ byte ptr [di]
|
||
getes macro
|
||
;
|
||
endm
|
||
ENDIF
|
||
;
|
||
;ftoa(number, abuf, maxwidth, flag)
|
||
;double number; register char *abuf;
|
||
procdef ftoa, <<number,cdouble>,<abuf,ptr>,<maxwidth,word>,<flag,word>>
|
||
add sp,-8
|
||
push di
|
||
push si
|
||
mov di,word ptr abuf ;load offset word of buffer
|
||
;{
|
||
; register int i;
|
||
; int exp, digit, decpos, ndig;
|
||
;
|
||
; ndig = maxwidth+1;
|
||
mov ax,maxwidth
|
||
inc ax
|
||
mov word ptr -8[bp],ax
|
||
; exp = 0;
|
||
mov word ptr -2[bp],0
|
||
; if (number < 0.0) {
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
lea bx,number
|
||
call $dldp
|
||
call $dlis
|
||
db 00H,00H,00H,00H,00H,00H,00H,00H
|
||
call $dcmp
|
||
je $4 ;skip scaling if zero
|
||
jge $3
|
||
; number = -number;
|
||
call $dng
|
||
; *buffer++ = '-';
|
||
getes
|
||
mov buffer,'-'
|
||
inc di
|
||
; }
|
||
$3:
|
||
call $isnan
|
||
je notnan
|
||
mov cx,ax
|
||
mov al,'?'
|
||
cmp cx,1
|
||
beq outrange
|
||
mov al,'*'
|
||
jmp outrange
|
||
notnan:
|
||
; if (number > 0.0) {
|
||
; while (number < 1.0) {
|
||
$5:
|
||
call $dlis
|
||
db 00H,00H,00H,00H,00H,00H,0f0H,03fH
|
||
call $dcmp
|
||
jge $6
|
||
; number *= 10.0;
|
||
call $dlis
|
||
db 00H,00H,00H,00H,00H,00H,024H,040H
|
||
call $dml
|
||
; --exp;
|
||
dec word ptr -2[bp]
|
||
; }
|
||
jmp $5
|
||
$6:
|
||
; while (number >= 10.0) {
|
||
call $dlis
|
||
db 00H,00H,00H,00H,00H,00H,024H,040H
|
||
$7:
|
||
call $dcmp
|
||
jl $8
|
||
; number /= 10.0;
|
||
call $ddv
|
||
; ++exp;
|
||
inc word ptr -2[bp]
|
||
; }
|
||
jmp $7
|
||
$8:
|
||
; }
|
||
;
|
||
; if (flag == 2) { /* 'g' format */
|
||
$4:
|
||
mov ax,flag
|
||
cmp ax,2
|
||
jne $9
|
||
; ndig = maxwidth;
|
||
mov ax,maxwidth
|
||
mov word ptr -8[bp],ax
|
||
; if (exp < -4 || exp >= maxwidth)
|
||
; flag = 0; /* switch to 'e' format */
|
||
mov ax,word ptr -2[bp]
|
||
cmp ax,-4
|
||
jl $11
|
||
cmp ax,maxwidth
|
||
jl $10
|
||
$11:
|
||
mov flag,0
|
||
$10:
|
||
jmp $12
|
||
; } else if (flag == 1) /* 'f' format */
|
||
; ndig += exp;
|
||
$9:
|
||
cmp al,1
|
||
jne $13
|
||
mov ax,word ptr -2[bp]
|
||
add word ptr -8[bp],ax
|
||
;
|
||
; if (ndig >= 0) {
|
||
$13:
|
||
$12:
|
||
mov bx,word ptr -8[bp]
|
||
test bx,bx
|
||
jl $14
|
||
; if ((number += round[ndig>16?16:ndig]) >= 10.0) {
|
||
cmp bx,16
|
||
jle $16
|
||
mov bx,16
|
||
$16:
|
||
mov cx,3
|
||
shl bx,cl
|
||
add bx,offset round_
|
||
ifdef LONGPTR
|
||
mov dx,ds
|
||
mov es,dx
|
||
endif
|
||
call $dlds
|
||
call $dad
|
||
call $dlis
|
||
db 00H,00H,00H,00H,00H,00H,024H,040H
|
||
call $dcmp
|
||
jl $15
|
||
; number = 1.0;
|
||
call $dlip
|
||
db 00H,00H,00H,00H,00H,00H,0f0H,03fH
|
||
; ++exp;
|
||
inc word ptr -2[bp]
|
||
; if (flag)
|
||
; ++ndig;
|
||
cmp flag,0
|
||
je $18
|
||
inc word ptr -8[bp]
|
||
; }
|
||
$18:
|
||
; }
|
||
$15:
|
||
;
|
||
; if (flag) {
|
||
$14:
|
||
cmp flag,0
|
||
je $19
|
||
; if (exp < 0) {
|
||
mov ax,word ptr -2[bp]
|
||
test ax,ax
|
||
jge $20
|
||
; *buffer++ = '0';
|
||
getes
|
||
mov buffer,'0'
|
||
inc di
|
||
; *buffer++ = '.';
|
||
mov buffer,'.'
|
||
inc di
|
||
; i = -exp - 1;
|
||
not ax
|
||
mov cx,ax
|
||
; if (ndig <= 0)
|
||
; i = maxwidth;
|
||
cmp word ptr -8[bp],0
|
||
jg $21
|
||
mov cx,maxwidth
|
||
$21:
|
||
; while (i--)
|
||
; *buffer++ = '0';
|
||
jcxz $23
|
||
mov al,'0'
|
||
rep stosb
|
||
$23:
|
||
; decpos = 0;
|
||
sub ax,ax
|
||
; } else {
|
||
jmp short $25
|
||
$20:
|
||
; decpos = exp+1;
|
||
; }
|
||
mov ax,word ptr -2[bp]
|
||
inc ax
|
||
jmp short $25
|
||
; } else {
|
||
$19:
|
||
; decpos = 1;
|
||
mov ax,1
|
||
; }
|
||
$25:
|
||
mov word ptr -6[bp],ax
|
||
;
|
||
; if (ndig > 0) {
|
||
cmp word ptr -8[bp],0
|
||
jle $28
|
||
; for (i = 0 ; ; ++i) {
|
||
mov si,0
|
||
jmp short $27
|
||
$26:
|
||
inc si
|
||
$27:
|
||
; if (i < 16) {
|
||
cmp si,16
|
||
jge $29
|
||
; digit = (int)number;
|
||
call $dtoi
|
||
push ax
|
||
; *buffer++ = digit+'0';
|
||
getes
|
||
add al,'0'
|
||
stosb
|
||
; number = (number - digit) * 10.0;
|
||
call $dswap ;preserve number
|
||
pop ax
|
||
call $utod
|
||
call $dswap ;number back into primary, digit into secondary
|
||
call $dsb
|
||
call $dlis
|
||
db 00H,00H,00H,00H,00H,00H,024H,040H
|
||
call $dml
|
||
jmp short $30
|
||
; } else
|
||
$29:
|
||
; *buffer++ = '0';
|
||
getes
|
||
mov buffer,'0'
|
||
inc di
|
||
$30:
|
||
; if (--ndig == 0)
|
||
; break;
|
||
dec word ptr -8[bp]
|
||
jz $28
|
||
; if (decpos && --decpos == 0)
|
||
; *buffer++ = '.';
|
||
mov ax,word ptr -6[bp]
|
||
test ax,ax
|
||
jz $26
|
||
dec ax
|
||
mov word ptr -6[bp],ax
|
||
jnz $26
|
||
getes
|
||
mov buffer,'.'
|
||
inc di
|
||
; }
|
||
jmp $26
|
||
; }
|
||
$28:
|
||
getes
|
||
;
|
||
; if (!flag) {
|
||
cmp flag,0
|
||
jne $32
|
||
; *buffer++ = 'e';
|
||
mov buffer,'e'
|
||
inc di
|
||
; if (exp < 0) {
|
||
; exp = -exp;
|
||
; *buffer++ = '-';
|
||
mov al,'+'
|
||
cmp word ptr -2[bp],0
|
||
jge $33
|
||
neg word ptr -2[bp]
|
||
mov al,'-'
|
||
; } else
|
||
; *buffer++ = '+';
|
||
$33:
|
||
stosb
|
||
; if (exp >= 100) {
|
||
mov ax,word ptr -2[bp]
|
||
cmp ax,100
|
||
jl $35
|
||
; *buffer++ = exp/100 + '0';
|
||
mov cx,100
|
||
cwd
|
||
idiv cx
|
||
add al,'0'
|
||
stosb
|
||
; exp %= 100;
|
||
mov ax,dx
|
||
; }
|
||
; *buffer++ = exp/10 + '0';
|
||
$35:
|
||
mov cx,10
|
||
cwd
|
||
idiv cx
|
||
add al,'0'
|
||
stosb
|
||
; *buffer++ = exp%10 + '0';
|
||
mov ax,dx
|
||
add al,'0'
|
||
stosb
|
||
; }
|
||
; *buffer = 0;
|
||
$32:
|
||
mov buffer,0
|
||
;}
|
||
pop si
|
||
pop di
|
||
mov sp,bp
|
||
pret
|
||
|
||
outrange:
|
||
mov cx,maxwidth
|
||
jcxz $32
|
||
rep stosb
|
||
jmp $32
|
||
;
|
||
ifdef FARPROC
|
||
extrn $dad:far,$dsb:far,$dml:far,$ddv:far
|
||
extrn $dldp:far,$dlds:far,$dlip:far,$dlis:far
|
||
extrn $dcmp:far,$dng:far,$dswap:far,$utod:far,$dtoi:far
|
||
extrn $isnan:far
|
||
else
|
||
extrn $dad:near,$dsb:near,$dml:near,$ddv:near
|
||
extrn $dldp:near,$dlds:near,$dlip:near,$dlis:near
|
||
extrn $dcmp:near,$dng:near,$dswap:near,$utod:near,$dtoi:near
|
||
extrn $isnan:near
|
||
endif
|
||
pend ftoa
|
||
finish
|
||
end
|
||
frexp.asm
|
||
; Copyright (C) 1983 by Manx Software Systems
|
||
; :ts=8
|
||
; the psuedo accumlators are formated as follows:
|
||
; -10 -8 -6 -4 -2 0
|
||
; |grd + LS ----- fraction ---- MS | exp | sign
|
||
;
|
||
; floating point system error codes:
|
||
UNDER_FLOW equ 1
|
||
OVER_FLOW equ 2
|
||
DIV_BY_ZERO equ 3
|
||
;
|
||
include lmacros.h
|
||
dataseg segment word public 'data'
|
||
dw 5 dup (?)
|
||
temp dw ?
|
||
extrn flprm:word,flsec:word
|
||
extrn flterr_:word
|
||
dataseg ends
|
||
assume ds:dataseg
|
||
|
||
ifdef FARPROC
|
||
extrn $dldp:far, $dst:far, $itod:far
|
||
extrn $dad:far, $dsb:far, $isnan:far
|
||
else
|
||
extrn $dldp:near, $dst:near, $itod:near
|
||
extrn $dad:near, $dsb:near, $isnan:near
|
||
endif
|
||
procdef isnan
|
||
sub ax,ax
|
||
pret
|
||
pend isnan
|
||
|
||
procdef frexp, <<d,cdouble>,<i,ptr>>
|
||
;
|
||
; frexp(d, &i)
|
||
; returns 0 <= x < 1
|
||
; such that: d = x * 2^i
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
lea bx,d ;compute address of first argument
|
||
call $dldp ;load it into the float primary
|
||
mov bx,flprm
|
||
mov ax,word ptr -2[bx] ;fetch current exponent value
|
||
test ax,ax
|
||
jnz fr_nzero
|
||
ldptr bx,i,es ;get pointer
|
||
ifndef LONGPTR
|
||
mov ds:word ptr [bx],0
|
||
else
|
||
mov es:word ptr [bx],0
|
||
endif
|
||
pret
|
||
fr_nzero:
|
||
sub ax,1022
|
||
mov word ptr -2[bx],1022
|
||
ldptr bx,i,es ;get pointer
|
||
ifndef LONGPTR
|
||
mov ds:word ptr [bx],ax
|
||
else
|
||
mov es:word ptr [bx],ax
|
||
endif
|
||
pret
|
||
pend frexp
|
||
;
|
||
; ldexp(d, i)
|
||
; returns x = d * 2^i
|
||
procdef ldexp, <<dou,cdouble>,<ii,word>>
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
lea bx,dou ;compute address of first argument
|
||
call $dldp ;load it into the float primary
|
||
mov bx,flprm
|
||
mov ax,word ptr -2[bx] ;fetch current exponent value
|
||
test ax,ax
|
||
jz ld_zero
|
||
add ax,ii ;add i to exponent
|
||
js ld_underflow
|
||
cmp ax,2048
|
||
jl ld_ret
|
||
mov flterr_,UNDER_FLOW
|
||
mov ax,2047
|
||
ld_ret:
|
||
mov word ptr -2[bx],ax
|
||
ld_zero:
|
||
pret
|
||
;
|
||
ld_underflow:
|
||
mov flterr_,UNDER_FLOW
|
||
sub ax,ax
|
||
jmp ld_ret
|
||
pend ldexp
|
||
;
|
||
; modf(d, dptr)
|
||
; returns fractional part of d, and
|
||
; stores integral part into *dptr
|
||
procdef modf,<<doubl,cdouble>,<dptr,ptr>>
|
||
push di
|
||
push si
|
||
pushds
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
lea bx,doubl ;compute address of first argument
|
||
call $dldp ;load it into the float primary
|
||
std
|
||
mov bx,flprm
|
||
mov ax,word ptr -2[bx] ;fetch current exponent value
|
||
test ax,ax
|
||
jnz mf_nzero
|
||
ldptr bx,dptr,es ;get pointer
|
||
call $dst
|
||
mf_return:
|
||
cld
|
||
popds
|
||
pop si
|
||
pop di
|
||
pret
|
||
mf_nzero:
|
||
mov di,ds
|
||
mov es,di
|
||
mov si,bx
|
||
mov di,offset temp
|
||
mov cx,6 ;save value for fraction part later
|
||
rep movsw
|
||
sub ax,1023
|
||
jns int_notzero
|
||
mov ax,0
|
||
call $itod
|
||
jmp get_fraction
|
||
int_notzero:
|
||
cmp ax,52
|
||
jna mf_frac
|
||
;fraction is zero
|
||
ldptr bx,dptr,es ;get pointer
|
||
call $dst ;store integer part away
|
||
sub ax,ax
|
||
call $itod
|
||
jmp mf_return
|
||
mf_frac:
|
||
sub di,di
|
||
mov cx,ax
|
||
mov ax,4
|
||
mf_count:
|
||
sub cx,ax
|
||
jbe mf_cdone
|
||
dec di
|
||
mov ax,8
|
||
jmp mf_count
|
||
mf_cdone:
|
||
jcxz no_shift
|
||
neg cx
|
||
mov al,byte ptr -3[bx][di]
|
||
shr al,cl
|
||
shl al,cl
|
||
mov byte ptr -3[bx][di],al
|
||
no_shift:
|
||
dec di
|
||
zap_loop:
|
||
cmp di,-8
|
||
jle get_fraction
|
||
mov byte ptr -3[bx][di],0
|
||
dec di
|
||
jmp zap_loop
|
||
get_fraction:
|
||
ldptr bx,dptr,es ;get pointer
|
||
call $dst ;store integer part away
|
||
std
|
||
popds
|
||
pushds
|
||
mov di,flprm
|
||
xchg di,flsec
|
||
mov flprm,di
|
||
mov si,ds
|
||
mov es,si
|
||
mov si,offset temp
|
||
mov cx,6 ;restore original value
|
||
rep movsw
|
||
call $dsb ;compute fractional part
|
||
jmp mf_return
|
||
pend modf
|
||
finish
|
||
end
|
||
fsubs.asm
|
||
; Copyright (C) 1983 by Manx Software Systems
|
||
; :ts=8
|
||
; the psuedo accumlators are formated as follows:
|
||
; -12 -10 -8 -6 -4 -2 0
|
||
; |guard digits + LS ----- fraction ---- MS | exp | sign
|
||
;
|
||
; floating point system error codes:
|
||
|
||
ifndef INTERNAL
|
||
include lmacros.h
|
||
UNDER_FLOW equ 1
|
||
OVER_FLOW equ 2
|
||
DIV_BY_ZERO equ 3
|
||
endif
|
||
;
|
||
dataseg segment word public 'data'
|
||
public flprm,flsec
|
||
ifndef INTERNAL
|
||
public flterr_
|
||
flterr_ dw 0
|
||
endif
|
||
|
||
flprm dw acc1
|
||
flsec dw acc2
|
||
YU dw ?
|
||
VEE dw ?
|
||
dw 5 dup (?)
|
||
acc1 dw 7 dup (?)
|
||
acc2 dw ?
|
||
;
|
||
;work area for divide and multiply routines
|
||
;
|
||
dw 4 dup (?)
|
||
temp dw 4 dup (?)
|
||
loop_count db 0 ;iterations left (for divide)
|
||
lcnt1 db 0 ;# iter. for this word of quotient
|
||
dataseg ends
|
||
ifdef LONGPTR
|
||
assume ds:dataseg
|
||
else
|
||
assume ds:dataseg,ss:dataseg
|
||
endif
|
||
|
||
ifndef INTERNAL
|
||
internal $floats
|
||
endif
|
||
|
||
intrdef $isnan
|
||
sub ax,ax
|
||
ret
|
||
|
||
intrdef $flds ;load single float into secondary accum
|
||
push di
|
||
mov di,flsec
|
||
jmp short fload
|
||
|
||
ifdef LONGPTR
|
||
intrdef $fldsss ;load single float into secondary accum
|
||
push di
|
||
mov di,ss
|
||
mov es,di
|
||
mov di,flsec
|
||
jmp short fload
|
||
|
||
intrdef $fldsds ;load single float into secondary accum
|
||
push di
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,flsec
|
||
jmp short fload
|
||
|
||
intrdef $fldpss ;load single float into primary accum
|
||
push di
|
||
mov di,ss
|
||
mov es,di
|
||
mov di,flprm
|
||
jmp short fload
|
||
|
||
intrdef $fldpds ;load single float into primary accum
|
||
push di
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,flprm
|
||
jmp short fload
|
||
|
||
endif
|
||
;
|
||
intrdef $fldp ;load single float into primary accum
|
||
push di
|
||
mov di,flprm
|
||
fload:
|
||
push si
|
||
ifndef LONGPTR
|
||
mov si,ds
|
||
mov es,si
|
||
endif
|
||
mov ax,es:2[bx] ;get exponent/sign word of number
|
||
mov byte ptr [di],ah ;save sign
|
||
mov dh,al ;save fraction bits
|
||
shl ax,1 ;get LS bit of exponent
|
||
xchg ah,al
|
||
and ax,0ffH
|
||
jnz fld_nz
|
||
pushds
|
||
ifdef LONGPTR
|
||
mov ax,ds
|
||
mov es,ax
|
||
endif
|
||
jmp loadzero
|
||
fld_nz:
|
||
sub ax,127 ;adjust from excess 127 notation
|
||
add ax,1023 ;put into excess 1023 notation
|
||
mov word ptr -2[di],ax ;and save
|
||
or dh,80H ;turn "hidden" bit back on
|
||
mov dl,es:byte ptr 1[bx]
|
||
mov ah,es:byte ptr [bx]
|
||
sub al,al
|
||
shr dx,1 ;shift fraction into same position as a double
|
||
rcr ax,1
|
||
shr dx,1
|
||
rcr ax,1
|
||
shr dx,1
|
||
rcr ax,1
|
||
mov word ptr -4[di],dx
|
||
mov word ptr -6[di],ax
|
||
sub ax,ax
|
||
mov word ptr -8[di],ax
|
||
mov word ptr -10[di],ax
|
||
mov word ptr -12[di],ax
|
||
pop si
|
||
pop di
|
||
ret
|
||
;
|
||
|
||
ifdef LONGPTR
|
||
intrdef $fstss
|
||
mov cx,ss
|
||
mov es,cx
|
||
jmp short dofst
|
||
|
||
intrdef $fstds
|
||
mov cx,ds
|
||
mov es,cx
|
||
jmp short dofst
|
||
|
||
intrdef $fstsss
|
||
mov cx,ss
|
||
mov es,cx
|
||
jmp short dofsts
|
||
|
||
intrdef $fstsds
|
||
mov cx,ds
|
||
mov es,cx
|
||
jmp short dofsts
|
||
endif
|
||
|
||
intrdef $fsts ; store single from secondary
|
||
dofsts:
|
||
mov ax,flprm
|
||
xchg ax,flsec
|
||
mov flprm,ax
|
||
ifdef FARPROC
|
||
call far ptr $fst
|
||
else
|
||
call $fst
|
||
endif
|
||
mov ax,flprm
|
||
xchg ax,flsec
|
||
mov flprm,ax
|
||
ret
|
||
|
||
intrdef $fst ;store single at addr in BX
|
||
ifndef LONGPTR
|
||
mov ax,ds
|
||
mov es,ax
|
||
endif
|
||
dofst:
|
||
push di
|
||
push si
|
||
push bx
|
||
call dornd
|
||
pop di
|
||
mov si,flprm
|
||
mov ax,-2[si] ;get exponent
|
||
test ax,ax
|
||
jnz fst_nzero
|
||
mov es:word ptr [di],0
|
||
mov es:word ptr 2[di],0
|
||
pop si
|
||
pop di
|
||
ret
|
||
fst_nzero:
|
||
sub ax,1023 ;switch from excess 1023 notation
|
||
add ax,127 ;into excess 127 notation
|
||
mov dx,-4[si]
|
||
mov bx,-6[si]
|
||
add bx,10H ;round number
|
||
adc dx,0
|
||
shl bx,1 ;move number back into proper position
|
||
rcl dx,1
|
||
shl bx,1
|
||
rcl dx,1
|
||
test dx,dx
|
||
js fix_exp
|
||
shl bx,1
|
||
rcl dx,1
|
||
jmp short fst_merge
|
||
fix_exp:
|
||
inc ax ;adjust exponent
|
||
fst_merge:
|
||
mov cl,7
|
||
shl ax,cl
|
||
mov cl,[si] ;get sign
|
||
and cl,80H
|
||
or ah,cl ;merge sign and exponent
|
||
and dh,7fH ;clear "hidden" bit
|
||
or al,dh ;merge with sign/exponent
|
||
mov es:word ptr 2[di],ax
|
||
mov es:byte ptr 1[di],dl
|
||
mov es:byte ptr [di],bh
|
||
pop si
|
||
pop di
|
||
ret
|
||
;
|
||
intrdef $dlis ;load double immediate secondary
|
||
ifdef LONGPTR
|
||
push bp
|
||
mov bp,sp
|
||
ifdef FARPROC
|
||
les bx,2[bp]
|
||
else
|
||
mov bx,cs
|
||
mov es,bx
|
||
mov bx,2[bp]
|
||
endif
|
||
add 2[bp],8 ;skip over double constant in code
|
||
pop bp
|
||
jmp dolds
|
||
|
||
else
|
||
mov bx,sp
|
||
push di
|
||
push si
|
||
mov cx,ds
|
||
mov es,cx
|
||
ifdef FARPROC
|
||
lds si,[bx] ;get return addr
|
||
else
|
||
mov si,[bx] ;get return addr
|
||
mov di,cs
|
||
mov ds,di
|
||
endif
|
||
cld
|
||
mov di,offset temp
|
||
movsw
|
||
movsw
|
||
movsw
|
||
movsw
|
||
mov ds,cx
|
||
mov [bx],si ;put back correct return addr
|
||
lea si,-2[di]
|
||
mov di,flsec
|
||
jmp dload2
|
||
endif
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $dldsds
|
||
mov cx,ds
|
||
mov es,cx
|
||
jmp dolds
|
||
|
||
intrdef $dldsss
|
||
mov cx,ss
|
||
mov es,cx
|
||
jmp dolds
|
||
endif
|
||
|
||
intrdef $dlds ;load double float into secondary accum
|
||
ifndef LONGPTR
|
||
mov ax,ds
|
||
mov es,ax
|
||
endif
|
||
dolds:
|
||
push di
|
||
mov di,flsec
|
||
jmp short dload
|
||
;
|
||
intrdef $dlip ;load double immediate primary
|
||
ifdef LONGPTR
|
||
push bp
|
||
mov bp,sp
|
||
ifdef FARPROC
|
||
les bx,2[bp]
|
||
else
|
||
mov bx,cs
|
||
mov es,bx
|
||
mov bx,2[bp]
|
||
endif
|
||
add 2[bp],8 ;skip over double constant in code
|
||
pop bp
|
||
jmp short dodldp
|
||
|
||
else
|
||
mov bx,sp
|
||
push di
|
||
push si
|
||
mov cx,ds
|
||
mov es,cx
|
||
ifdef FARPROC
|
||
lds si,[bx] ;get return addr
|
||
else
|
||
mov si,[bx] ;get return addr
|
||
mov di,cs
|
||
mov ds,di
|
||
endif
|
||
cld
|
||
mov di,offset temp
|
||
movsw
|
||
movsw
|
||
movsw
|
||
movsw
|
||
mov ds,cx
|
||
mov [bx],si ;put back correct return addr
|
||
lea si,-2[di]
|
||
mov di,flprm
|
||
jmp dload2
|
||
endif
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $dldpss
|
||
mov cx,ss
|
||
mov es,cx
|
||
jmp short dodldp
|
||
|
||
intrdef $dldpds
|
||
mov cx,ds
|
||
mov es,cx
|
||
jmp short dodldp
|
||
endif
|
||
|
||
intrdef $dldp ;load double float into primary accum
|
||
ifndef LONGPTR
|
||
mov ax,ds
|
||
mov es,ax
|
||
endif
|
||
dodldp:
|
||
push di
|
||
mov di,flprm
|
||
dload:
|
||
push si
|
||
lea si,6[bx]
|
||
dload2:
|
||
ifdef LONGPTR
|
||
push ds
|
||
mov cx,es ;swap the segment registers
|
||
mov dx,ds
|
||
mov es,dx
|
||
mov ds,cx
|
||
endif
|
||
std
|
||
lods word ptr [si];get first two bytes of number
|
||
mov es:byte ptr [di],ah ;save sign
|
||
mov dh,al ;save top nibble of fraction
|
||
mov cl,4
|
||
shr ax,cl
|
||
and ax,7ffH ;isolate exponent
|
||
jz loadzero
|
||
sub di,2
|
||
stos word ptr [di]
|
||
and dh,15 ;isolate fraction
|
||
or dh,10H ;put back "hidden" bit
|
||
mov es:byte ptr 1[di],dh
|
||
mov cx,6
|
||
inc si
|
||
rep movs byte ptr [di], byte ptr [si]
|
||
mov al,0
|
||
stosb ;clear guard bytes
|
||
stosb
|
||
stosb
|
||
cld
|
||
popds
|
||
pop si
|
||
pop di
|
||
ret
|
||
loadzero:
|
||
std
|
||
sub ax,ax
|
||
mov cx,7
|
||
rep stos word ptr [di]
|
||
cld
|
||
popds
|
||
pop si
|
||
pop di
|
||
ret
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $dstss
|
||
mov cx,ss
|
||
mov es,cx
|
||
jmp short dodst
|
||
|
||
intrdef $dstds
|
||
mov cx,ds
|
||
mov es,cx
|
||
jmp short dodst
|
||
|
||
intrdef $dstsss
|
||
mov cx,ss
|
||
mov es,cx
|
||
jmp short dodsts
|
||
|
||
intrdef $dstsds
|
||
mov cx,ds
|
||
mov es,cx
|
||
jmp short dodsts
|
||
endif
|
||
intrdef $dsts
|
||
dodsts:
|
||
mov ax,flprm
|
||
xchg ax,flsec
|
||
mov flprm,ax
|
||
ifdef FARPROC
|
||
call far ptr $dst
|
||
else
|
||
call $dst
|
||
endif
|
||
mov ax,flprm
|
||
xchg ax,flsec
|
||
mov flprm,ax
|
||
ret
|
||
|
||
|
||
intrdef $dst ;store double at addr in ES:BX
|
||
dodst:
|
||
std
|
||
ifndef LONGPTR
|
||
mov dx,ds
|
||
mov es,dx
|
||
endif
|
||
push di
|
||
push si
|
||
push bx ;save address
|
||
call dornd ;round fraction to 7 bytes
|
||
pop di ;restore address
|
||
add di,6
|
||
mov si,flprm
|
||
mov dl,[si] ;get sign
|
||
and dl,80H
|
||
sub si,2
|
||
lods word ptr [si];get exponent
|
||
mov cl,4
|
||
shl ax,cl
|
||
or ah,dl ;merge sign and exponent
|
||
mov dl,1[si]
|
||
and dl,15 ;clear "hidden" bit
|
||
or al,dl ;merge with sign/exponent
|
||
stos word ptr [di]
|
||
mov cx,6
|
||
inc di
|
||
rep movs byte ptr [di], byte ptr [si]
|
||
cld
|
||
pop si
|
||
pop di
|
||
ret
|
||
;
|
||
intrdef $dpshs ;push double float onto the stack
|
||
;from the primary accumulator
|
||
pop ax ;fetch return address
|
||
ifdef FARPROC
|
||
pop dx
|
||
endif
|
||
sub sp,8 ;make room for double on stack
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
mov bx,sp ;address of place to store
|
||
ifdef FARPROC
|
||
push dx
|
||
endif
|
||
push ax ;put return address back
|
||
jmp near ptr dodsts
|
||
;
|
||
intrdef $dpsh ;push double float onto the stack
|
||
;from the primary accumulator
|
||
pop ax ;fetch return address
|
||
ifdef FARPROC
|
||
pop dx
|
||
endif
|
||
sub sp,8 ;make room for double on stack
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
mov bx,sp ;address of place to store
|
||
ifdef FARPROC
|
||
push dx
|
||
endif
|
||
push ax ;put return address back
|
||
jmp near ptr dodst
|
||
;
|
||
intrdef $dpopp ;pop double float into secondary accum
|
||
push bx
|
||
push es
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
mov bx,sp
|
||
add bx,FPTRSIZE+4 ;address of data to load
|
||
ifdef FARPROC
|
||
call far ptr $dldp
|
||
else
|
||
call $dldp
|
||
endif
|
||
|
||
pop es
|
||
pop bx
|
||
ret 8 ;return and de-allocate space
|
||
;
|
||
intrdef $dpop ;pop double float into secondary accum
|
||
push bx
|
||
push es
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
mov bx,sp
|
||
add bx,FPTRSIZE+4 ;address of data to load
|
||
ifdef FARPROC
|
||
call far ptr $dlds
|
||
else
|
||
call $dlds
|
||
endif
|
||
pop es
|
||
pop bx
|
||
ret 8 ;return and de-allocate space
|
||
;
|
||
intrdef $dswap ;exchange primary and secondary
|
||
mov ax,flsec
|
||
xchg ax,flprm
|
||
mov flsec,ax
|
||
ret
|
||
;
|
||
intrdef $dng ;negate primary
|
||
mov bx,flprm
|
||
xor byte ptr [bx],80H ;flip sign
|
||
ret
|
||
;
|
||
intrdef $dtst ;test if primary is zero
|
||
mov bx,flprm
|
||
cmp word ptr -2[bx],0
|
||
jne true
|
||
sub ax,ax
|
||
ret
|
||
true:
|
||
sub ax,ax
|
||
inc ax
|
||
ret
|
||
;
|
||
intrdef $dcmp ;compare primary and secondary
|
||
push di
|
||
push si
|
||
std
|
||
mov si,flprm
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,flsec
|
||
mov al,byte ptr [si]
|
||
test al,al ;is primary negative
|
||
js dcneg
|
||
; primary is positive
|
||
xor al,byte ptr [di] ;check if signs the same
|
||
js p_gt_s ;differ then p > s
|
||
jmp short docomp
|
||
dcneg:
|
||
;primary is negative
|
||
xor al,byte ptr [di] ;check if signs the same
|
||
js p_lt_s ;differ the p < s
|
||
xchg di,si ;both negative reverse sense of test
|
||
docomp:
|
||
sub di,2 ;back up to exponent
|
||
sub si,2
|
||
mov cx,5 ;test exponent + 4 words of fraction
|
||
repe cmps acc1, es:acc2
|
||
jb p_lt_s
|
||
ja p_gt_s
|
||
;return 0 if p == s
|
||
xor ax,ax
|
||
jmp short cmp_return
|
||
;return 0 if p == s
|
||
p_lt_s: ;return < 0 if p < s
|
||
xor ax,ax
|
||
dec ax
|
||
jmp short cmp_return
|
||
;
|
||
p_gt_s: ; > 0 if p > s
|
||
xor ax,ax
|
||
inc ax
|
||
cmp_return:
|
||
pop si
|
||
pop di
|
||
cld
|
||
ret
|
||
;
|
||
intrdef $dsb ;subtract secondary from primary
|
||
mov bx,flsec
|
||
xor byte ptr [bx],80H ;flip sign of secondary
|
||
;and fall thru into add routine
|
||
;
|
||
intrdef $dad ;add secondary to primary
|
||
pushf
|
||
push bp
|
||
push si
|
||
push di
|
||
std
|
||
mov si,flprm
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,flsec
|
||
mov cx,word ptr -2[si] ;get exponent of primary
|
||
sub cx,word ptr -2[di] ;compute magnitude difference
|
||
jae order_ok
|
||
xchg si,di ;make largest number primary
|
||
mov flprm,si
|
||
mov flsec,di
|
||
neg cx ;fix exponent difference
|
||
order_ok:
|
||
cmp cx,64 ;see if numbers overlap
|
||
jna add_ok ;no overlap just return largest number
|
||
pop di
|
||
pop si
|
||
pop bp
|
||
popf
|
||
ret
|
||
add_ok:
|
||
lea si,-3[di]
|
||
mov di,offset temp+7
|
||
sub al,al
|
||
cx_check:
|
||
cmp cx,8 ;more than a byte to shift ?
|
||
jb shift_it ;no, then shift remaining part over
|
||
stos byte ptr [di]
|
||
sub cx,8
|
||
jmp cx_check
|
||
shift_it:
|
||
sub dl,dl
|
||
shift_loop:
|
||
mov ah,dl
|
||
lods byte ptr [si]
|
||
mov dl,al
|
||
shr ax,cl
|
||
stos byte ptr [di]
|
||
cmp di,offset temp-2
|
||
jae shift_loop
|
||
;
|
||
mov si,flprm
|
||
mov di,flsec
|
||
mov cx,5 ;load up for loops below
|
||
mov al,byte ptr [di]
|
||
xor al,byte ptr [si]
|
||
jns signs_same
|
||
test byte ptr [di],80H ;check which is negative
|
||
jnz sub_s_from_p
|
||
;
|
||
; subtract primary from secondary
|
||
;
|
||
clc
|
||
mov bx,0
|
||
sub_loop_1:
|
||
mov ax,temp-2[bx]
|
||
sbb ax,word ptr -12[bx][si]
|
||
mov word ptr -12[bx][si],ax
|
||
inc bx
|
||
inc bx
|
||
loop sub_loop_1
|
||
jmp short check_sign
|
||
;
|
||
; subtract secondary from primary
|
||
;
|
||
sub_s_from_p:
|
||
clc
|
||
mov bx,0
|
||
sub_loop_2:
|
||
mov ax,temp-2[bx]
|
||
sbb word ptr -12[bx][si],ax
|
||
inc bx
|
||
inc bx
|
||
loop sub_loop_2
|
||
check_sign:
|
||
mov byte ptr [si],0 ;mark result as positive
|
||
jnb do_normalize
|
||
mov byte ptr [si],0FFH ;mark result as negative
|
||
clc
|
||
mov bx,0
|
||
mov cx,5
|
||
neg_loop:
|
||
mov ax,0
|
||
sbb ax,word ptr -12[bx][si]
|
||
mov word ptr -12[bx][si],ax
|
||
inc bx
|
||
inc bx
|
||
loop neg_loop
|
||
jmp short do_normalize
|
||
;
|
||
; signs of numbers are the same just add them together
|
||
;
|
||
signs_same:
|
||
clc
|
||
mov bx,0
|
||
add_loop:
|
||
mov ax,temp-2[bx]
|
||
adc word ptr -12[bx][si],ax
|
||
inc bx
|
||
inc bx
|
||
loop add_loop
|
||
;;; jmp short do_normalize ;fall through
|
||
;
|
||
; normalize number such that first byte of number is >= 0x10
|
||
; and < 0x20
|
||
;
|
||
do_normalize:
|
||
mov si,flprm
|
||
lea bp,-12[si]
|
||
norm:
|
||
lea bx,-3[si]
|
||
mov dx,word ptr -2[si] ;get exponent
|
||
byte_loop:
|
||
cmp byte ptr [bx],0
|
||
jne bskip_done
|
||
dec bx
|
||
sub dx,8
|
||
cmp bx,bp
|
||
jae byte_loop
|
||
;
|
||
; number is zero
|
||
;
|
||
zero_result:
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,flprm
|
||
sub ax,ax
|
||
mov cx,7
|
||
rep stos word ptr [di]
|
||
pop di
|
||
pop si
|
||
pop bp
|
||
popf
|
||
ret
|
||
|
||
bskip_done:
|
||
sub cx,cx
|
||
lea di,-3[si]
|
||
mov ah,byte ptr [bx]
|
||
dec bx
|
||
cmp ah,20H
|
||
jnb too_big
|
||
;
|
||
mov al,byte ptr [bx]
|
||
mov ch,al
|
||
left_count:
|
||
cmp ah,10H
|
||
jae move_left
|
||
shl ax,1
|
||
inc cl
|
||
dec dx
|
||
jmp left_count
|
||
move_left:
|
||
mov [di],ah
|
||
dec di
|
||
dec bx
|
||
cmp bx,bp
|
||
jb clear_tail
|
||
mov ah,ch
|
||
mov al,byte ptr [bx]
|
||
mov ch,al
|
||
shl ax,cl
|
||
jmp move_left
|
||
;
|
||
;
|
||
too_big:
|
||
mov al,ah
|
||
sub ah,ah
|
||
mov ch,al
|
||
right_count:
|
||
inc cl
|
||
inc dx
|
||
shr ax,1
|
||
cmp al,20H
|
||
jnb right_count
|
||
move_right:
|
||
stos byte ptr [di]
|
||
cmp bx,bp
|
||
jb clear_tail
|
||
mov ah,ch
|
||
mov al,byte ptr [bx]
|
||
dec bx
|
||
mov ch,al
|
||
shr ax,cl
|
||
jmp move_right
|
||
;
|
||
clear_tail:
|
||
mov cx,di
|
||
sub cx,bp
|
||
inc cx
|
||
jcxz norm_done
|
||
sub al,al
|
||
rep stos byte ptr [di]
|
||
;
|
||
norm_done:
|
||
;
|
||
; overflow/underflow checking needs to be done here
|
||
;
|
||
cmp dx,0
|
||
jg no_under
|
||
mov flterr_,UNDER_FLOW
|
||
mov word ptr -2[si],1
|
||
jmp short clr_fraction
|
||
no_under:
|
||
cmp dx,2048
|
||
jl no_over
|
||
mov flterr_,OVER_FLOW
|
||
mov word ptr -2[si],2047
|
||
clr_fraction:
|
||
mov word ptr -4[si],1000H
|
||
lea di,-6[si]
|
||
sub ax,ax
|
||
stos word ptr [di]
|
||
stos word ptr [di]
|
||
stos word ptr [di]
|
||
jmp fault_handler
|
||
no_over:
|
||
mov word ptr -2[si],dx ;save new value of exponent
|
||
pop di
|
||
pop si
|
||
pop bp
|
||
popf
|
||
ret
|
||
;
|
||
intrdef $ddv
|
||
;double floating divide (primary = primary/secondary)
|
||
pushf
|
||
push bp
|
||
push si
|
||
push di
|
||
std
|
||
mov di,ds
|
||
mov es,di
|
||
mov bp,flprm
|
||
mov bx,flsec
|
||
mov ax,ds:-2[bp]
|
||
test ax,ax
|
||
jnz not_zero
|
||
jmp zero_result
|
||
not_zero:
|
||
mov dx,-2[bx]
|
||
test dx,dx
|
||
jnz div_ok
|
||
mov flterr_,DIV_BY_ZERO
|
||
jmp fault_handler
|
||
div_ok:
|
||
sub ax,dx
|
||
add ax,1019 ;exp = Ep - Es
|
||
mov ds:-2[bp],ax
|
||
mov al,byte ptr [bx]
|
||
xor ds:byte ptr [bp],al
|
||
;
|
||
mov ax,-6[bx] ;check if easy divide case
|
||
or ax,-8[bx]
|
||
or ax,-10[bx]
|
||
jnz hard_div
|
||
;
|
||
mov si,-4[bx]
|
||
lea di,ds:-4[bp]
|
||
mov cx,4
|
||
mov dx,[di]
|
||
cmp dx,si
|
||
jb ediv_loop
|
||
shl si,1
|
||
inc ds:word ptr -2[bp] ;adjust exponent
|
||
ediv_loop:
|
||
mov ax,-2[di]
|
||
div si
|
||
stos word ptr [di]
|
||
loop ediv_loop
|
||
sub ax,ax ;this IS the correct way
|
||
div si
|
||
stos word ptr [di]
|
||
jmp do_normalize
|
||
;
|
||
hard_div:
|
||
lea si,ds:-4[bp]
|
||
lea di,-4[bx]
|
||
mov cx,4
|
||
repe cmps acc1, es:acc2
|
||
jne do_div
|
||
; numbers are the same so answer is 1
|
||
add ds:word ptr -2[bp],4 ;adjust exponent
|
||
lea di,ds:-4[bp]
|
||
mov ax,1000H
|
||
stos es:acc1
|
||
sub ax,ax
|
||
stos es:acc1
|
||
stos es:acc1
|
||
stos es:acc1
|
||
mov si,bp
|
||
mov dx,word ptr -2[si]
|
||
jmp norm_done
|
||
;
|
||
do_div:
|
||
mov ds:word ptr -12[bp],0
|
||
mov ax,ds:-10[bp]
|
||
mov dx,ds:-8[bp]
|
||
mov si,ds:-6[bp]
|
||
mov di,ds:-4[bp]
|
||
jb dont_shift
|
||
inc ds:word ptr -2[bp] ;fix exponent
|
||
shr di,1
|
||
rcr si,1
|
||
rcr dx,1
|
||
rcr ax,1
|
||
dont_shift:
|
||
sub cx,cx
|
||
sub bp,4
|
||
mov loop_count,4
|
||
bdiv_loop:
|
||
mov lcnt1,16
|
||
div_loop:
|
||
shl cx,1
|
||
shl ax,1
|
||
rcl dx,1
|
||
rcl si,1
|
||
rcl di,1
|
||
sub ax,word ptr -10[bx]
|
||
sbb dx,word ptr -8[bx]
|
||
sbb si,word ptr -6[bx]
|
||
sbb di,word ptr -4[bx]
|
||
js zero_bit
|
||
one_bit:
|
||
inc cx ;set bit in quotient
|
||
dec lcnt1
|
||
jnz div_loop
|
||
mov ds:word ptr [bp],cx
|
||
sub bp,2
|
||
sub cx,cx
|
||
dec loop_count
|
||
jnz bdiv_loop
|
||
jmp do_normalize
|
||
;
|
||
bzero_loop:
|
||
mov lcnt1,16
|
||
zero_loop:
|
||
shl cx,1
|
||
shl ax,1
|
||
rcl dx,1
|
||
rcl si,1
|
||
rcl di,1
|
||
add ax,word ptr -10[bx]
|
||
adc dx,word ptr -8[bx]
|
||
adc si,word ptr -6[bx]
|
||
adc di,word ptr -4[bx]
|
||
jns one_bit
|
||
zero_bit:
|
||
dec lcnt1
|
||
jnz zero_loop
|
||
mov ds:word ptr [bp],cx
|
||
sub bp,2
|
||
sub cx,cx
|
||
dec loop_count
|
||
jnz bzero_loop
|
||
jmp do_normalize
|
||
;
|
||
;
|
||
intrdef $dml
|
||
;double floating multiply (primary = primary * secondary)
|
||
pushf
|
||
push bp
|
||
push si
|
||
push di
|
||
std
|
||
mov si,flprm
|
||
mov bx,flsec
|
||
mov ax,-2[si]
|
||
test ax,ax
|
||
jnz prm_not_zero
|
||
jmp zero_result
|
||
prm_not_zero:
|
||
mov dx,-2[bx]
|
||
test dx,dx
|
||
jnz alt_not_zero
|
||
jmp zero_result
|
||
alt_not_zero:
|
||
add ax,dx
|
||
sub ax,1019
|
||
mov -2[si],ax
|
||
mov al,byte ptr [bx]
|
||
xor byte ptr [si],al
|
||
sub ax,ax
|
||
mov cx,8
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,offset temp+6
|
||
rep stos word ptr [di] ;clear result
|
||
;
|
||
mov cx,-10[bx]
|
||
jcxz skip1
|
||
mov ax,-6[si]
|
||
test ax,ax
|
||
jz skip13
|
||
mul cx
|
||
mov temp-2,dx
|
||
skip13:
|
||
mov ax,-4[si]
|
||
test ax,ax
|
||
jz skip1
|
||
mul cx
|
||
add temp-2,ax
|
||
adc temp,dx
|
||
adc temp+2,0
|
||
skip1:
|
||
mov cx,-8[bx]
|
||
jcxz skip2
|
||
mov ax,-8[si]
|
||
test ax,ax
|
||
jz skip22
|
||
mul cx
|
||
add temp-2,dx
|
||
adc temp,0
|
||
adc temp+2,0
|
||
skip22:
|
||
mov ax,-6[si]
|
||
test ax,ax
|
||
jz skip23
|
||
mul cx
|
||
add temp-2,ax
|
||
adc temp,dx
|
||
adc temp+2,0
|
||
skip23:
|
||
mov ax,-4[si]
|
||
test ax,ax
|
||
jz skip2
|
||
mul cx
|
||
add temp,ax
|
||
adc temp+2,dx
|
||
adc temp+4,0
|
||
skip2:
|
||
mov cx,-6[bx]
|
||
jcxz skip3
|
||
mov ax,-10[si]
|
||
test ax,ax
|
||
jz skip3x
|
||
mul cx
|
||
add temp-2,dx
|
||
adc temp,0
|
||
adc temp+2,0
|
||
adc temp+4,0
|
||
skip3x:
|
||
mov ax,-8[si]
|
||
test ax,ax
|
||
jz skip31
|
||
mul cx
|
||
add temp-2,ax
|
||
adc temp,dx
|
||
adc temp+2,0
|
||
adc temp+4,0
|
||
skip31:
|
||
mov ax,-6[si]
|
||
test ax,ax
|
||
jz skip32
|
||
mul cx
|
||
add temp,ax
|
||
adc temp+2,dx
|
||
adc temp+4,0
|
||
skip32:
|
||
mov ax,-4[si]
|
||
test ax,ax
|
||
jz skip3
|
||
mul cx
|
||
add temp+2,ax
|
||
adc temp+4,dx
|
||
adc temp+6,0
|
||
skip3:
|
||
mov cx,-4[bx]
|
||
jcxz skip4
|
||
mov ax,-10[si]
|
||
test ax,ax
|
||
jz skip41
|
||
mul cx
|
||
add temp-2,ax
|
||
adc temp,dx
|
||
adc temp+2,0
|
||
adc temp+4,0
|
||
adc temp+6,0
|
||
skip41:
|
||
mov ax,-8[si]
|
||
test ax,ax
|
||
jz skip42
|
||
mul cx
|
||
add temp,ax
|
||
adc temp+2,dx
|
||
adc temp+4,0
|
||
adc temp+6,0
|
||
skip42:
|
||
mov ax,-6[si]
|
||
test ax,ax
|
||
jz skip43
|
||
mul cx
|
||
add temp+2,ax
|
||
adc temp+4,dx
|
||
adc temp+6,0
|
||
skip43:
|
||
mov ax,-4[si]
|
||
test ax,ax
|
||
jz skip4
|
||
mul cx
|
||
add temp+4,ax
|
||
adc temp+6,dx
|
||
skip4:
|
||
lea di,-4[si]
|
||
mov si,offset temp+6
|
||
mov cx,5
|
||
rep movs word ptr [di], word ptr [si]
|
||
jmp do_normalize
|
||
;
|
||
intrdef $utod
|
||
pushf
|
||
push bp
|
||
push si
|
||
push di
|
||
std
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,flprm
|
||
mov byte ptr [di],0 ;make sign positive
|
||
mov word ptr -2[di],1023+12 ;set exponent
|
||
sub di,4
|
||
stos word ptr [di]
|
||
sub ax,ax
|
||
stos word ptr [di]
|
||
stos word ptr [di]
|
||
stos word ptr [di]
|
||
stos word ptr [di]
|
||
jmp do_normalize
|
||
;
|
||
intrdef $itod
|
||
pushf
|
||
push bp
|
||
push si
|
||
push di
|
||
std
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,flprm
|
||
mov byte ptr [di],0 ;make sign positive
|
||
mov word ptr -2[di],1023+12 ;set exponent
|
||
test ax,ax
|
||
jns pos_int
|
||
neg ax
|
||
mov byte ptr [di],80H ;make sign negative
|
||
pos_int:
|
||
sub di,4
|
||
stos word ptr [di]
|
||
sub ax,ax
|
||
stos word ptr [di]
|
||
stos word ptr [di]
|
||
stos word ptr [di]
|
||
stos word ptr [di]
|
||
jmp do_normalize
|
||
;
|
||
dornd proc near
|
||
; round the number in the primary accumulator
|
||
mov di,flprm
|
||
mov ax,word ptr -12[di]
|
||
mov word ptr -12[di],0
|
||
cmp byte ptr -10[di],80H
|
||
mov byte ptr -10[di],0
|
||
jb rndexit
|
||
jne round_up
|
||
test ax,ax
|
||
jnz round_up
|
||
or byte ptr -9[di],1 ;round up on even, down on odd
|
||
ret
|
||
round_up:
|
||
add byte ptr -9[di],1
|
||
adc word ptr -8[di],0
|
||
adc word ptr -6[di],0
|
||
adc word ptr -4[di],0
|
||
cmp byte ptr -3[di],20h
|
||
jb rndexit
|
||
inc word ptr -2[di] ;bump exponent
|
||
shr word ptr -4[di],1 ;and re-normalize number
|
||
rcr word ptr -6[di],1
|
||
rcr word ptr -8[di],1
|
||
rcr word ptr -10[di],1
|
||
rndexit:
|
||
ret
|
||
dornd endp
|
||
;
|
||
intrdef $xtod
|
||
pushf
|
||
push bp
|
||
push si
|
||
push di
|
||
std
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,flprm
|
||
mov byte ptr [di],0 ;make sign positive
|
||
mov word ptr -2[di],1023+28 ;set exponent
|
||
test dx,dx
|
||
jns pos_long
|
||
neg dx
|
||
neg ax
|
||
sbb dx,0
|
||
mov byte ptr [di],80H ;make sign negative
|
||
pos_long:
|
||
sub di,4
|
||
xchg ax,dx
|
||
stos word ptr [di]
|
||
xchg ax,dx
|
||
stos word ptr [di]
|
||
sub ax,ax
|
||
stos word ptr [di]
|
||
stos word ptr [di]
|
||
stos word ptr [di]
|
||
jmp do_normalize
|
||
;
|
||
intrdef $dtou
|
||
intrdef $dtoi
|
||
intrdef $dtox
|
||
push si
|
||
push di
|
||
mov si,flprm
|
||
sub ax,ax
|
||
mov temp,ax
|
||
mov temp+2,ax
|
||
mov temp+4,ax
|
||
mov temp+6,ax
|
||
mov ax,word ptr -2[si]
|
||
sub ax,1023
|
||
js d2x_zero
|
||
cmp ax,54
|
||
jae d2x_zero
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,offset temp
|
||
sub bx,bx
|
||
mov cx,ax
|
||
mov ax,4
|
||
d2x_count:
|
||
sub cx,ax
|
||
jbe d2x_cdone
|
||
dec bx
|
||
mov ax,8
|
||
jmp d2x_count
|
||
d2x_cdone:
|
||
mov dl,byte ptr -3[si][bx]
|
||
mov byte ptr [di],dl
|
||
inc di
|
||
inc bx
|
||
jle d2x_cdone
|
||
neg cx
|
||
mov ax,temp
|
||
mov dx,temp+2
|
||
mov bx,temp+4 ;added 9/22/86 TTF to fix >29 bit converts
|
||
jcxz d2x_nshift
|
||
d2x_shift:
|
||
shr bx,1 ;added 9/22/86 TTF to fix >29 bit converts
|
||
rcr dx,1 ;chgd as above
|
||
rcr ax,1
|
||
loop d2x_shift
|
||
d2x_nshift:
|
||
test byte ptr [si],80H
|
||
jz d2x_ret
|
||
neg dx
|
||
neg ax
|
||
sbb dx,0
|
||
d2x_ret:
|
||
pop di
|
||
pop si
|
||
ret
|
||
|
||
d2x_zero:
|
||
sub ax,ax
|
||
sub dx,dx
|
||
pop di
|
||
pop si
|
||
ret
|
||
|
||
intrdef $dstat ; save floating state in buf es:bx
|
||
push si
|
||
push di
|
||
mov di,bx
|
||
mov si, offset flterr_ ; get start of data area
|
||
mov cx, offset lcnt1+1 ; get end of data area
|
||
sub cx, si ; get size
|
||
rep movs byte ptr [di], byte ptr [si] ; save floating state
|
||
pop di
|
||
pop si
|
||
ret
|
||
|
||
intrdef $drest ; restore floating state from buf es:bx
|
||
push si
|
||
push di
|
||
push ds
|
||
mov dx,ds ; swap segment registers
|
||
mov cx,es
|
||
mov ds,cx
|
||
mov es,dx
|
||
mov si,bx
|
||
mov di, offset flterr_ ; get start of data area
|
||
mov cx, offset lcnt1+1 ; get end of data area
|
||
sub cx, di ; get size
|
||
rep movs byte ptr [di], byte ptr [si] ; restore floating state
|
||
pop ds
|
||
pop di
|
||
pop si
|
||
ret
|
||
|
||
;
|
||
;
|
||
fault_handler:
|
||
pop di
|
||
pop si
|
||
pop bp
|
||
popf
|
||
ret
|
||
;
|
||
ifndef INTERNAL
|
||
$floats endp
|
||
finish
|
||
end
|
||
endif
|
||
sqrt87.asm
|
||
; Copyright (C) 1983 by Manx Software Systems
|
||
; :ts=8
|
||
include lmacros.h
|
||
|
||
dataseg segment word public 'data'
|
||
status dw ?
|
||
extrn chop_ctl:word, round_ctl:word
|
||
extrn errno_:word
|
||
dataseg ends
|
||
assume ds:dataseg
|
||
|
||
ERANGE equ -20
|
||
EDOM equ -21
|
||
|
||
procdef sqrt, <<doub,cdouble>>
|
||
;
|
||
; double sqrt(d)
|
||
;
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 40,doub ;fld qword ptr doub
|
||
wait
|
||
db 0d9h,0e4h ;ftst
|
||
wait
|
||
esc 47,status ;fstsw exponent
|
||
mov ah,byte ptr status+1
|
||
sahf
|
||
jnb sqrt_ok
|
||
wait
|
||
db 0d9h,0e0h ;fchs
|
||
mov errno_,EDOM
|
||
wait
|
||
sqrt_ok:
|
||
db 0d9h,0fah ;fsqrt
|
||
pret
|
||
pend sqrt
|
||
finish
|
||
end
|
||
frexp87.asm
|
||
; Copyright (C) 1983 by Manx Software Systems
|
||
; :ts=8
|
||
; the psuedo accumlators are formated as follows:
|
||
; -10 -8 -6 -4 -2 0
|
||
; |grd + LS ----- fraction ---- MS | exp | sign
|
||
;
|
||
; floating point system error codes:
|
||
UNDER_FLOW equ 1
|
||
OVER_FLOW equ 2
|
||
DIV_BY_ZERO equ 3
|
||
;
|
||
include lmacros.h
|
||
ifndef FARPROC
|
||
extrn $isnan:near
|
||
else
|
||
extrn $isnan:far
|
||
endif
|
||
|
||
dataseg segment word public 'data'
|
||
status dw ?
|
||
extrn chop_ctl:word, round_ctl:word
|
||
dataseg ends
|
||
assume ds:dataseg
|
||
|
||
procdef isnan,<<ddd,cdouble>>
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 40,ddd ;fld qword ptr 4[bp]
|
||
wait
|
||
call $isnan
|
||
pret
|
||
pend isnan
|
||
|
||
procdef frexp,<<d,cdouble>,<i,ptr>>
|
||
;
|
||
; frexp(d, &i)
|
||
; returns 0 <= x < 1
|
||
; such that: d = x * 2^i
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
db 0d9h,0e8h ;fld1
|
||
wait
|
||
db 0d9h,0e0h ;fchs
|
||
wait
|
||
esc 40,d ;fld qword ptr 4[bp]
|
||
wait
|
||
db 0d9h,0e4h ;ftst
|
||
wait
|
||
esc 47,status ;fstsw exponent
|
||
mov ah,byte ptr status+1
|
||
sahf
|
||
je zero
|
||
wait
|
||
db 0d9h,0f4h ;fxtract
|
||
wait
|
||
db 0d9h,0c9h ;fxch
|
||
wait
|
||
db 0d8h,0e2h ;fsub st,st(2)
|
||
ldptr bx,i,es
|
||
wait
|
||
ifdef LONGPTR
|
||
esc 59,es:[bx] ;fistp word ptr [bx]
|
||
else
|
||
esc 59,ds:[bx] ;fistp word ptr [bx]
|
||
endif
|
||
wait
|
||
db 0d9h,0fdh ;fscale
|
||
pret
|
||
zero:
|
||
ldptr bx,i,es
|
||
ifdef LONGPTR
|
||
mov es:word ptr [bx],0
|
||
else
|
||
mov ds:word ptr [bx],0
|
||
endif
|
||
pret
|
||
pend frexp
|
||
;
|
||
; ldexp(d, i)
|
||
; returns x = d * 2^i
|
||
procdef ldexp, <<dou,cdouble>,<ii,word>>
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 56,ii ;fild word ptr 12[bp]
|
||
wait
|
||
esc 40,dou ;fld qword ptr 4[bp]
|
||
wait
|
||
db 0d9h,0fdh ;fscale
|
||
pret
|
||
pend ldexp
|
||
;
|
||
; modf(d, dptr)
|
||
; returns fractional part of d, and
|
||
; stores integral part into *dptr
|
||
procdef modf, <<doub,cdouble>,<dptr,ptr>>
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 40,doub ;fld qword ptr 4[bp]
|
||
wait
|
||
db 0d9h,0c0h ;fld st(0)
|
||
wait
|
||
esc 13,chop_ctl ;fldcw chop_ctl
|
||
wait
|
||
db 0d9h,0fch ;frndint
|
||
ldptr bx,dptr,es
|
||
wait
|
||
esc 13,round_ctl ;fldcw round_ctl
|
||
wait
|
||
ifdef LONGPTR
|
||
esc 42,es:[bx] ;fst qword ptr [bx]
|
||
else
|
||
esc 42,ds:[bx] ;fst qword ptr [bx]
|
||
endif
|
||
wait
|
||
db 0deh,0e9h ;fsub
|
||
pret
|
||
pend modf
|
||
finish
|
||
end
|
||
fsubs87.asm
|
||
; Copyright (C) 1983 by Manx Software Systems
|
||
; page 54,130
|
||
; :ts=8
|
||
; floating point system error codes:
|
||
|
||
ifndef INTERNAL
|
||
include lmacros.h
|
||
UNDER_FLOW equ 1
|
||
OVER_FLOW equ 2
|
||
DIV_BY_ZERO equ 3
|
||
;
|
||
internal $floats
|
||
endif
|
||
|
||
dataseg segment word public 'data'
|
||
ifndef INTERNAL
|
||
public flterr_
|
||
flterr_ dw 0
|
||
endif
|
||
|
||
second db 8 dup (?)
|
||
work dw 4 dup (?)
|
||
status dw 0
|
||
public chop_ctl, round_ctl, rdown_ctl
|
||
chop_ctl dw 0fbfH ;control word for Chop mode
|
||
round_ctl dw 03bfH ;control word for Round nearest mode
|
||
rdown_ctl dw 07bfh ;control word for Round Down mode
|
||
dataseg ends
|
||
ifdef LONGPTR
|
||
assume ds:dataseg
|
||
else
|
||
assume ds:dataseg,es:dataseg,ss:dataseg
|
||
endif
|
||
ifdef FARPROC
|
||
frame equ 4
|
||
else
|
||
frame equ 2
|
||
endif
|
||
|
||
intrdef $isnan
|
||
wait
|
||
db 0d9h,0e5h ;fxam
|
||
wait
|
||
esc 47,status ;fstsw status
|
||
wait
|
||
mov ah,byte ptr status+1
|
||
and ah,047h
|
||
cmp ah,1
|
||
jz lnan
|
||
cmp ah,2
|
||
jz lnan
|
||
cmp ah,5
|
||
jz linf
|
||
cmp ah,7
|
||
jz linf
|
||
sub ax,ax
|
||
ret
|
||
lnan:
|
||
sub ax,ax
|
||
inc ax
|
||
ret
|
||
linf:
|
||
sub ax,ax
|
||
inc ax
|
||
inc ax
|
||
ret
|
||
|
||
intrdef $flds ;load single float into secondary accum
|
||
ifndef LONGPTR
|
||
mov ax,ds
|
||
mov es,ax
|
||
endif
|
||
wait
|
||
esc 8,es:[bx] ;fld dword ptr [bx]
|
||
wait
|
||
esc 43,second ;fstp qword ptr second
|
||
ret
|
||
|
||
ifdef LONGPTR
|
||
intrdef $fldsss ;load single float into secondary accum
|
||
wait
|
||
esc 8,ss:[bx] ;fld dword ptr [bx]
|
||
wait
|
||
esc 43,second ;fstp qword ptr second
|
||
ret
|
||
|
||
intrdef $fldsds ;load single float into secondary accum
|
||
wait
|
||
esc 8,ds:[bx] ;fld dword ptr [bx]
|
||
wait
|
||
esc 43,second ;fstp qword ptr second
|
||
ret
|
||
endif
|
||
;
|
||
intrdef $fldp ;load single float into primary accum
|
||
ifndef LONGPTR
|
||
mov ax,ds
|
||
mov es,ax
|
||
endif
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 8,es:[bx] ;fld dword ptr [bx]
|
||
ret
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $fldpss ;load single float into primary accum
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 8,ss:[bx] ;fld dword ptr [bx]
|
||
ret
|
||
;
|
||
intrdef $fldpds ;load single float into primary accum
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 8,ds:[bx] ;fld dword ptr [bx]
|
||
ret
|
||
endif
|
||
;
|
||
intrdef $fst ;store single at addr in BX
|
||
ifndef LONGPTR
|
||
mov ax,ds
|
||
mov es,ax
|
||
endif
|
||
wait
|
||
esc 10,es:[bx] ;fst dword ptr [bx]
|
||
wait
|
||
ret
|
||
;
|
||
intrdef $fsts ;store single at addr in BX
|
||
ifndef LONGPTR
|
||
mov ax,ds
|
||
mov es,ax
|
||
endif
|
||
; wait
|
||
; esc 40,second ;fld qword ptr second
|
||
;; wait
|
||
; db 0d9h,0c9h ;fxch
|
||
; wait
|
||
; esc 43,second ;fstp qword ptr second
|
||
; wait
|
||
; esc 10,es:[bx] ;fst dword ptr [bx]
|
||
; wait
|
||
; esc 40,second ;fld qword ptr second
|
||
; wait
|
||
; db 0d9h,0c9h ;fxch
|
||
; wait
|
||
; esc 43,second ;fstp qword ptr second
|
||
wait
|
||
esc 40,second ;fld qword ptr second
|
||
wait
|
||
esc 43,es:[bx] ;fstp dword ptr [bx]
|
||
ret
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $fstss ;store single at addr in BX
|
||
wait
|
||
esc 10,ss:[bx] ;fst dword ptr [bx]
|
||
wait
|
||
ret
|
||
;
|
||
intrdef $fstsds ;store single at addr in BX
|
||
; wait
|
||
; esc 40,second ;fld qword ptr second
|
||
; wait
|
||
; db 0d9h,0c9h ;fxch
|
||
; wait
|
||
; esc 43,second ;fstp qword ptr second
|
||
; wait
|
||
; esc 10,ds:[bx] ;fst dword ptr [bx]
|
||
; wait
|
||
; esc 40,second ;fld qword ptr second
|
||
; wait
|
||
; db 0d9h,0c9h ;fxch
|
||
; wait
|
||
; esc 43,second ;fstp qword ptr second
|
||
wait
|
||
esc 40,second ;fld qword ptr second
|
||
wait
|
||
esc 43,ds:[bx] ;fstp dword ptr [bx]
|
||
ret
|
||
|
||
intrdef $fstsss ;store single at addr in BX
|
||
; wait
|
||
; esc 40,second ;fld qword ptr second
|
||
; wait
|
||
; db 0d9h,0c9h ;fxch
|
||
; wait
|
||
; esc 43,second ;fstp qword ptr second
|
||
; wait
|
||
; esc 10,ss:[bx] ;fst dword ptr [bx]
|
||
; wait
|
||
; esc 40,second ;fld qword ptr second
|
||
; wait
|
||
; db 0d9h,0c9h ;fxch
|
||
; wait
|
||
; esc 43,second ;fstp qword ptr second
|
||
wait
|
||
esc 40,second ;fld qword ptr second
|
||
wait
|
||
esc 43,ds:[bx] ;fstp dword ptr [bx]
|
||
ret
|
||
;
|
||
intrdef $fstds ;store single at addr in BX
|
||
wait
|
||
esc 10,ds:[bx] ;fst dword ptr [bx]
|
||
wait
|
||
ret
|
||
endif
|
||
;
|
||
intrdef $dlis ;load double immediate secondary
|
||
pop bx
|
||
ifdef FARPROC
|
||
pop dx
|
||
endif
|
||
push di
|
||
push si
|
||
mov di,ds
|
||
mov es,di
|
||
mov di,offset second
|
||
mov si,bx ;get return addr
|
||
mov cx,4
|
||
ifdef FARPROC
|
||
push ds
|
||
mov ds,dx
|
||
lis_lp: ;8086 doesn't handle double prefixes
|
||
movs word ptr [di], word ptr [si]
|
||
else
|
||
lis_lp: ;8086 doesn't handle double prefixes
|
||
movs word ptr [di], cs:word ptr [si]
|
||
endif
|
||
loop lis_lp
|
||
mov bx,si
|
||
ifdef FARPROC
|
||
pop ds
|
||
endif
|
||
pop si
|
||
pop di
|
||
ifdef FARPROC
|
||
push dx
|
||
push bx
|
||
ret
|
||
else
|
||
jmp bx
|
||
endif
|
||
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $dldsss
|
||
mov cx,ss
|
||
mov es,cx
|
||
jmp dodlds
|
||
|
||
intrdef $dldsds
|
||
push di
|
||
push si
|
||
push ds
|
||
mov cx,ds
|
||
mov es,cx
|
||
jmp dodldsx
|
||
endif
|
||
intrdef $dlds ;load double float into secondary accum
|
||
dodlds:
|
||
push di
|
||
push si
|
||
ifdef LONGPTR
|
||
push ds
|
||
mov di,ds
|
||
mov si,es
|
||
mov ds,si
|
||
mov es,di
|
||
else
|
||
mov di,ds
|
||
mov es,di
|
||
endif
|
||
dodldsx:
|
||
mov di,offset second
|
||
mov si,bx
|
||
mov cx,4
|
||
rep movsw
|
||
popds
|
||
pop si
|
||
pop di
|
||
ret
|
||
;
|
||
intrdef $dlip ;load double immediate primary
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
pop bx
|
||
ifdef FARPROC
|
||
ifndef LONGPTR
|
||
mov cx,es
|
||
endif
|
||
pop es
|
||
wait
|
||
esc 40,es:[bx] ;fld cs:qword ptr [bx]
|
||
add bx,8
|
||
push es
|
||
push bx
|
||
ifndef LONGPTR
|
||
mov es,cx
|
||
endif
|
||
ret
|
||
else
|
||
wait
|
||
esc 40,cs:[bx] ;fld cs:qword ptr [bx]
|
||
add bx,8
|
||
jmp bx
|
||
endif
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $dldpss ;load double float into primary accum
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 40,ss:[bx] ;fld qword ptr [bx]
|
||
ret
|
||
|
||
intrdef $dldpds ;load double float into primary accum
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 40,ds:[bx] ;fld qword ptr [bx]
|
||
ret
|
||
endif
|
||
intrdef $dldp ;load double float into primary accum
|
||
ifndef LONGPTR
|
||
mov ax,ds
|
||
mov es,ax
|
||
endif
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 40,es:[bx] ;fld qword ptr [bx]
|
||
ret
|
||
;
|
||
intrdef $dsts
|
||
wait
|
||
esc 40,second ;fld qword ptr second
|
||
wait
|
||
db 0d9h,0c9h ;fxch
|
||
wait
|
||
esc 43,second ;fstp qword ptr second
|
||
call $dst
|
||
wait
|
||
esc 40,second ;fld qword ptr second
|
||
wait
|
||
db 0d9h,0c9h ;fxch
|
||
wait
|
||
esc 43,second ;fstp qword ptr second
|
||
wait
|
||
ret
|
||
|
||
intrdef $dst ;store double at addr in BX
|
||
ifndef LONGPTR
|
||
mov ax,ds
|
||
mov es,ax
|
||
endif
|
||
wait
|
||
esc 42,es:[bx] ;fst qword ptr [bx]
|
||
wait
|
||
ret
|
||
ifdef LONGPTR
|
||
intrdef $dstss ;store double at addr in BX
|
||
wait
|
||
esc 42,ss:[bx] ;fst qword ptr [bx]
|
||
wait
|
||
ret
|
||
|
||
intrdef $dstds ;store double at addr in BX
|
||
wait
|
||
esc 42,ds:[bx] ;fst qword ptr [bx]
|
||
wait
|
||
ret
|
||
|
||
intrdef $dstsss ;store double at addr in BX
|
||
wait
|
||
esc 40,second ;fld qword ptr second
|
||
wait
|
||
db 0d9h,0c9h ;fxch
|
||
wait
|
||
esc 43,second ;fstp qword ptr second
|
||
wait
|
||
esc 42,ss:[bx] ;fst qword ptr [bx]
|
||
wait
|
||
esc 40,second ;fld qword ptr second
|
||
wait
|
||
db 0d9h,0c9h ;fxch
|
||
wait
|
||
esc 43,second ;fstp qword ptr second
|
||
ret
|
||
|
||
intrdef $dstsds ;store double at addr in BX
|
||
wait
|
||
esc 40,second ;fld qword ptr second
|
||
wait
|
||
db 0d9h,0c9h ;fxch
|
||
wait
|
||
esc 43,second ;fstp qword ptr second
|
||
wait
|
||
esc 42,ds:[bx] ;fst qword ptr [bx]
|
||
wait
|
||
esc 40,second ;fld qword ptr second
|
||
wait
|
||
db 0d9h,0c9h ;fxch
|
||
wait
|
||
esc 43,second ;fstp qword ptr second
|
||
ret
|
||
endif
|
||
;
|
||
intrdef $dpsh ;push double float onto the stack
|
||
;from the primary accumulator
|
||
pop ax ;fetch return address
|
||
ifdef FARPROC
|
||
pop dx
|
||
endif
|
||
sub sp,8 ;make room for double on stack
|
||
mov bx,sp ;address of place to store
|
||
ifdef FARPROC
|
||
push dx
|
||
endif
|
||
push ax ;put return address back
|
||
ifdef LONGPTR
|
||
jmp $dstss
|
||
else
|
||
jmp $dst
|
||
endif
|
||
;
|
||
intrdef $dpshs ;push double float onto the stack
|
||
;from the primary accumulator
|
||
pop ax ;fetch return address
|
||
ifdef FARPROC
|
||
pop dx
|
||
endif
|
||
sub sp,8 ;make room for double on stack
|
||
mov bx,sp ;address of place to store
|
||
ifdef FARPROC
|
||
push dx
|
||
endif
|
||
push ax ;put return address back
|
||
ifdef LONGPTR
|
||
jmp $dstsss
|
||
else
|
||
jmp $dsts
|
||
endif
|
||
intrdef $dpopp ;pop double float into secondary accum
|
||
push bx
|
||
push es
|
||
mov bx,sp
|
||
add bx,frame+4 ;address of data to load
|
||
ifdef LONGPTR
|
||
call $dldpss
|
||
else
|
||
call $dldp
|
||
endif
|
||
pop es
|
||
pop bx
|
||
ret 8 ;return and de-allocate space
|
||
;
|
||
intrdef $dpop ;pop double float into secondary accum
|
||
push bx
|
||
push es
|
||
mov bx,sp
|
||
add bx,frame+4 ;address of data to load
|
||
ifdef LONGPTR
|
||
call $dldsss
|
||
else
|
||
call $dlds
|
||
endif
|
||
pop es
|
||
pop bx
|
||
ret 8 ;return and de-allocate space
|
||
;
|
||
intrdef $dswap ;exchange primary and secondary
|
||
wait
|
||
esc 40,second ;fld qword ptr second
|
||
wait
|
||
db 0d9h,0c9h ;fxch
|
||
wait
|
||
esc 43,second ;fstp qword ptr second
|
||
ret
|
||
;
|
||
intrdef $dng ;negate primary
|
||
wait
|
||
db 0d9h,0e0h ;fchs
|
||
ret
|
||
;
|
||
intrdef $dtst ;test if primary is zero
|
||
wait
|
||
db 0d9h,0e4h ;ftst
|
||
wait
|
||
esc 47,status ;fstsw status
|
||
wait
|
||
mov ah,byte ptr status+1
|
||
sahf
|
||
jne ltrue
|
||
sub ax,ax
|
||
ret
|
||
ltrue:
|
||
sub ax,ax
|
||
inc ax
|
||
ret
|
||
;
|
||
intrdef $dcmp ;compare primary and secondary
|
||
wait
|
||
esc 34,second ;fcom qword ptr second
|
||
wait
|
||
esc 47,status ;fstsw status
|
||
wait
|
||
mov ah,byte ptr status+1
|
||
sahf
|
||
jb lp_lt_s
|
||
ja lp_gt_s
|
||
;return 0 if p == s
|
||
xor ax,ax
|
||
ret
|
||
;return 0 if p == s
|
||
lp_lt_s: ;return < 0 if p < s
|
||
xor ax,ax
|
||
dec ax
|
||
ret
|
||
;
|
||
lp_gt_s: ; > 0 if p > s
|
||
xor ax,ax
|
||
inc ax
|
||
ret
|
||
;
|
||
intrdef $dsb ;subtract secondary from primary
|
||
wait
|
||
esc 36,second ;fsub qword ptr second
|
||
ret
|
||
;
|
||
intrdef $dad ;add secondary to primary
|
||
wait
|
||
esc 32,second ;fadd qword ptr second
|
||
ret
|
||
;
|
||
intrdef $ddv
|
||
;double floating divide (primary = primary/secondary)
|
||
wait
|
||
esc 38,second ;fdiv qword ptr second
|
||
ret
|
||
;
|
||
intrdef $dml
|
||
;double floating multiply (primary = primary * secondary)
|
||
wait
|
||
esc 33,second ;fmul qword ptr second
|
||
ret
|
||
;
|
||
intrdef $utod
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
mov work,ax
|
||
mov work+2,0
|
||
wait
|
||
esc 24,work ;fild dword ptr work
|
||
ret
|
||
;
|
||
intrdef $itod
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
mov work,ax
|
||
wait
|
||
esc 56,work ;fild word ptr work
|
||
ret
|
||
;
|
||
intrdef $xtod
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
mov work,ax
|
||
mov work+2,dx
|
||
wait
|
||
esc 24,work ;fild dword ptr work
|
||
ret
|
||
;
|
||
intrdef $dtou
|
||
intrdef $dtoi
|
||
intrdef $dtox
|
||
wait
|
||
esc 13,chop_ctl ;fldcw chop_ctl
|
||
wait
|
||
esc 26,work ;fist dword ptr work
|
||
wait
|
||
esc 13,round_ctl ;fldcw round_ctl
|
||
mov ax,work
|
||
mov dx,work+2
|
||
ret
|
||
|
||
intrdef $dstat ; save floating state in buf es:bx
|
||
push si
|
||
push di
|
||
push ds
|
||
mov di,bx
|
||
mov si,offset flterr_ ;get start of data
|
||
mov cx,offset status+2 ;get end of data
|
||
sub cx,si ;get size
|
||
add bx,cx ;save end
|
||
rep movs byte ptr [di], byte ptr [si] ; save data
|
||
mov cx,es
|
||
mov ds,cx
|
||
esc 101110b,[bx] ; save floating state (acts like finit)
|
||
wait
|
||
esc 101100b,[bx] ; restore floating state
|
||
pop ds
|
||
pop di
|
||
pop si
|
||
ret
|
||
|
||
intrdef $drest ; restore floating state from buf es:bx
|
||
push si
|
||
push di
|
||
push ds
|
||
mov si,bx
|
||
mov cx,es ; swap segment registers
|
||
mov dx,ds
|
||
mov es,dx
|
||
mov ds,cx
|
||
mov di,offset flterr_ ;get start of data
|
||
mov cx,offset status+2 ;get end of data
|
||
sub cx,di ;get size
|
||
add bx,cx ;save end
|
||
rep movs byte ptr [di], byte ptr [si] ; save data
|
||
esc 101100b,[bx] ; restore floating state
|
||
wait
|
||
pop ds
|
||
pop di
|
||
pop si
|
||
ret
|
||
|
||
ifndef INTERNAL
|
||
$floats endp
|
||
finish
|
||
end
|
||
endif
|
||
frexp87s.asm
|
||
; Copyright (C) 1983 by Manx Software Systems
|
||
; :ts=8
|
||
; the psuedo accumlators are formated as follows:
|
||
; -10 -8 -6 -4 -2 0
|
||
; |grd + LS ----- fraction ---- MS | exp | sign
|
||
;
|
||
; floating point system error codes:
|
||
UNDER_FLOW equ 1
|
||
OVER_FLOW equ 2
|
||
DIV_BY_ZERO equ 3
|
||
;
|
||
include lmacros.h
|
||
dataseg segment word public 'data'
|
||
dw 5 dup (?)
|
||
temp dw ?
|
||
extrn flprm:word,flsec:word
|
||
extrn flterr_:word
|
||
status dw ?
|
||
extrn $flt_inx:word,chop_ctl:word, round_ctl:word
|
||
dataseg ends
|
||
assume ds:dataseg
|
||
|
||
ifdef FARPROC
|
||
extrn $dldp:far, $dst:far, $itod:far
|
||
extrn $dad:far, $dsb:far, $isnan:far
|
||
else
|
||
extrn $dldp:near, $dst:near, $itod:near
|
||
extrn $dad:near, $dsb:near, $isnan:near
|
||
endif
|
||
procdef isnan,<<ddd,cdouble>>
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
lea bx,ddd ;compute address of first argument
|
||
call $dldp ;load it into the float primary
|
||
call $isnan
|
||
pret
|
||
pend isnan
|
||
|
||
procdef frexp, <<d,cdouble>,<i,ptr>>
|
||
;
|
||
; frexp(d, &i)
|
||
; returns 0 <= x < 1
|
||
; such that: d = x * 2^i
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
lea bx,d ;compute address of first argument
|
||
call $dldp ;load it into the float primary
|
||
mov cx,$flt_inx
|
||
or cx,cx
|
||
jnz $frexp87
|
||
mov bx,flprm
|
||
mov ax,word ptr -2[bx] ;fetch current exponent value
|
||
test ax,ax
|
||
jnz fr_nzero
|
||
ldptr bx,i,es ;get pointer
|
||
ifdef LONGPTR
|
||
mov es:word ptr [bx],0
|
||
else
|
||
mov ds:word ptr [bx],0
|
||
endif
|
||
pret
|
||
fr_nzero:
|
||
sub ax,1022
|
||
mov word ptr -2[bx],1022
|
||
ldptr bx,i,es ;get pointer
|
||
ifdef LONGPTR
|
||
mov es:word ptr [bx],ax
|
||
else
|
||
mov ds:word ptr [bx],ax
|
||
endif
|
||
pret
|
||
$frexp87:
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
db 0d9h,0e8h ;fld1
|
||
wait
|
||
db 0d9h,0e0h ;fchs
|
||
wait
|
||
esc 40,d ;fld qword ptr 4[bp]
|
||
wait
|
||
db 0d9h,0e4h ;ftst
|
||
wait
|
||
esc 47,status ;fstsw exponent
|
||
mov ah,byte ptr status+1
|
||
sahf
|
||
je zero
|
||
wait
|
||
db 0d9h,0f4h ;fxtract
|
||
wait
|
||
db 0d9h,0c9h ;fxch
|
||
wait
|
||
db 0d8h,0e2h ;fsub st,st(2)
|
||
ldptr bx,i,es
|
||
wait
|
||
ifdef LONGPTR
|
||
esc 59,es:[bx] ;fistp word ptr [bx]
|
||
else
|
||
esc 59,ds:[bx] ;fistp word ptr [bx]
|
||
endif
|
||
wait
|
||
db 0d9h,0fdh ;fscale
|
||
pret
|
||
zero:
|
||
ldptr bx,i,es
|
||
ifdef LONGPTR
|
||
mov es:word ptr [bx],0
|
||
else
|
||
mov ds:word ptr [bx],0
|
||
endif
|
||
pret
|
||
pend frexp
|
||
;
|
||
; ldexp(d, i)
|
||
; returns x = d * 2^i
|
||
procdef ldexp, <<dou,cdouble>,<ii,word>>
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
lea bx,dou ;compute address of first argument
|
||
call $dldp ;load it into the float primary
|
||
mov cx,$flt_inx
|
||
or cx,cx
|
||
jnz $ldexp87
|
||
mov bx,flprm
|
||
mov ax,word ptr -2[bx] ;fetch current exponent value
|
||
test ax,ax
|
||
jz ld_zero
|
||
add ax,ii ;add i to exponent
|
||
js ld_underflow
|
||
cmp ax,2048
|
||
jl ld_ret
|
||
mov flterr_,UNDER_FLOW
|
||
mov ax,2047
|
||
ld_ret:
|
||
mov word ptr -2[bx],ax
|
||
ld_zero:
|
||
pret
|
||
;
|
||
ld_underflow:
|
||
mov flterr_,UNDER_FLOW
|
||
sub ax,ax
|
||
jmp ld_ret
|
||
$ldexp87:
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 56,ii ;fild word ptr 12[bp]
|
||
wait
|
||
esc 40,dou ;fld qword ptr 4[bp]
|
||
wait
|
||
db 0d9h,0fdh ;fscale
|
||
pret
|
||
pend ldexp
|
||
;
|
||
; modf(d, dptr)
|
||
; returns fractional part of d, and
|
||
; stores integral part into *dptr
|
||
procdef modf,<<doubl,cdouble>,<dptr,ptr>>
|
||
push di
|
||
push si
|
||
pushds
|
||
ifdef LONGPTR
|
||
mov bx,ss
|
||
mov es,bx
|
||
endif
|
||
lea bx,doubl ;compute address of first argument
|
||
call $dldp ;load it into the float primary
|
||
mov cx,$flt_inx
|
||
or cx,cx
|
||
jz around
|
||
jmp $modf87
|
||
around:
|
||
std
|
||
mov bx,flprm
|
||
mov ax,word ptr -2[bx] ;fetch current exponent value
|
||
test ax,ax
|
||
jnz mf_nzero
|
||
ldptr bx,dptr,es ;get pointer
|
||
call $dst
|
||
mf_return:
|
||
cld
|
||
popds
|
||
pop si
|
||
pop di
|
||
pret
|
||
mf_nzero:
|
||
mov di,ds
|
||
mov es,di
|
||
mov si,bx
|
||
mov di,offset temp
|
||
mov cx,6 ;save value for fraction part later
|
||
rep movsw
|
||
sub ax,1023
|
||
jns int_notzero
|
||
mov ax,0
|
||
call $itod
|
||
jmp get_fraction
|
||
int_notzero:
|
||
cmp ax,52
|
||
jna mf_frac
|
||
;fraction is zero
|
||
ldptr bx,dptr,es ;get pointer
|
||
call $dst ;store integer part away
|
||
sub ax,ax
|
||
call $itod
|
||
jmp mf_return
|
||
mf_frac:
|
||
sub di,di
|
||
mov cx,ax
|
||
mov ax,4
|
||
mf_count:
|
||
sub cx,ax
|
||
jbe mf_cdone
|
||
dec di
|
||
mov ax,8
|
||
jmp mf_count
|
||
mf_cdone:
|
||
jcxz no_shift
|
||
neg cx
|
||
mov al,byte ptr -3[bx][di]
|
||
shr al,cl
|
||
shl al,cl
|
||
mov byte ptr -3[bx][di],al
|
||
no_shift:
|
||
dec di
|
||
zap_loop:
|
||
cmp di,-8
|
||
jle get_fraction
|
||
mov byte ptr -3[bx][di],0
|
||
dec di
|
||
jmp zap_loop
|
||
get_fraction:
|
||
ldptr bx,dptr,es ;get pointer
|
||
call $dst ;store integer part away
|
||
std
|
||
popds
|
||
pushds
|
||
mov di,flprm
|
||
xchg di,flsec
|
||
mov flprm,di
|
||
mov si,ds
|
||
mov es,si
|
||
mov si,offset temp
|
||
mov cx,6 ;restore original value
|
||
rep movsw
|
||
call $dsb ;compute fractional part
|
||
jmp mf_return
|
||
$modf87:
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 40,doubl ;fld qword ptr 4[bp]
|
||
wait
|
||
db 0d9h,0c0h ;fld st(0)
|
||
wait
|
||
esc 13,chop_ctl ;fldcw chop_ctl
|
||
wait
|
||
db 0d9h,0fch ;frndint
|
||
ldptr bx,dptr,es
|
||
wait
|
||
esc 13,round_ctl ;fldcw round_ctl
|
||
wait
|
||
ifdef LONGPTR
|
||
esc 42,es:[bx] ;fst qword ptr [bx]
|
||
else
|
||
esc 42,ds:[bx] ;fst qword ptr [bx]
|
||
endif
|
||
wait
|
||
db 0deh,0e9h ;fsub
|
||
popds
|
||
pop si
|
||
pop di
|
||
pret
|
||
pend modf
|
||
finish
|
||
end
|
||
sqrt87s.asm
|
||
include lmacros.h
|
||
dataseg segment para public 'data'
|
||
status dw ?
|
||
extrn chop_ctl:word, round_ctl:word
|
||
extrn errno_:word
|
||
extrn $flt_inx:word
|
||
dataseg ends
|
||
assume ds:dataseg
|
||
;#include "math.h"
|
||
;#include "errno.h"
|
||
ifdef FARPROC
|
||
OFFS equ 2
|
||
else
|
||
OFFS equ 0
|
||
endif
|
||
;
|
||
ifndef LONGPTR
|
||
$dldsss equ $dlds
|
||
$dldpss equ $dldp
|
||
$dstss equ $dst
|
||
$dldsds equ $dlds
|
||
$dldpds equ $dldp
|
||
$dstds equ $dst
|
||
$fldsss equ $flds
|
||
$fldpss equ $fldp
|
||
$fstss equ $fst
|
||
$fldsds equ $flds
|
||
$fldpds equ $fldp
|
||
$fstds equ $fst
|
||
endif
|
||
;double sqrt(x)
|
||
;double x;
|
||
procdef sqrt, <<doub,cdouble>>
|
||
lea bx,doub
|
||
call $dldpss
|
||
mov cx,$flt_inx
|
||
or cx,cx
|
||
jz $sqrt86
|
||
;
|
||
;
|
||
|
||
ERANGE equ -20
|
||
EDOM equ -21
|
||
|
||
$sqrt87:
|
||
wait
|
||
db 0dbh,0e3h ;finit
|
||
wait
|
||
esc 40,ss:4+OFFS[bp] ;fld qword ptr 4+OFFS[bp]
|
||
wait
|
||
db 0d9h,0e4h ;ftst
|
||
wait
|
||
esc 47,status ;fstsw exponent
|
||
mov ah,byte ptr status+1
|
||
sahf
|
||
jnb sqrt_ok
|
||
wait
|
||
db 0d9h,0e0h ;fchs
|
||
mov errno_,EDOM
|
||
wait
|
||
sqrt_ok:
|
||
db 0d9h,0fah ;fsqrt
|
||
pret sqrt
|
||
;
|
||
$sqrt86:
|
||
;
|
||
;{
|
||
; double f, y;
|
||
; int n;
|
||
; extern int errno;
|
||
add sp,$2
|
||
push di
|
||
push si
|
||
;
|
||
; if (x == 0.0)
|
||
; return x;
|
||
call $dlis
|
||
db 00H,00H,00H,00H,00H,00H,00H,00H
|
||
call $dcmp
|
||
jne $3
|
||
lea bx,doub
|
||
call $dldpss
|
||
jmp $cret
|
||
; if (x < 0.0) {
|
||
$3:
|
||
lea bx,doub
|
||
call $dldpss
|
||
call $dlis
|
||
db 00H,00H,00H,00H,00H,00H,00H,00H
|
||
call $dcmp
|
||
jge $4
|
||
; errno = EDOM;
|
||
mov word ptr errno_,22
|
||
; return 0.0;
|
||
call $dlip
|
||
db 00H,00H,00H,00H,00H,00H,00H,00H
|
||
|
||
jmp $cret
|
||
; }
|
||
; f = frexp(x, &n);
|
||
$4:
|
||
lea ax,word ptr -18[bp]
|
||
ifdef LONGPTR
|
||
push ss
|
||
endif
|
||
push ax
|
||
lea bx,doub
|
||
call $dldpss
|
||
call $dpsh
|
||
call frexp_
|
||
ifdef LONGPTR
|
||
add sp,12
|
||
else
|
||
add sp,10
|
||
endif
|
||
lea bx,word ptr -8[bp]
|
||
call $dstss
|
||
; y = 0.41731 + 0.59016 * f;
|
||
lea bx,word ptr -8[bp]
|
||
call $dldpss
|
||
call $dlis
|
||
db 018H,09H,06dH,039H,097H,0e2H,0e2H,03fH
|
||
call $dml
|
||
call $dlis
|
||
db 0f7H,0ccH,092H,00H,035H,0b5H,0daH,03fH
|
||
call $dad
|
||
lea bx,word ptr -16[bp]
|
||
call $dstss
|
||
; y = (y + f/y);
|
||
lea bx,word ptr -8[bp]
|
||
call $dldpss
|
||
lea bx,word ptr -16[bp]
|
||
call $dldsss
|
||
call $ddv
|
||
lea bx,word ptr -16[bp]
|
||
call $dldsss
|
||
call $dad
|
||
lea bx,word ptr -16[bp]
|
||
call $dstss
|
||
; y = ldexp(y,-2) + f/y; /* fast calculation of y2 */
|
||
mov ax,-2
|
||
push ax
|
||
lea bx,word ptr -16[bp]
|
||
call $dldpss
|
||
call $dpsh
|
||
call ldexp_
|
||
add sp,10
|
||
call $dpsh
|
||
lea bx,word ptr -8[bp]
|
||
call $dldpss
|
||
lea bx,word ptr -16[bp]
|
||
call $dldsss
|
||
call $ddv
|
||
call $dpop
|
||
call $dad
|
||
lea bx,word ptr -16[bp]
|
||
call $dstss
|
||
; y = ldexp(y + f/y, -1);
|
||
mov ax,-1
|
||
push ax
|
||
lea bx,word ptr -8[bp]
|
||
call $dldpss
|
||
lea bx,word ptr -16[bp]
|
||
call $dldsss
|
||
call $ddv
|
||
lea bx,word ptr -16[bp]
|
||
call $dldsss
|
||
call $dad
|
||
call $dpsh
|
||
call ldexp_
|
||
add sp,10
|
||
lea bx,word ptr -16[bp]
|
||
call $dstss
|
||
; y = ldexp(y + f/y, -1);
|
||
mov ax,-1
|
||
push ax
|
||
lea bx,word ptr -8[bp]
|
||
call $dldpss
|
||
lea bx,word ptr -16[bp]
|
||
call $dldsss
|
||
call $ddv
|
||
lea bx,word ptr -16[bp]
|
||
call $dldsss
|
||
call $dad
|
||
call $dpsh
|
||
call ldexp_
|
||
add sp,10
|
||
lea bx,word ptr -16[bp]
|
||
call $dstss
|
||
;
|
||
; if (n&1) {
|
||
mov ax,word ptr -18[bp]
|
||
test ax,1
|
||
jeq $5
|
||
; y *= 0.70710678118654752440;
|
||
lea bx,word ptr -16[bp]
|
||
call $dldpss
|
||
call $dlis
|
||
db 0cdH,03bH,07fH,066H,09eH,0a0H,0e6H,03fH
|
||
call $dml
|
||
lea bx,word ptr -16[bp]
|
||
call $dstss
|
||
; ++n;
|
||
inc word ptr -18[bp]
|
||
; }
|
||
; return ldexp(y,n/2);
|
||
$5:
|
||
mov ax,word ptr -18[bp]
|
||
mov cx,2
|
||
cwd
|
||
idiv cx
|
||
push ax
|
||
lea bx,word ptr -16[bp]
|
||
call $dldpss
|
||
call $dpsh
|
||
call ldexp_
|
||
add sp,10
|
||
jmp $cret
|
||
|
||
$cret:
|
||
pop si
|
||
pop di
|
||
mov sp,bp
|
||
pop bp
|
||
ret
|
||
;}
|
||
$2 = -18
|
||
;
|
||
ifdef FARPROC
|
||
extrn frexp_:far
|
||
extrn ldexp_:far
|
||
extrn $dad:far,$dsb:far,$dml:far,$ddv:far
|
||
extrn $dldp:far,$dlds:far,$dlip:far,$dlis:far,$dst:far
|
||
extrn $fldp:far,$flds:far,$fst:far,$dcmp:far,$dtst:far
|
||
extrn $dpsh:far,$dpopp:far,$dpop:far,$dng:far,$dswap:far
|
||
extrn $itod:far,$utod:far,$xtod:far
|
||
extrn $dtoi:far,$dtou:far,$dtox:far
|
||
else
|
||
extrn frexp_:near
|
||
extrn ldexp_:near
|
||
extrn $dad:near,$dsb:near,$dml:near,$ddv:near
|
||
extrn $dldp:near,$dlds:near,$dlip:near,$dlis:near,$dst:near
|
||
extrn $fldp:near,$flds:near,$fst:near,$dcmp:near,$dtst:near
|
||
extrn $dpsh:near,$dpopp:near,$dpop:near,$dng:near,$dswap:near
|
||
extrn $itod:near,$utod:near,$xtod:near
|
||
extrn $dtoi:near,$dtou:near,$dtox:near
|
||
endif
|
||
ifdef LONGPTR
|
||
ifdef FARPROC
|
||
extrn $dldpss:far,$dldsss:far,$dstss:far
|
||
extrn $dldpds:far,$dldsds:far,$dstds:far
|
||
extrn $fldpss:far,$fldsss:far,$fstss:far
|
||
extrn $fldpds:far,$fldsds:far,$fstds:far
|
||
else
|
||
extrn $dldpss:near,$dldsss:near,$dstss:near
|
||
extrn $dldpds:near,$dldsds:near,$dstds:near
|
||
extrn $fldpss:near,$fldsss:near,$fstss:near
|
||
extrn $fldpds:near,$fldsds:near,$fstds:near
|
||
endif
|
||
endif
|
||
pend sqrt
|
||
dataseg segment para public 'data'
|
||
extrn errno_:word
|
||
dataseg ends
|
||
end
|
||
fsubs87s.asm
|
||
; Copyright (C) 1983 by Manx Software Systems
|
||
; page 54,130
|
||
; :ts=8
|
||
; floating point system error codes:
|
||
include lmacros.h
|
||
|
||
internal $floats
|
||
|
||
UNDER_FLOW equ 1
|
||
OVER_FLOW equ 2
|
||
DIV_BY_ZERO equ 3
|
||
;
|
||
public flterr_
|
||
dataseg segment para public 'data'
|
||
public $flt_inx
|
||
$flt_inx dw 0 ; 8087/software emulation switch index
|
||
flterr_ dw 0
|
||
dataseg ends
|
||
|
||
ifdef LONGPTR
|
||
assume ds:dataseg
|
||
else
|
||
assume ds:dataseg,es:dataseg,ss:dataseg
|
||
endif
|
||
|
||
ifdef FARPROC
|
||
CALLSZ equ 5
|
||
else
|
||
CALLSZ equ 3
|
||
endif
|
||
|
||
dataseg segment para public 'data'
|
||
$flttb86: ; 8086 software indirection table
|
||
dw $isnan86
|
||
dw $flds86
|
||
dw $fldp86
|
||
dw $fst86
|
||
dw $fsts86
|
||
dw $dlis86
|
||
dw $dlds86
|
||
dw $dlip86
|
||
dw $dldp86
|
||
dw $dst86
|
||
dw $dsts86
|
||
dw $dpsh86
|
||
dw $dpshs86
|
||
dw $dpop86
|
||
dw $dpopp86
|
||
dw $dswap86
|
||
dw $dng86
|
||
dw $dtst86
|
||
dw $dcmp86
|
||
dw $dsb86
|
||
dw $dad86
|
||
dw $ddv86
|
||
dw $dml86
|
||
dw $utod86
|
||
dw $itod86
|
||
dw $xtod86
|
||
dw $dtoi86
|
||
dw $dstat86
|
||
dw $drest86
|
||
ifdef LONGPTR
|
||
dw $fldsss86
|
||
dw $fldsds86
|
||
dw $fldpss86
|
||
dw $fldpds86
|
||
dw $fstss86
|
||
dw $fstds86
|
||
dw $fstsss86
|
||
dw $fstsds86
|
||
dw $dldsss86
|
||
dw $dldsds86
|
||
dw $dldpss86
|
||
dw $dldpds86
|
||
dw $dstss86
|
||
dw $dstds86
|
||
dw $dstsss86
|
||
dw $dstsds86
|
||
endif
|
||
|
||
$flttb87: ; 8087 hardware indirection table
|
||
dw $isnan87
|
||
dw $flds87
|
||
dw $fldp87
|
||
dw $fst87
|
||
dw $fsts87
|
||
dw $dlis87
|
||
dw $dlds87
|
||
dw $dlip87
|
||
dw $dldp87
|
||
dw $dst87
|
||
dw $dsts87
|
||
dw $dpsh87
|
||
dw $dpshs87
|
||
dw $dpop87
|
||
dw $dpopp87
|
||
dw $dswap87
|
||
dw $dng87
|
||
dw $dtst87
|
||
dw $dcmp87
|
||
dw $dsb87
|
||
dw $dad87
|
||
dw $ddv87
|
||
dw $dml87
|
||
dw $utod87
|
||
dw $itod87
|
||
dw $xtod87
|
||
dw $dtoi87
|
||
dw $dstat87
|
||
dw $drest87
|
||
ifdef LONGPTR
|
||
dw $fldsss87
|
||
dw $fldsds87
|
||
dw $fldpss87
|
||
dw $fldpds87
|
||
dw $fstss87
|
||
dw $fstds87
|
||
dw $fstsss87
|
||
dw $fstsds87
|
||
dw $dldsss87
|
||
dw $dldsds87
|
||
dw $dldpss87
|
||
dw $dldpds87
|
||
dw $dstss87
|
||
dw $dstds87
|
||
dw $dstsss87
|
||
dw $dstsds87
|
||
endif
|
||
dataseg ends
|
||
|
||
|
||
$flttb: ; initial indirection table
|
||
$isnantb dw $flt_tst
|
||
$fldstb dw $flt_tst
|
||
$fldptb dw $flt_tst
|
||
$fsttb dw $flt_tst
|
||
$fststb dw $flt_tst
|
||
$dlistb dw $flt_tst
|
||
$dldstb dw $flt_tst
|
||
$dliptb dw $flt_tst
|
||
$dldptb dw $flt_tst
|
||
$dsttb dw $flt_tst
|
||
$dststb dw $flt_tst
|
||
$dpshtb dw $flt_tst
|
||
$dpshstb dw $flt_tst
|
||
$dpoptb dw $flt_tst
|
||
$dpopptb dw $flt_tst
|
||
$dswaptb dw $flt_tst
|
||
$dngtb dw $flt_tst
|
||
$dtsttb dw $flt_tst
|
||
$dcmptb dw $flt_tst
|
||
$dsbtb dw $flt_tst
|
||
$dadtb dw $flt_tst
|
||
$ddvtb dw $flt_tst
|
||
$dmltb dw $flt_tst
|
||
$utodtb dw $flt_tst
|
||
$itodtb dw $flt_tst
|
||
$xtodtb dw $flt_tst
|
||
$dtoitb dw $flt_tst
|
||
$dstattb dw $flt_tst
|
||
$dresttb dw $flt_tst
|
||
ifdef LONGPTR
|
||
$fldssstb dw $flt_tst
|
||
$fldsdstb dw $flt_tst
|
||
$fldpsstb dw $flt_tst
|
||
$fldpdstb dw $flt_tst
|
||
$fstsstb dw $flt_tst
|
||
$fstdstb dw $flt_tst
|
||
$fstssstb dw $flt_tst
|
||
$fstsdstb dw $flt_tst
|
||
$dldssstb dw $flt_tst
|
||
$dldsdstb dw $flt_tst
|
||
$dldpsstb dw $flt_tst
|
||
$dldpdstb dw $flt_tst
|
||
$dstsstb dw $flt_tst
|
||
$dstdstb dw $flt_tst
|
||
$dstssstb dw $flt_tst
|
||
$dstsdstb dw $flt_tst
|
||
endif
|
||
|
||
|
||
ifdef LONGPTR
|
||
SIZFLTTB equ 45
|
||
else
|
||
SIZFLTTB equ 29
|
||
endif
|
||
|
||
$flt_tst:
|
||
; test for 8087 goes here
|
||
push si
|
||
push di
|
||
push es
|
||
mov ds:status,0
|
||
esc 28,bx ; finit (initialize 8087)
|
||
xor cx,cx
|
||
esc 15,ds:status ; fstcw
|
||
mov cx,50
|
||
w1loop: loop w1loop ; wait for a while
|
||
and status,01f3fh ; clear unused bits
|
||
cmp status,0033fh ; is 8087 there?
|
||
mov si,offset $flttb86 ; assume not
|
||
mov cx,0
|
||
jnz $fltnxt ; no, use software emulation
|
||
wait
|
||
esc 47,status ; fstsw status
|
||
mov cx,50
|
||
w2loop: loop w2loop ; wait for a while
|
||
test ds:status,0b8bfh ; all status bits should be off
|
||
mov si,offset $flttb86 ; assume not
|
||
mov cx,0
|
||
jnz $fltnxt ; bad status, assume not there
|
||
mov si,offset $flttb87 ; 8087 is there!
|
||
mov cx,2
|
||
$fltnxt:
|
||
mov $flt_inx,cx ; set index for outside routines
|
||
mov di,cs
|
||
mov es,di
|
||
mov di,cs:offset $flttb ; get pointer to indirection table
|
||
mov cx,SIZFLTTB
|
||
cld
|
||
rep movsw ; and overwrite it with new table
|
||
pop es
|
||
pop di
|
||
pop si
|
||
pop cx ; get return address offset part
|
||
sub cx,CALLSZ ; back up return over call
|
||
push cx ; put back on stack
|
||
ret ; and return to reissue call
|
||
|
||
intrdef $isnan
|
||
jmp cs:word ptr $isnantb
|
||
|
||
intrdef $flds ;load single float into secondary accum
|
||
jmp cs:word ptr $fldstb
|
||
|
||
ifdef LONGPTR
|
||
intrdef $fldsss ;load single float into secondary accum
|
||
jmp cs:word ptr $fldssstb
|
||
|
||
intrdef $fldsds ;load single float into secondary accum
|
||
jmp cs:word ptr $fldsdstb
|
||
endif
|
||
;
|
||
intrdef $fldp ;load single float into primary accum
|
||
jmp cs:word ptr $fldptb
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $fldpss ;load single float into primary accum
|
||
jmp cs:word ptr $fldpsstb
|
||
;
|
||
intrdef $fldpds ;load single float into primary accum
|
||
jmp cs:word ptr $fldpdstb
|
||
endif
|
||
;
|
||
intrdef $fst ;store single at addr in BX
|
||
jmp cs:word ptr $fsttb
|
||
;
|
||
intrdef $fsts ;store single at addr in BX
|
||
jmp cs:word ptr $fststb
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $fstss ;store single at addr in BX
|
||
jmp cs:word ptr $fstsstb
|
||
;
|
||
intrdef $fstds ;store single at addr in BX
|
||
jmp cs:word ptr $fstdstb
|
||
|
||
intrdef $fstsss ;store single at addr in BX
|
||
jmp cs:word ptr $fstssstb
|
||
;
|
||
intrdef $fstsds ;store single at addr in BX
|
||
jmp cs:word ptr $fstsdstb
|
||
endif
|
||
;
|
||
intrdef $dlis ;load double immediate secondary
|
||
jmp cs:word ptr $dlistb
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $dldsss
|
||
jmp cs:word ptr $dldssstb
|
||
|
||
intrdef $dldsds
|
||
jmp cs:word ptr $dldsdstb
|
||
endif
|
||
intrdef $dlds ;load double float into secondary accum
|
||
jmp cs:word ptr $dldstb
|
||
;
|
||
intrdef $dlip ;load double immediate primary
|
||
jmp cs:word ptr $dliptb
|
||
;
|
||
ifdef LONGPTR
|
||
intrdef $dldpss ;load double float into primary accum
|
||
jmp cs:word ptr $dldpsstb
|
||
|
||
intrdef $dldpds ;load double float into primary accum
|
||
jmp cs:word ptr $dldpdstb
|
||
endif
|
||
intrdef $dldp ;load double float into primary accum
|
||
jmp cs:word ptr $dldptb
|
||
;
|
||
intrdef $dsts
|
||
jmp cs:word ptr $dststb
|
||
|
||
intrdef $dst ;store double at addr in BX
|
||
jmp cs:word ptr $dsttb
|
||
ifdef LONGPTR
|
||
intrdef $dstss ;store double at addr in BX
|
||
jmp cs:word ptr $dstsstb
|
||
|
||
intrdef $dstds ;store double at addr in BX
|
||
jmp cs:word ptr $dstdstb
|
||
|
||
intrdef $dstsss ;store double at addr in BX
|
||
jmp cs:word ptr $dstssstb
|
||
|
||
intrdef $dstsds ;store double at addr in BX
|
||
jmp cs:word ptr $dstsdstb
|
||
endif
|
||
;
|
||
intrdef $dpsh ;push double float onto the stack
|
||
;from the primary accumulator
|
||
jmp cs:word ptr $dpshtb
|
||
;
|
||
intrdef $dpshs ;push double float onto the stack
|
||
;from the secondary accumulator
|
||
jmp cs:word ptr $dpshstb
|
||
|
||
intrdef $dpopp ;pop double float into primary accum
|
||
jmp cs:word ptr $dpopptb
|
||
;
|
||
intrdef $dpop ;pop double float into secondary accum
|
||
jmp cs:word ptr $dpoptb
|
||
;
|
||
intrdef $dswap ;exchange primary and secondary
|
||
jmp cs:word ptr $dswaptb
|
||
;
|
||
intrdef $dng ;negate primary
|
||
jmp cs:word ptr $dngtb
|
||
;
|
||
intrdef $dtst ;test if primary is zero
|
||
jmp cs:word ptr $dtsttb
|
||
;
|
||
intrdef $dcmp ;compare primary and secondary
|
||
jmp cs:word ptr $dcmptb
|
||
;
|
||
intrdef $dsb ;subtract secondary from primary
|
||
jmp cs:word ptr $dsbtb
|
||
;
|
||
intrdef $dad ;add secondary to primary
|
||
jmp cs:word ptr $dadtb
|
||
;
|
||
intrdef $ddv
|
||
;double floating divide (primary = primary/secondary)
|
||
jmp cs:word ptr $ddvtb
|
||
;
|
||
intrdef $dml
|
||
;double floating multiply (primary = primary * secondary)
|
||
jmp cs:word ptr $dmltb
|
||
;
|
||
intrdef $utod
|
||
jmp cs:word ptr $utodtb
|
||
;
|
||
intrdef $itod
|
||
jmp cs:word ptr $itodtb
|
||
;
|
||
intrdef $xtod
|
||
jmp cs:word ptr $xtodtb
|
||
;
|
||
intrdef $dtou
|
||
intrdef $dtoi
|
||
intrdef $dtox
|
||
jmp cs:word ptr $dtoitb
|
||
|
||
intrdef $dstat
|
||
jmp cs:word ptr $dstattb
|
||
|
||
intrdef $drest
|
||
jmp cs:word ptr $dresttb
|
||
|
||
INTERNAL equ 1
|
||
purge intrdef
|
||
intrdef macro pname
|
||
pname&86 label near
|
||
endm
|
||
include fsubs.asm
|
||
purge intrdef
|
||
intrdef macro pname
|
||
pname&87 label near
|
||
endm
|
||
include fsubs87.asm
|
||
purge intrdef
|
||
intrdef macro pname
|
||
public pname
|
||
ifdef FARPROC
|
||
pname label far
|
||
else
|
||
pname label near
|
||
endif
|
||
endm
|
||
$floats endp
|
||
finish
|
||
end
|
||
fabs.c
|
||
#ifdef MPU68K
|
||
#define SIGN 0
|
||
#else
|
||
#define SIGN 7
|
||
#endif
|
||
|
||
double
|
||
fabs(dou)
|
||
double dou;
|
||
{
|
||
register char *cp;
|
||
|
||
cp = (char *)&dou;
|
||
cp[SIGN] &= 0x7f;
|
||
return dou;
|
||
}
|
||
|