From a0e9ecc4bd6a1db4aaba250c66920dec5d7dbb6e Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 12 Jan 2019 16:42:51 +0200 Subject: [PATCH] Debugger updates. --- cfgfile.cpp | 6 + debug.cpp | 496 ++++++++++++++++++- debugmem.cpp | 1159 ++++++++++++++++++++++++++++++++++++++++---- filesys.cpp | 13 +- include/debug.h | 4 + include/debugmem.h | 4 +- include/options.h | 1 + newcpu.cpp | 57 ++- 8 files changed, 1620 insertions(+), 120 deletions(-) diff --git a/cfgfile.cpp b/cfgfile.cpp index 7adf9133..10fce2c7 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -1829,6 +1829,9 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) } } + if (p->trainerfile[0]) + cfgfile_write_str(f, _T("trainerfile"), p->trainerfile); + if (p->statefile[0]) cfgfile_write_str (f, _T("statefile"), p->statefile); if (p->quitstatefile[0]) @@ -3752,6 +3755,9 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value) return 1; } + if (cfgfile_path(option, value, _T("trainerfile"), p->trainerfile, sizeof p->trainerfile / sizeof(TCHAR))) + return 1; + if (cfgfile_path (option, value, _T("statefile_quit"), p->quitstatefile, sizeof p->quitstatefile / sizeof (TCHAR))) return 1; diff --git a/debug.cpp b/debug.cpp index 52852333..6c2bf313 100644 --- a/debug.cpp +++ b/debug.cpp @@ -47,6 +47,8 @@ #include "drawing.h" #include "devices.h" #include "blitter.h" +#include "ini.h" +#include "readcpu.h" #define TRACE_SKIP_INS 1 #define TRACE_MATCH_PC 2 @@ -896,7 +898,8 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def) double out; form[0] = 0; - *size = 0; + if (size) + *size = 0; p = form; for (;;) { uae_u32 v; @@ -908,7 +911,8 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def) p += _tcslen (p); if (peekchar (cp) == '.') { readchar (cp); - *size = readsize (v, cp); + if (size) + *size = readsize (v, cp); } if (!isoperator (cp)) break; @@ -917,7 +921,7 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def) *p = 0; } if (!gotop) { - if (*size == 0) { + if (size && *size == 0) { uae_s32 v = (uae_s32)(*val); if (v > 65535 || v < -32767) { *size = 4; @@ -931,7 +935,7 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def) } if (calc (form, &out)) { *val = (uae_u32)out; - if (*size == 0) { + if (size && *size == 0) { uae_s32 v = (uae_s32)(*val); if (v > 255 || v < -127) { *size = 2; @@ -2947,6 +2951,11 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u3 isoldval = 1; } + if (m->pc != 0xffffff) { + if (m->pc != regs.instruction_pc) + continue; + } + if (!m->frozen && m->val_enabled) { int trigger = 0; uae_u32 mask = m->size == 4 ? 0xffffffff : (1 << (m->size * 8)) - 1; @@ -3022,7 +3031,6 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u3 } // if (!notinrom ()) // return 1; - mwhit.pc = M68K_GETPC; mwhit.addr = addr; mwhit.rwi = rwi; mwhit.size = size; @@ -3033,7 +3041,7 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u3 mwhit.val = val; memwatch_triggered = i + 1; debugging = 1; - debug_pc = mwhit.pc; + debug_pc = M68K_GETPC; debug_cycles(); set_special (SPCFLAG_BRK); return 1; @@ -3382,6 +3390,10 @@ static void initialize_memwatch (int mode) debug_mem_banks = xcalloc (addrbank*, membank_total); debug_mem_area = xcalloc (addrbank, membank_total); membank_stores = xcalloc (struct membank_store, MEMWATCH_STORE_SLOTS); + for (int i = 0; i < MEMWATCH_TOTAL; i++) { + struct memwatch_node *m = &mwnodes[i]; + m->pc = 0xffffffff; + } #if 0 int i, j, as; addrbank *a1, *a2, *oa; @@ -3483,7 +3495,9 @@ void memwatch_dump2 (TCHAR *buf, int bufsize, int num) if (mwn->modval_written) buf = buf_out (buf, &bufsize, _T(" =M")); if (mwn->mustchange) - buf = buf_out (buf, &bufsize, _T(" C")); + buf = buf_out(buf, &bufsize, _T(" C")); + if (mwn->pc != 0xffffffff) + buf = buf_out(buf, &bufsize, _T(" PC=%08x"), mwn->pc); for (int j = 0; memwatch_access_masks[j].mask; j++) { uae_u32 mask = memwatch_access_masks[j].mask; if ((mwn->access_mask & mask) == mask && (usedmask & mask) == 0) { @@ -3609,7 +3623,7 @@ static void memwatch (TCHAR **c) ignore_ws (c); if (more_params(c)) { for (;;) { - TCHAR ncc = peek_next_char(c); + TCHAR ncc = _totupper(peek_next_char(c)); TCHAR nc = _totupper (next_char (c)); if (mwn->rwi == 7) mwn->rwi = 0; @@ -3623,6 +3637,10 @@ static void memwatch (TCHAR **c) mwn->rwi |= 1; if (ncc == ' ') break; + if (nc == 'P' && ncc == 'C') { + next_char(c); + mwn->pc = readhex(c, NULL); + } if (!more_params(c)) break; } @@ -6539,3 +6557,465 @@ void debug_parser (const TCHAR *cmd, TCHAR *out, uae_u32 outsize) setconsolemode (NULL, 0); xfree (input); } + +/* + +trainer file is .ini file with following one or more [patch] sections. +Each [patch] section describes single trainer option. + +After [patch] section must come at least one patch descriptor. + +[patch] +name=name +enable=true/false + +; patch descriptor +data=200e46802d400026200cxx02 ; this is comment +offset=2 +access=write +setvalue= +type=nop/freeze/set/setonce + +; patch descriptor +data=11223344556677889900 +offset=10 +replacedata=4e71 +replaceoffset=4 + +; next patch section +[patch] + + +name: name of the option (appears in GUI in the future) +enable: true = automatically enabled at startup. (false=manually activated using key shortcut etc.., will be implemented later) + +data: match data, when emulated CPU executes first opcode of this data and following words also match: match is detected. x = anything. +offset: word offset from beginning of "data" that points to memory read/write instruction that you want to "patch". Default=0. +access: read=read access, write=write access. Default: write if instruction does both memory read and write, read if read-only. + +setvalue: value to write if type is set or setonce. +type=nop: found instruction's write does nothing. This instruction only. Other instruction(s) modifying same memory location are not skipped. +type=freeze: found instruction's memory read always returns value in memory. Write does nothing. +type=set: found instruction's memory read always returns "setvalue" contents. Write works normally. +type=setonce: "setvalue" contents are written to memory when patch is detected. + +replacedata: data to be copied over data + replaceoffset. x masking is also supported. Memory is modified. +replaceoffset: word offset from data. + +--- + +Internally it uses debugger memory watch points to modify/freeze memory contents. No memory or code is modified. +Only type=setonce and replacedata modifies memory. + +When CPU emulator current to be executed instruction's matches contents of data[offset], other words of data are also checked. +If all words match: instruction's effective address(es) are calculated and matching (read/write) EA is stored. Matching part +of patch is now done. + +Reason for this complexity is to enable single patch to work even if game is relocatable or it uses different memory +locations depending on hardware config. + +If type=nop/freeze/set: debugger memwatch point is set that handles faking of read/write access. +If type=setonce: "setvalue" contents gets written to detected effective address. +If replacedata is set: copy code. + +Detection phase may cause increased CPU load, this may get optimized more but it shouldn't be (too) noticeable in basic +A500 or A1200 modes. + +*/ + +#define TRAINER_NOP 0 +#define TRAINER_FREEZE 1 +#define TRAINER_SET 2 +#define TRAINER_SETONCE 3 + +struct trainerpatch +{ + TCHAR *name; + uae_u16 *data; + uae_u16 *maskdata; + uae_u16 *replacedata; + uae_u16 *replacemaskdata; + uae_u16 *replacedata_original; + uae_u16 first; + int length; + int offset; + int access; + int replacelength; + int replaceoffset; + uaecptr addr; + uaecptr varaddr; + int varsize; + uae_u32 oldval; + int patchtype; + int setvalue; + int memwatchindex; + bool enabledatstart; + bool enabled; +}; + +static struct trainerpatch **tpptr; +static int tpptrcnt; +bool debug_opcode_watch; + +uaecptr ShowEA(void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode); + +static int debug_trainer_get_ea(struct trainerpatch *tp, uaecptr pc, uae_u16 opcode, uaecptr *addr) +{ + struct instr *dp = table68k + opcode; + uae_u32 sea = 0, dea = 0; + uaecptr spc = 0, dpc = 0; + uaecptr pc2 = pc + 2; + if (dp->suse) { + spc = pc2; + pc2 = ShowEA(NULL, pc2, opcode, dp->sreg, dp->smode, dp->size, NULL, &sea, 1); + if (sea == spc) + spc = 0xffffffff; + } + if (dp->duse) { + dpc = pc2; + pc2 = ShowEA(NULL, pc2, opcode, dp->dreg, dp->dmode, dp->size, NULL, &dea, 1); + if (dea == dpc) + dpc = 0xffffffff; + } + if (dea && dpc != 0xffffffff && tp->access == 1) { + *addr = dea; + return 1 << dp->size; + } + if (sea && spc != 0xffffffff && tp->access == 0) { + *addr = sea; + return 1 << dp->size; + } + if (dea && tp->access > 1) { + *addr = dea; + return 1 << dp->size; + } + if (sea && tp->access > 1) { + *addr = sea; + return 1 << dp->size; + } + return 0; +} + +static void debug_trainer_enable(struct trainerpatch *tp, bool enable) +{ + if (tp->enabled == enable) + return; + + if (tp->replacedata) { + if (enable) { + bool first = false; + if (!tp->replacedata_original) { + tp->replacedata_original = xcalloc(uae_u16, tp->replacelength); + first = true; + } + for (int j = 0; j < tp->replacelength; j++) { + uae_u16 v = tp->replacedata[j]; + uae_u16 m = tp->replacemaskdata[j]; + uaecptr addr = (tp->addr - tp->offset * 2) + j * 2 + tp->replaceoffset * 2; + if (m == 0xffff) { + x_put_word(addr, v); + } else { + uae_u16 vo = x_get_word(addr); + x_put_word(addr, (vo & ~m) | (v & m)); + if (first) + tp->replacedata_original[j] = vo; + } + } + } else if (tp->replacedata_original) { + for (int j = 0; j < tp->replacelength; j++) { + uae_u16 m = tp->replacemaskdata[j]; + uaecptr addr = (tp->addr - tp->offset * 2) + j * 2 + tp->replaceoffset * 2; + if (m != 0xffff) { + x_put_word(addr, tp->replacedata_original[j]); + } + } + } + } + + if (tp->patchtype == TRAINER_SETONCE && tp->varaddr != 0xffffffff) { + uae_u32 v = enable ? tp->setvalue : tp->oldval; + switch (tp->varsize) + { + case 1: + x_put_byte(tp->varaddr, tp->setvalue); + break; + case 2: + x_put_word(tp->varaddr, tp->setvalue); + break; + case 4: + x_put_long(tp->varaddr, tp->setvalue); + break; + } + } + + if ((tp->patchtype == TRAINER_NOP || tp->patchtype == TRAINER_FREEZE || tp->patchtype == TRAINER_SET) && tp->varaddr != 0xffffffff) { + struct memwatch_node *mwn; + if (!memwatch_enabled) + initialize_memwatch(0); + if (enable) { + int i; + for (i = MEMWATCH_TOTAL - 1; i >= 0; i--) { + mwn = &mwnodes[i]; + if (!mwn->size) + break; + } + if (i < 0) { + write_log(_T("Trainer out of free memwatchpoints ('%s' %08x\n).\n"), tp->name, tp->addr); + } else { + mwn->addr = tp->varaddr; + mwn->size = tp->varsize; + mwn->rwi = 1 | 2; + mwn->access_mask = MW_MASK_CPU_D_R | MW_MASK_CPU_D_W; + mwn->reg = 0xffffffff; + mwn->pc = tp->patchtype == TRAINER_NOP ? tp->addr : 0xffffffff; + mwn->frozen = tp->patchtype == TRAINER_FREEZE; + mwn->modval_written = 0; + mwn->val_enabled = 0; + mwn->val_mask = 0xffffffff; + mwn->val = 0; + if (tp->patchtype == TRAINER_SET) { + mwn->val_enabled = 1; + mwn->val = tp->setvalue; + } + memwatch_setup(); + TCHAR buf[256]; + memwatch_dump2(buf, sizeof(buf) / sizeof(TCHAR), i); + write_log(_T("%s"), buf); + } + } else { + mwn = &mwnodes[tp->memwatchindex]; + mwn->size = 0; + memwatch_setup(); + } + } + + write_log(_T("Trainer '%s' %s (addr=%08x)\n"), tp->name, enable ? _T("enabled") : _T("disabled"), tp->addr); + tp->enabled = enable; +} + +void debug_trainer_match(void) +{ + uaecptr pc = m68k_getpc(); + uae_u16 opcode = x_get_word(pc); + for (int i = 0; i < tpptrcnt; i++) { + struct trainerpatch *tp = tpptr[i]; + if (tp->first != opcode) + continue; + if (tp->addr) + continue; + int j; + for (j = 0; j < tp->length; j++) { + uae_u16 d = x_get_word(pc + (j - tp->offset) * 2); + if ((d & tp->maskdata[j]) != tp->data[j]) + break; + } + if (j < tp->length) + continue; + tp->first = 0xffff; + tp->addr = pc; + tp->varsize = -1; + tp->varaddr = 0xffffffff; + tp->oldval = 0xffffffff; + if (tp->access >= 0) { + tp->varsize = debug_trainer_get_ea(tp, pc, opcode, &tp->varaddr); + switch (tp->varsize) + { + case 1: + tp->oldval = x_get_byte(tp->varaddr); + break; + case 2: + tp->oldval = x_get_word(tp->varaddr); + break; + case 4: + tp->oldval = x_get_long(tp->varaddr); + break; + } + } + write_log(_T("Patch %d match at %08x. Addr %08x, size %d, val %08x\n"), i, pc, tp->varaddr, tp->varsize, tp->oldval); + + if (tp->enabledatstart) + debug_trainer_enable(tp, true); + + // all detected? + for (j = 0; j < tpptrcnt; j++) { + struct trainerpatch *tp = tpptr[j]; + if (!tp->addr) + break; + } + if (j == tpptrcnt) + debug_opcode_watch = false; + } +} + +static int parsetrainerdata(const TCHAR *data, uae_u16 *outdata, uae_u16 *outmask) +{ + int len = _tcslen(data); + uae_u16 v = 0, vm = 0; + int j = 0; + for (int i = 0; i < len; ) { + TCHAR c1 = _totupper(data[i + 0]); + TCHAR c2 = _totupper(data[i + 1]); + if (c1 > 0 && c1 <= ' ') { + i++; + continue; + } + if (i + 1 >= len) + return 0; + + vm <<= 8; + vm |= 0xff; + if (c1 == 'X' || c1 == '?') + vm &= 0x0f; + if (c2 == 'X' || c2 == '?') + vm &= 0xf0; + + if (c1 >= 'A') + c1 -= 'A' - 10; + else if (c1 >= '0') + c1 -= '0'; + if (c2 >= 'A') + c2 -= 'A' - 10; + else if (c2 >= '0') + c2 -= '0'; + + v <<= 8; + if (c1 >= 0 && c1 < 16) + v |= c1 << 4; + if (c2 >= 0 && c2 < 16) + v |= c2; + + if (i & 2) { + outdata[j] = v; + outmask[j] = vm; + j++; + } + + i += 2; + } + return j; +} + +void debug_init_trainer(const TCHAR *file) +{ + TCHAR *data; + TCHAR section[256]; + int cnt = 1; + + struct ini_data *ini = ini_load(file, false); + if (!ini) + return; + + write_log(_T("Loaded '%s'\n"), file); + + _tcscpy(section, _T("patch")); + + for (;;) { + struct ini_context ictx; + ini_initcontext(ini, &ictx); + + for (;;) { + TCHAR *name = NULL; + + ini_getstring_multi(ini, section, _T("name"), &name, &ictx); + + if (!ini_getstring_multi(ini, section, _T("data"), &data, &ictx)) + break; + ini_setcurrentasstart(ini, &ictx); + ini_setlast(ini, section, _T("data"), &ictx); + + TCHAR *p = _tcschr(data, ';'); + if (p) + *p = 0; + my_trim(data); + + struct trainerpatch *tp = xcalloc(struct trainerpatch, 1); + + int datalen = (_tcslen(data) + 3) / 4; + tp->data = xcalloc(uae_u16, datalen); + tp->maskdata = xcalloc(uae_u16, datalen); + tp->length = parsetrainerdata(data, tp->data, tp->maskdata); + xfree(data); + data = NULL; + + ini_getval_multi(ini, section, _T("offset"), &tp->offset, &ictx); + if (tp->offset < 0 || tp->offset >= tp->length) + tp->offset = 0; + + if (ini_getstring_multi(ini, section, _T("replacedata"), &data, &ictx)) { + int replacedatalen = (_tcslen(data) + 3) / 4; + tp->replacedata = xcalloc(uae_u16, replacedatalen); + tp->replacemaskdata = xcalloc(uae_u16, replacedatalen); + tp->replacelength = parsetrainerdata(data, tp->replacedata, tp->replacemaskdata); + xfree(data); + data = NULL; + ini_getval_multi(ini, section, _T("replaceoffset"), &tp->offset, &ictx); + if (tp->replaceoffset < 0 || tp->replaceoffset >= tp->length) + tp->replaceoffset = 0; + tp->access = -1; + } + + tp->access = 2; + if (ini_getstring_multi(ini, section, _T("access"), &tp->data, &ictx)) { + if (!_tcsicmp(data, _T("read"))) + tp->access = 0; + else if (!_tcsicmp(data, _T("write"))) + tp->access = 1; + } + + if (ini_getstring_multi(ini, section, _T("enable"), &data, &ictx)) { + if (!_tcsicmp(data, _T("true"))) + tp->enabledatstart = true; + } + + if (ini_getstring_multi(ini, section, _T("type"), &data, &ictx)) { + if (!_tcsicmp(data, _T("freeze"))) + tp->patchtype = TRAINER_FREEZE; + else if (!_tcsicmp(data, _T("nop"))) + tp->patchtype = TRAINER_NOP; + else if (!_tcsicmp(data, _T("set"))) + tp->patchtype = TRAINER_SET; + else if (!_tcsicmp(data, _T("setonce"))) + tp->patchtype = TRAINER_SETONCE; + xfree(data); + } + + if (ini_getstring_multi(ini, section, _T("setvalue"), &data, &ictx)) { + TCHAR *endptr; + if (data[0] == '$') { + tp->setvalue = _tcstol(data + 1, &endptr, 16); + } else if (_tcslen(data) > 2 && data[0] == '0' && _totupper(data[1]) == 'x') { + tp->setvalue = _tcstol(data + 2, &endptr, 16); + } else { + tp->setvalue = _tcstol(data, &endptr, 10); + } + xfree(data); + } + + tp->first = tp->data[tp->offset]; + tp->name = name; + + if (tpptrcnt) + tpptr = xrealloc(struct trainerpatch*, tpptr, tpptrcnt + 1); + else + tpptr = xcalloc(struct trainerpatch*, tpptrcnt + 1); + tpptr[tpptrcnt++] = tp; + + write_log(_T("%d: '%s' parsed and enabled\n"), cnt, tp->name ? tp->name : _T("")); + cnt++; + + ini_setlastasstart(ini, &ictx); + } +err: + xfree(data); + + if (!ini_nextsection(ini, section)) + break; + + } + +end: + if (tpptrcnt > 0) + debug_opcode_watch = true; + + ini_free(ini); +} diff --git a/debugmem.cpp b/debugmem.cpp index 9b6cf2bb..e37b8d02 100644 --- a/debugmem.cpp +++ b/debugmem.cpp @@ -17,6 +17,7 @@ #include "zfile.h" #include "uae.h" #include "fsdb.h" +#include "rommgr.h" #define N_GSYM 0x20 #define N_FUN 0x24 @@ -106,7 +107,7 @@ struct stabtype struct debugcodefile { - const TCHAR *name; + const TCHAR *name, *path; int length; uae_u8 *data; int lines; @@ -142,7 +143,7 @@ struct debugsymbol void *data; }; static struct debugsymbol **symbols; -static int symbolcnt; +static int symbolcnt, symbolindex; struct libname { @@ -229,9 +230,23 @@ struct debugsegtracker uaecptr resident; }; static struct debugsegtracker **dsegt; -static int segtrackermax; +static int segtrackermax, segtrackerindex; static uae_u32 inhibit_break, last_break; +static uae_u8 *lebx(uae_u8 *p, uae_u32 *v) +{ + uae_u32 val = 0; + for (;;) { + uae_u8 b = *p++; + val |= b & 0x7f; + if (!(b & 0x80)) + break; + val <<= 7; + } + *v = val; + return p; +} + bool debugmem_break(int type) { if (inhibit_break & (1 << type)) @@ -1032,13 +1047,13 @@ static uae_u32 gl(uae_u8 *p) return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); } -static struct debugcodefile *loadcodefile(const TCHAR *path, const TCHAR *name) +static bool loadcodefiledata(struct debugcodefile *cf) { TCHAR fpath[MAX_DPATH]; fpath[0] = 0; - if (path) - _tcscat(fpath, path); - _tcscat(fpath, name); + if (cf->path) + _tcscat(fpath, cf->path); + _tcscat(fpath, cf->name); struct zfile *zf = zfile_fopen(fpath, _T("rb")); if (!zf) { console_out_f(_T("Couldn't open source file '%s'\n"), fpath); @@ -1055,12 +1070,6 @@ static struct debugcodefile *loadcodefile(const TCHAR *path, const TCHAR *name) memcpy(data, data2, length); xfree(data2); zfile_fclose(zf); - struct debugcodefile *cf = codefiles[codefilecnt]; - if (!cf) { - cf = codefiles[codefilecnt] = xcalloc(struct debugcodefile, 1); - } - codefilecnt++; - cf->name = my_strdup(name); cf->data = data; cf->length = length; cf->lines = 1; @@ -1089,7 +1098,40 @@ static struct debugcodefile *loadcodefile(const TCHAR *path, const TCHAR *name) s[len - 1] = 0; } } - console_out_f(_T("Loaded source file '%s', %d bytes, %d lines\n"), fpath, cf->length, cf->lines); +} + +static struct debugcodefile *preallocatecodefile(const TCHAR *path, const TCHAR *name) +{ + struct debugcodefile *cf = codefiles[codefilecnt]; + if (!cf) { + cf = codefiles[codefilecnt] = xcalloc(struct debugcodefile, 1); + } + codefilecnt++; + cf->name = my_strdup(name); + cf->path = my_strdup(path); + return cf; +} + +static void freecodefile(struct debugcodefile *cf) +{ + for (int i = 0; i < codefilecnt; i++) { + struct debugcodefile *c = codefiles[i]; + if (c == cf) { + xfree(codefiles[i]); + codefiles[i] = NULL; + } + } +} + +static struct debugcodefile *loadcodefile(const TCHAR *path, const TCHAR *name) +{ + struct debugcodefile *cf = preallocatecodefile(path, name); + if (!loadcodefiledata(cf)) { + freecodefile(cf); + cf = NULL; + } else { + console_out_f(_T("Loaded source file '%s' '%s', %d bytes, %d lines\n"), cf->path, cf->name, cf->length, cf->lines); + } return cf; } @@ -1109,7 +1151,7 @@ static struct debugsymbol *issymbol(const TCHAR *name) { for (int i = 0; i < symbolcnt; i++) { struct debugsymbol *ds = symbols[i]; - if (!_tcsicmp(ds->name, name)) { + if (ds->allocid && !_tcsicmp(ds->name, name)) { return ds; } } @@ -1346,6 +1388,172 @@ static void parse_stabs(void) xfree(pathprefix); } +static uae_u32 getrombase(int size) +{ + if (size > 524288 * 3) + return 0; + if (size > 524288 * 2) { + return 0xa00000; + } else if (size > 524288 * 1) { + return 0xa80000; + } else { + return 0xf80000; + } +} + +static void addsimplesymbol(const TCHAR *name, uae_u32 v, int type, int flags, int segmentid, int segmentnum) +{ + if (!symbols) + return; + + for (int i = 0; i < symbolcnt; i++) { + struct debugsymbol *ds = symbols[i]; + if (ds->segment == segmentid && !_tcscmp(name, ds->name)) + return; + } + //write_log(_T("ELF Section %d, symbol %s=%08x\n"), segmentnum, name, v); + int rnd = 0; + for (;;) { + if (symbolindex >= MAX_DEBUGSYMS) { + symbolindex = 0; + rnd++; + if (rnd > 1) + return; + } else { + symbolindex++; + } + struct debugsymbol *ds = symbols[symbolindex]; + if (ds->allocid == 0) { + ds->allocid = -1; + ds->name = my_strdup(name); + ds->value = v; + ds->type = type; + ds->flags = flags; + ds->segment = segmentid; + if (symbolindex >= symbolcnt) + symbolcnt = symbolindex + 1; + return; + } + } +} + +static uae_u8 *loadhunkfile(uae_u8 *file, int filelen, uae_u32 seglist, int segmentid, int *outsizep, bool rommode) +{ + uae_u8 *p = file; + uae_u8 *out = NULL; + + if (gl(p) != 0x3f3) { + return NULL; + } + p += 4; + if (gl(p) != 0) { + return 0; + } + p += 4; + int hunktotal = gl(p); + int first = gl(p + 4); + int last = gl(p + 8); + if (hunktotal > 1000 || (last - first + 1) > 1000) { + return 0; + } + if (first > last) { + return 0; + } + p += 12; + uae_u32 *hunklens = xcalloc(uae_u32, last + 1); + uae_u32 *hunkoffsets = xcalloc(uae_u32, last + 1); + int totalsize = 0; + for (int i = first; i <= last; i++) { + uae_u32 len = gl(p); + p += 4; + if ((len & 0xc0000000) == 0xc0000000) { + p += 4; + } + len &= ~(0x80000000 | 0x40000000); + hunklens[i] = len * 4; + hunkoffsets[i] = totalsize; + totalsize += hunklens[i]; + } + uae_u32 relocate_base = getrombase(totalsize); + int outsize = 0; + int hunkindex = -1; + for (;;) { + uae_u32 hunktype = gl(p) & ~0xc0000000; + if (hunktype == 0x3e9 || hunktype == 0x3ea || hunktype == 0x3eb) { + uae_u32 hunklen = gl(p + 4) * 4; + p += 8; + hunkindex++; + if (!out) + out = xcalloc(uae_u8, outsize + hunklens[hunkindex]); + else + out = xrealloc(uae_u8, out, outsize + hunklens[hunkindex]); + memset(out + outsize, 0, hunklens[hunkindex]); + if (hunktype != 0x3eb) { + memcpy(out + outsize, p, hunklen); + p += hunklen; + } + outsize += hunklens[hunkindex]; + + if (gl(p) == 0x3ec) { // reloc + + p += 4; + for (;;) { + int reloccnt = gl(p); + p += 4; + if (!reloccnt) + break; + int relochunk = gl(p); + p += 4; + if (relochunk > last) { + return 0; + } + uaecptr hunkptr = hunkoffsets[relochunk] + relocate_base; + uae_u8 *currenthunk = out + hunkoffsets[relochunk]; + for (int j = 0; j < reloccnt; j++) { + uae_u32 reloc = gl(p); + p += 4; + if (reloc >= outsize - 3) { + return 0; + } + put_long_host(currenthunk + reloc, get_long_host(currenthunk + reloc) + hunkptr); + } + } + } + continue; + } + + if (hunktype == 0x3f0) { // symbol + int symcnt = 0; + p += 4; + for (;;) { + int size = gl(p); + p += 4; + if (!size) + break; + if (hunkindex >= 0) { + p += 4 * size; + addsimplesymbol(au((char*)p), gl(p) + hunkoffsets[hunkindex] + 8 + relocate_base, 0, SYMBOL_GLOBAL, hunkindex, -1); + p += 4; + } else { + p += 4 * size + 4; + } + } + } else if (hunktype == 0x3f2) { + + p += 4; + + } else { + + break; + + } + } + xfree(hunkoffsets); + xfree(hunklens); + *outsizep = outsize; + return out; +} + uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr task, uae_u32 *stack) { uae_u8 *p = get_real_address(exeaddress); @@ -1354,7 +1562,7 @@ uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr task, uae_u32 *s uae_u32 lens[1000], memtypes[1000]; uae_u32 parentid = 0; - debugmem_init(); + debugmem_init(true); if (!debugmem_initialized) return 0; @@ -1987,40 +2195,584 @@ bool debugger_load_libraries(void) return true; } +struct elfheader +{ + uae_u8 ident[16]; + uae_u16 type; + uae_u16 machine; + uae_u32 version; + uae_u32 entry; + uae_u32 phoff; + uae_u32 shoff; + uae_u32 flags; + uae_u16 ehsize; + uae_u16 phentsize; + uae_u16 phnum; + uae_u16 shentsize; + uae_u16 shnum; + uae_u16 shstrndx; +}; +struct sheader +{ + uae_u32 name; + uae_u32 type; + uae_u32 flags; + uae_u32 addr; + uae_u32 offset; + uae_u32 size; + uae_u32 link; + uae_u32 info; + uae_u32 addralign; + uae_u32 entsize; +}; +struct symbol +{ + uae_u32 name; + uae_u32 value; + uae_u32 size; + uae_u8 info; + uae_u8 other; + uae_u16 shindex; +}; +struct rel +{ + uae_u32 offset; + uae_u32 info; + uae_u32 addend; +}; +struct debuglineheader +{ + uae_u16 length[2]; + uae_u16 version; + uae_u16 header_length[2]; + uae_u8 min_instruction_length; + uae_u8 default_is_stmt; + uae_s8 line_base; + uae_u8 line_range; + uae_u8 opcode_base; + uae_u8 std_opcode_lengths[12]; +}; + +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SYMTAB_SHNDX 18 + +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_XINDEX 0xffff + +#define R_68K_NONE 0 +#define R_68K_32 1 +#define R_68K_16 2 +#define R_68K_8 3 +#define R_68K_PC32 4 +#define R_68K_PC16 5 +#define R_68K_PC8 6 + +#define SHF_ALLOC (1 << 1) + +static void wswp(uae_u16 *v) +{ + *v = (*v >> 8) | (*v << 8); +} +static void lswp(uae_u32 *v) +{ + *v = (*v >> 24) | ((*v >> 8) & 0x0000ff00) | ((*v << 8) & 0x00ff0000) | (*v << 24); +} +static void lwswp(uae_u16 *vp) +{ + uae_u32 v = (vp[1] << 16) | vp[0]; + v = (v >> 24) | ((v >> 8) & 0x0000ff00) | ((v << 8) & 0x00ff0000) | (v << 24); + vp[1] = v >> 16; + vp[0] = v; +} + +static void swap_lineheader(struct debuglineheader *d, struct debuglineheader *s) +{ + memcpy(d, s, sizeof(struct debuglineheader)); + lwswp(d->length); + lwswp(d->header_length); +} + +static void swap_header(struct sheader *d, struct sheader *s) +{ + memcpy(d, s, sizeof(struct sheader)); + lswp(&d->name); + lswp(&d->type); + lswp(&d->flags); + lswp(&d->addr); + lswp(&d->offset); + lswp(&d->size); + lswp(&d->link); + lswp(&d->info); + lswp(&d->addralign); + lswp(&d->entsize); +} +static void swap_symbol(struct symbol *d, struct symbol *s) +{ + memcpy(d, s, sizeof(struct symbol)); + lswp(&d->name); + wswp(&d->shindex); + lswp(&d->value); + lswp(&d->size); +} +static void swap_rel(struct rel *d, struct rel *s) +{ + memcpy(d, s, sizeof(struct rel)); + lswp(&d->addend); + lswp(&d->info); + lswp(&d->offset); +} + +static int loadelf(uae_u8 *file, int filelen, uae_u8 **outp, int outsize, uae_u32 addr, struct sheader *sh) +{ + int size = sh->size; + uae_u8 *out = *outp; + if (!out) + out = xcalloc(uae_u8, outsize + size); + else + out = xrealloc(uae_u8, out, outsize + size); + memcpy(out + outsize, file + sh->offset, size); + outsize += size; + *outp = out; + return outsize; +} + +static uae_u8 *loadelffile(uae_u8 *file, int filelen, uae_u32 seglist, int segmentid, int *outsizep, bool rommode) +{ + uae_u8 *outp = NULL; + uae_u8 *outptr = NULL; + int outsize; + bool relocate = rommode; + uae_u32 relocate_base = 0; + + struct elfheader *eh = (struct elfheader*)file; + uae_u8 *p = file + sizeof(struct elfheader); + + wswp(&eh->type); + wswp(&eh->machine); + wswp(&eh->ehsize); + wswp(&eh->phentsize); + wswp(&eh->phnum); + wswp(&eh->shentsize); + wswp(&eh->shnum); + wswp(&eh->shstrndx); + lswp(&eh->version); + lswp(&eh->flags); + lswp(&eh->entry); + lswp(&eh->phoff); + lswp(&eh->shoff); + + uae_u32 shnum = eh->shnum; + if (shnum == 0) { + if (eh->shoff == 0) + return NULL; + struct sheader *sh = (struct sheader*)p; + shnum = sh->size; + if (shnum == 0) + return NULL; + p += sizeof(struct sheader); + } + + uae_u8 *strtab = NULL, *strtabsym = NULL; + struct sheader *symtab_shndx = NULL, *linesheader = NULL; + struct debuglineheader lineheader; + struct symbol *symtab = NULL; + uae_u8 *debuginfo = NULL; + int debuginfo_size; + int symtab_num = 0; + for (int i = 0; i < shnum; i++) { + struct sheader *shp = (struct sheader*)(file + i * sizeof(sheader) + eh->shoff); + struct sheader sh; + swap_header(&sh, shp); + if (sh.type == SHT_STRTAB) { + if (!strtab && i != eh->shstrndx) { + strtab = file + sh.offset; + } + if (!strtabsym && i == eh->shstrndx) { + strtabsym = file + sh.offset; + } + } else if (sh.type == SHT_SYMTAB_SHNDX) { + if (!symtab_shndx) + symtab_shndx = (struct sheader*)(file + sh.offset); + } else if (sh.type == SHT_SYMTAB) { + if (!symtab) { + symtab = (struct symbol*)(file + sh.offset); + symtab_num = sh.size / sh.entsize; + } + } + } + for (int i = 0; i < shnum; i++) { + struct sheader *shp = (struct sheader*)(file + i * sizeof(sheader) + eh->shoff); + struct sheader sh; + swap_header(&sh, shp); + uae_char *name = (uae_char*)(strtabsym + sh.name); + if (sh.type == SHT_PROGBITS && !strcmp(name, ".debug_line")) { + swap_lineheader(&lineheader, (struct debuglineheader*)(file + sh.offset)); + linesheader = shp; + } else if (sh.type == SHT_PROGBITS && !strcmp(name, ".debug_info")) { + debuginfo = file + sh.offset; + debuginfo_size = sh.size; + } + } + + struct sheader *shp_first = (struct sheader*)(file + eh->shoff); + int section = -1; + uae_u32 seg = seglist * 4; + uae_u32 nextseg = 0; + + uae_u32 *sectionoffsets = xcalloc(uae_u32, shnum); + uae_u32 *sectionbases = xcalloc(uae_u32, shnum); + outsize = 0; + for (int i = 0; i < shnum; i++) { + struct sheader *shp = (struct sheader*)&shp_first[i]; + struct sheader sh; + swap_header(&sh, shp); + sectionoffsets[i] = 0xffffffff; + sectionbases[i] = 0xffffffff; + uae_char *namep = (uae_char*)(strtab + sh.name); + TCHAR *n = au(namep); + write_log(_T("ELF section %d: type=%08x flags=%08x size=%08x ('%s')\n"), i, sh.type, sh.flags, sh.size, n); + xfree(n); + if (sh.type == SHT_PROGBITS) { + if ((sh.flags & SHF_ALLOC) && sh.size) { + write_log(_T(" - load data. Offset %08x\n"), outsize); + sectionoffsets[i] = outsize; + if (relocate) + sectionbases[i] = outsize; + outsize += sh.size; + } + } else if (sh.type == SHT_NOBITS) { + if (sh.size) { + sectionbases[i] = sh.addr; + } + } + } + + if (rommode) { + relocate_base = getrombase(outsize); + if (!relocate_base) + goto end; + for (int i = 0; i < shnum; i++) { + if (sectionoffsets[i] != 0xffffffff) + sectionbases[i] += relocate_base; + } + } + + for (int i = 0; i < symtab_num; i++) { + struct symbol sym; + swap_symbol(&sym, &symtab[i]); + if (!sym.name) + continue; + int sflags, stype; + uae_u8 type = sym.info & 15; + uae_u8 bind = sym.info >> 4; + if (type == 1) { + stype = 0; + } else if (type == 2) { + stype = SYMBOLTYPE_FUNC; + } else { + continue; + } + if (bind == 0) { + sflags = SYMBOL_LOCAL; + } else if (bind == 1) { + sflags = SYMBOL_GLOBAL; + } else { + continue; + } + if (sym.shindex == SHN_ABS) { + uae_char *namep = (uae_char*)(strtabsym + sym.name); + TCHAR *name = au(namep); + addsimplesymbol(name, sym.value, stype, sflags, segmentid, sym.shindex); + xfree(name); + } else if (sym.shindex < shnum && sectionoffsets[i] != 0xffffffff) { + uae_char *namep = (uae_char*)(strtabsym + sym.name); + TCHAR *name = au(namep); + uae_u32 v = sym.value + sectionbases[sym.shindex]; + addsimplesymbol(name, v, stype, sflags, segmentid, sym.shindex); + xfree(name); + } + } + + outsize = 0; + outptr = NULL; + for (int i = 0; i < shnum; i++) { + struct sheader *shp = (struct sheader*)&shp_first[i]; + struct sheader sh; + swap_header(&sh, shp); + + if (nextseg) { + seg = nextseg; + nextseg = 0; + } + + sectionoffsets[i] = outsize; + + if (sh.type == SHT_NOBITS) { + outptr = NULL; + if ((sh.flags & SHF_ALLOC) && sh.size) { + section++; + if (seg) + nextseg = get_long(seg) * 4; + } + continue; + } + + if (sh.type == SHT_PROGBITS) { + outptr = NULL; + if ((sh.flags & SHF_ALLOC) && sh.size) { + section++; + if (seg) + nextseg = get_long(seg) * 4; + if (relocate) { + int newoutsize = loadelf(file, filelen, &outp, outsize, relocate_base, &sh); + outptr = outp + outsize; + outsize = newoutsize; + *outsizep = outsize; + } + } + continue; + } + + + + if (sh.type != SHT_RELA) + continue; + + struct sheader *shsymtabp = &shp_first[sh.link]; + struct sheader shsymtab; + swap_header(&shsymtab, shsymtabp); + + struct sheader *torelocp = &shp_first[sh.info]; + struct sheader toreloc; + swap_header(&toreloc, torelocp); + + struct symbol *symtabp = (struct symbol *)(file + shsymtab.offset); + struct symbol symtab; + swap_symbol(&symtab, symtabp); + + int numrel = sh.size / sh.entsize; + + for (int j = 0; j < numrel; j++) { + + struct rel *relp = (struct rel*)(file + sh.offset + j * sizeof(rel)); + struct rel rel; + swap_rel(&rel, relp); + + struct symbol *symp = &symtabp[rel.info >> 8]; + struct symbol sym; + swap_symbol(&sym, symp); + + uae_u32 shindex; + uae_u32 addr; + uae_u32 s; + uae_u32 relocaddr; + + relocaddr = rel.offset; -void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock) + if (sym.shindex != SHN_XINDEX) { + shindex = sym.shindex; + } else { + if (symtab_shndx == NULL) + return NULL; + shindex = ((uae_u32*)(file + symtab_shndx->offset))[rel.info >> 8]; + } + uae_char *namep = (uae_char*)(file + gl((uae_u8*)(&shp_first[shsymtab.link].offset)) + sym.name); + bool doreloc = false; + TCHAR *name = au(namep); + switch (shindex) + { + case SHN_COMMON: + { + write_log(_T("ELF Common symbol '%s'"), name); + break; + } + case SHN_ABS: + { + s = sym.value; + doreloc = true; + break; + } + case SHN_UNDEF: + { + if ((rel.info & 0xff) != 0) { + write_log(_T("ELF Undefined symbol '%s'\n"), name); + } + } + default: + { + if (sectionbases[shindex] == 0xffffffff) { + s = 0; + } else { + s = sectionbases[shindex] + sym.value; + doreloc = true; + } + break; + } + } + if (doreloc) { + bool has = false; + switch (rel.info & 0xff) + { + case R_68K_32: + addr = s + rel.addend; + if (outptr) { + outptr[relocaddr + 0] = (uae_u8)(addr >> 24); + outptr[relocaddr + 1] = (uae_u8)(addr >> 16); + outptr[relocaddr + 2] = (uae_u8)(addr >> 8); + outptr[relocaddr + 3] = (uae_u8)(addr >> 0); + } + has = true; + break; + case R_68K_16: + addr = s + rel.addend; + if (outptr) { + outptr[relocaddr + 0] = (uae_u8)(addr >> 8); + outptr[relocaddr + 1] = (uae_u8)(addr >> 0); + } + has = true; + break; + case R_68K_8: + addr = s + rel.addend; + if (outptr) { + outptr[relocaddr] = (uae_u8)addr; + } + has = true; + break; + case R_68K_PC32: + addr = s + rel.addend - (sectionbases[shindex] + relocaddr); + if (outptr) { + outptr[relocaddr + 0] = (uae_u8)(addr >> 24); + outptr[relocaddr + 1] = (uae_u8)(addr >> 16); + outptr[relocaddr + 2] = (uae_u8)(addr >> 8); + outptr[relocaddr + 3] = (uae_u8)(addr >> 0); + } + has = true; + break; + case R_68K_PC16: + addr = s + rel.addend - (sectionbases[shindex] + relocaddr); + if (outptr) { + outptr[relocaddr + 0] = (uae_u8)(addr >> 8); + outptr[relocaddr + 1] = (uae_u8)(addr >> 0); + } + has = true; + break; + case R_68K_PC8: + addr = s + rel.addend - (sectionbases[shindex] + relocaddr); + if (outptr) { + outptr[relocaddr] = (uae_u8)addr; + } + has = true; + break; + case R_68K_NONE: + default: + break; + } + if (has) { + if (seg) + addr += seg + 4; + addsimplesymbol(name, addr, 0, SYMBOL_GLOBAL, segmentid, i); + } + } + xfree(name); + } + outptr = NULL; + } +#if 0 + if (debuginfo) { + uae_u8 *p = debuginfo; + while (debuginfo_size > 0) { + uae_u8 *start = p; + uae_u32 length = gl(p); + p += 4; + uae_u8 *end = p + length; + p += 2; + uae_u32 abbrev_offset = gl(p); + p += 4; + uae_u8 ptr_size = *p++; + while (p < end) { + uae_u8 abbrevnum = *p++; + switch (abbrevnum) + { + case 1: + { + p += 4; // producer + p++; //language + uae_char *namep = (uae_char*)start + gl(p); + p += 4; + uae_u32 low_pc = gl(p); + p += 4; + uae_u32 high_pc = gl(p); + p += 4; + p += 4; + break; + } + case 2: + { + p += 4 + 1 + 1 + 4; + break; + } + case 3: + { + p += 1 + 1 + 4; + break; + } + } + } + debuginfo_size -= length; + } + } +#endif + +end: + xfree(sectionoffsets); + xfree(sectionbases); + return outp; +} + +void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock, bool residentonly) { uae_u8 *file = NULL; - int filelen; - bool hasfile = false; + uae_u8 *symfile = NULL; + int filelen, symfilelen; + bool elffile = false, elfsymfile = false; int fileoffset = 0; int segmentid; if (!debugmem_initialized) - debugmem_init(); + debugmem_init(true); if (!seg || !debugmem_initialized) return; seg *= 4; uaecptr seg2 = seg; uaecptr resident = 0; - while (seg) { - uaecptr next = get_long(seg) * 4; - uaecptr len = get_long(seg - 4) * 4; - for (int i = 0; i < len - 26; i += 2) { - uae_u16 w = get_word(seg + 4 + i); - if (w == 0x4afc) { - uae_u32 l = get_long(seg + 4 + i + 2); - if (l == seg + 4 + i) { - resident = seg + 4 + i; - seg = 0; - break; + if (residentonly) { + while (seg) { + uaecptr next = get_long(seg) * 4; + uaecptr len = get_long(seg - 4) * 4; + for (int i = 0; i < len - 26; i += 2) { + uae_u16 w = get_word(seg + 4 + i); + if (w == 0x4afc) { + uae_u32 l = get_long(seg + 4 + i + 2); + if (l == seg + 4 + i) { + resident = seg + 4 + i; + seg = 0; + break; + } } } + seg = next; } - seg = next; + if (!resident) + return; } - if (!resident) - return; console_out_f(_T("Adding segment %08x, Resident %08x.\n"), seg2, resident); struct debugsegtracker *sg = NULL; for (segmentid = 0; segmentid < MAX_DEBUGSEGS; segmentid++) { @@ -2040,28 +2792,59 @@ void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock) nativepath[0] = 0; strcpyah_safe(aname, name, sizeof aname); sg->name = au(aname); - if (lock && !get_native_path(ctx, lock, nativepath)) { - struct zfile *zf = zfile_fopen(nativepath, _T("rb")); - if (zf) { - file = zfile_getdata(zf, 0, -1, &filelen); - zfile_fclose(zf); - + if (!lock) { + _tcscpy(nativepath, currprefs.mountconfig[0].ci.rootdir); + _tcscat(nativepath, sg->name); + } else { + get_native_path(ctx, lock, nativepath); + } + struct zfile *zf = zfile_fopen(nativepath, _T("rb")); + if (zf) { + file = zfile_getdata(zf, 0, -1, &filelen); + zfile_fclose(zf); + } + _tcscat(nativepath, _T(".dbg")); + zf = zfile_fopen(nativepath, _T("rb")); + if (zf) { + symfile = zfile_getdata(zf, 0, -1, &symfilelen); + zfile_fclose(zf); + } + if (file) { + uae_u32 v = gl(file); + if (v == 0x7f454c46) { + // elf + elffile = true; + } else if (v == 0x000003f3) { + // hunk + if (gl(file + 4) == 0x0) { + int hunks = gl(file + 8); + fileoffset = 5 * 4 + hunks * 4; + } + } else { + xfree(file); + file = NULL; } - while (file) { - if (gl(file) != 0x03f3) - break; - if (gl(file + 4) != 0x0) - break; - int hunks = gl(file + 8); - hasfile = true; - fileoffset = 5 * 4 + hunks * 4; - break; + } + if (symfile) { + uae_u32 v = gl(symfile); + if (v == 0x7f454c46) { + elfsymfile = true; + } else { + xfree(symfile); + symfile = NULL; } } console_out_f(_T("Name '%s', native path '%s'\n"), sg->name, nativepath[0] ? nativepath : _T("")); } else { sg->name = my_strdup(_T("")); } + + if (elfsymfile) { + loadelffile(symfile, symfilelen, seg, segmentid, NULL, false); + } else if (elffile) { + loadelffile(file, filelen, seg, segmentid, NULL, false); + } + int parentid = 0; int cnt = 1; seg = seg2; @@ -2074,7 +2857,7 @@ void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock) parentid = dm->id; dm->parentid = dm->id; } - if (hasfile) { + if (file && !elffile) { dm->idtype = gl(&file[fileoffset]); fileoffset += 4; int hunklen = gl(&file[fileoffset]); @@ -2154,7 +2937,9 @@ void debugmem_remsegs(uaecptr seg) } seg = next; } - console_out_f(_T("Freeing segment %08x...\n"), seg); + + console_out_f(_T("Freeing segment %08x...\n"), seg2); + struct debugmemallocs *nextavail = NULL; for (int i = 0; i < MAX_DEBUGMEMALLOCS; i++) { struct debugmemallocs *alloc = allocs[i]; @@ -2164,6 +2949,7 @@ void debugmem_remsegs(uaecptr seg) nextavail = alloc; } } + struct debugsegtracker *sg = NULL; for (int i = 0; i < MAX_DEBUGSEGS; i++) { if (dsegt[i]->allocid == parentid) { @@ -2173,6 +2959,14 @@ void debugmem_remsegs(uaecptr seg) break; } } + + for (int i = 0; i < symbolcnt; i++) { + struct debugsymbol *ds = symbols[i]; + if (ds->segment == parentid) { + ds->allocid = 0; + } + } + if (!sg) { return; } @@ -2195,53 +2989,174 @@ static void allocate_stackframebuffers(void) stackframecntsuper = 0; } -void debugmem_init(void) +#if 0 +void debugmem_add_seglist(TrapContext *ctx, uaecptr segList, uaecptr aname) { - debug_waiting = false; - if (!debugmem_bank.baseaddr) { - int size = 0x10000000; - for (uae_u32 mem = 0x70000000; mem < 0xf0000000; mem += size) { - if (get_mem_bank_real(mem) == &dummy_bank && get_mem_bank_real(mem + size - 65536) == &dummy_bank) { - debugmem_bank.reserved_size = size; - debugmem_bank.mask = debugmem_bank.reserved_size - 1; - debugmem_bank.start = mem; - if (!mapped_malloc(&debugmem_bank)) { - console_out_f(_T("Failed to automatically allocate debugmem (mapped_malloc)!\n")); - return; + int rnd = 0; + if (!debugmem_initialized) { + debugmem_init(false); + } + for (;;) { + if (segtrackerindex >= MAX_DEBUGSEGS) { + segtrackerindex = 0; + rnd++; + if (rnd > 1) + return; + } else { + segtrackerindex++; + } + struct debugsegtracker *st = dsegt[segtrackermax]; + if (!st->allocid) { + uae_char name[256]; + strcpyah_safe(name, aname, sizeof name); + st->name = au(name); + st->resident = mod; + st->allocid = segtrackerindex; + if (segtrackerindex > segtrackermax) + segtrackermax = segtrackerindex; + return; + } + } +} +void debugmem_rem_seglist(TrapContext *ctx, uaecptr segList) +{ + for (int i = 0; i < segtrackermax; i++) { + struct debugsegtracker *st = dsegt[i]; + if (st->resident == mod) { + for (int j = 0; j < MAX_DEBUGMEMALLOCS; j++) { + struct debugmemallocs *dm = allocs[j]; + if (dm->parentid == st->allocid) { + dm->id = 0; + if (segtrackerindex >= j) + segtrackerindex = j - 1; } - map_banks(&debugmem_bank, debugmem_bank.start >> 16, debugmem_bank.allocated_size >> 16, 0); - console_out_f(_T("Automatically allocated debugmem location: %08x - %08x %08x\n"), - debugmem_bank.start, debugmem_bank.start + debugmem_bank.allocated_size - 1, debugmem_bank.allocated_size); - break; } } - if (!debugmem_bank.baseaddr) { - console_out_f(_T("Failed to automatically allocate debugmem (no space)!\n")); + } +} + +void debugmem_add_segment(uaecptr mod, uae_u32 num, uae_u32 type, uaecptr start, uae_u32 size) +{ + struct debugsegtracker *st = NULL; + for (int i = 0; i < segtrackermax; i++) { + if (dsegt[i]->resident == mod) { + st = dsegt[i]; + break; + } + } + if (!st) + return; + struct debugmemallocs *dm = getallocblock(); + if (!dm) + return; + dm->parentid = st->allocid; + dm->internalid = num; + dm->type = type; + dm->start = start; + dm->size = size; +} +void debugmem_rem_segment(uaecptr mod, uaecptr start) +{ + struct debugsegtracker *st = NULL; + for (int i = 0; i < segtrackermax; i++) { + if (dsegt[i]->resident == mod) { + st = dsegt[i]; + break; + } + } + if (!st) + return; + for (int j = 0; j < MAX_DEBUGMEMALLOCS; j++) { + struct debugmemallocs *dm = allocs[j]; + if (start >= dm->start && start < dm->start + dm->size) { + dm->id = 0; + for (int j = 0; j < MAX_DEBUGSYMS; j++) { + struct debugsymbol *ds = symbols[j]; + if (ds->allocid && dm->start <= ds->value && dm->start + dm->size >= ds->value) { + ds->allocid = 0; + } + } + symbolindex = 0; + } + } +} +void debugmem_add_symbol(uae_u32 value, uaecptr aname) +{ + int rnd = 0; + for (;;) { + if (symbolindex >= MAX_DEBUGSYMS) { + symbolindex = 0; + rnd++; + if (rnd > 1) + return; + } else { + symbolindex++; + } + struct debugsymbol *ds = symbols[symbolindex]; + if (ds->allocid == 0) { + uae_char name[256]; + strcpyah_safe(name, aname, sizeof name); + ds->allocid = symbolindex; + ds->value = value; + ds->name = au(name); + ds->type = SYMBOL_GLOBAL; + if (symbolindex > symbolcnt) + symbolcnt = symbolindex; return; } } - memset(debugmem_bank.baseaddr, 0xa5, debugmem_bank.allocated_size); - if (!debugmem_func_lgeti) { - - debugmem_func_lgeti = debugmem_bank.lgeti; - debugmem_func_wgeti = debugmem_bank.wgeti; - debugmem_func_lget = debugmem_bank.lget; - debugmem_func_wget = debugmem_bank.wget; - debugmem_func_bget = debugmem_bank.bget; - debugmem_func_lput = debugmem_bank.lput; - debugmem_func_wput = debugmem_bank.wput; - debugmem_func_bput = debugmem_bank.bput; - debugmem_func_xlate = debugmem_bank.xlateaddr; - - debugmem_bank.lgeti = debugmem_lgeti; - debugmem_bank.wgeti = debugmem_wgeti; - debugmem_bank.lget = debugmem_lget; - debugmem_bank.wget = debugmem_wget; - debugmem_bank.bget = debugmem_bget; - debugmem_bank.lput = debugmem_lput; - debugmem_bank.wput = debugmem_wput; - debugmem_bank.bput = debugmem_bput; - debugmem_bank.xlateaddr = debugmem_xlate; +} +#endif + +void debugmem_init(bool initmem) +{ + debug_waiting = false; + if (initmem) { + if (!debugmem_bank.baseaddr) { + int size = 0x10000000; + for (uae_u32 mem = 0x70000000; mem < 0xf0000000; mem += size) { + if (get_mem_bank_real(mem) == &dummy_bank && get_mem_bank_real(mem + size - 65536) == &dummy_bank) { + debugmem_bank.reserved_size = size; + debugmem_bank.mask = debugmem_bank.reserved_size - 1; + debugmem_bank.start = mem; + if (!mapped_malloc(&debugmem_bank)) { + console_out_f(_T("Failed to automatically allocate debugmem (mapped_malloc)!\n")); + return; + } + map_banks(&debugmem_bank, debugmem_bank.start >> 16, debugmem_bank.allocated_size >> 16, 0); + console_out_f(_T("Automatically allocated debugmem location: %08x - %08x %08x\n"), + debugmem_bank.start, debugmem_bank.start + debugmem_bank.allocated_size - 1, debugmem_bank.allocated_size); + break; + } + } + if (!debugmem_bank.baseaddr) { + console_out_f(_T("Failed to automatically allocate debugmem (no space)!\n")); + return; + } + } + memset(debugmem_bank.baseaddr, 0xa5, debugmem_bank.allocated_size); + if (!debugmem_func_lgeti) { + + debugmem_func_lgeti = debugmem_bank.lgeti; + debugmem_func_wgeti = debugmem_bank.wgeti; + debugmem_func_lget = debugmem_bank.lget; + debugmem_func_wget = debugmem_bank.wget; + debugmem_func_bget = debugmem_bank.bget; + debugmem_func_lput = debugmem_bank.lput; + debugmem_func_wput = debugmem_bank.wput; + debugmem_func_bput = debugmem_bank.bput; + debugmem_func_xlate = debugmem_bank.xlateaddr; + + debugmem_bank.lgeti = debugmem_lgeti; + debugmem_bank.wgeti = debugmem_wgeti; + debugmem_bank.lget = debugmem_lget; + debugmem_bank.wget = debugmem_wget; + debugmem_bank.bget = debugmem_bget; + debugmem_bank.lput = debugmem_lput; + debugmem_bank.wput = debugmem_wput; + debugmem_bank.bput = debugmem_bput; + debugmem_bank.xlateaddr = debugmem_xlate; + } } alloccnt = 0; if (!allocs) { @@ -2320,8 +3235,10 @@ void debugmem_init(void) linemapsize = 0; codefilecnt = 0; symbolcnt = 0; + symbolindex = 0; executable_last_segment = 0; segtrackermax = 0; + segtrackerindex = 0; debugmem_initialized = true; debugmem_chiplimit = 0x400; debugstack_word_state = 0; @@ -2416,14 +3333,14 @@ bool debugmem_get_symbol_value(const TCHAR *name, uae_u32 *valp) } for (int i = 0; i < symbolcnt; i++) { struct debugsymbol *ds = symbols[i]; - if (!_tcscmp(ds->name, name)) { + if (ds->allocid && !_tcscmp(ds->name, name)) { *valp = ds->value; return true; } } for (int i = 0; i < symbolcnt; i++) { struct debugsymbol *ds = symbols[i]; - if (!_tcsicmp(ds->name, name)) { + if (ds->allocid && !_tcsicmp(ds->name, name)) { *valp = ds->value; return true; } @@ -2438,7 +3355,7 @@ int debugmem_get_symbol(uaecptr addr, TCHAR *out, int maxsize) int found = 0; for (int i = 0; i < symbolcnt; i++) { struct debugsymbol *ds = symbols[i]; - if (ds->value == addr) { + if (ds->allocid && ds->value == addr) { if (out) { TCHAR txt[256]; _tcscpy(txt, ds->name); @@ -2531,7 +3448,10 @@ int debugmem_get_sourceline(uaecptr addr, TCHAR *out, int maxsize) break; } struct debugcodefile *cf = lm->file; - if (cf->lineptr[line] && cf->lineptr[line][0]) { + if (!cf->data) { + loadcodefiledata(cf); + } + if (cf->data && cf->lineptr[line] && cf->lineptr[line][0]) { if (last_codefile != cf) { TCHAR txt[256]; last_codefile = cf; @@ -2769,3 +3689,52 @@ bool debugmem_illg(uae_u16 opcode) debugmem_break(12); return true; } + +static const uae_u8 romend[20] = { + 0x00, 0x08, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x1d, 0x00, 0x1e, 0x00, 0x1f +}; + +struct zfile *read_executable_rom(struct zfile *z, int size, int maxblocks) +{ + int len, outlen; + uae_u8 *out; + uae_u8 *file = zfile_getdata(z, 0, -1, &len); + if (!file) + return NULL; + if (!debugmem_initialized) + debugmem_init(false); + if (!debugmem_initialized) + return NULL; + uae_u8 header[8] = { 0 }; + zfile_fseek(z, 0, SEEK_SET); + zfile_fread(header, 1, sizeof(header), z); + zfile_fseek(z, 0, SEEK_SET); + if (header[0] == 0x7f) + out = loadelffile(file, len, 0, -1, &outlen, true); + else + out = loadhunkfile(file, len, 0, -1, &outlen, true); + if (out) { + if (outlen > size * maxblocks) { + write_log(_T("read_executable_rom '%s' size %d larger than max %d\n"), zfile_getname(z), outlen, size); + xfree(out); + return NULL; + } + int romsize = ((outlen + size - 1) / size) * size; + uae_u8 *temp = xcalloc(uae_u8, romsize); + memcpy(temp, out, outlen); + if (outlen < romsize && romsize == 524288) { + if (outlen < size - 16) { + memcpy(temp + size - 20, romend, sizeof(romend)); + } + kickstart_fix_checksum(temp, size); + } + struct zfile *zo = zfile_fopen_empty(NULL, zfile_getname(z), romsize); + zfile_fwrite(temp, 1, romsize, zo); + zfile_fseek(zo, 0, SEEK_SET); + write_log(_T("read_executable_rom loaded '%s' size %d -> %d\n"), zfile_getname(z), outlen, romsize); + return zo; + } + xfree(file); + return NULL; +} diff --git a/filesys.cpp b/filesys.cpp index 28ddc167..447e1ead 100644 --- a/filesys.cpp +++ b/filesys.cpp @@ -8965,10 +8965,11 @@ static uae_u32 REGPARAM2 mousehack_done (TrapContext *ctx) debugmem_break(8); return 1; } else if (mode == 202) { - // a0 = segment, a1 = name, d2 = lock - debugmem_addsegs(ctx, trap_get_areg(ctx, 0), trap_get_areg(ctx, 1), trap_get_dreg(ctx, 2)); + // a0 = seglist, a1 = name, d2 = lock + debugmem_addsegs(ctx, trap_get_areg(ctx, 0), trap_get_areg(ctx, 1), trap_get_dreg(ctx, 2), true); return 1; } else if (mode == 203) { + // a0 = seglist debugmem_remsegs(trap_get_areg(ctx, 0)); return 1; } else if (mode == 204 || mode == 206) { @@ -8994,6 +8995,14 @@ static uae_u32 REGPARAM2 mousehack_done (TrapContext *ctx) } else if (mode == 210) { // debug trapcode debugmem_trap(trap_get_areg(ctx, 0)); + } else if (mode == 212) { + // a0 = seglist, a1 = name, d2 = lock + debugmem_addsegs(ctx, trap_get_areg(ctx, 0), trap_get_areg(ctx, 1), trap_get_dreg(ctx, 2), false); + return 1; + } else if (mode == 213) { + // a0 = seglist + debugmem_remsegs(trap_get_areg(ctx, 0)); + return 1; } else if (mode == 299) { return debugmem_exit(); diff --git a/include/debug.h b/include/debug.h index 725579be..57ace369 100644 --- a/include/debug.h +++ b/include/debug.h @@ -60,6 +60,10 @@ extern int debug_write_memory_8 (uaecptr addr, uae_u8 v); extern bool debug_enforcer(void); extern int debug_safe_addr(uaecptr addr, int size); +extern void debug_init_trainer(const TCHAR*); +extern void debug_trainer_match(void); +extern bool debug_opcode_watch; + #define BREAKPOINT_TOTAL 20 #define BREAKPOINT_REG_Dx 0 #define BREAKPOINT_REG_Ax 8 diff --git a/include/debugmem.h b/include/debugmem.h index 25a63305..4fc3be47 100644 --- a/include/debugmem.h +++ b/include/debugmem.h @@ -1,10 +1,10 @@ uaecptr debugmem_reloc(uaecptr exeaddress, uae_u32 len, uaecptr task, uae_u32 *stack); -void debugmem_init(void); +void debugmem_init(bool); uaecptr debugmem_allocmem(int mode, uae_u32 size, uae_u32 flags, uae_u32 caller); uae_u32 debugmem_freemem(int mode, uaecptr addr, uae_u32 size, uae_u32 caller); void debugmem_trap(uaecptr addr); -void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock); +void debugmem_addsegs(TrapContext *ctx, uaecptr seg, uaecptr name, uae_u32 lock, bool residentonly); void debugmem_remsegs(uaecptr seg); uae_u32 debugmem_exit(void); bool debugmem_break(int); diff --git a/include/options.h b/include/options.h index e5023aef..f55618d3 100644 --- a/include/options.h +++ b/include/options.h @@ -685,6 +685,7 @@ struct uae_prefs { TCHAR quitstatefile[MAX_DPATH]; TCHAR statefile[MAX_DPATH]; TCHAR inprecfile[MAX_DPATH]; + TCHAR trainerfile[MAX_DPATH]; bool inprec_autoplay; bool refresh_indicator; diff --git a/newcpu.cpp b/newcpu.cpp index d2f5ca7c..57ce33e2 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -2378,7 +2378,7 @@ static uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHA return addr; } -static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode) +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; @@ -3953,6 +3953,7 @@ static void m68k_reset2(bool hardreset) } // regs.ce020memcycles = 0; regs.ce020startcycle = regs.ce020endcycle = 0; + fill_prefetch (); } @@ -4020,6 +4021,7 @@ static void cpu_do_fallback(void) fallback_cpu_model = 0; } init_m68k(); + build_cpufunctbl(); m68k_reset2(false); if (!fallbackmode) { // restore original 68020+ @@ -5088,6 +5090,9 @@ static void m68k_run_1 (void) //write_log (_T("%08X-%04X "), pc, r->opcode); } #endif + if (debug_opcode_watch) { + debug_trainer_match(); + } do_cycles (cpu_cycles); r->instruction_pc = m68k_getpc (); cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode); @@ -5193,6 +5198,10 @@ static void m68k_run_1_ce (void) inprec_playdebug_cpu (1); } + if (debug_opcode_watch) { + debug_trainer_match(); + } + r->instruction_pc = m68k_getpc (); (*cpufunctbl[r->opcode])(r->opcode); wait_memory_cycles(); @@ -6039,6 +6048,10 @@ static void m68k_run_3ce (void) if (regs.cacr & 0x8000) fill_icache040(r->instruction_pc + 16); + if (debug_opcode_watch) { + debug_trainer_match(); + } + (*cpufunctbl[r->opcode])(r->opcode); if (r->spcflags) { @@ -6080,6 +6093,10 @@ static void m68k_run_3p(void) if (regs.cacr & 0x8000) fill_icache040(r->instruction_pc + 16); + if (debug_opcode_watch) { + debug_trainer_match(); + } + (*cpufunctbl[r->opcode])(r->opcode); cpu_cycles = 1 * CYCLE_UNIT; @@ -6215,6 +6232,10 @@ static void m68k_run_2ce (void) inprec_playdebug_cpu (1); } + if (debug_opcode_watch) { + debug_trainer_match(); + } + (*cpufunctbl[r->opcode])(r->opcode); wait_memory_cycles(); @@ -6337,6 +6358,10 @@ static void m68k_run_2p (void) inprec_playdebug_cpu (1); } + if (debug_opcode_watch) { + debug_trainer_match(); + } + if (cpu_cycles > 0) x_do_cycles(cpu_cycles); @@ -6436,6 +6461,9 @@ static void m68k_run_2 (void) r->opcode = x_get_iword(0); count_instr (r->opcode); + if (debug_opcode_watch) { + debug_trainer_match(); + } do_cycles (cpu_cycles); cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode); @@ -6616,6 +6644,9 @@ void m68k_go (int may_quit) if (changed_prefs.inprecfile[0] && input_record) inprec_prepare_record (savestate_fname[0] ? savestate_fname : NULL); + if (changed_prefs.trainerfile[0]) + debug_init_trainer(changed_prefs.trainerfile); + set_cpu_tracer (false); #ifdef DEBUGGER @@ -7704,17 +7735,17 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn } else if (lookup->mnemo == i_MVMEL) { uae_u16 mask = extra; pc += 2; - pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); + 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(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); + 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(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); + 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); @@ -7726,13 +7757,13 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn TCHAR *p; pc += 2; if (!(extra & 0x0800)) { - pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); + 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(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); + 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 || @@ -7747,7 +7778,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn reg = (extra >> 12) & 7; if (lookup->mnemo == i_BFINS) _stprintf(p, _T("D%d,"), reg); - pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); _tcscat(instrname, _T(" {")); p = instrname + _tcslen(instrname); if (extra & 0x0800) @@ -7839,9 +7870,9 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn else movemout(instrname, regmask, dp->dmode, fpmode, false); _tcscat(instrname, _T(",")); - pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); + pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); } else { - pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); + 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); @@ -7861,7 +7892,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn _tcscat(instrname, _T(" ")); p = instrname + _tcslen(instrname); _stprintf(p, _T("FP%d,"), (extra >> 7) & 7); - pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode); + 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)); @@ -7875,7 +7906,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn _tcscat(instrname, _T(".")); _tcscat(instrname, fpsizes[size]); _tcscat(instrname, _T(" ")); - pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode); + 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); @@ -7893,7 +7924,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn _tcscpy(instrname, _T("A-LINE")); } else { if (dp->suse) { - pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); + 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) { @@ -7912,7 +7943,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn if (dp->suse && dp->duse) _tcscat (instrname, _T(",")); if (dp->duse) { - pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode); + pc = ShowEA (NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode); } } -- 2.47.3