static char rmw_varname[100];
static struct instr *g_instr;
static char g_srcname[100];
+static int loopmode;
#define GENA_GETV_NO_FETCH 0
#define GENA_GETV_FETCH 1
check_prefetch_bus_error(o, 0);
}
+static void loopmode_begin(void)
+{
+ if (loopmode) {
+ printf("\tif(!regs.loop_mode) {\n");
+ printf("\t\tregs.ird = opcode;\n");
+ }
+}
+static void loopmode_end(void)
+{
+ if (loopmode) {
+ printf("\t} else {\n");
+ addcycles000(2);
+ printf("\t}\n");
+ }
+}
+
static void fill_prefetch_next_noopcodecopy(const char *format, ...)
{
if (using_prefetch) {
+ loopmode_begin();
irc2ir();
if (using_bus_error) {
bus_error_code[0] = 0;
if (using_bus_error) {
copy_opcode();
}
+ loopmode_end();
}
}
static void fill_prefetch_next(void)
{
if (using_prefetch) {
+ loopmode_begin();
irc2ir();
if (using_bus_error) {
copy_opcode();
}
fill_prefetch_1(m68k_pc_offset + 2);
+ loopmode_end();
}
}
static void fill_prefetch_next_t(void)
{
if (using_prefetch) {
+ loopmode_begin();
irc2ir();
if (using_bus_error) {
copy_opcode();
strcat(bus_error_code, "\t\tif (regs.t1) opcode |= 0x10000;\n");
}
fill_prefetch_1(m68k_pc_offset + 2);
+ loopmode_end();
}
}
static void fill_prefetch_next_extra(const char *cond, const char *format, ...)
{
if (using_prefetch) {
+ loopmode_begin();
irc2ir();
if (using_bus_error) {
if (cond)
}
}
fill_prefetch_1(m68k_pc_offset + 2);
+ loopmode_end();
}
}
static void fill_prefetch_next_after(int copy, const char *format, ...)
{
if (using_prefetch) {
+ loopmode_begin();
irc2ir();
printf("\topcode |= 0x20000;\n");
bus_error_code[0] = 0;
opcode_nextcopy = 1;
}
}
+ loopmode_end();
}
}
if (mode == Apdi && g_instr->size == sz_word && g_instr->mnemo != i_CLR) {
printf("\t\tm68k_areg(regs, %s) = %sa;\n", reg, name);
}
+ if (mode == Apdi) {
+ ;// printf("\t\tregs.read_buffer = 0;\n");
+ }
}
if (g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) {
dstblrmw = NULL;
dstwlrmw = NULL;
dstllrmw = NULL;
- getpc = "m68k_getpc ()";
+ getpc = "m68k_getpc()";
if (using_indirect > 0) {
// tracer
- getpc = "m68k_getpci ()";
+ getpc = "m68k_getpci()";
if (using_mmu == 68030) {
// 68030 cache MMU / CE cache MMU
disp020 = "get_disp_ea_020_mmu030c";
srcwd = "get_word_mmu030c";
dstld = "put_long_mmu030c";
dstwd = "put_word_mmu030c";
- getpc = "m68k_getpci ()";
+ getpc = "m68k_getpci()";
} else if (!using_ce020 && !using_prefetch_020 && !using_ce) {
// generic + indirect
disp020 = "x_get_disp_ea_020";
srcwd = "get_word_mmu030";
dstld = "put_long_mmu030";
dstwd = "put_word_mmu030";
- getpc = "m68k_getpci ()";
+ getpc = "m68k_getpci()";
} else if (using_mmu == 68040) {
// 68040 MMU
disp020 = "x_get_disp_ea_020";
dstblrmw = "put_lrmw_byte_mmu040";
dstwlrmw = "put_lrmw_word_mmu040";
dstllrmw = "put_lrmw_long_mmu040";
- getpc = "m68k_getpci ()";
+ getpc = "m68k_getpci()";
} else if (using_mmu) {
// 68060 MMU
disp020 = "x_get_disp_ea_020";
dstbrmw = "put_rmw_byte_mmu060";
dstwrmw = "put_rmw_word_mmu060";
dstlrmw = "put_rmw_long_mmu060";
- getpc = "m68k_getpci ()";
+ getpc = "m68k_getpci()";
} else if (using_ce) {
// 68000 ce
prefetch_word = "get_word_ce000_prefetch";
srcb = "get_byte_ce000";
dstb = "put_byte_ce000";
do_cycles = "do_cycles_ce000";
- getpc = "m68k_getpci ()";
+ getpc = "m68k_getpci()";
} else if (using_prefetch) {
// 68000 prefetch
prefetch_word = "get_word_000_prefetch";
dstw = "put_word_000";
srcb = "get_byte_000";
dstb = "put_byte_000";
- getpc = "m68k_getpci ()";
+ getpc = "m68k_getpci()";
} else {
// generic + direct
prefetch_long = "get_dilong";
bus_error_code2[0] = 0;
opcode_nextcopy = 0;
+ loopmode = 0;
+ // 68010 loop mode available if
+ if (cpu_level == 1) {
+ loopmode = opcode_loop_mode(opcode);
+ if (curi->mnemo == i_DBcc || loopmode) {
+ next_level_000();
+ }
+ }
+
// do not unnecessarily create useless mmuop030
// functions when CPU is not 68030
if (curi->mnemo == i_MMUOP030 && cpu_level != 3 && !cpu_generic) {
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));
+ if (cpu_level == 1) {
+ printf("\tregs.loop_mode = false;\n");
+ }
printf("\tuaecptr oldpc = %s;\n", getpc);
addcycles000 (2);
if (using_exception_3 && cpu_level >= 4) {
write_return_cycles("\t\t", 0);
printf("\t\t}\n");
}
+ // 68010 loop mode handling
+ if (cpu_level == 1) {
+ printf("\t\tif(offs == -4 && !regs.t1 && loop_mode_table[regs.ird]) {\n");
+ printf("\t\t\tregs.loop_mode = true;\n");
+ printf("\t\t\tsrc = m68k_dreg(regs, srcreg);\n");
+ genastore("(src - 1)", curi->smode, "srcreg", curi->size, "src");
+ addcycles000(2);
+ printf("\t\t\tif (src) {\n");
+ if (using_ce) {
+ printf("\t\t\t\tloop_mode_table[regs.ird](regs.ird);\n");
+ } else {
+ printf("\t\t\t\tcount_cycles += loop_mode_table[regs.ird](regs.ird);\n");
+ }
+ setpc("oldpc");
+ check_ipl();
+ addcycles000(2);
+ returncycles("\t\t\t\t", 4);
+ printf("\t\t\t} else {\n");
+ addcycles000(2);
+ printf("\t\t\t}\n");
+ printf("\t\t\tregs.loop_mode = false;\n");
+ setpc("oldpc + %d", m68k_pc_offset);
+ fill_prefetch_full_000_special();
+ returncycles("\t\t\t", 6);
+ printf("\t\t}\n");
+ }
+
printf("\t");
fill_prefetch_1(0);
printf("\t");
struct mnemolookup lookuptab[] = {
{ i_ILLG, _T("ILLEGAL"), NULL, 0 },
- { i_OR, _T("OR"), NULL, 1 },
+ { i_OR, _T("OR"), NULL, 1 | 2 },
{ i_CHK, _T("CHK"), NULL, 0 },
{ i_CHK2, _T("CHK2"), NULL, 0 },
- { i_AND, _T("AND"), NULL, 1 },
- { i_EOR, _T("EOR"), NULL, 1 },
+ { i_AND, _T("AND"), NULL, 1 | 2 },
+ { i_EOR, _T("EOR"), NULL, 1 | 2 },
{ i_ORSR, _T("ORSR"), _T("OR"), 0 },
{ i_ANDSR, _T("ANDSR"), _T("AND"), 0 },
{ i_EORSR, _T("EORSR"), _T("EOR"), 0 },
- { i_SUB, _T("SUB"), NULL, 1 },
- { i_SUBA, _T("SUBA"), NULL, 1 },
- { i_SUBX, _T("SUBX"), NULL, 0 },
- { i_SBCD, _T("SBCD"), NULL, 0 },
- { i_ADD, _T("ADD"), NULL, 1 },
- { i_ADDA, _T("ADDA"), NULL, 1 },
- { i_ADDX, _T("ADDX"), NULL, 0 },
- { i_ABCD, _T("ABCD"), NULL, 0 },
- { i_NEG, _T("NEG"), NULL, 1 },
- { i_NEGX, _T("NEGX"), NULL, 1 },
- { i_NBCD, _T("NBCD"), NULL, 0 },
- { i_CLR, _T("CLR"), NULL, 1 },
- { i_NOT, _T("NOT"), NULL, 1 },
- { i_TST, _T("TST"), NULL, 1 },
+ { i_SUB, _T("SUB"), NULL, 1 | 2 },
+ { i_SUBA, _T("SUBA"), NULL, 1 | 2 },
+ { i_SUBX, _T("SUBX"), NULL, 0 | 2 },
+ { i_SBCD, _T("SBCD"), NULL, 0 | 2 },
+ { i_ADD, _T("ADD"), NULL, 1 | 2 },
+ { i_ADDA, _T("ADDA"), NULL, 1 | 2 },
+ { i_ADDX, _T("ADDX"), NULL, 0 | 2 },
+ { i_ABCD, _T("ABCD"), NULL, 0 | 2 },
+ { i_NEG, _T("NEG"), NULL, 1 | 2 },
+ { i_NEGX, _T("NEGX"), NULL, 1 | 2 },
+ { i_NBCD, _T("NBCD"), NULL, 0 | 2 },
+ { i_CLR, _T("CLR"), NULL, 1 | 2 },
+ { i_NOT, _T("NOT"), NULL, 1 | 2 },
+ { i_TST, _T("TST"), NULL, 1 | 2 },
{ i_BTST, _T("BTST"), NULL, 1 },
{ i_BCHG, _T("BCHG"), NULL, 1 },
{ i_BCLR, _T("BCLR"), NULL, 1 },
{ i_BSET, _T("BSET"), NULL, 1 },
- { i_CMP, _T("CMP"), NULL, 1 },
- { i_CMPM, _T("CMPM"), NULL, 1 },
- { i_CMPA, _T("CMPA"), NULL, 1 },
+ { i_CMP, _T("CMP"), NULL, 1 | 2 },
+ { i_CMPM, _T("CMPM"), NULL, 1 | 2 },
+ { i_CMPA, _T("CMPA"), NULL, 1 | 2 },
{ i_MVPRM, _T("MVPRM"), _T("MOVEP"), 0 },
{ i_MVPMR, _T("MVPMR"), _T("MOVEP"), 0 },
- { i_MOVE, _T("MOVE"), NULL, 1 },
- { i_MOVEA, _T("MOVEA"), NULL, 1 },
+ { i_MOVE, _T("MOVE"), NULL, 1 | 2 },
+ { i_MOVEA, _T("MOVEA"), NULL, 1 | 2 },
{ i_MVSR2, _T("MVSR2"), _T("MOVE"), 0 },
{ i_MV2SR, _T("MV2SR"), _T("MOVE"), 0 },
{ i_SWAP, _T("SWAP"), NULL, 0 },
{ i_ROR, _T("ROR"), NULL, 0 },
{ i_ROXL, _T("ROXL"), NULL, 1 },
{ i_ROXR, _T("ROXR"), NULL, 1 },
- { i_ASRW, _T("ASRW"), _T("ASR"), 1 },
- { i_ASLW, _T("ASLW"), _T("ASL"), 1 },
- { i_LSRW, _T("LSRW"), _T("LSR"), 1 },
- { i_LSLW, _T("LSLW"), _T("LSL"), 1 },
- { i_ROLW, _T("ROLW"), _T("ROL"), 1 },
- { i_RORW, _T("RORW"), _T("ROR"), 1 },
- { i_ROXLW, _T("ROXLW"), _T("ROXL"), 1 },
- { i_ROXRW, _T("ROXRW"), _T("ROXR"), 1 },
+ { i_ASRW, _T("ASRW"), _T("ASR"), 1 | 2 },
+ { i_ASLW, _T("ASLW"), _T("ASL"), 1 | 2 },
+ { i_LSRW, _T("LSRW"), _T("LSR"), 1 | 2 },
+ { i_LSLW, _T("LSLW"), _T("LSL"), 1 | 2 },
+ { i_ROLW, _T("ROLW"), _T("ROL"), 1 | 2 },
+ { i_RORW, _T("RORW"), _T("ROR"), 1 | 2 },
+ { i_ROXLW, _T("ROXLW"), _T("ROXL"), 1 | 2 },
+ { i_ROXRW, _T("ROXRW"), _T("ROXR"), 1 | 2 },
{ i_MOVE2C, _T("MOVE2C"), _T("MOVEC"), 0 },
{ i_MOVEC2, _T("MOVEC2"), _T("MOVEC"), 0 },
{
return imismatch;
}
+
+static int isreg(amodes mode)
+{
+ if (mode == Dreg || mode == Areg)
+ return 1;
+ return 0;
+}
+
+bool opcode_loop_mode(uae_u16 opcode)
+{
+ instr *c = &table68k[opcode];
+ bool loopmode = false;
+ int i;
+ for (i = 0; lookuptab[i].name[0]; i++) {
+ if (c->mnemo == lookuptab[i].mnemo)
+ break;
+ }
+ if (lookuptab[i].flags & 2) {
+ // Source is Dn,An,(An),(An)+,-(An)
+ // Destination is Dn,An,(An),(An)+,-(An)
+ // Both source and destination must not be Dn or An.
+ // RMW instruction must not be Dn or An
+ if (((isreg(c->smode) || c->smode == Aind || c->smode == Apdi || c->smode == Aipi)) &&
+ ((!c->duse && !isreg(c->smode)) || (c->duse && (isreg(c->dmode) || c->dmode == Aind || c->dmode == Apdi || c->dmode == Aipi))) &&
+ (!c->duse || (isreg(c->smode) && !isreg(c->dmode)) || (!isreg(c->smode) && isreg(c->dmode)) || (!isreg(c->smode) && !isreg(c->dmode)))) {
+ loopmode = true;
+ }
+ if (c->mnemo == i_MOVE && isreg(c->dmode)) {
+ loopmode = false;
+ }
+ }
+ return loopmode;
+}