From 1795dc4199acd23a8771d06d5f193988fafc2306 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Wed, 7 Aug 2019 20:41:04 +0300 Subject: [PATCH] Initial CPU tester commit. --- .gitignore | 5 +- assem.cpp | 439 +++ cputest.cpp | 2556 +++++++++++++++++ cputest/68kDisass.c | 2315 +++++++++++++++ cputest/68kDisass.h | 27 + cputest/amiga.S | 74 + cputest/asm.S | 340 +++ cputest/cputest_defines.h | 35 + cputest/cputestgen.ini | 66 + cputest/main.c | 1478 ++++++++++ cputest/makefile | 26 + cputest/msc_dirent.h | 1160 ++++++++ cputest_support.cpp | 100 + disasm.cpp | 2067 +++++++++++++ fpp.cpp | 41 +- gencpu.cpp | 170 +- include/cputest.h | 58 + include/disasm.h | 10 + include/memory.h | 75 + include/newcpu.h | 2 +- include/readcpu.h | 2 +- ini.cpp | 7 +- newcpu.cpp | 2271 +-------------- newcpu_common.cpp | 12 + od-win32/cputester/cputester.vcxproj | 242 ++ od-win32/cputester/cputester.vcxproj.filters | 69 + .../cputester_m68k/cputester_m68k.vcxproj | 132 + .../cputester_m68k.vcxproj.filters | 25 + od-win32/winuae_msvc15/winuae_msvc.sln | 148 + od-win32/winuae_msvc15/winuae_msvc.vcxproj | 23 +- .../winuae_msvc15/winuae_msvc.vcxproj.filters | 3 + readcpu.cpp | 8 +- softfloat/softfloat_decimal.cpp | 2 +- 33 files changed, 11727 insertions(+), 2261 deletions(-) create mode 100644 assem.cpp create mode 100644 cputest.cpp create mode 100644 cputest/68kDisass.c create mode 100644 cputest/68kDisass.h create mode 100644 cputest/amiga.S create mode 100644 cputest/asm.S create mode 100644 cputest/cputest_defines.h create mode 100644 cputest/cputestgen.ini create mode 100644 cputest/main.c create mode 100644 cputest/makefile create mode 100644 cputest/msc_dirent.h create mode 100644 cputest_support.cpp create mode 100644 disasm.cpp create mode 100644 include/cputest.h create mode 100644 include/disasm.h create mode 100644 od-win32/cputester/cputester.vcxproj create mode 100644 od-win32/cputester/cputester.vcxproj.filters create mode 100644 od-win32/cputester_m68k/cputester_m68k.vcxproj create mode 100644 od-win32/cputester_m68k/cputester_m68k.vcxproj.filters diff --git a/.gitignore b/.gitignore index 44d2b211..c4210916 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ *.idb *.res *.pch -*.ini release debug bin @@ -63,10 +62,13 @@ aros.rom.cpp /cpuemu_40.cpp /cpuemu_50.cpp /cpustbl.cpp +/cpustbl_test.cpp /cputbl.h +/cputbl_test.h /jit/compemu.cpp /jit/compstbl.cpp /jit/comptbl.h +/cputest/data /linetoscr.cpp *.iobj *.ipdb @@ -76,3 +78,4 @@ packages.config *.sqlite *.db-shm *.db-wal +*.o diff --git a/assem.cpp b/assem.cpp new file mode 100644 index 00000000..a5f43778 --- /dev/null +++ b/assem.cpp @@ -0,0 +1,439 @@ + +static const TCHAR *fpsizes[] = { + _T("L"), + _T("S"), + _T("X"), + _T("P"), + _T("W"), + _T("D"), + _T("B"), + _T("P") +}; +static const int fpsizeconv[] = { + sz_long, + sz_single, + sz_extended, + sz_packed, + sz_word, + sz_double, + sz_byte, + sz_packed +}; +static const int datasizes[] = { + 1, + 2, + 4, + 4, + 8, + 12, + 12 +}; + +static void showea_val(TCHAR *buffer, uae_u16 opcode, uaecptr addr, int size) +{ + struct mnemolookup *lookup; + instr *table = &table68k[opcode]; + + if (addr >= 0xe90000 && addr < 0xf00000) + goto skip; + if (addr >= 0xdff000 && addr < 0xe00000) + goto skip; + + for (lookup = lookuptab; lookup->mnemo != table->mnemo; lookup++) + ; + if (!(lookup->flags & 1)) + goto skip; + buffer += _tcslen(buffer); + if (debug_safe_addr(addr, datasizes[size])) { + bool cached = false; + switch (size) + { + case sz_byte: + { + uae_u8 v = get_byte_cache_debug(addr, &cached); + uae_u8 v2 = v; + if (cached) + v2 = get_byte_debug(addr); + if (v != v2) { + _stprintf(buffer, _T(" [%02x:%02x]"), v, v2); + } else { + _stprintf(buffer, _T(" [%s%02x]"), cached ? _T("*") : _T(""), v); + } + } + break; + case sz_word: + { + uae_u16 v = get_word_cache_debug(addr, &cached); + uae_u16 v2 = v; + if (cached) + v2 = get_word_debug(addr); + if (v != v2) { + _stprintf(buffer, _T(" [%04x:%04x]"), v, v2); + } else { + _stprintf(buffer, _T(" [%s%04x]"), cached ? _T("*") : _T(""), v); + } + } + break; + case sz_long: + { + uae_u32 v = get_long_cache_debug(addr, &cached); + uae_u32 v2 = v; + if (cached) + v2 = get_long_debug(addr); + if (v != v2) { + _stprintf(buffer, _T(" [%08x:%08x]"), v, v2); + } else { + _stprintf(buffer, _T(" [%s%08x]"), cached ? _T("*") : _T(""), v); + } + } + break; + case sz_single: + { + fpdata fp; + fpp_to_single(&fp, get_long_debug(addr)); + _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0)); + } + break; + case sz_double: + { + fpdata fp; + fpp_to_double(&fp, get_long_debug(addr), get_long_debug(addr + 4)); + _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0)); + } + break; + case sz_extended: + { + fpdata fp; + fpp_to_exten(&fp, get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8)); + _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0)); + break; + } + case sz_packed: + _stprintf(buffer, _T("[%08x%08x%08x]"), get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8)); + break; + } + } +skip: + for (int i = 0; i < size; i++) { + TCHAR name[256]; + if (debugmem_get_symbol(addr + i, name, sizeof(name) / sizeof(TCHAR))) { + _stprintf(buffer + _tcslen(buffer), _T(" %s"), name); + } + } +} + +static uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name) +{ + uaecptr addr; + uae_u16 dp; + int r; + uae_u32 dispreg; + uaecptr pc = *pcp; + TCHAR mult[20]; + + dp = get_iword_debug(pc); + pc += 2; + + r = (dp & 0x7000) >> 12; // REGISTER + + dispreg = dp & 0x8000 ? m68k_areg(regs, r) : m68k_dreg(regs, r); + if (!(dp & 0x800)) { // W/L + dispreg = (uae_s32)(uae_s16)(dispreg); + } + + if (currprefs.cpu_model >= 68020) { + dispreg <<= (dp >> 9) & 3; // SCALE + } + + int m = 1 << ((dp >> 9) & 3); + mult[0] = 0; + if (m > 1) { + _stprintf(mult, _T("*%d"), m); + } + + buffer[0] = 0; + if ((dp & 0x100) && currprefs.cpu_model >= 68020) { + TCHAR dr[20]; + // Full format extension (68020+) + uae_s32 outer = 0, disp = 0; + if (dp & 0x80) { // BS (base register suppress) + base = 0; + name = NULL; + } + _stprintf(dr, _T("%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W'); + if (dp & 0x40) { // IS (index suppress) + dispreg = 0; + dr[0] = 0; + } + + _tcscpy(buffer, _T("(")); + TCHAR *p = buffer + _tcslen(buffer); + + if (dp & 3) { + // indirect + _stprintf(p, _T("[")); + p += _tcslen(p); + } else { + // (an,dn,word/long) + if (name) { + _stprintf(p, _T("%s,"), name); + p += _tcslen(p); + } + if (dr[0]) { + _stprintf(p, _T("%s%s,"), dr, mult); + p += _tcslen(p); + } + } + + if ((dp & 0x30) == 0x20) { // BD SIZE = 2 (WORD) + disp = (uae_s32)(uae_s16)get_iword_debug(pc); + _stprintf(p, _T("$%04x,"), (uae_s16)disp); + p += _tcslen(p); + pc += 2; + base += disp; + } else if ((dp & 0x30) == 0x30) { // BD SIZE = 3 (LONG) + disp = get_ilong_debug(pc); + _stprintf(p, _T("$%08x,"), disp); + p += _tcslen(p); + pc += 4; + base += disp; + } + + if (dp & 3) { + if (name) { + _stprintf(p, _T("%s,"), name); + p += _tcslen(p); + } + + if (!(dp & 0x04)) { + if (dr[0]) { + _stprintf(p, _T("%s%s,"), dr, mult); + p += _tcslen(p); + } + } + + if (p[-1] == ',') + p--; + _stprintf(p, _T("],")); + p += _tcslen(p); + + if ((dp & 0x04)) { + if (dr[0]) { + _stprintf(p, _T("%s%s,"), dr, mult); + p += _tcslen(p); + } + } + + } + + if ((dp & 0x03) == 0x02) { + outer = (uae_s32)(uae_s16)get_iword_debug(pc); + _stprintf(p, _T("$%04x,"), (uae_s16)outer); + p += _tcslen(p); + pc += 2; + } else if ((dp & 0x03) == 0x03) { + outer = get_ilong_debug(pc); + _stprintf(p, _T("$%08x,"), outer); + p += _tcslen(p); + pc += 4; + } + + if (p[-1] == ',') + p--; + _stprintf(p, _T(")")); + p += _tcslen(p); + + if ((dp & 0x4) == 0) + base += dispreg; + if (dp & 0x3) + base = get_long_debug(base); + if (dp & 0x4) + base += dispreg; + + addr = base + outer; + + _stprintf(p, _T(" == $%08x"), addr); + p += _tcslen(p); + + } else { + // Brief format extension + TCHAR regstr[20]; + uae_s8 disp8 = dp & 0xFF; + + regstr[0] = 0; + _stprintf(regstr, _T(",%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W'); + addr = base + (uae_s32)((uae_s8)disp8) + dispreg; + _stprintf(buffer, _T("(%s%s%s,$%02x) == $%08x"), name, regstr, mult, disp8, addr); + if (dp & 0x100) { + _tcscat(buffer, _T(" (68020+)")); + } + } + + *pcp = pc; + return addr; +} + +uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode) +{ + uaecptr addr = pc; + uae_s16 disp16; + uae_s32 offset = 0; + TCHAR buffer[80]; + + switch (mode){ + case Dreg: + _stprintf (buffer, _T("D%d"), reg); + break; + case Areg: + _stprintf (buffer, _T("A%d"), reg); + break; + case Aind: + _stprintf (buffer, _T("(A%d)"), reg); + addr = regs.regs[reg + 8]; + showea_val(buffer, opcode, addr, size); + break; + case Aipi: + _stprintf (buffer, _T("(A%d)+"), reg); + addr = regs.regs[reg + 8]; + showea_val(buffer, opcode, addr, size); + break; + case Apdi: + _stprintf (buffer, _T("-(A%d)"), reg); + addr = regs.regs[reg + 8]; + showea_val(buffer, opcode, addr - datasizes[size], size); + break; + case Ad16: + { + TCHAR offtxt[8]; + disp16 = get_iword_debug (pc); pc += 2; + if (disp16 < 0) + _stprintf (offtxt, _T("-$%04x"), -disp16); + else + _stprintf (offtxt, _T("$%04x"), disp16); + addr = m68k_areg (regs, reg) + disp16; + _stprintf (buffer, _T("(A%d,%s) == $%08x"), reg, offtxt, addr); + showea_val(buffer, opcode, addr, size); + } + break; + case Ad8r: + { + TCHAR name[10]; + _stprintf(name, _T("A%d"), reg); + addr = ShowEA_disp(&pc, m68k_areg(regs, reg), buffer, name); + showea_val(buffer, opcode, addr, size); + } + break; + case PC16: + disp16 = get_iword_debug (pc); pc += 2; + addr += (uae_s16)disp16; + _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr); + showea_val(buffer, opcode, addr, size); + break; + case PC8r: + { + addr = ShowEA_disp(&pc, addr, buffer, _T("PC")); + showea_val(buffer, opcode, addr, size); + } + break; + case absw: + addr = (uae_s32)(uae_s16)get_iword_debug (pc); + _stprintf (buffer, _T("$%04x"), (uae_u16)addr); + pc += 2; + showea_val(buffer, opcode, addr, size); + break; + case absl: + addr = get_ilong_debug (pc); + _stprintf (buffer, _T("$%08x"), addr); + pc += 4; + showea_val(buffer, opcode, addr, size); + break; + case imm: + switch (size){ + case sz_byte: + _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff)); + pc += 2; + break; + case sz_word: + _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff)); + pc += 2; + break; + case sz_long: + _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc))); + pc += 4; + break; + case sz_single: + { + fpdata fp; + fpp_to_single(&fp, get_ilong_debug(pc)); + _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0)); + pc += 4; + } + break; + case sz_double: + { + fpdata fp; + fpp_to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4)); + _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0)); + pc += 8; + } + break; + case sz_extended: + { + fpdata fp; + fpp_to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8)); + _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0)); + pc += 12; + break; + } + case sz_packed: + _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8)); + pc += 12; + break; + default: + break; + } + break; + case imm0: + offset = (uae_s32)(uae_s8)get_iword_debug (pc); + _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff)); + addr = pc + 2 + offset; + if ((opcode & 0xf000) == 0x6000) { + showea_val(buffer, opcode, addr, 1); + } + pc += 2; + break; + case imm1: + offset = (uae_s32)(uae_s16)get_iword_debug (pc); + buffer[0] = 0; + _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff)); + addr = pc + offset; + if ((opcode & 0xf000) == 0x6000) { + showea_val(buffer, opcode, addr, 2); + } + pc += 2; + break; + case imm2: + offset = (uae_s32)get_ilong_debug (pc); + _stprintf (buffer, _T("#$%08x"), (uae_u32)offset); + addr = pc + offset; + if ((opcode & 0xf000) == 0x6000) { + showea_val(buffer, opcode, addr, 4); + } + pc += 4; + break; + case immi: + offset = (uae_s32)(uae_s8)(reg & 0xff); + _stprintf (buffer, _T("#$%02x"), (uae_u8)offset); + addr = pc + offset; + break; + default: + break; + } + if (buf == NULL) + f_out (f, _T("%s"), buffer); + else + _tcscat (buf, buffer); + if (eaddr) + *eaddr = addr; + return pc; +} diff --git a/cputest.cpp b/cputest.cpp new file mode 100644 index 00000000..1f5149f5 --- /dev/null +++ b/cputest.cpp @@ -0,0 +1,2556 @@ + +#include "cputest.h" +#include "cputbl_test.h" +#include "readcpu.h" +#include "disasm.h" +#include "ini.h" + +#include "options.h" + +#define MAX_REGISTERS 16 + +static uae_u32 registers[] = +{ + 0x00000010, + 0x00000000, + 0xffffffff, + 0xffffff00, + 0xffff0000, + 0x80008080, + 0x7fff7fff, + 0xaaaaaaaa, + + 0x00000000, + 0x00000080, + 0x00008000, + 0x00007fff, + 0xfffffffe, + 0xffffff00, + 0x00000000, // replaced with opcode memory + 0x00000000 // replaced with stack +}; + +// TODO: fill FPU registers +static floatx80 fpuregisters[8]; +static uae_u32 fpu_fpiar, fpu_fpcr, fpu_fpsr; + +const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 }; +const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 }; + +int movem_index1[256]; +int movem_index2[256]; +int movem_next[256]; +cpuop_func *cpufunctbl[65536]; +struct cputbl_data +{ + uae_s16 length; + uae_s8 disp020[2]; + uae_u8 branch; +}; +static struct cputbl_data cpudatatbl[65536]; + +struct regstruct regs; +struct flag_struct regflags; + +static int verbose = 1; +static int feature_exception3_data = 0; +static int feature_exception3_instruction = 0; +static int feature_sr_mask = 0; +static int feature_full_extension_format = 0; +static uae_u32 feature_addressing_modes[2]; +static int ad8r[2], pc8r[2]; + +#define LOW_MEMORY_END 0x8000 +#define HIGH_MEMORY_START (0x01000000 - 0x8000) + +// large enough for RTD +#define STACK_SIZE (0x8000 + 8) +#define RESERVED_SUPERSTACK 1024 + +static uae_u32 test_low_memory_start; +static uae_u32 test_low_memory_end; +static uae_u32 test_high_memory_start; +static uae_u32 test_high_memory_end; + +static uae_u8 low_memory[32768], high_memory[32768], *test_memory; +static uae_u8 low_memory_temp[32768], high_memory_temp[32768], *test_memory_temp; +static uae_u8 dummy_memory[4]; +static uaecptr test_memory_start, test_memory_end, opcode_memory_start; +static uae_u32 test_memory_size; +static int hmem_rom, lmem_rom; +static uae_u8 *opcode_memory; +static uae_u8 *storage_buffer; +static char inst_name[16+1]; +static int storage_buffer_watermark; +static int max_storage_buffer = 1000000; + +static bool out_of_test_space; +static uaecptr out_of_test_space_addr; +static int test_exception; +static int forced_immediate_mode; +static uaecptr test_exception_addr; +static int test_exception_3_inst; +static uae_u8 imm8_cnt; +static uae_u16 imm16_cnt; +static uae_u32 imm32_cnt; +static uae_u32 addressing_mask; +static int opcodecnt; +static int cpu_stopped; +static int cpu_lvl = 0; +static int test_count; +static int testing_active; +static time_t starttime; +static int filecount; +static uae_u16 sr_undefined_mask; + +struct uae_prefs currprefs; + +struct accesshistory +{ + uaecptr addr; + uae_u32 val; + uae_u32 oldval; + int size; +}; +static int ahcnt, ahcnt2; +static int noaccesshistory = 0; + +#define MAX_ACCESSHIST 32 +static struct accesshistory ahist[MAX_ACCESSHIST]; +static struct accesshistory ahist2[MAX_ACCESSHIST]; + +#define OPCODE_AREA 32 + +static bool valid_address(uaecptr addr, int size, int w) +{ + addr &= addressing_mask; + size--; + if (addr + size < LOW_MEMORY_END) { + if (addr < test_low_memory_start) + goto oob; + // exception vectors needed during tests + if ((addr + size >= 0x0c && addr < 0x30 || (addr + size >= 0x80 && addr < 0xc0)) && regs.vbr == 0) + goto oob; + if (addr + size >= test_low_memory_end) + goto oob; + if (w && lmem_rom) + goto oob; + return 1; + } + if (addr >= HIGH_MEMORY_START && addr < HIGH_MEMORY_START + 0x8000) { + if (addr < test_high_memory_start) + goto oob; + if (addr + size >= test_high_memory_end) + goto oob; + if (w && hmem_rom) + goto oob; + return 1; + } + if (addr >= test_memory_start && addr + size < test_memory_end - RESERVED_SUPERSTACK) { + // make sure we don't modify our test instruction + if (testing_active && w) { + if (addr >= opcode_memory_start && addr + size < opcode_memory_start + OPCODE_AREA) + goto oob; + } + return 1; + } +oob: + return 0; +} + +static uae_u8 *get_addr(uaecptr addr, int size, int w) +{ + // allow debug output to read memory even if oob condition + if (w >= 0 && out_of_test_space) + goto oob; + if (!valid_address(addr, 1, w)) + goto oob; + if (size > 1) { + if (!valid_address(addr + size - 1, 1, w)) + goto oob; + } + addr &= addressing_mask; + size--; + if (addr + size < LOW_MEMORY_END) { + return low_memory + addr; + } else if (addr >= HIGH_MEMORY_START && addr < HIGH_MEMORY_START + 0x8000) { + return high_memory + (addr - HIGH_MEMORY_START); + } else if (addr >= test_memory_start && addr + size < test_memory_end - RESERVED_SUPERSTACK) { + return test_memory + (addr - test_memory_start); + } +oob: + if (w >= 0) { + if (!out_of_test_space) { + out_of_test_space = true; + out_of_test_space_addr = addr; + } + } + dummy_memory[0] = 0; + dummy_memory[1] = 0; + dummy_memory[2] = 0; + dummy_memory[3] = 0; + return dummy_memory; +} + +uae_u32 REGPARAM2 op_illg_1(uae_u32 opcode) +{ + if ((opcode & 0xf000) == 0xf000) + test_exception = 11; + else if ((opcode & 0xf000) == 0xa000) + test_exception = 10; + else + test_exception = 4; + return 0; +} +uae_u32 REGPARAM2 op_unimpl_1(uae_u32 opcode) +{ + return 0; +} +void REGPARAM2 op_unimpl(uae_u32 opcode) +{ + op_unimpl_1(opcode); +} +uae_u32 REGPARAM2 op_illg(uae_u32 opcode) +{ + return op_illg_1(opcode); +} + +uae_u16 get_word_test_prefetch(int o) +{ + // no real prefetch + if (cpu_lvl < 2) + o -= 2; + regs.irc = get_word_test(m68k_getpci() + o + 2); + return get_word_test(m68k_getpci() + o); +} + +// Move from SR does two writes to same address: +// ignore the first one +static void previoussame(uaecptr addr, int size) +{ + if (!ahcnt) + return; + struct accesshistory *ah = &ahist[ahcnt - 1]; + if (ah->addr == addr && ah->size == size) { + ahcnt--; + } +} + +void put_byte_test(uaecptr addr, uae_u32 v) +{ + uae_u8 *p = get_addr(addr, 1, 1); + if (!out_of_test_space && !noaccesshistory) { + previoussame(addr, sz_byte); + if (ahcnt >= MAX_ACCESSHIST) { + wprintf(_T("ahist overflow!")); + abort(); + } + struct accesshistory *ah = &ahist[ahcnt++]; + ah->addr = addr; + ah->val = v & 0xff; + ah->oldval = *p; + ah->size = sz_byte; + } + *p = v; +} +void put_word_test(uaecptr addr, uae_u32 v) +{ + if (addr & 1) { + put_byte_test(addr + 0, v >> 8); + put_byte_test(addr + 1, v >> 0); + } else { + uae_u8 *p = get_addr(addr, 2, 1); + if (!out_of_test_space && !noaccesshistory) { + previoussame(addr, sz_word); + if (ahcnt >= MAX_ACCESSHIST) { + wprintf(_T("ahist overflow!")); + abort(); + } + struct accesshistory *ah = &ahist[ahcnt++]; + ah->addr = addr; + ah->val = v & 0xffff; + ah->oldval = (p[0] << 8) | p[1]; + ah->size = sz_word; + } + p[0] = v >> 8; + p[1] = v & 0xff; + } +} +void put_long_test(uaecptr addr, uae_u32 v) +{ + if (addr & 1) { + put_byte_test(addr + 0, v >> 24); + put_word_test(addr + 1, v >> 8); + put_byte_test(addr + 3, v >> 0); + } else if (addr & 2) { + put_word_test(addr + 0, v >> 16); + put_word_test(addr + 2, v >> 0); + } else { + uae_u8 *p = get_addr(addr, 4, 1); + if (!out_of_test_space && !noaccesshistory) { + previoussame(addr, sz_long); + if (ahcnt >= MAX_ACCESSHIST) { + wprintf(_T("ahist overflow!")); + abort(); + } + struct accesshistory *ah = &ahist[ahcnt++]; + ah->addr = addr; + ah->val = v; + ah->oldval = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + ah->size = sz_long; + } + p[0] = v >> 24; + p[1] = v >> 16; + p[2] = v >> 8; + p[3] = v >> 0; + } +} + + +static void undo_memory(struct accesshistory *ahp, int *cntp) +{ + out_of_test_space = 0; + int cnt = *cntp; + noaccesshistory = 1; + for (int i = cnt - 1; i >= 0; i--) { + struct accesshistory *ah = &ahp[i]; + switch (ah->size) + { + case sz_byte: + put_byte_test(ah->addr, ah->oldval); + break; + case sz_word: + put_word_test(ah->addr, ah->oldval); + break; + case sz_long: + put_long_test(ah->addr, ah->oldval); + break; + } + } + noaccesshistory = 0; + if (out_of_test_space) { + wprintf(_T("undo_memory out of test space fault!?\n")); + abort(); + } +} + + +uae_u32 get_byte_test(uaecptr addr) +{ + uae_u8 *p = get_addr(addr, 1, 0); + return *p; +} +uae_u32 get_word_test(uaecptr addr) +{ + if (addr & 1) { + return (get_byte_test(addr + 0) << 8) | (get_byte_test(addr + 1) << 0); + } else { + uae_u8 *p = get_addr(addr, 2, 0); + return (p[0] << 8) | (p[1]); + } +} +uae_u32 get_long_test(uaecptr addr) +{ + if (addr & 1) { + uae_u8 v0 = get_byte_test(addr + 0); + uae_u16 v1 = get_word_test(addr + 1); + uae_u8 v3 = get_byte_test(addr + 3); + return (v0 << 24) | (v1 << 8) | (v3 << 0); + } else if (addr & 2) { + uae_u16 v0 = get_word_test(addr + 0); + uae_u16 v1 = get_word_test(addr + 2); + return (v0 << 16) | (v1 << 0); + } else { + uae_u8 *p = get_addr(addr, 4, 0); + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); + } +} + +uae_u32 get_byte_debug(uaecptr addr) +{ + uae_u8 *p = get_addr(addr, 1, -1); + return *p; +} +uae_u32 get_word_debug(uaecptr addr) +{ + uae_u8 *p = get_addr(addr, 2, -1); + return (p[0] << 8) | (p[1]); +} +uae_u32 get_long_debug(uaecptr addr) +{ + uae_u8 *p = get_addr(addr, 4, -1); + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); +} +uae_u32 get_iword_debug(uaecptr addr) +{ + return get_word_debug(addr); +} +uae_u32 get_ilong_debug(uaecptr addr) +{ + return get_long_debug(addr); +} + +uae_u32 get_byte_cache_debug(uaecptr addr, bool *cached) +{ + *cached = false; + return get_byte_test(addr); +} +uae_u32 get_word_cache_debug(uaecptr addr, bool *cached) +{ + *cached = false; + return get_word_test(addr); +} +uae_u32 get_long_cache_debug(uaecptr addr, bool *cached) +{ + *cached = false; + return get_long_test(addr); +} + +uae_u32 sfc_nommu_get_byte(uaecptr addr) +{ + return get_byte_test(addr); +} +uae_u32 sfc_nommu_get_word(uaecptr addr) +{ + return get_word_test(addr); +} +uae_u32 sfc_nommu_get_long(uaecptr addr) +{ + return get_long_test(addr); +} + +uae_u32 memory_get_byte(uaecptr addr) +{ + return get_byte_test(addr); +} +uae_u32 memory_get_word(uaecptr addr) +{ + return get_word_test(addr); +} +uae_u32 memory_get_wordi(uaecptr addr) +{ + return get_word_test(addr); +} +uae_u32 memory_get_long(uaecptr addr) +{ + return get_long_test(addr); +} +uae_u32 memory_get_longi(uaecptr addr) +{ + return get_long_test(addr); +} + +void memory_put_long(uaecptr addr, uae_u32 v) +{ + put_long_test(addr, v); +} +void memory_put_word(uaecptr addr, uae_u32 v) +{ + put_word_test(addr, v); +} +void memory_put_byte(uaecptr addr, uae_u32 v) +{ + put_byte_test(addr, v); +} + +uae_u8 *memory_get_real_address(uaecptr addr) +{ + return NULL; +} + +uae_u32 next_iword_test(void) +{ + uae_u32 v = get_word_test_prefetch(0); + regs.pc += 2; + return v; +} + +uae_u32 next_ilong_test(void) +{ + uae_u32 v = get_word_test_prefetch(0) << 16; + v |= get_word_test_prefetch(2); + regs.pc += 4; + return v; +} + +uae_u32(*x_get_long)(uaecptr); +uae_u32(*x_get_word)(uaecptr); +void (*x_put_long)(uaecptr, uae_u32); +void (*x_put_word)(uaecptr, uae_u32); + +uae_u32(*x_cp_get_long)(uaecptr); +uae_u32(*x_cp_get_word)(uaecptr); +uae_u32(*x_cp_get_byte)(uaecptr); +void (*x_cp_put_long)(uaecptr, uae_u32); +void (*x_cp_put_word)(uaecptr, uae_u32); +void (*x_cp_put_byte)(uaecptr, uae_u32); +uae_u32(*x_cp_next_iword)(void); +uae_u32(*x_cp_next_ilong)(void); + +uae_u32(*x_next_iword)(void); +uae_u32(*x_next_ilong)(void); +void (*x_do_cycles)(unsigned long); + +uae_u32(REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM; + +static int SPCFLAG_TRACE, SPCFLAG_DOTRACE; + +uae_u32 get_disp_ea_test(uae_u32 base, uae_u32 dp) +{ + int reg = (dp >> 12) & 15; + uae_s32 regd = regs.regs[reg]; + if ((dp & 0x800) == 0) + regd = (uae_s32)(uae_s16)regd; + return base + (uae_s8)dp + regd; +} + +static void activate_trace(void) +{ + SPCFLAG_TRACE = 0; + SPCFLAG_DOTRACE = 1; +} + +static void do_trace(void) +{ + if (regs.t0 && currprefs.cpu_model >= 68020) { + // this is obsolete + return; + } + if (regs.t1) { + activate_trace(); + } +} + +void REGPARAM2 MakeSR(void) +{ + regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) + | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8) + | (GET_XFLG() << 4) | (GET_NFLG() << 3) + | (GET_ZFLG() << 2) | (GET_VFLG() << 1) + | GET_CFLG()); +} +void MakeFromSR_x(int t0trace) +{ + int oldm = regs.m; + int olds = regs.s; + int oldt0 = regs.t0; + int oldt1 = regs.t1; + + SET_XFLG((regs.sr >> 4) & 1); + SET_NFLG((regs.sr >> 3) & 1); + SET_ZFLG((regs.sr >> 2) & 1); + SET_VFLG((regs.sr >> 1) & 1); + SET_CFLG(regs.sr & 1); + + if (regs.t1 == ((regs.sr >> 15) & 1) && + regs.t0 == ((regs.sr >> 14) & 1) && + regs.s == ((regs.sr >> 13) & 1) && + regs.m == ((regs.sr >> 12) & 1) && + regs.intmask == ((regs.sr >> 8) & 7)) + return; + + regs.t1 = (regs.sr >> 15) & 1; + regs.t0 = (regs.sr >> 14) & 1; + regs.s = (regs.sr >> 13) & 1; + regs.m = (regs.sr >> 12) & 1; + regs.intmask = (regs.sr >> 8) & 7; + + if (currprefs.cpu_model >= 68020) { + /* 68060 does not have MSP but does have M-bit.. */ + if (currprefs.cpu_model >= 68060) + regs.msp = regs.isp; + if (olds != regs.s) { + if (olds) { + if (oldm) + regs.msp = m68k_areg (regs, 7); + else + regs.isp = m68k_areg (regs, 7); + m68k_areg (regs, 7) = regs.usp; + } else { + regs.usp = m68k_areg (regs, 7); + m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp; + } + } else if (olds && oldm != regs.m) { + if (oldm) { + regs.msp = m68k_areg (regs, 7); + m68k_areg (regs, 7) = regs.isp; + } else { + regs.isp = m68k_areg (regs, 7); + m68k_areg (regs, 7) = regs.msp; + } + } + if (currprefs.cpu_model >= 68060) + regs.t0 = 0; + } else { + regs.t0 = regs.m = 0; + if (olds != regs.s) { + if (olds) { + regs.isp = m68k_areg (regs, 7); + m68k_areg (regs, 7) = regs.usp; + } else { + regs.usp = m68k_areg (regs, 7); + m68k_areg (regs, 7) = regs.isp; + } + } + } + + if (regs.t1 || regs.t0) { + SPCFLAG_TRACE = 1; + } else { + /* Keep SPCFLAG_DOTRACE, we still want a trace exception for + SR-modifying instructions (including STOP). */ + SPCFLAG_TRACE = 0; + } + // Stop SR-modification does not generate T0 + // If this SR modification set Tx bit, no trace until next instruction. + if ((oldt0 && t0trace && currprefs.cpu_model >= 68020) || oldt1) { + // Always trace if Tx bits were already set, even if this SR modification cleared them. + activate_trace(); + } + +} + +void REGPARAM2 MakeFromSR_T0(void) +{ + MakeFromSR_x(1); +} +void REGPARAM2 MakeFromSR(void) +{ + MakeFromSR_x(0); +} + +static void exception_check_trace(int nr) +{ + SPCFLAG_TRACE = 0; + SPCFLAG_DOTRACE = 0; + if (regs.t1 && !regs.t0) { + /* trace stays pending if exception is div by zero, chk, + * trapv or trap #x + */ + if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47)) + SPCFLAG_DOTRACE = 1; + } + regs.t1 = regs.t0 = 0; +} + +void m68k_setstopped(void) +{ + /* A traced STOP instruction drops through immediately without + actually stopping. */ + if (SPCFLAG_DOTRACE == 0) { + cpu_stopped = 1; + } else { + cpu_stopped = 0; + } +} + +void check_t0_trace(void) +{ + if (regs.t0 && currprefs.cpu_model >= 68020) { + SPCFLAG_TRACE = 0; + SPCFLAG_DOTRACE = 1; + } +} + +void cpureset(void) +{ + test_exception = 1; +} + +void exception3_read(uae_u32 opcode, uae_u32 addr) +{ + test_exception = 3; + test_exception_3_inst = 0; + test_exception_addr = addr; +} +void exception3_write(uae_u32 opcode, uae_u32 addr) +{ + test_exception = 3; + test_exception_3_inst = 0; + test_exception_addr = addr; +} +void REGPARAM2 Exception(int n) +{ + test_exception = n; + test_exception_3_inst = 0; + test_exception_addr = m68k_getpci(); +} +void REGPARAM2 Exception_cpu(int n) +{ + test_exception = n; + test_exception_3_inst = 0; + test_exception_addr = m68k_getpci(); + + bool t0 = currprefs.cpu_model >= 68020 && regs.t0; + // check T0 trace + if (t0) { + activate_trace(); + } +} +void exception3i(uae_u32 opcode, uaecptr addr) +{ + test_exception = 3; + test_exception_3_inst = 1; + test_exception_addr = addr; +} +void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc) +{ + test_exception = 3; + test_exception_3_inst = i; + test_exception_addr = addr; +} + +int cctrue(int cc) +{ + uae_u32 cznv = regflags.cznv; + + switch (cc) { + case 0: return 1; /* T */ + case 1: return 0; /* F */ + case 2: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) == 0; /* !CFLG && !ZFLG HI */ + case 3: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) != 0; /* CFLG || ZFLG LS */ + case 4: return (cznv & FLAGVAL_C) == 0; /* !CFLG CC */ + case 5: return (cznv & FLAGVAL_C) != 0; /* CFLG CS */ + case 6: return (cznv & FLAGVAL_Z) == 0; /* !ZFLG NE */ + case 7: return (cznv & FLAGVAL_Z) != 0; /* ZFLG EQ */ + case 8: return (cznv & FLAGVAL_V) == 0; /* !VFLG VC */ + case 9: return (cznv & FLAGVAL_V) != 0; /* VFLG VS */ + case 10: return (cznv & FLAGVAL_N) == 0; /* !NFLG PL */ + case 11: return (cznv & FLAGVAL_N) != 0; /* NFLG MI */ + + case 12: /* NFLG == VFLG GE */ + return ((cznv >> FLAGBIT_N) & 1) == ((cznv >> FLAGBIT_V) & 1); + case 13: /* NFLG != VFLG LT */ + return ((cznv >> FLAGBIT_N) & 1) != ((cznv >> FLAGBIT_V) & 1); + case 14: /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */ + return !(cznv & FLAGVAL_Z) && (((cznv >> FLAGBIT_N) & 1) == ((cznv >> FLAGBIT_V) & 1)); + case 15: /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */ + return (cznv & FLAGVAL_Z) || (((cznv >> FLAGBIT_N) & 1) != ((cznv >> FLAGBIT_V) & 1)); + } + return 0; +} + +static uae_u32 xorshiftstate; +static uae_u32 xorshift32(void) +{ + uae_u32 x = xorshiftstate; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + xorshiftstate = x; + return xorshiftstate; +} + +static int rand16_cnt; +static uae_u16 rand16(void) +{ + int cnt = rand16_cnt & 15; + uae_u16 v = 0; + rand16_cnt++; + if (cnt < 15) { + v = (uae_u16)xorshift32(); + if (cnt <= 6) + v &= ~0x8000; + else + v |= 0x8000; + } + if (forced_immediate_mode == 1) + v &= ~1; + if (forced_immediate_mode == 2) + v |= 1; + return v; +} +static int rand32_cnt; +static uae_u32 rand32(void) +{ + int cnt = rand32_cnt & 31; + uae_u32 v = 0; + rand32_cnt++; + if (cnt < 31) { + v = xorshift32(); + if (cnt <= 14) + v &= ~0x80000000; + else + v |= 0x80000000; + } + if (forced_immediate_mode == 1) + v &= ~1; + if (forced_immediate_mode == 2) + v |= 1; + return v; +} + +// first 3 values: positive +// next 4 values: negative +// last: zero +static int rand8_cnt; +static uae_u8 rand8(void) +{ + int cnt = rand8_cnt & 7; + uae_u8 v = 0; + rand8_cnt++; + if (cnt < 7) { + v = (uae_u8)xorshift32(); + if (cnt <= 2) + v &= ~0x80; + else + v |= 0x80; + } + if (forced_immediate_mode == 1) + v &= ~1; + if (forced_immediate_mode == 2) + v |= 1; + return v; +} + +static uae_u8 frand8(void) +{ + return (uae_u8)xorshift32(); +} + +static void fill_memory_buffer(uae_u8 *p, int size) +{ + for (int i = 0; i < size; i++) { + p[i] = frand8(); + } + // fill extra zeros + for (int i = 0; i < size; i++) { + if (frand8() < 0x70) + p[i] = 0x00; + } +} + +static void fill_memory(void) +{ + fill_memory_buffer(low_memory_temp, 32768); + fill_memory_buffer(high_memory_temp, 32768); + fill_memory_buffer(test_memory_temp, test_memory_size); +} + +static void save_memory(const TCHAR *path, const TCHAR *name, uae_u8 *p, int size) +{ + TCHAR fname[1000]; + _stprintf(fname, _T("%s%s"), path, name); + FILE *f = _tfopen(fname, _T("wb")); + if (!f) { + wprintf(_T("Couldn't open '%s'\n"), fname); + abort(); + } + fwrite(p, 1, size, f); + fclose(f); +} + + + +static uae_u8 *store_rel(uae_u8 *dst, uae_u8 mode, uae_u32 s, uae_u32 d) +{ + int diff = (uae_s32)d - (uae_s32)s; + if (diff == 0) + return dst; + if (diff >= -128 && diff < 128) { + *dst++ = mode | CT_RELATIVE_START_BYTE; + *dst++ = diff & 0xff; + } else if (diff >= -32768 && diff < 32767) { + *dst++ = mode | CT_RELATIVE_START_WORD; + *dst++ = (diff >> 8) & 0xff; + *dst++ = diff & 0xff; + } else if (d < LOW_MEMORY_END) { + *dst++ = mode | CT_ABSOLUTE_WORD; + *dst++ = (d >> 8) & 0xff; + *dst++ = d & 0xff; + } else if ((d & ~addressing_mask) == ~addressing_mask && (d & addressing_mask) >= HIGH_MEMORY_START) { + *dst++ = mode | CT_ABSOLUTE_WORD; + *dst++ = (d >> 8) & 0xff; + *dst++ = d & 0xff; + } else { + *dst++ = mode | CT_ABSOLUTE_LONG; + *dst++ = (d >> 24) & 0xff; + *dst++ = (d >> 16) & 0xff; + *dst++ = (d >> 8) & 0xff; + *dst++ = d & 0xff; + } + return dst; +} + +static uae_u8 *store_fpureg(uae_u8 *dst, uae_u8 mode, floatx80 d) +{ + *dst++ = mode | CT_SIZE_FPU; + *dst++ = (d.high >> 8) & 0xff; + *dst++ = (d.high >> 0) & 0xff; + *dst++ = (d.low >> 56) & 0xff; + *dst++ = (d.low >> 48) & 0xff; + *dst++ = (d.low >> 40) & 0xff; + *dst++ = (d.low >> 32) & 0xff; + *dst++ = (d.low >> 24) & 0xff; + *dst++ = (d.low >> 16) & 0xff; + *dst++ = (d.low >> 8) & 0xff; + *dst++ = (d.low >> 0) & 0xff; + return dst; +} + +static uae_u8 *store_reg(uae_u8 *dst, uae_u8 mode, uae_u32 s, uae_u32 d, int size) +{ + if (s == d && size < 0) + return dst; + if (((s & 0xffffff00) == (d & 0xffffff00) && size < 0) || size == sz_byte) { + *dst++ = mode | CT_SIZE_BYTE; + *dst++ = d & 0xff; + } else if (((s & 0xffff0000) == (d & 0xffff0000) && size < 0) || size == sz_word) { + *dst++ = mode | CT_SIZE_WORD; + *dst++ = (d >> 8) & 0xff; + *dst++ = d & 0xff; + } else { + *dst++ = mode | CT_SIZE_LONG; + *dst++ = (d >> 24) & 0xff; + *dst++ = (d >> 16) & 0xff; + *dst++ = (d >> 8) & 0xff; + *dst++ = d & 0xff; + } + return dst; +} + +static uae_u8 *store_mem_bytes(uae_u8 *dst, uaecptr start, int len, uae_u8 *old) +{ + if (!len) + return dst; + if (len > 32) { + wprintf(_T("too long byte count!\n")); + abort(); + } + uaecptr oldstart = start; + uae_u8 offset = 0; + // start + for (int i = 0; i < len; i++) { + uae_u8 v = get_byte_test(start); + if (v != *old) + break; + start++; + old++; + } + // end + offset = start - oldstart; + if (offset > 7) { + start -= (offset - 7); + offset = 7; + } + len -= offset; + for (int i = len - 1; i >= 0; i--) { + uae_u8 v = get_byte_test(start + i); + if (v != old[i]) + break; + len--; + } + if (!len) + return dst; + *dst++ = CT_MEMWRITES | CT_PC_BYTES; + *dst++ = (offset << 5) | (uae_u8)(len == 32 ? 0 : len); + for (int i = 0; i < len; i++) { + *dst++ = get_byte_test(start); + start++; + } + return dst; +} + +static uae_u8 *store_mem(uae_u8 *dst, int storealways) +{ + if (ahcnt == 0) + return dst; + for (int i = 0; i < ahcnt; i++) { + struct accesshistory *ah = &ahist[i]; + if (ah->oldval == ah->val && !storealways) + continue; + uaecptr addr = ah->addr; + addr &= addressing_mask; + if (addr < LOW_MEMORY_END) { + *dst++ = CT_MEMWRITE | CT_ABSOLUTE_WORD; + *dst++ = (addr >> 8) & 0xff; + *dst++ = addr & 0xff; + } else if (addr >= HIGH_MEMORY_START) { + *dst++ = CT_MEMWRITE | CT_ABSOLUTE_WORD; + *dst++ = (addr >> 8) & 0xff; + *dst++ = addr & 0xff; + } else if (addr >= opcode_memory_start && addr < opcode_memory_start + 32768) { + *dst++ = CT_MEMWRITE | CT_RELATIVE_START_WORD; + uae_u16 diff = addr - opcode_memory_start; + *dst++ = (diff >> 8) & 0xff; + *dst++ = diff & 0xff; + } else if (addr < opcode_memory_start && addr >= opcode_memory_start - 32768) { + *dst++ = CT_MEMWRITE | CT_RELATIVE_START_WORD; + uae_u16 diff = addr - opcode_memory_start; + *dst++ = (diff >> 8) & 0xff; + *dst++ = diff & 0xff; + } else { + *dst++ = CT_MEMWRITE | CT_ABSOLUTE_LONG; + *dst++ = (addr >> 24) & 0xff; + *dst++ = (addr >> 16) & 0xff; + *dst++ = (addr >> 8) & 0xff; + *dst++ = addr & 0xff; + } + dst = store_reg(dst, CT_MEMWRITE, 0, ah->oldval, ah->size); + dst = store_reg(dst, CT_MEMWRITE, 0, ah->val, ah->size); + } + return dst; +} + + +static void pl(uae_u8 *p, uae_u32 v) +{ + p[0] = v >> 24; + p[1] = v >> 16; + p[2] = v >> 8; + p[3] = v >> 0; +} + +static bool load_file(const TCHAR *path, const TCHAR *file, uae_u8 *p, int size, int offset) +{ + TCHAR fname[1000]; + if (path) { + _stprintf(fname, _T("%s%s"), path, file); + } else { + _tcscpy(fname, file); + } + FILE *f = _tfopen(fname, _T("rb")); + if (!f) + return false; + if (offset < 0) { + fseek(f, -size, SEEK_END); + } else { + fseek(f, offset, SEEK_SET); + } + int lsize = fread(p, 1, size, f); + if (lsize != size) { + wprintf(_T("Couldn't read file '%s'\n"), fname); + exit(0); + } + fclose(f); + return true; +} + +static void save_data(uae_u8 *dst, const TCHAR *dir) +{ + TCHAR path[1000]; + + if (dst == storage_buffer) + return; + + if (dst - storage_buffer > max_storage_buffer) { + wprintf(_T("data buffer overrun!\n")); + abort(); + } + + _wmkdir(dir); + _stprintf(path, _T("%s/%04d.dat"), dir, filecount); + FILE *f = _tfopen(path, _T("wb")); + if (!f) { + wprintf(_T("couldn't open '%s'\n"), path); + abort(); + } + if (filecount == 0) { + uae_u8 data[4]; + pl(data, 0x00000001); + fwrite(data, 1, 4, f); + pl(data, (uae_u32)starttime); + fwrite(data, 1, 4, f); + pl(data, (hmem_rom << 16) | lmem_rom); + fwrite(data, 1, 4, f); + pl(data, test_memory_start); + fwrite(data, 1, 4, f); + pl(data, test_memory_size); + fwrite(data, 1, 4, f); + pl(data, opcode_memory_start - test_memory_start); + fwrite(data, 1, 4, f); + pl(data, (cpu_lvl << 16) | sr_undefined_mask); + fwrite(data, 1, 4, f); + pl(data, currprefs.fpu_model); + fwrite(data, 1, 4, f); + fwrite(inst_name, 1, sizeof(inst_name) - 1, f); + fclose(f); + filecount++; + save_data(dst, dir); + } else { + uae_u8 data[4]; + pl(data, 0x00000001); + fwrite(data, 1, 4, f); + pl(data, (uae_u32)starttime); + fwrite(data, 1, 4, f); + pl(data, 0); + fwrite(data, 1, 4, f); + fwrite(data, 1, 4, f); + *dst++ = CT_END_FINISH; + fwrite(storage_buffer, 1, dst - storage_buffer, f); + fclose(f); + filecount++; + } +} + +static int full_format_cnt; + +static uaecptr putfpuimm(uaecptr pc, int opcodesize, int *isconstant) +{ + // TODO: generate FPU immediates + switch (opcodesize) + { + case 0: // L + put_long_test(pc, rand32()); + pc += 4; + break; + case 4: // W + put_word_test(pc, rand16()); + pc += 2; + break; + case 6: // B + put_word_test(pc, rand16()); + pc += 2; + break; + case 1: // S + put_long(pc, 0); + pc += 4; + break; + case 2: // X + put_long(pc, 0); + put_long(pc + 4, 0); + put_long(pc + 8, 0); + pc += 12; + break; + case 3: // P + put_long(pc, 0); + put_long(pc + 4, 0); + put_long(pc + 8, 0); + pc += 12; + break; + case 5: // D + put_long(pc, 0); + put_long(pc + 4, 0); + pc += 8; + break; + } + return pc; +} + +// generate mostly random EA. +static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct instr *dp, int *isconstant, int srcdst, int fpuopcode, int opcodesize) +{ + uaecptr old_pc = pc; + uae_u16 opcode = *opcodep; + int am = mode >= imm ? imm : mode; + + if (!((1 << am) & feature_addressing_modes[srcdst])) + return -1; + + switch (mode) + { + case Dreg: + case Areg: + case Aind: + case Aipi: + case Apdi: + break; + case Ad16: + case PC16: + put_word_test(pc, rand16()); + *isconstant = 16; + pc += 2; + break; + case Ad8r: + case PC8r: + { + uae_u16 v = rand16(); + if (!feature_full_extension_format) + v &= ~0x100; + if (mode == Ad8r) { + if ((ad8r[srcdst] & 3) == 1) + v &= ~0x100; + if ((ad8r[srcdst] & 3) == 2) + v |= 0x100; + } else if (mode == PC8r) { + if ((pc8r[srcdst] & 3) == 1) + v &= ~0x100; + if ((pc8r[srcdst] & 3) == 2) + v |= 0x100; + } + if (currprefs.cpu_model < 68020 || (v & 0x100) == 0) { + *isconstant = 16; + put_word_test(pc, v); + pc += 2; + } else { + // full format extension + // attempt to generate every possible combination, + // one by one. + for (;;) { + v &= 0xff00; + v |= full_format_cnt & 0xff; + // skip reserved combinations for now + int is = (v >> 6) & 1; + int iis = v & 7; + int sz = (v >> 4) & 3; + int bit3 = (v >> 3) & 1; + if ((is && iis >= 4) || iis == 4 || sz == 0 || bit3 == 1) { + full_format_cnt++; + continue; + } + break; + } + put_word_test(pc, v); + uaecptr pce = pc; + pc += 2; + // calculate lenght of extension + ShowEA_disp(&pce, mode == Ad8r ? regs.regs[reg + 8] : pce, NULL, NULL); + while (pc < pce) { + v = rand16(); + put_word_test(pc, v); + pc += 2; + } + *isconstant = 32; + } + break; + } + case absw: + put_word_test(pc, rand16()); + *isconstant = 16; + pc += 2; + break; + case absl: + put_long_test(pc, rand32()); + *isconstant = 32; + pc += 4; + break; + case imm: + if (fpuopcode >= 0 && opcodesize < 8) { + pc = putfpuimm(pc, opcodesize, isconstant); + } else { + if (dp->size == sz_long) { + put_long_test(pc, rand32()); + *isconstant = 32; + pc += 4; + } + else { + put_word_test(pc, rand16()); + *isconstant = 16; + pc += 2; + } + } + break; + case imm0: + { + // byte immediate but randomly fill also upper byte + uae_u16 v = rand16(); + if ((imm8_cnt & 3) == 0) + v &= 0xff; + imm8_cnt++; + put_word_test(pc, v); + *isconstant = 16; + pc += 2; + break; + } + case imm1: + { + // word immediate + if (fpuopcode >= 0) { + uae_u16 v = 0; + if (opcodesize == 7) { + // FMOVECR + v = 0x4000; + v |= opcodesize << 10; + v |= imm16_cnt & 0x3ff; + imm16_cnt++; + if ((opcode & 0x3f) != 0) + return -1; + *isconstant = 0; + if (imm16_cnt < 0x400) + *isconstant = -1; + } else if (opcodesize == 8) { + // FMOVEM/FMOVE to/from control registers + v |= 0x8000; + v |= (imm16_cnt & 15) << 11; + v |= rand16() & 0x07ff; + imm16_cnt++; + if (imm16_cnt >= 32) + *isconstant = 0; + else + *isconstant = -1; + } else { + v |= fpuopcode; + if (imm16_cnt & 1) { + // EA to FP reg + v |= 0x4000; + v |= opcodesize << 10; + imm16_cnt++; + } else { + // FP reg to FP reg + v |= ((imm16_cnt >> 1) & 7) << 10; + // clear mode/reg field + opcode &= ~0x3f; + imm16_cnt++; + if (opcodesize != 2) { + // not X: skip + return -2; + } + } + *isconstant = 16; + } + put_word_test(pc, v); + pc += 2; + } else { + if (opcodecnt == 1) { + // STOP #xxxx: test all combinations + // (also includes RTD) + put_word_test(pc, imm16_cnt++); + if (imm16_cnt == 0) + *isconstant = 0; + else + *isconstant = -1; + } else { + uae_u16 v = rand16(); + if ((imm16_cnt & 7) == 0) + v &= 0x00ff; + if ((imm16_cnt & 15) == 0) + v &= 0x000f; + imm16_cnt++; + put_word_test(pc, v); + *isconstant = 16; + } + pc += 2; + } + break; + } + case imm2: + { + // long immediate + uae_u32 v = rand32(); + if ((imm32_cnt & 7) == 0) + v &= 0x0000ffff; + imm32_cnt++; + put_long_test(pc, v); + if (imm32_cnt < 256) + *isconstant = -1; + else + *isconstant = 32; + pc += 4; + break; + } + } + *opcodep = opcode; + return pc - old_pc; +} + +static int imm_special; + +static int handle_specials_branch(uae_u16 opcode, uaecptr pc, struct instr *dp, int *isconstant) +{ + // 68020 BCC.L is BCC.B to odd address if 68000/010 + if ((opcode & 0xf0ff) == 0x60ff) { + if (currprefs.cpu_model >= 68020) { + return 0; + } + return -2; + } + return 0; +} + +static int handle_specials_stack(uae_u16 opcode, uaecptr pc, struct instr *dp, int *isconstant) +{ + int offset = 0; + if (opcode == 0x4e73 || opcode == 0x4e74 || opcode == 0x4e75 || opcode == 0x4e77) { + uae_u32 v; + uaecptr addr = regs.regs[8 + 7]; + imm_special++; + // RTE, RTD, RTS and RTR + if (opcode == 0x4e77) { + // RTR + v = imm_special; + uae_u16 ccr = v & 31; + ccr |= rand16() & ~31; + put_word_test(addr, ccr); + addr += 2; + offset += 2; + *isconstant = imm_special >= (1 << (0 + 5)) * 4 ? 0 : -1; + } else if (opcode == 0x4e77) { + // RTD + v = imm_special >> 2; + uae_u16 sr = v & 31; + sr |= (v >> 5) << 12; + put_word_test(addr, sr); + addr += 2; + offset += 2; + *isconstant = imm_special >= (1 << (4 + 5)) * 4 ? 0 : -1; + } else if (opcode == 0x4e73) { + // RTE + if (currprefs.cpu_model == 68000) { + v = imm_special >> 2; + uae_u16 sr = v & 31; + sr |= (v >> 5) << 12; + put_word_test(addr, sr); + addr += 2; + offset += 2; + } else { + // TODO 68010+ RTE + } + *isconstant = imm_special >= (1 << (4 + 5)) * 4 ? 0 : -1; + } else if (opcode == 0x4e75) { + // RTS + *isconstant = imm_special >= 256 ? 0 : -1; + } + v = rand32(); + switch (imm_special & 3) + { + case 0: + case 3: + v = opcode_memory_start + 128; + break; + case 1: + v &= 0xffff; + break; + case 2: + v = opcode_memory_start + (uae_s16)v; + break; + } + put_long_test(addr, v); + if (out_of_test_space) { + wprintf(_T("handle_specials out of bounds access!?")); + abort(); + } + } + return offset; +} + +static void execute_ins(uae_u16 opc) +{ + uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0); + uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0); + if (opc == 0x6100 + && opw1 == 0x001e +// && opw2 == 0x2770 + ) + printf(""); + + // execute instruction + SPCFLAG_TRACE = 0; + SPCFLAG_DOTRACE = 0; + + MakeFromSR(); + + testing_active = 1; + + if (SPCFLAG_TRACE) + do_trace(); + + (*cpufunctbl[opc])(opc); + + if (!test_exception) { + if (SPCFLAG_DOTRACE) + Exception(9); + + if (cpu_stopped && regs.s == 0 && currprefs.cpu_model <= 68010) { + // 68000/68010 undocumented special case: + // if STOP clears S-bit and T was not set: + // cause privilege violation exception, PC pointing to following instruction. + // If T was set before STOP: STOP works as documented. + cpu_stopped = 0; + Exception(8); + } + } + + testing_active = 0; + + if (regs.s) { + regs.regs[15] = regs.usp; + } +} + +// any instruction that can branch execution +static int isbranchinst(struct instr *dp) +{ + switch (dp->mnemo) + { + case i_Bcc: + case i_BSR: + case i_JMP: + case i_JSR: + return 1; + case i_RTS: + case i_RTR: + case i_RTD: + case i_RTE: + return 2; + case i_DBcc: + case i_FBcc: + return -1; + case i_FDBcc: + return 1; + } + return 0; +} + +// only test instructions that can have +// special trace behavior +static int is_test_trace(struct instr *dp) +{ + if (isbranchinst(dp)) + return 1; + switch (dp->mnemo) + { + case i_STOP: + case i_MV2SR: + case i_MVSR2: + return 1; + } + return 0; +} + +static int isunsupported(struct instr *dp) +{ + switch (dp->mnemo) + { + case i_MOVE2C: + case i_MOVEC2: + return 1; + case i_RTE: + if (cpu_lvl > 0) + return 1; + break; + } + return 0; + +} + +static const TCHAR *sizes[] = { _T("B"), _T("W"), _T("L") }; + +static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, int opcodesize, int fpuopcode) +{ + TCHAR dir[1000]; + uae_u8 *dst = NULL; + int mn; + int size; + bool fpumode = 0; + + uae_u32 test_cnt = 0; + + if (mnemo == NULL || mnemo[0] == 0) + return; + + size = 3; + if (fpuopcode < 0) { + if (opcodesize == 0) + size = 2; + else if (opcodesize == 4) + size = 1; + else if (opcodesize == 6) + size = 0; + } + + xorshiftstate = 1; + filecount = 0; + + struct mnemolookup *lookup = NULL; + for (int i = 0; lookuptab[i].name; i++) { + lookup = &lookuptab[i]; + if (!_tcsicmp(lookup->name, mnemo) || (lookup->friendlyname && !_tcsicmp(lookup->friendlyname, mnemo))) + break; + } + if (!lookup) { + wprintf(_T("'%s' not found.\n"), mnemo); + return; + } + mn = lookup->mnemo; + const TCHAR *mns = lookup->name; + if (fpuopcode >= 0) { + mns = fpuopcodes[fpuopcode]; + if (opcodesize == 7) + mns = _T("FMOVECR"); + if (opcodesize == 8) + mns = _T("FMOVEM"); + } + + int pathlen = _tcslen(path); + _stprintf(dir, _T("%s%s"), path, mns); + if (fpuopcode < 0) { + if (size < 3) { + _tcscat(dir, _T(".")); + _tcscat(dir, sizes[size]); + } + } else { + _tcscat(dir, _T(".")); + _tcscat(dir, fpsizes[opcodesize < 7 ? opcodesize : 2]); + } + memset(inst_name, 0, sizeof(inst_name)); + ua_copy(inst_name, sizeof(inst_name), dir + pathlen); + + opcodecnt = 0; + for (int opcode = 0; opcode < 65536; opcode++) { + struct instr *dp = table68k + opcode; + // match requested mnemonic + if (dp->mnemo != lookup->mnemo) + continue; + // match requested size + if ((size >= 0 && size <= 2) && (size != dp->size || dp->unsized)) + continue; + if (size == 3 && !dp->unsized) + continue; + // skip all unsupported instructions if not specifically testing i_ILLG + if (dp->clev > cpu_lvl && lookup->mnemo != i_ILLG) + continue; + opcodecnt++; + if (isunsupported(dp)) + return; + fpumode = currprefs.fpu_model && (opcode & 0xf000) == 0xf000; + } + + if (!opcodecnt) + return; + + wprintf(_T("%s\n"), dir); + + int quick = 0; + int rounds = 4; + int subtest_count = 0; + + int count = 0; + + registers[8 + 6] = opcode_memory_start - 0x100; + registers[8 + 7] = test_memory_end - STACK_SIZE; + + uae_u32 cur_registers[MAX_REGISTERS]; + for (int i = 0; i < MAX_REGISTERS; i++) { + cur_registers[i] = registers[i]; + } + floatx80 cur_fpuregisters[MAX_REGISTERS]; + for (int i = 0; i < 8; i++) { + cur_fpuregisters[i] = fpuregisters[i]; + } + + dst = storage_buffer; + + memcpy(low_memory, low_memory_temp, 32768); + memcpy(high_memory, high_memory_temp, 32768); + memcpy(test_memory, test_memory_temp, test_memory_size); + + full_format_cnt = 0; + + int sr_override = 0; + + for (;;) { + + if (quick) + break; + + for (int i = 0; i < MAX_REGISTERS; i++) { + dst = store_reg(dst, CT_DREG + i, 0, cur_registers[i], -1); + regs.regs[i] = cur_registers[i]; + } + for (int i = 0; i < 8; i++) { + dst = store_fpureg(dst, CT_FPREG + i, cur_fpuregisters[i]); + regs.fp[i].fpx = cur_fpuregisters[i]; + } + + for (int opcode = 0; opcode < 65536; opcode++) { + + struct instr *dp = table68k + opcode; + // match requested mnemonic + if (dp->mnemo != lookup->mnemo) + continue; + + // match requested size + if ((size >= 0 && size <= 2) && (size != dp->size || dp->unsized)) + continue; + if (size == 3 && !dp->unsized) + continue; + // skip all unsupported instructions if not specifically testing i_ILLG + if (dp->clev > cpu_lvl && lookup->mnemo != i_ILLG) + continue; + + int extra_loops = 3; + while (extra_loops-- > 0) { + + // force both odd and even immediate values + // for better address error testing + forced_immediate_mode = 0; + if ((currprefs.cpu_model == 68000 || currprefs.cpu_model == 68010) && (feature_exception3_data == 1 || feature_exception3_instruction == 1)) { + if (dp->size > 0) { + if (extra_loops == 1) + forced_immediate_mode = 1; + if (extra_loops == 0) + forced_immediate_mode = 2; + } else { + extra_loops = 0; + } + } else if (currprefs.cpu_model == 68020 && ((ad8r[0] & 3) == 2 || (pc8r[0] & 3) == 2 || (ad8r[1] & 3) == 2 || (pc8r[1] & 3) == 2)) { + ; // if only 68020+ addressing modes: do extra loops + } else { + extra_loops = 0; + } + + imm8_cnt = 0; + imm16_cnt = 0; + imm32_cnt = 0; + imm_special = 0; + + // retry few times if out of bounds access + int oob_retries = 10; + // if instruction has immediate(s), repeat instruction test multiple times + // each round generates new random immediate(s) + int constant_loops = 32; + while (constant_loops-- > 0) { + uae_u8 oldbytes[OPCODE_AREA]; + memcpy(oldbytes, opcode_memory, sizeof(oldbytes)); + + uae_u16 opc = opcode; + int isconstant_src = 0; + int isconstant_dst = 0; + int did_out_of_bounds = 0; + uae_u8 *prev_dst2 = dst; + + out_of_test_space = 0; + ahcnt = 0; + + if (opc == 0xf228) + printf(""); + if (subtest_count == 1568) + printf(""); + + + uaecptr pc = opcode_memory_start + 2; + + // create source addressing mode + if (dp->suse) { + int o = create_ea(&opc, pc, dp->smode, dp->sreg, dp, &isconstant_src, 0, fpuopcode, opcodesize); + if (o < 0) { + memcpy(opcode_memory, oldbytes, sizeof(oldbytes)); + if (o == -1) + goto nextopcode; + continue; + } + pc += o; + } + + uae_u8 *ao = opcode_memory + 2; + uae_u16 apw1 = (ao[0] << 8) | (ao[1] << 0); + uae_u16 apw2 = (ao[2] << 8) | (ao[3] << 0); + if (opc == 0x3fb2 + && apw1 == 0xa190 + && apw2 == 0x2770 + ) + printf(""); + + if (opc != opcode) { + // source EA modified opcode + dp = table68k + opc; + } + + // create destination addressing mode + if (dp->duse) { + int o = create_ea(&opc, pc, dp->dmode, dp->dreg, dp, &isconstant_dst, 1, fpuopcode, opcodesize); + if (o < 0) { + memcpy(opcode_memory, oldbytes, sizeof(oldbytes)); + if (o == -1) + goto nextopcode; + continue; + goto nextopcode; + } + pc += o; + } + + uae_u8 *bo = opcode_memory + 2; + uae_u16 bopw1 = (bo[0] << 8) | (bo[1] << 0); + uae_u16 bopw2 = (bo[2] << 8) | (bo[3] << 0); + if (opc == 0xf228 + && bopw1 == 0x003a + //&& bopw2 == 0x2770 + ) + printf(""); + + // bcc.x + pc += handle_specials_branch(opc, pc, dp, &isconstant_src); + + put_word_test(opcode_memory_start, opc); + // end word, needed to detect if instruction finished normally when + // running on real hardware. + put_word_test(pc, 0x4afc); // illegal instruction + pc += 2; + + if (isconstant_src < 0 || isconstant_dst < 0) { + constant_loops++; + quick = 1; + } else { + // the smaller the immediate, the less test loops + if (constant_loops > isconstant_src && constant_loops > isconstant_dst) + constant_loops = isconstant_dst > isconstant_src ? isconstant_dst : isconstant_src; + + // don't do extra tests if no immediates + if (!isconstant_dst && !isconstant_src) + extra_loops = 0; + } + + if (out_of_test_space) { + wprintf(_T("Setting up test instruction generated out of bounds error!?\n")); + abort(); + } + + dst = store_mem_bytes(dst, opcode_memory_start, pc - opcode_memory_start, oldbytes); + ahcnt = 0; + + + TCHAR out[256]; + uaecptr srcaddr, dstaddr; + memset(out, 0, sizeof(out)); + // disassemble and output generated instruction + for (int i = 0; i < MAX_REGISTERS; i++) { + regs.regs[i] = cur_registers[i]; + } + for (int i = 0; i < 8; i++) { + regs.fp[i].fpx = cur_fpuregisters[i]; + } + uaecptr nextpc; + m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), opcode_memory_start, &nextpc, 1, &srcaddr, &dstaddr, 0xffffffff, 0); + if (verbose) { + my_trim(out); + wprintf(_T("%08u %s"), subtest_count, out); + } +#if 0 + // can't test because dp may be empty if instruction is invalid + if (nextpc != pc - 2) { + wprintf(_T("Disassembler/generator instruction length mismatch!\n")); + abort(); + } +#endif + int bc = isbranchinst(dp); + if (bc) { + if (bc < 0) { + srcaddr = dstaddr; + } + if (bc == 2) { + // RTS and friends + int stackoffset = handle_specials_stack(opc, pc, dp, &isconstant_src); + if (isconstant_src < 0 || isconstant_dst < 0) { + constant_loops++; + quick = 0; + } + srcaddr = get_long_test(regs.regs[8 + 7] + stackoffset); + } + // branch target is not accessible? skip. + if ((srcaddr >= cur_registers[15] - 16 && srcaddr <= cur_registers[15] + 16) || ((srcaddr & 1) && !feature_exception3_instruction)) { + // lets not jump directly to stack.. + prev_dst2 = dst; + if (verbose) { + if (srcaddr & 1) + wprintf(_T(" Branch target is odd\n")); + else + wprintf(_T(" Branch target is stack\n")); + } + continue; + } + testing_active = 1; + if (!valid_address(srcaddr, 2, 1)) { + if (verbose) { + wprintf(_T(" Branch target inaccessible\n")); + } + testing_active = 0; + prev_dst2 = dst; + continue; + } else { + // branch target = generate exception + put_word_test(srcaddr, 0x4afc); + dst = store_mem(dst, 1); + memcpy(&ahist2, &ahist, sizeof(struct accesshistory) *MAX_ACCESSHIST); + ahcnt2 = ahcnt; + } + testing_active = 0; + } + + *dst++ = CT_END_INIT; + + int exception_array[256] = { 0 }; + int ok = 0; + int cnt_stopped = 0; + + uae_u16 last_sr = 0; + uae_u32 last_pc = 0; + uae_u32 last_registers[MAX_REGISTERS]; + floatx80 last_fpuregisters[8]; + uae_u32 last_fpiar = 0; + uae_u32 last_fpsr = 0; + uae_u32 last_fpcr = 0; + + int ccr_done = 0; + int prev_s_cnt = 0; + int s_cnt = 0; + int t_cnt = 0; + + int extraccr = 0; + + // extra loops for supervisor and trace + uae_u16 sr_allowed_mask = feature_sr_mask & 0xf000; + uae_u16 sr_mask_request = feature_sr_mask & 0xf000; + + for (;;) { + uae_u16 sr_mask = 0; + + if (extraccr & 1) + sr_mask |= 0x2000; // S + if (extraccr & 2) + sr_mask |= 0x4000; // T0 + if (extraccr & 4) + sr_mask |= 0x8000; // T1 + if (extraccr & 8) + sr_mask |= 0x1000; // M + + if((sr_mask & ~sr_allowed_mask) || (sr_mask & ~sr_mask_request)) + goto nextextra; + + if (extraccr) { + *dst++ = (uae_u8)extraccr; + } + + // Test every CPU CCR or FPU SR/rounding/precision combination + for (int ccr = 0; ccr < (fpumode ? 256 : 32); ccr++) { + + bool skipped = false; + + out_of_test_space = 0; + test_exception = 0; + cpu_stopped = 0; + ahcnt = 0; + + memset(®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 ''\n")); + return 0; + } + + TCHAR *modep = mode; + while(modep) { + + int all = 0; + int mnemo = -1; + int fpuopcode = -1; + int sizes = -1; + + if (!_tcsicmp(mode, _T("all"))) { + + verbose = 0; + for (int j = 1; lookuptab[j].name; j++) { + for (int i = 0; i < 8; i++) { + test_mnemo(path, lookuptab[j].name, i, fpuopcode); + } + } + // illg last. All currently selected CPU model's unsupported opcodes + // (illegal instruction, a-line and f-line) + for (int i = 0; i < 8; i++) { + test_mnemo(path, lookuptab[0].name, i, fpuopcode); + } + break; + } + + TCHAR *sp = _tcschr(modep, ','); + if (sp) + *sp++ = 0; + TCHAR modetxt[100]; + _tcscpy(modetxt, modep); + my_trim(modetxt); + TCHAR *s = _tcschr(modetxt, '.'); + if (s) { + *s = 0; + TCHAR c = _totlower(s[1]); + if (c == 'b') + sizes = 6; + if (c == 'w') + sizes = 4; + if (c == 'l') + sizes = 0; + if (c == 'u') + sizes = 8; + if (c == 's') + sizes = 1; + if (c == 'x') + sizes = 2; + if (c == 'p') + sizes = 3; + if (c == 'd') + sizes = 5; + } + for (int j = 0; lookuptab[j].name; j++) { + if (!_tcsicmp(modetxt, lookuptab[j].name)) { + mnemo = j; + break; + } + } + if (mnemo < 0) { + if (_totlower(modetxt[0]) == 'f') { + if (!_tcsicmp(modetxt, _T("fmovecr"))) { + mnemo = i_FPP; + sizes = 7; + fpuopcode = 0; + } else if (!_tcsicmp(modetxt, _T("fmovem"))) { + mnemo = i_FPP; + sizes = 8; + fpuopcode = 0; + } else { + for (int i = 0; i < 64; i++) { + if (fpuopcodes[i] && !_tcsicmp(modetxt, fpuopcodes[i])) { + mnemo = i_FPP; + fpuopcode = i; + break; + } + } + } + } + if (mnemo < 0) { + wprintf(_T("Couldn't find '%s'\n"), modetxt); + return 0; + } + } + + if (mnemo >= 0 && sizes < 0) { + if (fpuopcode >= 0) { + for (int i = 0; i < 8; i++) { + test_mnemo(path, lookuptab[mnemo].name, i, fpuopcode); + } + } else { + test_mnemo(path, lookuptab[mnemo].name, 0, -1); + test_mnemo(path, lookuptab[mnemo].name, 4, -1); + test_mnemo(path, lookuptab[mnemo].name, 6, -1); + test_mnemo(path, lookuptab[mnemo].name, -1, -1); + } + } else { + test_mnemo(path, lookuptab[mnemo].name, sizes, fpuopcode); + } + + modep = sp; + } + + wprintf(_T("%d total tests generated\n"), test_count); + + return 0; +} diff --git a/cputest/68kDisass.c b/cputest/68kDisass.c new file mode 100644 index 00000000..06d90db3 --- /dev/null +++ b/cputest/68kDisass.c @@ -0,0 +1,2315 @@ +/*** + * 68k disassembler, written 2010 by Markus Fritze, www.sarnau.com + * + * This file is distributed under the GNU General Public License, version 2 + * or at your option any later version. Read the file gpl.txt for details. + ***/ + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include + +#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; iaddr; + + 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; jcount; ++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; iaddr; + 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 // # + +#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 + // – (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 + // # + 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 ,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; iop[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) + { + // ,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 + + // 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 ,FPn{k-Factor} + int src = (opcode[1] >> 10) & 7; + // ,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) + { + // ,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 + + // 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+1op[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 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 0) + strcat(hexdumpBuffer, " "); + if(j + 2 > plen) + { + sprintf(hexdumpBuffer+strlen(hexdumpBuffer), "%2.2x", Disass68kGetWord(addr+j) >> 8); + } else { + sprintf(hexdumpBuffer+strlen(hexdumpBuffer), "%4.4x", Disass68kGetWord(addr+j)); + } + } + + lineBuffer[0] = 0; + if(optionPosAddress >= 0) + Disass68kComposeStr(lineBuffer, addressBuffer, optionPosAddress, 0); + if(optionPosHexdump >= 0) + Disass68kComposeStr(lineBuffer, hexdumpBuffer, optionPosHexdump, optionPosLabel); + if(optionPosLabel >= 0) + Disass68kComposeStr(lineBuffer, labelBuffer, optionPosLabel, 0); + if(optionPosOpcode >= 0) + Disass68kComposeStr(lineBuffer, opcodeBuffer, optionPosOpcode, 0); + if(optionPosOperand >= 0) + { + size_t l = strlen(lineBuffer); + if(lineBuffer[l-1] != ' ') // force at least one space between opcode and operand + { + lineBuffer[l++] = ' '; + lineBuffer[l] = 0; + } + Disass68kComposeStr(lineBuffer, operandBuffer, optionPosOperand, 0); + } + if (optionPosComment >= 0) + { + /* show comments only if profile data is missing */ + if (commentBuffer[0]) + { + Disass68kComposeStr(lineBuffer, " ;", optionPosComment, 0); + Disass68kComposeStr(lineBuffer, commentBuffer, optionPosComment+3, 0); + } + } + addr += len; + if (f) + fprintf(f, "%s\n", lineBuffer); +// if(strstr(opcodeBuffer, "RTS") || strstr(opcodeBuffer, "RTE") || strstr(opcodeBuffer, "JMP") +// || strstr(opcodeBuffer, "rts") || strstr(opcodeBuffer, "rte") || strstr(opcodeBuffer, "jmp")) +// fprintf(f, "\n"); + } + if (nextpc) + *nextpc = addr; +} + + +/** + * Calculate next PC address from given one, without output + * @return next PC address + */ +Uint32 Disasm_GetNextPC(Uint32 pc) +{ + uaecptr nextpc; + Disass68k_loop (NULL, pc, &nextpc, 1); + return nextpc; +} + +/** + * Set CPU and FPU mask used for disassembly (when changed from the UI or the options) + */ +void Disasm_SetCPUType ( int CPU , int FPU ) +{ + optionCPUTypeMask = 0; + + if ( ( FPU == 68881 ) || ( FPU == 68882 ) ) + optionCPUTypeMask |= MC_FPU; + + switch ( CPU ) + { + case 0 : optionCPUTypeMask |= MC68000 ; break; + case 1 : optionCPUTypeMask |= MC68010 ; break; + case 2 : optionCPUTypeMask |= MC68020 ; break; + case 3 : optionCPUTypeMask |= MC68030 ; break; + case 4 : optionCPUTypeMask |= MC68040 ; break; + default : optionCPUTypeMask |= MC68000 ; break; + } +} diff --git a/cputest/68kDisass.h b/cputest/68kDisass.h new file mode 100644 index 00000000..80f3c96f --- /dev/null +++ b/cputest/68kDisass.h @@ -0,0 +1,27 @@ +/* + Hatari - 68kDisass.h + + This file is distributed under the GNU General Public License, version 2 + or at your option any later version. Read the file gpl.txt for details. +*/ +#ifndef HATARI_68KDISASS_H +#define HATARI_68KDISASS_H + +extern Uint32 Disasm_GetNextPC(Uint32 pc); +extern void Disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt); + +enum { + DISASM_COLUMN_ADDRESS = 0, + DISASM_COLUMN_HEXDUMP, + DISASM_COLUMN_LABEL, + DISASM_COLUMN_OPCODE, + DISASM_COLUMN_OPERAND, + DISASM_COLUMN_COMMENT, + DISASM_COLUMNS /* number of columns in disassembly output */ +}; + +#define DISASM_COLUMN_DISABLE -1 + +void Disasm_SetCPUType ( int CPU , int FPU ); + +#endif /* HATARI_68KDISASS_H */ diff --git a/cputest/amiga.S b/cputest/amiga.S new file mode 100644 index 00000000..263662a6 --- /dev/null +++ b/cputest/amiga.S @@ -0,0 +1,74 @@ + + .text + + .globl _allocate_absolute + .globl _free_absolute + .globl _touser + .globl _tosuper + .globl _testexit + .globl _get_cpu_model + + | check left mouse button/joystick fire +_testexit: + moveq #0,d0 + move.b 0xbfe001,d0 + and.b #0xc0,d0 + eor.b #0xc0,d0 + | d0 != 0: -> exit + rts + + | super mode, disable interrupts +_tosuper: + move.l a6,-(sp) + move.l 4.w,a6 + jsr -0x78(a6) | Disable + jsr -0x96(a6) | SuperState + move.w #0x0200,0xdff096 + move.l (sp)+,a6 + rts + + | back to user mode, enable interrupts +_touser: + move.l a6,-(sp) + move.l 4.w,a6 + move.l 8(sp),d0 + jsr -0x9c(a6) | UserState + move.w #0x8200,0xdff096 + jsr -0x7e(a6) | Enable + move.l (sp)+,a6 + rts + + | free absolute allocated test memory +_free_absolute: + move.l a6,-(sp) + move.l 8(sp),a1 + move.l 12(sp),d0 + move.l 4.w,a6 + jsr -0xd2(a6) | FreeMem + move.l (sp)+,a6 + rts + + | allocate absolute memory +_allocate_absolute: + move.l a6,-(sp) + move.l 8(sp),a1 + move.l 12(sp),d0 + move.l 4.w,a6 + jsr -0xcc(a6) | AllocAbs + move.l (sp)+,a6 + rts + + | return CPU model (68000=0, 68010=1, 68020=2) +_get_cpu_model: + move.l 4.w,a0 + moveq #0,d0 + move.w 0x128(a0),d1 + and.w #3,d1 + beq.s .cpudone + moveq #2,d0 + btst #1,d1 + bne.s .cpudone + moveq #1,d0 +.cpudone: + rts + diff --git a/cputest/asm.S b/cputest/asm.S new file mode 100644 index 00000000..01a3c5e4 --- /dev/null +++ b/cputest/asm.S @@ -0,0 +1,340 @@ + + .text + + .globl _execute_test000 + .globl _execute_test010 + .globl _execute_test020 + .globl _execute_testfpu + .globl _exception010 + .globl _exception020 + .globl _exceptionfpu + .globl _exceptiontable000 + .globl _setvbr + .globl _setcpu + .globl _flushcache + +S_DREG = 0 +S_AREG = S_DREG+8*4 +S_SSP = S_AREG+8*4 +S_MSP = S_SSP+4 +S_PC = S_MSP+4 +S_SR = S_PC+4 +S_EXC = S_SR+4 +S_FPU = S_EXC+4 +S_FPIAR = S_FPU+8*12 +S_FPCR = S_FPIAR+4 +S_FPSR = S_FPCR+4 + + | set CPU special registers +_setcpu: + move.l 4(sp),d1 | cpu_lvl + move.l 8(sp),a1 | new + move.l 12(sp),a0 | store + cmp.w #1,d1 + bcs.s .scend1 + move.l a0,d0 + beq.s .scend1 + movec sfc,d0 + move.l d0,(a0)+ + movec dfc,d0 + move.l d0,(a0)+ + cmp.w #2,d1 + bcs.s .scend1 + movec cacr,d0 + move.l d0,(a0)+ + movec caar,d0 + move.l d0,(a0)+ + movec msp,d0 + move.l d0,(a0)+ +.scend1: + move.l a1,d0 + beq.s .scend2 + cmp.w #1,d1 + bcs.s .scend2 + move.l (a1)+,d0 + movec d0,sfc + move.l (a1)+,d0 + movec d0,dfc + cmp.w #2,d1 + bcs.s .scend2 + move.l (a1)+,d0 + movec d0,cacr + move.l (a1)+,d0 + movec d0,caar + move.l (a1)+,d0 + move.c d0,msp +.scend2: + rts + +_flushcache: + movec cacr,d0 + bset #3,d0 + movec d0,cacr + rts + + | set and return old VBR +_setvbr: + move.l 4(sp),d1 + movec vbr,d0 + movec d1,vbr + rts + + | 68000 test entrypoint +_execute_test000: + movem.l d1-d7/a0-a6,-(sp) + move.l 14*4+4(sp),a0 | register struct + move.w sr,-(sp) + lea datapointer(pc),a1 + move.l a0,(a1)+ + move.l sp,(a1) + move.l S_SSP(a0),sp + move.l S_PC(a0),a1 + move.l a1,-(sp) + move.w (a1)+,d0 + move.w (a1),d1 + eor.w d1,d0 + move.w d0,0xdff180 | opcode^first param = background color + move.w S_SR+2(a0),-(sp) + move.l S_AREG+7*4(a0),a1 + move.l a1,USP + movem.l (a0),d0-d7/a0-a6 + + | cmp.l #0x,0x7a0000 + | bne.s .not + | clr.w 0x100 +|.not: + + rte + + | 68010+ test entrypoint +_execute_test010: + movem.l d1-d7/a0-a6,-(sp) + move.l 14*4+4(sp),a0 | register struct + move.w sr,-(sp) + lea datapointer(pc),a1 + move.l a0,(a1)+ + move.l sp,(a1) + move.l S_SSP(a0),sp + move.l S_PC(a0),a1 + clr.w -(sp) + move.l a1,-(sp) + move.w (a1)+,d0 + move.w (a1),d1 + eor.w d1,d0 + move.w d0,0xdff180 | opcode^first param = background color + move.w S_SR+2(a0),-(sp) + move.l S_AREG+7*4(a0),a1 + move.l a1,USP + movem.l (a0),d0-d7/a0-a6 + rte + + | 68020 test entrypoint +_execute_test020: + movem.l d1-d7/a0-a6,-(sp) + move.l 14*4+4(sp),a0 | register struct + move.w sr,-(sp) + lea datapointer(pc),a1 + move.l a0,(a1)+ + move.l sp,(a1) + move.l S_SSP(a0),sp + move.l S_PC(a0),a1 + clr.w -(sp) + move.l a1,-(sp) + move.w (a1)+,d0 + move.w (a1),d1 + eor.w d1,d0 + move.w d0,0xdff180 | opcode^first param = background color + move.w S_SR+2(a0),-(sp) + move.l S_AREG+7*4(a0),a1 + move.l a1,USP + move.l S_MSP(a0),a1 + movec a1,MSP + movem.l (a0),d0-d7/a0-a6 + rte + + | 68020+FPU test entrypoint +_execute_testfpu: + movem.l d1-d7/a0-a6,-(sp) + move.l 14*4+4(sp),a0 | register struct + move.w sr,-(sp) + lea datapointer(pc),a1 + move.l a0,(a1)+ + move.l sp,(a1) + move.l S_SSP(a0),sp + move.l S_PC(a0),a1 + clr.w -(sp) + move.l a1,-(sp) + move.w (a1)+,d0 + move.w (a1),d1 + eor.w d1,d0 + move.w d0,0xdff180 | opcode^first param = background color + move.w S_SR+2(a0),-(sp) + move.l S_AREG+7*4(a0),a1 + move.l a1,USP + move.l S_MSP(a0),a1 + movec a1,MSP + fmovem.x S_FPU(a0),fp0-fp7 + lea S_FPIAR(a0),a1 + fmove.l (a1)+,fpiar + fmove.l (a1)+,fpcr + fmove.l (a1)+,fpsr + movem.l (a0),d0-d7/a0-a6 + rte + + +_exceptiontable000: + bsr.s exception | 3 + bsr.s exception | 4 + bsr.s exception | 5 + bsr.s exception | 6 + bsr.s exception | 7 + bsr.s exception | 8 + bsr.s exception | 9 + bsr.s exception | 10 + bsr.s exception | 11 + bsr.s exception | 12 + bsr.s exception | 13 + bsr.s exception | 14 + bsr.s exception | 15 + bsr.s exception | 16 + bsr.s exception | 17 + bsr.s exception | 18 + bsr.s exception | 19 + bsr.s exception | 20 + bsr.s exception | 21 + bsr.s exception | 22 + bsr.s exception | 23 + bsr.s exception | 24 + bsr.s exception | 25 + bsr.s exception | 26 + bsr.s exception | 27 + bsr.s exception | 28 + bsr.s exception | 29 + bsr.s exception | 30 + bsr.s exception | 31 + bsr.s exception | 32 + bsr.s exception | 33 + bsr.s exception | 34 + bsr.s exception | 35 + bsr.s exception | 36 + bsr.s exception | 37 + bsr.s exception | 38 + bsr.s exception | 30 + bsr.s exception | 40 + bsr.s exception | 41 + bsr.s exception | 42 + bsr.s exception | 43 + bsr.s exception | 44 + bsr.s exception | 45 + bsr.s exception | 46 + bsr.s exception | 47 + nop +exception: + move.l a0,-(sp) + move.l datapointer(pc),a0 + movem.l d0-d7/a0-a6,(a0) + move.l (sp)+,8*4(a0) + move.l (sp)+,d0 + lea _exceptiontable000(pc),a1 + sub.l a1,d0 + lsr.w #1,d0 + addq.w #2,d0 + move.w d0,S_EXC+2(a0) + + cmp.w #3,d0 + bne.s .noaddresserror + move.w (sp),S_EXC+0(a0) + addq.w #8,sp +.noaddresserror: + move.w (sp)+,S_SR+2(a0) + move.l (sp)+,S_PC(a0) + + move.l USP,a1 + move.l a1,S_AREG+7*4(a0) + + move.l superstack(pc),sp + move.w (sp)+,sr + movem.l (sp)+,d1-d7/a0-a6 + rts + +_exception010: + move.l a0,-(sp) + move.l datapointer(pc),a0 + movem.l d0-d7/a0-a6,(a0) + move.l (sp)+,8*4(a0) + + move.w (sp)+,S_SR+2(a0) + move.l (sp)+,S_PC(a0) + move.w (sp),d0 + and.w #0xfff,d0 + lsr.w #2,d0 + move.w d0,S_EXC+2(a0) + + move.l USP,a1 + move.l a1,S_AREG+7*4(a0) + + move.l superstack(pc),sp + move.w (sp)+,sr + movem.l (sp)+,d1-d7/a0-a6 + rts + +_exception020: + move.l a0,-(sp) + move.l datapointer(pc),a0 + movem.l d0-d7/a0-a6,(a0) + move.l (sp)+,8*4(a0) + + move.w (sp)+,S_SR+2(a0) + move.l (sp)+,S_PC(a0) + move.w (sp),d0 + and.w #0xfff,d0 + lsr.w #2,d0 + move.w d0,S_EXC+2(a0) + + movec MSP,a1 + move.l a1,S_MSP(a0) + move.l USP,a1 + move.l a1,S_AREG+7*4(a0) + + | restore SR first, then stack + | M-bit may have been set. + move.l superstack(pc),a0 + move.w (a0)+,sr + move.l a0,sp + movem.l (sp)+,d1-d7/a0-a6 + rts + +_exceptionfpu: + move.l a0,-(sp) + move.l datapointer(pc),a0 + movem.l d0-d7/a0-a6,(a0) + move.l (sp)+,8*4(a0) + + move.w (sp)+,S_SR+2(a0) + move.l (sp)+,S_PC(a0) + move.w (sp),d0 + and.w #0xfff,d0 + lsr.w #2,d0 + move.w d0,S_EXC+2(a0) + + movec MSP,a1 + move.l a1,S_MSP(a0) + move.l USP,a1 + move.l a1,S_AREG+7*4(a0) + + fmovem.x fp0-fp7,S_FPU(a0) + lea S_FPIAR(a0),a1 + fmove.l fpiar,(a1)+ + fmove.l fpcr,(a1)+ + fmove.l fpsr,(a1)+ + + move.l superstack(pc),a0 + move.w (a0)+,sr + move.l a0,sp + movem.l (sp)+,d1-d7/a0-a6 + rts + +datapointer: + dc.l 0 +superstack: + dc.l 0 diff --git a/cputest/cputest_defines.h b/cputest/cputest_defines.h new file mode 100644 index 00000000..35044293 --- /dev/null +++ b/cputest/cputest_defines.h @@ -0,0 +1,35 @@ + +#define CT_FPREG 0 +#define CT_DREG 0 +#define CT_AREG 8 +#define CT_SSP 16 +#define CT_MSP 17 +#define CT_SR 18 +#define CT_PC 19 +#define CT_FPIAR 20 +#define CT_FPSR 21 +#define CT_FPCR 22 +#define CT_MEMWRITE 30 +#define CT_MEMWRITES 31 +#define CT_DATA_MASK 31 +#define CT_EXCEPTION_MASK 63 + +#define CT_SIZE_BYTE (0 << 5) +#define CT_SIZE_WORD (1 << 5) +#define CT_SIZE_LONG (2 << 5) +#define CT_SIZE_FPU (3 << 5) // CT_DREG -> CT_FPREG +#define CT_SIZE_MASK (3 << 5) + +// if MEMWRITE or PC +#define CT_RELATIVE_START_WORD (0 << 5) // word +#define CT_ABSOLUTE_WORD (1 << 5) +#define CT_ABSOLUTE_LONG (2 << 5) +// if MEMWRITES +#define CT_PC_BYTES (3 << 5) +// if PC +#define CT_RELATIVE_START_BYTE (3 << 5) + +#define CT_END 0x80 +#define CT_END_FINISH 0xff +#define CT_END_INIT (0x80 | 0x40) +#define CT_END_SKIP (0x80 | 0x40 | 0x01) diff --git a/cputest/cputestgen.ini b/cputest/cputestgen.ini new file mode 100644 index 00000000..ca12bd0c --- /dev/null +++ b/cputest/cputestgen.ini @@ -0,0 +1,66 @@ + +[cputest] + +; CPU model (68000, 68020). +; Always select 68020 when testing FPU instructions, even if test hardware CPU is 68040 or 68060. +cpu=68000 + +; FPU model (empty string or 0, 68881, 68882, 68040, 68060) +; Enable only when testing FPU. Enabled FPU mode will slow down execution. +fpu= + +; Write generated instructions to standard output. Always disabled in "all" mode. +verbose=1 + +; Where to generate test files +path=data/ + +; Low address space limits (0x0000 to 0x8000 is complete space) +test_low_memory_start=0x0000 +test_low_memory_end=0x8000 + +; High address space limits (0x00ff8000 to 0x01000000 is complete space) +test_high_memory_start=0x00ff8000 +test_high_memory_end=0x01000000 + +; ROM high address space +high_rom=D:\amiga\roms\Kickstart v3.1 rev 40.63 (1993)(Commodore)(A500-A600-A2000)[!].rom + +; main test memory start and size (real hardware must have RAM in same address space) +test_memory_start=0x780000 +test_memory_size=0x080000 + +; test word or long odd data access address errors (68000/010 only) +; 0 = do not generate address errors +; 1 = include address errors +; 2 = only generate test instructions that generate address errors +feature_exception3_data=1 + +; test branches to odd addresses +; same as above +feature_exception3_instruction=1 + +; SR extra mask. +; 0x8000 = T1 +; 0x4000 = T0 (68020) +; 0x2000 = S +; 0x1000 = M (68020) +; Other bits are ignored. +; For example 0xa000 adds 3 extra test rounds: S=1/T1=0, S=0/T1=1 and S=1/T1=1 +; Note: instructions that generate privilege violation exception will automatically add extra S=1 round. +feature_sr_mask=0x0000 + +; 68020+ addressing modes (this makes test files much larger if other addressing modes are also enabled) +; currently does not generate any reserved mode bit combinations. +feature_full_extension_format=0 + +; empty = all addressing modes (feature_full_extension_format=1 enables 68020+ modes) +; Dreg, Areg, Aind, Aipi, Apdi, Ad16, PC16, Ad8r, PC8r, absw, absl, imm. +; Ad8rf and PC8rf = 68020+ full extension only. For example "Aind,Aipi,imm" +; Note: FPU source EA is considered destination EA. +feature_addressing_modes_src= +feature_addressing_modes_dst= + +; mnemonics separated by comma or all. +; all = generate all. tst = generate tst.b, tst.w and tst.l. tst.l = generate only tst.l +mode=abcd,mv2sr,mvsr2 diff --git a/cputest/main.c b/cputest/main.c new file mode 100644 index 00000000..0804ec62 --- /dev/null +++ b/cputest/main.c @@ -0,0 +1,1478 @@ + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include +#include + + +#ifdef _MSC_VER +#include "msc_dirent.h" +#else +#include +#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 () (continue)\n"); + printf("mnemonic = test single mnemonic\n"); + printf("all = test all\n"); + printf("all = test all, starting from \n"); + printf("continue = don't stop on error (all mode only)\n"); + printf("ccrmask = ignore CCR bits that are not set.\n"); + return 0; + } + + sprintf(path + strlen(path), "%lu/", 68000 + cpu_lvl * 10); + + strcpy(opcode, argv[1]); + + check_undefined_sr = 1; + ccr_mask = 0xff; + for (int i = 1; i < argc; i++) { + char *s = argv[i]; + char *next = i + 1 < argc ? argv[i + 1] : NULL; + if (!_stricmp(s, "continue")) { + stop_on_error = 0; + } else if (!_stricmp(s, "noundefined")) { + check_undefined_sr = 0; + } else if (!_stricmp(s, "ccrmask")) { + ccr_mask = 0; + if (next) { + ccr_mask = getparamval(next); + i++; + } + } + } + + size = 32768; + load_file(path, "lmem.dat", low_memory_temp, &size); + size = 32768; + load_file(path, "hmem.dat", high_memory_temp, &size); + + if (!_stricmp(opcode, "all")) { + DIR *d = opendir(path); + if (!d) { + printf("Couldn't list directory '%s'\n", path); + return 0; + } +#define MAX_FILE_LEN 128 +#define MAX_MNEMOS 256 + char *dirs = calloc(MAX_MNEMOS, MAX_FILE_LEN); + int diroff = 0; + if (!dirs) + return 0; + + for (;;) { + struct dirent *dr = readdir(d); + if (!dr) + break; + if (dr->d_type == DT_DIR && dr->d_name[0] != '.') { + strcpy(dirs + diroff, dr->d_name); + diroff += MAX_FILE_LEN; + if (diroff >= MAX_FILE_LEN * MAX_MNEMOS) { + printf("too many directories!?\n"); + return 0; + } + } + } + closedir(d); + + for (int i = 0; i < diroff; i += MAX_FILE_LEN) { + for (int j = i + MAX_FILE_LEN; j < diroff; j += MAX_FILE_LEN) { + if (_stricmp(dirs + i, dirs + j) > 0) { + char tmp[MAX_FILE_LEN]; + strcpy(tmp, dirs + j); + strcpy(dirs + j, dirs + i); + strcpy(dirs + i, tmp); + } + } + } + + int first = 0; + if (argc >= 3) { + for (int i = 0; i < diroff; i += MAX_FILE_LEN) { + if (!_stricmp(dirs + i, argv[2])) { + first = i; + break; + } + } + } + for (int i = first; i < diroff; i += MAX_FILE_LEN) { + if (test_mnemo(path, dirs + i)) { + if (stop_on_error) + break; + } + } + + free(dirs); + + } else { + test_mnemo(path, opcode); + } +} diff --git a/cputest/makefile b/cputest/makefile new file mode 100644 index 00000000..75cb52a1 --- /dev/null +++ b/cputest/makefile @@ -0,0 +1,26 @@ + +NOWDATE := "\"$(shell date "+%-d.%-m.%Y")\"" +NOWTIME := "\"$(shell date "+%T")\"" + +CC=/opt/amiga/bin/m68k-amigaos-gcc +AS=/opt/amiga/bin/m68k-amigaos-as + +CFLAGS = -mcrt=nix13 -O2 -m68000 -fomit-frame-pointer -msmall-code -msoft-float -DREVDATE=$(NOWDATE) -DREVTIME=$(NOWTIME) -DAMIGA +LINK_CFLAGS = -mcrt=nix13 -lm -s + +OBJS = main.o 68kDisass.o asm.o amiga.o + +all: $(OBJS) + $(CC) $(LINK_CFLAGS) -o cputest $^ + +main.o: main.c + $(CC) $(CFLAGS) -I. -c -o $@ main.c + +68kDisass.o: main.c + $(CC) $(CFLAGS) -I. -c -o $@ 68kDisass.c + +asm.o: asm.S + $(AS) -m68020 -o $@ asm.S + +amiga.o: amiga.S + $(AS) -m68020 -o $@ amiga.S diff --git a/cputest/msc_dirent.h b/cputest/msc_dirent.h new file mode 100644 index 00000000..f7a46daf --- /dev/null +++ b/cputest/msc_dirent.h @@ -0,0 +1,1160 @@ +/* + * Dirent interface for Microsoft Visual Studio + * + * Copyright (C) 1998-2019 Toni Ronkko + * This file is part of dirent. Dirent may be freely distributed + * under the MIT license. For all details and documentation, see + * https://github.com/tronkko/dirent + */ +#ifndef DIRENT_H +#define DIRENT_H + +/* Hide warnings about unreferenced local functions */ +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunused-function" +#elif defined(_MSC_VER) +# pragma warning(disable:4505) +#elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wunused-function" +#endif + +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of the file name without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return the maximum size of a file name */ +#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX+1]; +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; + +/* Multi-byte character version */ +struct dirent { + /* Always zero */ + long d_ino; + + /* File position within stream */ + long d_off; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX+1]; +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + + +/* Dirent functions */ +static DIR *opendir (const char *dirname); +static _WDIR *_wopendir (const wchar_t *dirname); + +static struct dirent *readdir (DIR *dirp); +static struct _wdirent *_wreaddir (_WDIR *dirp); + +static int readdir_r( + DIR *dirp, struct dirent *entry, struct dirent **result); +static int _wreaddir_r( + _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); + +static int closedir (DIR *dirp); +static int _wclosedir (_WDIR *dirp); + +static void rewinddir (DIR* dirp); +static void _wrewinddir (_WDIR* dirp); + +static int scandir (const char *dirname, struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)); + +static int alphasort (const struct dirent **a, const struct dirent **b); + +static int versionsort (const struct dirent **a, const struct dirent **b); + + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); + +static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + +static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + +static void dirent_set_errno (int error); + + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR* +_wopendir( + const wchar_t *dirname) +{ + _WDIR *dirp; + DWORD n; + wchar_t *p; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); + if (!dirp) { + return NULL; + } + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* + * Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW (dirname, 0, NULL, NULL); +#else + /* WinRT */ + n = wcslen (dirname); +#endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); + if (dirp->patt == NULL) { + goto exit_closedir; + } + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume it is an absolute path. + */ +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + /* Desktop */ + n = GetFullPathNameW (dirname, n, dirp->patt, NULL); + if (n <= 0) { + goto exit_closedir; + } +#else + /* WinRT */ + wcsncpy_s (dirp->patt, n+1, dirname, n); +#endif + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (!dirent_first (dirp)) { + goto exit_closedir; + } + + /* Success */ + return dirp; + + /* Failure */ +exit_closedir: + _wclosedir (dirp); + return NULL; +} + +/* + * Read next directory entry. + * + * Returns pointer to static directory entry which may be overwritten by + * subsequent calls to _wreaddir(). + */ +static struct _wdirent* +_wreaddir( + _WDIR *dirp) +{ + struct _wdirent *entry; + + /* + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. + */ + (void) _wreaddir_r (dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry. + * + * Returns zero on success. If end of directory stream is reached, then sets + * result to NULL and returns zero. + */ +static int +_wreaddir_r( + _WDIR *dirp, + struct _wdirent *entry, + struct _wdirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next (dirp); + if (datap) { + size_t n; + DWORD attr; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n < PATH_MAX && datap->cFileName[n] != 0) { + entry->d_name[n] = datap->cFileName[n]; + n++; + } + entry->d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof (struct _wdirent); + + /* Set result address */ + *result = entry; + + } else { + + /* Return NULL to indicate end of directory */ + *result = NULL; + + } + + return /*OK*/0; +} + +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int +_wclosedir( + _WDIR *dirp) +{ + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Release search pattern */ + free (dirp->patt); + + /* Release directory structure */ + free (dirp); + ok = /*success*/0; + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void +_wrewinddir( + _WDIR* dirp) +{ + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Open new search handle */ + dirent_first (dirp); + } +} + +/* Get first directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_first( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + DWORD error; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } else { + + /* Failed to open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + /* Set error code */ + error = GetLastError (); + switch (error) { + case ERROR_ACCESS_DENIED: + /* No read access to directory */ + dirent_set_errno (EACCES); + break; + + case ERROR_DIRECTORY: + /* Directory name is invalid */ + dirent_set_errno (ENOTDIR); + break; + + case ERROR_PATH_NOT_FOUND: + default: + /* Cannot find the file */ + dirent_set_errno (ENOENT); + } + + } + return datap; +} + +/* + * Get next directory entry (internal). + * + * Returns + */ +static WIN32_FIND_DATAW* +dirent_next( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } else { + /* The very last entry has been processed or an error occurred */ + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; +} + +/* + * Open directory stream using plain old C-string. + */ +static DIR* +opendir( + const char *dirname) +{ + struct DIR *dirp; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*) malloc (sizeof (struct DIR)); + if (!dirp) { + return NULL; + } + { + int error; + wchar_t wname[PATH_MAX + 1]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s( + &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1); + if (error) { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + goto exit_free; + } + + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir (wname); + if (!dirp->wdirp) { + goto exit_free; + } + + } + + /* Success */ + return dirp; + + /* Failure */ +exit_free: + free (dirp); + return NULL; +} + +/* + * Read next directory entry. + */ +static struct dirent* +readdir( + DIR *dirp) +{ + struct dirent *entry; + + /* + * Read directory entry to buffer. We can safely ignore the return value + * as entry will be set to NULL in case of error. + */ + (void) readdir_r (dirp, &dirp->ent, &entry); + + /* Return pointer to statically allocated directory entry */ + return entry; +} + +/* + * Read next directory entry into called-allocated buffer. + * + * Returns zero on success. If the end of directory stream is reached, then + * sets result to NULL and returns zero. + */ +static int +readdir_r( + DIR *dirp, + struct dirent *entry, + struct dirent **result) +{ + WIN32_FIND_DATAW *datap; + + /* Read next directory entry */ + datap = dirent_next (dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, entry->d_name, PATH_MAX + 1, + datap->cAlternateFileName, PATH_MAX + 1); + } + + if (!error) { + DWORD attr; + + /* Length of file name excluding zero terminator */ + entry->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entry->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + + /* Reset dummy fields */ + entry->d_ino = 0; + entry->d_off = 0; + entry->d_reclen = sizeof (struct dirent); + + } else { + + /* + * Cannot convert file name to multi-byte string so construct + * an erroneous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entry->d_name[0] = '?'; + entry->d_name[1] = '\0'; + entry->d_namlen = 1; + entry->d_type = DT_UNKNOWN; + entry->d_ino = 0; + entry->d_off = -1; + entry->d_reclen = 0; + + } + + /* Return pointer to directory entry */ + *result = entry; + + } else { + + /* No more directory entries */ + *result = NULL; + + } + + return /*OK*/0; +} + +/* + * Close directory stream. + */ +static int +closedir( + DIR *dirp) +{ + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir (dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free (dirp); + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream to beginning. + */ +static void +rewinddir( + DIR* dirp) +{ + /* Rewind wide-character string directory stream */ + _wrewinddir (dirp->wdirp); +} + +/* + * Scan directory for entries. + */ +static int +scandir( + const char *dirname, + struct dirent ***namelist, + int (*filter)(const struct dirent*), + int (*compare)(const struct dirent**, const struct dirent**)) +{ + struct dirent **files = NULL; + size_t size = 0; + size_t allocated = 0; + const size_t init_size = 1; + DIR *dir = NULL; + struct dirent *entry; + struct dirent *tmp = NULL; + size_t i; + int result = 0; + + /* Open directory stream */ + dir = opendir (dirname); + if (dir) { + + /* Read directory entries to memory */ + while (1) { + + /* Enlarge pointer table to make room for another pointer */ + if (size >= allocated) { + void *p; + size_t num_entries; + + /* Compute number of entries in the enlarged pointer table */ + if (size < init_size) { + /* Allocate initial pointer table */ + num_entries = init_size; + } else { + /* Double the size */ + num_entries = size * 2; + } + + /* Allocate first pointer table or enlarge existing table */ + p = realloc (files, sizeof (void*) * num_entries); + if (p != NULL) { + /* Got the memory */ + files = (dirent**) p; + allocated = num_entries; + } else { + /* Out of memory */ + result = -1; + break; + } + + } + + /* Allocate room for temporary directory entry */ + if (tmp == NULL) { + tmp = (struct dirent*) malloc (sizeof (struct dirent)); + if (tmp == NULL) { + /* Cannot allocate temporary directory entry */ + result = -1; + break; + } + } + + /* Read directory entry to temporary area */ + if (readdir_r (dir, tmp, &entry) == /*OK*/0) { + + /* Did we get an entry? */ + if (entry != NULL) { + int pass; + + /* Determine whether to include the entry in result */ + if (filter) { + /* Let the filter function decide */ + pass = filter (tmp); + } else { + /* No filter function, include everything */ + pass = 1; + } + + if (pass) { + /* Store the temporary entry to pointer table */ + files[size++] = tmp; + tmp = NULL; + + /* Keep up with the number of files */ + result++; + } + + } else { + + /* + * End of directory stream reached => sort entries and + * exit. + */ + qsort (files, size, sizeof (void*), + (int (*) (const void*, const void*)) compare); + break; + + } + + } else { + /* Error reading directory entry */ + result = /*Error*/ -1; + break; + } + + } + + } else { + /* Cannot open directory */ + result = /*Error*/ -1; + } + + /* Release temporary directory entry */ + free (tmp); + + /* Release allocated memory on error */ + if (result < 0) { + for (i = 0; i < size; i++) { + free (files[i]); + } + free (files); + files = NULL; + } + + /* Close directory stream */ + if (dir) { + closedir (dir); + } + + /* Pass pointer table to caller */ + if (namelist) { + *namelist = files; + } + return result; +} + +/* Alphabetical sorting */ +static int +alphasort( + const struct dirent **a, const struct dirent **b) +{ + return strcoll ((*a)->d_name, (*b)->d_name); +} + +/* Sort versions */ +static int +versionsort( + const struct dirent **a, const struct dirent **b) +{ + /* FIXME: implement strverscmp and use that */ + return alphasort (a, b); +} + +/* Convert multi-byte string to wide character string */ +static int +dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs (wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } + + /* Length of resulting multi-byte string WITH zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Could not convert string */ + error = 1; + + } + +#endif + return error; +} + +/* Convert wide-character string to multi-byte string */ +static int +dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs (mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Cannot convert string */ + error = 1; + + } + +#endif + return error; +} + +/* Set errno variable */ +static void +dirent_set_errno( + int error) +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 and later */ + _set_errno (error); + +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; + +#endif +} + + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ diff --git a/cputest_support.cpp b/cputest_support.cpp new file mode 100644 index 00000000..1ef0dd64 --- /dev/null +++ b/cputest_support.cpp @@ -0,0 +1,100 @@ + +#include "sysconfig.h" +#include "sysdeps.h" + +#include "options.h" +#include "memory.h" +#include "newcpu.h" +#include "fpp.h" + +void my_trim(TCHAR *s) +{ + int len; + while (_tcslen(s) > 0 && _tcscspn(s, _T("\t \r\n")) == 0) + memmove(s, s + 1, (_tcslen(s + 1) + 1) * sizeof(TCHAR)); + len = _tcslen(s); + while (len > 0 && _tcscspn(s + len - 1, _T("\t \r\n")) == 0) + s[--len] = '\0'; +} + +void write_log(const TCHAR *format, ...) +{ + +} +void f_out(void *f, const TCHAR *format, ...) +{ + +} + +TCHAR *buf_out(TCHAR *buffer, int *bufsize, const TCHAR *format, ...) +{ + int count; + va_list parms; + va_start(parms, format); + + if (buffer == NULL) + return 0; + count = _vsntprintf(buffer, (*bufsize) - 1, format, parms); + va_end(parms); + *bufsize -= _tcslen(buffer); + return buffer + _tcslen(buffer); +} + +void fpux_restore(int *v) +{ +} +void fp_init_native(void) +{ + wprintf(_T("fp_init_native called!")); + exit(0); +} +void fp_init_native_80(void) +{ + wprintf(_T("fp_init_native_80 called!")); + exit(0); +} +void init_fpucw_x87(void) +{ +} +void init_fpucw_x87_80(void) +{ +} + +int debugmem_get_segment(uaecptr addr, bool *exact, bool *ext, TCHAR *out, TCHAR *name) +{ + return 0; +} +int debugmem_get_symbol(uaecptr addr, TCHAR *out, int maxsize) +{ + return 0; +} +int debugmem_get_sourceline(uaecptr addr, TCHAR *out, int maxsize) +{ + return -1; +} +bool debugger_get_library_symbol(uaecptr base, uaecptr addr, TCHAR *out) +{ + return false; +} + +int debug_safe_addr(uaecptr addr, int size) +{ + return 1; +} + +void set_cpu_caches(bool flush) +{ +} + +void flush_icache(int v) +{ +} + +void mmu_tt_modified(void) +{ +} + +uae_u16 REGPARAM2 mmu_set_tc(uae_u16 tc) +{ + return 0; +} \ No newline at end of file diff --git a/disasm.cpp b/disasm.cpp new file mode 100644 index 00000000..cf2849b7 --- /dev/null +++ b/disasm.cpp @@ -0,0 +1,2067 @@ + +#include "sysconfig.h" +#include "sysdeps.h" + +#include "options.h" +#include "debug.h" +#include "memory.h" +#include "newcpu.h" +#include "fpp.h" +#include "debugmem.h" +#include "disasm.h" + + +struct cpum2c m2cregs[] = { + { 0, _T("SFC") }, + { 1, _T("DFC") }, + { 2, _T("CACR") }, + { 3, _T("TC") }, + { 4, _T("ITT0") }, + { 5, _T("ITT1") }, + { 6, _T("DTT0") }, + { 7, _T("DTT1") }, + { 8, _T("BUSC") }, + { 0x800, _T("USP") }, + { 0x801, _T("VBR") }, + { 0x802, _T("CAAR") }, + { 0x803, _T("MSP") }, + { 0x804, _T("ISP") }, + { 0x805, _T("MMUS") }, + { 0x806, _T("URP") }, + { 0x807, _T("SRP") }, + { 0x808, _T("PCR") }, + { -1, NULL } +}; + +const TCHAR *fpsizes[] = { + _T("L"), + _T("S"), + _T("X"), + _T("P"), + _T("W"), + _T("D"), + _T("B"), + _T("P") +}; +static const int fpsizeconv[] = { + sz_long, + sz_single, + sz_extended, + sz_packed, + sz_word, + sz_double, + sz_byte, + sz_packed +}; +static const int datasizes[] = { + 1, + 2, + 4, + 4, + 8, + 12, + 12 +}; + +static void showea_val(TCHAR *buffer, uae_u16 opcode, uaecptr addr, int size) +{ + struct mnemolookup *lookup; + instr *table = &table68k[opcode]; + + if (addr >= 0xe90000 && addr < 0xf00000) + goto skip; + if (addr >= 0xdff000 && addr < 0xe00000) + goto skip; + + for (lookup = lookuptab; lookup->mnemo != table->mnemo; lookup++) + ; + if (!(lookup->flags & 1)) + goto skip; + buffer += _tcslen(buffer); + if (debug_safe_addr(addr, datasizes[size])) { + bool cached = false; + switch (size) + { + case sz_byte: + { + uae_u8 v = get_byte_cache_debug(addr, &cached); + uae_u8 v2 = v; + if (cached) + v2 = get_byte_debug(addr); + if (v != v2) { + _stprintf(buffer, _T(" [%02x:%02x]"), v, v2); + } else { + _stprintf(buffer, _T(" [%s%02x]"), cached ? _T("*") : _T(""), v); + } + } + break; + case sz_word: + { + uae_u16 v = get_word_cache_debug(addr, &cached); + uae_u16 v2 = v; + if (cached) + v2 = get_word_debug(addr); + if (v != v2) { + _stprintf(buffer, _T(" [%04x:%04x]"), v, v2); + } else { + _stprintf(buffer, _T(" [%s%04x]"), cached ? _T("*") : _T(""), v); + } + } + break; + case sz_long: + { + uae_u32 v = get_long_cache_debug(addr, &cached); + uae_u32 v2 = v; + if (cached) + v2 = get_long_debug(addr); + if (v != v2) { + _stprintf(buffer, _T(" [%08x:%08x]"), v, v2); + } else { + _stprintf(buffer, _T(" [%s%08x]"), cached ? _T("*") : _T(""), v); + } + } + break; + case sz_single: + { + fpdata fp; + fpp_to_single(&fp, get_long_debug(addr)); + _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0)); + } + break; + case sz_double: + { + fpdata fp; + fpp_to_double(&fp, get_long_debug(addr), get_long_debug(addr + 4)); + _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0)); + } + break; + case sz_extended: + { + fpdata fp; + fpp_to_exten(&fp, get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8)); + _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0)); + break; + } + case sz_packed: + _stprintf(buffer, _T("[%08x%08x%08x]"), get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8)); + break; + } + } +skip: + for (int i = 0; i < size; i++) { + TCHAR name[256]; + if (debugmem_get_symbol(addr + i, name, sizeof(name) / sizeof(TCHAR))) { + _stprintf(buffer + _tcslen(buffer), _T(" %s"), name); + } + } +} + +uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name) +{ + uaecptr addr; + uae_u16 dp; + int r; + uae_u32 dispreg; + uaecptr pc = *pcp; + TCHAR mult[20]; + TCHAR *p = NULL; + + dp = get_iword_debug(pc); + pc += 2; + + r = (dp & 0x7000) >> 12; // REGISTER + + dispreg = dp & 0x8000 ? m68k_areg(regs, r) : m68k_dreg(regs, r); + if (!(dp & 0x800)) { // W/L + dispreg = (uae_s32)(uae_s16)(dispreg); + } + + if (currprefs.cpu_model >= 68020) { + dispreg <<= (dp >> 9) & 3; // SCALE + } + + int m = 1 << ((dp >> 9) & 3); + mult[0] = 0; + if (m > 1 && buffer) { + _stprintf(mult, _T("*%d"), m); + } + + if (buffer) + buffer[0] = 0; + if ((dp & 0x100) && currprefs.cpu_model >= 68020) { + TCHAR dr[20]; + // Full format extension (68020+) + uae_s32 outer = 0, disp = 0; + if (dp & 0x80) { // BS (base register suppress) + base = 0; + if (buffer) + name = NULL; + } + if (buffer) + _stprintf(dr, _T("%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W'); + if (dp & 0x40) { // IS (index suppress) + dispreg = 0; + dr[0] = 0; + } + + if (buffer) { + _tcscpy(buffer, _T("(")); + p = buffer + _tcslen(buffer); + + if (dp & 3) { + // indirect + _stprintf(p, _T("[")); + p += _tcslen(p); + } else { + // (an,dn,word/long) + if (name) { + _stprintf(p, _T("%s,"), name); + p += _tcslen(p); + } + if (dr[0]) { + _stprintf(p, _T("%s%s,"), dr, mult); + p += _tcslen(p); + } + } + } + + if ((dp & 0x30) == 0x20) { // BD SIZE = 2 (WORD) + disp = (uae_s32)(uae_s16)get_iword_debug(pc); + if (buffer) { + _stprintf(p, _T("$%04x,"), (uae_s16)disp); + p += _tcslen(p); + } + pc += 2; + base += disp; + } else if ((dp & 0x30) == 0x30) { // BD SIZE = 3 (LONG) + disp = get_ilong_debug(pc); + if (buffer) { + _stprintf(p, _T("$%08x,"), disp); + p += _tcslen(p); + } + pc += 4; + base += disp; + } + + if ((dp & 3) && buffer) { + if (name) { + _stprintf(p, _T("%s,"), name); + p += _tcslen(p); + } + + if (!(dp & 0x04)) { + if (dr[0]) { + _stprintf(p, _T("%s%s,"), dr, mult); + p += _tcslen(p); + } + } + + if (p[-1] == ',') + p--; + _stprintf(p, _T("],")); + p += _tcslen(p); + + if ((dp & 0x04)) { + if (dr[0]) { + _stprintf(p, _T("%s%s,"), dr, mult); + p += _tcslen(p); + } + } + + } + + if ((dp & 0x03) == 0x02) { + outer = (uae_s32)(uae_s16)get_iword_debug(pc); + if (buffer) { + _stprintf(p, _T("$%04x,"), (uae_s16)outer); + p += _tcslen(p); + } + pc += 2; + } else if ((dp & 0x03) == 0x03) { + outer = get_ilong_debug(pc); + if (buffer) { + _stprintf(p, _T("$%08x,"), outer); + p += _tcslen(p); + } + pc += 4; + } + + if (buffer) { + if (p[-1] == ',') + p--; + _stprintf(p, _T(")")); + p += _tcslen(p); + } + + if ((dp & 0x4) == 0) + base += dispreg; + if (dp & 0x3) + base = get_long_debug(base); + if (dp & 0x4) + base += dispreg; + + addr = base + outer; + + if (buffer) { + _stprintf(p, _T(" == $%08x"), addr); + p += _tcslen(p); + } + + } else { + // Brief format extension + TCHAR regstr[20]; + uae_s8 disp8 = dp & 0xFF; + + regstr[0] = 0; + _stprintf(regstr, _T(",%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W'); + addr = base + (uae_s32)((uae_s8)disp8) + dispreg; + if (buffer) { + _stprintf(buffer, _T("(%s%s%s,$%02x) == $%08x"), name, regstr, mult, (uae_u8)disp8, addr); + if (dp & 0x100) { + _tcscat(buffer, _T(" (68020+)")); + } + } + } + + *pcp = pc; + return addr; +} + +uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode) +{ + uaecptr addr = pc; + uae_s16 disp16; + uae_s32 offset = 0; + TCHAR buffer[80]; + + if ((opcode & 0xf0ff) == 0x60ff && currprefs.cpu_model < 68020) { + // bcc.l is bcc.s if 68000/68010 + mode = immi; + } + + switch (mode){ + case Dreg: + _stprintf (buffer, _T("D%d"), reg); + break; + case Areg: + _stprintf (buffer, _T("A%d"), reg); + break; + case Aind: + _stprintf (buffer, _T("(A%d)"), reg); + addr = regs.regs[reg + 8]; + showea_val(buffer, opcode, addr, size); + break; + case Aipi: + _stprintf (buffer, _T("(A%d)+"), reg); + addr = regs.regs[reg + 8]; + showea_val(buffer, opcode, addr, size); + break; + case Apdi: + _stprintf (buffer, _T("-(A%d)"), reg); + addr = regs.regs[reg + 8]; + showea_val(buffer, opcode, addr - datasizes[size], size); + break; + case Ad16: + { + TCHAR offtxt[8]; + disp16 = get_iword_debug (pc); pc += 2; + if (disp16 < 0) + _stprintf (offtxt, _T("-$%04x"), -disp16); + else + _stprintf (offtxt, _T("$%04x"), disp16); + addr = m68k_areg (regs, reg) + disp16; + _stprintf (buffer, _T("(A%d,%s) == $%08x"), reg, offtxt, addr); + showea_val(buffer, opcode, addr, size); + } + break; + case Ad8r: + { + TCHAR name[10]; + _stprintf(name, _T("A%d"), reg); + addr = ShowEA_disp(&pc, m68k_areg(regs, reg), buffer, name); + showea_val(buffer, opcode, addr, size); + } + break; + case PC16: + disp16 = get_iword_debug (pc); pc += 2; + addr += (uae_s16)disp16; + _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr); + showea_val(buffer, opcode, addr, size); + break; + case PC8r: + { + addr = ShowEA_disp(&pc, addr, buffer, _T("PC")); + showea_val(buffer, opcode, addr, size); + } + break; + case absw: + addr = (uae_s32)(uae_s16)get_iword_debug (pc); + _stprintf (buffer, _T("$%04x"), (uae_u16)addr); + pc += 2; + showea_val(buffer, opcode, addr, size); + break; + case absl: + addr = get_ilong_debug (pc); + _stprintf (buffer, _T("$%08x"), addr); + pc += 4; + showea_val(buffer, opcode, addr, size); + break; + case imm: + switch (size){ + case sz_byte: + _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff)); + pc += 2; + break; + case sz_word: + _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff)); + pc += 2; + break; + case sz_long: + _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc))); + pc += 4; + break; + case sz_single: + { + fpdata fp; + fpp_to_single(&fp, get_ilong_debug(pc)); + _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0)); + pc += 4; + } + break; + case sz_double: + { + fpdata fp; + fpp_to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4)); + _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0)); + pc += 8; + } + break; + case sz_extended: + { + fpdata fp; + fpp_to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8)); + _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0)); + pc += 12; + break; + } + case sz_packed: + _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8)); + pc += 12; + break; + default: + break; + } + break; + case imm0: + offset = (uae_s32)(uae_s8)get_iword_debug (pc); + _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff)); + addr = pc + 2 + offset; + if ((opcode & 0xf000) == 0x6000) { + showea_val(buffer, opcode, addr, 1); + } + pc += 2; + break; + case imm1: + offset = (uae_s32)(uae_s16)get_iword_debug (pc); + buffer[0] = 0; + _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff)); + addr = pc + offset; + if ((opcode & 0xf000) == 0x6000) { + showea_val(buffer, opcode, addr, 2); + } + pc += 2; + break; + case imm2: + offset = (uae_s32)get_ilong_debug (pc); + _stprintf (buffer, _T("#$%08x"), (uae_u32)offset); + addr = pc + offset; + if ((opcode & 0xf000) == 0x6000) { + showea_val(buffer, opcode, addr, 4); + } + pc += 4; + break; + case immi: + offset = (uae_s32)(uae_s8)(reg & 0xff); + _stprintf (buffer, _T("#$%02x"), (uae_u8)offset); + addr = pc + offset; + break; + default: + break; + } + if (buf == NULL) + f_out (f, _T("%s"), buffer); + else + _tcscat (buf, buffer); + if (eaddr) + *eaddr = addr; + return pc; +} + +static const TCHAR *ccnames[] = +{ + _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"), + _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE") +}; +static const TCHAR *fpccnames[] = +{ + _T("F"), + _T("EQ"), + _T("OGT"), + _T("OGE"), + _T("OLT"), + _T("OLE"), + _T("OGL"), + _T("OR"), + _T("UN"), + _T("UEQ"), + _T("UGT"), + _T("UGE"), + _T("ULT"), + _T("ULE"), + _T("NE"), + _T("T"), + _T("SF"), + _T("SEQ"), + _T("GT"), + _T("GE"), + _T("LT"), + _T("LE"), + _T("GL"), + _T("GLE"), + _T("NGLE"), + _T("NGL"), + _T("NLE"), + _T("NLT"), + _T("NGE"), + _T("NGT"), + _T("SNE"), + _T("ST") +}; +const TCHAR *fpuopcodes[] = +{ + _T("FMOVE"), + _T("FINT"), + _T("FSINH"), + _T("FINTRZ"), + _T("FSQRT"), + NULL, + _T("FLOGNP1"), + NULL, + _T("FETOXM1"), + _T("FTANH"), + _T("FATAN"), + NULL, + _T("FASIN"), + _T("FATANH"), + _T("FSIN"), + _T("FTAN"), + _T("FETOX"), // 0x10 + _T("FTWOTOX"), + _T("FTENTOX"), + NULL, + _T("FLOGN"), + _T("FLOG10"), + _T("FLOG2"), + NULL, + _T("FABS"), + _T("FCOSH"), + _T("FNEG"), + NULL, + _T("FACOS"), + _T("FCOS"), + _T("FGETEXP"), + _T("FGETMAN"), + _T("FDIV"), // 0x20 + _T("FMOD"), + _T("FADD"), + _T("FMUL"), + _T("FSGLDIV"), + _T("FREM"), + _T("FSCALE"), + _T("FSGLMUL"), + _T("FSUB"), + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + _T("FSINCOS"), // 0x30 + _T("FSINCOS"), + _T("FSINCOS"), + _T("FSINCOS"), + _T("FSINCOS"), + _T("FSINCOS"), + _T("FSINCOS"), + _T("FSINCOS"), + _T("FCMP"), + NULL, + _T("FTST"), + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static const TCHAR *movemregs[] = +{ + _T("D0"), + _T("D1"), + _T("D2"), + _T("D3"), + _T("D4"), + _T("D5"), + _T("D6"), + _T("D7"), + _T("A0"), + _T("A1"), + _T("A2"), + _T("A3"), + _T("A4"), + _T("A5"), + _T("A6"), + _T("A7"), + _T("FP0"), + _T("FP1"), + _T("FP2"), + _T("FP3"), + _T("FP4"), + _T("FP5"), + _T("FP6"), + _T("FP7"), + _T("FPIAR"), + _T("FPSR"), + _T("FPCR") +}; + +static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode) +{ + TCHAR *p = out + _tcslen (out); + if (*prevreg < 0) { + *prevreg = reg; + *lastreg = reg; + return; + } + if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) { + _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]); + p = p + _tcslen (p); + if (*lastreg != *prevreg) { + if ((*lastreg) + 2 == reg) { + _stprintf(p, _T("/%s"), movemregs[*prevreg]); + } else if ((*lastreg) != (*prevreg)) { + _stprintf(p, _T("-%s"), movemregs[*prevreg]); + } + } + *lastreg = reg; + *first = 0; + } + *prevreg = reg; +} + +static bool movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode, bool dst) +{ + unsigned int dmask, amask; + int prevreg = -1, lastreg = -1, first = 1; + + if (mode == Apdi && !fpmode) { + uae_u8 dmask2; + uae_u8 amask2; + + amask2 = mask & 0xff; + dmask2 = (mask >> 8) & 0xff; + dmask = 0; + amask = 0; + for (int i = 0; i < 8; i++) { + if (dmask2 & (1 << i)) + dmask |= 1 << (7 - i); + if (amask2 & (1 << i)) + amask |= 1 << (7 - i); + } + } else { + dmask = mask & 0xff; + amask = (mask >> 8) & 0xff; + if (fpmode == 1 && mode != Apdi) { + uae_u8 dmask2 = dmask; + dmask = 0; + for (int i = 0; i < 8; i++) { + if (dmask2 & (1 << i)) + dmask |= 1 << (7 - i); + } + } + } + bool dataout = dmask != 0 || amask != 0; + if (dst && dataout) + _tcscat(out, _T(",")); + if (fpmode) { + while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; } + } else { + while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; } + while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; } + } + addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode); + return dataout; +} + +static void disasm_size (TCHAR *instrname, struct instr *dp) +{ + if (dp->unsized) { + _tcscat(instrname, _T(" ")); + return; + } + switch (dp->size) + { + case sz_byte: + _tcscat (instrname, _T(".B ")); + break; + case sz_word: + _tcscat (instrname, _T(".W ")); + break; + case sz_long: + _tcscat (instrname, _T(".L ")); + break; + default: + _tcscat (instrname, _T(" ")); + break; + } +} + +static void asm_add_extensions(uae_u16 *data, int *dcntp, int mode, uae_u32 v, int extcnt, uae_u16 *ext, uaecptr pc, int size) +{ + int dcnt = *dcntp; + if (mode < 0) + return; + if (mode == Ad16) { + data[dcnt++] = v; + } + if (mode == PC16) { + data[dcnt++] = v - (pc + 2); + } + if (mode == Ad8r || mode == PC8r) { + for (int i = 0; i < extcnt; i++) { + data[dcnt++] = ext[i]; + } + } + if (mode == absw) { + data[dcnt++] = (uae_u16)v; + } + if (mode == absl) { + data[dcnt++] = (uae_u16)(v >> 16); + data[dcnt++] = (uae_u16)v; + } + if ((mode == imm && size == 0) || mode == imm0) { + data[dcnt++] = (uae_u8)v; + } + if ((mode == imm && size == 1) || mode == imm1) { + data[dcnt++] = (uae_u16)v; + } + if ((mode == imm && size == 2) || mode == imm2) { + data[dcnt++] = (uae_u16)(v >> 16); + data[dcnt++] = (uae_u16)v; + } + *dcntp = dcnt; +} + +static int asm_isdreg(const TCHAR *s) +{ + if (s[0] == 'D' && s[1] >= '0' && s[1] <= '7') + return s[1] - '0'; + return -1; +} +static int asm_isareg(const TCHAR *s) +{ + if (s[0] == 'A' && s[1] >= '0' && s[1] <= '7') + return s[1] - '0'; + if (s[0] == 'S' && s[1] == 'P') + return 7; + return -1; +} +static int asm_ispc(const TCHAR *s) +{ + if (s[0] == 'P' && s[1] == 'C') + return 1; + return 0; +} + +static uae_u32 asmgetval(const TCHAR *s) +{ + TCHAR *endptr; + if (s[0] == '-') + return _tcstol(s, &endptr, 16); + return _tcstoul(s, &endptr, 16); +} + +static int asm_parse_mode020(TCHAR *s, uae_u8 *reg, uae_u32 *v, int *extcnt, uae_u16 *ext) +{ + return -1; +} + +static int asm_parse_mode(TCHAR *s, uae_u8 *reg, uae_u32 *v, int *extcnt, uae_u16 *ext) +{ + TCHAR *ss = s; + *reg = -1; + *v = 0; + *ext = 0; + *extcnt = 0; + if (s[0] == 0) + return -1; + // Dn + if (asm_isdreg(s) >= 0 && s[2] == 0) { + *reg = asm_isdreg(s); + return Dreg; + } + // An + if (asm_isareg(s) >= 0 && s[2] == 0) { + *reg = asm_isareg(s); + return Areg; + } + // (An) and (An)+ + if (s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')') { + *reg = asm_isareg(s + 1); + if (s[4] == '+' && s[5] == 0) + return Aipi; + if (s[4] == 0) + return Aind; + return -1; + } + // -(An) + if (s[0] == '-' && s[1] == '(' && asm_isareg(s + 2) >= 0 && s[4] == ')' && s[5] == 0) { + *reg = asm_isareg(s + 2); + return Apdi; + } + // Immediate + if (s[0] == '#') { + if (s[1] == '!') { + *v = _tstol(s + 2); + } else { + *v = asmgetval(s + 1); + } + return imm; + } + // Value + if (s[0] == '!') { + *v = _tstol(s + 1); + } else { + *v = asmgetval(s); + } + int dots = 0; + int fullext = 0; + for (int i = 0; i < _tcslen(s); i++) { + if (s[i] == ',') { + dots++; + } else if (s[i] == '[') { + if (fullext > 0) + fullext = -1; + else + fullext = 1; + } else if (s[i] == ']') { + if (fullext != 1) + fullext = -1; + else + fullext = 2; + fullext++; + } + } + if (fullext < 0 || fullext == 1) + return -1; + if (fullext == 2) { + return asm_parse_mode020(s, reg, v, extcnt, ext); + } + while (*s != 0) { + // d16(An) + if (dots == 0 && s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')' && s[4] == 0) { + *reg = asm_isareg(s + 1); + return Ad16; + } + // d16(PC) + if (dots == 0 && s[0] == '(' && asm_ispc(s + 1) && s[3] == ')' && s[4] == 0) { + *reg = 2; + return PC16; + } + // (d16,An) / (d16,PC) + if (dots == 1 && s[0] == '(' && !asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) { + TCHAR *startptr, *endptr; + if (s[1] == '!') { + startptr = s + 2; + *v = _tcstol(startptr, &endptr, 10); + } else { + startptr = s + 1; + *v = _tcstol(startptr, &endptr, 16); + } + if (endptr == startptr || endptr[0] != ',') + return -1; + if (asm_ispc(endptr + 1) && endptr[3] == ')') { + *reg = 2; + return PC16; + } + if (asm_isareg(endptr + 1) >= 0 && endptr[3] == ')') { + *reg = asm_isareg(endptr + 1); + return Ad16; + } + return -1; + } + // Ad8r PC8r + if (s[0] == '(') { + TCHAR *s2 = s; + if (!asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) { + if (dots != 2) + return -1; + TCHAR *startptr, *endptr; + if (s[1] == '!') { + startptr = s + 2; + *v = _tcstol(startptr, &endptr, 10); + } else { + startptr = s + 1; + *v = _tcstol(startptr, &endptr, 16); + } + if (endptr == startptr || endptr[0] != ',') + return -1; + s2 = endptr + 1; + } else if (((asm_isareg(s + 1) >= 0 || asm_ispc(s + 1)) && s[3] == ',') || (asm_isdreg(s + 4) >= 0 || asm_isareg(s + 4) >= 0)) { + if (dots != 1) + return -1; + s2 = s + 1; + } else { + return -1; + } + uae_u8 reg2; + bool ispc = asm_ispc(s2); + if (ispc) { + *reg = 3; + } else { + *reg = asm_isareg(s2); + } + *extcnt = 1; + s2 += 2; + if (*s2 != ',') + return -1; + s2++; + if (asm_isdreg(s2) >= 0) { + reg2 = asm_isdreg(s2); + } else { + reg2 = asm_isareg(s2); + *ext |= 1 << 15; + } + s2 += 2; + *ext |= reg2 << 12; + *ext |= (*v) & 0xff; + if (s2[0] == '.' && s2[1] == 'W') { + s2 += 2; + } else if (s2[0] == '.' && s2[1] == 'L') { + *ext |= 1 << 11; + s2 += 2; + } + if (s2[0] == '*') { + TCHAR scale = s2[1]; + if (scale == '2') + *ext |= 1 << 9; + else if (scale == '4') + *ext |= 2 << 9; + else if (scale == '8') + *ext |= 3 << 9; + else + return -1; + s2 += 2; + } + if (s2[0] == ')' && s2[1] == 0) { + return ispc ? PC8r : Ad8r; + } + return -1; + } + s++; + } + // abs.w + if (s - ss > 2 && s[-2] == '.' && s[-1] == 'W') { + *reg = 0; + return absw; + } + // abs.l + *reg = 1; + return absl; +} + +static TCHAR *asm_parse_parm(TCHAR *parm, TCHAR *out) +{ + TCHAR *p = parm; + bool quote = false; + + for (;;) { + if (*p == '(') { + quote = true; + } + if (*p == ')') { + if (!quote) + return NULL; + quote = false; + } + if ((*p == ',' || *p == 0) && !quote) { + TCHAR c = *p; + p[0] = 0; + _tcscpy(out, parm); + my_trim(out); + if (c) + p++; + return p; + } + p++; + } +} + +static bool m68k_asm_parse_movec(TCHAR *s, TCHAR *d) +{ + for (int i = 0; m2cregs[i].regname; i++) { + if (!_tcscmp(s, m2cregs[i].regname)) { + uae_u16 v = m2cregs[i].regno; + if (asm_isareg(d) >= 0) + v |= 0x8000 | (asm_isareg(d) << 12); + else if (asm_isdreg(d) >= 0) + v |= (asm_isdreg(d) << 12); + else + return false; + _stprintf(s, _T("#%X"), v); + return true; + } + } + return false; +} + +static bool m68k_asm_parse_movem(TCHAR *s, int dir) +{ + TCHAR *d = s; + uae_u16 regmask = 0; + uae_u16 mask = dir ? 0x8000 : 0x0001; + bool ret = false; + while(*s) { + int dreg = asm_isdreg(s); + int areg = asm_isareg(s); + if (dreg < 0 && areg < 0) + break; + int reg = dreg >= 0 ? dreg : areg + 8; + regmask |= dir ? (mask >> reg) : (mask << reg); + s += 2; + if (*s == 0) { + ret = true; + break; + } else if (*s == '/') { + s++; + continue; + } else if (*s == '-') { + s++; + int dreg2 = asm_isdreg(s); + int areg2 = asm_isareg(s); + if (dreg2 < 0 && areg2 < 0) + break; + int reg2 = dreg2 >= 0 ? dreg2 : areg2 + 8; + if (reg2 < reg) + break; + while (reg2 >= reg) { + regmask |= dir ? (mask >> reg) : (mask << reg); + reg++; + } + s += 2; + if (*s == 0) { + ret = true; + break; + } + } else { + break; + } + } + if (ret) + _stprintf(d, _T("#%X"), regmask); + return ret; +} + +int m68k_asm(TCHAR *sline, uae_u16 *out, uaecptr pc) +{ + TCHAR *p; + const TCHAR *cp1; + TCHAR ins[256], parms[256]; + TCHAR line[256]; + TCHAR srcea[256], dstea[256]; + uae_u16 data[16], sexts[8], dexts[8]; + int sextcnt, dextcnt; + int dcnt = 0; + int cc = -1; + int quick = 0; + bool immrelpc = false; + + if (_tcslen(sline) > 100) + return -1; + + srcea[0] = dstea[0] = 0; + parms[0] = 0; + + // strip all white space except first space + p = line; + bool firstsp = true; + for (int i = 0; sline[i]; i++) { + TCHAR c = sline[i]; + if (c == 32 && firstsp) { + firstsp = false; + *p++ = 32; + } + if (c <= 32) + continue; + *p++ = c; + } + *p = 0; + + to_upper(line, _tcslen(line)); + + p = line; + while (*p && *p != ' ') + p++; + if (*p == ' ') { + *p = 0; + _tcscpy(parms, p + 1); + my_trim(parms); + } + _tcscpy(ins, line); + + if (_tcslen(ins) == 0) + return 0; + + int size = 1; + int inssize = -1; + cp1 = _tcschr(line, '.'); + if (cp1) { + size = cp1[1]; + if (size == 'W') + size = 1; + else if (size == 'L') + size = 2; + else if (size == 'B') + size = 0; + else + return 0; + inssize = size; + line[cp1 - line] = 0; + _tcscpy(ins, line); + } + + TCHAR *parmp = parms; + parmp = asm_parse_parm(parmp, srcea); + if (!parmp) + return 0; + if (srcea[0]) { + parmp = asm_parse_parm(parmp, dstea); + if (!parmp) + return 0; + } + + int smode = -1; + int dmode = -1; + uae_u8 sreg = -1; + uae_u8 dreg = -1; + uae_u32 sval = 0; + uae_u32 dval = 0; + int ssize = -1; + int dsize = -1; + + dmode = asm_parse_mode(dstea, &dreg, &dval, &dextcnt, dexts); + + + // Common alias + if (!_tcscmp(ins, _T("BRA"))) { + _tcscpy(ins, _T("BT")); + } else if (!_tcscmp(ins, _T("BSR"))) { + immrelpc = true; + } else if (!_tcscmp(ins, _T("MOVEM"))) { + if (dmode >= Aind && _tcschr(dstea, '-') == NULL && _tcschr(dstea, '/') == NULL) { + _tcscpy(ins, _T("MVMLE")); + if (!m68k_asm_parse_movem(srcea, dmode == Apdi)) + return -1; + } else { + TCHAR tmp[256]; + _tcscpy(ins, _T("MVMEL")); + _tcscpy(tmp, srcea); + _tcscpy(srcea, dstea); + _tcscpy(dstea, tmp); + if (!m68k_asm_parse_movem(srcea, 0)) + return -1; + dmode = asm_parse_mode(dstea, &dreg, &dval, &dextcnt, dexts); + } + } else if (!_tcscmp(ins, _T("MOVEC"))) { + if (dmode == Dreg || dmode == Areg) { + _tcscpy(ins, _T("MOVEC2")); + if (!m68k_asm_parse_movec(srcea, dstea)) + return -1; + } else { + TCHAR tmp[256]; + _tcscpy(ins, _T("MOVE2C")); + _tcscpy(tmp, srcea); + _tcscpy(srcea, dstea); + dstea[0] = 0; + if (!m68k_asm_parse_movec(srcea, tmp)) + return -1; + } + dmode = -1; + } + + if (dmode == Areg) { + int l = _tcslen(ins); + if (l <= 2) + return -1; + TCHAR last = ins[l- 1]; + if (last == 'Q') { + last = ins[l - 2]; + if (last != 'A') { + ins[l - 1] = 'A'; + ins[l] = 'Q'; + ins[l + 1] = 0; + } + } else if (last != 'A') { + _tcscat(ins, _T("A")); + } + } + + bool fp = ins[0] == 'F'; + + if (ins[_tcslen(ins) - 1] == 'Q' && _tcslen(ins) > 3 && !fp) { + quick = 1; + ins[_tcslen(ins) - 1] = 0; + } + + struct mnemolookup *lookup; + for (lookup = lookuptab; lookup->name; lookup++) { + if (!_tcscmp(ins, lookup->name)) + break; + } + if (!lookup->name) { + // Check cc variants + for (lookup = lookuptab; lookup->name; lookup++) { + const TCHAR *ccp = _tcsstr(lookup->name, _T("cc")); + if (ccp) { + TCHAR tmp[256]; + for (int i = 0; i < (fp ? 32 : 16); i++) { + const TCHAR *ccname = fp ? fpccnames[i] : ccnames[i]; + _tcscpy(tmp, lookup->name); + _tcscpy(tmp + (ccp - lookup->name), ccname); + if (tmp[_tcslen(tmp) - 1] == ' ') + tmp[_tcslen(tmp) - 1] = 0; + if (!_tcscmp(tmp, ins)) { + _tcscpy(ins, lookup->name); + cc = i; + if (lookup->mnemo == i_DBcc || lookup->mnemo == i_Bcc) { + // Bcc.B uses same encoding mode as MOVEQ + immrelpc = true; + } + if (size == 0) { + quick = 2; + } + break; + } + } + } + if (cc >= 0) + break; + } + } + + if (!lookup->name) + return 0; + + int mnemo = lookup->mnemo; + + int found = 0; + int sizemask = 0; + int tsize = size; + int unsized = 0; + + for (int round = 0; round < 9; round++) { + + if (!found && round == 8) + return 0; + + if (round == 3) { + // Q is always LONG sized + if (quick == 1) { + tsize = 2; + } + bool isimm = srcea[0] == '#'; + if (immrelpc && !isimm) { + TCHAR tmp[256]; + _tcscpy(tmp, srcea); + srcea[0] = '#'; + _tcscpy(srcea + 1, tmp); + } + smode = asm_parse_mode(srcea, &sreg, &sval, &sextcnt, sexts); + if (immrelpc && !isimm) { + sval = sval - (pc + 2); + } + if (quick) { + smode = immi; + sreg = sval & 0xff; + } + } + + if (round == 1) { + if (!quick && (sizemask == 1 || sizemask == 2 || sizemask == 4)) { + tsize = 0; + if (sizemask == 2) + tsize = 1; + else if (sizemask == 4) + tsize = 2; + } else { + continue; + } + } + if (round == 2 && !found) { + unsized = 1; + } + + if (round == 4 && smode == imm) { + smode = imm0; + } else if (round == 5 && smode == imm0) { + smode = imm1; + } else if (round == 6 && smode == imm1) { + smode = imm2; + } else if (round == 7 && smode == imm2) { + smode = immi; + sreg = sval & 0xff; + } else if (round == 4) { + round += 5 - 1; + } + + for (int opcode = 0; opcode < 65536; opcode++) { + struct instr *table = &table68k[opcode]; + if (table->mnemo != mnemo) + continue; + if (cc >= 0 && table->cc != cc) + continue; + +#if 0 + if (round == 0) { + console_out_f(_T("%s OP=%04x S=%d SR=%d SM=%d SU=%d SP=%d DR=%d DM=%d DU=%d DP=%d SDU=%d\n"), lookup->name, opcode, table->size, + table->sreg, table->smode, table->suse, table->spos, + table->dreg, table->dmode, table->duse, table->dpos, + table->sduse); + } +#endif + + if (table->duse && !(table->dmode == dmode || (dmode >= imm && dmode <= imm2 && table->dmode >= imm && table->dmode <= imm2))) + continue; + if (round == 0) { + sizemask |= 1 << table->size; + } + if (unsized > 0 && !table->unsized) { + continue; + } + + found++; + + if (round >= 3) { + + if ( + ((table->size == tsize || table->unsized)) && + ((!table->suse && smode < 0) || (table->suse && table->smode == smode)) && + ((!table->duse && dmode < 0) || (table->duse && (table->dmode == dmode || (dmode == imm && (table->dmode >= imm && table->dmode <= imm2))))) && + ((table->sreg == sreg || (table->smode >= absw && table->smode != immi))) && + ((table->dreg == dreg || table->dmode >= absw)) + ) + { + if (inssize >= 0 && tsize != inssize) + continue; + + + data[dcnt++] = opcode; + asm_add_extensions(data, &dcnt, smode, sval, sextcnt, sexts, pc, tsize); + if (smode >= 0) + asm_add_extensions(data, &dcnt, dmode, dval, dextcnt, dexts, pc, tsize); + for (int i = 0; i < dcnt; i++) { + out[i] = data[i]; + } + return dcnt; + } + + } + } + } + + return 0; +} + +static void resolve_if_jmp(TCHAR *s, uae_u32 addr) +{ + uae_u16 opcode = get_word_debug(addr); + if (opcode == 0x4ef9) { // JMP x.l + TCHAR *p = s + _tcslen(s); + uae_u32 addr2 = get_long_debug(addr + 2); + _stprintf(p, _T(" == $%08x "), addr2); + showea_val(p + _tcslen(p), opcode, addr2, 4); + TCHAR txt[256]; + bool ext; + if (debugmem_get_segment(addr2, NULL, &ext, NULL, txt)) { + if (ext) { + _tcscat(p, _T(" ")); + _tcscat(p, txt); + } + } + } +} + +static bool mmu_op30_helper_get_fc(uae_u16 extra, TCHAR *out) +{ + switch (extra & 0x0018) { + case 0x0010: + _stprintf(out, _T("#%d"), extra & 7); + return true; + case 0x0008: + _stprintf(out, _T("D%d"), extra & 7); + return true; + case 0x0000: + if (extra & 1) { + _tcscpy(out, _T("DFC")); + } else { + _tcscpy(out, _T("SFC")); + } + return true; + default: + return false; + } +} + +static bool mmu_op30_invea(uae_u32 opcode) +{ + int eamode = (opcode >> 3) & 7; + int rreg = opcode & 7; + + // Dn, An, (An)+, -(An), immediate and PC-relative not allowed + if (eamode == 0 || eamode == 1 || eamode == 3 || eamode == 4 || (eamode == 7 && rreg > 1)) + return true; + return false; +} + +static uaecptr disasm_mmu030(uaecptr pc, uae_u16 opcode, uae_u16 extra, struct instr *dp, TCHAR *instrname, uae_u32 *seaddr2, int safemode) +{ + int type = extra >> 13; + + _tcscpy(instrname, _T("F-LINE (MMU 68030)")); + pc += 2; + + switch (type) + { + case 0: + case 2: + case 3: + { + // PMOVE + int preg = (extra >> 10) & 31; + int rw = (extra >> 9) & 1; + int fd = (extra >> 8) & 1; + int unused = (extra & 0xff); + const TCHAR *r = NULL; + + if (mmu_op30_invea(opcode)) + break; + if (unused) + break; + if (rw && fd) + break; + switch (preg) + { + case 0x10: + r = _T("TC"); + break; + case 0x12: + r = _T("SRP"); + break; + case 0x13: + r = _T("CRP"); + break; + case 0x18: + r = _T("MMUSR"); + break; + case 0x02: + r = _T("TT0"); + break; + case 0x03: + r = _T("TT1"); + break; + } + if (!r) + break; + + _tcscpy(instrname, _T("PMOVE")); + if (fd) + _tcscat(instrname, _T("FD")); + _tcscat(instrname, _T(" ")); + + if (!rw) { + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); + _tcscat(instrname, _T(",")); + } + _tcscat(instrname, r); + if (rw) { + _tcscat(instrname, _T(",")); + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); + } + break; + } + case 1: + { + // PLOAD/PFLUSH + uae_u16 mode = (extra >> 8) & 31; + int unused = (extra & (0x100 | 0x80 | 0x40 | 0x20)); + uae_u16 fc_mask = (extra & 0x00E0) >> 5; + uae_u16 fc_bits = extra & 0x7f; + TCHAR fc[10]; + + if (unused) + break; + + switch (mode) { + case 0x00: // PLOAD W + case 0x02: // PLOAD R + if (mmu_op30_invea(opcode)) + break; + _stprintf(instrname, _T("PLOAD%c %s,"), mode == 0 ? 'W' : 'R', fc); + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); + break; + case 0x04: // PFLUSHA + if (fc_bits) + break; + _tcscpy(instrname, _T("PFLUSHA")); + break; + case 0x10: // FC + if (!mmu_op30_helper_get_fc(extra, fc)) + break; + _stprintf(instrname, _T("PFLUSH %s,%d"), fc, fc_mask); + break; + case 0x18: // FC + EA + if (mmu_op30_invea(opcode)) + break; + if (!mmu_op30_helper_get_fc(extra, fc)) + break; + _stprintf(instrname, _T("PFLUSH %s,%d"), fc, fc_mask); + _tcscat(instrname, _T(",")); + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); + break; + } + break; + } + case 4: + { + // PTEST + int level = (extra & 0x1C00) >> 10; + int rw = (extra >> 9) & 1; + int a = (extra >> 8) & 1; + int areg = (extra & 0xE0) >> 5; + TCHAR fc[10]; + + if (mmu_op30_invea(opcode)) + break; + if (!mmu_op30_helper_get_fc(extra, fc)) + break; + if (!level && a) + break; + _stprintf(instrname, _T("PTEST%c %s,"), rw ? 'R' : 'W', fc); + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); + _stprintf(instrname + _tcslen(instrname), _T(",#%d"), level); + if (a) + _stprintf(instrname + _tcslen(instrname), _T(",A%d"), areg); + break; + } + } + return pc; +} + + +void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc, int safemode) +{ + uae_u32 seaddr2; + uae_u32 deaddr2; + + if (!table68k) + return; + while (cnt-- > 0) { + TCHAR instrname[256], *ccpt; + TCHAR segout[256], segname[256]; + int i; + uae_u32 opcode; + uae_u16 extra; + struct mnemolookup *lookup; + struct instr *dp; + uaecptr oldpc; + uaecptr m68kpc_illg = 0; + bool illegal = false; + int segid, lastsegid; + TCHAR *symbolpos; + + seaddr2 = deaddr2 = 0; + oldpc = pc; + opcode = get_word_debug (pc); + extra = get_word_debug (pc + 2); + if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) { + m68kpc_illg = pc + 2; + illegal = TRUE; + } + + dp = table68k + opcode; + if (dp->mnemo == i_ILLG) { + illegal = FALSE; + opcode = 0x4AFC; + dp = table68k + opcode; + } + for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) + ; + + lastsegid = -1; + bool exact = false; + if (lastpc != 0xffffffff) { + lastsegid = debugmem_get_segment(lastpc, NULL, NULL, NULL, NULL); + } + segid = debugmem_get_segment(pc, &exact, NULL, segout, segname); + if (segid && (lastsegid != -1 || exact) && (segid != lastsegid || pc == lastpc || exact)) { + buf = buf_out(buf, &bufsize, _T("%s\n"), segname); + } + symbolpos = buf; + + buf = buf_out (buf, &bufsize, _T("%08X "), pc); + + if (segid) { + buf = buf_out(buf, &bufsize, _T("%s "), segout); + } + + pc += 2; + + if (lookup->friendlyname) + _tcscpy (instrname, lookup->friendlyname); + else + _tcscpy (instrname, lookup->name); + ccpt = _tcsstr (instrname, _T("cc")); + if (ccpt != 0) { + if ((opcode & 0xf000) == 0xf000) + _tcscpy (ccpt, fpccnames[extra & 0x1f]); + else + _tcsncpy (ccpt, ccnames[dp->cc], 2); + } + disasm_size (instrname, dp); + + if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) { + uae_u16 imm = extra; + uae_u16 creg = imm & 0x0fff; + uae_u16 r = imm >> 12; + TCHAR regs[16]; + const TCHAR *cname = _T("?"); + int j; + for (j = 0; m2cregs[j].regname; j++) { + if (m2cregs[j].regno == creg) + break; + } + _stprintf(regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r); + if (m2cregs[j].regname) + cname = m2cregs[j].regname; + if (lookup->mnemo == i_MOVE2C) { + _tcscat(instrname, regs); + _tcscat(instrname, _T(",")); + _tcscat(instrname, cname); + } else { + _tcscat(instrname, cname); + _tcscat(instrname, _T(",")); + _tcscat(instrname, regs); + } + pc += 2; + } else if (lookup->mnemo == i_CHK2) { + TCHAR *p; + if (!(extra & 0x0800)) { + instrname[1] = 'M'; + instrname[2] = 'P'; + } + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); + extra = get_word_debug(pc); + pc += 2; + p = instrname + _tcslen(instrname); + _stprintf(p, (extra & 0x8000) ? _T(",A%d") : _T(",D%d"), (extra >> 12) & 7); + } else if (lookup->mnemo == i_CAS) { + TCHAR *p = instrname + _tcslen(instrname); + _stprintf(p, _T("D%d,D%d,"), extra & 7, (extra >> 6) & 7); + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); + } else if (lookup->mnemo == i_CAS2) { + TCHAR *p = instrname + _tcslen(instrname); + uae_u16 extra2 = get_word_debug(pc + 2); + _stprintf(p, _T("D%d:D%d,D%d,D%d,(%c%d):(%c%d)"), + extra & 7, extra2 & 7, (extra >> 6) & 7, (extra2 >> 6) & 7, + (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7, + (extra2 & 0x8000) ? 'A' : 'D', (extra2 >> 12) & 7); + pc += 4; + } else if (lookup->mnemo == i_ORSR || lookup->mnemo == i_ANDSR || lookup->mnemo == i_EORSR) { + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); + _tcscat(instrname, dp->size == sz_byte ? _T(",CCR") : _T(",SR")); + } else if (lookup->mnemo == i_MVR2USP) { + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); + _tcscat(instrname, _T(",USP")); + } else if (lookup->mnemo == i_MVUSP2R) { + _tcscat(instrname, _T("USP,")); + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); + } else if (lookup->mnemo == i_MV2SR) { + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); + _tcscat(instrname, dp->size == sz_byte ? _T(",CCR") : _T(",SR")); + } else if (lookup->mnemo == i_MVSR2) { + _tcscat(instrname, dp->size == sz_byte ? _T("CCR,") : _T("SR,")); + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); + } else if (lookup->mnemo == i_MVMEL) { + uae_u16 mask = extra; + pc += 2; + pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); + movemout (instrname, mask, dp->dmode, 0, true); + } else if (lookup->mnemo == i_MVMLE) { + uae_u16 mask = extra; + pc += 2; + if (movemout(instrname, mask, dp->dmode, 0, false)) + _tcscat(instrname, _T(",")); + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); + } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) { + TCHAR *p; + extra = get_word_debug(pc); + pc += 2; + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); + p = instrname + _tcslen(instrname); + if (extra & 0x0400) + _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7); + else + _stprintf(p, _T(",D%d"), (extra >> 12) & 7); + } else if (lookup->mnemo == i_MOVES) { + TCHAR *p; + pc += 2; + if (!(extra & 0x0800)) { + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); + p = instrname + _tcslen(instrname); + _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7); + } else { + p = instrname + _tcslen(instrname); + _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7); + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); + } + } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || + lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR || + lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS || + lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) { + TCHAR *p; + int reg = -1; + + pc += 2; + p = instrname + _tcslen(instrname); + if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS) + reg = (extra >> 12) & 7; + if (lookup->mnemo == i_BFINS) + _stprintf(p, _T("D%d,"), reg); + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); + _tcscat(instrname, _T(" {")); + p = instrname + _tcslen(instrname); + if (extra & 0x0800) + _stprintf(p, _T("D%d"), (extra >> 6) & 7); + else + _stprintf(p, _T("%d"), (extra >> 6) & 31); + _tcscat(instrname, _T(":")); + p = instrname + _tcslen(instrname); + if (extra & 0x0020) + _stprintf(p, _T("D%d"), extra & 7); + else + _stprintf(p, _T("%d"), extra & 31); + _tcscat(instrname, _T("}")); + p = instrname + _tcslen(instrname); + if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU) + _stprintf(p, _T(",D%d"), reg); + } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || + lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) { + if ((opcode & 0xc0) == 0xc0) + _tcscat(instrname, _T("BC")); + else if (opcode & 0x80) + _tcscat(instrname, _T("IC")); + else if (opcode & 0x40) + _tcscat(instrname, _T("DC")); + else + _tcscat(instrname, _T("?")); + if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) { + TCHAR *p = instrname + _tcslen(instrname); + _stprintf(p, _T(",(A%d)"), opcode & 7); + } + } else if (lookup->mnemo == i_MOVE16) { + TCHAR *p = instrname + _tcslen(instrname); + if (opcode & 0x20) { + _stprintf(p, _T("(A%d)+,(A%d)+"), opcode & 7, (extra >> 12) & 7); + pc += 2; + } else { + uae_u32 addr = get_long_debug(pc + 2); + int ay = opcode & 7; + pc += 4; + switch ((opcode >> 3) & 3) + { + case 0: + _stprintf(p, _T("(A%d)+,$%08x"), ay, addr); + break; + case 1: + _stprintf(p, _T("$%08x,(A%d)+"), addr, ay); + break; + case 2: + _stprintf(p, _T("(A%d),$%08x"), ay, addr); + break; + case 3: + _stprintf(p, _T("$%08x,(A%d)"), addr, ay); + break; + } + } + } else if (lookup->mnemo == i_FDBcc) { + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); + pc += 2; + _tcscat(instrname, _T(",")); + pc = ShowEA(NULL, pc, opcode, 0, imm1, sz_word, instrname, &deaddr2, safemode); + } else if (lookup->mnemo == i_FPP) { + TCHAR *p; + int ins = extra & 0x3f; + int size = (extra >> 10) & 7; + + pc += 2; + if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7) + fpdata fp; + fpu_get_constant(&fp, extra); + _stprintf(instrname, _T("FMOVECR.X #0x%02x [%s],FP%d"), extra & 0x7f, fpp_print(&fp, 0), (extra >> 7) & 7); + } else if ((extra & 0x8000) == 0x8000) { // FMOVEM + int dr = (extra >> 13) & 1; + int mode; + int dreg = (extra >> 4) & 7; + int regmask, fpmode; + + if (extra & 0x4000) { + mode = (extra >> 11) & 3; + regmask = extra & 0xff; // FMOVEM FPx + fpmode = 1; + _tcscpy(instrname, _T("FMOVEM.X ")); + } else { + mode = 0; + regmask = (extra >> 10) & 7; // FMOVEM control + fpmode = 2; + _tcscpy(instrname, _T("FMOVEM.L ")); + if (regmask == 1 || regmask == 2 || regmask == 4) + _tcscpy(instrname, _T("FMOVE.L ")); + } + p = instrname + _tcslen(instrname); + if (dr) { + if (mode & 1) + _stprintf(p, _T("D%d"), dreg); + else + movemout(p, regmask, dp->dmode, fpmode, false); + _tcscat(instrname, _T(",")); + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); + } else { + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); + p = instrname + _tcslen(instrname); + if (mode & 1) + _stprintf(p, _T(",D%d"), dreg); + else + movemout(p, regmask, dp->dmode, fpmode, true); + } + } else { + if (fpuopcodes[ins]) + _tcscpy(instrname, fpuopcodes[ins]); + else + _tcscpy(instrname, _T("F?")); + + if ((extra & 0xe000) == 0x6000) { // FMOVE to memory + int kfactor = extra & 0x7f; + _tcscpy(instrname, _T("FMOVE.")); + _tcscat(instrname, fpsizes[size]); + _tcscat(instrname, _T(" ")); + p = instrname + _tcslen(instrname); + _stprintf(p, _T("FP%d,"), (extra >> 7) & 7); + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode); + p = instrname + _tcslen(instrname); + if (size == 7) { + _stprintf(p, _T(" {D%d}"), (kfactor >> 4)); + } else if (kfactor) { + if (kfactor & 0x40) + kfactor |= ~0x3f; + _stprintf(p, _T(" {%d}"), kfactor); + } + } else { + if (extra & 0x4000) { // source is EA + _tcscat(instrname, _T(".")); + _tcscat(instrname, fpsizes[size]); + _tcscat(instrname, _T(" ")); + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode); + } else { // source is FPx + p = instrname + _tcslen(instrname); + _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7); + } + p = instrname + _tcslen(instrname); + if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7))) + _stprintf(p, _T(",FP%d"), (extra >> 7) & 7); + if (ins >= 0x30 && ins < 0x38) { // FSINCOS + p = instrname + _tcslen(instrname); + _stprintf(p, _T(",FP%d"), extra & 7); + } + } + } + } else if (lookup->mnemo == i_MMUOP030) { + pc = disasm_mmu030(pc, opcode, extra, dp, instrname, &seaddr2, safemode); + } else if ((opcode & 0xf000) == 0xa000) { + _tcscpy(instrname, _T("A-LINE")); + } else { + if (dp->suse) { + pc = ShowEA (NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); + + // JSR x(a6) / JMP x(a6) + if (opcode == 0x4ea8 + 6 || opcode == 0x4ee8 + 6) { + TCHAR sname[256]; + if (debugger_get_library_symbol(m68k_areg(regs, 6), 0xffff0000 | extra, sname)) { + TCHAR *p = instrname + _tcslen(instrname); + _stprintf(p, _T(" %s"), sname); + resolve_if_jmp(instrname, m68k_areg(regs, 6) + (uae_s16)extra); + } + } + // show target address if JSR x(pc) + JMP xxxx combination + if (opcode == 0x4eba && seaddr2 && instrname[0]) { // JSR x(pc) + resolve_if_jmp(instrname, seaddr2); + } + } + if (dp->suse && dp->duse) + _tcscat (instrname, _T(",")); + if (dp->duse) { + pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode); + } + } + + for (i = 0; i < (pc - oldpc) / 2; i++) { + buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2)); + } + while (i++ < 5) + buf = buf_out (buf, &bufsize, _T(" ")); + + if (illegal) + buf = buf_out (buf, &bufsize, _T("[ ")); + buf = buf_out (buf, &bufsize, instrname); + if (illegal) + buf = buf_out (buf, &bufsize, _T(" ]")); + + if (ccpt != 0) { + uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2; + if (deaddr) + *deaddr = pc; + if ((opcode & 0xf000) == 0xf000) { + if (fpp_cond(dp->cc)) { + buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2); + } else { + buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2); + } + } else { + if (dp->mnemo == i_Bcc || dp->mnemo == i_DBcc) { + if (cctrue(dp->cc)) { + buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2); + } else { + buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2); + } + } else { + if (cctrue(dp->cc)) { + buf = buf_out(buf, &bufsize, _T(" (T)")); + } else { + buf = buf_out(buf, &bufsize, _T(" (F)")); + } + } + } + } else if ((opcode & 0xff00) == 0x6100) { /* BSR */ + if (deaddr) + *deaddr = pc; + buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2); + } + buf = buf_out (buf, &bufsize, _T("\n")); + + for (uaecptr segpc = oldpc; segpc < pc; segpc++) { + TCHAR segout[256]; + if (debugmem_get_symbol(segpc, segout, sizeof(segout) / sizeof(TCHAR))) { + _tcscat(segout, _T(":\n")); + if (bufsize > _tcslen(segout)) { + memmove(symbolpos + _tcslen(segout), symbolpos, (_tcslen(symbolpos) + 1) * sizeof(TCHAR)); + memcpy(symbolpos, segout, _tcslen(segout) * sizeof(TCHAR)); + bufsize -= _tcslen(segout); + buf += _tcslen(segout); + symbolpos += _tcslen(segout); + } + } + } + + int srcline = -1; + for (uaecptr segpc = oldpc; segpc < pc; segpc++) { + TCHAR sourceout[256]; + int line = debugmem_get_sourceline(segpc, sourceout, sizeof(sourceout) / sizeof(TCHAR)); + if (line < 0) + break; + if (srcline != line) { + if (srcline < 0) + buf = buf_out(buf, &bufsize, _T("\n")); + buf = buf_out(buf, &bufsize, sourceout); + srcline = line; + } + } + if (srcline >= 0) { + buf = buf_out(buf, &bufsize, _T("\n")); + } + + if (illegal) + pc = m68kpc_illg; + } + if (nextpc) + *nextpc = pc; + if (seaddr) + *seaddr = seaddr2; + if (deaddr) + *deaddr = deaddr2; +} + + +/************************************************************* +Disasm the m68kcode at the given address into instrname +and instrcode +*************************************************************/ +void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc, uaecptr lastpc) +{ + TCHAR *ccpt; + uae_u32 opcode; + struct mnemolookup *lookup; + struct instr *dp; + uaecptr pc, oldpc; + + pc = oldpc = addr; + opcode = get_word_debug (pc); + if (cpufunctbl[opcode] == op_illg_1) { + opcode = 0x4AFC; + } + dp = table68k + opcode; + for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++); + + pc += 2; + + _tcscpy (instrname, lookup->name); + ccpt = _tcsstr (instrname, _T("cc")); + if (ccpt != 0) { + _tcsncpy (ccpt, ccnames[dp->cc], 2); + } + switch (dp->size){ + case sz_byte: _tcscat (instrname, _T(".B ")); break; + case sz_word: _tcscat (instrname, _T(".W ")); break; + case sz_long: _tcscat (instrname, _T(".L ")); break; + default: _tcscat (instrname, _T(" ")); break; + } + + if (dp->suse) { + pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0); + } + if (dp->suse && dp->duse) + _tcscat (instrname, _T(",")); + if (dp->duse) { + pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0); + } + if (instrcode) + { + int i; + for (i = 0; i < (pc - oldpc) / 2; i++) + { + _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2)); + instrcode += _tcslen (instrcode); + } + } + if (nextpc) + *nextpc = pc; +} diff --git a/fpp.cpp b/fpp.cpp index 54d285a1..3372f60d 100644 --- a/fpp.cpp +++ b/fpp.cpp @@ -34,6 +34,12 @@ #include "cpummu030.h" #include "debug.h" +#ifndef CPU_TESTER +#define SUPPORT_MMU 1 +#else +#define SUPPORT_MMU 0 +#endif + #include "softfloat/softfloat.h" // global variable for JIT FPU @@ -989,7 +995,7 @@ static void fp_unimp_datatype(uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr fsave_data.stag = 7; // undocumented } else { fpp_from_exten_fmovem(src, &fsave_data.et[0], &fsave_data.et[1], &fsave_data.et[2]); - fsave_data.stag = get_ftag(src, (opclass == 0) ? -1U : size); + fsave_data.stag = get_ftag(src, (opclass == 0) ? 0xffffffff : size); if (fsave_data.stag == 5) { fsave_data.et[0] = (size == 1) ? 0x3f800000 : 0x3c000000; // exponent for denormalized single and double } @@ -1046,11 +1052,12 @@ static bool fault_if_no_fpu (uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr #if EXCEPTION_FPP write_log (_T("no FPU: %04X-%04X PC=%08X\n"), opcode, extra, oldpc); #endif +#if SUPPORT_MMU if (fpu_mmu_fixup) { m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value; mmufixup[0].reg = -1; - } +#endif fpu_op_illg(opcode, ea, oldpc); return true; } @@ -1358,17 +1365,21 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old break; case 3: // (An)+ // Also needed by fault_if_no_fpu +#if SUPPORT_MMU mmufixup[0].reg = reg; mmufixup[0].value = m68k_areg (regs, reg); fpu_mmu_fixup = true; +#endif ad = m68k_areg (regs, reg); m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; case 4: // -(An) // Also needed by fault_if_no_fpu +#if SUPPORT_MMU mmufixup[0].reg = reg; mmufixup[0].value = m68k_areg (regs, reg); fpu_mmu_fixup = true; +#endif m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; ad = m68k_areg (regs, reg); // 68060 no fpu -(an): EA points to -4, not -12 if extended precision @@ -1576,17 +1587,21 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o break; case 3: // (An)+ // Also needed by fault_if_no_fpu +#if SUPPORT_MMU mmufixup[0].reg = reg; mmufixup[0].value = m68k_areg (regs, reg); fpu_mmu_fixup = true; +#endif ad = m68k_areg (regs, reg); m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; case 4: // -(An) // Also needed by fault_if_no_fpu +#if SUPPORT_MMU mmufixup[0].reg = reg; mmufixup[0].value = m68k_areg (regs, reg); fpu_mmu_fixup = true; +#endif m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; ad = m68k_areg (regs, reg); // 68060 no fpu -(an): EA points to -4, not -12 if extended precision @@ -1866,7 +1881,7 @@ void fpuop_dbcc (uae_u32 opcode, uae_u16 extra) if (fault_if_no_6888x (opcode, extra, pc - 4)) return; - disp = (uae_s32) (uae_s16) x_cp_next_iword (); + disp = (uae_s32) (uae_s16)x_cp_next_iword(); if (fault_if_no_fpu_u (opcode, extra, pc + disp, pc - 4)) return; regs.fpiar = pc - 4; @@ -2432,6 +2447,7 @@ static uaecptr fmovem2mem (uaecptr ad, uae_u32 list, int incr, int regdir) // 68030 MMU state saving is annoying! if (currprefs.mmu_model == 68030) { +#if SUPPORT_MMU int idx = 0; uae_u32 wrd[3]; mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM1; @@ -2461,6 +2477,7 @@ static uaecptr fmovem2mem (uaecptr ad, uae_u32 list, int incr, int regdir) } list <<= 1; } +#endif } else { for (int r = 0; r < 8; r++) { uae_u32 wrd1, wrd2, wrd3; @@ -2489,6 +2506,7 @@ static uaecptr fmovem2fpp (uaecptr ad, uae_u32 list, int incr, int regdir) int reg; if (currprefs.mmu_model == 68030) { +#if SUPPORT_MMU uae_u32 wrd[3]; int idx = 0; mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM1 | MMU030_STATEFLAG1_FMOVEM; @@ -2522,6 +2540,7 @@ static uaecptr fmovem2fpp (uaecptr ad, uae_u32 list, int incr, int regdir) } list <<= 1; } +#endif } else { for (int r = 0; r < 8; r++) { uae_u32 wrd1, wrd2, wrd3; @@ -3083,9 +3102,11 @@ void fpuop_arithmetic (uae_u32 opcode, uae_u16 extra) write_log(_T("FPUOP %04x %04x PC=%08x\n"), opcode, extra, M68K_GETPC); #endif fpuop_arithmetic2 (opcode, extra); +#if SUPPORT_MMU if (fpu_mmu_fixup) { mmufixup[0].reg = -1; } +#endif } static void get_features(void) @@ -3099,6 +3120,8 @@ void fpu_clearstatus(void) fpp_clear_status(); } +#ifndef CPU_TESTER + void fpu_modechange(void) { uae_u32 temp_ext[8][3]; @@ -3131,6 +3154,8 @@ void fpu_modechange(void) } } +#endif + #if FPU_TEST static void fpu_test(void) @@ -3149,6 +3174,7 @@ static void fpu_test(void) void fpu_reset (void) { +#ifndef CPU_TESTER currprefs.fpu_mode = changed_prefs.fpu_mode; if (currprefs.fpu_mode > 0) { fp_init_softfloat(currprefs.fpu_model); @@ -3170,10 +3196,15 @@ void fpu_reset (void) #ifdef MSVC_LONG_DOUBLE init_fpucw_x87_80(); #endif +#endif +#else + fp_init_softfloat(currprefs.fpu_model); + use_long_double = false; #endif regs.fpiar = 0; regs.fpu_exp_state = 0; + regs.fp_unimp_pend = 0; get_features(); fpp_set_fpcr (0); fpp_set_fpsr (0); @@ -3188,6 +3219,8 @@ void fpu_reset (void) } +#ifndef CPU_TESTER + uae_u8 *restore_fpu (uae_u8 *src) { uae_u32 w1, w2, w3; @@ -3326,3 +3359,5 @@ uae_u8 *save_fpu (int *len, uae_u8 *dstptr) *len = dst - dstbak; return dstbak; } + +#endif diff --git a/gencpu.cpp b/gencpu.cpp index 07105e86..5e5622cf 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -18,6 +18,8 @@ * Copyright 1995, 1996, 1997, 1998, 1999, 2000 Bernd Schmidt */ +#define CPU_TESTER 0 + #include "sysconfig.h" #include "sysdeps.h" #include @@ -44,6 +46,8 @@ static int using_ce; static int using_tracer; static int using_waitstates; static int using_simple_cycles; +static int using_debugmem; +static int using_test; static int cpu_level, cpu_generic; static int count_read, count_write, count_cycles, count_ncycles; static int count_cycles_ce020; @@ -814,7 +818,7 @@ static void setpc (const char *format, ...) if (using_mmu) printf("\tm68k_setpci(%s);\n", buffer); - else if (using_prefetch || using_prefetch_020) + else if (using_prefetch || using_prefetch_020 || using_test) printf ("\tm68k_setpci_j(%s);\n", buffer); else printf ("\tm68k_setpc_j(%s);\n", buffer); @@ -829,7 +833,7 @@ static void incpc (const char *format, ...) _vsnprintf (buffer, 1000 - 1, format, parms); va_end (parms); - if (using_mmu || using_prefetch || using_prefetch_020) + if (using_mmu || using_prefetch || using_prefetch_020 || using_test) printf ("\tm68k_incpci (%s);\n", buffer); else printf ("\tm68k_incpc (%s);\n", buffer); @@ -2337,14 +2341,13 @@ static void genmovemel_ce (uae_u16 opcode) int size = table68k[opcode].size == sz_long ? 4 : 2; printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0)); printf ("\tuae_u32 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - printf ("\tuae_u32 v;\n"); if (table68k[opcode].dmode == Ad8r || table68k[opcode].dmode == PC8r) addcycles000 (2); genamode (NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, GF_AA | GF_MOVE); start_brace (); if (table68k[opcode].size == sz_long) { printf ("\twhile (dmask) {\n"); - printf ("\t\tv = %s (srca) << 16;\n", srcw); + printf ("\t\tuae_u32 v = %s (srca) << 16;\n", srcw); printf ("\t\tv |= %s (srca + 2);\n", srcw); printf ("\t\tm68k_dreg (regs, movem_index1[dmask]) = v;\n"); printf ("\t\tsrca += %d;\n", size); @@ -2352,7 +2355,7 @@ static void genmovemel_ce (uae_u16 opcode) addcycles000_nonce("\t\t", 8); printf ("\t}\n"); printf ("\twhile (amask) {\n"); - printf ("\t\tv = %s (srca) << 16;\n", srcw); + printf ("\t\tuae_u32 v = %s (srca) << 16;\n", srcw); printf ("\t\tv |= %s (srca + 2);\n", srcw); printf ("\t\tm68k_areg (regs, movem_index1[amask]) = v;\n"); printf ("\t\tsrca += %d;\n", size); @@ -3187,6 +3190,21 @@ static void resetvars (void) dstb = "put_byte"; } } + + if (using_test) { + prefetch_word = "get_word_test_prefetch"; + srcwi = "get_wordi_test"; + srcl = "get_long_test"; + dstl = "put_long_test"; + srcw = "get_word_test"; + dstw = "put_word_test"; + srcb = "get_byte_test"; + dstb = "put_byte_test"; + do_cycles = "do_cycles_test"; + getpc = "m68k_getpci()"; + disp000 = "get_disp_ea_test"; + } + if (!dstld) dstld = dstl; if (!dstwd) @@ -3771,6 +3789,7 @@ static void gen_opcode (unsigned int opcode) int dualprefetch = curi->dmode == absl && (curi->smode != Dreg && curi->smode != Areg && curi->smode != imm); genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0); + flags = GF_MOVE | GF_APDI; //if (curi->size == sz_long && (curi->smode == Dreg || curi->smode == Areg)) // flags &= ~GF_APDI; @@ -3784,8 +3803,9 @@ static void gen_opcode (unsigned int opcode) fill_prefetch_next (); prefetch_done = 1; } + if (curi->mnemo == i_MOVE) - genflags (flag_logical, curi->size, "src", "", ""); + genflags(flag_logical, curi->size, "src", "", ""); if (curi->size == sz_long) { if ((curi->dmode == Ad16 || curi->dmode == PC16) && curi->smode == imm) { @@ -3940,9 +3960,9 @@ static void gen_opcode (unsigned int opcode) printf("\tuae_u16 sr = src;\n"); } // STOP undocumented features: - // if SR is not set: + // if new SR S-bit is not set: // 68000 (68010?): Update SR, increase PC and then cause privilege violation exception (handled in newcpu) - // 68000 (68010?): Traced STOP also runs 4 cycles faster. + // 68000 (68010?): Traced STOP runs 4 cycles faster. // 68020 68030: STOP works normally // 68040 68060: Immediate privilege violation exception if ((cpu_level == 0 || cpu_level == 1) && using_ce) { @@ -3989,7 +4009,9 @@ static void gen_opcode (unsigned int opcode) printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); setpc ("pc"); - printf("\tbranch_stack_pop_rte(oldpc);\n"); + if (using_debugmem) { + printf("\tbranch_stack_pop_rte(oldpc);\n"); + } makefromsr(); } else if (cpu_level == 1 && using_prefetch) { // 68010 @@ -4019,7 +4041,9 @@ static void gen_opcode (unsigned int opcode) printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); setpc ("newpc"); - printf("\tbranch_stack_pop_rte(oldpc);\n"); + if (using_debugmem) { + printf("\tbranch_stack_pop_rte(oldpc);\n"); + } check_ipl (); need_endlabel = 1; } else { @@ -4093,7 +4117,9 @@ static void gen_opcode (unsigned int opcode) printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); setpc ("newpc"); - printf("\tbranch_stack_pop_rte(oldpc);\n"); + if (using_debugmem) { + printf("\tbranch_stack_pop_rte(oldpc);\n"); + } check_ipl (); need_endlabel = 1; } @@ -4173,7 +4199,7 @@ static void gen_opcode (unsigned int opcode) printf("\t\tgoto %s;\n", endlabelstr); printf("\t}\n"); } - if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce) { + if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce && !using_test) { printf("\tm68k_do_rtsi_jit ();\n"); } else if (using_mmu) { printf ("\tm68k_do_rts_mmu%s ();\n", mmu_postfix); @@ -4190,8 +4216,10 @@ static void gen_opcode (unsigned int opcode) } else { printf ("\tm68k_do_rts ();\n"); } - printf("\tif (debugmem_trace)\n"); - printf("\t\tbranch_stack_pop_rts(pc);\n"); + if (using_debugmem) { + printf("\tif (debugmem_trace)\n"); + printf("\t\tbranch_stack_pop_rts(pc);\n"); + } printf ("\tif (%s & 1) {\n", getpc); printf ("\t\tuaecptr faultpc = %s;\n", getpc); setpc ("pc"); @@ -4277,8 +4305,10 @@ static void gen_opcode (unsigned int opcode) } else { printf ("\t%s (m68k_areg (regs, 7), nextpc);\n", dstl); } - printf("\tif (debugmem_trace)\n"); - printf("\t\tbranch_stack_push(oldpc, nextpc);\n"); + if (using_debugmem) { + printf("\tif (debugmem_trace)\n"); + printf("\t\tbranch_stack_push(oldpc, nextpc);\n"); + } } count_write += 2; fill_prefetch_full_020 (); @@ -4336,7 +4366,7 @@ static void gen_opcode (unsigned int opcode) addcycles000 (2); printf("\tuaecptr oldpc = %s;\n", getpc); printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset); - if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce) { + if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce && !using_test) { printf("\tm68k_do_bsri_jit (nextpc, s);\n"); } else if (using_mmu) { printf ("\tm68k_do_bsr_mmu%s (nextpc, s);\n", mmu_postfix); @@ -4351,8 +4381,10 @@ static void gen_opcode (unsigned int opcode) } else { printf ("\tm68k_do_bsr (nextpc, s);\n"); } - printf("\tif (debugmem_trace)\n"); - printf("\t\tbranch_stack_push(oldpc, nextpc);\n"); + if (using_debugmem) { + printf("\tif (debugmem_trace)\n"); + printf("\t\tbranch_stack_push(oldpc, nextpc);\n"); + } count_write += 2; clear_m68k_offset(); fill_prefetch_full (); @@ -4708,7 +4740,7 @@ bccl_not68020: printf ("\tcnt &= 63;\n"); printf ("\tCLEAR_CZNV ();\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); - printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size)); + printf ("\t\tval = %s & (uae_u32)(0 - sign);\n", bit_mask (curi->size)); printf ("\t\tSET_CFLG (sign);\n"); duplicate_carry (1); if (source_is_imm1_8 (curi)) @@ -4719,7 +4751,7 @@ bccl_not68020: printf ("\t\tSET_CFLG (val & 1);\n"); duplicate_carry (1); printf ("\t\tval >>= 1;\n"); - printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n", + printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)(0 - sign);\n", bit_mask (curi->size), bit_size (curi->size)); printf ("\t\tval &= %s;\n", bit_mask (curi->size)); @@ -5570,14 +5602,15 @@ bccl_not68020: { if ((opcode & 0xfff8) == 0xf620) { /* MOVE16 (Ax)+,(Ay)+ */ - printf ("\tuae_u32 v[4];\n"); printf ("\tuaecptr mems = m68k_areg (regs, srcreg) & ~15, memd;\n"); printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword (0)); printf ("\tmemd = m68k_areg (regs, dstreg) & ~15;\n"); if (using_mmu >= 68040) { + printf("\tuae_u32 v[4];\n"); printf ("\tget_move16_mmu (mems, v);\n"); printf ("\tput_move16_mmu (memd, v);\n"); } else { + printf("\tuae_u32 v[4];\n"); printf ("\tv[0] = %s (mems);\n", srcl); printf ("\tv[1] = %s (mems + 4);\n", srcl); printf ("\tv[2] = %s (mems + 8);\n", srcl); @@ -5592,18 +5625,19 @@ bccl_not68020: printf ("\tm68k_areg (regs, dstreg) += 16;\n"); } else { /* Other variants */ - printf ("\tuae_u32 v[4];\n"); genamode (curi, curi->smode, "srcreg", curi->size, "mems", 0, 2, 0); genamode (curi, curi->dmode, "dstreg", curi->size, "memd", 0, 2, 0); if (using_mmu == 68040) { printf ("\tget_move16_mmu (memsa, mmu040_move16);\n"); printf ("\tput_move16_mmu (memda, mmu040_move16);\n"); } else if (using_mmu == 68060) { + printf("\tuae_u32 v[4];\n"); printf ("\tget_move16_mmu (memsa, v);\n"); printf ("\tput_move16_mmu (memda, v);\n"); } else { printf ("\tmemsa &= ~15;\n"); printf ("\tmemda &= ~15;\n"); + printf("\tuae_u32 v[4];\n"); printf ("\tv[0] = %s (memsa);\n", srcl); printf ("\tv[1] = %s (memsa + 4);\n", srcl); printf ("\tv[2] = %s (memsa + 8);\n", srcl); @@ -6043,6 +6077,70 @@ static void generate_func (const char *extra) fprintf (stblfile, "{ 0, 0 }};\n"); } +#if CPU_TESTER + +static void generate_cpu_test(int mode) +{ + char fname[100]; + const char *extra = "_test", *extraup; + int rp; + int id = 90 + mode; + + using_tracer = 0; + extraup = ""; + postfix = id; + + fprintf(stblfile, "#ifdef CPUEMU_%d%s\n", postfix, extraup); + sprintf(fname, "cpuemu_%d%s.cpp", postfix, extra); + if (freopen(fname, "wb", stdout) == NULL) { + abort(); + } + + using_exception_3 = 1; + using_prefetch = 0; + using_prefetch_020 = 0; + using_ce = 0; + using_ce020 = 0; + using_mmu = 0; + using_waitstates = 0; + memory_cycle_cnt = 4; + mmu_postfix = ""; + xfc_postfix = ""; + using_simple_cycles = 0; + using_indirect = 1; + cpu_generic = false; + + cpu_level = 0; + using_prefetch = 1; + using_exception_3 = 1; + using_simple_cycles = 1; + + if (mode == 1) { + cpu_level = 1; + } else if (mode == 2) { + cpu_level = 2; + using_prefetch = 0; + using_simple_cycles = 0; + } + + + read_counts(); + for (rp = 0; rp < nr_cpuop_funcs; rp++) + opcode_next_clev[rp] = cpu_level; + + printf("#include \"cputest.h\"\n"); + if (!mode) { + fprintf(stblfile, "#include \"cputest.h\"\n"); + } + + fprintf(stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d%s)[] = {\n", postfix, extra); + endlabelno = id; + generate_func(extra); + fprintf(stblfile, "#endif /* CPUEMU_%d%s */\n", postfix, extraup); +} + +#endif + static void generate_cpu (int id, int mode) { char fname[100]; @@ -6232,8 +6330,6 @@ static void generate_cpu (int id, int mode) int main(int argc, char *argv[]) { - int i; - read_table68k (); do_merges (); @@ -6247,18 +6343,34 @@ int main(int argc, char *argv[]) * cputbl.h that way), but cpuopti can't cope. That could be fixed, but * I don't dare to touch the 68k version. */ - headerfile = fopen ("cputbl.h", "wb"); +#if CPU_TESTER - stblfile = fopen ("cpustbl.cpp", "wb"); - generate_includes (stblfile, 0); + using_test = 1; + headerfile = fopen("cputbl_test.h", "wb"); + stblfile = fopen("cpustbl_test.cpp", "wb"); + generate_stbl = 1; + generate_cpu_test(0); + generate_cpu_test(1); + generate_cpu_test(2); - for (i = 0; i <= 55; i++) { +#else + + using_debugmem = 1; + + headerfile = fopen("cputbl.h", "wb"); + + stblfile = fopen("cpustbl.cpp", "wb"); + generate_includes(stblfile, 0); + + for (int i = 0; i <= 55; i++) { if ((i >= 6 && i < 11) || (i > 14 && i < 20) || (i > 25 && i < 31) || (i > 35 && i < 40)) continue; generate_stbl = 1; generate_cpu (i, 0); } +#endif + free (table68k); return 0; } diff --git a/include/cputest.h b/include/cputest.h new file mode 100644 index 00000000..29cdcdab --- /dev/null +++ b/include/cputest.h @@ -0,0 +1,58 @@ + +#include "sysconfig.h" +#include "sysdeps.h" + +#include "options.h" +#include "memory.h" +#include "newcpu.h" + +#include "cputest/cputest_defines.h" + + +typedef uae_u32 REGPARAM3 cpuop_func(uae_u32) REGPARAM; + +#include "cputbl_test.h" + +#define CPUFUNC(x) x##_ff +#define SET_CFLG_ALWAYS(x) SET_CFLG(x) +#define SET_NFLG_ALWAYS(x) SET_NFLG(x) + +#define m68k_dreg(r,num) ((r).regs[(num)]) +#define m68k_areg(r,num) (((r).regs + 8)[(num)]) + +int cctrue(int); + +extern const int areg_byteinc[]; +extern const int imm8_table[]; + +extern const struct cputbl op_smalltbl_90_test_ff[]; +extern const struct cputbl op_smalltbl_91_test_ff[]; +extern const struct cputbl op_smalltbl_92_test_ff[]; + +extern struct flag_struct regflags; + +extern int movem_index1[256]; +extern int movem_index2[256]; +extern int movem_next[256]; + +uae_u16 get_word_test_prefetch(int); + +void put_byte_test(uaecptr, uae_u32); +void put_word_test(uaecptr, uae_u32); +void put_long_test(uaecptr, uae_u32); + +uae_u32 get_byte_test(uaecptr); +uae_u32 get_word_test(uaecptr); +uae_u32 get_long_test(uaecptr); + +uae_u32 get_disp_ea_test(uae_u32, uae_u32); +void m68k_incpci(int); +uaecptr m68k_getpci(void); +void m68k_setpci_j(uaecptr); +void m68k_do_rtsi(void); +void m68k_do_bsri(uaecptr, uae_s32); + +void m68k_setstopped(void); +void check_t0_trace(void); + +void cpureset(void); diff --git a/include/disasm.h b/include/disasm.h new file mode 100644 index 00000000..22e79fa9 --- /dev/null +++ b/include/disasm.h @@ -0,0 +1,10 @@ +uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode); +uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name); +void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc, int safemode); +void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc, uaecptr lastpc); +uae_u32 REGPARAM2 op_illg_1(uae_u32 opcode); +uae_u32 REGPARAM2 op_unimpl_1(uae_u32 opcode); + +extern struct cpum2c m2cregs[]; +extern const TCHAR *fpuopcodes[]; +extern const TCHAR *fpsizes[]; \ No newline at end of file diff --git a/include/memory.h b/include/memory.h index 8a7c8915..fb473b48 100644 --- a/include/memory.h +++ b/include/memory.h @@ -552,6 +552,52 @@ STATIC_INLINE uae_u32 get_wordi(uaecptr addr) return memory_get_wordi(addr); } +// do split memory access if it can cross memory banks +STATIC_INLINE uae_u32 get_long_compatible(uaecptr addr) +{ + if ((addr &0xffff) < 0xfffd) { + return memory_get_long(addr); + } else if (addr & 1) { + uae_u8 v0 = memory_get_byte(addr + 0); + uae_u16 v1 = memory_get_word(addr + 1); + uae_u8 v3 = memory_get_byte(addr + 3); + return (v0 << 24) | (v1 << 8) | (v3 << 0); + } else { + uae_u16 v0 = memory_get_word(addr + 0); + uae_u16 v1 = memory_get_word(addr + 2); + return (v0 << 16) | (v1 << 0); + } +} +STATIC_INLINE uae_u32 get_word_compatible(uaecptr addr) +{ + if ((addr & 0xffff) < 0xffff) { + return memory_get_word(addr); + } else { + uae_u8 v0 = memory_get_byte(addr + 0); + uae_u8 v1 = memory_get_byte(addr + 1); + return (v0 << 8) | (v1 << 0); + } +} +STATIC_INLINE uae_u32 get_byte_compatible(uaecptr addr) +{ + return memory_get_byte(addr); +} +STATIC_INLINE uae_u32 get_longi_compatible(uaecptr addr) +{ + if ((addr & 0xffff) < 0xfffd) { + return memory_get_longi(addr); + } else { + uae_u16 v0 = memory_get_wordi(addr + 0); + uae_u16 v1 = memory_get_wordi(addr + 2); + return (v0 << 16) | (v1 << 0); + } +} +STATIC_INLINE uae_u32 get_wordi_compatible(uaecptr addr) +{ + return memory_get_wordi(addr); +} + + STATIC_INLINE uae_u32 get_long_jit(uaecptr addr) { #ifdef JIT @@ -640,6 +686,35 @@ STATIC_INLINE void put_byte (uaecptr addr, uae_u32 b) memory_put_byte(addr, b); } +// do split memory access if it can cross memory banks +STATIC_INLINE void put_long_compatible(uaecptr addr, uae_u32 l) +{ + if ((addr & 0xffff) < 0xfffd) { + memory_put_long(addr, l); + } else if (addr & 1) { + memory_put_byte(addr + 0, l >> 24); + memory_put_word(addr + 1, l >> 8); + memory_put_byte(addr + 3, l >> 0); + } else { + memory_put_word(addr + 0, l >> 16); + memory_put_word(addr + 2, l >> 0); + } +} +STATIC_INLINE void put_word_compatible(uaecptr addr, uae_u32 w) +{ + if ((addr & 0xffff) < 0xffff) { + memory_put_word(addr, w); + } else { + memory_put_byte(addr + 0, w >> 8); + memory_put_byte(addr + 1, w >> 0); + } +} +STATIC_INLINE void put_byte_compatible(uaecptr addr, uae_u32 b) +{ + memory_put_byte(addr, b); +} + + STATIC_INLINE void put_long_jit(uaecptr addr, uae_u32 l) { #ifdef JIT diff --git a/include/newcpu.h b/include/newcpu.h index 8988eb07..b7dcfb74 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -85,7 +85,7 @@ struct comptbl { #endif extern uae_u32 REGPARAM3 op_illg (uae_u32) REGPARAM; -extern void REGPARAM3 op_unimpl (uae_u16) REGPARAM; +extern void REGPARAM3 op_unimpl (uae_u32) REGPARAM; typedef uae_u8 flagtype; diff --git a/include/readcpu.h b/include/readcpu.h index 4fc4f2ec..86639dee 100644 --- a/include/readcpu.h +++ b/include/readcpu.h @@ -105,7 +105,7 @@ extern struct instr { unsigned int dmode:5; unsigned int suse:1; unsigned int duse:1; - unsigned int unused1:1; + unsigned int ccuse:1; unsigned int clev:3, unimpclev:3; unsigned int isjmp:1; unsigned int unused2:1; diff --git a/ini.cpp b/ini.cpp index f4d49d79..bd68b8fd 100644 --- a/ini.cpp +++ b/ini.cpp @@ -347,7 +347,12 @@ bool ini_getval_multi(struct ini_data *ini, const TCHAR *section, const TCHAR *k TCHAR *out2 = NULL; if (!ini_getstring_multi(ini, section, key, &out2, ctx)) return false; - *v = _tstol(out2); + if (_tcslen(out2) > 2 && out2[0] == '0' && _totupper(out2[1]) == 'X') { + TCHAR *endptr; + *v = _tcstol(out2 + 2, &endptr, 16); + } else { + *v = _tstol(out2); + } xfree(out2); return true; } diff --git a/newcpu.cpp b/newcpu.cpp index 8a6d497d..8b89290c 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -26,6 +26,7 @@ #include "memory.h" #include "custom.h" #include "newcpu.h" +#include "disasm.h" #include "cpummu.h" #include "cpummu030.h" #include "cpu_prefetch.h" @@ -988,12 +989,12 @@ static void set_x_funcs (void) x_get_ibyte = get_iibyte; x_next_iword = NULL; x_next_ilong = NULL; - x_put_long = put_long; - x_put_word = put_word; - x_put_byte = put_byte; - x_get_long = get_long; - x_get_word = get_word; - x_get_byte = get_byte; + x_put_long = put_long_compatible; + x_put_word = put_word_compatible; + x_put_byte = put_byte_compatible; + x_get_long = get_long_compatible; + x_get_word = get_word_compatible; + x_get_byte = get_byte_compatible; x_do_cycles = do_cycles; x_do_cycles_pre = do_cycles; x_do_cycles_post = do_cycles_post; @@ -1099,12 +1100,12 @@ static void set_x_funcs (void) x_get_ibyte = NULL; x_next_iword = next_iword_020_prefetch; x_next_ilong = next_ilong_020_prefetch; - x_put_long = put_long; - x_put_word = put_word; - x_put_byte = put_byte; - x_get_long = get_long; - x_get_word = get_word; - x_get_byte = get_byte; + x_put_long = put_long_compatible; + x_put_word = put_word_compatible; + x_put_byte = put_byte_compatible; + x_get_long = get_long_compatible; + x_get_word = get_word_compatible; + x_get_byte = get_byte_compatible; x_do_cycles = do_cycles; x_do_cycles_pre = do_cycles; x_do_cycles_post = do_cycles_post; @@ -1720,12 +1721,12 @@ STATIC_INLINE void count_instr (unsigned int opcode) { } -static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode) +uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode) { op_illg (opcode); return 4; } -static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode) +uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode) { if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060) op_illg (opcode); @@ -1755,7 +1756,7 @@ static void build_cpufunctbl (void) { int i, opcnt; unsigned long opcode; - const struct cputbl *tbl = 0; + const struct cputbl *tbl = NULL; int lvl, mode; if (!currprefs.cachesize) { @@ -2126,579 +2127,6 @@ struct regstruct regs, mmu_backup_regs; struct flag_struct regflags; static int m68kpc_offset; -static const TCHAR *fpsizes[] = { - _T("L"), - _T("S"), - _T("X"), - _T("P"), - _T("W"), - _T("D"), - _T("B"), - _T("P") -}; -static const int fpsizeconv[] = { - sz_long, - sz_single, - sz_extended, - sz_packed, - sz_word, - sz_double, - sz_byte, - sz_packed -}; -static const int datasizes[] = { - 1, - 2, - 4, - 4, - 8, - 12, - 12 -}; - -static void showea_val(TCHAR *buffer, uae_u16 opcode, uaecptr addr, int size) -{ - struct mnemolookup *lookup; - instr *table = &table68k[opcode]; - - if (addr >= 0xe90000 && addr < 0xf00000) - goto skip; - if (addr >= 0xdff000 && addr < 0xe00000) - goto skip; - - for (lookup = lookuptab; lookup->mnemo != table->mnemo; lookup++) - ; - if (!(lookup->flags & 1)) - goto skip; - buffer += _tcslen(buffer); - if (debug_safe_addr(addr, datasizes[size])) { - bool cached = false; - switch (size) - { - case sz_byte: - { - uae_u8 v = get_byte_cache_debug(addr, &cached); - uae_u8 v2 = v; - if (cached) - v2 = get_byte_debug(addr); - if (v != v2) { - _stprintf(buffer, _T(" [%02x:%02x]"), v, v2); - } else { - _stprintf(buffer, _T(" [%s%02x]"), cached ? _T("*") : _T(""), v); - } - } - break; - case sz_word: - { - uae_u16 v = get_word_cache_debug(addr, &cached); - uae_u16 v2 = v; - if (cached) - v2 = get_word_debug(addr); - if (v != v2) { - _stprintf(buffer, _T(" [%04x:%04x]"), v, v2); - } else { - _stprintf(buffer, _T(" [%s%04x]"), cached ? _T("*") : _T(""), v); - } - } - break; - case sz_long: - { - uae_u32 v = get_long_cache_debug(addr, &cached); - uae_u32 v2 = v; - if (cached) - v2 = get_long_debug(addr); - if (v != v2) { - _stprintf(buffer, _T(" [%08x:%08x]"), v, v2); - } else { - _stprintf(buffer, _T(" [%s%08x]"), cached ? _T("*") : _T(""), v); - } - } - break; - case sz_single: - { - fpdata fp; - fpp_to_single(&fp, get_long_debug(addr)); - _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0)); - } - break; - case sz_double: - { - fpdata fp; - fpp_to_double(&fp, get_long_debug(addr), get_long_debug(addr + 4)); - _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0)); - } - break; - case sz_extended: - { - fpdata fp; - fpp_to_exten(&fp, get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8)); - _stprintf(buffer, _T("[%s]"), fpp_print(&fp, 0)); - break; - } - case sz_packed: - _stprintf(buffer, _T("[%08x%08x%08x]"), get_long_debug(addr), get_long_debug(addr + 4), get_long_debug(addr + 8)); - break; - } - } -skip: - for (int i = 0; i < size; i++) { - TCHAR name[256]; - if (debugmem_get_symbol(addr + i, name, sizeof(name) / sizeof(TCHAR))) { - _stprintf(buffer + _tcslen(buffer), _T(" %s"), name); - } - } -} - -static uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name) -{ - uaecptr addr; - uae_u16 dp; - int r; - uae_u32 dispreg; - uaecptr pc = *pcp; - TCHAR mult[20]; - - dp = get_iword_debug(pc); - pc += 2; - - r = (dp & 0x7000) >> 12; // REGISTER - - dispreg = dp & 0x8000 ? m68k_areg(regs, r) : m68k_dreg(regs, r); - if (!(dp & 0x800)) { // W/L - dispreg = (uae_s32)(uae_s16)(dispreg); - } - - if (currprefs.cpu_model >= 68020) { - dispreg <<= (dp >> 9) & 3; // SCALE - } - - int m = 1 << ((dp >> 9) & 3); - mult[0] = 0; - if (m > 1) { - _stprintf(mult, _T("*%d"), m); - } - - buffer[0] = 0; - if ((dp & 0x100) && currprefs.cpu_model >= 68020) { - TCHAR dr[20]; - // Full format extension (68020+) - uae_s32 outer = 0, disp = 0; - if (dp & 0x80) { // BS (base register suppress) - base = 0; - name = NULL; - } - _stprintf(dr, _T("%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W'); - if (dp & 0x40) { // IS (index suppress) - dispreg = 0; - dr[0] = 0; - } - - _tcscpy(buffer, _T("(")); - TCHAR *p = buffer + _tcslen(buffer); - - if (dp & 3) { - // indirect - _stprintf(p, _T("[")); - p += _tcslen(p); - } else { - // (an,dn,word/long) - if (name) { - _stprintf(p, _T("%s,"), name); - p += _tcslen(p); - } - if (dr[0]) { - _stprintf(p, _T("%s%s,"), dr, mult); - p += _tcslen(p); - } - } - - if ((dp & 0x30) == 0x20) { // BD SIZE = 2 (WORD) - disp = (uae_s32)(uae_s16)get_iword_debug(pc); - _stprintf(p, _T("$%04x,"), (uae_s16)disp); - p += _tcslen(p); - pc += 2; - base += disp; - } else if ((dp & 0x30) == 0x30) { // BD SIZE = 3 (LONG) - disp = get_ilong_debug(pc); - _stprintf(p, _T("$%08x,"), disp); - p += _tcslen(p); - pc += 4; - base += disp; - } - - if (dp & 3) { - if (name) { - _stprintf(p, _T("%s,"), name); - p += _tcslen(p); - } - - if (!(dp & 0x04)) { - if (dr[0]) { - _stprintf(p, _T("%s%s,"), dr, mult); - p += _tcslen(p); - } - } - - if (p[-1] == ',') - p--; - _stprintf(p, _T("],")); - p += _tcslen(p); - - if ((dp & 0x04)) { - if (dr[0]) { - _stprintf(p, _T("%s%s,"), dr, mult); - p += _tcslen(p); - } - } - - } - - if ((dp & 0x03) == 0x02) { - outer = (uae_s32)(uae_s16)get_iword_debug(pc); - _stprintf(p, _T("$%04x,"), (uae_s16)outer); - p += _tcslen(p); - pc += 2; - } else if ((dp & 0x03) == 0x03) { - outer = get_ilong_debug(pc); - _stprintf(p, _T("$%08x,"), outer); - p += _tcslen(p); - pc += 4; - } - - if (p[-1] == ',') - p--; - _stprintf(p, _T(")")); - p += _tcslen(p); - - if ((dp & 0x4) == 0) - base += dispreg; - if (dp & 0x3) - base = get_long_debug(base); - if (dp & 0x4) - base += dispreg; - - addr = base + outer; - - _stprintf(p, _T(" == $%08x"), addr); - p += _tcslen(p); - - } else { - // Brief format extension - TCHAR regstr[20]; - uae_s8 disp8 = dp & 0xFF; - - regstr[0] = 0; - _stprintf(regstr, _T(",%c%d.%c"), dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W'); - addr = base + (uae_s32)((uae_s8)disp8) + dispreg; - _stprintf(buffer, _T("(%s%s%s,$%02x) == $%08x"), name, regstr, mult, disp8, addr); - if (dp & 0x100) { - _tcscat(buffer, _T(" (68020+)")); - } - } - - *pcp = pc; - return addr; -} - -uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode) -{ - uaecptr addr = pc; - uae_s16 disp16; - uae_s32 offset = 0; - TCHAR buffer[80]; - - switch (mode){ - case Dreg: - _stprintf (buffer, _T("D%d"), reg); - break; - case Areg: - _stprintf (buffer, _T("A%d"), reg); - break; - case Aind: - _stprintf (buffer, _T("(A%d)"), reg); - addr = regs.regs[reg + 8]; - showea_val(buffer, opcode, addr, size); - break; - case Aipi: - _stprintf (buffer, _T("(A%d)+"), reg); - addr = regs.regs[reg + 8]; - showea_val(buffer, opcode, addr, size); - break; - case Apdi: - _stprintf (buffer, _T("-(A%d)"), reg); - addr = regs.regs[reg + 8]; - showea_val(buffer, opcode, addr - datasizes[size], size); - break; - case Ad16: - { - TCHAR offtxt[8]; - disp16 = get_iword_debug (pc); pc += 2; - if (disp16 < 0) - _stprintf (offtxt, _T("-$%04x"), -disp16); - else - _stprintf (offtxt, _T("$%04x"), disp16); - addr = m68k_areg (regs, reg) + disp16; - _stprintf (buffer, _T("(A%d,%s) == $%08x"), reg, offtxt, addr); - showea_val(buffer, opcode, addr, size); - } - break; - case Ad8r: - { - TCHAR name[10]; - _stprintf(name, _T("A%d"), reg); - addr = ShowEA_disp(&pc, m68k_areg(regs, reg), buffer, name); - showea_val(buffer, opcode, addr, size); - } - break; - case PC16: - disp16 = get_iword_debug (pc); pc += 2; - addr += (uae_s16)disp16; - _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr); - showea_val(buffer, opcode, addr, size); - break; - case PC8r: - { - addr = ShowEA_disp(&pc, addr, buffer, _T("PC")); - showea_val(buffer, opcode, addr, size); - } - break; - case absw: - addr = (uae_s32)(uae_s16)get_iword_debug (pc); - _stprintf (buffer, _T("$%04x"), (uae_u16)addr); - pc += 2; - showea_val(buffer, opcode, addr, size); - break; - case absl: - addr = get_ilong_debug (pc); - _stprintf (buffer, _T("$%08x"), addr); - pc += 4; - showea_val(buffer, opcode, addr, size); - break; - case imm: - switch (size){ - case sz_byte: - _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff)); - pc += 2; - break; - case sz_word: - _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff)); - pc += 2; - break; - case sz_long: - _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc))); - pc += 4; - break; - case sz_single: - { - fpdata fp; - fpp_to_single(&fp, get_ilong_debug(pc)); - _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0)); - pc += 4; - } - break; - case sz_double: - { - fpdata fp; - fpp_to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4)); - _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0)); - pc += 8; - } - break; - case sz_extended: - { - fpdata fp; - fpp_to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8)); - _stprintf(buffer, _T("#%s"), fpp_print(&fp, 0)); - pc += 12; - break; - } - case sz_packed: - _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8)); - pc += 12; - break; - default: - break; - } - break; - case imm0: - offset = (uae_s32)(uae_s8)get_iword_debug (pc); - _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff)); - addr = pc + 2 + offset; - if ((opcode & 0xf000) == 0x6000) { - showea_val(buffer, opcode, addr, 1); - } - pc += 2; - break; - case imm1: - offset = (uae_s32)(uae_s16)get_iword_debug (pc); - buffer[0] = 0; - _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff)); - addr = pc + offset; - if ((opcode & 0xf000) == 0x6000) { - showea_val(buffer, opcode, addr, 2); - } - pc += 2; - break; - case imm2: - offset = (uae_s32)get_ilong_debug (pc); - _stprintf (buffer, _T("#$%08x"), (uae_u32)offset); - addr = pc + offset; - if ((opcode & 0xf000) == 0x6000) { - showea_val(buffer, opcode, addr, 4); - } - pc += 4; - break; - case immi: - offset = (uae_s32)(uae_s8)(reg & 0xff); - _stprintf (buffer, _T("#$%02x"), (uae_u8)offset); - addr = pc + offset; - break; - default: - break; - } - if (buf == NULL) - f_out (f, _T("%s"), buffer); - else - _tcscat (buf, buffer); - if (eaddr) - *eaddr = addr; - return pc; -} - -#if 0 -/* The plan is that this will take over the job of exception 3 handling - -* the CPU emulation functions will just do a longjmp to m68k_go whenever -* they hit an odd address. */ -static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val) -{ - uae_u16 dp; - uae_s8 disp8; - uae_s16 disp16; - int r; - uae_u32 dispreg; - uaecptr addr; - uae_s32 offset = 0; - - switch (mode){ - case Dreg: - *val = m68k_dreg (regs, reg); - return 1; - case Areg: - *val = m68k_areg (regs, reg); - return 1; - - case Aind: - case Aipi: - addr = m68k_areg (regs, reg); - break; - case Apdi: - addr = m68k_areg (regs, reg); - break; - case Ad16: - disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - addr = m68k_areg (regs, reg) + (uae_s16)disp16; - break; - case Ad8r: - addr = m68k_areg (regs, reg); -d8r_common: - dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - disp8 = dp & 0xFF; - r = (dp & 0x7000) >> 12; - dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r); - if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); - dispreg <<= (dp >> 9) & 3; - - if (dp & 0x100) { - uae_s32 outer = 0, disp = 0; - uae_s32 base = addr; - if (dp & 0x80) base = 0; - if (dp & 0x40) dispreg = 0; - if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - base += disp; - - if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } - if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } - - if (!(dp & 4)) base += dispreg; - if (dp & 3) base = get_long (base); - if (dp & 4) base += dispreg; - - addr = base + outer; - } else { - addr += (uae_s32)((uae_s8)disp8) + dispreg; - } - break; - case PC16: - addr = m68k_getpc () + m68kpc_offset; - disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - addr += (uae_s16)disp16; - break; - case PC8r: - addr = m68k_getpc () + m68kpc_offset; - goto d8r_common; - case absw: - addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - break; - case absl: - addr = get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - break; - case imm: - switch (size){ - case sz_byte: - *val = get_iword_1 (m68kpc_offset) & 0xff; - m68kpc_offset += 2; - break; - case sz_word: - *val = get_iword_1 (m68kpc_offset) & 0xffff; - m68kpc_offset += 2; - break; - case sz_long: - *val = get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - break; - default: - break; - } - return 1; - case imm0: - *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - return 1; - case imm1: - *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); - m68kpc_offset += 2; - return 1; - case imm2: - *val = get_ilong_1 (m68kpc_offset); - m68kpc_offset += 4; - return 1; - case immi: - *val = (uae_s32)(uae_s8)(reg & 0xff); - return 1; - default: - addr = 0; - break; - } - if ((addr & 1) == 0) - return 1; - - last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset; - last_fault_for_exception_3 = addr; - last_writeaccess_for_exception_3 = 0; - last_instructionaccess_for_exception_3 = 0; - return 0; -} -#endif - -int get_cpu_model (void) -{ - return currprefs.cpu_model; -} - - STATIC_INLINE int in_rom (uaecptr pc) { return (munge24 (pc) & 0xFFF80000) == 0xF80000; @@ -2816,6 +2244,7 @@ static void MakeFromSR_x(int t0trace) regs.s = (regs.sr >> 13) & 1; regs.m = (regs.sr >> 12) & 1; regs.intmask = (regs.sr >> 8) & 7; + if (currprefs.cpu_model >= 68020) { /* 68060 does not have MSP but does have M-bit.. */ if (currprefs.cpu_model >= 68060) @@ -3925,6 +3354,14 @@ void NMI (void) do_interrupt (7); } +static void maybe_disable_fpu(void) +{ + if (currprefs.cpu_model == 68060 && currprefs.cpuboard_type == 0 && (rtarea_base != 0xf00000 || !need_uae_boot_rom(&currprefs))) { + // disable FPU at reset if no 68060 accelerator board and no $f0 ROM. + regs.pcr |= 2; + } +} + static void m68k_reset_sr(void) { SET_XFLG ((regs.sr >> 4) & 1); @@ -4039,10 +3476,7 @@ static void m68k_reset2(bool hardreset) if (currprefs.cpu_model == 68060) { regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR; regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8; - if (currprefs.fpu_model == 0 || (currprefs.cpuboard_type == 0 && rtarea_base != 0xf00000)) { - /* disable FPU if no accelerator board and no $f0 ROM */ - regs.pcr |= 2; - } + maybe_disable_fpu(); } // regs.ce020memcycles = 0; regs.ce020startcycle = regs.ce020endcycle = 0; @@ -4141,7 +3575,7 @@ static void m68k_reset_restore(void) } } -void REGPARAM2 op_unimpl (uae_u16 opcode) +void REGPARAM2 op_unimpl (uae_u32 opcode) { static int warned; if (warned < 20) { @@ -5509,7 +4943,7 @@ static void run_cpu_thread(void *(*f)(void *)) int maxperloop = 10; while (!uae_sem_trywait(&cpu_out_sema)) { - uae_u32 cmd, addr, data, size, mode; + uae_u32 addr, data, size, mode; addr = cpu_thread_indirect_addr; data = cpu_thread_indirect_val; @@ -6656,6 +6090,7 @@ void m68k_go (int may_quit) cpu_prefs_changed_flag = 0; in_m68k_go++; for (;;) { + int restored = 0; void (*run_func)(void); cputrace.state = -1; @@ -6674,7 +6109,6 @@ void m68k_go (int may_quit) inprec_startup (); if (quit_program > 0) { - int restored = 0; cpu_keyboardreset = quit_program == UAE_RESET_KEYBOARD; cpu_hardreset = ((quit_program == UAE_RESET_HARD ? 1 : 0) | hardboot) != 0; @@ -6714,7 +6148,7 @@ void m68k_go (int may_quit) record_dma_reset (); record_dma_reset (); } - savestate_restore_finish (); + restored = savestate_restore_finish (); memory_map_dump (); if (currprefs.mmu_model == 68030) { mmu030_decode_tc (tc_030, true); @@ -6722,7 +6156,6 @@ void m68k_go (int may_quit) mmu_set_tc (regs.tcr); } startup = 1; - restored = 1; } #endif if (currprefs.produce_sound == 0) @@ -6786,6 +6219,13 @@ void m68k_go (int may_quit) event_wait = true; unset_special(SPCFLAG_MODE_CHANGE); +#ifdef SAVESTATE + if (restored) { + restored = 0; + savestate_restore_final(); + } +#endif + if (!regs.halted) { // check that PC points to something that looks like memory. uaecptr pc = m68k_getpc(); @@ -6833,1628 +6273,38 @@ void m68k_go (int may_quit) in_m68k_go--; } -#if 0 -static void m68k_verify (uaecptr addr, uaecptr *nextpc) -{ - uae_u16 opcode, val; - struct instr *dp; - opcode = get_iword_1 (0); - last_op_for_exception_3 = opcode; - m68kpc_offset = 2; - if (cpufunctbl[opcode] == op_illg_1) { - opcode = 0x4AFC; - } - dp = table68k + opcode; +void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc) +{ + TCHAR *buf; - if (dp->suse) { - if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) { - Exception (3, 0); - return; - } - } - if (dp->duse) { - if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) { - Exception (3, 0); - return; - } - } + buf = xcalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt); + if (!buf) + return; + m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, seaddr, deaddr, lastpc, 1); + xfree (buf); } -#endif - -static const TCHAR *ccnames[] = +void m68k_disasm (uaecptr addr, uaecptr *nextpc, uaecptr lastpc, int cnt) { - _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"), - _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE") -}; -static const TCHAR *fpccnames[] = -{ - _T("F"), - _T("EQ"), - _T("OGT"), - _T("OGE"), - _T("OLT"), - _T("OLE"), - _T("OGL"), - _T("OR"), - _T("UN"), - _T("UEQ"), - _T("UGT"), - _T("UGE"), - _T("ULT"), - _T("ULE"), - _T("NE"), - _T("T"), - _T("SF"), - _T("SEQ"), - _T("GT"), - _T("GE"), - _T("LT"), - _T("LE"), - _T("GL"), - _T("GLE"), - _T("NGLE"), - _T("NGL"), - _T("NLE"), - _T("NLT"), - _T("NGE"), - _T("NGT"), - _T("SNE"), - _T("ST") -}; -static const TCHAR *fpuopcodes[] = -{ - _T("FMOVE"), - _T("FINT"), - _T("FSINH"), - _T("FINTRZ"), - _T("FSQRT"), - NULL, - _T("FLOGNP1"), - NULL, - _T("FETOXM1"), - _T("FTANH"), - _T("FATAN"), - NULL, - _T("FASIN"), - _T("FATANH"), - _T("FSIN"), - _T("FTAN"), - _T("FETOX"), // 0x10 - _T("FTWOTOX"), - _T("FTENTOX"), - NULL, - _T("FLOGN"), - _T("FLOG10"), - _T("FLOG2"), - NULL, - _T("FABS"), - _T("FCOSH"), - _T("FNEG"), - NULL, - _T("FACOS"), - _T("FCOS"), - _T("FGETEXP"), - _T("FGETMAN"), - _T("FDIV"), // 0x20 - _T("FMOD"), - _T("FADD"), - _T("FMUL"), - _T("FSGLDIV"), - _T("FREM"), - _T("FSCALE"), - _T("FSGLMUL"), - _T("FSUB"), - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - _T("FSINCOS"), // 0x30 - _T("FSINCOS"), - _T("FSINCOS"), - _T("FSINCOS"), - _T("FSINCOS"), - _T("FSINCOS"), - _T("FSINCOS"), - _T("FSINCOS"), - _T("FCMP"), - NULL, - _T("FTST"), - NULL, - NULL, - NULL, - NULL, - NULL -}; - -static const TCHAR *movemregs[] = -{ - _T("D0"), - _T("D1"), - _T("D2"), - _T("D3"), - _T("D4"), - _T("D5"), - _T("D6"), - _T("D7"), - _T("A0"), - _T("A1"), - _T("A2"), - _T("A3"), - _T("A4"), - _T("A5"), - _T("A6"), - _T("A7"), - _T("FP0"), - _T("FP1"), - _T("FP2"), - _T("FP3"), - _T("FP4"), - _T("FP5"), - _T("FP6"), - _T("FP7"), - _T("FPIAR"), - _T("FPSR"), - _T("FPCR") -}; + TCHAR *buf; -static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode) -{ - TCHAR *p = out + _tcslen (out); - if (*prevreg < 0) { - *prevreg = reg; - *lastreg = reg; + buf = xcalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt); + if (!buf) return; - } - if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) { - _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]); - p = p + _tcslen (p); - if (*lastreg != *prevreg) { - if ((*lastreg) + 2 == reg) { - _stprintf(p, _T("/%s"), movemregs[*prevreg]); - } else if ((*lastreg) != (*prevreg)) { - _stprintf(p, _T("-%s"), movemregs[*prevreg]); - } - } - *lastreg = reg; - *first = 0; - } - *prevreg = reg; + m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, NULL, NULL, lastpc, 0); + console_out_f (_T("%s"), buf); + xfree (buf); } -static bool movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode, bool dst) +void m68k_dumpstate(uaecptr *nextpc, uaecptr prevpc) { - unsigned int dmask, amask; - int prevreg = -1, lastreg = -1, first = 1; + int i, j; + uaecptr pc = M68K_GETPC; - if (mode == Apdi && !fpmode) { - uae_u8 dmask2; - uae_u8 amask2; - - amask2 = mask & 0xff; - dmask2 = (mask >> 8) & 0xff; - dmask = 0; - amask = 0; - for (int i = 0; i < 8; i++) { - if (dmask2 & (1 << i)) - dmask |= 1 << (7 - i); - if (amask2 & (1 << i)) - amask |= 1 << (7 - i); - } - } else { - dmask = mask & 0xff; - amask = (mask >> 8) & 0xff; - if (fpmode == 1 && mode != Apdi) { - uae_u8 dmask2 = dmask; - dmask = 0; - for (int i = 0; i < 8; i++) { - if (dmask2 & (1 << i)) - dmask |= 1 << (7 - i); - } - } - } - bool dataout = dmask != 0 || amask != 0; - if (dst && dataout) - _tcscat(out, _T(",")); - if (fpmode) { - while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; } - } else { - while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; } - while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; } - } - addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode); - return dataout; -} - -static void disasm_size (TCHAR *instrname, struct instr *dp) -{ - if (dp->unsized) { - _tcscat(instrname, _T(" ")); - return; - } - switch (dp->size) - { - case sz_byte: - _tcscat (instrname, _T(".B ")); - break; - case sz_word: - _tcscat (instrname, _T(".W ")); - break; - case sz_long: - _tcscat (instrname, _T(".L ")); - break; - default: - _tcscat (instrname, _T(" ")); - break; - } -} - -static void asm_add_extensions(uae_u16 *data, int *dcntp, int mode, uae_u32 v, int extcnt, uae_u16 *ext, uaecptr pc, int size) -{ - int dcnt = *dcntp; - if (mode < 0) - return; - if (mode == Ad16) { - data[dcnt++] = v; - } - if (mode == PC16) { - data[dcnt++] = v - (pc + 2); - } - if (mode == Ad8r || mode == PC8r) { - for (int i = 0; i < extcnt; i++) { - data[dcnt++] = ext[i]; - } - } - if (mode == absw) { - data[dcnt++] = (uae_u16)v; - } - if (mode == absl) { - data[dcnt++] = (uae_u16)(v >> 16); - data[dcnt++] = (uae_u16)v; - } - if ((mode == imm && size == 0) || mode == imm0) { - data[dcnt++] = (uae_u8)v; - } - if ((mode == imm && size == 1) || mode == imm1) { - data[dcnt++] = (uae_u16)v; - } - if ((mode == imm && size == 2) || mode == imm2) { - data[dcnt++] = (uae_u16)(v >> 16); - data[dcnt++] = (uae_u16)v; - } - *dcntp = dcnt; -} - -static int asm_isdreg(const TCHAR *s) -{ - if (s[0] == 'D' && s[1] >= '0' && s[1] <= '7') - return s[1] - '0'; - return -1; -} -static int asm_isareg(const TCHAR *s) -{ - if (s[0] == 'A' && s[1] >= '0' && s[1] <= '7') - return s[1] - '0'; - if (s[0] == 'S' && s[1] == 'P') - return 7; - return -1; -} -static int asm_ispc(const TCHAR *s) -{ - if (s[0] == 'P' && s[1] == 'C') - return 1; - return 0; -} - -static uae_u32 asmgetval(const TCHAR *s) -{ - TCHAR *endptr; - if (s[0] == '-') - return _tcstol(s, &endptr, 16); - return _tcstoul(s, &endptr, 16); -} - -static int asm_parse_mode020(TCHAR *s, uae_u8 *reg, uae_u32 *v, int *extcnt, uae_u16 *ext) -{ - return -1; -} - -static int asm_parse_mode(TCHAR *s, uae_u8 *reg, uae_u32 *v, int *extcnt, uae_u16 *ext) -{ - TCHAR *ss = s; - *reg = -1; - *v = 0; - *ext = 0; - *extcnt = 0; - if (s[0] == 0) - return -1; - // Dn - if (asm_isdreg(s) >= 0 && s[2] == 0) { - *reg = asm_isdreg(s); - return Dreg; - } - // An - if (asm_isareg(s) >= 0 && s[2] == 0) { - *reg = asm_isareg(s); - return Areg; - } - // (An) and (An)+ - if (s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')') { - *reg = asm_isareg(s + 1); - if (s[4] == '+' && s[5] == 0) - return Aipi; - if (s[4] == 0) - return Aind; - return -1; - } - // -(An) - if (s[0] == '-' && s[1] == '(' && asm_isareg(s + 2) >= 0 && s[4] == ')' && s[5] == 0) { - *reg = asm_isareg(s + 2); - return Apdi; - } - // Immediate - if (s[0] == '#') { - if (s[1] == '!') { - *v = _tstol(s + 2); - } else { - *v = asmgetval(s + 1); - } - return imm; - } - // Value - if (s[0] == '!') { - *v = _tstol(s + 1); - } else { - *v = asmgetval(s); - } - int dots = 0; - int fullext = 0; - for (int i = 0; i < _tcslen(s); i++) { - if (s[i] == ',') { - dots++; - } else if (s[i] == '[') { - if (fullext > 0) - fullext = -1; - else - fullext = 1; - } else if (s[i] == ']') { - if (fullext != 1) - fullext = -1; - else - fullext = 2; - fullext++; - } - } - if (fullext < 0 || fullext == 1) - return -1; - if (fullext == 2) { - return asm_parse_mode020(s, reg, v, extcnt, ext); - } - while (*s != 0) { - // d16(An) - if (dots == 0 && s[0] == '(' && asm_isareg(s + 1) >= 0 && s[3] == ')' && s[4] == 0) { - *reg = asm_isareg(s + 1); - return Ad16; - } - // d16(PC) - if (dots == 0 && s[0] == '(' && asm_ispc(s + 1) && s[3] == ')' && s[4] == 0) { - *reg = 2; - return PC16; - } - // (d16,An) / (d16,PC) - if (dots == 1 && s[0] == '(' && !asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) { - TCHAR *startptr, *endptr; - if (s[1] == '!') { - startptr = s + 2; - *v = _tcstol(startptr, &endptr, 10); - } else { - startptr = s + 1; - *v = _tcstol(startptr, &endptr, 16); - } - if (endptr == startptr || endptr[0] != ',') - return -1; - if (asm_ispc(endptr + 1) && endptr[3] == ')') { - *reg = 2; - return PC16; - } - if (asm_isareg(endptr + 1) >= 0 && endptr[3] == ')') { - *reg = asm_isareg(endptr + 1); - return Ad16; - } - return -1; - } - // Ad8r PC8r - if (s[0] == '(') { - TCHAR *s2 = s; - if (!asm_ispc(s + 1) && asm_isareg(s + 1) < 0 && asm_isdreg(s + 1) < 0) { - if (dots != 2) - return -1; - TCHAR *startptr, *endptr; - if (s[1] == '!') { - startptr = s + 2; - *v = _tcstol(startptr, &endptr, 10); - } else { - startptr = s + 1; - *v = _tcstol(startptr, &endptr, 16); - } - if (endptr == startptr || endptr[0] != ',') - return -1; - s2 = endptr + 1; - } else if (((asm_isareg(s + 1) >= 0 || asm_ispc(s + 1)) && s[3] == ',') || (asm_isdreg(s + 4) >= 0 || asm_isareg(s + 4) >= 0)) { - if (dots != 1) - return -1; - s2 = s + 1; - } else { - return -1; - } - uae_u8 reg2; - bool ispc = asm_ispc(s2); - if (ispc) { - *reg = 3; - } else { - *reg = asm_isareg(s2); - } - *extcnt = 1; - s2 += 2; - if (*s2 != ',') - return -1; - s2++; - if (asm_isdreg(s2) >= 0) { - reg2 = asm_isdreg(s2); - } else { - reg2 = asm_isareg(s2); - *ext |= 1 << 15; - } - s2 += 2; - *ext |= reg2 << 12; - *ext |= (*v) & 0xff; - if (s2[0] == '.' && s2[1] == 'W') { - s2 += 2; - } else if (s2[0] == '.' && s2[1] == 'L') { - *ext |= 1 << 11; - s2 += 2; - } - if (s2[0] == '*') { - TCHAR scale = s2[1]; - if (scale == '2') - *ext |= 1 << 9; - else if (scale == '4') - *ext |= 2 << 9; - else if (scale == '8') - *ext |= 3 << 9; - else - return -1; - s2 += 2; - } - if (s2[0] == ')' && s2[1] == 0) { - return ispc ? PC8r : Ad8r; - } - return -1; - } - s++; - } - // abs.w - if (s - ss > 2 && s[-2] == '.' && s[-1] == 'W') { - *reg = 0; - return absw; - } - // abs.l - *reg = 1; - return absl; -} - -static TCHAR *asm_parse_parm(TCHAR *parm, TCHAR *out) -{ - TCHAR *p = parm; - bool quote = false; - - for (;;) { - if (*p == '(') { - quote = true; - } - if (*p == ')') { - if (!quote) - return NULL; - quote = false; - } - if ((*p == ',' || *p == 0) && !quote) { - TCHAR c = *p; - p[0] = 0; - _tcscpy(out, parm); - my_trim(out); - if (c) - p++; - return p; - } - p++; - } -} - -static bool m68k_asm_parse_movec(TCHAR *s, TCHAR *d) -{ - for (int i = 0; m2cregs[i].regname; i++) { - if (!_tcscmp(s, m2cregs[i].regname)) { - uae_u16 v = m2cregs[i].regno; - if (asm_isareg(d) >= 0) - v |= 0x8000 | (asm_isareg(d) << 12); - else if (asm_isdreg(d) >= 0) - v |= (asm_isdreg(d) << 12); - else - return false; - _stprintf(s, _T("#%X"), v); - return true; - } - } - return false; -} - -static bool m68k_asm_parse_movem(TCHAR *s, int dir) -{ - TCHAR *d = s; - uae_u16 regmask = 0; - uae_u16 mask = dir ? 0x8000 : 0x0001; - bool ret = false; - while(*s) { - int dreg = asm_isdreg(s); - int areg = asm_isareg(s); - if (dreg < 0 && areg < 0) - break; - int reg = dreg >= 0 ? dreg : areg + 8; - regmask |= dir ? (mask >> reg) : (mask << reg); - s += 2; - if (*s == 0) { - ret = true; - break; - } else if (*s == '/') { - s++; - continue; - } else if (*s == '-') { - s++; - int dreg2 = asm_isdreg(s); - int areg2 = asm_isareg(s); - if (dreg2 < 0 && areg2 < 0) - break; - int reg2 = dreg2 >= 0 ? dreg2 : areg2 + 8; - if (reg2 < reg) - break; - while (reg2 >= reg) { - regmask |= dir ? (mask >> reg) : (mask << reg); - reg++; - } - s += 2; - if (*s == 0) { - ret = true; - break; - } - } else { - break; - } - } - if (ret) - _stprintf(d, _T("#%X"), regmask); - return ret; -} - -int m68k_asm(TCHAR *sline, uae_u16 *out, uaecptr pc) -{ - TCHAR *p; - const TCHAR *cp1; - TCHAR ins[256], parms[256]; - TCHAR line[256]; - TCHAR srcea[256], dstea[256]; - uae_u16 data[16], sexts[8], dexts[8]; - int sextcnt, dextcnt; - int dcnt = 0; - int cc = -1; - int quick = 0; - bool immrelpc = false; - - if (_tcslen(sline) > 100) - return -1; - - srcea[0] = dstea[0] = 0; - parms[0] = 0; - - // strip all white space except first space - p = line; - bool firstsp = true; - for (int i = 0; sline[i]; i++) { - TCHAR c = sline[i]; - if (c == 32 && firstsp) { - firstsp = false; - *p++ = 32; - } - if (c <= 32) - continue; - *p++ = c; - } - *p = 0; - - to_upper(line, _tcslen(line)); - - p = line; - while (*p && *p != ' ') - p++; - if (*p == ' ') { - *p = 0; - _tcscpy(parms, p + 1); - my_trim(parms); - } - _tcscpy(ins, line); - - if (_tcslen(ins) == 0) - return 0; - - int size = 1; - int inssize = -1; - cp1 = _tcschr(line, '.'); - if (cp1) { - size = cp1[1]; - if (size == 'W') - size = 1; - else if (size == 'L') - size = 2; - else if (size == 'B') - size = 0; - else - return 0; - inssize = size; - line[cp1 - line] = 0; - _tcscpy(ins, line); - } - - TCHAR *parmp = parms; - parmp = asm_parse_parm(parmp, srcea); - if (!parmp) - return 0; - if (srcea[0]) { - parmp = asm_parse_parm(parmp, dstea); - if (!parmp) - return 0; - } - - int smode = -1; - int dmode = -1; - uae_u8 sreg = -1; - uae_u8 dreg = -1; - uae_u32 sval = 0; - uae_u32 dval = 0; - int ssize = -1; - int dsize = -1; - - dmode = asm_parse_mode(dstea, &dreg, &dval, &dextcnt, dexts); - - - // Common alias - if (!_tcscmp(ins, _T("BRA"))) { - _tcscpy(ins, _T("BT")); - } else if (!_tcscmp(ins, _T("BSR"))) { - immrelpc = true; - } else if (!_tcscmp(ins, _T("MOVEM"))) { - if (dmode >= Aind && _tcschr(dstea, '-') == NULL && _tcschr(dstea, '/') == NULL) { - _tcscpy(ins, _T("MVMLE")); - if (!m68k_asm_parse_movem(srcea, dmode == Apdi)) - return -1; - } else { - TCHAR tmp[256]; - _tcscpy(ins, _T("MVMEL")); - _tcscpy(tmp, srcea); - _tcscpy(srcea, dstea); - _tcscpy(dstea, tmp); - if (!m68k_asm_parse_movem(srcea, 0)) - return -1; - dmode = asm_parse_mode(dstea, &dreg, &dval, &dextcnt, dexts); - } - } else if (!_tcscmp(ins, _T("MOVEC"))) { - if (dmode == Dreg || dmode == Areg) { - _tcscpy(ins, _T("MOVEC2")); - if (!m68k_asm_parse_movec(srcea, dstea)) - return -1; - } else { - TCHAR tmp[256]; - _tcscpy(ins, _T("MOVE2C")); - _tcscpy(tmp, srcea); - _tcscpy(srcea, dstea); - dstea[0] = 0; - if (!m68k_asm_parse_movec(srcea, tmp)) - return -1; - } - dmode = -1; - } - - if (dmode == Areg) { - int l = _tcslen(ins); - if (l <= 2) - return -1; - TCHAR last = ins[l- 1]; - if (last == 'Q') { - last = ins[l - 2]; - if (last != 'A') { - ins[l - 1] = 'A'; - ins[l] = 'Q'; - ins[l + 1] = 0; - } - } else if (last != 'A') { - _tcscat(ins, _T("A")); - } - } - - bool fp = ins[0] == 'F'; - - if (ins[_tcslen(ins) - 1] == 'Q' && _tcslen(ins) > 3 && !fp) { - quick = 1; - ins[_tcslen(ins) - 1] = 0; - } - - struct mnemolookup *lookup; - for (lookup = lookuptab; lookup->name; lookup++) { - if (!_tcscmp(ins, lookup->name)) - break; - } - if (!lookup->name) { - // Check cc variants - for (lookup = lookuptab; lookup->name; lookup++) { - const TCHAR *ccp = _tcsstr(lookup->name, _T("cc")); - if (ccp) { - TCHAR tmp[256]; - for (int i = 0; i < (fp ? 32 : 16); i++) { - const TCHAR *ccname = fp ? fpccnames[i] : ccnames[i]; - _tcscpy(tmp, lookup->name); - _tcscpy(tmp + (ccp - lookup->name), ccname); - if (tmp[_tcslen(tmp) - 1] == ' ') - tmp[_tcslen(tmp) - 1] = 0; - if (!_tcscmp(tmp, ins)) { - _tcscpy(ins, lookup->name); - cc = i; - if (lookup->mnemo == i_DBcc || lookup->mnemo == i_Bcc) { - // Bcc.B uses same encoding mode as MOVEQ - immrelpc = true; - } - if (size == 0) { - quick = 2; - } - break; - } - } - } - if (cc >= 0) - break; - } - } - - if (!lookup->name) - return 0; - - int mnemo = lookup->mnemo; - - int found = 0; - int sizemask = 0; - int tsize = size; - int unsized = 0; - - for (int round = 0; round < 9; round++) { - - if (!found && round == 8) - return 0; - - if (round == 3) { - // Q is always LONG sized - if (quick == 1) { - tsize = 2; - } - bool isimm = srcea[0] == '#'; - if (immrelpc && !isimm) { - TCHAR tmp[256]; - _tcscpy(tmp, srcea); - srcea[0] = '#'; - _tcscpy(srcea + 1, tmp); - } - smode = asm_parse_mode(srcea, &sreg, &sval, &sextcnt, sexts); - if (immrelpc && !isimm) { - sval = sval - (pc + 2); - } - if (quick) { - smode = immi; - sreg = sval & 0xff; - } - } - - if (round == 1) { - if (!quick && (sizemask == 1 || sizemask == 2 || sizemask == 4)) { - tsize = 0; - if (sizemask == 2) - tsize = 1; - else if (sizemask == 4) - tsize = 2; - } else { - continue; - } - } - if (round == 2 && !found) { - unsized = 1; - } - - if (round == 4 && smode == imm) { - smode = imm0; - } else if (round == 5 && smode == imm0) { - smode = imm1; - } else if (round == 6 && smode == imm1) { - smode = imm2; - } else if (round == 7 && smode == imm2) { - smode = immi; - sreg = sval & 0xff; - } else if (round == 4) { - round += 5 - 1; - } - - for (int opcode = 0; opcode < 65536; opcode++) { - struct instr *table = &table68k[opcode]; - if (table->mnemo != mnemo) - continue; - if (cc >= 0 && table->cc != cc) - continue; - -#if 0 - if (round == 0) { - console_out_f(_T("%s OP=%04x S=%d SR=%d SM=%d SU=%d SP=%d DR=%d DM=%d DU=%d DP=%d SDU=%d\n"), lookup->name, opcode, table->size, - table->sreg, table->smode, table->suse, table->spos, - table->dreg, table->dmode, table->duse, table->dpos, - table->sduse); - } -#endif - - if (table->duse && !(table->dmode == dmode || (dmode >= imm && dmode <= imm2 && table->dmode >= imm && table->dmode <= imm2))) - continue; - if (round == 0) { - sizemask |= 1 << table->size; - } - if (unsized > 0 && !table->unsized) { - continue; - } - - found++; - - if (round >= 3) { - - if ( - ((table->size == tsize || table->unsized)) && - ((!table->suse && smode < 0) || (table->suse && table->smode == smode)) && - ((!table->duse && dmode < 0) || (table->duse && (table->dmode == dmode || (dmode == imm && (table->dmode >= imm && table->dmode <= imm2))))) && - ((table->sreg == sreg || (table->smode >= absw && table->smode != immi))) && - ((table->dreg == dreg || table->dmode >= absw)) - ) - { - if (inssize >= 0 && tsize != inssize) - continue; - - - data[dcnt++] = opcode; - asm_add_extensions(data, &dcnt, smode, sval, sextcnt, sexts, pc, tsize); - if (smode >= 0) - asm_add_extensions(data, &dcnt, dmode, dval, dextcnt, dexts, pc, tsize); - for (int i = 0; i < dcnt; i++) { - out[i] = data[i]; - } - return dcnt; - } - - } - } - } - - return 0; -} - -static void resolve_if_jmp(TCHAR *s, uae_u32 addr) -{ - uae_u16 opcode = get_word_debug(addr); - if (opcode == 0x4ef9) { // JMP x.l - TCHAR *p = s + _tcslen(s); - uae_u32 addr2 = get_long_debug(addr + 2); - _stprintf(p, _T(" == $%08x "), addr2); - showea_val(p + _tcslen(p), opcode, addr2, 4); - TCHAR txt[256]; - bool ext; - if (debugmem_get_segment(addr2, NULL, &ext, NULL, txt)) { - if (ext) { - _tcscat(p, _T(" ")); - _tcscat(p, txt); - } - } - } -} - -static bool mmu_op30_helper_get_fc(uae_u16 extra, TCHAR *out) -{ - switch (extra & 0x0018) { - case 0x0010: - _stprintf(out, _T("#%d"), extra & 7); - return true; - case 0x0008: - _stprintf(out, _T("D%d"), extra & 7); - return true; - case 0x0000: - if (extra & 1) { - _tcscpy(out, _T("DFC")); - } else { - _tcscpy(out, _T("SFC")); - } - return true; - default: - return false; - } -} - -static uaecptr disasm_mmu030(uaecptr pc, uae_u16 opcode, uae_u16 extra, struct instr *dp, TCHAR *instrname, uae_u32 *seaddr2, int safemode) -{ - int type = extra >> 13; - - _tcscpy(instrname, _T("F-LINE (MMU 68030)")); - pc += 2; - - switch (type) - { - case 0: - case 2: - case 3: - { - // PMOVE - int preg = (extra >> 10) & 31; - int rw = (extra >> 9) & 1; - int fd = (extra >> 8) & 1; - int unused = (extra & 0xff); - const TCHAR *r = NULL; - - if (mmu_op30_invea(opcode)) - break; - if (unused) - break; - if (rw && fd) - break; - switch (preg) - { - case 0x10: - r = _T("TC"); - break; - case 0x12: - r = _T("SRP"); - break; - case 0x13: - r = _T("CRP"); - break; - case 0x18: - r = _T("MMUSR"); - break; - case 0x02: - r = _T("TT0"); - break; - case 0x03: - r = _T("TT1"); - break; - } - if (!r) - break; - - _tcscpy(instrname, _T("PMOVE")); - if (fd) - _tcscat(instrname, _T("FD")); - _tcscat(instrname, _T(" ")); - - if (!rw) { - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); - _tcscat(instrname, _T(",")); - } - _tcscat(instrname, r); - if (rw) { - _tcscat(instrname, _T(",")); - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); - } - break; - } - case 1: - { - // PLOAD/PFLUSH - uae_u16 mode = (extra >> 8) & 31; - int unused = (extra & (0x100 | 0x80 | 0x40 | 0x20)); - uae_u16 fc_mask = (extra & 0x00E0) >> 5; - uae_u16 fc_bits = extra & 0x7f; - TCHAR fc[10]; - - if (unused) - break; - - switch (mode) { - case 0x00: // PLOAD W - case 0x02: // PLOAD R - if (mmu_op30_invea(opcode)) - break; - _stprintf(instrname, _T("PLOAD%c %s,"), mode == 0 ? 'W' : 'R', fc); - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); - break; - case 0x04: // PFLUSHA - if (fc_bits) - break; - _tcscpy(instrname, _T("PFLUSHA")); - break; - case 0x10: // FC - if (!mmu_op30_helper_get_fc(extra, fc)) - break; - _stprintf(instrname, _T("PFLUSH %s,%d"), fc, fc_mask); - break; - case 0x18: // FC + EA - if (mmu_op30_invea(opcode)) - break; - if (!mmu_op30_helper_get_fc(extra, fc)) - break; - _stprintf(instrname, _T("PFLUSH %s,%d"), fc, fc_mask); - _tcscat(instrname, _T(",")); - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); - break; - } - break; - } - case 4: - { - // PTEST - int level = (extra & 0x1C00) >> 10; - int rw = (extra >> 9) & 1; - int a = (extra >> 8) & 1; - int areg = (extra & 0xE0) >> 5; - TCHAR fc[10]; - - if (mmu_op30_invea(opcode)) - break; - if (!mmu_op30_helper_get_fc(extra, fc)) - break; - if (!level && a) - break; - _stprintf(instrname, _T("PTEST%c %s,"), rw ? 'R' : 'W', fc); - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); - _stprintf(instrname + _tcslen(instrname), _T(",#%d"), level); - if (a) - _stprintf(instrname + _tcslen(instrname), _T(",A%d"), areg); - break; - } - } - return pc; -} - - -void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc, int safemode) -{ - uae_u32 seaddr2; - uae_u32 deaddr2; - - if (!table68k) - return; - while (cnt-- > 0) { - TCHAR instrname[256], *ccpt; - TCHAR segout[256], segname[256]; - int i; - uae_u32 opcode; - uae_u16 extra; - struct mnemolookup *lookup; - struct instr *dp; - uaecptr oldpc; - uaecptr m68kpc_illg = 0; - bool illegal = false; - int segid, lastsegid; - TCHAR *symbolpos; - - seaddr2 = deaddr2 = 0; - oldpc = pc; - opcode = get_word_debug (pc); - extra = get_word_debug (pc + 2); - if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) { - m68kpc_illg = pc + 2; - illegal = TRUE; - } - - dp = table68k + opcode; - if (dp->mnemo == i_ILLG) { - illegal = FALSE; - opcode = 0x4AFC; - dp = table68k + opcode; - } - for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) - ; - - lastsegid = -1; - bool exact = false; - if (lastpc != 0xffffffff) { - lastsegid = debugmem_get_segment(lastpc, NULL, NULL, NULL, NULL); - } - segid = debugmem_get_segment(pc, &exact, NULL, segout, segname); - if (segid && (lastsegid != -1 || exact) && (segid != lastsegid || pc == lastpc || exact)) { - buf = buf_out(buf, &bufsize, _T("%s\n"), segname); - } - symbolpos = buf; - - buf = buf_out (buf, &bufsize, _T("%08X "), pc); - - if (segid) { - buf = buf_out(buf, &bufsize, _T("%s "), segout); - } - - pc += 2; - - if (lookup->friendlyname) - _tcscpy (instrname, lookup->friendlyname); - else - _tcscpy (instrname, lookup->name); - ccpt = _tcsstr (instrname, _T("cc")); - if (ccpt != 0) { - if ((opcode & 0xf000) == 0xf000) - _tcscpy (ccpt, fpccnames[extra & 0x1f]); - else - _tcsncpy (ccpt, ccnames[dp->cc], 2); - } - disasm_size (instrname, dp); - - if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) { - uae_u16 imm = extra; - uae_u16 creg = imm & 0x0fff; - uae_u16 r = imm >> 12; - TCHAR regs[16]; - const TCHAR *cname = _T("?"); - int j; - for (j = 0; m2cregs[j].regname; j++) { - if (m2cregs[j].regno == creg) - break; - } - _stprintf(regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r); - if (m2cregs[j].regname) - cname = m2cregs[j].regname; - if (lookup->mnemo == i_MOVE2C) { - _tcscat(instrname, regs); - _tcscat(instrname, _T(",")); - _tcscat(instrname, cname); - } else { - _tcscat(instrname, cname); - _tcscat(instrname, _T(",")); - _tcscat(instrname, regs); - } - pc += 2; - } else if (lookup->mnemo == i_CHK2) { - TCHAR *p; - if (!(extra & 0x0800)) { - instrname[1] = 'M'; - instrname[2] = 'P'; - } - pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); - extra = get_word_debug(pc); - pc += 2; - p = instrname + _tcslen(instrname); - _stprintf(p, (extra & 0x8000) ? _T(",A%d") : _T(",D%d"), (extra >> 12) & 7); - } else if (lookup->mnemo == i_ORSR || lookup->mnemo == i_ANDSR || lookup->mnemo == i_EORSR) { - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); - _tcscat(instrname, dp->size == sz_byte ? _T(",CCR") : _T(",SR")); - } else if (lookup->mnemo == i_MVR2USP) { - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); - _tcscat(instrname, _T(",USP")); - } else if (lookup->mnemo == i_MVUSP2R) { - _tcscat(instrname, _T("USP,")); - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); - } else if (lookup->mnemo == i_MV2SR) { - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); - _tcscat(instrname, dp->size == sz_byte ? _T(",CCR") : _T(",SR")); - } else if (lookup->mnemo == i_MVSR2) { - _tcscat(instrname, dp->size == sz_byte ? _T("CCR,") : _T("SR,")); - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); - } else if (lookup->mnemo == i_MVMEL) { - uae_u16 mask = extra; - pc += 2; - pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); - movemout (instrname, mask, dp->dmode, 0, true); - } else if (lookup->mnemo == i_MVMLE) { - uae_u16 mask = extra; - pc += 2; - if (movemout(instrname, mask, dp->dmode, 0, false)) - _tcscat(instrname, _T(",")); - pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); - } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) { - TCHAR *p; - pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); - extra = get_word_debug(pc); - pc += 2; - p = instrname + _tcslen(instrname); - if (extra & 0x0400) - _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7); - else - _stprintf(p, _T(",D%d"), (extra >> 12) & 7); - } else if (lookup->mnemo == i_MOVES) { - TCHAR *p; - pc += 2; - if (!(extra & 0x0800)) { - pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); - p = instrname + _tcslen(instrname); - _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7); - } else { - p = instrname + _tcslen(instrname); - _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7); - pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); - } - } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || - lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR || - lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS || - lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) { - TCHAR *p; - int reg = -1; - - pc += 2; - p = instrname + _tcslen(instrname); - if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS) - reg = (extra >> 12) & 7; - if (lookup->mnemo == i_BFINS) - _stprintf(p, _T("D%d,"), reg); - pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); - _tcscat(instrname, _T(" {")); - p = instrname + _tcslen(instrname); - if (extra & 0x0800) - _stprintf(p, _T("D%d"), (extra >> 6) & 7); - else - _stprintf(p, _T("%d"), (extra >> 6) & 31); - _tcscat(instrname, _T(":")); - p = instrname + _tcslen(instrname); - if (extra & 0x0020) - _stprintf(p, _T("D%d"), extra & 7); - else - _stprintf(p, _T("%d"), extra & 31); - _tcscat(instrname, _T("}")); - p = instrname + _tcslen(instrname); - if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU) - _stprintf(p, _T(",D%d"), reg); - } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || - lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) { - if ((opcode & 0xc0) == 0xc0) - _tcscat(instrname, _T("BC")); - else if (opcode & 0x80) - _tcscat(instrname, _T("IC")); - else if (opcode & 0x40) - _tcscat(instrname, _T("DC")); - else - _tcscat(instrname, _T("?")); - if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) { - TCHAR *p = instrname + _tcslen(instrname); - _stprintf(p, _T(",(A%d)"), opcode & 7); - } - } else if (lookup->mnemo == i_MOVE16) { - TCHAR *p = instrname + _tcslen(instrname); - if (opcode & 0x20) { - _stprintf(p, _T("(A%d)+,(A%d)+"), opcode & 7, (extra >> 12) & 7); - pc += 2; - } else { - uae_u32 addr = get_long_debug(pc + 2); - int ay = opcode & 7; - pc += 4; - switch ((opcode >> 3) & 3) - { - case 0: - _stprintf(p, _T("(A%d)+,$%08x"), ay, addr); - break; - case 1: - _stprintf(p, _T("$%08x,(A%d)+"), addr, ay); - break; - case 2: - _stprintf(p, _T("(A%d),$%08x"), ay, addr); - break; - case 3: - _stprintf(p, _T("$%08x,(A%d)"), addr, ay); - break; - } - } - } else if (lookup->mnemo == i_FPP) { - TCHAR *p; - int ins = extra & 0x3f; - int size = (extra >> 10) & 7; - - pc += 2; - if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7) - fpdata fp; - fpu_get_constant(&fp, extra); - _stprintf(instrname, _T("FMOVECR.X #0x%02x [%s],FP%d"), extra & 0x7f, fpp_print(&fp, 0), (extra >> 7) & 7); - } else if ((extra & 0x8000) == 0x8000) { // FMOVEM - int dr = (extra >> 13) & 1; - int mode; - int dreg = (extra >> 4) & 7; - int regmask, fpmode; - - if (extra & 0x4000) { - mode = (extra >> 11) & 3; - regmask = extra & 0xff; // FMOVEM FPx - fpmode = 1; - _tcscpy(instrname, _T("FMOVEM.X ")); - } else { - mode = 0; - regmask = (extra >> 10) & 7; // FMOVEM control - fpmode = 2; - _tcscpy(instrname, _T("FMOVEM.L ")); - if (regmask == 1 || regmask == 2 || regmask == 4) - _tcscpy(instrname, _T("FMOVE.L ")); - } - p = instrname + _tcslen(instrname); - if (dr) { - if (mode & 1) - _stprintf(instrname, _T("D%d"), dreg); - else - movemout(instrname, regmask, dp->dmode, fpmode, false); - _tcscat(instrname, _T(",")); - pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); - } else { - pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); - p = instrname + _tcslen(instrname); - if (mode & 1) - _stprintf(p, _T(",D%d"), dreg); - else - movemout(p, regmask, dp->dmode, fpmode, true); - } - } else { - if (fpuopcodes[ins]) - _tcscpy(instrname, fpuopcodes[ins]); - else - _tcscpy(instrname, _T("F?")); - - if ((extra & 0xe000) == 0x6000) { // FMOVE to memory - int kfactor = extra & 0x7f; - _tcscpy(instrname, _T("FMOVE.")); - _tcscat(instrname, fpsizes[size]); - _tcscat(instrname, _T(" ")); - p = instrname + _tcslen(instrname); - _stprintf(p, _T("FP%d,"), (extra >> 7) & 7); - pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode); - p = instrname + _tcslen(instrname); - if (size == 7) { - _stprintf(p, _T(" {D%d}"), (kfactor >> 4)); - } else if (kfactor) { - if (kfactor & 0x40) - kfactor |= ~0x3f; - _stprintf(p, _T(" {%d}"), kfactor); - } - } else { - if (extra & 0x4000) { // source is EA - _tcscat(instrname, _T(".")); - _tcscat(instrname, fpsizes[size]); - _tcscat(instrname, _T(" ")); - pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode); - } else { // source is FPx - p = instrname + _tcslen(instrname); - _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7); - } - p = instrname + _tcslen(instrname); - if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7))) - _stprintf(p, _T(",FP%d"), (extra >> 7) & 7); - if (ins >= 0x30 && ins < 0x38) { // FSINCOS - p = instrname + _tcslen(instrname); - _stprintf(p, _T(",FP%d"), extra & 7); - } - } - } - } else if (lookup->mnemo == i_MMUOP030) { - pc = disasm_mmu030(pc, opcode, extra, dp, instrname, &seaddr2, safemode); - } else if ((opcode & 0xf000) == 0xa000) { - _tcscpy(instrname, _T("A-LINE")); - } else { - if (dp->suse) { - pc = ShowEA (NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); - - // JSR x(a6) / JMP x(a6) - if (opcode == 0x4ea8 + 6 || opcode == 0x4ee8 + 6) { - TCHAR sname[256]; - if (debugger_get_library_symbol(m68k_areg(regs, 6), 0xffff0000 | extra, sname)) { - TCHAR *p = instrname + _tcslen(instrname); - _stprintf(p, _T(" %s"), sname); - resolve_if_jmp(instrname, m68k_areg(regs, 6) + (uae_s16)extra); - } - } - // show target address if JSR x(pc) + JMP xxxx combination - if (opcode == 0x4eba && seaddr2 && instrname[0]) { // JSR x(pc) - resolve_if_jmp(instrname, seaddr2); - } - } - if (dp->suse && dp->duse) - _tcscat (instrname, _T(",")); - if (dp->duse) { - pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode); - } - } - - for (i = 0; i < (pc - oldpc) / 2 && i < 5; i++) { - buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2)); - } - while (i++ < 5) - buf = buf_out (buf, &bufsize, _T(" ")); - - if (illegal) - buf = buf_out (buf, &bufsize, _T("[ ")); - buf = buf_out (buf, &bufsize, instrname); - if (illegal) - buf = buf_out (buf, &bufsize, _T(" ]")); - - if (ccpt != 0) { - uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2; - if (deaddr) - *deaddr = pc; - if ((opcode & 0xf000) == 0xf000) { - if (fpp_cond(dp->cc)) { - buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2); - } else { - buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2); - } - } else { - if (dp->mnemo == i_Bcc || dp->mnemo == i_DBcc) { - if (cctrue(dp->cc)) { - buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2); - } else { - buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2); - } - } else { - if (cctrue(dp->cc)) { - buf = buf_out(buf, &bufsize, _T(" (T)")); - } else { - buf = buf_out(buf, &bufsize, _T(" (F)")); - } - } - } - } else if ((opcode & 0xff00) == 0x6100) { /* BSR */ - if (deaddr) - *deaddr = pc; - buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2); - } - buf = buf_out (buf, &bufsize, _T("\n")); - - for (uaecptr segpc = oldpc; segpc < pc; segpc++) { - TCHAR segout[256]; - if (debugmem_get_symbol(segpc, segout, sizeof(segout) / sizeof(TCHAR))) { - _tcscat(segout, _T(":\n")); - if (bufsize > _tcslen(segout)) { - memmove(symbolpos + _tcslen(segout), symbolpos, (_tcslen(symbolpos) + 1) * sizeof(TCHAR)); - memcpy(symbolpos, segout, _tcslen(segout) * sizeof(TCHAR)); - bufsize -= _tcslen(segout); - buf += _tcslen(segout); - symbolpos += _tcslen(segout); - } - } - } - - int srcline = -1; - for (uaecptr segpc = oldpc; segpc < pc; segpc++) { - TCHAR sourceout[256]; - int line = debugmem_get_sourceline(segpc, sourceout, sizeof(sourceout) / sizeof(TCHAR)); - if (line < 0) - break; - if (srcline != line) { - if (srcline < 0) - buf = buf_out(buf, &bufsize, _T("\n")); - buf = buf_out(buf, &bufsize, sourceout); - srcline = line; - } - } - if (srcline >= 0) { - buf = buf_out(buf, &bufsize, _T("\n")); - } - - if (illegal) - pc = m68kpc_illg; - } - if (nextpc) - *nextpc = pc; - if (seaddr) - *seaddr = seaddr2; - if (deaddr) - *deaddr = deaddr2; -} - -void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, uaecptr lastpc) -{ - TCHAR *buf; - - buf = xcalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt); - if (!buf) - return; - m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, seaddr, deaddr, lastpc, 1); - xfree (buf); -} -void m68k_disasm (uaecptr addr, uaecptr *nextpc, uaecptr lastpc, int cnt) -{ - TCHAR *buf; - - buf = xcalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt); - if (!buf) - return; - m68k_disasm_2 (buf, MAX_LINEWIDTH * cnt, addr, nextpc, cnt, NULL, NULL, lastpc, 0); - console_out_f (_T("%s"), buf); - xfree (buf); -} - -/************************************************************* -Disasm the m68kcode at the given address into instrname -and instrcode -*************************************************************/ -void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc, uaecptr lastpc) -{ - TCHAR *ccpt; - uae_u32 opcode; - struct mnemolookup *lookup; - struct instr *dp; - uaecptr pc, oldpc; - - pc = oldpc = addr; - opcode = get_word_debug (pc); - if (cpufunctbl[opcode] == op_illg_1) { - opcode = 0x4AFC; - } - dp = table68k + opcode; - for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++); - - pc += 2; - - _tcscpy (instrname, lookup->name); - ccpt = _tcsstr (instrname, _T("cc")); - if (ccpt != 0) { - _tcsncpy (ccpt, ccnames[dp->cc], 2); - } - switch (dp->size){ - case sz_byte: _tcscat (instrname, _T(".B ")); break; - case sz_word: _tcscat (instrname, _T(".W ")); break; - case sz_long: _tcscat (instrname, _T(".L ")); break; - default: _tcscat (instrname, _T(" ")); break; - } - - if (dp->suse) { - pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0); - } - if (dp->suse && dp->duse) - _tcscat (instrname, _T(",")); - if (dp->duse) { - pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0); - } - if (instrcode) - { - int i; - for (i = 0; i < (pc - oldpc) / 2; i++) - { - _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2)); - instrcode += _tcslen (instrcode); - } - } - if (nextpc) - *nextpc = pc; -} - -struct cpum2c m2cregs[] = { - { 0, _T("SFC") }, - { 1, _T("DFC") }, - { 2, _T("CACR") }, - { 3, _T("TC") }, - { 4, _T("ITT0") }, - { 5, _T("ITT1") }, - { 6, _T("DTT0") }, - { 7, _T("DTT1") }, - { 8, _T("BUSC") }, - { 0x800, _T("USP") }, - { 0x801, _T("VBR") }, - { 0x802, _T("CAAR") }, - { 0x803, _T("MSP") }, - { 0x804, _T("ISP") }, - { 0x805, _T("MMUS") }, - { 0x806, _T("URP") }, - { 0x807, _T("SRP") }, - { 0x808, _T("PCR") }, - { -1, NULL } -}; - -void m68k_dumpstate(uaecptr *nextpc, uaecptr prevpc) -{ - int i, j; - uaecptr pc = M68K_GETPC; - - for (i = 0; i < 8; i++){ - console_out_f (_T(" D%d %08X "), i, m68k_dreg (regs, i)); - if ((i & 3) == 3) console_out_f (_T("\n")); + for (i = 0; i < 8; i++){ + console_out_f (_T(" D%d %08X "), i, m68k_dreg (regs, i)); + if ((i & 3) == 3) console_out_f (_T("\n")); } for (i = 0; i < 8; i++){ console_out_f (_T(" A%d %08X "), i, m68k_areg (regs, i)); @@ -9320,10 +7170,7 @@ void cpureset (void) uae_u16 ins; addrbank *ab; - if (currprefs.cpu_model == 68060 && currprefs.cpuboard_type == 0 && rtarea_base != 0xf00000) { - // disable FPU at reset if no accelerator board and no $f0 ROM. - regs.pcr |= 2; - } + maybe_disable_fpu(); m68k_reset_delay = currprefs.reset_delay; set_special(SPCFLAG_CHECK); send_internalevent(INTERNALEVENT_CPURESET); diff --git a/newcpu_common.cpp b/newcpu_common.cpp index 47ae3a55..c25e307a 100644 --- a/newcpu_common.cpp +++ b/newcpu_common.cpp @@ -12,6 +12,11 @@ #include "cpummu030.h" #include "cpu_prefetch.h" +int get_cpu_model(void) +{ + return currprefs.cpu_model; +} + void val_move2c2 (int regno, uae_u32 val) { switch (regno) { @@ -436,6 +441,7 @@ uae_u32 REGPARAM2 x_get_disp_ea_020 (uae_u32 base, int idx) regd = (uae_s32)(uae_s16)regd; regd <<= (dp >> 9) & 3; if (dp & 0x100) { + uae_s32 outer = 0; if (dp & 0x80) base = 0; @@ -476,11 +482,15 @@ uae_u32 REGPARAM2 x_get_disp_ea_020 (uae_u32 base, int idx) } else { v = base + (uae_s32)((uae_s8)dp) + regd; } +#ifndef CPU_TESTER if (cycles && currprefs.cpu_cycle_exact) x_do_cycles (cycles * cpucycleunit); +#endif return v; } +#ifndef CPU_TESTER + uae_u32 REGPARAM2 x_get_disp_ea_ce030 (uae_u32 base, int idx) { uae_u16 dp = next_iword_030ce (); @@ -612,6 +622,8 @@ uae_u32 REGPARAM2 x_get_disp_ea_040(uae_u32 base, int idx) } } +#endif + /* * Compute exact number of CPU cycles taken * by DIVU and DIVS on a 68000 processor. diff --git a/od-win32/cputester/cputester.vcxproj b/od-win32/cputester/cputester.vcxproj new file mode 100644 index 00000000..181a18ab --- /dev/null +++ b/od-win32/cputester/cputester.vcxproj @@ -0,0 +1,242 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Test + Win32 + + + Test + x64 + + + + 16.0 + {EDD28611-EAD9-4EB5-A873-18160AC44434} + cputester + 10.0 + + + + Application + true + v142 + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + $(IncludePath) + + + $(IncludePath) + + + $(IncludePath) + + + $(IncludePath) + + + $(IncludePath) + + + $(IncludePath) + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include;..\..;..\ + 4996 + _MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER + FastCall + CompileAsCpp + + + Console + true + true + + + + + Level3 + Disabled + true + true + ..\..\include;..\..;..\ + 4996 + _MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER + FastCall + CompileAsCpp + + + Console + + + + + Level3 + Disabled + true + true + ..\..\include;..\..;..\ + 4996 + _MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER + FastCall + CompileAsCpp + + + Console + + + + + Level3 + Disabled + true + true + ..\..\include;..\..;..\ + 4996 + _MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER + FastCall + CompileAsCpp + + + Console + + + + + Level3 + Disabled + true + true + ..\..\include;..\..;..\ + 4996 + _MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER + FastCall + CompileAsCpp + + + Console + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\include;..\..;..\ + 4996 + _MBCS;%(PreprocessorDefinitions);CPUEMU_90;CPUEMU_91;CPUEMU_92;CPU_TESTER + FastCall + CompileAsCpp + + + Console + true + true + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/od-win32/cputester/cputester.vcxproj.filters b/od-win32/cputester/cputester.vcxproj.filters new file mode 100644 index 00000000..0acda364 --- /dev/null +++ b/od-win32/cputester/cputester.vcxproj.filters @@ -0,0 +1,69 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {0ac04ffb-7253-4995-b1eb-8c49c2c61565} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\softfloat + + + Source Files\softfloat + + + Source Files\softfloat + + + \ No newline at end of file diff --git a/od-win32/cputester_m68k/cputester_m68k.vcxproj b/od-win32/cputester_m68k/cputester_m68k.vcxproj new file mode 100644 index 00000000..b968f614 --- /dev/null +++ b/od-win32/cputester_m68k/cputester_m68k.vcxproj @@ -0,0 +1,132 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F} + cputesterm68k + 10.0 + + + + Application + true + v142 + MultiByte + + + Application + false + v142 + true + MultiByte + + + Application + true + v142 + MultiByte + + + Application + false + v142 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + MaxSpeed + true + true + true + true + + + Console + true + true + + + + + Level3 + Disabled + true + true + + + Console + + + + + Level3 + Disabled + true + true + + + Console + + + + + Level3 + MaxSpeed + true + true + true + true + + + Console + true + true + + + + + + + + + + \ No newline at end of file diff --git a/od-win32/cputester_m68k/cputester_m68k.vcxproj.filters b/od-win32/cputester_m68k/cputester_m68k.vcxproj.filters new file mode 100644 index 00000000..abf5fcf9 --- /dev/null +++ b/od-win32/cputester_m68k/cputester_m68k.vcxproj.filters @@ -0,0 +1,25 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/od-win32/winuae_msvc15/winuae_msvc.sln b/od-win32/winuae_msvc15/winuae_msvc.sln index d9daf5a4..757ebe90 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.sln +++ b/od-win32/winuae_msvc15/winuae_msvc.sln @@ -34,8 +34,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unpackers", "..\unpackers\u EndProject Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "wix", "..\wix\wix.wixproj", "{BE211CE1-3955-4674-A664-5038FC791980}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cputester", "..\cputester\cputester.vcxproj", "{EDD28611-EAD9-4EB5-A873-18160AC44434}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cputester_m68k", "..\cputester_m68k\cputester_m68k.vcxproj", "{07609D0D-FE6B-4A84-8C87-F914A4566F6F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 FullRelease|Mixed Platforms = FullRelease|Mixed Platforms FullRelease|Win32 = FullRelease|Win32 FullRelease|x64 = FullRelease|x64 @@ -50,6 +57,12 @@ Global Test|x64 = Test|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|Win32.ActiveCfg = Debug|Win32 + {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|Win32.Build.0 = Debug|Win32 + {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|x64.ActiveCfg = Debug|x64 + {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Debug|x64.Build.0 = Debug|x64 {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32 {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32 {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.FullRelease|Win32.ActiveCfg = FullRelease|Win32 @@ -74,6 +87,11 @@ Global {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Test|Win32.Build.0 = Test|Win32 {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Test|x64.ActiveCfg = Test|x64 {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA}.Test|x64.Build.0 = Test|x64 + {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Debug|Win32.ActiveCfg = Debug|Win32 + {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Debug|Win32.Build.0 = Debug|Win32 + {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Debug|x64.ActiveCfg = Debug|Win32 {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32 {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32 {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.FullRelease|Win32.ActiveCfg = FullRelease|Win32 @@ -90,6 +108,11 @@ Global {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Test|Mixed Platforms.Build.0 = Test|Win32 {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Test|Win32.ActiveCfg = Test|Win32 {DEF7ACF7-050E-4069-BB99-5B5D93F60521}.Test|x64.ActiveCfg = Test|Win32 + {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Debug|Win32.ActiveCfg = Debug|Win32 + {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Debug|Win32.Build.0 = Debug|Win32 + {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Debug|x64.ActiveCfg = Debug|Win32 {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32 {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32 {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.FullRelease|Win32.ActiveCfg = FullRelease|Win32 @@ -106,6 +129,11 @@ Global {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Test|Mixed Platforms.Build.0 = Test|Win32 {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Test|Win32.ActiveCfg = Test|Win32 {54197DFF-9CAA-4A9F-B9C2-2881EA04EACB}.Test|x64.ActiveCfg = Test|Win32 + {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Debug|Win32.ActiveCfg = Debug|Win32 + {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Debug|Win32.Build.0 = Debug|Win32 + {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Debug|x64.ActiveCfg = Debug|Win32 {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32 {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32 {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.FullRelease|Win32.ActiveCfg = FullRelease|Win32 @@ -122,6 +150,11 @@ Global {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Test|Mixed Platforms.Build.0 = Test|Win32 {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Test|Win32.ActiveCfg = Test|Win32 {765B0AF0-B8D3-4998-89AF-D6F939E1CD18}.Test|x64.ActiveCfg = Test|Win32 + {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Debug|Win32.ActiveCfg = Debug|Win32 + {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Debug|Win32.Build.0 = Debug|Win32 + {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Debug|x64.ActiveCfg = Debug|Win32 {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32 {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32 {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.FullRelease|Win32.ActiveCfg = FullRelease|Win32 @@ -138,6 +171,11 @@ Global {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Test|Mixed Platforms.Build.0 = Test|Win32 {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Test|Win32.ActiveCfg = Test|Win32 {AF3DBBDE-E006-4DC3-9A26-CB0D7D82AE3C}.Test|x64.ActiveCfg = Test|Win32 + {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Debug|Win32.ActiveCfg = Debug|Win32 + {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Debug|Win32.Build.0 = Debug|Win32 + {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Debug|x64.ActiveCfg = Debug|Win32 {DAF2EB1A-546A-41B3-9755-187562C01E3C}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32 {DAF2EB1A-546A-41B3-9755-187562C01E3C}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32 {DAF2EB1A-546A-41B3-9755-187562C01E3C}.FullRelease|Win32.ActiveCfg = FullRelease|Win32 @@ -154,6 +192,11 @@ Global {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Test|Mixed Platforms.Build.0 = Test|Win32 {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Test|Win32.ActiveCfg = Test|Win32 {DAF2EB1A-546A-41B3-9755-187562C01E3C}.Test|x64.ActiveCfg = Test|Win32 + {C85288FB-A035-42CA-B5FB-8E6214319E97}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C85288FB-A035-42CA-B5FB-8E6214319E97}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {C85288FB-A035-42CA-B5FB-8E6214319E97}.Debug|Win32.ActiveCfg = Debug|Win32 + {C85288FB-A035-42CA-B5FB-8E6214319E97}.Debug|Win32.Build.0 = Debug|Win32 + {C85288FB-A035-42CA-B5FB-8E6214319E97}.Debug|x64.ActiveCfg = Debug|Win32 {C85288FB-A035-42CA-B5FB-8E6214319E97}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32 {C85288FB-A035-42CA-B5FB-8E6214319E97}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32 {C85288FB-A035-42CA-B5FB-8E6214319E97}.FullRelease|Win32.ActiveCfg = FullRelease|Win32 @@ -170,6 +213,11 @@ Global {C85288FB-A035-42CA-B5FB-8E6214319E97}.Test|Mixed Platforms.Build.0 = Test|Win32 {C85288FB-A035-42CA-B5FB-8E6214319E97}.Test|Win32.ActiveCfg = Test|Win32 {C85288FB-A035-42CA-B5FB-8E6214319E97}.Test|x64.ActiveCfg = Test|Win32 + {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Debug|Win32.ActiveCfg = Debug|Win32 + {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Debug|Win32.Build.0 = Debug|Win32 + {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Debug|x64.ActiveCfg = Debug|Win32 {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32 {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32 {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.FullRelease|Win32.ActiveCfg = FullRelease|Win32 @@ -186,6 +234,11 @@ Global {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Test|Mixed Platforms.Build.0 = Test|Win32 {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Test|Win32.ActiveCfg = Test|Win32 {960E83B5-9118-4EBD-AF50-18EFC1DC764B}.Test|x64.ActiveCfg = Test|Win32 + {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Debug|Win32.ActiveCfg = Debug|Win32 + {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Debug|Win32.Build.0 = Debug|Win32 + {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Debug|x64.ActiveCfg = Debug|Win32 {79BDABE6-5308-4D64-8884-A5A35909D8D3}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32 {79BDABE6-5308-4D64-8884-A5A35909D8D3}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32 {79BDABE6-5308-4D64-8884-A5A35909D8D3}.FullRelease|Win32.ActiveCfg = FullRelease|Win32 @@ -202,6 +255,11 @@ Global {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Test|Mixed Platforms.Build.0 = Test|Win32 {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Test|Win32.ActiveCfg = Test|Win32 {79BDABE6-5308-4D64-8884-A5A35909D8D3}.Test|x64.ActiveCfg = Test|Win32 + {E9F73E11-A463-45C6-A733-2BED75852BA1}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {E9F73E11-A463-45C6-A733-2BED75852BA1}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {E9F73E11-A463-45C6-A733-2BED75852BA1}.Debug|Win32.ActiveCfg = Debug|Win32 + {E9F73E11-A463-45C6-A733-2BED75852BA1}.Debug|Win32.Build.0 = Debug|Win32 + {E9F73E11-A463-45C6-A733-2BED75852BA1}.Debug|x64.ActiveCfg = Debug|Win32 {E9F73E11-A463-45C6-A733-2BED75852BA1}.FullRelease|Mixed Platforms.ActiveCfg = FullRelease|Win32 {E9F73E11-A463-45C6-A733-2BED75852BA1}.FullRelease|Mixed Platforms.Build.0 = FullRelease|Win32 {E9F73E11-A463-45C6-A733-2BED75852BA1}.FullRelease|Win32.ActiveCfg = FullRelease|Win32 @@ -218,6 +276,11 @@ Global {E9F73E11-A463-45C6-A733-2BED75852BA1}.Test|Mixed Platforms.Build.0 = Test|Win32 {E9F73E11-A463-45C6-A733-2BED75852BA1}.Test|Win32.ActiveCfg = Test|Win32 {E9F73E11-A463-45C6-A733-2BED75852BA1}.Test|x64.ActiveCfg = Test|Win32 + {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Debug|Win32.ActiveCfg = Debug|Win32 + {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Debug|Win32.Build.0 = Debug|Win32 + {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Debug|x64.ActiveCfg = Debug|Win32 {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32 {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.FullRelease|Mixed Platforms.Build.0 = Release|Win32 {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.FullRelease|Win32.ActiveCfg = Release|Win32 @@ -234,6 +297,11 @@ Global {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Test|Mixed Platforms.Build.0 = Test|Win32 {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Test|Win32.ActiveCfg = Test|Win32 {38FAC3FB-A2B7-453F-8A6A-73B97201BB04}.Test|x64.ActiveCfg = Test|Win32 + {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Debug|Win32.ActiveCfg = Debug|Win32 + {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Debug|Win32.Build.0 = Debug|Win32 + {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Debug|x64.ActiveCfg = Debug|Win32 {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32 {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.FullRelease|Mixed Platforms.Build.0 = Release|Win32 {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.FullRelease|Win32.ActiveCfg = Release|Win32 @@ -250,6 +318,12 @@ Global {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Test|Mixed Platforms.Build.0 = Test|Win32 {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Test|Win32.ActiveCfg = Test|Win32 {6181E50C-5F32-42DC-BEF6-827AA8A5429D}.Test|x64.ActiveCfg = Test|Win32 + {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|Win32.ActiveCfg = Debug|Win32 + {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|Win32.Build.0 = Debug|Win32 + {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|x64.ActiveCfg = Debug|x64 + {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Debug|x64.Build.0 = Debug|x64 {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32 {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.FullRelease|Mixed Platforms.Build.0 = Release|Win32 {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.FullRelease|Win32.ActiveCfg = Release|Win32 @@ -266,6 +340,12 @@ Global {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Test|Mixed Platforms.Build.0 = Test|Win32 {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Test|Win32.ActiveCfg = Test|Win32 {2C44DD04-F5D6-4CC3-B0D6-1F4E51A0D962}.Test|x64.ActiveCfg = Test|x64 + {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|Win32.ActiveCfg = Debug|Win32 + {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|Win32.Build.0 = Debug|Win32 + {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|x64.ActiveCfg = Debug|x64 + {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Debug|x64.Build.0 = Debug|x64 {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32 {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.FullRelease|Mixed Platforms.Build.0 = Release|Win32 {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.FullRelease|Win32.ActiveCfg = Release|Win32 @@ -282,6 +362,12 @@ Global {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Test|Mixed Platforms.Build.0 = Test|Win32 {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Test|Win32.ActiveCfg = Test|Win32 {8627DA33-98D1-4F60-B404-ECCEE0EE7BF9}.Test|x64.ActiveCfg = Test|x64 + {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|Win32.ActiveCfg = Debug|Win32 + {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|Win32.Build.0 = Debug|Win32 + {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|x64.ActiveCfg = Debug|x64 + {98BA115B-829F-4085-9729-ABD0D779A60A}.Debug|x64.Build.0 = Debug|x64 {98BA115B-829F-4085-9729-ABD0D779A60A}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32 {98BA115B-829F-4085-9729-ABD0D779A60A}.FullRelease|Mixed Platforms.Build.0 = Release|Win32 {98BA115B-829F-4085-9729-ABD0D779A60A}.FullRelease|Win32.ActiveCfg = Release|Win32 @@ -298,6 +384,9 @@ Global {98BA115B-829F-4085-9729-ABD0D779A60A}.Test|Mixed Platforms.Build.0 = Test|Win32 {98BA115B-829F-4085-9729-ABD0D779A60A}.Test|Win32.ActiveCfg = Test|Win32 {98BA115B-829F-4085-9729-ABD0D779A60A}.Test|x64.ActiveCfg = Test|x64 + {BE211CE1-3955-4674-A664-5038FC791980}.Debug|Mixed Platforms.ActiveCfg = Release|x86 + {BE211CE1-3955-4674-A664-5038FC791980}.Debug|Win32.ActiveCfg = Release|x86 + {BE211CE1-3955-4674-A664-5038FC791980}.Debug|x64.ActiveCfg = Release|x64 {BE211CE1-3955-4674-A664-5038FC791980}.FullRelease|Mixed Platforms.ActiveCfg = Release|x86 {BE211CE1-3955-4674-A664-5038FC791980}.FullRelease|Mixed Platforms.Build.0 = Release|x86 {BE211CE1-3955-4674-A664-5038FC791980}.FullRelease|Win32.ActiveCfg = Release|x86 @@ -313,6 +402,65 @@ Global {BE211CE1-3955-4674-A664-5038FC791980}.Test|Mixed Platforms.Build.0 = Release|x86 {BE211CE1-3955-4674-A664-5038FC791980}.Test|Win32.ActiveCfg = Release|x86 {BE211CE1-3955-4674-A664-5038FC791980}.Test|x64.ActiveCfg = Release|x86 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|Win32.ActiveCfg = Debug|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|Win32.Build.0 = Debug|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|x64.ActiveCfg = Debug|x64 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Debug|x64.Build.0 = Debug|x64 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|Mixed Platforms.Build.0 = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|Win32.ActiveCfg = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|Win32.Build.0 = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|x64.ActiveCfg = Release|x64 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.FullRelease|x64.Build.0 = Release|x64 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|Mixed Platforms.Build.0 = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|Win32.ActiveCfg = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|Win32.Build.0 = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|x64.ActiveCfg = Release|x64 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Release|x64.Build.0 = Release|x64 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|Mixed Platforms.ActiveCfg = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|Mixed Platforms.Build.0 = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|Win32.ActiveCfg = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|Win32.Build.0 = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|x64.ActiveCfg = Release|x64 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.ReleaseXP|x64.Build.0 = Release|x64 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Test|Mixed Platforms.ActiveCfg = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Test|Mixed Platforms.Build.0 = Release|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Test|Win32.ActiveCfg = Test|Win32 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Test|x64.ActiveCfg = Release|x64 + {EDD28611-EAD9-4EB5-A873-18160AC44434}.Test|x64.Build.0 = Release|x64 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|Win32.ActiveCfg = Debug|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|Win32.Build.0 = Debug|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|x64.ActiveCfg = Debug|x64 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Debug|x64.Build.0 = Debug|x64 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|Mixed Platforms.ActiveCfg = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|Mixed Platforms.Build.0 = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|Win32.ActiveCfg = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|Win32.Build.0 = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|x64.ActiveCfg = Release|x64 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.FullRelease|x64.Build.0 = Release|x64 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|Mixed Platforms.Build.0 = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|Win32.ActiveCfg = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|Win32.Build.0 = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|x64.ActiveCfg = Release|x64 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Release|x64.Build.0 = Release|x64 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|Mixed Platforms.ActiveCfg = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|Mixed Platforms.Build.0 = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|Win32.ActiveCfg = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|Win32.Build.0 = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|x64.ActiveCfg = Release|x64 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.ReleaseXP|x64.Build.0 = Release|x64 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|Mixed Platforms.ActiveCfg = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|Mixed Platforms.Build.0 = Release|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|Win32.ActiveCfg = Debug|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|Win32.Build.0 = Debug|Win32 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|x64.ActiveCfg = Release|x64 + {07609D0D-FE6B-4A84-8C87-F914A4566F6F}.Test|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj b/od-win32/winuae_msvc15/winuae_msvc.vcxproj index 209a0ecd..5663c22c 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj @@ -47,7 +47,7 @@ {4ADAA943-1AC8-4FB5-82E5-4FB753B6C2DA} winuae 8.1 - 8.1 + 10.0 @@ -200,15 +200,15 @@ winuae64 winuae64 winuae64 - $(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) - $(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) - $(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) + $(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath) + $(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath) + $(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath) C:\dev\lib;$(LibraryPath) C:\dev\lib;$(LibraryPath) C:\dev\lib;$(LibraryPath) C:\dev\lib;$(LibraryPath) - $(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) - $(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) + $(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath) + $(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath) $(VC_ReferencesPath_x86); C:\dev\lib;$(LibraryPath) true @@ -216,15 +216,15 @@ true true true - $(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) + $(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath) C:\dev\lib\x64;$(LibraryPath) - $(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) - $(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) - $(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) + $(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath) + $(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath) + $(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath) C:\dev\lib\x64;$(LibraryPath) C:\dev\lib\x64;$(LibraryPath) C:\dev\lib\x64;$(LibraryPath) - $(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) + $(MSBuildProgramFiles32)\Windows Kits\10\Include\10.0.18362.0\km;c:\dev\include;$(IncludePath) C:\dev\lib\x64;$(LibraryPath) @@ -1080,6 +1080,7 @@ + diff --git a/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters b/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters index 67979089..c5c520e2 100644 --- a/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters +++ b/od-win32/winuae_msvc15/winuae_msvc.vcxproj.filters @@ -937,6 +937,9 @@ x86 + + win32 + diff --git a/readcpu.cpp b/readcpu.cpp index e6f8bb5e..0f0b21e8 100644 --- a/readcpu.cpp +++ b/readcpu.cpp @@ -264,12 +264,14 @@ out1: int usesrc = 0, usedst = 0; int srctype = 0; int srcpos = -1, dstpos = -1; + int usecc = 0; amodes srcmode = am_unknown, destmode = am_unknown; int srcreg = -1, destreg = -1; - for (i = 0; i < lastbit; i++) + for (i = 0; i < lastbit; i++) { bitcnt[i] = bitval[i] = 0; + } vmsk = 1 << id.n_variable; @@ -285,6 +287,8 @@ out1: bitcnt[currbit]++; bitval[currbit] <<= 1; bitval[currbit] |= bit_set; + if (currbit == bitC || currbit == bitc) + usecc = 1; } } @@ -717,6 +721,8 @@ endofline: table68k[opc].mnemo = lookuptab[find].mnemo; } table68k[opc].cc = bitval[bitc]; + table68k[opc].ccuse = usecc != 0; + mnemo = table68k[opc].mnemo; if (mnemo == i_BTST || mnemo == i_BSET diff --git a/softfloat/softfloat_decimal.cpp b/softfloat/softfloat_decimal.cpp index 2c0eb5a4..ccb7f5a9 100644 --- a/softfloat/softfloat_decimal.cpp +++ b/softfloat/softfloat_decimal.cpp @@ -325,7 +325,7 @@ static int32_t getDecimalExponent(int32_t aExp, uint64_t aSig) zSig0 &= ~(((int64_t)(zSig1<<1) == 0) & 1); } - zExp = zSign ? -zSig0 : zSig0; + zExp = zSign ? (0 - zSig0) : zSig0; return zExp; } -- 2.47.3