]> Shamusworld >> Repos - virtualjaguar/commitdiff
Added new 68000 cpu core based on UAE's 68000. Here be dragons. ;-)
authorShamus Hammons <jlhamm@acm.org>
Thu, 3 Nov 2011 21:30:52 +0000 (21:30 +0000)
committerShamus Hammons <jlhamm@acm.org>
Thu, 3 Nov 2011 21:30:52 +0000 (21:30 +0000)
22 files changed:
Makefile
docs/README
docs/WHATSNEW
src/file.cpp
src/gui/about.cpp
src/jaguar.cpp
src/m68000/Makefile [new file with mode: 0644]
src/m68000/build68k.c [new file with mode: 0644]
src/m68000/cpudefs.h [new file with mode: 0644]
src/m68000/cpuextra.c [new file with mode: 0644]
src/m68000/cpuextra.h [new file with mode: 0644]
src/m68000/gencpu.c [new file with mode: 0644]
src/m68000/inlines.h [new file with mode: 0644]
src/m68000/m68kdasm.c [new file with mode: 0644]
src/m68000/m68kinterface.c [new file with mode: 0644]
src/m68000/m68kinterface.h [new file with mode: 0644]
src/m68000/readcpu.c [new file with mode: 0644]
src/m68000/readcpu.h [new file with mode: 0644]
src/m68000/sysdeps.h [new file with mode: 0644]
src/m68000/table68k [new file with mode: 0644]
src/m68kconf.h
virtualjaguar.pro

index d1cb758d830425b3fb0d6da19f6aacae331d0448..761360af08a7e04c7949bffe434c0b766de00ee0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,10 @@ endif
 all: prepare virtualjaguar
        @echo -e "\033[01;33m***\033[00;32m Success!\033[00m"
 
-prepare:
+obj:
+       @mkdir obj
+
+prepare: obj
        @echo -e "\033[01;33m***\033[00;32m Preparing to compile Virtual Jaguar...\033[00m"
 #      @echo "#define VJ_RELEASE_VERSION \"v2.0.2\"" > src/version.h
 #      @echo "#define VJ_RELEASE_SUBVERSION \"Final\"" >> src/version.h
@@ -36,9 +39,15 @@ makefile-qt: virtualjaguar.pro
        @echo -e "\033[01;33m***\033[00;32m Creating Qt makefile...\033[00m"
        qmake $(QMAKE_EXTRA) virtualjaguar.pro -o makefile-qt
 
-libs: obj/libmusashi.a obj/libjaguarcore.a
+#libs: obj/libmusashi.a obj/libjaguarcore.a
+libs: obj/libm68k.a obj/libjaguarcore.a
        @echo -e "\033[01;33m***\033[00;32m Libraries successfully made.\033[00m"
 
+obj/libm68k.a: src/m68000/Makefile sources
+       @echo -e "\033[01;33m***\033[00;32m Making Customized UAE 68K Core...\033[00m"
+       @$(MAKE) -C src/m68000
+       @cp src/m68000/obj/libm68k.a obj/
+
 obj/libmusashi.a: musashi.mak sources
        @echo -e "\033[01;33m***\033[00;32m Making Musashi...\033[00m"
        $(MAKE) -f musashi.mak
@@ -47,11 +56,12 @@ obj/libjaguarcore.a: jaguarcore.mak sources
        @echo -e "\033[01;33m***\033[00;32m Making Virtual Jaguar core...\033[00m"
        $(MAKE) -f jaguarcore.mak
 
-sources: src/*.h src/*.cpp src/*.c
+sources: src/*.h src/*.cpp src/*.c src/m68000/*.c src/m68000/*.h
 
 clean:
        @echo -ne "\033[01;33m***\033[00;32m Cleaning out the garbage...\033[00m"
        @-rm -rf ./obj
+       @-rm -rf ./src/m68000/obj
        @-rm -rf makefile-qt
        @-rm -rf virtualjaguar
        @-$(FIND) . -name "*~" -exec rm -f {} \;
index 5e5d3b17ee7ce9ed9277192002a3b861a056d773..9f75f917909acf14bd08fd40fbbb23543d878bfd 100644 (file)
@@ -15,21 +15,18 @@ software requirements.
 
 The use of this software is entirely at your own risk. While it won't rape
 your dog, it might do other nasty things. We can't be held responsible for
-damage done to you hardware and/or software. You may only use the ROM images if
-you own the cartridges itself. The use of Commercial ROMs without owning the
+damage done to your hardware and/or software. You may only use the ROM images
+if you own the cartridges itself. The use of commercial ROMs without owning the
 original cartridge is illegal in most countries and could result in fines
 and/or legal actions.
 
-This software is released under the GPL v3 or later. For more information I
-direct you to the GPLv3 file. You may hack/change the code anyway you like. You
-may not commercially sell this software. If you make changes, release the
-source code to the public and send the changes you made to the original
-authors.
-
 The products, trademarks and/or brands used in these documents and/or
 sourcecode are owned by their respective companies and/or successors in
 interest.
 
+This software is released under the GPL v3 or later. For more information, read
+the GPLv3 file.
+
 ----------------------------------------------------------------
 - IMPORTANT NOTE ABOUT JAGUAR FILE FORMATS--READ THIS OR ELSE! -
 ----------------------------------------------------------------
index 72625b0a57e8a52540324344758a7dfa1885cc70..68ece940736eb30c257eae51c48129a9c67113af 100644 (file)
@@ -3,6 +3,8 @@ Virtual Jaguar v2.0.2 GCC/Qt
 
 * Fixed problem on OP with 24BPP bitmaps. [Shamus]
 * Cosmetic GUI fixes. [Shamus]
+* Switched to UAE 68000 CPU core. [Shamus]
+
 
 Virtual Jaguar v2.0.1 GCC/Qt
 ----------------------------
@@ -14,6 +16,7 @@ Virtual Jaguar v2.0.1 GCC/Qt
   [Shamus]
 * Miscellaneous documentation fixes. [Shamus]
 
+
 Virtual Jaguar v2.0.0 GCC/Qt
 ----------------------------
 
index 7fd96ef59edaad467be216dbc7e9875928aac9c7..71f33e7199ad6bd2b59088c2d3880990ddfba6e5 100644 (file)
@@ -217,7 +217,7 @@ bool AlpineLoadFile(char * path)
 // Maybe instead of this, we could try requiring the STUBULATOR ROM? Just a thought...
        // Try setting the vector to say, $1000 and putting an instruction there that loops forever:
        // This kludge works! Yeah!
-       SET32(jaguarMainRAM, 0x10, 0x00001000);
+       SET32(jaguarMainRAM, 0x10, 0x00001000);         // Set Exception #4 (Illegal Instruction)
        SET16(jaguarMainRAM, 0x1000, 0x60FE);           // Here: bra Here
 
        return true;
@@ -307,7 +307,8 @@ uint32 GetFileFromZIP(const char * zipFile, FileType type, uint8 * &buffer)
 
                if ((type == FT_SOFTWARE) && (CheckExtension(ze->name, ".j64")
                        || CheckExtension(ze->name, ".rom") || CheckExtension(ze->name, ".abs")
-                       || CheckExtension(ze->name, ".cof") || CheckExtension(ze->name, ".jag")))
+                       || CheckExtension(ze->name, ".cof") || CheckExtension(ze->name, ".coff")
+                       || CheckExtension(ze->name, ".jag")))
                {
                        found = true;
                        WriteLog("FILE: Found software file '%s'.\n", ze->name);
index c9588ead7f43b3500530cd6477b1b5b753dcb906..1e11561479f8a686703283f83682b8b2341cd49c 100644 (file)
@@ -33,7 +33,7 @@ AboutWindow::AboutWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Dialog)
        image->setPixmap(QPixmap(":/res/vj_title_small.png"));
        layout->addWidget(image);
 
-       QString s;// = QString("");
+       QString s;
        s.append(tr(
                "<table>"
                "<tr><td align='right'><b>Version: </b></td><td>"
@@ -49,7 +49,7 @@ AboutWindow::AboutWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Dialog)
                "<br><br>"
                "<b>Aaron Giles</b> for the original CoJag sources<br>"
                "<b>David Raingeard</b> for the original Virtual Jaguar sources<br>"
-               "<b>Karl Stenerud</b> for his Musashi 68K emulator<br>"
+               "<b>Bernd Schmidt</b> for his UAE 68K emulator<br>"
                "<b>Sam Lantinga</b> for his amazing SDL libraries<br>"
                "<b>Ryan C. Gordon</b> for Virtual Jaguar's web presence<br>"
                "<b>Curt Vendel</b> for various Jaguar & other goodies (you <i>rock!</i>)<br>"
index 268befde8a1066121820e6219c06a47cbf6bbde1..75ece207b3049f11eca14c83261fb4a0ca715f4c 100644 (file)
@@ -88,6 +88,37 @@ static bool start = false;
 void M68KInstructionHook(void)
 {
        uint32 m68kPC = m68k_get_reg(NULL, M68K_REG_PC);
+// Temp, for comparing...
+{
+/*     static char buffer[2048];//, mem[64];
+       m68k_disassemble(buffer, m68kPC, M68K_CPU_TYPE_68000);
+       printf("%08X: %s\n", m68kPC, buffer);//*/
+}
+//JaguarDasm(m68kPC, 1);
+//Testing Hover Strike...
+#if 0
+//Dasm(regs.pc, 1);
+static int hitCount = 0;
+static int inRoutine = 0;
+static int instSeen;
+
+//if (regs.pc == 0x80340A)
+if (m68kPC == 0x803416)
+{
+       hitCount++;
+       inRoutine = 1;
+       instSeen = 0;
+       printf("%i: $80340A start. A0=%08X, A1=%08X ", hitCount, m68k_get_reg(NULL, M68K_REG_A0), m68k_get_reg(NULL, M68K_REG_A1));
+}
+else if (m68kPC == 0x803422)
+{
+       inRoutine = 0;
+       printf("(%i instructions)\n", instSeen);
+}
+
+if (inRoutine)
+       instSeen++;
+#endif
 
 // For tracebacks...
 // Ideally, we'd save all the registers as well...
@@ -854,7 +885,7 @@ int irq_ack_handler(int level)
        // Tracing the IPL lines on the Jaguar schematic yields the following:
        // IPL1 is connected to INTL on TOM (OUT to 68K)
        // IPL0-2 are also tied to Vcc via 4.7K resistors!
-       // (DINT on TOM goes into DINT on JERRY (IN from Jerry))
+       // (DINT on TOM goes into DINT on JERRY (IN Tom from Jerry))
        // There doesn't seem to be any other path to IPL0 or 2 on the schematic, which means
        // that *all* IRQs to the 68K are routed thru TOM at level 2. Which means they're all maskable.
 
@@ -1054,6 +1085,9 @@ void m68k_write_memory_8(unsigned int address, unsigned int value)
 /*if (effect_start)
        if (address >= 0x18FA70 && address < (0x18FA70 + 8000))
                WriteLog("M68K: Byte %02X written at %08X by 68K\n", value, address);//*/
+//$53D0
+/*if (address >= 0x53D0 && address <= 0x53FF)
+       printf("M68K: Writing byte $%02X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
 
 #ifndef USE_NEW_MMU
        if ((address >= 0x000000) && (address <= 0x3FFFFF))
@@ -1117,6 +1151,9 @@ if (address == 0xF02110)
 /*     if (address == 0x51136 || address == 0x51138 || address == 0xFB074 || address == 0xFB076
                || address == 0x1AF05E)
                WriteLog("[WM16  PC=%08X] Addr: %08X, val: %04X\n", m68k_get_reg(NULL, M68K_REG_PC), address, value);//*/
+//$53D0
+/*if (address >= 0x53D0 && address <= 0x53FF)
+       printf("M68K: Writing word $%04X at $%08X, PC=$%08X\n", value, address, m68k_get_reg(NULL, M68K_REG_PC));//*/
 
 #ifndef USE_NEW_MMU
        if ((address >= 0x000000) && (address <= 0x3FFFFE))
@@ -1777,8 +1814,8 @@ void JaguarDone(void)
        JaguarDasm(0x802000, 6000);
        WriteLog("\n");//*/
 #endif
-/*     WriteLog("\n\nM68000 disassembly at $080000...\n");
-       JaguarDasm(0x080000, 10000);
+/*     WriteLog("\n\nM68000 disassembly at $802000...\n");
+       JaguarDasm(0x802000, 10000);
        WriteLog("\n");//*/
 }
 
diff --git a/src/m68000/Makefile b/src/m68000/Makefile
new file mode 100644 (file)
index 0000000..8e45772
--- /dev/null
@@ -0,0 +1,82 @@
+#
+# Makefile for modified UAE 68000 CPU core
+#
+# by James Hammons
+# (C) 2011 Underground Software
+#
+# This makefile is released under the GPLv3 or later
+#
+
+CC      := gcc
+LD      := gcc
+AR      := ar
+ARFLAGS := -rs
+
+# Note that we use optimization level 2 instead of 3--3 doesn't seem to gain much over 2
+CFLAGS  := -MMD -O2 -ffast-math -fomit-frame-pointer
+
+INCS    := -I./ -I./obj `sdl-config --cflags`
+
+OBJS = \
+       obj/cpustbl.o \
+       obj/cpudefs.o \
+       obj/cpuemu.o \
+       obj/cpuextra.o \
+       obj/readcpu.o \
+       obj/m68kinterface.o \
+       obj/m68kdasm.o
+
+#      obj/newcpu.o \
+
+# Targets for convenience sake, not "real" targets
+.PHONY: clean
+
+all: obj obj/libm68k.a
+       @echo "Done!"
+
+# Library rules (might not be cross-platform compatible)
+obj/libm68k.a: $(OBJS) 
+       @$(AR) $(ARFLAGS) obj/libm68k.a $(OBJS)
+
+obj:
+       @mkdir ./obj
+
+# Main source compilation (implicit rules)...
+
+obj/%.o: %.c
+       @echo -e "\033[01;33m***\033[00;32m Compiling $<...\033[00m"
+       @$(CC) $(CFLAGS) $(INCS) -c $< -o $@
+
+obj/%.o: obj/%.c
+       @echo -e "\033[01;33m***\033[00;32m Compiling $<...\033[00m"
+       @$(CC) $(CFLAGS) $(INCS) -c $< -o $@
+
+# Generated code
+
+obj/cpuemu.c: obj/gencpu
+obj/cpustbl.c: obj/gencpu
+       @echo -e "\033[01;33m***\033[00;32m Generating cpuemu.c...\033[00m"
+       @cd obj && ./gencpu
+
+obj/gencpu: obj/cpudefs.c
+       @echo -e "\033[01;33m***\033[00;32m Generating gencpu...\033[00m"
+       @$(CC) $(CFLAGS) gencpu.c readcpu.c obj/cpudefs.c -o obj/gencpu -I./ -I./obj
+
+obj/cpudefs.c: obj/build68k
+       @echo -e "\033[01;33m***\033[00;32m Generating cpudefs.c...\033[00m"
+       @obj/build68k < table68k > obj/cpudefs.c
+
+obj/build68k: build68k.c
+       @echo -e "\033[01;33m***\033[00;32m Compiling build68k.c...\033[00m"
+       @$(CC) $(CFLAGS) build68k.c -o obj/build68k
+
+clean:
+       @echo -ne "\033[01;33m***\033[00;32m Cleaning out the garbage...\033[00m"
+       @-rm -rf ./obj
+#      @-$(FIND) . -name "*~" -exec rm -f {} \;
+       @echo "done!"
+
+# Pull in dependencies autogenerated by gcc's -MMD switch
+# The "-" in front is there just in case they haven't been created yet
+
+-include obj/*.d
diff --git a/src/m68000/build68k.c b/src/m68000/build68k.c
new file mode 100644 (file)
index 0000000..71aab43
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * UAE - The Un*x Amiga Emulator - CPU core
+ *
+ * Read 68000 CPU specs from file "table68k" and build table68k.c
+ *
+ * Copyright 1995,1996 Bernd Schmidt
+ *
+ * Adaptation to Hatari by Thomas Huth
+ *
+ * This file is distributed under the GNU Public License, version 3 or at
+ * your option any later version. Read the file GPLv3 for details.
+ */
+//const char Build68k_fileid[] = "Hatari build68k.c : " __DATE__ " " __TIME__;
+
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include "readcpu.h"
+
+
+static FILE * tablef;
+static int nextch = 0;
+
+static void getnextch(void)
+{
+       do
+       {
+               nextch = fgetc(tablef);
+
+               if (nextch == '%')
+               {
+                       do
+                       {
+                               nextch = fgetc(tablef);
+                       }
+                       while (nextch != EOF && nextch != '\n');
+               }
+       }
+       while (nextch != EOF && isspace(nextch));
+}
+
+static int nextchtohex(void)
+{
+       switch (isupper(nextch) ? tolower(nextch) : nextch)
+       {
+       case '0': return 0;
+       case '1': return 1;
+       case '2': return 2;
+       case '3': return 3;
+       case '4': return 4;
+       case '5': return 5;
+       case '6': return 6;
+       case '7': return 7;
+       case '8': return 8;
+       case '9': return 9;
+       case 'a': return 10;
+       case 'b': return 11;
+       case 'c': return 12;
+       case 'd': return 13;
+       case 'e': return 14;
+       case 'f': return 15;
+       default: abort();
+       }
+}
+
+int main(int argc, char ** argv)
+{
+       int no_insns = 0;
+
+       /*printf("#include \"sysconfig.h\"\n");*/
+       printf("#include \"sysdeps.h\"\n");
+       printf("#include \"readcpu.h\"\n");
+       printf("const struct instr_def defs68k[] = {\n");
+#if 0
+       tablef = fopen("table68k","r");
+       if (tablef == NULL) {
+       fprintf(stderr, "table68k not found\n");
+       exit(1);
+       }
+#else
+       tablef = stdin;
+#endif
+       getnextch();
+
+       while (nextch != EOF)
+       {
+               int cpulevel, plevel, sduse;
+               int i;
+
+               char patbits[16];
+               char opcstr[256];
+               int bitpos[16];
+               int flagset[5], flaguse[5];
+
+               unsigned int bitmask, bitpattern;
+               int n_variable;
+
+               n_variable = 0;
+               bitmask = bitpattern = 0;
+               memset(bitpos, 0, sizeof(bitpos));
+
+               for(i=0; i<16; i++)
+               {
+                       int currbit;
+                       bitmask <<= 1;
+                       bitpattern <<= 1;
+
+                       switch (nextch)
+                       {
+                       case '0': currbit = bit0; bitmask |= 1; break;
+                       case '1': currbit = bit1; bitmask |= 1; bitpattern |= 1; break;
+                       case 'c': currbit = bitc; break;
+                       case 'C': currbit = bitC; break;
+                       case 'f': currbit = bitf; break;
+                       case 'i': currbit = biti; break;
+                       case 'I': currbit = bitI; break;
+                       case 'j': currbit = bitj; break;
+                       case 'J': currbit = bitJ; break;
+                       case 'k': currbit = bitk; break;
+                       case 'K': currbit = bitK; break;
+                       case 's': currbit = bits; break;
+                       case 'S': currbit = bitS; break;
+                       case 'd': currbit = bitd; break;
+                       case 'D': currbit = bitD; break;
+                       case 'r': currbit = bitr; break;
+                       case 'R': currbit = bitR; break;
+                       case 'z': currbit = bitz; break;
+                       case 'p': currbit = bitp; break;
+                       default: abort();
+                       }
+
+                       if (!(bitmask & 1))
+                       {
+                               bitpos[n_variable] = currbit;
+                               n_variable++;
+                       }
+
+                       if (nextch == '0' || nextch == '1')
+                               bitmask |= 1;
+
+                       if (nextch == '1')
+                               bitpattern |= 1;
+
+                       patbits[i] = nextch;
+                       getnextch();
+               }
+
+               while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */
+                       getnextch();
+
+               switch (nextch)
+               {
+               case '0': cpulevel = 0; break;
+               case '1': cpulevel = 1; break;
+               case '2': cpulevel = 2; break;
+               case '3': cpulevel = 3; break;
+               case '4': cpulevel = 4; break;
+               default: abort();
+               }
+
+               getnextch();
+
+               switch (nextch)
+               {
+               case '0': plevel = 0; break;
+               case '1': plevel = 1; break;
+               case '2': plevel = 2; break;
+               case '3': plevel = 3; break;
+               default: abort();
+               }
+
+               getnextch();
+
+               while (isspace(nextch))                   /* Get flag set information */
+                       getnextch();
+
+               if (nextch != ':')
+                       abort();
+
+               for(i=0; i<5; i++)
+               {
+                       getnextch();
+
+                       switch (nextch)
+                       {
+                       case '-': flagset[i] = fa_unset; break;
+                       case '/': flagset[i] = fa_isjmp; break;
+                       case '+': flagset[i] = fa_isbranch; break;
+                       case '0': flagset[i] = fa_zero; break;
+                       case '1': flagset[i] = fa_one; break;
+                       case 'x': flagset[i] = fa_dontcare; break;
+                       case '?': flagset[i] = fa_unknown; break;
+                       default: flagset[i] = fa_set; break;
+                       }
+               }
+
+               getnextch();
+
+               while (isspace(nextch))
+                       getnextch();
+
+               if (nextch != ':')                        /* Get flag used information */
+                       abort();
+
+               for(i=0; i<5; i++)
+               {
+                       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 source/dest usage information */
+                       abort();
+
+               getnextch();
+               sduse = nextchtohex() << 4;
+               getnextch();
+               sduse |= nextchtohex();
+               getnextch();
+
+               while (isspace(nextch))
+                       getnextch();
+
+               if (nextch != ':')
+                       abort();
+
+               if (fgets(opcstr, 250, tablef) == NULL)
+               {
+                       perror("fgets");
+                       return -1;
+               }
+
+               getnextch();
+
+               {
+                       int j;
+                       /* Remove superfluous spaces from the string */
+                       char * opstrp = opcstr, * osendp;
+                       int slen = 0;
+
+                       while (isspace((unsigned)(*opstrp)))
+                               opstrp++;
+
+                       osendp = opstrp;
+
+                       while (*osendp)
+                       {
+                               if (!isspace ((unsigned)(*osendp)))
+                                       slen = osendp - opstrp + 1;
+
+                               osendp++;
+                       }
+
+                       opstrp[slen] = 0;
+
+                       if (no_insns > 0)
+                               printf(",\n");
+
+                       no_insns++;
+                       printf("{ %d, %d, {", bitpattern, n_variable);
+
+                       for(j=0; j<16; j++)
+                       {
+                               printf("%d", bitpos[j]);
+
+                               if (j < 15)
+                                       printf(",");
+                       }
+
+                       printf ("}, %d, %d, %d, { ", bitmask, cpulevel, plevel);
+
+                       for(i=0; i<5; i++)
+                       {
+                               printf("{ %d, %d }%c ", flaguse[i], flagset[i], i == 4 ? ' ' : ',');
+                       }
+
+                       printf("}, %d, \"%s\"}", sduse, opstrp);
+               }
+       }
+
+       printf("};\nint n_defs68k = %d;\n", no_insns);
+       return 0;
+}
diff --git a/src/m68000/cpudefs.h b/src/m68000/cpudefs.h
new file mode 100644 (file)
index 0000000..191057f
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// Common definitions for the UAE 68000 core
+//
+// by James Hammons
+// (C) 2011 Underground Software
+//
+// This file is distributed under the GNU Public License, version 3 or at your
+// option any later version. Read the file GPLv3 for details.
+//
+
+#ifndef __CPUDEFS_H__
+#define __CPUDEFS_H__
+
+#include "sysdeps.h"
+
+/* Special flags */
+#define SPCFLAG_DEBUGGER      0x001
+#define SPCFLAG_STOP          0x002
+#define SPCFLAG_BUSERROR      0x004
+#define SPCFLAG_INT           0x008
+#define SPCFLAG_BRK           0x010
+#define SPCFLAG_EXTRA_CYCLES  0x020
+#define SPCFLAG_TRACE         0x040
+#define SPCFLAG_DOTRACE       0x080
+#define SPCFLAG_DOINT         0x100
+#define SPCFLAG_MFP           0x200
+#define SPCFLAG_EXEC          0x400
+#define SPCFLAG_MODE_CHANGE   0x800
+
+struct regstruct
+{
+       uint32_t regs[16];
+       uint32_t usp, isp;
+       uint16_t sr;
+       uint8_t s;
+       uint8_t stopped;
+       int intmask;
+       int intLevel;
+
+       unsigned int c;
+       unsigned int z;
+       unsigned int n;
+       unsigned int v; 
+       unsigned int x;
+
+       uint32_t pc;
+       uint8_t * pc_p;
+       uint8_t * pc_oldp;
+
+       uint32_t spcflags;
+
+       uint32_t prefetch_pc;
+       uint32_t prefetch;
+
+       int32_t remainingCycles;
+       uint32_t interruptCycles;
+};
+
+extern struct regstruct regs, lastint_regs;
+
+#define m68k_dreg(r, num) ((r).regs[(num)])
+#define m68k_areg(r, num) (((r).regs + 8)[(num)])
+
+#define ZFLG (regs.z)
+#define NFLG (regs.n)
+#define CFLG (regs.c)
+#define VFLG (regs.v)
+#define XFLG (regs.x)
+
+/* Possible exceptions sources for M68000_Exception() and Exception() */
+#define M68000_EXC_SRC_CPU      1  /* Direct CPU exception */
+#define M68000_EXC_SRC_AUTOVEC  2  /* Auto-vector exception (e.g. VBL) */
+//#define M68000_EXC_SRC_INT_MFP  3  /* MFP interrupt exception */
+//#define M68000_EXC_SRC_INT_DSP  4  /* DSP interrupt exception */
+
+#define SET_CFLG(x) (CFLG = (x))
+#define SET_NFLG(x) (NFLG = (x))
+#define SET_VFLG(x) (VFLG = (x))
+#define SET_ZFLG(x) (ZFLG = (x))
+#define SET_XFLG(x) (XFLG = (x))
+
+#define GET_CFLG CFLG
+#define GET_NFLG NFLG
+#define GET_VFLG VFLG
+#define GET_ZFLG ZFLG
+#define GET_XFLG XFLG
+
+#define CLEAR_CZNV do { \
+ SET_CFLG(0); \
+ SET_ZFLG(0); \
+ SET_NFLG(0); \
+ SET_VFLG(0); \
+} while (0)
+
+#define COPY_CARRY (SET_XFLG(GET_CFLG))
+
+#endif // __CPUDEFS_H__
diff --git a/src/m68000/cpuextra.c b/src/m68000/cpuextra.c
new file mode 100644 (file)
index 0000000..230c316
--- /dev/null
@@ -0,0 +1,427 @@
+//
+// Stuff that's neither inline or generated by gencpu.c, but depended upon by
+// cpuemu.c.
+//
+// Originally part of UAE by Bernd Schmidt
+// and released under the GPL v2 or later
+//
+
+#include "cpuextra.h"
+#include "cpudefs.h"
+#include "inlines.h"
+
+
+uint16_t last_op_for_exception_3;              // Opcode of faulting instruction
+uint32_t last_addr_for_exception_3;            // PC at fault time
+uint32_t last_fault_for_exception_3;   // Address that generated the exception
+
+int OpcodeFamily;                                              // Used by cpuemu.c...
+int BusCyclePenalty = 0;                               // Used by cpuemu.c...
+int CurrentInstrCycles;
+
+struct regstruct regs;
+
+//
+// Make displacement effective address for 68000
+//
+uint32_t get_disp_ea_000(uint32_t base, uint32_t dp)
+{
+       int reg = (dp >> 12) & 0x0F;
+       int32_t regd = regs.regs[reg];
+
+#if 1
+       if ((dp & 0x800) == 0)
+               regd = (int32_t)(int16_t)regd;
+
+       return base + (int8_t)dp + regd;
+#else
+       /* Branch-free code... benchmark this again now that
+        * things are no longer inline.
+        */
+       int32_t regd16;
+       uint32_t mask;
+       mask = ((dp & 0x800) >> 11) - 1;
+       regd16 = (int32_t)(int16_t)regd;
+       regd16 &= mask;
+       mask = ~mask;
+       base += (int8_t)dp;
+       regd &= mask;
+       regd |= regd16;
+       return base + regd;
+#endif
+}
+
+//
+// Create the Status Register from the flags
+//
+void MakeSR(void)
+{
+       regs.sr = ((regs.s << 13) | (regs.intmask << 8) | (GET_XFLG << 4)
+               | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1) | GET_CFLG);
+}
+
+//
+// Set up the flags from Status Register
+//
+void MakeFromSR(void)
+{
+       int olds = regs.s;
+
+       regs.s = (regs.sr >> 13) & 1;
+       regs.intmask = (regs.sr >> 8) & 7;
+       SET_XFLG((regs.sr >> 4) & 1);
+       SET_NFLG((regs.sr >> 3) & 1);
+       SET_ZFLG((regs.sr >> 2) & 1);
+       SET_VFLG((regs.sr >> 1) & 1);
+       SET_CFLG(regs.sr & 1);
+
+       if (olds != regs.s)
+       {
+               if (olds)
+               {
+                       regs.isp = m68k_areg(regs, 7);
+                       m68k_areg(regs, 7) = regs.usp;
+               }
+               else
+               {
+                       regs.usp = m68k_areg(regs, 7);
+                       m68k_areg(regs, 7) = regs.isp;
+               }
+       }
+
+       /* Pending interrupts can occur again after a write to the SR: */
+//JLH: is this needed?
+//     set_special(SPCFLAG_DOINT);
+}
+
+//
+// Rudimentary exception handling. This is really stripped down from what
+// was in Hatari.
+//
+// Handle exceptions. We need a special case to handle MFP exceptions
+// on Atari ST, because it's possible to change the MFP's vector base
+// and get a conflict with 'normal' cpu exceptions.
+//
+void Exception(int nr, uint32_t oldpc, int ExceptionSource)
+{
+printf("Exception #%i occurred!\n", nr);
+printf("Vector @ #%i = %08X\n", nr, m68k_read_memory_32(nr * 4));
+//abort();
+       uint32_t currpc = m68k_getpc(), newpc;
+
+       /*if( nr>=2 && nr<10 )  fprintf(stderr,"Exception (-> %i bombs)!\n",nr);*/
+
+       MakeSR();
+
+       // Change to supervisor mode if necessary
+       if (!regs.s)
+       {
+               regs.usp = m68k_areg(regs, 7);
+               m68k_areg(regs, 7) = regs.isp;
+               regs.s = 1;
+       }
+
+       // Create 68000 style stack frame
+       m68k_areg(regs, 7) -= 4;                                // Push PC on stack
+       m68k_write_memory_32(m68k_areg(regs, 7), currpc);
+       m68k_areg(regs, 7) -= 2;                                // Push SR on stack
+       m68k_write_memory_16(m68k_areg(regs, 7), regs.sr);
+
+//     LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x\n",
+//     nr, currpc, BusErrorPC, get_long(4 * nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3);
+
+#if 0
+       /* 68000 bus/address errors: */
+       if ((nr == 2 || nr == 3) && ExceptionSource == M68000_EXC_SRC_CPU)
+       {
+               uint16_t specialstatus = 1;
+
+               /* Special status word emulation isn't perfect yet... :-( */
+               if (regs.sr & 0x2000)
+                       specialstatus |= 0x4;
+
+               m68k_areg(regs, 7) -= 8;
+
+               if (nr == 3)     /* Address error */
+               {
+                       specialstatus |= (last_op_for_exception_3 & (~0x1F));   /* [NP] unused bits of specialstatus are those of the last opcode ! */
+                       put_word(m68k_areg(regs, 7), specialstatus);
+                       put_long(m68k_areg(regs, 7) + 2, last_fault_for_exception_3);
+                       put_word(m68k_areg(regs, 7) + 6, last_op_for_exception_3);
+                       put_long(m68k_areg(regs, 7) + 10, last_addr_for_exception_3);
+
+//JLH: Not now...
+#if 0
+                       if (bExceptionDebugging)
+                       {
+                               fprintf(stderr,"Address Error at address $%x, PC=$%x\n", last_fault_for_exception_3, currpc);
+                               DebugUI();
+                       }
+#endif
+               }
+               else     /* Bus error */
+               {
+                       specialstatus |= (get_word(BusErrorPC) & (~0x1F));      /* [NP] unused bits of special status are those of the last opcode ! */
+
+                       if (bBusErrorReadWrite)
+                               specialstatus |= 0x10;
+
+                       put_word(m68k_areg(regs, 7), specialstatus);
+                       put_long(m68k_areg(regs, 7) + 2, BusErrorAddress);
+                       put_word(m68k_areg(regs, 7) + 6, get_word(BusErrorPC)); /* Opcode */
+
+                       /* [NP] PC stored in the stack frame is not necessarily pointing to the next instruction ! */
+                       /* FIXME : we should have a proper model for this, in the meantime we handle specific cases */
+                       if (get_word(BusErrorPC) == 0x21F8)                     /* move.l $0.w,$24.w (Transbeauce 2 loader) */
+                               put_long(m68k_areg(regs, 7) + 10, currpc - 2);          /* correct PC is 2 bytes less than usual value */
+
+                       /* Check for double bus errors: */
+                       if (regs.spcflags & SPCFLAG_BUSERROR)
+                       {
+                               fprintf(stderr, "Detected double bus error at address $%x, PC=$%lx => CPU halted!\n",
+                               BusErrorAddress, (long)currpc);
+                               unset_special(SPCFLAG_BUSERROR);
+
+                               if (bExceptionDebugging)
+                                       DebugUI();
+                               else
+                                       DlgAlert_Notice("Detected double bus error => CPU halted!\nEmulation needs to be reset.\n");
+
+                               regs.intmask = 7;
+                               m68k_setstopped(true);
+                               return;
+                       }
+
+                       if (bExceptionDebugging && BusErrorAddress != 0xFF8A00)
+                       {
+                               fprintf(stderr,"Bus Error at address $%x, PC=$%lx\n", BusErrorAddress, (long)currpc);
+                               DebugUI();
+                       }
+               }
+       }
+
+//Not now...
+#if 0
+       /* Set PC and flags */
+       if (bExceptionDebugging && get_long(4 * nr) == 0)
+       {
+               write_log("Uninitialized exception handler #%i!\n", nr);
+               DebugUI();
+       }
+#endif
+
+       newpc = get_long(4 * nr);
+
+       if (newpc & 1)                          /* check new pc is odd */
+       {
+               if (nr == 2 || nr == 3)                 /* address error during bus/address error -> stop emulation */
+               {
+                       fprintf(stderr,"Address Error during exception 2/3, aborting new PC=$%x\n", newpc);
+                       DebugUI();
+               }
+               else
+               {
+                       fprintf(stderr,"Address Error during exception, new PC=$%x\n", newpc);
+                       Exception(3, m68k_getpc(), M68000_EXC_SRC_CPU);
+               }
+
+               return;
+       }
+#endif
+
+       m68k_setpc(m68k_read_memory_32(4 * nr));
+       fill_prefetch_0();
+       /* Handle trace flags depending on current state */
+//JLH:no       exception_trace(nr);
+
+#if 0
+       /* Handle exception cycles (special case for MFP) */
+//     if (ExceptionSource == M68000_EXC_SRC_INT_MFP)
+//     {
+//             M68000_AddCycles(44 + 12);                      /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */
+//     }
+//     else
+       if (nr >= 24 && nr <= 31)
+       {
+#if 0
+               if (nr == 26)                           /* HBL */
+               {
+                       /* store current cycle pos when then interrupt was received (see video.c) */
+                       LastCycleHblException = Cycles_GetCounter(CYCLES_COUNTER_VIDEO);
+                       M68000_AddCycles(44 + 12);              /* Video Interrupt */
+               }
+               else if (nr == 28)                      /* VBL */
+                       M68000_AddCycles(44 + 12);              /* Video Interrupt */
+               else
+#endif
+                       M68000_AddCycles(44 + 4);                       /* Other Interrupts */
+       }
+       else if (nr >= 32 && nr <= 47)
+       {
+               M68000_AddCycles(34 - 4);                       /* Trap (total is 34, but cpuemu.c already adds 4) */
+       }
+       else switch(nr)
+       {
+               case 2: M68000_AddCycles(50); break;    /* Bus error */
+               case 3: M68000_AddCycles(50); break;    /* Address error */
+               case 4: M68000_AddCycles(34); break;    /* Illegal instruction */
+               case 5: M68000_AddCycles(38); break;    /* Div by zero */
+               case 6: M68000_AddCycles(40); break;    /* CHK */
+               case 7: M68000_AddCycles(34); break;    /* TRAPV */
+               case 8: M68000_AddCycles(34); break;    /* Privilege violation */
+               case 9: M68000_AddCycles(34); break;    /* Trace */
+               case 10: M68000_AddCycles(34); break;   /* Line-A - probably wrong */
+               case 11: M68000_AddCycles(34); break;   /* Line-F - probably wrong */
+               default:
+               /* FIXME: Add right cycles value for MFP interrupts and copro exceptions ... */
+               if (nr < 64)
+                       M68000_AddCycles(4);                    /* Coprocessor and unassigned exceptions (???) */
+               else
+                       M68000_AddCycles(44 + 12);              /* Must be a MFP or DSP interrupt */
+
+               break;
+       }
+#endif
+}
+
+/*
+ The routines below take dividend and divisor as parameters.
+ They return 0 if division by zero, or exact number of cycles otherwise.
+
+ The number of cycles returned assumes a register operand.
+ Effective address time must be added if memory operand.
+
+ For 68000 only (not 68010, 68012, 68020, etc).
+ Probably valid for 68008 after adding the extra prefetch cycle.
+
+
+ Best and worst cases are for register operand:
+ (Note the difference with the documented range.)
+
+
+ DIVU:
+
+ Overflow (always): 10 cycles.
+ Worst case: 136 cycles.
+ Best case: 76 cycles.
+
+
+ DIVS:
+
+ Absolute overflow: 16-18 cycles.
+ Signed overflow is not detected prematurely.
+
+ Worst case: 156 cycles.
+ Best case without signed overflow: 122 cycles.
+ Best case with signed overflow: 120 cycles
+ */
+
+//
+// DIVU
+// Unsigned division
+//
+STATIC_INLINE int getDivu68kCycles_2 (uint32_t dividend, uint16_t divisor)
+{
+       int mcycles;
+       uint32_t hdivisor;
+       int i;
+
+       if (divisor == 0)
+               return 0;
+
+       // Overflow
+       if ((dividend >> 16) >= divisor)
+               return (mcycles = 5) * 2;
+
+       mcycles = 38;
+       hdivisor = divisor << 16;
+
+       for(i=0; i<15; i++)
+       {
+               uint32_t temp;
+               temp = dividend;
+
+               dividend <<= 1;
+
+               // If carry from shift
+               if ((int32_t)temp < 0)
+                       dividend -= hdivisor;
+               else
+               {
+                       mcycles += 2;
+
+                       if (dividend >= hdivisor)
+                       {
+                               dividend -= hdivisor;
+                               mcycles--;
+                       }
+               }
+       }
+
+       return mcycles * 2;
+}
+
+// This is called by cpuemu.c
+int getDivu68kCycles(uint32_t dividend, uint16_t divisor)
+{
+       int v = getDivu68kCycles_2(dividend, divisor) - 4;
+//     write_log ("U%d ", v);
+       return v;
+}
+
+//
+// DIVS
+// Signed division
+//
+
+STATIC_INLINE int getDivs68kCycles_2(int32_t dividend, int16_t divisor)
+{
+       int mcycles;
+       uint32_t aquot;
+       int i;
+
+       if (divisor == 0)
+               return 0;
+
+       mcycles = 6;
+
+       if (dividend < 0)
+               mcycles++;
+
+       // Check for absolute overflow
+       if (((uint32_t)abs(dividend) >> 16) >= (uint16_t)abs(divisor))
+               return (mcycles + 2) * 2;
+
+       // Absolute quotient
+       aquot = (uint32_t)abs(dividend) / (uint16_t)abs(divisor);
+
+       mcycles += 55;
+
+       if (divisor >= 0)
+       {
+               if (dividend >= 0)
+                       mcycles--;
+               else
+                       mcycles++;
+       }
+
+       // Count 15 msbits in absolute of quotient
+
+       for(i=0; i<15; i++)
+       {
+               if ((int16_t)aquot >= 0)
+                       mcycles++;
+
+               aquot <<= 1;
+       }
+
+       return mcycles * 2;
+}
+
+// This is called by cpuemu.c
+int getDivs68kCycles(int32_t dividend, int16_t divisor)
+{
+       int v = getDivs68kCycles_2(dividend, divisor) - 4;
+//     write_log ("S%d ", v);
+       return v;
+}
diff --git a/src/m68000/cpuextra.h b/src/m68000/cpuextra.h
new file mode 100644 (file)
index 0000000..0efbbb4
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __CPUEXTRA_H__
+#define __CPUEXTRA_H__
+
+#include "sysdeps.h"
+
+typedef unsigned long cpuop_func(uint32_t);
+
+struct cputbl
+{
+       cpuop_func * handler;
+       int specific;
+       uint16_t opcode;
+};
+
+extern uint16_t last_op_for_exception_3;       /* Opcode of faulting instruction */
+extern uint32_t last_addr_for_exception_3;     /* PC at fault time */
+extern uint32_t last_fault_for_exception_3;    /* Address that generated the exception */
+
+/* Family of the latest instruction executed (to check for pairing) */
+extern int OpcodeFamily;                       /* see instrmnem in readcpu.h */
+
+/* How many cycles to add to the current instruction in case a "misaligned" bus access is made */
+/* (used when addressing mode is d8(an,ix)) */
+extern int BusCyclePenalty;
+extern int CurrentInstrCycles;
+
+extern uint32_t get_disp_ea_000(uint32_t base, uint32_t dp);
+extern void MakeSR(void);
+extern void MakeFromSR(void);
+extern void Exception(int, uint32_t, int);
+extern int getDivu68kCycles(uint32_t dividend, uint16_t divisor);
+extern int getDivs68kCycles(int32_t dividend, int16_t divisor);
+
+#endif // __CPUEXTRA_H__
diff --git a/src/m68000/gencpu.c b/src/m68000/gencpu.c
new file mode 100644 (file)
index 0000000..a4729a8
--- /dev/null
@@ -0,0 +1,2818 @@
+/*
+ * UAE - The Un*x Amiga Emulator - CPU core
+ *
+ * MC68000 emulation generator
+ *
+ * This is a fairly stupid program that generates a lot of case labels that
+ * can be #included in a switch statement.
+ * As an alternative, it can generate functions that handle specific
+ * MC68000 instructions, plus a prototype header file and a function pointer
+ * array to look up the function for an opcode.
+ * Error checking is bad, an illegal table68k file will cause the program to
+ * call abort().
+ * The generated code is sometimes sub-optimal, an optimizing compiler should
+ * take care of this.
+ *
+ * The source for the insn timings is Markt & Technik's Amiga Magazin 8/1992.
+ *
+ * Copyright 1995, 1996, 1997, 1998, 1999, 2000 Bernd Schmidt
+ *
+ * Adaptation to Hatari and better cpu timings by Thomas Huth
+ * Adaptation to Virtual Jaguar by James Hammons
+ *
+ * This file is distributed under the GNU Public License, version 3 or at
+ * your option any later version. Read the file GPLv3 for details.
+ *
+ */
+
+
+/* 2007/03/xx  [NP]    Use add_cycles.pl to set 'CurrentInstrCycles' in each opcode.                   */
+/* 2007/04/09  [NP]    Correct CLR : on 68000, CLR reads the memory before clearing it (but we should  */
+/*                     not add cycles for reading). This means CLR can give 2 wait states (one for     */
+/*                     read and one for right) (clr.b $fa1b.w in Decade's Demo Main Menu).             */
+/* 2007/04/14  [NP]    - Although dest -(an) normally takes 2 cycles, this is not the case for move :  */
+/*                     move dest (an), (an)+ and -(an) all take the same time (curi->dmode == Apdi)    */
+/*                     (Syntax Terror Demo Reset).                                                     */
+/*                     - Scc takes 6 cycles instead of 4 if the result is true (Ventura Demo Loader).  */
+/*                     - Store the family of the current opcode into OpcodeFamily : used to check      */
+/*                     instruction pairing on ST into m68000.c                                         */
+/* 2007/04/17  [NP]    Add support for cycle accurate MULU (No Cooper Greeting Screen).                */      
+/* 2007/04/24  [NP]    BCLR #n,Dx takes 12 cycles instead of 14 if n<16 (ULM Demo Menu).               */
+/* 2007/04/25  [NP]    On ST, d8(An,Xn) and d8(PC,Xn) take 2 cycles more than the official 68000's     */
+/*                     table (ULM Demo Menu).                                                          */
+/* 2007/11/12  [NP]    Add refill_prefetch for i_ADD to fix Transbeauce 2 demo self modified code.     */
+/*                     Ugly hack, we need better prefetch emulation (switch to winuae gencpu.c)        */
+/* 2007/11/25  [NP]    In i_DBcc, in case of address error, last_addr_for_exception_3 should be        */
+/*                     pc+4, not pc+2 (Transbeauce 2 demo) (e.g. 'dbf d0,#$fff5').                     */
+/*                     This means the value pushed on the frame stack should be the address of the     */
+/*                     instruction following the one generating the address error.                     */
+/*                     FIXME : this should be the case for i_BSR and i_BCC too (need to check on       */
+/*                     a real 68000).                                                                  */
+/* 2007/11/28  [NP]    Backport DIVS/DIVU cycles exact routines from WinUAE (original work by Jorge    */
+/*                     Cwik, pasti@fxatari.com).                                                       */
+/* 2007/12/08  [NP]    In case of CHK/CHK2 exception, PC stored on the stack wasn't pointing to the    */
+/*                     next instruction but to the current CHK/CHK2 instruction (Transbeauce 2 demo).  */
+/*                     We need to call 'sync_m68k_pc' before calling 'Exception'.                      */
+/* 2007/12/09  [NP]    CHK.L (e.g. $4700) doesn't exist on 68000 and should be considered as an illegal*/
+/*                     instruction (Transbeauce 2 demo) -> change in table68k.                         */
+/* 2008/01/24  [NP]    BCLR Dy,Dx takes 8 cycles instead of 10 if Dy<16 (Fullshade in Anomaly Demos).  */
+/* 2008/01/26  [NP]    On ST, d8(An,Xn) takes 2 cycles more when used with ADDA/SUBA (ULM Demo Menu)   */
+/*                     but not when used with MOVE (e.g. 'move.l 0(a5,d1),(a4)' takes 26 cycles and so */
+/*                     can pair with a lsr) (Anomaly Demo Intro).                                      */
+/* 2008/04/26  [NP]    Handle sz_byte for Areg in genamode, as 'move.b a1,(a0)' ($1089) is possible    */
+/*                     on ST (fix Blood Money on Superior 65)                                          */
+/* 2010/04/05  [NP]    On ST, d8(An,Xn) takes 2 cycles more (which can generate pairing).              */
+/*                     Use BusCyclePenalty to properly handle the 2/4 cycles added in that case when   */
+/*                     addressing mode is Ad8r or PC8r (ULM Demo Menu, Anomaly Demo Intro, DHS         */
+/*                     Sommarhack 2010) (see m68000.h)                                                 */
+
+
+const char GenCpu_fileid[] = "Hatari gencpu.c : " __DATE__ " " __TIME__;
+
+#include <ctype.h>
+#include <string.h>
+
+#include "sysdeps.h"
+#include "readcpu.h"
+
+#define BOOL_TYPE "int"
+
+static FILE *headerfile;
+static FILE *stblfile;
+
+static int using_prefetch;
+static int using_exception_3;
+static int cpu_level;
+
+char exactCpuCycles[256];   /* Space to store return string for exact cpu cycles */
+
+long nCurInstrCycPos;  /* Stores where we have to patch in the current cycles value */
+
+/* For the current opcode, the next lower level that will have different code.
+ * Initialized to -1 for each opcode. If it remains unchanged, indicates we
+ * are done with that opcode.  */
+static int next_cpu_level;
+static int *opcode_map;
+static int *opcode_next_clev;
+static int *opcode_last_postfix;
+static unsigned long *counts;
+
+
+static void read_counts (void)
+{
+    FILE *file;
+    unsigned long opcode, count, total;
+    char name[20];
+    int nr = 0;
+    memset (counts, 0, 65536 * sizeof *counts);
+
+    file = fopen ("frequent.68k", "r");
+    if (file) {
+       if (fscanf (file, "Total: %lu\n", &total) == EOF) {
+           perror("read_counts");
+       }
+       while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
+           opcode_next_clev[nr] = 4;
+           opcode_last_postfix[nr] = -1;
+           opcode_map[nr++] = opcode;
+           counts[opcode] = count;
+       }
+       fclose (file);
+    }
+    if (nr == nr_cpuop_funcs)
+       return;
+    for (opcode = 0; opcode < 0x10000; opcode++) {
+       if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG
+           && counts[opcode] == 0)
+       {
+           opcode_next_clev[nr] = 4;
+           opcode_last_postfix[nr] = -1;
+           opcode_map[nr++] = opcode;
+           counts[opcode] = count;
+       }
+    }
+    if (nr != nr_cpuop_funcs)
+       abort ();
+}
+
+static char endlabelstr[80];
+static int endlabelno = 0;
+static int need_endlabel;
+
+static int n_braces = 0;
+static int m68k_pc_offset = 0;
+static int insn_n_cycles;
+
+static void start_brace (void)
+{
+    n_braces++;
+    printf ("{");
+}
+
+static void close_brace (void)
+{
+    assert (n_braces > 0);
+    n_braces--;
+    printf ("}");
+}
+
+static void finish_braces (void)
+{
+    while (n_braces > 0)
+       close_brace ();
+}
+
+static void pop_braces (int to)
+{
+    while (n_braces > to)
+       close_brace ();
+}
+
+static int bit_size (int size)
+{
+    switch (size) {
+     case sz_byte: return 8;
+     case sz_word: return 16;
+     case sz_long: return 32;
+     default: abort ();
+    }
+    return 0;
+}
+
+static const char *bit_mask (int size)
+{
+    switch (size) {
+     case sz_byte: return "0xff";
+     case sz_word: return "0xffff";
+     case sz_long: return "0xffffffff";
+     default: abort ();
+    }
+    return 0;
+}
+
+static const char *gen_nextilong (void)
+{
+    static char buffer[80];
+    int r = m68k_pc_offset;
+    m68k_pc_offset += 4;
+
+    insn_n_cycles += 8;
+
+    if (using_prefetch)
+       sprintf (buffer, "get_ilong_prefetch(%d)", r);
+    else
+       sprintf (buffer, "get_ilong(%d)", r);
+    return buffer;
+}
+
+static const char *gen_nextiword (void)
+{
+    static char buffer[80];
+    int r = m68k_pc_offset;
+    m68k_pc_offset += 2;
+
+    insn_n_cycles += 4;
+
+    if (using_prefetch)
+       sprintf (buffer, "get_iword_prefetch(%d)", r);
+    else
+       sprintf (buffer, "get_iword(%d)", r);
+    return buffer;
+}
+
+static const char *gen_nextibyte (void)
+{
+    static char buffer[80];
+    int r = m68k_pc_offset;
+    m68k_pc_offset += 2;
+
+    insn_n_cycles += 4;
+
+    if (using_prefetch)
+       sprintf (buffer, "get_ibyte_prefetch(%d)", r);
+    else
+       sprintf (buffer, "get_ibyte(%d)", r);
+    return buffer;
+}
+
+static void fill_prefetch_0 (void)
+{
+    if (using_prefetch)
+       printf ("fill_prefetch_0 ();\n");
+}
+
+static void fill_prefetch_2 (void)
+{
+    if (using_prefetch)
+       printf ("fill_prefetch_2 ();\n");
+}
+
+static void sync_m68k_pc(void)
+{
+       if (m68k_pc_offset == 0)
+               return;
+
+       printf("m68k_incpc(%d);\n", m68k_pc_offset);
+
+       switch (m68k_pc_offset)
+       {
+       case 0:
+       /*fprintf (stderr, "refilling prefetch at 0\n"); */
+               break;
+       case 2:
+               fill_prefetch_2();
+               break;
+       default:
+               fill_prefetch_0();
+               break;
+       }
+
+       m68k_pc_offset = 0;
+}
+
+/* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0,
+ * the calling routine handles Apdi and Aipi modes.
+ * gb-- movem == 2 means the same thing but for a MOVE16 instruction */
+static void genamode(amodes mode, const char * reg, wordsizes size,
+       const char * name, int getv, int movem)
+{
+       start_brace();
+       switch (mode)
+       {
+       case Dreg:
+       if (movem)
+               abort ();
+       if (getv == 1)
+               switch (size) {
+               case sz_byte:
+               printf ("\tint8_t %s = m68k_dreg(regs, %s);\n", name, reg);
+               break;
+               case sz_word:
+               printf ("\tint16_t %s = m68k_dreg(regs, %s);\n", name, reg);
+               break;
+               case sz_long:
+               printf ("\tint32_t %s = m68k_dreg(regs, %s);\n", name, reg);
+               break;
+               default:
+               abort ();
+               }
+       return;
+       case Areg:
+       if (movem)
+               abort ();
+       if (getv == 1)
+               switch (size) {
+               case sz_byte:                           // [NP] Areg with .b is possible in MOVE source */
+               printf ("\tint8_t %s = m68k_areg(regs, %s);\n", name, reg);
+               break;
+               case sz_word:
+               printf ("\tint16_t %s = m68k_areg(regs, %s);\n", name, reg);
+               break;
+               case sz_long:
+               printf ("\tint32_t %s = m68k_areg(regs, %s);\n", name, reg);
+               break;
+               default:
+               abort ();
+               }
+       return;
+       case Aind:
+       printf ("\tuint32_t %sa = m68k_areg(regs, %s);\n", name, reg);
+       break;
+       case Aipi:
+       printf ("\tuint32_t %sa = m68k_areg(regs, %s);\n", name, reg);
+       break;
+       case Apdi:
+       insn_n_cycles += 2;
+       switch (size) {
+       case sz_byte:
+               if (movem)
+               printf ("\tuint32_t %sa = m68k_areg(regs, %s);\n", name, reg);
+               else
+               printf ("\tuint32_t %sa = m68k_areg(regs, %s) - areg_byteinc[%s];\n", name, reg, reg);
+               break;
+       case sz_word:
+               printf ("\tuint32_t %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 2);
+               break;
+       case sz_long:
+               printf ("\tuint32_t %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 4);
+               break;
+       default:
+               abort ();
+       }
+       break;
+       case Ad16:
+       printf ("\tuint32_t %sa = m68k_areg(regs, %s) + (int32_t)(int16_t)%s;\n", name, reg, gen_nextiword ());
+       break;
+       case Ad8r:
+       insn_n_cycles += 2;
+       if (cpu_level > 1) {
+               if (next_cpu_level < 1)
+               next_cpu_level = 1;
+               sync_m68k_pc ();
+               start_brace ();
+               /* This would ordinarily be done in gen_nextiword, which we bypass.  */
+               insn_n_cycles += 4;
+               printf ("\tuint32_t %sa = get_disp_ea_020(m68k_areg(regs, %s), next_iword());\n", name, reg);
+       } else {
+               printf ("\tuint32_t %sa = get_disp_ea_000(m68k_areg(regs, %s), %s);\n", name, reg, gen_nextiword ());
+       }
+       printf ("\tBusCyclePenalty += 2;\n");
+
+       break;
+       case PC16:
+       printf ("\tuint32_t %sa = m68k_getpc () + %d;\n", name, m68k_pc_offset);
+       printf ("\t%sa += (int32_t)(int16_t)%s;\n", name, gen_nextiword ());
+       break;
+       case PC8r:
+       insn_n_cycles += 2;
+       if (cpu_level > 1) {
+               if (next_cpu_level < 1)
+               next_cpu_level = 1;
+               sync_m68k_pc ();
+               start_brace ();
+               /* This would ordinarily be done in gen_nextiword, which we bypass.  */
+               insn_n_cycles += 4;
+               printf ("\tuint32_t tmppc = m68k_getpc();\n");
+               printf ("\tuint32_t %sa = get_disp_ea_020(tmppc, next_iword());\n", name);
+       } else {
+               printf ("\tuint32_t tmppc = m68k_getpc() + %d;\n", m68k_pc_offset);
+               printf ("\tuint32_t %sa = get_disp_ea_000(tmppc, %s);\n", name, gen_nextiword ());
+       }
+       printf ("\tBusCyclePenalty += 2;\n");
+
+       break;
+       case absw:
+       printf ("\tuint32_t %sa = (int32_t)(int16_t)%s;\n", name, gen_nextiword ());
+       break;
+       case absl:
+       printf ("\tuint32_t %sa = %s;\n", name, gen_nextilong ());
+       break;
+       case imm:
+       if (getv != 1)
+               abort ();
+       switch (size) {
+       case sz_byte:
+               printf ("\tint8_t %s = %s;\n", name, gen_nextibyte ());
+               break;
+       case sz_word:
+               printf ("\tint16_t %s = %s;\n", name, gen_nextiword ());
+               break;
+       case sz_long:
+               printf ("\tint32_t %s = %s;\n", name, gen_nextilong ());
+               break;
+       default:
+               abort ();
+       }
+       return;
+       case imm0:
+       if (getv != 1)
+               abort ();
+       printf ("\tint8_t %s = %s;\n", name, gen_nextibyte ());
+       return;
+       case imm1:
+       if (getv != 1)
+               abort ();
+       printf ("\tint16_t %s = %s;\n", name, gen_nextiword ());
+       return;
+       case imm2:
+       if (getv != 1)
+               abort ();
+       printf ("\tint32_t %s = %s;\n", name, gen_nextilong ());
+       return;
+       case immi:
+       if (getv != 1)
+               abort ();
+       printf ("\tuint32_t %s = %s;\n", name, reg);
+       return;
+       default:
+       abort ();
+       }
+
+       /* We get here for all non-reg non-immediate addressing modes to
+       * actually fetch the value. */
+
+       if (using_exception_3 && getv != 0 && size != sz_byte) {            
+       printf ("\tif ((%sa & 1) != 0) {\n", name);
+       printf ("\t\tlast_fault_for_exception_3 = %sa;\n", name);
+       printf ("\t\tlast_op_for_exception_3 = opcode;\n");
+       printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + %d;\n", m68k_pc_offset);
+       printf ("\t\tException(3, 0, M68000_EXC_SRC_CPU);\n");
+       printf ("\t\tgoto %s;\n", endlabelstr);
+       printf ("\t}\n");
+       need_endlabel = 1;
+       start_brace ();
+       }
+
+       if (getv == 1) {
+       switch (size) {
+       case sz_byte: insn_n_cycles += 4; break;
+       case sz_word: insn_n_cycles += 4; break;
+       case sz_long: insn_n_cycles += 8; break;
+       default: abort ();
+       }
+       start_brace ();
+       switch (size) {
+       case sz_byte: printf ("\tint8_t %s = m68k_read_memory_8(%sa);\n", name, name); break;
+       case sz_word: printf ("\tint16_t %s = m68k_read_memory_16(%sa);\n", name, name); break;
+       case sz_long: printf ("\tint32_t %s = m68k_read_memory_32(%sa);\n", name, name); break;
+       default: abort ();
+       }
+       }
+
+       /* We now might have to fix up the register for pre-dec or post-inc
+       * addressing modes. */
+       if (!movem)
+       switch (mode) {
+       case Aipi:
+               switch (size) {
+               case sz_byte:
+               printf ("\tm68k_areg(regs, %s) += areg_byteinc[%s];\n", reg, reg);
+               break;
+               case sz_word:
+               printf ("\tm68k_areg(regs, %s) += 2;\n", reg);
+               break;
+               case sz_long:
+               printf ("\tm68k_areg(regs, %s) += 4;\n", reg);
+               break;
+               default:
+               abort ();
+               }
+               break;
+       case Apdi:
+               printf ("\tm68k_areg (regs, %s) = %sa;\n", reg, name);
+               break;
+       default:
+               break;
+       }
+}
+
+static void genastore (const char *from, amodes mode, const char *reg,
+                       wordsizes size, const char *to)
+{
+    switch (mode) {
+     case Dreg:
+       switch (size) {
+        case sz_byte:
+           printf ("\tm68k_dreg(regs, %s) = (m68k_dreg(regs, %s) & ~0xff) | ((%s) & 0xff);\n", reg, reg, from);
+           break;
+        case sz_word:
+           printf ("\tm68k_dreg(regs, %s) = (m68k_dreg(regs, %s) & ~0xffff) | ((%s) & 0xffff);\n", reg, reg, from);
+           break;
+        case sz_long:
+           printf ("\tm68k_dreg(regs, %s) = (%s);\n", reg, from);
+           break;
+        default:
+           abort ();
+       }
+       break;
+     case Areg:
+       switch (size) {
+        case sz_word:
+           fprintf (stderr, "Foo\n");
+           printf ("\tm68k_areg(regs, %s) = (int32_t)(int16_t)(%s);\n", reg, from);
+           break;
+        case sz_long:
+           printf ("\tm68k_areg(regs, %s) = (%s);\n", reg, from);
+           break;
+        default:
+           abort ();
+       }
+       break;
+     case Aind:
+     case Aipi:
+     case Apdi:
+     case Ad16:
+     case Ad8r:
+     case absw:
+     case absl:
+     case PC16:
+     case PC8r:
+       if (using_prefetch)
+           sync_m68k_pc ();
+       switch (size) {
+        case sz_byte:
+           insn_n_cycles += 4;
+           printf ("\tm68k_write_memory_8(%sa,%s);\n", to, from);
+           break;
+        case sz_word:
+           insn_n_cycles += 4;
+           if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
+               abort ();
+           printf ("\tm68k_write_memory_16(%sa,%s);\n", to, from);
+           break;
+        case sz_long:
+           insn_n_cycles += 8;
+           if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
+               abort ();
+           printf ("\tm68k_write_memory_32(%sa,%s);\n", to, from);
+           break;
+        default:
+           abort ();
+       }
+       break;
+     case imm:
+     case imm0:
+     case imm1:
+     case imm2:
+     case immi:
+       abort ();
+       break;
+     default:
+       abort ();
+    }
+}
+
+
+static void genmovemel (uint16_t opcode)
+{
+    char getcode[100];
+    int bMovemLong = (table68k[opcode].size == sz_long);
+    int size = bMovemLong ? 4 : 2;
+
+    if (bMovemLong) {
+       strcpy (getcode, "m68k_read_memory_32(srca)");
+    } else {
+       strcpy (getcode, "(int32_t)(int16_t)m68k_read_memory_16(srca)");
+    }
+
+    printf ("\tuint16_t mask = %s;\n", gen_nextiword ());
+    printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
+    printf ("\tretcycles = 0;\n");
+    genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
+    start_brace ();
+    printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s;"
+            " srca += %d; dmask = movem_next[dmask]; retcycles+=%d; }\n",
+           getcode, size, (bMovemLong ? 8 : 4));
+    printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s;"
+            " srca += %d; amask = movem_next[amask]; retcycles+=%d; }\n",
+           getcode, size, (bMovemLong ? 8 : 4));
+
+    if (table68k[opcode].dmode == Aipi)
+       printf ("\tm68k_areg(regs, dstreg) = srca;\n");
+
+    /* Better cycles - experimental! (Thothy) */
+    switch(table68k[opcode].dmode)
+    {
+      case Aind:  insn_n_cycles=12; break;
+      case Aipi:  insn_n_cycles=12; break;
+      case Ad16:  insn_n_cycles=16; break;
+      case Ad8r:  insn_n_cycles=18; break;
+      case absw:  insn_n_cycles=16; break;
+      case absl:  insn_n_cycles=20; break;
+      case PC16:  insn_n_cycles=16; break;
+      case PC8r:  insn_n_cycles=18; break;
+    }
+    sprintf(exactCpuCycles," return (%i+retcycles);", insn_n_cycles);
+}
+
+static void genmovemle (uint16_t opcode)
+{
+    char putcode[100];
+    int bMovemLong = (table68k[opcode].size == sz_long);
+    int size = bMovemLong ? 4 : 2;
+
+    if (bMovemLong) {
+       strcpy (putcode, "m68k_write_memory_32(srca,");
+    } else {
+       strcpy (putcode, "m68k_write_memory_16(srca,");
+    }
+
+    printf ("\tuint16_t mask = %s;\n", gen_nextiword ());
+    printf ("\tretcycles = 0;\n");
+    genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
+    if (using_prefetch)
+       sync_m68k_pc ();
+
+    start_brace ();
+    if (table68k[opcode].dmode == Apdi) {
+        printf ("\tuint16_t amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
+        printf ("\twhile (amask) { srca -= %d; %s m68k_areg(regs, movem_index2[amask]));"
+                " amask = movem_next[amask]; retcycles+=%d; }\n",
+                size, putcode, (bMovemLong ? 8 : 4));
+        printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask]));"
+                " dmask = movem_next[dmask]; retcycles+=%d; }\n",
+                size, putcode, (bMovemLong ? 8 : 4));
+        printf ("\tm68k_areg(regs, dstreg) = srca;\n");
+    } else {
+        printf ("\tuint16_t dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
+        printf ("\twhile (dmask) { %s m68k_dreg(regs, movem_index1[dmask])); srca += %d;"
+                " dmask = movem_next[dmask]; retcycles+=%d; }\n",
+                putcode, size, (bMovemLong ? 8 : 4));
+        printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d;"
+                " amask = movem_next[amask]; retcycles+=%d; }\n",
+                putcode, size, (bMovemLong ? 8 : 4));
+    }
+
+    /* Better cycles - experimental! (Thothy) */
+    switch(table68k[opcode].dmode)
+    {
+      case Aind:  insn_n_cycles=8; break;
+      case Apdi:  insn_n_cycles=8; break;
+      case Ad16:  insn_n_cycles=12; break;
+      case Ad8r:  insn_n_cycles=14; break;
+      case absw:  insn_n_cycles=12; break;
+      case absl:  insn_n_cycles=16; break;
+    }
+    sprintf(exactCpuCycles," return (%i+retcycles);", insn_n_cycles);
+}
+
+
+static void duplicate_carry (void)
+{
+    printf ("\tCOPY_CARRY;\n");
+}
+
+typedef enum
+{
+  flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_zn,
+  flag_av, flag_sv
+}
+flagtypes;
+
+static void genflags_normal (flagtypes type, wordsizes size, const char *value,
+                             const char *src, const char *dst)
+{
+    char vstr[100], sstr[100], dstr[100];
+    char usstr[100], udstr[100];
+    char unsstr[100], undstr[100];
+
+    switch (size) {
+     case sz_byte:
+       strcpy (vstr, "((int8_t)(");
+       strcpy (usstr, "((uint8_t)(");
+       break;
+     case sz_word:
+       strcpy (vstr, "((int16_t)(");
+       strcpy (usstr, "((uint16_t)(");
+       break;
+     case sz_long:
+       strcpy (vstr, "((int32_t)(");
+       strcpy (usstr, "((uint32_t)(");
+       break;
+     default:
+       abort ();
+    }
+    strcpy (unsstr, usstr);
+
+    strcpy (sstr, vstr);
+    strcpy (dstr, vstr);
+    strcat (vstr, value);
+    strcat (vstr, "))");
+    strcat (dstr, dst);
+    strcat (dstr, "))");
+    strcat (sstr, src);
+    strcat (sstr, "))");
+
+    strcpy (udstr, usstr);
+    strcat (udstr, dst);
+    strcat (udstr, "))");
+    strcat (usstr, src);
+    strcat (usstr, "))");
+
+    strcpy (undstr, unsstr);
+    strcat (unsstr, "-");
+    strcat (undstr, "~");
+    strcat (undstr, dst);
+    strcat (undstr, "))");
+    strcat (unsstr, src);
+    strcat (unsstr, "))");
+
+    switch (type) {
+     case flag_logical_noclobber:
+     case flag_logical:
+     case flag_zn:
+     case flag_av:
+     case flag_sv:
+     case flag_addx:
+     case flag_subx:
+       break;
+
+     case flag_add:
+       start_brace ();
+       printf ("uint32_t %s = %s + %s;\n", value, dstr, sstr);
+       break;
+     case flag_sub:
+     case flag_cmp:
+       start_brace ();
+       printf ("uint32_t %s = %s - %s;\n", value, dstr, sstr);
+       break;
+    }
+
+    switch (type) {
+     case flag_logical_noclobber:
+     case flag_logical:
+     case flag_zn:
+       break;
+
+     case flag_add:
+     case flag_sub:
+     case flag_addx:
+     case flag_subx:
+     case flag_cmp:
+     case flag_av:
+     case flag_sv:
+       start_brace ();
+       printf ("\t" BOOL_TYPE " flgs = %s < 0;\n", sstr);
+       printf ("\t" BOOL_TYPE " flgo = %s < 0;\n", dstr);
+       printf ("\t" BOOL_TYPE " flgn = %s < 0;\n", vstr);
+       break;
+    }
+
+    switch (type) {
+     case flag_logical:
+       printf ("\tCLEAR_CZNV;\n");
+       printf ("\tSET_ZFLG (%s == 0);\n", vstr);
+       printf ("\tSET_NFLG (%s < 0);\n", vstr);
+       break;
+     case flag_logical_noclobber:
+       printf ("\tSET_ZFLG (%s == 0);\n", vstr);
+       printf ("\tSET_NFLG (%s < 0);\n", vstr);
+       break;
+     case flag_av:
+       printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
+       break;
+     case flag_sv:
+       printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
+       break;
+     case flag_zn:
+       printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr);
+       printf ("\tSET_NFLG (%s < 0);\n", vstr);
+       break;
+     case flag_add:
+       printf ("\tSET_ZFLG (%s == 0);\n", vstr);
+       printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
+       printf ("\tSET_CFLG (%s < %s);\n", undstr, usstr);
+       duplicate_carry ();
+       printf ("\tSET_NFLG (flgn != 0);\n");
+       break;
+     case flag_sub:
+       printf ("\tSET_ZFLG (%s == 0);\n", vstr);
+       printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
+       printf ("\tSET_CFLG (%s > %s);\n", usstr, udstr);
+       duplicate_carry ();
+       printf ("\tSET_NFLG (flgn != 0);\n");
+       break;
+     case flag_addx:
+       printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n"); /* minterm SON: 0x42 */
+       printf ("\tSET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));\n"); /* minterm SON: 0xD4 */
+       duplicate_carry ();
+       break;
+     case flag_subx:
+       printf ("\tSET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));\n"); /* minterm SON: 0x24 */
+       printf ("\tSET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));\n"); /* minterm SON: 0xB2 */
+       duplicate_carry ();
+       break;
+     case flag_cmp:
+       printf ("\tSET_ZFLG (%s == 0);\n", vstr);
+       printf ("\tSET_VFLG ((flgs != flgo) && (flgn != flgo));\n");
+       printf ("\tSET_CFLG (%s > %s);\n", usstr, udstr);
+       printf ("\tSET_NFLG (flgn != 0);\n");
+       break;
+    }
+}
+
+static void genflags (flagtypes type, wordsizes size, const char *value,
+                      const char *src, const char *dst)
+{
+    /* Temporarily deleted 68k/ARM flag optimizations.  I'd prefer to have
+       them in the appropriate m68k.h files and use just one copy of this
+       code here.  The API can be changed if necessary.  */
+#ifdef OPTIMIZED_FLAGS
+    switch (type) {
+     case flag_add:
+     case flag_sub:
+       start_brace ();
+       printf ("\tuint32_t %s;\n", value);
+       break;
+
+     default:
+       break;
+    }
+
+    /* At least some of those casts are fairly important! */
+    switch (type) {
+     case flag_logical_noclobber:
+       printf ("\t{uint32_t oldcznv = GET_CZNV & ~(FLAGVAL_Z | FLAGVAL_N);\n");
+       if (strcmp (value, "0") == 0) {
+           printf ("\tSET_CZNV (olcznv | FLAGVAL_Z);\n");
+       } else {
+           switch (size) {
+            case sz_byte: printf ("\toptflag_testb ((int8_t)(%s));\n", value); break;
+            case sz_word: printf ("\toptflag_testw ((int16_t)(%s));\n", value); break;
+            case sz_long: printf ("\toptflag_testl ((int32_t)(%s));\n", value); break;
+           }
+           printf ("\tIOR_CZNV (oldcznv);\n");
+       }
+       printf ("\t}\n");
+       return;
+     case flag_logical:
+       if (strcmp (value, "0") == 0) {
+           printf ("\tSET_CZNV (FLAGVAL_Z);\n");
+       } else {
+           switch (size) {
+            case sz_byte: printf ("\toptflag_testb ((int8_t)(%s));\n", value); break;
+            case sz_word: printf ("\toptflag_testw ((int16_t)(%s));\n", value); break;
+            case sz_long: printf ("\toptflag_testl ((int32_t)(%s));\n", value); break;
+           }
+       }
+       return;
+
+     case flag_add:
+       switch (size) {
+        case sz_byte: printf ("\toptflag_addb (%s, (int8_t)(%s), (int8_t)(%s));\n", value, src, dst); break;
+        case sz_word: printf ("\toptflag_addw (%s, (int16_t)(%s), (int16_t)(%s));\n", value, src, dst); break;
+        case sz_long: printf ("\toptflag_addl (%s, (int32_t)(%s), (int32_t)(%s));\n", value, src, dst); break;
+       }
+       return;
+
+     case flag_sub:
+       switch (size) {
+        case sz_byte: printf ("\toptflag_subb (%s, (int8_t)(%s), (int8_t)(%s));\n", value, src, dst); break;
+        case sz_word: printf ("\toptflag_subw (%s, (int16_t)(%s), (int16_t)(%s));\n", value, src, dst); break;
+        case sz_long: printf ("\toptflag_subl (%s, (int32_t)(%s), (int32_t)(%s));\n", value, src, dst); break;
+       }
+       return;
+
+     case flag_cmp:
+       switch (size) {
+        case sz_byte: printf ("\toptflag_cmpb ((int8_t)(%s), (int8_t)(%s));\n", src, dst); break;
+        case sz_word: printf ("\toptflag_cmpw ((int16_t)(%s), (int16_t)(%s));\n", src, dst); break;
+        case sz_long: printf ("\toptflag_cmpl ((int32_t)(%s), (int32_t)(%s));\n", src, dst); break;
+       }
+       return;
+       
+     default:
+       break;
+    }
+#endif
+
+    genflags_normal (type, size, value, src, dst);
+}
+
+static void force_range_for_rox (const char *var, wordsizes size)
+{
+    /* Could do a modulo operation here... which one is faster? */
+    switch (size) {
+     case sz_long:
+       printf ("\tif (%s >= 33) %s -= 33;\n", var, var);
+       break;
+     case sz_word:
+       printf ("\tif (%s >= 34) %s -= 34;\n", var, var);
+       printf ("\tif (%s >= 17) %s -= 17;\n", var, var);
+       break;
+     case sz_byte:
+       printf ("\tif (%s >= 36) %s -= 36;\n", var, var);
+       printf ("\tif (%s >= 18) %s -= 18;\n", var, var);
+       printf ("\tif (%s >= 9) %s -= 9;\n", var, var);
+       break;
+    }
+}
+
+static const char *cmask (wordsizes size)
+{
+    switch (size) {
+     case sz_byte: return "0x80";
+     case sz_word: return "0x8000";
+     case sz_long: return "0x80000000";
+     default: abort ();
+    }
+}
+
+static int source_is_imm1_8 (struct instr *i)
+{
+    return i->stype == 3;
+}
+
+
+
+static void gen_opcode (unsigned long int opcode)
+{
+#if 0
+    char *amodenames[] = { "Dreg", "Areg", "Aind", "Aipi", "Apdi", "Ad16", "Ad8r",
+         "absw", "absl", "PC16", "PC8r", "imm", "imm0", "imm1", "imm2", "immi", "am_unknown", "am_illg"};
+#endif
+
+    struct instr *curi = table68k + opcode;
+    insn_n_cycles = 4;
+
+    /* Store the family of the instruction (used to check for pairing on ST)
+     * and leave some space for patching in the current cycles later */
+    printf ("\tOpcodeFamily = %d; CurrentInstrCycles =     \n", curi->mnemo);
+    nCurInstrCycPos = ftell(stdout) - 5;
+
+    start_brace ();
+    m68k_pc_offset = 2;
+
+    switch (curi->plev) {
+    case 0: /* not privileged */
+       break;
+    case 1: /* unprivileged only on 68000 */
+       if (cpu_level == 0)
+           break;
+       if (next_cpu_level < 0)
+           next_cpu_level = 0;
+
+       /* fall through */
+    case 2: /* priviledged */
+       printf ("if (!regs.s) { Exception(8,0,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
+       need_endlabel = 1;
+       start_brace ();
+       break;
+    case 3: /* privileged if size == word */
+       if (curi->size == sz_byte)
+           break;
+       printf ("if (!regs.s) { Exception(8,0,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
+       need_endlabel = 1;
+       start_brace ();
+       break;
+    }
+
+    /* Build the opcodes: */
+    switch (curi->mnemo) {
+    case i_OR:
+    case i_AND:
+    case i_EOR:
+        genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+        genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+        printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^');
+        genflags (flag_logical, curi->size, "src", "", "");
+        genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
+        if(curi->size==sz_long && curi->dmode==Dreg)
+         {
+          insn_n_cycles += 2;
+          if(curi->smode==Dreg || curi->smode==Areg || (curi->smode>=imm && curi->smode<=immi))
+            insn_n_cycles += 2;
+         }
+#if 0
+        /* Output the CPU cycles: */
+        fprintf(stderr,"MOVE, size %i: ",curi->size);
+        fprintf(stderr," %s ->",amodenames[curi->smode]);
+        fprintf(stderr," %s ",amodenames[curi->dmode]);
+        fprintf(stderr," Cycles: %i\n",insn_n_cycles);
+#endif
+        break;
+    case i_ORSR:
+    case i_EORSR:
+        printf ("\tMakeSR();\n");
+        genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+        if (curi->size == sz_byte) {
+            printf ("\tsrc &= 0xFF;\n");
+        }
+        printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|');
+        printf ("\tMakeFromSR();\n");
+        insn_n_cycles = 20;
+        break;
+    case i_ANDSR:
+        printf ("\tMakeSR();\n");
+        genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+        if (curi->size == sz_byte) {
+            printf ("\tsrc |= 0xFF00;\n");
+        }
+        printf ("\tregs.sr &= src;\n");
+        printf ("\tMakeFromSR();\n");
+        insn_n_cycles = 20;
+        break;
+    case i_SUB:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       start_brace ();
+       genflags (flag_sub, curi->size, "newv", "src", "dst");
+       genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+        if(curi->size==sz_long && curi->dmode==Dreg)
+         {
+          insn_n_cycles += 2;
+          if(curi->smode==Dreg || curi->smode==Areg || (curi->smode>=imm && curi->smode<=immi))
+            insn_n_cycles += 2;
+         }
+       break;
+    case i_SUBA:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
+       start_brace ();
+       printf ("\tuint32_t newv = dst - src;\n");
+       genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+        if(curi->size==sz_long && curi->smode!=Dreg && curi->smode!=Areg && !(curi->smode>=imm && curi->smode<=immi))
+          insn_n_cycles += 2;
+         else
+          insn_n_cycles += 4;
+       break;
+    case i_SUBX:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       start_brace ();
+       printf ("\tuint32_t newv = dst - src - (GET_XFLG ? 1 : 0);\n");
+       genflags (flag_subx, curi->size, "newv", "src", "dst");
+       genflags (flag_zn, curi->size, "newv", "", "");
+       genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+        if(curi->smode==Dreg && curi->size==sz_long)
+          insn_n_cycles=8;
+        if(curi->smode==Apdi)
+         {
+          if(curi->size==sz_long)
+            insn_n_cycles=30;
+           else
+            insn_n_cycles=18;
+         }
+       break;
+    case i_SBCD:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       start_brace ();
+       printf ("\tuint16_t newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);\n");
+       printf ("\tuint16_t newv_hi = (dst & 0xF0) - (src & 0xF0);\n");
+       printf ("\tuint16_t newv, tmp_newv;\n");
+       printf ("\tint bcd = 0;\n");
+       printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n");
+       printf ("\tif (newv_lo & 0xF0) { newv -= 6; bcd = 6; };\n");
+       printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n");
+       printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG ? 1 : 0)) & 0x300) > 0xFF);\n");
+       duplicate_carry ();
+       genflags (flag_zn, curi->size, "newv", "", "");
+       printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
+       genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+       if(curi->smode==Dreg)  insn_n_cycles=6;
+       if(curi->smode==Apdi)  insn_n_cycles=18;
+       break;
+    case i_ADD:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       start_brace ();
+       printf("\trefill_prefetch (m68k_getpc(), 2);\n");       // FIXME [NP] For Transbeauce 2 demo, need better prefetch emulation
+       genflags (flag_add, curi->size, "newv", "src", "dst");
+       genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+        if(curi->size==sz_long && curi->dmode==Dreg)
+         {
+          insn_n_cycles += 2;
+          if(curi->smode==Dreg || curi->smode==Areg || (curi->smode>=imm && curi->smode<=immi))
+            insn_n_cycles += 2;
+         }
+       break;
+    case i_ADDA:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
+       start_brace ();
+       printf ("\tuint32_t newv = dst + src;\n");
+       genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+        if(curi->size==sz_long && curi->smode!=Dreg && curi->smode!=Areg && !(curi->smode>=imm && curi->smode<=immi))
+          insn_n_cycles += 2;
+         else
+          insn_n_cycles += 4;
+       break;
+    case i_ADDX:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       start_brace ();
+       printf ("\tuint32_t newv = dst + src + (GET_XFLG ? 1 : 0);\n");
+       genflags (flag_addx, curi->size, "newv", "src", "dst");
+       genflags (flag_zn, curi->size, "newv", "", "");
+       genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+        if(curi->smode==Dreg && curi->size==sz_long)
+          insn_n_cycles=8;
+        if(curi->smode==Apdi)
+         {
+          if(curi->size==sz_long)
+            insn_n_cycles=30;
+           else
+            insn_n_cycles=18;
+         }
+       break;
+    case i_ABCD:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       start_brace ();
+       printf ("\tuint16_t newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);\n");
+       printf ("\tuint16_t newv_hi = (src & 0xF0) + (dst & 0xF0);\n");
+       printf ("\tuint16_t newv, tmp_newv;\n");
+       printf ("\tint cflg;\n");
+       printf ("\tnewv = tmp_newv = newv_hi + newv_lo;");
+       printf ("\tif (newv_lo > 9) { newv += 6; }\n");
+       printf ("\tcflg = (newv & 0x3F0) > 0x90;\n");
+       printf ("\tif (cflg) newv += 0x60;\n");
+       printf ("\tSET_CFLG (cflg);\n");
+       duplicate_carry ();
+       genflags (flag_zn, curi->size, "newv", "", "");
+       printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n");
+       genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
+       if(curi->smode==Dreg)  insn_n_cycles=6;
+       if(curi->smode==Apdi)  insn_n_cycles=18;
+       break;
+    case i_NEG:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       start_brace ();
+       genflags (flag_sub, curi->size, "dst", "src", "0");
+       genastore ("dst", curi->smode, "srcreg", curi->size, "src");
+        if(curi->size==sz_long && curi->smode==Dreg)  insn_n_cycles += 2;
+       break;
+    case i_NEGX:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       start_brace ();
+       printf ("\tuint32_t newv = 0 - src - (GET_XFLG ? 1 : 0);\n");
+       genflags (flag_subx, curi->size, "newv", "src", "0");
+       genflags (flag_zn, curi->size, "newv", "", "");
+       genastore ("newv", curi->smode, "srcreg", curi->size, "src");
+        if(curi->size==sz_long && curi->smode==Dreg)  insn_n_cycles += 2;
+       break;
+    case i_NBCD:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       start_brace ();
+       printf ("\tuint16_t newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);\n");
+       printf ("\tuint16_t newv_hi = - (src & 0xF0);\n");
+       printf ("\tuint16_t newv;\n");
+       printf ("\tint cflg;\n");
+       printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n");
+       printf ("\tnewv = newv_hi + newv_lo;");
+       printf ("\tcflg = (newv & 0x1F0) > 0x90;\n");
+       printf ("\tif (cflg) newv -= 0x60;\n");
+       printf ("\tSET_CFLG (cflg);\n");
+       duplicate_carry();
+       genflags (flag_zn, curi->size, "newv", "", "");
+       genastore ("newv", curi->smode, "srcreg", curi->size, "src");
+       if(curi->smode==Dreg)  insn_n_cycles += 2;
+       break;
+    case i_CLR:
+       genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
+
+       /* [NP] CLR does a read before the write only on 68000 */
+       /* but there's no cycle penalty for doing the read */
+       if ( curi->smode != Dreg )                      // only if destination is memory
+         {
+           if (curi->size==sz_byte)
+             printf ("\tint8_t src = m68k_read_memory_8(srca);\n");
+           else if (curi->size==sz_word)
+             printf ("\tint16_t src = m68k_read_memory_16(srca);\n");
+           else if (curi->size==sz_long)
+             printf ("\tint32_t src = m68k_read_memory_32(srca);\n");
+         }
+
+       genflags (flag_logical, curi->size, "0", "", "");
+       genastore ("0", curi->smode, "srcreg", curi->size, "src");
+        if(curi->size==sz_long)
+        {
+          if(curi->smode==Dreg)
+            insn_n_cycles += 2;
+           else
+            insn_n_cycles += 4;
+        }
+        if(curi->smode!=Dreg)
+          insn_n_cycles += 4;
+       break;
+    case i_NOT:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       start_brace ();
+       printf ("\tuint32_t dst = ~src;\n");
+       genflags (flag_logical, curi->size, "dst", "", "");
+       genastore ("dst", curi->smode, "srcreg", curi->size, "src");
+        if(curi->size==sz_long && curi->smode==Dreg)  insn_n_cycles += 2;
+       break;
+    case i_TST:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genflags (flag_logical, curi->size, "src", "", "");
+       break;
+    case i_BTST:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       if (curi->size == sz_byte)
+           printf ("\tsrc &= 7;\n");
+       else
+           printf ("\tsrc &= 31;\n");
+       printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
+        if(curi->dmode==Dreg)  insn_n_cycles += 2;
+       break;
+    case i_BCHG:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       if (curi->size == sz_byte)
+           printf ("\tsrc &= 7;\n");
+       else
+           printf ("\tsrc &= 31;\n");
+       printf ("\tdst ^= (1 << src);\n");
+       printf ("\tSET_ZFLG (((uint32_t)dst & (1 << src)) >> src);\n");
+       genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
+        if(curi->dmode==Dreg)  insn_n_cycles += 4;
+       break;
+    case i_BCLR:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       if (curi->size == sz_byte)
+           printf ("\tsrc &= 7;\n");
+       else
+           printf ("\tsrc &= 31;\n");
+       printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
+       printf ("\tdst &= ~(1 << src);\n");
+       genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
+        if(curi->dmode==Dreg)  insn_n_cycles += 6;
+       /* [NP] BCLR #n,Dx takes 12 cycles instead of 14 if n<16 */
+        if((curi->smode==imm1) && (curi->dmode==Dreg))
+           printf ("\tif ( src < 16 ) { m68k_incpc(4); return 12; }\n");
+       /* [NP] BCLR Dy,Dx takes 8 cycles instead of 10 if Dy<16 */
+        if((curi->smode==Dreg) && (curi->dmode==Dreg))
+           printf ("\tif ( src < 16 ) { m68k_incpc(2); return 8; }\n");
+       break;
+    case i_BSET:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       if (curi->size == sz_byte)
+           printf ("\tsrc &= 7;\n");
+       else
+           printf ("\tsrc &= 31;\n");
+       printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
+       printf ("\tdst |= (1 << src);\n");
+       genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
+        if(curi->dmode==Dreg)  insn_n_cycles += 4;
+       break;
+    case i_CMPM:
+    case i_CMP:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       start_brace ();
+       genflags (flag_cmp, curi->size, "newv", "src", "dst");
+        if(curi->size==sz_long && curi->dmode==Dreg)
+          insn_n_cycles += 2;
+       break;
+    case i_CMPA:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
+       start_brace ();
+       genflags (flag_cmp, sz_long, "newv", "src", "dst");
+        insn_n_cycles += 2;
+       break;
+       /* The next two are coded a little unconventional, but they are doing
+        * weird things... */
+    case i_MVPRM:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+
+       printf ("\tuint32_t memp = m68k_areg(regs, dstreg) + (int32_t)(int16_t)%s;\n", gen_nextiword ());
+       if (curi->size == sz_word) {
+           printf ("\tm68k_write_memory_8(memp, src >> 8); m68k_write_memory_8(memp + 2, src);\n");
+       } else {
+           printf ("\tm68k_write_memory_8(memp, src >> 24); m68k_write_memory_8(memp + 2, src >> 16);\n");
+           printf ("\tm68k_write_memory_8(memp + 4, src >> 8); m68k_write_memory_8(memp + 6, src);\n");
+       }
+        if(curi->size==sz_long)  insn_n_cycles=24;  else  insn_n_cycles=16;
+       break;
+    case i_MVPMR:
+       printf ("\tuint32_t memp = m68k_areg(regs, srcreg) + (int32_t)(int16_t)%s;\n", gen_nextiword ());
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+       if (curi->size == sz_word) {
+           printf ("\tuint16_t val = (m68k_read_memory_8(memp) << 8) + m68k_read_memory_8(memp + 2);\n");
+       } else {
+           printf ("\tuint32_t val = (m68k_read_memory_8(memp) << 24) + (m68k_read_memory_8(memp + 2) << 16)\n");
+           printf ("              + (m68k_read_memory_8(memp + 4) << 8) + m68k_read_memory_8(memp + 6);\n");
+       }
+       genastore ("val", curi->dmode, "dstreg", curi->size, "dst");
+        if(curi->size==sz_long)  insn_n_cycles=24;  else  insn_n_cycles=16;
+       break;
+    case i_MOVE:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+
+       /* [NP] genamode counts 2 cycles if dest is -(An), this is wrong. */
+       /* For move dest (An), (An)+ and -(An) take the same time */
+       /* (for other instr, dest -(An) really takes 2 cycles more) */
+       if ( curi->dmode == Apdi )
+         insn_n_cycles -= 2;                   /* correct the wrong cycle count for -(An) */
+
+       genflags (flag_logical, curi->size, "src", "", "");
+       genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
+       break;
+    case i_MOVEA:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+       if (curi->size == sz_word) {
+           printf ("\tuint32_t val = (int32_t)(int16_t)src;\n");
+       } else {
+           printf ("\tuint32_t val = src;\n");
+       }
+       genastore ("val", curi->dmode, "dstreg", sz_long, "dst");
+       break;
+    case i_MVSR2:  /* Move from SR */
+       genamode (curi->smode, "srcreg", sz_word, "src", 2, 0);
+       printf ("\tMakeSR();\n");
+       if (curi->size == sz_byte)
+           genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src");
+       else
+           genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src");
+        if (curi->smode==Dreg)  insn_n_cycles += 2;  else  insn_n_cycles += 4;
+       break;
+    case i_MV2SR:  /* Move to SR */
+       genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
+       if (curi->size == sz_byte)
+           printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n");
+       else {
+           printf ("\tregs.sr = src;\n");
+       }
+       printf ("\tMakeFromSR();\n");
+        insn_n_cycles += 8;
+       break;
+    case i_SWAP:
+       genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
+       start_brace ();
+       printf ("\tuint32_t dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n");
+       genflags (flag_logical, sz_long, "dst", "", "");
+       genastore ("dst", curi->smode, "srcreg", sz_long, "src");
+       break;
+    case i_EXG:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       genastore ("dst", curi->smode, "srcreg", curi->size, "src");
+       genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
+        insn_n_cycles = 6;
+       break;
+    case i_EXT:
+       genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t dst = (int32_t)(int8_t)src;\n"); break;
+       case sz_word: printf ("\tuint16_t dst = (int16_t)(int8_t)src;\n"); break;
+       case sz_long: printf ("\tuint32_t dst = (int32_t)(int16_t)src;\n"); break;
+       default: abort ();
+       }
+       genflags (flag_logical,
+                 curi->size == sz_word ? sz_word : sz_long, "dst", "", "");
+       genastore ("dst", curi->smode, "srcreg",
+                  curi->size == sz_word ? sz_word : sz_long, "src");
+       break;
+    case i_MVMEL:
+       genmovemel (opcode);
+       break;
+    case i_MVMLE:
+       genmovemle (opcode);
+       break;
+    case i_TRAP:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tException(src+32,0,M68000_EXC_SRC_CPU);\n");
+       m68k_pc_offset = 0;
+       break;
+    case i_MVR2USP:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       printf ("\tregs.usp = src;\n");
+       break;
+    case i_MVUSP2R:
+       genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
+       genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src");
+       break;
+    case i_RESET:
+//JLH:Not needed       printf ("\tcustomreset();\n");
+        insn_n_cycles = 132;    /* I am not so sure about this!? - Thothy */
+       break;
+    case i_NOP:
+       break;
+    case i_STOP:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       printf ("\tregs.sr = src;\n");
+       printf ("\tMakeFromSR();\n");
+       printf ("\tm68k_setstopped(1);\n");
+        insn_n_cycles = 4;
+       break;
+    case i_RTE:
+       if (cpu_level == 0) {
+           genamode (Aipi, "7", sz_word, "sr", 1, 0);
+           genamode (Aipi, "7", sz_long, "pc", 1, 0);
+           printf ("\tregs.sr = sr; m68k_setpc_rte(pc);\n");
+           fill_prefetch_0 ();
+           printf ("\tMakeFromSR();\n");
+       } else {
+           int old_brace_level = n_braces;
+           if (next_cpu_level < 0)
+               next_cpu_level = 0;
+           printf ("\tuint16_t newsr; uint32_t newpc; for (;;) {\n");
+           genamode (Aipi, "7", sz_word, "sr", 1, 0);
+           genamode (Aipi, "7", sz_long, "pc", 1, 0);
+           genamode (Aipi, "7", sz_word, "format", 1, 0);
+           printf ("\tnewsr = sr; newpc = pc;\n");
+           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");
+           printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n");
+           printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n");
+           printf ("\telse if ((format & 0xF000) == 0xa000) { m68k_areg(regs, 7) += 24; break; }\n");
+           printf ("\telse if ((format & 0xF000) == 0xb000) { m68k_areg(regs, 7) += 84; break; }\n");
+           printf ("\telse { Exception(14,0,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
+           printf ("\tregs.sr = newsr; MakeFromSR();\n}\n");
+           pop_braces (old_brace_level);
+           printf ("\tregs.sr = newsr; MakeFromSR();\n");
+           printf ("\tm68k_setpc_rte(newpc);\n");
+           fill_prefetch_0 ();
+           need_endlabel = 1;
+       }
+       /* PC is set and prefetch filled. */
+       m68k_pc_offset = 0;
+        insn_n_cycles = 20;
+       break;
+    case i_RTD:
+       genamode (Aipi, "7", sz_long, "pc", 1, 0);
+       genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0);
+       printf ("\tm68k_areg(regs, 7) += offs;\n");
+       printf ("\tm68k_setpc_rte(pc);\n");
+       fill_prefetch_0 ();
+       /* PC is set and prefetch filled. */
+       m68k_pc_offset = 0;
+       break;
+    case i_LINK:
+       genamode (Apdi, "7", sz_long, "old", 2, 0);
+       genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
+       genastore ("src", Apdi, "7", sz_long, "old");
+       genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
+       genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
+       printf ("\tm68k_areg(regs, 7) += offs;\n");
+       break;
+    case i_UNLK:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       printf ("\tm68k_areg(regs, 7) = src;\n");
+       genamode (Aipi, "7", sz_long, "old", 1, 0);
+       genastore ("old", curi->smode, "srcreg", curi->size, "src");
+       break;
+    case i_RTS:
+       printf ("\tm68k_do_rts();\n");
+       fill_prefetch_0 ();
+       m68k_pc_offset = 0;
+        insn_n_cycles = 16;
+       break;
+    case i_TRAPV:
+       sync_m68k_pc ();
+       printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc(),M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
+       need_endlabel = 1;
+       break;
+    case i_RTR:
+       printf ("\tMakeSR();\n");
+       genamode (Aipi, "7", sz_word, "sr", 1, 0);
+       genamode (Aipi, "7", sz_long, "pc", 1, 0);
+       printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
+       printf ("\tregs.sr |= sr; m68k_setpc(pc);\n");
+       fill_prefetch_0 ();
+       printf ("\tMakeFromSR();\n");
+       m68k_pc_offset = 0;
+        insn_n_cycles = 20;
+       break;
+    case i_JSR:
+       genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
+       printf ("\tuint32_t oldpc = m68k_getpc () + %d;\n", m68k_pc_offset);
+       if (using_exception_3) {
+           printf ("\tif (srca & 1) {\n");
+           printf ("\t\tlast_addr_for_exception_3 = oldpc;\n");
+           printf ("\t\tlast_fault_for_exception_3 = srca;\n");
+           printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
+           printf ("\t}\n");
+           need_endlabel = 1;
+       }
+       printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset);
+       fill_prefetch_0 ();
+       m68k_pc_offset = 0;
+        switch(curi->smode)
+         {
+          case Aind:  insn_n_cycles=16; break;
+          case Ad16:  insn_n_cycles=18; break;
+          case Ad8r:  insn_n_cycles=22; break;
+          case absw:  insn_n_cycles=18; break;
+          case absl:  insn_n_cycles=20; break;
+          case PC16:  insn_n_cycles=18; break;
+          case PC8r:  insn_n_cycles=22; break;
+         }
+       break;
+    case i_JMP:
+       genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
+       if (using_exception_3) {
+           printf ("\tif (srca & 1) {\n");
+           printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 6;\n");
+           printf ("\t\tlast_fault_for_exception_3 = srca;\n");
+           printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
+           printf ("\t}\n");
+           need_endlabel = 1;
+       }
+       printf ("\tm68k_setpc(srca);\n");
+       fill_prefetch_0 ();
+       m68k_pc_offset = 0;
+        switch(curi->smode)
+         {
+          case Aind:  insn_n_cycles=8; break;
+          case Ad16:  insn_n_cycles=10; break;
+          case Ad8r:  insn_n_cycles=14; break;
+          case absw:  insn_n_cycles=10; break;
+          case absl:  insn_n_cycles=12; break;
+          case PC16:  insn_n_cycles=10; break;
+          case PC8r:  insn_n_cycles=14; break;
+         }
+       break;
+    case i_BSR:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       printf ("\tint32_t s = (int32_t)src + 2;\n");
+       if (using_exception_3) {
+           printf ("\tif (src & 1) {\n");
+           printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");     // [NP] FIXME should be +4, not +2 (same as DBcc) ?
+           printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + s;\n");
+           printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
+           printf ("\t}\n");
+           need_endlabel = 1;
+       }
+       printf ("\tm68k_do_bsr(m68k_getpc() + %d, s);\n", m68k_pc_offset);
+       fill_prefetch_0 ();
+       m68k_pc_offset = 0;
+        insn_n_cycles = 18;
+       break;
+    case i_Bcc:
+       if (curi->size == sz_long) {
+           if (cpu_level < 2) {
+               printf ("\tm68k_incpc(2);\n");
+               printf ("\tif (!cctrue(%d)) goto %s;\n", curi->cc, endlabelstr);
+               printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
+               printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 1;\n");
+               printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
+               need_endlabel = 1;
+           } else {
+               if (next_cpu_level < 1)
+                   next_cpu_level = 1;
+           }
+       }
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       printf ("\tif (!cctrue(%d)) goto didnt_jump;\n", curi->cc);
+       if (using_exception_3) {
+           printf ("\tif (src & 1) {\n");
+           printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");     // [NP] FIXME should be +4, not +2 (same as DBcc) ?
+           printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (int32_t)src;\n");
+           printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
+           printf ("\t}\n");
+           need_endlabel = 1;
+       }
+       printf ("\tm68k_incpc ((int32_t)src + 2);\n");
+       fill_prefetch_0 ();
+       printf ("\treturn 10;\n");
+       printf ("didnt_jump:;\n");
+       need_endlabel = 1;
+       insn_n_cycles = (curi->size == sz_byte) ? 8 : 12;
+       break;
+    case i_LEA:
+       genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+       genastore ("srca", curi->dmode, "dstreg", curi->size, "dst");
+        /* Set correct cycles: According to the M68K User Manual, LEA takes 12
+         * cycles in Ad8r and PC8r mode, but it takes 14 (or 16) cycles on a real ST: */
+        if (curi->smode == Ad8r || curi->smode == PC8r)
+          insn_n_cycles = 14;
+       break;
+    case i_PEA:
+       genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
+       genamode (Apdi, "7", sz_long, "dst", 2, 0);
+       genastore ("srca", Apdi, "7", sz_long, "dst");
+       /* Set correct cycles: */
+        switch(curi->smode)
+         {
+          case Aind:  insn_n_cycles=12; break;
+          case Ad16:  insn_n_cycles=16; break;
+          /* Note: according to the M68K User Manual, PEA takes 20 cycles for
+           * the Ad8r mode, but on a real ST, it takes 22 (or 24) cycles! */
+          case Ad8r:  insn_n_cycles=22; break;
+          case absw:  insn_n_cycles=16; break;
+          case absl:  insn_n_cycles=20; break;
+          case PC16:  insn_n_cycles=16; break;
+          /* Note: PEA with PC8r takes 20 cycles according to the User Manual,
+           * but it takes 22 (or 24) cycles on a real ST: */
+          case PC8r:  insn_n_cycles=22; break;
+         }
+       break;
+    case i_DBcc:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
+
+       printf ("\tif (!cctrue(%d)) {\n\t", curi->cc);
+       genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src");
+
+       printf ("\t\tif (src) {\n");
+       if (using_exception_3) {
+           printf ("\t\t\tif (offs & 1) {\n");
+           printf ("\t\t\tlast_addr_for_exception_3 = m68k_getpc() + 2 + 2;\n");       // [NP] last_addr is pc+4, not pc+2
+           printf ("\t\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (int32_t)offs + 2;\n");
+           printf ("\t\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
+           printf ("\t\t}\n");
+           need_endlabel = 1;
+       }
+       printf ("\t\t\tm68k_incpc((int32_t)offs + 2);\n");
+       fill_prefetch_0 ();
+       printf ("\t\t\treturn 10;\n");
+       printf ("\t\t} else {\n\t\t\t");
+        {
+         int tmp_offset = m68k_pc_offset;
+         sync_m68k_pc();              /* not so nice to call it here... */
+         m68k_pc_offset = tmp_offset;
+        }
+        printf ("\t\t\treturn 14;\n");
+        printf ("\t\t}\n");
+       printf ("\t}\n");
+       insn_n_cycles = 12;
+       need_endlabel = 1;
+       break;
+    case i_Scc:
+       genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
+       start_brace ();
+       printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc);
+       genastore ("val", curi->smode, "srcreg", curi->size, "src");
+        if (curi->smode!=Dreg)  insn_n_cycles += 4;
+       else
+         {                                     /* [NP] if result is TRUE, we return 6 instead of 4 */
+           printf ("\tif (val) { m68k_incpc(2) ; return 4+2; }\n");
+         }
+       break;
+    case i_DIVU:
+       printf ("\tuint32_t oldpc = m68k_getpc();\n");
+       genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
+       sync_m68k_pc ();
+       /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends
+        * on this (actually, it's doing a DIVS).  */
+       printf ("\tif (src == 0) { SET_VFLG (0); Exception (5, oldpc,M68000_EXC_SRC_CPU); goto %s; } else {\n", endlabelstr);
+       printf ("\tuint32_t newv = (uint32_t)dst / (uint32_t)(uint16_t)src;\n");
+       printf ("\tuint32_t rem = (uint32_t)dst %% (uint32_t)(uint16_t)src;\n");
+       /* The N flag appears to be set each time there is an overflow.
+        * Weird. */
+       printf ("\tif (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
+       genflags (flag_logical, sz_word, "newv", "", "");
+       printf ("\tnewv = (newv & 0xffff) | ((uint32_t)rem << 16);\n");
+       genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+       printf ("\t}\n");
+       printf ("\t}\n");
+//     insn_n_cycles += 136;
+       printf ("\tretcycles = getDivu68kCycles((uint32_t)dst, (uint16_t)src);\n");
+        sprintf(exactCpuCycles," return (%i+retcycles);", insn_n_cycles);
+       need_endlabel = 1;
+       break;
+    case i_DIVS:
+       printf ("\tuint32_t oldpc = m68k_getpc();\n");
+       genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc,M68000_EXC_SRC_CPU); goto %s; } else {\n", endlabelstr);
+       printf ("\tint32_t newv = (int32_t)dst / (int32_t)(int16_t)src;\n");
+       printf ("\tuint16_t rem = (int32_t)dst %% (int32_t)(int16_t)src;\n");
+       printf ("\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
+       printf ("\tif (((int16_t)rem < 0) != ((int32_t)dst < 0)) rem = -rem;\n");
+       genflags (flag_logical, sz_word, "newv", "", "");
+       printf ("\tnewv = (newv & 0xffff) | ((uint32_t)rem << 16);\n");
+       genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+       printf ("\t}\n");
+       printf ("\t}\n");
+//     insn_n_cycles += 154;
+       printf ("\tretcycles = getDivs68kCycles((int32_t)dst, (int16_t)src);\n");
+        sprintf(exactCpuCycles," return (%i+retcycles);", insn_n_cycles);
+       need_endlabel = 1;
+       break;
+    case i_MULU:
+       genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
+       start_brace ();
+       printf ("\tuint32_t newv = (uint32_t)(uint16_t)dst * (uint32_t)(uint16_t)src;\n");
+       genflags (flag_logical, sz_long, "newv", "", "");
+       genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+       /* [NP] number of cycles is 38 + 2n + ea time ; n is the number of 1 bits in src */
+       insn_n_cycles += 38-4;                  /* insn_n_cycles is already initialized to 4 instead of 0 */
+       printf ("\twhile (src) { if (src & 1) retcycles++; src = (uint16_t)src >> 1; }\n");
+        sprintf(exactCpuCycles," return (%i+retcycles*2);", insn_n_cycles);
+       break;
+    case i_MULS:
+       genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
+       start_brace ();
+       printf ("\tuint32_t newv = (int32_t)(int16_t)dst * (int32_t)(int16_t)src;\n");
+       printf ("\tuint32_t src2;\n");
+       genflags (flag_logical, sz_long, "newv", "", "");
+       genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
+       /* [NP] number of cycles is 38 + 2n + ea time ; n is the number of 01 or 10 patterns in src expanded to 17 bits */
+       insn_n_cycles += 38-4;                  /* insn_n_cycles is already initialized to 4 instead of 0 */
+       printf ("\tsrc2 = ((uint32_t)src) << 1;\n");
+       printf ("\twhile (src2) { if ( ( (src2 & 3) == 1 ) || ( (src2 & 3) == 2 ) ) retcycles++; src2 >>= 1; }\n");
+        sprintf(exactCpuCycles," return (%i+retcycles*2);", insn_n_cycles);
+       break;
+    case i_CHK:
+       printf ("\tuint32_t oldpc = m68k_getpc();\n");
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tif ((int32_t)dst < 0) { SET_NFLG (1); Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
+       printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
+       need_endlabel = 1;
+        insn_n_cycles += 6;
+       break;
+
+    case i_CHK2:
+       printf ("\tuint32_t oldpc = m68k_getpc();\n");
+       genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+       printf ("\t{int32_t upper,lower,reg = regs.regs[(extra >> 12) & 15];\n");
+       switch (curi->size) {
+       case sz_byte:
+           printf ("\tlower=(int32_t)(int8_t)m68k_read_memory_8(dsta); upper = (int32_t)(int8_t)m68k_read_memory_8(dsta+1);\n");
+           printf ("\tif ((extra & 0x8000) == 0) reg = (int32_t)(int8_t)reg;\n");
+           break;
+       case sz_word:
+           printf ("\tlower=(int32_t)(int16_t)m68k_read_memory_16(dsta); upper = (int32_t)(int16_t)m68k_read_memory_16(dsta+2);\n");
+           printf ("\tif ((extra & 0x8000) == 0) reg = (int32_t)(int16_t)reg;\n");
+           break;
+       case sz_long:
+           printf ("\tlower=m68k_read_memory_32(dsta); upper = m68k_read_memory_32(dsta+4);\n");
+           break;
+       default:
+           abort ();
+       }
+       printf ("\tSET_ZFLG (upper == reg || lower == reg);\n");
+       printf ("\tSET_CFLG (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n");
+       sync_m68k_pc ();
+       printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n}\n", endlabelstr);
+       need_endlabel = 1;
+       break;
+
+    case i_ASR:
+       genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tuint32_t sign = (%s & val) >> %d;\n", cmask (curi->size), bit_size (curi->size) - 1);
+       printf ("\tcnt &= 63;\n");
+        printf ("\tretcycles = cnt;\n");
+       printf ("\tCLEAR_CZNV;\n");
+       printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
+       printf ("\t\tval = %s & (uint32_t)-sign;\n", bit_mask (curi->size));
+       printf ("\t\tSET_CFLG (sign);\n");
+       duplicate_carry ();
+       if (source_is_imm1_8 (curi))
+           printf ("\t} else {\n");
+       else
+           printf ("\t} else if (cnt > 0) {\n");
+       printf ("\t\tval >>= cnt - 1;\n");
+       printf ("\t\tSET_CFLG (val & 1);\n");
+       duplicate_carry ();
+       printf ("\t\tval >>= 1;\n");
+       printf ("\t\tval |= (%s << (%d - cnt)) & (uint32_t)-sign;\n",
+               bit_mask (curi->size),
+               bit_size (curi->size));
+       printf ("\t\tval &= %s;\n", bit_mask (curi->size));
+       printf ("\t}\n");
+       genflags (flag_logical_noclobber, curi->size, "val", "", "");
+       genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+        if(curi->size==sz_long)
+            strcpy(exactCpuCycles," return (8+retcycles*2);");
+          else
+            strcpy(exactCpuCycles," return (6+retcycles*2);");
+       break;
+    case i_ASL:
+       genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tcnt &= 63;\n");
+        printf ("\tretcycles = cnt;\n");
+       printf ("\tCLEAR_CZNV;\n");
+       printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
+       printf ("\t\tSET_VFLG (val != 0);\n");
+       printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
+               bit_size (curi->size));
+       duplicate_carry ();
+       printf ("\t\tval = 0;\n");
+       if (source_is_imm1_8 (curi))
+           printf ("\t} else {\n");
+       else
+           printf ("\t} else if (cnt > 0) {\n");
+       printf ("\t\tuint32_t mask = (%s << (%d - cnt)) & %s;\n",
+               bit_mask (curi->size),
+               bit_size (curi->size) - 1,
+               bit_mask (curi->size));
+       printf ("\t\tSET_VFLG ((val & mask) != mask && (val & mask) != 0);\n");
+       printf ("\t\tval <<= cnt - 1;\n");
+       printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
+       duplicate_carry ();
+       printf ("\t\tval <<= 1;\n");
+       printf ("\t\tval &= %s;\n", bit_mask (curi->size));
+       printf ("\t}\n");
+       genflags (flag_logical_noclobber, curi->size, "val", "", "");
+       genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+        if(curi->size==sz_long)
+            strcpy(exactCpuCycles," return (8+retcycles*2);");
+          else
+            strcpy(exactCpuCycles," return (6+retcycles*2);");
+       break;
+    case i_LSR:
+       genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tcnt &= 63;\n");
+        printf ("\tretcycles = cnt;\n");
+       printf ("\tCLEAR_CZNV;\n");
+       printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
+       printf ("\t\tSET_CFLG ((cnt == %d) & (val >> %d));\n",
+               bit_size (curi->size), bit_size (curi->size) - 1);
+       duplicate_carry ();
+       printf ("\t\tval = 0;\n");
+       if (source_is_imm1_8 (curi))
+           printf ("\t} else {\n");
+       else
+           printf ("\t} else if (cnt > 0) {\n");
+       printf ("\t\tval >>= cnt - 1;\n");
+       printf ("\t\tSET_CFLG (val & 1);\n");
+       duplicate_carry ();
+       printf ("\t\tval >>= 1;\n");
+       printf ("\t}\n");
+       genflags (flag_logical_noclobber, curi->size, "val", "", "");
+       genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+        if(curi->size==sz_long)
+            strcpy(exactCpuCycles," return (8+retcycles*2);");
+          else
+            strcpy(exactCpuCycles," return (6+retcycles*2);");
+       break;
+    case i_LSL:
+       genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tcnt &= 63;\n");
+        printf ("\tretcycles = cnt;\n");
+       printf ("\tCLEAR_CZNV;\n");
+       printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
+       printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
+               bit_size (curi->size));
+       duplicate_carry ();
+       printf ("\t\tval = 0;\n");
+       if (source_is_imm1_8 (curi))
+           printf ("\t} else {\n");
+       else
+           printf ("\t} else if (cnt > 0) {\n");
+       printf ("\t\tval <<= (cnt - 1);\n");
+       printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
+       duplicate_carry ();
+       printf ("\t\tval <<= 1;\n");
+       printf ("\tval &= %s;\n", bit_mask (curi->size));
+       printf ("\t}\n");
+       genflags (flag_logical_noclobber, curi->size, "val", "", "");
+       genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+        if(curi->size==sz_long)
+            strcpy(exactCpuCycles," return (8+retcycles*2);");
+          else
+            strcpy(exactCpuCycles," return (6+retcycles*2);");
+       break;
+    case i_ROL:
+       genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tcnt &= 63;\n");
+        printf ("\tretcycles = cnt;\n");
+       printf ("\tCLEAR_CZNV;\n");
+       if (source_is_imm1_8 (curi))
+           printf ("{");
+       else
+           printf ("\tif (cnt > 0) {\n");
+       printf ("\tuint32_t loval;\n");
+       printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
+       printf ("\tloval = val >> (%d - cnt);\n", bit_size (curi->size));
+       printf ("\tval <<= cnt;\n");
+       printf ("\tval |= loval;\n");
+       printf ("\tval &= %s;\n", bit_mask (curi->size));
+       printf ("\tSET_CFLG (val & 1);\n");
+       printf ("}\n");
+       genflags (flag_logical_noclobber, curi->size, "val", "", "");
+       genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+        if(curi->size==sz_long)
+            strcpy(exactCpuCycles," return (8+retcycles*2);");
+          else
+            strcpy(exactCpuCycles," return (6+retcycles*2);");
+       break;
+    case i_ROR:
+       genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tcnt &= 63;\n");
+        printf ("\tretcycles = cnt;\n");
+       printf ("\tCLEAR_CZNV;\n");
+       if (source_is_imm1_8 (curi))
+           printf ("{");
+       else
+           printf ("\tif (cnt > 0) {");
+       printf ("\tuint32_t hival;\n");
+       printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
+       printf ("\thival = val << (%d - cnt);\n", bit_size (curi->size));
+       printf ("\tval >>= cnt;\n");
+       printf ("\tval |= hival;\n");
+       printf ("\tval &= %s;\n", bit_mask (curi->size));
+       printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
+       printf ("\t}\n");
+       genflags (flag_logical_noclobber, curi->size, "val", "", "");
+       genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+        if(curi->size==sz_long)
+            strcpy(exactCpuCycles," return (8+retcycles*2);");
+          else
+            strcpy(exactCpuCycles," return (6+retcycles*2);");
+       break;
+    case i_ROXL:
+       genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tcnt &= 63;\n");
+        printf ("\tretcycles = cnt;\n");
+       printf ("\tCLEAR_CZNV;\n");
+       if (source_is_imm1_8 (curi))
+           printf ("{");
+       else {
+           force_range_for_rox ("cnt", curi->size);
+           printf ("\tif (cnt > 0) {\n");
+       }
+       printf ("\tcnt--;\n");
+       printf ("\t{\n\tuint32_t carry;\n");
+       printf ("\tuint32_t loval = val >> (%d - cnt);\n", bit_size (curi->size) - 1);
+       printf ("\tcarry = loval & 1;\n");
+       printf ("\tval = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);\n");
+       printf ("\tSET_XFLG (carry);\n");
+       printf ("\tval &= %s;\n", bit_mask (curi->size));
+       printf ("\t} }\n");
+       printf ("\tSET_CFLG (GET_XFLG);\n");
+       genflags (flag_logical_noclobber, curi->size, "val", "", "");
+       genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+        if(curi->size==sz_long)
+            strcpy(exactCpuCycles," return (8+retcycles*2);");
+          else
+            strcpy(exactCpuCycles," return (6+retcycles*2);");
+       break;
+    case i_ROXR:
+       genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tcnt &= 63;\n");
+        printf ("\tretcycles = cnt;\n");
+       printf ("\tCLEAR_CZNV;\n");
+       if (source_is_imm1_8 (curi))
+           printf ("{");
+       else {
+           force_range_for_rox ("cnt", curi->size);
+           printf ("\tif (cnt > 0) {\n");
+       }
+       printf ("\tcnt--;\n");
+       printf ("\t{\n\tuint32_t carry;\n");
+       printf ("\tuint32_t hival = (val << 1) | GET_XFLG;\n");
+       printf ("\thival <<= (%d - cnt);\n", bit_size (curi->size) - 1);
+       printf ("\tval >>= cnt;\n");
+       printf ("\tcarry = val & 1;\n");
+       printf ("\tval >>= 1;\n");
+       printf ("\tval |= hival;\n");
+       printf ("\tSET_XFLG (carry);\n");
+       printf ("\tval &= %s;\n", bit_mask (curi->size));
+       printf ("\t} }\n");
+       printf ("\tSET_CFLG (GET_XFLG);\n");
+       genflags (flag_logical_noclobber, curi->size, "val", "", "");
+       genastore ("val", curi->dmode, "dstreg", curi->size, "data");
+        if(curi->size==sz_long)
+            strcpy(exactCpuCycles," return (8+retcycles*2);");
+          else
+            strcpy(exactCpuCycles," return (6+retcycles*2);");
+       break;
+    case i_ASRW:
+       genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tuint32_t sign = %s & val;\n", cmask (curi->size));
+       printf ("\tuint32_t cflg = val & 1;\n");
+       printf ("\tval = (val >> 1) | sign;\n");
+       genflags (flag_logical, curi->size, "val", "", "");
+       printf ("\tSET_CFLG (cflg);\n");
+       duplicate_carry ();
+       genastore ("val", curi->smode, "srcreg", curi->size, "data");
+       break;
+    case i_ASLW:
+       genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tuint32_t sign = %s & val;\n", cmask (curi->size));
+       printf ("\tuint32_t sign2;\n");
+       printf ("\tval <<= 1;\n");
+       genflags (flag_logical, curi->size, "val", "", "");
+       printf ("\tsign2 = %s & val;\n", cmask (curi->size));
+       printf ("\tSET_CFLG (sign != 0);\n");
+       duplicate_carry ();
+
+       printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n");
+       genastore ("val", curi->smode, "srcreg", curi->size, "data");
+       break;
+    case i_LSRW:
+       genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint32_t val = (uint8_t)data;\n"); break;
+       case sz_word: printf ("\tuint32_t val = (uint16_t)data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tuint32_t carry = val & 1;\n");
+       printf ("\tval >>= 1;\n");
+       genflags (flag_logical, curi->size, "val", "", "");
+       printf ("SET_CFLG (carry);\n");
+       duplicate_carry ();
+       genastore ("val", curi->smode, "srcreg", curi->size, "data");
+       break;
+    case i_LSLW:
+       genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint8_t val = data;\n"); break;
+       case sz_word: printf ("\tuint16_t val = data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tuint32_t carry = val & %s;\n", cmask (curi->size));
+       printf ("\tval <<= 1;\n");
+       genflags (flag_logical, curi->size, "val", "", "");
+       printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
+       duplicate_carry ();
+       genastore ("val", curi->smode, "srcreg", curi->size, "data");
+       break;
+    case i_ROLW:
+       genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint8_t val = data;\n"); break;
+       case sz_word: printf ("\tuint16_t val = data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tuint32_t carry = val & %s;\n", cmask (curi->size));
+       printf ("\tval <<= 1;\n");
+       printf ("\tif (carry)  val |= 1;\n");
+       genflags (flag_logical, curi->size, "val", "", "");
+       printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
+       genastore ("val", curi->smode, "srcreg", curi->size, "data");
+       break;
+    case i_RORW:
+       genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint8_t val = data;\n"); break;
+       case sz_word: printf ("\tuint16_t val = data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tuint32_t carry = val & 1;\n");
+       printf ("\tval >>= 1;\n");
+       printf ("\tif (carry) val |= %s;\n", cmask (curi->size));
+       genflags (flag_logical, curi->size, "val", "", "");
+       printf ("SET_CFLG (carry);\n");
+       genastore ("val", curi->smode, "srcreg", curi->size, "data");
+       break;
+    case i_ROXLW:
+       genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint8_t val = data;\n"); break;
+       case sz_word: printf ("\tuint16_t val = data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tuint32_t carry = val & %s;\n", cmask (curi->size));
+       printf ("\tval <<= 1;\n");
+       printf ("\tif (GET_XFLG) val |= 1;\n");
+       genflags (flag_logical, curi->size, "val", "", "");
+       printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
+       duplicate_carry ();
+       genastore ("val", curi->smode, "srcreg", curi->size, "data");
+       break;
+    case i_ROXRW:
+       genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
+       start_brace ();
+       switch (curi->size) {
+       case sz_byte: printf ("\tuint8_t val = data;\n"); break;
+       case sz_word: printf ("\tuint16_t val = data;\n"); break;
+       case sz_long: printf ("\tuint32_t val = data;\n"); break;
+       default: abort ();
+       }
+       printf ("\tuint32_t carry = val & 1;\n");
+       printf ("\tval >>= 1;\n");
+       printf ("\tif (GET_XFLG) val |= %s;\n", cmask (curi->size));
+       genflags (flag_logical, curi->size, "val", "", "");
+       printf ("SET_CFLG (carry);\n");
+       duplicate_carry ();
+       genastore ("val", curi->smode, "srcreg", curi->size, "data");
+       break;
+    case i_MOVEC2:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       start_brace ();
+       printf ("\tint regno = (src >> 12) & 15;\n");
+       printf ("\tuint32_t *regp = regs.regs + regno;\n");
+       printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
+       break;
+    case i_MOVE2C:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       start_brace ();
+       printf ("\tint regno = (src >> 12) & 15;\n");
+       printf ("\tuint32_t *regp = regs.regs + regno;\n");
+       printf ("\tif (! m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
+       break;
+    case i_CAS:
+    {
+       int old_brace_level;
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       start_brace ();
+       printf ("\tint ru = (src >> 6) & 7;\n");
+       printf ("\tint rc = src & 7;\n");
+       genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc)", "dst");
+       printf ("\tif (GET_ZFLG)");
+       old_brace_level = n_braces;
+       start_brace ();
+       genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst");
+       pop_braces (old_brace_level);
+       printf ("else");
+       start_brace ();
+       printf ("m68k_dreg(regs, rc) = dst;\n");
+       pop_braces (old_brace_level);
+    }
+    break;
+    case i_CAS2:
+       genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+       printf ("\tuint32_t rn1 = regs.regs[(extra >> 28) & 15];\n");
+       printf ("\tuint32_t rn2 = regs.regs[(extra >> 12) & 15];\n");
+       if (curi->size == sz_word) {
+           int old_brace_level = n_braces;
+           printf ("\tuint16_t dst1 = m68k_read_memory_16(rn1), dst2 = m68k_read_memory_16(rn2);\n");
+           genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1");
+           printf ("\tif (GET_ZFLG) {\n");
+           genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2");
+           printf ("\tif (GET_ZFLG) {\n");
+           printf ("\tm68k_write_memory_16(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n");
+           printf ("\tm68k_write_memory_16(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n");
+           printf ("\t}}\n");
+           pop_braces (old_brace_level);
+           printf ("\tif (! GET_ZFLG) {\n");
+           printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = (m68k_dreg(regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n");
+           printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = (m68k_dreg(regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n");
+           printf ("\t}\n");
+       } else {
+           int old_brace_level = n_braces;
+           printf ("\tuint32_t dst1 = m68k_read_memory_32(rn1), dst2 = m68k_read_memory_32(rn2);\n");
+           genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1");
+           printf ("\tif (GET_ZFLG) {\n");
+           genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2");
+           printf ("\tif (GET_ZFLG) {\n");
+           printf ("\tm68k_write_memory_32(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n");
+           printf ("\tm68k_write_memory_32(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n");
+           printf ("\t}}\n");
+           pop_braces (old_brace_level);
+           printf ("\tif (! GET_ZFLG) {\n");
+           printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = dst1;\n");
+           printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = dst2;\n");
+           printf ("\t}\n");
+       }
+       break;
+    case i_MOVES:              /* ignore DFC and SFC because we have no MMU */
+    {
+       int old_brace_level;
+       genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+       printf ("\tif (extra & 0x800)\n");
+       old_brace_level = n_braces;
+       start_brace ();
+       printf ("\tuint32_t src = regs.regs[(extra >> 12) & 15];\n");
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
+       genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
+       pop_braces (old_brace_level);
+       printf ("else");
+       start_brace ();
+       genamode (curi->dmode, "dstreg", curi->size, "src", 1, 0);
+       printf ("\tif (extra & 0x8000) {\n");
+       switch (curi->size) {
+       case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (int32_t)(int8_t)src;\n"); break;
+       case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (int32_t)(int16_t)src;\n"); break;
+       case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break;
+       default: abort ();
+       }
+       printf ("\t} else {\n");
+       genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "");
+       printf ("\t}\n");
+       pop_braces (old_brace_level);
+    }
+    break;
+    case i_BKPT:               /* only needed for hardware emulators */
+       sync_m68k_pc ();
+       printf ("\top_illg(opcode);\n");
+       break;
+    case i_CALLM:              /* not present in 68030 */
+       sync_m68k_pc ();
+       printf ("\top_illg(opcode);\n");
+       break;
+    case i_RTM:                /* not present in 68030 */
+       sync_m68k_pc ();
+       printf ("\top_illg(opcode);\n");
+       break;
+    case i_TRAPcc:
+       if (curi->smode != am_unknown && curi->smode != am_illg)
+           genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0);
+       printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc(),M68000_EXC_SRC_CPU); goto %s; }\n", curi->cc, endlabelstr);
+       need_endlabel = 1;
+       break;
+    case i_DIVL:
+       sync_m68k_pc ();
+       start_brace ();
+       printf ("\tuint32_t oldpc = m68k_getpc();\n");
+       genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n");
+       break;
+    case i_MULL:
+       genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+       genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tm68k_mull(opcode, dst, extra);\n");
+       break;
+    case i_BFTST:
+    case i_BFEXTU:
+    case i_BFCHG:
+    case i_BFEXTS:
+    case i_BFCLR:
+    case i_BFFFO:
+    case i_BFSET:
+    case i_BFINS:
+       genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+       genamode (curi->dmode, "dstreg", sz_long, "dst", 2, 0);
+       start_brace ();
+       printf ("\tint32_t offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n");
+       printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n");
+       if (curi->dmode == Dreg) {
+           printf ("\tuint32_t tmp = m68k_dreg(regs, dstreg) << (offset & 0x1f);\n");
+       } else {
+           printf ("\tuint32_t tmp,bf0,bf1;\n");
+           printf ("\tdsta += (offset >> 3) | (offset & 0x80000000 ? ~0x1fffffff : 0);\n");
+           printf ("\tbf0 = m68k_read_memory_32(dsta);bf1 = m68k_read_memory_8(dsta+4) & 0xff;\n");
+           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_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n");
+       switch (curi->mnemo) {
+       case i_BFTST:
+           break;
+       case i_BFEXTU:
+           printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
+           break;
+       case i_BFCHG:
+           printf ("\ttmp = ~tmp;\n");
+           break;
+       case i_BFEXTS:
+           printf ("\tif (GET_NFLG) tmp |= width == 32 ? 0 : (-1 << width);\n");
+           printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
+           break;
+       case i_BFCLR:
+           printf ("\ttmp = 0;\n");
+           break;
+       case i_BFFFO:
+           printf ("\t{ uint32_t mask = 1 << (width-1);\n");
+           printf ("\twhile (mask) { if (tmp & mask) break; mask >>= 1; offset++; }}\n");
+           printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = offset;\n");
+           break;
+       case i_BFSET:
+           printf ("\ttmp = 0xffffffff;\n");
+           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_ZFLG (tmp == 0);\n");
+           break;
+       default:
+           break;
+       }
+       if (curi->mnemo == i_BFCHG
+           || curi->mnemo == i_BFCLR
+           || curi->mnemo == i_BFSET
+           || curi->mnemo == i_BFINS)
+           {
+               printf ("\ttmp <<= (32 - width);\n");
+               if (curi->dmode == Dreg) {
+                   printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ((offset & 0x1f) == 0 ? 0 :\n");
+                   printf ("\t\t(0xffffffff << (32 - (offset & 0x1f))))) |\n");
+                   printf ("\t\t(tmp >> (offset & 0x1f)) |\n");
+                   printf ("\t\t(((offset & 0x1f) + width) >= 32 ? 0 :\n");
+                   printf (" (m68k_dreg(regs, dstreg) & ((uint32_t)0xffffffff >> ((offset & 0x1f) + width))));\n");
+               } else {
+                   printf ("\tbf0 = (bf0 & (0xff000000 << (8 - (offset & 7)))) |\n");
+                   printf ("\t\t(tmp >> (offset & 7)) |\n");
+                   printf ("\t\t(((offset & 7) + width) >= 32 ? 0 :\n");
+                   printf ("\t\t (bf0 & ((uint32_t)0xffffffff >> ((offset & 7) + width))));\n");
+                   printf ("\tm68k_write_memory_32(dsta,bf0 );\n");
+                   printf ("\tif (((offset & 7) + width) > 32) {\n");
+                   printf ("\t\tbf1 = (bf1 & (0xff >> (width - 32 + (offset & 7)))) |\n");
+                   printf ("\t\t\t(tmp << (8 - (offset & 7)));\n");
+                   printf ("\t\tm68k_write_memory_8(dsta+4,bf1);\n");
+                   printf ("\t}\n");
+               }
+           }
+       break;
+    case i_PACK:
+       if (curi->smode == Dreg) {
+           printf ("\tuint16_t val = m68k_dreg(regs, srcreg) + %s;\n", gen_nextiword ());
+           printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n");
+       } else {
+           printf ("\tuint16_t val;\n");
+           printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
+           printf ("\tval = (uint16_t)m68k_read_memory_8(m68k_areg(regs, srcreg));\n");
+           printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
+           printf ("\tval = (val | ((uint16_t)m68k_read_memory_8(m68k_areg(regs, srcreg)) << 8)) + %s;\n", gen_nextiword ());
+           printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
+           printf ("\tm68k_write_memory_8(m68k_areg(regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n");
+       }
+       break;
+    case i_UNPK:
+       if (curi->smode == Dreg) {
+           printf ("\tuint16_t val = m68k_dreg(regs, srcreg);\n");
+           printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ());
+           printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffff0000) | (val & 0xffff);\n");
+       } else {
+           printf ("\tuint16_t val;\n");
+           printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
+           printf ("\tval = (uint16_t)m68k_read_memory_8(m68k_areg(regs, srcreg));\n");
+           printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ());
+           printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
+           printf ("\tm68k_write_memory_8(m68k_areg(regs, dstreg),val);\n");
+           printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
+           printf ("\tm68k_write_memory_8(m68k_areg(regs, dstreg),val >> 8);\n");
+       }
+       break;
+    case i_TAS:
+       genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
+       genflags (flag_logical, curi->size, "src", "", "");
+       printf ("\tsrc |= 0x80;\n");
+       genastore ("src", curi->smode, "srcreg", curi->size, "src");
+        if( curi->smode!=Dreg )  insn_n_cycles += 2;
+       break;
+    case i_FPP:
+       genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tfpp_opp(opcode,extra);\n");
+       break;
+    case i_FDBcc:
+       genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tfdbcc_opp(opcode,extra);\n");
+       break;
+    case i_FScc:
+       genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tfscc_opp(opcode,extra);\n");
+       break;
+    case i_FTRAPcc:
+       sync_m68k_pc ();
+       start_brace ();
+       printf ("\tuint32_t oldpc = m68k_getpc();\n");
+       if (curi->smode != am_unknown && curi->smode != am_illg)
+           genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tftrapcc_opp(opcode,oldpc);\n");
+       break;
+    case i_FBcc:
+       sync_m68k_pc ();
+       start_brace ();
+       printf ("\tuint32_t pc = m68k_getpc();\n");
+       genamode (curi->dmode, "srcreg", curi->size, "extra", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tfbcc_opp(opcode,pc,extra);\n");
+       break;
+    case i_FSAVE:
+       sync_m68k_pc ();
+       printf ("\tfsave_opp(opcode);\n");
+       break;
+    case i_FRESTORE:
+       sync_m68k_pc ();
+       printf ("\tfrestore_opp(opcode);\n");
+       break;
+
+     case i_CINVL:
+     case i_CINVP:
+     case i_CINVA:
+     case i_CPUSHL:
+     case i_CPUSHP:
+     case i_CPUSHA:
+       break;
+     case i_MOVE16:
+       if ((opcode & 0xfff8) == 0xf620) {
+           /* MOVE16 (Ax)+,(Ay)+ */
+           printf ("\tuint32_t mems = m68k_areg(regs, srcreg) & ~15, memd;\n");
+           printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword());
+           printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n");
+           printf ("\tm68k_write_memory_32(memd, m68k_read_memory_32(mems));\n");
+           printf ("\tm68k_write_memory_32(memd+4, m68k_read_memory_32(mems+4));\n");
+           printf ("\tm68k_write_memory_32(memd+8, m68k_read_memory_32(mems+8));\n");
+           printf ("\tm68k_write_memory_32(memd+12, m68k_read_memory_32(mems+12));\n");
+           printf ("\tif (srcreg != dstreg)\n");
+           printf ("\tm68k_areg(regs, srcreg) += 16;\n");
+           printf ("\tm68k_areg(regs, dstreg) += 16;\n");
+       } else {
+           /* Other variants */
+           genamode (curi->smode, "srcreg", curi->size, "mems", 0, 2);
+           genamode (curi->dmode, "dstreg", curi->size, "memd", 0, 2);
+           printf ("\tmemsa &= ~15;\n");
+           printf ("\tmemda &= ~15;\n");
+           printf ("\tm68k_write_memory_32(memda, m68k_read_memory_32(memsa));\n");
+           printf ("\tm68k_write_memory_32(memda+4, m68k_read_memory_32(memsa+4));\n");
+           printf ("\tm68k_write_memory_32(memda+8, m68k_read_memory_32(memsa+8));\n");
+           printf ("\tm68k_write_memory_32(memda+12, m68k_read_memory_32(memsa+12));\n");
+           if ((opcode & 0xfff8) == 0xf600)
+               printf ("\tm68k_areg(regs, srcreg) += 16;\n");
+           else if ((opcode & 0xfff8) == 0xf608)
+               printf ("\tm68k_areg(regs, dstreg) += 16;\n");
+       }
+       break;
+
+    case i_MMUOP:
+       genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
+       sync_m68k_pc ();
+       printf ("\tmmu_op(opcode,extra);\n");
+       break;
+    default:
+       abort ();
+       break;
+    }
+    finish_braces ();
+    sync_m68k_pc ();
+}
+
+static void generate_includes(FILE * f)
+{
+//JLH:no       fprintf(f, "#include \"sysdeps.h\"\n");
+//JLH:no       fprintf(f, "#include \"hatari-glue.h\"\n");
+//JLH:no       fprintf(f, "#include \"maccess.h\"\n");
+//JLH:no       fprintf(f, "#include \"memory.h\"\n");
+//JLH:no       fprintf(f, "#include \"newcpu.h\"\n");
+       fprintf(f, "#include \"cpudefs.h\"\n");
+       fprintf(f, "#include \"cpuextra.h\"\n");
+       fprintf(f, "#include \"inlines.h\"\n");
+       fprintf(f, "#include \"cputbl.h\"\n");
+       fprintf(f, "#define CPUFUNC(x) x##_ff\n"
+               "#ifdef NOFLAGS\n"
+               "#include \"noflags.h\"\n"
+               "#endif\n");
+}
+
+// JLH: Since this is stuff that should be generated in a file that creates
+// constants, it's in here now. :-P
+static void GenerateTables(FILE * f)
+{
+       int i, j;
+
+       fprintf(f, "\nconst int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };\n");
+       fprintf(f, "const int imm8_table[]   = { 8, 1, 2, 3, 4, 5, 6, 7 };\n\n");
+       fprintf(f, "const int movem_index1[256] = {\n");
+
+       for(i=0; i<256; i++)
+       {
+               for(j=0; j<8; j++)
+                       if (i & (1 << j))
+                               break;
+
+               fprintf(f, "0x%02X, ", j);
+
+               if ((i % 16) == 15)
+                       fprintf(f, "\n");
+       }
+
+       fprintf(f, "};\n\n");
+       fprintf(f, "const int movem_index2[256] = {\n");
+
+       for(i=0; i<256; i++)
+       {
+               for(j=0; j<8; j++)
+                       if (i & (1 << j))
+                               break;
+
+               fprintf(f, "0x%02X, ", 7 - j);
+
+               if ((i % 16) == 15)
+                       fprintf(f, "\n");
+       }
+
+       fprintf(f, "};\n\n");
+       fprintf(f, "const int movem_next[256] = {\n");
+
+       for(i=0; i<256; i++)
+       {
+               for(j=0; j<8; j++)
+                       if (i & (1 << j))
+                               break;
+
+               fprintf(f, "0x%02X, ", i & (~(1 << j)));
+
+               if ((i % 16) == 15)
+                       fprintf(f, "\n");
+       }
+
+       fprintf(f, "};\n\n");
+}
+
+static int postfix;
+
+static void generate_one_opcode (int rp)
+{
+    int i;
+    uint16_t smsk, dmsk;
+    long int opcode = opcode_map[rp];
+
+    exactCpuCycles[0] = 0;  /* Default: not used */
+
+    if (table68k[opcode].mnemo == i_ILLG
+       || table68k[opcode].clev > cpu_level)
+       return;
+
+    for (i = 0; lookuptab[i].name[0]; i++) {
+       if (table68k[opcode].mnemo == lookuptab[i].mnemo)
+           break;
+    }
+
+    if (table68k[opcode].handler != -1)
+       return;
+
+    if (opcode_next_clev[rp] != cpu_level) {
+       fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp],
+                opcode, lookuptab[i].name);
+       return;
+    }
+    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 ("unsigned long CPUFUNC(op_%lx_%d)(uint32_t opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name);
+
+    switch (table68k[opcode].stype) {
+     case 0: smsk = 7; break;
+     case 1: smsk = 255; break;
+     case 2: smsk = 15; break;
+     case 3: smsk = 7; break;
+     case 4: smsk = 7; break;
+     case 5: smsk = 63; break;
+     case 7: smsk = 3; break;
+     default: abort ();
+    }
+    dmsk = 7;
+
+    next_cpu_level = -1;
+    if (table68k[opcode].suse
+       && 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)
+    {
+       if (table68k[opcode].spos == -1) {
+           if (((int) table68k[opcode].sreg) >= 128)
+               printf ("\tuint32_t srcreg = (int32_t)(int8_t)%d;\n", (int) table68k[opcode].sreg);
+           else
+               printf ("\tuint32_t srcreg = %d;\n", (int) table68k[opcode].sreg);
+       } else {
+           char source[100];
+           int pos = table68k[opcode].spos;
+
+           if (pos)
+               sprintf (source, "((opcode >> %d) & %d)", pos, smsk);
+           else
+               sprintf (source, "(opcode & %d)", smsk);
+
+           if (table68k[opcode].stype == 3)
+               printf ("\tuint32_t srcreg = imm8_table[%s];\n", source);
+           else if (table68k[opcode].stype == 1)
+               printf ("\tuint32_t srcreg = (int32_t)(int8_t)%s;\n", source);
+           else
+               printf ("\tuint32_t srcreg = %s;\n", source);
+       }
+    }
+    if (table68k[opcode].duse
+       /* Yes, the dmode can be imm, in case of LINK or DBcc */
+       && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0
+       && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2
+       && table68k[opcode].dmode != absw && table68k[opcode].dmode != absl)
+    {
+       if (table68k[opcode].dpos == -1) {
+           if (((int) table68k[opcode].dreg) >= 128)
+               printf ("\tuint32_t dstreg = (int32_t)(int8_t)%d;\n", (int) table68k[opcode].dreg);
+           else
+               printf ("\tuint32_t dstreg = %d;\n", (int) table68k[opcode].dreg);
+       } else {
+           int pos = table68k[opcode].dpos;
+#if 0
+           /* Check that we can do the little endian optimization safely.  */
+           if (pos < 8 && (dmsk >> (8 - pos)) != 0)
+               abort ();
+#endif     
+           if (pos)
+               printf ("\tuint32_t dstreg = (opcode >> %d) & %d;\n",
+                       pos, dmsk);
+           else
+               printf ("\tuint32_t dstreg = opcode & %d;\n", dmsk);
+       }
+    }
+    need_endlabel = 0;
+    endlabelno++;
+    sprintf (endlabelstr, "endlabel%d", endlabelno);
+    if(table68k[opcode].mnemo==i_ASR || table68k[opcode].mnemo==i_ASL || table68k[opcode].mnemo==i_LSR || table68k[opcode].mnemo==i_LSL
+       || table68k[opcode].mnemo==i_ROL || table68k[opcode].mnemo==i_ROR || table68k[opcode].mnemo==i_ROXL || table68k[opcode].mnemo==i_ROXR
+       || table68k[opcode].mnemo==i_MVMEL || table68k[opcode].mnemo==i_MVMLE
+       || table68k[opcode].mnemo==i_MULU || table68k[opcode].mnemo==i_MULS
+       || table68k[opcode].mnemo==i_DIVU || table68k[opcode].mnemo==i_DIVS )
+      printf("\tunsigned int retcycles = 0;\n");
+    gen_opcode (opcode);
+    if (need_endlabel)
+       printf ("%s: ;\n", endlabelstr);
+
+    if (strlen(exactCpuCycles) > 0)
+       printf("%s\n",exactCpuCycles);
+    else
+       printf ("return %d;\n", insn_n_cycles);
+    /* Now patch in the instruction cycles at the beginning of the function: */
+    fseek(stdout, nCurInstrCycPos, SEEK_SET);
+    printf("%d;", insn_n_cycles);
+    fseek(stdout, 0, SEEK_END);
+
+    printf ("}\n");
+    opcode_next_clev[rp] = next_cpu_level;
+    opcode_last_postfix[rp] = postfix;
+}
+
+static void generate_func(void)
+{
+       int i, j, rp;
+
+       using_prefetch = 0;
+       using_exception_3 = 0;
+//JLH:
+//     for(i=0; i<6; i++)
+//For some reason, this doesn't work properly. Seems something is making a bad
+//assumption somewhere.
+//and it's probably in opcode_next_clev[rp]...
+       for(i=4; i<6; i++)
+       {
+               cpu_level = 4 - i;
+
+               //JLH
+               for(rp=0; rp<nr_cpuop_funcs; rp++)
+                       opcode_next_clev[rp] = 0;
+
+               if (i == 5)
+               {
+                       cpu_level = 0;
+                       using_prefetch = 1;
+                       using_exception_3 = 1;
+       
+                       for(rp=0; rp<nr_cpuop_funcs; rp++)
+                               opcode_next_clev[rp] = 0;
+               }
+
+               postfix = i;
+               fprintf(stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix);
+
+               /* sam: this is for people with low memory (eg. me :)) */
+               printf("\n"
+                       "#if !defined(PART_1) && !defined(PART_2) && "
+                       "!defined(PART_3) && !defined(PART_4) && "
+                       "!defined(PART_5) && !defined(PART_6) && "
+                       "!defined(PART_7) && !defined(PART_8)"
+                       "\n"
+                       "#define PART_1 1\n"
+                       "#define PART_2 1\n"
+                       "#define PART_3 1\n"
+                       "#define PART_4 1\n"
+                       "#define PART_5 1\n"
+                       "#define PART_6 1\n"
+                       "#define PART_7 1\n"
+                       "#define PART_8 1\n"
+                       "#endif\n\n");
+
+               rp = 0;
+
+               for(j=1; j<=8; ++j)
+               {
+                       int k = (j * nr_cpuop_funcs) / 8;
+                       printf("#ifdef PART_%d\n", j);
+
+                       for(; rp<k; rp++)
+                               generate_one_opcode(rp);
+
+                       printf ("#endif\n\n");
+               }
+
+               fprintf(stblfile, "{ 0, 0, 0 }};\n");
+       }
+}
+
+int main(int argc, char ** argv)
+{
+       read_table68k();
+       do_merges();
+
+       opcode_map = (int *)malloc(sizeof(int) * nr_cpuop_funcs);
+       opcode_last_postfix = (int *)malloc(sizeof(int) * nr_cpuop_funcs);
+       opcode_next_clev = (int *)malloc(sizeof(int) * nr_cpuop_funcs);
+       counts = (unsigned long *)malloc(65536 * sizeof(unsigned long));
+       read_counts();
+
+       /* It would be a lot nicer to put all in one file (we'd also get rid of
+        * cputbl.h that way), but cpuopti can't cope.  That could be fixed, but
+        * I don't dare to touch the 68k version.  */
+
+       headerfile = fopen("cputbl.h", "wb");
+       stblfile = fopen("cpustbl.c", "wb");
+
+       if (freopen("cpuemu.c", "wb", stdout) == NULL)
+       {
+               perror("cpuemu.c");
+               return -1;
+       }
+
+       generate_includes(stdout);
+       generate_includes(stblfile);
+
+       GenerateTables(stdout);
+
+       generate_func();
+
+       free(table68k);
+       return 0;
+}
diff --git a/src/m68000/inlines.h b/src/m68000/inlines.h
new file mode 100644 (file)
index 0000000..ccac797
--- /dev/null
@@ -0,0 +1,203 @@
+//
+// Inline functions used by cpuemu.c
+//
+// Since inline functions have to be in a header, we have them all defined
+// here, in one place to make finding them easy.
+//
+
+#ifndef __INLINES_H__
+#define __INLINES_H__
+
+#include "cpudefs.h"
+
+STATIC_INLINE int cctrue(const int cc)
+{
+       switch (cc)
+       {
+               case 0:  return 1;                       /* T */
+               case 1:  return 0;                       /* F */
+               case 2:  return !CFLG && !ZFLG;          /* HI */
+               case 3:  return CFLG || ZFLG;            /* LS */
+               case 4:  return !CFLG;                   /* CC */
+               case 5:  return CFLG;                    /* CS */
+               case 6:  return !ZFLG;                   /* NE */
+               case 7:  return ZFLG;                    /* EQ */
+               case 8:  return !VFLG;                   /* VC */
+               case 9:  return VFLG;                    /* VS */
+               case 10: return !NFLG;                   /* PL */
+               case 11: return NFLG;                    /* MI */
+               case 12: return NFLG == VFLG;            /* GE */
+               case 13: return NFLG != VFLG;            /* LT */
+               case 14: return !ZFLG && (NFLG == VFLG); /* GT */
+               case 15: return ZFLG || (NFLG != VFLG);  /* LE */
+       }
+
+       abort();
+       return 0;
+}
+
+//no #define m68k_incpc(o) (regs.pc_p += (o))
+#define m68k_incpc(o) (regs.pc += (o))
+
+STATIC_INLINE void m68k_setpc(uint32_t newpc)
+{
+       //This is only done here... (get_real_address())
+//     regs.pc_p = regs.pc_oldp = get_real_address(newpc);
+       regs.pc = newpc;
+}
+
+#define m68k_setpc_rte  m68k_setpc
+
+STATIC_INLINE uint32_t m68k_getpc(void)
+{
+//     return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
+       return regs.pc;
+}
+
+#if 0
+STATIC_INLINE uint32_t m68k_getpc_p(uint8_t * p)
+{
+       return regs.pc + ((char *)p - (char *)regs.pc_oldp);
+}
+#endif
+
+STATIC_INLINE void m68k_setstopped(int stop)
+{
+       regs.stopped = stop;
+       regs.remainingCycles = 0;
+
+//But trace instructions are only on >68000 cpus, so this is bogus.
+#if 0
+       /* A traced STOP instruction drops through immediately without
+       actually stopping.  */
+       if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0)
+       regs.spcflags |= SPCFLAG_STOP;
+#endif
+}
+
+STATIC_INLINE void m68k_do_rts(void)
+{
+       m68k_setpc(m68k_read_memory_32(m68k_areg(regs, 7)));
+       m68k_areg(regs, 7) += 4;
+}
+
+STATIC_INLINE void m68k_do_bsr(uint32_t oldpc, int32_t offset)
+{
+       m68k_areg(regs, 7) -= 4;
+       m68k_write_memory_32(m68k_areg(regs, 7), oldpc);
+       m68k_incpc(offset);
+}
+
+STATIC_INLINE void m68k_do_jsr(uint32_t oldpc, uint32_t dest)
+{
+       m68k_areg(regs, 7) -= 4;
+       m68k_write_memory_32(m68k_areg(regs, 7), oldpc);
+       m68k_setpc(dest);
+}
+
+#if 0
+//These do_get_mem_* functions are only used in newcpu...
+//What it does is use a pointer to make instruction fetching quicker,
+//though it probably leads to more problems than it solves. Something to
+//decide using a profiler...
+#define get_ibyte(o) do_get_mem_byte(regs.pc_p + (o) + 1)
+#define get_iword(o) do_get_mem_word(regs.pc_p + (o))
+#define get_ilong(o) do_get_mem_long(regs.pc_p + (o))
+#else
+// For now, we'll punt this crap...
+// (Also, notice that the byte read is at address + 1...)
+#define get_ibyte(o)   m68k_read_memory_8(regs.pc + (o) + 1)
+#define get_iword(o)   m68k_read_memory_16(regs.pc + (o))
+#define get_ilong(o)   m68k_read_memory_32(regs.pc + (o))
+#endif
+
+// We don't use this crap, so let's comment out for now...
+STATIC_INLINE void refill_prefetch(uint32_t currpc, uint32_t offs)
+{
+#if 0
+       uint32_t t = (currpc + offs) & ~1;
+       int32_t pc_p_offs = t - currpc;
+       uint8_t * ptr = regs.pc_p + pc_p_offs;
+       uint32_t r;
+
+#ifdef UNALIGNED_PROFITABLE
+       r = *(uint32_t *)ptr;
+       regs.prefetch = r;
+#else
+       r = do_get_mem_long(ptr);
+       do_put_mem_long(&regs.prefetch, r);
+#endif
+       /* printf ("PC %lx T %lx PCPOFFS %d R %lx\n", currpc, t, pc_p_offs, r); */
+       regs.prefetch_pc = t;
+#endif
+}
+
+STATIC_INLINE uint32_t get_ibyte_prefetch(int32_t o)
+{
+#if 0
+       uint32_t currpc = m68k_getpc();
+       uint32_t addr = currpc + o + 1;
+       uint32_t offs = addr - regs.prefetch_pc;
+
+       if (offs > 3)
+       {
+               refill_prefetch(currpc, o + 1);
+               offs = addr - regs.prefetch_pc;
+       }
+
+       uint32_t v = do_get_mem_byte(((uint8_t *)&regs.prefetch) + offs);
+
+       if (offs >= 2)
+               refill_prefetch(currpc, 2);
+
+       /* printf ("get_ibyte PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
+       return v;
+#else
+       return 0;
+#endif
+}
+
+STATIC_INLINE uint32_t get_iword_prefetch(int32_t o)
+{
+#if 0
+       uint32_t currpc = m68k_getpc();
+       uint32_t addr = currpc + o;
+       uint32_t offs = addr - regs.prefetch_pc;
+
+       if (offs > 3)
+       {
+               refill_prefetch(currpc, o);
+               offs = addr - regs.prefetch_pc;
+       }
+
+       uint32_t v = do_get_mem_word(((uint8_t *)&regs.prefetch) + offs);
+
+       if (offs >= 2)
+               refill_prefetch(currpc, 2);
+
+/*     printf ("get_iword PC %lx ADDR %lx OFFS %lx V %lx\n", currpc, addr, offs, v); */
+       return v;
+#else
+       return 0;
+#endif
+}
+
+STATIC_INLINE uint32_t get_ilong_prefetch(int32_t o)
+{
+#if 0
+       uint32_t v = get_iword_prefetch(o);
+       v <<= 16;
+       v |= get_iword_prefetch(o + 2);
+       return v;
+#else
+       return 0;
+#endif
+}
+
+STATIC_INLINE void fill_prefetch_0(void)
+{
+}
+
+#define fill_prefetch_2 fill_prefetch_0
+
+#endif // __INLINES_H__
diff --git a/src/m68000/m68kdasm.c b/src/m68000/m68kdasm.c
new file mode 100644 (file)
index 0000000..3c54b67
--- /dev/null
@@ -0,0 +1,378 @@
+//
+// m68kdasm.c: 68000 instruction disassembly
+//
+// Originally part of the UAE 68000 cpu core
+// by Bernd Schmidt
+//
+// Adapted to Virtual Jaguar by James Hammons
+//
+// This file is distributed under the GNU Public License, version 3 or at your
+// option any later version. Read the file GPLv3 for details.
+//
+
+#include <string.h>
+#include "cpudefs.h"
+#include "cpuextra.h"
+#include "inlines.h"
+#include "readcpu.h"
+
+
+// Stuff from m68kinterface.c
+extern unsigned long IllegalOpcode(uint32_t opcode);
+extern cpuop_func * cpuFunctionTable[65536];
+
+// Local "global" variables
+static long int m68kpc_offset;
+
+#if 0
+#define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
+#define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
+#define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
+#else
+#define get_ibyte_1(o) m68k_read_memory_8(regs.pc + (o) + 1)
+#define get_iword_1(o) m68k_read_memory_16(regs.pc + (o))
+#define get_ilong_1(o) m68k_read_memory_32(regs.pc + (o))
+#endif
+
+
+int32_t ShowEA(FILE * f, int reg, amodes mode, wordsizes size, char * buf)
+{
+       uint16_t dp;
+       int8_t disp8;
+       int16_t disp16;
+       int r;
+       uint32_t dispreg;
+       uint32_t addr;
+       int32_t offset = 0;
+       char buffer[80];
+
+       switch (mode)
+       {
+       case Dreg:
+               sprintf(buffer,"D%d", reg);
+               break;
+       case Areg:
+               sprintf(buffer,"A%d", reg);
+               break;
+       case Aind:
+               sprintf(buffer,"(A%d)", reg);
+               break;
+       case Aipi:
+               sprintf(buffer,"(A%d)+", reg);
+               break;
+       case Apdi:
+               sprintf(buffer,"-(A%d)", reg);
+               break;
+       case Ad16:
+               disp16 = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
+               addr = m68k_areg(regs,reg) + (int16_t)disp16;
+               sprintf(buffer,"(A%d,$%04X) == $%08lX", reg, disp16 & 0xFFFF,
+                       (unsigned long)addr);
+               break;
+       case Ad8r:
+               dp = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
+               disp8 = dp & 0xFF;
+               r = (dp & 0x7000) >> 12;
+               dispreg = (dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r));
+
+               if (!(dp & 0x800))
+                       dispreg = (int32_t)(int16_t)(dispreg);
+
+               dispreg <<= (dp >> 9) & 3;
+
+               if (dp & 0x100)
+               {
+                       int32_t outer = 0, disp = 0;
+                       int32_t base = m68k_areg(regs,reg);
+                       char name[10];
+                       sprintf (name,"A%d, ",reg);
+                       if (dp & 0x80) { base = 0; name[0] = 0; }
+                       if (dp & 0x40) dispreg = 0;
+                       if ((dp & 0x30) == 0x20) { disp = (int32_t)(int16_t)get_iword_1(m68kpc_offset); m68kpc_offset += 2; }
+                       if ((dp & 0x30) == 0x30) { disp = get_ilong_1(m68kpc_offset); m68kpc_offset += 4; }
+                       base += disp;
+
+                       if ((dp & 0x3) == 0x2) { outer = (int32_t)(int16_t)get_iword_1(m68kpc_offset); m68kpc_offset += 2; }
+                       if ((dp & 0x3) == 0x3) { outer = get_ilong_1(m68kpc_offset); m68kpc_offset += 4; }
+
+                       if (!(dp & 4)) base += dispreg;
+                       if (dp & 3) base = m68k_read_memory_32(base);
+                       if (dp & 4) base += dispreg;
+
+                       addr = base + outer;
+                       sprintf(buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lX", name,
+                               dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
+                               1 << ((dp >> 9) & 3),
+                               (long)disp, (long)outer, (unsigned long)addr);
+               }
+               else
+               {
+                       addr = m68k_areg(regs,reg) + (int32_t)((int8_t)disp8) + dispreg;
+                       sprintf (buffer,"(A%d, %c%d.%c*%d, $%02X) == $%08lX", reg,
+                               dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
+                               1 << ((dp >> 9) & 3), disp8, (unsigned long)addr);
+               }
+               break;
+       case PC16:
+               addr = m68k_getpc() + m68kpc_offset;
+               disp16 = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
+               addr += (int16_t)disp16;
+               sprintf(buffer,"(PC,$%04X) == $%08lX", disp16 & 0xffff,(unsigned long)addr);
+               break;
+       case PC8r:
+               addr = m68k_getpc() + m68kpc_offset;
+               dp = get_iword_1(m68kpc_offset); m68kpc_offset += 2;
+               disp8 = dp & 0xFF;
+               r = (dp & 0x7000) >> 12;
+               dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
+
+               if (!(dp & 0x800))
+                       dispreg = (int32_t)(int16_t)(dispreg);
+
+               dispreg <<= (dp >> 9) & 3;
+
+               if (dp & 0x100)
+               {
+                       int32_t outer = 0,disp = 0;
+                       int32_t base = addr;
+                       char name[10];
+                       sprintf (name,"PC, ");
+                       if (dp & 0x80) { base = 0; name[0] = 0; }
+                       if (dp & 0x40) dispreg = 0;
+                       if ((dp & 0x30) == 0x20) { disp = (int32_t)(int16_t)get_iword_1(m68kpc_offset); m68kpc_offset += 2; }
+                       if ((dp & 0x30) == 0x30) { disp = get_ilong_1(m68kpc_offset); m68kpc_offset += 4; }
+                       base += disp;
+
+                       if ((dp & 0x3) == 0x2)
+                       {
+                               outer = (int32_t)(int16_t)get_iword_1(m68kpc_offset);
+                               m68kpc_offset += 2;
+                       }
+
+                       if ((dp & 0x3) == 0x3)
+                       {
+                               outer = get_ilong_1(m68kpc_offset);
+                               m68kpc_offset += 4;
+                       }
+
+                       if (!(dp & 4)) base += dispreg;
+                       if (dp & 3) base = m68k_read_memory_32(base);
+                       if (dp & 4) base += dispreg;
+
+                       addr = base + outer;
+                       sprintf(buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lX", name,
+                               dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
+                               1 << ((dp >> 9) & 3), (long)disp, (long)outer, (unsigned long)addr);
+               }
+               else
+               {
+                       addr += (int32_t)((int8_t)disp8) + dispreg;
+                       sprintf(buffer,"(PC, %c%d.%c*%d, $%02X) == $%08lX", dp & 0x8000 ? 'A' : 'D',
+                               (int)r, dp & 0x800 ? 'L' : 'W',  1 << ((dp >> 9) & 3),
+                               disp8, (unsigned long)addr);
+               }
+               break;
+       case absw:
+               sprintf(buffer,"$%08lX", (unsigned long)(int32_t)(int16_t)get_iword_1(m68kpc_offset));
+               m68kpc_offset += 2;
+               break;
+       case absl:
+               sprintf(buffer,"$%08lX", (unsigned long)get_ilong_1(m68kpc_offset));
+               m68kpc_offset += 4;
+               break;
+       case imm:
+               switch (size)
+               {
+               case sz_byte:
+                       sprintf(buffer,"#$%02X", (unsigned int)(get_iword_1(m68kpc_offset) & 0xFF));
+                       m68kpc_offset += 2;
+                       break;
+               case sz_word:
+                       sprintf(buffer,"#$%04X", (unsigned int)(get_iword_1(m68kpc_offset) & 0xFFFF));
+                       m68kpc_offset += 2;
+                       break;
+               case sz_long:
+                       sprintf(buffer,"#$%08lX", (unsigned long)(get_ilong_1(m68kpc_offset)));
+                       m68kpc_offset += 4;
+                       break;
+               default:
+                       break;
+               }
+               break;
+       case imm0:
+               offset = (int32_t)(int8_t)get_iword_1(m68kpc_offset);
+               m68kpc_offset += 2;
+               sprintf (buffer,"#$%02X", (unsigned int)(offset & 0xFF));
+               break;
+       case imm1:
+               offset = (int32_t)(int16_t)get_iword_1(m68kpc_offset);
+               m68kpc_offset += 2;
+               sprintf (buffer,"#$%04X", (unsigned int)(offset & 0xFFFF));
+               break;
+       case imm2:
+               offset = (int32_t)get_ilong_1(m68kpc_offset);
+               m68kpc_offset += 4;
+               sprintf(buffer,"#$%08lX", (unsigned long)offset);
+               break;
+       case immi:
+               offset = (int32_t)(int8_t)(reg & 0xFF);
+               sprintf(buffer,"#$%08lX", (unsigned long)offset);
+               break;
+       default:
+               break;
+       }
+
+       if (buf == 0)
+               fprintf(f, "%s", buffer);
+       else
+               strcat(buf, buffer);
+
+       return offset;
+}
+
+
+//void m68k_disasm(FILE * f, uint32_t addr, uint32_t * nextpc, int cnt)
+unsigned int m68k_disasm(char * output, uint32_t addr, uint32_t * nextpc, int cnt)
+{
+       char f[256], str[256];
+       static const char * const ccnames[] =
+               { "T ","F ","HI","LS","CC","CS","NE","EQ",
+                 "VC","VS","PL","MI","GE","LT","GT","LE" };
+
+       str[0] = 0;
+       output[0] = 0;
+       uint32_t newpc = 0;
+       m68kpc_offset = addr - m68k_getpc();
+       long int pcOffsetSave = m68kpc_offset;
+       int opwords;
+
+       while (cnt-- > 0)
+       {
+               char instrname[20], * ccpt;
+               uint32_t opcode;
+               const struct mnemolookup * lookup;
+               struct instr * dp;
+//             sprintf(f, "%06lX: ", m68k_getpc() + m68kpc_offset);
+//             strcat(str, f);
+
+#if 0
+               for(opwords=0; opwords<5; opwords++)
+               {
+                       sprintf(f, "%04X ", get_iword_1(m68kpc_offset + opwords * 2));
+                       strcat(str, f);
+               }
+#endif
+
+               opcode = get_iword_1(m68kpc_offset);
+               m68kpc_offset += 2;
+
+               if (cpuFunctionTable[opcode] == IllegalOpcode)
+               {
+                       opcode = 0x4AFC;
+               }
+
+               dp = table68k + opcode;
+
+               for(lookup=lookuptab; lookup->mnemo!=dp->mnemo; lookup++)
+                       ;
+
+               strcpy(instrname, lookup->name);
+               ccpt = strstr(instrname, "cc");
+
+               if (ccpt != 0)
+               {
+                       strncpy(ccpt, ccnames[dp->cc], 2);
+               }
+
+               sprintf(f, "%s", instrname);
+               strcat(str, f);
+
+#if 0
+               switch (dp->size)
+               {
+                       case sz_byte: sprintf(f, ".B "); break;
+                       case sz_word: sprintf(f, ".W "); break;
+                       case sz_long: sprintf(f, ".L "); break;
+                       default: sprintf(f, "   "); break;
+               }
+               strcat(str, f);
+#else
+               switch (dp->size)
+               {
+                       case sz_byte: strcat(str, ".B "); break;
+                       case sz_word: strcat(str, ".W "); break;
+                       case sz_long: strcat(str, ".L "); break;
+                       default: strcat(str, "   "); break;
+               }
+#endif
+
+               if (dp->suse)
+               {
+                       f[0] = 0;
+                       newpc = m68k_getpc() + m68kpc_offset;
+                       newpc += ShowEA(0, dp->sreg, dp->smode, dp->size, f);
+                       strcat(str, f);
+               }
+
+#if 1
+               if (dp->suse && dp->duse)
+               {
+//                     sprintf(f, ",");
+//                     strcat(str, f);
+                       strcat(str, ",");
+               }
+#endif
+
+               if (dp->duse)
+               {
+                       f[0] = 0;
+                       newpc = m68k_getpc() + m68kpc_offset;
+                       newpc += ShowEA(0, dp->dreg, dp->dmode, dp->size, f);
+                       strcat(str, f);
+               }
+
+               if (ccpt != 0)
+               {
+                       if (cctrue(dp->cc))
+                               sprintf(f, " == %08lX (TRUE)", (long)newpc);
+                       else
+                               sprintf(f, " == %08lX (FALSE)", (long)newpc);
+
+                       strcat(str, f);
+               }
+               else if ((opcode & 0xFF00) == 0x6100) // BSR
+               {
+                       sprintf(f, " == %08lX", (long)newpc);
+                       strcat(str, f);
+               }
+
+//             fprintf(f, "\n");
+       }
+
+//     if (nextpc)
+//             *nextpc = m68k_getpc() + m68kpc_offset;
+
+       long int numberOfBytes = m68kpc_offset - pcOffsetSave;
+
+       for(opwords=0; opwords<5; opwords++)
+       {
+               if (((opwords + 1) * 2) <= numberOfBytes)
+                       sprintf(f, "%04X ", get_iword_1(pcOffsetSave + opwords * 2));
+               else
+                       sprintf(f, "     ");
+
+               strcat(output, f);
+       }
+
+       strcat(output, str);
+
+       return numberOfBytes;
+}
+
+//
+// Disasemble one instruction at pc and store in str_buff
+//
+unsigned int m68k_disassemble(char * str_buff, unsigned int pc, unsigned int cpu_type)
+{
+       return m68k_disasm(str_buff, pc, 0, 1);
+}
diff --git a/src/m68000/m68kinterface.c b/src/m68000/m68kinterface.c
new file mode 100644 (file)
index 0000000..5292ca5
--- /dev/null
@@ -0,0 +1,631 @@
+//
+// m68kinterface.c: Code interface to the UAE 68000 core and support code
+//
+// by James L. Hammons
+// (C) 2011 Underground Software
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  10/28/2011  Created this file ;-)
+//
+
+#include "m68kinterface.h"
+#include "cpudefs.h"
+#include "inlines.h"
+#include "cpuextra.h"
+#include "readcpu.h"
+
+
+// Exception Vectors handled by emulation
+#define EXCEPTION_BUS_ERROR                2 /* This one is not emulated! */
+#define EXCEPTION_ADDRESS_ERROR            3 /* This one is partially emulated (doesn't stack a proper frame yet) */
+#define EXCEPTION_ILLEGAL_INSTRUCTION      4
+#define EXCEPTION_ZERO_DIVIDE              5
+#define EXCEPTION_CHK                      6
+#define EXCEPTION_TRAPV                    7
+#define EXCEPTION_PRIVILEGE_VIOLATION      8
+#define EXCEPTION_TRACE                    9
+#define EXCEPTION_1010                    10
+#define EXCEPTION_1111                    11
+#define EXCEPTION_FORMAT_ERROR            14
+#define EXCEPTION_UNINITIALIZED_INTERRUPT 15
+#define EXCEPTION_SPURIOUS_INTERRUPT      24
+#define EXCEPTION_INTERRUPT_AUTOVECTOR    24
+#define EXCEPTION_TRAP_BASE               32
+
+// These are found in obj/cpustbl.c (generated by gencpu)
+
+//extern const struct cputbl op_smalltbl_0_ff[];       /* 68040 */
+//extern const struct cputbl op_smalltbl_1_ff[];       /* 68020 + 68881 */
+//extern const struct cputbl op_smalltbl_2_ff[];       /* 68020 */
+//extern const struct cputbl op_smalltbl_3_ff[];       /* 68010 */
+extern const struct cputbl op_smalltbl_4_ff[]; /* 68000 */
+extern const struct cputbl op_smalltbl_5_ff[]; /* 68000 slow but compatible.  */
+
+// Externs, supplied by the user...
+extern int irq_ack_handler(int);
+
+// Function prototypes...
+STATIC_INLINE void m68ki_check_interrupts(void);
+void m68ki_exception_interrupt(uint intLevel);
+STATIC_INLINE uint32_t m68ki_init_exception(void);
+STATIC_INLINE void m68ki_stack_frame_3word(uint pc, uint sr);
+unsigned long IllegalOpcode(uint32_t opcode);
+void BuildCPUFunctionTable(void);
+
+// Local "Global" vars
+static int32_t initialCycles;
+cpuop_func * cpuFunctionTable[65536];
+
+
+#if 0
+#define ADD_CYCLES(A)    m68ki_remaining_cycles += (A)
+#define USE_CYCLES(A)    m68ki_remaining_cycles -= (A)
+#define SET_CYCLES(A)    m68ki_remaining_cycles = A
+#define GET_CYCLES()     m68ki_remaining_cycles
+#define USE_ALL_CYCLES() m68ki_remaining_cycles = 0
+
+#define CPU_INT_LEVEL    m68ki_cpu.int_level /* ASG: changed from CPU_INTS_PENDING */
+#define CPU_INT_CYCLES   m68ki_cpu.int_cycles /* ASG */
+#define CPU_STOPPED      m68ki_cpu.stopped
+#define CPU_PREF_ADDR    m68ki_cpu.pref_addr
+#define CPU_PREF_DATA    m68ki_cpu.pref_data
+#define CPU_ADDRESS_MASK m68ki_cpu.address_mask
+#define CPU_SR_MASK      m68ki_cpu.sr_mask
+#endif
+
+#define CPU_DEBUG
+void Dasm(uint32_t offset, uint32_t qt)
+{
+#ifdef CPU_DEBUG
+       static char buffer[2048];//, mem[64];
+       int pc = offset, oldpc;
+       uint32_t i;
+
+       for(i=0; i<qt; i++)
+       {
+/*             oldpc = pc;
+               for(int j=0; j<64; j++)
+                       mem[j^0x01] = jaguar_byte_read(pc + j);
+
+               pc += Dasm68000((char *)mem, buffer, 0);
+               WriteLog("%08X: %s\n", oldpc, buffer);//*/
+               oldpc = pc;
+               pc += m68k_disassemble(buffer, pc, 0);//M68K_CPU_TYPE_68000);
+//             WriteLog("%08X: %s\n", oldpc, buffer);//*/
+               printf("%08X: %s\n", oldpc, buffer);//*/
+       }
+#endif
+}
+
+
+void m68k_set_cpu_type(unsigned int type)
+{
+}
+
+// Pulse the RESET line on the CPU
+void m68k_pulse_reset(void)
+{
+       static uint emulation_initialized = 0;
+
+       // The first call to this function initializes the opcode handler jump table
+       if (!emulation_initialized)
+       {
+#if 0
+               m68ki_build_opcode_table();
+               m68k_set_int_ack_callback(NULL);
+               m68k_set_bkpt_ack_callback(NULL);
+               m68k_set_reset_instr_callback(NULL);
+               m68k_set_pc_changed_callback(NULL);
+               m68k_set_fc_callback(NULL);
+               m68k_set_instr_hook_callback(NULL);
+#else
+               // Build opcode handler table here...
+               read_table68k();
+               do_merges();
+               BuildCPUFunctionTable();
+#endif
+               emulation_initialized = 1;
+       }
+
+//     if (CPU_TYPE == 0)      /* KW 990319 */
+//             m68k_set_cpu_type(M68K_CPU_TYPE_68000);
+
+#if 0
+       /* Clear all stop levels and eat up all remaining cycles */
+       CPU_STOPPED = 0;
+       SET_CYCLES(0);
+
+       /* Turn off tracing */
+       FLAG_T1 = FLAG_T0 = 0;
+       m68ki_clear_trace();
+       /* Interrupt mask to level 7 */
+       FLAG_INT_MASK = 0x0700;
+       /* Reset VBR */
+       REG_VBR = 0;
+       /* Go to supervisor mode */
+       m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
+
+       /* Invalidate the prefetch queue */
+#if M68K_EMULATE_PREFETCH
+       /* Set to arbitrary number since our first fetch is from 0 */
+       CPU_PREF_ADDR = 0x1000;
+#endif /* M68K_EMULATE_PREFETCH */
+
+       /* Read the initial stack pointer and program counter */
+       m68ki_jump(0);
+       REG_SP = m68ki_read_imm_32();
+       REG_PC = m68ki_read_imm_32();
+       m68ki_jump(REG_PC);
+#else
+       regs.stopped = 0;
+       regs.remainingCycles = 0;
+       
+       regs.intmask = 0x07;
+       regs.s = 1;                                                             // Supervisor mode ON
+
+       // Read initial SP and PC
+       m68k_areg(regs, 7) = m68k_read_memory_32(0);
+       m68k_setpc(m68k_read_memory_32(4));
+       refill_prefetch(m68k_getpc(), 0);
+#endif
+}
+
+int m68k_execute(int num_cycles)
+{
+#if 0
+       /* Make sure we're not stopped */
+       if (CPU_STOPPED)
+       {
+               /* We get here if the CPU is stopped or halted */
+               SET_CYCLES(0);
+               CPU_INT_CYCLES = 0;
+
+               return num_cycles;
+       }
+#else
+       if (regs.stopped)
+       {
+               regs.remainingCycles = 0;       // int32_t
+               regs.interruptCycles = 0;       // uint32_t
+
+               return num_cycles;
+       }
+#endif
+
+#if 0
+       /* Set our pool of clock cycles available */
+       SET_CYCLES(num_cycles);
+       m68ki_initial_cycles = num_cycles;
+
+       /* ASG: update cycles */
+       USE_CYCLES(CPU_INT_CYCLES);
+       CPU_INT_CYCLES = 0;
+
+       /* Return point if we had an address error */
+       m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
+#else
+       regs.remainingCycles = num_cycles;
+       /*int32_t*/ initialCycles = num_cycles;
+       
+       regs.remainingCycles -= regs.interruptCycles;
+       regs.interruptCycles = 0;
+#endif
+
+       /* Main loop.  Keep going until we run out of clock cycles */
+       do
+       {
+#if 0
+               /* Set tracing accodring to T1. (T0 is done inside instruction) */
+               m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
+
+               /* Set the address space for reads */
+               m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
+
+               /* Call external hook to peek at CPU */
+               m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
+
+               /* Record previous program counter */
+               REG_PPC = REG_PC;
+
+               /* Read an instruction and call its handler */
+               REG_IR = m68ki_read_imm_16();
+               m68ki_instruction_jump_table[REG_IR]();
+               USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
+
+               /* Trace m68k_exception, if necessary */
+               m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
+#else
+//Testing Hover Strike...
+#if 0
+//Dasm(regs.pc, 1);
+static int hitCount = 0;
+static int inRoutine = 0;
+static int instSeen;
+
+//if (regs.pc == 0x80340A)
+if (regs.pc == 0x803416)
+{
+       hitCount++;
+       inRoutine = 1;
+       instSeen = 0;
+       printf("%i: $80340A start. A0=%08X, A1=%08X ", hitCount, regs.regs[8], regs.regs[9]);
+}
+else if (regs.pc == 0x803422)
+{
+       inRoutine = 0;
+       printf("(%i instructions)\n", instSeen);
+}
+
+if (inRoutine)
+       instSeen++;
+#endif
+               uint32_t opcode = get_iword(0);
+               int32_t cycles = (int32_t)(*cpuFunctionTable[opcode])(opcode);
+               regs.remainingCycles -= cycles;
+//printf("Executed opcode $%04X (%i cycles)...\n", opcode, cycles);
+#endif
+       }
+#if 0
+       while (GET_CYCLES() > 0);
+#else
+       while (regs.remainingCycles > 0);
+#endif
+
+#if 0
+       /* set previous PC to current PC for the next entry into the loop */
+       REG_PPC = REG_PC;
+
+       /* ASG: update cycles */
+       USE_CYCLES(CPU_INT_CYCLES);
+       CPU_INT_CYCLES = 0;
+
+       /* return how many clocks we used */
+       return m68ki_initial_cycles - GET_CYCLES();
+#else
+       regs.remainingCycles -= regs.interruptCycles;
+       regs.interruptCycles = 0;
+
+       // Return # of clock cycles used
+       return initialCycles - regs.remainingCycles;
+#endif
+}
+
+/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
+void m68k_set_irq(unsigned int intLevel)
+{
+#if 0
+       uint old_level = CPU_INT_LEVEL;
+       CPU_INT_LEVEL = int_level << 8;
+
+       /* A transition from < 7 to 7 always interrupts (NMI) */
+       /* Note: Level 7 can also level trigger like a normal IRQ */
+       if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
+               m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
+       else
+               m68ki_check_interrupts(); /* Level triggered (IRQ) */
+#else
+       int oldLevel = regs.intLevel;
+       regs.intLevel = intLevel;
+
+       // A transition from < 7 to 7 always interrupts (NMI)
+       // Note: Level 7 can also level trigger like a normal IRQ
+       if (oldLevel != 0x07 && regs.intLevel == 0x07)
+               m68ki_exception_interrupt(7);           // Edge triggered level 7 (NMI)
+       else
+               m68ki_check_interrupts();                       // Level triggered (IRQ)
+#endif
+}
+
+// Check for interrupts
+STATIC_INLINE void m68ki_check_interrupts(void)
+{
+#if 0
+       if(CPU_INT_LEVEL > FLAG_INT_MASK)
+               m68ki_exception_interrupt(CPU_INT_LEVEL>>8);
+#else
+       if (regs.intLevel > regs.intmask)
+               m68ki_exception_interrupt(regs.intLevel);
+#endif
+}
+
+// Service an interrupt request and start exception processing
+void m68ki_exception_interrupt(uint intLevel)
+{
+#if 0
+       uint vector;
+       uint sr;
+       uint new_pc;
+
+       /* Turn off the stopped state */
+       CPU_STOPPED &= ~STOP_LEVEL_STOP;
+
+       /* If we are halted, don't do anything */
+       if(CPU_STOPPED)
+               return;
+
+       /* Acknowledge the interrupt */
+       vector = m68ki_int_ack(int_level);
+
+       /* Get the interrupt vector */
+       if(vector == M68K_INT_ACK_AUTOVECTOR)
+               /* Use the autovectors.  This is the most commonly used implementation */
+               vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level;
+       else if(vector == M68K_INT_ACK_SPURIOUS)
+               /* Called if no devices respond to the interrupt acknowledge */
+               vector = EXCEPTION_SPURIOUS_INTERRUPT;
+       else if(vector > 255)
+       {
+               M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n",
+                        m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector));
+               return;
+       }
+
+       /* Start exception processing */
+       sr = m68ki_init_exception();
+
+       /* Set the interrupt mask to the level of the one being serviced */
+       FLAG_INT_MASK = int_level<<8;
+
+       /* Get the new PC */
+       new_pc = m68ki_read_data_32((vector<<2) + REG_VBR);
+
+       /* If vector is uninitialized, call the uninitialized interrupt vector */
+       if(new_pc == 0)
+               new_pc = m68ki_read_data_32((EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + REG_VBR);
+
+       /* Generate a stack frame */
+       m68ki_stack_frame_0000(REG_PC, sr, vector);
+
+       if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE))
+       {
+               /* Create throwaway frame */
+               m68ki_set_sm_flag(FLAG_S);      /* clear M */
+               sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */
+               m68ki_stack_frame_0001(REG_PC, sr, vector);
+       }
+
+       m68ki_jump(new_pc);
+
+       /* Defer cycle counting until later */
+       CPU_INT_CYCLES += CYC_EXCEPTION[vector];
+
+#if !M68K_EMULATE_INT_ACK
+       /* Automatically clear IRQ if we are not using an acknowledge scheme */
+       CPU_INT_LEVEL = 0;
+#endif /* M68K_EMULATE_INT_ACK */
+#else
+       // Turn off the stopped state
+       regs.stopped = 0;
+
+//JLH: need to add halt state?
+       // If we are halted, don't do anything
+//     if (CPU_STOPPED)
+//             return;
+
+       // Acknowledge the interrupt (NOTE: This is a user supplied function!)
+       uint32_t vector = irq_ack_handler(intLevel);
+
+       // Get the interrupt vector
+       if (vector == M68K_INT_ACK_AUTOVECTOR)
+               // Use the autovectors.  This is the most commonly used implementation
+               vector = EXCEPTION_INTERRUPT_AUTOVECTOR + intLevel;
+       else if (vector == M68K_INT_ACK_SPURIOUS)
+               // Called if no devices respond to the interrupt acknowledge
+               vector = EXCEPTION_SPURIOUS_INTERRUPT;
+       else if (vector > 255)
+       {
+//             M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n",
+//                      m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector));
+               return;
+       }
+
+       // Start exception processing
+       uint32_t sr = m68ki_init_exception();
+
+       // Set the interrupt mask to the level of the one being serviced
+       regs.intmask = intLevel;
+
+       // Get the new PC
+       uint32_t newPC = m68k_read_memory_32(vector << 2);
+
+       // If vector is uninitialized, call the uninitialized interrupt vector
+       if (newPC == 0)
+               newPC = m68k_read_memory_32(EXCEPTION_UNINITIALIZED_INTERRUPT << 2);
+
+       // Generate a stack frame
+       m68ki_stack_frame_3word(regs.pc, sr);
+
+       m68k_setpc(newPC);
+
+       // Defer cycle counting until later
+       regs.interruptCycles += 56;     // NOT ACCURATE-- !!! FIX !!!
+//     CPU_INT_CYCLES += CYC_EXCEPTION[vector];
+#endif
+}
+
+// Initiate exception processing
+STATIC_INLINE uint32_t m68ki_init_exception(void)
+{
+#if 0
+       /* Save the old status register */
+       uint sr = m68ki_get_sr();
+
+       /* Turn off trace flag, clear pending traces */
+       FLAG_T1 = FLAG_T0 = 0;
+       m68ki_clear_trace();
+       /* Enter supervisor mode */
+       m68ki_set_s_flag(SFLAG_SET);
+
+       return sr;
+#else
+       MakeSR();
+       uint32_t sr = regs.sr;                                  // Save old status register
+       regs.s = 1;                                                             // Set supervisor mode
+
+       return sr;
+#endif
+}
+
+// 3 word stack frame (68000 only)
+STATIC_INLINE void m68ki_stack_frame_3word(uint32_t pc, uint32_t sr)
+{
+#if 0
+       m68ki_push_32(pc);
+       m68ki_push_16(sr);
+#else
+       // Push PC on stack:
+       m68k_areg(regs, 7) -= 4;
+       m68k_write_memory_32(m68k_areg(regs, 7), pc);
+       // Push SR on stack:
+       m68k_areg(regs, 7) -= 2;
+       m68k_write_memory_16(m68k_areg(regs, 7), sr);
+#endif
+}
+
+unsigned int m68k_get_reg(void * context, m68k_register_t reg)
+{
+       if (reg <= M68K_REG_A7)
+               return regs.regs[reg];
+       else if (reg == M68K_REG_PC)
+               return regs.pc;
+       else if (reg == M68K_REG_SR)
+       {
+               MakeSR();
+               return regs.sr;
+       }
+       else if (reg == M68K_REG_SP)
+               return regs.regs[15];
+
+       return 0;
+}
+
+void m68k_set_reg(m68k_register_t reg, unsigned int value)
+{
+       if (reg <= M68K_REG_A7)
+               regs.regs[reg] = value;
+       else if (reg == M68K_REG_PC)
+               regs.pc = value;
+       else if (reg == M68K_REG_SR)
+       {
+               regs.sr = value;
+               MakeFromSR();
+       }
+       else if (reg == M68K_REG_SP)
+               regs.regs[15] = value;
+}
+
+//
+// Check if the instruction is a valid one
+//
+unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type)
+{
+       instruction &= 0xFFFF;
+
+       if (cpuFunctionTable[instruction] == IllegalOpcode)
+               return 0;
+
+       return 1;
+}
+
+// Dummy functions, for now, until we prove the concept here. :-)
+
+// Temp, while we're using the Musashi disassembler...
+#if 0
+unsigned int m68k_disassemble(char * str_buff, unsigned int pc, unsigned int cpu_type)
+{
+       return 0;
+}
+#endif
+
+int m68k_cycles_run(void) {}              /* Number of cycles run so far */
+int m68k_cycles_remaining(void) {}        /* Number of cycles left */
+void m68k_modify_timeslice(int cycles) {} /* Modify cycles left */
+//void m68k_end_timeslice(void) {}          /* End timeslice now */
+
+void m68k_end_timeslice(void)
+{
+#if 0
+       m68ki_initial_cycles = GET_CYCLES();
+       SET_CYCLES(0);
+#else
+       initialCycles = regs.remainingCycles;
+       regs.remainingCycles = 0;
+#endif
+}
+
+
+unsigned long IllegalOpcode(uint32_t opcode)
+{
+#if 0
+       uint32_t pc = m68k_getpc ();
+#endif
+       if ((opcode & 0xF000) == 0xF000)
+       {
+               Exception(0x0B, 0, M68000_EXC_SRC_CPU); // LineF exception...
+               return 4;
+       }
+       else if ((opcode & 0xF000) == 0xA000)
+       {
+               Exception(0x0A, 0, M68000_EXC_SRC_CPU); // LineA exception...
+               return 4;
+       }
+
+#if 0
+       write_log ("Illegal instruction: %04x at %08lx\n", opcode, (long)pc);
+#endif
+
+       Exception(0x04, 0, M68000_EXC_SRC_CPU);         // Illegal opcode exception...
+       return 4;
+}
+
+
+void BuildCPUFunctionTable(void)
+{
+       int i;
+       unsigned long opcode;
+
+       // We're only using the "fast" 68000 emulation here, not the "compatible"
+#if 0
+       const struct cputbl * tbl = (currprefs.cpu_compatible
+               ? op_smalltbl_5_ff : op_smalltbl_4_ff);
+#else
+       const struct cputbl * tbl = op_smalltbl_4_ff;
+#endif
+
+//     Log_Printf(LOG_DEBUG, "Building CPU function table (%d %d %d).\n",
+//             currprefs.cpu_level, currprefs.cpu_compatible, currprefs.address_space_24);
+
+       // Set all instructions to Illegal...
+       for(opcode=0; opcode<65536; opcode++)
+               cpuFunctionTable[opcode] = IllegalOpcode;
+
+       // Move functions from compact table into our full function table...
+       for(i=0; tbl[i].handler!=NULL; i++)
+               cpuFunctionTable[tbl[i].opcode] = tbl[i].handler;
+
+//JLH: According to readcpu.c, handler is set to -1 and never changes.
+// Actually, it does read this crap in readcpu.c, do_merges() does it... :-P
+// Again, seems like a build time thing could be done here...
+#if 1
+       for(opcode=0; opcode<65536; opcode++)
+       {
+//             if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > currprefs.cpu_level)
+               if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > 0)
+                       continue;
+
+               if (table68k[opcode].handler != -1)
+               {
+//printf("Relocate: $%04X->$%04X\n", table68k[opcode].handler, opcode);
+                       cpuop_func * f = cpuFunctionTable[table68k[opcode].handler];
+
+                       if (f == IllegalOpcode)
+                               abort();
+
+                       cpuFunctionTable[opcode] = f;
+               }
+       }
+#endif
+}
diff --git a/src/m68000/m68kinterface.h b/src/m68000/m68kinterface.h
new file mode 100644 (file)
index 0000000..08df443
--- /dev/null
@@ -0,0 +1,124 @@
+//
+// C interface to the UAE core
+//
+// by James Hammons
+// (C) 2011 Underground Software
+//
+// Most of these functions are in place to help make it easy to replace the
+// Musashi core with my bastardized UAE one. :-)
+//
+
+#ifndef __M68KINTERFACE_H__
+#define __M68KINTERFACE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Registers used by m68k_get_reg() and m68k_set_reg() */
+typedef enum
+{
+       /* Real registers */
+       M68K_REG_D0,            /* Data registers */
+       M68K_REG_D1,
+       M68K_REG_D2,
+       M68K_REG_D3,
+       M68K_REG_D4,
+       M68K_REG_D5,
+       M68K_REG_D6,
+       M68K_REG_D7,
+       M68K_REG_A0,            /* Address registers */
+       M68K_REG_A1,
+       M68K_REG_A2,
+       M68K_REG_A3,
+       M68K_REG_A4,
+       M68K_REG_A5,
+       M68K_REG_A6,
+       M68K_REG_A7,
+       M68K_REG_PC,            /* Program Counter */
+       M68K_REG_SR,            /* Status Register */
+       M68K_REG_SP,            /* The current Stack Pointer (located in A7) */
+       M68K_REG_USP,           /* User Stack Pointer */
+
+       /* Assumed registers */
+       /* These are cheat registers which emulate the 1-longword prefetch
+        * present in the 68000 and 68010.
+        */ 
+       M68K_REG_PREF_ADDR,     /* Last prefetch address */
+       M68K_REG_PREF_DATA,     /* Last prefetch data */
+
+       /* Convenience registers */
+       M68K_REG_PPC,           /* Previous value in the program counter */
+       M68K_REG_IR,            /* Instruction register */
+} m68k_register_t;
+
+/* Special interrupt acknowledge values.
+ * Use these as special returns from the interrupt acknowledge callback
+ * (specified later in this header).
+ */
+
+/* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
+ * This happens in a real 68K if VPA or AVEC is asserted during an interrupt
+ * acknowledge cycle instead of DTACK.
+ */
+#define M68K_INT_ACK_AUTOVECTOR    0xFFFFFFFF
+
+/* Causes the spurious interrupt vector (0x18) to be taken
+ * This happens in a real 68K if BERR is asserted during the interrupt
+ * acknowledge cycle (i.e. no devices responded to the acknowledge).
+ */
+#define M68K_INT_ACK_SPURIOUS      0xFFFFFFFE
+
+void m68k_set_cpu_type(unsigned int);
+void m68k_pulse_reset(void);
+int m68k_execute(int num_cycles);
+void m68k_set_irq(unsigned int int_level);
+
+// Functions that MUST be implemented by the user:
+
+// Read from anywhere
+unsigned int m68k_read_memory_8(unsigned int address);
+unsigned int m68k_read_memory_16(unsigned int address);
+unsigned int m68k_read_memory_32(unsigned int address);
+
+// Write to anywhere
+void m68k_write_memory_8(unsigned int address, unsigned int value);
+void m68k_write_memory_16(unsigned int address, unsigned int value);
+void m68k_write_memory_32(unsigned int address, unsigned int value);
+
+// Convenience functions
+
+/* Peek at the internals of a CPU context.  This can either be a context
+ * retrieved using m68k_get_context() or the currently running context.
+ * If context is NULL, the currently running CPU context will be used.
+ */
+unsigned int m68k_get_reg(void * context, m68k_register_t reg);
+
+/* Poke values into the internals of the currently running CPU context */
+void m68k_set_reg(m68k_register_t reg, unsigned int value);
+
+// Dummy functions, for now...
+
+/* Check if an instruction is valid for the specified CPU type */
+unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type);
+
+/* Disassemble 1 instruction using the epecified CPU type at pc.  Stores
+ * disassembly in str_buff and returns the size of the instruction in bytes.
+ */
+unsigned int m68k_disassemble(char * str_buff, unsigned int pc, unsigned int cpu_type);
+
+/* These functions let you read/write/modify the number of cycles left to run
+ * while m68k_execute() is running.
+ * These are useful if the 68k accesses a memory-mapped port on another device
+ * that requires immediate processing by another CPU.
+ */
+int m68k_cycles_run(void);              // Number of cycles run so far
+int m68k_cycles_remaining(void);        // Number of cycles left
+void m68k_modify_timeslice(int cycles); // Modify cycles left
+void m68k_end_timeslice(void);          // End timeslice now
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __M68KINTERFACE_H__
diff --git a/src/m68000/readcpu.c b/src/m68000/readcpu.c
new file mode 100644 (file)
index 0000000..4f34db2
--- /dev/null
@@ -0,0 +1,883 @@
+/*
+ * UAE - The Un*x Amiga Emulator - CPU core
+ *
+ * Read 68000 CPU specs from file "table68k"
+ *
+ * Copyright 1995,1996 Bernd Schmidt
+ *
+ * Adaptation to Hatari by Thomas Huth
+ * Adaptation to Virtual Jaguar by James Hammons
+ *
+ * This file is distributed under the GNU Public License, version 3 or at
+ * your option any later version. Read the file GPLv3 for details.
+ */
+
+
+/* 2008/04/26  [NP]    Handle sz_byte for Areg as a valid srcmode if current instruction is a MOVE     */
+/*                     (e.g. move.b a1,(a0) ($1089)) (fix Blood Money on Superior 65)                  */
+
+
+const char ReadCpu_fileid[] = "Hatari readcpu.c : " __DATE__ " " __TIME__;
+
+#include <ctype.h>
+#include <string.h>
+
+#include "readcpu.h"
+
+int nr_cpuop_funcs;
+
+const struct mnemolookup lookuptab[] = {
+    { i_ILLG, "ILLEGAL" },
+    { i_OR, "OR" },
+    { i_CHK, "CHK" },
+    { i_CHK2, "CHK2" },
+    { i_AND, "AND" },
+    { i_EOR, "EOR" },
+    { i_ORSR, "ORSR" },
+    { i_ANDSR, "ANDSR" },
+    { i_EORSR, "EORSR" },
+    { i_SUB, "SUB" },
+    { i_SUBA, "SUBA" },
+    { i_SUBX, "SUBX" },
+    { i_SBCD, "SBCD" },
+    { i_ADD, "ADD" },
+    { i_ADDA, "ADDA" },
+    { i_ADDX, "ADDX" },
+    { i_ABCD, "ABCD" },
+    { i_NEG, "NEG" },
+    { i_NEGX, "NEGX" },
+    { i_NBCD, "NBCD" },
+    { i_CLR, "CLR" },
+    { i_NOT, "NOT" },
+    { i_TST, "TST" },
+    { i_BTST, "BTST" },
+    { i_BCHG, "BCHG" },
+    { i_BCLR, "BCLR" },
+    { i_BSET, "BSET" },
+    { i_CMP, "CMP" },
+    { i_CMPM, "CMPM" },
+    { i_CMPA, "CMPA" },
+    { i_MVPRM, "MVPRM" },
+    { i_MVPMR, "MVPMR" },
+    { i_MOVE, "MOVE" },
+    { i_MOVEA, "MOVEA" },
+    { i_MVSR2, "MVSR2" },
+    { i_MV2SR, "MV2SR" },
+    { i_SWAP, "SWAP" },
+    { i_EXG, "EXG" },
+    { i_EXT, "EXT" },
+    { i_MVMEL, "MVMEL" },
+    { i_MVMLE, "MVMLE" },
+    { i_TRAP, "TRAP" },
+    { i_MVR2USP, "MVR2USP" },
+    { i_MVUSP2R, "MVUSP2R" },
+    { i_NOP, "NOP" },
+    { i_RESET, "RESET" },
+    { i_RTE, "RTE" },
+    { i_RTD, "RTD" },
+    { i_LINK, "LINK" },
+    { i_UNLK, "UNLK" },
+    { i_RTS, "RTS" },
+    { i_STOP, "STOP" },
+    { i_TRAPV, "TRAPV" },
+    { i_RTR, "RTR" },
+    { i_JSR, "JSR" },
+    { i_JMP, "JMP" },
+    { i_BSR, "BSR" },
+    { i_Bcc, "Bcc" },
+    { i_LEA, "LEA" },
+    { i_PEA, "PEA" },
+    { i_DBcc, "DBcc" },
+    { i_Scc, "Scc" },
+    { i_DIVU, "DIVU" },
+    { i_DIVS, "DIVS" },
+    { i_MULU, "MULU" },
+    { i_MULS, "MULS" },
+    { i_ASR, "ASR" },
+    { i_ASL, "ASL" },
+    { i_LSR, "LSR" },
+    { i_LSL, "LSL" },
+    { i_ROL, "ROL" },
+    { i_ROR, "ROR" },
+    { i_ROXL, "ROXL" },
+    { i_ROXR, "ROXR" },
+    { i_ASRW, "ASRW" },
+    { i_ASLW, "ASLW" },
+    { i_LSRW, "LSRW" },
+    { i_LSLW, "LSLW" },
+    { i_ROLW, "ROLW" },
+    { i_RORW, "RORW" },
+    { i_ROXLW, "ROXLW" },
+    { i_ROXRW, "ROXRW" },
+
+    { i_MOVE2C, "MOVE2C" },
+    { i_MOVEC2, "MOVEC2" },
+    { i_CAS, "CAS" },
+    { i_CAS2, "CAS2" },
+    { i_MULL, "MULL" },
+    { i_DIVL, "DIVL" },
+    { i_BFTST, "BFTST" },
+    { i_BFEXTU, "BFEXTU" },
+    { i_BFCHG, "BFCHG" },
+    { i_BFEXTS, "BFEXTS" },
+    { i_BFCLR, "BFCLR" },
+    { i_BFFFO, "BFFFO" },
+    { i_BFSET, "BFSET" },
+    { i_BFINS, "BFINS" },
+    { i_PACK, "PACK" },
+    { i_UNPK, "UNPK" },
+    { i_TAS, "TAS" },
+    { i_BKPT, "BKPT" },
+    { i_CALLM, "CALLM" },
+    { i_RTM, "RTM" },
+    { i_TRAPcc, "TRAPcc" },
+    { i_MOVES, "MOVES" },
+    { i_FPP, "FPP" },
+    { i_FDBcc, "FDBcc" },
+    { i_FScc, "FScc" },
+    { i_FTRAPcc, "FTRAPcc" },
+    { i_FBcc, "FBcc" },
+    { i_FBcc, "FBcc" },
+    { i_FSAVE, "FSAVE" },
+    { i_FRESTORE, "FRESTORE" },
+
+    { i_CINVL, "CINVL" },
+    { i_CINVP, "CINVP" },
+    { i_CINVA, "CINVA" },
+    { i_CPUSHL, "CPUSHL" },
+    { i_CPUSHP, "CPUSHP" },
+    { i_CPUSHA, "CPUSHA" },
+    { i_MOVE16, "MOVE16" },
+
+    { i_MMUOP, "MMUOP" },
+    { i_ILLG, "" },
+};
+
+struct instr *table68k;
+
+STATIC_INLINE amodes mode_from_str (const char *str)
+{
+    if (strncmp (str, "Dreg", 4) == 0) return Dreg;
+    if (strncmp (str, "Areg", 4) == 0) return Areg;
+    if (strncmp (str, "Aind", 4) == 0) return Aind;
+    if (strncmp (str, "Apdi", 4) == 0) return Apdi;
+    if (strncmp (str, "Aipi", 4) == 0) return Aipi;
+    if (strncmp (str, "Ad16", 4) == 0) return Ad16;
+    if (strncmp (str, "Ad8r", 4) == 0) return Ad8r;
+    if (strncmp (str, "absw", 4) == 0) return absw;
+    if (strncmp (str, "absl", 4) == 0) return absl;
+    if (strncmp (str, "PC16", 4) == 0) return PC16;
+    if (strncmp (str, "PC8r", 4) == 0) return PC8r;
+    if (strncmp (str, "Immd", 4) == 0) return imm;
+    abort ();
+    return 0;
+}
+
+STATIC_INLINE amodes mode_from_mr (int mode, int reg)
+{
+    switch (mode) {
+     case 0: return Dreg;
+     case 1: return Areg;
+     case 2: return Aind;
+     case 3: return Aipi;
+     case 4: return Apdi;
+     case 5: return Ad16;
+     case 6: return Ad8r;
+     case 7:
+       switch (reg) {
+        case 0: return absw;
+        case 1: return absl;
+        case 2: return PC16;
+        case 3: return PC8r;
+        case 4: return imm;
+        case 5:
+        case 6:
+        case 7: return am_illg;
+       }
+    }
+    abort ();
+    return 0;
+}
+
+static void build_insn(int insn)
+{
+    int find = -1;
+    int variants;
+    int isjmp = 0;
+    struct instr_def id;
+    const char *opcstr;
+    int j;
+
+    int flaglive = 0, flagdead = 0;
+
+    id = defs68k[insn];
+
+    /* Note: We treat anything with unknown flags as a jump. That
+       is overkill, but "the programmer" was lazy quite often, and
+       *this* programmer can't be bothered to work out what can and
+       can't trap. Usually, this will be overwritten with the gencomp
+       based information, anyway. */
+
+    for (j = 0; j < 5; j++) {
+       switch (id.flaginfo[j].flagset){
+        case fa_unset: break;
+        case fa_isjmp: isjmp = 1; break;
+        case fa_isbranch: isjmp = 1; break;
+        case fa_zero: flagdead |= 1 << j; break;
+        case fa_one: flagdead |= 1 << j; break;
+        case fa_dontcare: flagdead |= 1 << j; break;
+        case fa_unknown: isjmp = 1; flagdead = -1; goto out1;
+        case fa_set: flagdead |= 1 << j; break;
+       }
+    }
+
+  out1:
+    for (j = 0; j < 5; j++) {
+       switch (id.flaginfo[j].flaguse) {
+        case fu_unused: break;
+        case fu_isjmp: isjmp = 1; flaglive |= 1 << j; break;
+        case fu_maybecc: isjmp = 1; flaglive |= 1 << j; break;
+        case fu_unknown: isjmp = 1; flaglive |= 1 << j; break;
+        case fu_used: flaglive |= 1 << j; break;
+       }
+    }
+
+    opcstr = id.opcstr;
+    for (variants = 0; variants < (1 << id.n_variable); variants++) {
+       int bitcnt[lastbit];
+       int bitval[lastbit];
+       int bitpos[lastbit];
+       int i;
+       uint16_t opc = id.bits;
+       uint16_t msk, vmsk;
+       int pos = 0;
+       int mnp = 0;
+       int bitno = 0;
+       char mnemonic[10];
+
+       wordsizes sz = sz_long;
+       int srcgather = 0, dstgather = 0;
+       int usesrc = 0, usedst = 0;
+       int srctype = 0;
+       int srcpos = -1, dstpos = -1;
+
+       amodes srcmode = am_unknown, destmode = am_unknown;
+       int srcreg = -1, destreg = -1;
+
+       for (i = 0; i < lastbit; i++)
+           bitcnt[i] = bitval[i] = 0;
+
+       vmsk = 1 << id.n_variable;
+
+       for (i = 0, msk = 0x8000; i < 16; i++, msk >>= 1) {
+           if (!(msk & id.mask)) {
+               int currbit = id.bitpos[bitno++];
+               int bit_set;
+               vmsk >>= 1;
+               bit_set = variants & vmsk ? 1 : 0;
+               if (bit_set)
+                   opc |= msk;
+               bitpos[currbit] = 15 - i;
+               bitcnt[currbit]++;
+               bitval[currbit] <<= 1;
+               bitval[currbit] |= bit_set;
+           }
+       }
+
+       if (bitval[bitj] == 0) bitval[bitj] = 8;
+       /* first check whether this one does not match after all */
+       if (bitval[bitz] == 3 || bitval[bitC] == 1)
+           continue;
+       if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
+           continue;
+
+       /* bitI and bitC get copied to biti and bitc */
+       if (bitcnt[bitI]) {
+           bitval[biti] = bitval[bitI]; bitpos[biti] = bitpos[bitI];
+       }
+       if (bitcnt[bitC])
+           bitval[bitc] = bitval[bitC];
+
+       pos = 0;
+       while (opcstr[pos] && !isspace((unsigned)opcstr[pos])) {
+           if (opcstr[pos] == '.') {
+               pos++;
+               switch (opcstr[pos]) {
+
+                case 'B': sz = sz_byte; break;
+                case 'W': sz = sz_word; break;
+                case 'L': sz = sz_long; break;
+                case 'z':
+                   switch (bitval[bitz]) {
+                    case 0: sz = sz_byte; break;
+                    case 1: sz = sz_word; break;
+                    case 2: sz = sz_long; break;
+                    default: abort();
+                   }
+                   break;
+                default: abort();
+               }
+           } else {
+               mnemonic[mnp] = opcstr[pos];
+               if (mnemonic[mnp] == 'f') {
+                   find = -1;
+                   switch (bitval[bitf]) {
+                    case 0: mnemonic[mnp] = 'R'; break;
+                    case 1: mnemonic[mnp] = 'L'; break;
+                    default: abort();
+                   }
+               }
+               mnp++;
+           }
+           pos++;
+       }
+       mnemonic[mnp] = 0;
+
+       /* now, we have read the mnemonic and the size */
+       while (opcstr[pos] && isspace((unsigned)opcstr[pos]))
+           pos++;
+
+       /* A goto a day keeps the D******a away. */
+       if (opcstr[pos] == 0)
+           goto endofline;
+
+       /* parse the source address */
+       usesrc = 1;
+       switch (opcstr[pos++]) {
+        case 'D':
+           srcmode = Dreg;
+           switch (opcstr[pos++]) {
+            case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
+            case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
+            default: abort();
+           }
+
+           break;
+        case 'A':
+           srcmode = Areg;
+           switch (opcstr[pos++]) {
+            case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
+            case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
+            default: abort();
+           }
+           switch (opcstr[pos]) {
+            case 'p': srcmode = Apdi; pos++; break;
+            case 'P': srcmode = Aipi; pos++; break;
+           }
+           break;
+        case 'L':
+           srcmode = absl;
+           break;
+        case '#':
+           switch (opcstr[pos++]) {
+            case 'z': srcmode = imm; break;
+            case '0': srcmode = imm0; break;
+            case '1': srcmode = imm1; break;
+            case '2': srcmode = imm2; break;
+            case 'i': srcmode = immi; srcreg = (int32_t)(int8_t)bitval[biti];
+               if (CPU_EMU_SIZE < 4) {
+                   /* Used for branch instructions */
+                   srctype = 1;
+                   srcgather = 1;
+                   srcpos = bitpos[biti];
+               }
+               break;
+            case 'j': srcmode = immi; srcreg = bitval[bitj];
+               if (CPU_EMU_SIZE < 3) {
+                   /* 1..8 for ADDQ/SUBQ and rotshi insns */
+                   srcgather = 1;
+                   srctype = 3;
+                   srcpos = bitpos[bitj];
+               }
+               break;
+            case 'J': srcmode = immi; srcreg = bitval[bitJ];
+               if (CPU_EMU_SIZE < 5) {
+                   /* 0..15 */
+                   srcgather = 1;
+                   srctype = 2;
+                   srcpos = bitpos[bitJ];
+               }
+               break;
+            case 'k': srcmode = immi; srcreg = bitval[bitk];
+               if (CPU_EMU_SIZE < 3) {
+                   srcgather = 1;
+                   srctype = 4;
+                   srcpos = bitpos[bitk];
+               }
+               break;
+            case 'K': srcmode = immi; srcreg = bitval[bitK];
+               if (CPU_EMU_SIZE < 5) {
+                   /* 0..15 */
+                   srcgather = 1;
+                   srctype = 5;
+                   srcpos = bitpos[bitK];
+               }
+               break;
+            case 'p': srcmode = immi; srcreg = bitval[bitK];
+               if (CPU_EMU_SIZE < 5) {
+                   /* 0..3 */
+                   srcgather = 1;
+                   srctype = 7;
+                   srcpos = bitpos[bitp];
+               }
+               break;
+            default: abort();
+           }
+           break;
+        case 'd':
+           srcreg = bitval[bitD];
+           srcmode = mode_from_mr(bitval[bitd],bitval[bitD]);
+           if (srcmode == am_illg)
+               continue;
+           if (CPU_EMU_SIZE < 2 &&
+               (srcmode == Areg || srcmode == Dreg || srcmode == Aind
+                || srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
+                || srcmode == Apdi))
+           {
+               srcgather = 1; srcpos = bitpos[bitD];
+           }
+           if (opcstr[pos] == '[') {
+               pos++;
+               if (opcstr[pos] == '!') {
+                   /* exclusion */
+                   do {
+                       pos++;
+                       if (mode_from_str(opcstr+pos) == srcmode)
+                           goto nomatch;
+                       pos += 4;
+                   } while (opcstr[pos] == ',');
+                   pos++;
+               } else {
+                   if (opcstr[pos+4] == '-') {
+                       /* replacement */
+                       if (mode_from_str(opcstr+pos) == srcmode)
+                           srcmode = mode_from_str(opcstr+pos+5);
+                       else
+                           goto nomatch;
+                       pos += 10;
+                   } else {
+                       /* normal */
+                       while(mode_from_str(opcstr+pos) != srcmode) {
+                           pos += 4;
+                           if (opcstr[pos] == ']')
+                               goto nomatch;
+                           pos++;
+                       }
+                       while(opcstr[pos] != ']') pos++;
+                       pos++;
+                       break;
+                   }
+               }
+           }
+           /* Some addressing modes are invalid as destination */
+           if (srcmode == imm || srcmode == PC16 || srcmode == PC8r)
+               goto nomatch;
+           break;
+        case 's':
+           srcreg = bitval[bitS];
+           srcmode = mode_from_mr(bitval[bits],bitval[bitS]);
+
+           if (srcmode == am_illg)
+               continue;
+           if (CPU_EMU_SIZE < 2 &&
+               (srcmode == Areg || srcmode == Dreg || srcmode == Aind
+                || srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
+                || srcmode == Apdi))
+           {
+               srcgather = 1; srcpos = bitpos[bitS];
+           }
+           if (opcstr[pos] == '[') {
+               pos++;
+               if (opcstr[pos] == '!') {
+                   /* exclusion */
+                   do {
+                       pos++;
+                       if (mode_from_str(opcstr+pos) == srcmode)
+                           goto nomatch;
+                       pos += 4;
+                   } while (opcstr[pos] == ',');
+                   pos++;
+               } else {
+                   if (opcstr[pos+4] == '-') {
+                       /* replacement */
+                       if (mode_from_str(opcstr+pos) == srcmode)
+                           srcmode = mode_from_str(opcstr+pos+5);
+                       else
+                           goto nomatch;
+                       pos += 10;
+                   } else {
+                       /* normal */
+                       while(mode_from_str(opcstr+pos) != srcmode) {
+                           pos += 4;
+                           if (opcstr[pos] == ']')
+                               goto nomatch;
+                           pos++;
+                       }
+                       while(opcstr[pos] != ']') pos++;
+                       pos++;
+                   }
+               }
+           }
+           break;
+        default: abort();
+       }
+       /* safety check - might have changed */
+       if (srcmode != Areg && srcmode != Dreg && srcmode != Aind
+           && srcmode != Ad16 && srcmode != Ad8r && srcmode != Aipi
+           && srcmode != Apdi && srcmode != immi)
+       {
+           srcgather = 0;
+       }
+//     if (srcmode == Areg && sz == sz_byte)
+       if (srcmode == Areg && sz == sz_byte && strcmp ( mnemonic , "MOVE" ) != 0 )     // [NP] move.b is valid on 68000
+           goto nomatch;
+
+       if (opcstr[pos] != ',')
+           goto endofline;
+       pos++;
+
+       /* parse the destination address */
+       usedst = 1;
+       switch (opcstr[pos++]) {
+        case 'D':
+           destmode = Dreg;
+           switch (opcstr[pos++]) {
+            case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
+            case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
+            default: abort();
+           }
+            if (dstpos < 0 || dstpos >= 32)
+               abort ();
+           break;
+        case 'A':
+           destmode = Areg;
+           switch (opcstr[pos++]) {
+            case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
+            case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
+            case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
+            default: abort();
+           }
+            if (dstpos < 0 || dstpos >= 32)
+               abort ();
+           switch (opcstr[pos]) {
+            case 'p': destmode = Apdi; pos++; break;
+            case 'P': destmode = Aipi; pos++; break;
+           }
+           break;
+        case 'L':
+           destmode = absl;
+           break;
+        case '#':
+           switch (opcstr[pos++]) {
+            case 'z': destmode = imm; break;
+            case '0': destmode = imm0; break;
+            case '1': destmode = imm1; break;
+            case '2': destmode = imm2; break;
+            case 'i': destmode = immi; destreg = (int32_t)(int8_t)bitval[biti]; break;
+            case 'j': destmode = immi; destreg = bitval[bitj]; break;
+            case 'J': destmode = immi; destreg = bitval[bitJ]; break;
+            case 'k': destmode = immi; destreg = bitval[bitk]; break;
+            case 'K': destmode = immi; destreg = bitval[bitK]; break;
+            default: abort();
+           }
+           break;
+        case 'd':
+           destreg = bitval[bitD];
+           destmode = mode_from_mr(bitval[bitd],bitval[bitD]);
+           if (destmode == am_illg)
+               continue;
+           if (CPU_EMU_SIZE < 1 &&
+               (destmode == Areg || destmode == Dreg || destmode == Aind
+                || destmode == Ad16 || destmode == Ad8r || destmode == Aipi
+                || destmode == Apdi))
+           {
+               dstgather = 1; dstpos = bitpos[bitD];
+           }
+
+           if (opcstr[pos] == '[') {
+               pos++;
+               if (opcstr[pos] == '!') {
+                   /* exclusion */
+                   do {
+                       pos++;
+                       if (mode_from_str(opcstr+pos) == destmode)
+                           goto nomatch;
+                       pos += 4;
+                   } while (opcstr[pos] == ',');
+                   pos++;
+               } else {
+                   if (opcstr[pos+4] == '-') {
+                       /* replacement */
+                       if (mode_from_str(opcstr+pos) == destmode)
+                           destmode = mode_from_str(opcstr+pos+5);
+                       else
+                           goto nomatch;
+                       pos += 10;
+                   } else {
+                       /* normal */
+                       while(mode_from_str(opcstr+pos) != destmode) {
+                           pos += 4;
+                           if (opcstr[pos] == ']')
+                               goto nomatch;
+                           pos++;
+                       }
+                       while(opcstr[pos] != ']') pos++;
+                       pos++;
+                       break;
+                   }
+               }
+           }
+           /* Some addressing modes are invalid as destination */
+           if (destmode == imm || destmode == PC16 || destmode == PC8r)
+               goto nomatch;
+           break;
+        case 's':
+           destreg = bitval[bitS];
+           destmode = mode_from_mr(bitval[bits],bitval[bitS]);
+
+           if (destmode == am_illg)
+               continue;
+           if (CPU_EMU_SIZE < 1 &&
+               (destmode == Areg || destmode == Dreg || destmode == Aind
+                || destmode == Ad16 || destmode == Ad8r || destmode == Aipi
+                || destmode == Apdi))
+           {
+               dstgather = 1; dstpos = bitpos[bitS];
+           }
+
+           if (opcstr[pos] == '[') {
+               pos++;
+               if (opcstr[pos] == '!') {
+                   /* exclusion */
+                   do {
+                       pos++;
+                       if (mode_from_str(opcstr+pos) == destmode)
+                           goto nomatch;
+                       pos += 4;
+                   } while (opcstr[pos] == ',');
+                   pos++;
+               } else {
+                   if (opcstr[pos+4] == '-') {
+                       /* replacement */
+                       if (mode_from_str(opcstr+pos) == destmode)
+                           destmode = mode_from_str(opcstr+pos+5);
+                       else
+                           goto nomatch;
+                       pos += 10;
+                   } else {
+                       /* normal */
+                       while(mode_from_str(opcstr+pos) != destmode) {
+                           pos += 4;
+                           if (opcstr[pos] == ']')
+                               goto nomatch;
+                           pos++;
+                       }
+                       while(opcstr[pos] != ']') pos++;
+                       pos++;
+                   }
+               }
+           }
+           break;
+        default: abort();
+       }
+       /* safety check - might have changed */
+       if (destmode != Areg && destmode != Dreg && destmode != Aind
+           && destmode != Ad16 && destmode != Ad8r && destmode != Aipi
+           && destmode != Apdi)
+       {
+           dstgather = 0;
+       }
+
+       if (destmode == Areg && sz == sz_byte)
+           goto nomatch;
+#if 0
+       if (sz == sz_byte && (destmode == Aipi || destmode == Apdi)) {
+           dstgather = 0;
+       }
+#endif
+       endofline:
+       /* now, we have a match */
+       if (table68k[opc].mnemo != i_ILLG)
+           fprintf(stderr, "Double match: %x: %s\n", opc, opcstr);
+       if (find == -1) {
+           for (find = 0;; find++) {
+               if (strcmp(mnemonic, lookuptab[find].name) == 0) {
+                   table68k[opc].mnemo = lookuptab[find].mnemo;
+                   break;
+               }
+               if (strlen(lookuptab[find].name) == 0) abort();
+           }
+       }
+       else {
+           table68k[opc].mnemo = lookuptab[find].mnemo;
+       }
+       table68k[opc].cc = bitval[bitc];
+       if (table68k[opc].mnemo == i_BTST
+           || table68k[opc].mnemo == i_BSET
+           || table68k[opc].mnemo == i_BCLR
+           || table68k[opc].mnemo == i_BCHG)
+       {
+           sz = destmode == Dreg ? sz_long : sz_byte;
+       }
+       table68k[opc].size = sz;
+       table68k[opc].sreg = srcreg;
+       table68k[opc].dreg = destreg;
+       table68k[opc].smode = srcmode;
+       table68k[opc].dmode = destmode;
+       table68k[opc].spos = srcgather ? srcpos : -1;
+       table68k[opc].dpos = dstgather ? dstpos : -1;
+       table68k[opc].suse = usesrc;
+       table68k[opc].duse = usedst;
+       table68k[opc].stype = srctype;
+       table68k[opc].plev = id.plevel;
+       table68k[opc].clev = id.cpulevel;
+#if 0
+       for (i = 0; i < 5; i++) {
+           table68k[opc].flaginfo[i].flagset = id.flaginfo[i].flagset;
+           table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse;
+       }
+#endif
+       table68k[opc].flagdead = flagdead;
+       table68k[opc].flaglive = flaglive;
+       table68k[opc].isjmp = isjmp;
+      nomatch:
+       /* FOO! */;
+    }
+}
+
+
+void read_table68k(void)
+{
+       int i;
+       table68k = (struct instr *)malloc(65536 * sizeof(struct instr));
+
+       for(i=0; i<65536; i++)
+       {
+               table68k[i].mnemo = i_ILLG;
+               table68k[i].handler = -1;
+       }
+
+       for(i=0; i<n_defs68k; i++)
+               build_insn(i);
+}
+
+static int mismatch;
+
+static void handle_merges (long int opcode)
+{
+       uint16_t smsk;
+       uint16_t dmsk;
+       int sbitdst, dstend;
+       int srcreg, dstreg;
+
+       if (table68k[opcode].spos == -1)
+       {
+               sbitdst = 1;
+               smsk = 0;
+       }
+       else
+       {
+               switch (table68k[opcode].stype)
+               {
+               case 0:
+                       smsk = 7; sbitdst = 8; break;
+               case 1:
+                       smsk = 255; sbitdst = 256; break;
+               case 2:
+                       smsk = 15; sbitdst = 16; break;
+               case 3:
+                       smsk = 7; sbitdst = 8; break;
+               case 4:
+                       smsk = 7; sbitdst = 8; break;
+               case 5:
+                       smsk = 63; sbitdst = 64; break;
+               case 7:
+                       smsk = 3; sbitdst = 4; break;
+               default:
+                       smsk = 0; sbitdst = 0;
+                       abort();
+                       break;
+               }
+
+               smsk <<= table68k[opcode].spos;
+    }
+
+       if (table68k[opcode].dpos == -1)
+       {
+               dstend = 1; dmsk = 0;
+       }
+       else
+       {
+               dmsk = 7 << table68k[opcode].dpos;
+               dstend = 8;
+       }
+
+       for(srcreg=0; srcreg<sbitdst; srcreg++)
+       {
+               for(dstreg=0; dstreg<dstend; dstreg++)
+               {
+                       uint16_t code = opcode;
+
+                       code = (code & ~smsk) | (srcreg << table68k[opcode].spos);
+                       code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos);
+
+                       /* Check whether this is in fact the same instruction.
+                       * The instructions should never differ, except for the
+                       * Bcc.(BW) case. */
+                       if (table68k[code].mnemo != table68k[opcode].mnemo
+                       || table68k[code].size != table68k[opcode].size
+                       || table68k[code].suse != table68k[opcode].suse
+                       || table68k[code].duse != table68k[opcode].duse)
+                       {
+                               mismatch++; continue;
+                       }
+
+                       if (table68k[opcode].suse
+                       && (table68k[opcode].spos != table68k[code].spos
+                               || table68k[opcode].smode != table68k[code].smode
+                               || table68k[opcode].stype != table68k[code].stype))
+                       {
+                               mismatch++; continue;
+                       }
+
+                       if (table68k[opcode].duse
+                       && (table68k[opcode].dpos != table68k[code].dpos
+                               || table68k[opcode].dmode != table68k[code].dmode))
+                       {
+                               mismatch++; continue;
+                       }
+
+                       if (code != opcode)
+                       {
+                               table68k[code].handler = opcode;
+//printf("Relocate... ($%04X->$%04X)\n", (uint16_t)opcode, code);
+                       }
+               }
+       }
+}
+
+// What this really does is expand the # of handlers, which is why the
+// opcode has to be passed into the opcode handler...
+// E.g., $F620 maps into $F621-F627 as well; this code does this expansion.
+void do_merges(void)
+{
+       long int opcode;
+       int nr = 0;
+       mismatch = 0;
+
+       for(opcode=0; opcode<65536; opcode++)
+       {
+               if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG)
+                       continue;
+
+               nr++;
+               handle_merges(opcode);
+       }
+
+       nr_cpuop_funcs = nr;
+}
+
+int get_no_mismatches (void)
+{
+       return mismatch;
+}
diff --git a/src/m68000/readcpu.h b/src/m68000/readcpu.h
new file mode 100644 (file)
index 0000000..5fe0d49
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * readcpu.h - UAE CPU core
+ *
+ * This file is distributed under the GNU Public License, version 3 or at
+ * your option any later version. Read the file GPLv3 for details.
+ *
+ */
+
+#ifndef UAE_READCPU_H
+#define UAE_READCPU_H
+
+#include "sysdeps.h"
+
+
+ENUMDECL {
+  Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r,
+  absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg
+} ENUMNAME (amodes);
+
+ENUMDECL {
+    i_ILLG,
+
+    i_OR, i_AND, i_EOR, i_ORSR, i_ANDSR, i_EORSR,
+    i_SUB, i_SUBA, i_SUBX, i_SBCD,
+    i_ADD, i_ADDA, i_ADDX, i_ABCD,
+    i_NEG, i_NEGX, i_NBCD, i_CLR, i_NOT, i_TST,
+    i_BTST, i_BCHG, i_BCLR, i_BSET,
+    i_CMP, i_CMPM, i_CMPA,
+    i_MVPRM, i_MVPMR, i_MOVE, i_MOVEA, i_MVSR2, i_MV2SR,
+    i_SWAP, i_EXG, i_EXT, i_MVMEL, i_MVMLE,
+    i_TRAP, i_MVR2USP, i_MVUSP2R, i_RESET, i_NOP, i_STOP, i_RTE, i_RTD,
+    i_LINK, i_UNLK,
+    i_RTS, i_TRAPV, i_RTR,
+    i_JSR, i_JMP, i_BSR, i_Bcc,
+    i_LEA, i_PEA, i_DBcc, i_Scc,
+    i_DIVU, i_DIVS, i_MULU, i_MULS,
+    i_ASR, i_ASL, i_LSR, i_LSL, i_ROL, i_ROR, i_ROXL, i_ROXR,
+    i_ASRW, i_ASLW, i_LSRW, i_LSLW, i_ROLW, i_RORW, i_ROXLW, i_ROXRW,
+    i_CHK,i_CHK2,
+    i_MOVEC2, i_MOVE2C, i_CAS, i_CAS2, i_DIVL, i_MULL,
+    i_BFTST,i_BFEXTU,i_BFCHG,i_BFEXTS,i_BFCLR,i_BFFFO,i_BFSET,i_BFINS,
+    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,
+
+    MAX_OPCODE_FAMILY                          /* should always be last of the list */
+} ENUMNAME (instrmnem);
+
+extern const struct mnemolookup {
+    instrmnem mnemo;
+    const char *name;
+} lookuptab[];
+
+ENUMDECL {
+    sz_byte, sz_word, sz_long
+} ENUMNAME (wordsizes);
+
+ENUMDECL {
+    fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp,
+    fa_isbranch
+} ENUMNAME (flagaffect);
+
+ENUMDECL {
+    fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp
+} ENUMNAME (flaguse);
+
+ENUMDECL {
+    bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK,
+    bits, bitS, bitd, bitD, bitr, bitR, bitz, bitp, lastbit
+} ENUMNAME (bitvals);
+
+struct instr_def {
+    unsigned int bits;
+    int n_variable;
+    char bitpos[16];
+    unsigned int mask;
+    int cpulevel;
+    int plevel;
+    struct {
+       unsigned int flaguse:3;
+       unsigned int flagset:3;
+    } flaginfo[5];
+    unsigned char sduse;
+    const char *opcstr;
+};
+
+extern const struct instr_def defs68k[];
+extern int n_defs68k;
+
+extern struct instr {
+    long int handler;
+    unsigned char dreg;
+    unsigned char sreg;
+    signed char dpos;
+    signed char spos;
+    unsigned char sduse;
+    int flagdead:8, flaglive:8;
+    unsigned int mnemo:8;
+    unsigned int cc:4;
+    unsigned int plev:2;
+    unsigned int size:2;
+    unsigned int smode:5;
+    unsigned int stype:3;
+    unsigned int dmode:5;
+    unsigned int suse:1;
+    unsigned int duse:1;
+    unsigned int unused1:1;
+    unsigned int clev:3;
+    unsigned int isjmp:1;
+    unsigned int unused2:4;
+} *table68k;
+
+extern void read_table68k(void);
+extern void do_merges(void);
+extern int get_no_mismatches(void);
+extern int nr_cpuop_funcs;
+
+#endif /* ifndef UAE_READCPU_H */
diff --git a/src/m68000/sysdeps.h b/src/m68000/sysdeps.h
new file mode 100644 (file)
index 0000000..d927b8d
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * UAE - The Un*x Amiga Emulator - CPU core
+ *
+ * Try to include the right system headers and get other system-specific
+ * stuff right & other collected kludges.
+ *
+ * If you think about modifying this, think twice. Some systems rely on
+ * the exact order of the #include statements. That's also the reason
+ * why everything gets included unconditionally regardless of whether
+ * it's actually needed by the .c file.
+ *
+ * Copyright 1996, 1997 Bernd Schmidt
+ *
+ * Adaptation to Hatari by Thomas Huth
+ * Adaptation to Virtual Jagaur by James Hammons
+ *
+ * This file is distributed under the GNU Public License, version 3 or at
+ * your option any later version. Read the file GPLv3 for details.
+ *
+ */
+
+#ifndef UAE_SYSDEPS_H
+#define UAE_SYSDEPS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <limits.h>
+
+#ifndef __STDC__
+#error "Your compiler is not ANSI. Get a real one."
+#endif
+
+#include <stdarg.h>
+#include <stdint.h>
+
+
+#if EEXIST == ENOTEMPTY
+#define BROKEN_OS_PROBABLY_AIX
+#endif
+
+#ifdef __NeXT__
+#define S_IRUSR S_IREAD
+#define S_IWUSR S_IWRITE
+#define S_IXUSR S_IEXEC
+#define S_ISDIR(val) (S_IFDIR & val)
+struct utimbuf
+{
+    time_t actime;
+    time_t modtime;
+};
+#endif
+
+
+#if defined(WARPUP)
+#include "devices/timer.h"
+#include "osdep/posixemu.h"
+#define RETSIGTYPE
+#define USE_ZFILE
+#define strcasecmp stricmp
+#define memcpy q_memcpy
+#define memset q_memset
+#define strdup my_strdup
+#define random rand
+#define creat(x,y) open("T:creat",O_CREAT|O_RDWR|O_TRUNC,777)
+extern void * q_memset(void *, int, size_t);
+extern void * q_memcpy(void *, const void *, size_t);
+#endif
+
+
+/* Acorn specific stuff */
+#ifdef ACORN
+
+#define S_IRUSR S_IREAD
+#define S_IWUSR S_IWRITE
+#define S_IXUSR S_IEXEC
+
+#define strcasecmp stricmp
+
+#endif
+
+/* We can only rely on GNU C getting enums right. Mickeysoft VSC++ is known
+ * to have problems, and it's likely that other compilers choke too. */
+#ifdef __GNUC__
+#define ENUMDECL typedef enum
+#define ENUMNAME(name) name
+#else
+#define ENUMDECL enum
+#define ENUMNAME(name) ; typedef int name
+#endif
+
+/* When using GNU C, make abort more useful.  */
+#ifdef __GNUC__
+#define abort() \
+  do { \
+    fprintf(stderr, "Internal error; file %s, line %d\n", __FILE__, __LINE__); \
+    (abort) (); \
+} while (0)
+#endif
+
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifndef STATIC_INLINE
+#define STATIC_INLINE static __inline__
+#endif
+
+/*
+ * You can specify numbers from 0 to 5 here. It is possible that higher
+ * numbers will make the CPU emulation slightly faster, but if the setting
+ * is too high, you will run out of memory while compiling.
+ * Best to leave this as it is.
+ */
+#define CPU_EMU_SIZE 0
+
+#endif /* ifndef UAE_SYSDEPS_H */
diff --git a/src/m68000/table68k b/src/m68000/table68k
new file mode 100644 (file)
index 0000000..9cd456f
--- /dev/null
@@ -0,0 +1,260 @@
+% 0: bit 0
+% 1: bit 1
+% c: condition code
+% C: condition codes, except F
+% f: direction
+% i: immediate
+% 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)
+% s: source mode
+% S: source reg
+% d: dest mode
+% D: dest reg
+% r: reg
+% z: size
+%
+% Actually, a sssSSS may appear as a destination, and
+% vice versa. The only difference between sssSSS and
+% dddDDD are the valid addressing modes. There is
+% no match for immediate and pc-rel. addressing modes
+% in case of dddDDD.
+%
+% Arp: --> -(Ar)
+% ArP: --> (Ar)+
+% L: (xxx.L)
+%
+% Fields on a line: 
+% 16 chars bitpattern : 
+% CPU level / privildge level :
+%   CPU level 0: 68000
+%             1: 68010
+%             2: 68020
+%   privilege level 0: not privileged
+%                   1: unprivileged only on 68000 (check regs.s)
+%                   2: privileged                 (check regs.s)
+%                   3: privileged if size == word (check regs.s)
+% Flags set by instruction: XNZVC :
+% Flags used by instruction: XNZVC :
+%   - means flag unaffected / unused
+%   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
+% srcaddr status destaddr status :
+%   bitmasks of
+%   1 means fetched
+%   2 means stored
+%   4 means jump offset
+%   8 means jump address
+% 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 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 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]
+
+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:20:-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:20:?????:?????: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
+
+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
+
+% 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
+
+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
+
+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]
+
+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
+
+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 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]
+
+% 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 0101 iiii iSSS:40:?????:?????:11: MMUOP    #i,s
+
+% 68040 instructions
+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
+% 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]
index 4bfe955990bc4e26bdd1524462216b369a90b01d..4d161213b2b64aaa55364aff36324fdc76c0893b 100644 (file)
@@ -120,10 +120,14 @@ int irq_ack_handler(int);
 /* If on, CPU will call the instruction hook callback before every
  * instruction.
  */
+#if 0
 void M68KInstructionHook(void);
 #define M68K_INSTRUCTION_HOOK       OPT_SPECIFY_HANDLER
 #define M68K_INSTRUCTION_CALLBACK() M68KInstructionHook()
-
+#else
+#define M68K_INSTRUCTION_HOOK       OPT_OFF
+#define M68K_INSTRUCTION_CALLBACK() M68KInstructionHook()
+#endif
 
 /* If on, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
 #define M68K_EMULATE_PREFETCH       OPT_OFF
index dfc9c7d49bf613d0fdba87dafb6eb00f67de917e..aa65a916f527293fe9ba06bcd9b63e755eb6085a 100644 (file)
@@ -15,7 +15,8 @@
 TARGET     = virtualjaguar
 CONFIG    += qt warn_on release debug
 RESOURCES += virtualjaguar.qrc
-LIBS      += -lz -Lobj -ljaguarcore -lmusashi
+#LIBS      += -lz -Lobj -ljaguarcore -lmusashi
+LIBS      += -lz -Lobj -ljaguarcore -lm68k
 QT        += opengl
 
 # We stuff all the intermediate crap into obj/ so it won't confuse us mere mortals ;-)
@@ -47,7 +48,8 @@ INCLUDEPATH += \
 
 DEPENDPATH = \
        src \
-       src/gui
+       src/gui \
+       src/m68000
 
 # The GUI