- Merge with Basilisk II/JIT cpu core, interpretive part for now

- Clean use of USE_PREFETCH_BUFFER macro and dependent bits
This commit is contained in:
gbeauche 2002-09-01 15:17:13 +00:00
parent 4f8d06b671
commit 7972082c56
10 changed files with 811 additions and 356 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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"

View File

@ -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.h>
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)

View File

@ -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(&regs.prefetch);
return (do_get_mem_word (((uae_u16 *)&regs.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 */

View File

@ -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

View File

@ -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:

View File

@ -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 */

View File

@ -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 <pthread.h>
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 */

View File

@ -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