home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
PROGRAM
/
DJEMU106.ZIP
/
EMU387
/
RMOV.CC
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-08
|
6KB
|
358 lines
#include "emu.h"
#include "const.h"
#include "rmov.h"
extern "C" void djshld(void *v);
extern "C" void djshrd(void *v);
void normalize(reg& r)
{
if (!(r.sigl | r.sigh))
{
r.exp = 0;
r.tag = TW_Z;
return;
}
if (r.exp >= EXP_MAX)
{
r.tag = TW_S;
return;
}
while (!(r.sigh & 0x80000000))
{
if (r.exp == 0)
return;
djshld(&r.sigl);
r.exp--;
}
}
void r_mov(long double *s, reg& d)
{
unsigned long *sp = (unsigned long *)s;
if (sp[2] & 0x8000)
d.sign = SIGN_NEG;
else
d.sign = SIGN_POS;
d.exp = sp[2] & 0x7fff;
d.sigh = sp[1];
d.sigl = sp[0];
d.tag = TW_V;
normalize(d);
}
void r_mov(double *s, reg& d)
{
unsigned m64 = ((unsigned *)s)[1];
unsigned l64 = ((unsigned *)s)[0];
if (m64 & 0x80000000)
d.sign = SIGN_NEG;
else
d.sign = SIGN_POS;
if (!((m64 & 0x7fffffff) | (l64)))
{
int c = d.sign;
r_mov(CONST_Z, d);
d.sign = c;
return;
}
d.exp = (int)((m64>>20)&0x7ff) - 1023 + EXP_BIAS;
d.sigh = ((m64 & 0xfffff)<<11) | 0x80000000;
d.sigh |= l64 >> 21;
d.sigl = l64 << 11;
d.tag = TW_V;
if ((m64 & 0x7ff00000) == 0x7ff00000)
d.exp = EXP_MAX;
normalize(d);
}
void r_mov(float *s, reg& d)
{
unsigned m32 = *(unsigned *)s;
if (m32 & 0x80000000)
d.sign = SIGN_NEG;
else
d.sign = SIGN_POS;
if (!(m32 & 0x7fffffff))
{
int c = d.sign;
r_mov(CONST_Z, d);
d.sign = c;
return;
}
d.exp = (int)((m32>>23)&0xff) - 127 + EXP_BIAS;
d.sigh = ((m32 & 0x7fffff)<<8) | 0x80000000;
d.sigl = 0;
d.tag = TW_V;
if ((m32 & 0x7f800000) == 0x7f800000)
d.exp = EXP_MAX;
normalize(d);
}
void r_mov(long long *_s, reg& d)
{
long long s = *_s;
if (s == 0)
return r_mov(CONST_Z, d);
if (s > 0)
d.sign = SIGN_POS;
else
{
s = -s;
d.sign = SIGN_NEG;
}
int e = EXP_BIAS + 63;
while (s >= 0)
{
djshld(&s);
e -= 1;
}
d.sigh = s >> 32;
d.sigl = s;
d.exp = e;
d.tag = TW_V;
normalize(d);
}
void r_mov(long *_s, reg& d)
{
long s = *_s;
if (s == 0)
return r_mov(CONST_Z, d);
if (s > 0)
d.sign = SIGN_POS;
else
{
s = -s;
d.sign = SIGN_NEG;
}
int e = EXP_BIAS + 31;
while (!(s & 0x80000000))
{
s <<= 1;
e -= 1;
}
d.sigh = s;
d.sigl = 0;
d.exp = e;
d.tag = TW_V;
normalize(d);
}
void r_mov(short *_s, reg& d)
{
int s = *_s;
if (s == 0)
return r_mov(CONST_Z, d);
if (s > 0)
d.sign = SIGN_POS;
else
{
s = -s;
d.sign = SIGN_NEG;
}
int e = EXP_BIAS + 15;
while (!(s & 0x8000))
{
s <<= 1;
e -= 1;
}
d.sigh = s << 16;
d.sigl = 0;
d.exp = e;
d.tag = TW_V;
normalize(d);
}
void r_mov(char *s, reg& d)
{
int side=1, pos=8;
long long l;
l = 0;
for (int i=0; i<18; i++)
{
l *= 10;
switch (side)
{
case 0:
l += s[pos] & 0x0f;
side = 1;
pos--;
break;
case 1:
l += s[pos] >> 4;
side = 0;
break;
}
}
r_mov(&l, d);
if (s[9] & 0x80)
d.sign = SIGN_NEG;
}
//=============================================================================
static void round_to_int(reg& r) // r gets mangled such that sig is int, sign
{
reg t;
int more_than_half = 0;
int half_or_more = 0;
if (r.tag == TW_Z)
{
return;
}
while (r.exp < EXP_BIAS+62)
{
if (r.sigl & 1)
more_than_half = 1;
djshrd(&r.sigl);
r.exp++;
}
while (r.exp < EXP_BIAS+63)
{
if (r.sigl & 1)
half_or_more = 1;
djshrd(&r.sigl);
r.exp++;
}
if (r.exp > EXP_BIAS+63)
{
r.sigl = r.sigh = ~0;
return;
}
switch (control_word & CW_RC)
{
case RC_RND:
if (half_or_more)
if (more_than_half) // nearest
(*(long long *)(&r.sigl)) ++;
else
if (r.sigl & 1) // odd?
(*(long long *)(&r.sigl)) ++;
break;
case RC_DOWN:
if ((half_or_more||more_than_half) && r.sign)
(*(long long *)(&r.sigl)) ++;
break;
case RC_UP:
if ((half_or_more||more_than_half) && !r.sign)
(*(long long *)(&r.sigl)) ++;
break;
case RC_CHOP:
break;
}
}
void r_mov(reg& s, long double *d)
{
((short *)d)[2] = s.exp + s.sign*0x8000;
((long *)d)[0] = s.sigl;
((long *)d)[1] = s.sigh;
}
void r_mov(reg& s, double *d)
{
unsigned long *l = (unsigned long *)d;
if (s.tag == TW_Z)
{
l[0] = 0;
l[1] = 0;
}
else
{
l[0] = (s.sigl >> 11) | (s.sigh << 21);
l[1] = ((s.sigh >> 11) & 0xfffff) | (((s.exp-EXP_BIAS+1023) & 0x7ff) << 20);
}
if (s.sign)
l[1] |= 0x80000000;
}
void r_mov(reg& s, float *d)
{
long f;
if (s.tag == TW_Z)
{
f = 0;
}
else
{
f = (s.sigh >> 8) & 0x007fffff;
f |= ((s.exp-EXP_BIAS+127) & 0xff) << 23;
}
if (s.sign)
f |= 0x80000000;
*(long *)d = f;
}
void r_mov(reg& s, long long *d)
{
reg t;
r_mov(s, t);
round_to_int(t);
((long *)d)[0] = t.sigl;
((long *)d)[1] = t.sigh;
if (t.sign)
*d = - *d;
}
void r_mov(reg& s, long *d)
{
reg t;
r_mov(s, t);
round_to_int(t);
if (t.sigh || (t.sigl & 0x80000000))
*d = -1;
else
*d = s.sign ? -t.sigl : t.sigl;
}
void r_mov(reg& s, short *d)
{
reg t;
r_mov(s, t);
round_to_int(t);
if (t.sigh || (t.sigl & 0xFFFF8000))
*d = -1;
else
*d = s.sign ? -t.sigl : t.sigl;
}
void r_mov(reg& s, char *d)
{
reg t;
r_mov(s, t);
round_to_int(t);
long long ll = *(long long *)(&t.sigl);
int side = 0;
int r, i;
for (i=0; i<10; i++)
d[i] = 0;
int pos=0;
for (i=0; i<18; i++)
{
r = ll % 10;
ll /= 10;
if (side)
{
d[pos] |= r << 4;
side = 0;
pos++;
}
else
{
d[pos] |= r;
side = 1;
}
}
if (s.sign == SIGN_NEG)
d[9] = 0x80;
}