]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Initial CPU tester commit.
authorToni Wilen <twilen@winuae.net>
Wed, 7 Aug 2019 17:41:04 +0000 (20:41 +0300)
committerToni Wilen <twilen@winuae.net>
Wed, 7 Aug 2019 17:41:04 +0000 (20:41 +0300)
33 files changed:
.gitignore
assem.cpp [new file with mode: 0644]
cputest.cpp [new file with mode: 0644]
cputest/68kDisass.c [new file with mode: 0644]
cputest/68kDisass.h [new file with mode: 0644]
cputest/amiga.S [new file with mode: 0644]
cputest/asm.S [new file with mode: 0644]
cputest/cputest_defines.h [new file with mode: 0644]
cputest/cputestgen.ini [new file with mode: 0644]
cputest/main.c [new file with mode: 0644]
cputest/makefile [new file with mode: 0644]
cputest/msc_dirent.h [new file with mode: 0644]
cputest_support.cpp [new file with mode: 0644]
disasm.cpp [new file with mode: 0644]
fpp.cpp
gencpu.cpp
include/cputest.h [new file with mode: 0644]
include/disasm.h [new file with mode: 0644]
include/memory.h
include/newcpu.h
include/readcpu.h
ini.cpp
newcpu.cpp
newcpu_common.cpp
od-win32/cputester/cputester.vcxproj [new file with mode: 0644]
od-win32/cputester/cputester.vcxproj.filters [new file with mode: 0644]
od-win32/cputester_m68k/cputester_m68k.vcxproj [new file with mode: 0644]
od-win32/cputester_m68k/cputester_m68k.vcxproj.filters [new file with mode: 0644]
od-win32/winuae_msvc15/winuae_msvc.sln
od-win32/winuae_msvc15/winuae_msvc.vcxproj
od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters
readcpu.cpp
softfloat/softfloat_decimal.cpp

index 44d2b2118d513747ab2e014c2036242b8f6448ef..c421091659b1d8bad0d4d636fa9c30bba8d41aa2 100644 (file)
@@ -11,7 +11,6 @@
 *.idb
 *.res
 *.pch
-*.ini
 release
 debug
 bin
@@ -63,10 +62,13 @@ aros.rom.cpp
 /cpuemu_40.cpp
 /cpuemu_50.cpp
 /cpustbl.cpp
+/cpustbl_test.cpp
 /cputbl.h
+/cputbl_test.h
 /jit/compemu.cpp
 /jit/compstbl.cpp
 /jit/comptbl.h
+/cputest/data
 /linetoscr.cpp
 *.iobj
 *.ipdb
@@ -76,3 +78,4 @@ packages.config
 *.sqlite
 *.db-shm
 *.db-wal
+*.o
diff --git a/assem.cpp b/assem.cpp
new file mode 100644 (file)
index 0000000..a5f4377
--- /dev/null
+++ b/assem.cpp
@@ -0,0 +1,439 @@
+
+static const TCHAR *fpsizes[] = {
+       _T("L"),
+       _T("S"),
+       _T("X"),
+       _T("P"),
+       _T("W"),
+       _T("D"),
+       _T("B"),
+       _T("P")
+};
+static const int fpsizeconv[] = {
+       sz_long,
+       sz_single,
+       sz_extended,
+       sz_packed,
+       sz_word,
+       sz_double,
+       sz_byte,
+       sz_packed
+};
+static const int datasizes[] = {
+       1,
+       2,
+       4,
+       4,
+       8,
+       12,
+       12
+};
+
+static void showea_val(TCHAR *buffer, uae_u16 opcode, uaecptr addr, int size)
+{
+       struct mnemolookup *lookup;
+       instr *table = &table68k[opcode];
+
+       if (addr >= 0xe90000 && addr < 0xf00000)
+               goto skip;
+       if (addr >= 0xdff000 && addr < 0xe00000)
+               goto skip;
+
+       for (lookup = lookuptab; lookup->mnemo != table->mnemo; lookup++)
+               ;
+       if (!(lookup->flags & 1))
+               goto skip;
+       buffer += _tcslen(buffer);
+       if (debug_safe_addr(addr, datasizes[size])) {
+               bool cached = false;
+               switch (size)
+               {
+                       case sz_byte:
+                       {
+                               uae_u8 v = get_byte_cache_debug(addr, &cached);
+                               uae_u8 v2 = v;
+                               if (cached)
+                                       v2 = get_byte_debug(addr);
+                               if (v != v2) {
+                                       _stprintf(buffer, _T(" [%02x:%02x]"), v, v2);
+                               } else {
+                                       _stprintf(buffer, _T(" [%s%02x]"), cached ? _T("*") : _T(""), v);
+                               }
+                       }
+                       break;
+                       case sz_word:
+                       {
+                               uae_u16 v = get_word_cache_debug(addr, &cached);
+                               uae_u16 v2 = v;
+                               if (cached)
+                                       v2 = get_word_debug(addr);
+                               if (v != v2) {
+                                       _stprintf(buffer, _T(" [%04x:%04x]"), v, v2);
+                               } else {
+                                       _stprintf(buffer, _T(" [%s%04x]"), cached ? _T("*") : _T(""), v);
+                               }
+                       }
+                       break;
+                       case sz_long:
+                       {
+                               uae_u32 v = get_long_cache_debug(addr, &cached);
+                               uae_u32 v2 = v;
+                               if (cached)
+                                       v2 = get_long_debug(addr);
+                               if (v != v2) {
+                                       _stprintf(buffer, _T(" [%08x:%08x]"), v, v2);
+                               } else {
+                                       _stprintf(buffer, _T(" [%s%08x]"), cached ? _T("*") : _T(""), v);
+                               }
+                       }
+                       break;
+                       case sz_single:
+                       {
+                               fpdata fp;
+                               fpp_to_single(&fp, get_long_debug(addr));
+                               _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
+                       }
+                       break;
+                       case sz_double:
+                       {
+                               fpdata fp;
+                               fpp_to_double(&fp, get_long_debug(addr), get_long_debug(addr + 4));
+                               _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
+                       }
+                       break;
+                       case sz_extended:
+                       {
+                               fpdata fp;
+                               fpp_to_exten(&fp, get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8));
+                               _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
+                               break;
+                       }
+                       case sz_packed:
+                               _stprintf(buffer, _T("[%08x%08x%08x]"), get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8));
+                               break;
+               }
+       }
+skip:
+       for (int i = 0; i < size; i++) {
+               TCHAR name[256];
+               if (debugmem_get_symbol(addr + i, name, sizeof(name) / sizeof(TCHAR))) {
+                       _stprintf(buffer + _tcslen(buffer), _T(" %s"), name);
+               }
+       }
+}
+
+static uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name)
+{
+       uaecptr addr;
+       uae_u16 dp;
+       int r;
+       uae_u32 dispreg;
+       uaecptr pc = *pcp;
+       TCHAR mult[20];
+
+       dp = get_iword_debug(pc);
+       pc += 2;
+
+       r = (dp & 0x7000) >> 12; // REGISTER
+
+       dispreg = dp & 0x8000 ? m68k_areg(regs, r) : m68k_dreg(regs, r);
+       if (!(dp & 0x800)) { // W/L
+               dispreg = (uae_s32)(uae_s16)(dispreg);
+       }
+
+       if (currprefs.cpu_model >= 68020) {
+               dispreg <<= (dp >> 9) & 3; // SCALE
+       }
+
+       int m = 1 << ((dp >> 9) & 3);
+       mult[0] = 0;
+       if (m > 1) {
+               _stprintf(mult, _T("*%d"), m);
+       }
+
+       buffer[0] = 0;
+       if ((dp & 0x100) && currprefs.cpu_model >= 68020) {
+               TCHAR dr[20];
+               // Full format extension (68020+)
+               uae_s32 outer = 0, disp = 0;
+               if (dp & 0x80) { // BS (base register suppress)
+                       base = 0;
+                       name = NULL;
+               }
+               _stprintf(dr, _T("%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W');
+               if (dp & 0x40) { // IS (index suppress)
+                       dispreg = 0;
+                       dr[0] = 0;
+               }
+
+               _tcscpy(buffer, _T("("));
+               TCHAR *p = buffer + _tcslen(buffer);
+
+               if (dp & 3) {
+                       // indirect
+                       _stprintf(p, _T("["));
+                       p += _tcslen(p);
+               } else {
+                       // (an,dn,word/long)
+                       if (name) {
+                               _stprintf(p, _T("%s,"), name);
+                               p += _tcslen(p);
+                       }
+                       if (dr[0]) {
+                               _stprintf(p, _T("%s%s,"), dr, mult);
+                               p += _tcslen(p);
+                       }
+               }
+
+               if ((dp & 0x30) == 0x20) { // BD SIZE = 2 (WORD)
+                       disp = (uae_s32)(uae_s16)get_iword_debug(pc);
+                       _stprintf(p, _T("$%04x,"), (uae_s16)disp);
+                       p += _tcslen(p);
+                       pc += 2;
+                       base += disp;
+               } else if ((dp & 0x30) == 0x30) { // BD SIZE = 3 (LONG)
+                       disp = get_ilong_debug(pc);
+                       _stprintf(p, _T("$%08x,"), disp);
+                       p += _tcslen(p);
+                       pc += 4;
+                       base += disp;
+               }
+
+               if (dp & 3) {
+                       if (name) {
+                               _stprintf(p, _T("%s,"), name);
+                               p += _tcslen(p);
+                       }
+
+                       if (!(dp & 0x04)) {
+                               if (dr[0]) {
+                                       _stprintf(p, _T("%s%s,"), dr, mult);
+                                       p += _tcslen(p);
+                               }
+                       }
+
+                       if (p[-1] == ',')
+                               p--;
+                       _stprintf(p, _T("],"));
+                       p += _tcslen(p);
+
+                       if ((dp & 0x04)) {
+                               if (dr[0]) {
+                                       _stprintf(p, _T("%s%s,"), dr, mult);
+                                       p += _tcslen(p);
+                               }
+                       }
+
+               }
+
+               if ((dp & 0x03) == 0x02) {
+                       outer = (uae_s32)(uae_s16)get_iword_debug(pc);
+                       _stprintf(p, _T("$%04x,"), (uae_s16)outer);
+                       p += _tcslen(p);
+                       pc += 2;
+               } else  if ((dp & 0x03) == 0x03) {
+                       outer = get_ilong_debug(pc);
+                       _stprintf(p, _T("$%08x,"), outer);
+                       p += _tcslen(p);
+                       pc += 4;
+               }
+
+               if (p[-1] == ',')
+                       p--;
+               _stprintf(p, _T(")"));
+               p += _tcslen(p);
+
+               if ((dp & 0x4) == 0)
+                       base += dispreg;
+               if (dp & 0x3)
+                       base = get_long_debug(base);
+               if (dp & 0x4)
+                       base += dispreg;
+
+               addr = base + outer;
+
+               _stprintf(p, _T(" == $%08x"), addr);
+               p += _tcslen(p);
+
+       } else {
+               // Brief format extension
+               TCHAR regstr[20];
+               uae_s8 disp8 = dp & 0xFF;
+
+               regstr[0] = 0;
+               _stprintf(regstr, _T(",%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W');
+               addr = base + (uae_s32)((uae_s8)disp8) + dispreg;
+               _stprintf(buffer, _T("(%s%s%s,$%02x) == $%08x"), name, regstr, mult, disp8, addr);
+               if (dp & 0x100) {
+                       _tcscat(buffer, _T(" (68020+)"));
+               }
+       }
+
+       *pcp = pc;
+       return addr;
+}
+
+uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
+{
+       uaecptr addr = pc;
+       uae_s16 disp16;
+       uae_s32 offset = 0;
+       TCHAR buffer[80];
+
+       switch (mode){
+       case Dreg:
+               _stprintf (buffer, _T("D%d"), reg);
+               break;
+       case Areg:
+               _stprintf (buffer, _T("A%d"), reg);
+               break;
+       case Aind:
+               _stprintf (buffer, _T("(A%d)"), reg);
+               addr = regs.regs[reg + 8];
+               showea_val(buffer, opcode, addr, size);
+               break;
+       case Aipi:
+               _stprintf (buffer, _T("(A%d)+"), reg);
+               addr = regs.regs[reg + 8];
+               showea_val(buffer, opcode, addr, size);
+               break;
+       case Apdi:
+               _stprintf (buffer, _T("-(A%d)"), reg);
+               addr = regs.regs[reg + 8];
+               showea_val(buffer, opcode, addr - datasizes[size], size);
+               break;
+       case Ad16:
+               {
+                       TCHAR offtxt[8];
+                       disp16 = get_iword_debug (pc); pc += 2;
+                       if (disp16 < 0)
+                               _stprintf (offtxt, _T("-$%04x"), -disp16);
+                       else
+                               _stprintf (offtxt, _T("$%04x"), disp16);
+                       addr = m68k_areg (regs, reg) + disp16;
+                       _stprintf (buffer, _T("(A%d,%s) == $%08x"), reg, offtxt, addr);
+                       showea_val(buffer, opcode, addr, size);
+               }
+               break;
+       case Ad8r:
+               {
+                       TCHAR name[10];
+                       _stprintf(name, _T("A%d"), reg);
+                       addr = ShowEA_disp(&pc, m68k_areg(regs, reg), buffer, name);
+                       showea_val(buffer, opcode, addr, size);
+               }
+               break;
+       case PC16:
+               disp16 = get_iword_debug (pc); pc += 2;
+               addr += (uae_s16)disp16;
+               _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr);
+               showea_val(buffer, opcode, addr, size);
+               break;
+       case PC8r:
+               {
+                       addr = ShowEA_disp(&pc, addr, buffer, _T("PC"));
+                       showea_val(buffer, opcode, addr, size);
+               }
+               break;
+       case absw:
+               addr = (uae_s32)(uae_s16)get_iword_debug (pc);
+               _stprintf (buffer, _T("$%04x"), (uae_u16)addr);
+               pc += 2;
+               showea_val(buffer, opcode, addr, size);
+               break;
+       case absl:
+               addr = get_ilong_debug (pc);
+               _stprintf (buffer, _T("$%08x"), addr);
+               pc += 4;
+               showea_val(buffer, opcode, addr, size);
+               break;
+       case imm:
+               switch (size){
+               case sz_byte:
+                       _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff));
+                       pc += 2;
+                       break;
+               case sz_word:
+                       _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff));
+                       pc += 2;
+                       break;
+               case sz_long:
+                       _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc)));
+                       pc += 4;
+                       break;
+               case sz_single:
+                       {
+                               fpdata fp;
+                               fpp_to_single(&fp, get_ilong_debug(pc));
+                               _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
+                               pc += 4;
+                       }
+                       break;
+               case sz_double:
+                       {
+                               fpdata fp;
+                               fpp_to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
+                               _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
+                               pc += 8;
+                       }
+                       break;
+               case sz_extended:
+               {
+                       fpdata fp;
+                       fpp_to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
+                       _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
+                       pc += 12;
+                       break;
+               }
+               case sz_packed:
+                       _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
+                       pc += 12;
+                       break;
+               default:
+                       break;
+               }
+               break;
+       case imm0:
+               offset = (uae_s32)(uae_s8)get_iword_debug (pc);
+               _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff));
+               addr = pc + 2 + offset;
+               if ((opcode & 0xf000) == 0x6000) {
+                       showea_val(buffer, opcode, addr, 1);
+               }
+               pc += 2;
+               break;
+       case imm1:
+               offset = (uae_s32)(uae_s16)get_iword_debug (pc);
+               buffer[0] = 0;
+               _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff));
+               addr = pc + offset;
+               if ((opcode & 0xf000) == 0x6000) {
+                       showea_val(buffer, opcode, addr, 2);
+               }
+               pc += 2;
+               break;
+       case imm2:
+               offset = (uae_s32)get_ilong_debug (pc);
+               _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
+               addr = pc + offset;
+               if ((opcode & 0xf000) == 0x6000) {
+                       showea_val(buffer, opcode, addr, 4);
+               }
+               pc += 4;
+               break;
+       case immi:
+               offset = (uae_s32)(uae_s8)(reg & 0xff);
+               _stprintf (buffer, _T("#$%02x"), (uae_u8)offset);
+               addr = pc + offset;
+               break;
+       default:
+               break;
+       }
+       if (buf == NULL)
+               f_out (f, _T("%s"), buffer);
+       else
+               _tcscat (buf, buffer);
+       if (eaddr)
+               *eaddr = addr;
+       return pc;
+}
diff --git a/cputest.cpp b/cputest.cpp
new file mode 100644 (file)
index 0000000..1f5149f
--- /dev/null
@@ -0,0 +1,2556 @@
+
+#include "cputest.h"
+#include "cputbl_test.h"
+#include "readcpu.h"
+#include "disasm.h"
+#include "ini.h"
+
+#include "options.h"
+
+#define MAX_REGISTERS 16
+
+static uae_u32 registers[] =
+{
+       0x00000010,
+       0x00000000,
+       0xffffffff,
+       0xffffff00,
+       0xffff0000,
+       0x80008080,
+       0x7fff7fff,
+       0xaaaaaaaa,
+
+       0x00000000,
+       0x00000080,
+       0x00008000,
+       0x00007fff,
+       0xfffffffe,
+       0xffffff00,
+       0x00000000, // replaced with opcode memory
+       0x00000000  // replaced with stack
+};
+
+// TODO: fill FPU registers
+static floatx80 fpuregisters[8];
+static uae_u32 fpu_fpiar, fpu_fpcr, fpu_fpsr;
+
+const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };
+const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
+
+int movem_index1[256];
+int movem_index2[256];
+int movem_next[256];
+cpuop_func *cpufunctbl[65536];
+struct cputbl_data
+{
+       uae_s16 length;
+       uae_s8 disp020[2];
+       uae_u8 branch;
+};
+static struct cputbl_data cpudatatbl[65536];
+
+struct regstruct regs;
+struct flag_struct regflags;
+
+static int verbose = 1;
+static int feature_exception3_data = 0;
+static int feature_exception3_instruction = 0;
+static int feature_sr_mask = 0;
+static int feature_full_extension_format = 0;
+static uae_u32 feature_addressing_modes[2];
+static int ad8r[2], pc8r[2];
+
+#define LOW_MEMORY_END 0x8000
+#define HIGH_MEMORY_START (0x01000000 - 0x8000)
+
+// large enough for RTD
+#define STACK_SIZE (0x8000 + 8)
+#define RESERVED_SUPERSTACK 1024
+
+static uae_u32 test_low_memory_start;
+static uae_u32 test_low_memory_end;
+static uae_u32 test_high_memory_start;
+static uae_u32 test_high_memory_end;
+
+static uae_u8 low_memory[32768], high_memory[32768], *test_memory;
+static uae_u8 low_memory_temp[32768], high_memory_temp[32768], *test_memory_temp;
+static uae_u8 dummy_memory[4];
+static uaecptr test_memory_start, test_memory_end, opcode_memory_start;
+static uae_u32 test_memory_size;
+static int hmem_rom, lmem_rom;
+static uae_u8 *opcode_memory;
+static uae_u8 *storage_buffer;
+static char inst_name[16+1];
+static int storage_buffer_watermark;
+static int max_storage_buffer = 1000000;
+
+static bool out_of_test_space;
+static uaecptr out_of_test_space_addr;
+static int test_exception;
+static int forced_immediate_mode;
+static uaecptr test_exception_addr;
+static int test_exception_3_inst;
+static uae_u8 imm8_cnt;
+static uae_u16 imm16_cnt;
+static uae_u32 imm32_cnt;
+static uae_u32 addressing_mask;
+static int opcodecnt;
+static int cpu_stopped;
+static int cpu_lvl = 0;
+static int test_count;
+static int testing_active;
+static time_t starttime;
+static int filecount;
+static uae_u16 sr_undefined_mask;
+
+struct uae_prefs currprefs;
+
+struct accesshistory
+{
+       uaecptr addr;
+       uae_u32 val;
+       uae_u32 oldval;
+       int size;
+};
+static int ahcnt, ahcnt2;
+static int noaccesshistory = 0;
+
+#define MAX_ACCESSHIST 32
+static struct accesshistory ahist[MAX_ACCESSHIST];
+static struct accesshistory ahist2[MAX_ACCESSHIST];
+
+#define OPCODE_AREA 32
+
+static bool valid_address(uaecptr addr, int size, int w)
+{
+       addr &= addressing_mask;
+       size--;
+       if (addr + size < LOW_MEMORY_END) {
+               if (addr < test_low_memory_start)
+                       goto oob;
+               // exception vectors needed during tests
+               if ((addr + size >= 0x0c && addr < 0x30 || (addr + size >= 0x80 && addr < 0xc0)) && regs.vbr == 0)
+                       goto oob;
+               if (addr + size >= test_low_memory_end)
+                       goto oob;
+               if (w && lmem_rom)
+                       goto oob;
+               return 1;
+       }
+       if (addr >= HIGH_MEMORY_START && addr < HIGH_MEMORY_START + 0x8000) {
+               if (addr < test_high_memory_start)
+                       goto oob;
+               if (addr + size >= test_high_memory_end)
+                       goto oob;
+               if (w && hmem_rom)
+                       goto oob;
+               return 1;
+       }
+       if (addr >= test_memory_start && addr + size < test_memory_end - RESERVED_SUPERSTACK) {
+               // make sure we don't modify our test instruction
+               if (testing_active && w) {
+                       if (addr >= opcode_memory_start && addr + size < opcode_memory_start + OPCODE_AREA)
+                               goto oob;
+               }
+               return 1;
+       }
+oob:
+       return 0;
+}
+
+static uae_u8 *get_addr(uaecptr addr, int size, int w)
+{
+       // allow debug output to read memory even if oob condition
+       if (w >= 0 && out_of_test_space)
+               goto oob;
+       if (!valid_address(addr, 1, w))
+               goto oob;
+       if (size > 1) {
+               if (!valid_address(addr + size - 1, 1, w))
+                       goto oob;
+       }
+       addr &= addressing_mask;
+       size--;
+       if (addr + size < LOW_MEMORY_END) {
+               return low_memory + addr;
+       } else if (addr >= HIGH_MEMORY_START && addr < HIGH_MEMORY_START + 0x8000) {
+               return high_memory + (addr - HIGH_MEMORY_START);
+       } else if (addr >= test_memory_start && addr + size < test_memory_end - RESERVED_SUPERSTACK) {
+               return test_memory + (addr - test_memory_start);
+       }
+oob:
+       if (w >= 0) {
+               if (!out_of_test_space) {
+                       out_of_test_space = true;
+                       out_of_test_space_addr = addr;
+               }
+       }
+       dummy_memory[0] = 0;
+       dummy_memory[1] = 0;
+       dummy_memory[2] = 0;
+       dummy_memory[3] = 0;
+       return dummy_memory;
+}
+
+uae_u32 REGPARAM2 op_illg_1(uae_u32 opcode)
+{
+       if ((opcode & 0xf000) == 0xf000)
+               test_exception = 11;
+       else if ((opcode & 0xf000) == 0xa000)
+               test_exception = 10;
+       else
+               test_exception = 4;
+       return 0;
+}
+uae_u32 REGPARAM2 op_unimpl_1(uae_u32 opcode)
+{
+       return 0;
+}
+void REGPARAM2 op_unimpl(uae_u32 opcode)
+{
+       op_unimpl_1(opcode);
+}
+uae_u32 REGPARAM2 op_illg(uae_u32 opcode)
+{
+       return op_illg_1(opcode);
+}
+
+uae_u16 get_word_test_prefetch(int o)
+{
+       // no real prefetch
+       if (cpu_lvl < 2)
+               o -= 2;
+       regs.irc = get_word_test(m68k_getpci() + o + 2);
+       return get_word_test(m68k_getpci() + o);
+}
+
+// Move from SR does two writes to same address:
+// ignore the first one
+static void previoussame(uaecptr addr, int size)
+{
+       if (!ahcnt)
+               return;
+       struct accesshistory *ah = &ahist[ahcnt - 1];
+       if (ah->addr == addr && ah->size == size) {
+               ahcnt--;
+       }
+}
+
+void put_byte_test(uaecptr addr, uae_u32 v)
+{
+       uae_u8 *p = get_addr(addr, 1, 1);
+       if (!out_of_test_space && !noaccesshistory) {
+               previoussame(addr, sz_byte);
+               if (ahcnt >= MAX_ACCESSHIST) {
+                       wprintf(_T("ahist overflow!"));
+                       abort();
+               }
+               struct accesshistory *ah = &ahist[ahcnt++];
+               ah->addr = addr;
+               ah->val = v & 0xff;
+               ah->oldval = *p;
+               ah->size = sz_byte;
+       }
+       *p = v;
+}
+void put_word_test(uaecptr addr, uae_u32 v)
+{
+       if (addr & 1) {
+               put_byte_test(addr + 0, v >> 8);
+               put_byte_test(addr + 1, v >> 0);
+       } else {
+               uae_u8 *p = get_addr(addr, 2, 1);
+               if (!out_of_test_space && !noaccesshistory) {
+                       previoussame(addr, sz_word);
+                       if (ahcnt >= MAX_ACCESSHIST) {
+                               wprintf(_T("ahist overflow!"));
+                               abort();
+                       }
+                       struct accesshistory *ah = &ahist[ahcnt++];
+                       ah->addr = addr;
+                       ah->val = v & 0xffff;
+                       ah->oldval = (p[0] << 8) | p[1];
+                       ah->size = sz_word;
+               }
+               p[0] = v >> 8;
+               p[1] = v & 0xff;
+       }
+}
+void put_long_test(uaecptr addr, uae_u32 v)
+{
+       if (addr & 1) {
+               put_byte_test(addr + 0, v >> 24);
+               put_word_test(addr + 1, v >> 8);
+               put_byte_test(addr + 3, v >> 0);
+       } else if (addr & 2) {
+               put_word_test(addr + 0, v >> 16);
+               put_word_test(addr + 2, v >> 0);
+       } else {
+               uae_u8 *p = get_addr(addr, 4, 1);
+               if (!out_of_test_space && !noaccesshistory) {
+                       previoussame(addr, sz_long);
+                       if (ahcnt >= MAX_ACCESSHIST) {
+                               wprintf(_T("ahist overflow!"));
+                               abort();
+                       }
+                       struct accesshistory *ah = &ahist[ahcnt++];
+                       ah->addr = addr;
+                       ah->val = v;
+                       ah->oldval = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+                       ah->size = sz_long;
+               }
+               p[0] = v >> 24;
+               p[1] = v >> 16;
+               p[2] = v >> 8;
+               p[3] = v >> 0;
+       }
+}
+
+
+static void undo_memory(struct accesshistory *ahp, int  *cntp)
+{
+       out_of_test_space = 0;
+       int cnt = *cntp;
+       noaccesshistory = 1;
+       for (int i = cnt - 1; i >= 0; i--) {
+               struct accesshistory *ah = &ahp[i];
+               switch (ah->size)
+               {
+               case sz_byte:
+                       put_byte_test(ah->addr, ah->oldval);
+                       break;
+               case sz_word:
+                       put_word_test(ah->addr, ah->oldval);
+                       break;
+               case sz_long:
+                       put_long_test(ah->addr, ah->oldval);
+                       break;
+               }
+       }
+       noaccesshistory = 0;
+       if (out_of_test_space) {
+               wprintf(_T("undo_memory out of test space fault!?\n"));
+               abort();
+       }
+}
+
+
+uae_u32 get_byte_test(uaecptr addr)
+{
+       uae_u8 *p = get_addr(addr, 1, 0);
+       return *p;
+}
+uae_u32 get_word_test(uaecptr addr)
+{
+       if (addr & 1) {
+               return (get_byte_test(addr + 0) << 8) | (get_byte_test(addr + 1) << 0);
+       } else {
+               uae_u8 *p = get_addr(addr, 2, 0);
+               return (p[0] << 8) | (p[1]);
+       }
+}
+uae_u32 get_long_test(uaecptr addr)
+{
+       if (addr & 1) {
+               uae_u8 v0 = get_byte_test(addr + 0);
+               uae_u16 v1 = get_word_test(addr + 1);
+               uae_u8 v3 = get_byte_test(addr + 3);
+               return (v0 << 24) | (v1 << 8) | (v3 << 0);
+       } else if (addr & 2) {
+               uae_u16 v0 = get_word_test(addr + 0);
+               uae_u16 v1 = get_word_test(addr + 2);
+               return (v0 << 16) | (v1 << 0);
+       } else {
+               uae_u8 *p = get_addr(addr, 4, 0);
+               return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
+       }
+}
+
+uae_u32 get_byte_debug(uaecptr addr)
+{
+       uae_u8 *p = get_addr(addr, 1, -1);
+       return *p;
+}
+uae_u32 get_word_debug(uaecptr addr)
+{
+       uae_u8 *p = get_addr(addr, 2, -1);
+       return (p[0] << 8) | (p[1]);
+}
+uae_u32 get_long_debug(uaecptr addr)
+{
+       uae_u8 *p = get_addr(addr, 4, -1);
+       return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
+}
+uae_u32 get_iword_debug(uaecptr addr)
+{
+       return get_word_debug(addr);
+}
+uae_u32 get_ilong_debug(uaecptr addr)
+{
+       return get_long_debug(addr);
+}
+
+uae_u32 get_byte_cache_debug(uaecptr addr, bool *cached)
+{
+       *cached = false;
+       return get_byte_test(addr);
+}
+uae_u32 get_word_cache_debug(uaecptr addr, bool *cached)
+{
+       *cached = false;
+       return get_word_test(addr);
+}
+uae_u32 get_long_cache_debug(uaecptr addr, bool *cached)
+{
+       *cached = false;
+       return get_long_test(addr);
+}
+
+uae_u32 sfc_nommu_get_byte(uaecptr addr)
+{
+       return get_byte_test(addr);
+}
+uae_u32 sfc_nommu_get_word(uaecptr addr)
+{
+       return get_word_test(addr);
+}
+uae_u32 sfc_nommu_get_long(uaecptr addr)
+{
+       return get_long_test(addr);
+}
+
+uae_u32 memory_get_byte(uaecptr addr)
+{
+       return get_byte_test(addr);
+}
+uae_u32 memory_get_word(uaecptr addr)
+{
+       return get_word_test(addr);
+}
+uae_u32 memory_get_wordi(uaecptr addr)
+{
+       return get_word_test(addr);
+}
+uae_u32 memory_get_long(uaecptr addr)
+{
+       return get_long_test(addr);
+}
+uae_u32 memory_get_longi(uaecptr addr)
+{
+       return get_long_test(addr);
+}
+
+void memory_put_long(uaecptr addr, uae_u32 v)
+{
+       put_long_test(addr, v);
+}
+void memory_put_word(uaecptr addr, uae_u32 v)
+{
+       put_word_test(addr, v);
+}
+void memory_put_byte(uaecptr addr, uae_u32 v)
+{
+       put_byte_test(addr, v);
+}
+
+uae_u8 *memory_get_real_address(uaecptr addr)
+{
+       return NULL;
+}
+
+uae_u32 next_iword_test(void)
+{
+       uae_u32 v = get_word_test_prefetch(0);
+       regs.pc += 2;
+       return v;
+}
+
+uae_u32 next_ilong_test(void)
+{
+       uae_u32 v = get_word_test_prefetch(0) << 16;
+       v |= get_word_test_prefetch(2);
+       regs.pc += 4;
+       return v;
+}
+
+uae_u32(*x_get_long)(uaecptr);
+uae_u32(*x_get_word)(uaecptr);
+void (*x_put_long)(uaecptr, uae_u32);
+void (*x_put_word)(uaecptr, uae_u32);
+
+uae_u32(*x_cp_get_long)(uaecptr);
+uae_u32(*x_cp_get_word)(uaecptr);
+uae_u32(*x_cp_get_byte)(uaecptr);
+void (*x_cp_put_long)(uaecptr, uae_u32);
+void (*x_cp_put_word)(uaecptr, uae_u32);
+void (*x_cp_put_byte)(uaecptr, uae_u32);
+uae_u32(*x_cp_next_iword)(void);
+uae_u32(*x_cp_next_ilong)(void);
+
+uae_u32(*x_next_iword)(void);
+uae_u32(*x_next_ilong)(void);
+void (*x_do_cycles)(unsigned long);
+
+uae_u32(REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
+
+static int SPCFLAG_TRACE, SPCFLAG_DOTRACE;
+
+uae_u32 get_disp_ea_test(uae_u32 base, uae_u32 dp)
+{
+       int reg = (dp >> 12) & 15;
+       uae_s32 regd = regs.regs[reg];
+       if ((dp & 0x800) == 0)
+               regd = (uae_s32)(uae_s16)regd;
+       return base + (uae_s8)dp + regd;
+}
+
+static void activate_trace(void)
+{
+       SPCFLAG_TRACE = 0;
+       SPCFLAG_DOTRACE = 1;
+}
+
+static void do_trace(void)
+{
+       if (regs.t0 && currprefs.cpu_model >= 68020) {
+               // this is obsolete
+               return;
+       }
+       if (regs.t1) {
+               activate_trace();
+       }
+}
+
+void REGPARAM2 MakeSR(void)
+{
+       regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
+               | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
+               | (GET_XFLG() << 4) | (GET_NFLG() << 3)
+               | (GET_ZFLG() << 2) | (GET_VFLG() << 1)
+               | GET_CFLG());
+}
+void MakeFromSR_x(int t0trace)
+{
+       int oldm = regs.m;
+       int olds = regs.s;
+       int oldt0 = regs.t0;
+       int oldt1 = regs.t1;
+
+       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 (regs.t1 == ((regs.sr >> 15) & 1) &&
+               regs.t0 == ((regs.sr >> 14) & 1) &&
+               regs.s == ((regs.sr >> 13) & 1) &&
+               regs.m == ((regs.sr >> 12) & 1) &&
+               regs.intmask == ((regs.sr >> 8) & 7))
+               return;
+
+       regs.t1 = (regs.sr >> 15) & 1;
+       regs.t0 = (regs.sr >> 14) & 1;
+       regs.s = (regs.sr >> 13) & 1;
+       regs.m = (regs.sr >> 12) & 1;
+       regs.intmask = (regs.sr >> 8) & 7;
+
+       if (currprefs.cpu_model >= 68020) {
+               /* 68060 does not have MSP but does have M-bit.. */
+               if (currprefs.cpu_model >= 68060)
+                       regs.msp = regs.isp;
+               if (olds != regs.s) {
+                       if (olds) {
+                               if (oldm)
+                                       regs.msp = m68k_areg (regs, 7);
+                               else
+                                       regs.isp = m68k_areg (regs, 7);
+                               m68k_areg (regs, 7) = regs.usp;
+                       } else {
+                               regs.usp = m68k_areg (regs, 7);
+                               m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
+                       }
+               } else if (olds && oldm != regs.m) {
+                       if (oldm) {
+                               regs.msp = m68k_areg (regs, 7);
+                               m68k_areg (regs, 7) = regs.isp;
+                       } else {
+                               regs.isp = m68k_areg (regs, 7);
+                               m68k_areg (regs, 7) = regs.msp;
+                       }
+               }
+               if (currprefs.cpu_model >= 68060)
+                       regs.t0 = 0;
+       } else {
+               regs.t0 = regs.m = 0;
+               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;
+                       }
+               }
+       }
+
+       if (regs.t1 || regs.t0) {
+               SPCFLAG_TRACE = 1;
+       } else {
+               /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
+               SR-modifying instructions (including STOP).  */
+               SPCFLAG_TRACE = 0;
+       }
+       // Stop SR-modification does not generate T0
+       // If this SR modification set Tx bit, no trace until next instruction.
+       if ((oldt0 && t0trace && currprefs.cpu_model >= 68020) || oldt1) {
+               // Always trace if Tx bits were already set, even if this SR modification cleared them.
+               activate_trace();
+       }
+
+}
+
+void REGPARAM2 MakeFromSR_T0(void)
+{
+       MakeFromSR_x(1);
+}
+void REGPARAM2 MakeFromSR(void)
+{
+       MakeFromSR_x(0);
+}
+
+static void exception_check_trace(int nr)
+{
+       SPCFLAG_TRACE = 0;
+       SPCFLAG_DOTRACE = 0;
+       if (regs.t1 && !regs.t0) {
+               /* trace stays pending if exception is div by zero, chk,
+               * trapv or trap #x
+               */
+               if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
+                       SPCFLAG_DOTRACE = 1;
+       }
+       regs.t1 = regs.t0 = 0;
+}
+
+void m68k_setstopped(void)
+{
+       /* A traced STOP instruction drops through immediately without
+       actually stopping.  */
+       if (SPCFLAG_DOTRACE == 0) {
+               cpu_stopped = 1;
+       } else {
+               cpu_stopped = 0;
+       }
+}
+
+void check_t0_trace(void)
+{
+       if (regs.t0 && currprefs.cpu_model >= 68020) {
+               SPCFLAG_TRACE = 0;
+               SPCFLAG_DOTRACE = 1;
+       }
+}
+
+void cpureset(void)
+{
+       test_exception = 1;
+}
+
+void exception3_read(uae_u32 opcode, uae_u32 addr)
+{
+       test_exception = 3;
+       test_exception_3_inst = 0;
+       test_exception_addr = addr;
+}
+void exception3_write(uae_u32 opcode, uae_u32 addr)
+{
+       test_exception = 3;
+       test_exception_3_inst = 0;
+       test_exception_addr = addr;
+}
+void REGPARAM2 Exception(int n)
+{
+       test_exception = n;
+       test_exception_3_inst = 0;
+       test_exception_addr = m68k_getpci();
+}
+void REGPARAM2 Exception_cpu(int n)
+{
+       test_exception = n;
+       test_exception_3_inst = 0;
+       test_exception_addr = m68k_getpci();
+
+       bool t0 = currprefs.cpu_model >= 68020 && regs.t0;
+       // check T0 trace
+       if (t0) {
+               activate_trace();
+       }
+}
+void exception3i(uae_u32 opcode, uaecptr addr)
+{
+       test_exception = 3;
+       test_exception_3_inst = 1;
+       test_exception_addr = addr;
+}
+void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
+{
+       test_exception = 3;
+       test_exception_3_inst = i;
+       test_exception_addr = addr;
+}
+
+int cctrue(int cc)
+{
+       uae_u32 cznv = regflags.cznv;
+
+       switch (cc) {
+       case 0:  return 1;                                                                                      /*                                      T  */
+       case 1:  return 0;                                                                                      /*                                      F  */
+       case 2:  return (cznv & (FLAGVAL_C | FLAGVAL_Z)) == 0;          /* !CFLG && !ZFLG       HI */
+       case 3:  return (cznv & (FLAGVAL_C | FLAGVAL_Z)) != 0;          /*  CFLG || ZFLG        LS */
+       case 4:  return (cznv & FLAGVAL_C) == 0;                                        /* !CFLG                        CC */
+       case 5:  return (cznv & FLAGVAL_C) != 0;                                        /*  CFLG                        CS */
+       case 6:  return (cznv & FLAGVAL_Z) == 0;                                        /* !ZFLG                        NE */
+       case 7:  return (cznv & FLAGVAL_Z) != 0;                                        /*  ZFLG                        EQ */
+       case 8:  return (cznv & FLAGVAL_V) == 0;                                        /* !VFLG                        VC */
+       case 9:  return (cznv & FLAGVAL_V) != 0;                                        /*  VFLG                        VS */
+       case 10: return (cznv & FLAGVAL_N) == 0;                                        /* !NFLG                        PL */
+       case 11: return (cznv & FLAGVAL_N) != 0;                                        /*  NFLG                        MI */
+
+       case 12: /*  NFLG == VFLG               GE */
+               return ((cznv >> FLAGBIT_N) & 1) == ((cznv >> FLAGBIT_V) & 1);
+       case 13: /*  NFLG != VFLG               LT */
+               return ((cznv >> FLAGBIT_N) & 1) != ((cznv >> FLAGBIT_V) & 1);
+       case 14: /* !GET_ZFLG && (GET_NFLG == GET_VFLG);  GT */
+               return !(cznv & FLAGVAL_Z) && (((cznv >> FLAGBIT_N) & 1) == ((cznv >> FLAGBIT_V) & 1));
+       case 15: /* GET_ZFLG || (GET_NFLG != GET_VFLG);   LE */
+               return (cznv & FLAGVAL_Z) || (((cznv >> FLAGBIT_N) & 1) != ((cznv >> FLAGBIT_V) & 1));
+       }
+       return 0;
+}
+
+static uae_u32 xorshiftstate;
+static uae_u32 xorshift32(void)
+{
+       uae_u32 x = xorshiftstate;
+       x ^= x << 13;
+       x ^= x >> 17;
+       x ^= x << 5;
+       xorshiftstate = x;
+       return xorshiftstate;
+}
+
+static int rand16_cnt;
+static uae_u16 rand16(void)
+{
+       int cnt = rand16_cnt & 15;
+       uae_u16 v = 0;
+       rand16_cnt++;
+       if (cnt < 15) {
+               v = (uae_u16)xorshift32();
+               if (cnt <= 6)
+                       v &= ~0x8000;
+               else
+                       v |= 0x8000;
+       }
+       if (forced_immediate_mode == 1)
+               v &= ~1;
+       if (forced_immediate_mode == 2)
+               v |= 1;
+       return v;
+}
+static int rand32_cnt;
+static uae_u32 rand32(void)
+{
+       int cnt = rand32_cnt & 31;
+       uae_u32 v = 0;
+       rand32_cnt++;
+       if (cnt < 31) {
+               v = xorshift32();
+               if (cnt <= 14)
+                       v &= ~0x80000000;
+               else
+                       v |= 0x80000000;
+       }
+       if (forced_immediate_mode == 1)
+               v &= ~1;
+       if (forced_immediate_mode == 2)
+               v |= 1;
+       return v;
+}
+
+// first 3 values: positive
+// next 4 values: negative
+// last: zero
+static int rand8_cnt;
+static uae_u8 rand8(void)
+{
+       int cnt = rand8_cnt & 7;
+       uae_u8 v = 0;
+       rand8_cnt++;
+       if (cnt < 7) {
+               v = (uae_u8)xorshift32();
+               if (cnt <= 2)
+                       v &= ~0x80;
+               else
+                       v |= 0x80;
+       }
+       if (forced_immediate_mode == 1)
+               v &= ~1;
+       if (forced_immediate_mode == 2)
+               v |= 1;
+       return v;
+}
+
+static uae_u8 frand8(void)
+{
+       return (uae_u8)xorshift32();
+}
+
+static void fill_memory_buffer(uae_u8 *p, int size)
+{
+       for (int i = 0; i < size; i++) {
+               p[i] = frand8();
+       }
+       // fill extra zeros
+       for (int i = 0; i < size; i++) {
+               if (frand8() < 0x70)
+                       p[i] = 0x00;
+       }
+}
+
+static void fill_memory(void)
+{
+       fill_memory_buffer(low_memory_temp, 32768);
+       fill_memory_buffer(high_memory_temp, 32768);
+       fill_memory_buffer(test_memory_temp, test_memory_size);
+}
+
+static void save_memory(const TCHAR *path, const TCHAR *name, uae_u8 *p, int size)
+{
+       TCHAR fname[1000];
+       _stprintf(fname, _T("%s%s"), path, name);
+       FILE *f = _tfopen(fname, _T("wb"));
+       if (!f) {
+               wprintf(_T("Couldn't open '%s'\n"), fname);
+               abort();
+       }
+       fwrite(p, 1, size, f);
+       fclose(f);
+}
+
+
+
+static uae_u8 *store_rel(uae_u8 *dst, uae_u8 mode, uae_u32 s, uae_u32 d)
+{
+       int diff = (uae_s32)d - (uae_s32)s;
+       if (diff == 0)
+               return dst;
+       if (diff >= -128 && diff < 128) {
+               *dst++ = mode | CT_RELATIVE_START_BYTE;
+               *dst++ = diff & 0xff;
+       } else if (diff >= -32768 && diff < 32767) {
+               *dst++ = mode | CT_RELATIVE_START_WORD;
+               *dst++ = (diff >> 8) & 0xff;
+               *dst++ = diff & 0xff;
+       } else if (d < LOW_MEMORY_END) {
+               *dst++ = mode | CT_ABSOLUTE_WORD;
+               *dst++ = (d >> 8) & 0xff;
+               *dst++ = d & 0xff;
+       } else if ((d & ~addressing_mask) == ~addressing_mask && (d & addressing_mask) >= HIGH_MEMORY_START) {
+               *dst++ = mode | CT_ABSOLUTE_WORD;
+               *dst++ = (d >> 8) & 0xff;
+               *dst++ = d & 0xff;
+       } else {
+               *dst++ = mode | CT_ABSOLUTE_LONG;
+               *dst++ = (d >> 24) & 0xff;
+               *dst++ = (d >> 16) & 0xff;
+               *dst++ = (d >> 8) & 0xff;
+               *dst++ = d & 0xff;
+       }
+       return dst;
+}
+
+static uae_u8 *store_fpureg(uae_u8 *dst, uae_u8 mode, floatx80 d)
+{
+       *dst++ = mode | CT_SIZE_FPU;
+       *dst++ = (d.high >> 8) & 0xff;
+       *dst++ = (d.high >> 0) & 0xff;
+       *dst++ = (d.low >> 56) & 0xff;
+       *dst++ = (d.low >> 48) & 0xff;
+       *dst++ = (d.low >> 40) & 0xff;
+       *dst++ = (d.low >> 32) & 0xff;
+       *dst++ = (d.low >> 24) & 0xff;
+       *dst++ = (d.low >> 16) & 0xff;
+       *dst++ = (d.low >>  8) & 0xff;
+       *dst++ = (d.low >>  0) & 0xff;
+       return dst;
+}
+
+static uae_u8 *store_reg(uae_u8 *dst, uae_u8 mode, uae_u32 s, uae_u32 d, int size)
+{
+       if (s == d && size < 0)
+               return dst;
+       if (((s & 0xffffff00) == (d & 0xffffff00) && size < 0) || size == sz_byte) {
+               *dst++ = mode | CT_SIZE_BYTE;
+               *dst++ = d & 0xff;
+       } else if (((s & 0xffff0000) == (d & 0xffff0000) && size < 0) || size == sz_word) {
+               *dst++ = mode | CT_SIZE_WORD;
+               *dst++ = (d >> 8) & 0xff;
+               *dst++ = d & 0xff;
+       } else {
+               *dst++ = mode | CT_SIZE_LONG;
+               *dst++ = (d >> 24) & 0xff;
+               *dst++ = (d >> 16) & 0xff;
+               *dst++ = (d >> 8) & 0xff;
+               *dst++ = d & 0xff;
+       }
+       return dst;
+}
+
+static uae_u8 *store_mem_bytes(uae_u8 *dst, uaecptr start, int len, uae_u8 *old)
+{
+       if (!len)
+               return dst;
+       if (len > 32) {
+               wprintf(_T("too long byte count!\n"));
+               abort();
+       }
+       uaecptr oldstart = start;
+       uae_u8 offset = 0;
+       // start
+       for (int i = 0; i < len; i++) {
+               uae_u8 v = get_byte_test(start);
+               if (v != *old)
+                       break;
+               start++;
+               old++;
+       }
+       // end
+       offset = start - oldstart;
+       if (offset > 7) {
+               start -= (offset - 7);
+               offset = 7;
+       }
+       len -= offset;
+       for (int i = len - 1; i >= 0; i--) {
+               uae_u8 v = get_byte_test(start + i);
+               if (v != old[i])
+                       break;
+               len--;
+       }
+       if (!len)
+               return dst;
+       *dst++ = CT_MEMWRITES | CT_PC_BYTES;
+       *dst++ = (offset << 5) | (uae_u8)(len == 32 ? 0 : len);
+       for (int i = 0; i < len; i++) {
+               *dst++ = get_byte_test(start);
+               start++;
+       }
+       return dst;
+}
+
+static uae_u8 *store_mem(uae_u8 *dst, int storealways)
+{
+       if (ahcnt == 0)
+               return dst;
+       for (int i = 0; i < ahcnt; i++) {
+               struct accesshistory *ah = &ahist[i];
+               if (ah->oldval == ah->val && !storealways)
+                       continue;
+               uaecptr addr = ah->addr;
+               addr &= addressing_mask;
+               if (addr < LOW_MEMORY_END) {
+                       *dst++ = CT_MEMWRITE | CT_ABSOLUTE_WORD;
+                       *dst++ = (addr >> 8) & 0xff;
+                       *dst++ = addr & 0xff;
+               } else if (addr >= HIGH_MEMORY_START) {
+                       *dst++ = CT_MEMWRITE | CT_ABSOLUTE_WORD;
+                       *dst++ = (addr >> 8) & 0xff;
+                       *dst++ = addr & 0xff;
+               } else if (addr >= opcode_memory_start && addr < opcode_memory_start + 32768) {
+                       *dst++ = CT_MEMWRITE | CT_RELATIVE_START_WORD;
+                       uae_u16 diff = addr - opcode_memory_start;
+                       *dst++ = (diff >> 8) & 0xff;
+                       *dst++ = diff & 0xff;
+               } else if (addr < opcode_memory_start && addr >= opcode_memory_start - 32768) {
+                       *dst++ = CT_MEMWRITE | CT_RELATIVE_START_WORD;
+                       uae_u16 diff = addr - opcode_memory_start;
+                       *dst++ = (diff >> 8) & 0xff;
+                       *dst++ = diff & 0xff;
+               } else {
+                       *dst++ = CT_MEMWRITE | CT_ABSOLUTE_LONG;
+                       *dst++ = (addr >> 24) & 0xff;
+                       *dst++ = (addr >> 16) & 0xff;
+                       *dst++ = (addr >> 8) & 0xff;
+                       *dst++ = addr & 0xff;
+               }
+               dst = store_reg(dst, CT_MEMWRITE, 0, ah->oldval, ah->size);
+               dst = store_reg(dst, CT_MEMWRITE, 0, ah->val, ah->size);
+       }
+       return dst;
+}
+
+
+static void pl(uae_u8 *p, uae_u32 v)
+{
+       p[0] = v >> 24;
+       p[1] = v >> 16;
+       p[2] = v >> 8;
+       p[3] = v >> 0;
+}
+
+static bool load_file(const TCHAR *path, const TCHAR *file, uae_u8 *p, int size, int offset)
+{
+       TCHAR fname[1000];
+       if (path) {
+               _stprintf(fname, _T("%s%s"), path, file);
+       } else {
+               _tcscpy(fname, file);
+       }
+       FILE *f = _tfopen(fname, _T("rb"));
+       if (!f)
+               return false;
+       if (offset < 0) {
+               fseek(f, -size, SEEK_END);
+       } else {
+               fseek(f, offset, SEEK_SET);
+       }
+       int lsize = fread(p, 1, size, f);
+       if (lsize != size) {
+               wprintf(_T("Couldn't read file '%s'\n"), fname);
+               exit(0);
+       }
+       fclose(f);
+       return true;
+}
+
+static void save_data(uae_u8 *dst, const TCHAR *dir)
+{
+       TCHAR path[1000];
+
+       if (dst == storage_buffer)
+               return;
+
+       if (dst - storage_buffer > max_storage_buffer) {
+               wprintf(_T("data buffer overrun!\n"));
+               abort();
+       }
+
+       _wmkdir(dir);
+       _stprintf(path, _T("%s/%04d.dat"), dir, filecount);
+       FILE *f = _tfopen(path, _T("wb"));
+       if (!f) {
+               wprintf(_T("couldn't open '%s'\n"), path);
+               abort();
+       }
+       if (filecount == 0) {
+               uae_u8 data[4];
+               pl(data, 0x00000001);
+               fwrite(data, 1, 4, f);
+               pl(data, (uae_u32)starttime);
+               fwrite(data, 1, 4, f);
+               pl(data, (hmem_rom << 16) | lmem_rom);
+               fwrite(data, 1, 4, f);
+               pl(data, test_memory_start);
+               fwrite(data, 1, 4, f);
+               pl(data, test_memory_size);
+               fwrite(data, 1, 4, f);
+               pl(data, opcode_memory_start - test_memory_start);
+               fwrite(data, 1, 4, f);
+               pl(data, (cpu_lvl << 16) | sr_undefined_mask);
+               fwrite(data, 1, 4, f);
+               pl(data, currprefs.fpu_model);
+               fwrite(data, 1, 4, f);
+               fwrite(inst_name, 1, sizeof(inst_name) - 1, f);
+               fclose(f);
+               filecount++;
+               save_data(dst, dir);
+       } else {
+               uae_u8 data[4];
+               pl(data, 0x00000001);
+               fwrite(data, 1, 4, f);
+               pl(data, (uae_u32)starttime);
+               fwrite(data, 1, 4, f);
+               pl(data, 0);
+               fwrite(data, 1, 4, f);
+               fwrite(data, 1, 4, f);
+               *dst++ = CT_END_FINISH;
+               fwrite(storage_buffer, 1, dst - storage_buffer, f);
+               fclose(f);
+               filecount++;
+       }
+}
+
+static int full_format_cnt;
+
+static uaecptr putfpuimm(uaecptr pc, int opcodesize, int *isconstant)
+{
+       // TODO: generate FPU immediates
+       switch (opcodesize)
+       {
+       case 0: // L
+               put_long_test(pc, rand32());
+               pc += 4;
+               break;
+       case 4: // W
+               put_word_test(pc, rand16());
+               pc += 2;
+               break;
+       case 6: // B
+               put_word_test(pc, rand16());
+               pc += 2;
+               break;
+       case 1: // S
+               put_long(pc, 0);
+               pc += 4;
+               break;
+       case 2: // X
+               put_long(pc, 0);
+               put_long(pc + 4, 0);
+               put_long(pc + 8, 0);
+               pc += 12;
+               break;
+       case 3: // P
+               put_long(pc, 0);
+               put_long(pc + 4, 0);
+               put_long(pc + 8, 0);
+               pc += 12;
+               break;
+       case 5: // D
+               put_long(pc, 0);
+               put_long(pc + 4, 0);
+               pc += 8;
+               break;
+       }
+       return pc;
+}
+
+// generate mostly random EA.
+static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct instr *dp, int *isconstant, int srcdst, int fpuopcode, int opcodesize)
+{
+       uaecptr old_pc = pc;
+       uae_u16 opcode = *opcodep;
+       int am = mode >= imm ? imm : mode;
+
+       if (!((1 << am) & feature_addressing_modes[srcdst]))
+               return -1;
+
+       switch (mode)
+       {
+       case Dreg:
+       case Areg:
+       case Aind:
+       case Aipi:
+       case Apdi:
+               break;
+       case Ad16:
+       case PC16:
+               put_word_test(pc, rand16());
+               *isconstant = 16;
+               pc += 2;
+               break;
+       case Ad8r:
+       case PC8r:
+       {
+               uae_u16 v = rand16();
+               if (!feature_full_extension_format)
+                       v &= ~0x100;
+               if (mode == Ad8r) {
+                       if ((ad8r[srcdst] & 3) == 1)
+                               v &= ~0x100;
+                       if ((ad8r[srcdst] & 3) == 2)
+                               v |= 0x100;
+               } else if (mode == PC8r) {
+                       if ((pc8r[srcdst] & 3) == 1)
+                               v &= ~0x100;
+                       if ((pc8r[srcdst] & 3) == 2)
+                               v |= 0x100;
+               }
+               if (currprefs.cpu_model < 68020 || (v & 0x100) == 0) {
+                       *isconstant = 16;
+                       put_word_test(pc, v);
+                       pc += 2;
+               } else {
+                       // full format extension
+                       // attempt to generate every possible combination,
+                       // one by one.
+                       for (;;) {
+                               v &= 0xff00;
+                               v |= full_format_cnt & 0xff;
+                               // skip reserved combinations for now
+                               int is = (v >> 6) & 1;
+                               int iis = v & 7;
+                               int sz = (v >> 4) & 3;
+                               int bit3 = (v >> 3) & 1;
+                               if ((is && iis >= 4) || iis == 4 || sz == 0 || bit3 == 1) {
+                                       full_format_cnt++;
+                                       continue;
+                               }
+                               break;
+                       }
+                       put_word_test(pc, v);
+                       uaecptr pce = pc;
+                       pc += 2;
+                       // calculate lenght of extension
+                       ShowEA_disp(&pce, mode == Ad8r ? regs.regs[reg + 8] : pce, NULL, NULL);
+                       while (pc < pce) {
+                               v = rand16();
+                               put_word_test(pc, v);
+                               pc += 2;
+                       }
+                       *isconstant = 32;
+               }
+               break;
+       }
+       case absw:
+               put_word_test(pc, rand16());
+               *isconstant = 16;
+               pc += 2;
+               break;
+       case absl:
+               put_long_test(pc, rand32());
+               *isconstant = 32;
+               pc += 4;
+               break;
+       case imm:
+               if (fpuopcode >= 0 && opcodesize < 8) {
+                       pc = putfpuimm(pc, opcodesize, isconstant);
+               } else {
+                       if (dp->size == sz_long) {
+                               put_long_test(pc, rand32());
+                               *isconstant = 32;
+                               pc += 4;
+                       }
+                       else {
+                               put_word_test(pc, rand16());
+                               *isconstant = 16;
+                               pc += 2;
+                       }
+               }
+               break;
+       case imm0:
+       {
+               // byte immediate but randomly fill also upper byte
+               uae_u16 v = rand16();
+               if ((imm8_cnt & 3) == 0)
+                       v &= 0xff;
+               imm8_cnt++;
+               put_word_test(pc, v);
+               *isconstant = 16;
+               pc += 2;
+               break;
+       }
+       case imm1:
+       {
+               // word immediate
+               if (fpuopcode >= 0) {
+                       uae_u16 v = 0;
+                       if (opcodesize == 7) {
+                               // FMOVECR
+                               v = 0x4000;
+                               v |= opcodesize << 10;
+                               v |= imm16_cnt & 0x3ff;
+                               imm16_cnt++;
+                               if ((opcode & 0x3f) != 0)
+                                       return -1;
+                               *isconstant = 0;
+                               if (imm16_cnt < 0x400)
+                                       *isconstant = -1;
+                       } else if (opcodesize == 8) {
+                               // FMOVEM/FMOVE to/from control registers
+                               v |= 0x8000;
+                               v |= (imm16_cnt & 15) << 11;
+                               v |= rand16() & 0x07ff;
+                               imm16_cnt++;
+                               if (imm16_cnt >= 32)
+                                       *isconstant = 0;
+                               else
+                                       *isconstant = -1;
+                       } else {
+                               v |= fpuopcode;
+                               if (imm16_cnt & 1) {
+                                       // EA to FP reg
+                                       v |= 0x4000;
+                                       v |= opcodesize << 10;
+                                       imm16_cnt++;
+                               } else {
+                                       // FP reg to FP reg
+                                       v |= ((imm16_cnt >> 1) & 7) << 10;
+                                       // clear mode/reg field
+                                       opcode &= ~0x3f;
+                                       imm16_cnt++;
+                                       if (opcodesize != 2) {
+                                               // not X: skip
+                                               return -2;
+                                       }
+                               }
+                               *isconstant = 16;
+                       }
+                       put_word_test(pc, v);
+                       pc += 2;
+               } else {
+                       if (opcodecnt == 1) {
+                               // STOP #xxxx: test all combinations
+                               // (also includes RTD)
+                               put_word_test(pc, imm16_cnt++);
+                               if (imm16_cnt == 0)
+                                       *isconstant = 0;
+                               else
+                                       *isconstant = -1;
+                       } else {
+                               uae_u16 v = rand16();
+                               if ((imm16_cnt & 7) == 0)
+                                       v &= 0x00ff;
+                               if ((imm16_cnt & 15) == 0)
+                                       v &= 0x000f;
+                               imm16_cnt++;
+                               put_word_test(pc, v);
+                               *isconstant = 16;
+                       }
+                       pc += 2;
+               }
+               break;
+       }
+       case imm2:
+       {
+               // long immediate
+               uae_u32 v = rand32();
+               if ((imm32_cnt & 7) == 0)
+                       v &= 0x0000ffff;
+               imm32_cnt++;
+               put_long_test(pc, v);
+               if (imm32_cnt < 256)
+                       *isconstant = -1;
+               else
+                       *isconstant = 32;
+               pc += 4;
+               break;
+       }
+       }
+       *opcodep = opcode;
+       return pc - old_pc;
+}
+
+static int imm_special;
+
+static int handle_specials_branch(uae_u16 opcode, uaecptr pc, struct instr *dp, int *isconstant)
+{
+       // 68020 BCC.L is BCC.B to odd address if 68000/010
+       if ((opcode & 0xf0ff) == 0x60ff) {
+               if (currprefs.cpu_model >= 68020) {
+                       return 0;
+               }
+               return -2;
+       }
+       return 0;
+}
+
+static int handle_specials_stack(uae_u16 opcode, uaecptr pc, struct instr *dp, int *isconstant)
+{
+       int offset = 0;
+       if (opcode == 0x4e73 || opcode == 0x4e74 || opcode == 0x4e75 || opcode == 0x4e77) {
+               uae_u32 v;
+               uaecptr addr = regs.regs[8 + 7];
+               imm_special++;
+               // RTE, RTD, RTS and RTR
+               if (opcode == 0x4e77) {
+                       // RTR
+                       v = imm_special;
+                       uae_u16 ccr = v & 31;
+                       ccr |= rand16() & ~31;
+                       put_word_test(addr, ccr);
+                       addr += 2;
+                       offset += 2;
+                       *isconstant = imm_special >= (1 << (0 + 5)) * 4 ? 0 : -1;
+               } else if (opcode == 0x4e77) {
+                       // RTD
+                       v = imm_special >> 2;
+                       uae_u16 sr = v & 31;
+                       sr |= (v >> 5) << 12;
+                       put_word_test(addr, sr);
+                       addr += 2;
+                       offset += 2;
+                       *isconstant = imm_special >= (1 << (4 + 5)) * 4 ? 0 : -1;
+               } else if (opcode == 0x4e73) {
+                       // RTE
+                       if (currprefs.cpu_model == 68000) {
+                               v = imm_special >> 2;
+                               uae_u16 sr = v & 31;
+                               sr |= (v >> 5) << 12;
+                               put_word_test(addr, sr);
+                               addr += 2;
+                               offset += 2;
+                       } else {
+                               // TODO 68010+ RTE
+                       }
+                       *isconstant = imm_special >= (1 << (4 + 5)) * 4 ? 0 : -1;
+               } else if (opcode == 0x4e75) {
+                       // RTS
+                       *isconstant = imm_special >= 256 ? 0 : -1;
+               }
+               v = rand32();
+               switch (imm_special & 3)
+               {
+               case 0:
+               case 3:
+                       v = opcode_memory_start + 128;
+                       break;
+               case 1:
+                       v &= 0xffff;
+                       break;
+               case 2:
+                       v = opcode_memory_start + (uae_s16)v;
+                       break;
+               }
+               put_long_test(addr, v);
+               if (out_of_test_space) {
+                       wprintf(_T("handle_specials out of bounds access!?"));
+                       abort();
+               }
+       }
+       return offset;
+}
+
+static void execute_ins(uae_u16 opc)
+{
+       uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0);
+       uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0);
+       if (opc == 0x6100
+               && opw1 == 0x001e
+//             && opw2 == 0x2770
+               )
+               printf("");
+
+       // execute instruction
+       SPCFLAG_TRACE = 0;
+       SPCFLAG_DOTRACE = 0;
+
+       MakeFromSR();
+
+       testing_active = 1;
+
+       if (SPCFLAG_TRACE)
+               do_trace();
+
+       (*cpufunctbl[opc])(opc);
+
+       if (!test_exception) {
+               if (SPCFLAG_DOTRACE)
+                       Exception(9);
+
+               if (cpu_stopped && regs.s == 0 && currprefs.cpu_model <= 68010) {
+                       // 68000/68010 undocumented special case:
+                       // if STOP clears S-bit and T was not set:
+                       // cause privilege violation exception, PC pointing to following instruction.
+                       // If T was set before STOP: STOP works as documented.
+                       cpu_stopped = 0;
+                       Exception(8);
+               }
+       }
+
+       testing_active = 0;
+
+       if (regs.s) {
+               regs.regs[15] = regs.usp;
+       }
+}
+
+// any instruction that can branch execution
+static int isbranchinst(struct instr *dp)
+{
+       switch (dp->mnemo)
+       {
+       case i_Bcc:
+       case i_BSR:
+       case i_JMP:
+       case i_JSR:
+               return 1;
+       case i_RTS:
+       case i_RTR:
+       case i_RTD:
+       case i_RTE:
+               return 2;
+       case i_DBcc:
+       case i_FBcc:
+               return -1;
+       case i_FDBcc:
+               return 1;
+       }
+       return 0;
+}
+
+// only test instructions that can have
+// special trace behavior
+static int is_test_trace(struct instr *dp)
+{
+       if (isbranchinst(dp))
+               return 1;
+       switch (dp->mnemo)
+       {
+       case i_STOP:
+       case i_MV2SR:
+       case i_MVSR2:
+               return 1;
+       }
+       return 0;
+}
+
+static int isunsupported(struct instr *dp)
+{
+       switch (dp->mnemo)
+       {
+       case i_MOVE2C:
+       case i_MOVEC2:
+               return 1;
+       case i_RTE:
+               if (cpu_lvl > 0)
+                       return 1;
+               break;
+       }
+       return 0;
+
+}
+
+static const TCHAR *sizes[] = { _T("B"), _T("W"), _T("L") };
+
+static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, int opcodesize, int fpuopcode)
+{
+       TCHAR dir[1000];
+       uae_u8 *dst = NULL;
+       int mn;
+       int size;
+       bool fpumode = 0;
+
+       uae_u32 test_cnt = 0;
+
+       if (mnemo == NULL || mnemo[0] == 0)
+               return;
+
+       size = 3;
+       if (fpuopcode < 0) {
+               if (opcodesize == 0)
+                       size = 2;
+               else if (opcodesize == 4)
+                       size = 1;
+               else if (opcodesize == 6)
+                       size = 0;
+       }
+
+       xorshiftstate = 1;
+       filecount = 0;
+
+       struct mnemolookup *lookup = NULL;
+       for (int i = 0; lookuptab[i].name; i++) {
+               lookup = &lookuptab[i];
+               if (!_tcsicmp(lookup->name, mnemo) || (lookup->friendlyname && !_tcsicmp(lookup->friendlyname, mnemo)))
+                       break;
+       }
+       if (!lookup) {
+               wprintf(_T("'%s' not found.\n"), mnemo);
+               return;
+       }
+       mn = lookup->mnemo;
+       const TCHAR *mns = lookup->name;
+       if (fpuopcode >= 0) {
+               mns = fpuopcodes[fpuopcode];
+               if (opcodesize == 7)
+                       mns = _T("FMOVECR");
+               if (opcodesize == 8)
+                       mns = _T("FMOVEM");
+       }
+
+       int pathlen = _tcslen(path);
+       _stprintf(dir, _T("%s%s"), path, mns);
+       if (fpuopcode < 0) {
+               if (size < 3) {
+                       _tcscat(dir, _T("."));
+                       _tcscat(dir, sizes[size]);
+               }
+       } else {
+               _tcscat(dir, _T("."));
+               _tcscat(dir, fpsizes[opcodesize < 7 ? opcodesize : 2]);
+       }
+       memset(inst_name, 0, sizeof(inst_name));
+       ua_copy(inst_name, sizeof(inst_name), dir + pathlen);
+
+       opcodecnt = 0;
+       for (int opcode = 0; opcode < 65536; opcode++) {
+               struct instr *dp = table68k + opcode;
+               // match requested mnemonic
+               if (dp->mnemo != lookup->mnemo)
+                       continue;
+               // match requested size
+               if ((size >= 0 && size <= 2) && (size != dp->size || dp->unsized))
+                       continue;
+               if (size == 3 && !dp->unsized)
+                       continue;
+               // skip all unsupported instructions if not specifically testing i_ILLG
+               if (dp->clev > cpu_lvl && lookup->mnemo != i_ILLG)
+                       continue;
+               opcodecnt++;
+               if (isunsupported(dp))
+                       return;
+               fpumode = currprefs.fpu_model && (opcode & 0xf000) == 0xf000;
+       }
+
+       if (!opcodecnt)
+               return;
+
+       wprintf(_T("%s\n"), dir);
+
+       int quick = 0;
+       int rounds = 4;
+       int subtest_count = 0;
+
+       int count = 0;
+
+       registers[8 + 6] = opcode_memory_start - 0x100;
+       registers[8 + 7] = test_memory_end - STACK_SIZE;
+
+       uae_u32 cur_registers[MAX_REGISTERS];
+       for (int i = 0; i < MAX_REGISTERS; i++) {
+               cur_registers[i] = registers[i];
+       }
+       floatx80 cur_fpuregisters[MAX_REGISTERS];
+       for (int i = 0; i < 8; i++) {
+               cur_fpuregisters[i] = fpuregisters[i];
+       }
+
+       dst = storage_buffer;
+
+       memcpy(low_memory, low_memory_temp, 32768);
+       memcpy(high_memory, high_memory_temp, 32768);
+       memcpy(test_memory, test_memory_temp, test_memory_size);
+
+       full_format_cnt = 0;
+
+       int sr_override = 0;
+
+       for (;;) {
+
+               if (quick)
+                       break;
+
+               for (int i = 0; i < MAX_REGISTERS; i++) {
+                       dst = store_reg(dst, CT_DREG + i, 0, cur_registers[i], -1);
+                       regs.regs[i] = cur_registers[i];
+               }
+               for (int i = 0; i < 8; i++) {
+                       dst = store_fpureg(dst, CT_FPREG + i, cur_fpuregisters[i]);
+                       regs.fp[i].fpx = cur_fpuregisters[i];
+               }
+
+               for (int opcode = 0; opcode < 65536; opcode++) {
+
+                       struct instr *dp = table68k + opcode;
+                       // match requested mnemonic
+                       if (dp->mnemo != lookup->mnemo)
+                               continue;
+
+                       // match requested size
+                       if ((size >= 0 && size <= 2) && (size != dp->size || dp->unsized))
+                               continue;
+                       if (size == 3 && !dp->unsized)
+                               continue;
+                       // skip all unsupported instructions if not specifically testing i_ILLG
+                       if (dp->clev > cpu_lvl && lookup->mnemo != i_ILLG)
+                               continue;
+
+                       int extra_loops = 3;
+                       while (extra_loops-- > 0) {
+
+                               // force both odd and even immediate values
+                               // for better address error testing
+                               forced_immediate_mode = 0;
+                               if ((currprefs.cpu_model == 68000 || currprefs.cpu_model == 68010) && (feature_exception3_data == 1 || feature_exception3_instruction == 1)) {
+                                       if (dp->size > 0) {
+                                               if (extra_loops == 1)
+                                                       forced_immediate_mode = 1;
+                                               if (extra_loops == 0)
+                                                       forced_immediate_mode = 2;
+                                       } else {
+                                               extra_loops = 0;
+                                       }
+                               } else if (currprefs.cpu_model == 68020 && ((ad8r[0] & 3) == 2 || (pc8r[0] & 3) == 2 || (ad8r[1] & 3) == 2 || (pc8r[1] & 3) == 2)) {
+                                       ; // if only 68020+ addressing modes: do extra loops
+                               } else {
+                                       extra_loops = 0;
+                               }
+
+                               imm8_cnt = 0;
+                               imm16_cnt = 0;
+                               imm32_cnt = 0;
+                               imm_special = 0;
+
+                               // retry few times if out of bounds access
+                               int oob_retries = 10;
+                               // if instruction has immediate(s), repeat instruction test multiple times
+                               // each round generates new random immediate(s)
+                               int constant_loops = 32;
+                               while (constant_loops-- > 0) {
+                                       uae_u8 oldbytes[OPCODE_AREA];
+                                       memcpy(oldbytes, opcode_memory, sizeof(oldbytes));
+
+                                       uae_u16 opc = opcode;
+                                       int isconstant_src = 0;
+                                       int isconstant_dst = 0;
+                                       int did_out_of_bounds = 0;
+                                       uae_u8 *prev_dst2 = dst;
+
+                                       out_of_test_space = 0;
+                                       ahcnt = 0;
+
+                                       if (opc == 0xf228)
+                                               printf("");
+                                       if (subtest_count == 1568)
+                                               printf("");
+
+
+                                       uaecptr pc = opcode_memory_start + 2;
+
+                                       // create source addressing mode
+                                       if (dp->suse) {
+                                               int o = create_ea(&opc, pc, dp->smode, dp->sreg, dp, &isconstant_src, 0, fpuopcode, opcodesize);
+                                               if (o < 0) {
+                                                       memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
+                                                       if (o == -1)
+                                                               goto nextopcode;
+                                                       continue;
+                                               }
+                                               pc += o;
+                                       }
+
+                                       uae_u8 *ao = opcode_memory + 2;
+                                       uae_u16 apw1 = (ao[0] << 8) | (ao[1] << 0);
+                                       uae_u16 apw2 = (ao[2] << 8) | (ao[3] << 0);
+                                       if (opc == 0x3fb2
+                                               && apw1 == 0xa190
+                                               && apw2 == 0x2770
+                                               )
+                                               printf("");
+
+                                       if (opc != opcode) {
+                                               // source EA modified opcode
+                                               dp = table68k + opc;
+                                       }
+
+                                       // create destination addressing mode
+                                       if (dp->duse) {
+                                               int o = create_ea(&opc, pc, dp->dmode, dp->dreg, dp, &isconstant_dst, 1, fpuopcode, opcodesize);
+                                               if (o < 0) {
+                                                       memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
+                                                       if (o == -1)
+                                                               goto nextopcode;
+                                                       continue;
+                                                       goto nextopcode;
+                                               }
+                                               pc += o;
+                                       }
+
+                                       uae_u8 *bo = opcode_memory + 2;
+                                       uae_u16 bopw1 = (bo[0] << 8) | (bo[1] << 0);
+                                       uae_u16 bopw2 = (bo[2] << 8) | (bo[3] << 0);
+                                       if (opc == 0xf228
+                                               && bopw1 == 0x003a
+                                               //&& bopw2 == 0x2770
+                                               )
+                                               printf("");
+
+                                       // bcc.x
+                                       pc += handle_specials_branch(opc, pc, dp, &isconstant_src);
+
+                                       put_word_test(opcode_memory_start, opc);
+                                       // end word, needed to detect if instruction finished normally when
+                                       // running on real hardware.
+                                       put_word_test(pc, 0x4afc); // illegal instruction
+                                       pc += 2;
+
+                                       if (isconstant_src < 0 || isconstant_dst < 0) {
+                                               constant_loops++;
+                                               quick = 1;
+                                       } else {
+                                               // the smaller the immediate, the less test loops
+                                               if (constant_loops > isconstant_src && constant_loops > isconstant_dst)
+                                                       constant_loops = isconstant_dst > isconstant_src ? isconstant_dst : isconstant_src;
+
+                                               // don't do extra tests if no immediates
+                                               if (!isconstant_dst && !isconstant_src)
+                                                       extra_loops = 0;
+                                       }
+
+                                       if (out_of_test_space) {
+                                               wprintf(_T("Setting up test instruction generated out of bounds error!?\n"));
+                                               abort();
+                                       }
+
+                                       dst = store_mem_bytes(dst, opcode_memory_start, pc - opcode_memory_start, oldbytes);
+                                       ahcnt = 0;
+
+
+                                       TCHAR out[256];
+                                       uaecptr srcaddr, dstaddr;
+                                       memset(out, 0, sizeof(out));
+                                       // disassemble and output generated instruction
+                                       for (int i = 0; i < MAX_REGISTERS; i++) {
+                                               regs.regs[i] = cur_registers[i];
+                                       }
+                                       for (int i = 0; i < 8; i++) {
+                                               regs.fp[i].fpx = cur_fpuregisters[i];
+                                       }
+                                       uaecptr nextpc;
+                                       m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), opcode_memory_start, &nextpc, 1, &srcaddr, &dstaddr, 0xffffffff, 0);
+                                       if (verbose) {
+                                               my_trim(out);
+                                               wprintf(_T("%08u %s"), subtest_count, out);
+                                       }
+#if 0
+                                       // can't test because dp may be empty if instruction is invalid
+                                       if (nextpc != pc - 2) {
+                                               wprintf(_T("Disassembler/generator instruction length mismatch!\n"));
+                                               abort();
+                                       }
+#endif
+                                       int bc = isbranchinst(dp);
+                                       if (bc) {
+                                               if (bc < 0) {
+                                                       srcaddr = dstaddr;
+                                               }
+                                               if (bc == 2) {
+                                                       // RTS and friends
+                                                       int stackoffset = handle_specials_stack(opc, pc, dp, &isconstant_src);
+                                                       if (isconstant_src < 0 || isconstant_dst < 0) {
+                                                               constant_loops++;
+                                                               quick = 0;
+                                                       }
+                                                       srcaddr = get_long_test(regs.regs[8 + 7] + stackoffset);
+                                               }
+                                               // branch target is not accessible? skip.
+                                               if ((srcaddr >= cur_registers[15] - 16 && srcaddr <= cur_registers[15] + 16) || ((srcaddr & 1) && !feature_exception3_instruction)) {
+                                                       // lets not jump directly to stack..
+                                                       prev_dst2 = dst;
+                                                       if (verbose) {
+                                                               if (srcaddr & 1)
+                                                                       wprintf(_T(" Branch target is odd\n"));
+                                                               else
+                                                                       wprintf(_T(" Branch target is stack\n"));
+                                                       }
+                                                       continue;
+                                               }                               
+                                               testing_active = 1;
+                                               if (!valid_address(srcaddr, 2, 1)) {
+                                                       if (verbose) {
+                                                               wprintf(_T(" Branch target inaccessible\n"));
+                                                       }
+                                                       testing_active = 0;
+                                                       prev_dst2 = dst;
+                                                       continue;
+                                               } else {
+                                                       // branch target = generate exception
+                                                       put_word_test(srcaddr, 0x4afc);
+                                                       dst = store_mem(dst, 1);
+                                                       memcpy(&ahist2, &ahist, sizeof(struct accesshistory) *MAX_ACCESSHIST);
+                                                       ahcnt2 = ahcnt;
+                                               }
+                                               testing_active = 0;
+                                       }
+
+                                       *dst++ = CT_END_INIT;
+
+                                       int exception_array[256] = { 0 };
+                                       int ok = 0;
+                                       int cnt_stopped = 0;
+
+                                       uae_u16 last_sr = 0;
+                                       uae_u32 last_pc = 0;
+                                       uae_u32 last_registers[MAX_REGISTERS];
+                                       floatx80 last_fpuregisters[8];
+                                       uae_u32 last_fpiar = 0;
+                                       uae_u32 last_fpsr = 0;
+                                       uae_u32 last_fpcr = 0;
+
+                                       int ccr_done = 0;
+                                       int prev_s_cnt = 0;
+                                       int s_cnt = 0;
+                                       int t_cnt = 0;
+
+                                       int extraccr = 0;
+
+                                       // extra loops for supervisor and trace
+                                       uae_u16 sr_allowed_mask = feature_sr_mask & 0xf000;
+                                       uae_u16 sr_mask_request = feature_sr_mask & 0xf000;
+
+                                       for (;;) {
+                                               uae_u16 sr_mask = 0;
+
+                                               if (extraccr & 1)
+                                                       sr_mask |= 0x2000; // S
+                                               if (extraccr & 2)
+                                                       sr_mask |= 0x4000; // T0
+                                               if (extraccr & 4)
+                                                       sr_mask |= 0x8000; // T1
+                                               if (extraccr & 8)
+                                                       sr_mask |= 0x1000; // M
+
+                                               if((sr_mask & ~sr_allowed_mask) || (sr_mask & ~sr_mask_request))
+                                                       goto nextextra;
+
+                                               if (extraccr) {
+                                                       *dst++ = (uae_u8)extraccr;
+                                               }
+
+                                               // Test every CPU CCR or FPU SR/rounding/precision combination
+                                               for (int ccr = 0; ccr < (fpumode ? 256 : 32); ccr++) {
+
+                                                       bool skipped = false;
+
+                                                       out_of_test_space = 0;
+                                                       test_exception = 0;
+                                                       cpu_stopped = 0;
+                                                       ahcnt = 0;
+
+                                                       memset(&regs, 0, sizeof(regs));
+
+                                                       regs.pc = opcode_memory_start;
+                                                       regs.irc = get_word_test(regs.pc + 2);
+
+                                                       // set up registers
+                                                       for (int i = 0; i < MAX_REGISTERS; i++) {
+                                                               regs.regs[i] = cur_registers[i];
+                                                       }
+                                                       regs.fpcr = 0;
+                                                       regs.fpsr = 0;
+                                                       regs.fpiar = 0;
+                                                       if (fpumode) {
+                                                               for (int i = 0; i < 8; i++) {
+                                                                       regs.fp[i].fpx = cur_fpuregisters[i];
+                                                               }
+                                                               regs.fpiar = regs.pc;
+                                                               // condition codes
+                                                               regs.fpsr = (ccr & 15) << 24;
+                                                               // precision and rounding
+                                                               regs.fpcr = (ccr >> 4) << 4;
+                                                       }
+                                                       regs.sr = ccr | sr_mask;
+                                                       regs.usp = regs.regs[8 + 7];
+                                                       regs.isp = test_memory_end - 0x80;
+                                                       regs.msp = test_memory_end;
+
+                                                       // data size optimization, only store data
+                                                       // if it is different than in previous round
+                                                       if (!ccr && !extraccr) {
+                                                               last_sr = regs.sr;
+                                                               last_pc = regs.pc;
+                                                               for (int i = 0; i < 16; i++) {
+                                                                       last_registers[i] = regs.regs[i];
+                                                               }
+                                                               for (int i = 0; i < 8; i++) {
+                                                                       last_fpuregisters[i] = regs.fp[i].fpx;
+                                                               }
+                                                               last_fpiar = regs.fpiar;
+                                                               last_fpcr = regs.fpcr;
+                                                               last_fpsr = regs.fpsr;
+                                                       }
+
+                                                       if (regs.sr & 0x2000)
+                                                               prev_s_cnt++;
+
+                                                       execute_ins(opc);
+
+                                                       if (regs.s)
+                                                               s_cnt++;
+
+                                                       // validate PC
+                                                       uae_u8 *pcaddr = get_addr(regs.pc, 2, 0);
+
+                                                       // examine results
+                                                       if (cpu_stopped) {
+                                                               cnt_stopped++;
+                                                               // CPU stopped, skip test
+                                                               skipped = 1;
+                                                       } else if (out_of_test_space) {
+                                                               exception_array[0]++;
+                                                               // instruction accessed memory out of test address space bounds
+                                                               skipped = 1;
+                                                               did_out_of_bounds = true;
+                                                       } else if (test_exception) {
+                                                               // generated exception
+                                                               exception_array[test_exception]++;
+                                                               if (test_exception == 8 && !(sr_mask & 0x2000)) {
+                                                                       // Privilege violation exception? Switch to super mode in next round.
+                                                                       // Except if reset..
+                                                                       if (lookup->mnemo != i_RESET) {
+                                                                               sr_mask_request |= 0x2000;
+                                                                               sr_allowed_mask |= 0x2000;
+                                                                       }
+                                                               }
+                                                               if (test_exception == 3) {
+                                                                       if (!feature_exception3_data && !test_exception_3_inst) {
+                                                                               skipped = 1;
+                                                                       }
+                                                                       if (!feature_exception3_instruction && test_exception_3_inst) {
+                                                                               skipped = 1;
+                                                                       }
+                                                               } else {
+                                                                       if (feature_exception3_data == 2) {
+                                                                               skipped = 1;
+                                                                       }
+                                                                       if (feature_exception3_instruction == 2) {
+                                                                               skipped = 1;
+                                                                       }
+                                                               }
+                                                               if (test_exception == 9) {
+                                                                       t_cnt++;
+                                                               }
+                                                       } else {
+                                                               // instruction executed successfully
+                                                               ok++;
+                                                               // validate branch instructions
+                                                               if (isbranchinst(dp)) {
+                                                                       if ((regs.pc != srcaddr && regs.pc != pc - 2) || pcaddr[0] != 0x4a && pcaddr[1] != 0xfc) {
+                                                                               printf("Branch instruction target fault\n");
+                                                                               exit(0);
+                                                                       }
+                                                               }
+                                                       }
+                                                       MakeSR();
+                                                       if (!skipped) {
+                                                               // save modified registers
+                                                               for (int i = 0; i < MAX_REGISTERS; i++) {
+                                                                       uae_u32 s = last_registers[i];
+                                                                       uae_u32 d = regs.regs[i];
+                                                                       if (s != d) {
+                                                                               dst = store_reg(dst, CT_DREG + i, s, d, -1);
+                                                                               last_registers[i] = d;
+                                                                       }
+                                                               }
+                                                               if (regs.sr != last_sr) {
+                                                                       dst = store_reg(dst, CT_SR, last_sr, regs.sr, -1);
+                                                                       last_sr = regs.sr;
+                                                               }
+                                                               if (regs.pc != last_pc) {
+                                                                       dst = store_rel(dst, CT_PC, last_pc, regs.pc);
+                                                                       last_pc = regs.pc;
+                                                               }
+                                                               if (currprefs.fpu_model) {
+                                                                       for (int i = 0; i < 8; i++) {
+                                                                               floatx80 s = last_fpuregisters[i];
+                                                                               floatx80 d = regs.fp[i].fpx;
+                                                                               if (s.high != d.high || s.low != d.low) {
+                                                                                       dst = store_fpureg(dst, CT_FPREG + i, d);
+                                                                                       last_fpuregisters[i] = d;
+                                                                               }
+                                                                       }
+                                                                       if (regs.fpiar != last_fpiar) {
+                                                                               dst = store_rel(dst, CT_FPIAR, last_fpiar, regs.fpiar);
+                                                                               last_fpiar = regs.fpiar;
+                                                                       }
+                                                                       if (regs.fpsr != last_fpsr) {
+                                                                               dst = store_reg(dst, CT_FPSR, last_fpsr, regs.fpsr, -1);
+                                                                               last_fpsr = regs.fpsr;
+                                                                       }
+                                                                       if (regs.fpcr != last_fpcr) {
+                                                                               dst = store_reg(dst, CT_FPCR, last_fpcr, regs.fpcr, -1);
+                                                                               last_fpcr = regs.fpcr;
+                                                                       }
+                                                               }
+                                                               dst = store_mem(dst, 0);
+                                                               if (test_exception) {
+                                                                       *dst++ = CT_END | test_exception;
+                                                               } else {
+                                                                       *dst++ = CT_END;
+                                                               }
+                                                               test_count++;
+                                                               subtest_count++;
+                                                               ccr_done++;
+                                                       } else {
+                                                               *dst++ = CT_END_SKIP;
+                                                       }
+                                                       undo_memory(ahist, &ahcnt);
+                                               }
+                                       nextextra:
+                                               extraccr++;
+                                               if (extraccr >= 16)
+                                                       break;
+                                       }
+                                       *dst++ = CT_END;
+
+                                       undo_memory(ahist2, &ahcnt2);
+
+                                       if (!ccr_done) {
+                                               // undo whole previous ccr/extra loop if all tests were skipped
+                                               dst = prev_dst2;
+                                               //*dst++ = CT_END_INIT;
+                                               memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
+                                       } else {
+                                               full_format_cnt++;
+                                       }
+                                       if (verbose) {
+                                               wprintf(_T(" OK=%d OB=%d S=%d/%d T=%d STP=%d"), ok, exception_array[0], prev_s_cnt, s_cnt, t_cnt, cnt_stopped);
+                                               for (int i = 2; i < 128; i++) {
+                                                       if (exception_array[i])
+                                                               wprintf(_T(" E%d=%d"), i, exception_array[i]);
+                                               }
+                                       }
+                                       if (dst - storage_buffer >= storage_buffer_watermark) {
+                                               save_data(dst, dir);
+                                               dst = storage_buffer;
+                                               for (int i = 0; i < MAX_REGISTERS; i++) {
+                                                       dst = store_reg(dst, CT_DREG + i, 0, cur_registers[i], -1);
+                                                       regs.regs[i] = cur_registers[i];
+                                               }
+                                               if (currprefs.fpu_model) {
+                                                       for (int i = 0; i < 8; i++) {
+                                                               dst = store_fpureg(dst, CT_FPREG + i, cur_fpuregisters[i]);
+                                                               regs.fp[i].fpx = cur_fpuregisters[i];
+                                                       }
+                                               }
+                                       }
+                                       if (verbose) {
+                                               wprintf(_T("\n"));
+                                       }
+                                       if (did_out_of_bounds) {
+                                               if (oob_retries) {
+                                                       oob_retries--;
+                                                       constant_loops++;
+                                               } else {
+                                                       full_format_cnt++;
+                                               }
+                                       }
+                               }
+                       }
+               nextopcode:;
+               }
+
+               save_data(dst, dir);
+               dst = storage_buffer;
+
+               if (opcodecnt == 1)
+                       break;
+               if (lookup->mnemo == i_ILLG)
+                       break;
+
+               rounds--;
+               if (rounds < 0)
+                       break;
+
+               // randomize registers
+               for (int i = 0; i < 16 - 2; i++) {
+                       cur_registers[i] = rand32();
+               }
+               cur_registers[0] &= 0xffff;
+               cur_registers[8] &= 0xffff;
+               cur_registers[8 + 6]--;
+               cur_registers[8 + 7] -= 2;
+
+       }
+
+       wprintf(_T("- %d tests\n"), subtest_count);
+}
+
+static void my_trim(TCHAR *s)
+{
+       int len;
+       while (_tcslen(s) > 0 && _tcscspn(s, _T("\t \r\n")) == 0)
+               memmove(s, s + 1, (_tcslen(s + 1) + 1) * sizeof(TCHAR));
+       len = _tcslen(s);
+       while (len > 0 && _tcscspn(s + len - 1, _T("\t \r\n")) == 0)
+               s[--len] = '\0';
+}
+
+static const TCHAR *addrmodes[] =
+{
+       _T("Dreg"), _T("Areg"), _T("Aind"), _T("Aipi"), _T("Apdi"), _T("Ad16"), _T("Ad8r"),
+       _T("absw"), _T("absl"), _T("PC16"), _T("PC8r"), _T("imm"), _T("Ad8rf"), _T("PC8rf"),
+       NULL
+};
+
+#define INISECTION _T("cputest")
+
+int __cdecl main(int argc, char *argv[])
+{
+       const struct cputbl *tbl = NULL;
+       TCHAR path[1000];
+
+       struct ini_data *ini = ini_load(_T("cputestgen.ini"), false);
+       if (!ini) {
+               wprintf(_T("couldn't open cputestgen.ini"));
+               return 0;
+       }
+
+       currprefs.cpu_model = 68000;
+       ini_getval(ini, INISECTION, _T("cpu"), &currprefs.cpu_model);
+       if (currprefs.cpu_model != 68000 && currprefs.cpu_model != 68010 && currprefs.cpu_model != 68020) {
+               wprintf(_T("Unsupported CPU model.\n"));
+               return 0;
+       }
+       currprefs.fpu_model = 0;
+       currprefs.fpu_mode = 1;
+       ini_getval(ini, INISECTION, _T("fpu"), &currprefs.fpu_model);
+       if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
+               wprintf(_T("FPU requires 68020 CPU.\n"));
+               return 0;
+       }
+       if (currprefs.fpu_model != 0 && currprefs.fpu_model != 68881 && currprefs.fpu_model != 68882 && currprefs.fpu_model != 68040 && currprefs.fpu_model != 68060) {
+               wprintf(_T("Unsupported FPU model.\n"));
+               return 0;
+       }
+
+       verbose = 1;
+       ini_getval(ini, INISECTION, _T("verbose"), &verbose);
+
+       feature_addressing_modes[0] = 0xffffffff;
+       feature_addressing_modes[1] = 0xffffffff;
+       ad8r[0] = ad8r[1] = 1;
+       pc8r[0] = pc8r[1] = 1;
+
+       feature_exception3_data = 0;
+       ini_getval(ini, INISECTION, _T("feature_exception3_data"), &feature_exception3_data);
+       feature_exception3_instruction = 0;
+       ini_getval(ini, INISECTION, _T("feature_exception3_instruction"), &feature_exception3_instruction);
+       feature_sr_mask = 0;
+       ini_getval(ini, INISECTION, _T("feature_sr_mask"), &feature_sr_mask);
+       feature_full_extension_format = 0;
+       if (currprefs.cpu_model > 68000) {
+               ini_getval(ini, INISECTION, _T("feature_full_extension_format"), &feature_full_extension_format);
+               if (feature_full_extension_format) {
+                       ad8r[0] |= 2;
+                       ad8r[1] |= 2;
+                       pc8r[0] |= 2;
+                       pc8r[1] |= 2;
+               }
+       }
+       for (int j = 0; j < 2; j++) {
+               TCHAR *am = NULL;
+               if (ini_getstring(ini, INISECTION, j ? _T("feature_addressing_modes_dst") : _T("feature_addressing_modes_src"), &am)) {
+                       if (_tcslen(am) > 0) {
+                               feature_addressing_modes[j] = 0;
+                               ad8r[j] = 0;
+                               pc8r[j] = 0;
+                               TCHAR *p = am;
+                               while (p && *p) {
+                                       TCHAR *pp = _tcschr(p, ',');
+                                       if (pp) {
+                                               *pp++ = 0;
+                                       }
+                                       TCHAR amtext[256];
+                                       _tcscpy(amtext, p);
+                                       my_trim(amtext);
+                                       for (int i = 0; addrmodes[i]; i++) {
+                                               if (!_tcsicmp(addrmodes[i], amtext)) {
+                                                       feature_addressing_modes[j] |= 1 << i;
+                                                       break;
+                                               }
+                                       }
+                                       p = pp;
+                               }
+                               if (feature_addressing_modes[j] & (1 << Ad8r))
+                                       ad8r[j] |= 1;
+                               if (feature_addressing_modes[j] & (1 << imm0)) // Ad8rf
+                                       ad8r[j] |= 2;
+                               if (feature_addressing_modes[j] & (1 << PC8r))
+                                       pc8r[j] |= 1;
+                               if (feature_addressing_modes[j] & (1 << imm1)) // PC8rf
+                                       pc8r[j] |= 2;
+                               if (ad8r[j])
+                                       feature_addressing_modes[j] |= 1 << Ad8r;
+                               if (pc8r[j])
+                                       feature_addressing_modes[j] |= 1 << PC8r;
+                       }
+                       xfree(am);
+               }
+       }
+
+
+       TCHAR *mode = NULL;
+       ini_getstring(ini, INISECTION, _T("mode"), &mode);
+
+       TCHAR *ipath = NULL;
+       ini_getstring(ini, INISECTION, _T("path"), &ipath);
+       if (!ipath) {
+               _tcscpy(path, _T("data/"));
+       } else {
+               _tcscpy(path, ipath);
+       }
+       free(ipath);
+
+       _stprintf(path + _tcslen(path), _T("%lu/"), currprefs.cpu_model);
+       _wmkdir(path);
+
+       xorshiftstate = 1;
+
+       int v = 0;
+       ini_getval(ini, INISECTION, _T("test_memory_start"), &v);
+       if (!v) {
+               wprintf(_T("test_memory_start is required\n"));
+               return 0;
+       }
+       test_memory_start = v;
+
+       v = 0;
+       ini_getval(ini, INISECTION, _T("test_memory_size"), &v);
+       if (!v) {
+               wprintf(_T("test_memory_start is required\n"));
+               return 0;
+       }
+       test_memory_size = v;
+       test_memory_end = test_memory_start + test_memory_size;
+
+       test_low_memory_start = 0x0000;
+       test_low_memory_end = 0x8000;
+       v = 0;
+       if (ini_getval(ini, INISECTION, _T("test_low_memory_start"), &v))
+               test_low_memory_start = v;
+       v = 0;
+       if (ini_getval(ini, INISECTION, _T("test_low_memory_end"), &v))
+               test_low_memory_end = v;
+
+       test_high_memory_start = 0x00ff8000;
+       test_high_memory_end = 0x01000000;
+       v = 0;
+       if (ini_getval(ini, INISECTION, _T("test_high_memory_start"), &v))
+               test_high_memory_start = v;
+       v = 0;
+       if (ini_getval(ini, INISECTION, _T("test_high_memory_end"), &v))
+               test_high_memory_end = v;
+
+       test_memory = (uae_u8 *)calloc(1, test_memory_size);
+       test_memory_temp = (uae_u8 *)calloc(1, test_memory_size);
+       if (!test_memory || !test_memory_temp) {
+               wprintf(_T("Couldn't allocate test memory\n"));
+               return 0;
+       }
+
+       opcode_memory = test_memory + test_memory_size / 2;
+       opcode_memory_start = test_memory_start + test_memory_size / 2;
+
+       fill_memory();
+
+       TCHAR *lmem_rom_name = NULL;
+       ini_getstring(ini, INISECTION, _T("low_rom"), &lmem_rom_name);
+       if (lmem_rom_name) {
+               if (load_file(NULL, lmem_rom_name, low_memory_temp, 32768, 0)) {
+                       wprintf(_T("Low test memory ROM loaded\n"));
+                       lmem_rom = 1;
+               }
+       }
+       free(lmem_rom_name);
+
+       TCHAR *hmem_rom_name = NULL;
+       ini_getstring(ini, INISECTION, _T("high_rom"), &hmem_rom_name);
+       if (hmem_rom_name) {
+               if (load_file(NULL, hmem_rom_name, high_memory_temp, 32768, -1)) {
+                       wprintf(_T("High test memory ROM loaded\n"));
+                       hmem_rom = 1;
+               }
+       }
+       free(hmem_rom_name);
+
+       save_memory(path, _T("lmem.dat"), low_memory_temp, 32768);
+       save_memory(path, _T("hmem.dat"), high_memory_temp, 32768);
+       save_memory(path, _T("tmem.dat"), test_memory_temp, test_memory_size);
+
+       storage_buffer = (uae_u8 *)calloc(max_storage_buffer, 1);
+       // FMOVEM stores can use lots of memory
+       storage_buffer_watermark = max_storage_buffer - 70000;
+
+       for (int i = 0; i < 256; i++) {
+               int j;
+               for (j = 0; j < 8; j++) {
+                       if (i & (1 << j)) break;
+               }
+               movem_index1[i] = j;
+               movem_index2[i] = 7 - j;
+               movem_next[i] = i & (~(1 << j));
+       }
+
+       read_table68k();
+       do_merges();
+
+       if (currprefs.cpu_model == 68000) {
+               tbl = op_smalltbl_90_test_ff;
+               cpu_lvl = 0;
+               addressing_mask = 0x00ffffff;
+       } else if (currprefs.cpu_model == 68010) {
+               tbl = op_smalltbl_91_test_ff;
+               cpu_lvl = 1;
+               addressing_mask = 0x00ffffff;
+       } else if (currprefs.cpu_model == 68020) {
+               tbl = op_smalltbl_92_test_ff;
+               cpu_lvl = 2;
+               addressing_mask = 0x00ffffff;
+       } else {
+               wprintf(_T("Unsupported CPU model.\n"));
+               abort();
+       }
+
+       for (int opcode = 0; opcode < 65536; opcode++) {
+               cpufunctbl[opcode] = op_illg_1;
+       }
+
+       for (int i = 0; tbl[i].handler != NULL; i++) {
+               int opcode = tbl[i].opcode;
+               cpufunctbl[opcode] = tbl[i].handler;
+               cpudatatbl[opcode].length = tbl[i].length;
+               cpudatatbl[opcode].disp020[0] = tbl[i].disp020[0];
+               cpudatatbl[opcode].disp020[1] = tbl[i].disp020[1];
+               cpudatatbl[opcode].branch = tbl[i].branch;
+       }
+
+       for (int opcode = 0; opcode < 65536; opcode++) {
+               cpuop_func *f;
+               instr *table = &table68k[opcode];
+
+               if (table->mnemo == i_ILLG)
+                       continue;
+
+               if (table->clev > cpu_lvl) {
+                       continue;
+               }
+
+               if (table->handler != -1) {
+                       int idx = table->handler;
+                       f = cpufunctbl[idx];
+                       if (f == op_illg_1)
+                               abort();
+                       cpufunctbl[opcode] = f;
+                       memcpy(&cpudatatbl[opcode], &cpudatatbl[idx], sizeof(struct cputbl_data));
+               }
+       }
+
+       x_get_long = get_long_test;
+       x_get_word = get_word_test;
+       x_put_long = put_long_test;
+       x_put_word = put_word_test;
+
+       x_next_iword = next_iword_test;
+       x_cp_next_iword = next_iword_test;
+       x_next_ilong = next_ilong_test;
+       x_cp_next_ilong = next_ilong_test;
+
+       x_cp_get_disp_ea_020 = x_get_disp_ea_020;
+
+       x_cp_get_long = get_long_test;
+       x_cp_get_word = get_word_test;
+       x_cp_get_byte = get_byte_test;
+       x_cp_put_long = put_long_test;
+       x_cp_put_word = put_word_test;
+       x_cp_put_byte = put_byte_test;
+
+       if (currprefs.fpu_model) {
+               fpu_reset();
+       }
+
+       starttime = time(0);
+
+       if (!mode) {
+               wprintf(_T("Mode must be 'all' or '<mnemonic>'\n"));
+               return 0;
+       }
+
+       TCHAR *modep = mode;
+       while(modep) {
+
+               int all = 0;
+               int mnemo = -1;
+               int fpuopcode = -1;
+               int sizes = -1;
+
+               if (!_tcsicmp(mode, _T("all"))) {
+
+                       verbose = 0;
+                       for (int j = 1; lookuptab[j].name; j++) {
+                               for (int i = 0; i < 8; i++) {
+                                       test_mnemo(path, lookuptab[j].name, i, fpuopcode);
+                               }
+                       }
+                       // illg last. All currently selected CPU model's unsupported opcodes
+                       // (illegal instruction, a-line and f-line)
+                       for (int i = 0; i < 8; i++) {
+                               test_mnemo(path, lookuptab[0].name, i, fpuopcode);
+                       }
+                       break;
+               }
+
+               TCHAR *sp = _tcschr(modep, ',');
+               if (sp)
+                       *sp++ = 0;
+               TCHAR modetxt[100];
+               _tcscpy(modetxt, modep);
+               my_trim(modetxt);
+               TCHAR *s = _tcschr(modetxt, '.');
+               if (s) {
+                       *s = 0;
+                       TCHAR c = _totlower(s[1]);
+                       if (c == 'b')
+                               sizes = 6;
+                       if (c == 'w')
+                               sizes = 4;
+                       if (c == 'l')
+                               sizes = 0;
+                       if (c == 'u')
+                               sizes = 8;
+                       if (c == 's')
+                               sizes = 1;
+                       if (c == 'x')
+                               sizes = 2;
+                       if (c == 'p')
+                               sizes = 3;
+                       if (c == 'd')
+                               sizes = 5;
+               }
+               for (int j = 0; lookuptab[j].name; j++) {
+                       if (!_tcsicmp(modetxt, lookuptab[j].name)) {
+                               mnemo = j;
+                               break;
+                       }
+               }
+               if (mnemo < 0) {
+                       if (_totlower(modetxt[0]) == 'f') {
+                               if (!_tcsicmp(modetxt, _T("fmovecr"))) {
+                                       mnemo = i_FPP;
+                                       sizes = 7;
+                                       fpuopcode = 0;
+                               } else if (!_tcsicmp(modetxt, _T("fmovem"))) {
+                                       mnemo = i_FPP;
+                                       sizes = 8;
+                                       fpuopcode = 0;
+                               } else {
+                                       for (int i = 0; i < 64; i++) {
+                                               if (fpuopcodes[i] && !_tcsicmp(modetxt, fpuopcodes[i])) {
+                                                       mnemo = i_FPP;
+                                                       fpuopcode = i;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       if (mnemo < 0) {
+                               wprintf(_T("Couldn't find '%s'\n"), modetxt);
+                               return 0;
+                       }
+               }
+
+               if (mnemo >= 0 && sizes < 0) {
+                       if (fpuopcode >= 0) {
+                               for (int i = 0; i < 8; i++) {
+                                       test_mnemo(path, lookuptab[mnemo].name, i, fpuopcode);
+                               }
+                       } else {
+                               test_mnemo(path, lookuptab[mnemo].name, 0, -1);
+                               test_mnemo(path, lookuptab[mnemo].name, 4, -1);
+                               test_mnemo(path, lookuptab[mnemo].name, 6, -1);
+                               test_mnemo(path, lookuptab[mnemo].name, -1, -1);
+                       }
+               } else {
+                       test_mnemo(path, lookuptab[mnemo].name, sizes, fpuopcode);
+               }
+
+               modep = sp;
+       }
+
+       wprintf(_T("%d total tests generated\n"), test_count);
+
+       return 0;
+}
diff --git a/cputest/68kDisass.c b/cputest/68kDisass.c
new file mode 100644 (file)
index 0000000..06d90db
--- /dev/null
@@ -0,0 +1,2315 @@
+/***
+ *     68k disassembler, written 2010 by Markus Fritze, www.sarnau.com
+ *     
+ *     This file is distributed under the GNU General Public License, version 2
+ *     or at your option any later version. Read the file gpl.txt for details.
+ ***/
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define bool int
+#define false 0
+#define true 1
+typedef unsigned int uaecptr;
+typedef unsigned int uae_u32;
+typedef int uae_s32;
+typedef unsigned short uae_u16;
+typedef short uae_s16;
+typedef unsigned char uae_u8;
+typedef signed char uae_s8;
+typedef unsigned int Uint32;
+typedef int int32;
+
+#include "68kDisass.h"
+
+#define ADDRESS_ON_PC          1
+#define USE_SYMBOLS                    1
+
+typedef enum {
+       doptNoBrackets = 1,             // hide brackets around absolute addressing
+       doptOpcodesSmall = 2,   // opcodes are small letters
+       doptRegisterSmall = 4,  // register names are small letters
+       doptStackSP = 8         // stack pointer is named "SP" instead of "A7" (except for MOVEM)
+} Diss68kOptions;
+
+static Diss68kOptions  options = doptOpcodesSmall | doptRegisterSmall | doptStackSP | doptNoBrackets;
+
+/* all options */
+static const Diss68kOptions optionsMask = doptOpcodesSmall | doptRegisterSmall | doptStackSP | doptNoBrackets;
+
+// values <0 will hide the group
+static int                     optionPosAddress = 0;   // current address
+static int                     optionPosHexdump = 10;  // 16-bit words at this address
+static int                     optionPosLabel = 35;    // label, if defined
+static int                     optionPosOpcode = 47;   // opcode
+static int                     optionPosOperand = 57;  // operands for the opcode
+static int                     optionPosComment = 82;  // comment, if defined
+
+/***
+ *     Motorola 16-/32-Bit Microprocessor and coprocessor types
+ ***/
+#define MC68000                        0x000001        // 16-/32-Bit Microprocessor
+       #define MC68EC000       0x000002        // 16-/32-Bit Embedded Controller
+       #define MC68HC000       0x000004        // Low Power 16-/32-Bit Microprocessor
+#define MC68008                        0x000008        // 16-Bit Microprocessor with 8-Bit Data Bus
+#define MC68010                        0x000010        // 16-/32-Bit Virtual Memory Microprocessor
+#define MC68020                        0x000020        // 32-Bit Virtual Memory Microprocessor
+       #define MC68EC020       0x000040        // 32-Bit Embedded Controller (no PMMU)
+#define MC68030                        0x000080        // Second-Generation 32-Bit Enhanced Microprocessor
+       #define MC68EC030       0x000100        // 32-Bit Embedded Controller (no PMMU)
+#define MC68040                        0x000200        // Third-Generation 32-Bit Microprocessor
+       #define MC68LC040       0x000400        // Third-Generation 32-Bit Microprocessor (no FPU)
+       #define MC68EC040       0x000800        // 32-Bit Embedded Controller (no FPU, no PMMU)
+#define MC68330                        0x001000        // CPU32 Integrated CPU32 Processor
+#define MC68340                        0x002000        // CPU32 Integrated Processor with DMA
+#define MC68060                        0x004000        // Fourth-Generation 32-Bit Microprocessor
+       #define MC68LC060       0x008000        // Fourth-Generation 32-Bit Microprocessor (no FPU)
+       #define MC68EC060       0x010000        // Fourth-Generation 32-Bit Microprocessor (no FPU, no PMMU)
+#define MC_CPU32               (MC68330|MC68340)
+
+#define MC_020                 (MC68020|MC68EC020|MC68030|MC68EC030|MC68040|MC68LC040|MC68EC040|MC_CPU32|MC68060|MC68LC060|MC68EC060)
+#define MC_ALL                 (MC68000|MC68EC000|MC68HC000|MC68008|MC68010|MC_020)
+
+#define MC68851                        0x020000        // Paged Memory Management Unit
+
+#define MC68881                        0x040000        // Floating-PointCoprocessor
+#define MC68882                        0x080000        // Enhanced Floating-Point Coprocessor
+
+#define MC_PMMU                        (MC68881|MC68882)
+#define MC_FPU                 (MC68881|MC68882)
+
+static int                             optionCPUTypeMask = ( MC_ALL & ~MC68040 & ~MC_CPU32 & ~MC68060 ) | MC_PMMU | MC_FPU;
+
+
+typedef enum {
+       dtNone,
+       dtByte,                         // a specific number of bytes, usually 1
+       dtWord,                         // one 16-bit value
+       dtLong,                         // one 32-bit value
+       dtOpcode,                       // an opcode of variable length
+       dtASCString,            // a 0-byte terminated ASCII string
+       dtPointer,                      // a generic 32-bit pointer
+       dtFunctionPointer,      // a 32-bit pointer to a function
+       dtStringArray           // a specific number of ASCII bytes
+} Disass68kDataType;
+
+typedef struct {
+       char    *name;
+       char    *comment;
+       Disass68kDataType       type;
+       int             size;
+} disStructElement;
+
+typedef struct {
+       char    *name;                          // name of the structure
+       int             size;                           // size of structure
+       int             count;                          // number of lines
+       disStructElement        *elements;      // array of all elements of the struct
+} disStructEntry;
+
+static int                             disStructCounts;
+static disStructEntry  *disStructEntries;
+
+typedef struct {
+       long    addr;                           // address of the label
+       Disass68kDataType       type;   // type of the data on the address
+       int             size;                           // size of the label, references inside it are addressed via base address + offset
+       int             count;                          // number of elements at this address with the given size
+       int             structIndex;            // -1 no struct to describe the element
+       char    *name;                          // name of the label
+       char    *comment;                       // optional comment
+} disSymbolEntry;
+
+static int                             disSymbolCounts;
+static disSymbolEntry  *disSymbolEntries;
+
+
+static inline unsigned short   Disass68kGetWord(long addr)
+{
+       uae_u8 *p = (uae_u8 *)addr;
+       return (p[0] << 8) | p[1];
+}
+
+static Disass68kDataType       Disass68kType(long addr, char *addressLabel, char *commentBuffer, int *count)
+{
+       int     i,j;
+
+       addressLabel[0] = 0;
+       commentBuffer[0] = 0;
+       for(i=0; i<disSymbolCounts; ++i)
+       {
+               const disStructEntry    *se;
+               const disSymbolEntry    *dse = &disSymbolEntries[i];
+               int             offset = addr - dse->addr;
+
+               if(offset < 0 || offset >= dse->count * dse->size)
+                       continue;
+
+               // no special struct that devices this value?
+               if(dse->structIndex < 0)
+               {
+                       offset = (offset + dse->size - 1) / dse->size;
+                       *count = dse->count - offset;
+                       if(offset == 0) // only in the first line
+                       {
+                               strcpy(addressLabel, dse->name);
+                               if(dse->comment)
+                                       strcpy(commentBuffer, dse->comment);
+                       }
+                       return dse->type;
+               }
+
+               *count = 1;
+               se = &disStructEntries[dse->structIndex];
+               for(j=0; j<se->count; ++j)
+               {
+                       const disStructElement  *e = &se->elements[j];
+                       if(offset < e->size)
+                       {
+                               if(e->type == dtStringArray)
+                                       *count = e->size;
+                               if(j == 0)
+                                       strcpy(addressLabel, dse->name);
+
+                               sprintf(commentBuffer, "[%s]", e->name);
+                               if(e->comment)
+                                       strcat(commentBuffer, e->comment);
+                               return e->type;
+                       }
+                       offset -= e->size;
+               }
+               return dse->size;
+       }
+       return dtNone;
+}
+
+/***
+ *     Lookup a symbol name
+ ***/
+static const char      *Disass68kSymbolName(long addr, int size)
+{
+       int     i;
+
+       for(i=0; i<disSymbolCounts; ++i)
+       {
+               static char     symbolName[128];
+               const disSymbolEntry    *dse = &disSymbolEntries[i];
+               int     offset = addr - dse->addr;
+               int     reminder;
+
+               if(offset < 0 || offset >= dse->count * dse->size)
+                       continue;
+
+               if(dse->name[0] == 0)
+                       return NULL;
+
+               reminder = offset % dse->size;
+               offset /= dse->size;
+
+               strcpy(symbolName, dse->name);
+               if(offset)
+                       sprintf(symbolName+strlen(symbolName), "+%d*%d", dse->size, offset);
+               if(reminder)
+                       sprintf(symbolName+strlen(symbolName), "+%d", reminder);
+               return symbolName;
+       }
+       return NULL;
+}
+
+/***
+ *     return a string pointer to display a register name
+ ***/
+static const char      *Disass68kRegname(int reg)
+{
+       static char             regName[3];
+       switch(reg)
+       {
+       case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+               sprintf(regName, "%c%d", (options & doptRegisterSmall ? 'd' : 'D'), reg);
+               break;
+
+       case 0x0F:
+               if(options & doptStackSP)       // display A7 as SP
+               {
+                       if(options & doptRegisterSmall)
+                               return "sp";
+                       return "SP";
+               }
+       case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E:
+               sprintf(regName, "%c%d", (options & doptRegisterSmall ? 'a' : 'A'), reg & 7);
+               break;
+       }
+       return regName;
+}
+
+/***
+ *     return a string pointer to display a register name
+ ***/
+static const char      *Disass68kNumber(int val)
+{
+       static char             numString[32];
+       if(val >= -9 && val <= 9)
+       {
+               sprintf(numString, "%d", val);
+       } else {
+               // 4 characters/numbers or underscore (e.g. for cookies)
+               unsigned char c0 = (val >> 24) & 0xFF;
+               unsigned char c1 = (val >> 16) & 0xFF;
+               unsigned char c2 = (val >>  8) & 0xFF;
+               unsigned char c3 = (val >>  0) & 0xFF;
+               if((isalnum(c0) || c0 == '_') && (isalnum(c1) || c1 == '_') && (isalnum(c2) || c2 == '_') && (isalnum(c3) || c3 == '_'))
+               {
+                       sprintf(numString, "'%c%c%c%c'", c0, c1, c2, c3);
+               } else {
+                       sprintf(numString, "$%x", val);
+               }
+       }
+       return numString;
+}
+
+/***
+ *     Supported registers for e.g. MOVEC
+ ***/
+#define REG_CCR                        -1
+#define REG_SR                 -2
+#define REG_PC                 -3
+#define REG_ZPC                        -4
+#define REG_TT0                        -8
+#define REG_TT1                        -9
+#define REG_MMUSR              -10
+#define REG_USP                        0x800
+#define REG_SFC                        0x000
+#define REG_DFC                        0x001
+#define REG_TC                 0x10000
+#define REG_SRP                        0x10002
+#define REG_CRP                        0x10003
+#define REG_VAL                        0x20000
+#define REG_CACHES_NONE        0x20010
+#define REG_CACHES_IC  0x20011
+#define REG_CACHES_DC  0x20012
+#define REG_CACHES_ICDC        0x20013
+#define REG_FPU_FPCR   0x30004
+#define REG_FPU_FPSR   0x30002
+#define REG_FPU_FPIAR  0x30001
+
+static const char *Disass68kSpecialRegister(int reg)
+{
+       static char     buf[8];
+       const char      *sp = NULL;
+       switch (reg)
+       {
+       case 0x000:             sp = "SFC"; break;
+       case 0x001:             sp = "DFC"; break;
+       case 0x002:             sp = "CACR"; break;
+       case 0x003:             sp = "TC"; break;
+       case 0x004:             sp = "ITT0"; break;     // IACR0 on an 68EC040 only
+       case 0x005:             sp = "ITT1"; break;     // IACR1 on an 68EC040 only
+       case 0x006:             sp = "DTT0"; break;     // DACR0 on an 68EC040 only
+       case 0x007:             sp = "DTT1"; break;     // DACR1 on an 68EC040 only
+       case 0x008:             sp = "BUSCR"; break;
+
+       case 0x800:             sp = "USP"; break;
+       case 0x801:             sp = "VBR"; break;
+       case 0x802:             sp = "CAAR"; break;
+       case 0x803:             sp = "MSP"; break;
+       case 0x804:             sp = "ISP"; break;
+       case 0x805:             sp = "MMUSR"; break;
+       case 0x806:             sp = "URP"; break;
+       case 0x807:             sp = "SRP"; break;
+       case 0x808:             sp = "PCR"; break;
+
+       // MMU register
+       case 0x10000:   sp = "TC"; break;
+       case 0x10001:   sp = "DRP"; break;
+       case 0x10002:   sp = "SRP"; break;
+       case 0x10003:   sp = "CRP"; break;
+       case 0x10004:   sp = "CAL"; break;
+       case 0x10005:   sp = "VAL"; break;
+       case 0x10006:   sp = "SCCR"; break;
+       case 0x10007:   sp = "ACR"; break;
+
+       case REG_CCR:   sp = "CCR"; break;
+       case REG_SR:    sp = "SR"; break;
+       case REG_PC:    sp = "PC"; break;
+       case REG_ZPC:   sp = "ZPC"; break;
+       case REG_TT0:   sp = "TT0"; break;
+       case REG_TT1:   sp = "TT1"; break;
+       case REG_MMUSR: sp = "MMUSR"; break;
+
+       case REG_VAL:   sp = "VAL"; break;
+
+       case REG_CACHES_NONE:   sp = "NC"; break;
+       case REG_CACHES_IC:             sp = "IC"; break;
+       case REG_CACHES_DC:             sp = "DC"; break;
+       case REG_CACHES_ICDC:   sp = "IC/DC"; break;    // GCC lists this as "BC"
+
+       case REG_FPU_FPCR:              sp = "FPCR"; break;
+       case REG_FPU_FPSR:              sp = "FPSR"; break;
+       case REG_FPU_FPIAR:             sp = "FPIAR"; break;
+
+       // unknown register => unknown opcode!
+       default:                return NULL;
+       }
+
+       if(options & doptRegisterSmall)
+       {
+               char    *bp;
+               strcpy(buf, sp);
+               for (bp = buf; *bp; ++bp)
+                       *bp = tolower((unsigned char)*bp);
+               return buf;
+       }
+       return sp;
+}
+
+/***
+ *     680x0 EA disassembly, supports all address modes
+ *
+ *     disassbuf = output buffer for the EA, empty string in case of an illegal EA
+ *     addr = pointer to the address, which Disass68kGetWord() will allow to read memory.
+ *                Incremented by the function to point behind the opcode, when done
+ *     ea = 6-bit ea from the opcode
+ *  size = addressed size of the opcode in bytes (e.g. 1,2,4 for MOVE.B, MOVE.W, MOVE.L), only used for immediate addressing
+ ***/
+
+#define EA_Dn                          0x00001 // Dn
+#define EA_An                          0x00002 // An
+#define EA_Ani                         0x00004 // (An)
+#define EA_Anip                                0x00008 // (An)+
+#define EA_piAn                                0x00010 // -(An)
+#define EA_dAn                         0x00020 // d(An), d(An,Dn), etc.
+#define EA_PCRel                       0x00040 // d(PC), d(PC,Dn), etc.
+#define EA_Abs                         0x00080 // abs.w, abs.l
+#define EA_Immed                       0x00100 // #<val>
+
+#define EA_ImmedParameter      0x0200  // an immediate value as a parameter
+#define EA_ValueParameter      0x0400  // an immediate value as a parameter without the "#"
+#define EA_SpecialRegister     0x0800  // any special register e.g. SR,CCR,USP,etc
+#define EA_PCDisplacement      0x1000  // PC relative jump, like for BRA and friends
+
+#define EA_All                         (EA_Dn | EA_An | EA_Ani | EA_Anip | EA_piAn | EA_dAn | EA_Abs | EA_Immed | EA_PCRel)
+#define EA_Dest                                (EA_Dn | EA_An | EA_Ani | EA_Anip | EA_piAn | EA_dAn | EA_Abs)
+
+static char            *Disass68kEA(char *disassbuf, char *commentBuffer, long *addr, long opcodeAddr, int ea, int size, int allowedEAs, int parameterValue, int disassFlag)
+{
+       unsigned short  eWord1;
+       unsigned short  eWord2;
+       int                             xn,c,scale;
+       int                             reg = ea & 7;
+       const char              *sp;
+       long                    val;
+       char    regName[3];
+       signed long     pcoffset;
+
+       disassbuf[0] = 0;
+       switch(ea)
+       {
+       // M=000 = 0    Dn
+       // Data Register Direct Mode
+       // Dn
+       // M=001 = 1    An
+       // Address Register Direct Mode
+       // An
+       case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+               if((allowedEAs & EA_Dn) != EA_Dn)
+                       break;
+               sprintf(disassbuf, "%s", Disass68kRegname(ea & 0x0F));
+               break;
+       case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F:
+               if((allowedEAs & EA_An) != EA_An)
+                       break;
+               sprintf(disassbuf, "%s", Disass68kRegname(ea & 0x0F));
+               break;
+
+       // M=010 = 2
+       // Address Register Indirect Mode
+       // (An)
+       case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+               if((allowedEAs & EA_Ani) != EA_Ani)
+                       break;
+               sprintf(disassbuf, "(%s)", Disass68kRegname(reg | 8));
+               break;
+
+       // M=011 = 3
+       // Address Register Indirect with Postincrement Mode
+       // (An) +
+       case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
+               if((allowedEAs & EA_Anip) != EA_Anip)
+                       break;
+               sprintf(disassbuf, "(%s)+", Disass68kRegname(reg | 8));
+               break;
+
+       // M=100 = 4
+       // Address Register Indirect with Predecrement Mode
+       // \96 (An)
+       case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+               if((allowedEAs & EA_piAn) != EA_piAn)
+                       break;
+               sprintf(disassbuf, "-(%s)", Disass68kRegname(reg | 8));
+               break;
+
+       // M=101 = 5
+       // Address Register Indirect with Displacement Mode
+       // (d16,An)
+       case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F:
+               if((allowedEAs & EA_dAn) != EA_dAn)
+                       break;
+               eWord1 = Disass68kGetWord(*addr); *addr += 2;
+               sprintf(disassbuf, "%s(%s)", Disass68kNumber(eWord1), Disass68kRegname(reg | 8));
+               break;
+
+       // M=111 = 7, Xn/reg = 011 = 3
+       // Program Counter Indirect with Index (Base Displacement) Mode
+       // (bd, PC, Xn. SIZE*SCALE)
+       // Program Counter Memory Indirect Postindexed Mode
+       // ([bd,PC],Xn.SIZE*SCALE,od)
+       // Program Counter Memory Indirect Preindexed Mode
+       // ([bd,PC,Xn.SIZE*SCALE],od)
+       case 0x3B:
+               // This is equal to the following, except that instead of An, it is PC relative
+
+       // M=110 = 6
+       // Address Register Indirect with Index (Base Displacement) Mode
+       // (bd,An,Xn.SIZE*SCALE)
+       // Memory Indirect Postindexed Mode
+       // ([bd,An],Xn.SIZE*SCALE,od)
+       // Memory Indirect Preindexed Mode
+       // ([bd, An, Xn.SIZE*SCALE], od)
+       case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+               eWord1 = Disass68kGetWord(*addr); *addr += 2;
+               xn = (eWord1 >> 12) & 0x0F;                             // Register D0..D7/A0..A7
+               c = ((eWord1 >> 11) & 1) ? 'l' : 'w';   // Word/Long-Word Index Size 0 = Sign-Extended Word 1 = Long Word
+               scale = (eWord1 >> 9) & 3;                              // Scale Factor 00 = 1 01 = 2 10 = 4 11 = 8
+
+               if(ea == 0x3B)
+               {
+                       sp = Disass68kSpecialRegister(REG_PC);
+                       if(!sp) return NULL;
+                       strcpy(regName, sp);
+               } else {
+                       sprintf(regName, "%s", Disass68kRegname(reg | 8));
+               }
+
+               if((eWord1 & 0x0100) == 0)
+               {
+                       const char      *numStr;
+
+                       // BRIEF EXTENSION WORD FORMAT
+                       if(ea == 0x3B)
+                       {
+                               if((allowedEAs & EA_PCRel) != EA_PCRel)
+                                       break;
+                       } else {
+                               if((allowedEAs & EA_dAn) != EA_dAn)
+                                       break;
+                       }
+
+                       // Address Register Indirect with Index (8-Bit Displacement) Mode
+                       // (d8 ,An, Xn.SIZE*SCALE)
+                       numStr = Disass68kNumber(eWord1 & 0xFF);
+                       if(numStr[0] == '0' && numStr[1] == 0)
+                               numStr = "";
+
+                       // scale is only on 68020 and later supported
+                       if(scale != 0 && (optionCPUTypeMask & MC_020) == 0)
+                               return NULL;
+
+                       if(scale == 0)
+                       {
+#if ADDRESS_ON_PC
+                               if(ea == 0x3B)
+                                       sprintf(disassbuf, "$%lx(%s,%s.%c)", (signed char)(eWord1 & 0xFF) + opcodeAddr + 2, Disass68kSpecialRegister(REG_PC), Disass68kRegname(xn), c);
+                               else
+#endif
+                                       sprintf(disassbuf, "%s(%s,%s.%c)", numStr, regName, Disass68kRegname(xn), c);
+                       } else
+                       {
+#if ADDRESS_ON_PC
+                               if(ea == 0x3B)
+                                       sprintf(disassbuf, "$%lx(%s,%s.%c*%d)", (signed char)(eWord1 & 0xFF) + opcodeAddr + 2, Disass68kSpecialRegister(REG_PC), Disass68kRegname(xn), c, 1 << scale);
+                               else
+#endif
+                                       sprintf(disassbuf, "%s(%s,%s.%c*%d)", numStr, regName, Disass68kRegname(xn), c, 1 << scale);
+                       }
+#if USE_SYMBOLS
+                       if(ea == 0x3B)
+                       {
+                               const char      *symStr = Disass68kSymbolName((signed char)(eWord1 & 0xFF) + opcodeAddr + 2, size);
+                               if(symStr)
+                               {
+                                       commentBuffer += strlen(commentBuffer);
+                                       sprintf(commentBuffer+strlen(commentBuffer), "%s", symStr);
+                               }
+                       }
+#endif
+#if !ADDRESS_ON_PC
+                       if(ea == 0x3B)
+                       {
+                               commentBuffer += strlen(commentBuffer);
+                               sprintf(commentBuffer+strlen(commentBuffer), "$%lx", (signed char)(eWord1 & 0xFF) + opcodeAddr + 2);
+                       }
+#endif
+               } else {
+                       // FULL EXTENSION WORD FORMAT
+
+                       int     bs = (eWord1 >> 7) & 1;         // Base Register Suppress 0 = Base Register Added 1 = Base Register Suppressed
+                       int     is = (eWord1 >> 6) & 1;         // Index Suppress 0 = Evaluate and Add Index Operand 1 = Suppress Index Operand
+                       int     bdSize = (eWord1 >> 4) & 3;     // Base Displacement Size 00 = Reserved 01 = Null Displacement 10 = Word Displacement 11 = Long Displacement
+                       int     iis = eWord1 & 7;               // Index/Indirect Selection Indirect and Indexing Operand Determined in Conjunction with Bit 6, Index Suppress
+                       bool    prefixComma;
+                       long    bd, od;
+
+                       // reserved, has to be 0
+                       if((eWord1 & 8) != 0 || bdSize == 0 || (is && iis > 3) || iis == 4)
+                               break;
+
+                       // full extension format is only supported on 68020 or later
+                       if((optionCPUTypeMask & MC_020) == 0)
+                               return NULL;
+
+                       if(ea == 0x3B)
+                       {
+                               if((allowedEAs & EA_PCRel) != EA_PCRel)
+                                       break;
+                       } else {
+                               if((allowedEAs & EA_dAn) != EA_dAn)
+                                       break;
+                       }
+
+                       bd = 0;
+                       switch(bdSize)
+                       {
+                       case 3: 
+                               bd = Disass68kGetWord(*addr); *addr += 2;
+                               bd <<= 16;
+                       case 2:
+                               bd |= Disass68kGetWord(*addr); *addr += 2;
+                               break;
+                       default:
+                               break;
+                       }
+
+                       prefixComma = false;
+                       if(bdSize >= 2 && iis == 0)
+                               sprintf(disassbuf, "%s", Disass68kNumber(bd));
+                       strcat(disassbuf, "(");
+                       if(iis != 0)
+                       {
+                               // the CPU32 doesn't support the memory indirect mode
+                               if(optionCPUTypeMask & MC_CPU32)
+                                       return NULL;
+
+                               strcat(disassbuf, "[");
+                       }
+                       if(bdSize >= 2 && iis != 0)
+                       {
+                               sprintf(disassbuf+strlen(disassbuf), "%s", Disass68kNumber(bd));
+                               prefixComma = true;
+                       }
+                       if(bdSize == 1 && ((bs && is && iis > 0) || (bs && iis >= 5)))
+                       {
+                               if(ea == 0x3B)
+                               {
+                                       sp = Disass68kSpecialRegister(REG_ZPC);
+                                       if(!sp) return NULL;
+                                       strcat(disassbuf, sp);
+                               } else {
+                                       strcat(disassbuf, "0");
+                               }
+                       }
+                       if(!bs)
+                       {
+                               if(prefixComma)
+                                       strcat(disassbuf, ",");
+                               strcat(disassbuf, regName);
+                               prefixComma = true;
+                       }
+                       if(iis >= 5 && iis <= 7)
+                       {
+                               strcat(disassbuf, "]");
+                               prefixComma = true;
+                       }
+                       if(!is)
+                       {
+                               if(prefixComma)
+                                       strcat(disassbuf, ",");
+                               if(scale == 0)
+                               {
+                                       sprintf(disassbuf+strlen(disassbuf), "%s.%c", Disass68kRegname(xn), c);
+                               } else
+                               {
+                                       sprintf(disassbuf+strlen(disassbuf), "%s.%c*%d", Disass68kRegname(xn), c, 1 << scale);
+                               }
+                       }
+                       if(iis >= 1 && iis <= 3)
+                       {
+                               strcat(disassbuf, "]");
+                               prefixComma = true;
+                       }
+                       od = 0;
+                       switch(iis & 3)
+                       {
+                       case 3:
+                               od = Disass68kGetWord(*addr); *addr += 2;
+                               od <<= 16;
+                       case 2:
+                               od |= Disass68kGetWord(*addr); *addr += 2;
+                               if(prefixComma)
+                                       strcat(disassbuf, ",");
+                               sprintf(disassbuf+strlen(disassbuf), "%s", Disass68kNumber(od));
+                               break;
+                       default:
+                               break;
+                       }
+                       strcat(disassbuf, ")");
+               }
+               break;
+
+       // M=111 = 7, Xn/reg = 000 = 0
+       // Absolute Short Addressing Mode
+       // (xxx).W
+       case 0x38:
+               if((allowedEAs & EA_Abs) != EA_Abs)
+                       break;
+               eWord1 = Disass68kGetWord(*addr); *addr += 2;
+               val = eWord1;
+               if(eWord1 & 0x8000)
+                       val |= 0xFFFF0000;
+#if USE_SYMBOLS
+               sp = Disass68kSymbolName(val, size);
+               if(sp)
+               {
+                       if(options & doptNoBrackets)
+                               sprintf(disassbuf, "%s.w", sp);
+                       else
+                               sprintf(disassbuf, "(%s).w", sp);
+                       break;
+               }
+#endif
+               if(options & doptNoBrackets)
+               {
+                       if(val & 0x80000000)
+                               sprintf(disassbuf, "$%8.8lx.w", val);
+                       else
+                               sprintf(disassbuf, "$%4.4lx.w", val);
+               } else {
+                       if(val & 0x80000000)
+                               sprintf(disassbuf, "($%8.8lx).w", val);
+                       else
+                               sprintf(disassbuf, "($%4.4lx).w", val);
+               }
+               break;
+
+       // M=111 = 7, Xn/reg = 001 = 1
+       // Absolute Long Addressing Mode
+       // (xxx).L
+       case 0x39:
+               if((allowedEAs & EA_Abs) != EA_Abs)
+                       break;
+               eWord1 = Disass68kGetWord(*addr); *addr += 2;
+               eWord2 = Disass68kGetWord(*addr); *addr += 2;
+#if USE_SYMBOLS
+               val = (eWord1 << 16) | eWord2;
+               sp = Disass68kSymbolName(val, size);
+               if(sp)
+               {
+                       if(options & doptNoBrackets)
+                               sprintf(disassbuf, "%s", sp);
+                       else
+                               sprintf(disassbuf, "(%s).l", sp);
+                       break;
+               }
+#endif
+               if(options & doptNoBrackets)
+                       sprintf(disassbuf, "%s", Disass68kNumber((eWord1 << 16) | eWord2));
+               else
+                       sprintf(disassbuf, "(%s).l", Disass68kNumber((eWord1 << 16) | eWord2));
+               break;
+
+       // M=111 = 7, Xn/reg = 010 = 2
+       // Program Counter Indirect with Displacement Mode
+       // (d16,PC)
+       case 0x3A:
+               if((allowedEAs & EA_PCRel) != EA_PCRel)
+                       break;
+               eWord1 = Disass68kGetWord(*addr); *addr += 2;
+               sp = Disass68kSpecialRegister(REG_PC);
+               if(!sp) return NULL;
+#if ADDRESS_ON_PC
+       #if USE_SYMBOLS
+               sp = Disass68kSymbolName(((signed short)eWord1 + *addr - 2), size);
+               if(sp)
+               {
+                       sprintf(disassbuf, "%s(%s)", sp, Disass68kSpecialRegister(REG_PC));
+               } else {
+                       sprintf(disassbuf, "$%lx(%s)", (signed short)eWord1 + *addr - 2, Disass68kSpecialRegister(REG_PC));
+               }
+       #else
+               sprintf(disassbuf, "$%lx(%s)", (signed short)eWord1 + *addr - 2, Disass68kSpecialRegister(REG_PC));
+       #endif
+#else
+               sprintf(disassbuf, "%s(%s)", Disass68kNumber(eWord1),sp);
+               sprintf(commentBuffer+strlen(commentBuffer), "$%lx", (signed short)eWord1 + *addr - 2);
+#endif
+               break;
+
+       // M=111 = 7, Xn/reg = 100 = 4
+       // Immediate Data
+       // #<xxx>
+       case 0x3C:
+               if((allowedEAs & EA_Immed) != EA_Immed)
+                       break;
+               eWord1 = Disass68kGetWord(*addr); *addr += 2;
+               goto immed;
+
+       case 0x0100:    // Immediate Value as a parameter
+               if((allowedEAs & EA_ImmedParameter) != EA_ImmedParameter)
+                       break;
+               eWord1 = parameterValue;
+       immed:
+               switch(size)
+               {
+               case 1: eWord1 &= 0xFF;
+               case 2:
+#if USE_SYMBOLS
+                               if(disassFlag)
+                               {
+                                       val = eWord1;
+                                       if(eWord1 & 0x8000)
+                                               val |= 0xFFFF0000;
+                                       sp = Disass68kSymbolName(val, size);
+                                       if(sp)
+                                       {
+                                               sprintf(disassbuf, "#%s", sp);
+                                               break;
+                                       }
+                               }
+#endif
+                               sprintf(disassbuf, "#%s", Disass68kNumber(eWord1));
+                               break;
+               case 4: eWord2 = Disass68kGetWord(*addr); *addr += 2;
+#if USE_SYMBOLS
+                               if(disassFlag)
+                               {
+                                       val = (eWord1 << 16) | eWord2;
+                                       sp = Disass68kSymbolName(val, size);
+                                       if(sp)
+                                       {
+                                               sprintf(disassbuf, "#%s", sp);
+                                               break;
+                                       }
+                               }
+#endif
+                               sprintf(disassbuf, "#%s", Disass68kNumber((eWord1 << 16) | eWord2));
+                               break;
+               }
+               break;
+
+       case 0x0103:
+               if((allowedEAs & EA_ValueParameter) != EA_ValueParameter)
+                       break;
+               sprintf(disassbuf, "%d", parameterValue);
+               break;
+
+       case 0x0101:    // Special Registers as in the parameter
+               if((allowedEAs & EA_SpecialRegister) != EA_SpecialRegister)
+                       break;
+               sp = Disass68kSpecialRegister(parameterValue);
+               if(!sp) return NULL;
+               strcpy(disassbuf, sp);
+               break;
+
+       case 0x0102:    // PC relative jump, like for BRA and friends
+               if((allowedEAs & EA_PCDisplacement) != EA_PCDisplacement)
+                       break;
+               pcoffset = 0;
+               switch(size)
+               {
+               case 1: pcoffset = (signed char)parameterValue;
+                               break;
+               case 2: eWord1 = Disass68kGetWord(*addr); *addr += 2;
+                               pcoffset = (signed short)eWord1;
+                               pcoffset -= 2;
+                               break;
+               case 4: eWord1 = Disass68kGetWord(*addr); *addr += 2;
+                               eWord2 = Disass68kGetWord(*addr); *addr += 2;
+                               pcoffset = (signed int)((eWord1 << 16) | eWord2);
+                               pcoffset -= 4;
+                               break;
+               }
+#if ADDRESS_ON_PC
+       #if USE_SYMBOLS
+               sp = Disass68kSymbolName((*addr + pcoffset), size);
+               if(sp)
+               {
+                       strcat(disassbuf, sp);
+               } else {
+                       sprintf(disassbuf, "$%lx", *addr + pcoffset);
+               }
+       #else
+               sprintf(disassbuf, "$%lx", *addr + pcoffset);
+       #endif
+#else
+               if(pcoffset < 0)
+               {
+                       sprintf(disassbuf, "*-$%lx", -pcoffset - 2);
+               } else {
+                       sprintf(disassbuf, "*+$%lx", pcoffset + 2);
+               }
+               sprintf(commentBuffer+strlen(commentBuffer), "$%lx", *addr + pcoffset);
+#endif
+               break;
+
+       default:        // 0x3D..0x3F are reserved
+               break;
+
+       }
+       if(disassbuf[0] == 0)
+               return NULL;
+       return disassbuf + strlen(disassbuf);
+}
+
+/***
+ *     Create a register list for the MOVEM opcode
+ ***/
+static char    *Disass68kReglist(char *buf, unsigned short reglist)
+{
+       int bit;
+       int lastBit = -99;
+       int lastBitStart = -99;
+       char    regD = options & doptRegisterSmall ? 'd' : 'D';
+       char    regA = options & doptRegisterSmall ? 'a' : 'A';
+       for(bit=0; bit<=15; ++bit)
+       {
+               // bit clear?
+               if((reglist & (1 << bit)) == 0)
+               {
+                       // do we have a run? => close it!
+                       if(lastBitStart >= 0 && lastBitStart != (bit - 1))
+                       {
+                               *buf++ = '-';
+                               *buf++ = ((bit-1) >= 8) ? regA : regD;
+                               *buf++ = '0' + ((bit-1) & 7);
+                       }
+                       lastBitStart = -1;
+                       continue;
+               }
+               // reset when switching from D to A
+               if(bit == 8 && lastBitStart >= 0)
+               {
+                       *buf++ = '-';
+                       *buf++ = regD;
+                       *buf++ = '7';
+                       lastBit = 0;
+                       lastBitStart = -99;
+               }
+               // separate bits, skip runs of bits to merge them later
+               if(lastBit >= 0)
+               {
+                       if(lastBit == bit - 1)
+                       {
+                               lastBit = bit;
+                               continue;
+                       }
+                       *buf++ = '/';
+               }
+               *buf++ = (bit >= 8) ? regA : regD;
+               *buf++ = '0' + (bit & 7);
+               lastBit = bit;
+               lastBitStart = bit;
+       }
+       if(lastBitStart >= 0 && lastBitStart != (bit - 1))
+       {
+               *buf++ = '-';
+               *buf++ = regA;
+               *buf++ = '7';
+       }
+       if(lastBit < 0)
+       {
+               *buf++ = '0';
+       }
+       *buf = 0;
+       return buf;
+}
+
+/***
+ *     Flip the bits in an unsigned short, for MOVEM RegList,-(An)
+ ***/
+static unsigned short  Disass68kFlipBits(unsigned short mask)
+{
+       unsigned short  retMask = 0;
+       int     i;
+
+       for(i=0; i<=15; ++i)
+               if(mask & (1 << i))
+                       retMask |= (1 << (15-i));
+       return retMask;
+}
+
+/***
+ *     Create a register list for the MOVEM opcode
+ ***/
+static char    *Disass68kFPUReglist(char *buf, unsigned char reglist)
+{
+       int bit;
+       int lastBit = -99;
+       int lastBitStart = -99;
+       char    regFP1 = options & doptRegisterSmall ? 'f' : 'F';
+       char    regFP2 = options & doptRegisterSmall ? 'p' : 'P';
+       for(bit=0; bit<=7; ++bit)
+       {
+               // bit clear?
+               if((reglist & (1 << bit)) == 0)
+               {
+                       // do we have a run? => close it!
+                       if(lastBitStart >= 0 && lastBitStart != (bit - 1))
+                       {
+                               *buf++ = '-';
+                               *buf++ = regFP1;
+                               *buf++ = regFP2;
+                               *buf++ = '0' + ((bit-1) & 7);
+                       }
+                       lastBitStart = -1;
+                       continue;
+               }
+               // separate bits, skip runs of bits to merge them later
+               if(lastBit >= 0)
+               {
+                       if(lastBit == bit - 1)
+                       {
+                               lastBit = bit;
+                               continue;
+                       }
+                       *buf++ = '/';
+               }
+               *buf++ = regFP1;
+               *buf++ = regFP2;
+               *buf++ = '0' + (bit & 7);
+               lastBit = bit;
+               lastBitStart = bit;
+       }
+       if(lastBitStart >= 0 && lastBitStart != (bit - 1))
+       {
+               *buf++ = '-';
+               *buf++ = regFP1;
+               *buf++ = regFP2;
+               *buf++ = '7';
+       }
+       if(lastBit < 0)
+       {
+               *buf++ = '0';
+       }
+       *buf = 0;
+       return buf;
+}
+
+
+/***
+ *     List of special cases for the operands
+ ***/
+typedef enum {
+       ofNone,
+       ofEa,
+       ofDn,
+       ofAn,
+       ofAni,
+       ofI,
+       ofSpecReg,
+       ofSpecExtReg,
+       ofD16An,
+       ofDestDn,
+       ofDestAn,
+       ofExtReg,
+       ofExtAnip,
+       ofExtReg0,
+       ofExtRegA0,
+       ofExtRegD04,
+       ofExtRegA05,
+       ofFPUReglist,
+       ofFPUSRRegList,
+       ofDestEa6,
+       ofDestAbsL,
+       ofIOpcode,
+       ofCAS,
+       ofCAS2,
+       ofI3,
+       ofExtIm,
+       ofExtIm32,
+       ofExtIm4,
+       ofExtIm10,
+       ofDisp,
+       ofPiAn,
+       ofDestPiAn,
+       ofAnip,
+       ofDestAnip,
+       ofBFEa,
+       ofRegList,
+       ofExt4Dn,
+       ofFPU,
+       ofFPUMOVE,
+       ofFMOVECR,
+       ofFPU3Reg,
+       ofLineA
+} Disass68kOpcodeFormat;
+
+
+/***
+ *     The order of the table is not important (with the exception of some FPU opcodes, which are commented further down),
+ *     as each opcode should decline if it doesn't match 100%. The 68k CPU also doesn't do guessing based on the context!
+ ***/
+typedef const struct {
+       int                             cpuMask;
+       unsigned long   opcodeMask[2*5];
+       signed char             operationSize[4];
+       char                    op[5];
+       const char              *opcodeName;
+       int                             parameter[5];
+       int                             disassFlag;
+} OpcodeTableStruct;
+
+static const OpcodeTableStruct OpcodeTable[] = {
+       { MC_ALL, {0xff00, 0x0000}, {-1,6,2,0}, {ofI,ofEa}, "ORI.?",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xf1c0, 0x0100}, {4}, {ofDestDn,ofEa}, "BTST",{0,EA_An|EA_Immed} },
+       { MC_ALL, {0xf1c0, 0x0140}, {4}, {ofDestDn,ofEa}, "BCHG",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xf1c0, 0x0180}, {4}, {ofDestDn,ofEa}, "BCLR",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xf1c0, 0x01C0}, {4}, {ofDestDn,ofEa}, "BSET",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL-MC68060, {0xf1f8, 0x0108}, {2}, {ofD16An,ofDestDn}, "MOVEP.W"},
+       { MC_ALL-MC68060, {0xf1f8, 0x0148}, {4}, {ofD16An,ofDestDn}, "MOVEP.L"},
+       { MC_ALL-MC68060, {0xf1f8, 0x0188}, {2}, {ofDestDn,ofD16An}, "MOVEP.W"},
+       { MC_ALL-MC68060, {0xf1f8, 0x01C8}, {4}, {ofDestDn,ofD16An}, "MOVEP.L"},
+       { MC_ALL, {0xff00, 0x0200}, {-1,6,2,0}, {ofI,ofEa}, "ANDI.?",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xff00, 0x0400}, {-1,6,2,0}, {ofI,ofEa}, "SUBI.?",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xff00, 0x0600}, {-1,6,2,0}, {ofI,ofEa}, "ADDI.?",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xffc0, 0x0800}, {1}, {ofI,ofEa}, "BTST",{0,EA_An|EA_Immed} },
+       { MC_ALL, {0xffc0, 0x0840}, {1}, {ofI,ofEa}, "BCHG",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xffc0, 0x0880}, {1}, {ofI,ofEa}, "BCLR",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xffc0, 0x08C0}, {1}, {ofI,ofEa}, "BSET",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xff00, 0x0A00}, {-1,6,2,0}, {ofI,ofEa}, "EORI.?",{0,EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xff00, 0x0C00}, {-1,6,2,0}, {ofI,ofEa}, "CMPI.?",{0,EA_Immed|EA_An}},
+       { MC_ALL, {0xffff, 0x003C}, {1}, {ofEa,ofSpecReg}, "ORI",{0,REG_CCR} },
+       { MC_ALL, {0xffff, 0x007C}, {2}, {ofEa,ofSpecReg}, "ORI",{0,REG_SR} },
+       { MC_ALL, {0xffff, 0x023C}, {1}, {ofEa,ofSpecReg}, "ANDI",{0,REG_CCR} },
+       { MC_ALL, {0xffff, 0x027C}, {2}, {ofEa,ofSpecReg}, "ANDI",{0,REG_SR} },
+       { MC_ALL, {0xffff, 0x0A3C}, {1}, {ofEa,ofSpecReg}, "EORI",{0,REG_CCR} },
+       { MC_ALL, {0xffff, 0x0A7C}, {2}, {ofEa,ofSpecReg}, "EORI",{0,REG_SR} },
+       { MC68020, {0xffc0, 0x06C0}, {1}, {ofEa}, "CALLM",{EA_Dn|EA_An|EA_Immed|EA_Anip|EA_piAn} },
+       { MC68020, {0xfff0, 0x06C0}, {1}, {ofEa}, "RTM"},
+       { MC_020, {0xf9c0, 0x00C0, 0x0fff,0x0000}, {-1,9,2,0}, {ofEa,ofExtReg}, "CMP2.?",{EA_Dn|EA_An|EA_Immed|EA_Anip|EA_piAn} },
+       { MC_020, {0xf9c0, 0x00C0, 0x0fff,0x0800}, {-1,9,2,0}, {ofEa,ofExtReg}, "CHK2.?",{EA_Dn|EA_An|EA_Immed|EA_Anip|EA_piAn} },
+       { MC_020&~MC_CPU32, {0xffc0, 0x0AC0, 0xFE38,0x0000}, {1}, {ofCAS,ofEa}, "CAS.B",{0,EA_Immed|EA_PCRel|EA_An|EA_Dn}},
+       { MC_020&~MC_CPU32, {0xffc0, 0x0CC0, 0xFE38,0x0000}, {2}, {ofCAS,ofEa}, "CAS.W",{0,EA_Immed|EA_PCRel|EA_An|EA_Dn}},
+       { MC_020&~MC_CPU32, {0xffc0, 0x0EC0, 0xFE38,0x0000}, {4}, {ofCAS,ofEa}, "CAS.L",{0,EA_Immed|EA_PCRel|EA_An|EA_Dn}},
+       { MC_020&~MC_CPU32, {0xffff, 0x0CFC, 0x0E38,0x0000, 0x0E38,0x0000}, {2}, {ofCAS2}, "CAS2.W"},
+       { MC_020&~MC_CPU32, {0xffff, 0x0EFC, 0x0E38,0x0000, 0x0E38,0x0000}, {4}, {ofCAS2}, "CAS2.L"},
+       { MC68010|MC_020, {0xff00, 0x0e00, 0x0fff,0x0000}, {-1,6,2,0}, {ofEa,ofExtReg}, "MOVES.?",{EA_Immed|EA_PCRel|EA_An|EA_Dn,0}},
+       { MC68010|MC_020, {0xff00, 0x0e00, 0x0fff,0x0800}, {-1,6,2,0}, {ofExtReg,ofEa}, "MOVES.?",{0,EA_Immed|EA_PCRel|EA_An|EA_Dn}},
+
+       { MC_ALL, {0xf000, 0x1000}, {1}, {ofEa,ofDestEa6}, "MOVE.B"},
+
+       { MC_ALL, {0xf000, 0x2000}, {4}, {ofEa,ofDestEa6}, "MOVE.L"},
+       { MC_ALL, {0xf1c0, 0x2040}, {4}, {ofEa,ofDestAn}, "MOVEA.L",{0},1},
+
+       { MC_ALL, {0xf000, 0x3000}, {2}, {ofEa,ofDestEa6}, "MOVE.W"},
+       { MC_ALL, {0xf1c0, 0x3040}, {2}, {ofEa,ofDestAn}, "MOVEA.W",{0},1},
+
+       { MC_ALL, {0xff00, 0x4000}, {-1,6,2,0}, {ofEa}, "NEGX.?",{EA_Immed|EA_PCRel|EA_An}},
+       { MC_020, {0xf1c0, 0x4100}, {4}, {ofEa,ofDestDn}, "CHK.L", {EA_An,0}},
+       { MC_ALL, {0xf1c0, 0x4180}, {2}, {ofEa,ofDestDn}, "CHK.W", {EA_An,0}},
+       { MC_ALL, {0xf1c0, 0x41c0}, {4}, {ofEa,ofDestAn}, "LEA",{EA_Dn|EA_An|EA_Immed|EA_Anip|EA_piAn,0},1 },
+       { MC_ALL, {0xff00, 0x4200}, {-1,6,2,0}, {ofEa}, "CLR.?",{EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xff00, 0x4400}, {-1,6,2,0}, {ofEa}, "NEG.?",{EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xff00, 0x4600}, {-1,6,2,0}, {ofEa}, "NOT.?",{EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xffc0, 0x40c0}, {2}, {ofSpecReg,ofEa}, "MOVE",{REG_SR,EA_Immed|EA_PCRel|EA_An} },
+       { MC_ALL, {0xffc0, 0x42c0}, {1}, {ofSpecReg,ofEa}, "MOVE",{REG_CCR,EA_Immed|EA_PCRel|EA_An} },
+       { MC_ALL, {0xffc0, 0x44c0}, {1}, {ofEa,ofSpecReg}, "MOVE",{EA_An,REG_CCR} },
+       { MC_ALL, {0xffc0, 0x46c0}, {2}, {ofEa,ofSpecReg}, "MOVE",{EA_An,REG_SR} },
+       { MC_ALL, {0xffc0, 0x4800}, {1}, {ofEa}, "NBCD",{EA_Immed|EA_PCRel|EA_An}},
+       { MC_020, {0xfff8, 0x4808}, {4}, {ofEa,ofI}, "LINK.L"},
+       { MC_ALL, {0xffc0, 0x4840}, {0}, {ofEa}, "PEA",{EA_Dn|EA_An|EA_Immed|EA_Anip|EA_piAn},1 },
+       { MC_ALL, {0xfff8, 0x4840}, {4}, {ofEa}, "SWAP"},
+       { MC68010|MC_020, {0xfff8, 0x4848}, {0}, {ofIOpcode}, "BKPT",{0x07} },
+       { MC_ALL, {0xffc0, 0x4880, 0x10000}, {2}, {ofRegList,ofEa}, "MOVEM.W",{0,EA_Dn|EA_An|EA_Immed|EA_Anip|EA_PCRel} },
+       { MC_ALL, {0xffc0, 0x48c0, 0x10000}, {4}, {ofRegList,ofEa}, "MOVEM.L",{0,EA_Dn|EA_An|EA_Immed|EA_Anip|EA_PCRel} },
+       { MC_ALL, {0xfff8, 0x4880}, {2}, {ofEa}, "EXT.W"},
+       { MC_ALL, {0xfff8, 0x48c0}, {4}, {ofEa}, "EXT.L"},
+       { MC_020, {0xfff8, 0x49c0}, {4}, {ofEa}, "EXTB.L"},
+       { MC_ALL, {0xff00, 0x4a00}, {-1,6,2,0}, {ofEa}, "TST.?"},
+       { MC_ALL, {0xffc0, 0x4ac0}, {1}, {ofEa}, "TAS",{EA_Immed|EA_PCRel|EA_An}},
+       { MC_CPU32, {0xffff, 0x4afa}, {0}, {ofNone}, "BGND"},
+       { MC_ALL, {0xffff, 0x4afc}, {0}, {ofNone}, "ILLEGAL"},
+       { MC_020, {0xffc0, 0x4c00, 0x8ff8, 0x0000}, {4}, {ofEa,ofExtReg}, "MULU.L", {EA_An,0}},
+       { MC_020, {0xffc0, 0x4c00, 0x8ff8, 0x0800}, {4}, {ofEa,ofExtReg}, "MULS.L", {EA_An,0}},
+       { MC_020, {0xffc0, 0x4c40, 0x8ff8, 0x0000}, {4}, {ofEa,ofExtReg}, "DIVU.L", {EA_An,0}},
+       { MC_020, {0xffc0, 0x4c40, 0x8ff8, 0x0800}, {4}, {ofEa,ofExtReg}, "DIVS.L", {EA_An,0}},
+       { MC_020, {0xffc0, 0x4c00, 0x8ff8, 0x0400}, {4}, {ofEa,ofExtReg,ofExtReg0}, "MULU.L", {EA_An,0,0}},
+       { MC_020, {0xffc0, 0x4c00, 0x8ff8, 0x0c00}, {4}, {ofEa,ofExtReg,ofExtReg0}, "MULS.L", {EA_An,0,0}},
+       { MC_020, {0xffc0, 0x4c40, 0x8ff8, 0x0400}, {4}, {ofEa,ofExtReg,ofExtReg0}, "DIVU.L", {EA_An,0,0}},
+       { MC_020, {0xffc0, 0x4c40, 0x8ff8, 0x0c00}, {4}, {ofEa,ofExtReg,ofExtReg0}, "DIVS.L", {EA_An,0,0}},
+       { MC_ALL, {0xffc0, 0x4c80, 0x10000}, {2}, {ofEa,ofRegList}, "MOVEM.W",{EA_Dn|EA_An|EA_Immed|EA_piAn,0} },
+       { MC_ALL, {0xffc0, 0x4cc0, 0x10000}, {4}, {ofEa,ofRegList}, "MOVEM.L",{EA_Dn|EA_An|EA_Immed|EA_piAn,0} },
+       { MC_ALL, {0xfff0, 0x4e40}, {0}, {ofIOpcode}, "TRAP",{0x0f} },
+       { MC_ALL, {0xfff8, 0x4e50}, {2}, {ofAn,ofI}, "LINK"},
+       { MC_ALL, {0xfff8, 0x4e58}, {4}, {ofAn}, "UNLK"},
+       { MC_ALL, {0xfff8, 0x4e60}, {4}, {ofAn,ofSpecReg}, "MOVE",{0,REG_USP} },
+       { MC_ALL, {0xfff8, 0x4e68}, {4}, {ofSpecReg,ofAn}, "MOVE",{REG_USP,0} },
+       { MC_ALL, {0xffff, 0x4e70}, {0}, {ofNone}, "RESET"},
+       { MC_ALL, {0xffff, 0x4e71}, {0}, {ofNone}, "NOP"},
+       { MC_ALL, {0xffff, 0x4e72}, {2}, {ofI}, "STOP"},
+       { MC_ALL, {0xffff, 0x4e73}, {0}, {ofNone}, "RTE"},
+       { MC68010|MC_020, {0xffff, 0x4e74}, {2}, {ofI}, "RTD"},
+       { MC_ALL, {0xffff, 0x4e75}, {0}, {ofNone}, "RTS"},
+       { MC_ALL, {0xffff, 0x4e76}, {0}, {ofNone}, "TRAPV"},
+       { MC_ALL, {0xffff, 0x4e77}, {0}, {ofNone}, "RTR"},
+       { MC68010|MC_020, {0xffff, 0x4e7a, 0x10000}, {4}, {ofSpecExtReg,ofExtReg}, "MOVEC"},
+       { MC68010|MC_020, {0xffff, 0x4e7b, 0x10000}, {4}, {ofExtReg,ofSpecExtReg}, "MOVEC"},
+       { MC_ALL, {0xffc0, 0x4e80}, {0}, {ofEa}, "JSR",{EA_Dn|EA_An|EA_Immed|EA_Anip|EA_piAn} },
+       { MC_ALL, {0xffc0, 0x4ec0}, {0}, {ofEa}, "JMP",{EA_Dn|EA_An|EA_Immed|EA_Anip|EA_piAn} },
+
+       { MC_ALL, {0xf1c0, 0x5000}, {1}, {ofI3,ofEa}, "ADDQ.B",{0,EA_An|EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xf1c0, 0x5040}, {2}, {ofI3,ofEa}, "ADDQ.W",{0,EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xf1c0, 0x5080}, {4}, {ofI3,ofEa}, "ADDQ.L",{0,EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xf0c0, 0x50C0}, {1}, {ofEa}, "Sci",{EA_Immed|EA_PCRel|EA_An}},
+       { MC_ALL, {0xf0f8, 0x50C8}, {2}, {ofDn,ofDisp}, "DBcd"},
+       { MC_020, {0xf0ff, 0x50fa}, {2}, {ofI}, "TRAPci.W"},
+       { MC_020, {0xf0ff, 0x50fb}, {4}, {ofI}, "TRAPci.L"},
+       { MC_020, {0xf0ff, 0x50fc}, {0}, {ofNone}, "TRAPci"},
+       { MC_ALL, {0xf1c0, 0x5100}, {1}, {ofI3,ofEa}, "SUBQ.B",{0,EA_An|EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xf1c0, 0x5140}, {2}, {ofI3,ofEa}, "SUBQ.W",{0,EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xf1c0, 0x5180}, {4}, {ofI3,ofEa}, "SUBQ.L",{0,EA_Immed|EA_PCRel} },
+
+       { MC_ALL, {0xf0ff, 0x6000}, {2}, {ofDisp}, "Bcb"},
+       { MC_ALL, {0xf000, 0x6000}, {1}, {ofDisp}, "Bcb.S"},
+       { MC_020, {0xf0ff, 0x60FF}, {4}, {ofDisp}, "Bcb.L"},
+
+       { MC_ALL, {0xf100, 0x7000}, {0}, {ofIOpcode,ofDestDn}, "MOVEQ", {0xFF,0}},
+
+       { MC_ALL, {0xf100, 0x8000}, {-1,6,2,0}, {ofEa,ofDestDn}, "OR.?", {EA_An,0}},
+       { MC_ALL, {0xf100, 0x8100}, {-1,6,2,0}, {ofDestDn,ofEa}, "OR.?",{0,EA_Immed|EA_PCRel|EA_An|EA_Dn}},
+       { MC_ALL, {0xf1f8, 0x8100}, {1}, {ofDn,ofDestDn}, "SBCD"},
+       { MC_ALL, {0xf1f8, 0x8108}, {1}, {ofPiAn,ofDestPiAn}, "SBCD"},
+       { MC_020&~MC_CPU32, {0xf1f8, 0x8140, 0x10000}, {0}, {ofDn,ofDestDn,ofExtIm}, "PACK"},
+       { MC_020&~MC_CPU32, {0xf1f8, 0x8148, 0x10000}, {0}, {ofPiAn,ofDestPiAn,ofExtIm}, "PACK"},
+       { MC_020&~MC_CPU32, {0xf1f8, 0x8180, 0x10000}, {0}, {ofDn,ofDestDn,ofExtIm}, "UNPK"},
+       { MC_020&~MC_CPU32, {0xf1f8, 0x8188, 0x10000}, {0}, {ofPiAn,ofDestPiAn,ofExtIm}, "UNPK"},
+       { MC_ALL, {0xf1c0, 0x80c0}, {2}, {ofEa,ofDestDn}, "DIVU.W", {EA_An,0}},
+       { MC_ALL, {0xf1c0, 0x81c0}, {2}, {ofEa,ofDestDn}, "DIVS.W", {EA_An,0}},
+
+       { MC_ALL, {0xf1c0, 0x9000}, {1}, {ofEa,ofDestDn}, "SUB.B", {EA_An,0}},
+       { MC_ALL, {0xf1c0, 0x9040}, {2}, {ofEa,ofDestDn}, "SUB.W"},
+       { MC_ALL, {0xf1c0, 0x9080}, {4}, {ofEa,ofDestDn}, "SUB.L"},
+       { MC_ALL, {0xf1c0, 0x90c0}, {2}, {ofEa,ofDestAn}, "SUBA.W"},
+       { MC_ALL, {0xf1c0, 0x91c0}, {4}, {ofEa,ofDestAn}, "SUBA.L"},
+       { MC_ALL, {0xf100, 0x9100}, {-1,6,2,0}, {ofDestDn,ofEa}, "SUB.?",{0,EA_Immed|EA_PCRel|EA_An|EA_Dn}},
+       { MC_ALL, {0xf138, 0x9100}, {-1,6,2,0}, {ofDn,ofDestDn}, "SUBX.?"},
+       { MC_ALL, {0xf138, 0x9108}, {-1,6,2,0}, {ofPiAn,ofDestPiAn}, "SUBX.?"},
+
+       { MC_ALL, {0xf000, 0xa000}, {0}, {ofLineA}, "LINEA"},
+
+       { MC_ALL, {0xf1c0, 0xb000}, {1}, {ofEa,ofDestDn}, "CMP.B", {EA_An,0}},
+       { MC_ALL, {0xf1c0, 0xb040}, {2}, {ofEa,ofDestDn}, "CMP.W"},
+       { MC_ALL, {0xf1c0, 0xb080}, {4}, {ofEa,ofDestDn}, "CMP.L"},
+       { MC_ALL, {0xf1c0, 0xb0c0}, {2}, {ofEa,ofDestAn}, "CMPA.W"},
+       { MC_ALL, {0xf1c0, 0xb1c0}, {4}, {ofEa,ofDestAn}, "CMPA.L"},
+       { MC_ALL, {0xf100, 0xb100}, {-1,6,2,0}, {ofDestDn,ofEa}, "EOR.?",{0,EA_An|EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xf138, 0xb108}, {-1,6,2,0}, {ofAnip,ofDestAnip}, "CMPM.?"},
+
+       { MC_ALL, {0xf100, 0xc000}, {-1,6,2,0}, {ofEa,ofDestDn}, "AND.?", {EA_An,0}},
+       { MC_ALL, {0xf100, 0xc100}, {-1,6,2,0}, {ofDestDn,ofEa}, "AND.?",{0,EA_Immed|EA_PCRel|EA_An|EA_Dn}},
+       { MC_ALL, {0xf1f8, 0xc100}, {1}, {ofDn,ofDestDn}, "ABCD"},
+       { MC_ALL, {0xf1f8, 0xc108}, {1}, {ofPiAn,ofDestPiAn}, "ABCD"},
+       { MC_ALL, {0xf1f8, 0xc140}, {1}, {ofDestDn,ofDn}, "EXG"},
+       { MC_ALL, {0xf1f8, 0xc148}, {1}, {ofDestAn,ofAn}, "EXG"},
+       { MC_ALL, {0xf1f8, 0xc188}, {1}, {ofDestDn,ofAn}, "EXG"},
+       { MC_ALL, {0xf1c0, 0xc0c0}, {2}, {ofEa,ofDestDn}, "MULU.W", {EA_An,0}},
+       { MC_ALL, {0xf1c0, 0xc1c0}, {2}, {ofEa,ofDestDn}, "MULS.W", {EA_An,0}},
+
+       { MC_ALL, {0xf1c0, 0xd000}, {1}, {ofEa,ofDestDn}, "ADD.B", {EA_An,0}},
+       { MC_ALL, {0xf1c0, 0xd040}, {2}, {ofEa,ofDestDn}, "ADD.W"},
+       { MC_ALL, {0xf1c0, 0xd080}, {4}, {ofEa,ofDestDn}, "ADD.L"},
+       { MC_ALL, {0xf1c0, 0xd0c0}, {2}, {ofEa,ofDestAn}, "ADDA.W"},
+       { MC_ALL, {0xf1c0, 0xd1c0}, {4}, {ofEa,ofDestAn}, "ADDA.L"},
+       { MC_ALL, {0xf100, 0xd100}, {-1,6,2,0}, {ofDestDn,ofEa}, "ADD.?",{0,EA_Immed|EA_PCRel|EA_An|EA_Dn}},
+       { MC_ALL, {0xf138, 0xd100}, {-1,6,2,0}, {ofDn,ofDestDn}, "ADDX.?"},
+       { MC_ALL, {0xf138, 0xd108}, {-1,6,2,0}, {ofPiAn,ofDestPiAn}, "ADDX.?"},
+
+       { MC_ALL, {0xf138, 0xe000}, {-1,6,2,0}, {ofI3,ofDn}, "ASR.?"},
+       { MC_ALL, {0xf138, 0xe008}, {-1,6,2,0}, {ofI3,ofDn}, "LSR.?"},
+       { MC_ALL, {0xf138, 0xe010}, {-1,6,2,0}, {ofI3,ofDn}, "ROXR.?"},
+       { MC_ALL, {0xf138, 0xe018}, {-1,6,2,0}, {ofI3,ofDn}, "ROR.?"},
+       { MC_ALL, {0xf138, 0xe020}, {-1,6,2,0}, {ofDestDn,ofDn}, "ASR.?"},
+       { MC_ALL, {0xf138, 0xe028}, {-1,6,2,0}, {ofDestDn,ofDn}, "LSR.?"},
+       { MC_ALL, {0xf138, 0xe030}, {-1,6,2,0}, {ofDestDn,ofDn}, "ROXR.?"},
+       { MC_ALL, {0xf138, 0xe038}, {-1,6,2,0}, {ofDestDn,ofDn}, "ROR.?"},
+       { MC_ALL, {0xf138, 0xe100}, {-1,6,2,0}, {ofI3,ofDn}, "ASL.?"},
+       { MC_ALL, {0xf138, 0xe108}, {-1,6,2,0}, {ofI3,ofDn}, "LSL.?"},
+       { MC_ALL, {0xf138, 0xe110}, {-1,6,2,0}, {ofI3,ofDn}, "ROXL.?"},
+       { MC_ALL, {0xf138, 0xe118}, {-1,6,2,0}, {ofI3,ofDn}, "ROL.?"},
+       { MC_ALL, {0xf138, 0xe120}, {-1,6,2,0}, {ofDestDn,ofDn}, "ASL.?"},
+       { MC_ALL, {0xf138, 0xe128}, {-1,6,2,0}, {ofDestDn,ofDn}, "LSL.?"},
+       { MC_ALL, {0xf138, 0xe130}, {-1,6,2,0}, {ofDestDn,ofDn}, "ROXL.?"},
+       { MC_ALL, {0xf138, 0xe138}, {-1,6,2,0}, {ofDestDn,ofDn}, "ROL.?"},
+       { MC_ALL, {0xffc0, 0xe0c0}, {1}, {ofEa}, "ASR",{EA_Dn|EA_An|EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xffc0, 0xe1c0}, {1}, {ofEa}, "ASL",{EA_Dn|EA_An|EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xffc0, 0xe2c0}, {1}, {ofEa}, "LSR",{EA_Dn|EA_An|EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xffc0, 0xe3c0}, {1}, {ofEa}, "LSL",{EA_Dn|EA_An|EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xffc0, 0xe4c0}, {1}, {ofEa}, "ROXR",{EA_Dn|EA_An|EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xffc0, 0xe5c0}, {1}, {ofEa}, "ROXL",{EA_Dn|EA_An|EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xffc0, 0xe6c0}, {1}, {ofEa}, "ROR",{EA_Dn|EA_An|EA_Immed|EA_PCRel} },
+       { MC_ALL, {0xffc0, 0xe7c0}, {1}, {ofEa}, "ROL",{EA_Dn|EA_An|EA_Immed|EA_PCRel} },
+       { MC_020&~MC_CPU32, {0xffc0, 0xe8c0, 0xf000, 0x0000}, {1}, {ofBFEa}, "BFTST",{EA_An|EA_piAn|EA_Anip|EA_Immed}},
+       { MC_020&~MC_CPU32, {0xffc0, 0xe9c0, 0x8000, 0x0000}, {1}, {ofBFEa,ofExtReg}, "BFEXTU",{EA_An|EA_piAn|EA_Anip|EA_Immed}},
+       { MC_020&~MC_CPU32, {0xffc0, 0xeac0, 0xf000, 0x0000}, {1}, {ofBFEa}, "BFCHG",{EA_An|EA_piAn|EA_Anip|EA_Immed|EA_PCRel} },
+       { MC_020&~MC_CPU32, {0xffc0, 0xebc0, 0x8000, 0x0000}, {1}, {ofBFEa,ofExtReg}, "BFEXTS",{EA_An|EA_piAn|EA_Anip|EA_Immed}},
+       { MC_020&~MC_CPU32, {0xffc0, 0xecc0, 0xf000, 0x0000}, {1}, {ofBFEa}, "BFCLR",{EA_An|EA_piAn|EA_Anip|EA_Immed|EA_PCRel} },
+       { MC_020&~MC_CPU32, {0xffc0, 0xedc0, 0x8000, 0x0000}, {1}, {ofBFEa,ofExtReg}, "BFFFO",{EA_An|EA_piAn|EA_Anip|EA_Immed}},
+       { MC_020&~MC_CPU32, {0xffc0, 0xeec0, 0xf000, 0x0000}, {1}, {ofBFEa}, "BFSET",{EA_An|EA_piAn|EA_Anip|EA_Immed}},
+       { MC_020&~MC_CPU32, {0xffc0, 0xefc0, 0x8000, 0x0000}, {1}, {ofExtReg,ofBFEa}, "BFINS",{0,EA_An|EA_piAn|EA_Anip|EA_Immed|EA_PCRel} },
+
+
+       #define PMMU_COPROC_ID          0       // 0 is the standard PMMU
+
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x2000}, {0}, {ofSpecReg,ofEa}, "PLOADW",{REG_SFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x2001}, {0}, {ofSpecReg,ofEa}, "PLOADW",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xfff8, 0x2008}, {0}, {ofExtReg0,ofEa}, "PLOADW",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xfff0, 0x2010}, {0}, {ofExtIm4,ofEa}, "PLOADW",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x2200}, {0}, {ofSpecReg,ofEa}, "PLOADR",{REG_SFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x2201}, {0}, {ofSpecReg,ofEa}, "PLOADR",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xfff8, 0x2208}, {0}, {ofExtReg0,ofEa}, "PLOADR",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xfff0, 0x2210}, {0}, {ofExtIm4,ofEa}, "PLOADR",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+
+       { MC_PMMU, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0xa000}, {0}, {ofEa}, "PFLUSHR",{EA_Dn|EA_An} },
+
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x0800}, {0}, {ofEa,ofSpecReg}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TT0} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x0900}, {0}, {ofEa,ofSpecReg}, "PMOVEFD",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TT0} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x0B00}, {0}, {ofSpecReg,ofEa}, "PMOVEFD",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TT0} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x0C00}, {0}, {ofEa,ofSpecReg}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TT1} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x0C00}, {0}, {ofSpecReg,ofEa}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TT0} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x0D00}, {0}, {ofEa,ofSpecReg}, "PMOVEFD",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TT1} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x0E00}, {0}, {ofSpecReg,ofEa}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TT1} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x0F00}, {0}, {ofSpecReg,ofEa}, "PMOVEFD",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TT1} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4000}, {0}, {ofEa,ofSpecReg}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TC} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4100}, {0}, {ofEa,ofSpecReg}, "PMOVEFD",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TC} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4200}, {0}, {ofSpecReg,ofEa}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TC} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4300}, {0}, {ofSpecReg,ofEa}, "PMOVEFD",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_TC} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4800}, {0}, {ofEa,ofSpecReg}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_SRP} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4900}, {0}, {ofEa,ofSpecReg}, "PMOVEFD",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_SRP} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4A00}, {0}, {ofSpecReg,ofEa}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_SRP} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4B00}, {0}, {ofSpecReg,ofEa}, "PMOVEFD",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_SRP} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4C00}, {0}, {ofEa,ofSpecReg}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_CRP} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4D00}, {0}, {ofEa,ofSpecReg}, "PMOVEFD",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_CRP} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4e00}, {0}, {ofSpecReg,ofEa}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_CRP} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x4f00}, {0}, {ofSpecReg,ofEa}, "PMOVEFD",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_CRP} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x6000}, {0}, {ofEa,ofSpecReg}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_MMUSR} },
+       { MC_PMMU|MC68030, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x6200}, {0}, {ofSpecReg,ofEa}, "PMOVE",{EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel,REG_MMUSR} },
+
+       { MC_PMMU, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xffff, 0x2800}, {0}, {ofSpecReg,ofEa}, "PVALID",{REG_VAL,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xfff8, 0x2C00}, {0}, {ofExtRegA0,ofEa}, "PVALID",{0,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe3ff, 0x8000}, {0}, {ofSpecReg,ofEa,ofExtIm10}, "PTESTW",{REG_SFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe3ff, 0x8001}, {0}, {ofSpecReg,ofEa,ofExtIm10}, "PTESTW",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe3f8, 0x8008}, {0}, {ofExtReg0,ofEa,ofExtIm10}, "PTESTW",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe3f0, 0x8010}, {0}, {ofExtIm4,ofEa,ofExtIm10}, "PTESTW",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe3ff, 0x8200}, {0}, {ofSpecReg,ofEa,ofExtIm10}, "PTESTR",{REG_SFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe3ff, 0x8201}, {0}, {ofSpecReg,ofEa,ofExtIm10}, "PTESTR",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe3f8, 0x8208}, {0}, {ofExtReg0,ofEa,ofExtIm10}, "PTESTR",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe3f0, 0x8210}, {0}, {ofExtIm4,ofEa,ofExtIm10}, "PTESTR",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe31f, 0x8100}, {0}, {ofSpecReg,ofEa,ofExtIm10,ofExtRegA05}, "PTESTW",{REG_SFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe31f, 0x8101}, {0}, {ofSpecReg,ofEa,ofExtIm10,ofExtRegA05}, "PTESTW",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe318, 0x8108}, {0}, {ofExtReg0,ofEa,ofExtIm10,ofExtRegA05}, "PTESTW",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe310, 0x8110}, {0}, {ofExtIm4,ofEa,ofExtIm10,ofExtRegA05}, "PTESTW",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe31f, 0x8300}, {0}, {ofSpecReg,ofEa,ofExtIm10,ofExtRegA05}, "PTESTR",{REG_SFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe31f, 0x8301}, {0}, {ofSpecReg,ofEa,ofExtIm10,ofExtRegA05}, "PTESTR",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe318, 0x8308}, {0}, {ofExtReg0,ofEa,ofExtIm10,ofExtRegA05}, "PTESTR",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+       { MC_PMMU|MC68030|MC68040|MC68LC040, {0xffc0, 0xf000|(PMMU_COPROC_ID<<9), 0xe310, 0x8310}, {0}, {ofExtIm4,ofEa,ofExtIm10,ofExtRegA05}, "PTESTR",{REG_DFC,EA_Dn|EA_An|EA_Anip|EA_piAn|EA_Immed|EA_PCRel} },
+
+       { MC_PMMU, {0xffc0, 0xf040|(PMMU_COPROC_ID<<9), 0xfff0, 0x8310}, {0}, {ofEa}, "PScp",{EA_An|EA_Immed|EA_PCRel} },
+       { MC_PMMU, {0xfff8, 0xf048|(PMMU_COPROC_ID<<9), 0xfff0, 0x0000}, {2}, {ofDn,ofDisp}, "PDBcp"},
+       { MC_PMMU, {0xffff, 0xf07A|(PMMU_COPROC_ID<<9), 0xfff0, 0x0000, 0x10000,0x0000}, {2}, {ofExtIm32}, "PTRAPcp.W" },
+       { MC_PMMU, {0xffff, 0xf07B|(PMMU_COPROC_ID<<9), 0xfff0, 0x0000, 0x10000,0x0000}, {4}, {ofExtIm32}, "PTRAPcp.L" },
+       { MC_PMMU, {0xffff, 0xf07C|(PMMU_COPROC_ID<<9), 0xfff0, 0x0000}, {0}, {ofNone}, "PTRAPcp" },
+       { MC_PMMU, {0xfff0, 0xf080|(PMMU_COPROC_ID<<9)}, {2}, {ofDisp}, "PBcp.W"},
+       { MC_PMMU, {0xfff0, 0xf0C0|(PMMU_COPROC_ID<<9)}, {4}, {ofDisp}, "PBcp.L"},
+       { MC_PMMU, {0xffc0, 0xf100|(PMMU_COPROC_ID<<9)}, {0}, {ofEa}, "PSAVE",{EA_Dn|EA_An|EA_Anip|EA_Immed} },
+       { MC_PMMU, {0xffc0, 0xf140|(PMMU_COPROC_ID<<9)}, {0}, {ofEa}, "PRESTORE",{EA_Dn|EA_An|EA_piAn|EA_Immed} },
+
+
+       #define MC040_COPROC_ID         3       // 3 is the code for some 68040/68060 opcodes
+
+       { MC68040|MC68060, {0xfff8, 0xf000|(MC040_COPROC_ID<<9), 0x8fff, 0x8000}, {0}, {ofAnip,ofDestAbsL}, "MOVE16"},
+       { MC68040|MC68060, {0xfff8, 0xf008|(MC040_COPROC_ID<<9), 0x8fff, 0x8000}, {0}, {ofDestAbsL,ofAnip}, "MOVE16"},
+       { MC68040|MC68060, {0xfff8, 0xf010|(MC040_COPROC_ID<<9), 0x8fff, 0x8000}, {0}, {ofAni,ofDestAbsL}, "MOVE16"},
+       { MC68040|MC68060, {0xfff8, 0xf018|(MC040_COPROC_ID<<9), 0x8fff, 0x8000}, {0}, {ofDestAbsL,ofAni}, "MOVE16"},
+       { MC68040|MC68060, {0xfff8, 0xf020|(MC040_COPROC_ID<<9), 0x8fff, 0x8000}, {0}, {ofAnip,ofExtAnip}, "MOVE16"},
+
+
+       #define CPU32_COPROC_ID         4       // 4 is the code for some CPU32 opcodes
+
+       { MC68040|MC68060, {0xfff8, 0xf008|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVL",{REG_CACHES_NONE} },
+       { MC68040|MC68060, {0xfff8, 0xf048|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVL",{REG_CACHES_DC} },
+       { MC68040|MC68060, {0xfff8, 0xf088|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVL",{REG_CACHES_IC} },
+       { MC68040|MC68060, {0xfff8, 0xf0C8|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVL",{REG_CACHES_ICDC} },
+
+       { MC68040|MC68060, {0xfff8, 0xf010|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVP",{REG_CACHES_NONE} },
+       { MC68040|MC68060, {0xfff8, 0xf050|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVP",{REG_CACHES_DC} },
+       { MC68040|MC68060, {0xfff8, 0xf090|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVP",{REG_CACHES_IC} },
+       { MC68040|MC68060, {0xfff8, 0xf0D0|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVP",{REG_CACHES_ICDC} },
+
+       { MC68040|MC68060, {0xfff8, 0xf018|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVA",{REG_CACHES_NONE} },
+       { MC68040|MC68060, {0xfff8, 0xf058|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVA",{REG_CACHES_DC} },
+       { MC68040|MC68060, {0xfff8, 0xf098|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVA",{REG_CACHES_IC} },
+       { MC68040|MC68060, {0xfff8, 0xf0D8|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CINVA",{REG_CACHES_ICDC} },
+
+       { MC68040|MC68060, {0xfff8, 0xf028|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHL",{REG_CACHES_NONE} },
+       { MC68040|MC68060, {0xfff8, 0xf068|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHL",{REG_CACHES_DC} },
+       { MC68040|MC68060, {0xfff8, 0xf0A8|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHL",{REG_CACHES_IC} },
+       { MC68040|MC68060, {0xfff8, 0xf0E8|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHL",{REG_CACHES_ICDC} },
+
+       { MC68040|MC68060, {0xfff8, 0xf030|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHP",{REG_CACHES_NONE} },
+       { MC68040|MC68060, {0xfff8, 0xf070|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHP",{REG_CACHES_DC} },
+       { MC68040|MC68060, {0xfff8, 0xf0B0|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHP",{REG_CACHES_IC} },
+       { MC68040|MC68060, {0xfff8, 0xf0F0|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHP",{REG_CACHES_ICDC} },
+
+       { MC68040|MC68060, {0xfff8, 0xf038|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHA",{REG_CACHES_NONE} },
+       { MC68040|MC68060, {0xfff8, 0xf078|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHA",{REG_CACHES_DC} },
+       { MC68040|MC68060, {0xfff8, 0xf0B8|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHA",{REG_CACHES_IC} },
+       { MC68040|MC68060, {0xfff8, 0xf0F8|(CPU32_COPROC_ID<<9)}, {0}, {ofSpecReg,ofAn}, "CPUSHA",{REG_CACHES_ICDC} },
+
+       { MC_CPU32, {0xffc0, 0xf000|(CPU32_COPROC_ID<<9), 0x8f08, 0x0100}, {-1,16+6,2,0}, {ofExt4Dn}, "TBLU.?" },
+       { MC_CPU32, {0xffc0, 0xf000|(CPU32_COPROC_ID<<9), 0x8f3f, 0x0100}, {-1,16+6,2,0}, {ofExtReg,ofEa}, "TBLU.?",{EA_An|EA_An|EA_Anip|EA_Immed|EA_PCRel} },
+       { MC_CPU32, {0xffc0, 0xf000|(CPU32_COPROC_ID<<9), 0x8f28, 0x0500}, {-1,16+6,2,0}, {ofExt4Dn}, "TBLUN.?" },
+       { MC_CPU32, {0xffc0, 0xf000|(CPU32_COPROC_ID<<9), 0x8f3f, 0x0500}, {-1,16+6,2,0}, {ofExtReg,ofEa}, "TBLUN.?",{EA_An|EA_An|EA_Anip|EA_Immed|EA_PCRel} },
+
+       { MC_CPU32, {0xffc0, 0xf000|(CPU32_COPROC_ID<<9), 0x8f08, 0x0900}, {-1,16+6,2,0}, {ofExt4Dn}, "TBLS.?" },
+       { MC_CPU32, {0xffc0, 0xf000|(CPU32_COPROC_ID<<9), 0x8f3f, 0x0900}, {-1,16+6,2,0}, {ofExtReg,ofEa}, "TBLS.?",{EA_An|EA_An|EA_Anip|EA_Immed|EA_PCRel} },
+       { MC_CPU32, {0xffc0, 0xf000|(CPU32_COPROC_ID<<9), 0x8f28, 0x0D00}, {-1,16+6,2,0}, {ofExt4Dn}, "TBLSN.?" },
+       { MC_CPU32, {0xffc0, 0xf000|(CPU32_COPROC_ID<<9), 0x8f3f, 0x0D00}, {-1,16+6,2,0}, {ofExtReg,ofEa}, "TBLSN.?",{EA_An|EA_An|EA_Anip|EA_Immed|EA_PCRel} },
+
+       { MC_CPU32, {0xffff, 0xf000|(CPU32_COPROC_ID<<9), 0xffff, 0x01C0}, {2}, {ofI}, "LPSTOP" },
+
+
+       #define FPU_COPROC_ID           1       // 1 is the standard FPU, required to be 1 for the 68040 anyway
+
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0000}, {-1,16+10,3,1}, {ofFPU}, "FMOVE.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0001}, {-1,16+10,3,1}, {ofFPU}, "FINT.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0002}, {-1,16+10,3,1}, {ofFPU}, "FSINH.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0003}, {-1,16+10,3,1}, {ofFPU}, "FINTRZ.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0004}, {-1,16+10,3,1}, {ofFPU}, "FSQRT.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0006}, {-1,16+10,3,1}, {ofFPU}, "FLOGNP1.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0008}, {-1,16+10,3,1}, {ofFPU}, "FETOXM1.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0009}, {-1,16+10,3,1}, {ofFPU}, "FTANH.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x000A}, {-1,16+10,3,1}, {ofFPU}, "FATAN.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x000C}, {-1,16+10,3,1}, {ofFPU}, "FASIN.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x000D}, {-1,16+10,3,1}, {ofFPU}, "FATANH.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x000E}, {-1,16+10,3,1}, {ofFPU}, "FSIN.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x000F}, {-1,16+10,3,1}, {ofFPU}, "FTAN.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0010}, {-1,16+10,3,1}, {ofFPU}, "FETOX.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0011}, {-1,16+10,3,1}, {ofFPU}, "FTWOTOX.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0012}, {-1,16+10,3,1}, {ofFPU}, "FTENTOX.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0014}, {-1,16+10,3,1}, {ofFPU}, "FLOGN.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0015}, {-1,16+10,3,1}, {ofFPU}, "FLOG10.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0016}, {-1,16+10,3,1}, {ofFPU}, "FLOG2.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0018}, {-1,16+10,3,1}, {ofFPU}, "FABS.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0019}, {-1,16+10,3,1}, {ofFPU}, "FCOSH.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x001A}, {-1,16+10,3,1}, {ofFPU}, "FNEG.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x001C}, {-1,16+10,3,1}, {ofFPU}, "FACOS.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x001D}, {-1,16+10,3,1}, {ofFPU}, "FCOS.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x001E}, {-1,16+10,3,1}, {ofFPU}, "FGETEXP.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x001F}, {-1,16+10,3,1}, {ofFPU}, "FGETMAN.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0020}, {-1,16+10,3,1}, {ofFPU}, "FDIV.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0021}, {-1,16+10,3,1}, {ofFPU}, "FMOD.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0022}, {-1,16+10,3,1}, {ofFPU}, "FADD.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0023}, {-1,16+10,3,1}, {ofFPU}, "FMUL.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0024}, {-1,16+10,3,1}, {ofFPU}, "FSGLDIV.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0025}, {-1,16+10,3,1}, {ofFPU}, "FREM.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0026}, {-1,16+10,3,1}, {ofFPU}, "FSCALE.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0027}, {-1,16+10,3,1}, {ofFPU}, "FSGLMUL.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0028}, {-1,16+10,3,1}, {ofFPU}, "FSUB.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA078,0x0030}, {-1,16+10,3,1}, {ofFPU3Reg}, "FSINCOS.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0038}, {-1,16+10,3,1}, {ofFPU}, "FCMP.?" },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x003A}, {-1,16+10,3,1}, {ofFPU}, "FTST.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0040}, {-1,16+10,3,1}, {ofFPU}, "FSMOVE.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0041}, {-1,16+10,3,1}, {ofFPU}, "FSSQRT.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0042}, {-1,16+10,3,1}, {ofFPU}, "FSADD.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0044}, {-1,16+10,3,1}, {ofFPU}, "FDMOVE.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0045}, {-1,16+10,3,1}, {ofFPU}, "FDSQRT.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0046}, {-1,16+10,3,1}, {ofFPU}, "FDADD.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0058}, {-1,16+10,3,1}, {ofFPU}, "FSABS.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x005A}, {-1,16+10,3,1}, {ofFPU}, "FSNEG.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x005C}, {-1,16+10,3,1}, {ofFPU}, "FDABS.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x005E}, {-1,16+10,3,1}, {ofFPU}, "FDNEG.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0060}, {-1,16+10,3,1}, {ofFPU}, "FSDIV.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0063}, {-1,16+10,3,1}, {ofFPU}, "FSMUL.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0064}, {-1,16+10,3,1}, {ofFPU}, "FDDIV.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0067}, {-1,16+10,3,1}, {ofFPU}, "FDMUL.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x0068}, {-1,16+10,3,1}, {ofFPU}, "FSSUB.?" },
+       { MC68040,        {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xA07F,0x006C}, {-1,16+10,3,1}, {ofFPU}, "FDSUB.?" },
+       { MC68040|MC_FPU, {0xffff, 0xf000|(FPU_COPROC_ID<<9),0xFC00,0x5C00}, {0}, {ofFMOVECR}, "FMOVECR" },
+
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xE000,0x6000}, {-1,16+10,3,1}, {ofFPUMOVE}, "FMOVE.?" },
+
+       // these 3 are special versions of MOVEM with just one register, they have to be before the FMOVEM version
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xFFFF,0x8400}, {0}, {ofEa,ofSpecReg}, "FMOVE", {0,REG_FPU_FPIAR} },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xFFFF,0x8800}, {0}, {ofEa,ofSpecReg}, "FMOVE", {EA_An,REG_FPU_FPSR} },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xFFFF,0x9000}, {0}, {ofEa,ofSpecReg}, "FMOVE", {EA_An,REG_FPU_FPCR} },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xE3FF,0x8000}, {0}, {ofEa,ofFPUSRRegList}, "FMOVEM", {EA_Dn|EA_An,0} },
+       // these 3 are special versions of MOVEM with just one register, they have to be before the FMOVEM version
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xFFFF,0xA400}, {0}, {ofSpecReg,ofEa}, "FMOVE", {REG_FPU_FPIAR,EA_Immed|EA_PCRel} },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xFFFF,0xA800}, {0}, {ofSpecReg,ofEa}, "FMOVE", {REG_FPU_FPSR,EA_An|EA_Immed|EA_PCRel} },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xFFFF,0xB000}, {0}, {ofSpecReg,ofEa}, "FMOVE", {REG_FPU_FPCR,EA_An|EA_Immed|EA_PCRel} },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xE3FF,0xA000}, {0}, {ofFPUSRRegList,ofEa}, "FMOVEM", {0,EA_Dn|EA_An|EA_Immed|EA_PCRel} },
+
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xFE00,0xC000}, {0}, {ofFPUReglist,ofEa}, "FMOVEM.X",{0,EA_Dn|EA_An|EA_Anip|EA_Immed} },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xFE8F,0xC800}, {0}, {ofExtRegD04,ofEa}, "FMOVEM.X",{0,EA_Dn|EA_An|EA_piAn|EA_Immed} },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xFE00,0xE000}, {0}, {ofEa,ofFPUReglist}, "FMOVEM.X",{EA_Dn|EA_An|EA_piAn|EA_Immed,0} },
+       { MC68040|MC_FPU, {0xffc0, 0xf000|(FPU_COPROC_ID<<9),0xFE8F,0xE800}, {0}, {ofEa,ofExtRegD04}, "FMOVEM.X",{EA_Dn|EA_An|EA_Anip|EA_Immed|EA_PCRel} },
+
+       { MC68040|MC_FPU, {0xffc0, 0xf040|(FPU_COPROC_ID<<9),0xFFC0,0x0000}, {0}, {ofEa}, "FScf.B",{EA_An|EA_Immed|EA_PCRel} },
+       { MC68040|MC_FPU, {0xfff8, 0xf048|(FPU_COPROC_ID<<9),0xFFC0,0x0000}, {2}, {ofDn,ofDisp}, "FDBcf" },
+       { MC68040|MC_FPU, {0xffff, 0xf07A|(FPU_COPROC_ID<<9), 0xfff0, 0x0000, 0x10000,0x0000}, {2}, {ofExtIm32}, "FTRAPcf.W" },
+       { MC68040|MC_FPU, {0xffff, 0xf07B|(FPU_COPROC_ID<<9), 0xfff0, 0x0000, 0x10000,0x0000}, {4}, {ofExtIm32}, "FTRAPcf.L" },
+       { MC68040|MC_FPU, {0xffff, 0xf07C|(FPU_COPROC_ID<<9), 0xfff0, 0x0000}, {0}, {ofNone}, "FTRAPcf" },
+
+       // FNOP _has_ to be before FBcf.W, not worth to have a special case for that one
+       { MC68040|MC_FPU, {0xffff, 0xf080|(FPU_COPROC_ID<<9),0xFFFF,0x0000}, {0}, {ofNone}, "FNOP" },
+       { MC68040|MC_FPU, {0xffc0, 0xf080|(FPU_COPROC_ID<<9),0xFFFF,0x0000}, {2}, {ofDisp}, "FBcF.W" },
+       { MC68040|MC_FPU, {0xffc0, 0xf0c0|(FPU_COPROC_ID<<9),0xFFFF,0x0000}, {4}, {ofDisp}, "FBcF.L" },
+       { MC68040|MC68060|MC_FPU, {0xffc0, 0xf100|(FPU_COPROC_ID<<9)}, {0}, {ofEa}, "FSAVE", {EA_Dn|EA_An|EA_piAn|EA_Immed} },
+       { MC68040|MC68060|MC_FPU, {0xffc0, 0xf140|(FPU_COPROC_ID<<9)}, {0}, {ofEa}, "FRESTORE", {EA_Dn|EA_An|EA_piAn|EA_Immed} },
+
+       { 0 }
+};
+
+int    Disass68k(long addr, char *labelBuffer, char *opcodeBuffer, char *operandBuffer, char *commentBuffer)
+{
+       long    baseAddr = addr;
+       int             val;
+       int             i;
+       int             count = 0;
+       char    addressLabel[256];
+       char    cmtBuffer[256];
+       Disass68kDataType       type;
+       int     index;
+       long    opcodeAddr;
+
+       labelBuffer[0] = 0;
+       opcodeBuffer[0] = 0;
+       operandBuffer[0] = 0;
+       commentBuffer[0] = 0;
+
+       type = Disass68kType(baseAddr, addressLabel, cmtBuffer, &count);
+       if(addressLabel[0])
+               sprintf(labelBuffer, "%s:", addressLabel);
+       sprintf(commentBuffer, "%s", cmtBuffer);
+       switch(type)
+       {
+       case dtByte:
+               if(count > 8)
+                       count = 8;
+               strcpy(opcodeBuffer,"DC.B");
+               for (i = 0; i < count; ++i)
+               {
+                       char    hbuf[16];
+                       unsigned short  val;
+
+                       if((i & 7) > 0)
+                               strcat(operandBuffer, ",");
+                       val = Disass68kGetWord(addr+(i & ~1));
+                       if(i & 1)
+                               val &= 0xFF;
+                       else
+                               val = val >> 8;
+                       sprintf(hbuf,"$%2.2x", val);
+                       strcat(operandBuffer, hbuf);
+               }
+               return count;
+
+       case dtWord:
+               if(count > 4)
+                       count = 4;
+               strcpy(opcodeBuffer,"DC.W");
+               for (i = 0; i < count; ++i)
+               {
+                       char    hbuf[16];
+                       if((i & 3) > 0)
+                               strcat(operandBuffer, ",");
+                       sprintf(hbuf,"$%4.4x", Disass68kGetWord(addr+i*2));
+                       strcat(operandBuffer, hbuf);
+               }
+               return count * 2;
+
+       case dtLong:
+               if(count > 2)
+                       count = 2;
+               strcpy(opcodeBuffer,"DC.L");
+               for (i = 0; i < count; ++i)
+               {
+                       char    hbuf[16];
+                       if((i & 1) > 0)
+                               strcat(operandBuffer, ",");
+                       sprintf(hbuf,"$%8.8x", (Disass68kGetWord(addr+i*4) << 16) | Disass68kGetWord(addr+i*4+2));
+                       strcat(operandBuffer, hbuf);
+               }
+               return count * 4;
+
+       case dtStringArray:
+       {
+               char    *sp;
+               strcpy(opcodeBuffer,"DC.B");
+               strcat(operandBuffer, "'");
+               sp = operandBuffer + strlen(operandBuffer);
+               for (i = 0; i < count; ++i)
+               {
+                       unsigned short  val = Disass68kGetWord(addr+(i & ~1));
+                       if(i & 1)
+                               val &= 0xFF;
+                       else
+                               val = val >> 8;
+                       if(val == 0)
+                               break;
+                       switch(val)
+                       {
+                       case 9: *sp++ = '\\'; *sp++ = 't'; break;
+                       case 10: *sp++ = '\\'; *sp++ = 'n'; break;
+                       case 13: *sp++ = '\\'; *sp++ = 'r'; break;
+                       default:
+                               if(val >= 0x20 && val <= 0x7E)
+                                       *sp++ = val;
+                       }
+               }
+               *sp = 0;
+               strcat(sp, "'");
+               return count;
+       }
+
+       case dtASCString:
+       {
+               int     count = 1;
+               unsigned short  val = Disass68kGetWord(addr+0);
+               strcpy(opcodeBuffer,"DC.B");
+               if((val >> 8) == 0)
+               {
+                       strcat(operandBuffer, "0");
+               } else {
+                       char *sp;
+                       strcat(operandBuffer, "'");
+                       sp = operandBuffer + strlen(operandBuffer);
+                       for(i=0; ; ++i)
+                       {
+                               unsigned short  val = Disass68kGetWord(addr+(i & ~1));
+                               if(i & 1)
+                                       val &= 0xFF;
+                               else
+                                       val = val >> 8;
+                               if(val == 0)
+                                       break;
+                               switch(val)
+                               {
+                               case 9: *sp++ = '\\'; *sp++ = 't'; break;
+                               case 10: *sp++ = '\\'; *sp++ = 'n'; break;
+                               case 13: *sp++ = '\\'; *sp++ = 'r'; break;
+                               default:
+                                       if(val >= 0x20 && val <= 0x7E)
+                                               *sp++ = val;
+                               }
+                               ++count;
+                       }
+                       *sp = 0;
+                       strcat(sp, "',0");
+               }
+               return (count + 1) & ~1;
+       }
+
+       case dtPointer:
+       case dtFunctionPointer:
+       {
+               const char      *sp;
+               val = (Disass68kGetWord(addr) << 16) | Disass68kGetWord(addr+2);
+               sp = Disass68kSymbolName(val, 2);
+               strcpy(opcodeBuffer,"DC.L");
+               if(sp)
+                       sprintf(operandBuffer,"%s", sp);
+               else
+                       sprintf(operandBuffer,"$%6.6x", val);
+               return 4;
+       }
+
+       default:        break;
+       }
+
+       index = 0;
+       opcodeAddr = addr;
+more:
+       addr = opcodeAddr;
+
+       opcodeBuffer[0] = 0;
+       operandBuffer[0] = 0;
+
+       commentBuffer[0] = 0;
+       if(cmtBuffer[0])
+               sprintf(commentBuffer, "%s ", cmtBuffer);
+
+       while(1)
+       {
+               unsigned short  opcode[5];
+               unsigned int    i;
+               OpcodeTableStruct       *ots = &OpcodeTable[index++];
+               int     size;
+               char    sizeChar = 0;
+               char    *dbuf;
+               int     ea;
+               unsigned int    maxop;
+
+               if(ots->opcodeName == NULL)
+                       break;
+               if((ots->cpuMask & optionCPUTypeMask) == 0)     // CPU doesn't match?
+                       continue;
+
+               // search for the opcode plus up to 2 extension words
+               for(i=0; i<5; ++i)
+               {
+                       if(!ots->opcodeMask[i*2])
+                       {
+                               opcode[i] = 0;
+                               break;
+                       }
+                       opcode[i] = Disass68kGetWord(addr);
+                       if(((ots->opcodeMask[i*2] & 0xFFFF) & opcode[i]) != ots->opcodeMask[i*2+1])
+                               goto more;
+                       addr += 2;
+               }
+
+               // find out the size of the opcode operand
+               size = ots->operationSize[0];
+               if(size < 0)    // custom size?
+               {
+                       int     opcodeOffset = ots->operationSize[1] >> 4;
+                       int     bitShiftOffset = ots->operationSize[1] & 0x0F;
+                       int     sizeBitMask = (opcode[opcodeOffset] >> bitShiftOffset) & ((1 << ots->operationSize[2]) - 1);
+                       switch(ots->operationSize[3])
+                       {
+                       case 0: // 2 Bit Size
+                                       switch(sizeBitMask)
+                                       {
+                                       case 0: size = 1; sizeChar = 'B'; break;
+                                       case 1: size = 2; sizeChar = 'W'; break;
+                                       case 2: size = 4; sizeChar = 'L'; break;
+                                       case 3: goto more;      // illegal size mask
+                                       }
+                                       break;
+                       case 1: // 3 Bit FPU Size
+                                       if((opcode[1] & 0x4000) == 0x0000)      // Register => Register?
+                                               sizeBitMask = 2;                // => 'X' Format
+                                       switch(sizeBitMask)
+                                       {
+                                       case 0: size = 4; sizeChar = 'L'; break;
+                                       case 1: size = 4; sizeChar = 'S'; break;
+                                       case 2: size = 12; sizeChar = 'X'; break;
+                                       case 7: if((opcode[1] & 0xE000) != 0x6000)      // MOVE.P <ea>,FPn{Dn-Factor}
+                                                               goto more;      // illegal size mask
+                                       case 3: size = 12; sizeChar = 'P'; break;
+                                       case 4: size = 2; sizeChar = 'W'; break;
+                                       case 5: size = 8; sizeChar = 'D'; break;
+                                       case 6: size = 1; sizeChar = 'B'; break;
+                                       }
+                                       break;
+                       }
+               }
+
+               // copy the opcode plus a necessary TAB for the operand
+               dbuf = opcodeBuffer;
+               for(i=0; ots->opcodeName[i]; ++i)
+               {
+                       char    c = ots->opcodeName[i];
+                       if(c == 'c')    // condition code
+                       {
+                               static const char       *pmmuCond[16] = { "BS", "BC", "LS", "LC",  "SS", "SC", "AS", "AC",  "WS", "WC", "IS", "IC",  "GS", "GC", "CS", "CC" };
+                               static const char       *braCond[16]  = { "RA", "SR", "HI", "LS",  "CC", "CS", "NE", "EQ",  "VC", "VS", "PL", "MI",  "GE", "LT", "GT", "LE" };
+                               static const char       *sccCond[16]  = {  "T",  "F", "HI", "LS",  "CC", "CS", "NE", "EQ",  "VC", "VS", "PL", "MI",  "GE", "LT", "GT", "LE" };
+                               static const char       *dbCond[16]   = {  "T", "RA", "HI", "LS",  "CC", "CS", "NE", "EQ",  "VC", "VS", "PL", "MI",  "GE", "LT", "GT", "LE" };
+                               static const char       *fpuCond[64]  = { "F", "EQ", "OGT", "OGE", "OLT", "OLE", "OGL", "OR", "UN", "UEQ", "UGT", "UGE", "ULT", "ULE", "NE", "T", "SF", "SEQ", "GT", "GE", "LT", "LE", "GL", "GLE", "NGLE", "NGL", "NLE", "NLT", "NGE", "NGT", "SNE", "ST" };
+                               char    buf[8];
+
+                               const char      *sp = NULL;
+                               switch(ots->opcodeName[++i])
+                               {
+                               case 'p':       // PMMU conditions
+                                       sp = pmmuCond[opcode[1] & 0xF];
+                                       break;
+                               case 'b':       // BRA conditions
+                                       sp = braCond[(opcode[0] >> 8) & 0xF];
+                                       break;
+                               case 'i':       // Scc,TRAPcc conditions
+                                       sp = sccCond[(opcode[0] >> 8) & 0xF];
+                                       break;
+                               case 'd':       // DBcc conditions
+                                       sp = dbCond[(opcode[0] >> 8) & 0xF];
+                                       break;
+                               case 'F':       // FPU conditions (first word)
+                                       sp = fpuCond[opcode[0] & 0x3F];
+                                       break;
+                               case 'f':       // FPU conditions (second word)
+                                       sp = fpuCond[opcode[1] & 0x3F];
+                                       break;
+                               }
+                               if(sp)
+                               {
+                                       if(options & doptOpcodesSmall)
+                                       {
+                                               char    *bp;
+                                               strcpy(buf, sp);
+                                               sp = buf;
+                                               for (bp = buf; *bp; ++bp)
+                                                       *bp = tolower((unsigned char)*bp);
+                                       }
+                                       strcpy(dbuf, sp);
+                                       dbuf += strlen(sp);
+                                       continue;
+                               }
+                               goto more;
+                       }
+                       if(c == '?')    // size mask
+                               c = sizeChar;
+                       if(options & doptOpcodesSmall)
+                               c = tolower((unsigned char)c);
+                       *dbuf++ = c;
+               }
+               *dbuf = 0;
+
+               // Parse the EAs for all operands
+               ea = opcode[0] & 0x3F;
+               dbuf = operandBuffer;
+
+               maxop=(sizeof(ots->op)/sizeof(ots->op[0]));
+               for(i=0; i<maxop; ++i)
+               {
+                       int reg;
+
+                       switch(ots->op[i])
+                       {
+                       case ofNone:            // nothing
+                                       break;
+
+                       case ofEa:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ea, size, EA_All & ~(ots->parameter[i]), 0, ots->disassFlag);
+                                       break;
+
+                       case ofDn:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (ea & 7) | 0x00, size, EA_Dn, 0, ots->disassFlag);
+                                       break;
+                       case ofAn:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (ea & 7) | 0x08, size, EA_An, 0, ots->disassFlag);
+                                       break;
+                       case ofAni:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (ea & 7) | 0x10, size, EA_Ani, 0, ots->disassFlag);
+                                       break;
+                       case ofAnip:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (ea & 7) | 0x18, size, EA_Anip, 0, ots->disassFlag);
+                                       break;
+                       case ofPiAn:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (ea & 7) | 0x20, size, EA_piAn, 0, ots->disassFlag);
+                                       break;
+                       case ofD16An:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (ea & 7) | 0x28, size, EA_dAn, 0, ots->disassFlag);
+                                       break;
+
+                       case ofI:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x3C, size, EA_Immed, 0, ots->disassFlag);
+                                       break;
+
+                       case ofDestDn:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[0] >> 9) & 7) | 0x00, size, EA_Dn, 0, ots->disassFlag);
+                                       break;
+                       case ofDestAn:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[0] >> 9) & 7) | 0x08, size, EA_An, 0, ots->disassFlag);
+                                       break;
+                       case ofDestAnip:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[0] >> 9) & 7) | 0x18, size, EA_Anip, 0, ots->disassFlag);
+                                       break;
+                       case ofDestPiAn:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[0] >> 9) & 7) | 0x20, size, EA_piAn, 0, ots->disassFlag);
+                                       break;
+                       case ofDestEa6:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[0] >> 9) & 7) | (((opcode[0] >> 6) & 0x7) << 3), size, EA_Dest-EA_An, 0, ots->disassFlag);
+                                       break;
+                       case ofDestAbsL:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x39, size, EA_Abs, 0, ots->disassFlag);
+                                       break;
+
+                       case ofIOpcode:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, 1, EA_ImmedParameter, opcode[0] & ots->parameter[i], ots->disassFlag);
+                                       break;
+                       case ofI3:
+                                       val = ((opcode[0] >> 9) & 7);
+                                       if(!val) val = 8;
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, 1, EA_ImmedParameter, val, ots->disassFlag);
+                                       break;
+                       case ofExtIm:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, 2, EA_ImmedParameter, opcode[1], ots->disassFlag);
+                                       break;
+                       case ofExtIm32:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, size, EA_ImmedParameter, opcode[2], ots->disassFlag);
+                                       break;
+                       case ofExtIm4:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, 2, EA_ImmedParameter, opcode[1] & 0x0F, ots->disassFlag);
+                                       break;
+                       case ofExtIm10:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, 2, EA_ImmedParameter, (opcode[1] >> 10) & 0x07, ots->disassFlag);
+                                       break;
+                       case ofSpecReg:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0101, size, EA_SpecialRegister, ots->parameter[i], ots->disassFlag);
+                                       break;
+                       case ofSpecExtReg:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0101, size, EA_SpecialRegister, opcode[1] & 0xFFF, ots->disassFlag);
+                                       break;
+                       case ofExtReg0:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (opcode[1] & 0x07), size, EA_Dn, 0, ots->disassFlag);
+                                       break;
+                       case ofExtRegA0:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (opcode[1] & 0x07) | 0x08, size, EA_An, 0, ots->disassFlag);
+                                       break;
+                       case ofExtRegD04:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[1] >> 4) & 0x07) | 0x00, size, EA_Dn, 0, ots->disassFlag);
+                                       break;
+                       case ofExtRegA05:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[1] >> 5) & 0x07) | 0x08, size, EA_An, 0, ots->disassFlag);
+                                       break;
+                       case ofExtReg:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[1] >> 12) & 0x0F), size, EA_Dn|EA_An, 0, ots->disassFlag);
+                                       break;
+                       case ofExtAnip:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[1] >> 12) & 7) | 0x18, size, EA_Anip, 0, ots->disassFlag);
+                                       break;
+
+                       case ofDisp:
+                                       // branch treats the displacement 0x00 and 0xFF as an indicator how many words follow
+                                       // This test will decline a displacement with the wrong word offset
+                                       if((opcode[0] & 0xF000) == 0x6000)
+                                       {
+                                               val = opcode[0] & 0xFF;
+                                               if(val == 0x00 && size != 2) goto more;
+                                               if(val == 0xFF && size != 4) goto more;
+                                       }
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0102, size, EA_PCDisplacement, opcode[0] & 0xFF, ots->disassFlag);
+                                       break;
+
+                       case ofRegList:
+                                       val = opcode[1];
+                                       if((ea & 0x38) == 0x20)                         // -(An) has a flipped bitmask
+                                               val = Disass68kFlipBits(val);
+                                       dbuf = Disass68kReglist(dbuf, val);
+                                       break;
+
+                       case ofFPU:
+                                       {       // default FPU opcode modes
+                                       int     src = (opcode[1] >> 10) & 7;
+                                       int     dest = (opcode[1] >> 7) & 7;
+                                       char    regFP1 = options & doptRegisterSmall ? 'f' : 'F';
+                                       char    regFP2 = options & doptRegisterSmall ? 'p' : 'P';
+                                       if(opcode[1] & 0x4000)
+                                       {
+                                               // <ea>,FPn
+                                               int     mask = EA_All - EA_An;
+                                               if(src != 0 && src != 4 && src != 6)    // only .B,.W and .L allow Dn as a source
+                                                       mask -= EA_Dn;
+                                               dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ea, size, mask, 0, 0);
+                                               if(!dbuf) goto more;
+                                               *dbuf++ = ',';
+                                               *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+dest;
+                                               *dbuf = 0;
+                                       } else {
+                                               // FPn,FPn or FPn
+
+                                               // <ea> has to be 0
+                                               if((opcode[0] & 0x3F) != 0) goto more;
+
+                                               *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+src;
+                                               if(src != dest)
+                                               {
+                                                       *dbuf++ = ',';
+                                                       *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+dest;
+                                               }
+                                               *dbuf = 0;
+                                       }
+                                       }
+                                       break;
+                       case ofFPUMOVE:
+                                       {       // MOVE <ea>,FPn{k-Factor}
+                                       int     src = (opcode[1] >> 10) & 7;
+                                       // <ea>,FPn
+                                       int     mask = EA_All - EA_An;
+                                       char    regFP1 = options & doptRegisterSmall ? 'f' : 'F';
+                                       char    regFP2 = options & doptRegisterSmall ? 'p' : 'P';
+                                       if(src != 0 && src != 4 && src != 6)    // only .B,.W and .L allow Dn as a source
+                                               mask -= EA_Dn;
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ea, size, mask, 0, 0);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = ',';
+                                       *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+((opcode[1] >> 7) & 7);
+                                       if(src == 3)
+                                       {
+                                               int     kFactor = opcode[1] & 0x7F;
+                                               if(kFactor & 0x40)
+                                                       kFactor |= 0x80;
+                                               *dbuf++ = '{';
+                                               sprintf(dbuf, "%d", (signed char)kFactor);
+                                               dbuf += strlen(dbuf);
+                                               *dbuf++ = '}';
+                                       } else if(src == 7)
+                                       {
+                                               if((opcode[1] & 0x0F) != 0) goto more;
+                                               *dbuf++ = '{';
+                                               *dbuf++ = options & doptRegisterSmall ? 'd' : 'D';
+                                               *dbuf++ = '0' + ((opcode[1] >> 4) & 7);
+                                               *dbuf++ = '}';
+                                       } else {
+                                               if((opcode[1] & 0x7F) != 0) goto more;
+                                       }
+                                       *dbuf = 0;
+                                       }
+                                       break;
+                       case ofFMOVECR:
+                                       {       // MOVECR #const,FPn
+                                       char    regFP1 = options & doptRegisterSmall ? 'f' : 'F';
+                                       char    regFP2 = options & doptRegisterSmall ? 'p' : 'P';
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, 1, EA_ImmedParameter, opcode[1] & 0x7F, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       reg = (opcode[1] >> 7) & 7;
+                                       *dbuf++ = ',';
+                                       *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+reg;
+                                       *dbuf = 0;
+                                       switch(opcode[1] & 0x7F)        // document the well-known constants
+                                       {
+                                       case 0x00:      strcat(commentBuffer, "PI"); break;
+                                       case 0x0B:      strcat(commentBuffer, "Log10(2)"); break;
+                                       case 0x0C:      strcat(commentBuffer, "e"); break;
+                                       case 0x0D:      strcat(commentBuffer, "Log2(e)"); break;
+                                       case 0x0E:      strcat(commentBuffer, "Log10(e)"); break;
+                                       case 0x0F:      strcat(commentBuffer, "0.0"); break;
+                                       case 0x30:      strcat(commentBuffer, "1n(2)"); break;
+                                       case 0x31:      strcat(commentBuffer, "1n(10)"); break;
+                                       case 0x32:      strcat(commentBuffer, "100"); break;
+                                       case 0x33:      strcat(commentBuffer, "10^1"); break;
+                                       case 0x34:      strcat(commentBuffer, "10^2"); break;
+                                       case 0x35:      strcat(commentBuffer, "10^4"); break;
+                                       case 0x36:      strcat(commentBuffer, "10^8"); break;
+                                       case 0x37:      strcat(commentBuffer, "10^16"); break;
+                                       case 0x38:      strcat(commentBuffer, "10^32"); break;
+                                       case 0x39:      strcat(commentBuffer, "10^64"); break;
+                                       case 0x3A:      strcat(commentBuffer, "10^128"); break;
+                                       case 0x3B:      strcat(commentBuffer, "10^256"); break;
+                                       case 0x3C:      strcat(commentBuffer, "10^512"); break;
+                                       case 0x3D:      strcat(commentBuffer, "10^1024"); break;
+                                       case 0x3E:      strcat(commentBuffer, "10^2048"); break;
+                                       case 0x3F:      strcat(commentBuffer, "10^4096"); break;
+                                       }
+                                       }
+                                       break;
+                       case ofFPUSRRegList:
+                                       {
+                                       int     hasReg = 0;
+                                       *dbuf = 0;
+                                       if(opcode[1] & 0x0400)
+                                       {
+                                               strcat(dbuf, Disass68kSpecialRegister(REG_FPU_FPIAR));
+                                               hasReg = 1;
+                                       }
+                                       if(opcode[1] & 0x0800)
+                                       {
+                                               if(hasReg) strcat(dbuf, "/");
+                                               strcat(dbuf, Disass68kSpecialRegister(REG_FPU_FPSR));
+                                               hasReg = 1;
+                                       }
+                                       if(opcode[1] & 0x1000)
+                                       {
+                                               if(hasReg) strcat(dbuf, "/");
+                                               strcat(dbuf, Disass68kSpecialRegister(REG_FPU_FPCR));
+                                               hasReg = 1;
+                                       }
+                                       if(!hasReg)
+                                               strcat(dbuf, "0");
+                                       dbuf += strlen(dbuf);
+                                       }
+                                       break;
+                       case ofFPUReglist:      // FMOVEM
+                                       {
+                                       int     mask = opcode[1] & 0xFF;
+                                       if(opcode[1] & 0x0100)
+                                               mask = Disass68kFlipBits(mask) >> 8;
+                                       dbuf = Disass68kFPUReglist(dbuf, mask);
+                                       }
+                                       break;
+                       case ofFPU3Reg:
+                                       {       // FSINCOS
+                                       int     src = (opcode[1] >> 10) & 7;
+                                       int     dest = (opcode[1] >> 7) & 7;
+                                       char    regFP1 = options & doptRegisterSmall ? 'f' : 'F';
+                                       char    regFP2 = options & doptRegisterSmall ? 'p' : 'P';
+                                       if(opcode[1] & 0x4000)
+                                       {
+                                               // <ea>,FPn
+                                               int     mask = EA_All - EA_An;
+                                               if(src != 0 && src != 4 && src != 6)    // only .B,.W and .L allow Dn as a source
+                                                       mask -= EA_Dn;
+                                               dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ea, size, mask, 0, 0);
+                                               if(!dbuf) goto more;
+                                               *dbuf++ = ',';
+                                               *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+(opcode[1] & 7);
+                                               *dbuf++ = ',';
+                                               *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+dest;
+                                               *dbuf = 0;
+                                       } else {
+                                               // FPn,FPn or FPn
+
+                                               // <ea> has to be 0
+                                               if((opcode[0] & 0x3F) != 0) goto more;
+
+                                               *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+src;
+                                               *dbuf++ = ',';
+                                               *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+(opcode[1] & 7);
+                                               *dbuf++ = ',';
+                                               *dbuf++ = regFP1; *dbuf++ = regFP2; *dbuf++ = '0'+dest;
+                                               *dbuf = 0;
+                                       }
+                                       }
+                                       break;
+
+                       case ofCAS:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (opcode[1] & 0x07), size, EA_Dn, 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = ',';
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[1] >> 6) & 0x07), size, EA_Dn, 0, ots->disassFlag);
+                                       break;
+                       case ofCAS2:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (opcode[1] & 0x07), size, EA_Dn, 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = ':';
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (opcode[2] & 0x07), size, EA_Dn, 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = ',';
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[1] >> 6) & 0x07), size, EA_Dn, 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = ':';
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[2] >> 6) & 0x07), size, EA_Dn, 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = ',';
+                                       *dbuf++ = '(';
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[1] >> 12) & 0x0F), size, EA_Dn|EA_An, 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = ')';
+                                       *dbuf++ = ':';
+                                       *dbuf++ = '(';
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[2] >> 12) & 0x0F), size, EA_Dn|EA_An, 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = ')';
+                                       *dbuf = 0;
+                                       break;
+                       case ofExt4Dn:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (opcode[0] & 0x07), size, EA_Dn, 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = ':';
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, (opcode[1] & 0x07), size, EA_Dn, 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = ',';
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ((opcode[1] >> 12) & 0x07), size, EA_Dn, 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf = 0;
+                                       break;
+                       case ofBFEa:
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, ea, size, EA_All & ~(ots->parameter[i]), 0, ots->disassFlag);
+                                       if(!dbuf) goto more;
+                                       *dbuf++ = '{';
+                                       val = (opcode[1] >> 6) & 0x1F;
+                                       if(opcode[1] & 0x0800)
+                                       {
+                                               if(val & 0x18) goto more;
+                                               dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, val & 0x07, 1, EA_Dn, val, ots->disassFlag);
+                                       } else {
+                                               dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0103, 1, EA_ValueParameter, val, ots->disassFlag);
+                                       }
+                                       *dbuf++ = ':';
+                                       val = opcode[1] & 0x1F;
+                                       if(opcode[1] & 0x0020)
+                                       {
+                                               if(val & 0x18) goto more;
+                                               dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, val & 0x07, 1, EA_Dn, val, ots->disassFlag);
+                                       } else {
+                                               if(val == 0) val = 32;
+                                               dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0103, 1, EA_ValueParameter, val, ots->disassFlag);
+                                       }
+                                       *dbuf++ = '}';
+                                       *dbuf = 0;
+                                       break;
+                       case ofLineA:
+                                       {
+                                       int     lineAVal = opcode[0] & 0xFFF;
+                                       const char      *lineAStr[16] = { "Line-A Initialization",
+                                                                                                 "Put pixel",
+                                                                                                 "Get pixel",
+                                                                                                 "Arbitrary line",
+                                                                                                 "Horizontal line",
+                                                                                                 "Filled rectangle",
+                                                                                                 "Filled polygon",
+                                                                                                 "Bit block transfer",
+                                                                                                 "Text block transfer",
+                                                                                                 "Show mouse",
+                                                                                                 "Hide mouse",
+                                                                                                 "Transform mouse",
+                                                                                                 "Undraw sprite",
+                                                                                                 "Draw sprite",
+                                                                                                 "Copy raster form",
+                                                                                                 "Seedfill"
+                                                                                                 };
+                                       dbuf = Disass68kEA(dbuf, commentBuffer, &addr, opcodeAddr, 0x0100, 2, EA_ImmedParameter, lineAVal, ots->disassFlag);
+                                       if(lineAVal < 16)
+                                               strcat(commentBuffer, lineAStr[lineAVal]);
+                                       }
+                                       break;
+
+                       default:
+                                       goto more;
+                       }
+                       if(!dbuf) goto more;
+
+                       // does another operand follow => add separator
+                       if ( (i+1<maxop) && ( ots->op[i+1] != ofNone) )
+                               *dbuf++ = ',';
+               }
+               return addr-baseAddr;
+       }
+
+       // unknown opcode
+       strcpy(opcodeBuffer, "DC.W");
+       sprintf(operandBuffer,"$%4.4x", Disass68kGetWord(addr));
+       return 2;
+}
+
+static void            Disass68kComposeStr(char *dbuf, const char *str, int position, int maxPos)
+{
+       int             i;
+       int             len = strlen(dbuf);
+       while(len < position) {
+               dbuf[len++] = ' ';              /* Will give harmless warning from GCC */
+       }
+       for(i=0; str[i] && (!maxPos || len+i<maxPos); ++i)
+               dbuf[len+i] = str[i];
+       if(str[i])
+               dbuf[len+i-1] = '+';
+       dbuf[len+i] = 0;
+}
+
+static void Disass68k_loop (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt)
+{
+       while (cnt-- > 0) {
+               const int       addrWidth = 6;          // 6 on an ST, 8 on a TT
+               char    lineBuffer[1024];
+
+               char    addressBuffer[32];
+               char    hexdumpBuffer[256];
+               char    labelBuffer[256];
+               char    opcodeBuffer[64];
+               char    operandBuffer[256];
+               char    commentBuffer[256];
+               int     plen, len, j;
+
+               len = Disass68k(addr, labelBuffer, opcodeBuffer, operandBuffer, commentBuffer);
+               if(!len) break;
+
+               sprintf(addressBuffer, "$%*.*x :", addrWidth,addrWidth, addr);
+
+               hexdumpBuffer[0] = 0;
+               plen = len;
+               if(plen > 80 && (!strncmp(opcodeBuffer, "DC.", 3) || !strncmp(opcodeBuffer, "dc.", 3)))
+                       plen = ((optionPosLabel - optionPosHexdump) / 5) * 2;
+
+               for(j=0; j<plen; j += 2)
+               {
+                       if(j > 0)
+                               strcat(hexdumpBuffer, " ");
+                       if(j + 2 > plen)
+                       {
+                               sprintf(hexdumpBuffer+strlen(hexdumpBuffer), "%2.2x", Disass68kGetWord(addr+j) >> 8);
+                       } else {
+                               sprintf(hexdumpBuffer+strlen(hexdumpBuffer), "%4.4x", Disass68kGetWord(addr+j));
+                       }
+               }
+
+               lineBuffer[0] = 0;
+               if(optionPosAddress >= 0)
+                       Disass68kComposeStr(lineBuffer, addressBuffer, optionPosAddress, 0);
+               if(optionPosHexdump >= 0)
+                       Disass68kComposeStr(lineBuffer, hexdumpBuffer, optionPosHexdump, optionPosLabel);
+               if(optionPosLabel >= 0)
+                       Disass68kComposeStr(lineBuffer, labelBuffer, optionPosLabel, 0);
+               if(optionPosOpcode >= 0)
+                       Disass68kComposeStr(lineBuffer, opcodeBuffer, optionPosOpcode, 0);
+               if(optionPosOperand >= 0)
+               {
+                       size_t  l = strlen(lineBuffer);
+                       if(lineBuffer[l-1] != ' ')              // force at least one space between opcode and operand
+                       {
+                               lineBuffer[l++] = ' ';
+                               lineBuffer[l] = 0;
+                       }
+                       Disass68kComposeStr(lineBuffer, operandBuffer, optionPosOperand, 0);
+               }
+               if (optionPosComment >= 0)
+               {
+                       /* show comments only if profile data is missing */
+                       if (commentBuffer[0])
+                       {
+                               Disass68kComposeStr(lineBuffer, " ;", optionPosComment, 0);
+                               Disass68kComposeStr(lineBuffer, commentBuffer, optionPosComment+3, 0);
+                       }
+               }
+               addr += len;
+               if (f)
+                       fprintf(f, "%s\n", lineBuffer);
+//             if(strstr(opcodeBuffer, "RTS") || strstr(opcodeBuffer, "RTE") || strstr(opcodeBuffer, "JMP")
+//             || strstr(opcodeBuffer, "rts") || strstr(opcodeBuffer, "rte") || strstr(opcodeBuffer, "jmp"))
+//                     fprintf(f, "\n");
+    }
+    if (nextpc)
+               *nextpc = addr;
+}
+
+
+/**
+ * Calculate next PC address from given one, without output
+ * @return     next PC address
+ */
+Uint32 Disasm_GetNextPC(Uint32 pc)
+{
+       uaecptr nextpc;
+       Disass68k_loop (NULL, pc, &nextpc, 1);
+       return nextpc;
+}
+
+/**
+ * Set CPU and FPU mask used for disassembly (when changed from the UI or the options)
+ */
+void Disasm_SetCPUType ( int CPU , int FPU )
+{
+       optionCPUTypeMask = 0;
+
+       if ( ( FPU == 68881 ) || ( FPU == 68882 ) )
+               optionCPUTypeMask |= MC_FPU;
+
+       switch ( CPU )
+       {
+               case 0 :        optionCPUTypeMask |= MC68000 ; break;
+               case 1 :        optionCPUTypeMask |= MC68010 ; break;
+               case 2 :        optionCPUTypeMask |= MC68020 ; break;
+               case 3 :        optionCPUTypeMask |= MC68030 ; break;
+               case 4 :        optionCPUTypeMask |= MC68040 ; break;
+               default :       optionCPUTypeMask |= MC68000 ; break;
+       }       
+}
diff --git a/cputest/68kDisass.h b/cputest/68kDisass.h
new file mode 100644 (file)
index 0000000..80f3c96
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+  Hatari - 68kDisass.h
+
+  This file is distributed under the GNU General Public License, version 2
+  or at your option any later version. Read the file gpl.txt for details.
+*/
+#ifndef HATARI_68KDISASS_H
+#define HATARI_68KDISASS_H
+
+extern Uint32 Disasm_GetNextPC(Uint32 pc);
+extern void Disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt);
+
+enum {
+       DISASM_COLUMN_ADDRESS = 0,
+       DISASM_COLUMN_HEXDUMP,
+       DISASM_COLUMN_LABEL,
+       DISASM_COLUMN_OPCODE,
+       DISASM_COLUMN_OPERAND,
+       DISASM_COLUMN_COMMENT,
+       DISASM_COLUMNS                  /* number of columns in disassembly output */
+};
+
+#define DISASM_COLUMN_DISABLE -1
+
+void Disasm_SetCPUType ( int CPU , int FPU );
+
+#endif         /* HATARI_68KDISASS_H */
diff --git a/cputest/amiga.S b/cputest/amiga.S
new file mode 100644 (file)
index 0000000..263662a
--- /dev/null
@@ -0,0 +1,74 @@
+
+       .text
+
+       .globl _allocate_absolute
+       .globl _free_absolute
+       .globl _touser
+       .globl _tosuper
+       .globl _testexit
+       .globl _get_cpu_model
+
+       | check left mouse button/joystick fire
+_testexit:
+       moveq #0,d0
+       move.b 0xbfe001,d0
+       and.b #0xc0,d0
+       eor.b #0xc0,d0
+       | d0 != 0: -> exit
+       rts
+
+       | super mode, disable interrupts
+_tosuper:
+       move.l a6,-(sp)
+       move.l 4.w,a6
+       jsr -0x78(a6) | Disable
+       jsr -0x96(a6) | SuperState
+       move.w #0x0200,0xdff096
+       move.l (sp)+,a6
+       rts
+       
+       | back to user mode, enable interrupts
+_touser:
+       move.l a6,-(sp)
+       move.l 4.w,a6
+       move.l 8(sp),d0
+       jsr -0x9c(a6) | UserState
+       move.w #0x8200,0xdff096
+       jsr -0x7e(a6) | Enable
+       move.l (sp)+,a6
+       rts
+
+       | free absolute allocated test memory
+_free_absolute:
+       move.l a6,-(sp)
+       move.l 8(sp),a1
+       move.l 12(sp),d0
+       move.l 4.w,a6
+       jsr -0xd2(a6) | FreeMem
+       move.l (sp)+,a6
+       rts
+
+       | allocate absolute memory
+_allocate_absolute:
+       move.l a6,-(sp)
+       move.l 8(sp),a1
+       move.l 12(sp),d0
+       move.l 4.w,a6
+       jsr -0xcc(a6) | AllocAbs
+       move.l (sp)+,a6
+       rts
+
+       | return CPU model (68000=0, 68010=1, 68020=2)
+_get_cpu_model:
+       move.l 4.w,a0
+       moveq #0,d0
+       move.w 0x128(a0),d1
+       and.w #3,d1
+       beq.s .cpudone
+       moveq #2,d0
+       btst #1,d1
+       bne.s .cpudone
+       moveq #1,d0
+.cpudone:
+       rts
+
diff --git a/cputest/asm.S b/cputest/asm.S
new file mode 100644 (file)
index 0000000..01a3c5e
--- /dev/null
@@ -0,0 +1,340 @@
+
+       .text
+
+       .globl _execute_test000
+       .globl _execute_test010
+       .globl _execute_test020
+       .globl _execute_testfpu
+       .globl _exception010
+       .globl _exception020
+       .globl _exceptionfpu
+       .globl _exceptiontable000
+       .globl _setvbr
+       .globl _setcpu
+       .globl _flushcache
+
+S_DREG = 0
+S_AREG = S_DREG+8*4
+S_SSP = S_AREG+8*4
+S_MSP = S_SSP+4
+S_PC = S_MSP+4
+S_SR = S_PC+4
+S_EXC = S_SR+4
+S_FPU = S_EXC+4
+S_FPIAR = S_FPU+8*12
+S_FPCR = S_FPIAR+4
+S_FPSR = S_FPCR+4
+
+       | set CPU special registers
+_setcpu:
+       move.l 4(sp),d1 | cpu_lvl
+       move.l 8(sp),a1 | new
+       move.l 12(sp),a0 | store
+       cmp.w #1,d1
+       bcs.s .scend1
+       move.l a0,d0
+       beq.s .scend1
+       movec sfc,d0
+       move.l d0,(a0)+
+       movec dfc,d0
+       move.l d0,(a0)+
+       cmp.w #2,d1
+       bcs.s .scend1
+       movec cacr,d0
+       move.l d0,(a0)+
+       movec caar,d0
+       move.l d0,(a0)+
+       movec msp,d0
+       move.l d0,(a0)+
+.scend1:
+       move.l a1,d0
+       beq.s .scend2
+       cmp.w #1,d1
+       bcs.s .scend2
+       move.l (a1)+,d0
+       movec d0,sfc
+       move.l (a1)+,d0
+       movec d0,dfc    
+       cmp.w #2,d1
+       bcs.s .scend2
+       move.l (a1)+,d0
+       movec d0,cacr
+       move.l (a1)+,d0
+       movec d0,caar
+       move.l (a1)+,d0
+       move.c d0,msp
+.scend2:
+       rts
+
+_flushcache:
+       movec cacr,d0
+       bset #3,d0
+       movec d0,cacr
+       rts
+
+       | set and return old VBR
+_setvbr:
+       move.l 4(sp),d1
+       movec vbr,d0
+       movec d1,vbr
+       rts
+
+       | 68000 test entrypoint
+_execute_test000:
+       movem.l d1-d7/a0-a6,-(sp)
+       move.l 14*4+4(sp),a0 | register struct
+       move.w sr,-(sp)
+       lea datapointer(pc),a1
+       move.l a0,(a1)+
+       move.l sp,(a1)
+       move.l S_SSP(a0),sp
+       move.l S_PC(a0),a1
+       move.l a1,-(sp)
+       move.w (a1)+,d0
+       move.w (a1),d1
+       eor.w d1,d0
+       move.w d0,0xdff180 | opcode^first param = background color
+       move.w S_SR+2(a0),-(sp)
+       move.l S_AREG+7*4(a0),a1
+       move.l a1,USP
+       movem.l (a0),d0-d7/a0-a6
+       
+       | cmp.l #0x,0x7a0000
+       | bne.s .not
+       | clr.w 0x100
+|.not:
+       
+       rte
+
+       | 68010+ test entrypoint
+_execute_test010:
+       movem.l d1-d7/a0-a6,-(sp)
+       move.l 14*4+4(sp),a0 | register struct
+       move.w sr,-(sp)
+       lea datapointer(pc),a1
+       move.l a0,(a1)+
+       move.l sp,(a1)
+       move.l S_SSP(a0),sp
+       move.l S_PC(a0),a1
+       clr.w -(sp)
+       move.l a1,-(sp)
+       move.w (a1)+,d0
+       move.w (a1),d1
+       eor.w d1,d0
+       move.w d0,0xdff180 | opcode^first param = background color
+       move.w S_SR+2(a0),-(sp)
+       move.l S_AREG+7*4(a0),a1
+       move.l a1,USP
+       movem.l (a0),d0-d7/a0-a6
+       rte
+
+       | 68020 test entrypoint
+_execute_test020:
+       movem.l d1-d7/a0-a6,-(sp)
+       move.l 14*4+4(sp),a0 | register struct
+       move.w sr,-(sp)
+       lea datapointer(pc),a1
+       move.l a0,(a1)+
+       move.l sp,(a1)
+       move.l S_SSP(a0),sp
+       move.l S_PC(a0),a1
+       clr.w -(sp)
+       move.l a1,-(sp)
+       move.w (a1)+,d0
+       move.w (a1),d1
+       eor.w d1,d0
+       move.w d0,0xdff180 | opcode^first param = background color
+       move.w S_SR+2(a0),-(sp)
+       move.l S_AREG+7*4(a0),a1
+       move.l a1,USP
+       move.l S_MSP(a0),a1
+       movec a1,MSP
+       movem.l (a0),d0-d7/a0-a6
+       rte
+
+       | 68020+FPU test entrypoint
+_execute_testfpu:
+       movem.l d1-d7/a0-a6,-(sp)
+       move.l 14*4+4(sp),a0 | register struct
+       move.w sr,-(sp)
+       lea datapointer(pc),a1
+       move.l a0,(a1)+
+       move.l sp,(a1)
+       move.l S_SSP(a0),sp
+       move.l S_PC(a0),a1
+       clr.w -(sp)
+       move.l a1,-(sp)
+       move.w (a1)+,d0
+       move.w (a1),d1
+       eor.w d1,d0
+       move.w d0,0xdff180 | opcode^first param = background color
+       move.w S_SR+2(a0),-(sp)
+       move.l S_AREG+7*4(a0),a1
+       move.l a1,USP
+       move.l S_MSP(a0),a1
+       movec a1,MSP
+       fmovem.x S_FPU(a0),fp0-fp7
+       lea S_FPIAR(a0),a1
+       fmove.l (a1)+,fpiar
+       fmove.l (a1)+,fpcr
+       fmove.l (a1)+,fpsr
+       movem.l (a0),d0-d7/a0-a6
+       rte
+
+
+_exceptiontable000:
+       bsr.s exception | 3
+       bsr.s exception | 4
+       bsr.s exception | 5
+       bsr.s exception | 6
+       bsr.s exception | 7
+       bsr.s exception | 8
+       bsr.s exception | 9
+       bsr.s exception | 10
+       bsr.s exception | 11
+       bsr.s exception | 12
+       bsr.s exception | 13
+       bsr.s exception | 14
+       bsr.s exception | 15
+       bsr.s exception | 16
+       bsr.s exception | 17
+       bsr.s exception | 18
+       bsr.s exception | 19
+       bsr.s exception | 20
+       bsr.s exception | 21
+       bsr.s exception | 22
+       bsr.s exception | 23
+       bsr.s exception | 24
+       bsr.s exception | 25
+       bsr.s exception | 26
+       bsr.s exception | 27
+       bsr.s exception | 28
+       bsr.s exception | 29
+       bsr.s exception | 30
+       bsr.s exception | 31
+       bsr.s exception | 32
+       bsr.s exception | 33
+       bsr.s exception | 34
+       bsr.s exception | 35
+       bsr.s exception | 36
+       bsr.s exception | 37
+       bsr.s exception | 38
+       bsr.s exception | 30
+       bsr.s exception | 40
+       bsr.s exception | 41
+       bsr.s exception | 42
+       bsr.s exception | 43
+       bsr.s exception | 44
+       bsr.s exception | 45
+       bsr.s exception | 46
+       bsr.s exception | 47
+       nop
+exception:
+       move.l a0,-(sp)
+       move.l datapointer(pc),a0
+       movem.l d0-d7/a0-a6,(a0)
+       move.l (sp)+,8*4(a0)
+       move.l (sp)+,d0
+       lea _exceptiontable000(pc),a1
+       sub.l a1,d0
+       lsr.w #1,d0
+       addq.w #2,d0
+       move.w d0,S_EXC+2(a0)
+
+       cmp.w #3,d0
+       bne.s .noaddresserror
+       move.w (sp),S_EXC+0(a0)
+       addq.w #8,sp
+.noaddresserror:
+       move.w (sp)+,S_SR+2(a0)
+       move.l (sp)+,S_PC(a0)
+
+       move.l USP,a1
+       move.l a1,S_AREG+7*4(a0)
+
+       move.l superstack(pc),sp
+       move.w (sp)+,sr
+       movem.l (sp)+,d1-d7/a0-a6
+       rts
+
+_exception010:
+       move.l a0,-(sp)
+       move.l datapointer(pc),a0
+       movem.l d0-d7/a0-a6,(a0)
+       move.l (sp)+,8*4(a0)
+
+       move.w (sp)+,S_SR+2(a0)
+       move.l (sp)+,S_PC(a0)
+       move.w (sp),d0
+       and.w #0xfff,d0
+       lsr.w #2,d0
+       move.w d0,S_EXC+2(a0)
+       
+       move.l USP,a1
+       move.l a1,S_AREG+7*4(a0)
+               
+       move.l superstack(pc),sp
+       move.w (sp)+,sr
+       movem.l (sp)+,d1-d7/a0-a6
+       rts
+       
+_exception020:
+       move.l a0,-(sp)
+       move.l datapointer(pc),a0
+       movem.l d0-d7/a0-a6,(a0)
+       move.l (sp)+,8*4(a0)
+
+       move.w (sp)+,S_SR+2(a0)
+       move.l (sp)+,S_PC(a0)
+       move.w (sp),d0
+       and.w #0xfff,d0
+       lsr.w #2,d0
+       move.w d0,S_EXC+2(a0)
+       
+       movec MSP,a1
+       move.l a1,S_MSP(a0)
+       move.l USP,a1
+       move.l a1,S_AREG+7*4(a0)
+               
+       | restore SR first, then stack
+       | M-bit may have been set.
+       move.l superstack(pc),a0
+       move.w (a0)+,sr
+       move.l a0,sp
+       movem.l (sp)+,d1-d7/a0-a6
+       rts
+
+_exceptionfpu:
+       move.l a0,-(sp)
+       move.l datapointer(pc),a0
+       movem.l d0-d7/a0-a6,(a0)
+       move.l (sp)+,8*4(a0)
+
+       move.w (sp)+,S_SR+2(a0)
+       move.l (sp)+,S_PC(a0)
+       move.w (sp),d0
+       and.w #0xfff,d0
+       lsr.w #2,d0
+       move.w d0,S_EXC+2(a0)
+       
+       movec MSP,a1
+       move.l a1,S_MSP(a0)
+       move.l USP,a1
+       move.l a1,S_AREG+7*4(a0)
+
+       fmovem.x fp0-fp7,S_FPU(a0)
+       lea S_FPIAR(a0),a1
+       fmove.l fpiar,(a1)+
+       fmove.l fpcr,(a1)+
+       fmove.l fpsr,(a1)+
+               
+       move.l superstack(pc),a0
+       move.w (a0)+,sr
+       move.l a0,sp
+       movem.l (sp)+,d1-d7/a0-a6
+       rts
+
+datapointer:
+       dc.l 0
+superstack:
+       dc.l 0
diff --git a/cputest/cputest_defines.h b/cputest/cputest_defines.h
new file mode 100644 (file)
index 0000000..3504429
--- /dev/null
@@ -0,0 +1,35 @@
+
+#define CT_FPREG 0
+#define CT_DREG 0
+#define CT_AREG 8
+#define CT_SSP 16
+#define CT_MSP 17
+#define CT_SR 18
+#define CT_PC 19
+#define CT_FPIAR 20
+#define CT_FPSR 21
+#define CT_FPCR 22
+#define CT_MEMWRITE 30
+#define CT_MEMWRITES 31
+#define CT_DATA_MASK 31
+#define CT_EXCEPTION_MASK 63
+
+#define CT_SIZE_BYTE (0 << 5)
+#define CT_SIZE_WORD (1 << 5)
+#define CT_SIZE_LONG (2 << 5)
+#define CT_SIZE_FPU (3 << 5) // CT_DREG -> CT_FPREG
+#define CT_SIZE_MASK (3 << 5)
+
+// if MEMWRITE or PC
+#define CT_RELATIVE_START_WORD (0 << 5) // word
+#define CT_ABSOLUTE_WORD (1 << 5)
+#define CT_ABSOLUTE_LONG (2 << 5)
+// if MEMWRITES
+#define CT_PC_BYTES (3 << 5)
+// if PC
+#define CT_RELATIVE_START_BYTE (3 << 5)
+
+#define CT_END 0x80
+#define CT_END_FINISH 0xff
+#define CT_END_INIT (0x80 | 0x40)
+#define CT_END_SKIP (0x80 | 0x40 | 0x01)
diff --git a/cputest/cputestgen.ini b/cputest/cputestgen.ini
new file mode 100644 (file)
index 0000000..ca12bd0
--- /dev/null
@@ -0,0 +1,66 @@
+
+[cputest]
+
+; CPU model (68000, 68020).
+; Always select 68020 when testing FPU instructions, even if test hardware CPU is 68040 or 68060.
+cpu=68000
+
+; FPU model (empty string or 0, 68881, 68882, 68040, 68060)
+; Enable only when testing FPU. Enabled FPU mode will slow down execution.
+fpu=
+
+; Write generated instructions to standard output. Always disabled in "all" mode.
+verbose=1
+
+; Where to generate test files
+path=data/
+
+; Low address space limits (0x0000 to 0x8000 is complete space)
+test_low_memory_start=0x0000
+test_low_memory_end=0x8000
+
+; High address space limits (0x00ff8000 to 0x01000000 is complete space)
+test_high_memory_start=0x00ff8000
+test_high_memory_end=0x01000000
+
+; ROM high address space
+high_rom=D:\amiga\roms\Kickstart v3.1 rev 40.63 (1993)(Commodore)(A500-A600-A2000)[!].rom
+
+; main test memory start and size (real hardware must have RAM in same address space)
+test_memory_start=0x780000
+test_memory_size=0x080000
+
+; test word or long odd data access address errors (68000/010 only)
+; 0 = do not generate address errors
+; 1 = include address errors
+; 2 = only generate test instructions that generate address errors
+feature_exception3_data=1
+
+; test branches to odd addresses
+; same as above
+feature_exception3_instruction=1
+
+; SR extra mask.
+; 0x8000 = T1
+; 0x4000 = T0 (68020)
+; 0x2000 = S
+; 0x1000 = M (68020)
+; Other bits are ignored.
+; For example 0xa000 adds 3 extra test rounds: S=1/T1=0, S=0/T1=1 and S=1/T1=1
+; Note: instructions that generate privilege violation exception will automatically add extra S=1 round.
+feature_sr_mask=0x0000
+
+; 68020+ addressing modes (this makes test files much larger if other addressing modes are also enabled)
+; currently does not generate any reserved mode bit combinations.
+feature_full_extension_format=0
+
+; empty = all addressing modes (feature_full_extension_format=1 enables 68020+ modes)
+; Dreg, Areg, Aind, Aipi, Apdi, Ad16, PC16, Ad8r, PC8r, absw, absl, imm.
+; Ad8rf and PC8rf = 68020+ full extension only. For example "Aind,Aipi,imm"
+; Note: FPU source EA is considered destination EA.
+feature_addressing_modes_src=
+feature_addressing_modes_dst=
+
+; mnemonics separated by comma or all.
+; all = generate all. tst = generate tst.b, tst.w and tst.l. tst.l = generate only tst.l
+mode=abcd,mv2sr,mvsr2
diff --git a/cputest/main.c b/cputest/main.c
new file mode 100644 (file)
index 0000000..0804ec6
--- /dev/null
@@ -0,0 +1,1478 @@
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+
+
+#ifdef _MSC_VER
+#include "msc_dirent.h"
+#else
+#include <dirent.h>
+#endif
+
+#define DONTSTOPONERROR 0
+
+typedef unsigned int uae_u32;
+typedef int uae_s32;
+typedef unsigned short uae_u16;
+typedef short uae_s16;
+typedef unsigned char uae_u8;
+typedef signed char uae_s8;
+
+#include "cputest_defines.h"
+
+struct fpureg
+{
+       uae_u16 exp;
+       uae_u16 dummy;
+       uae_u32 m[2];
+};
+
+struct registers
+{
+       uae_u32 regs[16];
+       uae_u32 ssp;
+       uae_u32 msp;
+       uae_u32 pc;
+       uae_u32 sr;
+       uae_u32 exc;
+       struct fpureg fpuregs[8];
+       uae_u32 fpiar, fpcr, fpsr;
+};
+
+static struct registers test_regs;
+static struct registers last_registers;
+static struct registers regs;
+static uae_u8 *opcode_memory;
+static uae_u32 opcode_memory_addr;
+static uae_u8 *low_memory;
+static uae_u8 *high_memory;
+static uae_u8 *test_memory;
+static uae_u32 test_memory_addr;
+static uae_u32 test_memory_size;
+static uae_u8 *test_data;
+static int test_data_size;
+static uae_u32 oldvbr;
+static uae_u8 *vbr_zero = 0;
+static int hmem_rom, lmem_rom;
+static uae_u8 *absallocated;
+static int cpu_lvl, fpu_model;
+static uae_u16 sr_undefined_mask;
+static int check_undefined_sr;
+static uae_u32 cpustatearraystore[16];
+static uae_u32 cpustatearraynew[] = {
+       0x00000005, // SFC
+       0x00000005, // DFC
+       0x00000009, // CACR
+       0x00000000, // CAAR
+       0x00000000, // MSP
+};
+
+static uae_u8 low_memory_temp[32768];
+static uae_u8 high_memory_temp[32768];
+static uae_u8 low_memory_back[32768];
+static uae_u8 high_memory_back[32768];
+
+static uae_u32 vbr[256];
+       
+static char inst_name[16+1];
+#ifdef _MSC_VER
+static char outbuffer[40000];
+#else
+static char outbuffer[4000];
+#endif
+static char *outbp;
+static int infoadded;
+static int errors;
+static int testcnt;
+static int dooutput = 1;
+static int quit;
+static uae_u8 ccr_mask;
+static uae_u32 addressing_mask = 0x00ffffff;
+
+#ifdef _MSC_VER
+
+#define xmemcpy memcpy
+
+static uae_u8 *allocate_absolute(uae_u32 addr, uae_u32 size)
+{
+       return calloc(1, size);
+}
+static void free_absolute(uae_u32 addr, uae_u32 size)
+{
+}
+static void execute_test000(struct registers *regs)
+{
+}
+static void execute_test010(struct registers *regs)
+{
+}
+static void execute_test020(struct registers *regs)
+{
+}
+static void execute_testfpu(struct registers *regs)
+{
+}
+static uae_u32 tosuper(uae_u32 v)
+{
+       return 0;
+}
+static void touser(uae_u32 v)
+{
+}
+static uae_u32 exceptiontable000, exception010, exception020, exceptionfpu;
+static uae_u32 testexit(void)
+{
+       return 0;
+}
+static uae_u32 setvbr(uae_u32 v)
+{
+       return 0;
+}
+static uae_u32 get_cpu_model(void)
+{
+       return 0;
+}
+static void setcpu(uae_u32 v, uae_u32 *s, uae_u32 *d)
+{
+}
+static void flushcache(void)
+{
+}
+#else
+
+static void xmemcpy(void *d, void *s, int size)
+{
+       __builtin_memcpy(d, s, size);
+}
+
+extern uae_u8 *allocate_absolute(uae_u32, uae_u32);
+extern void free_absolute(uae_u32, uae_u32);
+extern void execute_test000(struct registers*);
+extern void execute_test010(struct registers *);
+extern void execute_test020(struct registers *);
+extern void execute_testfpu(struct registers *);
+extern uae_u32 tosuper(uae_u32);
+extern void touser(uae_u32);
+extern uae_u32 exceptiontable000, exception010, exception020, exceptionfpu;
+extern uae_u32 testexit(void);
+extern uae_u32 setvbr(uae_u32);
+extern uae_u32 get_cpu_model(void);
+extern void setcpu(uae_u32, uae_u32*, uae_u32*);
+extern void flushcache(void);
+
+#endif
+
+struct accesshistory
+{
+       uae_u8 *addr;
+       uae_u32 val;
+       uae_u32 oldval;
+       int size;
+};
+static int ahcnt;
+
+#define MAX_ACCESSHIST 8
+static struct accesshistory ahist[MAX_ACCESSHIST];
+
+static void endinfo(void)
+{
+       printf("Last test: %lu\n", testcnt);
+       uae_u8 *p = opcode_memory;
+       for (int i = 0; i < 32 * 2; i += 2) {
+               uae_u16 v = (p[i] << 8) | (p[i + 1]);
+               if (v == 0x4afc && i > 0)
+                       break;
+               printf(" %04x", v);
+       }
+       printf("\n");
+}
+
+static int test_active;
+static uae_u32 enable_data;
+
+static void start_test(void)
+{
+       if (test_active)
+               return;
+
+#ifndef _MSC_VER
+       if (lmem_rom) {
+               if (memcmp(low_memory, low_memory_temp, 32768)) {
+                       printf("Low memory ROM mismatch!\n");
+                       exit(0);
+               }
+       }
+       if (hmem_rom) {
+               if (memcmp(high_memory, high_memory_temp, 32768)) {
+                       printf("High memory ROM mismatch!\n");
+                       exit(0);
+               }
+       }
+#endif
+
+       test_active = 1;
+
+       enable_data = tosuper(0);
+
+       memcpy(low_memory_back, low_memory, 32768);
+       if (!hmem_rom)
+               memcpy(high_memory_back, high_memory, 32768);
+
+       memcpy(low_memory, low_memory_temp, 32768);
+       if (!hmem_rom)
+               memcpy(high_memory, high_memory_temp, 32768);
+
+       if (cpu_lvl == 0) {
+               uae_u32 *p = (uae_u32 *)vbr_zero;
+               for (int i = 3; i < 12; i++) {
+                       p[i] = (uae_u32)(((uae_u32)&exceptiontable000) + (i - 3) * 2);
+               }
+               for (int i = 32; i < 48; i++) {
+                       p[i] = (uae_u32)(((uae_u32)&exceptiontable000) + (i - 3) * 2);
+               }
+       } else {
+               oldvbr = setvbr((uae_u32)vbr);
+               for (int i = 0; i < 256; i++) {
+                       vbr[i] = fpu_model ? (uae_u32)(&exceptionfpu) : (cpu_lvl == 1 ? (uae_u32)(&exception010) : (uae_u32)(&exception020));
+               }
+       }
+       setcpu(cpu_lvl, cpustatearraynew, cpustatearraystore);
+}
+
+static void end_test(void)
+{
+       if (!test_active)
+               return;
+       test_active = 0;
+
+       memcpy(low_memory, low_memory_back, 32768);
+       if (!hmem_rom)
+               memcpy(high_memory, high_memory_back, 32768);
+
+       if (cpu_lvl > 0) {
+               setvbr(oldvbr);
+       }
+       setcpu(cpu_lvl, cpustatearraystore, NULL);
+
+       touser(enable_data);
+}
+
+static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *sizep)
+{
+       char fname[256];
+       sprintf(fname, "%s%s", path, file);
+       FILE *f = fopen(fname, "rb");
+       if (!f) {
+               printf("Couldn't open '%s'\n", fname);
+               exit(0);
+       }
+       int size = *sizep;
+       if (size < 0) {
+               fseek(f, 0, SEEK_END);
+               size = ftell(f);
+               fseek(f, 0, SEEK_SET);
+       }
+       if (!p) {
+               p = calloc(1, size);
+               if (!p) {
+                       printf("Couldn't allocate %ld bytes, file '%s'\n", size, fname);
+                       exit(0);
+               }
+       }
+       *sizep = fread(p, 1, size, f);
+       if (*sizep != size) {
+               printf("Couldn't read file '%s'\n", fname);
+               exit(0);
+       }
+       fclose(f);
+       return p;
+}
+
+static void pl(uae_u8 *p, uae_u32 v)
+{
+       p[0] = v >> 24;
+       p[1] = v >> 16;
+       p[2] = v >>  8;
+       p[3] = v >>  0;
+}
+static uae_u32 gl(uae_u8 *p)
+{
+       return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
+}
+
+static uae_u8 *restore_fpvalue(uae_u8 *p, struct fpureg *fp)
+{
+       uae_u8 v = *p++;
+       if ((v & CT_SIZE_MASK) != CT_SIZE_FPU) {
+               end_test();
+               printf("Expected CT_SIZE_FPU, got %02x\n", v);
+               endinfo();
+               exit(0);
+       }
+       fp->exp = (p[0] << 8) | p[1];
+       p += 2;
+       fp->m[0] = gl(p);
+       p += 4;
+       fp->m[1] = gl(p);
+       p += 4;
+       return p;
+}
+
+static uae_u8 *restore_value(uae_u8 *p, uae_u32 *vp, int *sizep)
+{
+       uae_u32 val = *vp;
+       uae_u8 v = *p++;
+       switch(v & CT_SIZE_MASK)
+       {
+               case CT_SIZE_BYTE:
+               val &= 0xffffff00;
+               val |= *p++;
+               *sizep = 0;
+               break;
+               case CT_SIZE_WORD:
+               val &= 0xffff0000;
+               val |= (*p++) << 8;
+               val |= *p++;
+               *sizep = 1;
+               break;
+               case CT_SIZE_LONG:
+               val  = (*p++) << 24;
+               val |= (*p++) << 16;
+               val |= (*p++) << 8;
+               val |= *p++;
+               *sizep = 2;
+               break;
+               case CT_SIZE_FPU:
+               end_test();
+               printf("Unexpected CT_SIZE_FPU\n");
+               endinfo();
+               exit(0);
+               break;
+       }
+       *vp = val;
+       return p;
+}
+
+static uae_u8 *restore_rel(uae_u8 *p, uae_u32 *vp)
+{
+       uae_u32 v = *vp;
+       switch ((*p++) & CT_SIZE_MASK)
+       {
+               case CT_RELATIVE_START_BYTE:
+               {
+                       uae_u8 val;
+                       val = *p++;
+                       v += (uae_s8)val;
+                       break;
+               }
+               case CT_RELATIVE_START_WORD:
+               {
+                       uae_u16 val;
+                       val = (*p++) << 8;
+                       val |= *p++;
+                       v += (uae_s16)val;
+                       break;
+               }
+               case CT_ABSOLUTE_WORD:
+               {
+                       uae_u16 val;
+                       val = (*p++) << 8;
+                       val |= *p++;
+                       v = (uae_s32)(uae_s16)val;
+                       break;
+               }
+               case CT_ABSOLUTE_LONG:
+               {
+                       uae_u32 val;
+                       val = (*p++) << 24;
+                       val |= (*p++) << 16;
+                       val |= (*p++) << 8;
+                       val |= *p++;
+                       v = val;
+                       if ((val & addressing_mask) < 0x8000) {
+                               ; // low memory
+                       } else if ((val & ~addressing_mask) == ~addressing_mask && val >= 0xfff80000) {
+                               ; // high memory
+                       } else if ((val & addressing_mask) < test_memory_addr || (val & addressing_mask) >= test_memory_addr + test_memory_size) {
+                               end_test();
+                               printf("restore_rel CT_ABSOLUTE_LONG outside of test memory! %08x\n", v);
+                               endinfo();
+                               exit(0);
+                       }
+                       break;
+               }
+       }
+       *vp = v;
+       return p;
+}
+
+static void validate_mode(uae_u8 mode, uae_u8 v)
+{
+       if ((mode & CT_DATA_MASK) != v) {
+               end_test();
+               printf("CT_MEMWRITE expected but got %02X\n", mode);
+               endinfo();
+               exit(0);
+       }
+}
+
+static uae_u8 *get_memory_addr(uae_u8 *p, uae_u8 **addrp)
+{
+       uae_u8 v = *p++;
+       switch(v & CT_SIZE_MASK)
+       {
+               case CT_ABSOLUTE_WORD:
+               {
+                       uae_u16 val;
+                       val = (*p++) << 8;
+                       val |= *p++;
+                       uae_u8 *addr;
+                       uae_s16 offset = (uae_s16)val;
+                       if (offset < 0) {
+                               addr = high_memory + 32768 + offset;
+                       } else {
+                               addr = low_memory + offset;
+                       }
+                       validate_mode(p[0], CT_MEMWRITE);
+                       *addrp = addr;
+                       return p;
+               }
+               case CT_ABSOLUTE_LONG:
+               {
+                       uae_u32 val;
+                       val  = (*p++) << 24;
+                       val |= (*p++) << 16;
+                       val |= (*p++) << 8;
+                       val |= *p++;
+                       if (val < test_memory_addr || val >= test_memory_addr + test_memory_size) {
+                               end_test();
+                               printf("get_memory_addr CT_ABSOLUTE_LONG outside of test memory! %08x\n", val);
+                               endinfo();
+                               exit(0);
+                       }
+#ifdef _MSC_VER
+                       uae_u8 *addr = test_memory + (val - test_memory_addr);
+#else
+                       uae_u8 *addr = (uae_u8 *)val;
+#endif
+                       validate_mode(p[0], CT_MEMWRITE);
+                       *addrp = addr;
+                       return p;
+               }
+               case CT_RELATIVE_START_WORD:
+               {
+                       uae_u16 val;
+                       val = (*p++) << 8;
+                       val |= *p++;
+                       uae_s16 offset = (uae_s16)val;
+                       uae_u8 *addr = opcode_memory + offset;
+                       validate_mode(p[0], CT_MEMWRITE);
+                       *addrp = addr;
+                       return p;
+               }
+               break;
+
+               default:
+                       end_test();
+                       printf("get_memory_addr unknown size %02x\n", v);
+                       endinfo();
+                       exit(0);
+       }
+       return NULL;            
+}
+
+static void tomem(uae_u8 *p, uae_u32 v, uae_u32 oldv, int size, int storedata)
+{
+       if (storedata) {
+               struct accesshistory *ah = &ahist[ahcnt++];
+               ah->oldval = oldv;
+               ah->val = v;
+               ah->size = size;
+               ah->addr = p;
+       }
+       switch (size)
+       {
+               case 0:
+                       p[0] = (uae_u8)v;
+                       break;
+               case 1:
+                       p[0] = (uae_u8)(v >> 8);
+                       p[1] = (uae_u8)(v >> 0);
+                       break;
+               case 2:
+                       p[0] = (uae_u8)(v >> 24);
+                       p[1] = (uae_u8)(v >> 16);
+                       p[2] = (uae_u8)(v >> 8);
+                       p[3] = (uae_u8)(v >> 0);
+                       break;
+       }
+}
+
+static void restoreahist(void)
+{
+       for (int i = ahcnt - 1; i >= 0; i--) {
+               struct accesshistory *ah = &ahist[ahcnt];
+               tomem(ah->addr, ah->oldval, 0, ah->size, 0);
+       }
+       ahcnt = 0;
+}
+
+
+static uae_u8 *restore_memory(uae_u8 *p, int storedata)
+{
+       uae_u8 v = *p;
+       switch (v & CT_SIZE_MASK)
+       {
+               case CT_ABSOLUTE_WORD:
+               {
+                       uae_u8 *addr;
+                       int size;
+                       p = get_memory_addr(p, &addr);
+                       uae_u32 mv = 0;
+                       uae_u32 oldv = 0;
+                       p = restore_value(p, &oldv, &size);
+                       p = restore_value(p, &mv, &size);
+                       tomem(addr, mv, oldv, size, storedata);
+                       return p;
+               }
+               case CT_ABSOLUTE_LONG:
+               {
+                       uae_u8 *addr;
+                       int size;
+                       p = get_memory_addr(p, &addr);
+                       uae_u32 mv = 0;
+                       uae_u32 oldv = 0;
+                       p = restore_value(p, &oldv, &size);
+                       p = restore_value(p, &mv, &size);
+                       tomem(addr, mv, oldv, size, storedata);
+                       return p;
+               }
+       }
+       if ((v & CT_DATA_MASK) == CT_MEMWRITES) {
+               switch (v & CT_SIZE_MASK)
+               {
+                       case CT_PC_BYTES:
+                       {
+                               p++;
+                               uae_u8 *addr = opcode_memory;
+                               uae_u8 v = *p++;
+                               addr += v >> 5;
+                               v &= 31;
+                               if (v == 0)
+                                       v = 32;
+                               memcpy(addr, p, v);
+                               p += v;
+                               break;
+                       }
+                       default:
+                               end_test();
+                               printf("Unknown restore_memory type!?\n");
+                               endinfo();
+                               exit(0);
+                               break;
+                       }
+       } else {
+               switch (v & CT_SIZE_MASK)
+               {
+                       case CT_RELATIVE_START_WORD:
+                       {
+                               uae_u8 *addr;
+                               int size;
+                               p = get_memory_addr(p, &addr);
+                               uae_u32 mv = 0, oldv = 0;
+                               p = restore_value(p, &oldv, &size);
+                               p = restore_value(p, &mv, &size);
+                               tomem(addr, mv, oldv, size, storedata);
+                               return p;
+                       }
+                       default:
+                               end_test();
+                               printf("Unknown restore_memory type!?\n");
+                               endinfo();
+                               exit(0);
+                               break;
+               }
+       }
+       return p;
+}
+
+static uae_u8 *restore_data(uae_u8 *p)
+{
+       uae_u8 v = *p;
+       if (v & CT_END) {
+               end_test();
+               printf("Unexpected end bit!? offset %ld\n", p - test_data);
+               endinfo();
+               exit(0);
+       }
+       int mode = v & CT_DATA_MASK;
+       if (mode < CT_AREG + 8) {
+               int size;
+               if ((v & CT_SIZE_MASK) == CT_SIZE_FPU) {
+                       p = restore_fpvalue(p, &regs.fpuregs[mode]);
+               } else {
+                       p = restore_value(p, &regs.regs[mode], &size);
+               }
+       } else if (mode == CT_SR) {
+               int size;
+               p = restore_value(p, &regs.sr, &size);
+       } else if (mode == CT_FPIAR) {
+               int size;
+               p = restore_value(p, &regs.fpiar, &size);
+       } else if (mode == CT_FPCR) {
+               int size;
+               p = restore_value(p, &regs.fpcr, &size);
+       } else if (mode == CT_FPSR) {
+               int size;
+               p = restore_value(p, &regs.fpsr, &size);
+       } else if (mode == CT_MEMWRITE) {
+               // if memwrite, store old data
+               p = restore_memory(p, 1);
+       } else if (mode == CT_MEMWRITES) {
+               p = restore_memory(p, 0);
+       } else {
+               end_test();
+               printf("Unexpected mode %02x\n", v);
+               endinfo();
+               exit(0);
+       }
+       return p;
+}
+
+int    Disass68k(long addr, char *labelBuffer, char *opcodeBuffer, char *operandBuffer, char *commentBuffer);
+void Disasm_SetCPUType(int CPU, int FPU);
+
+static uae_u16 test_sr;
+static uae_u32 test_fpsr, test_fpcr;
+
+static void addinfo(void)
+{
+       if (infoadded)
+               return;
+       infoadded = 1;
+       if (!dooutput)
+               return;
+       sprintf(outbp, "%lu:", testcnt);
+       outbp += strlen(outbp);
+       uae_u8 *p = opcode_memory;
+       for (int i = 0; i < 32 * 2; i += 2) {
+               uae_u16 v = (p[i] << 8) |(p[i + 1]);
+               if (v == 0x4afc && i > 0)
+                       break;
+               sprintf(outbp, " %04x", v);
+               outbp += strlen(outbp);
+       }
+       strcat(outbp, " ");
+       outbp += strlen(outbp);
+
+       Disasm_SetCPUType(0, 0);
+       char buf1[80], buf2[80], buf3[80], buf4[80];
+       Disass68k((long)opcode_memory, buf1, buf2, buf3, buf4);
+       sprintf(outbp, "%s %s\n", buf2, buf3);
+       outbp += strlen(outbp);
+}
+
+static void out_regs(struct registers *r, int before)
+{
+       for (int i = 0; i < 16; i++) {
+               if (i > 0 && (i % 4) == 0) {
+                       strcat(outbp, "\n");
+               } else if ((i % 8) != 0) {
+                       strcat(outbp, " ");
+               }
+               outbp += strlen(outbp);
+               sprintf(outbp, "%c%d:%c%08lx", i < 8 ? 'D' : 'A', i & 7, test_regs.regs[i] != regs.regs[i] ? '*' : ' ', r->regs[i]);
+               outbp += strlen(outbp);
+       }
+       strcat(outbp, "\n");
+       outbp += strlen(outbp);
+       sprintf(outbp, "SR:%c%04x   PC: %08lx ISP: %08lx MSP: %08lx\n", test_regs.sr != test_sr ? '*' : ' ', before ? test_sr : r->sr, r->pc, r->ssp, r->msp);
+       outbp += strlen(outbp);
+       uae_u16 s = before ? test_sr : r->sr;
+       uae_u16 s1 = test_regs.sr;
+       uae_u16 s2 = test_sr;
+       sprintf(outbp, "T%c%d S%c%d X%c%d N%c%d Z%c%d V%c%d C%c%d",
+               (s1 & 0x8000) != (s2 & 0x8000) ? '*' : '=', (s & 0x8000) != 0,
+               (s1 & 0x2000) != (s2 & 0x2000) ? '*' : '=', (s & 0x2000) != 0,
+               (s1 & 0x10) != (s2 & 0x10) ? '*' : '=', (s & 0x10) != 0,
+               (s1 & 0x08) != (s2 & 0x08) ? '*' : '=', (s & 0x08) != 0,
+               (s1 & 0x04) != (s2 & 0x04) ? '*' : '=', (s & 0x04) != 0,
+               (s1 & 0x02) != (s2 & 0x02) ? '*' : '=', (s & 0x02) != 0,
+               (s1 & 0x01) != (s2 & 0x01) ? '*' : '=', (s & 0x01) != 0);
+       outbp += strlen(outbp);
+
+       if (!fpu_model) {
+               strcat(outbp, "\n");
+               outbp += strlen(outbp);
+               return;
+       }
+
+       for (int i = 0; i < 8; i++) {
+               if ((i % 2) == 0) {
+                       strcat(outbp, "\n");
+               }
+               else if ((i % 4) != 0) {
+                       strcat(outbp, " ");
+               }
+               outbp += strlen(outbp);
+               struct fpureg *f = &r->fpuregs[i];
+               void *f1 = &regs.fpuregs[i];
+               void *f2 = &test_regs.fpuregs[i];
+               sprintf(outbp, "FP%d:%c%04x-%08lx%08lx %f",
+                       i,
+                       memcmp(f1, f2, 12) ? '*' : ' ',
+                       f->exp, f->m[0], f->m[1],
+                       *((long double*)f));
+               outbp += strlen(outbp);
+       }
+       sprintf(outbp, "\nFPSR:%c%08lx FPCR:%c%08lx FPIAR:%c%08lx\n",
+               test_fpsr != test_regs.fpsr ? '*' : ' ', before ? test_fpsr : r->fpsr,
+               test_fpcr != test_regs.fpcr ? '*' : ' ', before ? test_fpcr : r->fpcr,
+               regs.fpiar != test_regs.fpiar ? '*' : ' ', r->fpiar);
+
+       outbp += strlen(outbp);
+
+}
+
+static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
+{
+       uae_u8 regs_changed[16] = { 0 };
+       uae_u8 regs_fpuchanged[8] = { 0 };
+       uae_u8 sr_changed = 0, pc_changed = 0;
+       uae_u8 fpiar_changed = 0, fpsr_changed = 0, fpcr_changed = 0;
+       int exc = -1;
+
+       for (int i = 0; i < 16; i++) {
+               if (last_registers.regs[i] != test_regs.regs[i]) {
+                       regs_changed[i] = 1;
+               }
+       }
+       if (last_registers.sr != test_regs.sr) {
+               sr_changed = 1;
+       }
+       if (last_registers.pc != test_regs.pc) {
+               pc_changed = 1;
+       }
+       if (fpu_model) {
+               for (int i = 0; i < 8; i++) {
+                       if (memcmp(&last_registers.fpuregs[i], &test_regs.fpuregs[i], 12)) {
+                               regs_fpuchanged[i] = 1;
+                       }
+               }
+               if (last_registers.fpsr != test_regs.fpsr) {
+                       fpsr_changed = 1;
+               }
+               if (last_registers.fpcr != test_regs.fpcr) {
+                       fpcr_changed = 1;
+               }
+               if (last_registers.fpiar != test_regs.fpiar) {
+                       fpiar_changed = 1;
+               }
+       }
+
+       if (*p == CT_END_SKIP)
+               return p + 1;
+
+       for (;;) {
+               uae_u8 v = *p;
+               if (v & CT_END) {
+                       exc = v & CT_EXCEPTION_MASK;
+                       int cpuexc = test_regs.exc & 65535;
+                       p++;
+                       if ((v & CT_END_INIT) == CT_END_INIT) {
+                               end_test();
+                               printf("Unexpected CT_END_INIT %02x %08lx\n", v, p - test_data);
+                               endinfo();
+                               exit(0);
+                       }
+                       if (exc == 1) {
+                               end_test();
+                               printf("Invalid exception ID %02x\n", exc);
+                               endinfo();
+                               exit(0);
+                       }
+                       if (ignore_errors)
+                               break;
+                       if (exc == 0 && cpuexc == 4) {
+                               // successful complete generates exception 4 with matching PC
+                               if (last_registers.pc != test_regs.pc && dooutput) {
+                                       sprintf(outbp, "PC: expected %08lx but got %08lx\n", last_registers.pc, test_regs.pc);
+                                       outbp += strlen(outbp);
+                                       errors++;
+                               }
+                               break;
+                       }
+                       if (exc != cpuexc) {
+                               addinfo();
+                               if (dooutput) {
+                                       if (cpuexc == 4 && last_registers.pc == test_regs.pc) {
+                                               sprintf(outbp, "Exception ID: expected %d but got no exception.\n", exc);
+                                       } else {
+                                               sprintf(outbp, "Exception ID: expected %d but got %d\n", exc, cpuexc);
+                                       }
+                               }
+                               outbp += strlen(outbp);
+                               errors++;
+                       }
+                       break;
+               }
+               int mode = v & CT_DATA_MASK;
+               if (mode < CT_AREG + 8) {
+                       uae_u32 val = last_registers.regs[mode];
+                       int size;
+                       p = restore_value(p, &val, &size);
+                       if (val != test_regs.regs[mode] && !ignore_errors) {
+                               addinfo();
+                               if (dooutput) {
+                                       sprintf(outbp, "%c%d: expected %08lx but got %08lx\n", mode < CT_AREG ? 'D' : 'A', mode & 7, val, test_regs.regs[mode]);
+                                       outbp += strlen(outbp);
+                               }
+                               errors++;
+                       }
+                       regs_changed[mode] = 0;
+                       last_registers.regs[mode] = val;
+               } else if (mode == CT_SR) {
+                       uae_u32 val = last_registers.sr;
+                       int size;
+                       p = restore_value(p, &val, &size);
+                       if ((val & sr_undefined_mask) != (test_regs.sr & sr_undefined_mask) && !ignore_errors && !ignore_sr) {
+                               addinfo();
+                               if (dooutput) {
+                                       sprintf(outbp, "SR: expected %04x -> %04x but got %04x\n", test_sr, val, test_regs.sr);
+                                       outbp += strlen(outbp);
+                               }
+                               errors++;
+                       }
+                       sr_changed = 0;
+                       last_registers.sr = val;
+               } else if (mode == CT_PC) {
+                       uae_u32 val = last_registers.pc;
+                       p = restore_rel(p, &val);
+                       pc_changed = 0;
+                       last_registers.pc = val;
+               } else if (mode == CT_FPCR) {
+                       uae_u32 val = last_registers.fpcr;
+                       int size;
+                       p = restore_value(p, &val, &size);
+                       if (val != test_regs.fpcr && !ignore_errors) {
+                               addinfo();
+                               if (dooutput) {
+                                       sprintf(outbp, "FPCR: expected %08lx -> %08lx but got %08lx\n", test_fpcr, val, test_regs.fpcr);
+                                       outbp += strlen(outbp);
+                               }
+                               errors++;
+                       }
+                       fpcr_changed = 0;
+                       last_registers.fpcr = val;
+               } else if (mode == CT_FPSR) {
+                       uae_u32 val = last_registers.fpsr;
+                       int size;
+                       p = restore_value(p, &val, &size);
+                       if (val != test_regs.fpsr && !ignore_errors) {
+                               addinfo();
+                               if (dooutput) {
+                                       sprintf(outbp, "FPSR: expected %08lx -> %08lx but got %08lx\n", test_fpsr, val, test_regs.fpsr);
+                                       outbp += strlen(outbp);
+                               }
+                               errors++;
+                       }
+                       fpsr_changed = 0;
+                       last_registers.fpsr = val;
+               } else if (mode == CT_FPIAR) {
+                       uae_u32 val = last_registers.fpiar;
+                       p = restore_rel(p, &val);
+                       if (val != test_regs.fpiar && !ignore_errors) {
+                               addinfo();
+                               if (dooutput) {
+                                       sprintf(outbp, "FPIAR: expected %08x but got %08x\n", val, test_regs.fpiar);
+                                       outbp += strlen(outbp);
+                               }
+                               errors++;
+                       }
+                       fpiar_changed = 0;
+                       last_registers.fpiar = val;
+
+               } else if (mode == CT_MEMWRITES) {
+                       p = restore_memory(p, 0);
+               } else if (mode == CT_MEMWRITE) {
+                       uae_u8 *addr;
+                       uae_u32 val = 0, mval = 0, oldval = 0;
+                       int size;
+                       p = get_memory_addr(p, &addr);
+                       p = restore_value(p, &oldval, &size);
+                       p = restore_value(p, &val, &size);
+                       switch(size)
+                       {
+                               case 0:
+                               mval = addr[0];
+                               if (mval != val && !ignore_errors) {
+                                       addinfo();
+                                       if (dooutput) {
+                                               sprintf(outbp, "Memory byte write: address %08lx, expected %02x but got %02x\n", (uae_u32)addr, val, mval);
+                                               outbp += strlen(outbp);
+                                       }
+                                       errors++;
+                               }
+                               addr[0] = oldval;
+                               break;
+                               case 1:
+                               mval = (addr[0] << 8) | (addr[1]);
+                               if (mval != val && !ignore_errors) {
+                                       addinfo();
+                                       if (dooutput) {
+                                               sprintf(outbp, "Memory word write: address %08lx, expected %04x but got %04x\n", (uae_u32)addr, val, mval);
+                                               outbp += strlen(outbp);
+                                       }
+                                       errors++;
+                               }
+                               addr[0] = oldval >> 8;
+                               addr[1] = oldval;
+                               break;
+                               case 2:
+                               mval = gl(addr);
+                               if (mval != val && !ignore_errors) {
+                                       addinfo();
+                                       if (dooutput) {
+                                               sprintf(outbp, "Memory long write: address %08lx, expected %08lx but got %08x\n", (uae_u32)addr, val, mval);
+                                               outbp += strlen(outbp);
+                                       }
+                                       errors++;
+                               }
+                               pl(addr, oldval);
+                               break;
+                       }
+               } else {
+                       end_test();
+                       printf("Unknown test data %02x\n", v);
+                       exit(0);
+               }
+       }
+       if (!ignore_errors) {
+               for (int i = 0; i < 16; i++) {
+                       if (regs_changed[i]) {
+                               addinfo();
+                               if (dooutput) {
+                                       sprintf(outbp, "%c%d: modified %08lx -> %08lx but expected no modifications\n", i < 8 ? 'D' : 'A', i & 7, last_registers.regs[i], test_regs.regs[i]);
+                                       outbp += strlen(outbp);
+                               }
+                               errors++;
+                       }
+               }
+               if (sr_changed) {
+                       addinfo();
+                       if (dooutput) {
+                               sprintf(outbp, "SR: modified %04x -> %04x but expected no modifications\n", last_registers.sr, test_regs.sr);
+                               outbp += strlen(outbp);
+                       }
+                       errors++;
+               }
+               for (int i = 0; i < 8; i++) {
+                       if (regs_fpuchanged[i]) {
+                               addinfo();
+                               if (dooutput) {
+                                       sprintf(outbp, "FP%d: modified %f -> %f but expected no modifications\n", i,
+                                               *((long double *)(&last_registers.fpuregs[i])), *((long double *)(&test_regs.fpuregs[i])));
+                                       outbp += strlen(outbp);
+                               }
+                               errors++;
+                       }
+               }
+               if (fpsr_changed) {
+                       addinfo();
+                       if (dooutput) {
+                               sprintf(outbp, "FPSR: modified %08x -> %08x but expected no modifications\n", last_registers.fpsr, test_regs.fpsr);
+                               outbp += strlen(outbp);
+                       }
+                       errors++;
+               }
+               if (fpcr_changed) {
+                       addinfo();
+                       if (dooutput) {
+                               sprintf(outbp, "FPCR: modified %08x -> %08x but expected no modifications\n", last_registers.fpcr, test_regs.fpcr);
+                               outbp += strlen(outbp);
+                       }
+                       errors++;
+               }
+               if (fpiar_changed) {
+                       addinfo();
+                       if (dooutput) {
+                               sprintf(outbp, "FPIAR: modified %08x -> %08x but expected no modifications\n", last_registers.fpiar, test_regs.fpiar);
+                               outbp += strlen(outbp);
+                       }
+                       errors++;
+               }
+       }
+       if (errors && dooutput) {
+               addinfo();
+               if (!fpu_model) {
+                       strcat(outbp, "Registers before:\n");
+                       outbp += strlen(outbp);
+               }
+               out_regs(&regs, 1);
+               if (!fpu_model) {
+                       strcat(outbp, "Registers after:\n");
+                       outbp += strlen(outbp);
+               }
+               out_regs(&test_regs, 0);
+               if (exc > 1) {
+                       sprintf(outbp, "OK: Generated exception %d\n", exc);
+                       outbp += strlen(outbp);
+                       if (exc == 3 && cpu_lvl == 0) {
+                               sprintf(outbp, "RW=%d IN=%d FC=%d\n",
+                                       ((test_regs.exc >> (16 + 4)) & 1),
+                                       ((test_regs.exc >> (16 + 3)) & 1),
+                                       ((test_regs.exc >> (16 + 0)) & 7));
+                               outbp += strlen(outbp);
+                       }
+               } else if (exc == 0 && (test_regs.exc & 65535) == 4) {
+                       sprintf(outbp, "OK: No exception generated\n");
+                       outbp += strlen(outbp);
+               }
+       }
+       return p;
+}
+
+static void process_test(uae_u8 *p)
+{
+       outbp = outbuffer;
+       outbp[0] = 0;
+       infoadded = 0;
+       errors = 0;
+
+       memset(&regs, 0, sizeof(struct registers));
+
+       start_test();
+
+       ahcnt = 0;
+
+       for (;;) {
+
+#ifdef _MSC_VER
+               outbp = outbuffer;
+#endif
+
+               for (;;) {
+                       uae_u8 v = *p;
+                       if (v == CT_END_INIT || v == CT_END_FINISH)
+                               break;
+                       p = restore_data(p);
+               }
+               if (*p == CT_END_FINISH)
+                       break;
+               p++;
+
+               xmemcpy(&last_registers, &regs, sizeof(struct registers));
+
+               int fpumode = fpu_model && (opcode_memory[0] & 0xf0) == 0xf0;
+
+               if (cpu_lvl >= 2)
+                       flushcache();
+
+               uae_u32 pc = opcode_memory_addr;
+
+               int extraccr = 0;
+
+               uae_u32 last_pc = opcode_memory_addr;
+               uae_u32 last_fpiar = opcode_memory_addr;
+
+               for (;;) {
+                       uae_u16 sr_mask = 0;
+
+                       if (extraccr & 1)
+                               sr_mask |= 0x2000; // S
+                       if (extraccr & 2)
+                               sr_mask |= 0x4000; // T0
+                       if (extraccr & 4)
+                               sr_mask |= 0x8000; // T1
+                       if (extraccr & 8)
+                               sr_mask |= 0x1000; // M
+
+                       int ccrmax = fpumode ? 256 : 32;
+                       for (int ccr = 0; ccr < ccrmax; ccr++) {
+
+                               regs.ssp = test_memory_addr + test_memory_size - 0x80;
+                               regs.msp = test_memory_addr + test_memory_size;
+                               regs.pc = opcode_memory_addr;
+                               regs.fpiar = opcode_memory_addr;
+
+                               xmemcpy(&test_regs, &regs, sizeof(struct registers));
+
+                               test_regs.sr = ccr | sr_mask;
+                               test_sr = test_regs.sr;
+                               if (fpumode) {
+                                       test_regs.fpsr = (ccr & 15) << 24;
+                                       test_regs.fpcr = (ccr >> 4) << 4;
+                                       test_fpsr = test_regs.fpsr;
+                                       test_fpcr = test_regs.fpcr;
+                               }
+
+
+                               if ((*p) == CT_END_SKIP) {
+
+                                       p++;
+
+                               } else {
+
+                                       int ignore_errors = 0;
+                                       int ignore_sr = 0;
+
+                                       if ((ccr_mask & ccr) || (ccr == 0)) {
+
+                                               if (cpu_lvl == 1) {
+                                                       execute_test010(&test_regs);
+                                               } else if (cpu_lvl == 2) {
+                                                       if (fpu_model)
+                                                               execute_testfpu(&test_regs);
+                                                       else
+                                                               execute_test020(&test_regs);
+                                               } else {
+                                                       execute_test000(&test_regs);
+                                               }
+
+                                               if (ccr_mask == 0 && ccr == 0)
+                                                       ignore_sr = 1;
+
+                                       } else {
+
+                                               test_regs.sr = test_sr;
+                                               ignore_errors = 1;
+                                               ignore_sr = 1;
+
+                                       }
+
+                                       last_registers.pc = last_pc;
+                                       last_registers.fpiar = last_fpiar;
+
+                                       p = validate_test(p, ignore_errors, ignore_sr);
+
+                                       last_pc = last_registers.pc;
+                                       last_fpiar = last_registers.fpiar;
+
+                               }
+
+                               testcnt++;
+
+                               if (testexit()) {
+                                       end_test();
+                                       printf("\nAborted\n");
+                                       exit(0);
+                               }
+
+#if DONTSTOPONERROR == 0
+                               if (quit || errors)
+                                       goto end;
+#endif
+                       }
+
+                       if (*p == CT_END) {
+                               p++;
+                               break;
+                       }
+
+                       extraccr = *p++;
+
+               }
+
+               restoreahist();
+
+       }
+
+end:
+       end_test();
+
+       if (infoadded) {
+               printf("\n");
+               printf(outbuffer);
+       }
+
+}
+
+static void freestuff(void)
+{
+       if (test_memory && test_memory_addr)
+               free_absolute(test_memory_addr, test_memory_size);
+}
+
+
+static int test_mnemo(const char *path, const char *opcode)
+{
+       int size;
+       uae_u8 data[4] = { 0 };
+       uae_u32 v;
+       char fname[256], tfname[256];
+       int filecnt = 1;
+       uae_u32 starttimeid;
+
+       errors = 0;
+       quit = 0;
+
+       sprintf(tfname, "%s%s/0000.dat", path, opcode);
+       FILE *f = fopen(tfname, "rb");
+       if (!f) {
+               printf("Couldn't open '%s'\n", tfname);
+               exit(0);
+       }
+       int header_size = 32;
+       fread(data, 1, 4, f);
+       v = gl(data);
+       if (v != 0x00000001) {
+               printf("Invalid test data file (header)\n");
+               exit(0);
+       }
+       fread(data, 1, 4, f);
+       starttimeid = gl(data);
+       fread(data, 1, 4, f);
+       hmem_rom = gl(data) >> 16;
+       lmem_rom = gl(data) & 65535;
+       fread(data, 1, 4, f);
+       test_memory_addr = gl(data);
+       fread(data, 1, 4, f);
+       test_memory_size = gl(data);
+       fread(data, 1, 4, f);
+       opcode_memory_addr = gl(data) + test_memory_addr;
+       fread(data, 1, 4, f);
+       cpu_lvl = gl(data) >> 16;
+       sr_undefined_mask = gl(data);
+       fread(data, 1, 4, f);
+       fpu_model = gl(data);
+       fread(inst_name, 1, sizeof(inst_name) - 1, f);
+       inst_name[sizeof(inst_name) - 1] = 0;
+
+       if (!check_undefined_sr) {
+               sr_undefined_mask = ~sr_undefined_mask;
+       } else {
+               sr_undefined_mask = 0xffff;
+       }
+
+       if (!absallocated) {
+               test_memory = allocate_absolute(test_memory_addr, test_memory_size);
+               if (!test_memory) {
+                       printf("Couldn't allocate tmem area %08lx-%08lx\n", (uae_u32)test_memory_addr, test_memory_size);
+                       exit(0);
+               }
+               absallocated = test_memory;
+       }
+       if (absallocated != test_memory) {
+               printf("tmem area changed!?\n");
+               exit(0);
+       }
+
+       opcode_memory = test_memory + (opcode_memory_addr - test_memory_addr);
+
+       size = test_memory_size;
+       load_file(path, "tmem.dat", test_memory, &size);
+       if (size != test_memory_size) {
+               printf("tmem.dat size mismatch\n");
+               exit(0);
+       }
+
+       printf("%s:\n", inst_name);
+
+       testcnt = 0;
+
+       for (;;) {
+               printf("%s. %lu...\n", tfname, testcnt);
+
+               sprintf(tfname, "%s%s/%04ld.dat", path, opcode, filecnt);
+               FILE *f = fopen(tfname, "rb");
+               if (!f)
+                       break;
+               fread(data, 1, 4, f);
+               if (gl(data) != 0x00000001) {
+                       printf("Invalid test data file (header)\n");
+                       exit(0);
+               }
+               fread(data, 1, 4, f);
+               if (gl(data) != starttimeid) {
+                       printf("Test data file header mismatch\n");
+                       exit(0);
+               }
+               fseek(f, 0, SEEK_END);
+               test_data_size = ftell(f);
+               fseek(f, 16, SEEK_SET);
+               test_data_size -= 16;
+               if (test_data_size <= 0)
+                       break;
+               test_data = calloc(1, test_data_size);
+               if (!test_data) {
+                       printf("Couldn't allocate memory for '%s', %lu bytes\n", tfname, test_memory_size);
+                       exit(0);
+               }
+               if (fread(test_data, 1, test_data_size, f) != test_data_size) {
+                       printf("Couldn't read '%s'\n", fname);
+                       break;
+               }
+               fclose(f);
+               if (test_data[test_data_size - 1] != CT_END_FINISH) {
+                       printf("Invalid test data file (footer)\n");
+                       exit(0);
+               }
+
+               process_test(test_data);
+
+               if (errors || quit)
+                       break;
+
+               free(test_data);
+               filecnt++;
+       }
+
+       if (!errors && !quit) {
+               printf("All tests complete (total %lu).\n", testcnt);
+       }
+
+       return errors || quit;
+}
+
+static int getparamval(const char *p)
+{
+       if (strlen(p) > 2 && p[0] == '0' && toupper(p[1]) == 'X') {
+               char *endptr;
+               return strtol(p + 2, &endptr, 16);
+       } else {
+               return atol(p);
+       }
+}
+
+static char path[256];
+
+int main(int argc, char *argv[])
+{
+       int size;
+       char opcode[16];
+       int stop_on_error = 1;
+
+       atexit(freestuff);
+
+#ifdef _MSC_VER
+
+       char *params[] = { "", "or.w", "", NULL };
+       argv = params;
+       argc = 3;
+
+       strcpy(path, "C:\\projects\\winuae\\src\\cputest\\data\\");
+
+       low_memory = calloc(1, 32768);
+       high_memory = calloc(1, 32768);
+       vbr_zero = calloc(1, 1024);
+
+       cpu_lvl = 0;
+#else
+
+#define _stricmp stricmp
+
+       if (strlen(argv[1]) >= sizeof(opcode) - 1)
+               return 0;
+
+       strcpy(path, "data/");
+
+       low_memory = (uae_u8 *)0;
+       high_memory = (uae_u8 *)0xffff8000;
+
+       cpu_lvl = get_cpu_model();
+#endif
+
+       if (argc < 2) {
+               printf("cputest <all/mnemonic> (<start mnemonic>) (continue)\n");
+               printf("mnemonic = test single mnemonic\n");
+               printf("all = test all\n");
+               printf("all <mnemonic> = test all, starting from <mnemonic>\n");
+               printf("continue = don't stop on error (all mode only)\n");
+               printf("ccrmask = ignore CCR bits that are not set.\n");
+               return 0;
+       }
+
+       sprintf(path + strlen(path), "%lu/", 68000 + cpu_lvl * 10);
+
+       strcpy(opcode, argv[1]);
+
+       check_undefined_sr = 1;
+       ccr_mask = 0xff;
+       for (int i = 1; i < argc; i++) {
+               char *s = argv[i];
+               char *next = i + 1 < argc ? argv[i + 1] : NULL;
+               if (!_stricmp(s, "continue")) {
+                       stop_on_error = 0;
+               } else if (!_stricmp(s, "noundefined")) {
+                       check_undefined_sr = 0;
+               } else if (!_stricmp(s, "ccrmask")) {
+                       ccr_mask = 0;
+                       if (next) {
+                               ccr_mask = getparamval(next);
+                               i++;
+                       }
+               }
+       }
+
+       size = 32768;
+       load_file(path, "lmem.dat", low_memory_temp, &size);
+       size = 32768;
+       load_file(path, "hmem.dat", high_memory_temp, &size);
+
+       if (!_stricmp(opcode, "all")) {
+               DIR *d = opendir(path);
+               if (!d) {
+                       printf("Couldn't list directory '%s'\n", path);
+                       return 0;
+               }
+#define MAX_FILE_LEN 128
+#define MAX_MNEMOS 256
+               char *dirs = calloc(MAX_MNEMOS, MAX_FILE_LEN);
+               int diroff = 0;
+               if (!dirs)
+                       return 0;
+
+               for (;;) {
+                       struct dirent *dr = readdir(d);
+                       if (!dr)
+                               break;
+                       if (dr->d_type == DT_DIR && dr->d_name[0] != '.') {
+                               strcpy(dirs + diroff, dr->d_name);
+                               diroff += MAX_FILE_LEN;
+                               if (diroff >= MAX_FILE_LEN * MAX_MNEMOS) {
+                                       printf("too many directories!?\n");
+                                       return 0;
+                               }
+                       }
+               }
+               closedir(d);
+
+               for (int i = 0; i < diroff; i += MAX_FILE_LEN) {
+                       for (int j = i + MAX_FILE_LEN; j < diroff; j += MAX_FILE_LEN) {
+                               if (_stricmp(dirs + i, dirs + j) > 0) {
+                                       char tmp[MAX_FILE_LEN];
+                                       strcpy(tmp, dirs + j);
+                                       strcpy(dirs + j, dirs + i);
+                                       strcpy(dirs + i, tmp);
+                               }
+                       }
+               }
+
+               int first = 0;
+               if (argc >= 3) {
+                       for (int i = 0; i < diroff; i += MAX_FILE_LEN) {
+                               if (!_stricmp(dirs + i, argv[2])) {
+                                       first = i;
+                                       break;
+                               }
+                       }
+               }
+               for (int i = first; i < diroff; i += MAX_FILE_LEN) {
+                       if (test_mnemo(path, dirs + i)) {
+                               if (stop_on_error)
+                                       break;
+                       }
+               }
+
+               free(dirs);
+
+       } else {
+               test_mnemo(path, opcode);
+       }
+}
diff --git a/cputest/makefile b/cputest/makefile
new file mode 100644 (file)
index 0000000..75cb52a
--- /dev/null
@@ -0,0 +1,26 @@
+
+NOWDATE := "\"$(shell date "+%-d.%-m.%Y")\""
+NOWTIME := "\"$(shell date "+%T")\""
+
+CC=/opt/amiga/bin/m68k-amigaos-gcc
+AS=/opt/amiga/bin/m68k-amigaos-as
+
+CFLAGS = -mcrt=nix13 -O2 -m68000 -fomit-frame-pointer -msmall-code -msoft-float -DREVDATE=$(NOWDATE) -DREVTIME=$(NOWTIME) -DAMIGA
+LINK_CFLAGS = -mcrt=nix13 -lm -s
+
+OBJS = main.o 68kDisass.o asm.o amiga.o
+
+all: $(OBJS)
+       $(CC) $(LINK_CFLAGS) -o cputest $^
+
+main.o: main.c
+       $(CC) $(CFLAGS) -I. -c -o $@ main.c
+
+68kDisass.o: main.c
+       $(CC) $(CFLAGS) -I. -c -o $@ 68kDisass.c
+
+asm.o: asm.S
+       $(AS) -m68020  -o $@ asm.S
+
+amiga.o: amiga.S
+       $(AS) -m68020  -o $@ amiga.S
diff --git a/cputest/msc_dirent.h b/cputest/msc_dirent.h
new file mode 100644 (file)
index 0000000..f7a46da
--- /dev/null
@@ -0,0 +1,1160 @@
+/*
+ * Dirent interface for Microsoft Visual Studio
+ *
+ * Copyright (C) 1998-2019 Toni Ronkko
+ * This file is part of dirent.  Dirent may be freely distributed
+ * under the MIT license.  For all details and documentation, see
+ * https://github.com/tronkko/dirent
+ */
+#ifndef DIRENT_H
+#define DIRENT_H
+
+/* Hide warnings about unreferenced local functions */
+#if defined(__clang__)
+#   pragma clang diagnostic ignored "-Wunused-function"
+#elif defined(_MSC_VER)
+#   pragma warning(disable:4505)
+#elif defined(__GNUC__)
+#   pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+/*
+ * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
+ * Windows Sockets 2.0.
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+#   define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+/* Indicates that d_type field is available in dirent structure */
+#define _DIRENT_HAVE_D_TYPE
+
+/* Indicates that d_namlen field is available in dirent structure */
+#define _DIRENT_HAVE_D_NAMLEN
+
+/* Entries missing from MSVC 6.0 */
+#if !defined(FILE_ATTRIBUTE_DEVICE)
+#   define FILE_ATTRIBUTE_DEVICE 0x40
+#endif
+
+/* File type and permission flags for stat(), general mask */
+#if !defined(S_IFMT)
+#   define S_IFMT _S_IFMT
+#endif
+
+/* Directory bit */
+#if !defined(S_IFDIR)
+#   define S_IFDIR _S_IFDIR
+#endif
+
+/* Character device bit */
+#if !defined(S_IFCHR)
+#   define S_IFCHR _S_IFCHR
+#endif
+
+/* Pipe bit */
+#if !defined(S_IFFIFO)
+#   define S_IFFIFO _S_IFFIFO
+#endif
+
+/* Regular file bit */
+#if !defined(S_IFREG)
+#   define S_IFREG _S_IFREG
+#endif
+
+/* Read permission */
+#if !defined(S_IREAD)
+#   define S_IREAD _S_IREAD
+#endif
+
+/* Write permission */
+#if !defined(S_IWRITE)
+#   define S_IWRITE _S_IWRITE
+#endif
+
+/* Execute permission */
+#if !defined(S_IEXEC)
+#   define S_IEXEC _S_IEXEC
+#endif
+
+/* Pipe */
+#if !defined(S_IFIFO)
+#   define S_IFIFO _S_IFIFO
+#endif
+
+/* Block device */
+#if !defined(S_IFBLK)
+#   define S_IFBLK 0
+#endif
+
+/* Link */
+#if !defined(S_IFLNK)
+#   define S_IFLNK 0
+#endif
+
+/* Socket */
+#if !defined(S_IFSOCK)
+#   define S_IFSOCK 0
+#endif
+
+/* Read user permission */
+#if !defined(S_IRUSR)
+#   define S_IRUSR S_IREAD
+#endif
+
+/* Write user permission */
+#if !defined(S_IWUSR)
+#   define S_IWUSR S_IWRITE
+#endif
+
+/* Execute user permission */
+#if !defined(S_IXUSR)
+#   define S_IXUSR 0
+#endif
+
+/* Read group permission */
+#if !defined(S_IRGRP)
+#   define S_IRGRP 0
+#endif
+
+/* Write group permission */
+#if !defined(S_IWGRP)
+#   define S_IWGRP 0
+#endif
+
+/* Execute group permission */
+#if !defined(S_IXGRP)
+#   define S_IXGRP 0
+#endif
+
+/* Read others permission */
+#if !defined(S_IROTH)
+#   define S_IROTH 0
+#endif
+
+/* Write others permission */
+#if !defined(S_IWOTH)
+#   define S_IWOTH 0
+#endif
+
+/* Execute others permission */
+#if !defined(S_IXOTH)
+#   define S_IXOTH 0
+#endif
+
+/* Maximum length of file name */
+#if !defined(PATH_MAX)
+#   define PATH_MAX MAX_PATH
+#endif
+#if !defined(FILENAME_MAX)
+#   define FILENAME_MAX MAX_PATH
+#endif
+#if !defined(NAME_MAX)
+#   define NAME_MAX FILENAME_MAX
+#endif
+
+/* File type flags for d_type */
+#define DT_UNKNOWN 0
+#define DT_REG S_IFREG
+#define DT_DIR S_IFDIR
+#define DT_FIFO S_IFIFO
+#define DT_SOCK S_IFSOCK
+#define DT_CHR S_IFCHR
+#define DT_BLK S_IFBLK
+#define DT_LNK S_IFLNK
+
+/* Macros for converting between st_mode and d_type */
+#define IFTODT(mode) ((mode) & S_IFMT)
+#define DTTOIF(type) (type)
+
+/*
+ * File type macros.  Note that block devices, sockets and links cannot be
+ * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
+ * only defined for compatibility.  These macros should always return false
+ * on Windows.
+ */
+#if !defined(S_ISFIFO)
+#   define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISDIR)
+#   define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG)
+#   define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISLNK)
+#   define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK)
+#   define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISCHR)
+#   define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISBLK)
+#   define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
+#endif
+
+/* Return the exact length of the file name without zero terminator */
+#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
+
+/* Return the maximum size of a file name */
+#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Wide-character version */
+struct _wdirent {
+    /* Always zero */
+    long d_ino;
+
+    /* File position within stream */
+    long d_off;
+
+    /* Structure size */
+    unsigned short d_reclen;
+
+    /* Length of name without \0 */
+    size_t d_namlen;
+
+    /* File type */
+    int d_type;
+
+    /* File name */
+    wchar_t d_name[PATH_MAX+1];
+};
+typedef struct _wdirent _wdirent;
+
+struct _WDIR {
+    /* Current directory entry */
+    struct _wdirent ent;
+
+    /* Private file data */
+    WIN32_FIND_DATAW data;
+
+    /* True if data is valid */
+    int cached;
+
+    /* Win32 search handle */
+    HANDLE handle;
+
+    /* Initial directory name */
+    wchar_t *patt;
+};
+typedef struct _WDIR _WDIR;
+
+/* Multi-byte character version */
+struct dirent {
+    /* Always zero */
+    long d_ino;
+
+    /* File position within stream */
+    long d_off;
+
+    /* Structure size */
+    unsigned short d_reclen;
+
+    /* Length of name without \0 */
+    size_t d_namlen;
+
+    /* File type */
+    int d_type;
+
+    /* File name */
+    char d_name[PATH_MAX+1];
+};
+typedef struct dirent dirent;
+
+struct DIR {
+    struct dirent ent;
+    struct _WDIR *wdirp;
+};
+typedef struct DIR DIR;
+
+
+/* Dirent functions */
+static DIR *opendir (const char *dirname);
+static _WDIR *_wopendir (const wchar_t *dirname);
+
+static struct dirent *readdir (DIR *dirp);
+static struct _wdirent *_wreaddir (_WDIR *dirp);
+
+static int readdir_r(
+    DIR *dirp, struct dirent *entry, struct dirent **result);
+static int _wreaddir_r(
+    _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
+
+static int closedir (DIR *dirp);
+static int _wclosedir (_WDIR *dirp);
+
+static void rewinddir (DIR* dirp);
+static void _wrewinddir (_WDIR* dirp);
+
+static int scandir (const char *dirname, struct dirent ***namelist,
+    int (*filter)(const struct dirent*),
+    int (*compare)(const struct dirent**, const struct dirent**));
+
+static int alphasort (const struct dirent **a, const struct dirent **b);
+
+static int versionsort (const struct dirent **a, const struct dirent **b);
+
+
+/* For compatibility with Symbian */
+#define wdirent _wdirent
+#define WDIR _WDIR
+#define wopendir _wopendir
+#define wreaddir _wreaddir
+#define wclosedir _wclosedir
+#define wrewinddir _wrewinddir
+
+
+/* Internal utility functions */
+static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
+static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
+
+static int dirent_mbstowcs_s(
+    size_t *pReturnValue,
+    wchar_t *wcstr,
+    size_t sizeInWords,
+    const char *mbstr,
+    size_t count);
+
+static int dirent_wcstombs_s(
+    size_t *pReturnValue,
+    char *mbstr,
+    size_t sizeInBytes,
+    const wchar_t *wcstr,
+    size_t count);
+
+static void dirent_set_errno (int error);
+
+
+/*
+ * Open directory stream DIRNAME for read and return a pointer to the
+ * internal working area that is used to retrieve individual directory
+ * entries.
+ */
+static _WDIR*
+_wopendir(
+    const wchar_t *dirname)
+{
+    _WDIR *dirp;
+    DWORD n;
+    wchar_t *p;
+
+    /* Must have directory name */
+    if (dirname == NULL  ||  dirname[0] == '\0') {
+        dirent_set_errno (ENOENT);
+        return NULL;
+    }
+
+    /* Allocate new _WDIR structure */
+    dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
+    if (!dirp) {
+        return NULL;
+    }
+
+    /* Reset _WDIR structure */
+    dirp->handle = INVALID_HANDLE_VALUE;
+    dirp->patt = NULL;
+    dirp->cached = 0;
+
+    /*
+     * Compute the length of full path plus zero terminator
+     *
+     * Note that on WinRT there's no way to convert relative paths
+     * into absolute paths, so just assume it is an absolute path.
+     */
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+    /* Desktop */
+    n = GetFullPathNameW (dirname, 0, NULL, NULL);
+#else
+    /* WinRT */
+    n = wcslen (dirname);
+#endif
+
+    /* Allocate room for absolute directory name and search pattern */
+    dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
+    if (dirp->patt == NULL) {
+        goto exit_closedir;
+    }
+
+    /*
+     * Convert relative directory name to an absolute one.  This
+     * allows rewinddir() to function correctly even when current
+     * working directory is changed between opendir() and rewinddir().
+     *
+     * Note that on WinRT there's no way to convert relative paths
+     * into absolute paths, so just assume it is an absolute path.
+     */
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+    /* Desktop */
+    n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
+    if (n <= 0) {
+        goto exit_closedir;
+    }
+#else
+    /* WinRT */
+    wcsncpy_s (dirp->patt, n+1, dirname, n);
+#endif
+
+    /* Append search pattern \* to the directory name */
+    p = dirp->patt + n;
+    switch (p[-1]) {
+    case '\\':
+    case '/':
+    case ':':
+        /* Directory ends in path separator, e.g. c:\temp\ */
+        /*NOP*/;
+        break;
+
+    default:
+        /* Directory name doesn't end in path separator */
+        *p++ = '\\';
+    }
+    *p++ = '*';
+    *p = '\0';
+
+    /* Open directory stream and retrieve the first entry */
+    if (!dirent_first (dirp)) {
+        goto exit_closedir;
+    }
+
+    /* Success */
+    return dirp;
+
+    /* Failure */
+exit_closedir:
+    _wclosedir (dirp);
+    return NULL;
+}
+
+/*
+ * Read next directory entry.
+ *
+ * Returns pointer to static directory entry which may be overwritten by
+ * subsequent calls to _wreaddir().
+ */
+static struct _wdirent*
+_wreaddir(
+    _WDIR *dirp)
+{
+    struct _wdirent *entry;
+
+    /*
+     * Read directory entry to buffer.  We can safely ignore the return value
+     * as entry will be set to NULL in case of error.
+     */
+    (void) _wreaddir_r (dirp, &dirp->ent, &entry);
+
+    /* Return pointer to statically allocated directory entry */
+    return entry;
+}
+
+/*
+ * Read next directory entry.
+ *
+ * Returns zero on success.  If end of directory stream is reached, then sets
+ * result to NULL and returns zero.
+ */
+static int
+_wreaddir_r(
+    _WDIR *dirp,
+    struct _wdirent *entry,
+    struct _wdirent **result)
+{
+    WIN32_FIND_DATAW *datap;
+
+    /* Read next directory entry */
+    datap = dirent_next (dirp);
+    if (datap) {
+        size_t n;
+        DWORD attr;
+
+        /*
+         * Copy file name as wide-character string.  If the file name is too
+         * long to fit in to the destination buffer, then truncate file name
+         * to PATH_MAX characters and zero-terminate the buffer.
+         */
+        n = 0;
+        while (n < PATH_MAX  &&  datap->cFileName[n] != 0) {
+            entry->d_name[n] = datap->cFileName[n];
+            n++;
+        }
+        entry->d_name[n] = 0;
+
+        /* Length of file name excluding zero terminator */
+        entry->d_namlen = n;
+
+        /* File type */
+        attr = datap->dwFileAttributes;
+        if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+            entry->d_type = DT_CHR;
+        } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+            entry->d_type = DT_DIR;
+        } else {
+            entry->d_type = DT_REG;
+        }
+
+        /* Reset dummy fields */
+        entry->d_ino = 0;
+        entry->d_off = 0;
+        entry->d_reclen = sizeof (struct _wdirent);
+
+        /* Set result address */
+        *result = entry;
+
+    } else {
+
+        /* Return NULL to indicate end of directory */
+        *result = NULL;
+
+    }
+
+    return /*OK*/0;
+}
+
+/*
+ * Close directory stream opened by opendir() function.  This invalidates the
+ * DIR structure as well as any directory entry read previously by
+ * _wreaddir().
+ */
+static int
+_wclosedir(
+    _WDIR *dirp)
+{
+    int ok;
+    if (dirp) {
+
+        /* Release search handle */
+        if (dirp->handle != INVALID_HANDLE_VALUE) {
+            FindClose (dirp->handle);
+        }
+
+        /* Release search pattern */
+        free (dirp->patt);
+
+        /* Release directory structure */
+        free (dirp);
+        ok = /*success*/0;
+
+    } else {
+
+        /* Invalid directory stream */
+        dirent_set_errno (EBADF);
+        ok = /*failure*/-1;
+
+    }
+    return ok;
+}
+
+/*
+ * Rewind directory stream such that _wreaddir() returns the very first
+ * file name again.
+ */
+static void
+_wrewinddir(
+    _WDIR* dirp)
+{
+    if (dirp) {
+        /* Release existing search handle */
+        if (dirp->handle != INVALID_HANDLE_VALUE) {
+            FindClose (dirp->handle);
+        }
+
+        /* Open new search handle */
+        dirent_first (dirp);
+    }
+}
+
+/* Get first directory entry (internal) */
+static WIN32_FIND_DATAW*
+dirent_first(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *datap;
+    DWORD error;
+
+    /* Open directory and retrieve the first entry */
+    dirp->handle = FindFirstFileExW(
+        dirp->patt, FindExInfoStandard, &dirp->data,
+        FindExSearchNameMatch, NULL, 0);
+    if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+        /* a directory entry is now waiting in memory */
+        datap = &dirp->data;
+        dirp->cached = 1;
+
+    } else {
+
+        /* Failed to open directory: no directory entry in memory */
+        dirp->cached = 0;
+        datap = NULL;
+
+        /* Set error code */
+        error = GetLastError ();
+        switch (error) {
+        case ERROR_ACCESS_DENIED:
+            /* No read access to directory */
+            dirent_set_errno (EACCES);
+            break;
+
+        case ERROR_DIRECTORY:
+            /* Directory name is invalid */
+            dirent_set_errno (ENOTDIR);
+            break;
+
+        case ERROR_PATH_NOT_FOUND:
+        default:
+            /* Cannot find the file */
+            dirent_set_errno (ENOENT);
+        }
+
+    }
+    return datap;
+}
+
+/*
+ * Get next directory entry (internal).
+ *
+ * Returns
+ */
+static WIN32_FIND_DATAW*
+dirent_next(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *p;
+
+    /* Get next directory entry */
+    if (dirp->cached != 0) {
+
+        /* A valid directory entry already in memory */
+        p = &dirp->data;
+        dirp->cached = 0;
+
+    } else if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+        /* Get the next directory entry from stream */
+        if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
+            /* Got a file */
+            p = &dirp->data;
+        } else {
+            /* The very last entry has been processed or an error occurred */
+            FindClose (dirp->handle);
+            dirp->handle = INVALID_HANDLE_VALUE;
+            p = NULL;
+        }
+
+    } else {
+
+        /* End of directory stream reached */
+        p = NULL;
+
+    }
+
+    return p;
+}
+
+/*
+ * Open directory stream using plain old C-string.
+ */
+static DIR*
+opendir(
+    const char *dirname)
+{
+    struct DIR *dirp;
+
+    /* Must have directory name */
+    if (dirname == NULL  ||  dirname[0] == '\0') {
+        dirent_set_errno (ENOENT);
+        return NULL;
+    }
+
+    /* Allocate memory for DIR structure */
+    dirp = (DIR*) malloc (sizeof (struct DIR));
+    if (!dirp) {
+        return NULL;
+    }
+    {
+        int error;
+        wchar_t wname[PATH_MAX + 1];
+        size_t n;
+
+        /* Convert directory name to wide-character string */
+        error = dirent_mbstowcs_s(
+            &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
+        if (error) {
+            /*
+             * Cannot convert file name to wide-character string.  This
+             * occurs if the string contains invalid multi-byte sequences or
+             * the output buffer is too small to contain the resulting
+             * string.
+             */
+            goto exit_free;
+        }
+
+
+        /* Open directory stream using wide-character name */
+        dirp->wdirp = _wopendir (wname);
+        if (!dirp->wdirp) {
+            goto exit_free;
+        }
+
+    }
+
+    /* Success */
+    return dirp;
+
+    /* Failure */
+exit_free:
+    free (dirp);
+    return NULL;
+}
+
+/*
+ * Read next directory entry.
+ */
+static struct dirent*
+readdir(
+    DIR *dirp)
+{
+    struct dirent *entry;
+
+    /*
+     * Read directory entry to buffer.  We can safely ignore the return value
+     * as entry will be set to NULL in case of error.
+     */
+    (void) readdir_r (dirp, &dirp->ent, &entry);
+
+    /* Return pointer to statically allocated directory entry */
+    return entry;
+}
+
+/*
+ * Read next directory entry into called-allocated buffer.
+ *
+ * Returns zero on success.  If the end of directory stream is reached, then
+ * sets result to NULL and returns zero.
+ */
+static int
+readdir_r(
+    DIR *dirp,
+    struct dirent *entry,
+    struct dirent **result)
+{
+    WIN32_FIND_DATAW *datap;
+
+    /* Read next directory entry */
+    datap = dirent_next (dirp->wdirp);
+    if (datap) {
+        size_t n;
+        int error;
+
+        /* Attempt to convert file name to multi-byte string */
+        error = dirent_wcstombs_s(
+            &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
+
+        /*
+         * If the file name cannot be represented by a multi-byte string,
+         * then attempt to use old 8+3 file name.  This allows traditional
+         * Unix-code to access some file names despite of unicode
+         * characters, although file names may seem unfamiliar to the user.
+         *
+         * Be ware that the code below cannot come up with a short file
+         * name unless the file system provides one.  At least
+         * VirtualBox shared folders fail to do this.
+         */
+        if (error  &&  datap->cAlternateFileName[0] != '\0') {
+            error = dirent_wcstombs_s(
+                &n, entry->d_name, PATH_MAX + 1,
+                datap->cAlternateFileName, PATH_MAX + 1);
+        }
+
+        if (!error) {
+            DWORD attr;
+
+            /* Length of file name excluding zero terminator */
+            entry->d_namlen = n - 1;
+
+            /* File attributes */
+            attr = datap->dwFileAttributes;
+            if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+                entry->d_type = DT_CHR;
+            } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+                entry->d_type = DT_DIR;
+            } else {
+                entry->d_type = DT_REG;
+            }
+
+            /* Reset dummy fields */
+            entry->d_ino = 0;
+            entry->d_off = 0;
+            entry->d_reclen = sizeof (struct dirent);
+
+        } else {
+
+            /*
+             * Cannot convert file name to multi-byte string so construct
+             * an erroneous directory entry and return that.  Note that
+             * we cannot return NULL as that would stop the processing
+             * of directory entries completely.
+             */
+            entry->d_name[0] = '?';
+            entry->d_name[1] = '\0';
+            entry->d_namlen = 1;
+            entry->d_type = DT_UNKNOWN;
+            entry->d_ino = 0;
+            entry->d_off = -1;
+            entry->d_reclen = 0;
+
+        }
+
+        /* Return pointer to directory entry */
+        *result = entry;
+
+    } else {
+
+        /* No more directory entries */
+        *result = NULL;
+
+    }
+
+    return /*OK*/0;
+}
+
+/*
+ * Close directory stream.
+ */
+static int
+closedir(
+    DIR *dirp)
+{
+    int ok;
+    if (dirp) {
+
+        /* Close wide-character directory stream */
+        ok = _wclosedir (dirp->wdirp);
+        dirp->wdirp = NULL;
+
+        /* Release multi-byte character version */
+        free (dirp);
+
+    } else {
+
+        /* Invalid directory stream */
+        dirent_set_errno (EBADF);
+        ok = /*failure*/-1;
+
+    }
+    return ok;
+}
+
+/*
+ * Rewind directory stream to beginning.
+ */
+static void
+rewinddir(
+    DIR* dirp)
+{
+    /* Rewind wide-character string directory stream */
+    _wrewinddir (dirp->wdirp);
+}
+
+/*
+ * Scan directory for entries.
+ */
+static int
+scandir(
+    const char *dirname,
+    struct dirent ***namelist,
+    int (*filter)(const struct dirent*),
+    int (*compare)(const struct dirent**, const struct dirent**))
+{
+    struct dirent **files = NULL;
+    size_t size = 0;
+    size_t allocated = 0;
+    const size_t init_size = 1;
+    DIR *dir = NULL;
+    struct dirent *entry;
+    struct dirent *tmp = NULL;
+    size_t i;
+    int result = 0;
+
+    /* Open directory stream */
+    dir = opendir (dirname);
+    if (dir) {
+
+        /* Read directory entries to memory */
+        while (1) {
+
+            /* Enlarge pointer table to make room for another pointer */
+            if (size >= allocated) {
+                void *p;
+                size_t num_entries;
+
+                /* Compute number of entries in the enlarged pointer table */
+                if (size < init_size) {
+                    /* Allocate initial pointer table */
+                    num_entries = init_size;
+                } else {
+                    /* Double the size */
+                    num_entries = size * 2;
+                }
+
+                /* Allocate first pointer table or enlarge existing table */
+                p = realloc (files, sizeof (void*) * num_entries);
+                if (p != NULL) {
+                    /* Got the memory */
+                    files = (dirent**) p;
+                    allocated = num_entries;
+                } else {
+                    /* Out of memory */
+                    result = -1;
+                    break;
+                }
+
+            }
+
+            /* Allocate room for temporary directory entry */
+            if (tmp == NULL) {
+                tmp = (struct dirent*) malloc (sizeof (struct dirent));
+                if (tmp == NULL) {
+                    /* Cannot allocate temporary directory entry */
+                    result = -1;
+                    break;
+                }
+            }
+
+            /* Read directory entry to temporary area */
+            if (readdir_r (dir, tmp, &entry) == /*OK*/0) {
+
+                /* Did we get an entry? */
+                if (entry != NULL) {
+                    int pass;
+
+                    /* Determine whether to include the entry in result */
+                    if (filter) {
+                        /* Let the filter function decide */
+                        pass = filter (tmp);
+                    } else {
+                        /* No filter function, include everything */
+                        pass = 1;
+                    }
+
+                    if (pass) {
+                        /* Store the temporary entry to pointer table */
+                        files[size++] = tmp;
+                        tmp = NULL;
+
+                        /* Keep up with the number of files */
+                        result++;
+                    }
+
+                } else {
+
+                    /*
+                     * End of directory stream reached => sort entries and
+                     * exit.
+                     */
+                    qsort (files, size, sizeof (void*),
+                        (int (*) (const void*, const void*)) compare);
+                    break;
+
+                }
+
+            } else {
+                /* Error reading directory entry */
+                result = /*Error*/ -1;
+                break;
+            }
+
+        }
+
+    } else {
+        /* Cannot open directory */
+        result = /*Error*/ -1;
+    }
+
+    /* Release temporary directory entry */
+    free (tmp);
+
+    /* Release allocated memory on error */
+    if (result < 0) {
+        for (i = 0; i < size; i++) {
+            free (files[i]);
+        }
+        free (files);
+        files = NULL;
+    }
+
+    /* Close directory stream */
+    if (dir) {
+        closedir (dir);
+    }
+
+    /* Pass pointer table to caller */
+    if (namelist) {
+        *namelist = files;
+    }
+    return result;
+}
+
+/* Alphabetical sorting */
+static int
+alphasort(
+    const struct dirent **a, const struct dirent **b)
+{
+    return strcoll ((*a)->d_name, (*b)->d_name);
+}
+
+/* Sort versions */
+static int
+versionsort(
+    const struct dirent **a, const struct dirent **b)
+{
+    /* FIXME: implement strverscmp and use that */
+    return alphasort (a, b);
+}
+
+/* Convert multi-byte string to wide character string */
+static int
+dirent_mbstowcs_s(
+    size_t *pReturnValue,
+    wchar_t *wcstr,
+    size_t sizeInWords,
+    const char *mbstr,
+    size_t count)
+{
+    int error;
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 or later */
+    error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
+
+#else
+
+    /* Older Visual Studio or non-Microsoft compiler */
+    size_t n;
+
+    /* Convert to wide-character string (or count characters) */
+    n = mbstowcs (wcstr, mbstr, sizeInWords);
+    if (!wcstr  ||  n < count) {
+
+        /* Zero-terminate output buffer */
+        if (wcstr  &&  sizeInWords) {
+            if (n >= sizeInWords) {
+                n = sizeInWords - 1;
+            }
+            wcstr[n] = 0;
+        }
+
+        /* Length of resulting multi-byte string WITH zero terminator */
+        if (pReturnValue) {
+            *pReturnValue = n + 1;
+        }
+
+        /* Success */
+        error = 0;
+
+    } else {
+
+        /* Could not convert string */
+        error = 1;
+
+    }
+
+#endif
+    return error;
+}
+
+/* Convert wide-character string to multi-byte string */
+static int
+dirent_wcstombs_s(
+    size_t *pReturnValue,
+    char *mbstr,
+    size_t sizeInBytes, /* max size of mbstr */
+    const wchar_t *wcstr,
+    size_t count)
+{
+    int error;
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 or later */
+    error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
+
+#else
+
+    /* Older Visual Studio or non-Microsoft compiler */
+    size_t n;
+
+    /* Convert to multi-byte string (or count the number of bytes needed) */
+    n = wcstombs (mbstr, wcstr, sizeInBytes);
+    if (!mbstr  ||  n < count) {
+
+        /* Zero-terminate output buffer */
+        if (mbstr  &&  sizeInBytes) {
+            if (n >= sizeInBytes) {
+                n = sizeInBytes - 1;
+            }
+            mbstr[n] = '\0';
+        }
+
+        /* Length of resulting multi-bytes string WITH zero-terminator */
+        if (pReturnValue) {
+            *pReturnValue = n + 1;
+        }
+
+        /* Success */
+        error = 0;
+
+    } else {
+
+        /* Cannot convert string */
+        error = 1;
+
+    }
+
+#endif
+    return error;
+}
+
+/* Set errno variable */
+static void
+dirent_set_errno(
+    int error)
+{
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 and later */
+    _set_errno (error);
+
+#else
+
+    /* Non-Microsoft compiler or older Microsoft compiler */
+    errno = error;
+
+#endif
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*DIRENT_H*/
diff --git a/cputest_support.cpp b/cputest_support.cpp
new file mode 100644 (file)
index 0000000..1ef0dd6
--- /dev/null
@@ -0,0 +1,100 @@
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "options.h"
+#include "memory.h"
+#include "newcpu.h"
+#include "fpp.h"
+
+void my_trim(TCHAR *s)
+{
+       int len;
+       while (_tcslen(s) > 0 && _tcscspn(s, _T("\t \r\n")) == 0)
+               memmove(s, s + 1, (_tcslen(s + 1) + 1) * sizeof(TCHAR));
+       len = _tcslen(s);
+       while (len > 0 && _tcscspn(s + len - 1, _T("\t \r\n")) == 0)
+               s[--len] = '\0';
+}
+
+void write_log(const TCHAR *format, ...)
+{
+
+}
+void f_out(void *f, const TCHAR *format, ...)
+{
+
+}
+
+TCHAR *buf_out(TCHAR *buffer, int *bufsize, const TCHAR *format, ...)
+{
+       int count;
+       va_list parms;
+       va_start(parms, format);
+
+       if (buffer == NULL)
+               return 0;
+       count = _vsntprintf(buffer, (*bufsize) - 1, format, parms);
+       va_end(parms);
+       *bufsize -= _tcslen(buffer);
+       return buffer + _tcslen(buffer);
+}
+
+void fpux_restore(int *v)
+{
+}
+void fp_init_native(void)
+{
+       wprintf(_T("fp_init_native called!"));
+       exit(0);
+}
+void fp_init_native_80(void)
+{
+       wprintf(_T("fp_init_native_80 called!"));
+       exit(0);
+}
+void init_fpucw_x87(void)
+{
+}
+void init_fpucw_x87_80(void)
+{
+}
+
+int debugmem_get_segment(uaecptr addr, bool *exact, bool *ext, TCHAR *out, TCHAR *name)
+{
+       return 0;
+}
+int debugmem_get_symbol(uaecptr addr, TCHAR *out, int maxsize)
+{
+       return 0;
+}
+int debugmem_get_sourceline(uaecptr addr, TCHAR *out, int maxsize)
+{
+       return -1;
+}
+bool debugger_get_library_symbol(uaecptr base, uaecptr addr, TCHAR *out)
+{
+       return false;
+}
+
+int debug_safe_addr(uaecptr addr, int size)
+{
+       return 1;
+}
+
+void set_cpu_caches(bool flush)
+{
+}
+
+void flush_icache(int v)
+{
+}
+
+void mmu_tt_modified(void)
+{
+}
+
+uae_u16 REGPARAM2 mmu_set_tc(uae_u16 tc)
+{
+       return 0;
+}
\ No newline at end of file
diff --git a/disasm.cpp b/disasm.cpp
new file mode 100644 (file)
index 0000000..cf2849b
--- /dev/null
@@ -0,0 +1,2067 @@
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "options.h"
+#include "debug.h"
+#include "memory.h"
+#include "newcpu.h"
+#include "fpp.h"
+#include "debugmem.h"
+#include "disasm.h"
+
+
+struct cpum2c m2cregs[] = {
+       { 0, _T("SFC") },
+       { 1, _T("DFC") },
+       { 2, _T("CACR") },
+       { 3, _T("TC") },
+       { 4, _T("ITT0") },
+       { 5, _T("ITT1") },
+       { 6, _T("DTT0") },
+       { 7, _T("DTT1") },
+       { 8, _T("BUSC") },
+       { 0x800, _T("USP") },
+       { 0x801, _T("VBR") },
+       { 0x802, _T("CAAR") },
+       { 0x803, _T("MSP") },
+       { 0x804, _T("ISP") },
+       { 0x805, _T("MMUS") },
+       { 0x806, _T("URP") },
+       { 0x807, _T("SRP") },
+       { 0x808, _T("PCR") },
+    { -1, NULL }
+};
+
+const TCHAR *fpsizes[] = {
+       _T("L"),
+       _T("S"),
+       _T("X"),
+       _T("P"),
+       _T("W"),
+       _T("D"),
+       _T("B"),
+       _T("P")
+};
+static const int fpsizeconv[] = {
+       sz_long,
+       sz_single,
+       sz_extended,
+       sz_packed,
+       sz_word,
+       sz_double,
+       sz_byte,
+       sz_packed
+};
+static const int datasizes[] = {
+       1,
+       2,
+       4,
+       4,
+       8,
+       12,
+       12
+};
+
+static void showea_val(TCHAR *buffer, uae_u16 opcode, uaecptr addr, int size)
+{
+       struct mnemolookup *lookup;
+       instr *table = &table68k[opcode];
+
+       if (addr >= 0xe90000 && addr < 0xf00000)
+               goto skip;
+       if (addr >= 0xdff000 && addr < 0xe00000)
+               goto skip;
+
+       for (lookup = lookuptab; lookup->mnemo != table->mnemo; lookup++)
+               ;
+       if (!(lookup->flags & 1))
+               goto skip;
+       buffer += _tcslen(buffer);
+       if (debug_safe_addr(addr, datasizes[size])) {
+               bool cached = false;
+               switch (size)
+               {
+                       case sz_byte:
+                       {
+                               uae_u8 v = get_byte_cache_debug(addr, &cached);
+                               uae_u8 v2 = v;
+                               if (cached)
+                                       v2 = get_byte_debug(addr);
+                               if (v != v2) {
+                                       _stprintf(buffer, _T(" [%02x:%02x]"), v, v2);
+                               } else {
+                                       _stprintf(buffer, _T(" [%s%02x]"), cached ? _T("*") : _T(""), v);
+                               }
+                       }
+                       break;
+                       case sz_word:
+                       {
+                               uae_u16 v = get_word_cache_debug(addr, &cached);
+                               uae_u16 v2 = v;
+                               if (cached)
+                                       v2 = get_word_debug(addr);
+                               if (v != v2) {
+                                       _stprintf(buffer, _T(" [%04x:%04x]"), v, v2);
+                               } else {
+                                       _stprintf(buffer, _T(" [%s%04x]"), cached ? _T("*") : _T(""), v);
+                               }
+                       }
+                       break;
+                       case sz_long:
+                       {
+                               uae_u32 v = get_long_cache_debug(addr, &cached);
+                               uae_u32 v2 = v;
+                               if (cached)
+                                       v2 = get_long_debug(addr);
+                               if (v != v2) {
+                                       _stprintf(buffer, _T(" [%08x:%08x]"), v, v2);
+                               } else {
+                                       _stprintf(buffer, _T(" [%s%08x]"), cached ? _T("*") : _T(""), v);
+                               }
+                       }
+                       break;
+                       case sz_single:
+                       {
+                               fpdata fp;
+                               fpp_to_single(&fp, get_long_debug(addr));
+                               _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
+                       }
+                       break;
+                       case sz_double:
+                       {
+                               fpdata fp;
+                               fpp_to_double(&fp, get_long_debug(addr), get_long_debug(addr + 4));
+                               _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
+                       }
+                       break;
+                       case sz_extended:
+                       {
+                               fpdata fp;
+                               fpp_to_exten(&fp, get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8));
+                               _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
+                               break;
+                       }
+                       case sz_packed:
+                               _stprintf(buffer, _T("[%08x%08x%08x]"), get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8));
+                               break;
+               }
+       }
+skip:
+       for (int i = 0; i < size; i++) {
+               TCHAR name[256];
+               if (debugmem_get_symbol(addr + i, name, sizeof(name) / sizeof(TCHAR))) {
+                       _stprintf(buffer + _tcslen(buffer), _T(" %s"), name);
+               }
+       }
+}
+
+uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name)
+{
+       uaecptr addr;
+       uae_u16 dp;
+       int r;
+       uae_u32 dispreg;
+       uaecptr pc = *pcp;
+       TCHAR mult[20];
+       TCHAR *p = NULL;
+
+       dp = get_iword_debug(pc);
+       pc += 2;
+
+       r = (dp & 0x7000) >> 12; // REGISTER
+
+       dispreg = dp & 0x8000 ? m68k_areg(regs, r) : m68k_dreg(regs, r);
+       if (!(dp & 0x800)) { // W/L
+               dispreg = (uae_s32)(uae_s16)(dispreg);
+       }
+
+       if (currprefs.cpu_model >= 68020) {
+               dispreg <<= (dp >> 9) & 3; // SCALE
+       }
+
+       int m = 1 << ((dp >> 9) & 3);
+       mult[0] = 0;
+       if (m > 1 && buffer) {
+               _stprintf(mult, _T("*%d"), m);
+       }
+
+       if (buffer)
+               buffer[0] = 0;
+       if ((dp & 0x100) && currprefs.cpu_model >= 68020) {
+               TCHAR dr[20];
+               // Full format extension (68020+)
+               uae_s32 outer = 0, disp = 0;
+               if (dp & 0x80) { // BS (base register suppress)
+                       base = 0;
+                       if (buffer)
+                               name = NULL;
+               }
+               if (buffer)
+                       _stprintf(dr, _T("%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W');
+               if (dp & 0x40) { // IS (index suppress)
+                       dispreg = 0;
+                       dr[0] = 0;
+               }
+
+               if (buffer) {
+                       _tcscpy(buffer, _T("("));
+                       p = buffer + _tcslen(buffer);
+
+                       if (dp & 3) {
+                               // indirect
+                               _stprintf(p, _T("["));
+                               p += _tcslen(p);
+                       } else {
+                               // (an,dn,word/long)
+                               if (name) {
+                                       _stprintf(p, _T("%s,"), name);
+                                       p += _tcslen(p);
+                               }
+                               if (dr[0]) {
+                                       _stprintf(p, _T("%s%s,"), dr, mult);
+                                       p += _tcslen(p);
+                               }
+                       }
+               }
+
+               if ((dp & 0x30) == 0x20) { // BD SIZE = 2 (WORD)
+                       disp = (uae_s32)(uae_s16)get_iword_debug(pc);
+                       if (buffer) {
+                               _stprintf(p, _T("$%04x,"), (uae_s16)disp);
+                               p += _tcslen(p);
+                       }
+                       pc += 2;
+                       base += disp;
+               } else if ((dp & 0x30) == 0x30) { // BD SIZE = 3 (LONG)
+                       disp = get_ilong_debug(pc);
+                       if (buffer) {
+                               _stprintf(p, _T("$%08x,"), disp);
+                               p += _tcslen(p);
+                       }
+                       pc += 4;
+                       base += disp;
+               }
+
+               if ((dp & 3) && buffer) {
+                       if (name) {
+                               _stprintf(p, _T("%s,"), name);
+                               p += _tcslen(p);
+                       }
+
+                       if (!(dp & 0x04)) {
+                               if (dr[0]) {
+                                       _stprintf(p, _T("%s%s,"), dr, mult);
+                                       p += _tcslen(p);
+                               }
+                       }
+
+                       if (p[-1] == ',')
+                               p--;
+                       _stprintf(p, _T("],"));
+                       p += _tcslen(p);
+
+                       if ((dp & 0x04)) {
+                               if (dr[0]) {
+                                       _stprintf(p, _T("%s%s,"), dr, mult);
+                                       p += _tcslen(p);
+                               }
+                       }
+
+               }
+
+               if ((dp & 0x03) == 0x02) {
+                       outer = (uae_s32)(uae_s16)get_iword_debug(pc);
+                       if (buffer) {
+                               _stprintf(p, _T("$%04x,"), (uae_s16)outer);
+                               p += _tcslen(p);
+                       }
+                       pc += 2;
+               } else  if ((dp & 0x03) == 0x03) {
+                       outer = get_ilong_debug(pc);
+                       if (buffer) {
+                               _stprintf(p, _T("$%08x,"), outer);
+                               p += _tcslen(p);
+                       }
+                       pc += 4;
+               }
+
+               if (buffer) {
+                       if (p[-1] == ',')
+                               p--;
+                       _stprintf(p, _T(")"));
+                       p += _tcslen(p);
+               }
+
+               if ((dp & 0x4) == 0)
+                       base += dispreg;
+               if (dp & 0x3)
+                       base = get_long_debug(base);
+               if (dp & 0x4)
+                       base += dispreg;
+
+               addr = base + outer;
+
+               if (buffer) {
+                       _stprintf(p, _T(" == $%08x"), addr);
+                       p += _tcslen(p);
+               }
+
+       } else {
+               // Brief format extension
+               TCHAR regstr[20];
+               uae_s8 disp8 = dp & 0xFF;
+
+               regstr[0] = 0;
+               _stprintf(regstr, _T(",%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W');
+               addr = base + (uae_s32)((uae_s8)disp8) + dispreg;
+               if (buffer) {
+                       _stprintf(buffer, _T("(%s%s%s,$%02x) == $%08x"), name, regstr, mult, (uae_u8)disp8, addr);
+                       if (dp & 0x100) {
+                               _tcscat(buffer, _T(" (68020+)"));
+                       }
+               }
+       }
+
+       *pcp = pc;
+       return addr;
+}
+
+uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
+{
+       uaecptr addr = pc;
+       uae_s16 disp16;
+       uae_s32 offset = 0;
+       TCHAR buffer[80];
+
+       if ((opcode & 0xf0ff) == 0x60ff && currprefs.cpu_model < 68020) {
+               // bcc.l is bcc.s if 68000/68010
+               mode = immi;
+       }
+
+       switch (mode){
+       case Dreg:
+               _stprintf (buffer, _T("D%d"), reg);
+               break;
+       case Areg:
+               _stprintf (buffer, _T("A%d"), reg);
+               break;
+       case Aind:
+               _stprintf (buffer, _T("(A%d)"), reg);
+               addr = regs.regs[reg + 8];
+               showea_val(buffer, opcode, addr, size);
+               break;
+       case Aipi:
+               _stprintf (buffer, _T("(A%d)+"), reg);
+               addr = regs.regs[reg + 8];
+               showea_val(buffer, opcode, addr, size);
+               break;
+       case Apdi:
+               _stprintf (buffer, _T("-(A%d)"), reg);
+               addr = regs.regs[reg + 8];
+               showea_val(buffer, opcode, addr - datasizes[size], size);
+               break;
+       case Ad16:
+               {
+                       TCHAR offtxt[8];
+                       disp16 = get_iword_debug (pc); pc += 2;
+                       if (disp16 < 0)
+                               _stprintf (offtxt, _T("-$%04x"), -disp16);
+                       else
+                               _stprintf (offtxt, _T("$%04x"), disp16);
+                       addr = m68k_areg (regs, reg) + disp16;
+                       _stprintf (buffer, _T("(A%d,%s) == $%08x"), reg, offtxt, addr);
+                       showea_val(buffer, opcode, addr, size);
+               }
+               break;
+       case Ad8r:
+               {
+                       TCHAR name[10];
+                       _stprintf(name, _T("A%d"), reg);
+                       addr = ShowEA_disp(&pc, m68k_areg(regs, reg), buffer, name);
+                       showea_val(buffer, opcode, addr, size);
+               }
+               break;
+       case PC16:
+               disp16 = get_iword_debug (pc); pc += 2;
+               addr += (uae_s16)disp16;
+               _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr);
+               showea_val(buffer, opcode, addr, size);
+               break;
+       case PC8r:
+               {
+                       addr = ShowEA_disp(&pc, addr, buffer, _T("PC"));
+                       showea_val(buffer, opcode, addr, size);
+               }
+               break;
+       case absw:
+               addr = (uae_s32)(uae_s16)get_iword_debug (pc);
+               _stprintf (buffer, _T("$%04x"), (uae_u16)addr);
+               pc += 2;
+               showea_val(buffer, opcode, addr, size);
+               break;
+       case absl:
+               addr = get_ilong_debug (pc);
+               _stprintf (buffer, _T("$%08x"), addr);
+               pc += 4;
+               showea_val(buffer, opcode, addr, size);
+               break;
+       case imm:
+               switch (size){
+               case sz_byte:
+                       _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff));
+                       pc += 2;
+                       break;
+               case sz_word:
+                       _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff));
+                       pc += 2;
+                       break;
+               case sz_long:
+                       _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc)));
+                       pc += 4;
+                       break;
+               case sz_single:
+                       {
+                               fpdata fp;
+                               fpp_to_single(&fp, get_ilong_debug(pc));
+                               _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
+                               pc += 4;
+                       }
+                       break;
+               case sz_double:
+                       {
+                               fpdata fp;
+                               fpp_to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
+                               _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
+                               pc += 8;
+                       }
+                       break;
+               case sz_extended:
+               {
+                       fpdata fp;
+                       fpp_to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
+                       _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
+                       pc += 12;
+                       break;
+               }
+               case sz_packed:
+                       _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
+                       pc += 12;
+                       break;
+               default:
+                       break;
+               }
+               break;
+       case imm0:
+               offset = (uae_s32)(uae_s8)get_iword_debug (pc);
+               _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff));
+               addr = pc + 2 + offset;
+               if ((opcode & 0xf000) == 0x6000) {
+                       showea_val(buffer, opcode, addr, 1);
+               }
+               pc += 2;
+               break;
+       case imm1:
+               offset = (uae_s32)(uae_s16)get_iword_debug (pc);
+               buffer[0] = 0;
+               _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff));
+               addr = pc + offset;
+               if ((opcode & 0xf000) == 0x6000) {
+                       showea_val(buffer, opcode, addr, 2);
+               }
+               pc += 2;
+               break;
+       case imm2:
+               offset = (uae_s32)get_ilong_debug (pc);
+               _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
+               addr = pc + offset;
+               if ((opcode & 0xf000) == 0x6000) {
+                       showea_val(buffer, opcode, addr, 4);
+               }
+               pc += 4;
+               break;
+       case immi:
+               offset = (uae_s32)(uae_s8)(reg & 0xff);
+               _stprintf (buffer, _T("#$%02x"), (uae_u8)offset);
+               addr = pc + offset;
+               break;
+       default:
+               break;
+       }
+       if (buf == NULL)
+               f_out (f, _T("%s"), buffer);
+       else
+               _tcscat (buf, buffer);
+       if (eaddr)
+               *eaddr = addr;
+       return pc;
+}
+
+static const TCHAR *ccnames[] =
+{
+       _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
+       _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE")
+};
+static const TCHAR *fpccnames[] =
+{
+       _T("F"),
+       _T("EQ"),
+       _T("OGT"),
+       _T("OGE"),
+       _T("OLT"),
+       _T("OLE"),
+       _T("OGL"),
+       _T("OR"),
+       _T("UN"),
+       _T("UEQ"),
+       _T("UGT"),
+       _T("UGE"),
+       _T("ULT"),
+       _T("ULE"),
+       _T("NE"),
+       _T("T"),
+       _T("SF"),
+       _T("SEQ"),
+       _T("GT"),
+       _T("GE"),
+       _T("LT"),
+       _T("LE"),
+       _T("GL"),
+       _T("GLE"),
+       _T("NGLE"),
+       _T("NGL"),
+       _T("NLE"),
+       _T("NLT"),
+       _T("NGE"),
+       _T("NGT"),
+       _T("SNE"),
+       _T("ST")
+};
+const TCHAR *fpuopcodes[] =
+{
+       _T("FMOVE"),
+       _T("FINT"),
+       _T("FSINH"),
+       _T("FINTRZ"),
+       _T("FSQRT"),
+       NULL,
+       _T("FLOGNP1"),
+       NULL,
+       _T("FETOXM1"),
+       _T("FTANH"),
+       _T("FATAN"),
+       NULL,
+       _T("FASIN"),
+       _T("FATANH"),
+       _T("FSIN"),
+       _T("FTAN"),
+       _T("FETOX"),    // 0x10
+       _T("FTWOTOX"),
+       _T("FTENTOX"),
+       NULL,
+       _T("FLOGN"),
+       _T("FLOG10"),
+       _T("FLOG2"),
+       NULL,
+       _T("FABS"),
+       _T("FCOSH"),
+       _T("FNEG"),
+       NULL,
+       _T("FACOS"),
+       _T("FCOS"),
+       _T("FGETEXP"),
+       _T("FGETMAN"),
+       _T("FDIV"),             // 0x20
+       _T("FMOD"),
+       _T("FADD"),
+       _T("FMUL"),
+       _T("FSGLDIV"),
+       _T("FREM"),
+       _T("FSCALE"),
+       _T("FSGLMUL"),
+       _T("FSUB"),
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       _T("FSINCOS"),  // 0x30
+       _T("FSINCOS"),
+       _T("FSINCOS"),
+       _T("FSINCOS"),
+       _T("FSINCOS"),
+       _T("FSINCOS"),
+       _T("FSINCOS"),
+       _T("FSINCOS"),
+       _T("FCMP"),
+       NULL,
+       _T("FTST"),
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL
+};
+
+static const TCHAR *movemregs[] =
+{
+       _T("D0"),
+       _T("D1"),
+       _T("D2"),
+       _T("D3"),
+       _T("D4"),
+       _T("D5"),
+       _T("D6"),
+       _T("D7"),
+       _T("A0"),
+       _T("A1"),
+       _T("A2"),
+       _T("A3"),
+       _T("A4"),
+       _T("A5"),
+       _T("A6"),
+       _T("A7"),
+       _T("FP0"),
+       _T("FP1"),
+       _T("FP2"),
+       _T("FP3"),
+       _T("FP4"),
+       _T("FP5"),
+       _T("FP6"),
+       _T("FP7"),
+       _T("FPIAR"),
+       _T("FPSR"),
+       _T("FPCR")
+};
+
+static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode)
+{
+       TCHAR *p = out + _tcslen (out);
+       if (*prevreg < 0) {
+               *prevreg = reg;
+               *lastreg = reg;
+               return;
+       }
+       if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
+               _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]);
+               p = p + _tcslen (p);
+               if (*lastreg != *prevreg) {
+                       if ((*lastreg) + 2 == reg) {
+                               _stprintf(p, _T("/%s"), movemregs[*prevreg]);
+                       } else if ((*lastreg) != (*prevreg)) {
+                               _stprintf(p, _T("-%s"), movemregs[*prevreg]);
+                       }
+               }
+               *lastreg = reg;
+               *first = 0;
+       }
+       *prevreg = reg;
+}
+
+static bool movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode, bool dst)
+{
+       unsigned int dmask, amask;
+       int prevreg = -1, lastreg = -1, first = 1;
+
+       if (mode == Apdi && !fpmode) {
+               uae_u8 dmask2;
+               uae_u8 amask2;
+               
+               amask2 = mask & 0xff;
+               dmask2 = (mask >> 8) & 0xff;
+               dmask = 0;
+               amask = 0;
+               for (int i = 0; i < 8; i++) {
+                       if (dmask2 & (1 << i))
+                               dmask |= 1 << (7 - i);
+                       if (amask2 & (1 << i))
+                               amask |= 1 << (7 - i);
+               }
+       } else {
+               dmask = mask & 0xff;
+               amask = (mask >> 8) & 0xff;
+               if (fpmode == 1 && mode != Apdi) {
+                       uae_u8 dmask2 = dmask;
+                       dmask = 0;
+                       for (int i = 0; i < 8; i++) {
+                               if (dmask2 & (1 << i))
+                                       dmask |= 1 << (7 - i);
+                       }
+               }
+       }
+       bool dataout = dmask != 0 || amask != 0;
+       if (dst && dataout)
+               _tcscat(out, _T(","));
+       if (fpmode) {
+               while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; }
+       } else {
+               while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; }
+               while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; }
+       }
+       addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode);
+       return dataout;
+}
+
+static void disasm_size (TCHAR *instrname, struct instr *dp)
+{
+       if (dp->unsized) {
+               _tcscat(instrname, _T(" "));
+               return;
+       }
+       switch (dp->size)
+       {
+       case sz_byte:
+               _tcscat (instrname, _T(".B "));
+               break;
+       case sz_word:
+               _tcscat (instrname, _T(".W "));
+               break;
+       case sz_long:
+               _tcscat (instrname, _T(".L "));
+               break;
+       default:
+               _tcscat (instrname, _T(" "));
+               break;
+       }
+}
+
+static void asm_add_extensions(uae_u16 *data, int *dcntp, int mode, uae_u32 v, int extcnt, uae_u16 *ext, uaecptr pc, int size)
+{
+       int dcnt = *dcntp;
+       if (mode < 0)
+               return;
+       if (mode == Ad16) {
+               data[dcnt++] = v;
+       }
+       if (mode == PC16) {
+               data[dcnt++] = v - (pc + 2);
+       }
+       if (mode == Ad8r || mode == PC8r) {
+               for (int i = 0; i < extcnt; i++) {
+                       data[dcnt++] = ext[i];
+               }
+       }
+       if (mode == absw) {
+               data[dcnt++] = (uae_u16)v;
+       }
+       if (mode == absl) {
+               data[dcnt++] = (uae_u16)(v >> 16);
+               data[dcnt++] = (uae_u16)v;
+       }
+       if ((mode == imm && size == 0) || mode == imm0) {
+               data[dcnt++] = (uae_u8)v;
+       }
+       if ((mode == imm && size == 1) || mode == imm1) {
+               data[dcnt++] = (uae_u16)v;
+       }
+       if ((mode == imm && size == 2) || mode == imm2) {
+               data[dcnt++] = (uae_u16)(v >> 16);
+               data[dcnt++] = (uae_u16)v;
+       }
+       *dcntp = dcnt;
+}
+
+static int asm_isdreg(const TCHAR *s)
+{
+       if (s[0] == 'D' && s[1] >= '0' && s[1] <= '7')
+               return s[1] - '0';
+       return -1;
+}
+static int asm_isareg(const TCHAR *s)
+{
+       if (s[0] == 'A' && s[1] >= '0' && s[1] <= '7')
+               return s[1] - '0';
+       if (s[0] == 'S' && s[1] == 'P')
+               return 7;
+       return -1;
+}
+static int asm_ispc(const TCHAR *s)
+{
+       if (s[0] == 'P' && s[1] == 'C')
+               return 1;
+       return 0;
+}
+
+static uae_u32 asmgetval(const TCHAR *s)
+{
+       TCHAR *endptr;
+       if (s[0] == '-')
+               return _tcstol(s, &endptr, 16);
+       return _tcstoul(s, &endptr, 16);
+}
+
+static int asm_parse_mode020(TCHAR *s, uae_u8 *reg, uae_u32 *v, int *extcnt, uae_u16 *ext)
+{
+       return -1;
+}
+
+static int asm_parse_mode(TCHAR *s, uae_u8 *reg, uae_u32 *v, int *extcnt, uae_u16 *ext)
+{
+       TCHAR *ss = s;
+       *reg = -1;
+       *v = 0;
+       *ext = 0;
+       *extcnt = 0;
+       if (s[0] == 0)
+               return -1;
+       // Dn
+       if (asm_isdreg(s) >= 0 && s[2] == 0) {
+               *reg = asm_isdreg(s);
+               return Dreg;
+       }
+       // An
+       if (asm_isareg(s) >= 0 && s[2] == 0) {
+               *reg = asm_isareg(s);
+               return Areg;
+       }
+       // (An) and (An)+
+       if (s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')') {
+               *reg = asm_isareg(s + 1);
+               if (s[4] == '+' && s[5] == 0)
+                       return Aipi;
+               if (s[4] == 0)
+                       return Aind;
+               return -1;
+       }
+       // -(An)
+       if (s[0] == '-' && s[1] == '(' && asm_isareg(s + 2) >= 0 && s[4] == ')' && s[5] == 0) {
+               *reg = asm_isareg(s + 2);
+               return Apdi;
+       }
+       // Immediate
+       if (s[0] == '#') {
+               if (s[1] == '!') {
+                       *v = _tstol(s + 2);
+               } else {
+                       *v = asmgetval(s + 1);
+               }
+               return imm;
+       }
+       // Value
+       if (s[0] == '!') {
+               *v = _tstol(s + 1);
+       } else {
+               *v = asmgetval(s);
+       }
+       int dots = 0;
+       int fullext = 0;
+       for (int i = 0; i < _tcslen(s); i++) {
+               if (s[i] == ',') {
+                       dots++;
+               } else if (s[i] == '[') {
+                       if (fullext > 0)
+                               fullext = -1;
+                       else
+                               fullext = 1;
+               } else if (s[i] == ']') {
+                       if (fullext != 1)
+                               fullext = -1;
+                       else
+                               fullext = 2;
+                       fullext++;
+               }
+       }
+       if (fullext < 0 || fullext == 1)
+               return -1;
+       if (fullext == 2) {
+               return asm_parse_mode020(s, reg, v, extcnt, ext);
+       }
+       while (*s != 0) {
+               // d16(An)
+               if (dots == 0 && s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')' && s[4] == 0) {
+                       *reg = asm_isareg(s + 1);
+                       return Ad16;
+               }
+               // d16(PC)
+               if (dots == 0 && s[0] == '(' && asm_ispc(s + 1) && s[3] == ')' && s[4] == 0) {
+                       *reg = 2;
+                       return PC16;
+               }
+               // (d16,An) / (d16,PC)
+               if (dots == 1 && s[0] == '(' && !asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) {
+                       TCHAR *startptr, *endptr;
+                       if (s[1] == '!') {
+                               startptr = s + 2;
+                               *v = _tcstol(startptr, &endptr, 10);
+                       } else {
+                               startptr = s + 1;
+                               *v = _tcstol(startptr, &endptr, 16);
+                       }
+                       if (endptr == startptr || endptr[0] != ',')
+                               return -1;
+                       if (asm_ispc(endptr + 1) && endptr[3] == ')') {
+                               *reg = 2;
+                               return PC16;
+                       }
+                       if (asm_isareg(endptr + 1) >= 0 && endptr[3] == ')') {
+                               *reg = asm_isareg(endptr + 1);
+                               return Ad16;
+                       }
+                       return -1;
+               }
+               // Ad8r PC8r
+               if (s[0] == '(') {
+                       TCHAR *s2 = s;
+                       if (!asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) {
+                               if (dots != 2)
+                                       return -1;
+                               TCHAR *startptr, *endptr;
+                               if (s[1] == '!') {
+                                       startptr = s + 2;
+                                       *v = _tcstol(startptr, &endptr, 10);
+                               } else {
+                                       startptr = s + 1;
+                                       *v = _tcstol(startptr, &endptr, 16);
+                               }
+                               if (endptr == startptr || endptr[0] != ',')
+                                       return -1;
+                               s2 = endptr + 1;
+                       } else if (((asm_isareg(s + 1) >= 0 || asm_ispc(s + 1)) && s[3] == ',') || (asm_isdreg(s + 4) >= 0 || asm_isareg(s + 4) >= 0)) {
+                               if (dots != 1)
+                                       return -1;
+                               s2 = s + 1;
+                       } else {
+                               return -1;
+                       }
+                       uae_u8 reg2;
+                       bool ispc = asm_ispc(s2);
+                       if (ispc) {
+                               *reg = 3;
+                       } else {
+                               *reg = asm_isareg(s2);
+                       }
+                       *extcnt = 1;
+                       s2 += 2;
+                       if (*s2 != ',')
+                               return -1;
+                       s2++;
+                       if (asm_isdreg(s2) >= 0) {
+                               reg2 = asm_isdreg(s2);
+                       } else {
+                               reg2 = asm_isareg(s2);
+                               *ext |= 1 << 15;
+                       }
+                       s2 += 2;
+                       *ext |= reg2 << 12;
+                       *ext |= (*v) & 0xff;
+                       if (s2[0] == '.' && s2[1] == 'W') {
+                               s2 += 2;
+                       } else if (s2[0] == '.' && s2[1] == 'L') {
+                               *ext |= 1 << 11;
+                               s2 += 2;
+                       }
+                       if (s2[0] == '*') {
+                               TCHAR scale = s2[1];
+                               if (scale == '2')
+                                       *ext |= 1 << 9;
+                               else if (scale == '4')
+                                       *ext |= 2 << 9;
+                               else if (scale == '8')
+                                       *ext |= 3 << 9;
+                               else
+                                       return -1;
+                               s2 += 2;
+                       }
+                       if (s2[0] == ')' && s2[1] == 0) {
+                               return ispc ? PC8r : Ad8r;
+                       }
+                       return -1;
+               }
+               s++;
+       }
+       // abs.w
+       if (s - ss > 2 && s[-2] == '.' && s[-1] == 'W') {
+               *reg = 0;
+               return absw;
+       }
+       // abs.l
+       *reg = 1;
+       return absl;
+}
+
+static TCHAR *asm_parse_parm(TCHAR *parm, TCHAR *out)
+{
+       TCHAR *p = parm;
+       bool quote = false;
+
+       for (;;) {
+               if (*p == '(') {
+                       quote = true;
+               }
+               if (*p == ')') {
+                       if (!quote)
+                               return NULL;
+                       quote = false;
+               }
+               if ((*p == ',' || *p == 0) && !quote) {
+                       TCHAR c = *p;
+                       p[0] = 0;
+                       _tcscpy(out, parm);
+                       my_trim(out);
+                       if (c)
+                               p++;
+                       return p;
+               }
+               p++;
+       }
+}
+
+static bool m68k_asm_parse_movec(TCHAR *s, TCHAR *d)
+{
+       for (int i = 0; m2cregs[i].regname; i++) {
+               if (!_tcscmp(s, m2cregs[i].regname)) {
+                       uae_u16 v = m2cregs[i].regno;
+                       if (asm_isareg(d) >= 0)
+                               v |= 0x8000 | (asm_isareg(d) << 12);
+                       else if (asm_isdreg(d) >= 0)
+                               v |= (asm_isdreg(d) << 12);
+                       else
+                               return false;
+                       _stprintf(s, _T("#%X"), v);
+                       return true;
+               }
+       }
+       return false;
+}
+
+static bool m68k_asm_parse_movem(TCHAR *s, int dir)
+{
+       TCHAR *d = s;
+       uae_u16 regmask = 0;
+       uae_u16 mask = dir ? 0x8000 : 0x0001;
+       bool ret = false;
+       while(*s) {
+               int dreg = asm_isdreg(s);
+               int areg = asm_isareg(s);
+               if (dreg < 0 && areg < 0)
+                       break;
+               int reg = dreg >= 0 ? dreg : areg + 8;
+               regmask |= dir ? (mask >> reg) : (mask << reg);
+               s += 2;
+               if (*s == 0) {
+                       ret = true;
+                       break;
+               } else if (*s == '/') {
+                       s++;
+                       continue;
+               } else if (*s == '-') {
+                       s++;
+                       int dreg2 = asm_isdreg(s);
+                       int areg2 = asm_isareg(s);
+                       if (dreg2 < 0 && areg2 < 0)
+                               break;
+                       int reg2 = dreg2 >= 0 ? dreg2 : areg2 + 8;
+                       if (reg2 < reg)
+                               break;
+                       while (reg2 >= reg) {
+                               regmask |= dir ? (mask >> reg) : (mask << reg);
+                               reg++;
+                       }
+                       s += 2;
+                       if (*s == 0) {
+                               ret = true;
+                               break;
+                       }
+               } else {
+                       break;
+               }
+       }
+       if (ret)
+               _stprintf(d, _T("#%X"), regmask);
+       return ret;
+}
+
+int m68k_asm(TCHAR *sline, uae_u16 *out, uaecptr pc)
+{
+       TCHAR *p;
+       const TCHAR *cp1;
+       TCHAR ins[256], parms[256];
+       TCHAR line[256];
+       TCHAR srcea[256], dstea[256];
+       uae_u16 data[16], sexts[8], dexts[8];
+       int sextcnt, dextcnt;
+       int dcnt = 0;
+       int cc = -1;
+       int quick = 0;
+       bool immrelpc = false;
+
+       if (_tcslen(sline) > 100)
+               return -1;
+
+       srcea[0] = dstea[0] = 0;
+       parms[0] = 0;
+
+       // strip all white space except first space
+       p = line;
+       bool firstsp = true;
+       for (int i = 0; sline[i]; i++) {
+               TCHAR c = sline[i];
+               if (c == 32 && firstsp) {
+                       firstsp = false;
+                       *p++ = 32;
+               }
+               if (c <= 32)
+                       continue;
+               *p++ = c;
+       }
+       *p = 0;
+
+       to_upper(line, _tcslen(line));
+
+       p = line;
+       while (*p && *p != ' ')
+               p++;
+       if (*p == ' ') {
+               *p = 0;
+               _tcscpy(parms, p + 1);
+               my_trim(parms);
+       }
+       _tcscpy(ins, line);
+       
+       if (_tcslen(ins) == 0)
+               return 0;
+
+       int size = 1;
+       int inssize = -1;
+       cp1 = _tcschr(line, '.');
+       if (cp1) {
+               size = cp1[1];
+               if (size == 'W')
+                       size = 1;
+               else if (size == 'L')
+                       size = 2;
+               else if (size == 'B')
+                       size = 0;
+               else
+                       return 0;
+               inssize = size;
+               line[cp1 - line] = 0;
+               _tcscpy(ins, line);
+       }
+
+       TCHAR *parmp = parms;
+       parmp = asm_parse_parm(parmp, srcea);
+       if (!parmp)
+               return 0;
+       if (srcea[0]) {
+               parmp = asm_parse_parm(parmp, dstea);
+               if (!parmp)
+                       return 0;
+       }
+
+       int smode = -1;
+       int dmode = -1;
+       uae_u8 sreg = -1;
+       uae_u8 dreg = -1;
+       uae_u32 sval = 0;
+       uae_u32 dval = 0;
+       int ssize = -1;
+       int dsize = -1;
+
+       dmode = asm_parse_mode(dstea, &dreg, &dval, &dextcnt, dexts);
+
+
+       // Common alias
+       if (!_tcscmp(ins, _T("BRA"))) {
+               _tcscpy(ins, _T("BT"));
+       } else if (!_tcscmp(ins, _T("BSR"))) {
+               immrelpc = true;
+       } else if (!_tcscmp(ins, _T("MOVEM"))) {
+               if (dmode >= Aind && _tcschr(dstea, '-') == NULL && _tcschr(dstea, '/') == NULL) {
+                       _tcscpy(ins, _T("MVMLE"));
+                       if (!m68k_asm_parse_movem(srcea, dmode == Apdi))
+                               return -1;
+               } else {
+                       TCHAR tmp[256];
+                       _tcscpy(ins, _T("MVMEL"));
+                       _tcscpy(tmp, srcea);
+                       _tcscpy(srcea, dstea);
+                       _tcscpy(dstea, tmp);
+                       if (!m68k_asm_parse_movem(srcea, 0))
+                               return -1;
+                       dmode = asm_parse_mode(dstea, &dreg, &dval, &dextcnt, dexts);
+               }
+       } else if (!_tcscmp(ins, _T("MOVEC"))) {
+               if (dmode == Dreg || dmode == Areg) {
+                       _tcscpy(ins, _T("MOVEC2"));
+                       if (!m68k_asm_parse_movec(srcea, dstea))
+                               return -1;
+               } else {
+                       TCHAR tmp[256];
+                       _tcscpy(ins, _T("MOVE2C"));
+                       _tcscpy(tmp, srcea);
+                       _tcscpy(srcea, dstea);
+                       dstea[0] = 0;
+                       if (!m68k_asm_parse_movec(srcea, tmp))
+                               return -1;
+               }
+               dmode = -1;
+       }
+       
+       if (dmode == Areg) {
+               int l = _tcslen(ins);
+               if (l <= 2)
+                       return -1;
+               TCHAR last = ins[l- 1];
+               if (last == 'Q') {
+                       last = ins[l - 2];
+                       if (last != 'A') {
+                               ins[l - 1] = 'A';
+                               ins[l] = 'Q';
+                               ins[l + 1] = 0;
+                       }
+               } else if (last != 'A') {
+                       _tcscat(ins, _T("A"));
+               }
+       }
+
+       bool fp = ins[0] == 'F';
+
+       if (ins[_tcslen(ins) - 1] == 'Q' && _tcslen(ins) > 3 && !fp) {
+               quick = 1;
+               ins[_tcslen(ins) - 1] = 0;
+       }
+
+       struct mnemolookup *lookup;
+       for (lookup = lookuptab; lookup->name; lookup++) {
+               if (!_tcscmp(ins, lookup->name))
+                       break;
+       }
+       if (!lookup->name) {
+               // Check cc variants
+               for (lookup = lookuptab; lookup->name; lookup++) {
+                       const TCHAR *ccp = _tcsstr(lookup->name, _T("cc"));
+                       if (ccp) {
+                               TCHAR tmp[256];
+                               for (int i = 0; i < (fp ? 32 : 16); i++) {
+                                       const TCHAR *ccname = fp ? fpccnames[i] : ccnames[i];
+                                       _tcscpy(tmp, lookup->name);
+                                       _tcscpy(tmp + (ccp - lookup->name), ccname);
+                                       if (tmp[_tcslen(tmp) - 1] == ' ')
+                                               tmp[_tcslen(tmp) - 1] = 0;
+                                       if (!_tcscmp(tmp, ins)) {
+                                               _tcscpy(ins, lookup->name);
+                                               cc = i;
+                                               if (lookup->mnemo == i_DBcc || lookup->mnemo == i_Bcc) {
+                                                       // Bcc.B uses same encoding mode as MOVEQ
+                                                       immrelpc = true;
+                                               }
+                                               if (size == 0) {
+                                                       quick = 2;
+                                               }
+                                               break;
+                                       }
+                               }
+                       }
+                       if (cc >= 0)
+                               break;
+               }
+       }
+
+       if (!lookup->name)
+               return 0;
+
+       int mnemo = lookup->mnemo;
+
+       int found = 0;
+       int sizemask = 0;
+       int tsize = size;
+       int unsized = 0;
+
+       for (int round = 0; round < 9; round++) {
+
+               if (!found && round == 8)
+                       return 0;
+
+               if (round == 3) {
+                       // Q is always LONG sized
+                       if (quick == 1) {
+                               tsize = 2;
+                       }
+                       bool isimm = srcea[0] == '#';
+                       if (immrelpc && !isimm) {
+                               TCHAR tmp[256];
+                               _tcscpy(tmp, srcea);
+                               srcea[0] = '#';
+                               _tcscpy(srcea + 1, tmp);
+                       }
+                       smode = asm_parse_mode(srcea, &sreg, &sval, &sextcnt, sexts);
+                       if (immrelpc && !isimm) {
+                               sval = sval - (pc + 2);
+                       }
+                       if (quick) {
+                               smode = immi;
+                               sreg = sval & 0xff;
+                       }
+               }
+
+               if (round == 1) {
+                       if (!quick && (sizemask == 1 || sizemask == 2 || sizemask == 4)) {
+                               tsize = 0;
+                               if (sizemask == 2)
+                                       tsize = 1;
+                               else if (sizemask == 4)
+                                       tsize = 2;
+                       } else {
+                               continue;
+                       }
+               }
+               if (round == 2 && !found) {
+                       unsized = 1;
+               }
+
+               if (round == 4 && smode == imm) {
+                       smode = imm0;
+               } else if (round == 5 && smode == imm0) {
+                       smode = imm1;
+               } else if (round == 6 && smode == imm1) {
+                       smode = imm2;
+               } else if (round == 7 && smode == imm2) {
+                       smode = immi;
+                       sreg = sval & 0xff;
+               } else if (round == 4) {
+                       round += 5 - 1;
+               }
+
+               for (int opcode = 0; opcode < 65536; opcode++) {
+                       struct instr *table = &table68k[opcode];
+                       if (table->mnemo != mnemo)
+                               continue;
+                       if (cc >= 0 && table->cc != cc)
+                               continue;
+
+#if 0
+                       if (round == 0) {
+                               console_out_f(_T("%s OP=%04x S=%d SR=%d SM=%d SU=%d SP=%d DR=%d DM=%d DU=%d DP=%d SDU=%d\n"), lookup->name, opcode, table->size,
+                                       table->sreg, table->smode, table->suse, table->spos,
+                                       table->dreg, table->dmode, table->duse, table->dpos,
+                                       table->sduse);
+                       }
+#endif
+
+                       if (table->duse && !(table->dmode == dmode || (dmode >= imm && dmode <= imm2 && table->dmode >= imm && table->dmode <= imm2)))
+                               continue;
+                       if (round == 0) {
+                               sizemask |= 1 << table->size;
+                       }
+                       if (unsized > 0 && !table->unsized) {
+                               continue;
+                       }
+
+                       found++;
+
+                       if (round >= 3) {
+
+                               if (
+                                       ((table->size == tsize || table->unsized)) &&
+                                       ((!table->suse && smode < 0) || (table->suse && table->smode == smode)) &&
+                                       ((!table->duse && dmode < 0) || (table->duse && (table->dmode == dmode || (dmode == imm && (table->dmode >= imm && table->dmode <= imm2))))) &&
+                                       ((table->sreg == sreg || (table->smode >= absw && table->smode != immi))) &&
+                                       ((table->dreg == dreg || table->dmode >= absw))
+                                       )
+                               {
+                                       if (inssize >= 0 && tsize != inssize)
+                                               continue;
+
+
+                                       data[dcnt++] = opcode;
+                                       asm_add_extensions(data, &dcnt, smode, sval, sextcnt, sexts, pc, tsize);
+                                       if (smode >= 0)
+                                               asm_add_extensions(data, &dcnt, dmode, dval, dextcnt, dexts, pc, tsize);
+                                       for (int i = 0; i < dcnt; i++) {
+                                               out[i] = data[i];
+                                       }
+                                       return dcnt;
+                               }
+
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static void resolve_if_jmp(TCHAR *s, uae_u32 addr)
+{
+       uae_u16 opcode = get_word_debug(addr);
+       if (opcode == 0x4ef9) { // JMP x.l
+               TCHAR *p = s + _tcslen(s);
+               uae_u32 addr2 = get_long_debug(addr + 2);
+               _stprintf(p, _T(" == $%08x "), addr2);
+               showea_val(p + _tcslen(p), opcode, addr2, 4);
+               TCHAR txt[256];
+               bool ext;
+               if (debugmem_get_segment(addr2, NULL, &ext, NULL, txt)) {
+                       if (ext) {
+                               _tcscat(p, _T(" "));
+                               _tcscat(p, txt);
+                       }
+               }
+       }
+}
+
+static bool mmu_op30_helper_get_fc(uae_u16 extra, TCHAR *out)
+{
+       switch (extra & 0x0018) {
+       case 0x0010:
+               _stprintf(out, _T("#%d"), extra & 7);
+               return true;
+       case 0x0008:
+               _stprintf(out, _T("D%d"), extra & 7);
+               return true;
+       case 0x0000:
+               if (extra & 1) {
+                       _tcscpy(out, _T("DFC"));
+               } else {
+                       _tcscpy(out, _T("SFC"));
+               }
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool mmu_op30_invea(uae_u32 opcode)
+{
+       int eamode = (opcode >> 3) & 7;
+       int rreg = opcode & 7;
+
+       // Dn, An, (An)+, -(An), immediate and PC-relative not allowed
+       if (eamode == 0 || eamode == 1 || eamode == 3 || eamode == 4 || (eamode == 7 && rreg > 1))
+               return true;
+       return false;
+}
+
+static uaecptr disasm_mmu030(uaecptr pc, uae_u16 opcode, uae_u16 extra, struct instr *dp, TCHAR *instrname, uae_u32 *seaddr2, int safemode)
+{
+       int type = extra >> 13;
+
+       _tcscpy(instrname, _T("F-LINE (MMU 68030)"));
+       pc += 2;
+
+       switch (type)
+       {
+       case 0:
+       case 2:
+       case 3:
+       {
+               // PMOVE
+               int preg = (extra >> 10) & 31;
+               int rw = (extra >> 9) & 1;
+               int fd = (extra >> 8) & 1;
+               int unused = (extra & 0xff);
+               const TCHAR *r = NULL;
+
+               if (mmu_op30_invea(opcode))
+                       break;
+               if (unused)
+                       break;
+               if (rw && fd)
+                       break;
+               switch (preg)
+               {
+               case 0x10:
+                       r = _T("TC");
+                       break;
+               case 0x12:
+                       r = _T("SRP");
+                       break;
+               case 0x13:
+                       r = _T("CRP");
+                       break;
+               case 0x18:
+                       r = _T("MMUSR");
+                       break;
+               case 0x02:
+                       r = _T("TT0");
+                       break;
+               case 0x03:
+                       r = _T("TT1");
+                       break;
+               }
+               if (!r)
+                       break;
+
+               _tcscpy(instrname, _T("PMOVE"));
+               if (fd)
+                       _tcscat(instrname, _T("FD"));
+               _tcscat(instrname, _T(" "));
+
+               if (!rw) {
+                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode);
+                       _tcscat(instrname, _T(","));
+               }
+               _tcscat(instrname, r);
+               if (rw) {
+                       _tcscat(instrname, _T(","));
+                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode);
+               }
+               break;
+       }
+       case 1:
+       {
+               // PLOAD/PFLUSH
+               uae_u16 mode = (extra >> 8) & 31;
+               int unused = (extra & (0x100 | 0x80 | 0x40 | 0x20));
+               uae_u16 fc_mask = (extra & 0x00E0) >> 5;
+               uae_u16 fc_bits = extra & 0x7f;
+               TCHAR fc[10];
+
+               if (unused)
+                       break;
+
+               switch (mode) {
+               case 0x00: // PLOAD W
+               case 0x02: // PLOAD R
+                       if (mmu_op30_invea(opcode))
+                               break;
+                       _stprintf(instrname, _T("PLOAD%c %s,"), mode == 0 ? 'W' : 'R', fc);
+                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode);
+                       break;
+               case 0x04: // PFLUSHA
+                       if (fc_bits)
+                               break;
+                       _tcscpy(instrname, _T("PFLUSHA"));
+                       break;
+               case 0x10: // FC
+                       if (!mmu_op30_helper_get_fc(extra, fc))
+                               break;
+                       _stprintf(instrname, _T("PFLUSH %s,%d"), fc, fc_mask);
+                       break;
+               case 0x18: // FC + EA
+                       if (mmu_op30_invea(opcode))
+                               break;
+                       if (!mmu_op30_helper_get_fc(extra, fc))
+                               break;
+                       _stprintf(instrname, _T("PFLUSH %s,%d"), fc, fc_mask);
+                       _tcscat(instrname, _T(","));
+                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode);
+                       break;
+               }
+               break;
+       }
+       case 4:
+       {
+               // PTEST
+               int level = (extra & 0x1C00) >> 10;
+               int rw = (extra >> 9) & 1;
+               int a = (extra >> 8) & 1;
+               int areg = (extra & 0xE0) >> 5;
+               TCHAR fc[10];
+
+               if (mmu_op30_invea(opcode))
+                       break;
+               if (!mmu_op30_helper_get_fc(extra, fc))
+                       break;
+               if (!level && a)
+                       break;
+               _stprintf(instrname, _T("PTEST%c %s,"), rw ? 'R' : 'W', fc);
+               pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode);
+               _stprintf(instrname + _tcslen(instrname), _T(",#%d"), level);
+               if (a)
+                       _stprintf(instrname + _tcslen(instrname), _T(",A%d"), areg);
+               break;
+       }
+       }
+       return pc;
+}
+
+
+void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc, int safemode)
+{
+       uae_u32 seaddr2;
+       uae_u32 deaddr2;
+
+       if (!table68k)
+               return;
+       while (cnt-- > 0) {
+               TCHAR instrname[256], *ccpt;
+               TCHAR segout[256], segname[256];
+               int i;
+               uae_u32 opcode;
+               uae_u16 extra;
+               struct mnemolookup *lookup;
+               struct instr *dp;
+               uaecptr oldpc;
+               uaecptr m68kpc_illg = 0;
+               bool illegal = false;
+               int segid, lastsegid;
+               TCHAR *symbolpos;
+
+               seaddr2 = deaddr2 = 0;
+               oldpc = pc;
+               opcode = get_word_debug (pc);
+               extra = get_word_debug (pc + 2);
+               if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) {
+                       m68kpc_illg = pc + 2;
+                       illegal = TRUE;
+               }
+
+               dp = table68k + opcode;
+               if (dp->mnemo == i_ILLG) {
+                       illegal = FALSE;
+                       opcode = 0x4AFC;
+                       dp = table68k + opcode;
+               }
+               for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
+                       ;
+
+               lastsegid = -1;
+               bool exact = false;
+               if (lastpc != 0xffffffff) {
+                       lastsegid = debugmem_get_segment(lastpc, NULL, NULL, NULL, NULL);
+               }
+               segid = debugmem_get_segment(pc, &exact, NULL, segout, segname);
+               if (segid && (lastsegid != -1 || exact) && (segid != lastsegid || pc == lastpc || exact)) {
+                       buf = buf_out(buf, &bufsize, _T("%s\n"), segname);
+               }
+               symbolpos = buf;
+
+               buf = buf_out (buf, &bufsize, _T("%08X "), pc);
+
+               if (segid) {
+                       buf = buf_out(buf, &bufsize, _T("%s "), segout);
+               }
+
+               pc += 2;
+               
+               if (lookup->friendlyname)
+                       _tcscpy (instrname, lookup->friendlyname);
+               else
+                       _tcscpy (instrname, lookup->name);
+               ccpt = _tcsstr (instrname, _T("cc"));
+               if (ccpt != 0) {
+                       if ((opcode & 0xf000) == 0xf000)
+                               _tcscpy (ccpt, fpccnames[extra & 0x1f]);
+                       else
+                               _tcsncpy (ccpt, ccnames[dp->cc], 2);
+               }
+               disasm_size (instrname, dp);
+
+               if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
+                       uae_u16 imm = extra;
+                       uae_u16 creg = imm & 0x0fff;
+                       uae_u16 r = imm >> 12;
+                       TCHAR regs[16];
+                       const TCHAR *cname = _T("?");
+                       int j;
+                       for (j = 0; m2cregs[j].regname; j++) {
+                               if (m2cregs[j].regno == creg)
+                                       break;
+                       }
+                       _stprintf(regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
+                       if (m2cregs[j].regname)
+                               cname = m2cregs[j].regname;
+                       if (lookup->mnemo == i_MOVE2C) {
+                               _tcscat(instrname, regs);
+                               _tcscat(instrname, _T(","));
+                               _tcscat(instrname, cname);
+                       } else {
+                               _tcscat(instrname, cname);
+                               _tcscat(instrname, _T(","));
+                               _tcscat(instrname, regs);
+                       }
+                       pc += 2;
+               } else if (lookup->mnemo == i_CHK2) {
+                       TCHAR *p;
+                       if (!(extra & 0x0800)) {
+                               instrname[1] = 'M';
+                               instrname[2] = 'P';
+                       }
+                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
+                       extra = get_word_debug(pc);
+                       pc += 2;
+                       p = instrname + _tcslen(instrname);
+                       _stprintf(p, (extra & 0x8000) ? _T(",A%d") : _T(",D%d"), (extra >> 12) & 7);
+               } else if (lookup->mnemo == i_CAS) {
+                       TCHAR *p = instrname + _tcslen(instrname);
+                       _stprintf(p, _T("D%d,D%d,"), extra & 7, (extra >> 6) & 7);
+                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
+               } else if (lookup->mnemo == i_CAS2) {
+                       TCHAR *p = instrname + _tcslen(instrname);
+                       uae_u16 extra2 = get_word_debug(pc + 2);
+                       _stprintf(p, _T("D%d:D%d,D%d,D%d,(%c%d):(%c%d)"),
+                               extra & 7, extra2 & 7, (extra >> 6) & 7, (extra2 >> 6) & 7,
+                               (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7,
+                               (extra2 & 0x8000) ? 'A' : 'D', (extra2 >> 12) & 7);
+                       pc += 4;
+               } else if (lookup->mnemo == i_ORSR || lookup->mnemo == i_ANDSR || lookup->mnemo == i_EORSR) {
+                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
+                       _tcscat(instrname, dp->size == sz_byte ? _T(",CCR") : _T(",SR"));
+               } else if (lookup->mnemo == i_MVR2USP) {
+                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
+                       _tcscat(instrname, _T(",USP"));
+               } else if (lookup->mnemo == i_MVUSP2R) {
+                       _tcscat(instrname, _T("USP,"));
+                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
+               } else if (lookup->mnemo == i_MV2SR) {
+                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
+                       _tcscat(instrname, dp->size == sz_byte ? _T(",CCR") : _T(",SR"));
+               } else if (lookup->mnemo == i_MVSR2) {          
+                       _tcscat(instrname, dp->size == sz_byte ? _T("CCR,") : _T("SR,"));
+                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
+               } else if (lookup->mnemo == i_MVMEL) {
+                       uae_u16 mask = extra;
+                       pc += 2;
+                       pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
+                       movemout (instrname, mask, dp->dmode, 0, true);
+               } else if (lookup->mnemo == i_MVMLE) {
+                       uae_u16 mask = extra;
+                       pc += 2;
+                       if (movemout(instrname, mask, dp->dmode, 0, false))
+                               _tcscat(instrname, _T(","));
+                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
+               } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) {
+                       TCHAR *p;
+                       extra = get_word_debug(pc);
+                       pc += 2;
+                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
+                       p = instrname + _tcslen(instrname);
+                       if (extra & 0x0400)
+                               _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7);
+                       else
+                               _stprintf(p, _T(",D%d"), (extra >> 12) & 7);
+               } else if (lookup->mnemo == i_MOVES) {
+                       TCHAR *p;
+                       pc += 2;
+                       if (!(extra & 0x0800)) {
+                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
+                               p = instrname + _tcslen(instrname);
+                               _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
+                       } else {
+                               p = instrname + _tcslen(instrname);
+                               _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
+                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
+                       }
+               } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU ||
+                                  lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR ||
+                                  lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS ||
+                                  lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) {
+                       TCHAR *p;
+                       int reg = -1;
+
+                       pc += 2;
+                       p = instrname + _tcslen(instrname);
+                       if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS)
+                               reg = (extra >> 12) & 7;
+                       if (lookup->mnemo == i_BFINS)
+                               _stprintf(p, _T("D%d,"), reg);
+                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
+                       _tcscat(instrname, _T(" {"));
+                       p = instrname + _tcslen(instrname);
+                       if (extra & 0x0800)
+                               _stprintf(p, _T("D%d"), (extra >> 6) & 7);
+                       else
+                               _stprintf(p, _T("%d"), (extra >> 6) & 31);
+                       _tcscat(instrname, _T(":"));
+                       p = instrname + _tcslen(instrname);
+                       if (extra & 0x0020)
+                               _stprintf(p, _T("D%d"), extra & 7);
+                       else
+                               _stprintf(p, _T("%d"), extra  & 31);
+                       _tcscat(instrname, _T("}"));
+                       p = instrname + _tcslen(instrname);
+                       if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU)
+                               _stprintf(p, _T(",D%d"), reg);
+               } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP ||
+                       lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
+                       if ((opcode & 0xc0) == 0xc0)
+                               _tcscat(instrname, _T("BC"));
+                       else if (opcode & 0x80)
+                               _tcscat(instrname, _T("IC"));
+                       else if (opcode & 0x40)
+                               _tcscat(instrname, _T("DC"));
+                       else
+                               _tcscat(instrname, _T("?"));
+                       if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
+                               TCHAR *p = instrname + _tcslen(instrname);
+                               _stprintf(p, _T(",(A%d)"), opcode & 7);
+                       }
+               } else if (lookup->mnemo == i_MOVE16) {
+                       TCHAR *p = instrname + _tcslen(instrname);
+                       if (opcode & 0x20) {
+                               _stprintf(p, _T("(A%d)+,(A%d)+"), opcode & 7, (extra >> 12) & 7);
+                               pc += 2;
+                       } else {
+                               uae_u32 addr = get_long_debug(pc + 2);
+                               int ay = opcode & 7;
+                               pc += 4;
+                               switch ((opcode >> 3) & 3)
+                               {
+                               case 0:
+                                       _stprintf(p, _T("(A%d)+,$%08x"), ay, addr);
+                                       break;
+                               case 1:
+                                       _stprintf(p, _T("$%08x,(A%d)+"), addr, ay);
+                                       break;
+                               case 2:
+                                       _stprintf(p, _T("(A%d),$%08x"), ay, addr);
+                                       break;
+                               case 3:
+                                       _stprintf(p, _T("$%08x,(A%d)"), addr, ay);
+                                       break;
+                               }
+                       }
+               } else if (lookup->mnemo == i_FDBcc) {
+                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
+                       pc += 2;
+                       _tcscat(instrname, _T(","));
+                       pc = ShowEA(NULL, pc, opcode, 0, imm1, sz_word, instrname, &deaddr2, safemode);
+               } else if (lookup->mnemo == i_FPP) {
+                       TCHAR *p;
+                       int ins = extra & 0x3f;
+                       int size = (extra >> 10) & 7;
+
+                       pc += 2;
+                       if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7)
+                               fpdata fp;
+                               fpu_get_constant(&fp, extra);
+                               _stprintf(instrname, _T("FMOVECR.X #0x%02x [%s],FP%d"), extra & 0x7f, fpp_print(&fp, 0), (extra >> 7) & 7);
+                       } else if ((extra & 0x8000) == 0x8000) { // FMOVEM
+                               int dr = (extra >> 13) & 1;
+                               int mode;
+                               int dreg = (extra >> 4) & 7;
+                               int regmask, fpmode;
+                               
+                               if (extra & 0x4000) {
+                                       mode = (extra >> 11) & 3;
+                                       regmask = extra & 0xff;  // FMOVEM FPx
+                                       fpmode = 1;
+                                       _tcscpy(instrname, _T("FMOVEM.X "));
+                               } else {
+                                       mode = 0;
+                                       regmask = (extra >> 10) & 7;  // FMOVEM control
+                                       fpmode = 2;
+                                       _tcscpy(instrname, _T("FMOVEM.L "));
+                                       if (regmask == 1 || regmask == 2 || regmask == 4)
+                                               _tcscpy(instrname, _T("FMOVE.L "));
+                               }
+                               p = instrname + _tcslen(instrname);
+                               if (dr) {
+                                       if (mode & 1)
+                                               _stprintf(p, _T("D%d"), dreg);
+                                       else
+                                               movemout(p, regmask, dp->dmode, fpmode, false);
+                                       _tcscat(instrname, _T(","));
+                                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
+                               } else {
+                                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
+                                       p = instrname + _tcslen(instrname);
+                                       if (mode & 1)
+                                               _stprintf(p, _T(",D%d"), dreg);
+                                       else
+                                               movemout(p, regmask, dp->dmode, fpmode, true);
+                               }
+                       } else {
+                               if (fpuopcodes[ins])
+                                       _tcscpy(instrname, fpuopcodes[ins]);
+                               else
+                                       _tcscpy(instrname, _T("F?"));
+
+                               if ((extra & 0xe000) == 0x6000) { // FMOVE to memory
+                                       int kfactor = extra & 0x7f;
+                                       _tcscpy(instrname, _T("FMOVE."));
+                                       _tcscat(instrname, fpsizes[size]);
+                                       _tcscat(instrname, _T(" "));
+                                       p = instrname + _tcslen(instrname);
+                                       _stprintf(p, _T("FP%d,"), (extra >> 7) & 7);
+                                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
+                                       p = instrname + _tcslen(instrname);
+                                       if (size == 7) {
+                                               _stprintf(p, _T(" {D%d}"), (kfactor >> 4));
+                                       } else if (kfactor) {
+                                               if (kfactor & 0x40)
+                                                       kfactor |= ~0x3f;
+                                               _stprintf(p, _T(" {%d}"), kfactor);
+                                       }
+                               } else {
+                                       if (extra & 0x4000) { // source is EA
+                                               _tcscat(instrname, _T("."));
+                                               _tcscat(instrname, fpsizes[size]);
+                                               _tcscat(instrname, _T(" "));
+                                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
+                                       } else { // source is FPx
+                                               p = instrname + _tcslen(instrname);
+                                               _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7);
+                                       }
+                                       p = instrname + _tcslen(instrname);
+                                       if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7)))
+                                               _stprintf(p, _T(",FP%d"), (extra >> 7) & 7);
+                                       if (ins >= 0x30 && ins < 0x38) { // FSINCOS
+                                               p = instrname + _tcslen(instrname);
+                                               _stprintf(p, _T(",FP%d"), extra & 7);
+                                       }
+                               }
+                       }
+               } else if (lookup->mnemo == i_MMUOP030) {
+                       pc = disasm_mmu030(pc, opcode, extra, dp, instrname, &seaddr2, safemode);
+               } else if ((opcode & 0xf000) == 0xa000) {
+                       _tcscpy(instrname, _T("A-LINE"));
+               } else {
+                       if (dp->suse) {
+                               pc = ShowEA (NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
+
+                               // JSR x(a6) / JMP x(a6)
+                               if (opcode == 0x4ea8 + 6 || opcode == 0x4ee8 + 6) {
+                                       TCHAR sname[256];
+                                       if (debugger_get_library_symbol(m68k_areg(regs, 6), 0xffff0000 | extra, sname)) {
+                                               TCHAR *p = instrname + _tcslen(instrname);
+                                               _stprintf(p, _T(" %s"), sname);
+                                               resolve_if_jmp(instrname, m68k_areg(regs, 6) + (uae_s16)extra);
+                                       }
+                               }
+                               // show target address if JSR x(pc) + JMP xxxx combination
+                               if (opcode == 0x4eba && seaddr2 && instrname[0]) { // JSR x(pc)
+                                       resolve_if_jmp(instrname, seaddr2);
+                               }
+                       }
+                       if (dp->suse && dp->duse)
+                               _tcscat (instrname, _T(","));
+                       if (dp->duse) {
+                               pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
+                       }
+               }
+
+               for (i = 0; i < (pc - oldpc) / 2; i++) {
+                       buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2));
+               }
+               while (i++ < 5)
+                       buf = buf_out (buf, &bufsize, _T("     "));
+
+               if (illegal)
+                       buf = buf_out (buf, &bufsize, _T("[ "));
+               buf = buf_out (buf, &bufsize, instrname);
+               if (illegal)
+                       buf = buf_out (buf, &bufsize, _T(" ]"));
+
+               if (ccpt != 0) {
+                       uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
+                       if (deaddr)
+                               *deaddr = pc;
+                       if ((opcode & 0xf000) == 0xf000) {
+                               if (fpp_cond(dp->cc)) {
+                                       buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
+                               } else {
+                                       buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
+                               }
+                       } else {
+                               if (dp->mnemo == i_Bcc || dp->mnemo == i_DBcc) {
+                                       if (cctrue(dp->cc)) {
+                                               buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
+                                       } else {
+                                               buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
+                                       }
+                               } else {
+                                       if (cctrue(dp->cc)) {
+                                               buf = buf_out(buf, &bufsize, _T(" (T)"));
+                                       } else {
+                                               buf = buf_out(buf, &bufsize, _T(" (F)"));
+                                       }
+                               }
+                       }
+               } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
+                       if (deaddr)
+                               *deaddr = pc;
+                       buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2);
+               }
+               buf = buf_out (buf, &bufsize, _T("\n"));
+
+               for (uaecptr segpc = oldpc; segpc < pc; segpc++) {
+                       TCHAR segout[256];
+                       if (debugmem_get_symbol(segpc, segout, sizeof(segout) / sizeof(TCHAR))) {
+                               _tcscat(segout, _T(":\n"));
+                               if (bufsize > _tcslen(segout)) {
+                                       memmove(symbolpos + _tcslen(segout), symbolpos, (_tcslen(symbolpos) + 1) * sizeof(TCHAR));
+                                       memcpy(symbolpos, segout, _tcslen(segout) * sizeof(TCHAR));
+                                       bufsize -= _tcslen(segout);
+                                       buf += _tcslen(segout);
+                                       symbolpos += _tcslen(segout);
+                               }
+                       }
+               }
+
+               int srcline = -1;
+               for (uaecptr segpc = oldpc; segpc < pc; segpc++) {
+                       TCHAR sourceout[256];
+                       int line = debugmem_get_sourceline(segpc, sourceout, sizeof(sourceout) / sizeof(TCHAR));
+                       if (line < 0)
+                               break;
+                       if (srcline != line) {
+                               if (srcline < 0)
+                                       buf = buf_out(buf, &bufsize, _T("\n"));
+                               buf = buf_out(buf, &bufsize, sourceout);
+                               srcline = line;
+                       }
+               }
+               if (srcline >= 0) {
+                       buf = buf_out(buf, &bufsize, _T("\n"));
+               }
+
+               if (illegal)
+                       pc =  m68kpc_illg;
+       }
+       if (nextpc)
+               *nextpc = pc;
+       if (seaddr)
+               *seaddr = seaddr2;
+       if (deaddr)
+               *deaddr = deaddr2;
+}
+
+
+/*************************************************************
+Disasm the m68kcode at the given address into instrname
+and instrcode
+*************************************************************/
+void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc, uaecptr lastpc)
+{
+       TCHAR *ccpt;
+       uae_u32 opcode;
+       struct mnemolookup *lookup;
+       struct instr *dp;
+       uaecptr pc, oldpc;
+
+       pc = oldpc = addr;
+       opcode = get_word_debug (pc);
+       if (cpufunctbl[opcode] == op_illg_1) {
+               opcode = 0x4AFC;
+       }
+       dp = table68k + opcode;
+       for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
+
+       pc += 2;
+
+       _tcscpy (instrname, lookup->name);
+       ccpt = _tcsstr (instrname, _T("cc"));
+       if (ccpt != 0) {
+               _tcsncpy (ccpt, ccnames[dp->cc], 2);
+       }
+       switch (dp->size){
+       case sz_byte: _tcscat (instrname, _T(".B ")); break;
+       case sz_word: _tcscat (instrname, _T(".W ")); break;
+       case sz_long: _tcscat (instrname, _T(".L ")); break;
+       default: _tcscat (instrname, _T("   ")); break;
+       }
+
+       if (dp->suse) {
+               pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
+       }
+       if (dp->suse && dp->duse)
+               _tcscat (instrname, _T(","));
+       if (dp->duse) {
+               pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
+       }
+       if (instrcode)
+       {
+               int i;
+               for (i = 0; i < (pc - oldpc) / 2; i++)
+               {
+                       _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
+                       instrcode += _tcslen (instrcode);
+               }
+       }
+       if (nextpc)
+               *nextpc = pc;
+}
diff --git a/fpp.cpp b/fpp.cpp
index 54d285a1881ceee6fb77e84a4a300da05ef28e35..3372f60d0385bafa42090f403d87ea4433f4eb82 100644 (file)
--- a/fpp.cpp
+++ b/fpp.cpp
 #include "cpummu030.h"
 #include "debug.h"
 
+#ifndef CPU_TESTER
+#define SUPPORT_MMU 1
+#else
+#define SUPPORT_MMU 0
+#endif
+
 #include "softfloat/softfloat.h"
 
 // global variable for JIT FPU
@@ -989,7 +995,7 @@ static void fp_unimp_datatype(uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr
                                fsave_data.stag = 7; // undocumented
                        } else {
                                fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]);
-                               fsave_data.stag = get_ftag(src, (opclass == 0) ? -1U : size);
+                               fsave_data.stag = get_ftag(src, (opclass == 0) ? 0xffffffff : size);
                                if (fsave_data.stag == 5) {
                                        fsave_data.et[0] = (size == 1) ? 0x3f800000 : 0x3c000000; // exponent for denormalized single and double
                                }
@@ -1046,11 +1052,12 @@ static bool fault_if_no_fpu (uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr
 #if EXCEPTION_FPP
                write_log (_T("no FPU: %04X-%04X PC=%08X\n"), opcode, extra, oldpc);
 #endif
+#if SUPPORT_MMU
                if (fpu_mmu_fixup) {
                        m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
                        mmufixup[0].reg = -1;
-
                }
+#endif
                fpu_op_illg(opcode, ea, oldpc);
                return true;
        }
@@ -1358,17 +1365,21 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old
                        break;
                case 3: // (An)+
                        // Also needed by fault_if_no_fpu 
+#if SUPPORT_MMU
                        mmufixup[0].reg = reg;
                        mmufixup[0].value = m68k_areg (regs, reg);
                        fpu_mmu_fixup = true;
+#endif
                        ad = m68k_areg (regs, reg);
                        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
                        break;
                case 4: // -(An)
                        // Also needed by fault_if_no_fpu 
+#if SUPPORT_MMU
                        mmufixup[0].reg = reg;
                        mmufixup[0].value = m68k_areg (regs, reg);
                        fpu_mmu_fixup = true;
+#endif
                        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
                        ad = m68k_areg (regs, reg);
                        // 68060 no fpu -(an): EA points to -4, not -12 if extended precision
@@ -1576,17 +1587,21 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o
                        break;
                case 3: // (An)+
                        // Also needed by fault_if_no_fpu 
+#if SUPPORT_MMU
                        mmufixup[0].reg = reg;
                        mmufixup[0].value = m68k_areg (regs, reg);
                        fpu_mmu_fixup = true;
+#endif
                        ad = m68k_areg (regs, reg);
                        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
                        break;
                case 4: // -(An)
                        // Also needed by fault_if_no_fpu 
+#if SUPPORT_MMU
                        mmufixup[0].reg = reg;
                        mmufixup[0].value = m68k_areg (regs, reg);
                        fpu_mmu_fixup = true;
+#endif
                        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
                        ad = m68k_areg (regs, reg);
                        // 68060 no fpu -(an): EA points to -4, not -12 if extended precision
@@ -1866,7 +1881,7 @@ void fpuop_dbcc (uae_u32 opcode, uae_u16 extra)
        if (fault_if_no_6888x (opcode, extra, pc - 4))
                return;
 
-       disp = (uae_s32) (uae_s16) x_cp_next_iword ();
+       disp = (uae_s32) (uae_s16)x_cp_next_iword();
        if (fault_if_no_fpu_u (opcode, extra, pc + disp, pc - 4))
                return;
        regs.fpiar = pc - 4;
@@ -2432,6 +2447,7 @@ static uaecptr fmovem2mem (uaecptr ad, uae_u32 list, int incr, int regdir)
 
        // 68030 MMU state saving is annoying!
        if (currprefs.mmu_model == 68030) {
+#if SUPPORT_MMU
                int idx = 0;
                uae_u32 wrd[3];
                mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM1;
@@ -2461,6 +2477,7 @@ static uaecptr fmovem2mem (uaecptr ad, uae_u32 list, int incr, int regdir)
                        }
                        list <<= 1;
                }
+#endif
        } else {
                for (int r = 0; r < 8; r++) {
                        uae_u32 wrd1, wrd2, wrd3;
@@ -2489,6 +2506,7 @@ static uaecptr fmovem2fpp (uaecptr ad, uae_u32 list, int incr, int regdir)
        int reg;
 
        if (currprefs.mmu_model == 68030) {
+#if SUPPORT_MMU
                uae_u32 wrd[3];
                int idx = 0;
                mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM1 | MMU030_STATEFLAG1_FMOVEM;
@@ -2522,6 +2540,7 @@ static uaecptr fmovem2fpp (uaecptr ad, uae_u32 list, int incr, int regdir)
                        }
                        list <<= 1;
                }
+#endif
        } else {
                for (int r = 0; r < 8; r++) {
                        uae_u32 wrd1, wrd2, wrd3;
@@ -3083,9 +3102,11 @@ void fpuop_arithmetic (uae_u32 opcode, uae_u16 extra)
        write_log(_T("FPUOP %04x %04x PC=%08x\n"), opcode, extra, M68K_GETPC);
 #endif
        fpuop_arithmetic2 (opcode, extra);
+#if SUPPORT_MMU
        if (fpu_mmu_fixup) {
                mmufixup[0].reg = -1;
        }
+#endif
 }
 
 static void get_features(void)
@@ -3099,6 +3120,8 @@ void fpu_clearstatus(void)
        fpp_clear_status();
 }
 
+#ifndef CPU_TESTER
+
 void fpu_modechange(void)
 {
        uae_u32 temp_ext[8][3];
@@ -3131,6 +3154,8 @@ void fpu_modechange(void)
        }
 }
 
+#endif
+
 #if FPU_TEST
 
 static void fpu_test(void)
@@ -3149,6 +3174,7 @@ static void fpu_test(void)
 
 void fpu_reset (void)
 {
+#ifndef CPU_TESTER
        currprefs.fpu_mode = changed_prefs.fpu_mode;
        if (currprefs.fpu_mode > 0) {
                fp_init_softfloat(currprefs.fpu_model);
@@ -3170,10 +3196,15 @@ void fpu_reset (void)
 #ifdef MSVC_LONG_DOUBLE
        init_fpucw_x87_80();
 #endif
+#endif
+#else
+       fp_init_softfloat(currprefs.fpu_model);
+       use_long_double = false;
 #endif
 
        regs.fpiar = 0;
        regs.fpu_exp_state = 0;
+       regs.fp_unimp_pend = 0;
        get_features();
        fpp_set_fpcr (0);
        fpp_set_fpsr (0);
@@ -3188,6 +3219,8 @@ void fpu_reset (void)
 
 }
 
+#ifndef CPU_TESTER
+
 uae_u8 *restore_fpu (uae_u8 *src)
 {
        uae_u32 w1, w2, w3;
@@ -3326,3 +3359,5 @@ uae_u8 *save_fpu (int *len, uae_u8 *dstptr)
        *len = dst - dstbak;
        return dstbak;
 }
+
+#endif
index 07105e86df2b42accc78ec8fa3604106e7737e01..5e5622cfa755ddc4f7fbf27fdb1cc2c166642614 100644 (file)
@@ -18,6 +18,8 @@
 * Copyright 1995, 1996, 1997, 1998, 1999, 2000 Bernd Schmidt
 */
 
+#define CPU_TESTER 0
+
 #include "sysconfig.h"
 #include "sysdeps.h"
 #include <ctype.h>
@@ -44,6 +46,8 @@ static int using_ce;
 static int using_tracer;
 static int using_waitstates;
 static int using_simple_cycles;
+static int using_debugmem;
+static int using_test;
 static int cpu_level, cpu_generic;
 static int count_read, count_write, count_cycles, count_ncycles;
 static int count_cycles_ce020;
@@ -814,7 +818,7 @@ static void setpc (const char *format, ...)
 
        if (using_mmu)
                printf("\tm68k_setpci(%s);\n", buffer);
-       else if (using_prefetch || using_prefetch_020)
+       else if (using_prefetch || using_prefetch_020 || using_test)
                printf ("\tm68k_setpci_j(%s);\n", buffer);
        else
                printf ("\tm68k_setpc_j(%s);\n", buffer);
@@ -829,7 +833,7 @@ static void incpc (const char *format, ...)
        _vsnprintf (buffer, 1000 - 1, format, parms);
        va_end (parms);
 
-       if (using_mmu || using_prefetch || using_prefetch_020)
+       if (using_mmu || using_prefetch || using_prefetch_020 || using_test)
                printf ("\tm68k_incpci (%s);\n", buffer);
        else
                printf ("\tm68k_incpc (%s);\n", buffer);
@@ -2337,14 +2341,13 @@ static void genmovemel_ce (uae_u16 opcode)
        int size = table68k[opcode].size == sz_long ? 4 : 2;
        printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0));
        printf ("\tuae_u32 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
-       printf ("\tuae_u32 v;\n");
        if (table68k[opcode].dmode == Ad8r || table68k[opcode].dmode == PC8r)
                addcycles000 (2);
        genamode (NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, GF_AA | GF_MOVE);
        start_brace ();
        if (table68k[opcode].size == sz_long) {
                printf ("\twhile (dmask) {\n");
-               printf ("\t\tv = %s (srca) << 16;\n", srcw);
+               printf ("\t\tuae_u32 v = %s (srca) << 16;\n", srcw);
                printf ("\t\tv |= %s (srca + 2);\n", srcw);
                printf ("\t\tm68k_dreg (regs, movem_index1[dmask]) = v;\n");
                printf ("\t\tsrca += %d;\n", size);
@@ -2352,7 +2355,7 @@ static void genmovemel_ce (uae_u16 opcode)
                addcycles000_nonce("\t\t", 8);
                printf ("\t}\n");
                printf ("\twhile (amask) {\n");
-               printf ("\t\tv = %s (srca) << 16;\n", srcw);
+               printf ("\t\tuae_u32 v = %s (srca) << 16;\n", srcw);
                printf ("\t\tv |= %s (srca + 2);\n", srcw);
                printf ("\t\tm68k_areg (regs, movem_index1[amask]) = v;\n");
                printf ("\t\tsrca += %d;\n", size);
@@ -3187,6 +3190,21 @@ static void resetvars (void)
                        dstb = "put_byte";
                }
        }
+
+       if (using_test) {
+               prefetch_word = "get_word_test_prefetch";
+               srcwi = "get_wordi_test";
+               srcl = "get_long_test";
+               dstl = "put_long_test";
+               srcw = "get_word_test";
+               dstw = "put_word_test";
+               srcb = "get_byte_test";
+               dstb = "put_byte_test";
+               do_cycles = "do_cycles_test";
+               getpc = "m68k_getpci()";
+               disp000 = "get_disp_ea_test";
+       }
+
        if (!dstld)
                dstld = dstl;
        if (!dstwd)
@@ -3771,6 +3789,7 @@ static void gen_opcode (unsigned int opcode)
                                int dualprefetch = curi->dmode == absl && (curi->smode != Dreg && curi->smode != Areg && curi->smode != imm);
 
                                genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+
                                flags = GF_MOVE | GF_APDI;
                                //if (curi->size == sz_long && (curi->smode == Dreg || curi->smode == Areg))
                                //      flags &= ~GF_APDI;
@@ -3784,8 +3803,9 @@ static void gen_opcode (unsigned int opcode)
                                        fill_prefetch_next ();
                                        prefetch_done = 1;
                                }
+
                                if (curi->mnemo == i_MOVE)
-                                       genflags (flag_logical, curi->size, "src", "", "");
+                                       genflags(flag_logical, curi->size, "src", "", "");
 
                                if (curi->size == sz_long) {
                                        if ((curi->dmode == Ad16 || curi->dmode == PC16) && curi->smode == imm) {
@@ -3940,9 +3960,9 @@ static void gen_opcode (unsigned int opcode)
                        printf("\tuae_u16 sr = src;\n");
                }
                // STOP undocumented features:
-               // if SR is not set:
+               // if new SR S-bit is not set:
                // 68000 (68010?): Update SR, increase PC and then cause privilege violation exception (handled in newcpu)
-               // 68000 (68010?): Traced STOP also runs 4 cycles faster.
+               // 68000 (68010?): Traced STOP runs 4 cycles faster.
                // 68020 68030: STOP works normally
                // 68040 68060: Immediate privilege violation exception
                if ((cpu_level == 0 || cpu_level == 1) && using_ce) {
@@ -3989,7 +4009,9 @@ static void gen_opcode (unsigned int opcode)
                        printf ("\t\tgoto %s;\n", endlabelstr);
                        printf ("\t}\n");
                        setpc ("pc");
-                       printf("\tbranch_stack_pop_rte(oldpc);\n");
+                       if (using_debugmem) {
+                               printf("\tbranch_stack_pop_rte(oldpc);\n");
+                       }
                        makefromsr();
                } else if (cpu_level == 1 && using_prefetch) {
                        // 68010
@@ -4019,7 +4041,9 @@ static void gen_opcode (unsigned int opcode)
                        printf ("\t\tgoto %s;\n", endlabelstr);
                        printf ("\t}\n");
                    setpc ("newpc");
-                       printf("\tbranch_stack_pop_rte(oldpc);\n");
+                       if (using_debugmem) {
+                               printf("\tbranch_stack_pop_rte(oldpc);\n");
+                       }
                        check_ipl ();
                    need_endlabel = 1;
                } else {
@@ -4093,7 +4117,9 @@ static void gen_opcode (unsigned int opcode)
                        printf ("\t\tgoto %s;\n", endlabelstr);
                        printf ("\t}\n");
                    setpc ("newpc");
-                       printf("\tbranch_stack_pop_rte(oldpc);\n");
+                       if (using_debugmem) {
+                               printf("\tbranch_stack_pop_rte(oldpc);\n");
+                       }
                        check_ipl ();
                    need_endlabel = 1;
                }
@@ -4173,7 +4199,7 @@ static void gen_opcode (unsigned int opcode)
                        printf("\t\tgoto %s;\n", endlabelstr);
                        printf("\t}\n");
                }
-               if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce) {
+               if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce && !using_test) {
                        printf("\tm68k_do_rtsi_jit ();\n");
                } else if (using_mmu) {
                        printf ("\tm68k_do_rts_mmu%s ();\n", mmu_postfix);
@@ -4190,8 +4216,10 @@ static void gen_opcode (unsigned int opcode)
                } else {
                        printf ("\tm68k_do_rts ();\n");
                }
-               printf("\tif (debugmem_trace)\n");
-               printf("\t\tbranch_stack_pop_rts(pc);\n");
+               if (using_debugmem) {
+                       printf("\tif (debugmem_trace)\n");
+                       printf("\t\tbranch_stack_pop_rts(pc);\n");
+               }
            printf ("\tif (%s & 1) {\n", getpc);
                printf ("\t\tuaecptr faultpc = %s;\n", getpc);
                setpc ("pc");
@@ -4277,8 +4305,10 @@ static void gen_opcode (unsigned int opcode)
                        } else {
                                printf ("\t%s (m68k_areg (regs, 7), nextpc);\n", dstl);
                        }
-                       printf("\tif (debugmem_trace)\n");
-                       printf("\t\tbranch_stack_push(oldpc, nextpc);\n");
+                       if (using_debugmem) {
+                               printf("\tif (debugmem_trace)\n");
+                               printf("\t\tbranch_stack_push(oldpc, nextpc);\n");
+                       }
                }
                count_write += 2;
                fill_prefetch_full_020 ();
@@ -4336,7 +4366,7 @@ static void gen_opcode (unsigned int opcode)
                addcycles000 (2);
                printf("\tuaecptr oldpc = %s;\n", getpc);
                printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset);
-               if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce) {
+               if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce && !using_test) {
                        printf("\tm68k_do_bsri_jit (nextpc, s);\n");
                } else if (using_mmu) {
                        printf ("\tm68k_do_bsr_mmu%s (nextpc, s);\n", mmu_postfix);
@@ -4351,8 +4381,10 @@ static void gen_opcode (unsigned int opcode)
                } else {
                        printf ("\tm68k_do_bsr (nextpc, s);\n");
                }
-               printf("\tif (debugmem_trace)\n");
-               printf("\t\tbranch_stack_push(oldpc, nextpc);\n");
+               if (using_debugmem) {
+                       printf("\tif (debugmem_trace)\n");
+                       printf("\t\tbranch_stack_push(oldpc, nextpc);\n");
+               }
                count_write += 2;
                clear_m68k_offset();
                fill_prefetch_full ();
@@ -4708,7 +4740,7 @@ bccl_not68020:
                printf ("\tcnt &= 63;\n");
                printf ("\tCLEAR_CZNV ();\n");
                printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
-               printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size));
+               printf ("\t\tval = %s & (uae_u32)(0 - sign);\n", bit_mask (curi->size));
                printf ("\t\tSET_CFLG (sign);\n");
                duplicate_carry (1);
                if (source_is_imm1_8 (curi))
@@ -4719,7 +4751,7 @@ bccl_not68020:
                printf ("\t\tSET_CFLG (val & 1);\n");
                duplicate_carry (1);
                printf ("\t\tval >>= 1;\n");
-               printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n",
+               printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)(0 - sign);\n",
                        bit_mask (curi->size),
                        bit_size (curi->size));
                printf ("\t\tval &= %s;\n", bit_mask (curi->size));
@@ -5570,14 +5602,15 @@ bccl_not68020:
                {
                        if ((opcode & 0xfff8) == 0xf620) {
                                /* MOVE16 (Ax)+,(Ay)+ */
-                               printf ("\tuae_u32 v[4];\n");
                                printf ("\tuaecptr mems = m68k_areg (regs, srcreg) & ~15, memd;\n");
                                printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword (0));
                                printf ("\tmemd = m68k_areg (regs, dstreg) & ~15;\n");
                                if (using_mmu >= 68040) {
+                                       printf("\tuae_u32 v[4];\n");
                                        printf ("\tget_move16_mmu (mems, v);\n");
                                        printf ("\tput_move16_mmu (memd, v);\n");
                                } else {
+                                       printf("\tuae_u32 v[4];\n");
                                        printf ("\tv[0] = %s (mems);\n", srcl);
                                        printf ("\tv[1] = %s (mems + 4);\n", srcl);
                                        printf ("\tv[2] = %s (mems + 8);\n", srcl);
@@ -5592,18 +5625,19 @@ bccl_not68020:
                                printf ("\tm68k_areg (regs, dstreg) += 16;\n");
                        } else {
                                /* Other variants */
-                               printf ("\tuae_u32 v[4];\n");
                                genamode (curi, curi->smode, "srcreg", curi->size, "mems", 0, 2, 0);
                                genamode (curi, curi->dmode, "dstreg", curi->size, "memd", 0, 2, 0);
                                if (using_mmu == 68040) {
                                        printf ("\tget_move16_mmu (memsa, mmu040_move16);\n");
                                        printf ("\tput_move16_mmu (memda, mmu040_move16);\n");
                                } else if (using_mmu == 68060) {
+                                       printf("\tuae_u32 v[4];\n");
                                        printf ("\tget_move16_mmu (memsa, v);\n");
                                        printf ("\tput_move16_mmu (memda, v);\n");
                                } else {
                                        printf ("\tmemsa &= ~15;\n");
                                        printf ("\tmemda &= ~15;\n");
+                                       printf("\tuae_u32 v[4];\n");
                                        printf ("\tv[0] = %s (memsa);\n", srcl);
                                        printf ("\tv[1] = %s (memsa + 4);\n", srcl);
                                        printf ("\tv[2] = %s (memsa + 8);\n", srcl);
@@ -6043,6 +6077,70 @@ static void generate_func (const char *extra)
                fprintf (stblfile, "{ 0, 0 }};\n");
 }
 
+#if CPU_TESTER
+
+static void generate_cpu_test(int mode)
+{
+       char fname[100];
+       const char *extra = "_test", *extraup;
+       int rp;
+       int id = 90 + mode;
+
+       using_tracer = 0;
+       extraup = "";
+       postfix = id;
+
+       fprintf(stblfile, "#ifdef CPUEMU_%d%s\n", postfix, extraup);
+       sprintf(fname, "cpuemu_%d%s.cpp", postfix, extra);
+       if (freopen(fname, "wb", stdout) == NULL) {
+               abort();
+       }
+
+       using_exception_3 = 1;
+       using_prefetch = 0;
+       using_prefetch_020 = 0;
+       using_ce = 0;
+       using_ce020 = 0;
+       using_mmu = 0;
+       using_waitstates = 0;
+       memory_cycle_cnt = 4;
+       mmu_postfix = "";
+       xfc_postfix = "";
+       using_simple_cycles = 0;
+       using_indirect = 1;
+       cpu_generic = false;
+
+       cpu_level = 0;
+       using_prefetch = 1;
+       using_exception_3 = 1;
+       using_simple_cycles = 1;
+
+       if (mode == 1) {
+               cpu_level = 1;
+       } else if (mode == 2) {
+               cpu_level = 2;
+               using_prefetch = 0;
+               using_simple_cycles = 0;
+       }
+
+
+       read_counts();
+       for (rp = 0; rp < nr_cpuop_funcs; rp++)
+               opcode_next_clev[rp] = cpu_level;
+
+       printf("#include \"cputest.h\"\n");
+       if (!mode) {
+               fprintf(stblfile, "#include \"cputest.h\"\n");
+       }
+
+       fprintf(stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d%s)[] = {\n", postfix, extra);
+       endlabelno = id;
+       generate_func(extra);
+       fprintf(stblfile, "#endif /* CPUEMU_%d%s */\n", postfix, extraup);
+}
+
+#endif
+
 static void generate_cpu (int id, int mode)
 {
        char fname[100];
@@ -6232,8 +6330,6 @@ static void generate_cpu (int id, int mode)
 
 int main(int argc, char *argv[])
 {
-       int i;
-
        read_table68k ();
        do_merges ();
 
@@ -6247,18 +6343,34 @@ int main(int argc, char *argv[])
        * 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");
+#if CPU_TESTER
 
-       stblfile = fopen ("cpustbl.cpp", "wb");
-       generate_includes (stblfile, 0);
+       using_test = 1;
+       headerfile = fopen("cputbl_test.h", "wb");
+       stblfile = fopen("cpustbl_test.cpp", "wb");
+       generate_stbl = 1;
+       generate_cpu_test(0);
+       generate_cpu_test(1);
+       generate_cpu_test(2);
 
-       for (i = 0; i <= 55; i++) {
+#else
+
+       using_debugmem = 1;
+
+       headerfile = fopen("cputbl.h", "wb");
+
+       stblfile = fopen("cpustbl.cpp", "wb");
+       generate_includes(stblfile, 0);
+
+       for (int i = 0; i <= 55; i++) {
                if ((i >= 6 && i < 11) || (i > 14 && i < 20) || (i > 25 && i < 31) || (i > 35 && i < 40))
                        continue;
                generate_stbl = 1;
                generate_cpu (i, 0);
        }
 
+#endif
+
        free (table68k);
        return 0;
 }
diff --git a/include/cputest.h b/include/cputest.h
new file mode 100644 (file)
index 0000000..29cdcda
--- /dev/null
@@ -0,0 +1,58 @@
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "options.h"
+#include "memory.h"
+#include "newcpu.h"
+
+#include "cputest/cputest_defines.h"
+
+
+typedef uae_u32 REGPARAM3 cpuop_func(uae_u32) REGPARAM;
+
+#include "cputbl_test.h"
+
+#define CPUFUNC(x) x##_ff
+#define SET_CFLG_ALWAYS(x) SET_CFLG(x)
+#define SET_NFLG_ALWAYS(x) SET_NFLG(x)
+
+#define m68k_dreg(r,num) ((r).regs[(num)])
+#define m68k_areg(r,num) (((r).regs + 8)[(num)])
+
+int cctrue(int);
+
+extern const int areg_byteinc[];
+extern const int imm8_table[];
+
+extern const struct cputbl op_smalltbl_90_test_ff[];
+extern const struct cputbl op_smalltbl_91_test_ff[];
+extern const struct cputbl op_smalltbl_92_test_ff[];
+
+extern struct flag_struct regflags;
+
+extern int movem_index1[256];
+extern int movem_index2[256];
+extern int movem_next[256];
+
+uae_u16 get_word_test_prefetch(int);
+
+void put_byte_test(uaecptr, uae_u32);
+void put_word_test(uaecptr, uae_u32);
+void put_long_test(uaecptr, uae_u32);
+
+uae_u32 get_byte_test(uaecptr);
+uae_u32 get_word_test(uaecptr);
+uae_u32 get_long_test(uaecptr);
+
+uae_u32 get_disp_ea_test(uae_u32, uae_u32);
+void m68k_incpci(int);
+uaecptr m68k_getpci(void);
+void m68k_setpci_j(uaecptr);
+void m68k_do_rtsi(void);
+void m68k_do_bsri(uaecptr, uae_s32);
+
+void m68k_setstopped(void);
+void check_t0_trace(void);
+
+void cpureset(void);
diff --git a/include/disasm.h b/include/disasm.h
new file mode 100644 (file)
index 0000000..22e79fa
--- /dev/null
@@ -0,0 +1,10 @@
+uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode);
+uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name);
+void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc, int safemode);
+void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc, uaecptr lastpc);
+uae_u32 REGPARAM2 op_illg_1(uae_u32 opcode);
+uae_u32 REGPARAM2 op_unimpl_1(uae_u32 opcode);
+
+extern struct cpum2c m2cregs[];
+extern const TCHAR *fpuopcodes[];
+extern const TCHAR *fpsizes[];
\ No newline at end of file
index 8a7c891538856e089f462bff83f2ac4885700e7d..fb473b486b08796944995c7d4e71fc69697683b9 100644 (file)
@@ -552,6 +552,52 @@ STATIC_INLINE uae_u32 get_wordi(uaecptr addr)
        return memory_get_wordi(addr);
 }
 
+// do split memory access if it can cross memory banks
+STATIC_INLINE uae_u32 get_long_compatible(uaecptr addr)
+{
+       if ((addr &0xffff) < 0xfffd) {
+               return memory_get_long(addr);
+       } else if (addr & 1) {
+               uae_u8 v0 = memory_get_byte(addr + 0);
+               uae_u16 v1 = memory_get_word(addr + 1);
+               uae_u8 v3 = memory_get_byte(addr + 3);
+               return (v0 << 24) | (v1 << 8) | (v3 << 0);
+       } else {
+               uae_u16 v0 = memory_get_word(addr + 0);
+               uae_u16 v1 = memory_get_word(addr + 2);
+               return (v0 << 16) | (v1 << 0);
+       }
+}
+STATIC_INLINE uae_u32 get_word_compatible(uaecptr addr)
+{
+       if ((addr & 0xffff) < 0xffff) {
+               return memory_get_word(addr);
+       } else {
+               uae_u8 v0 = memory_get_byte(addr + 0);
+               uae_u8 v1 = memory_get_byte(addr + 1);
+               return (v0 << 8) | (v1 << 0);
+       }
+}
+STATIC_INLINE uae_u32 get_byte_compatible(uaecptr addr)
+{
+       return memory_get_byte(addr);
+}
+STATIC_INLINE uae_u32 get_longi_compatible(uaecptr addr)
+{
+       if ((addr & 0xffff) < 0xfffd) {
+               return memory_get_longi(addr);
+       } else {
+               uae_u16 v0 = memory_get_wordi(addr + 0);
+               uae_u16 v1 = memory_get_wordi(addr + 2);
+               return (v0 << 16) | (v1 << 0);
+       }
+}
+STATIC_INLINE uae_u32 get_wordi_compatible(uaecptr addr)
+{
+       return memory_get_wordi(addr);
+}
+
+
 STATIC_INLINE uae_u32 get_long_jit(uaecptr addr)
 {
 #ifdef JIT
@@ -640,6 +686,35 @@ STATIC_INLINE void put_byte (uaecptr addr, uae_u32 b)
        memory_put_byte(addr, b);
 }
 
+// do split memory access if it can cross memory banks
+STATIC_INLINE void put_long_compatible(uaecptr addr, uae_u32 l)
+{
+       if ((addr & 0xffff) < 0xfffd) {
+               memory_put_long(addr, l);
+       } else if (addr & 1) {
+               memory_put_byte(addr + 0, l >> 24);
+               memory_put_word(addr + 1, l >>  8);
+               memory_put_byte(addr + 3, l >>  0);
+       } else {
+               memory_put_word(addr + 0, l >> 16);
+               memory_put_word(addr + 2, l >>  0);
+       }
+}
+STATIC_INLINE void put_word_compatible(uaecptr addr, uae_u32 w)
+{
+       if ((addr & 0xffff) < 0xffff) {
+               memory_put_word(addr, w);
+       } else {
+               memory_put_byte(addr + 0, w >> 8);
+               memory_put_byte(addr + 1, w >> 0);
+       }
+}
+STATIC_INLINE void put_byte_compatible(uaecptr addr, uae_u32 b)
+{
+       memory_put_byte(addr, b);
+}
+
+
 STATIC_INLINE void put_long_jit(uaecptr addr, uae_u32 l)
 {
 #ifdef JIT
index 8988eb079281e4280f17b237116b9509ab803f43..b7dcfb7421495bd92b5198ac7d5f20694133d6b8 100644 (file)
@@ -85,7 +85,7 @@ struct comptbl {
 #endif
 
 extern uae_u32 REGPARAM3 op_illg (uae_u32) REGPARAM;
-extern void REGPARAM3 op_unimpl (uae_u16) REGPARAM;
+extern void REGPARAM3 op_unimpl (uae_u32) REGPARAM;
 
 typedef uae_u8 flagtype;
 
index 4fc4f2ec3ae125b886674e069773c20974b024bb..86639dee96f21dca8218f31debc4e25cab49b049 100644 (file)
@@ -105,7 +105,7 @@ extern struct instr {
     unsigned int dmode:5;
     unsigned int suse:1;
     unsigned int duse:1;
-    unsigned int unused1:1;
+    unsigned int ccuse:1;
     unsigned int clev:3, unimpclev:3;
     unsigned int isjmp:1;
     unsigned int unused2:1;
diff --git a/ini.cpp b/ini.cpp
index f4d49d79f22cae6948e203e2ae94c509e192f6e7..bd68b8fdf51bf865104eab1d34db3d84d16995b9 100644 (file)
--- a/ini.cpp
+++ b/ini.cpp
@@ -347,7 +347,12 @@ bool ini_getval_multi(struct ini_data *ini, const TCHAR *section, const TCHAR *k
        TCHAR *out2 = NULL;
        if (!ini_getstring_multi(ini, section, key, &out2, ctx))
                return false;
-       *v = _tstol(out2);
+       if (_tcslen(out2) > 2 && out2[0] == '0' && _totupper(out2[1]) == 'X') {
+               TCHAR *endptr;
+               *v = _tcstol(out2 + 2, &endptr, 16);
+       } else {
+               *v = _tstol(out2);
+       }
        xfree(out2);
        return true;
 }
index 8a6d497dc17f21764528a273b78790e7e626320e..8b89290c409357396f46f47f05a6221f8184a67e 100644 (file)
@@ -26,6 +26,7 @@
 #include "memory.h"
 #include "custom.h"
 #include "newcpu.h"
+#include "disasm.h"
 #include "cpummu.h"
 #include "cpummu030.h"
 #include "cpu_prefetch.h"
@@ -988,12 +989,12 @@ static void set_x_funcs (void)
                        x_get_ibyte = get_iibyte;
                        x_next_iword = NULL;
                        x_next_ilong = NULL;
-                       x_put_long = put_long;
-                       x_put_word = put_word;
-                       x_put_byte = put_byte;
-                       x_get_long = get_long;
-                       x_get_word = get_word;
-                       x_get_byte = get_byte;
+                       x_put_long = put_long_compatible;
+                       x_put_word = put_word_compatible;
+                       x_put_byte = put_byte_compatible;
+                       x_get_long = get_long_compatible;
+                       x_get_word = get_word_compatible;
+                       x_get_byte = get_byte_compatible;
                        x_do_cycles = do_cycles;
                        x_do_cycles_pre = do_cycles;
                        x_do_cycles_post = do_cycles_post;
@@ -1099,12 +1100,12 @@ static void set_x_funcs (void)
                                x_get_ibyte = NULL;
                                x_next_iword = next_iword_020_prefetch;
                                x_next_ilong = next_ilong_020_prefetch;
-                               x_put_long = put_long;
-                               x_put_word = put_word;
-                               x_put_byte = put_byte;
-                               x_get_long = get_long;
-                               x_get_word = get_word;
-                               x_get_byte = get_byte;
+                               x_put_long = put_long_compatible;
+                               x_put_word = put_word_compatible;
+                               x_put_byte = put_byte_compatible;
+                               x_get_long = get_long_compatible;
+                               x_get_word = get_word_compatible;
+                               x_get_byte = get_byte_compatible;
                                x_do_cycles = do_cycles;
                                x_do_cycles_pre = do_cycles;
                                x_do_cycles_post = do_cycles_post;
@@ -1720,12 +1721,12 @@ STATIC_INLINE void count_instr (unsigned int opcode)
 {
 }
 
-static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode)
+uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode)
 {
        op_illg (opcode);
        return 4;
 }
-static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
+uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
 {
        if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060)
                op_illg (opcode);
@@ -1755,7 +1756,7 @@ static void build_cpufunctbl (void)
 {
        int i, opcnt;
        unsigned long opcode;
-       const struct cputbl *tbl = 0;
+       const struct cputbl *tbl = NULL;
        int lvl, mode;
 
        if (!currprefs.cachesize) {
@@ -2126,579 +2127,6 @@ struct regstruct regs, mmu_backup_regs;
 struct flag_struct regflags;
 static int m68kpc_offset;
 
-static const TCHAR *fpsizes[] = {
-       _T("L"),
-       _T("S"),
-       _T("X"),
-       _T("P"),
-       _T("W"),
-       _T("D"),
-       _T("B"),
-       _T("P")
-};
-static const int fpsizeconv[] = {
-       sz_long,
-       sz_single,
-       sz_extended,
-       sz_packed,
-       sz_word,
-       sz_double,
-       sz_byte,
-       sz_packed
-};
-static const int datasizes[] = {
-       1,
-       2,
-       4,
-       4,
-       8,
-       12,
-       12
-};
-
-static void showea_val(TCHAR *buffer, uae_u16 opcode, uaecptr addr, int size)
-{
-       struct mnemolookup *lookup;
-       instr *table = &table68k[opcode];
-
-       if (addr >= 0xe90000 && addr < 0xf00000)
-               goto skip;
-       if (addr >= 0xdff000 && addr < 0xe00000)
-               goto skip;
-
-       for (lookup = lookuptab; lookup->mnemo != table->mnemo; lookup++)
-               ;
-       if (!(lookup->flags & 1))
-               goto skip;
-       buffer += _tcslen(buffer);
-       if (debug_safe_addr(addr, datasizes[size])) {
-               bool cached = false;
-               switch (size)
-               {
-                       case sz_byte:
-                       {
-                               uae_u8 v = get_byte_cache_debug(addr, &cached);
-                               uae_u8 v2 = v;
-                               if (cached)
-                                       v2 = get_byte_debug(addr);
-                               if (v != v2) {
-                                       _stprintf(buffer, _T(" [%02x:%02x]"), v, v2);
-                               } else {
-                                       _stprintf(buffer, _T(" [%s%02x]"), cached ? _T("*") : _T(""), v);
-                               }
-                       }
-                       break;
-                       case sz_word:
-                       {
-                               uae_u16 v = get_word_cache_debug(addr, &cached);
-                               uae_u16 v2 = v;
-                               if (cached)
-                                       v2 = get_word_debug(addr);
-                               if (v != v2) {
-                                       _stprintf(buffer, _T(" [%04x:%04x]"), v, v2);
-                               } else {
-                                       _stprintf(buffer, _T(" [%s%04x]"), cached ? _T("*") : _T(""), v);
-                               }
-                       }
-                       break;
-                       case sz_long:
-                       {
-                               uae_u32 v = get_long_cache_debug(addr, &cached);
-                               uae_u32 v2 = v;
-                               if (cached)
-                                       v2 = get_long_debug(addr);
-                               if (v != v2) {
-                                       _stprintf(buffer, _T(" [%08x:%08x]"), v, v2);
-                               } else {
-                                       _stprintf(buffer, _T(" [%s%08x]"), cached ? _T("*") : _T(""), v);
-                               }
-                       }
-                       break;
-                       case sz_single:
-                       {
-                               fpdata fp;
-                               fpp_to_single(&fp, get_long_debug(addr));
-                               _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
-                       }
-                       break;
-                       case sz_double:
-                       {
-                               fpdata fp;
-                               fpp_to_double(&fp, get_long_debug(addr), get_long_debug(addr + 4));
-                               _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
-                       }
-                       break;
-                       case sz_extended:
-                       {
-                               fpdata fp;
-                               fpp_to_exten(&fp, get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8));
-                               _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0));
-                               break;
-                       }
-                       case sz_packed:
-                               _stprintf(buffer, _T("[%08x%08x%08x]"), get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8));
-                               break;
-               }
-       }
-skip:
-       for (int i = 0; i < size; i++) {
-               TCHAR name[256];
-               if (debugmem_get_symbol(addr + i, name, sizeof(name) / sizeof(TCHAR))) {
-                       _stprintf(buffer + _tcslen(buffer), _T(" %s"), name);
-               }
-       }
-}
-
-static uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name)
-{
-       uaecptr addr;
-       uae_u16 dp;
-       int r;
-       uae_u32 dispreg;
-       uaecptr pc = *pcp;
-       TCHAR mult[20];
-
-       dp = get_iword_debug(pc);
-       pc += 2;
-
-       r = (dp & 0x7000) >> 12; // REGISTER
-
-       dispreg = dp & 0x8000 ? m68k_areg(regs, r) : m68k_dreg(regs, r);
-       if (!(dp & 0x800)) { // W/L
-               dispreg = (uae_s32)(uae_s16)(dispreg);
-       }
-
-       if (currprefs.cpu_model >= 68020) {
-               dispreg <<= (dp >> 9) & 3; // SCALE
-       }
-
-       int m = 1 << ((dp >> 9) & 3);
-       mult[0] = 0;
-       if (m > 1) {
-               _stprintf(mult, _T("*%d"), m);
-       }
-
-       buffer[0] = 0;
-       if ((dp & 0x100) && currprefs.cpu_model >= 68020) {
-               TCHAR dr[20];
-               // Full format extension (68020+)
-               uae_s32 outer = 0, disp = 0;
-               if (dp & 0x80) { // BS (base register suppress)
-                       base = 0;
-                       name = NULL;
-               }
-               _stprintf(dr, _T("%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W');
-               if (dp & 0x40) { // IS (index suppress)
-                       dispreg = 0;
-                       dr[0] = 0;
-               }
-
-               _tcscpy(buffer, _T("("));
-               TCHAR *p = buffer + _tcslen(buffer);
-
-               if (dp & 3) {
-                       // indirect
-                       _stprintf(p, _T("["));
-                       p += _tcslen(p);
-               } else {
-                       // (an,dn,word/long)
-                       if (name) {
-                               _stprintf(p, _T("%s,"), name);
-                               p += _tcslen(p);
-                       }
-                       if (dr[0]) {
-                               _stprintf(p, _T("%s%s,"), dr, mult);
-                               p += _tcslen(p);
-                       }
-               }
-
-               if ((dp & 0x30) == 0x20) { // BD SIZE = 2 (WORD)
-                       disp = (uae_s32)(uae_s16)get_iword_debug(pc);
-                       _stprintf(p, _T("$%04x,"), (uae_s16)disp);
-                       p += _tcslen(p);
-                       pc += 2;
-                       base += disp;
-               } else if ((dp & 0x30) == 0x30) { // BD SIZE = 3 (LONG)
-                       disp = get_ilong_debug(pc);
-                       _stprintf(p, _T("$%08x,"), disp);
-                       p += _tcslen(p);
-                       pc += 4;
-                       base += disp;
-               }
-
-               if (dp & 3) {
-                       if (name) {
-                               _stprintf(p, _T("%s,"), name);
-                               p += _tcslen(p);
-                       }
-
-                       if (!(dp & 0x04)) {
-                               if (dr[0]) {
-                                       _stprintf(p, _T("%s%s,"), dr, mult);
-                                       p += _tcslen(p);
-                               }
-                       }
-
-                       if (p[-1] == ',')
-                               p--;
-                       _stprintf(p, _T("],"));
-                       p += _tcslen(p);
-
-                       if ((dp & 0x04)) {
-                               if (dr[0]) {
-                                       _stprintf(p, _T("%s%s,"), dr, mult);
-                                       p += _tcslen(p);
-                               }
-                       }
-
-               }
-
-               if ((dp & 0x03) == 0x02) {
-                       outer = (uae_s32)(uae_s16)get_iword_debug(pc);
-                       _stprintf(p, _T("$%04x,"), (uae_s16)outer);
-                       p += _tcslen(p);
-                       pc += 2;
-               } else  if ((dp & 0x03) == 0x03) {
-                       outer = get_ilong_debug(pc);
-                       _stprintf(p, _T("$%08x,"), outer);
-                       p += _tcslen(p);
-                       pc += 4;
-               }
-
-               if (p[-1] == ',')
-                       p--;
-               _stprintf(p, _T(")"));
-               p += _tcslen(p);
-
-               if ((dp & 0x4) == 0)
-                       base += dispreg;
-               if (dp & 0x3)
-                       base = get_long_debug(base);
-               if (dp & 0x4)
-                       base += dispreg;
-
-               addr = base + outer;
-
-               _stprintf(p, _T(" == $%08x"), addr);
-               p += _tcslen(p);
-
-       } else {
-               // Brief format extension
-               TCHAR regstr[20];
-               uae_s8 disp8 = dp & 0xFF;
-
-               regstr[0] = 0;
-               _stprintf(regstr, _T(",%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W');
-               addr = base + (uae_s32)((uae_s8)disp8) + dispreg;
-               _stprintf(buffer, _T("(%s%s%s,$%02x) == $%08x"), name, regstr, mult, disp8, addr);
-               if (dp & 0x100) {
-                       _tcscat(buffer, _T(" (68020+)"));
-               }
-       }
-
-       *pcp = pc;
-       return addr;
-}
-
-uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
-{
-       uaecptr addr = pc;
-       uae_s16 disp16;
-       uae_s32 offset = 0;
-       TCHAR buffer[80];
-
-       switch (mode){
-       case Dreg:
-               _stprintf (buffer, _T("D%d"), reg);
-               break;
-       case Areg:
-               _stprintf (buffer, _T("A%d"), reg);
-               break;
-       case Aind:
-               _stprintf (buffer, _T("(A%d)"), reg);
-               addr = regs.regs[reg + 8];
-               showea_val(buffer, opcode, addr, size);
-               break;
-       case Aipi:
-               _stprintf (buffer, _T("(A%d)+"), reg);
-               addr = regs.regs[reg + 8];
-               showea_val(buffer, opcode, addr, size);
-               break;
-       case Apdi:
-               _stprintf (buffer, _T("-(A%d)"), reg);
-               addr = regs.regs[reg + 8];
-               showea_val(buffer, opcode, addr - datasizes[size], size);
-               break;
-       case Ad16:
-               {
-                       TCHAR offtxt[8];
-                       disp16 = get_iword_debug (pc); pc += 2;
-                       if (disp16 < 0)
-                               _stprintf (offtxt, _T("-$%04x"), -disp16);
-                       else
-                               _stprintf (offtxt, _T("$%04x"), disp16);
-                       addr = m68k_areg (regs, reg) + disp16;
-                       _stprintf (buffer, _T("(A%d,%s) == $%08x"), reg, offtxt, addr);
-                       showea_val(buffer, opcode, addr, size);
-               }
-               break;
-       case Ad8r:
-               {
-                       TCHAR name[10];
-                       _stprintf(name, _T("A%d"), reg);
-                       addr = ShowEA_disp(&pc, m68k_areg(regs, reg), buffer, name);
-                       showea_val(buffer, opcode, addr, size);
-               }
-               break;
-       case PC16:
-               disp16 = get_iword_debug (pc); pc += 2;
-               addr += (uae_s16)disp16;
-               _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr);
-               showea_val(buffer, opcode, addr, size);
-               break;
-       case PC8r:
-               {
-                       addr = ShowEA_disp(&pc, addr, buffer, _T("PC"));
-                       showea_val(buffer, opcode, addr, size);
-               }
-               break;
-       case absw:
-               addr = (uae_s32)(uae_s16)get_iword_debug (pc);
-               _stprintf (buffer, _T("$%04x"), (uae_u16)addr);
-               pc += 2;
-               showea_val(buffer, opcode, addr, size);
-               break;
-       case absl:
-               addr = get_ilong_debug (pc);
-               _stprintf (buffer, _T("$%08x"), addr);
-               pc += 4;
-               showea_val(buffer, opcode, addr, size);
-               break;
-       case imm:
-               switch (size){
-               case sz_byte:
-                       _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff));
-                       pc += 2;
-                       break;
-               case sz_word:
-                       _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff));
-                       pc += 2;
-                       break;
-               case sz_long:
-                       _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc)));
-                       pc += 4;
-                       break;
-               case sz_single:
-                       {
-                               fpdata fp;
-                               fpp_to_single(&fp, get_ilong_debug(pc));
-                               _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
-                               pc += 4;
-                       }
-                       break;
-               case sz_double:
-                       {
-                               fpdata fp;
-                               fpp_to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
-                               _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
-                               pc += 8;
-                       }
-                       break;
-               case sz_extended:
-               {
-                       fpdata fp;
-                       fpp_to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
-                       _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0));
-                       pc += 12;
-                       break;
-               }
-               case sz_packed:
-                       _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
-                       pc += 12;
-                       break;
-               default:
-                       break;
-               }
-               break;
-       case imm0:
-               offset = (uae_s32)(uae_s8)get_iword_debug (pc);
-               _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff));
-               addr = pc + 2 + offset;
-               if ((opcode & 0xf000) == 0x6000) {
-                       showea_val(buffer, opcode, addr, 1);
-               }
-               pc += 2;
-               break;
-       case imm1:
-               offset = (uae_s32)(uae_s16)get_iword_debug (pc);
-               buffer[0] = 0;
-               _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff));
-               addr = pc + offset;
-               if ((opcode & 0xf000) == 0x6000) {
-                       showea_val(buffer, opcode, addr, 2);
-               }
-               pc += 2;
-               break;
-       case imm2:
-               offset = (uae_s32)get_ilong_debug (pc);
-               _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
-               addr = pc + offset;
-               if ((opcode & 0xf000) == 0x6000) {
-                       showea_val(buffer, opcode, addr, 4);
-               }
-               pc += 4;
-               break;
-       case immi:
-               offset = (uae_s32)(uae_s8)(reg & 0xff);
-               _stprintf (buffer, _T("#$%02x"), (uae_u8)offset);
-               addr = pc + offset;
-               break;
-       default:
-               break;
-       }
-       if (buf == NULL)
-               f_out (f, _T("%s"), buffer);
-       else
-               _tcscat (buf, buffer);
-       if (eaddr)
-               *eaddr = addr;
-       return pc;
-}
-
-#if 0
-/* The plan is that this will take over the job of exception 3 handling -
-* the CPU emulation functions will just do a longjmp to m68k_go whenever
-* they hit an odd address. */
-static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
-{
-       uae_u16 dp;
-       uae_s8 disp8;
-       uae_s16 disp16;
-       int r;
-       uae_u32 dispreg;
-       uaecptr addr;
-       uae_s32 offset = 0;
-
-       switch (mode){
-       case Dreg:
-               *val = m68k_dreg (regs, reg);
-               return 1;
-       case Areg:
-               *val = m68k_areg (regs, reg);
-               return 1;
-
-       case Aind:
-       case Aipi:
-               addr = m68k_areg (regs, reg);
-               break;
-       case Apdi:
-               addr = m68k_areg (regs, reg);
-               break;
-       case Ad16:
-               disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
-               addr = m68k_areg (regs, reg) + (uae_s16)disp16;
-               break;
-       case Ad8r:
-               addr = m68k_areg (regs, reg);
-d8r_common:
-               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 = (uae_s32)(uae_s16)(dispreg);
-               dispreg <<= (dp >> 9) & 3;
-
-               if (dp & 0x100) {
-                       uae_s32 outer = 0, disp = 0;
-                       uae_s32 base = addr;
-                       if (dp & 0x80) base = 0;
-                       if (dp & 0x40) dispreg = 0;
-                       if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)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 = (uae_s32)(uae_s16)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 = get_long (base);
-                       if (dp & 4) base += dispreg;
-
-                       addr = base + outer;
-               } else {
-                       addr += (uae_s32)((uae_s8)disp8) + dispreg;
-               }
-               break;
-       case PC16:
-               addr = m68k_getpc () + m68kpc_offset;
-               disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
-               addr += (uae_s16)disp16;
-               break;
-       case PC8r:
-               addr = m68k_getpc () + m68kpc_offset;
-               goto d8r_common;
-       case absw:
-               addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
-               m68kpc_offset += 2;
-               break;
-       case absl:
-               addr = get_ilong_1 (m68kpc_offset);
-               m68kpc_offset += 4;
-               break;
-       case imm:
-               switch (size){
-               case sz_byte:
-                       *val = get_iword_1 (m68kpc_offset) & 0xff;
-                       m68kpc_offset += 2;
-                       break;
-               case sz_word:
-                       *val = get_iword_1 (m68kpc_offset) & 0xffff;
-                       m68kpc_offset += 2;
-                       break;
-               case sz_long:
-                       *val = get_ilong_1 (m68kpc_offset);
-                       m68kpc_offset += 4;
-                       break;
-               default:
-                       break;
-               }
-               return 1;
-       case imm0:
-               *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
-               m68kpc_offset += 2;
-               return 1;
-       case imm1:
-               *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
-               m68kpc_offset += 2;
-               return 1;
-       case imm2:
-               *val = get_ilong_1 (m68kpc_offset);
-               m68kpc_offset += 4;
-               return 1;
-       case immi:
-               *val = (uae_s32)(uae_s8)(reg & 0xff);
-               return 1;
-       default:
-               addr = 0;
-               break;
-       }
-       if ((addr & 1) == 0)
-               return 1;
-
-       last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
-       last_fault_for_exception_3 = addr;
-       last_writeaccess_for_exception_3 = 0;
-       last_instructionaccess_for_exception_3 = 0;
-       return 0;
-}
-#endif
-
-int get_cpu_model (void)
-{
-       return currprefs.cpu_model;
-}
-
-
 STATIC_INLINE int in_rom (uaecptr pc)
 {
        return (munge24 (pc) & 0xFFF80000) == 0xF80000;
@@ -2816,6 +2244,7 @@ static void MakeFromSR_x(int t0trace)
        regs.s  = (regs.sr >> 13) & 1;
        regs.m  = (regs.sr >> 12) & 1;
        regs.intmask = (regs.sr >> 8) & 7;
+
        if (currprefs.cpu_model >= 68020) {
                /* 68060 does not have MSP but does have M-bit.. */
                if (currprefs.cpu_model >= 68060)
@@ -3925,6 +3354,14 @@ void NMI (void)
        do_interrupt (7);
 }
 
+static void maybe_disable_fpu(void)
+{
+       if (currprefs.cpu_model == 68060 && currprefs.cpuboard_type == 0 && (rtarea_base != 0xf00000 || !need_uae_boot_rom(&currprefs))) {
+               // disable FPU at reset if no 68060 accelerator board and no $f0 ROM.
+               regs.pcr |= 2;
+       }
+}
+
 static void m68k_reset_sr(void)
 {
        SET_XFLG ((regs.sr >> 4) & 1);
@@ -4039,10 +3476,7 @@ static void m68k_reset2(bool hardreset)
        if (currprefs.cpu_model == 68060) {
                regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR;
                regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8;
-               if (currprefs.fpu_model == 0 || (currprefs.cpuboard_type == 0 && rtarea_base != 0xf00000)) {
-                       /* disable FPU if no accelerator board and no $f0 ROM */
-                       regs.pcr |= 2;
-               }
+               maybe_disable_fpu();
        }
 //     regs.ce020memcycles = 0;
        regs.ce020startcycle = regs.ce020endcycle = 0;
@@ -4141,7 +3575,7 @@ static void m68k_reset_restore(void)
        }
 }
 
-void REGPARAM2 op_unimpl (uae_u16 opcode)
+void REGPARAM2 op_unimpl (uae_u32 opcode)
 {
        static int warned;
        if (warned < 20) {
@@ -5509,7 +4943,7 @@ static void run_cpu_thread(void *(*f)(void *))
                int maxperloop = 10;
 
                while (!uae_sem_trywait(&cpu_out_sema)) {
-                       uae_u32 cmd, addr, data, size, mode;
+                       uae_u32 addr, data, size, mode;
 
                        addr = cpu_thread_indirect_addr;
                        data = cpu_thread_indirect_val;
@@ -6656,6 +6090,7 @@ void m68k_go (int may_quit)
        cpu_prefs_changed_flag = 0;
        in_m68k_go++;
        for (;;) {
+               int restored = 0;
                void (*run_func)(void);
 
                cputrace.state = -1;
@@ -6674,7 +6109,6 @@ void m68k_go (int may_quit)
                        inprec_startup ();
 
                if (quit_program > 0) {
-                       int restored = 0;
                        cpu_keyboardreset = quit_program == UAE_RESET_KEYBOARD;
                        cpu_hardreset = ((quit_program == UAE_RESET_HARD ? 1 : 0) | hardboot) != 0;
 
@@ -6714,7 +6148,7 @@ void m68k_go (int may_quit)
                                        record_dma_reset ();
                                        record_dma_reset ();
                                }
-                               savestate_restore_finish ();
+                               restored = savestate_restore_finish ();
                                memory_map_dump ();
                                if (currprefs.mmu_model == 68030) {
                                        mmu030_decode_tc (tc_030, true);
@@ -6722,7 +6156,6 @@ void m68k_go (int may_quit)
                                        mmu_set_tc (regs.tcr);
                                }
                                startup = 1;
-                               restored = 1;
                        }
 #endif
                        if (currprefs.produce_sound == 0)
@@ -6786,6 +6219,13 @@ void m68k_go (int may_quit)
                event_wait = true;
                unset_special(SPCFLAG_MODE_CHANGE);
 
+#ifdef SAVESTATE
+               if (restored) {
+                       restored = 0;
+                       savestate_restore_final();
+               }
+#endif
+
                if (!regs.halted) {
                        // check that PC points to something that looks like memory.
                        uaecptr pc = m68k_getpc();
@@ -6833,1628 +6273,38 @@ void m68k_go (int may_quit)
        in_m68k_go--;
 }
 
-#if 0
-static void m68k_verify (uaecptr addr, uaecptr *nextpc)
-{
-       uae_u16 opcode, val;
-       struct instr *dp;
 
-       opcode = get_iword_1 (0);
-       last_op_for_exception_3 = opcode;
-       m68kpc_offset = 2;
 
-       if (cpufunctbl[opcode] == op_illg_1) {
-               opcode = 0x4AFC;
-       }
-       dp = table68k + opcode;
+void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc)
+{
+       TCHAR *buf;
 
-       if (dp->suse) {
-               if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
-                       Exception (3, 0);
-                       return;
-               }
-       }
-       if (dp->duse) {
-               if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
-                       Exception (3, 0);
-                       return;
-               }
-       }
+       buf = xcalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
+       if (!buf)
+               return;
+       m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, seaddr, deaddr, lastpc, 1);
+       xfree (buf);
 }
-#endif
-
-static const TCHAR *ccnames[] =
+void m68k_disasm (uaecptr addr, uaecptr *nextpc, uaecptr lastpc, int cnt)
 {
-       _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
-       _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE")
-};
-static const TCHAR *fpccnames[] =
-{
-       _T("F"),
-       _T("EQ"),
-       _T("OGT"),
-       _T("OGE"),
-       _T("OLT"),
-       _T("OLE"),
-       _T("OGL"),
-       _T("OR"),
-       _T("UN"),
-       _T("UEQ"),
-       _T("UGT"),
-       _T("UGE"),
-       _T("ULT"),
-       _T("ULE"),
-       _T("NE"),
-       _T("T"),
-       _T("SF"),
-       _T("SEQ"),
-       _T("GT"),
-       _T("GE"),
-       _T("LT"),
-       _T("LE"),
-       _T("GL"),
-       _T("GLE"),
-       _T("NGLE"),
-       _T("NGL"),
-       _T("NLE"),
-       _T("NLT"),
-       _T("NGE"),
-       _T("NGT"),
-       _T("SNE"),
-       _T("ST")
-};
-static const TCHAR *fpuopcodes[] =
-{
-       _T("FMOVE"),
-       _T("FINT"),
-       _T("FSINH"),
-       _T("FINTRZ"),
-       _T("FSQRT"),
-       NULL,
-       _T("FLOGNP1"),
-       NULL,
-       _T("FETOXM1"),
-       _T("FTANH"),
-       _T("FATAN"),
-       NULL,
-       _T("FASIN"),
-       _T("FATANH"),
-       _T("FSIN"),
-       _T("FTAN"),
-       _T("FETOX"),    // 0x10
-       _T("FTWOTOX"),
-       _T("FTENTOX"),
-       NULL,
-       _T("FLOGN"),
-       _T("FLOG10"),
-       _T("FLOG2"),
-       NULL,
-       _T("FABS"),
-       _T("FCOSH"),
-       _T("FNEG"),
-       NULL,
-       _T("FACOS"),
-       _T("FCOS"),
-       _T("FGETEXP"),
-       _T("FGETMAN"),
-       _T("FDIV"),             // 0x20
-       _T("FMOD"),
-       _T("FADD"),
-       _T("FMUL"),
-       _T("FSGLDIV"),
-       _T("FREM"),
-       _T("FSCALE"),
-       _T("FSGLMUL"),
-       _T("FSUB"),
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       _T("FSINCOS"),  // 0x30
-       _T("FSINCOS"),
-       _T("FSINCOS"),
-       _T("FSINCOS"),
-       _T("FSINCOS"),
-       _T("FSINCOS"),
-       _T("FSINCOS"),
-       _T("FSINCOS"),
-       _T("FCMP"),
-       NULL,
-       _T("FTST"),
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       NULL
-};
-
-static const TCHAR *movemregs[] =
-{
-       _T("D0"),
-       _T("D1"),
-       _T("D2"),
-       _T("D3"),
-       _T("D4"),
-       _T("D5"),
-       _T("D6"),
-       _T("D7"),
-       _T("A0"),
-       _T("A1"),
-       _T("A2"),
-       _T("A3"),
-       _T("A4"),
-       _T("A5"),
-       _T("A6"),
-       _T("A7"),
-       _T("FP0"),
-       _T("FP1"),
-       _T("FP2"),
-       _T("FP3"),
-       _T("FP4"),
-       _T("FP5"),
-       _T("FP6"),
-       _T("FP7"),
-       _T("FPIAR"),
-       _T("FPSR"),
-       _T("FPCR")
-};
+       TCHAR *buf;
 
-static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode)
-{
-       TCHAR *p = out + _tcslen (out);
-       if (*prevreg < 0) {
-               *prevreg = reg;
-               *lastreg = reg;
+       buf = xcalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
+       if (!buf)
                return;
-       }
-       if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
-               _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]);
-               p = p + _tcslen (p);
-               if (*lastreg != *prevreg) {
-                       if ((*lastreg) + 2 == reg) {
-                               _stprintf(p, _T("/%s"), movemregs[*prevreg]);
-                       } else if ((*lastreg) != (*prevreg)) {
-                               _stprintf(p, _T("-%s"), movemregs[*prevreg]);
-                       }
-               }
-               *lastreg = reg;
-               *first = 0;
-       }
-       *prevreg = reg;
+       m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, NULL, NULL, lastpc, 0);
+       console_out_f (_T("%s"), buf);
+       xfree (buf);
 }
 
-static bool movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode, bool dst)
+void m68k_dumpstate(uaecptr *nextpc, uaecptr prevpc)
 {
-       unsigned int dmask, amask;
-       int prevreg = -1, lastreg = -1, first = 1;
+       int i, j;
+       uaecptr pc = M68K_GETPC;
 
-       if (mode == Apdi && !fpmode) {
-               uae_u8 dmask2;
-               uae_u8 amask2;
-               
-               amask2 = mask & 0xff;
-               dmask2 = (mask >> 8) & 0xff;
-               dmask = 0;
-               amask = 0;
-               for (int i = 0; i < 8; i++) {
-                       if (dmask2 & (1 << i))
-                               dmask |= 1 << (7 - i);
-                       if (amask2 & (1 << i))
-                               amask |= 1 << (7 - i);
-               }
-       } else {
-               dmask = mask & 0xff;
-               amask = (mask >> 8) & 0xff;
-               if (fpmode == 1 && mode != Apdi) {
-                       uae_u8 dmask2 = dmask;
-                       dmask = 0;
-                       for (int i = 0; i < 8; i++) {
-                               if (dmask2 & (1 << i))
-                                       dmask |= 1 << (7 - i);
-                       }
-               }
-       }
-       bool dataout = dmask != 0 || amask != 0;
-       if (dst && dataout)
-               _tcscat(out, _T(","));
-       if (fpmode) {
-               while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; }
-       } else {
-               while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; }
-               while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; }
-       }
-       addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode);
-       return dataout;
-}
-
-static void disasm_size (TCHAR *instrname, struct instr *dp)
-{
-       if (dp->unsized) {
-               _tcscat(instrname, _T(" "));
-               return;
-       }
-       switch (dp->size)
-       {
-       case sz_byte:
-               _tcscat (instrname, _T(".B "));
-               break;
-       case sz_word:
-               _tcscat (instrname, _T(".W "));
-               break;
-       case sz_long:
-               _tcscat (instrname, _T(".L "));
-               break;
-       default:
-               _tcscat (instrname, _T(" "));
-               break;
-       }
-}
-
-static void asm_add_extensions(uae_u16 *data, int *dcntp, int mode, uae_u32 v, int extcnt, uae_u16 *ext, uaecptr pc, int size)
-{
-       int dcnt = *dcntp;
-       if (mode < 0)
-               return;
-       if (mode == Ad16) {
-               data[dcnt++] = v;
-       }
-       if (mode == PC16) {
-               data[dcnt++] = v - (pc + 2);
-       }
-       if (mode == Ad8r || mode == PC8r) {
-               for (int i = 0; i < extcnt; i++) {
-                       data[dcnt++] = ext[i];
-               }
-       }
-       if (mode == absw) {
-               data[dcnt++] = (uae_u16)v;
-       }
-       if (mode == absl) {
-               data[dcnt++] = (uae_u16)(v >> 16);
-               data[dcnt++] = (uae_u16)v;
-       }
-       if ((mode == imm && size == 0) || mode == imm0) {
-               data[dcnt++] = (uae_u8)v;
-       }
-       if ((mode == imm && size == 1) || mode == imm1) {
-               data[dcnt++] = (uae_u16)v;
-       }
-       if ((mode == imm && size == 2) || mode == imm2) {
-               data[dcnt++] = (uae_u16)(v >> 16);
-               data[dcnt++] = (uae_u16)v;
-       }
-       *dcntp = dcnt;
-}
-
-static int asm_isdreg(const TCHAR *s)
-{
-       if (s[0] == 'D' && s[1] >= '0' && s[1] <= '7')
-               return s[1] - '0';
-       return -1;
-}
-static int asm_isareg(const TCHAR *s)
-{
-       if (s[0] == 'A' && s[1] >= '0' && s[1] <= '7')
-               return s[1] - '0';
-       if (s[0] == 'S' && s[1] == 'P')
-               return 7;
-       return -1;
-}
-static int asm_ispc(const TCHAR *s)
-{
-       if (s[0] == 'P' && s[1] == 'C')
-               return 1;
-       return 0;
-}
-
-static uae_u32 asmgetval(const TCHAR *s)
-{
-       TCHAR *endptr;
-       if (s[0] == '-')
-               return _tcstol(s, &endptr, 16);
-       return _tcstoul(s, &endptr, 16);
-}
-
-static int asm_parse_mode020(TCHAR *s, uae_u8 *reg, uae_u32 *v, int *extcnt, uae_u16 *ext)
-{
-       return -1;
-}
-
-static int asm_parse_mode(TCHAR *s, uae_u8 *reg, uae_u32 *v, int *extcnt, uae_u16 *ext)
-{
-       TCHAR *ss = s;
-       *reg = -1;
-       *v = 0;
-       *ext = 0;
-       *extcnt = 0;
-       if (s[0] == 0)
-               return -1;
-       // Dn
-       if (asm_isdreg(s) >= 0 && s[2] == 0) {
-               *reg = asm_isdreg(s);
-               return Dreg;
-       }
-       // An
-       if (asm_isareg(s) >= 0 && s[2] == 0) {
-               *reg = asm_isareg(s);
-               return Areg;
-       }
-       // (An) and (An)+
-       if (s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')') {
-               *reg = asm_isareg(s + 1);
-               if (s[4] == '+' && s[5] == 0)
-                       return Aipi;
-               if (s[4] == 0)
-                       return Aind;
-               return -1;
-       }
-       // -(An)
-       if (s[0] == '-' && s[1] == '(' && asm_isareg(s + 2) >= 0 && s[4] == ')' && s[5] == 0) {
-               *reg = asm_isareg(s + 2);
-               return Apdi;
-       }
-       // Immediate
-       if (s[0] == '#') {
-               if (s[1] == '!') {
-                       *v = _tstol(s + 2);
-               } else {
-                       *v = asmgetval(s + 1);
-               }
-               return imm;
-       }
-       // Value
-       if (s[0] == '!') {
-               *v = _tstol(s + 1);
-       } else {
-               *v = asmgetval(s);
-       }
-       int dots = 0;
-       int fullext = 0;
-       for (int i = 0; i < _tcslen(s); i++) {
-               if (s[i] == ',') {
-                       dots++;
-               } else if (s[i] == '[') {
-                       if (fullext > 0)
-                               fullext = -1;
-                       else
-                               fullext = 1;
-               } else if (s[i] == ']') {
-                       if (fullext != 1)
-                               fullext = -1;
-                       else
-                               fullext = 2;
-                       fullext++;
-               }
-       }
-       if (fullext < 0 || fullext == 1)
-               return -1;
-       if (fullext == 2) {
-               return asm_parse_mode020(s, reg, v, extcnt, ext);
-       }
-       while (*s != 0) {
-               // d16(An)
-               if (dots == 0 && s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')' && s[4] == 0) {
-                       *reg = asm_isareg(s + 1);
-                       return Ad16;
-               }
-               // d16(PC)
-               if (dots == 0 && s[0] == '(' && asm_ispc(s + 1) && s[3] == ')' && s[4] == 0) {
-                       *reg = 2;
-                       return PC16;
-               }
-               // (d16,An) / (d16,PC)
-               if (dots == 1 && s[0] == '(' && !asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) {
-                       TCHAR *startptr, *endptr;
-                       if (s[1] == '!') {
-                               startptr = s + 2;
-                               *v = _tcstol(startptr, &endptr, 10);
-                       } else {
-                               startptr = s + 1;
-                               *v = _tcstol(startptr, &endptr, 16);
-                       }
-                       if (endptr == startptr || endptr[0] != ',')
-                               return -1;
-                       if (asm_ispc(endptr + 1) && endptr[3] == ')') {
-                               *reg = 2;
-                               return PC16;
-                       }
-                       if (asm_isareg(endptr + 1) >= 0 && endptr[3] == ')') {
-                               *reg = asm_isareg(endptr + 1);
-                               return Ad16;
-                       }
-                       return -1;
-               }
-               // Ad8r PC8r
-               if (s[0] == '(') {
-                       TCHAR *s2 = s;
-                       if (!asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) {
-                               if (dots != 2)
-                                       return -1;
-                               TCHAR *startptr, *endptr;
-                               if (s[1] == '!') {
-                                       startptr = s + 2;
-                                       *v = _tcstol(startptr, &endptr, 10);
-                               } else {
-                                       startptr = s + 1;
-                                       *v = _tcstol(startptr, &endptr, 16);
-                               }
-                               if (endptr == startptr || endptr[0] != ',')
-                                       return -1;
-                               s2 = endptr + 1;
-                       } else if (((asm_isareg(s + 1) >= 0 || asm_ispc(s + 1)) && s[3] == ',') || (asm_isdreg(s + 4) >= 0 || asm_isareg(s + 4) >= 0)) {
-                               if (dots != 1)
-                                       return -1;
-                               s2 = s + 1;
-                       } else {
-                               return -1;
-                       }
-                       uae_u8 reg2;
-                       bool ispc = asm_ispc(s2);
-                       if (ispc) {
-                               *reg = 3;
-                       } else {
-                               *reg = asm_isareg(s2);
-                       }
-                       *extcnt = 1;
-                       s2 += 2;
-                       if (*s2 != ',')
-                               return -1;
-                       s2++;
-                       if (asm_isdreg(s2) >= 0) {
-                               reg2 = asm_isdreg(s2);
-                       } else {
-                               reg2 = asm_isareg(s2);
-                               *ext |= 1 << 15;
-                       }
-                       s2 += 2;
-                       *ext |= reg2 << 12;
-                       *ext |= (*v) & 0xff;
-                       if (s2[0] == '.' && s2[1] == 'W') {
-                               s2 += 2;
-                       } else if (s2[0] == '.' && s2[1] == 'L') {
-                               *ext |= 1 << 11;
-                               s2 += 2;
-                       }
-                       if (s2[0] == '*') {
-                               TCHAR scale = s2[1];
-                               if (scale == '2')
-                                       *ext |= 1 << 9;
-                               else if (scale == '4')
-                                       *ext |= 2 << 9;
-                               else if (scale == '8')
-                                       *ext |= 3 << 9;
-                               else
-                                       return -1;
-                               s2 += 2;
-                       }
-                       if (s2[0] == ')' && s2[1] == 0) {
-                               return ispc ? PC8r : Ad8r;
-                       }
-                       return -1;
-               }
-               s++;
-       }
-       // abs.w
-       if (s - ss > 2 && s[-2] == '.' && s[-1] == 'W') {
-               *reg = 0;
-               return absw;
-       }
-       // abs.l
-       *reg = 1;
-       return absl;
-}
-
-static TCHAR *asm_parse_parm(TCHAR *parm, TCHAR *out)
-{
-       TCHAR *p = parm;
-       bool quote = false;
-
-       for (;;) {
-               if (*p == '(') {
-                       quote = true;
-               }
-               if (*p == ')') {
-                       if (!quote)
-                               return NULL;
-                       quote = false;
-               }
-               if ((*p == ',' || *p == 0) && !quote) {
-                       TCHAR c = *p;
-                       p[0] = 0;
-                       _tcscpy(out, parm);
-                       my_trim(out);
-                       if (c)
-                               p++;
-                       return p;
-               }
-               p++;
-       }
-}
-
-static bool m68k_asm_parse_movec(TCHAR *s, TCHAR *d)
-{
-       for (int i = 0; m2cregs[i].regname; i++) {
-               if (!_tcscmp(s, m2cregs[i].regname)) {
-                       uae_u16 v = m2cregs[i].regno;
-                       if (asm_isareg(d) >= 0)
-                               v |= 0x8000 | (asm_isareg(d) << 12);
-                       else if (asm_isdreg(d) >= 0)
-                               v |= (asm_isdreg(d) << 12);
-                       else
-                               return false;
-                       _stprintf(s, _T("#%X"), v);
-                       return true;
-               }
-       }
-       return false;
-}
-
-static bool m68k_asm_parse_movem(TCHAR *s, int dir)
-{
-       TCHAR *d = s;
-       uae_u16 regmask = 0;
-       uae_u16 mask = dir ? 0x8000 : 0x0001;
-       bool ret = false;
-       while(*s) {
-               int dreg = asm_isdreg(s);
-               int areg = asm_isareg(s);
-               if (dreg < 0 && areg < 0)
-                       break;
-               int reg = dreg >= 0 ? dreg : areg + 8;
-               regmask |= dir ? (mask >> reg) : (mask << reg);
-               s += 2;
-               if (*s == 0) {
-                       ret = true;
-                       break;
-               } else if (*s == '/') {
-                       s++;
-                       continue;
-               } else if (*s == '-') {
-                       s++;
-                       int dreg2 = asm_isdreg(s);
-                       int areg2 = asm_isareg(s);
-                       if (dreg2 < 0 && areg2 < 0)
-                               break;
-                       int reg2 = dreg2 >= 0 ? dreg2 : areg2 + 8;
-                       if (reg2 < reg)
-                               break;
-                       while (reg2 >= reg) {
-                               regmask |= dir ? (mask >> reg) : (mask << reg);
-                               reg++;
-                       }
-                       s += 2;
-                       if (*s == 0) {
-                               ret = true;
-                               break;
-                       }
-               } else {
-                       break;
-               }
-       }
-       if (ret)
-               _stprintf(d, _T("#%X"), regmask);
-       return ret;
-}
-
-int m68k_asm(TCHAR *sline, uae_u16 *out, uaecptr pc)
-{
-       TCHAR *p;
-       const TCHAR *cp1;
-       TCHAR ins[256], parms[256];
-       TCHAR line[256];
-       TCHAR srcea[256], dstea[256];
-       uae_u16 data[16], sexts[8], dexts[8];
-       int sextcnt, dextcnt;
-       int dcnt = 0;
-       int cc = -1;
-       int quick = 0;
-       bool immrelpc = false;
-
-       if (_tcslen(sline) > 100)
-               return -1;
-
-       srcea[0] = dstea[0] = 0;
-       parms[0] = 0;
-
-       // strip all white space except first space
-       p = line;
-       bool firstsp = true;
-       for (int i = 0; sline[i]; i++) {
-               TCHAR c = sline[i];
-               if (c == 32 && firstsp) {
-                       firstsp = false;
-                       *p++ = 32;
-               }
-               if (c <= 32)
-                       continue;
-               *p++ = c;
-       }
-       *p = 0;
-
-       to_upper(line, _tcslen(line));
-
-       p = line;
-       while (*p && *p != ' ')
-               p++;
-       if (*p == ' ') {
-               *p = 0;
-               _tcscpy(parms, p + 1);
-               my_trim(parms);
-       }
-       _tcscpy(ins, line);
-       
-       if (_tcslen(ins) == 0)
-               return 0;
-
-       int size = 1;
-       int inssize = -1;
-       cp1 = _tcschr(line, '.');
-       if (cp1) {
-               size = cp1[1];
-               if (size == 'W')
-                       size = 1;
-               else if (size == 'L')
-                       size = 2;
-               else if (size == 'B')
-                       size = 0;
-               else
-                       return 0;
-               inssize = size;
-               line[cp1 - line] = 0;
-               _tcscpy(ins, line);
-       }
-
-       TCHAR *parmp = parms;
-       parmp = asm_parse_parm(parmp, srcea);
-       if (!parmp)
-               return 0;
-       if (srcea[0]) {
-               parmp = asm_parse_parm(parmp, dstea);
-               if (!parmp)
-                       return 0;
-       }
-
-       int smode = -1;
-       int dmode = -1;
-       uae_u8 sreg = -1;
-       uae_u8 dreg = -1;
-       uae_u32 sval = 0;
-       uae_u32 dval = 0;
-       int ssize = -1;
-       int dsize = -1;
-
-       dmode = asm_parse_mode(dstea, &dreg, &dval, &dextcnt, dexts);
-
-
-       // Common alias
-       if (!_tcscmp(ins, _T("BRA"))) {
-               _tcscpy(ins, _T("BT"));
-       } else if (!_tcscmp(ins, _T("BSR"))) {
-               immrelpc = true;
-       } else if (!_tcscmp(ins, _T("MOVEM"))) {
-               if (dmode >= Aind && _tcschr(dstea, '-') == NULL && _tcschr(dstea, '/') == NULL) {
-                       _tcscpy(ins, _T("MVMLE"));
-                       if (!m68k_asm_parse_movem(srcea, dmode == Apdi))
-                               return -1;
-               } else {
-                       TCHAR tmp[256];
-                       _tcscpy(ins, _T("MVMEL"));
-                       _tcscpy(tmp, srcea);
-                       _tcscpy(srcea, dstea);
-                       _tcscpy(dstea, tmp);
-                       if (!m68k_asm_parse_movem(srcea, 0))
-                               return -1;
-                       dmode = asm_parse_mode(dstea, &dreg, &dval, &dextcnt, dexts);
-               }
-       } else if (!_tcscmp(ins, _T("MOVEC"))) {
-               if (dmode == Dreg || dmode == Areg) {
-                       _tcscpy(ins, _T("MOVEC2"));
-                       if (!m68k_asm_parse_movec(srcea, dstea))
-                               return -1;
-               } else {
-                       TCHAR tmp[256];
-                       _tcscpy(ins, _T("MOVE2C"));
-                       _tcscpy(tmp, srcea);
-                       _tcscpy(srcea, dstea);
-                       dstea[0] = 0;
-                       if (!m68k_asm_parse_movec(srcea, tmp))
-                               return -1;
-               }
-               dmode = -1;
-       }
-       
-       if (dmode == Areg) {
-               int l = _tcslen(ins);
-               if (l <= 2)
-                       return -1;
-               TCHAR last = ins[l- 1];
-               if (last == 'Q') {
-                       last = ins[l - 2];
-                       if (last != 'A') {
-                               ins[l - 1] = 'A';
-                               ins[l] = 'Q';
-                               ins[l + 1] = 0;
-                       }
-               } else if (last != 'A') {
-                       _tcscat(ins, _T("A"));
-               }
-       }
-
-       bool fp = ins[0] == 'F';
-
-       if (ins[_tcslen(ins) - 1] == 'Q' && _tcslen(ins) > 3 && !fp) {
-               quick = 1;
-               ins[_tcslen(ins) - 1] = 0;
-       }
-
-       struct mnemolookup *lookup;
-       for (lookup = lookuptab; lookup->name; lookup++) {
-               if (!_tcscmp(ins, lookup->name))
-                       break;
-       }
-       if (!lookup->name) {
-               // Check cc variants
-               for (lookup = lookuptab; lookup->name; lookup++) {
-                       const TCHAR *ccp = _tcsstr(lookup->name, _T("cc"));
-                       if (ccp) {
-                               TCHAR tmp[256];
-                               for (int i = 0; i < (fp ? 32 : 16); i++) {
-                                       const TCHAR *ccname = fp ? fpccnames[i] : ccnames[i];
-                                       _tcscpy(tmp, lookup->name);
-                                       _tcscpy(tmp + (ccp - lookup->name), ccname);
-                                       if (tmp[_tcslen(tmp) - 1] == ' ')
-                                               tmp[_tcslen(tmp) - 1] = 0;
-                                       if (!_tcscmp(tmp, ins)) {
-                                               _tcscpy(ins, lookup->name);
-                                               cc = i;
-                                               if (lookup->mnemo == i_DBcc || lookup->mnemo == i_Bcc) {
-                                                       // Bcc.B uses same encoding mode as MOVEQ
-                                                       immrelpc = true;
-                                               }
-                                               if (size == 0) {
-                                                       quick = 2;
-                                               }
-                                               break;
-                                       }
-                               }
-                       }
-                       if (cc >= 0)
-                               break;
-               }
-       }
-
-       if (!lookup->name)
-               return 0;
-
-       int mnemo = lookup->mnemo;
-
-       int found = 0;
-       int sizemask = 0;
-       int tsize = size;
-       int unsized = 0;
-
-       for (int round = 0; round < 9; round++) {
-
-               if (!found && round == 8)
-                       return 0;
-
-               if (round == 3) {
-                       // Q is always LONG sized
-                       if (quick == 1) {
-                               tsize = 2;
-                       }
-                       bool isimm = srcea[0] == '#';
-                       if (immrelpc && !isimm) {
-                               TCHAR tmp[256];
-                               _tcscpy(tmp, srcea);
-                               srcea[0] = '#';
-                               _tcscpy(srcea + 1, tmp);
-                       }
-                       smode = asm_parse_mode(srcea, &sreg, &sval, &sextcnt, sexts);
-                       if (immrelpc && !isimm) {
-                               sval = sval - (pc + 2);
-                       }
-                       if (quick) {
-                               smode = immi;
-                               sreg = sval & 0xff;
-                       }
-               }
-
-               if (round == 1) {
-                       if (!quick && (sizemask == 1 || sizemask == 2 || sizemask == 4)) {
-                               tsize = 0;
-                               if (sizemask == 2)
-                                       tsize = 1;
-                               else if (sizemask == 4)
-                                       tsize = 2;
-                       } else {
-                               continue;
-                       }
-               }
-               if (round == 2 && !found) {
-                       unsized = 1;
-               }
-
-               if (round == 4 && smode == imm) {
-                       smode = imm0;
-               } else if (round == 5 && smode == imm0) {
-                       smode = imm1;
-               } else if (round == 6 && smode == imm1) {
-                       smode = imm2;
-               } else if (round == 7 && smode == imm2) {
-                       smode = immi;
-                       sreg = sval & 0xff;
-               } else if (round == 4) {
-                       round += 5 - 1;
-               }
-
-               for (int opcode = 0; opcode < 65536; opcode++) {
-                       struct instr *table = &table68k[opcode];
-                       if (table->mnemo != mnemo)
-                               continue;
-                       if (cc >= 0 && table->cc != cc)
-                               continue;
-
-#if 0
-                       if (round == 0) {
-                               console_out_f(_T("%s OP=%04x S=%d SR=%d SM=%d SU=%d SP=%d DR=%d DM=%d DU=%d DP=%d SDU=%d\n"), lookup->name, opcode, table->size,
-                                       table->sreg, table->smode, table->suse, table->spos,
-                                       table->dreg, table->dmode, table->duse, table->dpos,
-                                       table->sduse);
-                       }
-#endif
-
-                       if (table->duse && !(table->dmode == dmode || (dmode >= imm && dmode <= imm2 && table->dmode >= imm && table->dmode <= imm2)))
-                               continue;
-                       if (round == 0) {
-                               sizemask |= 1 << table->size;
-                       }
-                       if (unsized > 0 && !table->unsized) {
-                               continue;
-                       }
-
-                       found++;
-
-                       if (round >= 3) {
-
-                               if (
-                                       ((table->size == tsize || table->unsized)) &&
-                                       ((!table->suse && smode < 0) || (table->suse && table->smode == smode)) &&
-                                       ((!table->duse && dmode < 0) || (table->duse && (table->dmode == dmode || (dmode == imm && (table->dmode >= imm && table->dmode <= imm2))))) &&
-                                       ((table->sreg == sreg || (table->smode >= absw && table->smode != immi))) &&
-                                       ((table->dreg == dreg || table->dmode >= absw))
-                                       )
-                               {
-                                       if (inssize >= 0 && tsize != inssize)
-                                               continue;
-
-
-                                       data[dcnt++] = opcode;
-                                       asm_add_extensions(data, &dcnt, smode, sval, sextcnt, sexts, pc, tsize);
-                                       if (smode >= 0)
-                                               asm_add_extensions(data, &dcnt, dmode, dval, dextcnt, dexts, pc, tsize);
-                                       for (int i = 0; i < dcnt; i++) {
-                                               out[i] = data[i];
-                                       }
-                                       return dcnt;
-                               }
-
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static void resolve_if_jmp(TCHAR *s, uae_u32 addr)
-{
-       uae_u16 opcode = get_word_debug(addr);
-       if (opcode == 0x4ef9) { // JMP x.l
-               TCHAR *p = s + _tcslen(s);
-               uae_u32 addr2 = get_long_debug(addr + 2);
-               _stprintf(p, _T(" == $%08x "), addr2);
-               showea_val(p + _tcslen(p), opcode, addr2, 4);
-               TCHAR txt[256];
-               bool ext;
-               if (debugmem_get_segment(addr2, NULL, &ext, NULL, txt)) {
-                       if (ext) {
-                               _tcscat(p, _T(" "));
-                               _tcscat(p, txt);
-                       }
-               }
-       }
-}
-
-static bool mmu_op30_helper_get_fc(uae_u16 extra, TCHAR *out)
-{
-       switch (extra & 0x0018) {
-       case 0x0010:
-               _stprintf(out, _T("#%d"), extra & 7);
-               return true;
-       case 0x0008:
-               _stprintf(out, _T("D%d"), extra & 7);
-               return true;
-       case 0x0000:
-               if (extra & 1) {
-                       _tcscpy(out, _T("DFC"));
-               } else {
-                       _tcscpy(out, _T("SFC"));
-               }
-               return true;
-       default:
-               return false;
-       }
-}
-
-static uaecptr disasm_mmu030(uaecptr pc, uae_u16 opcode, uae_u16 extra, struct instr *dp, TCHAR *instrname, uae_u32 *seaddr2, int safemode)
-{
-       int type = extra >> 13;
-
-       _tcscpy(instrname, _T("F-LINE (MMU 68030)"));
-       pc += 2;
-
-       switch (type)
-       {
-       case 0:
-       case 2:
-       case 3:
-       {
-               // PMOVE
-               int preg = (extra >> 10) & 31;
-               int rw = (extra >> 9) & 1;
-               int fd = (extra >> 8) & 1;
-               int unused = (extra & 0xff);
-               const TCHAR *r = NULL;
-
-               if (mmu_op30_invea(opcode))
-                       break;
-               if (unused)
-                       break;
-               if (rw && fd)
-                       break;
-               switch (preg)
-               {
-               case 0x10:
-                       r = _T("TC");
-                       break;
-               case 0x12:
-                       r = _T("SRP");
-                       break;
-               case 0x13:
-                       r = _T("CRP");
-                       break;
-               case 0x18:
-                       r = _T("MMUSR");
-                       break;
-               case 0x02:
-                       r = _T("TT0");
-                       break;
-               case 0x03:
-                       r = _T("TT1");
-                       break;
-               }
-               if (!r)
-                       break;
-
-               _tcscpy(instrname, _T("PMOVE"));
-               if (fd)
-                       _tcscat(instrname, _T("FD"));
-               _tcscat(instrname, _T(" "));
-
-               if (!rw) {
-                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode);
-                       _tcscat(instrname, _T(","));
-               }
-               _tcscat(instrname, r);
-               if (rw) {
-                       _tcscat(instrname, _T(","));
-                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode);
-               }
-               break;
-       }
-       case 1:
-       {
-               // PLOAD/PFLUSH
-               uae_u16 mode = (extra >> 8) & 31;
-               int unused = (extra & (0x100 | 0x80 | 0x40 | 0x20));
-               uae_u16 fc_mask = (extra & 0x00E0) >> 5;
-               uae_u16 fc_bits = extra & 0x7f;
-               TCHAR fc[10];
-
-               if (unused)
-                       break;
-
-               switch (mode) {
-               case 0x00: // PLOAD W
-               case 0x02: // PLOAD R
-                       if (mmu_op30_invea(opcode))
-                               break;
-                       _stprintf(instrname, _T("PLOAD%c %s,"), mode == 0 ? 'W' : 'R', fc);
-                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode);
-                       break;
-               case 0x04: // PFLUSHA
-                       if (fc_bits)
-                               break;
-                       _tcscpy(instrname, _T("PFLUSHA"));
-                       break;
-               case 0x10: // FC
-                       if (!mmu_op30_helper_get_fc(extra, fc))
-                               break;
-                       _stprintf(instrname, _T("PFLUSH %s,%d"), fc, fc_mask);
-                       break;
-               case 0x18: // FC + EA
-                       if (mmu_op30_invea(opcode))
-                               break;
-                       if (!mmu_op30_helper_get_fc(extra, fc))
-                               break;
-                       _stprintf(instrname, _T("PFLUSH %s,%d"), fc, fc_mask);
-                       _tcscat(instrname, _T(","));
-                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode);
-                       break;
-               }
-               break;
-       }
-       case 4:
-       {
-               // PTEST
-               int level = (extra & 0x1C00) >> 10;
-               int rw = (extra >> 9) & 1;
-               int a = (extra >> 8) & 1;
-               int areg = (extra & 0xE0) >> 5;
-               TCHAR fc[10];
-
-               if (mmu_op30_invea(opcode))
-                       break;
-               if (!mmu_op30_helper_get_fc(extra, fc))
-                       break;
-               if (!level && a)
-                       break;
-               _stprintf(instrname, _T("PTEST%c %s,"), rw ? 'R' : 'W', fc);
-               pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode);
-               _stprintf(instrname + _tcslen(instrname), _T(",#%d"), level);
-               if (a)
-                       _stprintf(instrname + _tcslen(instrname), _T(",A%d"), areg);
-               break;
-       }
-       }
-       return pc;
-}
-
-
-void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc, int safemode)
-{
-       uae_u32 seaddr2;
-       uae_u32 deaddr2;
-
-       if (!table68k)
-               return;
-       while (cnt-- > 0) {
-               TCHAR instrname[256], *ccpt;
-               TCHAR segout[256], segname[256];
-               int i;
-               uae_u32 opcode;
-               uae_u16 extra;
-               struct mnemolookup *lookup;
-               struct instr *dp;
-               uaecptr oldpc;
-               uaecptr m68kpc_illg = 0;
-               bool illegal = false;
-               int segid, lastsegid;
-               TCHAR *symbolpos;
-
-               seaddr2 = deaddr2 = 0;
-               oldpc = pc;
-               opcode = get_word_debug (pc);
-               extra = get_word_debug (pc + 2);
-               if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) {
-                       m68kpc_illg = pc + 2;
-                       illegal = TRUE;
-               }
-
-               dp = table68k + opcode;
-               if (dp->mnemo == i_ILLG) {
-                       illegal = FALSE;
-                       opcode = 0x4AFC;
-                       dp = table68k + opcode;
-               }
-               for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
-                       ;
-
-               lastsegid = -1;
-               bool exact = false;
-               if (lastpc != 0xffffffff) {
-                       lastsegid = debugmem_get_segment(lastpc, NULL, NULL, NULL, NULL);
-               }
-               segid = debugmem_get_segment(pc, &exact, NULL, segout, segname);
-               if (segid && (lastsegid != -1 || exact) && (segid != lastsegid || pc == lastpc || exact)) {
-                       buf = buf_out(buf, &bufsize, _T("%s\n"), segname);
-               }
-               symbolpos = buf;
-
-               buf = buf_out (buf, &bufsize, _T("%08X "), pc);
-
-               if (segid) {
-                       buf = buf_out(buf, &bufsize, _T("%s "), segout);
-               }
-
-               pc += 2;
-               
-               if (lookup->friendlyname)
-                       _tcscpy (instrname, lookup->friendlyname);
-               else
-                       _tcscpy (instrname, lookup->name);
-               ccpt = _tcsstr (instrname, _T("cc"));
-               if (ccpt != 0) {
-                       if ((opcode & 0xf000) == 0xf000)
-                               _tcscpy (ccpt, fpccnames[extra & 0x1f]);
-                       else
-                               _tcsncpy (ccpt, ccnames[dp->cc], 2);
-               }
-               disasm_size (instrname, dp);
-
-               if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
-                       uae_u16 imm = extra;
-                       uae_u16 creg = imm & 0x0fff;
-                       uae_u16 r = imm >> 12;
-                       TCHAR regs[16];
-                       const TCHAR *cname = _T("?");
-                       int j;
-                       for (j = 0; m2cregs[j].regname; j++) {
-                               if (m2cregs[j].regno == creg)
-                                       break;
-                       }
-                       _stprintf(regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
-                       if (m2cregs[j].regname)
-                               cname = m2cregs[j].regname;
-                       if (lookup->mnemo == i_MOVE2C) {
-                               _tcscat(instrname, regs);
-                               _tcscat(instrname, _T(","));
-                               _tcscat(instrname, cname);
-                       } else {
-                               _tcscat(instrname, cname);
-                               _tcscat(instrname, _T(","));
-                               _tcscat(instrname, regs);
-                       }
-                       pc += 2;
-               } else if (lookup->mnemo == i_CHK2) {
-                       TCHAR *p;
-                       if (!(extra & 0x0800)) {
-                               instrname[1] = 'M';
-                               instrname[2] = 'P';
-                       }
-                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
-                       extra = get_word_debug(pc);
-                       pc += 2;
-                       p = instrname + _tcslen(instrname);
-                       _stprintf(p, (extra & 0x8000) ? _T(",A%d") : _T(",D%d"), (extra >> 12) & 7);
-               } else if (lookup->mnemo == i_ORSR || lookup->mnemo == i_ANDSR || lookup->mnemo == i_EORSR) {
-                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
-                       _tcscat(instrname, dp->size == sz_byte ? _T(",CCR") : _T(",SR"));
-               } else if (lookup->mnemo == i_MVR2USP) {
-                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
-                       _tcscat(instrname, _T(",USP"));
-               } else if (lookup->mnemo == i_MVUSP2R) {
-                       _tcscat(instrname, _T("USP,"));
-                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
-               } else if (lookup->mnemo == i_MV2SR) {
-                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
-                       _tcscat(instrname, dp->size == sz_byte ? _T(",CCR") : _T(",SR"));
-               } else if (lookup->mnemo == i_MVSR2) {          
-                       _tcscat(instrname, dp->size == sz_byte ? _T("CCR,") : _T("SR,"));
-                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
-               } else if (lookup->mnemo == i_MVMEL) {
-                       uae_u16 mask = extra;
-                       pc += 2;
-                       pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
-                       movemout (instrname, mask, dp->dmode, 0, true);
-               } else if (lookup->mnemo == i_MVMLE) {
-                       uae_u16 mask = extra;
-                       pc += 2;
-                       if (movemout(instrname, mask, dp->dmode, 0, false))
-                               _tcscat(instrname, _T(","));
-                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
-               } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) {
-                       TCHAR *p;
-                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
-                       extra = get_word_debug(pc);
-                       pc += 2;
-                       p = instrname + _tcslen(instrname);
-                       if (extra & 0x0400)
-                               _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7);
-                       else
-                               _stprintf(p, _T(",D%d"), (extra >> 12) & 7);
-               } else if (lookup->mnemo == i_MOVES) {
-                       TCHAR *p;
-                       pc += 2;
-                       if (!(extra & 0x0800)) {
-                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
-                               p = instrname + _tcslen(instrname);
-                               _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
-                       } else {
-                               p = instrname + _tcslen(instrname);
-                               _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
-                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
-                       }
-               } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU ||
-                                  lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR ||
-                                  lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS ||
-                                  lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) {
-                       TCHAR *p;
-                       int reg = -1;
-
-                       pc += 2;
-                       p = instrname + _tcslen(instrname);
-                       if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS)
-                               reg = (extra >> 12) & 7;
-                       if (lookup->mnemo == i_BFINS)
-                               _stprintf(p, _T("D%d,"), reg);
-                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
-                       _tcscat(instrname, _T(" {"));
-                       p = instrname + _tcslen(instrname);
-                       if (extra & 0x0800)
-                               _stprintf(p, _T("D%d"), (extra >> 6) & 7);
-                       else
-                               _stprintf(p, _T("%d"), (extra >> 6) & 31);
-                       _tcscat(instrname, _T(":"));
-                       p = instrname + _tcslen(instrname);
-                       if (extra & 0x0020)
-                               _stprintf(p, _T("D%d"), extra & 7);
-                       else
-                               _stprintf(p, _T("%d"), extra  & 31);
-                       _tcscat(instrname, _T("}"));
-                       p = instrname + _tcslen(instrname);
-                       if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU)
-                               _stprintf(p, _T(",D%d"), reg);
-               } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP ||
-                       lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
-                       if ((opcode & 0xc0) == 0xc0)
-                               _tcscat(instrname, _T("BC"));
-                       else if (opcode & 0x80)
-                               _tcscat(instrname, _T("IC"));
-                       else if (opcode & 0x40)
-                               _tcscat(instrname, _T("DC"));
-                       else
-                               _tcscat(instrname, _T("?"));
-                       if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
-                               TCHAR *p = instrname + _tcslen(instrname);
-                               _stprintf(p, _T(",(A%d)"), opcode & 7);
-                       }
-               } else if (lookup->mnemo == i_MOVE16) {
-                       TCHAR *p = instrname + _tcslen(instrname);
-                       if (opcode & 0x20) {
-                               _stprintf(p, _T("(A%d)+,(A%d)+"), opcode & 7, (extra >> 12) & 7);
-                               pc += 2;
-                       } else {
-                               uae_u32 addr = get_long_debug(pc + 2);
-                               int ay = opcode & 7;
-                               pc += 4;
-                               switch ((opcode >> 3) & 3)
-                               {
-                               case 0:
-                                       _stprintf(p, _T("(A%d)+,$%08x"), ay, addr);
-                                       break;
-                               case 1:
-                                       _stprintf(p, _T("$%08x,(A%d)+"), addr, ay);
-                                       break;
-                               case 2:
-                                       _stprintf(p, _T("(A%d),$%08x"), ay, addr);
-                                       break;
-                               case 3:
-                                       _stprintf(p, _T("$%08x,(A%d)"), addr, ay);
-                                       break;
-                               }
-                       }
-               } else if (lookup->mnemo == i_FPP) {
-                       TCHAR *p;
-                       int ins = extra & 0x3f;
-                       int size = (extra >> 10) & 7;
-
-                       pc += 2;
-                       if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7)
-                               fpdata fp;
-                               fpu_get_constant(&fp, extra);
-                               _stprintf(instrname, _T("FMOVECR.X #0x%02x [%s],FP%d"), extra & 0x7f, fpp_print(&fp, 0), (extra >> 7) & 7);
-                       } else if ((extra & 0x8000) == 0x8000) { // FMOVEM
-                               int dr = (extra >> 13) & 1;
-                               int mode;
-                               int dreg = (extra >> 4) & 7;
-                               int regmask, fpmode;
-                               
-                               if (extra & 0x4000) {
-                                       mode = (extra >> 11) & 3;
-                                       regmask = extra & 0xff;  // FMOVEM FPx
-                                       fpmode = 1;
-                                       _tcscpy(instrname, _T("FMOVEM.X "));
-                               } else {
-                                       mode = 0;
-                                       regmask = (extra >> 10) & 7;  // FMOVEM control
-                                       fpmode = 2;
-                                       _tcscpy(instrname, _T("FMOVEM.L "));
-                                       if (regmask == 1 || regmask == 2 || regmask == 4)
-                                               _tcscpy(instrname, _T("FMOVE.L "));
-                               }
-                               p = instrname + _tcslen(instrname);
-                               if (dr) {
-                                       if (mode & 1)
-                                               _stprintf(instrname, _T("D%d"), dreg);
-                                       else
-                                               movemout(instrname, regmask, dp->dmode, fpmode, false);
-                                       _tcscat(instrname, _T(","));
-                                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
-                               } else {
-                                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
-                                       p = instrname + _tcslen(instrname);
-                                       if (mode & 1)
-                                               _stprintf(p, _T(",D%d"), dreg);
-                                       else
-                                               movemout(p, regmask, dp->dmode, fpmode, true);
-                               }
-                       } else {
-                               if (fpuopcodes[ins])
-                                       _tcscpy(instrname, fpuopcodes[ins]);
-                               else
-                                       _tcscpy(instrname, _T("F?"));
-
-                               if ((extra & 0xe000) == 0x6000) { // FMOVE to memory
-                                       int kfactor = extra & 0x7f;
-                                       _tcscpy(instrname, _T("FMOVE."));
-                                       _tcscat(instrname, fpsizes[size]);
-                                       _tcscat(instrname, _T(" "));
-                                       p = instrname + _tcslen(instrname);
-                                       _stprintf(p, _T("FP%d,"), (extra >> 7) & 7);
-                                       pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
-                                       p = instrname + _tcslen(instrname);
-                                       if (size == 7) {
-                                               _stprintf(p, _T(" {D%d}"), (kfactor >> 4));
-                                       } else if (kfactor) {
-                                               if (kfactor & 0x40)
-                                                       kfactor |= ~0x3f;
-                                               _stprintf(p, _T(" {%d}"), kfactor);
-                                       }
-                               } else {
-                                       if (extra & 0x4000) { // source is EA
-                                               _tcscat(instrname, _T("."));
-                                               _tcscat(instrname, fpsizes[size]);
-                                               _tcscat(instrname, _T(" "));
-                                               pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
-                                       } else { // source is FPx
-                                               p = instrname + _tcslen(instrname);
-                                               _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7);
-                                       }
-                                       p = instrname + _tcslen(instrname);
-                                       if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7)))
-                                               _stprintf(p, _T(",FP%d"), (extra >> 7) & 7);
-                                       if (ins >= 0x30 && ins < 0x38) { // FSINCOS
-                                               p = instrname + _tcslen(instrname);
-                                               _stprintf(p, _T(",FP%d"), extra & 7);
-                                       }
-                               }
-                       }
-               } else if (lookup->mnemo == i_MMUOP030) {
-                       pc = disasm_mmu030(pc, opcode, extra, dp, instrname, &seaddr2, safemode);
-               } else if ((opcode & 0xf000) == 0xa000) {
-                       _tcscpy(instrname, _T("A-LINE"));
-               } else {
-                       if (dp->suse) {
-                               pc = ShowEA (NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
-
-                               // JSR x(a6) / JMP x(a6)
-                               if (opcode == 0x4ea8 + 6 || opcode == 0x4ee8 + 6) {
-                                       TCHAR sname[256];
-                                       if (debugger_get_library_symbol(m68k_areg(regs, 6), 0xffff0000 | extra, sname)) {
-                                               TCHAR *p = instrname + _tcslen(instrname);
-                                               _stprintf(p, _T(" %s"), sname);
-                                               resolve_if_jmp(instrname, m68k_areg(regs, 6) + (uae_s16)extra);
-                                       }
-                               }
-                               // show target address if JSR x(pc) + JMP xxxx combination
-                               if (opcode == 0x4eba && seaddr2 && instrname[0]) { // JSR x(pc)
-                                       resolve_if_jmp(instrname, seaddr2);
-                               }
-                       }
-                       if (dp->suse && dp->duse)
-                               _tcscat (instrname, _T(","));
-                       if (dp->duse) {
-                               pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
-                       }
-               }
-
-               for (i = 0; i < (pc - oldpc) / 2 && i < 5; i++) {
-                       buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2));
-               }
-               while (i++ < 5)
-                       buf = buf_out (buf, &bufsize, _T("     "));
-
-               if (illegal)
-                       buf = buf_out (buf, &bufsize, _T("[ "));
-               buf = buf_out (buf, &bufsize, instrname);
-               if (illegal)
-                       buf = buf_out (buf, &bufsize, _T(" ]"));
-
-               if (ccpt != 0) {
-                       uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
-                       if (deaddr)
-                               *deaddr = pc;
-                       if ((opcode & 0xf000) == 0xf000) {
-                               if (fpp_cond(dp->cc)) {
-                                       buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
-                               } else {
-                                       buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
-                               }
-                       } else {
-                               if (dp->mnemo == i_Bcc || dp->mnemo == i_DBcc) {
-                                       if (cctrue(dp->cc)) {
-                                               buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
-                                       } else {
-                                               buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
-                                       }
-                               } else {
-                                       if (cctrue(dp->cc)) {
-                                               buf = buf_out(buf, &bufsize, _T(" (T)"));
-                                       } else {
-                                               buf = buf_out(buf, &bufsize, _T(" (F)"));
-                                       }
-                               }
-                       }
-               } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
-                       if (deaddr)
-                               *deaddr = pc;
-                       buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2);
-               }
-               buf = buf_out (buf, &bufsize, _T("\n"));
-
-               for (uaecptr segpc = oldpc; segpc < pc; segpc++) {
-                       TCHAR segout[256];
-                       if (debugmem_get_symbol(segpc, segout, sizeof(segout) / sizeof(TCHAR))) {
-                               _tcscat(segout, _T(":\n"));
-                               if (bufsize > _tcslen(segout)) {
-                                       memmove(symbolpos + _tcslen(segout), symbolpos, (_tcslen(symbolpos) + 1) * sizeof(TCHAR));
-                                       memcpy(symbolpos, segout, _tcslen(segout) * sizeof(TCHAR));
-                                       bufsize -= _tcslen(segout);
-                                       buf += _tcslen(segout);
-                                       symbolpos += _tcslen(segout);
-                               }
-                       }
-               }
-
-               int srcline = -1;
-               for (uaecptr segpc = oldpc; segpc < pc; segpc++) {
-                       TCHAR sourceout[256];
-                       int line = debugmem_get_sourceline(segpc, sourceout, sizeof(sourceout) / sizeof(TCHAR));
-                       if (line < 0)
-                               break;
-                       if (srcline != line) {
-                               if (srcline < 0)
-                                       buf = buf_out(buf, &bufsize, _T("\n"));
-                               buf = buf_out(buf, &bufsize, sourceout);
-                               srcline = line;
-                       }
-               }
-               if (srcline >= 0) {
-                       buf = buf_out(buf, &bufsize, _T("\n"));
-               }
-
-               if (illegal)
-                       pc =  m68kpc_illg;
-       }
-       if (nextpc)
-               *nextpc = pc;
-       if (seaddr)
-               *seaddr = seaddr2;
-       if (deaddr)
-               *deaddr = deaddr2;
-}
-
-void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc)
-{
-       TCHAR *buf;
-
-       buf = xcalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
-       if (!buf)
-               return;
-       m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, seaddr, deaddr, lastpc, 1);
-       xfree (buf);
-}
-void m68k_disasm (uaecptr addr, uaecptr *nextpc, uaecptr lastpc, int cnt)
-{
-       TCHAR *buf;
-
-       buf = xcalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
-       if (!buf)
-               return;
-       m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, NULL, NULL, lastpc, 0);
-       console_out_f (_T("%s"), buf);
-       xfree (buf);
-}
-
-/*************************************************************
-Disasm the m68kcode at the given address into instrname
-and instrcode
-*************************************************************/
-void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc, uaecptr lastpc)
-{
-       TCHAR *ccpt;
-       uae_u32 opcode;
-       struct mnemolookup *lookup;
-       struct instr *dp;
-       uaecptr pc, oldpc;
-
-       pc = oldpc = addr;
-       opcode = get_word_debug (pc);
-       if (cpufunctbl[opcode] == op_illg_1) {
-               opcode = 0x4AFC;
-       }
-       dp = table68k + opcode;
-       for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
-
-       pc += 2;
-
-       _tcscpy (instrname, lookup->name);
-       ccpt = _tcsstr (instrname, _T("cc"));
-       if (ccpt != 0) {
-               _tcsncpy (ccpt, ccnames[dp->cc], 2);
-       }
-       switch (dp->size){
-       case sz_byte: _tcscat (instrname, _T(".B ")); break;
-       case sz_word: _tcscat (instrname, _T(".W ")); break;
-       case sz_long: _tcscat (instrname, _T(".L ")); break;
-       default: _tcscat (instrname, _T("   ")); break;
-       }
-
-       if (dp->suse) {
-               pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
-       }
-       if (dp->suse && dp->duse)
-               _tcscat (instrname, _T(","));
-       if (dp->duse) {
-               pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
-       }
-       if (instrcode)
-       {
-               int i;
-               for (i = 0; i < (pc - oldpc) / 2; i++)
-               {
-                       _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
-                       instrcode += _tcslen (instrcode);
-               }
-       }
-       if (nextpc)
-               *nextpc = pc;
-}
-
-struct cpum2c m2cregs[] = {
-       { 0, _T("SFC") },
-       { 1, _T("DFC") },
-       { 2, _T("CACR") },
-       { 3, _T("TC") },
-       { 4, _T("ITT0") },
-       { 5, _T("ITT1") },
-       { 6, _T("DTT0") },
-       { 7, _T("DTT1") },
-       { 8, _T("BUSC") },
-       { 0x800, _T("USP") },
-       { 0x801, _T("VBR") },
-       { 0x802, _T("CAAR") },
-       { 0x803, _T("MSP") },
-       { 0x804, _T("ISP") },
-       { 0x805, _T("MMUS") },
-       { 0x806, _T("URP") },
-       { 0x807, _T("SRP") },
-       { 0x808, _T("PCR") },
-    { -1, NULL }
-};
-
-void m68k_dumpstate(uaecptr *nextpc, uaecptr prevpc)
-{
-       int i, j;
-       uaecptr pc = M68K_GETPC;
-
-       for (i = 0; i < 8; i++){
-               console_out_f (_T("  D%d %08X "), i, m68k_dreg (regs, i));
-               if ((i & 3) == 3) console_out_f (_T("\n"));
+       for (i = 0; i < 8; i++){
+               console_out_f (_T("  D%d %08X "), i, m68k_dreg (regs, i));
+               if ((i & 3) == 3) console_out_f (_T("\n"));
        }
        for (i = 0; i < 8; i++){
                console_out_f (_T("  A%d %08X "), i, m68k_areg (regs, i));
@@ -9320,10 +7170,7 @@ void cpureset (void)
        uae_u16 ins;
        addrbank *ab;
 
-       if (currprefs.cpu_model == 68060 && currprefs.cpuboard_type == 0 && rtarea_base != 0xf00000) {
-               // disable FPU at reset if no accelerator board and no $f0 ROM.
-               regs.pcr |= 2;
-       }
+       maybe_disable_fpu();
        m68k_reset_delay = currprefs.reset_delay;
        set_special(SPCFLAG_CHECK);
        send_internalevent(INTERNALEVENT_CPURESET);
index 47ae3a55e505a737a62418723af05e83ed564d8b..c25e307a6f17e7e8738fbe99ac159caf48d32a6d 100644 (file)
 #include "cpummu030.h"
 #include "cpu_prefetch.h"
 
+int get_cpu_model(void)
+{
+       return currprefs.cpu_model;
+}
+
 void val_move2c2 (int regno, uae_u32 val)
 {
        switch (regno) {
@@ -436,6 +441,7 @@ uae_u32 REGPARAM2 x_get_disp_ea_020 (uae_u32 base, int idx)
                regd = (uae_s32)(uae_s16)regd;
        regd <<= (dp >> 9) & 3;
        if (dp & 0x100) {
+
                uae_s32 outer = 0;
                if (dp & 0x80)
                        base = 0;
@@ -476,11 +482,15 @@ uae_u32 REGPARAM2 x_get_disp_ea_020 (uae_u32 base, int idx)
        } else {
                v = base + (uae_s32)((uae_s8)dp) + regd;
        }
+#ifndef CPU_TESTER
        if (cycles && currprefs.cpu_cycle_exact)
                x_do_cycles (cycles * cpucycleunit);
+#endif
        return v;
 }
 
+#ifndef CPU_TESTER
+
 uae_u32 REGPARAM2 x_get_disp_ea_ce030 (uae_u32 base, int idx)
 {
        uae_u16 dp = next_iword_030ce ();
@@ -612,6 +622,8 @@ uae_u32 REGPARAM2 x_get_disp_ea_040(uae_u32 base, int idx)
        }
 }
 
+#endif
+
 /*
 * Compute exact number of CPU cycles taken
 * by DIVU and DIVS on a 68000 processor.
diff --git a/od-win32/cputester/cputester.vcxproj b/od-win32/cputester/cputester.vcxproj
new file mode 100644 (file)
index 0000000..181a18a
--- /dev/null
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Test|Win32">
+      <Configuration>Test</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Test|x64">
+      <Configuration>Test</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>16.0</VCProjectVersion>
+    <ProjectGuid>{EDD28611-EAD9-4EB5-A873-18160AC44434}</ProjectGuid>
+    <RootNamespace>cputester</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Test|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Test|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Test|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Test|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <IncludePath>$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Test|Win32'">
+    <IncludePath>$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <IncludePath>$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <IncludePath>$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Test|x64'">
+    <IncludePath>$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <IncludePath>$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\..\include;..\..;..\</AdditionalIncludeDirectories>
+      <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+      <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER</PreprocessorDefinitions>
+      <CallingConvention>FastCall</CallingConvention>
+      <CompileAs>CompileAsCpp</CompileAs>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\..\include;..\..;..\</AdditionalIncludeDirectories>
+      <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+      <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER</PreprocessorDefinitions>
+      <CallingConvention>FastCall</CallingConvention>
+      <CompileAs>CompileAsCpp</CompileAs>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Test|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\..\include;..\..;..\</AdditionalIncludeDirectories>
+      <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+      <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER</PreprocessorDefinitions>
+      <CallingConvention>FastCall</CallingConvention>
+      <CompileAs>CompileAsCpp</CompileAs>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\..\include;..\..;..\</AdditionalIncludeDirectories>
+      <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+      <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER</PreprocessorDefinitions>
+      <CallingConvention>FastCall</CallingConvention>
+      <CompileAs>CompileAsCpp</CompileAs>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Test|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\..\include;..\..;..\</AdditionalIncludeDirectories>
+      <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+      <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER</PreprocessorDefinitions>
+      <CallingConvention>FastCall</CallingConvention>
+      <CompileAs>CompileAsCpp</CompileAs>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>..\..\include;..\..;..\</AdditionalIncludeDirectories>
+      <DisableSpecificWarnings>4996</DisableSpecificWarnings>
+      <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER</PreprocessorDefinitions>
+      <CallingConvention>FastCall</CallingConvention>
+      <CompileAs>CompileAsCpp</CompileAs>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\cpudefs.cpp" />
+    <ClCompile Include="..\..\cpuemu_90_test.cpp" />
+    <ClCompile Include="..\..\cpuemu_91_test.cpp" />
+    <ClCompile Include="..\..\cpuemu_92_test.cpp" />
+    <ClCompile Include="..\..\cpustbl_test.cpp" />
+    <ClCompile Include="..\..\cputest.cpp" />
+    <ClCompile Include="..\..\cputest_support.cpp" />
+    <ClCompile Include="..\..\disasm.cpp" />
+    <ClCompile Include="..\..\fpp.cpp" />
+    <ClCompile Include="..\..\fpp_softfloat.cpp" />
+    <ClCompile Include="..\..\ini.cpp" />
+    <ClCompile Include="..\..\newcpu_common.cpp" />
+    <ClCompile Include="..\..\readcpu.cpp" />
+    <ClCompile Include="..\..\softfloat\softfloat.cpp" />
+    <ClCompile Include="..\..\softfloat\softfloat_decimal.cpp" />
+    <ClCompile Include="..\..\softfloat\softfloat_fpsp.cpp" />
+    <ClCompile Include="..\unicode.cpp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/od-win32/cputester/cputester.vcxproj.filters b/od-win32/cputester/cputester.vcxproj.filters
new file mode 100644 (file)
index 0000000..0acda36
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="Source Files\softfloat">
+      <UniqueIdentifier>{0ac04ffb-7253-4995-b1eb-8c49c2c61565}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\cpuemu_90_test.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\cputest.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\readcpu.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\cpudefs.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\cpustbl_test.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\disasm.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\cputest_support.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\unicode.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\cpuemu_92_test.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\newcpu_common.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\cpuemu_91_test.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\ini.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\fpp.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\fpp_softfloat.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\softfloat\softfloat.cpp">
+      <Filter>Source Files\softfloat</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\softfloat\softfloat_decimal.cpp">
+      <Filter>Source Files\softfloat</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\softfloat\softfloat_fpsp.cpp">
+      <Filter>Source Files\softfloat</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/od-win32/cputester_m68k/cputester_m68k.vcxproj b/od-win32/cputester_m68k/cputester_m68k.vcxproj
new file mode 100644 (file)
index 0000000..b968f61
--- /dev/null
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>16.0</VCProjectVersion>
+    <ProjectGuid>{07609D0D-FE6B-4A84-8C87-F914A4566F6F}</ProjectGuid>
+    <RootNamespace>cputesterm68k</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup />
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\cputest\68kDisass.c" />
+    <ClCompile Include="..\..\cputest\main.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/od-win32/cputester_m68k/cputester_m68k.vcxproj.filters b/od-win32/cputester_m68k/cputester_m68k.vcxproj.filters
new file mode 100644 (file)
index 0000000..abf5fcf
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\cputest\main.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\cputest\68kDisass.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
index d9daf5a47e522591c8b4087fbb991af10cefcc5e..757ebe900b8d3186f68bd88ce6bab2d8a3e445c7 100644 (file)
@@ -34,8 +34,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unpackers", "..\unpackers\u
 EndProject
 Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "wix", "..\wix\wix.wixproj", "{BE211CE1-3955-4674-A664-5038FC791980}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cputester", "..\cputester\cputester.vcxproj", "{EDD28611-EAD9-4EB5-A873-18160AC44434}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cputester_m68k", "..\cputester_m68k\cputester_m68k.vcxproj", "{07609D0D-FE6B-4A84-8C87-F914A4566F6F}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Mixed Platforms = Debug|Mixed Platforms
+               Debug|Win32 = Debug|Win32
+               Debug|x64 = Debug|x64
                FullRelease|Mixed Platforms = FullRelease|Mixed Platforms
                FullRelease|Win32 = FullRelease|Win32
                FullRelease|x64 = FullRelease|x64
@@ -50,6 +57,12 @@ Global
                Test|x64 = Test|x64
        EndGlobalSection
        GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|Win32.ActiveCfg = Debug|Win32
+               {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|Win32.Build.0 = Debug|Win32
+               {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|x64.ActiveCfg = Debug|x64
+               {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|x64.Build.0 = Debug|x64
                {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32
                {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32
                {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.FullRelease|Win32.ActiveCfg = FullRelease|Win32
@@ -74,6 +87,11 @@ Global
                {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Test|Win32.Build.0 = Test|Win32
                {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Test|x64.ActiveCfg = Test|x64
                {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Test|x64.Build.0 = Test|x64
+               {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Debug|Win32.ActiveCfg = Debug|Win32
+               {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Debug|Win32.Build.0 = Debug|Win32
+               {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Debug|x64.ActiveCfg = Debug|Win32
                {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32
                {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32
                {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.FullRelease|Win32.ActiveCfg = FullRelease|Win32
@@ -90,6 +108,11 @@ Global
                {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Test|Mixed Platforms.Build.0 = Test|Win32
                {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Test|Win32.ActiveCfg = Test|Win32
                {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Test|x64.ActiveCfg = Test|Win32
+               {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Debug|Win32.ActiveCfg = Debug|Win32
+               {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Debug|Win32.Build.0 = Debug|Win32
+               {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Debug|x64.ActiveCfg = Debug|Win32
                {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32
                {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32
                {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.FullRelease|Win32.ActiveCfg = FullRelease|Win32
@@ -106,6 +129,11 @@ Global
                {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Test|Mixed Platforms.Build.0 = Test|Win32
                {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Test|Win32.ActiveCfg = Test|Win32
                {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Test|x64.ActiveCfg = Test|Win32
+               {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Debug|Win32.ActiveCfg = Debug|Win32
+               {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Debug|Win32.Build.0 = Debug|Win32
+               {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Debug|x64.ActiveCfg = Debug|Win32
                {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32
                {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32
                {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.FullRelease|Win32.ActiveCfg = FullRelease|Win32
@@ -122,6 +150,11 @@ Global
                {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Test|Mixed Platforms.Build.0 = Test|Win32
                {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Test|Win32.ActiveCfg = Test|Win32
                {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Test|x64.ActiveCfg = Test|Win32
+               {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Debug|Win32.ActiveCfg = Debug|Win32
+               {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Debug|Win32.Build.0 = Debug|Win32
+               {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Debug|x64.ActiveCfg = Debug|Win32
                {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32
                {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32
                {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.FullRelease|Win32.ActiveCfg = FullRelease|Win32
@@ -138,6 +171,11 @@ Global
                {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Test|Mixed Platforms.Build.0 = Test|Win32
                {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Test|Win32.ActiveCfg = Test|Win32
                {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Test|x64.ActiveCfg = Test|Win32
+               {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Debug|Win32.ActiveCfg = Debug|Win32
+               {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Debug|Win32.Build.0 = Debug|Win32
+               {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Debug|x64.ActiveCfg = Debug|Win32
                {DAF2EB1A-546A-41B3-9755-187562C01E3C}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32
                {DAF2EB1A-546A-41B3-9755-187562C01E3C}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32
                {DAF2EB1A-546A-41B3-9755-187562C01E3C}.FullRelease|Win32.ActiveCfg = FullRelease|Win32
@@ -154,6 +192,11 @@ Global
                {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Test|Mixed Platforms.Build.0 = Test|Win32
                {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Test|Win32.ActiveCfg = Test|Win32
                {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Test|x64.ActiveCfg = Test|Win32
+               {C85288FB-A035-42CA-B5FB-8E6214319E97}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {C85288FB-A035-42CA-B5FB-8E6214319E97}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {C85288FB-A035-42CA-B5FB-8E6214319E97}.Debug|Win32.ActiveCfg = Debug|Win32
+               {C85288FB-A035-42CA-B5FB-8E6214319E97}.Debug|Win32.Build.0 = Debug|Win32
+               {C85288FB-A035-42CA-B5FB-8E6214319E97}.Debug|x64.ActiveCfg = Debug|Win32
                {C85288FB-A035-42CA-B5FB-8E6214319E97}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32
                {C85288FB-A035-42CA-B5FB-8E6214319E97}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32
                {C85288FB-A035-42CA-B5FB-8E6214319E97}.FullRelease|Win32.ActiveCfg = FullRelease|Win32
@@ -170,6 +213,11 @@ Global
                {C85288FB-A035-42CA-B5FB-8E6214319E97}.Test|Mixed Platforms.Build.0 = Test|Win32
                {C85288FB-A035-42CA-B5FB-8E6214319E97}.Test|Win32.ActiveCfg = Test|Win32
                {C85288FB-A035-42CA-B5FB-8E6214319E97}.Test|x64.ActiveCfg = Test|Win32
+               {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Debug|Win32.ActiveCfg = Debug|Win32
+               {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Debug|Win32.Build.0 = Debug|Win32
+               {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Debug|x64.ActiveCfg = Debug|Win32
                {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32
                {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32
                {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.FullRelease|Win32.ActiveCfg = FullRelease|Win32
@@ -186,6 +234,11 @@ Global
                {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Test|Mixed Platforms.Build.0 = Test|Win32
                {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Test|Win32.ActiveCfg = Test|Win32
                {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Test|x64.ActiveCfg = Test|Win32
+               {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Debug|Win32.ActiveCfg = Debug|Win32
+               {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Debug|Win32.Build.0 = Debug|Win32
+               {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Debug|x64.ActiveCfg = Debug|Win32
                {79BDABE6-5308-4D64-8884-A5A35909D8D3}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32
                {79BDABE6-5308-4D64-8884-A5A35909D8D3}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32
                {79BDABE6-5308-4D64-8884-A5A35909D8D3}.FullRelease|Win32.ActiveCfg = FullRelease|Win32
@@ -202,6 +255,11 @@ Global
                {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Test|Mixed Platforms.Build.0 = Test|Win32
                {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Test|Win32.ActiveCfg = Test|Win32
                {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Test|x64.ActiveCfg = Test|Win32
+               {E9F73E11-A463-45C6-A733-2BED75852BA1}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {E9F73E11-A463-45C6-A733-2BED75852BA1}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {E9F73E11-A463-45C6-A733-2BED75852BA1}.Debug|Win32.ActiveCfg = Debug|Win32
+               {E9F73E11-A463-45C6-A733-2BED75852BA1}.Debug|Win32.Build.0 = Debug|Win32
+               {E9F73E11-A463-45C6-A733-2BED75852BA1}.Debug|x64.ActiveCfg = Debug|Win32
                {E9F73E11-A463-45C6-A733-2BED75852BA1}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32
                {E9F73E11-A463-45C6-A733-2BED75852BA1}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32
                {E9F73E11-A463-45C6-A733-2BED75852BA1}.FullRelease|Win32.ActiveCfg = FullRelease|Win32
@@ -218,6 +276,11 @@ Global
                {E9F73E11-A463-45C6-A733-2BED75852BA1}.Test|Mixed Platforms.Build.0 = Test|Win32
                {E9F73E11-A463-45C6-A733-2BED75852BA1}.Test|Win32.ActiveCfg = Test|Win32
                {E9F73E11-A463-45C6-A733-2BED75852BA1}.Test|x64.ActiveCfg = Test|Win32
+               {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Debug|Win32.ActiveCfg = Debug|Win32
+               {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Debug|Win32.Build.0 = Debug|Win32
+               {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Debug|x64.ActiveCfg = Debug|Win32
                {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32
                {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.FullRelease|Mixed Platforms.Build.0 = Release|Win32
                {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.FullRelease|Win32.ActiveCfg = Release|Win32
@@ -234,6 +297,11 @@ Global
                {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Test|Mixed Platforms.Build.0 = Test|Win32
                {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Test|Win32.ActiveCfg = Test|Win32
                {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Test|x64.ActiveCfg = Test|Win32
+               {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Debug|Win32.ActiveCfg = Debug|Win32
+               {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Debug|Win32.Build.0 = Debug|Win32
+               {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Debug|x64.ActiveCfg = Debug|Win32
                {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32
                {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.FullRelease|Mixed Platforms.Build.0 = Release|Win32
                {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.FullRelease|Win32.ActiveCfg = Release|Win32
@@ -250,6 +318,12 @@ Global
                {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Test|Mixed Platforms.Build.0 = Test|Win32
                {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Test|Win32.ActiveCfg = Test|Win32
                {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Test|x64.ActiveCfg = Test|Win32
+               {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|Win32.ActiveCfg = Debug|Win32
+               {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|Win32.Build.0 = Debug|Win32
+               {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|x64.ActiveCfg = Debug|x64
+               {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|x64.Build.0 = Debug|x64
                {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32
                {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.FullRelease|Mixed Platforms.Build.0 = Release|Win32
                {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.FullRelease|Win32.ActiveCfg = Release|Win32
@@ -266,6 +340,12 @@ Global
                {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Test|Mixed Platforms.Build.0 = Test|Win32
                {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Test|Win32.ActiveCfg = Test|Win32
                {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Test|x64.ActiveCfg = Test|x64
+               {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|Win32.ActiveCfg = Debug|Win32
+               {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|Win32.Build.0 = Debug|Win32
+               {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|x64.ActiveCfg = Debug|x64
+               {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|x64.Build.0 = Debug|x64
                {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32
                {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.FullRelease|Mixed Platforms.Build.0 = Release|Win32
                {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.FullRelease|Win32.ActiveCfg = Release|Win32
@@ -282,6 +362,12 @@ Global
                {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Test|Mixed Platforms.Build.0 = Test|Win32
                {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Test|Win32.ActiveCfg = Test|Win32
                {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Test|x64.ActiveCfg = Test|x64
+               {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|Win32.ActiveCfg = Debug|Win32
+               {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|Win32.Build.0 = Debug|Win32
+               {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|x64.ActiveCfg = Debug|x64
+               {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|x64.Build.0 = Debug|x64
                {98BA115B-829F-4085-9729-ABD0D779A60A}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32
                {98BA115B-829F-4085-9729-ABD0D779A60A}.FullRelease|Mixed Platforms.Build.0 = Release|Win32
                {98BA115B-829F-4085-9729-ABD0D779A60A}.FullRelease|Win32.ActiveCfg = Release|Win32
@@ -298,6 +384,9 @@ Global
                {98BA115B-829F-4085-9729-ABD0D779A60A}.Test|Mixed Platforms.Build.0 = Test|Win32
                {98BA115B-829F-4085-9729-ABD0D779A60A}.Test|Win32.ActiveCfg = Test|Win32
                {98BA115B-829F-4085-9729-ABD0D779A60A}.Test|x64.ActiveCfg = Test|x64
+               {BE211CE1-3955-4674-A664-5038FC791980}.Debug|Mixed Platforms.ActiveCfg = Release|x86
+               {BE211CE1-3955-4674-A664-5038FC791980}.Debug|Win32.ActiveCfg = Release|x86
+               {BE211CE1-3955-4674-A664-5038FC791980}.Debug|x64.ActiveCfg = Release|x64
                {BE211CE1-3955-4674-A664-5038FC791980}.FullRelease|Mixed Platforms.ActiveCfg = Release|x86
                {BE211CE1-3955-4674-A664-5038FC791980}.FullRelease|Mixed Platforms.Build.0 = Release|x86
                {BE211CE1-3955-4674-A664-5038FC791980}.FullRelease|Win32.ActiveCfg = Release|x86
@@ -313,6 +402,65 @@ Global
                {BE211CE1-3955-4674-A664-5038FC791980}.Test|Mixed Platforms.Build.0 = Release|x86
                {BE211CE1-3955-4674-A664-5038FC791980}.Test|Win32.ActiveCfg = Release|x86
                {BE211CE1-3955-4674-A664-5038FC791980}.Test|x64.ActiveCfg = Release|x86
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|Win32.ActiveCfg = Debug|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|Win32.Build.0 = Debug|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|x64.ActiveCfg = Debug|x64
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|x64.Build.0 = Debug|x64
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|Mixed Platforms.Build.0 = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|Win32.ActiveCfg = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|Win32.Build.0 = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|x64.ActiveCfg = Release|x64
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|x64.Build.0 = Release|x64
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|Mixed Platforms.Build.0 = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|Win32.ActiveCfg = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|Win32.Build.0 = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|x64.ActiveCfg = Release|x64
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|x64.Build.0 = Release|x64
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|Mixed Platforms.ActiveCfg = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|Mixed Platforms.Build.0 = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|Win32.ActiveCfg = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|Win32.Build.0 = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|x64.ActiveCfg = Release|x64
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|x64.Build.0 = Release|x64
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Test|Mixed Platforms.ActiveCfg = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Test|Mixed Platforms.Build.0 = Release|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Test|Win32.ActiveCfg = Test|Win32
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Test|x64.ActiveCfg = Release|x64
+               {EDD28611-EAD9-4EB5-A873-18160AC44434}.Test|x64.Build.0 = Release|x64
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|Win32.ActiveCfg = Debug|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|Win32.Build.0 = Debug|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|x64.ActiveCfg = Debug|x64
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|x64.Build.0 = Debug|x64
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|Mixed Platforms.Build.0 = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|Win32.ActiveCfg = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|Win32.Build.0 = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|x64.ActiveCfg = Release|x64
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|x64.Build.0 = Release|x64
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|Mixed Platforms.Build.0 = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|Win32.ActiveCfg = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|Win32.Build.0 = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|x64.ActiveCfg = Release|x64
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|x64.Build.0 = Release|x64
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|Mixed Platforms.ActiveCfg = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|Mixed Platforms.Build.0 = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|Win32.ActiveCfg = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|Win32.Build.0 = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|x64.ActiveCfg = Release|x64
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|x64.Build.0 = Release|x64
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|Mixed Platforms.ActiveCfg = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|Mixed Platforms.Build.0 = Release|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|Win32.ActiveCfg = Debug|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|Win32.Build.0 = Debug|Win32
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|x64.ActiveCfg = Release|x64
+               {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|x64.Build.0 = Release|x64
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
index 209a0ecd7f7d38a936671667853a01b4b53e72ca..5663c22cdf6c686cbe946f573dd6ecf3353beaf1 100644 (file)
@@ -47,7 +47,7 @@
     <ProjectGuid>{4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}</ProjectGuid>
     <RootNamespace>winuae</RootNamespace>
     <TargetPlatformVersion>8.1</TargetPlatformVersion>
-    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='FullRelease|Win32'" Label="Configuration">
     <TargetName Condition="'$(Configuration)|$(Platform)'=='ReleaseXP|x64'">winuae64</TargetName>
     <TargetName Condition="'$(Configuration)|$(Platform)'=='Test|x64'">winuae64</TargetName>
     <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">winuae64</TargetName>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\ucrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\winrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\um;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\shared;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\km;c:\dev\include;$(IncludePath)</IncludePath>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='ReleaseXP|Win32'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\ucrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\winrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\um;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\shared;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\km;c:\dev\include;$(IncludePath)</IncludePath>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Test|Win32'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\ucrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\winrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\um;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\shared;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\km;c:\dev\include;$(IncludePath)</IncludePath>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath)</IncludePath>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='ReleaseXP|Win32'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath)</IncludePath>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Test|Win32'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath)</IncludePath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\dev\lib;$(LibraryPath)</LibraryPath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='ReleaseXP|Win32'">C:\dev\lib;$(LibraryPath)</LibraryPath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Test|Win32'">C:\dev\lib;$(LibraryPath)</LibraryPath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\dev\lib;$(LibraryPath)</LibraryPath>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\ucrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\winrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\um;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\shared;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\km;c:\dev\include;$(IncludePath)</IncludePath>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='FullRelease|Win32'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\ucrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\winrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\um;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\shared;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\km;c:\dev\include;$(IncludePath)</IncludePath>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath)</IncludePath>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='FullRelease|Win32'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath)</IncludePath>
     <ReferencePath Condition="'$(Configuration)|$(Platform)'=='FullRelease|Win32'">$(VC_ReferencesPath_x86);</ReferencePath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='FullRelease|Win32'">C:\dev\lib;$(LibraryPath)</LibraryPath>
     <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</EmbedManifest>
     <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Test|Win32'">true</EmbedManifest>
     <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EmbedManifest>
     <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='FullRelease|Win32'">true</EmbedManifest>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\ucrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\winrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\um;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\shared;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\km;c:\dev\include;$(IncludePath)</IncludePath>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath)</IncludePath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\dev\lib\x64;$(LibraryPath)</LibraryPath>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\ucrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\winrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\um;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\shared;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\km;c:\dev\include;$(IncludePath)</IncludePath>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='ReleaseXP|x64'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\ucrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\winrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\um;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\shared;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\km;c:\dev\include;$(IncludePath)</IncludePath>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Test|x64'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\ucrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\winrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\um;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\shared;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\km;c:\dev\include;$(IncludePath)</IncludePath>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath)</IncludePath>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='ReleaseXP|x64'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath)</IncludePath>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Test|x64'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath)</IncludePath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\dev\lib\x64;$(LibraryPath)</LibraryPath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='ReleaseXP|x64'">C:\dev\lib\x64;$(LibraryPath)</LibraryPath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Test|x64'">C:\dev\lib\x64;$(LibraryPath)</LibraryPath>
-    <IncludePath Condition="'$(Configuration)|$(Platform)'=='FullRelease|x64'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\ucrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\winrt;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\um;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\shared;$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.17763.0\km;c:\dev\include;$(IncludePath)</IncludePath>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='FullRelease|x64'">$(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath)</IncludePath>
     <LibraryPath Condition="'$(Configuration)|$(Platform)'=='FullRelease|x64'">C:\dev\lib\x64;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Test|x64'">
     <ClCompile Include="..\..\debugmem.cpp" />
     <ClCompile Include="..\..\def_icons.cpp" />
     <ClCompile Include="..\..\devices.cpp" />
+    <ClCompile Include="..\..\disasm.cpp" />
     <ClCompile Include="..\..\dlopen.cpp" />
     <ClCompile Include="..\..\ethernet.cpp" />
     <ClCompile Include="..\..\events.cpp" />
index 67979089b9b92b3883175851e7b65da6268df5ca..c5c520e2ef04918aa5e19263aa6b71df210a7178 100644 (file)
     <ClCompile Include="..\..\pcem\mouse_ps2.cpp">
       <Filter>x86</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\disasm.cpp">
+      <Filter>win32</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\resources\35floppy.ico">
index e6f8bb5e8f1352f93f56e5e97dbc56c866be5fc2..0f0b21e82aaab3b2ebb6920cd49aec1f60f0fb26 100644 (file)
@@ -264,12 +264,14 @@ out1:
                int usesrc = 0, usedst = 0;
                int srctype = 0;
                int srcpos = -1, dstpos = -1;
+               int usecc = 0;
 
                amodes srcmode = am_unknown, destmode = am_unknown;
                int srcreg = -1, destreg = -1;
 
-               for (i = 0; i < lastbit; i++)
+               for (i = 0; i < lastbit; i++) {
                        bitcnt[i] = bitval[i] = 0;
+               }
 
                vmsk = 1 << id.n_variable;
 
@@ -285,6 +287,8 @@ out1:
                                bitcnt[currbit]++;
                                bitval[currbit] <<= 1;
                                bitval[currbit] |= bit_set;
+                               if (currbit == bitC || currbit == bitc)
+                                       usecc = 1;
                        }
                }
 
@@ -717,6 +721,8 @@ endofline:
                        table68k[opc].mnemo = lookuptab[find].mnemo;
                }
                table68k[opc].cc = bitval[bitc];
+               table68k[opc].ccuse = usecc != 0;
+
                mnemo = table68k[opc].mnemo;
                if (mnemo == i_BTST
                        || mnemo == i_BSET
index 2c0eb5a4d879bc2143510bad43dbfad5130064ca..ccb7f5a974df1f91bccb9c55c42bd56534500c95 100644 (file)
@@ -325,7 +325,7 @@ static int32_t getDecimalExponent(int32_t aExp, uint64_t aSig)
                zSig0 &= ~(((int64_t)(zSig1<<1) == 0) & 1);
        }
        
-       zExp = zSign ? -zSig0 : zSig0;
+       zExp = zSign ? (0 - zSig0) : zSig0;
 
        return zExp;
 }