home *** CD-ROM | disk | FTP | other *** search
- #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;
- }
-
-
-