Added JIT FPU, removed Softfloat option (too slow to be useful) - Thanks TomB!
This commit is contained in:
parent
f24301e8dd
commit
a8815b211e
55 changed files with 3579 additions and 10940 deletions
|
@ -8,7 +8,7 @@
|
|||
* Modified 2005 Peter Keunecke
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "sysconfig.h"
|
||||
#include "sysdeps.h"
|
||||
|
@ -18,41 +18,794 @@
|
|||
#include "custom.h"
|
||||
#include "newcpu.h"
|
||||
#include "compemu.h"
|
||||
#include "flags_arm.h"
|
||||
|
||||
#if defined(JIT)
|
||||
|
||||
extern void fpp_to_exten(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3);
|
||||
|
||||
static const int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
|
||||
static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
|
||||
|
||||
/* return the required floating point precision or -1 for failure, 0=E, 1=S, 2=D */
|
||||
STATIC_INLINE int comp_fp_get (uae_u32 opcode, uae_u16 extra, int treg)
|
||||
{
|
||||
int reg = opcode & 7;
|
||||
int mode = (opcode >> 3) & 7;
|
||||
int size = (extra >> 10) & 7;
|
||||
|
||||
if ((size == 2 && (mode != 7 || reg != 4)) || size == 3 || size == 7) /* 2 = long double, 3 = packed decimal, 7 is not defined */
|
||||
return -1;
|
||||
switch (mode) {
|
||||
case 0: /* Dn */
|
||||
switch (size) {
|
||||
case 0: /* Long */
|
||||
fmov_l_rr (treg, reg);
|
||||
return 2;
|
||||
case 1: /* Single */
|
||||
fmov_s_rr (treg, reg);
|
||||
return 1;
|
||||
case 4: /* Word */
|
||||
fmov_w_rr (treg, reg);
|
||||
return 1;
|
||||
case 6: /* Byte */
|
||||
fmov_b_rr (treg, reg);
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
case 1: /* An, invalid mode */
|
||||
return -1;
|
||||
case 2: /* (An) */
|
||||
mov_l_rr (S1, reg + 8);
|
||||
break;
|
||||
case 3: /* (An)+ */
|
||||
mov_l_rr (S1, reg + 8);
|
||||
arm_ADD_l_ri8(reg + 8, (reg == 7 ? sz2[size] : sz1[size]));
|
||||
break;
|
||||
case 4: /* -(An) */
|
||||
arm_SUB_l_ri8(reg + 8, (reg == 7 ? sz2[size] : sz1[size]));
|
||||
mov_l_rr (S1, reg + 8);
|
||||
break;
|
||||
case 5: /* (d16,An) */
|
||||
{
|
||||
uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_rr (S1, reg + 8);
|
||||
lea_l_brr (S1, S1, off);
|
||||
break;
|
||||
}
|
||||
case 6: /* (d8,An,Xn) or (bd,An,Xn) or ([bd,An,Xn],od) or ([bd,An],Xn,od) */
|
||||
{
|
||||
uae_u32 dp = comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
calc_disp_ea_020 (reg + 8, dp, S1, S2);
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
switch (reg) {
|
||||
case 0: /* (xxx).W */
|
||||
{
|
||||
uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_ri (S1, off);
|
||||
break;
|
||||
}
|
||||
case 1: /* (xxx).L */
|
||||
{
|
||||
uae_u32 off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
mov_l_ri (S1, off);
|
||||
break;
|
||||
}
|
||||
case 2: /* (d16,PC) */
|
||||
{
|
||||
uae_u32 address = start_pc + ((uae_char*) comp_pc_p - (uae_char*) start_pc_p) +
|
||||
m68k_pc_offset;
|
||||
uae_s32 PC16off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_ri (S1, address + PC16off);
|
||||
break;
|
||||
}
|
||||
case 3: /* (d8,PC,Xn) or (bd,PC,Xn) or ([bd,PC,Xn],od) or ([bd,PC],Xn,od) */
|
||||
return -1; /* rarely used, fallback to non-JIT */
|
||||
case 4: /* # < data >; Constants should be converted just once by the JIT */
|
||||
m68k_pc_offset += sz2[size];
|
||||
switch (size) {
|
||||
case 0:
|
||||
{
|
||||
uae_s32 li = comp_get_ilong(m68k_pc_offset - 4);
|
||||
float si = (float)li;
|
||||
|
||||
if (li == (int)si) {
|
||||
//write_log ("converted immediate LONG constant to SINGLE\n");
|
||||
fmov_s_ri(treg, *(uae_u32 *)&si);
|
||||
return 1;
|
||||
}
|
||||
//write_log ("immediate LONG constant\n");
|
||||
fmov_l_ri(treg, *(uae_u32 *)&li);
|
||||
return 2;
|
||||
}
|
||||
case 1:
|
||||
//write_log (_T("immediate SINGLE constant\n"));
|
||||
fmov_s_ri(treg, comp_get_ilong(m68k_pc_offset - 4));
|
||||
return 1;
|
||||
case 2:
|
||||
{
|
||||
//write_log (_T("immediate LONG DOUBLE constant\n"));
|
||||
uae_u32 wrd1, wrd2, wrd3;
|
||||
fpdata tmp;
|
||||
wrd3 = comp_get_ilong(m68k_pc_offset - 4);
|
||||
wrd2 = comp_get_ilong(m68k_pc_offset - 8);
|
||||
wrd1 = comp_get_iword(m68k_pc_offset - 12) << 16;
|
||||
fpp_to_exten(&tmp, wrd1, wrd2, wrd3);
|
||||
mov_l_ri(S1, ((uae_u32*)&tmp)[0]);
|
||||
mov_l_ri(S2, ((uae_u32*)&tmp)[1]);
|
||||
fmov_d_rrr (treg, S1, S2);
|
||||
return 0;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
float si = (float)(uae_s16)comp_get_iword(m68k_pc_offset-2);
|
||||
|
||||
//write_log (_T("converted immediate WORD constant %f to SINGLE\n"), si);
|
||||
fmov_s_ri(treg, *(uae_u32 *)&si);
|
||||
return 1;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
//write_log (_T("immediate DOUBLE constant\n"));
|
||||
mov_l_ri(S1, comp_get_ilong(m68k_pc_offset - 4));
|
||||
mov_l_ri(S2, comp_get_ilong(m68k_pc_offset - 8));
|
||||
fmov_d_rrr (treg, S1, S2);
|
||||
return 2;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
float si = (float)(uae_s8)comp_get_ibyte(m68k_pc_offset - 2);
|
||||
|
||||
//write_log (_T("converted immediate BYTE constant to SINGLE\n"));
|
||||
fmov_s_ri(treg, *(uae_u32 *)&si);
|
||||
return 1;
|
||||
}
|
||||
default: /* never reached */
|
||||
return -1;
|
||||
}
|
||||
default: /* never reached */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case 0: /* Long */
|
||||
readlong (S1, S2, S3);
|
||||
fmov_l_rr (treg, S2);
|
||||
return 2;
|
||||
case 1: /* Single */
|
||||
readlong (S1, S2, S3);
|
||||
fmov_s_rr (treg, S2);
|
||||
return 1;
|
||||
case 4: /* Word */
|
||||
readword (S1, S2, S3);
|
||||
fmov_w_rr (treg, S2);
|
||||
return 1;
|
||||
case 5: /* Double */
|
||||
readlong (S1, S2, S3);
|
||||
add_l_ri (S1, 4);
|
||||
readlong (S1, S4, S3);
|
||||
fmov_d_rrr (treg, S4, S2);
|
||||
return 2;
|
||||
case 6: /* Byte */
|
||||
readbyte (S1, S2, S3);
|
||||
fmov_b_rr (treg, S2);
|
||||
return 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* return of -1 means failure, >=0 means OK */
|
||||
STATIC_INLINE int comp_fp_put (uae_u32 opcode, uae_u16 extra)
|
||||
{
|
||||
int reg = opcode & 7;
|
||||
int sreg = (extra >> 7) & 7;
|
||||
int mode = (opcode >> 3) & 7;
|
||||
int size = (extra >> 10) & 7;
|
||||
|
||||
if (size == 2 || size == 3 || size == 7) /* 2 = long double, 3 = packed decimal, 7 is not defined */
|
||||
return -1;
|
||||
switch (mode) {
|
||||
case 0: /* Dn */
|
||||
switch (size) {
|
||||
case 0: /* FMOVE.L FPx, Dn */
|
||||
fmov_to_l_rr(reg, sreg);
|
||||
return 0;
|
||||
case 1: /* FMOVE.S FPx, Dn */
|
||||
fmov_to_s_rr(reg, sreg);
|
||||
return 0;
|
||||
case 4: /* FMOVE.W FPx, Dn */
|
||||
fmov_to_w_rr(reg, sreg);
|
||||
return 0;
|
||||
case 6: /* FMOVE.B FPx, Dn */
|
||||
fmov_to_b_rr(reg, sreg);
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
case 1: /* An, invalid mode */
|
||||
return -1;
|
||||
case 2: /* (An) */
|
||||
mov_l_rr (S1, reg + 8);
|
||||
break;
|
||||
case 3: /* (An)+ */
|
||||
mov_l_rr (S1, reg + 8);
|
||||
arm_ADD_l_ri8(reg + 8, (reg == 7 ? sz2[size] : sz1[size]));
|
||||
break;
|
||||
case 4: /* -(An) */
|
||||
arm_SUB_l_ri8(reg + 8, (reg == 7 ? sz2[size] : sz1[size]));
|
||||
mov_l_rr (S1, reg + 8);
|
||||
break;
|
||||
case 5: /* (d16,An) */
|
||||
{
|
||||
uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_rr (S1, reg + 8);
|
||||
add_l_ri (S1, off);
|
||||
break;
|
||||
}
|
||||
case 6: /* (d8,An,Xn) or (bd,An,Xn) or ([bd,An,Xn],od) or ([bd,An],Xn,od) */
|
||||
{
|
||||
uae_u32 dp = comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
calc_disp_ea_020 (reg + 8, dp, S1, S2);
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
switch (reg) {
|
||||
case 0: /* (xxx).W */
|
||||
{
|
||||
uae_u32 off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_ri (S1, off);
|
||||
break;
|
||||
}
|
||||
case 1: /* (xxx).L */
|
||||
{
|
||||
uae_u32 off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
mov_l_ri (S1, off);
|
||||
break;
|
||||
}
|
||||
default: /* All other modes are not allowed for FPx to <EA> */
|
||||
write_log (_T ("JIT FMOVE FPx,<EA> Mode is not allowed %04x %04x\n"), opcode, extra);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
switch (size) {
|
||||
case 0: /* Long */
|
||||
fmov_to_l_rr(S2, sreg);
|
||||
writelong_clobber (S1, S2, S3);
|
||||
return 0;
|
||||
case 1: /* Single */
|
||||
fmov_to_s_rr(S2, sreg);
|
||||
writelong_clobber (S1, S2, S3);
|
||||
return 0;
|
||||
case 4: /* Word */
|
||||
fmov_to_w_rr(S2, sreg);
|
||||
writeword (S1, S2, S3);
|
||||
return 0;
|
||||
case 5: /* Double */
|
||||
fmov_to_d_rrr(S2, S3, sreg);
|
||||
writelong_clobber (S1, S3, S4);
|
||||
add_l_ri (S1, 4);
|
||||
writelong_clobber (S1, S2, S4);
|
||||
return 0;
|
||||
case 6: /* Byte */
|
||||
fmov_to_b_rr(S2, sreg);
|
||||
writebyte (S1, S2, S3);
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* return -1 for failure, or register number for success */
|
||||
STATIC_INLINE int comp_fp_adr (uae_u32 opcode)
|
||||
{
|
||||
uae_s32 off;
|
||||
int mode = (opcode >> 3) & 7;
|
||||
int reg = opcode & 7;
|
||||
|
||||
switch (mode) {
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
mov_l_rr (S1, 8 + reg);
|
||||
return S1;
|
||||
case 5:
|
||||
off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_rr (S1, 8 + reg);
|
||||
add_l_ri (S1, off);
|
||||
return S1;
|
||||
case 7:
|
||||
switch (reg) {
|
||||
case 0:
|
||||
off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
mov_l_ri (S1, off);
|
||||
return S1;
|
||||
case 1:
|
||||
off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
mov_l_ri (S1, off);
|
||||
return S1;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void comp_fdbcc_opp (uae_u32 opcode, uae_u16 extra)
|
||||
{
|
||||
printf("comp_fdbcc_opp not yet implemented\n");
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
|
||||
void comp_fscc_opp (uae_u32 opcode, uae_u16 extra)
|
||||
{
|
||||
printf("comp_fscc_opp not yet implemented\n");
|
||||
//printf("comp_fscc_opp() called (0x%04x, 0x%04x)\n", opcode, extra);
|
||||
if (!currprefs.compfpu) {
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
|
||||
void comp_ftrapcc_opp (uae_u32 opcode, uaecptr oldpc)
|
||||
{
|
||||
printf("comp_ftrapcc_opp not yet implemented\n");
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
|
||||
void comp_fbcc_opp (uae_u32 opcode)
|
||||
{
|
||||
printf("comp_fbcc_opp not yet implemented\n");
|
||||
uae_u32 start_68k_offset = m68k_pc_offset;
|
||||
uae_u32 off, v1, v2;
|
||||
int cc;
|
||||
|
||||
if (!currprefs.compfpu) {
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (opcode & 0x20) { /* only cc from 00 to 1f are defined */
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
if (!(opcode & 0x40)) {
|
||||
off = (uae_s32) (uae_s16) comp_get_iword ((m68k_pc_offset += 2) - 2);
|
||||
}
|
||||
else {
|
||||
off = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
}
|
||||
|
||||
/* according to fpp.c, the 0x10 bit is ignored
|
||||
(it handles exception handling, which we don't
|
||||
do, anyway ;-) */
|
||||
cc = opcode & 0x0f;
|
||||
if(cc == 0)
|
||||
return; /* jump never */
|
||||
|
||||
/* Note, "off" will sometimes be (unsigned) "negative", so the following
|
||||
* uintptr can be > 0xffffffff, but the result will be correct due to
|
||||
* wraparound when truncated to 32 bit in the call to mov_l_ri. */
|
||||
mov_l_ri(S1, (uintptr)
|
||||
(comp_pc_p + off - (m68k_pc_offset - start_68k_offset)));
|
||||
mov_l_ri(PC_P, (uintptr) comp_pc_p);
|
||||
|
||||
/* Now they are both constant. Might as well fold in m68k_pc_offset */
|
||||
add_l_ri (S1, m68k_pc_offset);
|
||||
add_l_ri (PC_P, m68k_pc_offset);
|
||||
m68k_pc_offset = 0;
|
||||
|
||||
v1 = get_const (PC_P);
|
||||
v2 = get_const (S1);
|
||||
fflags_into_flags ();
|
||||
|
||||
switch (cc) {
|
||||
case 1: register_branch (v1, v2, NATIVE_CC_EQ); break;
|
||||
case 2: register_branch (v1, v2, NATIVE_CC_F_OGT); break;
|
||||
case 3: register_branch (v1, v2, NATIVE_CC_F_OGE); break;
|
||||
case 4: register_branch (v1, v2, NATIVE_CC_F_OLT); break;
|
||||
case 5: register_branch (v1, v2, NATIVE_CC_F_OLE); break;
|
||||
case 6: register_branch (v1, v2, NATIVE_CC_F_OGL); break;
|
||||
case 7: register_branch (v1, v2, NATIVE_CC_F_OR); break;
|
||||
case 8: register_branch (v1, v2, NATIVE_CC_F_UN); break;
|
||||
case 9: register_branch (v1, v2, NATIVE_CC_F_UEQ); break;
|
||||
case 10: register_branch (v1, v2, NATIVE_CC_F_UGT); break;
|
||||
case 11: register_branch (v1, v2, NATIVE_CC_F_UGE); break;
|
||||
case 12: register_branch (v1, v2, NATIVE_CC_F_ULT); break;
|
||||
case 13: register_branch (v1, v2, NATIVE_CC_F_ULE); break;
|
||||
case 14: register_branch (v1, v2, NATIVE_CC_NE); break;
|
||||
case 15: register_branch (v2, v2, NATIVE_CC_AL); break;
|
||||
}
|
||||
}
|
||||
|
||||
void comp_fsave_opp (uae_u32 opcode)
|
||||
{
|
||||
printf("comp_fsave_opp not yet implemented\n");
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
|
||||
void comp_frestore_opp (uae_u32 opcode)
|
||||
{
|
||||
printf("comp_frestore_opp not yet implemented\n");
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
|
||||
static uae_u32 dhex_pi[] ={0x54442D18, 0x400921FB};
|
||||
static uae_u32 dhex_exp_1[] ={0x8B145769, 0x4005BF0A};
|
||||
static uae_u32 dhex_l2_e[] ={0x652B82FE, 0x3FF71547};
|
||||
static uae_u32 dhex_ln_2[] ={0xFEFA39EF, 0x3FE62E42};
|
||||
static uae_u32 dhex_ln_10[] ={0xBBB55516, 0x40026BB1};
|
||||
static uae_u32 dhex_l10_2[] ={0x509F79FF, 0x3FD34413};
|
||||
static uae_u32 dhex_l10_e[] ={0x1526E50E, 0x3FDBCB7B};
|
||||
static uae_u32 dhex_1e16[] ={0x37E08000, 0x4341C379};
|
||||
static uae_u32 dhex_1e32[] ={0xB5056E17, 0x4693B8B5};
|
||||
static uae_u32 dhex_1e64[] ={0xE93FF9F5, 0x4D384F03};
|
||||
static uae_u32 dhex_1e128[] ={0xF9301D32, 0x5A827748};
|
||||
static uae_u32 dhex_1e256[] ={0x7F73BF3C, 0x75154FDD};
|
||||
static uae_u32 dhex_inf[] ={0x00000000, 0x7ff00000};
|
||||
static uae_u32 dhex_nan[] ={0xffffffff, 0x7fffffff};
|
||||
extern double fp_1e8;
|
||||
|
||||
void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
|
||||
{
|
||||
printf("comp_fpp_opp not yet implemented\n");
|
||||
int reg;
|
||||
int sreg, prec = 0;
|
||||
int dreg = (extra >> 7) & 7;
|
||||
int source = (extra >> 13) & 7;
|
||||
int opmode = extra & 0x7f;
|
||||
|
||||
if (!currprefs.compfpu) {
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
switch (source) {
|
||||
case 3: /* FMOVE FPx, <EA> */
|
||||
if (comp_fp_put (opcode, extra) < 0)
|
||||
FAIL (1);
|
||||
return;
|
||||
case 4: /* FMOVE.L <EA>, ControlReg */
|
||||
if (!(opcode & 0x30)) { /* Dn or An */
|
||||
if (extra & 0x1000) { /* FPCR */
|
||||
mov_l_mr (uae_p32(®s.fpcr), opcode & 15);
|
||||
return;
|
||||
}
|
||||
if (extra & 0x0800) { /* FPSR */
|
||||
FAIL (1);
|
||||
return;
|
||||
// set_fpsr(m68k_dreg (regs, opcode & 15));
|
||||
}
|
||||
if (extra & 0x0400) { /* FPIAR */
|
||||
mov_l_mr (uae_p32(®s.fpiar), opcode & 15); return;
|
||||
}
|
||||
}
|
||||
else if ((opcode & 0x3f) == 0x3c) {
|
||||
if (extra & 0x1000) { /* FPCR */
|
||||
uae_u32 val = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
mov_l_mi (uae_p32(®s.fpcr), val);
|
||||
return;
|
||||
}
|
||||
if (extra & 0x0800) { /* FPSR */
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
if (extra & 0x0400) { /* FPIAR */
|
||||
uae_u32 val = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
mov_l_mi (uae_p32(®s.fpiar), val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
FAIL (1);
|
||||
return;
|
||||
case 5: /* FMOVE.L ControlReg, <EA> */
|
||||
if (!(opcode & 0x30)) { /* Dn or An */
|
||||
if (extra & 0x1000) { /* FPCR */
|
||||
mov_l_rm (opcode & 15, uae_p32(®s.fpcr)); return;
|
||||
}
|
||||
if (extra & 0x0800) { /* FPSR */
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
if (extra & 0x0400) { /* FPIAR */
|
||||
mov_l_rm (opcode & 15, uae_p32(®s.fpiar)); return;
|
||||
}
|
||||
}
|
||||
FAIL (1);
|
||||
return;
|
||||
case 6:
|
||||
case 7:
|
||||
FAIL (1);
|
||||
return;
|
||||
case 2: /* from <EA> to FPx */
|
||||
dont_care_fflags ();
|
||||
if ((extra & 0xfc00) == 0x5c00) { /* FMOVECR */
|
||||
//write_log (_T("JIT FMOVECR %x\n"), opmode);
|
||||
switch (opmode) {
|
||||
case 0x00:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_pi));
|
||||
break;
|
||||
case 0x0b:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_l10_2));
|
||||
break;
|
||||
case 0x0c:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_exp_1));
|
||||
break;
|
||||
case 0x0d:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_l2_e));
|
||||
break;
|
||||
case 0x0e:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_l10_e));
|
||||
break;
|
||||
case 0x0f:
|
||||
fmov_d_ri_0 (dreg);
|
||||
break;
|
||||
case 0x30:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_ln_2));
|
||||
break;
|
||||
case 0x31:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_ln_10));
|
||||
break;
|
||||
case 0x32:
|
||||
fmov_d_ri_1 (dreg);
|
||||
break;
|
||||
case 0x33:
|
||||
fmov_d_ri_10 (dreg);
|
||||
break;
|
||||
case 0x34:
|
||||
fmov_d_ri_100 (dreg);
|
||||
break;
|
||||
case 0x35:
|
||||
fmov_l_ri (dreg, 10000);
|
||||
break;
|
||||
case 0x36:
|
||||
fmov_rm (dreg, uae_p32(&fp_1e8));
|
||||
break;
|
||||
case 0x37:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_1e16));
|
||||
break;
|
||||
case 0x38:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_1e32));
|
||||
break;
|
||||
case 0x39:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_1e64));
|
||||
break;
|
||||
case 0x3a:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_1e128));
|
||||
break;
|
||||
case 0x3b:
|
||||
fmov_d_rm (dreg, uae_p32(&dhex_1e256));
|
||||
break;
|
||||
default:
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
fmov_rr (FP_RESULT, dreg);
|
||||
return;
|
||||
}
|
||||
if (opmode & 0x20) /* two operands, so we need a scratch reg */
|
||||
sreg = FS1;
|
||||
else /* one operand only, thus we can load the argument into dreg */
|
||||
sreg = dreg;
|
||||
if ((prec = comp_fp_get (opcode, extra, sreg)) < 0) {
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
if (!opmode) { /* FMOVE <EA>,FPx */
|
||||
fmov_rr (FP_RESULT, dreg);
|
||||
return;
|
||||
}
|
||||
/* no break here for <EA> to dreg */
|
||||
case 0: /* directly from sreg to dreg */
|
||||
if (!source) { /* no <EA> */
|
||||
dont_care_fflags ();
|
||||
sreg = (extra >> 10) & 7;
|
||||
}
|
||||
switch (opmode) {
|
||||
case 0x00: /* FMOVE */
|
||||
fmov_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x01: /* FINT */
|
||||
frndint_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x02: /* FSINH */
|
||||
ffunc_rr (sinh, dreg, sreg);
|
||||
break;
|
||||
case 0x03: /* FINTRZ */
|
||||
frndintz_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x04: /* FSQRT */
|
||||
fsqrt_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x06: /* FLOGNP1 */
|
||||
ffunc_rr (log1p, dreg, sreg);
|
||||
break;
|
||||
case 0x08: /* FETOXM1 */
|
||||
ffunc_rr (expm1, dreg, sreg);
|
||||
break;
|
||||
case 0x09: /* FTANH */
|
||||
ffunc_rr (tanh, dreg, sreg);
|
||||
break;
|
||||
case 0x0a: /* FATAN */
|
||||
ffunc_rr (atan, dreg, sreg);
|
||||
break;
|
||||
case 0x0c: /* FASIN */
|
||||
ffunc_rr (asin, dreg, sreg);
|
||||
break;
|
||||
case 0x0d: /* FATANH */
|
||||
ffunc_rr (atanh, dreg, sreg);
|
||||
break;
|
||||
case 0x0e: /* FSIN */
|
||||
ffunc_rr (sin, dreg, sreg);
|
||||
break;
|
||||
case 0x0f: /* FTAN */
|
||||
ffunc_rr (tan, dreg, sreg);
|
||||
break;
|
||||
case 0x10: /* FETOX */
|
||||
ffunc_rr (exp, dreg, sreg);
|
||||
break;
|
||||
case 0x11: /* FTWOTOX */
|
||||
fpowx_rr (2, dreg, sreg);
|
||||
break;
|
||||
case 0x12: /* FTENTOX */
|
||||
fpowx_rr (10, dreg, sreg);
|
||||
break;
|
||||
case 0x14: /* FLOGN */
|
||||
ffunc_rr (log, dreg, sreg);
|
||||
break;
|
||||
case 0x15: /* FLOG10 */
|
||||
ffunc_rr (log10, dreg, sreg);
|
||||
break;
|
||||
case 0x16: /* FLOG2 */
|
||||
ffunc_rr (log2, dreg, sreg);
|
||||
break;
|
||||
case 0x18: /* FABS */
|
||||
fabs_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x19: /* FCOSH */
|
||||
ffunc_rr (cosh, dreg, sreg);
|
||||
break;
|
||||
case 0x1a: /* FNEG */
|
||||
fneg_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x1c: /* FACOS */
|
||||
ffunc_rr (acos, dreg, sreg);
|
||||
break;
|
||||
case 0x1d: /* FCOS */
|
||||
ffunc_rr (cos, dreg, sreg);
|
||||
break;
|
||||
case 0x20: /* FDIV */
|
||||
fdiv_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x21: /* FMOD */
|
||||
fmod_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x22: /* FADD */
|
||||
fadd_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x23: /* FMUL */
|
||||
fmul_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x24: /* FSGLDIV */
|
||||
fsgldiv_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x60: /* FSDIV */
|
||||
fdiv_rr (dreg, sreg);
|
||||
if (!currprefs.fpu_strict) /* faster, but less strict rounding */
|
||||
break;
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x25: /* FREM */
|
||||
frem1_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x27: /* FSGLMUL */
|
||||
fsglmul_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x63: /* FSMUL */
|
||||
fmul_rr (dreg, sreg);
|
||||
if (!currprefs.fpu_strict) /* faster, but less strict rounding */
|
||||
break;
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x28: /* FSUB */
|
||||
fsub_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x30: /* FSINCOS */
|
||||
case 0x31:
|
||||
case 0x32:
|
||||
case 0x33:
|
||||
case 0x34:
|
||||
case 0x35:
|
||||
case 0x36:
|
||||
case 0x37:
|
||||
if (dreg == (extra & 7))
|
||||
ffunc_rr (sin, dreg, sreg);
|
||||
else
|
||||
fsincos_rr (dreg, extra & 7, sreg);
|
||||
break;
|
||||
case 0x38: /* FCMP */
|
||||
fmov_rr (FP_RESULT, dreg);
|
||||
fsub_rr (FP_RESULT, sreg);
|
||||
return;
|
||||
case 0x3a: /* FTST */
|
||||
fmov_rr (FP_RESULT, sreg);
|
||||
return;
|
||||
case 0x40: /* FSMOVE */
|
||||
if (prec == 1 || !currprefs.fpu_strict) {
|
||||
if (sreg != dreg) /* no <EA> */
|
||||
fmov_rr (dreg, sreg);
|
||||
}
|
||||
else {
|
||||
fmovs_rr (dreg, sreg);
|
||||
}
|
||||
break;
|
||||
case 0x44: /* FDMOVE */
|
||||
if (sreg != dreg) /* no <EA> */
|
||||
fmov_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x41: /* FSSQRT */
|
||||
fsqrt_rr (dreg, sreg);
|
||||
if (!currprefs.fpu_strict) /* faster, but less strict rounding */
|
||||
break;
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x45: /* FDSQRT */
|
||||
fsqrt_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x58: /* FSABS */
|
||||
fabs_rr (dreg, sreg);
|
||||
if (prec != 1 && currprefs.fpu_strict)
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x5a: /* FSNEG */
|
||||
fneg_rr (dreg, sreg);
|
||||
if (prec != 1 && currprefs.fpu_strict)
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x5c: /* FDABS */
|
||||
fabs_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x5e: /* FDNEG */
|
||||
fneg_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x62: /* FSADD */
|
||||
fadd_rr (dreg, sreg);
|
||||
if (!currprefs.fpu_strict) /* faster, but less strict rounding */
|
||||
break;
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x64: /* FDDIV */
|
||||
fdiv_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x66: /* FDADD */
|
||||
fadd_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x67: /* FDMUL */
|
||||
fmul_rr (dreg, sreg);
|
||||
break;
|
||||
case 0x68: /* FSSUB */
|
||||
fsub_rr (dreg, sreg);
|
||||
if (!currprefs.fpu_strict) /* faster, but less strict rounding */
|
||||
break;
|
||||
fcuts_r (dreg);
|
||||
break;
|
||||
case 0x6c: /* FDSUB */
|
||||
fsub_rr (dreg, sreg);
|
||||
break;
|
||||
default:
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
fmov_rr (FP_RESULT, dreg);
|
||||
return;
|
||||
default:
|
||||
write_log (_T ("Unsupported JIT-FPU instruction: 0x%04x %04x\n"), opcode, extra);
|
||||
FAIL (1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue