22 |
|
#include "memory.h" |
23 |
|
#include "readcpu.h" |
24 |
|
#include "newcpu.h" |
25 |
+ |
#include "compiler/compemu.h" |
26 |
+ |
#include "fpu/fpu.h" |
27 |
|
|
28 |
|
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) |
29 |
|
B2_mutex *spcflags_lock = NULL; |
34 |
|
#include "mon_disass.h" |
35 |
|
#endif |
36 |
|
|
37 |
< |
int quit_program = 0; |
36 |
< |
const int debugging = 0; |
37 |
> |
bool quit_program = false; |
38 |
|
struct flag_struct regflags; |
39 |
|
|
40 |
|
/* Opcode of faulting instruction */ |
51 |
|
int movem_index2[256]; |
52 |
|
int movem_next[256]; |
53 |
|
|
53 |
– |
int fpp_movem_index1[256]; |
54 |
– |
int fpp_movem_index2[256]; |
55 |
– |
int fpp_movem_next[256]; |
56 |
– |
|
54 |
|
cpuop_func *cpufunctbl[65536]; |
55 |
|
|
59 |
– |
#define FLIGHT_RECORDER 0 |
60 |
– |
|
56 |
|
#if FLIGHT_RECORDER |
57 |
|
struct rec_step { |
58 |
+ |
uae_u32 pc; |
59 |
+ |
#if FLIGHT_RECORDER >= 2 |
60 |
|
uae_u32 d[8]; |
61 |
|
uae_u32 a[8]; |
62 |
< |
uae_u32 pc; |
62 |
> |
#endif |
63 |
|
}; |
64 |
|
|
65 |
< |
const int LOG_SIZE = 8192; |
65 |
> |
const int LOG_SIZE = 32768; |
66 |
|
static rec_step log[LOG_SIZE]; |
67 |
|
static int log_ptr = -1; // First time initialization |
68 |
|
|
72 |
|
return name ? name : "log.68k"; |
73 |
|
} |
74 |
|
|
75 |
< |
static void record_step(uaecptr pc) |
75 |
> |
void m68k_record_step(uaecptr pc) |
76 |
|
{ |
77 |
< |
for (int i = 0; i < 8; i++) { |
78 |
< |
log[log_ptr].d[i] = m68k_dreg(regs, i); |
79 |
< |
log[log_ptr].a[i] = m68k_areg(regs, i); |
77 |
> |
#if FLIGHT_RECORDER >= 2 |
78 |
> |
/* XXX: if LSB is set, we are recording from generated code and we |
79 |
> |
don't support registers recording yet. */ |
80 |
> |
if ((pc & 1) == 0) { |
81 |
> |
for (int i = 0; i < 8; i++) { |
82 |
> |
log[log_ptr].d[i] = m68k_dreg(regs, i); |
83 |
> |
log[log_ptr].a[i] = m68k_areg(regs, i); |
84 |
> |
} |
85 |
|
} |
86 |
+ |
#endif |
87 |
|
log[log_ptr].pc = pc; |
88 |
|
log_ptr = (log_ptr + 1) % LOG_SIZE; |
89 |
|
} |
95 |
|
return; |
96 |
|
for (int i = 0; i < LOG_SIZE; i++) { |
97 |
|
int j = (i + log_ptr) % LOG_SIZE; |
98 |
< |
fprintf(f, "pc %08x\n", log[j].pc); |
99 |
< |
fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", log[j].d[0], log[j].d[1], log[j].d[2], log[j].d[3]); |
100 |
< |
fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", log[j].d[4], log[j].d[5], log[j].d[6], log[j].d[7]); |
101 |
< |
fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", log[j].a[0], log[j].a[1], log[j].a[2], log[j].a[3]); |
102 |
< |
fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", log[j].a[4], log[j].a[5], log[j].a[6], log[j].a[7]); |
98 |
> |
uae_u32 pc = log[j].pc & ~1; |
99 |
> |
fprintf(f, "pc %08x", pc); |
100 |
> |
#if FLIGHT_RECORDER >= 2 |
101 |
> |
fprintf(f, "\n"); |
102 |
> |
if ((log[j].pc & 1) == 0) { |
103 |
> |
fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", log[j].d[0], log[j].d[1], log[j].d[2], log[j].d[3]); |
104 |
> |
fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", log[j].d[4], log[j].d[5], log[j].d[6], log[j].d[7]); |
105 |
> |
fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", log[j].a[0], log[j].a[1], log[j].a[2], log[j].a[3]); |
106 |
> |
fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", log[j].a[4], log[j].a[5], log[j].a[6], log[j].a[7]); |
107 |
> |
} |
108 |
> |
#else |
109 |
> |
fprintf(f, " | "); |
110 |
> |
#endif |
111 |
|
#if ENABLE_MON |
112 |
< |
disass_68k(f, log[j].pc); |
112 |
> |
disass_68k(f, pc); |
113 |
|
#endif |
114 |
|
} |
115 |
|
fclose(f); |
116 |
|
} |
117 |
|
#endif |
118 |
|
|
119 |
+ |
#if ENABLE_MON |
120 |
+ |
static void dump_regs(void) |
121 |
+ |
{ |
122 |
+ |
m68k_dumpstate(NULL); |
123 |
+ |
} |
124 |
+ |
#endif |
125 |
+ |
|
126 |
|
#define COUNT_INSTRS 0 |
127 |
|
|
128 |
|
#if COUNT_INSTRS |
186 |
|
#endif |
187 |
|
} |
188 |
|
|
189 |
< |
cpuop_rettype REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; |
189 |
> |
void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; |
190 |
|
|
191 |
< |
cpuop_rettype REGPARAM2 op_illg_1 (uae_u32 opcode) |
191 |
> |
void REGPARAM2 op_illg_1 (uae_u32 opcode) |
192 |
|
{ |
193 |
< |
cpuop_return( op_illg (cft_map (opcode)) ); |
193 |
> |
op_illg (cft_map (opcode)); |
194 |
|
} |
195 |
|
|
196 |
|
static void build_cpufunctbl (void) |
253 |
|
movem_index2[i] = 7-j; |
254 |
|
movem_next[i] = i & (~(1 << j)); |
255 |
|
} |
238 |
– |
for (i = 0 ; i < 256 ; i++) { |
239 |
– |
int j; |
240 |
– |
for (j = 7 ; j >= 0 ; j--) { |
241 |
– |
if (i & (1 << j)) break; |
242 |
– |
} |
243 |
– |
fpp_movem_index1[i] = 7-j; |
244 |
– |
fpp_movem_index2[i] = j; |
245 |
– |
fpp_movem_next[i] = i & (~(1 << j)); |
246 |
– |
} |
256 |
|
#if COUNT_INSTRS |
257 |
|
{ |
258 |
|
FILE *f = fopen (icountfilename (), "r"); |
277 |
|
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) |
278 |
|
spcflags_lock = B2_create_mutex(); |
279 |
|
#endif |
280 |
< |
|
272 |
< |
fpu_init (); |
273 |
< |
fpu_set_integral_fpu (CPUType == 4); |
280 |
> |
fpu_init(CPUType == 4); |
281 |
|
} |
282 |
|
|
283 |
|
void exit_m68k (void) |
823 |
|
switch (regno) { |
824 |
|
case 0: regs.sfc = *regp & 7; break; |
825 |
|
case 1: regs.dfc = *regp & 7; break; |
826 |
< |
case 2: cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000); break; |
826 |
> |
case 2: |
827 |
> |
cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000); |
828 |
> |
#if USE_JIT |
829 |
> |
if (CPUType < 4) { |
830 |
> |
set_cache_state(cacr&1); |
831 |
> |
if (*regp & 0x08) |
832 |
> |
flush_icache(1); |
833 |
> |
} |
834 |
> |
else { |
835 |
> |
set_cache_state((cacr&0x8000) || 0); |
836 |
> |
// FIXME: The User Manual claims bit 3 of CACR is undefined |
837 |
> |
if (*regp & 0x08) |
838 |
> |
flush_icache(2); |
839 |
> |
} |
840 |
> |
#endif |
841 |
> |
break; |
842 |
|
case 3: tc = *regp & 0xc000; break; |
843 |
|
case 4: itt0 = *regp & 0xffffe364; break; |
844 |
|
case 5: itt1 = *regp & 0xffffe364; break; |
1175 |
|
fpu_reset(); |
1176 |
|
|
1177 |
|
#if FLIGHT_RECORDER |
1178 |
+ |
log_ptr = 0; |
1179 |
+ |
memset(log, 0, sizeof(log)); |
1180 |
+ |
#endif |
1181 |
+ |
|
1182 |
|
#if ENABLE_MON |
1183 |
< |
if (log_ptr == -1) { |
1183 |
> |
static bool first_time = true; |
1184 |
> |
if (first_time) { |
1185 |
> |
first_time = false; |
1186 |
> |
mon_add_command("regs", dump_regs, "regs Dump m68k emulator registers\n"); |
1187 |
> |
#if FLIGHT_RECORDER |
1188 |
|
// Install "log" command in mon |
1189 |
|
mon_add_command("log", dump_log, "log Dump m68k emulation log\n"); |
1160 |
– |
} |
1190 |
|
#endif |
1191 |
< |
log_ptr = 0; |
1163 |
< |
memset(log, 0, sizeof(log)); |
1191 |
> |
} |
1192 |
|
#endif |
1193 |
|
} |
1194 |
|
|
1195 |
|
void m68k_emulop_return(void) |
1196 |
|
{ |
1197 |
|
SPCFLAGS_SET( SPCFLAG_BRK ); |
1198 |
< |
quit_program = 1; |
1198 |
> |
quit_program = true; |
1199 |
|
} |
1200 |
|
|
1201 |
|
void m68k_emulop(uae_u32 opcode) |
1218 |
|
MakeFromSR(); |
1219 |
|
} |
1220 |
|
|
1221 |
< |
cpuop_rettype REGPARAM2 op_illg (uae_u32 opcode) |
1221 |
> |
void REGPARAM2 op_illg (uae_u32 opcode) |
1222 |
|
{ |
1223 |
|
uaecptr pc = m68k_getpc (); |
1224 |
|
|
1225 |
|
if ((opcode & 0xF000) == 0xA000) { |
1226 |
|
Exception(0xA,0); |
1227 |
< |
cpuop_return(CFLOW_TRAP); |
1227 |
> |
return; |
1228 |
|
} |
1229 |
|
|
1230 |
|
if ((opcode & 0xF000) == 0xF000) { |
1231 |
|
Exception(0xB,0); |
1232 |
< |
cpuop_return(CFLOW_TRAP); |
1232 |
> |
return; |
1233 |
|
} |
1234 |
|
|
1235 |
|
write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); |
1236 |
+ |
#if USE_JIT && JIT_DEBUG |
1237 |
+ |
compiler_dumpstate(); |
1238 |
+ |
#endif |
1239 |
|
|
1240 |
|
Exception (4,0); |
1241 |
< |
cpuop_return(CFLOW_TRAP); |
1241 |
> |
return; |
1242 |
|
} |
1243 |
|
|
1244 |
|
void mmu_op(uae_u32 opcode, uae_u16 extra) |
1293 |
|
|
1294 |
|
int m68k_do_specialties (void) |
1295 |
|
{ |
1296 |
+ |
#if USE_JIT |
1297 |
+ |
// Block was compiled |
1298 |
+ |
SPCFLAGS_CLEAR( SPCFLAG_JIT_END_COMPILE ); |
1299 |
+ |
|
1300 |
+ |
// Retain the request to get out of compiled code until |
1301 |
+ |
// we reached the toplevel execution, i.e. the one that |
1302 |
+ |
// can compile then run compiled code. This also means |
1303 |
+ |
// we processed all (nested) EmulOps |
1304 |
+ |
if ((m68k_execute_depth == 0) && SPCFLAGS_TEST( SPCFLAG_JIT_EXEC_RETURN )) |
1305 |
+ |
SPCFLAGS_CLEAR( SPCFLAG_JIT_EXEC_RETURN ); |
1306 |
+ |
#endif |
1307 |
+ |
|
1308 |
|
if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) { |
1309 |
|
Exception (9,last_trace_ad); |
1310 |
|
} |
1336 |
|
} |
1337 |
|
if (SPCFLAGS_TEST( SPCFLAG_BRK )) { |
1338 |
|
SPCFLAGS_CLEAR( SPCFLAG_BRK ); |
1339 |
< |
return CFLOW_EXEC_RETURN; |
1339 |
> |
return 1; |
1340 |
|
} |
1341 |
|
return 0; |
1342 |
|
} |
1346 |
|
for (;;) { |
1347 |
|
uae_u32 opcode = GET_OPCODE; |
1348 |
|
#if FLIGHT_RECORDER |
1349 |
< |
record_step(m68k_getpc()); |
1349 |
> |
m68k_record_step(m68k_getpc()); |
1350 |
|
#endif |
1308 |
– |
#ifdef X86_ASSEMBLY |
1309 |
– |
__asm__ __volatile__("\tpushl %%ebp\n\tcall *%%ebx\n\tpopl %%ebp" /* FIXME */ |
1310 |
– |
: : "b" (cpufunctbl[opcode]), "a" (opcode) |
1311 |
– |
: "%edx", "%ecx", "%esi", "%edi", "%ebp", "memory", "cc"); |
1312 |
– |
#else |
1351 |
|
(*cpufunctbl[opcode])(opcode); |
1352 |
< |
#endif |
1353 |
< |
if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { |
1316 |
< |
if (m68k_do_specialties()) |
1352 |
> |
if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { |
1353 |
> |
if (m68k_do_specialties()) |
1354 |
|
return; |
1355 |
|
} |
1356 |
|
} |
1357 |
|
} |
1358 |
|
|
1359 |
+ |
#if USE_JIT && !(defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY)) |
1360 |
+ |
void m68k_compile_execute (void) |
1361 |
+ |
{ |
1362 |
+ |
for (;;) { |
1363 |
+ |
if (quit_program) |
1364 |
+ |
break; |
1365 |
+ |
m68k_do_compile_execute(); |
1366 |
+ |
} |
1367 |
+ |
} |
1368 |
+ |
#endif |
1369 |
+ |
|
1370 |
|
void m68k_execute (void) |
1371 |
|
{ |
1372 |
+ |
#if USE_JIT |
1373 |
+ |
++m68k_execute_depth; |
1374 |
+ |
#endif |
1375 |
|
for (;;) { |
1376 |
< |
if (quit_program > 0) { |
1326 |
< |
if (quit_program == 1) |
1376 |
> |
if (quit_program) |
1377 |
|
break; |
1378 |
< |
quit_program = 0; |
1329 |
< |
m68k_reset (); |
1330 |
< |
} |
1331 |
< |
m68k_do_execute(); |
1378 |
> |
m68k_do_execute(); |
1379 |
|
} |
1380 |
< |
if (debugging) { |
1381 |
< |
uaecptr nextpc; |
1382 |
< |
m68k_dumpstate(&nextpc); |
1336 |
< |
exit(1); |
1337 |
< |
} |
1380 |
> |
#if USE_JIT |
1381 |
> |
--m68k_execute_depth; |
1382 |
> |
#endif |
1383 |
|
} |
1384 |
|
|
1385 |
|
static void m68k_verify (uaecptr addr, uaecptr *nextpc) |
1488 |
|
printf ("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n", |
1489 |
|
regs.t1, regs.t0, regs.s, regs.m, |
1490 |
|
GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask); |
1491 |
< |
for (i = 0; i < 8; i++){ |
1492 |
< |
printf ("FP%d: %g ", i, regs.fp[i]); |
1493 |
< |
if ((i & 3) == 3) printf ("\n"); |
1494 |
< |
} |
1450 |
< |
printf ("N=%d Z=%d I=%d NAN=%d\n", |
1451 |
< |
(regs.fpsr & 0x8000000) != 0, |
1452 |
< |
(regs.fpsr & 0x4000000) != 0, |
1453 |
< |
(regs.fpsr & 0x2000000) != 0, |
1454 |
< |
(regs.fpsr & 0x1000000) != 0); |
1455 |
< |
|
1491 |
> |
|
1492 |
> |
fpu_dump_registers(); |
1493 |
> |
fpu_dump_flags(); |
1494 |
> |
|
1495 |
|
m68k_disasm(m68k_getpc (), nextpc, 1); |
1496 |
|
if (nextpc) |
1497 |
|
printf ("next PC: %08lx\n", *nextpc); |