CPU improvements
Merged from TomB
This commit is contained in:
parent
8e3ae80c69
commit
4789eea572
17 changed files with 44870 additions and 10786 deletions
|
@ -205,9 +205,9 @@ struct instr_def defs68k[] = {
|
|||
/* RTR */
|
||||
{0x4E77, 0,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFFF,0,0,0,{{1,0},{1,0},{1,0},{1,0},{1,0}}, 3, 0,_T("RTR"), 1, 0,12, 0},
|
||||
/* MOVEC2 */
|
||||
{0x4E7A, 0,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFFF,1,0,2,{{1,1},{1,1},{1,1},{1,1},{1,1}}, 4, 16,_T("MOVEC2 #1"), 6, 0, 6, 0},
|
||||
{0x4E7A, 0,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFFF,1,0,0,{{1,1},{1,1},{1,1},{1,1},{1,1}}, 4, 16,_T("MOVEC2 #1"), 6, 0, 6, 0},
|
||||
/* MOVE2C */
|
||||
{0x4E7B, 0,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFFF,1,0,2,{{1,1},{1,1},{1,1},{1,1},{1,1}}, 4, 16,_T("MOVE2C #1"), 6, 0, 6, 0},
|
||||
{0x4E7B, 0,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFFF,1,0,0,{{1,1},{1,1},{1,1},{1,1},{1,1}}, 4, 16,_T("MOVE2C #1"), 6, 0, 6, 0},
|
||||
/* JSR.L */
|
||||
{0x4E80, 6,{11,11,11,12,12,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFC0,0,0,0,{{4,6},{4,6},{4,6},{4,6},{4,6}}, 2, 128,_T("JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]"), 0, 0, 4, 5},
|
||||
/* CHK.L */
|
||||
|
@ -455,11 +455,5 @@ struct instr_def defs68k[] = {
|
|||
/* MOVE16 */
|
||||
{0xF600, 6,{11,11,11,12,12,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFC0,4,0,0,{{1,1},{1,1},{1,1},{1,1},{1,1}}, 0, 18,_T("MOVE16 s[Aind],Al"), 0, 0, 0, 0},
|
||||
/* MOVE16 */
|
||||
{0xF600, 6,{13,13,13,14,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFC0,4,0,0,{{1,1},{1,1},{1,1},{1,1},{1,1}}, 0, 18,_T("MOVE16 Al,d[Aipi-Aind]"), 0, 0, 0, 0},
|
||||
/* LPSTOP */
|
||||
{0xF800, 0,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFFF,5,0,2,{{3,5},{3,5},{3,5},{3,5},{3,5}}, 4, 16,_T("LPSTOP #1"), 0, 0, 0, 0},
|
||||
/* PLPAW */
|
||||
{0xF588, 3,{15,15,15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFF8,5,0,2,{{1,1},{1,1},{1,1},{1,1},{1,1}}, 4, 0,_T("PLPAW Ara"), 0, 0, 0, 0},
|
||||
/* PLPAR */
|
||||
{0xF5C8, 3,{15,15,15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFF8,5,0,2,{{1,1},{1,1},{1,1},{1,1},{1,1}}, 4, 0,_T("PLPAR Ara"), 0, 0, 0, 0}};
|
||||
int n_defs68k = 230;
|
||||
{0xF600, 6,{13,13,13,14,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},0xFFC0,4,0,0,{{1,1},{1,1},{1,1},{1,1},{1,1}}, 0, 18,_T("MOVE16 Al,d[Aipi-Aind]"), 0, 0, 0, 0}};
|
||||
int n_defs68k = 227;
|
||||
|
|
6282
src/cpuemu_0.cpp
6282
src/cpuemu_0.cpp
File diff suppressed because it is too large
Load diff
30150
src/cpuemu_11.cpp
30150
src/cpuemu_11.cpp
File diff suppressed because it is too large
Load diff
3551
src/cpuemu_4.cpp
3551
src/cpuemu_4.cpp
File diff suppressed because it is too large
Load diff
6204
src/cpuemu_40.cpp
6204
src/cpuemu_40.cpp
File diff suppressed because it is too large
Load diff
3551
src/cpuemu_44.cpp
3551
src/cpuemu_44.cpp
File diff suppressed because it is too large
Load diff
2736
src/cpustbl.cpp
2736
src/cpustbl.cpp
File diff suppressed because it is too large
Load diff
22
src/fpp.cpp
22
src/fpp.cpp
|
@ -922,7 +922,7 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old
|
|||
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword ();
|
||||
break;
|
||||
case 6: // (d8,An,Xn)+
|
||||
ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0);
|
||||
ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg));
|
||||
break;
|
||||
case 7:
|
||||
switch (reg)
|
||||
|
@ -938,7 +938,7 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old
|
|||
ad += (uae_s32) (uae_s16) x_cp_next_iword ();
|
||||
break;
|
||||
case 3: // (d8,PC,Xn)+
|
||||
ad = x_cp_get_disp_ea_020 (m68k_getpc (), 0);
|
||||
ad = x_cp_get_disp_ea_020 (m68k_getpc ());
|
||||
break;
|
||||
case 4: // #imm
|
||||
doext = 1;
|
||||
|
@ -1092,7 +1092,7 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o
|
|||
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword ();
|
||||
break;
|
||||
case 6: // (d8,An,Xn)+
|
||||
ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0);
|
||||
ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg));
|
||||
break;
|
||||
case 7:
|
||||
switch (reg)
|
||||
|
@ -1198,7 +1198,7 @@ static int get_fp_ad (uae_u32 opcode, uae_u32 * ad)
|
|||
*ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword ();
|
||||
break;
|
||||
case 6: // (d8,An,Xn)+
|
||||
*ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0);
|
||||
*ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg));
|
||||
break;
|
||||
case 7:
|
||||
switch (reg)
|
||||
|
@ -1214,7 +1214,7 @@ static int get_fp_ad (uae_u32 opcode, uae_u32 * ad)
|
|||
*ad += (uae_s32) (uae_s16) x_cp_next_iword ();
|
||||
break;
|
||||
case 3: // (d8,PC,Xn)+
|
||||
*ad = x_cp_get_disp_ea_020 (m68k_getpc (), 0);
|
||||
*ad = x_cp_get_disp_ea_020 (m68k_getpc ());
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -1324,6 +1324,12 @@ static void maybe_idle_state (void)
|
|||
regs.fpu_state = 1;
|
||||
}
|
||||
|
||||
static void trace_t0_68040(void)
|
||||
{
|
||||
if (regs.t0 && currprefs.cpu_model == 68040)
|
||||
check_t0_trace();
|
||||
}
|
||||
|
||||
void fpuop_dbcc (uae_u32 opcode, uae_u16 extra)
|
||||
{
|
||||
uaecptr pc = m68k_getpc ();
|
||||
|
@ -1357,6 +1363,8 @@ void fpuop_dbcc (uae_u32 opcode, uae_u16 extra)
|
|||
regs.fp_branch = true;
|
||||
}
|
||||
}
|
||||
// 68040 FDBCC: T0 always
|
||||
trace_t0_68040();
|
||||
}
|
||||
|
||||
void fpuop_scc (uae_u32 opcode, uae_u16 extra)
|
||||
|
@ -1541,6 +1549,8 @@ void fpuop_save (uae_u32 opcode)
|
|||
x_cp_put_long(ad, fsave_data.et[2]); // ETM
|
||||
ad += 4;
|
||||
}
|
||||
// 68040 FSAVE: T0 always
|
||||
trace_t0_68040();
|
||||
} else { /* 68881/68882 */
|
||||
uae_u32 biu_flags = 0x540effff;
|
||||
int frame_size = currprefs.fpu_model == 68882 ? 0x3c : 0x1c;
|
||||
|
@ -2165,6 +2175,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
|
|||
m68k_areg (regs, opcode & 7) = ad;
|
||||
if ((opcode & 0x38) == 0x20)
|
||||
m68k_areg (regs, opcode & 7) = ad;
|
||||
trace_t0_68040();
|
||||
} else {
|
||||
/* FMOVEM Memory->Control Register */
|
||||
uae_u32 ad;
|
||||
|
@ -2254,6 +2265,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra)
|
|||
if (extra & 0x2000) {
|
||||
/* FMOVEM FPP->Memory */
|
||||
ad = fmovem2mem (ad, list, incr, regdir);
|
||||
trace_t0_68040();
|
||||
} else {
|
||||
/* FMOVEM Memory->FPP */
|
||||
ad = fmovem2fpp (ad, list, incr, regdir);
|
||||
|
|
10
src/include/cpummu030.h
Normal file
10
src/include/cpummu030.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef UAE_CPUMMU030_H
|
||||
#define UAE_CPUMMU030_H
|
||||
|
||||
#include "uae/types.h"
|
||||
|
||||
#include "mmu_common.h"
|
||||
|
||||
#define MAX_MMU030_ACCESS 9
|
||||
|
||||
#endif /* UAE_CPUMMU030_H */
|
2218
src/include/cputbl.h
2218
src/include/cputbl.h
File diff suppressed because it is too large
Load diff
|
@ -2,34 +2,26 @@
|
|||
#define UAE_MMU_COMMON_H
|
||||
|
||||
#include "uae/types.h"
|
||||
#include "uae/likely.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct m68k_exception {
|
||||
struct m68k_exception
|
||||
{
|
||||
int prb;
|
||||
m68k_exception (int exc) : prb (exc) {}
|
||||
operator int() { return prb; }
|
||||
|
||||
explicit m68k_exception(int exc) : prb(exc)
|
||||
{
|
||||
}
|
||||
|
||||
explicit operator int() const { return prb; }
|
||||
};
|
||||
|
||||
#define TRY(var) try
|
||||
#define CATCH(var) catch(m68k_exception var)
|
||||
#define THROW(n) throw m68k_exception(n)
|
||||
#define ENDTRY
|
||||
#else
|
||||
/* we are in plain C, just use a stack of long jumps */
|
||||
#include <setjmp.h>
|
||||
extern jmp_buf __exbuf;
|
||||
extern int __exvalue;
|
||||
#define TRY(DUMMY) __exvalue=setjmp(__exbuf); \
|
||||
if (__exvalue==0) { __pushtry(&__exbuf);
|
||||
#define CATCH(x) __poptry(); } else {m68k_exception x=__exvalue;
|
||||
#define ENDTRY __poptry();}
|
||||
#define THROW(x) if (__is_catched()) {longjmp(__exbuf,x);}
|
||||
jmp_buf* __poptry(void);
|
||||
void __pushtry(jmp_buf *j);
|
||||
int __is_catched(void);
|
||||
|
||||
typedef int m68k_exception;
|
||||
|
||||
#endif
|
||||
/* special status word (access error stack frame) */
|
||||
/* 68030 */
|
||||
#define MMU030_SSW_RW 0x0040
|
||||
#define MMU030_SSW_SIZE_W 0x0020
|
||||
|
||||
#endif /* UAE_MMU_COMMON_H */
|
||||
|
|
|
@ -132,6 +132,7 @@ struct regstruct
|
|||
|
||||
uae_u16 irc, ir, db;
|
||||
volatile uae_atomic spcflags;
|
||||
uae_u16 write_buffer, read_buffer;
|
||||
|
||||
uaecptr usp, isp, msp;
|
||||
uae_u16 sr;
|
||||
|
@ -142,6 +143,7 @@ struct regstruct
|
|||
flagtype x;
|
||||
flagtype stopped;
|
||||
int halted;
|
||||
int exception;
|
||||
int intmask;
|
||||
|
||||
uae_u32 vbr, sfc, dfc;
|
||||
|
@ -154,6 +156,7 @@ struct regstruct
|
|||
uae_u32 fpcr, fpsr, fpiar;
|
||||
uae_u32 fpu_state;
|
||||
uae_u32 fpu_exp_state;
|
||||
uae_u16 fp_opword;
|
||||
uaecptr fp_ea;
|
||||
uae_u32 fp_exp_pend, fp_unimp_pend;
|
||||
bool fpu_exp_pre;
|
||||
|
@ -164,6 +167,7 @@ struct regstruct
|
|||
uae_u32 cacr, caar;
|
||||
uae_u32 itt0, itt1, dtt0, dtt1;
|
||||
uae_u32 tcr, mmusr, urp, srp, buscr;
|
||||
uae_u32 mmu_fault_addr;
|
||||
|
||||
uae_u32 pcr;
|
||||
uae_u32 address_space_mask;
|
||||
|
@ -233,7 +237,7 @@ extern void (*x_put_long)(uaecptr addr, uae_u32 v);
|
|||
#define x_cp_next_iword() next_diword()
|
||||
#define x_cp_next_ilong() next_dilong()
|
||||
|
||||
#define x_cp_get_disp_ea_020(base,idx) _get_disp_ea_020(base)
|
||||
#define x_cp_get_disp_ea_020(base) _get_disp_ea_020(base)
|
||||
|
||||
/* direct (regs.pc_p) access */
|
||||
|
||||
|
@ -325,20 +329,6 @@ STATIC_INLINE void m68k_incpci(int o)
|
|||
regs.pc += o;
|
||||
}
|
||||
|
||||
STATIC_INLINE void m68k_do_bsri(uaecptr oldpc, uae_s32 offset)
|
||||
{
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), oldpc);
|
||||
m68k_incpci(offset);
|
||||
}
|
||||
|
||||
STATIC_INLINE void m68k_do_rtsi(void)
|
||||
{
|
||||
uae_u32 newpc = x_get_long(m68k_areg(regs, 7));
|
||||
m68k_setpci(newpc);
|
||||
m68k_areg(regs, 7) += 4;
|
||||
}
|
||||
|
||||
/* common access */
|
||||
|
||||
STATIC_INLINE void m68k_incpc_normal(int o)
|
||||
|
@ -370,7 +360,7 @@ extern void m68k_setstopped(void);
|
|||
extern void m68k_resumestopped(void);
|
||||
extern void m68k_cancel_idle(void);
|
||||
|
||||
#define get_disp_ea_020(base,idx) _get_disp_ea_020(base)
|
||||
#define get_disp_ea_020(base) _get_disp_ea_020(base)
|
||||
extern uae_u32 REGPARAM3 _get_disp_ea_020(uae_u32 base) REGPARAM;
|
||||
|
||||
extern uae_u32 REGPARAM3 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM;
|
||||
|
@ -389,17 +379,17 @@ extern void doint(void);
|
|||
extern void dump_counts(void);
|
||||
extern int m68k_move2c(int, uae_u32*);
|
||||
extern int m68k_movec2(int, uae_u32*);
|
||||
extern void m68k_divl(uae_u32, uae_u32, uae_u16);
|
||||
extern void m68k_mull(uae_u32, uae_u32, uae_u16);
|
||||
extern bool m68k_divl (uae_u32, uae_u32, uae_u16);
|
||||
extern bool m68k_mull (uae_u32, uae_u32, uae_u16);
|
||||
extern void init_m68k(void);
|
||||
extern void m68k_go(int);
|
||||
extern int getDivu68kCycles(uae_u32 dividend, uae_u16 divisor);
|
||||
extern int getDivs68kCycles(uae_s32 dividend, uae_s16 divisor);
|
||||
extern void divbyzero_special(bool issigned, uae_s32 dst);
|
||||
extern void setdivuoverflowflags(uae_u32 dividend, uae_u16 divisor);
|
||||
extern void setdivsoverflowflags(uae_s32 dividend, uae_s16 divisor);
|
||||
extern void setdivuflags(uae_u32 dividend, uae_u16 divisor);
|
||||
extern void setdivsflags(uae_s32 dividend, uae_s16 divisor);
|
||||
extern void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size);
|
||||
extern void setchk2undefinedflags(uae_u32 lower, uae_u32 upper, uae_u32 val, int size);
|
||||
extern void setchk2undefinedflags(uae_s32 lower, uae_s32 upper, uae_s32 val, int size);
|
||||
extern void protect_roms(bool);
|
||||
extern void unprotect_maprom(void);
|
||||
extern bool is_hardreset(void);
|
||||
|
@ -409,6 +399,9 @@ extern void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 s
|
|||
extern void Exception_build_68000_address_error_stack_frame(uae_u16 mode, uae_u16 opcode, uaecptr fault_addr,
|
||||
uaecptr pc);
|
||||
extern uae_u32 exception_pc(int nr);
|
||||
extern void cpu_restore_fixup(void);
|
||||
extern bool privileged_copro_instruction(uae_u16 opcode);
|
||||
extern bool generates_group1_exception(uae_u16 opcode);
|
||||
|
||||
void ccr_68000_long_move_ae_LZN(uae_s32 src);
|
||||
void ccr_68000_long_move_ae_LN(uae_s32 src);
|
||||
|
@ -443,11 +436,12 @@ extern void fpuop_save(uae_u32);
|
|||
extern void fpuop_restore(uae_u32);
|
||||
extern void fpu_reset(void);
|
||||
|
||||
extern void exception3_read(uae_u32 opcode, uaecptr addr);
|
||||
extern void exception3_write(uae_u32 opcode, uaecptr addr);
|
||||
extern void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc);
|
||||
extern void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc);
|
||||
extern void exception3i(uae_u32 opcode, uaecptr addr);
|
||||
extern void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc);
|
||||
extern void exception2(uaecptr addr, bool read, int size, uae_u32 fc);
|
||||
extern void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc);
|
||||
extern void cpureset(void);
|
||||
extern void cpu_halt(int id);
|
||||
extern int cpu_sleep_millis(int ms);
|
||||
|
|
|
@ -35,7 +35,7 @@ ENUMDECL {
|
|||
i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16,
|
||||
i_MMUOP030, i_PFLUSHN, i_PFLUSH, i_PFLUSHAN, i_PFLUSHA,
|
||||
i_PLPAR, i_PLPAW, i_PTESTR, i_PTESTW,
|
||||
i_LPSTOP,
|
||||
i_LPSTOP, i_HALT, i_PULSE,
|
||||
MAX_OPCODE_FAMILY
|
||||
} ENUMNAME (instrmnem);
|
||||
|
||||
|
@ -110,7 +110,7 @@ extern struct instr {
|
|||
unsigned int cc:4;
|
||||
unsigned int plev:2;
|
||||
unsigned int size:2;
|
||||
unsigned int unsized:1;
|
||||
unsigned int unsized:1;
|
||||
unsigned int smode:5;
|
||||
unsigned int stype:3;
|
||||
unsigned int dmode:5;
|
||||
|
|
|
@ -44,7 +44,11 @@ typedef uae_u32 uintptr;
|
|||
#define TAGMASK 0x0000ffff
|
||||
#define TAGSIZE (TAGMASK+1)
|
||||
#define MAXRUN 1024
|
||||
#define cacheline(x) (((uintptr)x)&TAGMASK)
|
||||
#if defined(CPU_AARCH64)
|
||||
#define cacheline(x) (((uae_u64)x)&TAGMASK)
|
||||
#else
|
||||
#define cacheline(x) (((uae_u32)x)&TAGMASK)
|
||||
#endif
|
||||
|
||||
extern uae_u8* start_pc_p;
|
||||
extern uae_u32 start_pc;
|
||||
|
@ -360,7 +364,7 @@ typedef struct blockinfo_t {
|
|||
#define BI_COMPILING 5
|
||||
#define BI_FINALIZING 6
|
||||
|
||||
#if defined(CPU_arm) && !defined(ARMV6T2)
|
||||
#if defined(CPU_arm) && !defined(ARMV6T2) && !defined(CPU_AARCH64)
|
||||
const int POPALLSPACE_SIZE = 2048; /* That should be enough space */
|
||||
#else
|
||||
const int POPALLSPACE_SIZE = 512; /* That should be enough space */
|
||||
|
|
201
src/newcpu.cpp
201
src/newcpu.cpp
|
@ -40,8 +40,12 @@ static uaecptr last_addr_for_exception_3;
|
|||
static uaecptr last_fault_for_exception_3;
|
||||
/* read (0) or write (1) access */
|
||||
static bool last_writeaccess_for_exception_3;
|
||||
/* instruction (1) or data (0) access */
|
||||
static bool last_instructionaccess_for_exception_3;
|
||||
/* size */
|
||||
static bool last_size_for_exception_3;
|
||||
/* FC */
|
||||
static int last_fc_for_exception_3;
|
||||
/* Data (1) or instruction fetch (0) */
|
||||
static int last_di_for_exception_3;
|
||||
/* not instruction */
|
||||
static bool last_notinstruction_for_exception_3;
|
||||
/* set when writing exception stack frame */
|
||||
|
@ -81,7 +85,7 @@ static uae_u16 fake_mmusr_030;
|
|||
int cpu_last_stop_vpos, cpu_stopped_lines;
|
||||
|
||||
#if COUNT_INSTRS
|
||||
static uae_u32 instrcount[65536];
|
||||
static unsigned long instrcount[65536];
|
||||
static uae_u16 opcodenums[65536];
|
||||
|
||||
static int compfn (const void *el1, const void *el2)
|
||||
|
@ -100,7 +104,7 @@ static TCHAR *icountfilename (void)
|
|||
void dump_counts (void)
|
||||
{
|
||||
FILE *f = fopen (icountfilename (), "w");
|
||||
uae_u32 total;
|
||||
unsigned long total;
|
||||
int i;
|
||||
|
||||
write_log (_T("Writing instruction count file...\n"));
|
||||
|
@ -112,7 +116,7 @@ void dump_counts (void)
|
|||
|
||||
fprintf (f, "Total: %lu\n", total);
|
||||
for (i=0; i < 65536; i++) {
|
||||
uae_u32 cnt = instrcount[opcodenums[i]];
|
||||
unsigned long cnt = instrcount[opcodenums[i]];
|
||||
struct instr *dp;
|
||||
struct mnemolookup *lookup;
|
||||
if (!cnt)
|
||||
|
@ -284,7 +288,7 @@ static const struct cputbl* cputbls[5][3] =
|
|||
static void build_cpufunctbl(void)
|
||||
{
|
||||
int i;
|
||||
uae_u32 opcode;
|
||||
unsigned long opcode;
|
||||
const struct cputbl* tbl = nullptr;
|
||||
int lvl, mode;
|
||||
|
||||
|
@ -653,7 +657,7 @@ void REGPARAM2 MakeSR(void)
|
|||
| GET_CFLG());
|
||||
}
|
||||
|
||||
STATIC_INLINE void MakeFromSR_x(int t0trace)
|
||||
static void MakeFromSR_x(int t0trace)
|
||||
{
|
||||
int oldm = regs.m;
|
||||
int olds = regs.s;
|
||||
|
@ -760,8 +764,7 @@ void REGPARAM2 MakeFromSR(void)
|
|||
static void exception_check_trace(int nr)
|
||||
{
|
||||
unset_special(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
|
||||
if (regs.t1 && !regs.t0)
|
||||
{
|
||||
if (regs.t1) {
|
||||
/* trace stays pending if exception is div by zero, chk,
|
||||
* trapv or trap #x
|
||||
*/
|
||||
|
@ -876,7 +879,7 @@ static void add_approximate_exception_cycles(int nr)
|
|||
|
||||
static void exception3_notinstruction(uae_u32 opcode, uaecptr addr);
|
||||
|
||||
void Exception(int nr)
|
||||
static void Exception_normal (int nr)
|
||||
{
|
||||
uae_u32 newpc;
|
||||
uae_u32 currpc = m68k_getpc();
|
||||
|
@ -887,11 +890,6 @@ void Exception(int nr)
|
|||
|
||||
interrupt = nr >= 24 && nr < 24 + 8;
|
||||
|
||||
#ifdef JIT
|
||||
if (currprefs.cachesize)
|
||||
regs.instruction_pc = m68k_getpc();
|
||||
#endif
|
||||
|
||||
if (interrupt && currprefs.cpu_model <= 68010)
|
||||
vector_nr = iack_cycle(nr);
|
||||
|
||||
|
@ -984,25 +982,27 @@ void Exception(int nr)
|
|||
else if (currprefs.cpu_model >= 68020)
|
||||
{
|
||||
// 68020/030 odd PC address error (partially implemented only)
|
||||
uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
|
||||
ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
|
||||
ssw |= 0x20;
|
||||
Exception_build_stack_frame(oldpc, currpc, ssw, nr, 0x0a);
|
||||
// annoyingly this generates frame B, not A.
|
||||
uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3;
|
||||
ssw |= MMU030_SSW_RW | MMU030_SSW_SIZE_W;
|
||||
regs.mmu_fault_addr = last_fault_for_exception_3;
|
||||
Exception_build_stack_frame(last_fault_for_exception_3, currpc, ssw, nr, 0x0b);
|
||||
used_exception_build_stack_frame = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 68010 address error (partially implemented only)
|
||||
uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
|
||||
ssw |= last_writeaccess_for_exception_3 ? 0 : 0x100;
|
||||
ssw |= last_instructionaccess_for_exception_3 ? 0 : 0x2000;
|
||||
} else {
|
||||
// 68010 bus/address error (partially implemented only)
|
||||
uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3;
|
||||
ssw |= last_di_for_exception_3 ? 0x0000 : 0x2000; // IF
|
||||
ssw |= (!last_writeaccess_for_exception_3 && last_di_for_exception_3) ? 0x1000 : 0x000; // DF
|
||||
ssw |= (last_op_for_exception_3 & 0x10000) ? 0x0400 : 0x0000; // HB
|
||||
ssw |= last_size_for_exception_3 == 0 ? 0x0200 : 0x0000; // BY
|
||||
ssw |= last_writeaccess_for_exception_3 ? 0x0000 : 0x0100; // RW
|
||||
if (last_op_for_exception_3 & 0x20000)
|
||||
ssw &= 0x00ff;
|
||||
regs.mmu_fault_addr = last_addr_for_exception_3;
|
||||
Exception_build_stack_frame(oldpc, currpc, ssw, nr, 0x08);
|
||||
used_exception_build_stack_frame = true;
|
||||
}
|
||||
}
|
||||
else if (regs.m && interrupt)
|
||||
{
|
||||
/* M + Interrupt */
|
||||
} else if (regs.m && interrupt) { /* M + Interrupt */
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), vector_nr * 4);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
|
@ -1025,19 +1025,13 @@ void Exception(int nr)
|
|||
else
|
||||
{
|
||||
nextpc = m68k_getpc();
|
||||
if (nr == 2 || nr == 3)
|
||||
{
|
||||
// 68000 bus error/address error
|
||||
uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
|
||||
if (nr == 2 || nr == 3) {
|
||||
// 68000 bus/address error
|
||||
uae_u16 mode = (sv ? 4 : 0) | last_fc_for_exception_3;
|
||||
mode |= last_writeaccess_for_exception_3 ? 0 : 16;
|
||||
mode |= last_notinstruction_for_exception_3 ? 8 : 0;
|
||||
uae_u16 statusormask = (last_op_for_exception_3 >> 16) & 0xff;
|
||||
uae_u16 statusandmask = (last_op_for_exception_3 >> 24) & 0xff;
|
||||
mode |= statusormask;
|
||||
mode &= ~statusandmask;
|
||||
exception_in_exception = -1;
|
||||
Exception_build_68000_address_error_stack_frame(mode, last_op_for_exception_3, last_fault_for_exception_3,
|
||||
last_addr_for_exception_3);
|
||||
Exception_build_68000_address_error_stack_frame(mode, last_op_for_exception_3, last_fault_for_exception_3, last_addr_for_exception_3);
|
||||
goto kludge_me_do;
|
||||
}
|
||||
}
|
||||
|
@ -1069,16 +1063,38 @@ kludge_me_do:
|
|||
exception_check_trace(nr);
|
||||
}
|
||||
|
||||
// address = format $2 stack frame address field
|
||||
static void ExceptionX (int nr)
|
||||
{
|
||||
regs.exception = nr;
|
||||
|
||||
#ifdef JIT
|
||||
if (currprefs.cachesize)
|
||||
regs.instruction_pc = m68k_getpc ();
|
||||
#endif
|
||||
|
||||
{
|
||||
Exception_normal(nr);
|
||||
}
|
||||
regs.exception = 0;
|
||||
}
|
||||
|
||||
void REGPARAM2 Exception_cpu(int nr)
|
||||
{
|
||||
bool t0 = currprefs.cpu_model >= 68020 && regs.t0;
|
||||
Exception(nr);
|
||||
// check T0 trace
|
||||
if (t0)
|
||||
{
|
||||
bool t0 = currprefs.cpu_model >= 68020 && regs.t0 && !regs.t1;
|
||||
ExceptionX (nr);
|
||||
// Check T0 trace
|
||||
// RTE format error ignores T0 trace
|
||||
if (nr != 14) {
|
||||
if (t0) {
|
||||
activate_trace();
|
||||
}
|
||||
}
|
||||
}
|
||||
void REGPARAM2 Exception (int nr)
|
||||
{
|
||||
ExceptionX (nr);
|
||||
}
|
||||
|
||||
static void bus_error(void)
|
||||
{
|
||||
|
@ -1114,6 +1130,13 @@ void NMI(void)
|
|||
do_interrupt(7);
|
||||
}
|
||||
|
||||
static void maybe_disable_fpu(void)
|
||||
{
|
||||
if (!currprefs.fpu_model) {
|
||||
regs.pcr |= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void m68k_reset_sr(void)
|
||||
{
|
||||
SET_XFLG((regs.sr >> 4) & 1);
|
||||
|
@ -1147,13 +1170,13 @@ static void m68k_reset(bool hardreset)
|
|||
regs.spcflags = 0;
|
||||
|
||||
#ifdef SAVESTATE
|
||||
if (isrestore())
|
||||
{
|
||||
if (isrestore ()) {
|
||||
m68k_reset_sr();
|
||||
m68k_setpc_normal(regs.pc);
|
||||
return;
|
||||
} else {
|
||||
set_special(SPCFLAG_CHECK);
|
||||
}
|
||||
set_special(SPCFLAG_CHECK);
|
||||
#endif
|
||||
regs.s = 1;
|
||||
v = get_long(4);
|
||||
|
@ -1255,9 +1278,13 @@ uae_u32 REGPARAM2 op_illg(uae_u32 opcode)
|
|||
}
|
||||
#endif
|
||||
|
||||
if ((opcode & 0xF000) == 0xF000)
|
||||
{
|
||||
if ((opcode & 0xF000) == 0xF000) {
|
||||
// Missing MMU or FPU cpSAVE/cpRESTORE privilege check
|
||||
if (privileged_copro_instruction(opcode)) {
|
||||
Exception(8);
|
||||
} else {
|
||||
Exception(0xB);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
if ((opcode & 0xF000) == 0xA000)
|
||||
|
@ -1535,8 +1562,7 @@ void mmu_op(uae_u32 opcode, uae_u32 extra)
|
|||
|
||||
static void do_trace(void)
|
||||
{
|
||||
if (regs.t0 && currprefs.cpu_model >= 68020)
|
||||
{
|
||||
if (regs.t0 && !regs.t1 && currprefs.cpu_model >= 68020) {
|
||||
// this is obsolete
|
||||
return;
|
||||
}
|
||||
|
@ -1574,8 +1600,7 @@ static void check_uae_int_request(void)
|
|||
|
||||
int cpu_sleep_millis(int ms)
|
||||
{
|
||||
const auto ret = sleep_millis_main(ms);
|
||||
return ret;
|
||||
return sleep_millis_main(ms);
|
||||
}
|
||||
|
||||
static bool haltloop(void)
|
||||
|
@ -1637,6 +1662,7 @@ static int do_specialties(int cycles)
|
|||
/* exit from HRTMon? */
|
||||
if (hrtmon_flag == ACTION_REPLAY_ACTIVE && !isinhrt)
|
||||
hrtmon_hide();
|
||||
/* HRTMon breakpoint? (not via IRQ7) */
|
||||
if (hrtmon_flag == ACTION_REPLAY_ACTIVATE)
|
||||
hrtmon_enter();
|
||||
}
|
||||
|
@ -2356,8 +2382,7 @@ uae_u8* save_cpu(int* len, uae_u8* dstptr)
|
|||
|
||||
#endif /* SAVESTATE */
|
||||
|
||||
static void exception3f(uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction,
|
||||
uaecptr pc, bool plus2)
|
||||
static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, int size, bool plus2, int fc)
|
||||
{
|
||||
if (currprefs.cpu_model >= 68040)
|
||||
addr &= ~1;
|
||||
|
@ -2381,49 +2406,81 @@ static void exception3f(uae_u32 opcode, uaecptr addr, bool writeaccess, bool ins
|
|||
last_fault_for_exception_3 = addr;
|
||||
last_op_for_exception_3 = opcode;
|
||||
last_writeaccess_for_exception_3 = writeaccess;
|
||||
last_instructionaccess_for_exception_3 = instructionaccess;
|
||||
last_fc_for_exception_3 = fc >= 0 ? fc : (instructionaccess ? 2 : 1);
|
||||
last_notinstruction_for_exception_3 = notinstruction;
|
||||
last_size_for_exception_3 = size;
|
||||
Exception(3);
|
||||
}
|
||||
|
||||
static void exception3_notinstruction(uae_u32 opcode, uaecptr addr)
|
||||
{
|
||||
exception3f(opcode, addr, true, false, true, 0xffffffff, false);
|
||||
exception3f (opcode, addr, true, false, true, 0xffffffff, 1, false, -1);
|
||||
}
|
||||
|
||||
void exception3_read(uae_u32 opcode, uaecptr addr)
|
||||
void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc)
|
||||
{
|
||||
exception3f(opcode, addr, false, false, false, 0xffffffff, false);
|
||||
bool ni = false;
|
||||
if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
|
||||
if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) {
|
||||
ni = true;
|
||||
fc = -1;
|
||||
}
|
||||
if (opcode & 0x10000)
|
||||
ni = true;
|
||||
opcode = regs.ir;
|
||||
}
|
||||
|
||||
void exception3_write(uae_u32 opcode, uaecptr addr)
|
||||
exception3f (opcode, addr, false, 0, ni, 0xffffffff, size, false, fc);
|
||||
}
|
||||
void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
|
||||
{
|
||||
exception3f(opcode, addr, true, false, false, 0xffffffff, false);
|
||||
bool ni = false;
|
||||
if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
|
||||
if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) {
|
||||
ni = true;
|
||||
fc = -1;
|
||||
}
|
||||
if (opcode & 0x10000)
|
||||
ni = true;
|
||||
opcode = regs.ir;
|
||||
}
|
||||
exception3f (opcode, addr, true, 0, ni, 0xffffffff, size, false, fc);
|
||||
regs.write_buffer = val;
|
||||
}
|
||||
|
||||
void exception3i(uae_u32 opcode, uaecptr addr)
|
||||
{
|
||||
exception3f(opcode, addr, false, true, false, 0xffffffff, true);
|
||||
exception3f (opcode, addr, 0, 1, false, 0xffffffff, 1, true, -1);
|
||||
}
|
||||
|
||||
void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
|
||||
{
|
||||
exception3f(opcode, addr, w, i, false, pc, true);
|
||||
exception3f (opcode, addr, w, i, false, pc, 1, true, -1);
|
||||
}
|
||||
|
||||
void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc)
|
||||
{
|
||||
uae_u32 opcode = last_op_for_exception_3;
|
||||
last_addr_for_exception_3 = m68k_getpc();
|
||||
last_fault_for_exception_3 = addr;
|
||||
last_writeaccess_for_exception_3 = read == 0;
|
||||
last_instructionaccess_for_exception_3 = (fc & 1) == 0;
|
||||
last_fc_for_exception_3 = fc;
|
||||
last_op_for_exception_3 = regs.opcode;
|
||||
last_notinstruction_for_exception_3 = exception_in_exception != 0;
|
||||
last_size_for_exception_3 = size;
|
||||
last_di_for_exception_3 = 1;
|
||||
|
||||
if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
|
||||
if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) {
|
||||
last_notinstruction_for_exception_3 = true;
|
||||
fc = -1;
|
||||
}
|
||||
if (opcode & 0x10000)
|
||||
last_notinstruction_for_exception_3 = true;
|
||||
if (!(opcode & 0x20000))
|
||||
last_op_for_exception_3 = regs.ir;
|
||||
}
|
||||
}
|
||||
|
||||
void exception2(uaecptr addr, bool read, int size, uae_u32 fc)
|
||||
{
|
||||
exception2_setup(addr, read, size, fc);
|
||||
exception2_setup(addr, read, size == 1 ? 0 : (size == 2 ? 1 : 2), fc);
|
||||
THROW(2);
|
||||
}
|
||||
|
||||
|
@ -2435,6 +2492,7 @@ void cpureset(void)
|
|||
uae_u16 ins;
|
||||
addrbank* ab;
|
||||
|
||||
maybe_disable_fpu();
|
||||
set_special(SPCFLAG_CHECK);
|
||||
send_internalevent(INTERNALEVENT_CPURESET);
|
||||
if (currprefs.cpu_compatible && currprefs.cpu_model <= 68020)
|
||||
|
@ -2495,8 +2553,7 @@ void m68k_resumestopped(void)
|
|||
|
||||
void check_t0_trace(void)
|
||||
{
|
||||
if (regs.t0 && currprefs.cpu_model >= 68020)
|
||||
{
|
||||
if (regs.t0 && !regs.t1 && currprefs.cpu_model >= 68020) {
|
||||
unset_special(SPCFLAG_TRACE);
|
||||
set_special(SPCFLAG_DOTRACE);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "options.h"
|
||||
#include "memory.h"
|
||||
#include "newcpu.h"
|
||||
#include "cpummu030.h"
|
||||
|
||||
int get_cpu_model(void)
|
||||
{
|
||||
|
@ -42,9 +43,17 @@ static int movec_illg (int regno)
|
|||
int m68k_move2c (int regno, uae_u32 *regp)
|
||||
{
|
||||
if (movec_illg (regno)) {
|
||||
if (!regs.s) {
|
||||
Exception(8);
|
||||
return 0;
|
||||
}
|
||||
op_illg (0x4E7B);
|
||||
return 0;
|
||||
} else {
|
||||
if (!regs.s) {
|
||||
Exception(8);
|
||||
return 0;
|
||||
}
|
||||
switch (regno) {
|
||||
case 0: regs.sfc = *regp & 7; break;
|
||||
case 1: regs.dfc = *regp & 7; break;
|
||||
|
@ -61,18 +70,15 @@ int m68k_move2c (int regno, uae_u32 *regp)
|
|||
set_cpu_caches(false);
|
||||
}
|
||||
break;
|
||||
/* 68040/060 only */
|
||||
/* 68040 only */
|
||||
case 3:
|
||||
regs.tcr = *regp & 0xc000;
|
||||
break;
|
||||
|
||||
/* no differences between 68040 and 68060 */
|
||||
case 4: regs.itt0 = *regp & 0xffffe364; break;
|
||||
case 5: regs.itt1 = *regp & 0xffffe364; break;
|
||||
case 6: regs.dtt0 = *regp & 0xffffe364; break;
|
||||
case 7: regs.dtt1 = *regp & 0xffffe364; break;
|
||||
/* 68060 only */
|
||||
case 8: regs.buscr = *regp & 0xf0000000; break;
|
||||
|
||||
case 0x800: regs.usp = *regp; break;
|
||||
case 0x801: regs.vbr = *regp; break;
|
||||
|
@ -81,9 +87,9 @@ int m68k_move2c (int regno, uae_u32 *regp)
|
|||
case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break;
|
||||
/* 68040 only */
|
||||
case 0x805: regs.mmusr = *regp; break;
|
||||
/* 68040 stores all bits, 68060 zeroes low 9 bits */
|
||||
case 0x806: regs.urp = *regp; break;
|
||||
case 0x807: regs.srp = *regp; break;
|
||||
/* 68040 stores all bits */
|
||||
case 0x806: regs.urp = *regp & 0xffffffff; break;
|
||||
case 0x807: regs.srp = *regp & 0xffffffff; break;
|
||||
default:
|
||||
op_illg (0x4E7B);
|
||||
return 0;
|
||||
|
@ -95,9 +101,17 @@ int m68k_move2c (int regno, uae_u32 *regp)
|
|||
int m68k_movec2 (int regno, uae_u32 *regp)
|
||||
{
|
||||
if (movec_illg (regno)) {
|
||||
if (!regs.s) {
|
||||
Exception(8);
|
||||
return 0;
|
||||
}
|
||||
op_illg (0x4E7A);
|
||||
return 0;
|
||||
} else {
|
||||
if (!regs.s) {
|
||||
Exception(8);
|
||||
return 0;
|
||||
}
|
||||
switch (regno) {
|
||||
case 0: *regp = regs.sfc; break;
|
||||
case 1: *regp = regs.dfc; break;
|
||||
|
@ -229,7 +243,6 @@ uae_u32 REGPARAM2 _get_disp_ea_020 (uae_u32 base)
|
|||
regd = (uae_s32)(uae_s16)regd;
|
||||
regd <<= (dp >> 9) & 3;
|
||||
if (dp & 0x100) {
|
||||
|
||||
uae_s32 outer = 0;
|
||||
if (dp & 0x80) base = 0;
|
||||
if (dp & 0x40) regd = 0;
|
||||
|
@ -396,7 +409,7 @@ int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor)
|
|||
*
|
||||
* 68000 Signed: NVC=0 Z=1. Unsigned: VC=0 N=(dst>>16)<0 Z=(dst>>16)==0
|
||||
* 68020 and 68030: Signed: Z=1 NC=0. V=? (sometimes random!) Unsigned: V=1, N=(dst>>16)<0 Z=(dst>>16)==0, C=0.
|
||||
* 68040/68060 C=0.
|
||||
* 68040 C=0.
|
||||
*
|
||||
*/
|
||||
void divbyzero_special (bool issigned, uae_s32 dst)
|
||||
|
@ -413,7 +426,7 @@ void divbyzero_special (bool issigned, uae_s32 dst)
|
|||
SET_ZFLG(1);
|
||||
SET_VFLG (1);
|
||||
}
|
||||
} else if (currprefs.cpu_model >= 68040) {
|
||||
} else if (currprefs.cpu_model == 68040) {
|
||||
SET_CFLG (0);
|
||||
} else {
|
||||
// 68000/010
|
||||
|
@ -432,47 +445,58 @@ void divbyzero_special (bool issigned, uae_s32 dst)
|
|||
|
||||
/* DIVU overflow
|
||||
*
|
||||
* 68000: V=1 N=1
|
||||
* 68020: V=1 N=X
|
||||
* 68040: V=1
|
||||
* 68060: V=1
|
||||
* 68000: V=1, N=1, C=0, Z=0
|
||||
* 68010: V=1, N=divisor<0x8000, C=0, Z=divided upper word == 0xffff and divisor == 0xffff
|
||||
* 68020: V=1, C=0, Z=0, N=X
|
||||
* 68040: V=1, C=0, NZ not modified.
|
||||
*
|
||||
* X) N is set if original 32-bit destination value is negative.
|
||||
*
|
||||
*/
|
||||
|
||||
void setdivuoverflowflags(uae_u32 dividend, uae_u16 divisor)
|
||||
void setdivuflags(uae_u32 dividend, uae_u16 divisor)
|
||||
{
|
||||
if (currprefs.cpu_model >= 68040) {
|
||||
if (currprefs.cpu_model == 68040) {
|
||||
SET_VFLG(1);
|
||||
SET_CFLG(0);
|
||||
} else if (currprefs.cpu_model >= 68020) {
|
||||
SET_VFLG(1);
|
||||
if ((uae_s32)dividend < 0)
|
||||
SET_NFLG(1);
|
||||
} else if (currprefs.cpu_model == 68010) {
|
||||
SET_VFLG(1);
|
||||
SET_NFLG(divisor < 0x8000);
|
||||
// can anyone explain this?
|
||||
SET_ZFLG((dividend >> 16) == 0xffff && divisor == 0xffff);
|
||||
SET_CFLG(0);
|
||||
} else {
|
||||
// 68000
|
||||
SET_VFLG(1);
|
||||
SET_NFLG(1);
|
||||
SET_ZFLG(0);
|
||||
SET_CFLG(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* DIVS overflow
|
||||
*
|
||||
* 68000: V = 1 N = 1
|
||||
* 68020: V = 1 ZN = X
|
||||
* 68040: V = 1
|
||||
* 68060: V = 1
|
||||
* 68000: V=1, C=0, N=1, Z=0
|
||||
* 68020: V=1, C=0, ZN = X
|
||||
* 68040: V=1, C=0. NZ not modified.
|
||||
*
|
||||
* X) if absolute overflow(Check getDivs68kCycles for details) : Z = 0, N = 0
|
||||
* if not absolute overflow : N is set if internal result BYTE is negative, Z is set if it is zero!
|
||||
*
|
||||
*/
|
||||
|
||||
void setdivsoverflowflags(uae_s32 dividend, uae_s16 divisor)
|
||||
void setdivsflags(uae_s32 dividend, uae_s16 divisor)
|
||||
{
|
||||
if (currprefs.cpu_model >= 68040) {
|
||||
if (currprefs.cpu_model == 68040) {
|
||||
SET_VFLG(1);
|
||||
SET_CFLG(0);
|
||||
} else if (currprefs.cpu_model >= 68020) {
|
||||
CLEAR_CZNV();
|
||||
SET_VFLG(1);
|
||||
// absolute overflow?
|
||||
if (((uae_u32)abs(dividend) >> 16) >= (uae_u16)abs(divisor))
|
||||
|
@ -482,23 +506,30 @@ void setdivsoverflowflags(uae_s32 dividend, uae_s16 divisor)
|
|||
SET_ZFLG(1);
|
||||
if ((uae_s8)aquot < 0)
|
||||
SET_NFLG(1);
|
||||
} else if (currprefs.cpu_model == 68010) {
|
||||
CLEAR_CZNV();
|
||||
SET_VFLG(1);
|
||||
SET_NFLG(1);
|
||||
} else {
|
||||
// 68000
|
||||
CLEAR_CZNV();
|
||||
SET_VFLG(1);
|
||||
SET_NFLG(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CHK.W undefined flags
|
||||
* CHK undefined flags
|
||||
*
|
||||
* 68000: CV=0. Z: dst==0. N: dst < 0. !N: dst > src.
|
||||
* 68020: Z: dst==0. N: dst < 0. V: src-dst overflow. C: if dst < 0: (dst > src || src >= 0), if dst > src: (src >= 0).
|
||||
* 68040: C=0. C=1 if exception and (dst < 0 && src >= 0) || (src >= 0 && dst >= src) || (dst < 0 && src < dst)
|
||||
*
|
||||
*/
|
||||
void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
|
||||
{
|
||||
CLEAR_CZNV();
|
||||
if (currprefs.cpu_model < 68020) {
|
||||
CLEAR_CZNV();
|
||||
if (dst == 0)
|
||||
SET_ZFLG(1);
|
||||
if (dst < 0)
|
||||
|
@ -506,6 +537,7 @@ void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
|
|||
else if (dst > src)
|
||||
SET_NFLG(0);
|
||||
} else if (currprefs.cpu_model == 68020 || currprefs.cpu_model == 68030) {
|
||||
CLEAR_CZNV();
|
||||
if (dst == 0)
|
||||
SET_ZFLG(1);
|
||||
SET_NFLG(dst < 0);
|
||||
|
@ -529,72 +561,200 @@ void setchkundefinedflags(uae_s32 src, uae_s32 dst, int size)
|
|||
SET_CFLG(src >= 0);
|
||||
}
|
||||
}
|
||||
} else if (currprefs.cpu_model == 68040) {
|
||||
SET_CFLG(0);
|
||||
if (dst < 0 || dst > src) {
|
||||
if (dst < 0 && src >= 0) {
|
||||
SET_CFLG(1);
|
||||
} else if (src >= 0 && dst >= src) {
|
||||
SET_CFLG(1);
|
||||
} else if (dst < 0 && src < dst) {
|
||||
SET_CFLG(1);
|
||||
}
|
||||
}
|
||||
SET_NFLG(dst < 0);
|
||||
}
|
||||
}
|
||||
|
||||
void setchk2undefinedflags(uae_u32 lower, uae_u32 upper, uae_u32 val, int size)
|
||||
/*
|
||||
* CHK2/CMP2 undefined flags
|
||||
*
|
||||
* 68020-68030: See below..
|
||||
* 68040: NV not modified.
|
||||
*
|
||||
*/
|
||||
|
||||
// This is the complex one.
|
||||
// Someone else can attempt to simplify this..
|
||||
void setchk2undefinedflags(uae_s32 lower, uae_s32 upper, uae_s32 val, int size)
|
||||
{
|
||||
uae_u32 nmask;
|
||||
if (size == sz_byte)
|
||||
nmask = 0x80;
|
||||
else if (size == sz_word)
|
||||
nmask = 0x8000;
|
||||
else
|
||||
nmask = 0x80000000;
|
||||
if (currprefs.cpu_model == 68040) {
|
||||
return;
|
||||
}
|
||||
|
||||
SET_NFLG(0);
|
||||
if ((upper & nmask) && val > upper) {
|
||||
SET_NFLG(1);
|
||||
} else if (!(upper & nmask) && val > upper && val < nmask) {
|
||||
SET_NFLG(1);
|
||||
} else if (val < lower) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
SET_VFLG(0);
|
||||
}
|
||||
|
||||
#if !defined (uae_s64)
|
||||
STATIC_INLINE int div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
|
||||
{
|
||||
uae_u32 q = 0, cbit = 0;
|
||||
int i;
|
||||
if (val == lower || val == upper)
|
||||
return;
|
||||
|
||||
if (div <= src_hi) {
|
||||
return 1;
|
||||
if (lower < 0 && upper >= 0) {
|
||||
if (val < lower) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
if (val >= 0 && val < upper) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
if (val >= 0 && lower - val >= 0) {
|
||||
SET_VFLG(1);
|
||||
SET_NFLG(0);
|
||||
if (val > upper) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
}
|
||||
} else if (lower >= 0 && upper < 0) {
|
||||
if (val >= 0) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
if (val > upper) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
if (val > lower && upper - val >= 0) {
|
||||
SET_VFLG(1);
|
||||
SET_NFLG(0);
|
||||
}
|
||||
} else if (lower >= 0 && upper >= 0 && lower > upper) {
|
||||
if (val > upper && val < lower) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
if (val < 0 && lower - val < 0) {
|
||||
SET_VFLG(1);
|
||||
}
|
||||
if (val < 0 && lower - val >= 0) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
} else if (lower >= 0 && upper >= 0 && lower <= upper) {
|
||||
if (val >= 0 && val < lower) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
if (val > upper) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
if (val < 0 && upper - val < 0) {
|
||||
SET_VFLG(1);
|
||||
SET_NFLG(1);
|
||||
}
|
||||
} else if (lower < 0 && upper < 0 && lower > upper) {
|
||||
if (val >= 0) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
if (val > upper && val < lower) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
if (val >= 0 && val - lower < 0) {
|
||||
SET_NFLG(0);
|
||||
SET_VFLG(1);
|
||||
}
|
||||
} else if (lower < 0 && upper < 0 && lower <= upper) {
|
||||
if (val < lower) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
if (val < 0 && val > upper) {
|
||||
SET_NFLG(1);
|
||||
}
|
||||
for (i = 0 ; i < 32 ; i++) {
|
||||
cbit = src_hi & 0x80000000ul;
|
||||
src_hi <<= 1;
|
||||
if (src_lo & 0x80000000ul) src_hi++;
|
||||
src_lo <<= 1;
|
||||
q = q << 1;
|
||||
if (cbit || div <= src_hi) {
|
||||
q |= 1;
|
||||
src_hi -= div;
|
||||
if (val >= 0 && val - lower < 0) {
|
||||
SET_NFLG(1);
|
||||
SET_VFLG(1);
|
||||
}
|
||||
}
|
||||
*quot = q;
|
||||
*rem = src_hi;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void divl_overflow(void)
|
||||
static void divsl_overflow(uae_u16 extra, uae_s64 a, uae_s32 divider)
|
||||
{
|
||||
if (currprefs.cpu_model >= 68040) {
|
||||
SET_VFLG(1);
|
||||
SET_CFLG(0);
|
||||
} else {
|
||||
uae_s32 a32 = (uae_s32)a;
|
||||
bool neg64 = a < 0;
|
||||
bool neg32 = a32 < 0;
|
||||
SET_VFLG(1);
|
||||
if (extra & 0x0400) {
|
||||
// this is still missing condition where Z is set
|
||||
// without none of input parameters being zero.
|
||||
uae_s32 ahigh = a >> 32;
|
||||
if (ahigh == 0) {
|
||||
SET_ZFLG(1);
|
||||
SET_NFLG(0);
|
||||
} else if (ahigh < 0 && divider < 0 && ahigh > divider) {
|
||||
SET_ZFLG(0);
|
||||
SET_NFLG(0);
|
||||
} else {
|
||||
if (a32 == 0) {
|
||||
SET_ZFLG(1);
|
||||
SET_NFLG(0);
|
||||
} else {
|
||||
SET_ZFLG(0);
|
||||
SET_NFLG(neg32 ^ neg64);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (a32 == 0) {
|
||||
SET_ZFLG(1);
|
||||
SET_NFLG(0);
|
||||
} else {
|
||||
SET_NFLG(neg32);
|
||||
SET_ZFLG(0);
|
||||
}
|
||||
}
|
||||
SET_CFLG(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void divul_overflow(uae_u16 extra, uae_s64 a)
|
||||
{
|
||||
if (currprefs.cpu_model >= 68040) {
|
||||
SET_VFLG(1);
|
||||
SET_CFLG(0);
|
||||
} else {
|
||||
uae_s32 a32 = (uae_s32)a;
|
||||
bool neg32 = a32 < 0;
|
||||
SET_VFLG(1);
|
||||
SET_NFLG(neg32);
|
||||
SET_ZFLG(a32 == 0);
|
||||
SET_CFLG(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void divsl_divbyzero(uae_u16 extra, uae_s64 a)
|
||||
{
|
||||
if (currprefs.cpu_model >= 68040) {
|
||||
SET_CFLG(0);
|
||||
} else {
|
||||
SET_NFLG(0);
|
||||
SET_ZFLG(1);
|
||||
SET_CFLG(0);
|
||||
}
|
||||
Exception_cpu(5);
|
||||
}
|
||||
|
||||
static void divul_divbyzero(uae_u16 extra, uae_s64 a)
|
||||
{
|
||||
if (currprefs.cpu_model >= 68040) {
|
||||
SET_CFLG(0);
|
||||
} else {
|
||||
uae_s32 a32 = (uae_s32)a;
|
||||
bool neg32 = a32 < 0;
|
||||
SET_NFLG(neg32);
|
||||
SET_ZFLG(a32 == 0);
|
||||
SET_VFLG(1);
|
||||
SET_NFLG(1);
|
||||
SET_CFLG(0);
|
||||
SET_ZFLG(0);
|
||||
}
|
||||
Exception_cpu(5);
|
||||
}
|
||||
|
||||
void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra)
|
||||
bool m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra)
|
||||
{
|
||||
// Done in caller
|
||||
//if (src == 0) {
|
||||
// Exception_cpu (5);
|
||||
// return;
|
||||
//}
|
||||
#if defined(uae_s64)
|
||||
if (extra & 0x800) {
|
||||
/* signed variant */
|
||||
uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
|
||||
|
@ -605,15 +765,20 @@ void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra)
|
|||
a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32;
|
||||
}
|
||||
|
||||
if (src == 0) {
|
||||
divsl_divbyzero(extra, a);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((uae_u64)a == 0x8000000000000000UL && src == ~0u) {
|
||||
divl_overflow();
|
||||
divsl_overflow(extra, a, src);
|
||||
} else {
|
||||
rem = a % (uae_s64)(uae_s32)src;
|
||||
quot = a / (uae_s64)(uae_s32)src;
|
||||
if ((quot & UVAL64(0xffffffff80000000)) != 0
|
||||
&& (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
|
||||
{
|
||||
divl_overflow();
|
||||
divsl_overflow(extra, a, src);
|
||||
} else {
|
||||
if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
|
||||
SET_VFLG (0);
|
||||
|
@ -633,10 +798,16 @@ void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra)
|
|||
a &= 0xffffffffu;
|
||||
a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32;
|
||||
}
|
||||
|
||||
if (src == 0) {
|
||||
divul_divbyzero(extra, a);
|
||||
return false;
|
||||
}
|
||||
|
||||
rem = a % (uae_u64)src;
|
||||
quot = a / (uae_u64)src;
|
||||
if (quot > 0xffffffffu) {
|
||||
divl_overflow();
|
||||
divul_overflow(extra, a);
|
||||
} else {
|
||||
SET_VFLG (0);
|
||||
SET_CFLG (0);
|
||||
|
@ -646,85 +817,11 @@ void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra)
|
|||
m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (extra & 0x800) {
|
||||
/* signed variant */
|
||||
uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
|
||||
uae_s32 hi = lo < 0 ? -1 : 0;
|
||||
uae_s32 save_high;
|
||||
uae_u32 quot, rem;
|
||||
uae_u32 sign;
|
||||
|
||||
if (extra & 0x400) {
|
||||
hi = (uae_s32)m68k_dreg(regs, extra & 7);
|
||||
}
|
||||
save_high = hi;
|
||||
sign = (hi ^ src);
|
||||
if (hi < 0) {
|
||||
hi = ~hi;
|
||||
lo = -lo;
|
||||
if (lo == 0) hi++;
|
||||
}
|
||||
if ((uae_s32)src < 0) src = -src;
|
||||
if (div_unsigned(hi, lo, src, ", &rem) ||
|
||||
(sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
|
||||
divl_overflow();
|
||||
} else {
|
||||
if (sign & 0x80000000) quot = -quot;
|
||||
if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
|
||||
SET_VFLG (0);
|
||||
SET_CFLG (0);
|
||||
SET_ZFLG (((uae_s32)quot) == 0);
|
||||
SET_NFLG (((uae_s32)quot) < 0);
|
||||
m68k_dreg(regs, extra & 7) = rem;
|
||||
m68k_dreg(regs, (extra >> 12) & 7) = quot;
|
||||
}
|
||||
} else {
|
||||
/* unsigned */
|
||||
uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
|
||||
uae_u32 hi = 0;
|
||||
uae_u32 quot, rem;
|
||||
|
||||
if (extra & 0x400) {
|
||||
hi = (uae_u32)m68k_dreg(regs, extra & 7);
|
||||
}
|
||||
if (div_unsigned(hi, lo, src, ", &rem)) {
|
||||
divl_overflow();
|
||||
} else {
|
||||
SET_VFLG (0);
|
||||
SET_CFLG (0);
|
||||
SET_ZFLG (((uae_s32)quot) == 0);
|
||||
SET_NFLG (((uae_s32)quot) < 0);
|
||||
m68k_dreg(regs, extra & 7) = rem;
|
||||
m68k_dreg(regs, (extra >> 12) & 7) = quot;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined (uae_s64)
|
||||
STATIC_INLINE void mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
|
||||
bool m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
|
||||
{
|
||||
uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
|
||||
uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
|
||||
uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
|
||||
uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
|
||||
uae_u32 lo;
|
||||
|
||||
lo = r0 + ((r1 << 16) & 0xffff0000ul);
|
||||
if (lo < r0) r3++;
|
||||
r0 = lo;
|
||||
lo = r0 + ((r2 << 16) & 0xffff0000ul);
|
||||
if (lo < r0) r3++;
|
||||
r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
|
||||
*dst_lo = lo;
|
||||
*dst_hi = r3;
|
||||
}
|
||||
#endif
|
||||
|
||||
void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
|
||||
{
|
||||
#if defined(uae_s64)
|
||||
if (extra & 0x800) {
|
||||
/* signed */
|
||||
uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
|
||||
|
@ -734,8 +831,15 @@ void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
|
|||
SET_CFLG (0);
|
||||
if (extra & 0x400) {
|
||||
// 32 * 32 = 64
|
||||
// 68040 is different.
|
||||
if (currprefs.cpu_model >= 68040) {
|
||||
m68k_dreg(regs, extra & 7) = (uae_u32)(a >> 32);
|
||||
m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
|
||||
} else {
|
||||
// 020/030
|
||||
m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
|
||||
m68k_dreg(regs, extra & 7) = (uae_u32)(a >> 32);
|
||||
}
|
||||
SET_ZFLG (a == 0);
|
||||
SET_NFLG (a < 0);
|
||||
} else {
|
||||
|
@ -757,8 +861,15 @@ void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
|
|||
SET_CFLG (0);
|
||||
if (extra & 0x400) {
|
||||
// 32 * 32 = 64
|
||||
// 68040 is different.
|
||||
if (currprefs.cpu_model >= 68040) {
|
||||
m68k_dreg(regs, extra & 7) = (uae_u32)(a >> 32);
|
||||
m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
|
||||
} else {
|
||||
// 020/030
|
||||
m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
|
||||
m68k_dreg(regs, extra & 7) = (uae_u32)(a >> 32);
|
||||
}
|
||||
SET_ZFLG (a == 0);
|
||||
SET_NFLG (((uae_s64)a) < 0);
|
||||
} else {
|
||||
|
@ -772,60 +883,7 @@ void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
|
|||
SET_NFLG(b < 0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (extra & 0x800) {
|
||||
/* signed */
|
||||
uae_s32 src1,src2;
|
||||
uae_u32 dst_lo,dst_hi;
|
||||
uae_u32 sign;
|
||||
|
||||
src1 = (uae_s32)src;
|
||||
src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
|
||||
sign = (src1 ^ src2);
|
||||
if (src1 < 0) src1 = -src1;
|
||||
if (src2 < 0) src2 = -src2;
|
||||
mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo);
|
||||
if (sign & 0x80000000) {
|
||||
dst_hi = ~dst_hi;
|
||||
dst_lo = -dst_lo;
|
||||
if (dst_lo == 0) dst_hi++;
|
||||
}
|
||||
SET_VFLG (0);
|
||||
SET_CFLG (0);
|
||||
if (extra & 0x400) {
|
||||
m68k_dreg(regs, extra & 7) = dst_hi;
|
||||
SET_ZFLG (dst_hi == 0 && dst_lo == 0);
|
||||
SET_NFLG (((uae_s32)dst_hi) < 0);
|
||||
} else {
|
||||
if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0) && ((dst_hi & 0xffffffff) != 0xffffffff || (dst_lo & 0x80000000) != 0x80000000)) {
|
||||
SET_VFLG (1);
|
||||
}
|
||||
SET_ZFLG(dst_lo == 0);
|
||||
SET_NFLG(((uae_s32)dst_lo) < 0);
|
||||
}
|
||||
m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
|
||||
} else {
|
||||
/* unsigned */
|
||||
uae_u32 dst_lo,dst_hi;
|
||||
|
||||
mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo);
|
||||
|
||||
SET_VFLG (0);
|
||||
SET_CFLG (0);
|
||||
if (extra & 0x400) {
|
||||
m68k_dreg(regs, extra & 7) = dst_hi;
|
||||
SET_ZFLG (dst_hi == 0 && dst_lo == 0);
|
||||
SET_NFLG (((uae_s32)dst_hi) < 0);
|
||||
} else {
|
||||
if (dst_hi != 0) {
|
||||
SET_VFLG (1);
|
||||
}
|
||||
SET_ZFLG(dst_lo == 0);
|
||||
SET_NFLG(((uae_s32)dst_lo) < 0);
|
||||
}
|
||||
m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
uae_u32 exception_pc(int nr)
|
||||
|
@ -838,6 +896,8 @@ uae_u32 exception_pc(int nr)
|
|||
|
||||
void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (format) {
|
||||
case 0x0: // four word stack frame
|
||||
case 0x1: // throwaway four word stack frame
|
||||
|
@ -856,30 +916,113 @@ void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int
|
|||
m68k_areg (regs, 7) -= 4;
|
||||
x_put_long (m68k_areg (regs, 7), oldpc);
|
||||
break;
|
||||
case 0x7: // access error stack frame (68040)
|
||||
|
||||
for (i = 3; i >= 0; i--) {
|
||||
// WB1D/PD0,PD1,PD2,PD3
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0);
|
||||
}
|
||||
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0); // WB1A
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0); // WB2D
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0); // WB2A
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0); // WB3D
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), regs.mmu_fault_addr); // WB3A
|
||||
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), regs.mmu_fault_addr); // FA
|
||||
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0);
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0);
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0);
|
||||
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), ssw);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0);
|
||||
break;
|
||||
case 0x8: // address error (68010)
|
||||
for (int i = 0; i < 15; i++) {
|
||||
{
|
||||
uae_u16 in = regs.read_buffer;
|
||||
uae_u16 out = regs.write_buffer;
|
||||
for (i = 0; i < 15; i++) {
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0);
|
||||
}
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0); // version
|
||||
x_put_word(m68k_areg(regs, 7), 0x0000); // version (probably bits 12 to 15 only because other bits change)
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), regs.opcode); // instruction input buffer
|
||||
x_put_word(m68k_areg(regs, 7), regs.irc); // instruction input buffer
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0); // unused
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0); // data input buffer
|
||||
x_put_word(m68k_areg(regs, 7), in); // data input buffer
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0); // unused
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0); // data output buffer
|
||||
x_put_word(m68k_areg(regs, 7), out); // data output buffer
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0); // unused
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0); // fault addr
|
||||
x_put_long(m68k_areg(regs, 7), regs.mmu_fault_addr); // fault addr
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), ssw); // ssw
|
||||
break;
|
||||
}
|
||||
case 0x9: // coprocessor mid-instruction stack frame (68020, 68030)
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), regs.fp_ea);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), regs.fp_opword);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), oldpc);
|
||||
break;
|
||||
case 0xB: // long bus cycle fault stack frame (68020, 68030)
|
||||
// Store state information to internal register space
|
||||
for (i = 0; i < 1; i++) {
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0);
|
||||
}
|
||||
while (i < MAX_MMU030_ACCESS) {
|
||||
uae_u32 v = 0;
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), v);
|
||||
i++;
|
||||
}
|
||||
// version & internal information (We store index here)
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0);
|
||||
// 3* internal registers
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0);
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0);
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0);
|
||||
// data input buffer = fault address
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), regs.mmu_fault_addr);
|
||||
// 2xinternal
|
||||
{
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0);
|
||||
}
|
||||
// stage b address
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0);
|
||||
// 2xinternal
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0);
|
||||
/* fall through */
|
||||
case 0xA:
|
||||
// short bus cycle fault stack frame (68020, 68030)
|
||||
// used when instruction's last write causes bus fault
|
||||
|
@ -889,9 +1032,13 @@ void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int
|
|||
// Data output buffer = value that was going to be written
|
||||
x_put_long(m68k_areg(regs, 7), 0);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
if (format == 0xb) {
|
||||
x_put_long(m68k_areg(regs, 7), 0); // Internal register (opcode storage)
|
||||
} else {
|
||||
x_put_long(m68k_areg(regs, 7), regs.irc); // Internal register (opcode storage)
|
||||
}
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
x_put_long(m68k_areg(regs, 7), 0); // data cycle fault address
|
||||
x_put_long(m68k_areg(regs, 7), regs.mmu_fault_addr); // data cycle fault address
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0); // Instr. pipe stage B
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
|
@ -899,7 +1046,7 @@ void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int
|
|||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), ssw);
|
||||
m68k_areg(regs, 7) -= 2;
|
||||
x_put_word(m68k_areg(regs, 7), 0); // = mmu030_state[1]);
|
||||
x_put_word(m68k_areg(regs, 7), 0);
|
||||
break;
|
||||
default:
|
||||
write_log(_T("Unknown exception stack frame format: %X\n"), format);
|
||||
|
@ -952,7 +1099,15 @@ void Exception_build_68000_address_error_stack_frame(uae_u16 mode, uae_u16 opcod
|
|||
x_put_long(m68k_areg(regs, 7) + 10, pc);
|
||||
}
|
||||
|
||||
// Low word: Z and N
|
||||
void cpu_restore_fixup(void)
|
||||
{
|
||||
if (mmufixup[0].reg >= 0) {
|
||||
m68k_areg(regs, mmufixup[0].reg) = mmufixup[0].value;
|
||||
mmufixup[0].reg = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Low word: Clear + Z and N
|
||||
void ccr_68000_long_move_ae_LZN(uae_s32 src)
|
||||
{
|
||||
CLEAR_CZNV();
|
||||
|
@ -961,7 +1116,7 @@ void ccr_68000_long_move_ae_LZN(uae_s32 src)
|
|||
SET_NFLG(vsrc < 0);
|
||||
}
|
||||
|
||||
// Low word: N only
|
||||
// Low word: Clear + N only
|
||||
void ccr_68000_long_move_ae_LN(uae_s32 src)
|
||||
{
|
||||
CLEAR_CZNV();
|
||||
|
@ -997,3 +1152,46 @@ void ccr_68000_word_move_ae_normal(uae_s16 src)
|
|||
SET_ZFLG(src == 0);
|
||||
SET_NFLG(src < 0);
|
||||
}
|
||||
|
||||
// Change F-line to privilege violation if missing co-pro
|
||||
bool privileged_copro_instruction(uae_u16 opcode)
|
||||
{
|
||||
if (currprefs.cpu_model >= 68020 && !regs.s) {
|
||||
int reg = opcode & 7;
|
||||
int mode = (opcode >> 3) & 7;
|
||||
int id = (opcode >> 9) & 7;
|
||||
// cpSAVE and cpRESTORE: privilege violation if user mode.
|
||||
if ((opcode & 0xf1c0) == 0xf100) {
|
||||
// cpSAVE
|
||||
if (mode == 2 || (mode >= 4 && mode <= 6) || (mode == 7 && (reg == 0 || reg == 1))) {
|
||||
if ((currprefs.cpu_model >= 68040 && id > 0) || currprefs.cpu_model < 68040)
|
||||
return true;
|
||||
}
|
||||
} else if ((opcode & 0xf1c0) == 0xf140) {
|
||||
// cpRESTORE
|
||||
if (mode == 2 || mode == 3 || (mode >= 5 && mode <= 6) || (mode == 7 && reg <= 3)) {
|
||||
if ((currprefs.cpu_model >= 68040 && id > 0) || currprefs.cpu_model < 68040)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool generates_group1_exception(uae_u16 opcode)
|
||||
{
|
||||
struct instr *table = &table68k[opcode];
|
||||
// illegal/a-line/f-line?
|
||||
if (table->mnemo == i_ILLG)
|
||||
return true;
|
||||
// privilege violation?
|
||||
if (!regs.s) {
|
||||
if (table->plev == 1 && currprefs.cpu_model > 68000)
|
||||
return true;
|
||||
if (table->plev == 2)
|
||||
return true;
|
||||
if (table->plev == 3 && table->size == sz_word)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ struct mnemolookup lookuptab[] = {
|
|||
{ i_CAS2, _T("CAS2") },
|
||||
{ i_MULL, _T("MULL") },
|
||||
{ i_DIVL, _T("DIVL") },
|
||||
|
||||
{ i_BFTST, _T("BFTST") },
|
||||
{ i_BFEXTU, _T("BFEXTU") },
|
||||
{ i_BFCHG, _T("BFCHG") },
|
||||
|
@ -109,6 +110,7 @@ struct mnemolookup lookuptab[] = {
|
|||
{ i_BFFFO, _T("BFFFO") },
|
||||
{ i_BFSET, _T("BFSET") },
|
||||
{ i_BFINS, _T("BFINS") },
|
||||
|
||||
{ i_PACK, _T("PACK") },
|
||||
{ i_UNPK, _T("UNPK") },
|
||||
{ i_TAS, _T("TAS") },
|
||||
|
@ -117,6 +119,7 @@ struct mnemolookup lookuptab[] = {
|
|||
{ i_RTM, _T("RTM") },
|
||||
{ i_TRAPcc, _T("TRAPcc") },
|
||||
{ i_MOVES, _T("MOVES") },
|
||||
|
||||
{ i_FPP, _T("FPP") },
|
||||
{ i_FDBcc, _T("FDBcc") },
|
||||
{ i_FScc, _T("FScc") },
|
||||
|
@ -836,7 +839,7 @@ void read_table68k (void)
|
|||
|
||||
static int imismatch;
|
||||
|
||||
static void handle_merges (long int opcode)
|
||||
static void handle_merges (uae_s32 opcode)
|
||||
{
|
||||
uae_u16 smsk;
|
||||
uae_u16 dmsk;
|
||||
|
@ -915,7 +918,7 @@ static void handle_merges (long int opcode)
|
|||
|
||||
void do_merges (void)
|
||||
{
|
||||
long int opcode;
|
||||
uae_s32 opcode;
|
||||
int nr = 0;
|
||||
imismatch = 0;
|
||||
for (opcode = 0; opcode < 65536; opcode++) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue