23 |
|
#include "readcpu.h" |
24 |
|
#include "newcpu.h" |
25 |
|
|
26 |
+ |
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) && defined(HAVE_PTHREADS) |
27 |
+ |
#include <pthread.h> |
28 |
+ |
pthread_mutex_t spcflags_lock = PTHREAD_MUTEX_INITIALIZER; |
29 |
+ |
#endif |
30 |
+ |
|
31 |
|
#if ENABLE_MON |
32 |
|
#include "mon.h" |
33 |
|
#include "mon_disass.h" |
34 |
|
#endif |
35 |
|
|
36 |
|
int quit_program = 0; |
37 |
< |
int debugging = 0; |
37 |
> |
const int debugging = 0; |
38 |
|
struct flag_struct regflags; |
39 |
|
|
40 |
|
/* Opcode of faulting instruction */ |
169 |
|
#endif |
170 |
|
} |
171 |
|
|
172 |
< |
static void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; |
172 |
> |
cpuop_rettype REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; |
173 |
|
|
174 |
< |
static void REGPARAM2 op_illg_1 (uae_u32 opcode) |
174 |
> |
cpuop_rettype REGPARAM2 op_illg_1 (uae_u32 opcode) |
175 |
|
{ |
176 |
< |
op_illg (cft_map (opcode)); |
176 |
> |
cpuop_return( op_illg (cft_map (opcode)) ); |
177 |
|
} |
178 |
|
|
179 |
|
static void build_cpufunctbl (void) |
192 |
|
cpu_level = 1; |
193 |
|
} |
194 |
|
struct cputbl *tbl = ( |
195 |
< |
cpu_level == 4 ? op_smalltbl_0 |
196 |
< |
: cpu_level == 3 ? op_smalltbl_1 |
197 |
< |
: cpu_level == 2 ? op_smalltbl_2 |
198 |
< |
: cpu_level == 1 ? op_smalltbl_3 |
199 |
< |
: op_smalltbl_4); |
195 |
> |
cpu_level == 4 ? op_smalltbl_0_ff |
196 |
> |
: cpu_level == 3 ? op_smalltbl_1_ff |
197 |
> |
: cpu_level == 2 ? op_smalltbl_2_ff |
198 |
> |
: cpu_level == 1 ? op_smalltbl_3_ff |
199 |
> |
: op_smalltbl_4_ff); |
200 |
|
|
201 |
|
for (opcode = 0; opcode < 65536; opcode++) |
202 |
|
cpufunctbl[cft_map (opcode)] = op_illg_1; |
708 |
|
} |
709 |
|
} |
710 |
|
|
711 |
< |
regs.spcflags |= SPCFLAG_INT; |
711 |
> |
SPCFLAGS_SET( SPCFLAG_INT ); |
712 |
|
if (regs.t1 || regs.t0) |
713 |
< |
regs.spcflags |= SPCFLAG_TRACE; |
713 |
> |
SPCFLAGS_SET( SPCFLAG_TRACE ); |
714 |
|
else |
715 |
|
/* Keep SPCFLAG_DOTRACE, we still want a trace exception for |
716 |
|
SR-modifying instructions (including STOP). */ |
717 |
< |
regs.spcflags &= ~SPCFLAG_TRACE; |
717 |
> |
SPCFLAGS_CLEAR( SPCFLAG_TRACE ); |
718 |
|
} |
719 |
|
|
720 |
|
void Exception(int nr, uaecptr oldpc) |
779 |
|
m68k_areg(regs, 7) -= 2; |
780 |
|
put_word (m68k_areg(regs, 7), regs.sr); |
781 |
|
m68k_setpc (get_long (regs.vbr + 4*nr)); |
782 |
+ |
SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE ); |
783 |
|
fill_prefetch_0 (); |
784 |
|
regs.t1 = regs.t0 = regs.m = 0; |
785 |
< |
regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE); |
785 |
> |
SPCFLAGS_CLEAR( SPCFLAG_TRACE | SPCFLAG_DOTRACE ); |
786 |
|
} |
787 |
|
|
788 |
|
static void Interrupt(int nr) |
793 |
|
Exception(nr+24, 0); |
794 |
|
|
795 |
|
regs.intmask = nr; |
796 |
< |
regs.spcflags |= SPCFLAG_INT; |
796 |
> |
SPCFLAGS_SET( SPCFLAG_INT ); |
797 |
|
} |
798 |
|
|
799 |
|
static int caar, cacr, tc, itt0, itt1, dtt0, dtt1, mmusr, urp, srp; |
1121 |
|
{ "T ","F ","HI","LS","CC","CS","NE","EQ", |
1122 |
|
"VC","VS","PL","MI","GE","LT","GT","LE" }; |
1123 |
|
|
1124 |
+ |
// If value is greater than zero, this means we are still processing an EmulOp |
1125 |
+ |
// because the counter is incremented only in m68k_execute(), i.e. interpretive |
1126 |
+ |
// execution only |
1127 |
+ |
static int m68k_execute_depth = 0; |
1128 |
+ |
|
1129 |
|
void m68k_reset (void) |
1130 |
|
{ |
1131 |
|
m68k_areg (regs, 7) = 0x2000; |
1132 |
|
m68k_setpc (ROMBaseMac + 0x2a); |
1133 |
|
fill_prefetch_0 (); |
1123 |
– |
regs.kick_mask = 0xF80000; |
1134 |
|
regs.s = 1; |
1135 |
|
regs.m = 0; |
1136 |
|
regs.stopped = 0; |
1141 |
|
SET_CFLG (0); |
1142 |
|
SET_VFLG (0); |
1143 |
|
SET_NFLG (0); |
1144 |
< |
regs.spcflags = 0; |
1144 |
> |
SPCFLAGS_INIT( 0 ); |
1145 |
|
regs.intmask = 7; |
1146 |
|
regs.vbr = regs.sfc = regs.dfc = 0; |
1137 |
– |
/* gb-- moved into {fpp,fpu_x86}.cpp::fpu_init() |
1138 |
– |
regs.fpcr = regs.fpsr = regs.fpiar = 0; */ |
1147 |
|
fpu_reset(); |
1148 |
|
|
1149 |
|
#if FLIGHT_RECORDER |
1158 |
|
#endif |
1159 |
|
} |
1160 |
|
|
1161 |
< |
void REGPARAM2 op_illg (uae_u32 opcode) |
1161 |
> |
void m68k_emulop_return(void) |
1162 |
|
{ |
1163 |
< |
uaecptr pc = m68k_getpc (); |
1163 |
> |
SPCFLAGS_SET( SPCFLAG_BRK ); |
1164 |
> |
quit_program = 1; |
1165 |
> |
} |
1166 |
|
|
1167 |
< |
if ((opcode & 0xFF00) == 0x7100) { |
1167 |
> |
void m68k_emulop(uae_u32 opcode) |
1168 |
> |
{ |
1169 |
|
struct M68kRegisters r; |
1170 |
|
int i; |
1171 |
|
|
1161 |
– |
// Return from Exectue68k()? |
1162 |
– |
if (opcode == M68K_EXEC_RETURN) { |
1163 |
– |
regs.spcflags |= SPCFLAG_BRK; |
1164 |
– |
quit_program = 1; |
1165 |
– |
return; |
1166 |
– |
} |
1167 |
– |
|
1168 |
– |
// Call EMUL_OP opcode |
1172 |
|
for (i=0; i<8; i++) { |
1173 |
|
r.d[i] = m68k_dreg(regs, i); |
1174 |
|
r.a[i] = m68k_areg(regs, i); |
1182 |
|
} |
1183 |
|
regs.sr = r.sr; |
1184 |
|
MakeFromSR(); |
1185 |
< |
m68k_incpc(2); |
1186 |
< |
fill_prefetch_0 (); |
1187 |
< |
return; |
1188 |
< |
} |
1185 |
> |
} |
1186 |
> |
|
1187 |
> |
cpuop_rettype REGPARAM2 op_illg (uae_u32 opcode) |
1188 |
> |
{ |
1189 |
> |
uaecptr pc = m68k_getpc (); |
1190 |
|
|
1191 |
|
if ((opcode & 0xF000) == 0xA000) { |
1192 |
|
Exception(0xA,0); |
1193 |
< |
return; |
1193 |
> |
cpuop_return(CFLOW_TRAP); |
1194 |
|
} |
1195 |
|
|
1192 |
– |
// write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); |
1193 |
– |
|
1196 |
|
if ((opcode & 0xF000) == 0xF000) { |
1197 |
|
Exception(0xB,0); |
1198 |
< |
return; |
1198 |
> |
cpuop_return(CFLOW_TRAP); |
1199 |
|
} |
1200 |
|
|
1201 |
|
write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); |
1202 |
|
|
1203 |
|
Exception (4,0); |
1204 |
+ |
cpuop_return(CFLOW_TRAP); |
1205 |
|
} |
1206 |
|
|
1207 |
|
void mmu_op(uae_u32 opcode, uae_u16 extra) |
1228 |
|
/* We can afford this to be inefficient... */ |
1229 |
|
m68k_setpc (m68k_getpc ()); |
1230 |
|
fill_prefetch_0 (); |
1231 |
< |
opcode = get_word (regs.pc); |
1231 |
> |
opcode = get_word(m68k_getpc()); |
1232 |
|
if (opcode == 0x4e72 /* RTE */ |
1233 |
|
|| opcode == 0x4e74 /* RTD */ |
1234 |
|
|| opcode == 0x4e75 /* RTS */ |
1244 |
|
&& (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) |
1245 |
|
{ |
1246 |
|
last_trace_ad = m68k_getpc (); |
1247 |
< |
regs.spcflags &= ~SPCFLAG_TRACE; |
1248 |
< |
regs.spcflags |= SPCFLAG_DOTRACE; |
1247 |
> |
SPCFLAGS_CLEAR( SPCFLAG_TRACE ); |
1248 |
> |
SPCFLAGS_SET( SPCFLAG_DOTRACE ); |
1249 |
|
} |
1250 |
|
} else if (regs.t1) { |
1251 |
|
last_trace_ad = m68k_getpc (); |
1252 |
< |
regs.spcflags &= ~SPCFLAG_TRACE; |
1253 |
< |
regs.spcflags |= SPCFLAG_DOTRACE; |
1252 |
> |
SPCFLAGS_CLEAR( SPCFLAG_TRACE ); |
1253 |
> |
SPCFLAGS_SET( SPCFLAG_DOTRACE ); |
1254 |
|
} |
1255 |
|
} |
1256 |
|
|
1257 |
< |
|
1255 |
< |
static int do_specialties (void) |
1257 |
> |
int m68k_do_specialties (void) |
1258 |
|
{ |
1259 |
< |
/*n_spcinsns++;*/ |
1258 |
< |
if (regs.spcflags & SPCFLAG_DOTRACE) { |
1259 |
> |
if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) { |
1260 |
|
Exception (9,last_trace_ad); |
1261 |
|
} |
1262 |
< |
while (regs.spcflags & SPCFLAG_STOP) { |
1263 |
< |
if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)){ |
1262 |
> |
while (SPCFLAGS_TEST( SPCFLAG_STOP )) { |
1263 |
> |
if (SPCFLAGS_TEST( SPCFLAG_INT | SPCFLAG_DOINT )){ |
1264 |
> |
SPCFLAGS_CLEAR( SPCFLAG_INT | SPCFLAG_DOINT ); |
1265 |
|
int intr = intlev (); |
1264 |
– |
regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT); |
1266 |
|
if (intr != -1 && intr > regs.intmask) { |
1267 |
|
Interrupt (intr); |
1268 |
|
regs.stopped = 0; |
1269 |
< |
regs.spcflags &= ~SPCFLAG_STOP; |
1269 |
> |
SPCFLAGS_CLEAR( SPCFLAG_STOP ); |
1270 |
|
} |
1271 |
|
} |
1272 |
|
} |
1273 |
< |
if (regs.spcflags & SPCFLAG_TRACE) |
1273 |
> |
if (SPCFLAGS_TEST( SPCFLAG_TRACE )) |
1274 |
|
do_trace (); |
1275 |
|
|
1276 |
< |
if (regs.spcflags & SPCFLAG_DOINT) { |
1276 |
> |
if (SPCFLAGS_TEST( SPCFLAG_DOINT )) { |
1277 |
> |
SPCFLAGS_CLEAR( SPCFLAG_DOINT ); |
1278 |
|
int intr = intlev (); |
1277 |
– |
regs.spcflags &= ~SPCFLAG_DOINT; |
1279 |
|
if (intr != -1 && intr > regs.intmask) { |
1280 |
|
Interrupt (intr); |
1281 |
|
regs.stopped = 0; |
1282 |
|
} |
1283 |
|
} |
1284 |
< |
if (regs.spcflags & SPCFLAG_INT) { |
1285 |
< |
regs.spcflags &= ~SPCFLAG_INT; |
1286 |
< |
regs.spcflags |= SPCFLAG_DOINT; |
1287 |
< |
} |
1288 |
< |
if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { |
1289 |
< |
regs.spcflags &= ~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); |
1290 |
< |
return 1; |
1284 |
> |
if (SPCFLAGS_TEST( SPCFLAG_INT )) { |
1285 |
> |
SPCFLAGS_CLEAR( SPCFLAG_INT ); |
1286 |
> |
SPCFLAGS_SET( SPCFLAG_DOINT ); |
1287 |
> |
} |
1288 |
> |
if (SPCFLAGS_TEST( SPCFLAG_BRK )) { |
1289 |
> |
SPCFLAGS_CLEAR( SPCFLAG_BRK ); |
1290 |
> |
return CFLOW_EXEC_RETURN; |
1291 |
|
} |
1292 |
|
return 0; |
1293 |
|
} |
1294 |
|
|
1295 |
< |
static void m68k_run_1 (void) |
1295 |
> |
void m68k_do_execute (void) |
1296 |
|
{ |
1297 |
|
for (;;) { |
1298 |
|
uae_u32 opcode = GET_OPCODE; |
1306 |
|
#else |
1307 |
|
(*cpufunctbl[opcode])(opcode); |
1308 |
|
#endif |
1309 |
< |
if (regs.spcflags) { |
1310 |
< |
if (do_specialties()) |
1309 |
> |
if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { |
1310 |
> |
if (m68k_do_specialties()) |
1311 |
|
return; |
1312 |
|
} |
1313 |
|
} |
1314 |
|
} |
1315 |
|
|
1316 |
< |
#define m68k_run1 m68k_run_1 |
1316 |
< |
|
1317 |
< |
int in_m68k_go = 0; |
1318 |
< |
|
1319 |
< |
void m68k_go (int may_quit) |
1316 |
> |
void m68k_execute (void) |
1317 |
|
{ |
1321 |
– |
// m68k_go() must be reentrant for Execute68k() and Execute68kTrap() to work |
1322 |
– |
/* |
1323 |
– |
if (in_m68k_go || !may_quit) { |
1324 |
– |
write_log("Bug! m68k_go is not reentrant.\n"); |
1325 |
– |
abort(); |
1326 |
– |
} |
1327 |
– |
*/ |
1328 |
– |
in_m68k_go++; |
1318 |
|
for (;;) { |
1319 |
|
if (quit_program > 0) { |
1320 |
|
if (quit_program == 1) |
1322 |
|
quit_program = 0; |
1323 |
|
m68k_reset (); |
1324 |
|
} |
1325 |
< |
m68k_run1(); |
1325 |
> |
m68k_do_execute(); |
1326 |
|
} |
1327 |
|
if (debugging) { |
1328 |
|
uaecptr nextpc; |
1329 |
|
m68k_dumpstate(&nextpc); |
1330 |
|
exit(1); |
1331 |
|
} |
1343 |
– |
in_m68k_go--; |
1332 |
|
} |
1333 |
|
|
1334 |
|
static void m68k_verify (uaecptr addr, uaecptr *nextpc) |