680x0 FPU update: [R. Belmont]

- Implemented FMOVECR
 - Added load extended PC relative indexed support
 - Cleanup some duplicated code
This commit is contained in:
R. Belmont 2010-03-14 21:13:32 +00:00 committed by Emmanuel Anne
parent 7a934a8506
commit 3ec8f605b4
3 changed files with 132 additions and 29 deletions

View file

@ -88,6 +88,15 @@ typedef sint32 sint64;
typedef uint32 uint64;
#endif /* M68K_USE_64_BIT */
/* U64 and S64 are used to wrap long integer constants. */
#ifdef __GNUC__
#define U64(val) val##ULL
#define S64(val) val##LL
#else
#define U64(val) val
#define S64(val) val
#endif
#include "softfloat/milieu.h"
#include "softfloat/softfloat.h"

View file

@ -1713,6 +1713,13 @@ static void d68040_fpu(void)
src = (w2 >> 10) & 0x7;
dst_reg = (w2 >> 7) & 0x7;
// special override for FMOVECR
if ((((w2 >> 13) & 0x7) == 2) && (((w2>>10)&0x7) == 7))
{
sprintf(g_dasm_str, "fmovecr #$%0x, fp%d", (w2&0x7f), dst_reg);
return;
}
switch ((w2 >> 13) & 0x7)
{
case 0x0:

145
m68kfpu.c
View file

@ -601,6 +601,21 @@ static void WRITE_EA_64(int ea, uint64 data)
}
}
static inline floatx80 load_extended_float80(uint32 ea)
{
uint32 d1,d2;
uint16 d3;
floatx80 fp;
d3 = m68ki_read_16(ea);
d1 = m68ki_read_32(ea+4);
d2 = m68ki_read_32(ea+8);
fp.high = d3;
fp.low = ((uint64)d1<<32) | (d2 & 0xffffffff);
return fp;
}
static floatx80 READ_EA_FPE(int ea)
{
floatx80 fpr;
@ -611,36 +626,51 @@ static floatx80 READ_EA_FPE(int ea)
{
case 2: // (An)
{
uint32 d1,d2;
uint16 d3;
uint32 ea = REG_A[reg];
d3 = m68ki_read_16(ea);
d1 = m68ki_read_32(ea+4);
d2 = m68ki_read_32(ea+8);
fpr.high = d3;
fpr.low = ((uint64)d1<<32) | (d2 & 0xffffffff);
fpr = load_extended_float80(ea);
break;
}
case 3: // (An)+
{
uint32 d1,d2;
uint16 d3;
uint32 ea = REG_A[reg];
REG_A[reg] += 12;
d3 = m68ki_read_16(ea);
d1 = m68ki_read_32(ea+4);
d2 = m68ki_read_32(ea+8);
fpr.high = d3;
fpr.low = ((uint64)d1<<32) | (d2 & 0xffffffff);
fpr = load_extended_float80(ea);
break;
}
default: fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
case 7: // extended modes
{
switch (reg)
{
case 3: // (d16,PC,Dx.w)
{
uint32 ea = EA_PCIX_32();
fpr = load_extended_float80(ea);
}
break;
default:
fatalerror("M68kFPU: READ_EA_FPE0: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
break;
}
}
break;
default: fatalerror("M68kFPU: READ_EA_FPE1: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break;
}
return fpr;
}
static inline void store_extended_float80(uint32 ea, floatx80 fpr)
{
m68ki_write_16(ea+0, fpr.high);
m68ki_write_16(ea+2, 0);
m68ki_write_32(ea+4, (fpr.low>>32)&0xffffffff);
m68ki_write_32(ea+8, fpr.low&0xffffffff);
}
static void WRITE_EA_FPE(int ea, floatx80 fpr)
{
int mode = (ea >> 3) & 0x7;
@ -652,10 +682,7 @@ static void WRITE_EA_FPE(int ea, floatx80 fpr)
{
uint32 ea;
ea = REG_A[reg];
m68ki_write_16(ea+0, fpr.high);
m68ki_write_16(ea+2, 0);
m68ki_write_32(ea+4, (fpr.low>>32)&0xffffffff);
m68ki_write_32(ea+8, fpr.low&0xffffffff);
store_extended_float80(ea, fpr);
break;
}
@ -663,10 +690,7 @@ static void WRITE_EA_FPE(int ea, floatx80 fpr)
{
uint32 ea;
ea = REG_A[reg];
m68ki_write_16(ea+0, fpr.high);
m68ki_write_16(ea+2, 0);
m68ki_write_32(ea+4, (fpr.low>>32)&0xffffffff);
m68ki_write_32(ea+8, fpr.low&0xffffffff);
store_extended_float80(ea, fpr);
REG_A[reg] += 12;
break;
}
@ -676,10 +700,7 @@ static void WRITE_EA_FPE(int ea, floatx80 fpr)
uint32 ea;
REG_A[reg] -= 12;
ea = REG_A[reg];
m68ki_write_16(ea+0, fpr.high);
m68ki_write_16(ea+2, 0);
m68ki_write_32(ea+4, (fpr.low>>32)&0xffffffff);
m68ki_write_32(ea+8, fpr.low&0xffffffff);
store_extended_float80(ea, fpr);
break;
}
@ -687,7 +708,6 @@ static void WRITE_EA_FPE(int ea, floatx80 fpr)
{
switch (reg)
{
case 3: // (d8,PC,Xn)
default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
}
}
@ -706,6 +726,8 @@ static void fpgen_rm_reg(uint16 w2)
int opmode = w2 & 0x7f;
floatx80 source;
// fmovecr #$f, fp0 f200 5c0f
if (rm)
{
switch (src)
@ -751,7 +773,72 @@ static void fpgen_rm_reg(uint16 w2)
source = int32_to_floatx80((sint32)d);
break;
}
default: fatalerror("fmove_rm_reg: invalid source specifier at %08X\n", REG_PC-4);
case 7: // FMOVECR load from constant ROM
{
switch (w2 & 0x7f)
{
case 0x0: // Pi
source.high = 0x4000;
source.low = U64(0xc90fdaa22168c235);
break;
case 0xb: // log10(2)
source.high = 0x3ffd;
source.low = U64(0x9a209a84fbcff798);
break;
case 0xc: // e
source.high = 0x4000;
source.low = U64(0xadf85458a2bb4a9b);
break;
case 0xd: // log2(e)
source.high = 0x3fff;
source.low = U64(0xb8aa3b295c17f0bc);
break;
case 0xe: // log10(e)
source.high = 0x3ffd;
source.low = U64(0xde5bd8a937287195);
break;
case 0xf: // 0.0
source = int32_to_floatx80((sint32)0);
break;
case 0x30: // ln(2)
source.high = 0x3ffe;
source.low = U64(0xb17217f7d1cf79ac);
break;
case 0x31: // ln(10)
source.high = 0x4000;
source.low = U64(0x935d8dddaaa8ac17);
break;
case 0x32: // 1 (or 100? manuals are unclear, but 1 would make more sense)
source = int32_to_floatx80((sint32)1);
break;
case 0x33: // 10^1
source = int32_to_floatx80((sint32)10);
break;
case 0x34: // 10^2
source = int32_to_floatx80((sint32)10*10);
break;
default:
fatalerror("fmove_rm_reg: unknown constant ROM offset %x at %08x\n", w2&0x7f, REG_PC-4);
break;
}
// handle it right here, the usual opmode bits aren't valid in the FMOVECR case
REG_FP[dst] = source;
USE_CYCLES(4);
return;
}
default: fatalerror("fmove_rm_reg: invalid source specifier %x at %08X\n", src, REG_PC-4);
}
}
else