kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
1134 wiersze
27 KiB
C
1134 wiersze
27 KiB
C
/*
|
|
* UAE - The Un*x Amiga Emulator
|
|
*
|
|
* MC68881 emulation
|
|
*
|
|
* Copyright 1996 Herman ten Brugge
|
|
*/
|
|
|
|
#include <math.h>
|
|
|
|
#include "shared.h"
|
|
|
|
#include "memory.h"
|
|
#include "custom.h"
|
|
#include "readcpu.h"
|
|
#include "newcpu.h"
|
|
#include "ersatz.h"
|
|
|
|
#if CPU_LEVEL >= 3
|
|
|
|
#define DEBUG_FPP 0
|
|
|
|
/* single : S 8*E 23*F */
|
|
/* double : S 11*E 52*F */
|
|
/* extended : S 15*E 64*F */
|
|
/* E = 0 & F = 0 -> 0 */
|
|
/* E = MAX & F = 0 -> Infin */
|
|
/* E = MAX & F # 0 -> NotANumber */
|
|
/* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */
|
|
|
|
static __inline__ double
|
|
to_single(uae_u32 value)
|
|
{
|
|
double frac;
|
|
|
|
if ((value & 0x7fffffff) == 0) return(0.0);
|
|
frac = (double)((value & 0x7fffff) | 0x800000) / 8388608.0;
|
|
if (value & 0x80000000) frac = -frac;
|
|
return(ldexp(frac, ((value >> 23) & 0xff) - 127));
|
|
}
|
|
|
|
static __inline__ uae_u32
|
|
from_single(double src)
|
|
{
|
|
int expon;
|
|
uae_u32 tmp;
|
|
double frac;
|
|
|
|
if (src == 0.0) return 0;
|
|
if (src < 0) { tmp = 0x80000000 ; src = -src; }
|
|
else { tmp = 0; }
|
|
frac = frexp(src,&expon);
|
|
frac += 0.5 / 16777216.0;
|
|
if (frac >= 1.0) { frac /= 2.0; expon++; }
|
|
return (tmp | (((expon + 127 - 1) & 0xff) << 23) |
|
|
(((int)(frac * 16777216.0)) & 0x7fffff));
|
|
}
|
|
|
|
static __inline__ double
|
|
to_exten(uae_u32 wrd1,uae_u32 wrd2,uae_u32 wrd3)
|
|
{
|
|
double frac;
|
|
|
|
if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) return 0.0;
|
|
frac = (double)wrd2 / 2147483648.0 +
|
|
(double)wrd3 / 9223372036854775808.0;
|
|
if (wrd1 & 0x80000000) frac = -frac;
|
|
return ldexp(frac, ((wrd1 >> 16) & 0x7fff) - 16383);
|
|
}
|
|
|
|
static __inline__ void
|
|
from_exten(double src,uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 * wrd3)
|
|
{
|
|
int expon;
|
|
double frac;
|
|
|
|
if (src == 0.0) { *wrd1 = 0; *wrd2 = 0; *wrd3 = 0; return; }
|
|
if (src < 0) { *wrd1 = 0x80000000 ; src = -src; }
|
|
else { *wrd1 = 0; }
|
|
frac = frexp(src,&expon);
|
|
frac += 0.5 / 18446744073709551616.0;
|
|
if (frac >= 1.0) { frac /= 2.0; expon++; }
|
|
*wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
|
|
*wrd2 = (uae_u32)(frac * 4294967296.0);
|
|
*wrd3 = (uae_u32)(frac * 18446744073709551616.0 - *wrd2 * 4294967296.0);
|
|
}
|
|
|
|
static __inline__ double
|
|
to_double(uae_u32 wrd1,uae_u32 wrd2)
|
|
{
|
|
double frac;
|
|
|
|
if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) return 0.0;
|
|
frac = (double)((wrd1 & 0xfffff) | 0x100000) / 1048576.0 +
|
|
(double)wrd2 / 4503599627370496.0;
|
|
if (wrd1 & 0x80000000) frac = -frac;
|
|
return ldexp(frac, ((wrd1 >> 20) & 0x7ff) - 1023);
|
|
}
|
|
|
|
static __inline__ void
|
|
from_double(double src,uae_u32 *wrd1, uae_u32 *wrd2)
|
|
{
|
|
int expon;
|
|
int tmp;
|
|
double frac;
|
|
|
|
if (src == 0.0) { *wrd1 = 0; *wrd2 = 0; return; }
|
|
if (src < 0) { *wrd1 = 0x80000000 ; src = -src; }
|
|
else { *wrd1 = 0; }
|
|
frac = frexp(src,&expon);
|
|
frac += 0.5 / 9007199254740992.0;
|
|
if (frac >= 1.0) { frac /= 2.0; expon++; }
|
|
tmp = (uae_u32)(frac * 2097152.0);
|
|
*wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff);
|
|
*wrd2 = (uae_u32)(frac * 9007199254740992.0 - tmp * 4294967296.0);
|
|
}
|
|
|
|
static __inline__ double
|
|
to_pack(uae_u32 wrd1,uae_u32 wrd2,uae_u32 wrd3)
|
|
{
|
|
double d;
|
|
char *cp;
|
|
char str[100];
|
|
|
|
cp = str;
|
|
if (wrd1 & 0x80000000) *cp++ = '-';
|
|
*cp++ = (wrd1 & 0xf) + '0';
|
|
*cp++ = '.';
|
|
*cp++ = ((wrd2 >> 28) & 0xf) + '0';
|
|
*cp++ = ((wrd2 >> 24) & 0xf) + '0';
|
|
*cp++ = ((wrd2 >> 20) & 0xf) + '0';
|
|
*cp++ = ((wrd2 >> 16) & 0xf) + '0';
|
|
*cp++ = ((wrd2 >> 12) & 0xf) + '0';
|
|
*cp++ = ((wrd2 >> 8) & 0xf) + '0';
|
|
*cp++ = ((wrd2 >> 4) & 0xf) + '0';
|
|
*cp++ = ((wrd2 >> 0) & 0xf) + '0';
|
|
*cp++ = ((wrd3 >> 28) & 0xf) + '0';
|
|
*cp++ = ((wrd3 >> 24) & 0xf) + '0';
|
|
*cp++ = ((wrd3 >> 20) & 0xf) + '0';
|
|
*cp++ = ((wrd3 >> 16) & 0xf) + '0';
|
|
*cp++ = ((wrd3 >> 12) & 0xf) + '0';
|
|
*cp++ = ((wrd3 >> 8) & 0xf) + '0';
|
|
*cp++ = ((wrd3 >> 4) & 0xf) + '0';
|
|
*cp++ = ((wrd3 >> 0) & 0xf) + '0';
|
|
*cp++ = 'E';
|
|
if (wrd1 & 0x40000000) *cp++ = '-';
|
|
*cp++ = ((wrd1 >> 24) & 0xf) + '0';
|
|
*cp++ = ((wrd1 >> 20) & 0xf) + '0';
|
|
*cp++ = ((wrd1 >> 16) & 0xf) + '0';
|
|
*cp = 0;
|
|
sscanf(str,"%le",&d);
|
|
return d;
|
|
}
|
|
|
|
static __inline__ void
|
|
from_pack(double src,uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 * wrd3)
|
|
{
|
|
int i;
|
|
int t;
|
|
char *cp;
|
|
char str[100];
|
|
|
|
sprintf(str,"%.16e",src);
|
|
cp = str;
|
|
*wrd1 = *wrd2 = *wrd3 = 0;
|
|
if (*cp == '-') { cp++ ; *wrd1 = 0x80000000; }
|
|
if (*cp == '+') cp++;
|
|
*wrd1 |= (*cp++ - '0');
|
|
if (*cp == '.') cp++;
|
|
for (i = 0 ; i < 8 ; i++) {
|
|
*wrd2 <<= 4;
|
|
if (*cp >= '0' && *cp <= '9')
|
|
*wrd2 |= *cp++ - '0';
|
|
}
|
|
for (i = 0 ; i < 8 ; i++) {
|
|
*wrd3 <<= 4;
|
|
if (*cp >= '0' && *cp <= '9')
|
|
*wrd3 |= *cp++ - '0';
|
|
}
|
|
if (*cp == 'e' || *cp == 'E') {
|
|
cp++;
|
|
if (*cp == '-') { cp++; *wrd1 |= 0x40000000; }
|
|
if (*cp == '+') cp++;
|
|
t = 0;
|
|
for (i = 0 ; i < 3 ; i++) {
|
|
if (*cp >= '0' && *cp <= '9')
|
|
t = (t << 4) | (*cp++ - '0');
|
|
}
|
|
*wrd1 |= t << 16;
|
|
}
|
|
}
|
|
|
|
static __inline__ int
|
|
get_fp_value(uae_u32 opcode, uae_u16 extra,double *src)
|
|
{
|
|
int size;
|
|
int mode;
|
|
int reg;
|
|
uae_u32 ad = 0;
|
|
static int sz1[8] = { 4,4,12,12,2,8,1,0 };
|
|
static int sz2[8] = { 4,4,12,12,2,8,2,0 };
|
|
|
|
if ((extra & 0x4000) == 0) {
|
|
*src = regs.fp[(extra >> 10) & 7];
|
|
return 1;
|
|
}
|
|
mode = (opcode >> 3) & 7;
|
|
reg = opcode & 7;
|
|
size = (extra >> 10) & 7;
|
|
switch (mode) {
|
|
case 0:
|
|
switch (size) {
|
|
case 6: *src = (double)(uae_s8)m68k_dreg(regs, reg);
|
|
break;
|
|
case 4: *src = (double)(uae_s16)m68k_dreg(regs, reg);
|
|
break;
|
|
case 0: *src = (double)(uae_s32)m68k_dreg(regs, reg);
|
|
break;
|
|
case 1: *src = to_single(m68k_dreg(regs, reg));
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
return 1;
|
|
case 1:
|
|
return 0;
|
|
case 2:
|
|
ad = m68k_areg(regs, reg);
|
|
break;
|
|
case 3:
|
|
ad = m68k_areg(regs, reg);
|
|
m68k_areg(regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
|
break;
|
|
case 4:
|
|
m68k_areg(regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
|
ad = m68k_areg(regs, reg);
|
|
break;
|
|
case 5:
|
|
ad = m68k_areg(regs, reg) + (uae_s32)(uae_s16)nextiword();
|
|
break;
|
|
case 6:
|
|
ad = get_disp_ea(m68k_areg(regs, reg));
|
|
break;
|
|
case 7:
|
|
switch (reg) {
|
|
case 0: ad = (uae_s32)(uae_s16)nextiword();
|
|
break;
|
|
case 1: ad = nextilong();
|
|
break;
|
|
case 2: ad = m68k_getpc();
|
|
ad += (uae_s32)(uae_s16)nextiword();
|
|
break;
|
|
case 3: ad = get_disp_ea(m68k_getpc());
|
|
break;
|
|
case 4: ad = m68k_getpc();
|
|
m68k_setpc(ad + sz2[size]);
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
switch (size) {
|
|
case 0: *src = (double)(uae_s32)get_long(ad);
|
|
break;
|
|
case 1: *src = to_single(get_long(ad));
|
|
break;
|
|
case 2: { uae_u32 wrd1,wrd2,wrd3;
|
|
wrd1 = get_long(ad);ad+=4;
|
|
wrd2 = get_long(ad);ad+=4;
|
|
wrd3 = get_long(ad);
|
|
*src = to_exten(wrd1,wrd2,wrd3);
|
|
}
|
|
break;
|
|
case 3: { uae_u32 wrd1,wrd2,wrd3;
|
|
wrd1 = get_long(ad);ad+=4;
|
|
wrd2 = get_long(ad);ad+=4;
|
|
wrd3 = get_long(ad);
|
|
*src = to_pack(wrd1,wrd2,wrd3);
|
|
}
|
|
break;
|
|
case 4: *src = (double)(uae_s16)get_word(ad);
|
|
break;
|
|
case 5: { uae_u32 wrd1,wrd2;
|
|
wrd1 = get_long(ad);ad+=4;
|
|
wrd2 = get_long(ad);
|
|
*src = to_double(wrd1,wrd2);
|
|
}
|
|
break;
|
|
case 6: *src = (double)(uae_s8)get_byte(ad);
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static __inline__ int
|
|
put_fp_value(double value, uae_u32 opcode, uae_u16 extra)
|
|
{
|
|
int size;
|
|
int mode;
|
|
int reg;
|
|
uae_u32 ad;
|
|
static int sz1[8] = { 4,4,12,12,2,8,1,0 };
|
|
static int sz2[8] = { 4,4,12,12,2,8,2,0 };
|
|
|
|
if ((extra & 0x4000) == 0) {
|
|
regs.fp[(extra >> 10) & 7] = value;
|
|
return 1;
|
|
}
|
|
mode = (opcode >> 3) & 7;
|
|
reg = opcode & 7;
|
|
size = (extra >> 10) & 7;
|
|
ad = -1;
|
|
switch (mode) {
|
|
case 0:
|
|
switch (size) {
|
|
case 6: m68k_dreg(regs, reg) = ((int)value & 0xff) |
|
|
(m68k_dreg(regs, reg) & ~0xff);
|
|
break;
|
|
case 4: m68k_dreg(regs, reg) = ((int)value & 0xffff) |
|
|
(m68k_dreg(regs, reg) & ~0xffff);
|
|
break;
|
|
case 0: m68k_dreg(regs, reg) = (int)value;
|
|
break;
|
|
case 1: m68k_dreg(regs, reg) = from_single(value);
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
return 1;
|
|
case 1:
|
|
return 0;
|
|
case 2:
|
|
ad = m68k_areg(regs, reg);
|
|
break;
|
|
case 3:
|
|
ad = m68k_areg(regs, reg);
|
|
m68k_areg(regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
|
break;
|
|
case 4:
|
|
m68k_areg(regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
|
ad = m68k_areg(regs, reg);
|
|
break;
|
|
case 5:
|
|
ad = m68k_areg(regs, reg) + (uae_s32)(uae_s16)nextiword();
|
|
break;
|
|
case 6:
|
|
ad = get_disp_ea(m68k_areg(regs, reg));
|
|
break;
|
|
case 7:
|
|
switch (reg) {
|
|
case 0: ad = (uae_s32)(uae_s16)nextiword();
|
|
break;
|
|
case 1: ad = nextilong();
|
|
break;
|
|
case 2: ad = m68k_getpc();
|
|
ad += (uae_s32)(uae_s16)nextiword();
|
|
break;
|
|
case 3: ad = get_disp_ea(m68k_getpc());
|
|
break;
|
|
case 4: ad = m68k_getpc();
|
|
m68k_setpc(ad + sz2[size]);
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
switch (size) {
|
|
case 0: put_long(ad,(uae_s32)value);
|
|
break;
|
|
case 1: put_long(ad,from_single(value));
|
|
break;
|
|
case 2: { uae_u32 wrd1,wrd2,wrd3;
|
|
from_exten(value,&wrd1,&wrd2,&wrd3);
|
|
put_long(ad,wrd1);ad+=4;
|
|
put_long(ad,wrd2);ad+=4;
|
|
put_long(ad,wrd3);
|
|
}
|
|
break;
|
|
case 3: { uae_u32 wrd1,wrd2,wrd3;
|
|
from_pack(value,&wrd1,&wrd2,&wrd3);
|
|
put_long(ad,wrd1);ad+=4;
|
|
put_long(ad,wrd2);ad+=4;
|
|
put_long(ad,wrd3);
|
|
}
|
|
break;
|
|
case 4: put_word(ad,(uae_s16)value);
|
|
break;
|
|
case 5: { uae_u32 wrd1,wrd2;
|
|
from_double(value,&wrd1,&wrd2);
|
|
put_long(ad,wrd1);ad+=4;
|
|
put_long(ad,wrd2);
|
|
}
|
|
break;
|
|
case 6: put_byte(ad,(uae_s8)value);
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static __inline__ int
|
|
get_fp_ad(uae_u32 opcode,uae_u32 *ad)
|
|
{
|
|
int mode;
|
|
int reg;
|
|
|
|
mode = (opcode >> 3) & 7;
|
|
reg = opcode & 7;
|
|
switch (mode) {
|
|
case 0:
|
|
case 1:
|
|
return 0;
|
|
case 2:
|
|
*ad = m68k_areg(regs, reg);
|
|
break;
|
|
case 3:
|
|
*ad = m68k_areg(regs, reg);
|
|
break;
|
|
case 4:
|
|
*ad = m68k_areg(regs, reg);
|
|
break;
|
|
case 5:
|
|
*ad = m68k_areg(regs, reg) + (uae_s32)(uae_s16)nextiword();
|
|
break;
|
|
case 6:
|
|
*ad = get_disp_ea(m68k_areg(regs, reg));
|
|
break;
|
|
case 7:
|
|
switch (reg) {
|
|
case 0: *ad = (uae_s32)(uae_s16)nextiword();
|
|
break;
|
|
case 1: *ad = nextilong();
|
|
break;
|
|
case 2: *ad = m68k_getpc();
|
|
*ad += (uae_s32)(uae_s16)nextiword();
|
|
break;
|
|
case 3: *ad = get_disp_ea(m68k_getpc());
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static __inline__ int
|
|
fpp_cond(uae_u32 opcode, int contition)
|
|
{
|
|
int N = (regs.fpsr & 0x8000000) != 0;
|
|
int Z = (regs.fpsr & 0x4000000) != 0;
|
|
/* int I = (regs.fpsr & 0x2000000) != 0; */
|
|
int NotANumber = (regs.fpsr & 0x1000000) != 0;
|
|
|
|
switch (contition) {
|
|
case 0x00: return 0;
|
|
case 0x01: return Z;
|
|
case 0x02: return !(NotANumber || Z || N);
|
|
case 0x03: return Z || !(NotANumber || N);
|
|
case 0x04: return N && !(NotANumber || Z);
|
|
case 0x05: return Z || (N && !NotANumber);
|
|
case 0x06: return !(NotANumber || Z);
|
|
case 0x07: return !NotANumber;
|
|
case 0x08: return NotANumber;
|
|
case 0x09: return NotANumber || Z;
|
|
case 0x0a: return NotANumber || !(N || Z);
|
|
case 0x0b: return NotANumber || Z || !N;
|
|
case 0x0c: return NotANumber || (N && !Z);
|
|
case 0x0d: return NotANumber || Z || N;
|
|
case 0x0e: return !Z;
|
|
case 0x0f: return 1;
|
|
case 0x10: return 0;
|
|
case 0x11: return Z;
|
|
case 0x12: return !(NotANumber || Z || N);
|
|
case 0x13: return Z || !(NotANumber || N);
|
|
case 0x14: return N && !(NotANumber || Z);
|
|
case 0x15: return Z || (N && !NotANumber);
|
|
case 0x16: return !(NotANumber || Z);
|
|
case 0x17: return !NotANumber;
|
|
case 0x18: return NotANumber;
|
|
case 0x19: return NotANumber || Z;
|
|
case 0x1a: return NotANumber || !(N || Z);
|
|
case 0x1b: return NotANumber || Z || !N;
|
|
case 0x1c: return NotANumber || (Z && N);
|
|
case 0x1d: return NotANumber || Z || N;
|
|
case 0x1e: return !Z;
|
|
case 0x1f: return 1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void
|
|
fdbcc_opp(uae_u32 opcode, uae_u16 extra)
|
|
{
|
|
uaecptr pc = (uae_u32)m68k_getpc();
|
|
uae_s32 disp = (uae_s32)(uae_s16)nextiword();
|
|
int cc;
|
|
|
|
#if DEBUG_FPP
|
|
printf("fdbcc_opp at %08lx\n",m68k_getpc());fflush(stdout);
|
|
#endif
|
|
cc = fpp_cond(opcode, extra & 0x3f);
|
|
if (cc == -1) {
|
|
m68k_setpc(pc-2);
|
|
op_illg(opcode);
|
|
} else if (!cc) {
|
|
int reg = opcode & 0x7;
|
|
|
|
m68k_dreg(regs, reg) = ((m68k_dreg(regs, reg) & ~0xffff)
|
|
| ((m68k_dreg(regs, reg)-1) & 0xffff));
|
|
if ((m68k_dreg(regs, reg) & 0xffff) == 0xffff)
|
|
m68k_setpc(pc + disp);
|
|
}
|
|
}
|
|
|
|
void
|
|
fscc_opp(uae_u32 opcode, uae_u16 extra)
|
|
{
|
|
uae_u32 ad;
|
|
int cc;
|
|
|
|
#if DEBUG_FPP
|
|
printf("fscc_opp at %08lx\n",m68k_getpc());fflush(stdout);
|
|
#endif
|
|
cc = fpp_cond(opcode, extra & 0x3f);
|
|
if (cc == -1) {
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
}
|
|
else if ((opcode & 0x38) == 0) {
|
|
m68k_dreg(regs, opcode & 7) = (m68k_dreg(regs, opcode & 7) & ~0xff) |
|
|
(cc ? 0xff : 0x00);
|
|
}
|
|
else {
|
|
if (get_fp_ad(opcode,&ad) == 0) {
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
}
|
|
else
|
|
put_byte(ad,cc ? 0xff : 0x00);
|
|
}
|
|
}
|
|
|
|
void
|
|
ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
|
|
{
|
|
int cc;
|
|
|
|
#if DEBUG_FPP
|
|
printf("ftrapcc_opp at %08lx\n",m68k_getpc());fflush(stdout);
|
|
#endif
|
|
cc = fpp_cond(opcode, opcode & 0x3f);
|
|
if (cc == -1) {
|
|
m68k_setpc(oldpc);
|
|
op_illg(opcode);
|
|
}
|
|
if (cc)
|
|
Exception(7,oldpc-2);
|
|
}
|
|
|
|
void
|
|
fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra)
|
|
{
|
|
int cc;
|
|
|
|
#if DEBUG_FPP
|
|
printf("fbcc_opp at %08lx\n",m68k_getpc());fflush(stdout);
|
|
#endif
|
|
cc = fpp_cond(opcode, opcode & 0x3f);
|
|
if (cc == -1) {
|
|
m68k_setpc(pc);
|
|
op_illg(opcode);
|
|
}
|
|
else if (cc) {
|
|
if ((opcode & 0x40) == 0)
|
|
extra = (uae_s32)(uae_s16)extra;
|
|
m68k_setpc(pc + extra);
|
|
}
|
|
}
|
|
|
|
void
|
|
fsave_opp(uae_u32 opcode)
|
|
{
|
|
uae_u32 ad;
|
|
int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
|
|
int i;
|
|
|
|
#if DEBUG_FPP
|
|
printf("fsave_opp at %08lx\n",m68k_getpc());fflush(stdout);
|
|
#endif
|
|
if (get_fp_ad(opcode,&ad) == 0) {
|
|
op_illg(opcode);
|
|
return;
|
|
}
|
|
if (incr < 0) {
|
|
ad -= 4;put_long(ad,0x70000000);
|
|
for (i = 0 ; i < 5 ; i++) {
|
|
ad -= 4;put_long(ad,0x00000000);
|
|
}
|
|
ad -= 4;put_long(ad,0x1f180000);
|
|
}
|
|
else {
|
|
put_long(ad,0x1f180000); ad += 4;
|
|
for (i = 0 ; i < 5 ; i++) {
|
|
put_long(ad,0x00000000); ad += 4;
|
|
}
|
|
put_long(ad,0x70000000); ad += 4;
|
|
}
|
|
if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
|
|
if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad;
|
|
}
|
|
|
|
void
|
|
frestore_opp(uae_u32 opcode)
|
|
{
|
|
uae_u32 ad;
|
|
uae_u32 d;
|
|
int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
|
|
|
|
#if DEBUG_FPP
|
|
printf("frestore_opp at %08lx\n",m68k_getpc());fflush(stdout);
|
|
#endif
|
|
if (get_fp_ad(opcode,&ad) == 0) {
|
|
op_illg(opcode);
|
|
return;
|
|
}
|
|
if (incr < 0) {
|
|
ad -= 4; d = get_long(ad);
|
|
if ((d & 0xff000000) != 0) {
|
|
if ((d & 0x00ff0000) == 0x00180000)
|
|
ad -= 6 * 4;
|
|
else if ((d & 0x00ff0000) == 0x00380000)
|
|
ad -= 14 * 4;
|
|
else if ((d & 0x00ff0000) == 0x00b40000)
|
|
ad -= 45 * 4;
|
|
}
|
|
}
|
|
else {
|
|
d = get_long(ad); ad += 4;
|
|
if ((d & 0xff000000) != 0) {
|
|
if ((d & 0x00ff0000) == 0x00180000)
|
|
ad += 6 * 4;
|
|
else if ((d & 0x00ff0000) == 0x00380000)
|
|
ad += 14 * 4;
|
|
else if ((d & 0x00ff0000) == 0x00b40000)
|
|
ad += 45 * 4;
|
|
}
|
|
}
|
|
if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
|
|
if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad;
|
|
}
|
|
|
|
void
|
|
fpp_opp(uae_u32 opcode, uae_u16 extra)
|
|
{
|
|
int reg;
|
|
double src;
|
|
|
|
#if DEBUG_FPP
|
|
printf("FPP %04lx %04x at %08lx\n",opcode & 0xffff,extra & 0xffff,
|
|
m68k_getpc()-4);fflush(stdout);
|
|
#endif
|
|
switch ((extra >> 13) & 0x7) {
|
|
case 3:
|
|
if (put_fp_value(regs.fp[(extra >> 7) & 7], opcode, extra)== 0){
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
}
|
|
return;
|
|
case 4:
|
|
case 5:
|
|
if ((opcode & 0x38) == 0) {
|
|
if (extra & 0x2000) {
|
|
if (extra & 0x1000)
|
|
m68k_dreg(regs, opcode & 7) = regs.fpcr;
|
|
if (extra & 0x0800)
|
|
m68k_dreg(regs, opcode & 7) = regs.fpsr;
|
|
if (extra & 0x0400)
|
|
m68k_dreg(regs, opcode & 7) = regs.fpiar;
|
|
}
|
|
else {
|
|
if (extra & 0x1000)
|
|
regs.fpcr = m68k_dreg(regs, opcode & 7);
|
|
if (extra & 0x0800)
|
|
regs.fpsr = m68k_dreg(regs, opcode & 7);
|
|
if (extra & 0x0400)
|
|
regs.fpiar = m68k_dreg(regs, opcode & 7);
|
|
}
|
|
}
|
|
else if ((opcode & 0x38) == 1) {
|
|
if (extra & 0x2000) {
|
|
if (extra & 0x1000)
|
|
m68k_areg(regs, opcode & 7) = regs.fpcr;
|
|
if (extra & 0x0800)
|
|
m68k_areg(regs, opcode & 7) = regs.fpsr;
|
|
if (extra & 0x0400)
|
|
m68k_areg(regs, opcode & 7) = regs.fpiar;
|
|
}
|
|
else {
|
|
if (extra & 0x1000)
|
|
regs.fpcr = m68k_areg(regs, opcode & 7);
|
|
if (extra & 0x0800)
|
|
regs.fpsr = m68k_areg(regs, opcode & 7);
|
|
if (extra & 0x0400)
|
|
regs.fpiar = m68k_areg(regs, opcode & 7);
|
|
}
|
|
}
|
|
else if ((opcode & 0x3f) == 0x3c) {
|
|
if ((extra & 0x2000) == 0) {
|
|
if (extra & 0x1000)
|
|
regs.fpcr = nextilong();
|
|
if (extra & 0x0800)
|
|
regs.fpsr = nextilong();
|
|
if (extra & 0x0400)
|
|
regs.fpiar = nextilong();
|
|
}
|
|
}
|
|
else if (extra & 0x2000) {
|
|
/* FMOVEM FPP->memory */
|
|
uae_u32 ad;
|
|
int incr = 0;
|
|
|
|
if (get_fp_ad(opcode,&ad) == 0) {
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
return;
|
|
}
|
|
if ((opcode & 0x38) == 0x20) {
|
|
if (extra & 0x1000) incr += 4;
|
|
if (extra & 0x0800) incr += 4;
|
|
if (extra & 0x0400) incr += 4;
|
|
}
|
|
ad -= incr;
|
|
if (extra & 0x1000) {
|
|
put_long(ad,regs.fpcr);ad+=4;
|
|
}
|
|
if (extra & 0x0800) {
|
|
put_long(ad,regs.fpsr);ad+=4;
|
|
}
|
|
if (extra & 0x0400) {
|
|
put_long(ad,regs.fpiar);ad+=4;
|
|
}
|
|
ad -= incr;
|
|
if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
|
|
if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad;
|
|
}
|
|
else {
|
|
/* FMOVEM memory->FPP */
|
|
uae_u32 ad;
|
|
|
|
if (get_fp_ad(opcode,&ad) == 0) {
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
return;
|
|
}
|
|
ad = (opcode & 0x38) == 0x20 ? ad-12 : ad;
|
|
if (extra & 0x1000) {
|
|
regs.fpcr = get_long(ad);ad+=4;
|
|
}
|
|
if (extra & 0x0800) {
|
|
regs.fpsr = get_long(ad);ad+=4;
|
|
}
|
|
if (extra & 0x0400) {
|
|
regs.fpiar = get_long(ad);ad+=4;
|
|
}
|
|
if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
|
|
if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad-12;
|
|
}
|
|
return;
|
|
case 6:
|
|
case 7:
|
|
{
|
|
uae_u32 ad,list = 0;
|
|
int incr = 0;
|
|
if (extra & 0x2000) {
|
|
/* FMOVEM FPP->memory */
|
|
if (get_fp_ad(opcode,&ad) == 0) {
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
return;
|
|
}
|
|
switch ((extra >> 11) & 3) {
|
|
case 0: /* static pred */
|
|
list = extra & 0xff;
|
|
incr = -1;
|
|
break;
|
|
case 1: /* dynamic pred */
|
|
list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
|
|
incr = -1;
|
|
break;
|
|
case 2: /* static postinc */
|
|
list = extra & 0xff;
|
|
incr = 1;
|
|
break;
|
|
case 3: /* dynamic postinc */
|
|
list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
|
|
incr = 1;
|
|
break;
|
|
}
|
|
while (list) {
|
|
uae_u32 wrd1,wrd2,wrd3;
|
|
if (incr < 0) {
|
|
from_exten(
|
|
regs.fp[fpp_movem_index2[list]],
|
|
&wrd1,&wrd2,&wrd3);
|
|
ad-=4;put_long(ad,wrd3);
|
|
ad-=4;put_long(ad,wrd2);
|
|
ad-=4;put_long(ad,wrd1);
|
|
}
|
|
else {
|
|
from_exten(
|
|
regs.fp[fpp_movem_index1[list]],
|
|
&wrd1,&wrd2,&wrd3);
|
|
put_long(ad,wrd1);ad+=4;
|
|
put_long(ad,wrd2);ad+=4;
|
|
put_long(ad,wrd3);ad+=4;
|
|
}
|
|
list = fpp_movem_next[list];
|
|
}
|
|
if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
|
|
if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad;
|
|
}
|
|
else {
|
|
/* FMOVEM memory->FPP */
|
|
if (get_fp_ad(opcode,&ad) == 0) {
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
return;
|
|
}
|
|
switch ((extra >> 11) & 3) {
|
|
case 0: /* static pred */
|
|
list = extra & 0xff;
|
|
incr = -1;
|
|
break;
|
|
case 1: /* dynamic pred */
|
|
list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
|
|
incr = -1;
|
|
break;
|
|
case 2: /* static postinc */
|
|
list = extra & 0xff;
|
|
incr = 1;
|
|
break;
|
|
case 3: /* dynamic postinc */
|
|
list = m68k_dreg(regs, (extra >> 4) & 3) & 0xff;
|
|
incr = 1;
|
|
break;
|
|
}
|
|
while (list) {
|
|
uae_u32 wrd1,wrd2,wrd3;
|
|
if (incr < 0) {
|
|
ad-=4;wrd3 = get_long(ad);
|
|
ad-=4;wrd2 = get_long(ad);
|
|
ad-=4;wrd1 = get_long(ad);
|
|
regs.fp[fpp_movem_index2[list]] =
|
|
to_exten(wrd1,wrd2,wrd3);
|
|
}
|
|
else {
|
|
wrd1 = get_long(ad);ad+=4;
|
|
wrd2 = get_long(ad);ad+=4;
|
|
wrd3 = get_long(ad);ad+=4;
|
|
regs.fp[fpp_movem_index1[list]] =
|
|
to_exten(wrd1,wrd2,wrd3);
|
|
}
|
|
list = fpp_movem_next[list];
|
|
}
|
|
if ((opcode & 0x38) == 0x18) m68k_areg(regs, opcode & 7) = ad;
|
|
if ((opcode & 0x38) == 0x20) m68k_areg(regs, opcode & 7) = ad;
|
|
}
|
|
}
|
|
return;
|
|
case 0:
|
|
case 2:
|
|
reg = (extra >> 7) & 7;
|
|
if ((extra & 0xfc00) == 0x5c00) {
|
|
switch (extra & 0x7f) {
|
|
case 0x00: regs.fp[reg] = 4.0*atan(1.0); break;
|
|
case 0x0b: regs.fp[reg] = log10(2.0); break;
|
|
case 0x0c: regs.fp[reg] = exp(1.0); break;
|
|
case 0x0d: regs.fp[reg] = log(exp(1.0))/log(2.0); break;
|
|
case 0x0e: regs.fp[reg] = log(exp(1.0))/log(10.0); break;
|
|
case 0x0f: regs.fp[reg] = 0.0; break;
|
|
case 0x30: regs.fp[reg] = log(2.0); break;
|
|
case 0x31: regs.fp[reg] = log(10.0); break;
|
|
case 0x32: regs.fp[reg] = 1.0e0; break;
|
|
case 0x33: regs.fp[reg] = 1.0e1; break;
|
|
case 0x34: regs.fp[reg] = 1.0e2; break;
|
|
case 0x35: regs.fp[reg] = 1.0e4; break;
|
|
case 0x36: regs.fp[reg] = 1.0e8; break;
|
|
case 0x37: regs.fp[reg] = 1.0e16; break;
|
|
case 0x38: regs.fp[reg] = 1.0e32; break;
|
|
case 0x39: regs.fp[reg] = 1.0e64; break;
|
|
case 0x3a: regs.fp[reg] = 1.0e128; break;
|
|
case 0x3b: regs.fp[reg] = 1.0e256; break;
|
|
#if 0
|
|
case 0x3c: regs.fp[reg] = 1.0e512; break;
|
|
case 0x3d: regs.fp[reg] = 1.0e1024; break;
|
|
case 0x3e: regs.fp[reg] = 1.0e2048; break;
|
|
case 0x3f: regs.fp[reg] = 1.0e4096; break;
|
|
#endif
|
|
default:
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
if (get_fp_value(opcode, extra, &src) == 0) {
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
return;
|
|
}
|
|
switch (extra & 0x7f) {
|
|
case 0x00: /* FMOVE */
|
|
regs.fp[reg] = src;
|
|
break;
|
|
case 0x01: /* FINT */
|
|
regs.fp[reg] = (int)(src + 0.5);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x02: /* FSINH */
|
|
regs.fp[reg] = sinh(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x03: /* FINTRZ */
|
|
regs.fp[reg] = (int)src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x04: /* FSQRT */
|
|
regs.fp[reg] = sqrt(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x06: /* FLOGNP1 */
|
|
regs.fp[reg] = log(src + 1.0);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x08: /* FETOXM1 */
|
|
regs.fp[reg] = exp(src) - 1.0;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x09: /* FTANH */
|
|
regs.fp[reg] = tanh(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x0a: /* FATAN */
|
|
regs.fp[reg] = atan(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x0c: /* FASIN */
|
|
regs.fp[reg] = asin(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x0d: /* FATANH */
|
|
#if 1 /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */
|
|
regs.fp[reg] = log((1+src)/(1-src))/2;
|
|
#else
|
|
regs.fp[reg] = atanh(src);
|
|
#endif
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x0e: /* FSIN */
|
|
regs.fp[reg] = sin(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x0f: /* FTAN */
|
|
regs.fp[reg] = tan(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x10: /* FETOX */
|
|
regs.fp[reg] = exp(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x11: /* FTWOTOX */
|
|
regs.fp[reg] = pow(2.0,src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x12: /* FTENTOX */
|
|
regs.fp[reg] = pow(10.0,src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x14: /* FLOGN */
|
|
regs.fp[reg] = log(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x15: /* FLOG10 */
|
|
regs.fp[reg] = log10(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x16: /* FLOG2 */
|
|
regs.fp[reg] = log(src) / log(2.0);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x18: /* FABS */
|
|
regs.fp[reg] = src < 0 ? -src : src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x19: /* FCOSH */
|
|
regs.fp[reg] = cosh(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x1a: /* FNEG */
|
|
regs.fp[reg] = -src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x1c: /* FACOS */
|
|
regs.fp[reg] = acos(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x1d: /* FCOS */
|
|
regs.fp[reg] = cos(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x1e: /* FGETEXP */
|
|
{ int expon;
|
|
frexp(src,&expon);
|
|
regs.fp[reg] = (double)(expon-1);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
}
|
|
break;
|
|
case 0x1f: /* FGETMAN */
|
|
{ int expon;
|
|
regs.fp[reg] = frexp(src,&expon) * 2.0;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
}
|
|
break;
|
|
case 0x20: /* FDIV */
|
|
regs.fp[reg] /= src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x21: /* FMOD */
|
|
regs.fp[reg] = regs.fp[reg] -
|
|
(double)((int)(regs.fp[reg] / src)) * src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x22: /* FADD */
|
|
regs.fp[reg] += src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x23: /* FMUL */
|
|
regs.fp[reg] *= src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x24: /* FSGLDIV */
|
|
regs.fp[reg] /= src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x25: /* FREM */
|
|
regs.fp[reg] = regs.fp[reg] -
|
|
(double)((int)(regs.fp[reg] / src + 0.5)) * src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x26: /* FSCALE */
|
|
regs.fp[reg] *= exp(log(2.0)*src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x27: /* FSGLMUL */
|
|
regs.fp[reg] *= src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x28: /* FSUB */
|
|
regs.fp[reg] -= src;
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x30: /* FSINCOS */
|
|
case 0x31:
|
|
case 0x32:
|
|
case 0x33:
|
|
case 0x34:
|
|
case 0x35:
|
|
case 0x36:
|
|
case 0x37:
|
|
regs.fp[reg] = sin(src);
|
|
regs.fp[extra & 7] = cos(src);
|
|
regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
|
|
(regs.fp[reg] < 0 ? 0x8000000 : 0);
|
|
break;
|
|
case 0x38: /* FCMP */
|
|
{ double tmp = regs.fp[reg] - src;
|
|
regs.fpsr = (tmp == 0 ? 0x4000000 : 0) |
|
|
(tmp < 0 ? 0x8000000 : 0);
|
|
}
|
|
break;
|
|
case 0x3a: /* FTST */
|
|
regs.fpsr = (src == 0 ? 0x4000000 : 0) |
|
|
(src < 0 ? 0x8000000 : 0);
|
|
break;
|
|
default:
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
m68k_setpc(m68k_getpc()-2);
|
|
op_illg(opcode);
|
|
}
|
|
|
|
#endif
|