out("if(t1) opcode |= 0x10000;\n");
}
next_level_000();
+ set_ipl();
fill_prefetch_1(2);
} else {
fill_prefetch_1_empty(2);
addcycles000(4);
out("MakeSR();\nregs.sr &= 0xFF00;\nregs.sr |= src & 0xFF;\n");
makefromsr();
- set_ipl();
} else {
// MOVE TO SR
check_trace();
addcycles000(4);
- set_ipl();
out("regs.sr = src;\n");
makefromsr_t0();
}
} else {
addop_ce020(curi, 0, 0);
// smode must be first in case it is A7. Except if 68040!
+ set_ipl();
if (cpu_level == 4) {
genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA | GF_NOEXC3);
genamode(NULL, curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA);
write_return_cycles(0);
out("}\n");
}
- genastore_2("src", Apdi, "7", sz_long, "old", 0, GF_IPLMID);
+ genastore_2("src", Apdi, "7", sz_long, "old", 0, 0);
genastore("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
out("m68k_areg(regs, 7) += offs;\n");
fill_prefetch_next_t();
out("m68k_areg(regs, srcreg) = old;\n");
} else {
m68k_pc_offset = 4;
+ set_ipl();
genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
- genamode(NULL, am_unknown, "src", sz_long, "old", 1, 0, GF_IPLMID);
+ genamode(NULL, am_unknown, "src", sz_long, "old", 1, 0, 0);
out("m68k_areg(regs, 7) = src + 4;\n");
m68k_pc_offset = 2;
genastore("old", curi->smode, "srcreg", curi->size, "src");
SET_ZFLG((regs.sr >> 2) & 1);
SET_VFLG((regs.sr >> 1) & 1);
SET_CFLG(regs.sr & 1);
+
if (regs.t1 == ((regs.sr >> 15) & 1) &&
regs.t0 == ((regs.sr >> 14) & 1) &&
regs.s == ((regs.sr >> 13) & 1) &&
regs.m == ((regs.sr >> 12) & 1) &&
regs.intmask == ((regs.sr >> 8) & 7))
return;
+
regs.t1 = (regs.sr >> 15) & 1;
regs.t0 = (regs.sr >> 14) & 1;
regs.s = (regs.sr >> 13) & 1;
- regs.m = (regs.sr >> 12) & 1;
+ regs.m = (regs.sr >> 12) & 1;
if (regs.intmask != ((regs.sr >> 8) & 7)) {
int newimask = (regs.sr >> 8) & 7;
if (t0trace < 0 && regs.ipl[0] <= regs.intmask && regs.ipl[0] > newimask && regs.ipl[0] < 7) {
regs.ipl[0] = 0;
}
+ } else {
+ if (regs.ipl[0] <= regs.intmask && regs.ipl_pin > newimask) {
+ set_special(SPCFLAG_INT);
+ }
}
regs.intmask = newimask;
- if (regs.ipl_pin > regs.intmask) {
- set_special(SPCFLAG_INT);
- }
}
if (currprefs.cpu_model >= 68020) {
return;
}
regs.ird = regs.ir;
- if (m68k_accurate_ipl && interrupt) {
- ipl_fetch_now();
- }
x_do_cycles(2 * cpucycleunit);
- if (m68k_accurate_ipl && !interrupt) {
+ if (m68k_accurate_ipl) {
ipl_fetch_next();
}
regs.irc = x_get_word(m68k_getpc() + 2); // prefetch 2
// ipl check mid next memory cycle
void ipl_fetch_next_pre(void)
{
+ ipl_fetch_next();
regs.ipl_evt_pre = get_cycles();
regs.ipl_evt_pre_mode = 1;
}
void ipl_fetch_now_pre(void)
{
- regs.ipl[1] = regs.ipl_pin;
+ ipl_fetch_now();
regs.ipl_evt_pre = get_cycles();
regs.ipl_evt_pre_mode = 0;
}
void ipl_fetch_now(void)
{
evt_t c = get_cycles();
+
regs.ipl_evt = c;
regs.ipl[0] = regs.ipl_pin;
regs.ipl[1] = 0;
void ipl_fetch_next(void)
{
evt_t c = get_cycles();
+
if (c - regs.ipl_pin_change_evt >= cpuipldelay4) {
regs.ipl[0] = regs.ipl_pin;
regs.ipl[1] = 0;
+ } else if (c - regs.ipl_pin_change_evt_p >= cpuipldelay2) {
+ regs.ipl[0] = regs.ipl_pin_p;
+ regs.ipl[1] = 0;
} else {
regs.ipl[1] = regs.ipl_pin;
}
doint();
}
+static void update_ipl(int ipl)
+{
+ evt_t c = get_cycles();
+ regs.ipl_pin_change_evt_p = regs.ipl_pin_change_evt;
+ regs.ipl_pin_p = regs.ipl_pin;
+ regs.ipl_pin_change_evt = c;
+ regs.ipl_pin = ipl;
+ if (m68k_accurate_ipl) {
+ // check if 68000/010 interrupt was detected mid memory access,
+ // 2 cycles from start of memory cycle
+ if (ipl > 0 && c == regs.ipl_evt_pre + cpuipldelay2) {
+ if (regs.ipl_evt_pre_mode) {
+ ipl_fetch_next();
+ } else {
+ ipl_fetch_now();
+ }
+ }
+ }
+#ifdef DEBUGGER
+ if (debug_dma) {
+ record_dma_ipl(current_hpos(), vpos);
+ }
+#endif
+}
+
+static void doint_delayed(uae_u32 v)
+{
+ update_ipl(v);
+}
+
void doint(void)
{
#ifdef WITH_PPC
return;
}
#endif
- int il = intlev();
- if (regs.ipl_pin != il) {
- regs.ipl_pin = il;
- regs.ipl_pin_change_evt = get_cycles();
- if (m68k_accurate_ipl) {
- // check if 68000/010 interrupt was detected mid memory access,
- // 2 cycles from start of memory cycle
- if (il > 0 && get_cycles() == regs.ipl_evt_pre + cpuipldelay2) {
- if (regs.ipl_evt_pre_mode) {
- ipl_fetch_next();
- } else {
- ipl_fetch_now();
- }
- }
- }
-#ifdef DEBUGGER
- if (debug_dma) {
- record_dma_ipl(current_hpos(), vpos);
+ int ipl = intlev();
+
+ if (regs.ipl_pin != ipl) {
+
+ // Paula does low to high IPL changes about 1.5 CPU clocks later than high to low.
+ // -> CPU detects IPL change 1 CCK later if any IPL pin has high to low transition.
+ // (In real world IPL is active low and delay is added if 0 to 1 transition)
+ if (m68k_accurate_ipl && regs.ipl_pin >= 0 && ipl >= 0 && (
+ ((regs.ipl_pin & 1) && !(ipl & 1)) ||
+ ((regs.ipl_pin & 2) && !(ipl & 2)) ||
+ ((regs.ipl_pin & 4) && !(ipl & 4))
+ )) {
+ event2_newevent_xx(-1, CYCLE_UNIT, ipl, doint_delayed);
+ return;
}
-#endif
+
+ update_ipl(ipl);
}
if (m68k_interrupt_delay) {
if (!m68k_accurate_ipl && regs.ipl_pin > regs.intmask) {
cpu_cycles = adjust_cycles (cpu_cycles);
do_cycles(cpu_cycles);
regs.instruction_cnt++;
- if (r->spcflags || regs.ipl[0]) {
+ if (r->spcflags || regs.ipl[0] > 0) {
if (do_specialties (cpu_cycles))
exit = true;
}
log_dma_record ();
}
- if (r->spcflags || regs.ipl[0]) {
+ if (r->spcflags || regs.ipl[0] > 0) {
if (do_specialties (0))
exit = true;
}
regs.instruction_cnt++;
cont:
- if (r->spcflags || regs.ipl[0]) {
+ if (r->spcflags || regs.ipl[0] > 0) {
if (do_specialties (0))
exit = true;
}
x_do_cycles(cpu_cycles);
cont:
- if (r->spcflags || regs.ipl[0]) {
+ if (r->spcflags || regs.ipl[0] > 0) {
if (do_specialties (cpu_cycles))
exit = true;
}
regs.ipl[0] = restore_u8();
regs.ipl[1] = restore_u8();
regs.ipl_pin = (uae_s32)restore_u8();
+ regs.ipl_pin_p = (uae_s32)restore_u8();
regs.ipl_evt = restore_u64();
regs.ipl_evt_pre = restore_u64();
regs.ipl_pin_change_evt = restore_u64();
+ regs.ipl_pin_change_evt_p = restore_u64();
}
}
save_u8(regs.ipl[0]);
save_u8(regs.ipl[1]);
save_u8(regs.ipl_pin);
+ save_u8(regs.ipl_pin_p);
save_u64(regs.ipl_evt);
save_u64(regs.ipl_evt_pre);
save_u64(regs.ipl_pin_change_evt);
+ save_u64(regs.ipl_pin_change_evt_p);
}
*len = dst - dstbak;
return dstbak;