Fixed JIT FPU bugs (Starstruck demo corruption, etc.)
This commit is contained in:
parent
88316d7916
commit
b9dc57af87
14 changed files with 1735 additions and 121 deletions
|
@ -943,6 +943,48 @@ STATIC_INLINE void compemu_raw_jcc_l_oponly(int cc)
|
|||
// emit of target will be done by caller
|
||||
}
|
||||
|
||||
STATIC_INLINE void compemu_raw_handle_except(IMM cycles)
|
||||
{
|
||||
uae_u32* branchadd;
|
||||
|
||||
clobber_flags();
|
||||
|
||||
MOVW_ri16(REG_WORK2, (uae_u32)(&jit_exception));
|
||||
MOVT_ri16(REG_WORK2, ((uae_u32)(&jit_exception)) >> 16);
|
||||
LDR_rR(REG_WORK1, REG_WORK2);
|
||||
TST_rr(REG_WORK1, REG_WORK1);
|
||||
BNE_i(1); // exception, skip LDR and target
|
||||
|
||||
LDR_rRI(RPC_INDEX, RPC_INDEX, -4); // jump to next opcode
|
||||
branchadd = (uae_u32*)get_target();
|
||||
skip_long(); // emit of target (next opcode handler) will be done later
|
||||
|
||||
// countdown -= scaled_cycles(totcycles);
|
||||
uae_s32 offs = (uae_u32)&countdown - (uae_u32)®s;
|
||||
LDR_rRI(REG_WORK1, R_REGSTRUCT, offs);
|
||||
if(CHECK32(cycles)) {
|
||||
SUBS_rri(REG_WORK1, REG_WORK1, cycles);
|
||||
} else {
|
||||
#ifdef ARMV6T2
|
||||
MOVW_ri16(REG_WORK2, cycles);
|
||||
if(cycles >> 16)
|
||||
MOVT_ri16(REG_WORK2, cycles >> 16);
|
||||
#else
|
||||
int offs2 = data_long_offs(cycles);
|
||||
LDR_rRI(REG_WORK2, RPC_INDEX, offs2);
|
||||
#endif
|
||||
SUBS_rrr(REG_WORK1, REG_WORK1, REG_WORK2);
|
||||
}
|
||||
STR_rRI(REG_WORK1, R_REGSTRUCT, offs);
|
||||
|
||||
LDR_rRI(RPC_INDEX, RPC_INDEX, -4); // <popall_execute_exception>
|
||||
emit_long((uintptr)popall_execute_exception);
|
||||
|
||||
// Write target of next instruction
|
||||
write_jmp_target(branchadd, (cpuop_func*)get_target());
|
||||
|
||||
}
|
||||
|
||||
STATIC_INLINE void compemu_raw_jl(uae_u32 t)
|
||||
{
|
||||
#ifdef ARMV6T2
|
||||
|
@ -1185,8 +1227,7 @@ LOWFUNC(NONE,NONE,2,raw_fmov_to_w_rr,(W4 d, FR s))
|
|||
{
|
||||
VCVTR64toI_sd(SCRATCH_F32_1, s);
|
||||
VMOV32_rs(REG_WORK1, SCRATCH_F32_1);
|
||||
SSAT_rir(REG_WORK1, 15, REG_WORK1);
|
||||
BFI_rrii(d, REG_WORK1, 0, 15);
|
||||
SSAT_rir(d, 15, REG_WORK1);
|
||||
}
|
||||
LENDFUNC(NONE,NONE,2,raw_fmov_to_w_rr,(W4 d, FR s))
|
||||
|
||||
|
@ -1194,8 +1235,7 @@ LOWFUNC(NONE,NONE,2,raw_fmov_to_b_rr,(W4 d, FR s))
|
|||
{
|
||||
VCVTR64toI_sd(SCRATCH_F32_1, s);
|
||||
VMOV32_rs(REG_WORK1, SCRATCH_F32_1);
|
||||
SSAT_rir(REG_WORK1, 7, REG_WORK1);
|
||||
BFI_rrii(d, REG_WORK1, 0, 7);
|
||||
SSAT_rir(d, 7, REG_WORK1);
|
||||
}
|
||||
LENDFUNC(NONE,NONE,2,raw_fmov_to_b_rr,(W4 d, FR s))
|
||||
|
||||
|
@ -1343,7 +1383,7 @@ LOWFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s))
|
|||
|
||||
VMRS_r(REG_WORK2);
|
||||
UBFX_rrii(REG_WORK1, REG_WORK1, 22, 2);
|
||||
BFI_rrii(REG_WORK2, REG_WORK1, 22, 2);
|
||||
BFI_rrii(REG_WORK2, REG_WORK1, 22, 23);
|
||||
VMSR_r(REG_WORK2);
|
||||
}
|
||||
LENDFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s))
|
||||
|
@ -1425,7 +1465,7 @@ LOWFUNC(NONE,WRITE,2,raw_fp_from_exten_mr,(RR4 adr, FR s))
|
|||
ADD_rrr(REG_WORK1, adr, REG_WORK1);
|
||||
|
||||
REV_rr(REG_WORK3, REG_WORK3);
|
||||
STR_rR(REG_WORK3, REG_WORK1); // write exponent
|
||||
STRH_rR(REG_WORK3, REG_WORK1); // write exponent
|
||||
|
||||
VSHL64_ddi(SCRATCH_F64_1, s, 11); // shift mantissa to correct position
|
||||
VMOV64_rrd(REG_WORK3, REG_WORK2, SCRATCH_F64_1);
|
||||
|
@ -1494,7 +1534,7 @@ LOWFUNC(NONE,READ,2,raw_fp_to_exten_rm,(FW d, RR4 adr))
|
|||
MOVW_ri16(REG_WORK1, 15360); // diff of bias between double and long double
|
||||
SUB_rrr(REG_WORK3, REG_WORK3, REG_WORK1); // exponent done, ToDo: check for carry -> result gets Inf in double
|
||||
UBFX_rrii(REG_WORK2, REG_WORK2, 15, 1); // extract sign
|
||||
BFI_rrii(REG_WORK3, REG_WORK2, 11, 1); // insert sign
|
||||
BFI_rrii(REG_WORK3, REG_WORK2, 11, 11); // insert sign
|
||||
VSHR64_ddi(d, d, 11); // shift mantissa to correct position
|
||||
LSL_rri(REG_WORK3, REG_WORK3, 20);
|
||||
VMOV_I64_dimmI(0, 0x00);
|
||||
|
@ -1503,7 +1543,7 @@ LOWFUNC(NONE,READ,2,raw_fp_to_exten_rm,(FW d, RR4 adr))
|
|||
// end_of_op
|
||||
|
||||
}
|
||||
LENDFUNC(NONE,READ,2,raw_fp_from_exten_mr,(FW d, RR4 adr))
|
||||
LENDFUNC(NONE,READ,2,raw_fp_to_exten_rm,(FW d, RR4 adr))
|
||||
|
||||
STATIC_INLINE void raw_fflags_into_flags(int r)
|
||||
{
|
||||
|
@ -1621,4 +1661,13 @@ LOWFUNC(NONE,NONE,2,raw_fp_fscc_ri,(RW4 d, int cc))
|
|||
}
|
||||
LENDFUNC(NONE,NONE,2,raw_fp_fscc_ri,(RW4 d, int cc))
|
||||
|
||||
LOWFUNC(NONE,NONE,1,raw_roundingmode,(IMM mode))
|
||||
{
|
||||
VMRS_r(REG_WORK1);
|
||||
BIC_rri(REG_WORK1, REG_WORK1, 0x00c00000);
|
||||
ORR_rri(REG_WORK1, REG_WORK1, mode);
|
||||
VMSR_r(REG_WORK1);
|
||||
}
|
||||
LENDFUNC(NONE,NONE,1,raw_roundingmode,(IMM mode))
|
||||
|
||||
#endif // USE_JIT_FPU
|
||||
|
|
|
@ -1401,11 +1401,17 @@ enum {
|
|||
#define CC_VCVT32toI_ss(cc,Sd,Sm) _W(((cc) << 28) | (0xe << 24) | (0xb << 20) | (0xd << 16) | (0xa << 8) | (0xc << 4) | MAKE_Sd(Sd) | MAKE_Sm(Sm))
|
||||
#define VCVT32toI_ss(Sd,Sm) CC_VCVT32toI_ss(NATIVE_CC_AL,Sd,Sm)
|
||||
|
||||
#define CC_VCVT64toIu_sd(cc,Sd,Dm) _W(((cc) << 28) | (0xe << 24) | (0xb << 20) | (0xd << 16) | (0xb << 8) | (0xc << 4) | MAKE_Sd(Sd) | MAKE_Dm(Dm))
|
||||
#define VCVT64toIu_sd(Sd,Dm) CC_VCVT64toIu_sd(NATIVE_CC_AL,Sd,Dm)
|
||||
|
||||
#define CC_VCVTIto64_ds(cc,Dd,Sm) _W(((cc) << 28) | (0xe << 24) | (0xb << 20) | (0x8 << 16) | (0xb << 8) | (0xc << 4) | MAKE_Dd(Dd) | MAKE_Sm(Sm))
|
||||
#define VCVTIto64_ds(Dd,Sm) CC_VCVTIto64_ds(NATIVE_CC_AL,Dd,Sm)
|
||||
#define CC_VCVTIto32_ss(cc,Sd,Sm) _W(((cc) << 28) | (0xe << 24) | (0xb << 20) | (0x8 << 16) | (0xa << 8) | (0xc << 4) | MAKE_Sd(Sd) | MAKE_Sm(Sm))
|
||||
#define VCVTIto32_ss(Sd,Sm) CC_VCVTIto32_ss(NATIVE_CC_AL,Dd,Sm)
|
||||
|
||||
#define CC_VCVTIuto64_ds(cc,Dd,Sm) _W(((cc) << 28) | (0xe << 24) | (0xb << 20) | (0x8 << 16) | (0xb << 8) | (0x4 << 4) | MAKE_Dd(Dd) | MAKE_Sm(Sm))
|
||||
#define VCVTIuto64_ds(Dd,Sm) CC_VCVTIuto64_ds(NATIVE_CC_AL,Dd,Sm)
|
||||
|
||||
#define CC_VADD64_ddd(cc,Dd,Dn,Dm) _W(((cc) << 28) | (0xe << 24) | (0x3 << 20) | (0xb << 8) | (0x0 << 4) | MAKE_Dd(Dd) | MAKE_Dn(Dn) | MAKE_Dm(Dm))
|
||||
#define VADD64_ddd(Dd,Dn,Dm) CC_VADD64_ddd(NATIVE_CC_AL,Dd,Dn,Dm)
|
||||
#define CC_VADD32_sss(cc,Sd,Sn,Sm) _W(((cc) << 28) | (0xe << 24) | (0x3 << 20) | (0xa << 8) | (0x0 << 4) | MAKE_Sd(Sd) | MAKE_Sn(Sn) | MAKE_Sm(Sm))
|
||||
|
@ -1481,6 +1487,6 @@ enum {
|
|||
#define VSHL64_ddi(Dd,Dm,imm) _W((0xf << 28) | (0x2 << 24) | (0x8 << 20) | (0x5 << 8) | (0x9 << 4) | MAKE_Dd(Dd) | MAKE_Dm(Dm) | FIMM6(imm))
|
||||
#define VSHR64_ddi(Dd,Dm,imm) _W((0xf << 28) | (0x3 << 24) | (0x8 << 20) | (0x0 << 8) | (0x9 << 4) | MAKE_Dd(Dd) | MAKE_Dm(Dm) | FIMM6(64-imm))
|
||||
|
||||
#define VORR_ddd(Dd,Dn,Dm) _W((0xf << 28) | (0x2 << 24) | (0x2 << 20) | (0x1 << 8) | (0x1 << 4) | MAKE_Dd(Dd) | MAKE_Dm(Dn) | MAKE_Dm(Dm))
|
||||
#define VORR_ddd(Dd,Dn,Dm) _W((0xf << 28) | (0x2 << 24) | (0x2 << 20) | (0x1 << 8) | (0x1 << 4) | MAKE_Dd(Dd) | MAKE_Dn(Dn) | MAKE_Dm(Dm))
|
||||
|
||||
#endif /* ARM_RTASM_H */
|
||||
|
|
1254
src/jit/compemu.cpp
1254
src/jit/compemu.cpp
File diff suppressed because it is too large
Load diff
|
@ -129,7 +129,6 @@ typedef union {
|
|||
#endif
|
||||
#define N_FREGS 16 // We use 10 regs: 6 - FP_RESULT, 7 - SCRATCH, 8-15 - Amiga regs FP0-FP7
|
||||
|
||||
|
||||
/* Functions exposed to newcpu, or to what was moved from newcpu.c to
|
||||
* compemu_support.c */
|
||||
extern void compiler_exit(void);
|
||||
|
@ -332,6 +331,7 @@ extern void sync_m68k_pc(void);
|
|||
extern uae_u32 get_const(int r);
|
||||
extern int is_const(int r);
|
||||
extern void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond);
|
||||
extern void register_possible_exception(void);
|
||||
|
||||
#define comp_get_ibyte(o) do_get_mem_byte((uae_u8 *)(comp_pc_p + (o) + 1))
|
||||
#define comp_get_iword(o) do_get_mem_word((uae_u16 *)(comp_pc_p + (o)))
|
||||
|
@ -403,6 +403,7 @@ typedef struct blockinfo_t {
|
|||
void execute_normal(void);
|
||||
void exec_nostats(void);
|
||||
void do_nothing(void);
|
||||
void execute_exception(void);
|
||||
|
||||
/* ARAnyM uses fpu_register name, used in scratch_t */
|
||||
/* FIXME: check that no ARAnyM code assumes different floating point type */
|
||||
|
|
|
@ -497,6 +497,11 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
|
|||
int source = (extra >> 13) & 7;
|
||||
int opmode = extra & 0x7f;
|
||||
|
||||
if (special_mem) {
|
||||
FAIL(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currprefs.compfpu) {
|
||||
FAIL (1);
|
||||
return;
|
||||
|
@ -525,6 +530,25 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
|
|||
if (extra & 0x1000) { /* FPCR */
|
||||
uae_u32 val = comp_get_ilong ((m68k_pc_offset += 4) - 4);
|
||||
mov_l_mi (uae_p32(®s.fpcr), val);
|
||||
switch(val & 0x30) {
|
||||
case 0x00:
|
||||
// round to nearest
|
||||
roundingmode(0x00000000);
|
||||
break;
|
||||
case 0x10:
|
||||
// round toward minus infinity
|
||||
roundingmode(0x00800000);
|
||||
break;
|
||||
case 0x01:
|
||||
// round toward plus infinity
|
||||
roundingmode(0x00400000);
|
||||
break;
|
||||
case 0x11:
|
||||
default:
|
||||
// round towards zero
|
||||
roundingmode(0x00c00000);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (extra & 0x0800) { /* FPSR */
|
||||
|
@ -875,11 +899,6 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
|
|||
case 0x37:
|
||||
FAIL (1);
|
||||
return;
|
||||
// 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);
|
||||
|
|
|
@ -109,7 +109,7 @@ MIDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s))
|
|||
s = readreg(s, 2);
|
||||
d = writereg(d, 4);
|
||||
}
|
||||
else { /* If we try to lock this twice, with different sizes, we are int trouble! */
|
||||
else { /* If we try to lock this twice, with different sizes, we are in trouble! */
|
||||
s = d = rmw(s, 4, 2);
|
||||
}
|
||||
SIGNED16_REG_2_REG(d, s);
|
||||
|
@ -628,7 +628,7 @@ MENDFUNC(2,fmov_to_s_rr,(W4 d, FR s))
|
|||
MIDFUNC(2,fmov_to_w_rr,(W4 d, FR s))
|
||||
{
|
||||
s = f_readreg(s);
|
||||
d = rmw(d, 2, 4);
|
||||
d = writereg(d, 2);
|
||||
raw_fmov_to_w_rr(d, s);
|
||||
unlock2(d);
|
||||
f_unlock(s);
|
||||
|
@ -638,7 +638,7 @@ MENDFUNC(2,fmov_to_w_rr,(W4 d, FR s))
|
|||
MIDFUNC(2,fmov_to_b_rr,(W4 d, FR s))
|
||||
{
|
||||
s = f_readreg(s);
|
||||
d = rmw(d, 1, 4);
|
||||
d = writereg(d, 1);
|
||||
raw_fmov_to_b_rr(d, s);
|
||||
unlock2(d);
|
||||
f_unlock(s);
|
||||
|
@ -864,54 +864,48 @@ MENDFUNC(2,fmovs_rr,(FW d, FR s))
|
|||
MIDFUNC(3,ffunc_rr,(double (*func)(double), FW d, FR s))
|
||||
{
|
||||
clobber_flags();
|
||||
prepare_for_call_1();
|
||||
prepare_for_call_2();
|
||||
|
||||
s = f_readreg(s);
|
||||
d = f_writereg(d);
|
||||
int reald = f_writereg(d);
|
||||
|
||||
raw_ffunc_rr(func, d, s);
|
||||
prepare_for_call_1();
|
||||
|
||||
f_unlock(s);
|
||||
f_unlock(d);
|
||||
f_unlock(reald);
|
||||
|
||||
prepare_for_call_2();
|
||||
|
||||
raw_ffunc_rr(func, reald, s);
|
||||
|
||||
live.fat[reald].holds = d;
|
||||
live.fat[reald].nholds = 1;
|
||||
|
||||
live.fate[d].realreg = reald;
|
||||
live.fate[d].status = DIRTY;
|
||||
}
|
||||
MENDFUNC(3,ffunc_rr,(double (*func)(double), FW d, FR s))
|
||||
|
||||
//MIDFUNC(3,fsincos_rr,(FW d, FW c, FR s))
|
||||
//{
|
||||
// clobber_flags();
|
||||
// prepare_for_call_1();
|
||||
// prepare_for_call_2();
|
||||
//
|
||||
// s = f_readreg(s); /* s for source */
|
||||
// d = f_writereg(d); /* d for sine */
|
||||
// c = f_writereg(c); /* c for cosine */
|
||||
//
|
||||
// // s may be FS1, so we need to save it before we call external func
|
||||
//
|
||||
// raw_ffunc_rr(cos, c, s);
|
||||
// raw_ffunc_rr(sin, d, s);
|
||||
//
|
||||
// f_unlock(s);
|
||||
// f_unlock(d);
|
||||
// f_unlock(c);
|
||||
//}
|
||||
//MENDFUNC(3,fsincos_rr,(FW d, FW c, FR s))
|
||||
|
||||
MIDFUNC(3,fpowx_rr,(uae_u32 x, FW d, FR s))
|
||||
{
|
||||
clobber_flags();
|
||||
prepare_for_call_1();
|
||||
prepare_for_call_2();
|
||||
|
||||
s = f_readreg(s);
|
||||
d = f_writereg(d);
|
||||
int reald = f_writereg(d);
|
||||
|
||||
raw_fpowx_rr(x, d, s);
|
||||
prepare_for_call_1();
|
||||
|
||||
f_unlock(s);
|
||||
f_unlock(d);
|
||||
f_unlock(reald);
|
||||
|
||||
prepare_for_call_2();
|
||||
|
||||
raw_fpowx_rr(x, reald, s);
|
||||
|
||||
live.fat[reald].holds = d;
|
||||
live.fat[reald].nholds = 1;
|
||||
|
||||
live.fate[d].realreg = reald;
|
||||
live.fate[d].status = DIRTY;
|
||||
}
|
||||
MENDFUNC(3,fpowx_rr,(uae_u32 x, FW d, FR s))
|
||||
|
||||
|
@ -954,4 +948,11 @@ MIDFUNC(2,fp_fscc_ri,(RW4 d, int cc))
|
|||
}
|
||||
MENDFUNC(2,fp_fscc_ri,(RW4 d, int cc))
|
||||
|
||||
MIDFUNC(1,roundingmode,(IMM mode))
|
||||
{
|
||||
raw_roundingmode(mode);
|
||||
}
|
||||
MENDFUNC(1,roundingmode,(IMM mode))
|
||||
|
||||
|
||||
#endif // USE_JIT_FPU
|
||||
|
|
|
@ -111,3 +111,4 @@ DECLARE_MIDFUNC(fflags_into_flags());
|
|||
DECLARE_MIDFUNC(fp_from_exten_mr(RR4 adr, FR s));
|
||||
DECLARE_MIDFUNC(fp_to_exten_rm(FW d, RR4 adr));
|
||||
DECLARE_MIDFUNC(fp_fscc_ri(RW4, int cc));
|
||||
DECLARE_MIDFUNC(roundingmode(IMM mode));
|
||||
|
|
|
@ -1852,28 +1852,44 @@ MENDFUNC(2,jff_DBCC,(RR2 d, IMM cc))
|
|||
* C Always cleared.
|
||||
*
|
||||
*/
|
||||
// ToDo: How to handle exceptions (division by zero). Performance improvement isn't big, so this is on hold.
|
||||
MIDFUNC(3,jnf_DIVU,(W4 d, RR4 s1, RR4 s2))
|
||||
{
|
||||
s1 = readreg(s1, 4);
|
||||
s2 = readreg(s2, 4);
|
||||
d = writereg(d, 4);
|
||||
|
||||
VMOV32_sr(0, s1); // move to s0
|
||||
VMOV32_sr(1, s2); // move to s1
|
||||
VCVTIto64_ds(2, 0); // convert s0 to d2 (int to float)
|
||||
VCVTIto64_ds(3, 1); // convert s1 to d3 (int to float)
|
||||
VDIV64_ddd(4, 2, 3); // d4 = d2 / d3
|
||||
VCVT64toI_sd(0, 4); // convert d4 to s0 (float to int)
|
||||
VMOV32_rs(REG_WORK1, 0); // move from s0
|
||||
UNSIGNED16_REG_2_REG(REG_WORK3, s2);
|
||||
TST_rr(REG_WORK3, REG_WORK3);
|
||||
BNE_i(6); // src is not 0
|
||||
|
||||
// Signal exception 5
|
||||
MOV_ri(REG_WORK1, 5);
|
||||
MOVW_ri16(REG_WORK2, (uae_u32)(&jit_exception));
|
||||
MOVT_ri16(REG_WORK2, ((uae_u32)(&jit_exception)) >> 16);
|
||||
STR_rR(REG_WORK1, REG_WORK2);
|
||||
|
||||
// simplified flag handling for div0: set Z and V (for signed DIV: Z only)
|
||||
MOV_ri(REG_WORK1, ARM_Z_FLAG | ARM_V_FLAG);
|
||||
MSR_CPSRf_r(REG_WORK1);
|
||||
B_i(11); // end_of_op
|
||||
|
||||
// src is not 0
|
||||
VMOVi_from_ARM_dr(SCRATCH_F64_1, s1, 0);
|
||||
VMOVi_from_ARM_dr(SCRATCH_F64_2, REG_WORK3, 0);
|
||||
VCVTIuto64_ds(SCRATCH_F64_1, SCRATCH_F32_1);
|
||||
VCVTIuto64_ds(SCRATCH_F64_2, SCRATCH_F32_2);
|
||||
VDIV64_ddd(SCRATCH_F64_3, SCRATCH_F64_1, SCRATCH_F64_2);
|
||||
VCVT64toIu_sd(SCRATCH_F32_1, SCRATCH_F64_3);
|
||||
VMOVi_to_ARM_rd(REG_WORK1, SCRATCH_F64_1, 0);
|
||||
|
||||
LSRS_rri(REG_WORK2, REG_WORK1, 16); // if result of this is not 0, DIVU overflows -> no result
|
||||
BNE_i(2);
|
||||
|
||||
// Here we have to calc reminder
|
||||
MUL_rrr(REG_WORK2, REG_WORK1, s2);
|
||||
MUL_rrr(REG_WORK2, REG_WORK1, REG_WORK3);
|
||||
SUB_rrr(REG_WORK2, s1, REG_WORK2);
|
||||
PKHBT_rrrLSLi(d, REG_WORK1, REG_WORK2, 16);
|
||||
// end_of_op
|
||||
|
||||
unlock2(d);
|
||||
unlock2(s1);
|
||||
|
@ -1887,13 +1903,29 @@ MIDFUNC(3,jff_DIVU,(W4 d, RR4 s1, RR4 s2))
|
|||
s2 = readreg(s2, 4);
|
||||
d = writereg(d, 4);
|
||||
|
||||
VMOV32_sr(0, s1); // move to s0
|
||||
VMOV32_sr(1, s2); // move to s1
|
||||
VCVTIto64_ds(2, 0); // convert s0 to d2 (int to float)
|
||||
VCVTIto64_ds(3, 1); // convert s1 to d3 (int to float)
|
||||
VDIV64_ddd(4, 2, 3); // d4 = d2 / d3
|
||||
VCVT64toI_sd(0, 4); // convert d4 to s0 (float to int)
|
||||
VMOV32_rs(REG_WORK1, 0); // move from s0
|
||||
UNSIGNED16_REG_2_REG(REG_WORK3, s2);
|
||||
TST_rr(REG_WORK3, REG_WORK3);
|
||||
BNE_i(6); // src is not 0
|
||||
|
||||
// Signal exception 5
|
||||
MOV_ri(REG_WORK1, 5);
|
||||
MOVW_ri16(REG_WORK2, (uae_u32)(&jit_exception));
|
||||
MOVT_ri16(REG_WORK2, ((uae_u32)(&jit_exception)) >> 16);
|
||||
STR_rR(REG_WORK1, REG_WORK2);
|
||||
|
||||
// simplified flag handling for div0: set Z and V (for signed DIV: Z only)
|
||||
MOV_ri(REG_WORK1, ARM_Z_FLAG | ARM_V_FLAG);
|
||||
MSR_CPSRf_r(REG_WORK1);
|
||||
B_i(18); // end_of_op
|
||||
|
||||
// src is not 0
|
||||
VMOVi_from_ARM_dr(SCRATCH_F64_1, s1, 0);
|
||||
VMOVi_from_ARM_dr(SCRATCH_F64_2, REG_WORK3, 0);
|
||||
VCVTIuto64_ds(SCRATCH_F64_1, SCRATCH_F32_1);
|
||||
VCVTIuto64_ds(SCRATCH_F64_2, SCRATCH_F32_2);
|
||||
VDIV64_ddd(SCRATCH_F64_3, SCRATCH_F64_1, SCRATCH_F64_2);
|
||||
VCVT64toIu_sd(SCRATCH_F32_1, SCRATCH_F64_3);
|
||||
VMOVi_to_ARM_rd(REG_WORK1, SCRATCH_F64_1, 0);
|
||||
|
||||
LSRS_rri(REG_WORK2, REG_WORK1, 16); // if result of this is not 0, DIVU overflows
|
||||
BEQ_i(2);
|
||||
|
@ -1908,9 +1940,10 @@ MIDFUNC(3,jff_DIVU,(W4 d, RR4 s1, RR4 s2))
|
|||
BIC_rri(REG_WORK2, REG_WORK2, ARM_C_FLAG | ARM_V_FLAG);
|
||||
MSR_CPSRf_r(REG_WORK2);
|
||||
|
||||
MUL_rrr(REG_WORK2, REG_WORK1, s2);
|
||||
MUL_rrr(REG_WORK2, REG_WORK1, REG_WORK3);
|
||||
SUB_rrr(REG_WORK2, s1, REG_WORK2);
|
||||
PKHBT_rrrLSLi(d, REG_WORK1, REG_WORK2, 16);
|
||||
// end_of_op
|
||||
|
||||
unlock2(d);
|
||||
unlock2(s1);
|
||||
|
@ -1918,6 +1951,138 @@ MIDFUNC(3,jff_DIVU,(W4 d, RR4 s1, RR4 s2))
|
|||
}
|
||||
MENDFUNC(3,jff_DIVU,(W4 d, RR4 s1, RR4 s2))
|
||||
|
||||
/*
|
||||
* DIVS
|
||||
*
|
||||
* X Not affected.
|
||||
* N Set if the most significant bit of the result is set or overflow. Cleared otherwise.
|
||||
* Z Set if the result is zero. Cleared otherwise.
|
||||
* V Set if overflow. Cleared otherwise.
|
||||
* C Always cleared.
|
||||
*
|
||||
*/
|
||||
MIDFUNC(3,jnf_DIVS,(W4 d, RR4 s1, RR4 s2))
|
||||
{
|
||||
s1 = readreg(s1, 4);
|
||||
s2 = readreg(s2, 4);
|
||||
d = writereg(d, 4);
|
||||
|
||||
SIGNED16_REG_2_REG(REG_WORK3, s2);
|
||||
TST_rr(REG_WORK3, REG_WORK3);
|
||||
BNE_i(6); // src is not 0
|
||||
|
||||
// Signal exception 5
|
||||
MOV_ri(REG_WORK1, 5);
|
||||
MOVW_ri16(REG_WORK2, (uae_u32)(&jit_exception));
|
||||
MOVT_ri16(REG_WORK2, ((uae_u32)(&jit_exception)) >> 16);
|
||||
STR_rR(REG_WORK1, REG_WORK2);
|
||||
|
||||
// simplified flag handling for div0: set Z and V (for signed DIV: Z only)
|
||||
MOV_ri(REG_WORK1, ARM_Z_FLAG);
|
||||
MSR_CPSRf_r(REG_WORK1);
|
||||
B_i(18); // end_of_op
|
||||
|
||||
// src is not 0
|
||||
VMOVi_from_ARM_dr(SCRATCH_F64_1, s1, 0);
|
||||
VMOVi_from_ARM_dr(SCRATCH_F64_2, REG_WORK3, 0);
|
||||
VCVTIto64_ds(SCRATCH_F64_1, SCRATCH_F32_1);
|
||||
VCVTIto64_ds(SCRATCH_F64_2, SCRATCH_F32_2);
|
||||
VDIV64_ddd(SCRATCH_F64_3, SCRATCH_F64_1, SCRATCH_F64_2);
|
||||
VCVT64toI_sd(SCRATCH_F32_1, SCRATCH_F64_3);
|
||||
VMOVi_to_ARM_rd(REG_WORK1, SCRATCH_F64_1, 0);
|
||||
|
||||
// check for overflow
|
||||
MVN_ri(REG_WORK2, 0);
|
||||
LSL_rri(REG_WORK2, REG_WORK2, 15); // REG_WORK2 is now 0xffff8000
|
||||
ANDS_rrr(REG_WORK3, REG_WORK1, REG_WORK2);
|
||||
BEQ_i(1); // positive result, no overflow
|
||||
CMP_rr(REG_WORK3, REG_WORK2);
|
||||
BNE_i(5); // overflow -> end_of_op
|
||||
|
||||
// Here we have to calc reminder
|
||||
SIGNED16_REG_2_REG(REG_WORK3, s2);
|
||||
MUL_rrr(REG_WORK2, REG_WORK1, REG_WORK3);
|
||||
SUB_rrr(REG_WORK2, s1, REG_WORK2); // REG_WORK2 contains remainder
|
||||
|
||||
EORS_rrr(REG_WORK3, REG_WORK2, s1); // If sign of remainder and first operand differs, change sign of remainder
|
||||
CC_RSB_rri(NATIVE_CC_MI, REG_WORK2, REG_WORK2, 0);
|
||||
|
||||
PKHBT_rrrLSLi(d, REG_WORK1, REG_WORK2, 16);
|
||||
// end_of_op
|
||||
|
||||
unlock2(d);
|
||||
unlock2(s1);
|
||||
unlock2(s2);
|
||||
}
|
||||
MENDFUNC(3,jnf_DIVS,(W4 d, RR4 s1, RR4 s2))
|
||||
|
||||
MIDFUNC(3,jff_DIVS,(W4 d, RR4 s1, RR4 s2))
|
||||
{
|
||||
s1 = readreg(s1, 4);
|
||||
s2 = readreg(s2, 4);
|
||||
d = writereg(d, 4);
|
||||
|
||||
SIGNED16_REG_2_REG(REG_WORK3, s2);
|
||||
TST_rr(REG_WORK3, REG_WORK3);
|
||||
BNE_i(6); // src is not 0
|
||||
|
||||
// Signal exception 5
|
||||
MOV_ri(REG_WORK1, 5);
|
||||
MOVW_ri16(REG_WORK2, (uae_u32)(&jit_exception));
|
||||
MOVT_ri16(REG_WORK2, ((uae_u32)(&jit_exception)) >> 16);
|
||||
STR_rR(REG_WORK1, REG_WORK2);
|
||||
|
||||
// simplified flag handling for div0: set Z and V (for signed DIV: Z only)
|
||||
MOV_ri(REG_WORK1, ARM_Z_FLAG);
|
||||
MSR_CPSRf_r(REG_WORK1);
|
||||
B_i(25); // end_of_op
|
||||
|
||||
// src is not 0
|
||||
VMOVi_from_ARM_dr(SCRATCH_F64_1, s1, 0);
|
||||
VMOVi_from_ARM_dr(SCRATCH_F64_2, REG_WORK3, 0);
|
||||
VCVTIto64_ds(SCRATCH_F64_1, SCRATCH_F32_1);
|
||||
VCVTIto64_ds(SCRATCH_F64_2, SCRATCH_F32_2);
|
||||
VDIV64_ddd(SCRATCH_F64_3, SCRATCH_F64_1, SCRATCH_F64_2);
|
||||
VCVT64toI_sd(SCRATCH_F32_1, SCRATCH_F64_3);
|
||||
VMOVi_to_ARM_rd(REG_WORK1, SCRATCH_F64_1, 0);
|
||||
|
||||
// check for overflow
|
||||
MVN_ri(REG_WORK2, 0);
|
||||
LSL_rri(REG_WORK2, REG_WORK2, 15); // REG_WORK2 is now 0xffff8000
|
||||
ANDS_rrr(REG_WORK3, REG_WORK1, REG_WORK2);
|
||||
BEQ_i(4); // positive result, no overflow
|
||||
CMP_rr(REG_WORK3, REG_WORK2);
|
||||
BEQ_i(2); // no overflow
|
||||
|
||||
// Here we handle overflow
|
||||
MOV_ri(REG_WORK1, ARM_V_FLAG | ARM_N_FLAG);
|
||||
MSR_CPSRf_r(REG_WORK1);
|
||||
B_i(9);
|
||||
|
||||
// calc flags
|
||||
LSLS_rri(REG_WORK2, REG_WORK1, 16); // N and Z ok
|
||||
MRS_CPSR(REG_WORK2);
|
||||
BIC_rri(REG_WORK2, REG_WORK2, ARM_C_FLAG | ARM_V_FLAG);
|
||||
MSR_CPSRf_r(REG_WORK2);
|
||||
|
||||
// calc remainder
|
||||
SIGNED16_REG_2_REG(REG_WORK3, s2);
|
||||
MUL_rrr(REG_WORK2, REG_WORK1, REG_WORK3);
|
||||
SUB_rrr(REG_WORK2, s1, REG_WORK2); // REG_WORK2 contains remainder
|
||||
|
||||
EORS_rrr(REG_WORK3, REG_WORK2, s1); // If sign of remainder and first operand differs, change sign of remainder
|
||||
CC_RSB_rri(NATIVE_CC_MI, REG_WORK2, REG_WORK2, 0);
|
||||
|
||||
PKHBT_rrrLSLi(d, REG_WORK1, REG_WORK2, 16);
|
||||
|
||||
// end_of_op
|
||||
|
||||
unlock2(d);
|
||||
unlock2(s1);
|
||||
unlock2(s2);
|
||||
}
|
||||
MENDFUNC(3,jff_DIVS,(W4 d, RR4 s1, RR4 s2))
|
||||
|
||||
/*
|
||||
* EOR
|
||||
* Operand Syntax: Dn, <ea>
|
||||
|
@ -5114,7 +5279,7 @@ MIDFUNC(2,jnf_MEM_WRITE_OFF_b,(RR4 adr, RR4 b))
|
|||
LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
|
||||
|
||||
adr = readreg(adr, 4);
|
||||
b = readreg(b, 4);
|
||||
b = readreg(b, 1);
|
||||
|
||||
STRB_rRR(b, adr, REG_WORK2);
|
||||
|
||||
|
@ -5129,7 +5294,7 @@ MIDFUNC(2,jnf_MEM_WRITE_OFF_w,(RR4 adr, RR4 w))
|
|||
LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
|
||||
|
||||
adr = readreg(adr, 4);
|
||||
w = readreg(w, 4);
|
||||
w = readreg(w, 2);
|
||||
|
||||
REV16_rr(REG_WORK1, w);
|
||||
STRH_rRR(REG_WORK1, adr, REG_WORK2);
|
||||
|
@ -5162,7 +5327,7 @@ MIDFUNC(2,jnf_MEM_READ_OFF_b,(W4 d, RR4 adr))
|
|||
LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
|
||||
|
||||
adr = readreg(adr, 4);
|
||||
d = writereg(d, 4);
|
||||
d = writereg(d, 1);
|
||||
|
||||
LDRB_rRR(d, adr, REG_WORK2);
|
||||
|
||||
|
@ -5177,7 +5342,7 @@ MIDFUNC(2,jnf_MEM_READ_OFF_w,(W4 d, RR4 adr))
|
|||
LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
|
||||
|
||||
adr = readreg(adr, 4);
|
||||
d = writereg(d, 4);
|
||||
d = writereg(d, 2);
|
||||
|
||||
LDRH_rRR(REG_WORK1, adr, REG_WORK2);
|
||||
REV16_rr(d, REG_WORK1);
|
||||
|
@ -5210,7 +5375,7 @@ MIDFUNC(2,jnf_MEM_WRITE24_OFF_b,(RR4 adr, RR4 b))
|
|||
LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
|
||||
|
||||
adr = readreg(adr, 4);
|
||||
b = readreg(b, 4);
|
||||
b = readreg(b, 1);
|
||||
|
||||
BIC_rri(REG_WORK1, adr, 0xff000000);
|
||||
STRB_rRR(b, REG_WORK1, REG_WORK2);
|
||||
|
@ -5226,7 +5391,7 @@ MIDFUNC(2,jnf_MEM_WRITE24_OFF_w,(RR4 adr, RR4 w))
|
|||
LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
|
||||
|
||||
adr = readreg(adr, 4);
|
||||
w = readreg(w, 4);
|
||||
w = readreg(w, 2);
|
||||
|
||||
BIC_rri(REG_WORK1, adr, 0xff000000);
|
||||
REV16_rr(REG_WORK3, w);
|
||||
|
@ -5261,7 +5426,7 @@ MIDFUNC(2,jnf_MEM_READ24_OFF_b,(W4 d, RR4 adr))
|
|||
LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
|
||||
|
||||
adr = readreg(adr, 4);
|
||||
d = writereg(d, 4);
|
||||
d = writereg(d, 1);
|
||||
|
||||
BIC_rri(REG_WORK1, adr, 0xff000000);
|
||||
LDRB_rRR(d, REG_WORK1, REG_WORK2);
|
||||
|
@ -5277,7 +5442,7 @@ MIDFUNC(2,jnf_MEM_READ24_OFF_w,(W4 d, RR4 adr))
|
|||
LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
|
||||
|
||||
adr = readreg(adr, 4);
|
||||
d = writereg(d, 4);
|
||||
d = writereg(d, 2);
|
||||
|
||||
BIC_rri(REG_WORK1, adr, 0xff000000);
|
||||
LDRH_rRR(REG_WORK1, REG_WORK1, REG_WORK2);
|
||||
|
|
|
@ -161,6 +161,10 @@ DECLARE_MIDFUNC(jff_DBCC(RR2 d, IMM cc));
|
|||
DECLARE_MIDFUNC(jnf_DIVU(W4 d, RR4 s1, RR4 s2));
|
||||
DECLARE_MIDFUNC(jff_DIVU(W4 d, RR4 s1, RR4 s2));
|
||||
|
||||
// DIVS
|
||||
DECLARE_MIDFUNC(jnf_DIVS(W4 d, RR4 s1, RR4 s2));
|
||||
DECLARE_MIDFUNC(jff_DIVS(W4 d, RR4 s1, RR4 s2));
|
||||
|
||||
// EOR
|
||||
DECLARE_MIDFUNC(jnf_EOR(W4 d, RR4 s, RR4 v));
|
||||
DECLARE_MIDFUNC(jff_EOR_b(W4 d, RR1 s, RR1 v));
|
||||
|
|
|
@ -126,6 +126,10 @@ static int optcount[10] = {
|
|||
|
||||
op_properties prop[65536];
|
||||
|
||||
uae_u32 jit_exception = 0;
|
||||
bool may_raise_exception = false;
|
||||
|
||||
|
||||
STATIC_INLINE bool is_const_jump(uae_u32 opcode)
|
||||
{
|
||||
return (prop[opcode].cflow == fl_const_jump);
|
||||
|
@ -160,6 +164,7 @@ static void* popall_execute_normal = NULL;
|
|||
static void* popall_cache_miss = NULL;
|
||||
static void* popall_recompile_block = NULL;
|
||||
static void* popall_check_checksum = NULL;
|
||||
static void* popall_execute_exception = NULL;
|
||||
|
||||
/* The 68k only ever executes from even addresses. So right now, we
|
||||
* waste half the entries in this array
|
||||
|
@ -1393,7 +1398,6 @@ STATIC_INLINE void f_disassociate(int r)
|
|||
f_evict(r);
|
||||
}
|
||||
|
||||
|
||||
static int f_alloc_reg(int r, int willclobber)
|
||||
{
|
||||
int bestreg;
|
||||
|
@ -1651,6 +1655,8 @@ void init_comp(void)
|
|||
live.flags_in_flags = TRASH;
|
||||
live.flags_on_stack = VALID;
|
||||
live.flags_are_important = 1;
|
||||
|
||||
jit_exception = 0;
|
||||
}
|
||||
|
||||
/* Only do this if you really mean it! The next call should be to init!*/
|
||||
|
@ -1797,6 +1803,11 @@ void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond)
|
|||
branch_cc = cond;
|
||||
}
|
||||
|
||||
void register_possible_exception(void)
|
||||
{
|
||||
may_raise_exception = true;
|
||||
}
|
||||
|
||||
/* Note: get_handler may fail in 64 Bit environments, if direct_handler_to_use is
|
||||
* outside 32 bit
|
||||
*/
|
||||
|
@ -2379,6 +2390,12 @@ STATIC_INLINE void create_popalls(void)
|
|||
raw_pop_preserved_regs();
|
||||
compemu_raw_jmp(uae_p32(check_checksum));
|
||||
|
||||
align_target(align_jumps);
|
||||
popall_execute_exception = get_target();
|
||||
raw_inc_sp(stack_space);
|
||||
raw_pop_preserved_regs();
|
||||
compemu_raw_jmp(uae_p32(execute_exception));
|
||||
|
||||
#if defined(CPU_arm) && !defined(ARMV6T2)
|
||||
reset_data_buffer();
|
||||
#endif
|
||||
|
@ -2776,6 +2793,7 @@ void compile_block(cpu_history* pc_hist, int blocklen, int totcycles)
|
|||
was_comp = 1;
|
||||
|
||||
for (i = 0; i < blocklen && get_target_noopt() < MAX_COMPILE_PTR; i++) {
|
||||
may_raise_exception = false;
|
||||
cpuop_func **cputbl;
|
||||
compop_func **comptbl;
|
||||
uae_u32 opcode = DO_GET_OPCODE(pc_hist[i].location);
|
||||
|
@ -2845,6 +2863,9 @@ void compile_block(cpu_history* pc_hist, int blocklen, int totcycles)
|
|||
compemu_raw_jmp((uintptr)popall_do_nothing);
|
||||
*(branchadd - 4) = (((uintptr)get_target() - (uintptr)branchadd) - 4) >> 2;
|
||||
}
|
||||
} else if(may_raise_exception) {
|
||||
compemu_raw_handle_except(scaled_cycles(totcycles));
|
||||
may_raise_exception = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1246,17 +1246,17 @@ extern const struct comptbl op_smalltbl_0_comp_ff[] = {
|
|||
{ op_80ba_0_comp_ff, 0x00000002, 32954 }, /* OR */
|
||||
{ op_80bb_0_comp_ff, 0x00000002, 32955 }, /* OR */
|
||||
{ op_80bc_0_comp_ff, 0x00000002, 32956 }, /* OR */
|
||||
{ NULL, 0x00000001, 32960 }, /* DIVU */
|
||||
{ NULL, 0x00000001, 32976 }, /* DIVU */
|
||||
{ NULL, 0x00000001, 32984 }, /* DIVU */
|
||||
{ NULL, 0x00000001, 32992 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33000 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33008 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33016 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33017 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33018 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33019 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33020 }, /* DIVU */
|
||||
{ op_80c0_0_comp_ff, 0x00000000, 32960 }, /* DIVU */
|
||||
{ op_80d0_0_comp_ff, 0x00000000, 32976 }, /* DIVU */
|
||||
{ op_80d8_0_comp_ff, 0x00000000, 32984 }, /* DIVU */
|
||||
{ op_80e0_0_comp_ff, 0x00000000, 32992 }, /* DIVU */
|
||||
{ op_80e8_0_comp_ff, 0x00000002, 33000 }, /* DIVU */
|
||||
{ op_80f0_0_comp_ff, 0x00000002, 33008 }, /* DIVU */
|
||||
{ op_80f8_0_comp_ff, 0x00000002, 33016 }, /* DIVU */
|
||||
{ op_80f9_0_comp_ff, 0x00000002, 33017 }, /* DIVU */
|
||||
{ op_80fa_0_comp_ff, 0x00000002, 33018 }, /* DIVU */
|
||||
{ op_80fb_0_comp_ff, 0x00000002, 33019 }, /* DIVU */
|
||||
{ op_80fc_0_comp_ff, 0x00000002, 33020 }, /* DIVU */
|
||||
{ NULL, 0x00000000, 33024 }, /* SBCD */
|
||||
{ NULL, 0x00000000, 33032 }, /* SBCD */
|
||||
{ op_8110_0_comp_ff, 0x00000000, 33040 }, /* OR */
|
||||
|
@ -1284,17 +1284,17 @@ extern const struct comptbl op_smalltbl_0_comp_ff[] = {
|
|||
{ op_81b0_0_comp_ff, 0x00000002, 33200 }, /* OR */
|
||||
{ op_81b8_0_comp_ff, 0x00000002, 33208 }, /* OR */
|
||||
{ op_81b9_0_comp_ff, 0x00000002, 33209 }, /* OR */
|
||||
{ NULL, 0x00000001, 33216 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33232 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33240 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33248 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33256 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33264 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33272 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33273 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33274 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33275 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33276 }, /* DIVS */
|
||||
{ op_81c0_0_comp_ff, 0x00000000, 33216 }, /* DIVS */
|
||||
{ op_81d0_0_comp_ff, 0x00000000, 33232 }, /* DIVS */
|
||||
{ op_81d8_0_comp_ff, 0x00000000, 33240 }, /* DIVS */
|
||||
{ op_81e0_0_comp_ff, 0x00000000, 33248 }, /* DIVS */
|
||||
{ op_81e8_0_comp_ff, 0x00000002, 33256 }, /* DIVS */
|
||||
{ op_81f0_0_comp_ff, 0x00000002, 33264 }, /* DIVS */
|
||||
{ op_81f8_0_comp_ff, 0x00000002, 33272 }, /* DIVS */
|
||||
{ op_81f9_0_comp_ff, 0x00000002, 33273 }, /* DIVS */
|
||||
{ op_81fa_0_comp_ff, 0x00000002, 33274 }, /* DIVS */
|
||||
{ op_81fb_0_comp_ff, 0x00000002, 33275 }, /* DIVS */
|
||||
{ op_81fc_0_comp_ff, 0x00000002, 33276 }, /* DIVS */
|
||||
{ op_9000_0_comp_ff, 0x00000000, 36864 }, /* SUB */
|
||||
{ op_9010_0_comp_ff, 0x00000000, 36880 }, /* SUB */
|
||||
{ op_9018_0_comp_ff, 0x00000000, 36888 }, /* SUB */
|
||||
|
@ -3118,17 +3118,17 @@ extern const struct comptbl op_smalltbl_0_comp_nf[] = {
|
|||
{ op_80ba_0_comp_nf, 0x00000002, 32954 }, /* OR */
|
||||
{ op_80bb_0_comp_nf, 0x00000002, 32955 }, /* OR */
|
||||
{ op_80bc_0_comp_nf, 0x00000002, 32956 }, /* OR */
|
||||
{ NULL, 0x00000001, 32960 }, /* DIVU */
|
||||
{ NULL, 0x00000001, 32976 }, /* DIVU */
|
||||
{ NULL, 0x00000001, 32984 }, /* DIVU */
|
||||
{ NULL, 0x00000001, 32992 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33000 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33008 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33016 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33017 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33018 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33019 }, /* DIVU */
|
||||
{ NULL, 0x00000003, 33020 }, /* DIVU */
|
||||
{ op_80c0_0_comp_nf, 0x00000000, 32960 }, /* DIVU */
|
||||
{ op_80d0_0_comp_nf, 0x00000000, 32976 }, /* DIVU */
|
||||
{ op_80d8_0_comp_nf, 0x00000000, 32984 }, /* DIVU */
|
||||
{ op_80e0_0_comp_nf, 0x00000000, 32992 }, /* DIVU */
|
||||
{ op_80e8_0_comp_nf, 0x00000002, 33000 }, /* DIVU */
|
||||
{ op_80f0_0_comp_nf, 0x00000002, 33008 }, /* DIVU */
|
||||
{ op_80f8_0_comp_nf, 0x00000002, 33016 }, /* DIVU */
|
||||
{ op_80f9_0_comp_nf, 0x00000002, 33017 }, /* DIVU */
|
||||
{ op_80fa_0_comp_nf, 0x00000002, 33018 }, /* DIVU */
|
||||
{ op_80fb_0_comp_nf, 0x00000002, 33019 }, /* DIVU */
|
||||
{ op_80fc_0_comp_nf, 0x00000002, 33020 }, /* DIVU */
|
||||
{ NULL, 0x00000000, 33024 }, /* SBCD */
|
||||
{ NULL, 0x00000000, 33032 }, /* SBCD */
|
||||
{ op_8110_0_comp_nf, 0x00000000, 33040 }, /* OR */
|
||||
|
@ -3156,17 +3156,17 @@ extern const struct comptbl op_smalltbl_0_comp_nf[] = {
|
|||
{ op_81b0_0_comp_nf, 0x00000002, 33200 }, /* OR */
|
||||
{ op_81b8_0_comp_nf, 0x00000002, 33208 }, /* OR */
|
||||
{ op_81b9_0_comp_nf, 0x00000002, 33209 }, /* OR */
|
||||
{ NULL, 0x00000001, 33216 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33232 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33240 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33248 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33256 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33264 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33272 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33273 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33274 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33275 }, /* DIVS */
|
||||
{ NULL, 0x00000001, 33276 }, /* DIVS */
|
||||
{ op_81c0_0_comp_nf, 0x00000000, 33216 }, /* DIVS */
|
||||
{ op_81d0_0_comp_nf, 0x00000000, 33232 }, /* DIVS */
|
||||
{ op_81d8_0_comp_nf, 0x00000000, 33240 }, /* DIVS */
|
||||
{ op_81e0_0_comp_nf, 0x00000000, 33248 }, /* DIVS */
|
||||
{ op_81e8_0_comp_nf, 0x00000002, 33256 }, /* DIVS */
|
||||
{ op_81f0_0_comp_nf, 0x00000002, 33264 }, /* DIVS */
|
||||
{ op_81f8_0_comp_nf, 0x00000002, 33272 }, /* DIVS */
|
||||
{ op_81f9_0_comp_nf, 0x00000002, 33273 }, /* DIVS */
|
||||
{ op_81fa_0_comp_nf, 0x00000002, 33274 }, /* DIVS */
|
||||
{ op_81fb_0_comp_nf, 0x00000002, 33275 }, /* DIVS */
|
||||
{ op_81fc_0_comp_nf, 0x00000002, 33276 }, /* DIVS */
|
||||
{ op_9000_0_comp_nf, 0x00000000, 36864 }, /* SUB */
|
||||
{ op_9010_0_comp_nf, 0x00000000, 36880 }, /* SUB */
|
||||
{ op_9018_0_comp_nf, 0x00000000, 36888 }, /* SUB */
|
||||
|
|
|
@ -1010,6 +1010,17 @@ extern compop_func op_80b9_0_comp_ff;
|
|||
extern compop_func op_80ba_0_comp_ff;
|
||||
extern compop_func op_80bb_0_comp_ff;
|
||||
extern compop_func op_80bc_0_comp_ff;
|
||||
extern compop_func op_80c0_0_comp_ff;
|
||||
extern compop_func op_80d0_0_comp_ff;
|
||||
extern compop_func op_80d8_0_comp_ff;
|
||||
extern compop_func op_80e0_0_comp_ff;
|
||||
extern compop_func op_80e8_0_comp_ff;
|
||||
extern compop_func op_80f0_0_comp_ff;
|
||||
extern compop_func op_80f8_0_comp_ff;
|
||||
extern compop_func op_80f9_0_comp_ff;
|
||||
extern compop_func op_80fa_0_comp_ff;
|
||||
extern compop_func op_80fb_0_comp_ff;
|
||||
extern compop_func op_80fc_0_comp_ff;
|
||||
extern compop_func op_8110_0_comp_ff;
|
||||
extern compop_func op_8118_0_comp_ff;
|
||||
extern compop_func op_8120_0_comp_ff;
|
||||
|
@ -1031,6 +1042,17 @@ extern compop_func op_81a8_0_comp_ff;
|
|||
extern compop_func op_81b0_0_comp_ff;
|
||||
extern compop_func op_81b8_0_comp_ff;
|
||||
extern compop_func op_81b9_0_comp_ff;
|
||||
extern compop_func op_81c0_0_comp_ff;
|
||||
extern compop_func op_81d0_0_comp_ff;
|
||||
extern compop_func op_81d8_0_comp_ff;
|
||||
extern compop_func op_81e0_0_comp_ff;
|
||||
extern compop_func op_81e8_0_comp_ff;
|
||||
extern compop_func op_81f0_0_comp_ff;
|
||||
extern compop_func op_81f8_0_comp_ff;
|
||||
extern compop_func op_81f9_0_comp_ff;
|
||||
extern compop_func op_81fa_0_comp_ff;
|
||||
extern compop_func op_81fb_0_comp_ff;
|
||||
extern compop_func op_81fc_0_comp_ff;
|
||||
extern compop_func op_9000_0_comp_ff;
|
||||
extern compop_func op_9010_0_comp_ff;
|
||||
extern compop_func op_9018_0_comp_ff;
|
||||
|
@ -2479,6 +2501,17 @@ extern compop_func op_80b9_0_comp_nf;
|
|||
extern compop_func op_80ba_0_comp_nf;
|
||||
extern compop_func op_80bb_0_comp_nf;
|
||||
extern compop_func op_80bc_0_comp_nf;
|
||||
extern compop_func op_80c0_0_comp_nf;
|
||||
extern compop_func op_80d0_0_comp_nf;
|
||||
extern compop_func op_80d8_0_comp_nf;
|
||||
extern compop_func op_80e0_0_comp_nf;
|
||||
extern compop_func op_80e8_0_comp_nf;
|
||||
extern compop_func op_80f0_0_comp_nf;
|
||||
extern compop_func op_80f8_0_comp_nf;
|
||||
extern compop_func op_80f9_0_comp_nf;
|
||||
extern compop_func op_80fa_0_comp_nf;
|
||||
extern compop_func op_80fb_0_comp_nf;
|
||||
extern compop_func op_80fc_0_comp_nf;
|
||||
extern compop_func op_8110_0_comp_nf;
|
||||
extern compop_func op_8118_0_comp_nf;
|
||||
extern compop_func op_8120_0_comp_nf;
|
||||
|
@ -2500,6 +2533,17 @@ extern compop_func op_81a8_0_comp_nf;
|
|||
extern compop_func op_81b0_0_comp_nf;
|
||||
extern compop_func op_81b8_0_comp_nf;
|
||||
extern compop_func op_81b9_0_comp_nf;
|
||||
extern compop_func op_81c0_0_comp_nf;
|
||||
extern compop_func op_81d0_0_comp_nf;
|
||||
extern compop_func op_81d8_0_comp_nf;
|
||||
extern compop_func op_81e0_0_comp_nf;
|
||||
extern compop_func op_81e8_0_comp_nf;
|
||||
extern compop_func op_81f0_0_comp_nf;
|
||||
extern compop_func op_81f8_0_comp_nf;
|
||||
extern compop_func op_81f9_0_comp_nf;
|
||||
extern compop_func op_81fa_0_comp_nf;
|
||||
extern compop_func op_81fb_0_comp_nf;
|
||||
extern compop_func op_81fc_0_comp_nf;
|
||||
extern compop_func op_9000_0_comp_nf;
|
||||
extern compop_func op_9010_0_comp_nf;
|
||||
extern compop_func op_9018_0_comp_nf;
|
||||
|
|
|
@ -123,7 +123,8 @@
|
|||
//#define DISABLE_I_FSCC
|
||||
//#define DISABLE_I_MOVE16
|
||||
|
||||
#define DISABLE_I_DIVU // DIVU works, but we have to think about exceptions. No big performance enhancement.
|
||||
//#define DISABLE_I_DIVU
|
||||
//#define DISABLE_I_DIVS
|
||||
|
||||
|
||||
#define RETURN "return 0;"
|
||||
|
@ -1268,6 +1269,7 @@ static void gen_divu(uae_u32 opcode, struct instr *curi, char* ssize) {
|
|||
genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0);
|
||||
|
||||
comprintf("\tint tmp=scratchie++;\n");
|
||||
comprintf("\tregister_possible_exception();\n");
|
||||
if (!noflags) {
|
||||
comprintf("\tjff_DIVU(tmp,dst,src);\n");
|
||||
comprintf("\tlive_flags();\n");
|
||||
|
@ -1275,7 +1277,27 @@ static void gen_divu(uae_u32 opcode, struct instr *curi, char* ssize) {
|
|||
comprintf("\tjnf_DIVU(tmp,dst,src);\n");
|
||||
}
|
||||
|
||||
genastore("tmp", curi->dmode, "dstreg", curi->size, "dst");
|
||||
genastore("tmp", curi->dmode, "dstreg", sz_long /*curi->size*/, "dst");
|
||||
}
|
||||
|
||||
static void gen_divs(uae_u32 opcode, struct instr *curi, char* ssize) {
|
||||
(void)opcode;
|
||||
(void)ssize;
|
||||
comprintf("\t dont_care_flags();\n");
|
||||
genamode(curi->smode, "srcreg", sz_word, "src", 1, 0);
|
||||
genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0);
|
||||
|
||||
comprintf("\tint tmp=scratchie++;\n");
|
||||
comprintf("\tregister_possible_exception();\n");
|
||||
if (!noflags) {
|
||||
comprintf("\tjff_DIVS(tmp,dst,src);\n");
|
||||
comprintf("\tlive_flags();\n");
|
||||
}
|
||||
else {
|
||||
comprintf("\tjnf_DIVS(tmp,dst,src);\n");
|
||||
}
|
||||
|
||||
genastore("tmp", curi->dmode, "dstreg", sz_long /*curi->size*/, "dst");
|
||||
}
|
||||
|
||||
static void gen_eor(uae_u32 opcode, struct instr *curi, char* ssize) {
|
||||
|
@ -2507,8 +2529,11 @@ gen_opcode(unsigned long int opcode) {
|
|||
break;
|
||||
|
||||
case i_DIVS:
|
||||
#ifdef DISABLE_I_DIVS
|
||||
isjump;
|
||||
failure;
|
||||
#endif
|
||||
gen_divs(opcode, curi, ssize);
|
||||
break;
|
||||
|
||||
case i_MULU:
|
||||
|
@ -3018,6 +3043,13 @@ generate_one_opcode(int rp, int noflags)
|
|||
dmsk = 7;
|
||||
|
||||
next_cpu_level = -1;
|
||||
if (table68k[opcode].mnemo == i_DIVU || table68k[opcode].mnemo == i_DIVS) {
|
||||
comprintf("#ifndef ARMV6T2\n");
|
||||
comprintf(" FAIL(1);\n");
|
||||
comprintf(" " RETURN "\n");
|
||||
comprintf("#else\n");
|
||||
}
|
||||
|
||||
if (table68k[opcode].suse
|
||||
&& table68k[opcode].smode != imm && table68k[opcode].smode != imm0
|
||||
&& table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2
|
||||
|
@ -3109,6 +3141,10 @@ generate_one_opcode(int rp, int noflags)
|
|||
if (global_fpu) flags |= 32;
|
||||
|
||||
comprintf ("return 0;\n");
|
||||
if (table68k[opcode].mnemo == i_DIVU || table68k[opcode].mnemo == i_DIVS) {
|
||||
comprintf("#endif\n");
|
||||
}
|
||||
|
||||
comprintf("}\n");
|
||||
|
||||
char name[100] = { 0 };
|
||||
|
@ -3132,6 +3168,7 @@ generate_one_opcode(int rp, int noflags)
|
|||
com_flush();
|
||||
}
|
||||
}
|
||||
|
||||
opcode_next_clev[rp] = next_cpu_level;
|
||||
opcode_last_postfix[rp] = postfix;
|
||||
}
|
||||
|
|
|
@ -1597,6 +1597,18 @@ static void m68k_run_1 (void)
|
|||
|
||||
#ifdef JIT /* Completely different run_2 replacement */
|
||||
|
||||
extern uae_u32 jit_exception;
|
||||
|
||||
void execute_exception(void)
|
||||
{
|
||||
Exception_cpu(jit_exception);
|
||||
jit_exception = 0;
|
||||
cpu_cycles = adjust_cycles(4 * CYCLE_UNIT / 2);
|
||||
do_cycles (cpu_cycles);
|
||||
// after leaving this function, we fall back to execute_normal()
|
||||
}
|
||||
|
||||
|
||||
void do_nothing(void)
|
||||
{
|
||||
/* What did you expect this to do? */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue