#define GF_CLR68010 0x20000 // 68010
#define GF_NOEXC3 0x40000
#define GF_EXC3 0x80000
+// internal PC is 2 less than address being prefetched.
+#define GF_PCM2 0x100000
+// internal PC is 2 more than address being prefetched.
+#define GF_PCP2 0x200000
typedef enum
{
mmu040_movem = 0;
}
+static void setpcstring(char *dst, const char *format, ...)
+{
+ va_list parms;
+ char buffer[1000];
+
+ va_start(parms, format);
+ _vsnprintf(buffer, 1000 - 1, format, parms);
+ va_end(parms);
+
+ if (using_mmu)
+ sprintf(dst, "m68k_setpci(%s);\n", buffer);
+ else if (using_prefetch || using_prefetch_020 || using_test)
+ sprintf(dst, "m68k_setpci_j(%s);\n", buffer);
+ else
+ sprintf(dst, "m68k_setpc_j(%s);\n", buffer);
+}
+
+static void setpc(const char *format, ...)
+{
+ va_list parms;
+ char buffer[1000];
+
+ va_start(parms, format);
+ _vsnprintf(buffer, 1000 - 1, format, parms);
+ va_end(parms);
+
+ if (using_mmu)
+ out("m68k_setpci(%s);\n", buffer);
+ else if (using_prefetch || using_prefetch_020 || using_test)
+ out("m68k_setpci_j(%s);\n", buffer);
+ else
+ out("m68k_setpc_j(%s);\n", buffer);
+}
+
+static void incpc(const char *format, ...)
+{
+ va_list parms;
+ char buffer[1000];
+
+ va_start(parms, format);
+ _vsnprintf(buffer, 1000 - 1, format, parms);
+ va_end(parms);
+
+ if (using_mmu || using_prefetch || using_prefetch_020 || using_test)
+ out("m68k_incpci(%s);\n", buffer);
+ else
+ out("m68k_incpc(%s);\n", buffer);
+}
+
+static void sync_m68k_pc(void)
+{
+ m68k_pc_offset_old = m68k_pc_offset;
+ if (m68k_pc_offset == 0)
+ return;
+ incpc("%d", m68k_pc_offset);
+ m68k_pc_total += m68k_pc_offset;
+ m68k_pc_offset = 0;
+}
+
+static void clear_m68k_offset(void)
+{
+ m68k_pc_total += m68k_pc_offset;
+ m68k_pc_offset = 0;
+}
+
+static void sync_m68k_pc_noreset(void)
+{
+ sync_m68k_pc();
+ m68k_pc_offset = m68k_pc_offset_old;
+}
+
static char bus_error_text[200];
static int bus_error_specials;
static int bus_error_cycles;
if (bus_error_text[0]) {
out("if(hardware_bus_error) {\n");
+ out("int pcoffset = 0;\n");
if (bus_error_code[0])
out("%s", bus_error_code);
out("%s", bus_error_text);
bus_error_specials = 0;
}
-static void check_bus_error_ins(int offset)
+static void check_bus_error_ins(int offset, int pcoffset)
{
const char *opcode;
if (bus_error_specials) {
} else {
opcode = "opcode";
}
- sprintf(bus_error_text, "exception2_fetch(%s, %d);\n", opcode, offset);
+ if (pcoffset == -1) {
+ sprintf(bus_error_text, "exception2_fetch(%s, %d, pcoffset);\n", opcode, offset);
+ } else {
+ sprintf(bus_error_text, "exception2_fetch(%s, %d, %d);\n", opcode, offset, pcoffset);
+ }
}
-static void check_bus_error_ins_opcode(int offset)
+static void check_bus_error_ins_opcode(int offset, int pcoffset)
{
const char *opcode;
if (bus_error_specials) {
} else {
opcode = "opcode";
}
- sprintf(bus_error_text, "exception2_fetch_opcode(%s, %d);\n", opcode, offset);
+ if (pcoffset == -1) {
+ sprintf(bus_error_text, "exception2_fetch_opcode(%s, %d, pcoffset);\n", opcode, offset);
+ } else {
+ sprintf(bus_error_text, "exception2_fetch_opcode(%s, %d, %d);\n", opcode, offset, pcoffset);
+ }
}
-static void check_prefetch_bus_error(int offset, int secondprefetchmode)
+static void check_prefetch_bus_error(int offset, int pcoffset, int secondprefetchmode)
{
if (!needbuserror())
return;
bus_error_specials = 1;
}
}
- check_bus_error_ins_opcode(offset);
+ check_bus_error_ins_opcode(offset, pcoffset);
do_instruction_buserror();
}
-static void check_prefetch_buserror(int offset)
+static void check_prefetch_buserror(int offset, int pcoffset)
{
- check_bus_error_ins(offset);
+ check_bus_error_ins(offset, pcoffset);
do_instruction_buserror();
}
-static void gen_nextilong2 (const char *type, const char *name, int flags, int movem)
+static void gen_nextilong2(const char *type, const char *name, int flags, int movem)
{
int r = m68k_pc_offset;
+ int pcoffset = ((flags & (GF_PCM2 | GF_PCP2)) == (GF_PCM2 | GF_PCP2) ? 0 : (((flags & GF_PCM2) ? -2 : (flags & GF_PCP2) ? 2 : 0)));
m68k_pc_offset += 4;
out("%s %s;\n", type, name);
out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
count_readw++;
out("%s |= regs.irc;\n", name);
- check_bus_error_ins(r + 2);
+ check_bus_error_ins(r + 2, pcoffset);
do_instruction_buserror();
strcpy(bus_error_code, bus_error_code2);
bus_error_code2[0] = 0;
} else {
out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
count_readw++;
- check_bus_error_ins(r + 2);
+ check_bus_error_ins(r + 2, pcoffset);
do_instruction_buserror();
strcpy(bus_error_code, bus_error_code2);
bus_error_code2[0] = 0;
set_last_access();
out("%s |= %s(%d);\n", name, prefetch_word, r + 4);
count_readw++;
- check_bus_error_ins(r + 4);
+ check_bus_error_ins(r + 4, -1);
}
} else if (using_prefetch) {
if (flags & GF_NOREFILL) {
out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
count_readw++;
out("%s |= regs.irc;\n", name);
- check_bus_error_ins(r + 2);
+ check_bus_error_ins(r + 2, pcoffset);
do_instruction_buserror();
strcpy(bus_error_code, bus_error_code2);
bus_error_code2[0] = 0;
} else {
out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2);
count_readw++;
- check_bus_error_ins(r + 2);
+ check_bus_error_ins(r + 2, pcoffset);
do_instruction_buserror();
strcpy(bus_error_code, bus_error_code2);
bus_error_code2[0] = 0;
set_last_access();
out("%s |= %s(%d);\n", name, prefetch_word, r + 4);
count_readw++;
- check_bus_error_ins(r + 4);
+ check_bus_error_ins(r + 4, -1);
}
} else {
if (flags & GF_NOREFILL) {
gen_nextilong2 (type, name, flags, 0);
}
-static const char *gen_nextiword (int flags)
+static const char *gen_nextiword(int flags)
{
static char buffer[80];
int r = m68k_pc_offset;
+ int pcoffset = ((flags & (GF_PCM2 | GF_PCP2)) == (GF_PCM2 | GF_PCP2) ? 0 : (((flags & GF_PCM2) ? -2 : (flags & GF_PCP2) ? 2 : 0)));
m68k_pc_offset += 2;
bus_error_text[0] = 0;
set_last_access();
sprintf(buffer, "%s(%d)", prefetch_word, r + 2);
count_readw++;
- check_bus_error_ins(r + 2);
+ check_bus_error_ins(r + 2, pcoffset);
}
} else if (using_prefetch) {
if (flags & GF_NOREFILL) {
set_last_access();
sprintf(buffer, "%s(%d)", prefetch_word, r + 2);
count_readw++;
- check_bus_error_ins(r + 2);
+ check_bus_error_ins(r + 2, pcoffset);
}
} else {
sprintf(buffer, "%s(%d)", prefetch_word, r);
if (!(flags & GF_NOREFILL)) {
count_readw++;
count_readp++;
- check_bus_error_ins(r);
+ check_bus_error_ins(r, pcoffset);
}
}
return buffer;
}
-static const char *gen_nextibyte (int flags)
+static const char *gen_nextibyte(int flags)
{
static char buffer[80];
int r = m68k_pc_offset;
+ int pcoffset = ((flags & (GF_PCM2 | GF_PCP2)) == (GF_PCM2 | GF_PCP2) ? 0 : (((flags & GF_PCM2) ? -2 : (flags & GF_PCP2) ? 2 : 0)));
m68k_pc_offset += 2;
bus_error_text[0] = 0;
set_last_access();
sprintf(buffer, "(uae_u8)%s(%d)", prefetch_word, r + 2);
count_readw++;
- check_bus_error_ins(r + 2);
+ check_bus_error_ins(r + 2, pcoffset);
}
} else if (using_prefetch) {
if (flags & GF_NOREFILL) {
set_last_access();
sprintf(buffer, "(uae_u8)%s(%d)", prefetch_word, r + 2);
count_readw++;
- check_bus_error_ins(r + 2);
+ check_bus_error_ins(r + 2, pcoffset);
}
} else {
sprintf(buffer, "%s(%d)", srcbi, r);
if (!(flags & GF_NOREFILL)) {
count_readw++;
count_readp++;
- check_bus_error_ins(r);
+ check_bus_error_ins(r, pcoffset);
}
}
return buffer;
set_last_access();
out("%s(%d);\n", prefetch_word, m68k_pc_offset + 2);
count_readw++;
- check_prefetch_bus_error(m68k_pc_offset + 2, 0);
+ check_prefetch_bus_error(m68k_pc_offset + 2, -1, 0);
did_prefetch = 1;
ir2irc = 0;
}
} else {
addcycles000_nonce(4);
}
- check_prefetch_bus_error(o, 0);
+ check_prefetch_bus_error(o, -1, 0);
did_prefetch = 1;
ir2irc = 0;
} else {
set_last_access();
out("%s(%d);\n", prefetch_word, o);
count_readw++;
- check_prefetch_bus_error(o ? -2 : -1, 0);
+ check_prefetch_bus_error(o ? -2 : -1, 0, 0);
did_prefetch = 1;
ir2irc = 0;
} else {
}
}
-static void fill_prefetch_full_000_special(const char *format, ...)
+// 0 = pc not changed
+// 1 = pc == oldpc + 2, both address and PC
+// 2 = pc not changed, stacked PC is oldpc + 2
+// -1 = first fetch: pcoffset - adjustment second: pcoffset = 0 (dbcc)
+static void fill_prefetch_full_000_special(int pctype, const char *format, ...)
{
+ char tmp[100];
if (!using_prefetch) {
if (format && cpu_level <= 1) {
char outbuf[256];
out("%s(%d);\n", prefetch_word, 0);
count_readw++;
- check_prefetch_bus_error(-1, -1);
+ if (pctype == 1) {
+ setpcstring(tmp, "oldpc + 2");
+ strcpy(bus_error_code, tmp);
+ } else if (pctype == 2) {
+ sprintf(tmp, "pcoffset = oldpc - %s + 2;\n", getpc);
+ strcpy(bus_error_code, tmp);
+ } else if (pctype == -1) {
+ strcpy(bus_error_code, "pcoffset += pcadjust;\n");
+ }
+ check_prefetch_bus_error(-1, -1, -1);
irc2ir();
if (using_bus_error) {
copy_opcode();
set_last_access();
out("%s(%d);\n", prefetch_word, 2);
count_readw++;
- check_prefetch_bus_error(-2, -1);
+ if (pctype > 0) {
+ strcpy(bus_error_code, tmp);
+ }
+ check_prefetch_bus_error(-2, -1, -1);
did_prefetch = 1;
ir2irc = 0;
}
if (using_prefetch) {
out("%s(0);\n", prefetch_word);
count_readw++;
- check_prefetch_bus_error(0, 0);
+ check_prefetch_bus_error(0, 0, 0);
did_prefetch = 1;
ir2irc = 0;
} else {
}
}
-static void setpc (const char *format, ...)
-{
- va_list parms;
- char buffer[1000];
-
- va_start (parms, format);
- _vsnprintf(buffer, 1000 - 1, format, parms);
- va_end (parms);
-
- if (using_mmu)
- out("m68k_setpci(%s);\n", buffer);
- else if (using_prefetch || using_prefetch_020 || using_test)
- out("m68k_setpci_j(%s);\n", buffer);
- else
- out("m68k_setpc_j(%s);\n", buffer);
-}
-
-static void incpc (const char *format, ...)
-{
- va_list parms;
- char buffer[1000];
-
- va_start (parms, format);
- _vsnprintf(buffer, 1000 - 1, format, parms);
- va_end (parms);
-
- if (using_mmu || using_prefetch || using_prefetch_020 || using_test)
- out("m68k_incpci(%s);\n", buffer);
- else
- out("m68k_incpc(%s);\n", buffer);
-}
-
static void dummy_prefetch(const char *newpc, const char *oldpc)
{
if (using_prefetch && cpu_level == 1) {
}
}
-static void sync_m68k_pc (void)
-{
- m68k_pc_offset_old = m68k_pc_offset;
- if (m68k_pc_offset == 0)
- return;
- incpc ("%d", m68k_pc_offset);
- m68k_pc_total += m68k_pc_offset;
- m68k_pc_offset = 0;
-}
-
-static void clear_m68k_offset(void)
-{
- m68k_pc_total += m68k_pc_offset;
- m68k_pc_offset = 0;
-}
-
-static void sync_m68k_pc_noreset (void)
-{
- sync_m68k_pc();
- m68k_pc_offset = m68k_pc_offset_old;
-}
-
static void duplicate_carry(void)
{
out("COPY_CARRY();\n");
if (pcoffset < 0) {
incpc("%d", m68k_pc_offset + 2);
- } else if (exception_pc_offset || exception_pc_offset_extra || pcoffset) {
+ } else if (exception_pc_offset + exception_pc_offset_extra + pcoffset) {
incpc("%d", exception_pc_offset + exception_pc_offset_extra + pcoffset);
}
int pc_68000_offset_fetch = 0;
int pc_68000_offset_store = 0;
bool addr = false;
+ // common EA prefetch bus error PC behavior
+ int pcflag = !(flags & (GF_PCM2 | GF_PCP2)) ? GF_PCM2 : 0;
sprintf(namea, "%sa", name);
if ((flags & GF_RMW) && using_mmu == 68060) {
case Ad16: // (d16,An)
out("uaecptr %sa;\n", name);
start_mmu040_movem(movem);
- out("%sa = m68k_areg(regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword (flags));
+ out("%sa = m68k_areg(regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword(flags | pcflag));
count_read_ea++;
addr = true;
break;
out("uaecptr %sa;\n", name);
start_mmu040_movem(movem);
out("%sa = %s + %d;\n", name, getpc, m68k_pc_offset);
- out("%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags));
+ out("%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword(flags | pcflag));
addr = true;
break;
case Ad8r: // (d8,An,Xn)
if ((flags & GF_NOREFILL) && using_prefetch) {
out("%sa = %s(m68k_areg(regs, %s), regs.irc);\n", name, disp000, reg);
} else {
- out("%sa = %s(m68k_areg(regs, %s), %s);\n", name, disp000, reg, gen_nextiword (flags));
+ out("%sa = %s(m68k_areg(regs, %s), %s);\n", name, disp000, reg, gen_nextiword(flags | pcflag));
}
count_read_ea++;
}
if ((flags & GF_NOREFILL) && using_prefetch) {
out("%sa = %s(tmppc, regs.irc);\n", name, disp000);
} else {
- out("%sa = %s(tmppc, %s);\n", name, disp000, gen_nextiword (flags));
+ out("%sa = %s(tmppc, %s);\n", name, disp000, gen_nextiword(flags | pcflag));
}
}
if ((flags & GF_NOFETCH) && using_prefetch) {
case absw:
out("uaecptr %sa;\n", name);
start_mmu040_movem(movem);
- out("%sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags));
+ out("%sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword(flags));
pc_68000_offset_fetch += 2;
addr = true;
break;
case absl:
- gen_nextilong2 ("uaecptr", namea, flags, movem);
+ gen_nextilong2("uaecptr", namea, flags | pcflag, movem);
count_read_ea += 2;
pc_68000_offset_fetch += 4;
pc_68000_offset_store += 2;
term();
switch (size) {
case sz_byte:
- out("uae_s8 %s = %s;\n", name, gen_nextibyte (flags));
+ out("uae_s8 %s = %s;\n", name, gen_nextibyte(flags));
count_read_ea++;
break;
case sz_word:
- out("uae_s16 %s = %s;\n", name, gen_nextiword (flags));
+ out("uae_s16 %s = %s;\n", name, gen_nextiword(flags));
count_read_ea++;
break;
case sz_long:
- gen_nextilong ("uae_s32", name, flags);
+ gen_nextilong("uae_s32", name, flags | pcflag);
count_read_ea += 2;
break;
default:
case imm0:
if (getv != 1)
term();
- out("uae_s8 %s = %s;\n", name, gen_nextibyte (flags));
+ out("uae_s8 %s = %s;\n", name, gen_nextibyte(flags));
count_read_ea++;
do_instruction_buserror();
maybeaddop_ce020 (flags);
case imm1:
if (getv != 1)
term();
- out("uae_s16 %s = %s;\n", name, gen_nextiword (flags));
+ out("uae_s16 %s = %s;\n", name, gen_nextiword(flags));
count_read_ea++;
do_instruction_buserror();
maybeaddop_ce020 (flags);
case imm2:
if (getv != 1)
term();
- gen_nextilong ("uae_s32", name, flags);
+ gen_nextilong("uae_s32", name, flags);
count_read_ea += 2;
- maybeaddop_ce020 (flags);
- syncmovepc (getv, flags);
+ maybeaddop_ce020(flags);
+ syncmovepc(getv, flags);
strcpy(g_srcname, name);
return;
case immi:
}
}
- exception_pc_offset = 0;
+ exception_pc_offset = pc_68000_offset;
if (getv == 2) {
// store
if (pc_68000_offset) {
- exception_pc_offset = pc_68000_offset + pc_68000_offset_store + 2;
+ exception_pc_offset += pc_68000_offset_store + 2;
}
} else {
// fetch
- exception_pc_offset = pc_68000_offset + pc_68000_offset_fetch;
+ exception_pc_offset += pc_68000_offset_fetch;
}
if (!(flags & GF_NOEXC3)) {
{
char tmp[100];
+ exception_pc_offset = m68k_pc_offset;
+
if (candormw) {
if (strcmp (rmw_varname, to) != 0)
candormw = false;
static void genmovemel_ce(uae_u16 opcode)
{
int size = table68k[opcode].size == sz_long ? 4 : 2;
- out("uae_u16 mask = %s;\n", gen_nextiword (0));
- check_prefetch_buserror(m68k_pc_offset);
+ amodes mode = table68k[opcode].dmode;
+ out("uae_u16 mask = %s;\n", gen_nextiword(mode < Ad16 ? GF_PCM2 : 0));
+ do_instruction_buserror();
out("uae_u32 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
- if (table68k[opcode].dmode == Ad8r || table68k[opcode].dmode == PC8r) {
+ if (mode == Ad8r || mode == PC8r) {
addcycles000(2);
}
- genamode(NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, -1, GF_AA | GF_MOVE);
+ genamode(NULL, mode, "dstreg", table68k[opcode].size, "src", 2, -1, GF_AA | GF_MOVE | GF_PCM2);
movem_ex3(0);
if (table68k[opcode].size == sz_long) {
out("while (dmask) {\n");
out("%s(srca);\n", srcw); // and final extra word fetch that goes nowhere..
count_readw++;
check_bus_error("src", 0, 0, 1, NULL, 1, -1);
- if (table68k[opcode].dmode == Aipi)
+ if (mode == Aipi) {
out("m68k_areg(regs, dstreg) = srca;\n");
+ }
count_ncycles++;
fill_prefetch_next_t();
}
static void genmovemle_ce (uae_u16 opcode)
{
int size = table68k[opcode].size == sz_long ? 4 : 2;
+ amodes mode = table68k[opcode].dmode;
- out("uae_u16 mask = %s;\n", gen_nextiword (0));
- check_prefetch_buserror(m68k_pc_offset);
- if (table68k[opcode].dmode == Ad8r || table68k[opcode].dmode == PC8r) {
+ out("uae_u16 mask = %s;\n", gen_nextiword(mode >= Ad8r && mode != absw && mode != absl ? GF_PCM2 : ((mode == Ad16 || mode == PC16 || mode == absw || mode == absl) ? 0 : GF_PCP2)));
+ do_instruction_buserror();
+ if (mode == Ad8r || mode == PC8r) {
addcycles000(2);
}
- genamode(NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, GF_AA | GF_MOVE | GF_REVERSE | GF_REVERSE2);
+ strcpy(bus_error_code2, "pcoffset += 2;\n");
+ genamode(NULL, mode, "dstreg", table68k[opcode].size, "src", 2, 1, GF_AA | GF_MOVE | GF_REVERSE | GF_REVERSE2 | (mode == absl ? GF_PCM2 : GF_PCP2));
if (table68k[opcode].size == sz_long) {
- if (table68k[opcode].dmode == Apdi) {
+ if (mode == Apdi) {
out("uae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
movem_ex3(1);
out("while (amask) {\n");
out("}\n");
}
} else {
- if (table68k[opcode].dmode == Apdi) {
+ if (mode == Apdi) {
out("uae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
movem_ex3(1);
out("while (amask) {\n");
"SET_XFLG(GET_CFLG());\n"
"SET_VFLG((bflgs ^ bflgo) & (bflgn ^ bflgo));\n");
}
- if (c > 0)
+ if (c > 0) {
addcycles000(c);
+ }
genastore_rev("newv", curi->dmode, "dstreg", curi->size, "dst");
} else {
if (curi->dmode == Dreg) {
fill_prefetch_next_t();
loopmodeextra = 4;
}
- if (c > 0)
+ if (c > 0) {
addcycles000(c);
+ }
if (curi->dmode != Dreg) {
genastore_rev("newv", curi->dmode, "dstreg", curi->size, "dst");
}
} else {
fill_prefetch_next_after(1, NULL);
}
- if (isreg (curi->smode) && curi->size == sz_long)
+ if (isreg(curi->smode) && curi->size == sz_long) {
addcycles000(2);
+ }
if (curi->smode != Dreg) {
genastore_rev("dst", curi->smode, "srcreg", curi->size, "src");
}
* weird things... */
case i_MVPRM: // MOVEP R->M
genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, cpu_level == 1 ? GF_NOFETCH : 0);
- out("uaecptr mempa = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword (0));
- check_prefetch_buserror(m68k_pc_offset);
+ out("uaecptr mempa = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword(0));
+ check_prefetch_buserror(m68k_pc_offset, -2);
if (curi->size == sz_word) {
out("%s(mempa, src >> 8);\n", dstb);
count_writew++;
next_level_000();
break;
case i_MVPMR: // MOVEP M->R
- out("uaecptr mempa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword (0));
- check_prefetch_buserror(m68k_pc_offset);
+ out("uaecptr mempa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword(0));
+ check_prefetch_buserror(m68k_pc_offset, -2);
genamode(curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, cpu_level == 1 ? GF_NOFETCH : 0);
if (curi->size == sz_word) {
out("uae_u16 val = (%s(mempa) & 0xff) << 8;\n", srcb);
} else if (cpu_level < 2) {
- int prefetch_done = 0, flags;
+ int prefetch_done = 0;
+ int flags = 0;
int dualprefetch = curi->dmode == absl && (curi->smode != Dreg && curi->smode != Areg && curi->smode != imm);
- genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+ if (curi->size == sz_long) {
+ if (curi->smode >= Aind && curi->smode != absw) {
+ flags |= GF_PCM2;
+ } else {
+ flags |= GF_PCM2 | GF_PCP2;
+ }
+ } else {
+ if (curi->smode >= Aind && curi->smode != absw && curi->smode != imm) {
+ flags |= GF_PCM2;
+ } else {
+ flags |= GF_PCM2 | GF_PCP2;
+ }
+ }
+
+ genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, flags);
+
+ flags = 0;
+ // unexpectedly MOVEA vs MOVE have different prefetch bus error stack frame PC field behavior.
+ if (curi->mnemo == i_MOVE) {
+ if ((curi->smode == imm && curi->dmode == absl)
+ || (curi->smode >= Ad16 && curi->smode != imm && curi->smode != absw && curi->smode != absl && curi->dmode < Ad16)
+ || (curi->smode == absl && curi->dmode < Ad16)
+ || ((curi->smode == Areg || curi->smode == Dreg) && curi->dmode == absl)) {
+ flags |= GF_PCM2;
+ } else {
+ flags |= GF_PCM2 | GF_PCP2;
+ }
+ }
- flags = GF_MOVE | GF_APDI;
+ flags |= GF_MOVE | GF_APDI;
flags |= dualprefetch ? GF_NOREFILL : 0;
if (curi->dmode == Apdi && curi->size == sz_long)
flags |= GF_REVERSE;
clear_m68k_offset();
tail_ce020_done = true;
if (using_ce || using_prefetch) {
- fill_prefetch_full_000_special(NULL);
+ fill_prefetch_full_000_special(2, NULL);
} else {
fill_prefetch_full_ntx(0);
}
next_cpu_level = cpu_level - 1;
break;
case i_RTD:
+ out("uaecptr oldpc = %s;\n", getpc);
addop_ce020 (curi, 0, 0);
if (using_mmu) {
genamode(curi, curi->smode, "srcreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
clear_m68k_offset();
tail_ce020_done = true;
if (using_prefetch || using_ce) {
- fill_prefetch_full_000_special(NULL);
+ fill_prefetch_full_000_special(1, NULL);
} else {
fill_prefetch_full(0);
}
genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA | GF_NOEXC3);
}
strcpy(bus_error_code, "m68k_areg(regs, 7) += 4;\n");
- genamode(NULL, curi->dmode, "dstreg", curi->size, "offs", 1, 0, 0);
+ genamode(NULL, curi->dmode, "dstreg", curi->size, "offs", 1, 0, GF_PCP2);
if (cpu_level <= 1 && using_exception_3) {
out("if (olda & 1) {\n");
out("m68k_areg(regs, 7) += 4;\n");
break;
case i_RTS:
addop_ce020 (curi, 0, 0);
- out("uaecptr pc = %s;\n", getpc);
+ out("uaecptr oldpc = %s;\n", getpc);
if (cpu_level <= 1 && using_exception_3) {
out("if (m68k_areg(regs, 7) & 1) {\n");
incpc("2");
}
if (using_debugmem) {
out("if (debugmem_trace) {\n");
- out("branch_stack_pop_rts(pc);\n");
+ out("branch_stack_pop_rts(oldpc);\n");
out("}\n");
}
out("if (%s & 1) {\n", getpc);
out("uaecptr faultpc = %s;\n", getpc);
- setpc("pc");
+ setpc("oldpc");
if (cpu_level >= 4) {
out("m68k_areg(regs, 7) -= 4;\n");
}
out("}\n");
clear_m68k_offset();
if (using_prefetch || using_ce) {
- fill_prefetch_full_000_special(NULL);
+ fill_prefetch_full_000_special(2, NULL);
} else {
fill_prefetch_full(0);
}
"regs.sr |= 0x2000;\n"
"regs.sr &= ~0x8000;\n"
"MakeFromSR();\n"
+ "pcoffset -= 2;\n"
"} else {\n"
"opcode = regs.ir | 0x20000;\n"
"if(regs.t1) opcode |= 0x10000;\n"
}
clear_m68k_offset();
if (using_prefetch || using_ce) {
- fill_prefetch_full_000_special(NULL);
+ fill_prefetch_full_000_special(2, NULL);
} else {
fill_prefetch_full(0);
}
out("if(regs.t1) opcode |= 0x10000;\n");
out("%s(%d);\n", prefetch_word, 2);
count_readw++;
- check_prefetch_bus_error(-2, sp);
+ check_prefetch_bus_error(-2, 0, sp);
did_prefetch = 1;
ir2irc = 0;
} else {
if (using_prefetch || using_ce) {
out("%s(%d);\n", prefetch_word, 0);
count_readw++;
- check_prefetch_bus_error(-1, 0);
+ check_prefetch_bus_error(-1, 0, 0);
irc2ir();
set_last_access();
out("%s(%d);\n", prefetch_word, 2);
if (sp < 0 && cpu_level == 0)
out("if(regs.t1) opcode |= 0x10000;\n");
count_readw++;
- check_prefetch_bus_error(-2, sp);
+ check_prefetch_bus_error(-2, 0, sp);
did_prefetch = 1;
ir2irc = 0;
} else {
}
clear_m68k_offset();
if (using_prefetch || using_ce) {
- fill_prefetch_full_000_special(NULL);
+ fill_prefetch_full_000_special(0, NULL);
} else {
fill_prefetch_full(0);
}
}
break;
case i_Bcc:
+ out("uaecptr oldpc = %s;\n", getpc);
tail_ce020_done = true;
if (curi->size == sz_long) {
if (cpu_level < 2) {
push_ins_cnt();
if (using_prefetch) {
incpc ("(uae_s32)src + 2");
- fill_prefetch_full_000_special(NULL);
+ fill_prefetch_full_000_special(2, NULL);
check_ipl_always();
if (using_ce)
out("return;\n");
fill_prefetch_bcc();
} else if (curi->size == sz_word) {
add_head_cycs (6);
- fill_prefetch_full_000_special(NULL);
+ fill_prefetch_full_000_special(0, NULL);
} else {
add_head_cycs (6);
- fill_prefetch_full_000_special(NULL);
+ fill_prefetch_full_000_special(0, NULL);
}
insn_n_cycles = curi->size == sz_byte ? 8 : 12;
branch_inst = 1;
next_level_020_to_010();
break;
case i_LEA:
- if (curi->smode == Ad8r || curi->smode == PC8r)
+ if (curi->smode == Ad8r || curi->smode == PC8r) {
addcycles000(2);
+ }
if (curi->smode == absl) {
if (cpu_level == 0) {
strcpy(bus_error_code, "m68k_areg(regs, dstreg) = (m68k_areg(regs, dstreg) & 0x0000ffff) | (srca & 0xffff0000);\n");
}
}
genamodedual(curi,
- curi->smode, "srcreg", curi->size, "src", 0, GF_AA,
+ curi->smode, "srcreg", curi->size, "src", 0, GF_AA | ((curi->smode == absw) ? GF_PCM2 : 0),
curi->dmode, "dstreg", curi->size, "dst", 2, GF_AA);
if (curi->smode == Ad8r || curi->smode == PC8r)
addcycles000(2);
// cc false, counter expired: idle cycle, prefetch (from branch address), 2xprefetch (from next address)
// cc false, counter not expired: idle cycle, prefetch
tail_ce020_done = true;
+ if(cpu_level <= 1) {
+ // this is quite annoying instruction..
+ out("int pcadjust = -2;\n");
+ }
genamodedual(curi,
curi->smode, "srcreg", curi->size, "src", 1, GF_AA | (cpu_level < 2 ? GF_NOREFILL : 0),
curi->dmode, "dstreg", curi->size, "offs", 1, GF_AA | (cpu_level < 2 ? GF_NOREFILL : 0));
// read looping instruction opcode
addcycles000_nonce(4);
out("%s(%d);\n", prefetch_word, 0);
- check_prefetch_bus_error(-1, -1);
+ check_prefetch_bus_error(-1, 0, -1);
// read dbcc opcode
addcycles000_nonce(4);
out("%s(%d);\n", prefetch_word, 2);
- check_prefetch_bus_error(-2, -1);
+ check_prefetch_bus_error(-2, 0, -1);
out("regs.irc = irc;\n");
out("} else {\n");
addcycles000(2);
int old_m68k_pc_total = m68k_pc_total;
clear_m68k_offset();
get_prefetch_020_continue();
- fill_prefetch_full_000_special(NULL);
+ fill_prefetch_full_000_special(1, NULL);
returncycles(8);
m68k_pc_offset = old_m68k_pc_offset;
m68k_pc_total = old_m68k_pc_total;
out("}\n");
out("regs.loop_mode = 0;\n");
setpc("oldpc + %d", m68k_pc_offset);
- fill_prefetch_full_000_special(NULL);
+ fill_prefetch_full_000_special(1, NULL);
returncycles(8);
out("}\n");
pop_ins_cnt();
}
+ sprintf(bus_error_code, "pcoffset = oldpc - %s + 4;\n", getpc);
fill_prefetch_1(0);
+ bus_error_code[0] = 0;
if (cpu_level >= 4) {
genastore("(src - 1)", curi->smode, "srcreg", curi->size, "src");
}
out("if(regs.t1) opcode |= 0x10000;\n");
}
out("%s(%d);\n", prefetch_word, 2);
- check_prefetch_bus_error(-2, -1);
+ check_prefetch_bus_error(-2, 0, -1);
did_prefetch = 1;
ir2irc = 0;
count_readw++;
addcycles000_nonce(6);
}
add_head_cycs (10);
+ if (cpu_level <= 1) {
+ out("pcadjust = 0;\n");
+ }
if (cpu_level == 0 && using_ce) {
out("} else {\n");
addcycles000_onlyce(2);
setpc ("oldpc + %d", m68k_pc_offset);
clear_m68k_offset();
get_prefetch_020_continue();
- fill_prefetch_full_000_special("if (!cctrue(%d)) {\nm68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src - 1)) & 0xffff);\n}\n", curi->cc);
+ fill_prefetch_full_000_special(-1, "if (!cctrue(%d)) {\nm68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src - 1)) & 0xffff);\n}\n", curi->cc);
branch_inst = 1;
if (!next_level_040_to_030()) {
if (!next_level_020_to_010())
fill_prefetch_next_after(1,
"CLEAR_CZNV();\n"
"SET_ZFLG(1);\n"
- "m68k_dreg(regs, dstreg) &= 0xffff0000;\n");
+ "pcoffset -= %d;\n"
+ "m68k_dreg(regs, dstreg) &= 0xffff0000;\n",
+ // strange EA behavior, no other instruction work like this
+ curi->smode == Apdi ? 0 : (curi->smode == absl || curi->smode == absw || curi->smode == imm ? 2 : m68k_pc_offset));
out("uae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n");
genflags (flag_logical, sz_long, "newv", "", "");
if (using_ce) {
fill_prefetch_next_after(1,
"CLEAR_CZNV();\n"
"SET_ZFLG(1);\n"
- "m68k_dreg(regs, dstreg) &= 0xffff0000;\n");
+ "pcoffset -= %d;\n"
+ "m68k_dreg(regs, dstreg) &= 0xffff0000;\n",
+ curi->smode == Apdi ? 0 : (curi->smode == absl || curi->smode == absw || curi->smode == imm ? 2 : m68k_pc_offset));
out("uae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n");
genflags (flag_logical, sz_long, "newv", "", "");
if (using_ce) {