diff --git a/BasiliskII/src/uae_cpu/basilisk_glue.cpp b/BasiliskII/src/uae_cpu/basilisk_glue.cpp index d70b344e..1b6e6c21 100644 --- a/BasiliskII/src/uae_cpu/basilisk_glue.cpp +++ b/BasiliskII/src/uae_cpu/basilisk_glue.cpp @@ -65,7 +65,7 @@ bool Init680x0(void) ROMBaseMac = (uint32)ROMBaseHost; #elif DIRECT_ADDRESSING // Mac address space = host address space minus constant offset (MEMBaseDiff) - // NOTE: MEMBaseDiff is set in main_unix.cpp/main() + // NOTE: MEMBaseDiff is set up in main_unix.cpp/main() RAMBaseMac = 0; ROMBaseMac = Host2MacAddr(ROMBaseHost); #else @@ -122,7 +122,7 @@ void InitFrameBufferMapping(void) void Start680x0(void) { m68k_reset(); - m68k_go(true); + m68k_execute(); } @@ -132,7 +132,7 @@ void Start680x0(void) void TriggerInterrupt(void) { - regs.spcflags |= SPCFLAG_INT; + SPCFLAGS_SET( SPCFLAG_INT ); } void TriggerNMI(void) @@ -179,7 +179,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r) m68k_setpc(m68k_areg(regs, 7)); fill_prefetch_0(); quit_program = 0; - m68k_go(true); + m68k_execute(); // Clean up stack m68k_areg(regs, 7) += 4; @@ -226,7 +226,7 @@ void Execute68k(uint32 addr, struct M68kRegisters *r) m68k_setpc(addr); fill_prefetch_0(); quit_program = 0; - m68k_go(true); + m68k_execute(); // Clean up stack m68k_areg(regs, 7) += 2; diff --git a/BasiliskII/src/uae_cpu/build68k.c b/BasiliskII/src/uae_cpu/build68k.c index 1cf8c610..6d6fd55d 100644 --- a/BasiliskII/src/uae_cpu/build68k.c +++ b/BasiliskII/src/uae_cpu/build68k.c @@ -58,8 +58,8 @@ int main(int argc, char **argv) printf ("#include \"sysdeps.h\"\n"); printf ("#include \"readcpu.h\"\n"); printf ("struct instr_def defs68k[] = {\n"); -#if 0 - tablef = fopen("table68k","r"); +#ifdef WIN32 + tablef = fopen(argc > 1 ? argv[1] : "table68k","r"); if (tablef == NULL) { fprintf(stderr, "table68k not found\n"); exit(1); @@ -76,6 +76,7 @@ int main(int argc, char **argv) char opcstr[256]; int bitpos[16]; int flagset[5], flaguse[5]; + char cflow; unsigned int bitmask,bitpattern; int n_variable; @@ -107,6 +108,7 @@ int main(int argc, char **argv) case 'r': currbit = bitr; break; case 'R': currbit = bitR; break; case 'z': currbit = bitz; break; + case 'E': currbit = bitE; break; case 'p': currbit = bitp; break; default: abort(); } @@ -156,7 +158,6 @@ int main(int argc, char **argv) getnextch(); switch(nextch){ case '-': flagset[i] = fa_unset; break; - case '/': flagset[i] = fa_isjmp; break; case '0': flagset[i] = fa_zero; break; case '1': flagset[i] = fa_one; break; case 'x': flagset[i] = fa_dontcare; break; @@ -176,13 +177,31 @@ int main(int argc, char **argv) getnextch(); switch(nextch){ case '-': flaguse[i] = fu_unused; break; - case '/': flaguse[i] = fu_isjmp; break; - case '+': flaguse[i] = fu_maybecc; break; case '?': flaguse[i] = fu_unknown; break; default: flaguse[i] = fu_used; break; } } + getnextch(); + while (isspace(nextch)) + getnextch(); + + if (nextch != ':') /* Get control flow information */ + abort(); + + cflow = 0; + for(i = 0; i < 2; i++) { + getnextch(); + switch(nextch){ + case '-': break; + case 'R': cflow |= fl_return; break; + case 'B': cflow |= fl_branch; break; + case 'J': cflow |= fl_jump; break; + case 'T': cflow |= fl_trap; break; + default: abort(); + } + } + getnextch(); while (isspace(nextch)) getnextch(); @@ -234,7 +253,7 @@ int main(int argc, char **argv) for(i = 0; i < 5; i++) { printf("{ %d, %d }%c ", flaguse[i], flagset[i], i == 4 ? ' ' : ','); } - printf("}, %d, \"%s\"}", sduse, opstrp); + printf("}, %d, %d, \"%s\"}", cflow, sduse, opstrp); } } printf("};\nint n_defs68k = %d;\n", no_insns); diff --git a/BasiliskII/src/uae_cpu/gencpu.c b/BasiliskII/src/uae_cpu/gencpu.c index 8329b706..b966fc55 100644 --- a/BasiliskII/src/uae_cpu/gencpu.c +++ b/BasiliskII/src/uae_cpu/gencpu.c @@ -725,7 +725,6 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch start_brace (); printf ("\tuae_u32 %s;\n", value); break; - default: break; } @@ -746,6 +745,7 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch } printf ("\t}\n"); return; + case flag_logical: if (strcmp (value, "0") == 0) { printf ("\tSET_CZNV (FLAGVAL_Z);\n"); @@ -786,7 +786,6 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch break; } #endif - genflags_normal (type, size, value, src, dst); } @@ -824,6 +823,25 @@ static int source_is_imm1_8 (struct instr *i) return i->stype == 3; } +static const char * cflow_string_of(uae_u32 opcode) +{ + const char * cflow_type_str; + + int cflow_type = table68k[opcode].cflow & ~fl_trap; + switch (cflow_type) { + case fl_branch: cflow_type_str = "CFLOW_BRANCH"; break; + case fl_jump: cflow_type_str = "CFLOW_JUMP"; break; + case fl_return: cflow_type_str = "CFLOW_RETURN"; break; + default: cflow_type_str = "CFLOW_NORMAL"; + } + + /* Patch M68K_EXEC_RETURN instruction */ + if (table68k[opcode].mnemo == i_EMULOP_RETURN) + cflow_type_str = "CFLOW_EXEC_RETURN"; + + return cflow_type_str; +} + static void gen_opcode (unsigned long int opcode) { struct instr *curi = table68k + opcode; @@ -957,7 +975,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n"); printf ("\tuae_u16 newv, tmp_newv;\n"); printf ("\tint cflg;\n"); - printf ("\tnewv = tmp_newv = newv_hi + newv_lo;"); + printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n"); printf ("\tif (newv_lo > 9) { newv += 6; }\n"); printf ("\tcflg = (newv & 0x3F0) > 0x90;\n"); printf ("\tif (cflg) newv += 0x60;\n"); @@ -989,7 +1007,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tuae_u16 newv;\n"); printf ("\tint cflg;\n"); printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n"); - printf ("\tnewv = newv_hi + newv_lo;"); + printf ("\tnewv = newv_hi + newv_lo;\n"); printf ("\tcflg = (newv & 0x1F0) > 0x90;\n"); printf ("\tif (cflg) newv -= 0x60;\n"); printf ("\tSET_CFLG (cflg);\n"); @@ -1201,6 +1219,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n"); printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n"); printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n"); + /* gb-- the next two lines are deleted in Bernie's gencpu.c */ printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x7000) { m68k_areg(regs, 7) += 52; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n"); @@ -1289,6 +1308,18 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_Bcc: + if (0 && !using_prefetch && !using_exception_3 && (cpu_level >= 2)) { + /* gb-- variant probably more favorable to compiler optimizations + also assumes no prefetch buffer is used + Hmm, that would make sense with processors capable of conditional moves */ + if (curi->size == sz_long && next_cpu_level < 1) + next_cpu_level = 1; + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + printf ("\tm68k_incpc (cctrue(%d) ? ((uae_s32)src + 2) : %d);\n", curi->cc, m68k_pc_offset); + m68k_pc_offset = 0; + } + else { + /* original code for branch instructions */ if (curi->size == sz_long) { if (cpu_level < 2) { printf ("\tm68k_incpc(2);\n"); @@ -1312,15 +1343,12 @@ static void gen_opcode (unsigned long int opcode) printf ("\t}\n"); need_endlabel = 1; } -#ifdef USE_COMPILER - printf ("\tm68k_setpc_bcc(m68k_getpc() + 2 + (uae_s32)src);\n"); -#else printf ("\tm68k_incpc ((uae_s32)src + 2);\n"); -#endif fill_prefetch_0 (); - printf ("\tgoto %s;\n", endlabelstr); + printf ("cpuop_return(%s);\n", cflow_string_of(opcode)); printf ("didnt_jump:;\n"); need_endlabel = 1; + } break; case i_LEA: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); @@ -1348,13 +1376,9 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\t}\n"); need_endlabel = 1; } -#ifdef USE_COMPILER - printf ("\t\t\tm68k_setpc_bcc(m68k_getpc() + (uae_s32)offs + 2);\n"); -#else printf ("\t\t\tm68k_incpc((uae_s32)offs + 2);\n"); -#endif fill_prefetch_0 (); - printf ("\t\tgoto %s;\n", endlabelstr); + printf ("cpuop_return(%s);\n", cflow_string_of(opcode)); printf ("\t\t}\n"); printf ("\t}\n"); need_endlabel = 1; @@ -1452,7 +1476,7 @@ static void gen_opcode (unsigned long int opcode) abort (); } printf ("\tSET_ZFLG (upper == reg || lower == reg);\n"); - printf ("\tSET_CFLG (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n"); + printf ("\tSET_CFLG_ALWAYS (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n"); printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc); goto %s; }\n}\n", endlabelstr); need_endlabel = 1; break; @@ -1989,7 +2013,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\ttmp = (bf0 << (offset & 7)) | (bf1 >> (8 - (offset & 7)));\n"); } printf ("\ttmp >>= (32 - width);\n"); - printf ("\tSET_NFLG (tmp & (1 << (width-1)) ? 1 : 0);\n"); + printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width-1)) ? 1 : 0);\n"); printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n"); switch (curi->mnemo) { case i_BFTST: @@ -2017,7 +2041,7 @@ static void gen_opcode (unsigned long int opcode) break; case i_BFINS: printf ("\ttmp = m68k_dreg(regs, (extra >> 12) & 7);\n"); - printf ("\tSET_NFLG (tmp & (1 << (width - 1)) ? 1 : 0);\n"); + printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width - 1)) ? 1 : 0);\n"); printf ("\tSET_ZFLG (tmp == 0);\n"); break; default: @@ -2175,6 +2199,18 @@ static void gen_opcode (unsigned long int opcode) swap_opcode (); printf ("\tmmu_op(opcode,extra);\n"); break; + + case i_EMULOP_RETURN: + printf ("\tm68k_emulop_return();\n"); + m68k_pc_offset = 0; + break; + + case i_EMULOP: + printf ("\n"); + swap_opcode (); + printf ("\tm68k_emulop(opcode);\n"); + break; + default: abort (); break; @@ -2186,11 +2222,22 @@ static void gen_opcode (unsigned long int opcode) static void generate_includes (FILE * f) { fprintf (f, "#include \"sysdeps.h\"\n"); + fprintf (f, "#include \"m68k.h\"\n"); fprintf (f, "#include \"memory.h\"\n"); fprintf (f, "#include \"readcpu.h\"\n"); fprintf (f, "#include \"newcpu.h\"\n"); fprintf (f, "#include \"cputbl.h\"\n"); + + fprintf (f, "#define SET_CFLG_ALWAYS(x) SET_CFLG(x)\n"); + fprintf (f, "#define SET_NFLG_ALWAYS(x) SET_NFLG(x)\n"); + fprintf (f, "#define CPUFUNC_FF(x) x##_ff\n"); + fprintf (f, "#define CPUFUNC_NF(x) x##_nf\n"); + fprintf (f, "#define CPUFUNC(x) CPUFUNC_FF(x)\n"); + + fprintf (f, "#ifdef NOFLAGS\n"); + fprintf (f, "# include \"noflags.h\"\n"); + fprintf (f, "#endif\n"); } static int postfix; @@ -2214,13 +2261,28 @@ static void generate_one_opcode (int rp) return; if (opcode_next_clev[rp] != cpu_level) { - fprintf (stblfile, "{ op_%lx_%d, 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], + fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], opcode, lookuptab[i].name); return; } - fprintf (stblfile, "{ op_%lx_%d, 0, %ld }, /* %s */\n", opcode, postfix, opcode, lookuptab[i].name); - fprintf (headerfile, "extern cpuop_func op_%lx_%d;\n", opcode, postfix); - printf ("void REGPARAM2 op_%lx_%d(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name); + + if (table68k[opcode].flagdead == 0) + /* force to the "ff" variant since the instruction doesn't set at all the condition codes */ + fprintf (stblfile, "{ CPUFUNC_FF(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, lookuptab[i].name); + else + fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, lookuptab[i].name); + + fprintf (headerfile, "extern cpuop_func op_%lx_%d_nf;\n", opcode, postfix); + fprintf (headerfile, "extern cpuop_func op_%lx_%d_ff;\n", opcode, postfix); + printf ("cpuop_rettype REGPARAM2 CPUFUNC(op_%lx_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name); + printf ("\tcpuop_begin();\n"); + + /* gb-- The "nf" variant for an instruction that doesn't set the condition + codes at all is the same as the "ff" variant, so we don't need the "nf" + variant to be compiled since it is mapped to the "ff" variant in the + smalltbl. */ + if (table68k[opcode].flagdead == 0) + printf ("#ifndef NOFLAGS\n"); switch (table68k[opcode].stype) { case 0: smsk = 7; break; @@ -2229,6 +2291,7 @@ static void generate_one_opcode (int rp) case 3: smsk = 7; break; case 4: smsk = 7; break; case 5: smsk = 63; break; + case 6: smsk = 255; break; case 7: smsk = 3; break; default: abort (); } @@ -2239,7 +2302,12 @@ static void generate_one_opcode (int rp) && table68k[opcode].smode != imm && table68k[opcode].smode != imm0 && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2 && table68k[opcode].smode != absw && table68k[opcode].smode != absl - && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16) + && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16 + /* gb-- We don't want to fetch the EmulOp code since the EmulOp() + routine uses the whole opcode value. Maybe all the EmulOps + could be expanded out but I don't think it is an improvement */ + && table68k[opcode].stype != 6 + ) { if (table68k[opcode].spos == -1) { if (((int) table68k[opcode].sreg) >= 128) @@ -2335,6 +2403,9 @@ static void generate_one_opcode (int rp) gen_opcode (opcode); if (need_endlabel) printf ("%s: ;\n", endlabelstr); + if (table68k[opcode].flagdead == 0) + printf ("\n#endif\n"); + printf ("\tcpuop_end(%s);\n", cflow_string_of(opcode)); printf ("}\n"); opcode_next_clev[rp] = next_cpu_level; opcode_last_postfix[rp] = postfix; @@ -2362,7 +2433,7 @@ static void generate_func (void) opcode_next_clev[rp] = 0; } postfix = i; - fprintf (stblfile, "struct cputbl op_smalltbl_%d[] = {\n", postfix); + fprintf (stblfile, "struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix); /* sam: this is for people with low memory (eg. me :)) */ printf ("\n" diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index 1c69078a..c8204c38 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -23,13 +23,18 @@ extern int intlev(void); // From baisilisk_glue.cpp #include "readcpu.h" #include "newcpu.h" +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) && defined(HAVE_PTHREADS) +#include +pthread_mutex_t spcflags_lock = PTHREAD_MUTEX_INITIALIZER; +#endif + #if ENABLE_MON #include "mon.h" #include "mon_disass.h" #endif int quit_program = 0; -int debugging = 0; +const int debugging = 0; struct flag_struct regflags; /* Opcode of faulting instruction */ @@ -164,11 +169,11 @@ static __inline__ unsigned int cft_map (unsigned int f) #endif } -static void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; +cpuop_rettype REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; -static void REGPARAM2 op_illg_1 (uae_u32 opcode) +cpuop_rettype REGPARAM2 op_illg_1 (uae_u32 opcode) { - op_illg (cft_map (opcode)); + cpuop_return( op_illg (cft_map (opcode)) ); } static void build_cpufunctbl (void) @@ -187,11 +192,11 @@ static void build_cpufunctbl (void) cpu_level = 1; } struct cputbl *tbl = ( - cpu_level == 4 ? op_smalltbl_0 - : cpu_level == 3 ? op_smalltbl_1 - : cpu_level == 2 ? op_smalltbl_2 - : cpu_level == 1 ? op_smalltbl_3 - : op_smalltbl_4); + cpu_level == 4 ? op_smalltbl_0_ff + : cpu_level == 3 ? op_smalltbl_1_ff + : cpu_level == 2 ? op_smalltbl_2_ff + : cpu_level == 1 ? op_smalltbl_3_ff + : op_smalltbl_4_ff); for (opcode = 0; opcode < 65536; opcode++) cpufunctbl[cft_map (opcode)] = op_illg_1; @@ -703,13 +708,13 @@ void MakeFromSR (void) } } - regs.spcflags |= SPCFLAG_INT; + SPCFLAGS_SET( SPCFLAG_INT ); if (regs.t1 || regs.t0) - regs.spcflags |= SPCFLAG_TRACE; + SPCFLAGS_SET( SPCFLAG_TRACE ); else /* Keep SPCFLAG_DOTRACE, we still want a trace exception for SR-modifying instructions (including STOP). */ - regs.spcflags &= ~SPCFLAG_TRACE; + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); } void Exception(int nr, uaecptr oldpc) @@ -774,9 +779,10 @@ kludge_me_do: m68k_areg(regs, 7) -= 2; put_word (m68k_areg(regs, 7), regs.sr); m68k_setpc (get_long (regs.vbr + 4*nr)); + SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE ); fill_prefetch_0 (); regs.t1 = regs.t0 = regs.m = 0; - regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE); + SPCFLAGS_CLEAR( SPCFLAG_TRACE | SPCFLAG_DOTRACE ); } static void Interrupt(int nr) @@ -787,7 +793,7 @@ static void Interrupt(int nr) Exception(nr+24, 0); regs.intmask = nr; - regs.spcflags |= SPCFLAG_INT; + SPCFLAGS_SET( SPCFLAG_INT ); } static int caar, cacr, tc, itt0, itt1, dtt0, dtt1, mmusr, urp, srp; @@ -1115,12 +1121,16 @@ static char* ccnames[] = { "T ","F ","HI","LS","CC","CS","NE","EQ", "VC","VS","PL","MI","GE","LT","GT","LE" }; +// If value is greater than zero, this means we are still processing an EmulOp +// because the counter is incremented only in m68k_execute(), i.e. interpretive +// execution only +static int m68k_execute_depth = 0; + void m68k_reset (void) { m68k_areg (regs, 7) = 0x2000; m68k_setpc (ROMBaseMac + 0x2a); fill_prefetch_0 (); - regs.kick_mask = 0xF80000; regs.s = 1; regs.m = 0; regs.stopped = 0; @@ -1131,11 +1141,9 @@ void m68k_reset (void) SET_CFLG (0); SET_VFLG (0); SET_NFLG (0); - regs.spcflags = 0; + SPCFLAGS_INIT( 0 ); regs.intmask = 7; regs.vbr = regs.sfc = regs.dfc = 0; - /* gb-- moved into {fpp,fpu_x86}.cpp::fpu_init() - regs.fpcr = regs.fpsr = regs.fpiar = 0; */ fpu_reset(); #if FLIGHT_RECORDER @@ -1150,22 +1158,17 @@ void m68k_reset (void) #endif } -void REGPARAM2 op_illg (uae_u32 opcode) +void m68k_emulop_return(void) { - uaecptr pc = m68k_getpc (); + SPCFLAGS_SET( SPCFLAG_BRK ); + quit_program = 1; +} - if ((opcode & 0xFF00) == 0x7100) { +void m68k_emulop(uae_u32 opcode) +{ struct M68kRegisters r; int i; - // Return from Exectue68k()? - if (opcode == M68K_EXEC_RETURN) { - regs.spcflags |= SPCFLAG_BRK; - quit_program = 1; - return; - } - - // Call EMUL_OP opcode for (i=0; i<8; i++) { r.d[i] = m68k_dreg(regs, i); r.a[i] = m68k_areg(regs, i); @@ -1179,26 +1182,26 @@ void REGPARAM2 op_illg (uae_u32 opcode) } regs.sr = r.sr; MakeFromSR(); - m68k_incpc(2); - fill_prefetch_0 (); - return; - } +} + +cpuop_rettype REGPARAM2 op_illg (uae_u32 opcode) +{ + uaecptr pc = m68k_getpc (); if ((opcode & 0xF000) == 0xA000) { Exception(0xA,0); - return; + cpuop_return(CFLOW_TRAP); } -// write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); - if ((opcode & 0xF000) == 0xF000) { Exception(0xB,0); - return; + cpuop_return(CFLOW_TRAP); } write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); Exception (4,0); + cpuop_return(CFLOW_TRAP); } void mmu_op(uae_u32 opcode, uae_u16 extra) @@ -1225,7 +1228,7 @@ static void do_trace (void) /* We can afford this to be inefficient... */ m68k_setpc (m68k_getpc ()); fill_prefetch_0 (); - opcode = get_word (regs.pc); + opcode = get_word(m68k_getpc()); if (opcode == 0x4e72 /* RTE */ || opcode == 0x4e74 /* RTD */ || opcode == 0x4e75 /* RTS */ @@ -1241,57 +1244,55 @@ static void do_trace (void) && (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) { last_trace_ad = m68k_getpc (); - regs.spcflags &= ~SPCFLAG_TRACE; - regs.spcflags |= SPCFLAG_DOTRACE; + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_DOTRACE ); } } else if (regs.t1) { last_trace_ad = m68k_getpc (); - regs.spcflags &= ~SPCFLAG_TRACE; - regs.spcflags |= SPCFLAG_DOTRACE; + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_DOTRACE ); } } - -static int do_specialties (void) +int m68k_do_specialties (void) { - /*n_spcinsns++;*/ - if (regs.spcflags & SPCFLAG_DOTRACE) { + if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) { Exception (9,last_trace_ad); } - while (regs.spcflags & SPCFLAG_STOP) { - if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)){ + while (SPCFLAGS_TEST( SPCFLAG_STOP )) { + if (SPCFLAGS_TEST( SPCFLAG_INT | SPCFLAG_DOINT )){ + SPCFLAGS_CLEAR( SPCFLAG_INT | SPCFLAG_DOINT ); int intr = intlev (); - regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT); if (intr != -1 && intr > regs.intmask) { Interrupt (intr); regs.stopped = 0; - regs.spcflags &= ~SPCFLAG_STOP; + SPCFLAGS_CLEAR( SPCFLAG_STOP ); } } } - if (regs.spcflags & SPCFLAG_TRACE) + if (SPCFLAGS_TEST( SPCFLAG_TRACE )) do_trace (); - if (regs.spcflags & SPCFLAG_DOINT) { + if (SPCFLAGS_TEST( SPCFLAG_DOINT )) { + SPCFLAGS_CLEAR( SPCFLAG_DOINT ); int intr = intlev (); - regs.spcflags &= ~SPCFLAG_DOINT; if (intr != -1 && intr > regs.intmask) { Interrupt (intr); regs.stopped = 0; } } - if (regs.spcflags & SPCFLAG_INT) { - regs.spcflags &= ~SPCFLAG_INT; - regs.spcflags |= SPCFLAG_DOINT; + if (SPCFLAGS_TEST( SPCFLAG_INT )) { + SPCFLAGS_CLEAR( SPCFLAG_INT ); + SPCFLAGS_SET( SPCFLAG_DOINT ); } - if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { - regs.spcflags &= ~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); - return 1; + if (SPCFLAGS_TEST( SPCFLAG_BRK )) { + SPCFLAGS_CLEAR( SPCFLAG_BRK ); + return CFLOW_EXEC_RETURN; } return 0; } -static void m68k_run_1 (void) +void m68k_do_execute (void) { for (;;) { uae_u32 opcode = GET_OPCODE; @@ -1305,27 +1306,15 @@ static void m68k_run_1 (void) #else (*cpufunctbl[opcode])(opcode); #endif - if (regs.spcflags) { - if (do_specialties()) + if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { + if (m68k_do_specialties()) return; } } } -#define m68k_run1 m68k_run_1 - -int in_m68k_go = 0; - -void m68k_go (int may_quit) +void m68k_execute (void) { -// m68k_go() must be reentrant for Execute68k() and Execute68kTrap() to work -/* - if (in_m68k_go || !may_quit) { - write_log("Bug! m68k_go is not reentrant.\n"); - abort(); - } -*/ - in_m68k_go++; for (;;) { if (quit_program > 0) { if (quit_program == 1) @@ -1333,14 +1322,13 @@ void m68k_go (int may_quit) quit_program = 0; m68k_reset (); } - m68k_run1(); + m68k_do_execute(); } if (debugging) { uaecptr nextpc; m68k_dumpstate(&nextpc); exit(1); } - in_m68k_go--; } static void m68k_verify (uaecptr addr, uaecptr *nextpc) diff --git a/BasiliskII/src/uae_cpu/newcpu.h b/BasiliskII/src/uae_cpu/newcpu.h index b920ece6..ac559e5d 100644 --- a/BasiliskII/src/uae_cpu/newcpu.h +++ b/BasiliskII/src/uae_cpu/newcpu.h @@ -9,18 +9,10 @@ #ifndef NEWCPU_H #define NEWCPU_H -#define SPCFLAG_STOP 2 -#define SPCFLAG_DISK 4 -#define SPCFLAG_INT 8 -#define SPCFLAG_BRK 16 -#define SPCFLAG_EXTRA_CYCLES 32 -#define SPCFLAG_TRACE 64 -#define SPCFLAG_DOTRACE 128 -#define SPCFLAG_DOINT 256 -#define SPCFLAG_BLTNASTY 512 -#define SPCFLAG_EXEC 1024 -#define SPCFLAG_MODE_CHANGE 8192 - +#include "m68k.h" +#include "readcpu.h" +#include "spcflags.h" + extern int areg_byteinc[]; extern int imm8_table[]; @@ -34,50 +26,77 @@ extern int fpp_movem_next[256]; extern int broken_in; -typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM; +/* Control flow information */ +#define CFLOW_NORMAL 0 +#define CFLOW_BRANCH 1 +#define CFLOW_JUMP 2 +#define CFLOW_TRAP CFLOW_JUMP +#define CFLOW_RETURN 3 +#define CFLOW_SPCFLAGS 32 /* some spcflags are set */ +#define CFLOW_EXEC_RETURN 64 /* must exit from the execution loop */ +#define cpuop_rettype void +#define cpuop_return(v) do { (v); return; } while (0) + +#ifdef X86_ASSEMBLY +/* This hack seems to force all register saves (pushl %reg) to be moved to the + begining of the function, thus making it possible to cpuopti to remove them + since m68k_run_1 will save those registers before calling the instruction + handler */ +# define cpuop_tag(tag) __asm__ __volatile__ ( "#cpuop_" tag ) +#else +# define cpuop_tag(tag) ; +#endif + +#define cpuop_begin() do { cpuop_tag("begin"); } while (0) +#define cpuop_end(cflow) do { cpuop_tag("end"); cpuop_return(cflow); } while (0) + +typedef cpuop_rettype REGPARAM2 cpuop_func (uae_u32) REGPARAM; + struct cputbl { cpuop_func *handler; - int specific; + uae_u16 specific; uae_u16 opcode; }; -extern void REGPARAM2 op_illg (uae_u32) REGPARAM; +extern cpuop_rettype REGPARAM2 op_illg (uae_u32) REGPARAM; typedef char flagtype; -extern struct regstruct -{ - uae_u32 regs[16]; - uaecptr usp,isp,msp; - uae_u16 sr; - flagtype t1; - flagtype t0; - flagtype s; - flagtype m; - flagtype x; - flagtype stopped; - int intmask; +struct regstruct { + uae_u32 regs[16]; - uae_u32 pc; - uae_u8 *pc_p; - uae_u8 *pc_oldp; + uae_u32 pc; + uae_u8 * pc_p; + uae_u8 * pc_oldp; - uae_u32 vbr,sfc,dfc; + spcflags_t spcflags; + int intmask; - double fp[8]; - uae_u32 fpcr,fpsr,fpiar; + uae_u32 vbr, sfc, dfc; + uaecptr usp, isp, msp; + uae_u16 sr; + flagtype t1; + flagtype t0; + flagtype s; + flagtype m; + flagtype x; + flagtype stopped; - uae_u32 spcflags; - uae_u32 kick_mask; + double fp[8]; + uae_u32 fpcr,fpsr,fpiar; +#if USE_PREFETCH_BUFFER /* Fellow sources say this is 4 longwords. That's impossible. It needs * to be at least a longword. The HRM has some cryptic comment about two * instructions being on the same longword boundary. * The way this is implemented now seems like a good compromise. */ uae_u32 prefetch; -} regs, lastint_regs; +#endif +}; + +extern regstruct regs, lastint_regs; #define m68k_dreg(r,num) ((r).regs[(num)]) #define m68k_areg(r,num) (((r).regs + 8)[(num)]) @@ -92,6 +111,7 @@ extern struct regstruct #define GET_OPCODE (get_iword (0)) #endif +#if USE_PREFETCH_BUFFER static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o) { if (o > 3 || o < 0) @@ -114,6 +134,7 @@ static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o) return do_get_mem_long(®s.prefetch); return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4)); } +#endif #define m68k_incpc(o) (regs.pc_p += (o)) @@ -166,7 +187,6 @@ static __inline__ uae_u32 next_ilong (void) return r; } -#if !defined USE_COMPILER static __inline__ void m68k_setpc (uaecptr newpc) { #if REAL_ADDRESSING || DIRECT_ADDRESSING @@ -176,9 +196,6 @@ static __inline__ void m68k_setpc (uaecptr newpc) regs.pc = newpc; #endif } -#else -extern void m68k_setpc (uaecptr newpc); -#endif static __inline__ uaecptr m68k_getpc (void) { @@ -189,15 +206,9 @@ static __inline__ uaecptr m68k_getpc (void) #endif } -#ifdef USE_COMPILER -extern void m68k_setpc_fast (uaecptr newpc); -extern void m68k_setpc_bcc (uaecptr newpc); -extern void m68k_setpc_rte (uaecptr newpc); -#else #define m68k_setpc_fast m68k_setpc #define m68k_setpc_bcc m68k_setpc #define m68k_setpc_rte m68k_setpc -#endif static __inline__ void m68k_do_rts(void) { @@ -225,7 +236,7 @@ static __inline__ void m68k_setstopped (int stop) /* A traced STOP instruction drops through immediately without actually stopping. */ if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0) - regs.spcflags |= SPCFLAG_STOP; + SPCFLAGS_SET( SPCFLAG_STOP ); } extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp); @@ -241,13 +252,15 @@ extern int m68k_move2c (int, uae_u32 *); extern int m68k_movec2 (int, uae_u32 *); extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr); extern void m68k_mull (uae_u32, uae_u32, uae_u16); +extern void m68k_emulop (uae_u32); +extern void m68k_emulop_return (void); extern void init_m68k (void); extern void exit_m68k (void); -extern void m68k_go (int); extern void m68k_dumpstate (uaecptr *); extern void m68k_disasm (uaecptr, uaecptr *, int); extern void m68k_reset (void); extern void m68k_enter_debugger(void); +extern int m68k_do_specialties(void); extern void mmu_op (uae_u32, uae_u16); @@ -274,16 +287,17 @@ extern uaecptr last_fault_for_exception_3; #define CPU_OP_NAME(a) op ## a /* 68020 + 68881 */ -extern struct cputbl op_smalltbl_0[]; +extern struct cputbl op_smalltbl_0_ff[]; /* 68020 */ -extern struct cputbl op_smalltbl_1[]; +extern struct cputbl op_smalltbl_1_ff[]; /* 68010 */ -extern struct cputbl op_smalltbl_2[]; +extern struct cputbl op_smalltbl_2_ff[]; /* 68000 */ -extern struct cputbl op_smalltbl_3[]; +extern struct cputbl op_smalltbl_3_ff[]; /* 68000 slow but compatible. */ -extern struct cputbl op_smalltbl_4[]; - -extern cpuop_func *cpufunctbl[65536] ASM_SYM_FOR_FUNC ("cpufunctbl"); +extern struct cputbl op_smalltbl_4_ff[]; +extern void m68k_do_execute(void); +extern void m68k_execute(void); + #endif /* NEWCPU_H */ diff --git a/BasiliskII/src/uae_cpu/noflags.h b/BasiliskII/src/uae_cpu/noflags.h new file mode 100644 index 00000000..eacbc214 --- /dev/null +++ b/BasiliskII/src/uae_cpu/noflags.h @@ -0,0 +1,142 @@ +#ifndef NOFLAGS_H +#define NOFLAGS_H + +/* Undefine everything that will *set* flags. Note: Leave *reading* + flags alone ;-). We assume that nobody does something like + SET_ZFLG(a=b+c), i.e. expect side effects of the macros. That would + be a stupid thing to do when using macros. +*/ + +/* Gwenole Beauchesne pointed out that CAS and CAS2 use flag_cmp to set + flags that are then used internally, and that thus the noflags versions + of those instructions were broken. Oops! + Easy fix: Leave flag_cmp alone. It is only used by CMP* and CAS* + instructions. For CAS*, noflags is a bad idea. For CMP*, which has + setting flags as its only function, the noflags version is kinda pointless, + anyway. + Note that this will only work while using the optflag_* routines --- + as we do on all (one ;-) platforms that will ever use the noflags + versions, anyway. + However, if you try to compile without optimized flags, the "SET_ZFLAG" + macro will be left unchanged, to make CAS and CAS2 work right. Of course, + this is contrary to the whole idea of noflags, but better be right than + be fast. + + Another problem exists with one of the bitfield operations. Once again, + one of the operations sets a flag, and looks at it later. And the CHK2 + instruction does so as well. For those, a different solution is possible. + the *_ALWAYS versions of the SET_?FLG macros shall remain untouched by + the redefinitions in this file. + Unfortunately, they are defined in terms of the macros we *do* redefine. + So here comes a bit of trickery.... +*/ +#define NOFLAGS_CMP 0 + +#undef SET_NFLG_ALWAYS +static __inline__ void SET_NFLG_ALWAYS(uae_u32 x) +{ + SET_NFLG(x); /* This has not yet been redefined */ +} + +#undef SET_CFLG_ALWAYS +static __inline__ void SET_CFLG_ALWAYS(uae_u32 x) +{ + SET_CFLG(x); /* This has not yet been redefined */ +} + +#undef CPUFUNC +#define CPUFUNC(x) x##_nf + +#ifndef OPTIMIZED_FLAGS +#undef SET_ZFLG +#define SET_ZFLG(y) do {uae_u32 dummy=(y); } while (0) +#endif + +#undef SET_CFLG +#define SET_CFLG(y) do {uae_u32 dummy=(y); } while (0) +#undef SET_VFLG +#define SET_VFLG(y) do {uae_u32 dummy=(y); } while (0) +#undef SET_NFLG +#define SET_NFLG(y) do {uae_u32 dummy=(y); } while (0) +#undef SET_XFLG +#define SET_XFLG(y) do {uae_u32 dummy=(y); } while (0) + +#undef CLEAR_CZNV +#define CLEAR_CZNV +#undef IOR_CZNV +#define IOR_CZNV(y) do {uae_u32 dummy=(y); } while (0) +#undef SET_CZNV +#define SET_CZNV(y) do {uae_u32 dummy=(y); } while (0) +#undef COPY_CARRY +#define COPY_CARRY + +#ifdef optflag_testl +#undef optflag_testl +#endif + +#ifdef optflag_testw +#undef optflag_testw +#endif + +#ifdef optflag_testb +#undef optflag_testb +#endif + +#ifdef optflag_addl +#undef optflag_addl +#endif + +#ifdef optflag_addw +#undef optflag_addw +#endif + +#ifdef optflag_addb +#undef optflag_addb +#endif + +#ifdef optflag_subl +#undef optflag_subl +#endif + +#ifdef optflag_subw +#undef optflag_subw +#endif + +#ifdef optflag_subb +#undef optflag_subb +#endif + +#if NOFLAGS_CMP +#ifdef optflag_cmpl +#undef optflag_cmpl +#endif + +#ifdef optflag_cmpw +#undef optflag_cmpw +#endif + +#ifdef optflag_cmpb +#undef optflag_cmpb +#endif +#endif + +#define optflag_testl(v) do { } while (0) +#define optflag_testw(v) do { } while (0) +#define optflag_testb(v) do { } while (0) + +#define optflag_addl(v, s, d) (v = (uae_s32)(d) + (uae_s32)(s)) +#define optflag_addw(v, s, d) (v = (uae_s16)(d) + (uae_s16)(s)) +#define optflag_addb(v, s, d) (v = (uae_s8)(d) + (uae_s8)(s)) + +#define optflag_subl(v, s, d) (v = (uae_s32)(d) - (uae_s32)(s)) +#define optflag_subw(v, s, d) (v = (uae_s16)(d) - (uae_s16)(s)) +#define optflag_subb(v, s, d) (v = (uae_s8)(d) - (uae_s8)(s)) + +#if NOFLAGS_CMP +/* These are just for completeness sake */ +#define optflag_cmpl(s, d) do { } while (0) +#define optflag_cmpw(s, d) do { } while (0) +#define optflag_cmpb(s, d) do { } while (0) +#endif + +#endif diff --git a/BasiliskII/src/uae_cpu/readcpu.cpp b/BasiliskII/src/uae_cpu/readcpu.cpp index 708f2f4f..e99ec27a 100644 --- a/BasiliskII/src/uae_cpu/readcpu.cpp +++ b/BasiliskII/src/uae_cpu/readcpu.cpp @@ -139,6 +139,9 @@ struct mnemolookup lookuptab[] = { { i_CPUSHA, "CPUSHA" }, { i_MOVE16, "MOVE16" }, + { i_EMULOP_RETURN, "EMULOP_RETURN" }, + { i_EMULOP, "EMULOP" }, + { i_MMUOP, "MMUOP" }, { i_ILLG, "" }, }; @@ -195,16 +198,34 @@ static void build_insn (int insn) int variants; struct instr_def id; const char *opcstr; - int i; + int i, n; int flaglive = 0, flagdead = 0; + int cflow = 0; id = defs68k[insn]; + // Control flow information + cflow = id.cflow; + + // Mask of flags set/used + unsigned char flags_set(0), flags_used(0); + + for (i = 0, n = 4; i < 5; i++, n--) { + switch (id.flaginfo[i].flagset) { + case fa_unset: case fa_isjmp: break; + default: flags_set |= (1 << n); + } + + switch (id.flaginfo[i].flaguse) { + case fu_unused: case fu_isjmp: break; + default: flags_used |= (1 << n); + } + } + for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flagset){ case fa_unset: break; - case fa_isjmp: break; case fa_zero: flagdead |= 1 << i; break; case fa_one: flagdead |= 1 << i; break; case fa_dontcare: flagdead |= 1 << i; break; @@ -217,8 +238,6 @@ static void build_insn (int insn) for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flaguse) { case fu_unused: break; - case fu_isjmp: flaglive |= 1 << i; break; - case fu_maybecc: flaglive |= 1 << i; break; case fu_unknown: flaglive = -1; goto out2; case fu_used: flaglive |= 1 << i; break; } @@ -273,6 +292,8 @@ static void build_insn (int insn) continue; if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff)) continue; + if (bitcnt[bitE] && (bitval[bitE] == 0x00)) + continue; /* bitI and bitC get copied to biti and bitc */ if (bitcnt[bitI]) { @@ -395,6 +416,14 @@ static void build_insn (int insn) srctype = 5; srcpos = bitpos[bitK]; } + break; + case 'E': srcmode = immi; srcreg = bitval[bitE]; + if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ?? + /* 1..255 */ + srcgather = 1; + srctype = 6; + srcpos = bitpos[bitE]; + } break; case 'p': srcmode = immi; srcreg = bitval[bitp]; if (CPU_EMU_SIZE < 5) { @@ -719,8 +748,16 @@ static void build_insn (int insn) table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse; } #endif + +#if 1 + /* gb-- flagdead and flaglive would not have correct information */ + table68k[opc].flagdead = flags_set; + table68k[opc].flaglive = flags_used; +#else table68k[opc].flagdead = flagdead; table68k[opc].flaglive = flaglive; +#endif + table68k[opc].cflow = cflow; nomatch: /* FOO! */; } @@ -739,6 +776,66 @@ void read_table68k (void) for (i = 0; i < n_defs68k; i++) { build_insn (i); } + + /* Extra fixes in table68k for control flow information and flag usage */ + for (i = 0; i < 65536; i++) { + instrmnem mnemo = (instrmnem)(table68k[i].mnemo); + +#define IS_CONST_JUMP(opc) \ + ( ((table68k[opc].mnemo == i_Bcc) && (table68k[opc].cc < 2)) \ + || (table68k[opc].mnemo == i_BSR) \ + ) + +#if 0 + // gb-- Don't follow false and true branches as we may not be + // able to determine the whole block length in bytes in order + // to compute the block checksum + + // We can follow unconditional jumps if neither Lazy Flusher + // nor Dynamic Code Patches feature is enabled + + // UPDATE: this is no longer permitted since we can decide + // at runtime whether the JIT compiler is used or not + if (IS_CONST_JUMP(i)) + table68k[i].cflow = fl_normal; +#endif + + // Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions + int flags_used = table68k[i].flaglive; + if ( (mnemo == i_Scc) + || (mnemo == i_Bcc) + || (mnemo == i_DBcc) + || (mnemo == i_TRAPcc) + ) { + switch (table68k[i].cc) { + // CC mask: XNZVC + // 8421 + case 0: flags_used = 0x00; break; /* T */ + case 1: flags_used = 0x00; break; /* F */ + case 2: flags_used = 0x05; break; /* HI */ + case 3: flags_used = 0x05; break; /* LS */ + case 4: flags_used = 0x01; break; /* CC */ + case 5: flags_used = 0x01; break; /* CS */ + case 6: flags_used = 0x04; break; /* NE */ + case 7: flags_used = 0x04; break; /* EQ */ + case 8: flags_used = 0x02; break; /* VC */ + case 9: flags_used = 0x02; break; /* VS */ + case 10:flags_used = 0x08; break; /* PL */ + case 11:flags_used = 0x08; break; /* MI */ + case 12:flags_used = 0x0A; break; /* GE */ + case 13:flags_used = 0x0A; break; /* LT */ + case 14:flags_used = 0x0E; break; /* GT */ + case 15:flags_used = 0x0E; break; /* LE */ + } + } + + /* Unconditional jumps don't evaluate condition codes, so they + don't actually use any flags themselves */ + if (IS_CONST_JUMP(i)) + flags_used = 0; + + table68k[i].flaglive = flags_used; + } } static int mismatch; @@ -766,6 +863,8 @@ static void handle_merges (long int opcode) smsk = 7; sbitdst = 8; break; case 5: smsk = 63; sbitdst = 64; break; + case 6: + smsk = 255; sbitdst = 256; break; case 7: smsk = 3; sbitdst = 4; break; default: diff --git a/BasiliskII/src/uae_cpu/readcpu.h b/BasiliskII/src/uae_cpu/readcpu.h index 6594627b..e61850fa 100644 --- a/BasiliskII/src/uae_cpu/readcpu.h +++ b/BasiliskII/src/uae_cpu/readcpu.h @@ -1,3 +1,6 @@ +#ifndef READCPU_H +#define READCPU_H + #ifdef __cplusplus extern "C" { #endif @@ -32,7 +35,8 @@ ENUMDECL { i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES, i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE, i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16, - i_MMUOP + i_MMUOP, + i_EMULOP_RETURN, i_EMULOP } ENUMNAME (instrmnem); extern struct mnemolookup { @@ -52,9 +56,21 @@ ENUMDECL { fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp } ENUMNAME (flaguse); +ENUMDECL { + fl_normal = 0, + fl_branch = 1, + fl_jump = 2, + fl_return = 3, + fl_trap = 4, + fl_compiled = 8, + + /* Instructions that can trap don't mark the end of a block */ + fl_end_block = 3 +} ENUMNAME (cflow_t); + ENUMDECL { bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK, - bits, bitS, bitd, bitD, bitr, bitR, bitz, bitp, lastbit + bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit } ENUMNAME (bitvals); struct instr_def { @@ -68,6 +84,7 @@ struct instr_def { unsigned int flaguse:3; unsigned int flagset:3; } flaginfo[5]; + unsigned char cflow; unsigned char sduse; const char *opcstr; }; @@ -101,7 +118,8 @@ extern struct instr { unsigned int duse:1; unsigned int unused1:1; unsigned int clev:3; - unsigned int unused2:5; + unsigned int cflow:3; + unsigned int unused2:2; } *table68k; extern void read_table68k (void); @@ -112,3 +130,5 @@ extern int nr_cpuop_funcs; #ifdef __cplusplus } #endif + +#endif /* READCPU_H */ diff --git a/BasiliskII/src/uae_cpu/spcflags.h b/BasiliskII/src/uae_cpu/spcflags.h new file mode 100644 index 00000000..53c3b83e --- /dev/null +++ b/BasiliskII/src/uae_cpu/spcflags.h @@ -0,0 +1,89 @@ + /* + * UAE - The Un*x Amiga Emulator + * + * MC68000 emulation + * + * Copyright 1995 Bernd Schmidt + */ + +#ifndef SPCFLAGS_H +#define SPCFLAGS_H + +typedef uae_u32 spcflags_t; + +enum { + SPCFLAG_STOP = 0x01, + SPCFLAG_INT = 0x02, + SPCFLAG_BRK = 0x04, + SPCFLAG_TRACE = 0x08, + SPCFLAG_DOTRACE = 0x10, + SPCFLAG_DOINT = 0x20, + SPCFLAG_JIT_END_COMPILE = 0, + SPCFLAG_JIT_EXEC_RETURN = 0, + SPCFLAG_ALL = SPCFLAG_STOP + | SPCFLAG_INT + | SPCFLAG_BRK + | SPCFLAG_TRACE + | SPCFLAG_DOTRACE + | SPCFLAG_DOINT + | SPCFLAG_JIT_END_COMPILE + | SPCFLAG_JIT_EXEC_RETURN, + SPCFLAG_ALL_BUT_EXEC_RETURN = SPCFLAG_ALL & ~SPCFLAG_JIT_EXEC_RETURN +}; + +#define SPCFLAGS_TEST(m) \ + ((regs.spcflags & (m)) != 0) + +/* Macro only used in m68k_reset() */ +#define SPCFLAGS_INIT(m) do { \ + regs.spcflags = (m); \ +} while (0) + +#if !(ENABLE_EXCLUSIVE_SPCFLAGS) + +#define SPCFLAGS_SET(m) do { \ + regs.spcflags |= (m); \ +} while (0) + +#define SPCFLAGS_CLEAR(m) do { \ + regs.spcflags &= ~(m); \ +} while (0) + +#elif defined(__i386__) && defined(X86_ASSEMBLY) + +#define HAVE_HARDWARE_LOCKS + +#define SPCFLAGS_SET(m) do { \ + __asm__ __volatile__("lock\n\torl %1,%0" : "=m" (regs.spcflags) : "i" ((m))); \ +} while (0) + +#define SPCFLAGS_CLEAR(m) do { \ + __asm__ __volatile__("lock\n\tandl %1,%0" : "=m" (regs.spcflags) : "i" (~(m))); \ +} while (0) + +#elif defined(HAVE_PTHREADS) + +#undef HAVE_HARDWARE_LOCKS + +#include +extern pthread_mutex_t spcflags_lock; + +#define SPCFLAGS_SET(m) do { \ + pthread_mutex_lock(&spcflags_lock); \ + regs.spcflags |= (m); \ + pthread_mutex_unlock(&spcflags_lock); \ +} while (0) + +#define SPCFLAGS_CLEAR(m) do { \ + pthread_mutex_lock(&spcflags_lock); \ + regs.spcflags &= ~(m); \ + pthread_mutex_unlock(&spcflags_lock); \ +} while (0) + +#else + +#error "Can't handle spcflags atomically!" + +#endif + +#endif /* SPCFLAGS_H */ diff --git a/BasiliskII/src/uae_cpu/table68k b/BasiliskII/src/uae_cpu/table68k index a450b3a5..ab9eabe1 100644 --- a/BasiliskII/src/uae_cpu/table68k +++ b/BasiliskII/src/uae_cpu/table68k @@ -4,12 +4,13 @@ % C: condition codes, except F % f: direction % i: immediate +% E: immediate, except 00 (for EmulOp instructions) % I: immediate, except 00 and ff % j: immediate 1..8 % J: immediate 0..15 % k: immediate 0..7 % K: immediate 0..63 -% p: immediate 0..3 (CINV and CPUSH: cache field) +% p: immediate 0..3 (CINV and CPUSH instructions: Cache Field) % s: source mode % S: source reg % d: dest mode @@ -25,7 +26,7 @@ % % Arp: --> -(Ar) % ArP: --> (Ar)+ -% L: (xxx.L) +% L: --> (xxx.L) % % Fields on a line: % 16 chars bitpattern : @@ -45,10 +46,17 @@ % 0 means flag reset % 1 means flag set % ? means programmer was too lazy to check or instruction may trap -% + means instruction is conditional branch % everything else means flag set/used -% / means instruction is unconditional branch/call % x means flag is unknown and well-behaved programs shouldn't check it +% +% Control flow +% two letters, combination of +% - nothing +% T the instruction may trap or cause an exception +% B branch instruction +% J jump instruction +% R return instruction +% % srcaddr status destaddr status : % bitmasks of % 1 means fetched @@ -58,204 +66,209 @@ % instruction % -0000 0000 0011 1100:00:XNZVC:XNZVC:10: ORSR.B #1 -0000 0000 0111 1100:02:?????:?????:10: ORSR.W #1 -0000 0zz0 11ss sSSS:20:?????:?????:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd] -0000 0000 zzdd dDDD:00:-NZ00:-----:13: OR.z #z,d[!Areg] -0000 0010 0011 1100:00:XNZVC:XNZVC:10: ANDSR.B #1 -0000 0010 0111 1100:02:?????:?????:10: ANDSR.W #1 -0000 0010 zzdd dDDD:00:-NZ00:-----:13: AND.z #z,d[!Areg] -0000 0100 zzdd dDDD:00:XNZVC:-----:13: SUB.z #z,d[!Areg] -0000 0110 zzdd dDDD:00:XNZVC:-----:13: ADD.z #z,d[!Areg] -0000 0110 11ss sSSS:20:?????:?????:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd] -0000 0110 11ss sSSS:20:?????:?????:10: RTM s[Dreg,Areg] -0000 1000 00ss sSSS:00:--Z--:-----:11: BTST #1,s[!Areg] -0000 1000 01ss sSSS:00:--Z--:-----:13: BCHG #1,s[!Areg,Immd] -0000 1000 10ss sSSS:00:--Z--:-----:13: BCLR #1,s[!Areg,Immd] -0000 1000 11ss sSSS:00:--Z--:-----:13: BSET #1,s[!Areg,Immd] -0000 1010 0011 1100:00:XNZVC:XNZVC:10: EORSR.B #1 -0000 1010 0111 1100:02:?????:?????:10: EORSR.W #1 -0000 1010 zzdd dDDD:00:-NZ00:-----:13: EOR.z #z,d[!Areg] -0000 1100 zzss sSSS:00:-NZVC:-----:11: CMP.z #z,s[!Areg,Immd] +0000 0000 0011 1100:00:XNZVC:XNZVC:--:10: ORSR.B #1 +0000 0000 0111 1100:02:XNZVC:XNZVC:T-:10: ORSR.W #1 +0000 0zz0 11ss sSSS:20:-?Z?C:-----:T-:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd] +0000 0000 zzdd dDDD:00:-NZ00:-----:--:13: OR.z #z,d[!Areg] +0000 0010 0011 1100:00:XNZVC:XNZVC:--:10: ANDSR.B #1 +0000 0010 0111 1100:02:XNZVC:XNZVC:T-:10: ANDSR.W #1 +0000 0010 zzdd dDDD:00:-NZ00:-----:--:13: AND.z #z,d[!Areg] +0000 0100 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #z,d[!Areg] +0000 0110 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #z,d[!Areg] +0000 0110 11ss sSSS:20:-----:XNZVC:--:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd] +0000 0110 11ss sSSS:20:XNZVC:-----:-R:10: RTM s[Dreg,Areg] +0000 1000 00ss sSSS:00:--Z--:-----:--:11: BTST #1,s[!Areg] +0000 1000 01ss sSSS:00:--Z--:-----:--:13: BCHG #1,s[!Areg,Immd] +0000 1000 10ss sSSS:00:--Z--:-----:--:13: BCLR #1,s[!Areg,Immd] +0000 1000 11ss sSSS:00:--Z--:-----:--:13: BSET #1,s[!Areg,Immd] +0000 1010 0011 1100:00:XNZVC:XNZVC:--:10: EORSR.B #1 +0000 1010 0111 1100:02:XNZVC:XNZVC:T-:10: EORSR.W #1 +0000 1010 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z #z,d[!Areg] +0000 1100 zzss sSSS:00:-NZVC:-----:--:11: CMP.z #z,s[!Areg,Immd] -0000 1010 11ss sSSS:20:?????:?????:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1100 11ss sSSS:20:?????:?????:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1100 1111 1100:20:?????:?????:10: CAS2.W #2 -0000 1110 zzss sSSS:22:?????:?????:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1110 11ss sSSS:20:?????:?????:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16] -0000 1110 1111 1100:20:?????:?????:10: CAS2.L #2 +0000 1010 11ss sSSS:20:-NZVC:-----:--:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1100 11ss sSSS:20:-NZVC:-----:--:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1100 1111 1100:20:-NZVC:-----:--:10: CAS2.W #2 +0000 1110 zzss sSSS:22:-----:-----:T-:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1110 11ss sSSS:20:-NZVC:-----:--:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16] +0000 1110 1111 1100:20:-NZVC:-----:--:10: CAS2.L #2 -0000 rrr1 00dd dDDD:00:-----:-----:12: MVPMR.W d[Areg-Ad16],Dr -0000 rrr1 01dd dDDD:00:-----:-----:12: MVPMR.L d[Areg-Ad16],Dr -0000 rrr1 10dd dDDD:00:-----:-----:12: MVPRM.W Dr,d[Areg-Ad16] -0000 rrr1 11dd dDDD:00:-----:-----:12: MVPRM.L Dr,d[Areg-Ad16] -0000 rrr1 00ss sSSS:00:--Z--:-----:11: BTST Dr,s[!Areg] -0000 rrr1 01ss sSSS:00:--Z--:-----:13: BCHG Dr,s[!Areg,Immd] -0000 rrr1 10ss sSSS:00:--Z--:-----:13: BCLR Dr,s[!Areg,Immd] -0000 rrr1 11ss sSSS:00:--Z--:-----:13: BSET Dr,s[!Areg,Immd] +0000 rrr1 00dd dDDD:00:-----:-----:--:12: MVPMR.W d[Areg-Ad16],Dr +0000 rrr1 01dd dDDD:00:-----:-----:--:12: MVPMR.L d[Areg-Ad16],Dr +0000 rrr1 10dd dDDD:00:-----:-----:--:12: MVPRM.W Dr,d[Areg-Ad16] +0000 rrr1 11dd dDDD:00:-----:-----:--:12: MVPRM.L Dr,d[Areg-Ad16] +0000 rrr1 00ss sSSS:00:--Z--:-----:--:11: BTST Dr,s[!Areg] +0000 rrr1 01ss sSSS:00:--Z--:-----:--:13: BCHG Dr,s[!Areg,Immd] +0000 rrr1 10ss sSSS:00:--Z--:-----:--:13: BCLR Dr,s[!Areg,Immd] +0000 rrr1 11ss sSSS:00:--Z--:-----:--:13: BSET Dr,s[!Areg,Immd] -0001 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.B s,d[!Areg] -0010 DDDd ddss sSSS:00:-----:-----:12: MOVEA.L s,d[Areg] -0010 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.L s,d[!Areg] -0011 DDDd ddss sSSS:00:-----:-----:12: MOVEA.W s,d[Areg] -0011 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.W s,d[!Areg] +0001 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.B s,d[!Areg] +0010 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.L s,d[Areg] +0010 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.L s,d[!Areg] +0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg] +0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg] -0100 0000 zzdd dDDD:00:XxZxC:X-Z--:30: NEGX.z d[!Areg] -0100 0000 11dd dDDD:01:?????:?????:10: MVSR2.W d[!Areg] -0100 0010 zzdd dDDD:00:-0100:-----:20: CLR.z d[!Areg] -0100 0010 11dd dDDD:10:?????:?????:10: MVSR2.B d[!Areg] -0100 0100 zzdd dDDD:00:XNZVC:-----:30: NEG.z d[!Areg] -0100 0100 11ss sSSS:00:XNZVC:-----:10: MV2SR.B s[!Areg] -0100 0110 zzdd dDDD:00:-NZ00:-----:30: NOT.z d[!Areg] -0100 0110 11ss sSSS:02:?????:?????:10: MV2SR.W s[!Areg] -0100 1000 0000 1rrr:20:-----:-----:31: LINK.L Ar,#2 -0100 1000 00dd dDDD:00:X?Z?C:X-Z--:30: NBCD.B d[!Areg] -0100 1000 0100 1kkk:20:?????:?????:10: BKPT #k -0100 1000 01ss sSSS:00:-NZ00:-----:30: SWAP.W s[Dreg] -0100 1000 01ss sSSS:00:-----:-----:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 1000 10dd dDDD:00:-NZ00:-----:30: EXT.W d[Dreg] -0100 1000 10dd dDDD:00:-----:-----:02: MVMLE.W #1,d[!Dreg,Areg,Aipi] -0100 1000 11dd dDDD:00:-NZ00:-----:30: EXT.L d[Dreg] -0100 1000 11dd dDDD:00:-----:-----:02: MVMLE.L #1,d[!Dreg,Areg,Aipi] -0100 1001 11dd dDDD:00:-NZ00:-----:30: EXT.B d[Dreg] -0100 1010 zzss sSSS:00:-NZ00:-----:10: TST.z s -0100 1010 11dd dDDD:00:?????:?????:30: TAS.B d[!Areg] -0100 1010 1111 1100:00:?????:?????:00: ILLEGAL -0100 1100 00ss sSSS:20:-NZVC:-----:13: MULL.L #1,s[!Areg] -0100 1100 01ss sSSS:20:?????:?????:13: DIVL.L #1,s[!Areg] -0100 1100 10ss sSSS:00:-----:-----:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd] -0100 1100 11ss sSSS:00:-----:-----:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd] -0100 1110 0100 JJJJ:00:-----:XNZVC:10: TRAP #J -0100 1110 0101 0rrr:00:-----:-----:31: LINK.W Ar,#1 -0100 1110 0101 1rrr:00:-----:-----:30: UNLK.L Ar -0100 1110 0110 0rrr:02:-----:-----:10: MVR2USP.L Ar -0100 1110 0110 1rrr:02:-----:-----:20: MVUSP2R.L Ar -0100 1110 0111 0000:02:-----:-----:00: RESET -0100 1110 0111 0001:00:-----:-----:00: NOP -0100 1110 0111 0010:02:XNZVC:-----:10: STOP #1 -0100 1110 0111 0011:02:XNZVC:-----:00: RTE -0100 1110 0111 0100:00:?????:?????:10: RTD #1 -0100 1110 0111 0101:00:-----:-----:00: RTS -0100 1110 0111 0110:00:-----:XNZVC:00: TRAPV -0100 1110 0111 0111:00:XNZVC:-----:00: RTR -0100 1110 0111 1010:12:?????:?????:10: MOVEC2 #1 -0100 1110 0111 1011:12:?????:?????:10: MOVE2C #1 -0100 1110 10ss sSSS:00://///://///:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 rrr1 00ss sSSS:00:?????:?????:11: CHK.L s[!Areg],Dr -0100 rrr1 10ss sSSS:00:?????:?????:11: CHK.W s[!Areg],Dr -0100 1110 11ss sSSS:00://///://///:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd] -0100 rrr1 11ss sSSS:00:-----:-----:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar +0100 0000 zzdd dDDD:00:XxZxC:X-Z--:--:30: NEGX.z d[!Areg] +0100 0000 11dd dDDD:01:-----:XNZVC:T-:10: MVSR2.W d[!Areg] +0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg] +0100 0010 11dd dDDD:10:-----:XNZVC:--:10: MVSR2.B d[!Areg] +0100 0100 zzdd dDDD:00:XNZVC:-----:--:30: NEG.z d[!Areg] +0100 0100 11ss sSSS:00:XNZVC:-----:--:10: MV2SR.B s[!Areg] +0100 0110 zzdd dDDD:00:-NZ00:-----:--:30: NOT.z d[!Areg] +0100 0110 11ss sSSS:02:XNZVC:XNZVC:T-:10: MV2SR.W s[!Areg] +0100 1000 0000 1rrr:20:-----:-----:--:31: LINK.L Ar,#2 +0100 1000 00dd dDDD:00:X?Z?C:X-Z--:--:30: NBCD.B d[!Areg] +0100 1000 0100 1kkk:20:-----:-----:T-:10: BKPT #k +0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg] +0100 1000 01ss sSSS:00:-----:-----:--:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg] +0100 1000 10dd dDDD:00:-----:-----:--:02: MVMLE.W #1,d[!Dreg,Areg,Aipi] +0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg] +0100 1000 11dd dDDD:00:-----:-----:--:02: MVMLE.L #1,d[!Dreg,Areg,Aipi] +0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg] +0100 1010 zzss sSSS:00:-NZ00:-----:--:10: TST.z s +0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg] +0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL +0100 1100 00ss sSSS:20:-NZVC:-----:--:13: MULL.L #1,s[!Areg] +0100 1100 01ss sSSS:20:-NZV0:-----:T-:13: DIVL.L #1,s[!Areg] +0100 1100 10ss sSSS:00:-----:-----:--:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd] +0100 1100 11ss sSSS:00:-----:-----:--:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd] +0100 1110 0100 JJJJ:00:-----:XNZVC:--:10: TRAP #J +0100 1110 0101 0rrr:00:-----:-----:--:31: LINK.W Ar,#1 +0100 1110 0101 1rrr:00:-----:-----:--:30: UNLK.L Ar +0100 1110 0110 0rrr:02:-----:-----:T-:10: MVR2USP.L Ar +0100 1110 0110 1rrr:02:-----:-----:T-:20: MVUSP2R.L Ar +0100 1110 0111 0000:02:-----:-----:T-:00: RESET +0100 1110 0111 0001:00:-----:-----:--:00: NOP +0100 1110 0111 0010:02:XNZVC:-----:T-:10: STOP #1 +0100 1110 0111 0011:02:XNZVC:-----:TR:00: RTE +0100 1110 0111 0100:00:-----:-----:-R:10: RTD #1 +0100 1110 0111 0101:00:-----:-----:-R:00: RTS +0100 1110 0111 0110:00:-----:XNZVC:T-:00: TRAPV +0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR +0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1 +0100 1110 0111 1011:12:-----:-----:T-:10: MOVE2C #1 +0100 1110 10ss sSSS:00:-----:-----:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 rrr1 00ss sSSS:00:-N???:-----:T-:11: CHK.L s[!Areg],Dr +0100 rrr1 10ss sSSS:00:-N???:-----:T-:11: CHK.W s[!Areg],Dr +0100 1110 11ss sSSS:00:-----:-----:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd] +0100 rrr1 11ss sSSS:00:-----:-----:--:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar -0101 jjj0 01dd dDDD:00:-----:-----:13: ADDA.W #j,d[Areg] -0101 jjj0 10dd dDDD:00:-----:-----:13: ADDA.L #j,d[Areg] -0101 jjj0 zzdd dDDD:00:XNZVC:-----:13: ADD.z #j,d[!Areg] -0101 jjj1 01dd dDDD:00:-----:-----:13: SUBA.W #j,d[Areg] -0101 jjj1 10dd dDDD:00:-----:-----:13: SUBA.L #j,d[Areg] -0101 jjj1 zzdd dDDD:00:XNZVC:-----:13: SUB.z #j,d[!Areg] -0101 cccc 1100 1rrr:00:-----:-++++:31: DBcc.W Dr,#1 -0101 cccc 11dd dDDD:00:-----:-++++:20: Scc.B d[!Areg] -0101 cccc 1111 1010:20:?????:?????:10: TRAPcc #1 -0101 cccc 1111 1011:20:?????:?????:10: TRAPcc #2 -0101 cccc 1111 1100:20:?????:?????:00: TRAPcc +0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg] +0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg] +0101 jjj0 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #j,d[!Areg] +0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg] +0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg] +0101 jjj1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #j,d[!Areg] + +0101 cccc 1100 1rrr:00:-----:-????:-B:31: DBcc.W Dr,#1 +0101 cccc 11dd dDDD:00:-----:-????:--:20: Scc.B d[!Areg] +0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1 +0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2 +0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc % Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal % instruction exceptions when compiling a 68000 only emulation, which isn't % what we want either. -0110 0001 0000 0000:00://///://///:40: BSR.W #1 -0110 0001 IIII IIII:00://///://///:40: BSR.B #i -0110 0001 1111 1111:00://///://///:40: BSR.L #2 -0110 CCCC 0000 0000:00:-----:-++++:40: Bcc.W #1 -0110 CCCC IIII IIII:00:-----:-++++:40: Bcc.B #i -0110 CCCC 1111 1111:00:-----:-++++:40: Bcc.L #2 +0110 0001 0000 0000:00:-----:-----:-B:40: BSR.W #1 +0110 0001 IIII IIII:00:-----:-----:-B:40: BSR.B #i +0110 0001 1111 1111:00:-----:-----:-B:40: BSR.L #2 +0110 CCCC 0000 0000:00:-----:-????:-B:40: Bcc.W #1 +0110 CCCC IIII IIII:00:-----:-????:-B:40: Bcc.B #i +0110 CCCC 1111 1111:00:-----:-????:-B:40: Bcc.L #2 -0111 rrr0 iiii iiii:00:-NZ00:-----:12: MOVE.L #i,Dr +0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr -1000 rrr0 zzss sSSS:00:-NZ00:-----:13: OR.z s[!Areg],Dr -1000 rrr0 11ss sSSS:00:?????:?????:13: DIVU.W s[!Areg],Dr -1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Dreg],Dr -1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Areg-Apdi],Arp -1000 rrr1 zzdd dDDD:00:-NZ00:-----:13: OR.z Dr,d[!Areg,Dreg] -1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Dreg],Dr -1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Areg-Apdi],Arp -1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Dreg],Dr -1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Areg-Apdi],Arp -1000 rrr1 11ss sSSS:00:?????:?????:13: DIVS.W s[!Areg],Dr +1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr +1000 rrr0 11ss sSSS:00:-NZV0:-----:T-:13: DIVU.W s[!Areg],Dr +1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Dreg],Dr +1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp +1000 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: OR.z Dr,d[!Areg,Dreg] +1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr +1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp +1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr +1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp +1000 rrr1 11ss sSSS:00:-NZV0:-----:T-:13: DIVS.W s[!Areg],Dr -1001 rrr0 zzss sSSS:00:XNZVC:-----:13: SUB.z s,Dr -1001 rrr0 11ss sSSS:00:-----:-----:13: SUBA.W s,Ar -1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Dreg],Dr -1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Areg-Apdi],Arp -1001 rrr1 zzdd dDDD:00:XNZVC:-----:13: SUB.z Dr,d[!Areg,Dreg] -1001 rrr1 11ss sSSS:00:-----:-----:13: SUBA.L s,Ar +1001 rrr0 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr +1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar +1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr +1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp +1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg] +1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar -1011 rrr0 zzss sSSS:00:-NZVC:-----:11: CMP.z s,Dr -1011 rrr0 11ss sSSS:00:-NZVC:-----:11: CMPA.W s,Ar -1011 rrr1 11ss sSSS:00:-NZVC:-----:11: CMPA.L s,Ar -1011 rrr1 zzdd dDDD:00:-NZVC:-----:11: CMPM.z d[Areg-Aipi],ArP -1011 rrr1 zzdd dDDD:00:-NZ00:-----:13: EOR.z Dr,d[!Areg] +1011 rrr0 zzss sSSS:00:-NZVC:-----:--:11: CMP.z s,Dr +1011 rrr0 11ss sSSS:00:-NZVC:-----:--:11: CMPA.W s,Ar +1011 rrr1 11ss sSSS:00:-NZVC:-----:--:11: CMPA.L s,Ar +1011 rrr1 zzdd dDDD:00:-NZVC:-----:--:11: CMPM.z d[Areg-Aipi],ArP +1011 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z Dr,d[!Areg] -1100 rrr0 zzss sSSS:00:-NZ00:-----:13: AND.z s[!Areg],Dr -1100 rrr0 11ss sSSS:00:-NZ00:-----:13: MULU.W s[!Areg],Dr -1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: ABCD.B d[Dreg],Dr -1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: ABCD.B d[Areg-Apdi],Arp -1100 rrr1 zzdd dDDD:00:-NZ00:-----:13: AND.z Dr,d[!Areg,Dreg] -1100 rrr1 01dd dDDD:00:-----:-----:33: EXG.L Dr,d[Dreg] -1100 rrr1 01dd dDDD:00:-----:-----:33: EXG.L Ar,d[Areg] -1100 rrr1 10dd dDDD:00:-----:-----:33: EXG.L Dr,d[Areg] -1100 rrr1 11ss sSSS:00:-NZ00:-----:13: MULS.W s[!Areg],Dr +1100 rrr0 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr +1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W s[!Areg],Dr +1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Dreg],Dr +1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp +1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg] +1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg] +1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg] +1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg] +1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr -1101 rrr0 zzss sSSS:00:XNZVC:-----:13: ADD.z s,Dr -1101 rrr0 11ss sSSS:00:-----:-----:13: ADDA.W s,Ar -1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: ADDX.z d[Dreg],Dr -1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: ADDX.z d[Areg-Apdi],Arp -1101 rrr1 zzdd dDDD:00:XNZVC:-----:13: ADD.z Dr,d[!Areg,Dreg] -1101 rrr1 11ss sSSS:00:-----:-----:13: ADDA.L s,Ar +1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr +1101 rrr0 11ss sSSS:00:-----:-----:--:13: ADDA.W s,Ar +1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr +1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp +1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg] +1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar -1110 jjjf zz00 0RRR:00:XNZVC:-----:13: ASf.z #j,DR -1110 jjjf zz00 1RRR:00:XNZ0C:-----:13: LSf.z #j,DR -1110 jjjf zz01 0RRR:00:XNZ0C:X----:13: ROXf.z #j,DR -1110 jjjf zz01 1RRR:00:-NZ0C:-----:13: ROf.z #j,DR -1110 rrrf zz10 0RRR:00:XNZVC:X----:13: ASf.z Dr,DR -1110 rrrf zz10 1RRR:00:XNZ0C:X----:13: LSf.z Dr,DR -1110 rrrf zz11 0RRR:00:XNZ0C:X----:13: ROXf.z Dr,DR -1110 rrrf zz11 1RRR:00:-NZ0C:-----:13: ROf.z Dr,DR -1110 000f 11dd dDDD:00:XNZVC:-----:13: ASfW.W d[!Dreg,Areg] -1110 001f 11dd dDDD:00:XNZ0C:-----:13: LSfW.W d[!Dreg,Areg] -1110 010f 11dd dDDD:00:XNZ0C:X----:13: ROXfW.W d[!Dreg,Areg] -1110 011f 11dd dDDD:00:-NZ0C:-----:13: ROfW.W d[!Dreg,Areg] +1110 jjjf zz00 0RRR:00:XNZVC:-----:--:13: ASf.z #j,DR +1110 jjjf zz00 1RRR:00:XNZ0C:-----:--:13: LSf.z #j,DR +1110 jjjf zz01 0RRR:00:XNZ0C:X----:--:13: ROXf.z #j,DR +1110 jjjf zz01 1RRR:00:-NZ0C:-----:--:13: ROf.z #j,DR +1110 rrrf zz10 0RRR:00:XNZVC:-----:--:13: ASf.z Dr,DR +1110 rrrf zz10 1RRR:00:XNZ0C:-----:--:13: LSf.z Dr,DR +1110 rrrf zz11 0RRR:00:XNZ0C:X----:--:13: ROXf.z Dr,DR +1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR +1110 000f 11dd dDDD:00:XNZVC:-----:--:13: ASfW.W d[!Dreg,Areg] +1110 001f 11dd dDDD:00:XNZ0C:-----:--:13: LSfW.W d[!Dreg,Areg] +1110 010f 11dd dDDD:00:XNZ0C:X----:--:13: ROXfW.W d[!Dreg,Areg] +1110 011f 11dd dDDD:00:-NZ0C:-----:--:13: ROfW.W d[!Dreg,Areg] -1110 1000 11ss sSSS:20:?????:?????:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd] -1110 1001 11ss sSSS:20:?????:?????:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd] -1110 1010 11ss sSSS:20:?????:?????:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] -1110 1011 11ss sSSS:20:?????:?????:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd] -1110 1100 11ss sSSS:20:?????:?????:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] -1110 1101 11ss sSSS:20:?????:?????:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd] -1110 1110 11ss sSSS:20:?????:?????:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] -1110 1111 11ss sSSS:20:?????:?????:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1000 11ss sSSS:20:-NZ00:-----:--:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd] +1110 1001 11ss sSSS:20:-NZ00:-----:--:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd] +1110 1010 11ss sSSS:20:-NZ00:-----:--:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1011 11ss sSSS:20:-NZ00:-----:--:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd] +1110 1100 11ss sSSS:20:-NZ00:-----:--:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1101 11ss sSSS:20:-NZ00:-----:--:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd] +1110 1110 11ss sSSS:20:-NZ00:-----:--:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] +1110 1111 11ss sSSS:20:-NZ00:-----:--:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16] % floating point co processor -1111 0010 00ss sSSS:30:?????:?????:11: FPP #1,s -1111 0010 01ss sSSS:30:?????:?????:11: FDBcc #1,s[Areg-Dreg] -1111 0010 01ss sSSS:30:?????:?????:11: FScc #1,s[!Areg,Immd,PC8r,PC16] -1111 0010 0111 1010:30:?????:?????:10: FTRAPcc #1 -1111 0010 0111 1011:30:?????:?????:10: FTRAPcc #2 -1111 0010 0111 1100:30:?????:?????:00: FTRAPcc -1111 0010 10KK KKKK:30:?????:?????:11: FBcc #K,#1 -1111 0010 11KK KKKK:30:?????:?????:11: FBcc #K,#2 -1111 0011 00ss sSSS:32:?????:?????:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16] -1111 0011 01ss sSSS:32:?????:?????:10: FRESTORE s[!Dreg,Areg,Apdi,Immd] +1111 0010 00ss sSSS:30:-----:-----:--:11: FPP #1,s +1111 0010 01ss sSSS:30:-----:-----:-B:11: FDBcc #1,s[Areg-Dreg] +1111 0010 01ss sSSS:30:-----:-----:--:11: FScc #1,s[!Areg,Immd,PC8r,PC16] +1111 0010 0111 1010:30:-----:-----:T-:10: FTRAPcc #1 +1111 0010 0111 1011:30:-----:-----:T-:10: FTRAPcc #2 +1111 0010 0111 1100:30:-----:-----:T-:00: FTRAPcc +1111 0010 10KK KKKK:30:-----:-----:-B:11: FBcc #K,#1 +1111 0010 11KK KKKK:30:-----:-----:-B:11: FBcc #K,#2 +1111 0011 00ss sSSS:32:-----:-----:--:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16] +1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd] % 68040 instructions -1111 0101 iiii iSSS:40:?????:?????:11: MMUOP #i,s -1111 0100 pp00 1rrr:42:-----:-----:02: CINVL #p,Ar -1111 0100 pp01 0rrr:42:-----:-----:02: CINVP #p,Ar -1111 0100 pp01 1rrr:42:-----:-----:00: CINVA #p -1111 0100 pp10 1rrr:42:-----:-----:02: CPUSHL #p,Ar -1111 0100 pp11 0rrr:42:-----:-----:02: CPUSHP #p,Ar -1111 0100 pp11 1rrr:42:-----:-----:00: CPUSHA #p +1111 0101 iiii iSSS:40:-----:-----:T-:11: MMUOP #i,s +1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar +1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar +1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p +1111 0100 pp10 1rrr:42:-----:-----:T-:02: CPUSHL #p,Ar +1111 0100 pp11 0rrr:42:-----:-----:T-:02: CPUSHP #p,Ar +1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p % destination register number is encoded in the following word -1111 0110 0010 0rrr:40:-----:-----:12: MOVE16 ArP,AxP -1111 0110 00ss sSSS:40:-----:-----:12: MOVE16 s[Dreg-Aipi],L -1111 0110 00dd dDDD:40:-----:-----:12: MOVE16 L,d[Areg-Aipi] -1111 0110 00ss sSSS:40:-----:-----:12: MOVE16 s[Aind],L -1111 0110 00dd dDDD:40:-----:-----:12: MOVE16 L,d[Aipi-Aind] +1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP +1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],L +1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Areg-Aipi] +1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],L +1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Aipi-Aind] + +% EmulOp instructions +0111 0001 0000 0000:00:-----:-----:-R:00: EMULOP_RETURN +0111 0001 EEEE EEEE:00:-----:-----:-J:10: EMULOP #E