680x0 FPU update: [R. Belmont]
- Implemented FMOVECR - Added load extended PC relative indexed support - Cleanup some duplicated code
This commit is contained in:
parent
7a934a8506
commit
3ec8f605b4
3 changed files with 132 additions and 29 deletions
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
145
m68kfpu.c
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue