Fixed JIT FPU bugs (Starstruck demo corruption, etc.)

This commit is contained in:
Dimitris Panokostas 2018-02-08 20:40:37 +01:00
parent 88316d7916
commit b9dc57af87
14 changed files with 1735 additions and 121 deletions

View file

@ -943,6 +943,48 @@ STATIC_INLINE void compemu_raw_jcc_l_oponly(int cc)
// emit of target will be done by caller // 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)&regs;
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) STATIC_INLINE void compemu_raw_jl(uae_u32 t)
{ {
#ifdef ARMV6T2 #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); VCVTR64toI_sd(SCRATCH_F32_1, s);
VMOV32_rs(REG_WORK1, SCRATCH_F32_1); VMOV32_rs(REG_WORK1, SCRATCH_F32_1);
SSAT_rir(REG_WORK1, 15, REG_WORK1); SSAT_rir(d, 15, REG_WORK1);
BFI_rrii(d, REG_WORK1, 0, 15);
} }
LENDFUNC(NONE,NONE,2,raw_fmov_to_w_rr,(W4 d, FR s)) 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); VCVTR64toI_sd(SCRATCH_F32_1, s);
VMOV32_rs(REG_WORK1, SCRATCH_F32_1); VMOV32_rs(REG_WORK1, SCRATCH_F32_1);
SSAT_rir(REG_WORK1, 7, REG_WORK1); SSAT_rir(d, 7, REG_WORK1);
BFI_rrii(d, REG_WORK1, 0, 7);
} }
LENDFUNC(NONE,NONE,2,raw_fmov_to_b_rr,(W4 d, FR s)) 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); VMRS_r(REG_WORK2);
UBFX_rrii(REG_WORK1, REG_WORK1, 22, 2); 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); VMSR_r(REG_WORK2);
} }
LENDFUNC(NONE,NONE,2,raw_frem1_rr,(FRW d, FR s)) 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); ADD_rrr(REG_WORK1, adr, REG_WORK1);
REV_rr(REG_WORK3, REG_WORK3); 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 VSHL64_ddi(SCRATCH_F64_1, s, 11); // shift mantissa to correct position
VMOV64_rrd(REG_WORK3, REG_WORK2, SCRATCH_F64_1); 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 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 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 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 VSHR64_ddi(d, d, 11); // shift mantissa to correct position
LSL_rri(REG_WORK3, REG_WORK3, 20); LSL_rri(REG_WORK3, REG_WORK3, 20);
VMOV_I64_dimmI(0, 0x00); 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 // 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) 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)) 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 #endif // USE_JIT_FPU

View file

@ -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 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 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 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 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 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 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 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 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)) #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 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 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 */ #endif /* ARM_RTASM_H */

File diff suppressed because it is too large Load diff

View file

@ -129,7 +129,6 @@ typedef union {
#endif #endif
#define N_FREGS 16 // We use 10 regs: 6 - FP_RESULT, 7 - SCRATCH, 8-15 - Amiga regs FP0-FP7 #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 /* Functions exposed to newcpu, or to what was moved from newcpu.c to
* compemu_support.c */ * compemu_support.c */
extern void compiler_exit(void); extern void compiler_exit(void);
@ -332,6 +331,7 @@ extern void sync_m68k_pc(void);
extern uae_u32 get_const(int r); extern uae_u32 get_const(int r);
extern int is_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_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_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))) #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 execute_normal(void);
void exec_nostats(void); void exec_nostats(void);
void do_nothing(void); void do_nothing(void);
void execute_exception(void);
/* ARAnyM uses fpu_register name, used in scratch_t */ /* ARAnyM uses fpu_register name, used in scratch_t */
/* FIXME: check that no ARAnyM code assumes different floating point type */ /* FIXME: check that no ARAnyM code assumes different floating point type */

View file

@ -497,6 +497,11 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
int source = (extra >> 13) & 7; int source = (extra >> 13) & 7;
int opmode = extra & 0x7f; int opmode = extra & 0x7f;
if (special_mem) {
FAIL(1);
return;
}
if (!currprefs.compfpu) { if (!currprefs.compfpu) {
FAIL (1); FAIL (1);
return; return;
@ -525,6 +530,25 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
if (extra & 0x1000) { /* FPCR */ if (extra & 0x1000) { /* FPCR */
uae_u32 val = comp_get_ilong ((m68k_pc_offset += 4) - 4); uae_u32 val = comp_get_ilong ((m68k_pc_offset += 4) - 4);
mov_l_mi (uae_p32(&regs.fpcr), val); mov_l_mi (uae_p32(&regs.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; return;
} }
if (extra & 0x0800) { /* FPSR */ if (extra & 0x0800) { /* FPSR */
@ -875,11 +899,6 @@ void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
case 0x37: case 0x37:
FAIL (1); FAIL (1);
return; return;
// if (dreg == (extra & 7))
// ffunc_rr (sin, dreg, sreg);
// else
// fsincos_rr (dreg, extra & 7, sreg);
// break;
case 0x38: /* FCMP */ case 0x38: /* FCMP */
fmov_rr (FP_RESULT, dreg); fmov_rr (FP_RESULT, dreg);
fsub_rr (FP_RESULT, sreg); fsub_rr (FP_RESULT, sreg);

View file

@ -109,7 +109,7 @@ MIDFUNC(2,sign_extend_16_rr,(W4 d, RR2 s))
s = readreg(s, 2); s = readreg(s, 2);
d = writereg(d, 4); 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); s = d = rmw(s, 4, 2);
} }
SIGNED16_REG_2_REG(d, s); 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)) MIDFUNC(2,fmov_to_w_rr,(W4 d, FR s))
{ {
s = f_readreg(s); s = f_readreg(s);
d = rmw(d, 2, 4); d = writereg(d, 2);
raw_fmov_to_w_rr(d, s); raw_fmov_to_w_rr(d, s);
unlock2(d); unlock2(d);
f_unlock(s); 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)) MIDFUNC(2,fmov_to_b_rr,(W4 d, FR s))
{ {
s = f_readreg(s); s = f_readreg(s);
d = rmw(d, 1, 4); d = writereg(d, 1);
raw_fmov_to_b_rr(d, s); raw_fmov_to_b_rr(d, s);
unlock2(d); unlock2(d);
f_unlock(s); 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)) MIDFUNC(3,ffunc_rr,(double (*func)(double), FW d, FR s))
{ {
clobber_flags(); clobber_flags();
prepare_for_call_1();
prepare_for_call_2();
s = f_readreg(s); 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(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)) 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)) MIDFUNC(3,fpowx_rr,(uae_u32 x, FW d, FR s))
{ {
clobber_flags(); clobber_flags();
prepare_for_call_1();
prepare_for_call_2();
s = f_readreg(s); 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(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)) 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)) 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 #endif // USE_JIT_FPU

View file

@ -111,3 +111,4 @@ DECLARE_MIDFUNC(fflags_into_flags());
DECLARE_MIDFUNC(fp_from_exten_mr(RR4 adr, FR s)); DECLARE_MIDFUNC(fp_from_exten_mr(RR4 adr, FR s));
DECLARE_MIDFUNC(fp_to_exten_rm(FW d, RR4 adr)); DECLARE_MIDFUNC(fp_to_exten_rm(FW d, RR4 adr));
DECLARE_MIDFUNC(fp_fscc_ri(RW4, int cc)); DECLARE_MIDFUNC(fp_fscc_ri(RW4, int cc));
DECLARE_MIDFUNC(roundingmode(IMM mode));

View file

@ -1852,28 +1852,44 @@ MENDFUNC(2,jff_DBCC,(RR2 d, IMM cc))
* C Always cleared. * 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)) MIDFUNC(3,jnf_DIVU,(W4 d, RR4 s1, RR4 s2))
{ {
s1 = readreg(s1, 4); s1 = readreg(s1, 4);
s2 = readreg(s2, 4); s2 = readreg(s2, 4);
d = writereg(d, 4); d = writereg(d, 4);
VMOV32_sr(0, s1); // move to s0 UNSIGNED16_REG_2_REG(REG_WORK3, s2);
VMOV32_sr(1, s2); // move to s1 TST_rr(REG_WORK3, REG_WORK3);
VCVTIto64_ds(2, 0); // convert s0 to d2 (int to float) BNE_i(6); // src is not 0
VCVTIto64_ds(3, 1); // convert s1 to d3 (int to float)
VDIV64_ddd(4, 2, 3); // d4 = d2 / d3 // Signal exception 5
VCVT64toI_sd(0, 4); // convert d4 to s0 (float to int) MOV_ri(REG_WORK1, 5);
VMOV32_rs(REG_WORK1, 0); // move from s0 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 LSRS_rri(REG_WORK2, REG_WORK1, 16); // if result of this is not 0, DIVU overflows -> no result
BNE_i(2); BNE_i(2);
// Here we have to calc reminder // 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); SUB_rrr(REG_WORK2, s1, REG_WORK2);
PKHBT_rrrLSLi(d, REG_WORK1, REG_WORK2, 16); PKHBT_rrrLSLi(d, REG_WORK1, REG_WORK2, 16);
// end_of_op
unlock2(d); unlock2(d);
unlock2(s1); unlock2(s1);
@ -1887,13 +1903,29 @@ MIDFUNC(3,jff_DIVU,(W4 d, RR4 s1, RR4 s2))
s2 = readreg(s2, 4); s2 = readreg(s2, 4);
d = writereg(d, 4); d = writereg(d, 4);
VMOV32_sr(0, s1); // move to s0 UNSIGNED16_REG_2_REG(REG_WORK3, s2);
VMOV32_sr(1, s2); // move to s1 TST_rr(REG_WORK3, REG_WORK3);
VCVTIto64_ds(2, 0); // convert s0 to d2 (int to float) BNE_i(6); // src is not 0
VCVTIto64_ds(3, 1); // convert s1 to d3 (int to float)
VDIV64_ddd(4, 2, 3); // d4 = d2 / d3 // Signal exception 5
VCVT64toI_sd(0, 4); // convert d4 to s0 (float to int) MOV_ri(REG_WORK1, 5);
VMOV32_rs(REG_WORK1, 0); // move from s0 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 LSRS_rri(REG_WORK2, REG_WORK1, 16); // if result of this is not 0, DIVU overflows
BEQ_i(2); 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); BIC_rri(REG_WORK2, REG_WORK2, ARM_C_FLAG | ARM_V_FLAG);
MSR_CPSRf_r(REG_WORK2); 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); SUB_rrr(REG_WORK2, s1, REG_WORK2);
PKHBT_rrrLSLi(d, REG_WORK1, REG_WORK2, 16); PKHBT_rrrLSLi(d, REG_WORK1, REG_WORK2, 16);
// end_of_op
unlock2(d); unlock2(d);
unlock2(s1); 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)) 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 * EOR
* Operand Syntax: Dn, <ea> * 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); LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
adr = readreg(adr, 4); adr = readreg(adr, 4);
b = readreg(b, 4); b = readreg(b, 1);
STRB_rRR(b, adr, REG_WORK2); 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); LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
adr = readreg(adr, 4); adr = readreg(adr, 4);
w = readreg(w, 4); w = readreg(w, 2);
REV16_rr(REG_WORK1, w); REV16_rr(REG_WORK1, w);
STRH_rRR(REG_WORK1, adr, REG_WORK2); 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); LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
adr = readreg(adr, 4); adr = readreg(adr, 4);
d = writereg(d, 4); d = writereg(d, 1);
LDRB_rRR(d, adr, REG_WORK2); 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); LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
adr = readreg(adr, 4); adr = readreg(adr, 4);
d = writereg(d, 4); d = writereg(d, 2);
LDRH_rRR(REG_WORK1, adr, REG_WORK2); LDRH_rRR(REG_WORK1, adr, REG_WORK2);
REV16_rr(d, REG_WORK1); 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); LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
adr = readreg(adr, 4); adr = readreg(adr, 4);
b = readreg(b, 4); b = readreg(b, 1);
BIC_rri(REG_WORK1, adr, 0xff000000); BIC_rri(REG_WORK1, adr, 0xff000000);
STRB_rRR(b, REG_WORK1, REG_WORK2); 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); LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
adr = readreg(adr, 4); adr = readreg(adr, 4);
w = readreg(w, 4); w = readreg(w, 2);
BIC_rri(REG_WORK1, adr, 0xff000000); BIC_rri(REG_WORK1, adr, 0xff000000);
REV16_rr(REG_WORK3, w); 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); LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
adr = readreg(adr, 4); adr = readreg(adr, 4);
d = writereg(d, 4); d = writereg(d, 1);
BIC_rri(REG_WORK1, adr, 0xff000000); BIC_rri(REG_WORK1, adr, 0xff000000);
LDRB_rRR(d, REG_WORK1, REG_WORK2); 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); LDR_rRI(REG_WORK2, R_REGSTRUCT, offs);
adr = readreg(adr, 4); adr = readreg(adr, 4);
d = writereg(d, 4); d = writereg(d, 2);
BIC_rri(REG_WORK1, adr, 0xff000000); BIC_rri(REG_WORK1, adr, 0xff000000);
LDRH_rRR(REG_WORK1, REG_WORK1, REG_WORK2); LDRH_rRR(REG_WORK1, REG_WORK1, REG_WORK2);

View file

@ -161,6 +161,10 @@ DECLARE_MIDFUNC(jff_DBCC(RR2 d, IMM cc));
DECLARE_MIDFUNC(jnf_DIVU(W4 d, RR4 s1, RR4 s2)); DECLARE_MIDFUNC(jnf_DIVU(W4 d, RR4 s1, RR4 s2));
DECLARE_MIDFUNC(jff_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 // EOR
DECLARE_MIDFUNC(jnf_EOR(W4 d, RR4 s, RR4 v)); DECLARE_MIDFUNC(jnf_EOR(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jff_EOR_b(W4 d, RR1 s, RR1 v)); DECLARE_MIDFUNC(jff_EOR_b(W4 d, RR1 s, RR1 v));

View file

@ -126,6 +126,10 @@ static int optcount[10] = {
op_properties prop[65536]; op_properties prop[65536];
uae_u32 jit_exception = 0;
bool may_raise_exception = false;
STATIC_INLINE bool is_const_jump(uae_u32 opcode) STATIC_INLINE bool is_const_jump(uae_u32 opcode)
{ {
return (prop[opcode].cflow == fl_const_jump); 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_cache_miss = NULL;
static void* popall_recompile_block = NULL; static void* popall_recompile_block = NULL;
static void* popall_check_checksum = 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 /* The 68k only ever executes from even addresses. So right now, we
* waste half the entries in this array * waste half the entries in this array
@ -1393,7 +1398,6 @@ STATIC_INLINE void f_disassociate(int r)
f_evict(r); f_evict(r);
} }
static int f_alloc_reg(int r, int willclobber) static int f_alloc_reg(int r, int willclobber)
{ {
int bestreg; int bestreg;
@ -1651,6 +1655,8 @@ void init_comp(void)
live.flags_in_flags = TRASH; live.flags_in_flags = TRASH;
live.flags_on_stack = VALID; live.flags_on_stack = VALID;
live.flags_are_important = 1; live.flags_are_important = 1;
jit_exception = 0;
} }
/* Only do this if you really mean it! The next call should be to init!*/ /* 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; 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 /* Note: get_handler may fail in 64 Bit environments, if direct_handler_to_use is
* outside 32 bit * outside 32 bit
*/ */
@ -2379,6 +2390,12 @@ STATIC_INLINE void create_popalls(void)
raw_pop_preserved_regs(); raw_pop_preserved_regs();
compemu_raw_jmp(uae_p32(check_checksum)); 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) #if defined(CPU_arm) && !defined(ARMV6T2)
reset_data_buffer(); reset_data_buffer();
#endif #endif
@ -2776,6 +2793,7 @@ void compile_block(cpu_history* pc_hist, int blocklen, int totcycles)
was_comp = 1; was_comp = 1;
for (i = 0; i < blocklen && get_target_noopt() < MAX_COMPILE_PTR; i++) { for (i = 0; i < blocklen && get_target_noopt() < MAX_COMPILE_PTR; i++) {
may_raise_exception = false;
cpuop_func **cputbl; cpuop_func **cputbl;
compop_func **comptbl; compop_func **comptbl;
uae_u32 opcode = DO_GET_OPCODE(pc_hist[i].location); 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); compemu_raw_jmp((uintptr)popall_do_nothing);
*(branchadd - 4) = (((uintptr)get_target() - (uintptr)branchadd) - 4) >> 2; *(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;
} }
} }

View file

@ -1246,17 +1246,17 @@ extern const struct comptbl op_smalltbl_0_comp_ff[] = {
{ op_80ba_0_comp_ff, 0x00000002, 32954 }, /* OR */ { op_80ba_0_comp_ff, 0x00000002, 32954 }, /* OR */
{ op_80bb_0_comp_ff, 0x00000002, 32955 }, /* OR */ { op_80bb_0_comp_ff, 0x00000002, 32955 }, /* OR */
{ op_80bc_0_comp_ff, 0x00000002, 32956 }, /* OR */ { op_80bc_0_comp_ff, 0x00000002, 32956 }, /* OR */
{ NULL, 0x00000001, 32960 }, /* DIVU */ { op_80c0_0_comp_ff, 0x00000000, 32960 }, /* DIVU */
{ NULL, 0x00000001, 32976 }, /* DIVU */ { op_80d0_0_comp_ff, 0x00000000, 32976 }, /* DIVU */
{ NULL, 0x00000001, 32984 }, /* DIVU */ { op_80d8_0_comp_ff, 0x00000000, 32984 }, /* DIVU */
{ NULL, 0x00000001, 32992 }, /* DIVU */ { op_80e0_0_comp_ff, 0x00000000, 32992 }, /* DIVU */
{ NULL, 0x00000003, 33000 }, /* DIVU */ { op_80e8_0_comp_ff, 0x00000002, 33000 }, /* DIVU */
{ NULL, 0x00000003, 33008 }, /* DIVU */ { op_80f0_0_comp_ff, 0x00000002, 33008 }, /* DIVU */
{ NULL, 0x00000003, 33016 }, /* DIVU */ { op_80f8_0_comp_ff, 0x00000002, 33016 }, /* DIVU */
{ NULL, 0x00000003, 33017 }, /* DIVU */ { op_80f9_0_comp_ff, 0x00000002, 33017 }, /* DIVU */
{ NULL, 0x00000003, 33018 }, /* DIVU */ { op_80fa_0_comp_ff, 0x00000002, 33018 }, /* DIVU */
{ NULL, 0x00000003, 33019 }, /* DIVU */ { op_80fb_0_comp_ff, 0x00000002, 33019 }, /* DIVU */
{ NULL, 0x00000003, 33020 }, /* DIVU */ { op_80fc_0_comp_ff, 0x00000002, 33020 }, /* DIVU */
{ NULL, 0x00000000, 33024 }, /* SBCD */ { NULL, 0x00000000, 33024 }, /* SBCD */
{ NULL, 0x00000000, 33032 }, /* SBCD */ { NULL, 0x00000000, 33032 }, /* SBCD */
{ op_8110_0_comp_ff, 0x00000000, 33040 }, /* OR */ { 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_81b0_0_comp_ff, 0x00000002, 33200 }, /* OR */
{ op_81b8_0_comp_ff, 0x00000002, 33208 }, /* OR */ { op_81b8_0_comp_ff, 0x00000002, 33208 }, /* OR */
{ op_81b9_0_comp_ff, 0x00000002, 33209 }, /* OR */ { op_81b9_0_comp_ff, 0x00000002, 33209 }, /* OR */
{ NULL, 0x00000001, 33216 }, /* DIVS */ { op_81c0_0_comp_ff, 0x00000000, 33216 }, /* DIVS */
{ NULL, 0x00000001, 33232 }, /* DIVS */ { op_81d0_0_comp_ff, 0x00000000, 33232 }, /* DIVS */
{ NULL, 0x00000001, 33240 }, /* DIVS */ { op_81d8_0_comp_ff, 0x00000000, 33240 }, /* DIVS */
{ NULL, 0x00000001, 33248 }, /* DIVS */ { op_81e0_0_comp_ff, 0x00000000, 33248 }, /* DIVS */
{ NULL, 0x00000001, 33256 }, /* DIVS */ { op_81e8_0_comp_ff, 0x00000002, 33256 }, /* DIVS */
{ NULL, 0x00000001, 33264 }, /* DIVS */ { op_81f0_0_comp_ff, 0x00000002, 33264 }, /* DIVS */
{ NULL, 0x00000001, 33272 }, /* DIVS */ { op_81f8_0_comp_ff, 0x00000002, 33272 }, /* DIVS */
{ NULL, 0x00000001, 33273 }, /* DIVS */ { op_81f9_0_comp_ff, 0x00000002, 33273 }, /* DIVS */
{ NULL, 0x00000001, 33274 }, /* DIVS */ { op_81fa_0_comp_ff, 0x00000002, 33274 }, /* DIVS */
{ NULL, 0x00000001, 33275 }, /* DIVS */ { op_81fb_0_comp_ff, 0x00000002, 33275 }, /* DIVS */
{ NULL, 0x00000001, 33276 }, /* DIVS */ { op_81fc_0_comp_ff, 0x00000002, 33276 }, /* DIVS */
{ op_9000_0_comp_ff, 0x00000000, 36864 }, /* SUB */ { op_9000_0_comp_ff, 0x00000000, 36864 }, /* SUB */
{ op_9010_0_comp_ff, 0x00000000, 36880 }, /* SUB */ { op_9010_0_comp_ff, 0x00000000, 36880 }, /* SUB */
{ op_9018_0_comp_ff, 0x00000000, 36888 }, /* 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_80ba_0_comp_nf, 0x00000002, 32954 }, /* OR */
{ op_80bb_0_comp_nf, 0x00000002, 32955 }, /* OR */ { op_80bb_0_comp_nf, 0x00000002, 32955 }, /* OR */
{ op_80bc_0_comp_nf, 0x00000002, 32956 }, /* OR */ { op_80bc_0_comp_nf, 0x00000002, 32956 }, /* OR */
{ NULL, 0x00000001, 32960 }, /* DIVU */ { op_80c0_0_comp_nf, 0x00000000, 32960 }, /* DIVU */
{ NULL, 0x00000001, 32976 }, /* DIVU */ { op_80d0_0_comp_nf, 0x00000000, 32976 }, /* DIVU */
{ NULL, 0x00000001, 32984 }, /* DIVU */ { op_80d8_0_comp_nf, 0x00000000, 32984 }, /* DIVU */
{ NULL, 0x00000001, 32992 }, /* DIVU */ { op_80e0_0_comp_nf, 0x00000000, 32992 }, /* DIVU */
{ NULL, 0x00000003, 33000 }, /* DIVU */ { op_80e8_0_comp_nf, 0x00000002, 33000 }, /* DIVU */
{ NULL, 0x00000003, 33008 }, /* DIVU */ { op_80f0_0_comp_nf, 0x00000002, 33008 }, /* DIVU */
{ NULL, 0x00000003, 33016 }, /* DIVU */ { op_80f8_0_comp_nf, 0x00000002, 33016 }, /* DIVU */
{ NULL, 0x00000003, 33017 }, /* DIVU */ { op_80f9_0_comp_nf, 0x00000002, 33017 }, /* DIVU */
{ NULL, 0x00000003, 33018 }, /* DIVU */ { op_80fa_0_comp_nf, 0x00000002, 33018 }, /* DIVU */
{ NULL, 0x00000003, 33019 }, /* DIVU */ { op_80fb_0_comp_nf, 0x00000002, 33019 }, /* DIVU */
{ NULL, 0x00000003, 33020 }, /* DIVU */ { op_80fc_0_comp_nf, 0x00000002, 33020 }, /* DIVU */
{ NULL, 0x00000000, 33024 }, /* SBCD */ { NULL, 0x00000000, 33024 }, /* SBCD */
{ NULL, 0x00000000, 33032 }, /* SBCD */ { NULL, 0x00000000, 33032 }, /* SBCD */
{ op_8110_0_comp_nf, 0x00000000, 33040 }, /* OR */ { 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_81b0_0_comp_nf, 0x00000002, 33200 }, /* OR */
{ op_81b8_0_comp_nf, 0x00000002, 33208 }, /* OR */ { op_81b8_0_comp_nf, 0x00000002, 33208 }, /* OR */
{ op_81b9_0_comp_nf, 0x00000002, 33209 }, /* OR */ { op_81b9_0_comp_nf, 0x00000002, 33209 }, /* OR */
{ NULL, 0x00000001, 33216 }, /* DIVS */ { op_81c0_0_comp_nf, 0x00000000, 33216 }, /* DIVS */
{ NULL, 0x00000001, 33232 }, /* DIVS */ { op_81d0_0_comp_nf, 0x00000000, 33232 }, /* DIVS */
{ NULL, 0x00000001, 33240 }, /* DIVS */ { op_81d8_0_comp_nf, 0x00000000, 33240 }, /* DIVS */
{ NULL, 0x00000001, 33248 }, /* DIVS */ { op_81e0_0_comp_nf, 0x00000000, 33248 }, /* DIVS */
{ NULL, 0x00000001, 33256 }, /* DIVS */ { op_81e8_0_comp_nf, 0x00000002, 33256 }, /* DIVS */
{ NULL, 0x00000001, 33264 }, /* DIVS */ { op_81f0_0_comp_nf, 0x00000002, 33264 }, /* DIVS */
{ NULL, 0x00000001, 33272 }, /* DIVS */ { op_81f8_0_comp_nf, 0x00000002, 33272 }, /* DIVS */
{ NULL, 0x00000001, 33273 }, /* DIVS */ { op_81f9_0_comp_nf, 0x00000002, 33273 }, /* DIVS */
{ NULL, 0x00000001, 33274 }, /* DIVS */ { op_81fa_0_comp_nf, 0x00000002, 33274 }, /* DIVS */
{ NULL, 0x00000001, 33275 }, /* DIVS */ { op_81fb_0_comp_nf, 0x00000002, 33275 }, /* DIVS */
{ NULL, 0x00000001, 33276 }, /* DIVS */ { op_81fc_0_comp_nf, 0x00000002, 33276 }, /* DIVS */
{ op_9000_0_comp_nf, 0x00000000, 36864 }, /* SUB */ { op_9000_0_comp_nf, 0x00000000, 36864 }, /* SUB */
{ op_9010_0_comp_nf, 0x00000000, 36880 }, /* SUB */ { op_9010_0_comp_nf, 0x00000000, 36880 }, /* SUB */
{ op_9018_0_comp_nf, 0x00000000, 36888 }, /* SUB */ { op_9018_0_comp_nf, 0x00000000, 36888 }, /* SUB */

View file

@ -1010,6 +1010,17 @@ extern compop_func op_80b9_0_comp_ff;
extern compop_func op_80ba_0_comp_ff; extern compop_func op_80ba_0_comp_ff;
extern compop_func op_80bb_0_comp_ff; extern compop_func op_80bb_0_comp_ff;
extern compop_func op_80bc_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_8110_0_comp_ff;
extern compop_func op_8118_0_comp_ff; extern compop_func op_8118_0_comp_ff;
extern compop_func op_8120_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_81b0_0_comp_ff;
extern compop_func op_81b8_0_comp_ff; extern compop_func op_81b8_0_comp_ff;
extern compop_func op_81b9_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_9000_0_comp_ff;
extern compop_func op_9010_0_comp_ff; extern compop_func op_9010_0_comp_ff;
extern compop_func op_9018_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_80ba_0_comp_nf;
extern compop_func op_80bb_0_comp_nf; extern compop_func op_80bb_0_comp_nf;
extern compop_func op_80bc_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_8110_0_comp_nf;
extern compop_func op_8118_0_comp_nf; extern compop_func op_8118_0_comp_nf;
extern compop_func op_8120_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_81b0_0_comp_nf;
extern compop_func op_81b8_0_comp_nf; extern compop_func op_81b8_0_comp_nf;
extern compop_func op_81b9_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_9000_0_comp_nf;
extern compop_func op_9010_0_comp_nf; extern compop_func op_9010_0_comp_nf;
extern compop_func op_9018_0_comp_nf; extern compop_func op_9018_0_comp_nf;

View file

@ -123,7 +123,8 @@
//#define DISABLE_I_FSCC //#define DISABLE_I_FSCC
//#define DISABLE_I_MOVE16 //#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;" #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); genamode(curi->dmode, "dstreg", sz_word, "dst", 1, 0);
comprintf("\tint tmp=scratchie++;\n"); comprintf("\tint tmp=scratchie++;\n");
comprintf("\tregister_possible_exception();\n");
if (!noflags) { if (!noflags) {
comprintf("\tjff_DIVU(tmp,dst,src);\n"); comprintf("\tjff_DIVU(tmp,dst,src);\n");
comprintf("\tlive_flags();\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"); 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) { static void gen_eor(uae_u32 opcode, struct instr *curi, char* ssize) {
@ -2507,8 +2529,11 @@ gen_opcode(unsigned long int opcode) {
break; break;
case i_DIVS: case i_DIVS:
#ifdef DISABLE_I_DIVS
isjump; isjump;
failure; failure;
#endif
gen_divs(opcode, curi, ssize);
break; break;
case i_MULU: case i_MULU:
@ -3018,6 +3043,13 @@ generate_one_opcode(int rp, int noflags)
dmsk = 7; dmsk = 7;
next_cpu_level = -1; 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 if (table68k[opcode].suse
&& table68k[opcode].smode != imm && table68k[opcode].smode != imm0 && table68k[opcode].smode != imm && table68k[opcode].smode != imm0
&& table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2 && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2
@ -3109,6 +3141,10 @@ generate_one_opcode(int rp, int noflags)
if (global_fpu) flags |= 32; if (global_fpu) flags |= 32;
comprintf ("return 0;\n"); comprintf ("return 0;\n");
if (table68k[opcode].mnemo == i_DIVU || table68k[opcode].mnemo == i_DIVS) {
comprintf("#endif\n");
}
comprintf("}\n"); comprintf("}\n");
char name[100] = { 0 }; char name[100] = { 0 };
@ -3132,6 +3168,7 @@ generate_one_opcode(int rp, int noflags)
com_flush(); com_flush();
} }
} }
opcode_next_clev[rp] = next_cpu_level; opcode_next_clev[rp] = next_cpu_level;
opcode_last_postfix[rp] = postfix; opcode_last_postfix[rp] = postfix;
} }

View file

@ -1597,6 +1597,18 @@ static void m68k_run_1 (void)
#ifdef JIT /* Completely different run_2 replacement */ #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) void do_nothing(void)
{ {
/* What did you expect this to do? */ /* What did you expect this to do? */