else
c_hpos += 2;
- if (cop_state.strobe) {
- if (cop_state.strobe > 0)
- cop_state.ip = cop_state.strobe == 1 ? cop1lc : cop2lc;
- cop_state.strobe = 0;
- }
-
switch (cop_state.state)
{
case COP_wait_in2:
if (debug_dma)
record_dma (0x8c, chipmem_agnus_wget (cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
#endif
+ cop_state.ip += 2;
break;
case COP_strobe_delay2:
// second cycle after COPJMP is like second read cycle except
cop_state.state = COP_read1;
alloc_cycle (old_hpos, CYCLE_COPPER);
if (debug_dma)
- record_dma (0x1fe, chipmem_agnus_wget (cop_state.ip + 2), cop_state.ip + 2, old_hpos, vpos, DMARECORD_COPPER);
+ record_dma (0x1fe, chipmem_agnus_wget (cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
+ // next cycle finally reads from new pointer
+ if (cop_state.strobe == 1)
+ cop_state.ip = cop1lc;
+ else
+ cop_state.ip = cop2lc;
+ cop_state.strobe = 0;
break;
case COP_start_delay:
if (copper_cant_read (old_hpos, 1))
alloc_cycle (old_hpos, CYCLE_COPPER);
if (debug_dma)
record_dma (0x1fe, 0, 0xffffffff, old_hpos, vpos, DMARECORD_COPPER);
+ cop_state.ip = cop1lc;
break;
case COP_read1:
cop_state.last_write = reg;
cop_state.last_write_hpos = old_hpos;
if (reg == 0x88) {
- cop_state.ip = cop1lc;
+ cop_state.strobe = 1;
cop_state.state = COP_strobe_delay1;
- } else if (reg == 0x8A) {
- cop_state.ip = cop2lc;
+ } else if (reg == 0x8a) {
+ cop_state.strobe = 2;
cop_state.state = COP_strobe_delay1;
} else {
// FIX: all copper writes happen 1 cycle later than CPU writes
// at least 4 cycles (all DMA cycles count, not just blitter cycles, even
// blitter idle cycles do count!)
-STATIC_INLINE int dma_cycle (int *waited)
+STATIC_INLINE int dma_cycle (void)
{
int hpos, hpos_old;
blitter_nasty = 1;
- *waited = 0;
for (;;) {
int bpldma;
int blitpri = dmacon & DMA_BLITPRI;
alloc_cycle (hpos_old, CYCLE_CPU);
break;
}
- *waited = 1;
regs.ce020memcycles -= CYCLE_UNIT;
do_cycles (1 * CYCLE_UNIT);
/* bus was allocated to dma channel, wait for next cycle.. */
uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode)
{
uae_u32 v = 0;
- int hpos, waited;
+ int hpos;
struct dma_rec *dr;
- hpos = dma_cycle (&waited);
- if (waited)
- do_cycles_ce (CYCLE_UNIT);
+ hpos = dma_cycle ();
+ do_cycles_ce (CYCLE_UNIT);
#ifdef DEBUGGER
if (debug_dma) {
- dr = record_dma (0x1000, v, addr, hpos, vpos, DMARECORD_CPU);
+ int reg = 0x1000;
+ if (mode < 0)
+ reg |= 4;
+ else if (mode > 0)
+ reg |= 2;
+ else
+ reg |= 1;
+ dr = record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU);
checknasty (hpos, vpos);
}
#endif
dr->dat = v;
#endif
- if (!waited)
- do_cycles_ce (2 * CYCLE_UNIT);
- else
- do_cycles_ce (CYCLE_UNIT);
- regs.ce020memcycles -= 2 * CYCLE_UNIT;
+ do_cycles_ce (CYCLE_UNIT);
return v;
}
uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode)
{
- return wait_cpu_cycle_read (addr, mode);
+ uae_u32 v = 0;
+ int hpos;
+ struct dma_rec *dr;
+
+ hpos = dma_cycle ();
+ do_cycles_ce (CYCLE_UNIT);
+
+#ifdef DEBUGGER
+ if (debug_dma) {
+ int reg = 0x1000;
+ if (mode < 0)
+ reg |= 4;
+ else if (mode > 0)
+ reg |= 2;
+ else
+ reg |= 1;
+ dr = record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU);
+ checknasty (hpos, vpos);
+ }
+#endif
+ if (mode < 0)
+ v = get_long (addr);
+ else if (mode > 0)
+ v = get_word (addr);
+ else if (mode == 0)
+ v = get_byte (addr);
+
+#ifdef DEBUGGER
+ if (debug_dma)
+ dr->dat = v;
+#endif
+
+ regs.ce020memcycles -= CYCLE_UNIT;
+ return v;
}
void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v)
{
int hpos;
- int waited;
- hpos = dma_cycle (&waited);
- if (waited)
- do_cycles_ce (CYCLE_UNIT);
+ hpos = dma_cycle ();
+ do_cycles_ce (CYCLE_UNIT);
#ifdef DEBUGGER
if (debug_dma) {
- record_dma (0x1001, v, addr, hpos, vpos, DMARECORD_CPU);
+ int reg = 0x1100;
+ if (mode < 0)
+ reg |= 4;
+ else if (mode > 0)
+ reg |= 2;
+ else
+ reg |= 1;
+ record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU);
checknasty (hpos, vpos);
}
#endif
put_word (addr, v);
else if (mode == 0)
put_byte (addr, v);
- if (!waited)
- do_cycles_ce (2 * CYCLE_UNIT);
- else
- do_cycles_ce (CYCLE_UNIT);
- regs.ce020memcycles -= 2 * CYCLE_UNIT;
+ do_cycles_ce (CYCLE_UNIT);
}
void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v)
{
- wait_cpu_cycle_write (addr, mode, v);
+ int hpos;
+
+ hpos = dma_cycle ();
+ do_cycles_ce (CYCLE_UNIT);
+
+#ifdef DEBUGGER
+ if (debug_dma) {
+ int reg = 0x1100;
+ if (mode < 0)
+ reg |= 4;
+ else if (mode > 0)
+ reg |= 2;
+ else
+ reg |= 1;
+ record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU);
+ checknasty (hpos, vpos);
+ }
+#endif
+
+ if (mode < 0)
+ put_long (addr, v);
+ else if (mode > 0)
+ put_word (addr, v);
+ else if (mode == 0)
+ put_byte (addr, v);
+
+ regs.ce020memcycles -= CYCLE_UNIT;
}
void do_cycles_ce (long cycles)
#define GF_NOREFILL 8
#define GF_PREFETCH 16
#define GF_FC 32
+#define GF_MOVE 64
/* For the current opcode, the next lower level that will have different code.
* Initialized to -1 for each opcode. If it remains unchanged, indicates we
return 0;
}
-static void gen_nextilong (char *type, char *name, int norefill)
+static void gen_nextilong (char *type, char *name, int flags)
{
int r = m68k_pc_offset;
m68k_pc_offset += 4;
} else if (using_ce) {
printf ("\t%s %s;\n", type, name);
/* we must do this because execution order of (something | something2) is not defined */
- if (norefill) {
+ if (flags & GF_NOREFILL) {
printf ("\t%s = get_word_ce_prefetch (%d) << 16;\n", name, r + 2);
count_read++;
printf ("\t%s |= regs.irc;\n", name);
}
} else {
if (using_prefetch) {
- if (norefill) {
+ if (flags & GF_NOREFILL) {
printf ("\t%s %s;\n", type, name);
printf ("\t%s = get_word_prefetch (%d) << 16;\n", name, r + 2);
count_read++;
}
}
-static const char *gen_nextiword (int norefill)
+static const char *gen_nextiword (int flags)
{
static char buffer[80];
int r = m68k_pc_offset;
sprintf (buffer, "get_word_ce020_prefetch (%d)", r);
count_read++;
} else if (using_ce) {
- if (norefill) {
+ if (flags & GF_NOREFILL) {
strcpy (buffer, "regs.irc");
} else {
sprintf (buffer, "get_word_ce_prefetch (%d)", r + 2);
}
} else {
if (using_prefetch) {
- if (norefill) {
+ if (flags & GF_NOREFILL) {
sprintf (buffer, "regs.irc", r);
} else {
sprintf (buffer, "get_word_prefetch (%d)", r + 2);
return buffer;
}
-static const char *gen_nextibyte (int norefill)
+static const char *gen_nextibyte (int flags)
{
static char buffer[80];
int r = m68k_pc_offset;
sprintf (buffer, "(uae_u8)get_word_ce020_prefetch (%d)", r);
count_read++;
} else if (using_ce) {
- if (norefill) {
+ if (flags & GF_NOREFILL) {
strcpy (buffer, "(uae_u8)regs.irc");
} else {
sprintf (buffer, "(uae_u8)get_word_ce_prefetch (%d)", r + 2);
} else {
insn_n_cycles += 4;
if (using_prefetch) {
- if (norefill) {
+ if (flags & GF_NOREFILL) {
sprintf (buffer, "(uae_u8)regs.irc", r);
} else {
sprintf (buffer, "(uae_u8)get_word_prefetch (%d)", r + 2);
m68k_pc_offset = 0;
}
+static void syncmovepc (int getv, int flags)
+{
+#if 0
+ if (!(flags & GF_MOVE))
+ return;
+ if (getv == 1) {
+ sync_m68k_pc ();
+ //fill_prefetch_next ();
+ }
+#endif
+}
+
/* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0,
* the calling routine handles Apdi and Aipi modes.
* gb-- movem == 2 means the same thing but for a MOVE16 instruction */
* side effect in case a bus fault is generated by any memory access.
* XJ - 2006/11/13 */
-static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int flags, int fixup, int e3fudge)
+static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int flags, int fixup)
{
char namea[100];
int m68k_pc_offset_last = m68k_pc_offset;
default:
abort ();
}
+ syncmovepc (getv, flags);
return;
case Areg:
if (movem)
default:
abort ();
}
+ syncmovepc (getv, flags);
return;
case Aind: // (An)
printf ("\tuaecptr %sa = m68k_areg (regs, %s);\n", name, reg);
}
break;
case Ad16: // (d16,An)
- printf ("\tuaecptr %sa = m68k_areg (regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword (flags & GF_NOREFILL));
+ printf ("\tuaecptr %sa = m68k_areg (regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword (flags));
count_read_ea++;
break;
case Ad8r: // (d8,An,Xn)
else
printf ("\t%sa = get_disp_ea_020 (m68k_areg (regs, %s), next_iword ());\n", name, reg);
} else {
- printf ("\t%sa = get_disp_ea_000 (m68k_areg (regs, %s), %s);\n", name, reg, gen_nextiword (flags & GF_NOREFILL));
+ if (!(flags & GF_AD8R)) {
+ addcycles000 (2);
+ insn_n_cycles += 2;
+ count_cycles_ea += 2;
+ }
+ printf ("\t%sa = get_disp_ea_000 (m68k_areg (regs, %s), %s);\n", name, reg, gen_nextiword (flags));
count_read_ea++;
}
- if (!(flags & GF_AD8R)) {
- addcycles000 (2);
- insn_n_cycles += 2;
- count_cycles_ea += 2;
- }
break;
case PC16: // (d16,PC,Xn)
printf ("\tuaecptr %sa = m68k_getpc () + %d;\n", name, m68k_pc_offset);
- printf ("\t%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags & GF_NOREFILL));
+ printf ("\t%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags));
break;
case PC8r: // (d8,PC,Xn)
printf ("\tuaecptr tmppc;\n");
printf ("\t%sa = get_disp_ea_020 (tmppc, next_iword ());\n", name);
} else {
printf ("\ttmppc = m68k_getpc () + %d;\n", m68k_pc_offset);
- printf ("\t%sa = get_disp_ea_000 (tmppc, %s);\n", name, gen_nextiword (flags & GF_NOREFILL));
- }
- if (!(flags & GF_PC8R)) {
- addcycles000 (2);
- insn_n_cycles += 2;
- count_cycles_ea += 2;
+ if (!(flags & GF_PC8R)) {
+ addcycles000 (2);
+ insn_n_cycles += 2;
+ count_cycles_ea += 2;
+ }
+ printf ("\t%sa = get_disp_ea_000 (tmppc, %s);\n", name, gen_nextiword (flags));
}
break;
case absw:
- printf ("\tuaecptr %sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags & GF_NOREFILL));
+ printf ("\tuaecptr %sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags));
break;
case absl:
- gen_nextilong ("uaecptr", namea, flags & GF_NOREFILL);
+ gen_nextilong ("uaecptr", namea, flags);
count_read_ea += 2;
break;
case imm:
insn_n_cycles020++;
switch (size) {
case sz_byte:
- printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte (flags & GF_NOREFILL));
+ printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte (flags));
count_read_ea++;
break;
case sz_word:
- printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword (flags & GF_NOREFILL));
+ printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword (flags));
count_read_ea++;
break;
case sz_long:
- gen_nextilong ("uae_s32", name, flags & GF_NOREFILL);
+ gen_nextilong ("uae_s32", name, flags);
count_read_ea += 2;
break;
default:
abort ();
}
+ syncmovepc (getv, flags);
return;
case imm0:
if (getv != 1)
abort ();
- printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte (flags & GF_NOREFILL));
+ printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte (flags));
count_read_ea++;
+ syncmovepc (getv, flags);
return;
case imm1:
if (getv != 1)
abort ();
- printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword (flags & GF_NOREFILL));
+ printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword (flags));
count_read_ea++;
+ syncmovepc (getv, flags);
return;
case imm2:
if (getv != 1)
abort ();
- gen_nextilong ("uae_s32", name, flags & GF_NOREFILL);
+ gen_nextilong ("uae_s32", name, flags);
count_read_ea += 2;
+ syncmovepc (getv, flags);
return;
case immi:
if (getv != 1)
abort ();
printf ("\tuae_u32 %s = %s;\n", name, reg);
+ syncmovepc (getv, flags);
return;
default:
abort ();
}
+ syncmovepc (getv, flags);
+
/* We get here for all non-reg non-immediate addressing modes to
* actually fetch the value. */
if ((using_prefetch || using_ce) && using_exception_3 && getv != 0 && size != sz_byte) {
+ int offset = 0;
+ if (flags & GF_MOVE)
+ offset = m68k_pc_offset;
+ else
+ offset = m68k_pc_offset_last;
printf ("\tif (%sa & 1) {\n", name);
printf ("\t\texception3 (opcode, m68k_getpc () + %d, %sa);\n",
- m68k_pc_offset_last + e3fudge, name);
+ offset, name);
printf ("\t\tgoto %s;\n", endlabelstr);
printf ("\t}\n");
need_endlabel = 1;
static void genamode_fixup (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int flags, int fixup)
{
if (fixup != 2) {
- genamode2 (mode, reg, size, name, getv, movem, flags, fixup, 0);
+ genamode2 (mode, reg, size, name, getv, movem, flags, fixup);
} else {
if (!movem) {
switch (mode)
static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int flags)
{
- genamode2 (mode, reg, size, name, getv, movem, flags, 0, 0);
+ genamode2 (mode, reg, size, name, getv, movem, flags, 0);
}
static void genamode_pre (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int flags)
{
if (using_mmu)
genamode_fixup (mode, reg, size, name, getv, movem, flags, 2);
}
-static void genamode_e3 (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int flags, int e3fudge)
-{
- genamode2 (mode, reg, size, name, getv, movem, flags, 0, e3fudge);
-}
static void genastore_2 (char *from, amodes mode, char *reg, wordsizes size, char *to, int store_dir, int flags)
{
if (curi->smode == imm || curi->smode == Dreg)
c += 2;
}
+ fill_prefetch_next ();
if (c > 0)
addcycles000 (c);
- fill_prefetch_next ();
- genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
+ genastore_rev ("src", curi->dmode, "dstreg", curi->size, "dst");
break;
}
case i_ORSR:
printf ("\tMakeFromSR ();\n");
break;
case i_SUB:
+ {
+ int c = 0;
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
if (curi->dmode == Dreg) {
- int c = 0;
if (curi->size == sz_long) {
c += 2;
if (curi->smode == imm || curi->smode == immi || curi->smode == Dreg)
c += 2;
}
- if (c > 0)
- addcycles000 (c);
}
fill_prefetch_next ();
+ if (c > 0)
+ addcycles000 (c);
start_brace ();
genflags (flag_sub, curi->size, "newv", "src", "dst");
- genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+ genastore_rev ("newv", curi->dmode, "dstreg", curi->size, "dst");
break;
+ }
case i_SUBA:
+ {
+ int c = 0;
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0);
if (curi->smode == immi) {
- int c = 4;
- if (c > 0)
- addcycles000 (c);
+ c = 4;
} else {
- int c = curi->size == sz_long ? 2 : 4;
+ c = curi->size == sz_long ? 2 : 4;
if (islongimm (curi))
c += 2;
- if (c > 0)
- addcycles000 (c);
}
fill_prefetch_next ();
+ if (c > 0)
+ addcycles000 (c);
start_brace ();
printf ("\tuae_u32 newv = dst - src;\n");
genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
break;
+ }
case i_SUBX:
genamode_pre (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA);
genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
break;
case i_ADD:
+ {
+ int c = 0;
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
if (curi->dmode == Dreg) {
- int c = 0;
if (curi->size == sz_long) {
c += 2;
if (curi->smode == imm || curi->smode == immi || curi->smode == Dreg)
c += 2;
}
- if (c > 0)
- addcycles000 (c);
}
fill_prefetch_next ();
+ if (c > 0)
+ addcycles000 (c);
start_brace ();
genflags (flag_add, curi->size, "newv", "src", "dst");
- genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+ genastore_rev ("newv", curi->dmode, "dstreg", curi->size, "dst");
break;
+ }
case i_ADDA:
+ {
+ int c = 0;
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0);
if (curi->smode == immi) {
- int c = curi->size == sz_long ? 4 : 0;
- if (islongimm (curi))
- c += 2;
- if (c > 0)
- addcycles000 (c);
+ c += 4;
} else {
- int c = curi->size == sz_long ? 2 : 4;
+ c = curi->size == sz_long ? 2 : 4;
if (islongimm (curi))
c += 2;
- if (c > 0)
- addcycles000 (c);
}
fill_prefetch_next ();
+ if (c > 0)
+ addcycles000 (c);
start_brace ();
printf ("\tuae_u32 newv = dst + src;\n");
genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
break;
+ }
case i_ADDX:
genamode_pre (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA);
case i_CMP:
genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
+ fill_prefetch_next ();
if (curi->dmode == Dreg && curi->size == sz_long)
addcycles000 (2);
- fill_prefetch_next ();
start_brace ();
genflags (flag_cmp, curi->size, "newv", "src", "dst");
break;
case i_MOVE:
case i_MOVEA:
{
- /* 2 MOVE instructions have special prefetch sequence:
+ /* 2 MOVE instruction variants have special prefetch sequence:
* - MOVE <ea>,-(An) = prefetch is before writes (Apdi)
- * - MOVE memory,(xxx).L, the most stupid ever. 2 prefetches after write
+ * - MOVE memory,(xxx).L = 2 prefetches after write
* - all others = prefetch is done after writes
*
* - move.x xxx,[at least 1 extension word here] = fetch 1 extension word before (xxx)
+ *
+ * - current theory: moves are build from 3 separate microcode subroutines, fetch, move and write
*/
int prefetch_done = 0, flags;
int dualprefetch = curi->dmode == absl && (curi->smode != Dreg && curi->smode != Areg && curi->smode != imm);
- genamode_pre (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+ genamode_pre (curi->smode, "srcreg", curi->size, "src", 1, 0, GF_MOVE);
flags = 1 | (dualprefetch ? GF_NOREFILL : 0);
- /* MOVE.L dx,(ax) exception3 PC points to next instruction. hackhackhack */
- genamode_e3 (curi->dmode, "dstreg", curi->size, "dst", 2, 0, flags, curi->smode == Dreg && curi->dmode == Aind ? 2 : 0);
+ genamode2 (curi->dmode, "dstreg", curi->size, "dst", 2, 0, flags, 0);
genamode_post (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
if (curi->mnemo == i_MOVEA && curi->size == sz_word)
printf ("\tsrc = (uae_s32)(uae_s16)src;\n");