*.idb
*.res
*.pch
-*.ini
release
debug
bin
/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
*.sqlite
*.db-shm
*.db-wal
+*.o
--- /dev/null
+
+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;
+}
--- /dev/null
+
+#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(®s, 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;
+}
--- /dev/null
+/***
+ * 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;
+ }
+}
--- /dev/null
+/*
+ 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 */
--- /dev/null
+
+ .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
+
--- /dev/null
+
+ .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
--- /dev/null
+
+#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)
--- /dev/null
+
+[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
--- /dev/null
+
+#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, ®s.fpuregs[mode]);
+ } else {
+ p = restore_value(p, ®s.regs[mode], &size);
+ }
+ } else if (mode == CT_SR) {
+ int size;
+ p = restore_value(p, ®s.sr, &size);
+ } else if (mode == CT_FPIAR) {
+ int size;
+ p = restore_value(p, ®s.fpiar, &size);
+ } else if (mode == CT_FPCR) {
+ int size;
+ p = restore_value(p, ®s.fpcr, &size);
+ } else if (mode == CT_FPSR) {
+ int size;
+ p = restore_value(p, ®s.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 = ®s.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(®s, 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(®s, 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, ®s, 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, ®s, 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);
+ }
+}
--- /dev/null
+
+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
--- /dev/null
+/*
+ * 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*/
--- /dev/null
+
+#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
--- /dev/null
+
+#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;
+}
#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
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
}
#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;
}
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
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
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;
// 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;
}
list <<= 1;
}
+#endif
} else {
for (int r = 0; r < 8; r++) {
uae_u32 wrd1, wrd2, wrd3;
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;
}
list <<= 1;
}
+#endif
} else {
for (int r = 0; r < 8; r++) {
uae_u32 wrd1, wrd2, wrd3;
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)
fpp_clear_status();
}
+#ifndef CPU_TESTER
+
void fpu_modechange(void)
{
uae_u32 temp_ext[8][3];
}
}
+#endif
+
#if FPU_TEST
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);
#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);
}
+#ifndef CPU_TESTER
+
uae_u8 *restore_fpu (uae_u8 *src)
{
uae_u32 w1, w2, w3;
*len = dst - dstbak;
return dstbak;
}
+
+#endif
* Copyright 1995, 1996, 1997, 1998, 1999, 2000 Bernd Schmidt
*/
+#define CPU_TESTER 0
+
#include "sysconfig.h"
#include "sysdeps.h"
#include <ctype.h>
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;
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);
_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);
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);
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);
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)
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;
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) {
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) {
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
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 {
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;
}
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);
} 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");
} 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 ();
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);
} 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 ();
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))
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));
{
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);
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);
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];
int main(int argc, char *argv[])
{
- int i;
-
read_table68k ();
do_merges ();
* 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;
}
--- /dev/null
+
+#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);
--- /dev/null
+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
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
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
#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;
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;
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;
}
#include "memory.h"
#include "custom.h"
#include "newcpu.h"
+#include "disasm.h"
#include "cpummu.h"
#include "cpummu030.h"
#include "cpu_prefetch.h"
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;
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;
{
}
-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);
{
int i, opcnt;
unsigned long opcode;
- const struct cputbl *tbl = 0;
+ const struct cputbl *tbl = NULL;
int lvl, mode;
if (!currprefs.cachesize) {
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;
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)
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);
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;
}
}
-void REGPARAM2 op_unimpl (uae_u16 opcode)
+void REGPARAM2 op_unimpl (uae_u32 opcode)
{
static int warned;
if (warned < 20) {
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;
cpu_prefs_changed_flag = 0;
in_m68k_go++;
for (;;) {
+ int restored = 0;
void (*run_func)(void);
cputrace.state = -1;
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;
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);
mmu_set_tc (regs.tcr);
}
startup = 1;
- restored = 1;
}
#endif
if (currprefs.produce_sound == 0)
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();
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));
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);
#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) {
regd = (uae_s32)(uae_s16)regd;
regd <<= (dp >> 9) & 3;
if (dp & 0x100) {
+
uae_s32 outer = 0;
if (dp & 0x80)
base = 0;
} 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 ();
}
}
+#endif
+
/*
* Compute exact number of CPU cycles taken
* by DIVU and DIVS on a 68000 processor.
--- /dev/null
+<?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
--- /dev/null
+<?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
--- /dev/null
+<?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
--- /dev/null
+<?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
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
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
{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
{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
{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
{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
{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
{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
{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
{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
{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
{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
{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
{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
{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
{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
{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
{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
<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" />
<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">
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;
bitcnt[currbit]++;
bitval[currbit] <<= 1;
bitval[currbit] |= bit_set;
+ if (currbit == bitC || currbit == bitc)
+ usecc = 1;
}
}
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
zSig0 &= ~(((int64_t)(zSig1<<1) == 0) & 1);
}
- zExp = zSign ? -zSig0 : zSig0;
+ zExp = zSign ? (0 - zSig0) : zSig0;
return zExp;
}