return;
printf ("\tregs.irc = %s (0);\n", prefetch_word);
}
+static void get_prefetch_020_continue(void)
+{
+ if (!isprefetch020())
+ return;
+ if (using_ce020)
+ printf("\tcontinue_ce020_prefetch();\n");
+ else
+ printf ("\tcontinue_020_prefetch();\n");
+}
static void returntail (bool iswrite)
{
need_endlabel = 1;
sync_m68k_pc ();
addcycles000 (2);
- get_prefetch_020_0 ();
+ get_prefetch_020_continue ();
if (curi->size == sz_byte) {
irc2ir ();
add_head_cycs (4);
fill_prefetch_full_000 ();
}
insn_n_cycles = curi->size == sz_byte ? 8 : 12;
- if (curi->cc == 0)
- branch_inst = 1;
+ branch_inst = 1;
bccl_not68020:
break;
case i_LEA:
pop_ins_cnt();
setpc ("oldpc + %d", m68k_pc_offset);
clear_m68k_offset();
- get_prefetch_020_0 ();
+ get_prefetch_020_continue ();
fill_prefetch_full_000 ();
insn_n_cycles = 12;
need_endlabel = 1;
+ branch_inst = 1;
break;
case i_Scc:
// confirmed
struct cputbl_tmp
{
uae_s16 length;
- uae_u8 disp020[2];
+ uae_s8 disp020[2];
uae_u8 branch;
};
static struct cputbl_tmp cputbltmp[65536];
if ((opcode & 0xf000) == 0xf000)
m68k_pc_total = -1;
cputbltmp[opcode].length = m68k_pc_total;
- cputbltmp[opcode].disp020[0] = genamode8r_offset[0];
- cputbltmp[opcode].disp020[1] = genamode8r_offset[1];
+
+ cputbltmp[opcode].disp020[0] = 0;
+ if (genamode8r_offset[0] > 0)
+ cputbltmp[opcode].disp020[0] = m68k_pc_total - genamode8r_offset[0] + 2;
+ cputbltmp[opcode].disp020[1] = 0;
+ if (genamode8r_offset[1] > 0)
+ cputbltmp[opcode].disp020[1] = m68k_pc_total - genamode8r_offset[1] + 2;
+
cputbltmp[opcode].branch = branch_inst;
if (generate_stbl) {
struct cputbl_data
{
uae_s16 length;
- uae_u8 disp020[2];
+ uae_s8 disp020[2];
uae_u8 branch;
};
static struct cputbl_data cpudatatbl[65536];
struct cache020 *c;
addr &= ~3;
+ if (regs.cacheholdingaddr020 == addr)
+ return;
index = (addr >> 2) & (CACHELINES020 - 1);
tag = regs.s | (addr & ~((CACHELINES020 << 2) - 1));
c = &caches020[index];
}
#if MORE_ACCURATE_68020_PIPELINE
+#define PIPELINE_DEBUG 0
+#if PIPELINE_DEBUG
+static uae_u16 pipeline_opcode;
+#endif
static void pipeline_020(uae_u16 w, uaecptr pc)
{
- if (regs.pipeline_pos < 0)
- return;
- if (regs.pipeline_pos > 2) {
- regs.pipeline_pos -= 2;
+ if (regs.pipeline_pos < 0)
return;
- }
- if (regs.pipeline_pos == 2) {
- if (regs.pipeline_r8[0]) {
+ if (regs.pipeline_pos > 0) {
+ // handle annoying 68020+ addressing modes
+ if (regs.pipeline_pos == regs.pipeline_r8[0]) {
regs.pipeline_r8[0] = 0;
- // disp 020+ word
if (w & 0x100) {
+ int extra = 0;
if ((w & 0x30) == 0x20)
- regs.pipeline_pos += 2;
+ extra += 2;
if ((w & 0x30) == 0x30)
- regs.pipeline_pos += 4;
+ extra += 4;
if ((w & 0x03) == 0x02)
- regs.pipeline_pos += 2;
+ extra += 2;
if ((w & 0x03) == 0x03)
- regs.pipeline_pos += 4;
+ extra += 4;
+ regs.pipeline_pos += extra;
}
return;
}
- if (regs.pipeline_r8[1]) {
+ if (regs.pipeline_pos == regs.pipeline_r8[1]) {
regs.pipeline_r8[1] = 0;
- // disp 020+ word
if (w & 0x100) {
+ int extra = 0;
if ((w & 0x30) == 0x20)
- regs.pipeline_pos += 2;
+ extra += 2;
if ((w & 0x30) == 0x30)
- regs.pipeline_pos += 4;
+ extra += 4;
if ((w & 0x03) == 0x02)
- regs.pipeline_pos += 2;
+ extra += 2;
if ((w & 0x03) == 0x03)
- regs.pipeline_pos += 4;
+ extra += 4;
+ regs.pipeline_pos += extra;
}
return;
}
}
+ if (regs.pipeline_pos > 2) {
+ regs.pipeline_pos -= 2;
+ // If stop set, prefetches stop 1 word early.
+ if (regs.pipeline_stop > 0 && regs.pipeline_pos == 2)
+ regs.pipeline_stop = -1;
+ return;
+ }
if (regs.pipeline_stop) {
regs.pipeline_stop = -1;
return;
}
- regs.pipeline_r8[0] = cpudatatbl[w].disp020[0] != 0;
- regs.pipeline_r8[1] = cpudatatbl[w].disp020[1] != 0;
+#if PIPELINE_DEBUG
+ pipeline_opcode = w;
+#endif
+ regs.pipeline_r8[0] = cpudatatbl[w].disp020[0];
+ regs.pipeline_r8[1] = cpudatatbl[w].disp020[1];
regs.pipeline_pos = cpudatatbl[w].length;
-#if 0
+#if PIPELINE_DEBUG
if (!regs.pipeline_pos) {
write_log(_T("Opcode %04x has no size PC=%08x!\n"), w, pc);
}
if (regs.pipeline_pos > 0 && branch) {
// Short branches (Bcc.s) still do one more prefetch.
// RTS and other unconditional single opcode instruction stop immediately.
- regs.pipeline_pos -= 1 * 2;
- if (branch == 2)
- regs.pipeline_stop = -1; // immediate stop
- else
+ if (branch == 2) {
+ // Immediate stop
+ regs.pipeline_stop = -1;
+ } else {
+ // Stop 1 word early than normally
regs.pipeline_stop = 1;
+ }
}
}
+
+// Not exactly right, requires logic analyzer checks.
+void continue_ce020_prefetch(void)
+{
+ fill_prefetch_020();
+}
+void continue_020_prefetch(void)
+{
+ fill_prefetch_020();
+}
#endif
uae_u32 get_word_ce020_prefetch (int o)
struct cache030 *c;
addr &= ~3;
+ if (regs.cacheholdingaddr020 == addr)
+ return;
c = getcache030 (icaches030, addr, &tag, &lws);
if (c->valid[lws] && c->tag == tag) {
// cache hit
uae_u32 (*fetch)(uaecptr) = currprefs.cpu_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi;
regs.pipeline_pos = 0;
regs.pipeline_stop = 0;
+ regs.pipeline_r8[0] = regs.pipeline_r8[1] = -1;
fill_icache020 (pc, fetch);
if (currprefs.cpu_cycle_exact)