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
}
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)
{
#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

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 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 */

File diff suppressed because it is too large Load diff

View file

@ -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 */

View file

@ -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(&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;
}
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);

View file

@ -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

View file

@ -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));

View file

@ -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);

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(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));

View file

@ -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;
}
}

View file

@ -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 */

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_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;

View file

@ -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;
}

View file

@ -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? */