/********************************** fpmath.h ****************************/ #define MUL(xx,yy,zz,ww) { _CL = yy; \ _AL = xx; \ asm mul cl; \ zz = _AL; \ ww = _AH; } /********************************** fpmath.c ****************************/ #include #include #include #include "utype.h" #include "interp.h" #include "asm.h" #include "fpmath.h" extern char *bufptr; extern BOOL usefp; extern BOOL usedfloating; BYTE ten02[8][12] = { { 0x3f, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x40, 0x02, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x40, 0x05, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x40, 0x08, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x40, 0x0c, 0x00, 0x00, 0x9c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x40, 0x0f, 0x00, 0x00, 0xc3, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x40, 0x12, 0x00, 0x00, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x40, 0x16, 0x00, 0x00, 0x98, 0x96, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 } } ; BYTE ten3[12] = {0x40, 0x19, 0x00, 0x00, 0xbe, 0xbc, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 } ; BYTE ten4[12] = {0x40, 0x34, 0x00, 0x00, 0x8e, 0x1b, 0xc9, 0xbf, 0x04, 0x00, 0x00, 0x00 } ; BYTE ten5[12] = {0x40, 0x69, 0x00, 0x00, 0x9d, 0xc5, 0xad, 0xa8, 0x2b, 0x70, 0xb5, 0x9e } ; BYTE ten6[12] = {0x40, 0xd3, 0x00, 0x00, 0xc2, 0x78, 0x1f, 0x49, 0xff, 0xcf, 0xa6, 0xd5 } ; BYTE ten7[12] = {0x41, 0xa8, 0x00, 0x00, 0x93, 0xba, 0x47, 0xc9, 0x80, 0xe9, 0x8c, 0xe0 } ; BYTE ten8[12] = {0x43, 0x51, 0x00, 0x00, 0xaa, 0x7e, 0xeb, 0xfb, 0x9d, 0xf9, 0xde, 0x8e } ; BYTE ten9[12] = {0x46, 0xa3, 0x00, 0x00, 0xe3, 0x19, 0xa0, 0xae, 0xa6, 0x0e, 0x91, 0xc7 } ; BYTE ten10[12] = {0x4d, 0x48, 0x00, 0x00, 0xc9, 0x76, 0x75, 0x86, 0x81, 0x75, 0x0c, 0x17 } ; BYTE ten11[12] = {0x5a, 0x92, 0x00, 0x00, 0x9e, 0x8b, 0x3b, 0x5d, 0xc5, 0x3d, 0x5d, 0xe5 } ; BYTE ten12[12] = {0x75, 0x25, 0x00, 0x00, 0xc4, 0x60, 0x52, 0x02, 0x8a, 0x20, 0x97, 0x9b } ; void IllegalFloat(void) { Error("Illegal placement of floating point"); } void FloatOverflow(void) { Error("Floating point overflow"); } void BadControl(int reg) { if (reg > 7) Error("Can't use floating point control register here"); } void NeedFP(void) { Error("Need floating point reg here"); } void NoFloat(void) { if (!usefp) Error("Floating point not enabled"); else usedfloating = TRUE; } void or(BYTE *dest, BYTE *src) { int i; for (i=0; i < 8; i++) dest[i] |= src[i]; } int sub(BYTE *dest, BYTE *src) { int i, carry = 0; for (i= 7; i >=0; i--) { int oldcarry = carry; if (src[i] + carry> dest[i]) carry = 1; else carry = 0; dest[i] -= src[i] + oldcarry; } return(carry); } int add(BYTE *dest, BYTE *src) { int i, carry = 0; for (i= 7; i >=0; i--) { int oldcarry = carry; if (src[i] +carry + dest[i] > 255) carry = 1; else carry = 0; dest[i] += src[i] + oldcarry; } return(carry); } int fp_rotr(BYTE *fl, int bytes, int bits) { int bytemove = bits >> 3; int i,mask = 0,r=0; BYTE answer[16]; memset(answer,0,16); if (bits == 0) return(0); bits = bits & 7; for (i=0; i < bits; i++) { mask <<=1; mask |= 1; } for (i=0; i > bits; answer[i+bytemove] = q+r; r = t << (8-bits); } memcpy(fl,answer,bytes); return(r); } int fp_rotl(BYTE *fl, int bytes, int bits) { int bytemove = bits >> 3; int i, mask = 0x00, r=0; BYTE answer[16]; memset(answer,0,16); if (bits == 0) return(0); bits = bits & 7; for (i=0; i >= 1; mask |= 0x80; } for (i=bytes-1; i >=bytemove; i--) { BYTE t = fl[i] & mask; BYTE q = fl[i] << bits; answer[i-bytemove] = q+r; r = t >> (8-bits); } memcpy(fl,answer,bytes); return(r); } int fp_signif(BYTE *fl, int bytes) { int j; for (j=0; j < bytes; j++) { int mask = 0x80,i=1; while (mask) { if (mask & fl[j]) return((bytes-j)*8-i); i++; mask>>=1; } } return(-1); } void fp_mul(BYTE *dest, BYTE *src) { BYTE interrim[16], *srcw; long expd = ((dest[0] &0x7f)<< 8) + dest[1]; long exps = ((src[0] &0x7f)<< 8) + src[1]; long exp = expd + exps - 16383; int sign = (dest[0] ^ src[0]) & 0x80; int i,j; for (i=0; i < 16; i++) interrim[i] = 0; srcw = src+11; for (i=0; i < 8; i++) { BYTE carry = 0; BYTE temp; BYTE *ip = &interrim[15-i]; BYTE *dstw = dest+11; for (j=0; j< 8; j++) { BYTE oldcarry = carry; MUL(*srcw,*dstw,temp,carry); carry+= (*ip + oldcarry + temp)>>8; *ip += oldcarry + temp; ip--; dstw--; } srcw--; *ip += carry; } if (interrim[0] & 0x80) exp++; else { j = 16*8-1-fp_signif(interrim,16); fp_rotl(interrim,16,j); exp-=j-1; } if (exp < 0) if (exp < -63) { for (i=0; i < 12; i++) dest[i] = 0; return; } else { fp_rotr(interrim,8,-exp); exp = 0; } else if (exp > 32766) { exp = 32767; for (i=0; i < 8; i++) dest[i+4] = 0; return; } for (i=0; i < 8; i++) dest[i+4] = interrim[i]; dest[0] = (exp >> 8) | sign; dest[1] = exp & 0xff; } void fp_div(BYTE *dest, BYTE *src) { BYTE interrim[8],dividend[8],divisor[8],bit[8],answer[8]; long expd = ((dest[0] &0x7f)<< 8) + dest[1]; long exps = ((src[0] &0x7f)<< 8) + src[1]; long exp = expd - exps + 16383; int sign = (dest[0] ^ src[0]) & 0x80; int i,j; memset(answer,0,8); memset(bit,0,8); for (i=0; i<8; i++) { dividend[i] = dest[i+4]; divisor[i] = src[i+4]; } bit[0] |= 0x80; for (i= 0; i < 8; i++) { for (j=0; j < 8; j++) { memcpy(interrim,dividend,8); if (sub(dividend,divisor)) memcpy(dividend,interrim,8); else or(answer,bit); fp_rotr(bit,8,1); fp_rotr(divisor,8,1); } } j = 8*8-1-fp_signif(answer,8); fp_rotl(answer,8,j); exp -=j; if (exp < 0) if (exp < -63) { for (i=0; i < 12; i++) dest[i] = 0; return; } else { fp_rotr(interrim,8,-exp); exp = 0; } else if (exp > 32766) { exp = 32767; for (i=0; i < 8; i++) dest[i+4] = 0; return; } for (i=0; i < 8; i++) dest[i+4] = answer[i]; dest[0] = (exp >> 8) | sign; dest[1] = exp & 0xff; } void fp_pow(BYTE *dest, int power) { int i; if (!power) return; if (power > 4932) { dest [0] |= 0x7f; dest[1] |= 0xff; for (i=2; i<12; i++) dest[i] = 0; } else { if (power < -4951) { dest[0] &= 0x80; for (i=1; i < 12; i++) dest[i] = 0; } else { BYTE udest[12]; int abspower = power; int start; if (abspower < 0) abspower = - abspower; start = abspower & 7; memcpy(udest,ten02[start],12); if (abspower & 0x8) fp_mul(udest,ten3); if (abspower & 0x10) fp_mul(udest,ten4); if (abspower & 0x20) fp_mul(udest,ten5); if (abspower & 0x40) fp_mul(udest,ten6); if (abspower & 0x80) fp_mul(udest,ten7); if (abspower & 0x100) fp_mul(udest,ten9); if (abspower & 0x200) fp_mul(udest,ten9); if (abspower & 0x400) fp_mul(udest,ten10); if (abspower & 0x800) fp_mul(udest,ten11); if (abspower & 0x1000) fp_mul(udest,ten12); if (power < 0) fp_div(dest,udest); else fp_mul(dest,udest); } } } void GetFloatNumber(int curchar,long val,BYTE *fp) { int i; long exp = 0,sexp = 0,bias = 0; BYTE save[12],overflow=0; for (i=0; i < 12; i++) fp[i] = 0; fp[11] = val &0xff; fp[10] = (val>>8) &0xff; fp[9] = (val>>16) &0xff; fp[8] = (