Skip to content

Commit 24a9a2c

Browse files
committed
[fix] Update disassembler to work with 24bit addresses
Fixes #13 Closes #7
1 parent 1175924 commit 24a9a2c

3 files changed

Lines changed: 68 additions & 44 deletions

File tree

roms/multibank.xex

51 Bytes
Binary file not shown.

src/ui/ui_dbg.h

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ typedef struct ui_dbg_state_t {
229229
uint64_t last_tick_pins; // cpu pins in last tick
230230
uint32_t frame_id; // used in trap callback to detect when a new frame has started
231231
uint32_t cur_op_ticks;
232-
uint16_t cur_op_pc; // PC of current instruction
233-
uint16_t stepover_pc;
232+
uint32_t cur_op_pc; // PC of current instruction
233+
uint32_t stepover_pc;
234234
int last_trap_id; // can be used to identify breakpoint which caused trap
235235
int delete_breakpoint_index;
236236
int num_breakpoints;
@@ -306,13 +306,13 @@ typedef struct ui_dbg_heatmap_t {
306306
int scale;
307307
int cur_y;
308308
bool popup_addr_valid;
309-
uint16_t popup_addr;
310-
ui_dbg_heatmapitem_t items[1<<16]; /* execution counter map */
311-
uint32_t pixels[1<<16]; /* execution counters converted to pixel data */
309+
uint32_t popup_addr;
310+
ui_dbg_heatmapitem_t items[1<<24]; /* execution counter map */
311+
uint32_t pixels[1<<24]; /* execution counters converted to pixel data */
312312
} ui_dbg_heatmap_t;
313313

314314
typedef struct ui_dbg_history_t {
315-
uint16_t pc[UI_DBG_NUM_HISTORY_ITEMS];
315+
uint32_t pc[UI_DBG_NUM_HISTORY_ITEMS];
316316
uint16_t pos;
317317
} ui_dbg_history_t;
318318

@@ -434,7 +434,7 @@ static inline uint16_t _ui_dbg_read_word(ui_dbg_t* win, uint32_t addr) {
434434
return (uint16_t) (h<<8)|l;
435435
}
436436

437-
static inline uint16_t _ui_dbg_get_pc(ui_dbg_t* win) {
437+
static inline uint32_t _ui_dbg_get_pc(ui_dbg_t* win) {
438438
return win->dbg.cur_op_pc;
439439
}
440440

@@ -458,7 +458,7 @@ static void _ui_dbg_dasm_out_cb(char c, void* user_data) {
458458
}
459459

460460
// disassemble instruction at address
461-
static inline uint16_t _ui_dbg_disasm(ui_dbg_t* win, uint32_t addr) {
461+
static inline uint32_t _ui_dbg_disasm(ui_dbg_t* win, uint32_t addr) {
462462
memset(&win->dasm_line, 0, sizeof(win->dasm_line));
463463
win->dasm_line.addr = addr;
464464
#if defined(UI_DBG_USE_Z80)
@@ -468,7 +468,7 @@ static inline uint16_t _ui_dbg_disasm(ui_dbg_t* win, uint32_t addr) {
468468
#elif defined(UI_DBG_USE_W65C816S)
469469
w65816dasm_op(addr, w65816_p(win->dbg.w65816) | (w65816_e(win->dbg.w65816) ? W65816_UF : 0), _ui_dbg_dasm_in_cb, _ui_dbg_dasm_out_cb, win);
470470
#endif
471-
uint16_t next_addr = win->dasm_line.addr;
471+
uint32_t next_addr = win->dasm_line.addr;
472472
win->dasm_line.addr = addr;
473473
return next_addr;
474474
}
@@ -594,7 +594,7 @@ static void _ui_dbg_step_into(ui_dbg_t* win) {
594594
static void _ui_dbg_step_over(ui_dbg_t* win) {
595595
win->dbg.stopped = false;
596596
win->ui.request_scroll = true;
597-
uint16_t next_pc = _ui_dbg_disasm(win, _ui_dbg_get_pc(win));
597+
uint32_t next_pc = _ui_dbg_disasm(win, _ui_dbg_get_pc(win));
598598
if (_ui_dbg_is_stepover_op(win->dasm_line.bytes[0])) {
599599
win->dbg.step_mode = UI_DBG_STEPMODE_OVER;
600600
win->dbg.stepover_pc = next_pc;
@@ -618,12 +618,12 @@ static void _ui_dbg_history_reboot(ui_dbg_t* win) {
618618
_ui_dbg_history_reset(win);
619619
}
620620

621-
static void _ui_dbg_history_push(ui_dbg_t* win, uint16_t pc) {
621+
static void _ui_dbg_history_push(ui_dbg_t* win, uint32_t pc) {
622622
win->history.pc[win->history.pos] = pc;
623623
win->history.pos = (win->history.pos + 1) & (UI_DBG_NUM_HISTORY_ITEMS-1);
624624
}
625625

626-
static uint16_t _ui_dbg_history_get(ui_dbg_t* win, uint16_t rel_pos) {
626+
static uint32_t _ui_dbg_history_get(ui_dbg_t* win, uint16_t rel_pos) {
627627
uint16_t index = (win->history.pos - rel_pos - 1) & (UI_DBG_NUM_HISTORY_ITEMS-1);
628628
return win->history.pc[index];
629629
}
@@ -656,7 +656,7 @@ static void _ui_dbg_history_draw(ui_dbg_t* win) {
656656
}
657657

658658
/* get history PC */
659-
uint16_t pc = _ui_dbg_history_get(win, line_i);
659+
uint32_t pc = _ui_dbg_history_get(win, line_i);
660660
uint32_t addr = _ui_dbg_disasm(win, pc);
661661
const int num_bytes = addr - pc;
662662

@@ -687,7 +687,7 @@ static void _ui_dbg_history_draw(ui_dbg_t* win) {
687687
/* tick count */
688688
x += glyph_width * 17;
689689
if (win->ui.show_ticks) {
690-
int ticks = win->heatmap.items[pc].ticks;
690+
int ticks = win->heatmap.items[pc&0xFFFFFF].ticks;
691691
ImGui::SameLine(x);
692692
ImGui::Text("%d", ticks);
693693
}
@@ -734,7 +734,7 @@ static void _ui_dbg_dbgstate_reboot(ui_dbg_t* win) {
734734
}
735735

736736
// evaluate per-opcode breakpoints, called at the start of a new instrucion
737-
static int _ui_dbg_eval_op_breakpoints(ui_dbg_t* win, int trap_id, uint16_t pc) {
737+
static int _ui_dbg_eval_op_breakpoints(ui_dbg_t* win, int trap_id, uint32_t pc) {
738738
if (win->dbg.step_mode != UI_DBG_STEPMODE_NONE) {
739739
switch (win->dbg.step_mode) {
740740
case UI_DBG_STEPMODE_INTO:
@@ -1062,8 +1062,8 @@ static void _ui_dbg_bp_draw(ui_dbg_t* win) {
10621062
ImGui::PopItemWidth();
10631063
if (bt->show_addr) {
10641064
ImGui::SameLine();
1065-
uint16_t old_addr = bp->addr;
1066-
bp->addr = ui_util_input_u16("##addr", old_addr);
1065+
uint32_t old_addr = bp->addr;
1066+
bp->addr = ui_util_input_u24("##addr", old_addr);
10671067
if (upd_val || (old_addr != bp->addr)) {
10681068
/* if breakpoint type or address has changed, update the breakpoint's value from memory */
10691069
switch (bp->type) {
@@ -1188,16 +1188,16 @@ static void _ui_dbg_heatmap_clear_all(ui_dbg_t* win) {
11881188
}
11891189

11901190
static void _ui_dbg_heatmap_clear_rw(ui_dbg_t* win) {
1191-
for (int i = 0; i < (1<<16); i++) {
1191+
for (int i = 0; i < (1<<24); i++) {
11921192
win->heatmap.items[i].state &= ~(UI_DBG_HEATMAP_ITEM_READ|UI_DBG_HEATMAP_ITEM_WRITE);
11931193
}
11941194
}
11951195

1196-
static void _ui_dbg_heatmap_record_op(ui_dbg_t* win, uint16_t pc) {
1196+
static void _ui_dbg_heatmap_record_op(ui_dbg_t* win, uint32_t pc) {
11971197
// record per-op heatmap events
1198-
win->heatmap.items[pc].state |= UI_DBG_HEATMAP_ITEM_OPCODE;
1198+
win->heatmap.items[pc&0xFFFFFF].state |= UI_DBG_HEATMAP_ITEM_OPCODE;
11991199
// update last instruction's ticks
1200-
win->heatmap.items[win->dbg.cur_op_pc].ticks = win->dbg.cur_op_ticks;
1200+
win->heatmap.items[win->dbg.cur_op_pc&0xFFFFFF].ticks = win->dbg.cur_op_ticks;
12011201
}
12021202

12031203
static void _ui_dbg_heatmap_record_tick(ui_dbg_t* win, uint64_t pins) {
@@ -1220,23 +1220,23 @@ static void _ui_dbg_heatmap_record_tick(ui_dbg_t* win, uint64_t pins) {
12201220
const uint32_t addr = W65816_GET_ADDR(pins);
12211221
// FIXME: handle 24-bit address
12221222
if (0 != (pins & W65816_RW)) {
1223-
win->heatmap.items[addr].state |= UI_DBG_HEATMAP_ITEM_READ;
1223+
win->heatmap.items[addr&0xFFFFFF].state |= UI_DBG_HEATMAP_ITEM_READ;
12241224
} else {
1225-
win->heatmap.items[addr].state |= UI_DBG_HEATMAP_ITEM_WRITE;
1225+
win->heatmap.items[addr&0xFFFFFF].state |= UI_DBG_HEATMAP_ITEM_WRITE;
12261226
}
12271227
#endif
12281228
}
12291229

1230-
static inline bool _ui_dbg_heatmap_is_opcode(ui_dbg_t* win, uint16_t addr) {
1231-
return 0 != (win->heatmap.items[addr].state & UI_DBG_HEATMAP_ITEM_OPCODE);
1230+
static inline bool _ui_dbg_heatmap_is_opcode(ui_dbg_t* win, uint32_t addr) {
1231+
return 0 != (win->heatmap.items[addr&0xFFFFFF].state & UI_DBG_HEATMAP_ITEM_OPCODE);
12321232
}
12331233

1234-
static inline bool _ui_dbg_heatmap_is_read(ui_dbg_t* win, uint16_t addr) {
1235-
return 0 != (win->heatmap.items[addr].state & UI_DBG_HEATMAP_ITEM_READ);
1234+
static inline bool _ui_dbg_heatmap_is_read(ui_dbg_t* win, uint32_t addr) {
1235+
return 0 != (win->heatmap.items[addr&0xFFFFFF].state & UI_DBG_HEATMAP_ITEM_READ);
12361236
}
12371237

1238-
static inline bool _ui_dbg_heatmap_is_write(ui_dbg_t* win, uint16_t addr) {
1239-
return 0 != (win->heatmap.items[addr].state & UI_DBG_HEATMAP_ITEM_WRITE);
1238+
static inline bool _ui_dbg_heatmap_is_write(ui_dbg_t* win, uint32_t addr) {
1239+
return 0 != (win->heatmap.items[addr&0xFFFFFF].state & UI_DBG_HEATMAP_ITEM_WRITE);
12401240
}
12411241

12421242
static void _ui_dbg_heatmap_update(ui_dbg_t* win) {
@@ -1251,13 +1251,13 @@ static void _ui_dbg_heatmap_update(ui_dbg_t* win) {
12511251
if (_ui_dbg_get_pc(win) == i) {
12521252
p |= 0xFF00FFFF;
12531253
}
1254-
if (win->heatmap.show_ops && _ui_dbg_heatmap_is_opcode(win, (uint16_t)i)) {
1254+
if (win->heatmap.show_ops && _ui_dbg_heatmap_is_opcode(win, i&0xFFFFFF)) {
12551255
p |= 0xFF0000FF;
12561256
}
1257-
if (win->heatmap.show_writes && _ui_dbg_heatmap_is_write(win, (uint16_t)i)) {
1257+
if (win->heatmap.show_writes && _ui_dbg_heatmap_is_write(win, i&0xFFFFFF)) {
12581258
p |= 0xFF008800;
12591259
}
1260-
if (win->heatmap.show_reads && _ui_dbg_heatmap_is_read(win, (uint16_t)i)) {
1260+
if (win->heatmap.show_reads && _ui_dbg_heatmap_is_read(win, i&0xFFFFFF)) {
12611261
p |= 0xFF880000;
12621262
}
12631263
win->heatmap.pixels[i] = p;
@@ -1328,7 +1328,7 @@ static void _ui_dbg_heatmap_draw(ui_dbg_t* win) {
13281328
if (_ui_dbg_heatmap_is_opcode(win, addr)) {
13291329
_ui_dbg_disasm(win, addr);
13301330
ImGui::SetTooltip("%04X: %s (ticks: %d)\n(right-click for options)",
1331-
addr, win->dasm_line.chars, hm->items[addr].ticks);
1331+
addr, win->dasm_line.chars, hm->items[addr&0xFFFFFF].ticks);
13321332
} else {
13331333
ImGui::SetTooltip("%04X: %02X %02X %02X %02X\n(right-click for options)", addr,
13341334
_ui_dbg_read_byte(win, addr),
@@ -1771,8 +1771,8 @@ typedef struct {
17711771

17721772
static _ui_dbg_disasm_backscan_result_t _ui_dbg_disasm_backscan(ui_dbg_t* win, uint32_t addr) {
17731773
bool is_known_op = false;
1774-
uint16_t bs_addr = addr - 1;
1775-
uint16_t scan_addr = bs_addr;
1774+
uint32_t bs_addr = addr - 1;
1775+
uint32_t scan_addr = bs_addr;
17761776
for (int i = 0; i < 4; i++, scan_addr--) {
17771777
if (_ui_dbg_heatmap_is_opcode(win, scan_addr)) {
17781778
// Z80: prefixed instruction?
@@ -1810,7 +1810,7 @@ static void _ui_dbg_update_line_array(ui_dbg_t* win, uint32_t addr) {
18101810
/* one half is backtraced from current PC, the other half is
18111811
'forward tracked' from current PC
18121812
*/
1813-
uint16_t bs_addr = addr;
1813+
uint32_t bs_addr = addr;
18141814
int line_idx;
18151815
for (line_idx = 0; line_idx < UI_DBG_NUM_BACKTRACE_LINES; line_idx++) {
18161816
// scan backwards for op start in blocks of 4 bytes (== max length of an instruction)
@@ -1835,8 +1835,8 @@ static void _ui_dbg_update_line_array(ui_dbg_t* win, uint32_t addr) {
18351835
executed before.
18361836
*/
18371837
static bool _ui_dbg_addr_inside_line_array(ui_dbg_t* win, uint32_t addr) {
1838-
uint16_t first_addr = win->ui.line_array[UI_DBG_NUM_BACKTRACE_LINES].addr;
1839-
uint16_t last_addr = win->ui.line_array[UI_DBG_NUM_LINES-16].addr;
1838+
uint32_t first_addr = win->ui.line_array[UI_DBG_NUM_BACKTRACE_LINES].addr;
1839+
uint32_t last_addr = win->ui.line_array[UI_DBG_NUM_LINES-16].addr;
18401840
if (first_addr == last_addr) {
18411841
return false;
18421842
} else if (first_addr < last_addr) {
@@ -1886,7 +1886,7 @@ static void _ui_dbg_draw_main(ui_dbg_t* win) {
18861886
const ImU32 ctrlflow_color = 0x44888888;
18871887

18881888
/* update the line array if PC is outside or its content has become outdated */
1889-
const uint16_t pc = _ui_dbg_get_pc(win);
1889+
const uint32_t pc = _ui_dbg_get_pc(win);
18901890
bool force_scroll = false;
18911891
if (_ui_dbg_line_array_needs_update(win, pc)) {
18921892
_ui_dbg_update_line_array(win, pc);
@@ -1925,7 +1925,7 @@ static void _ui_dbg_draw_main(ui_dbg_t* win) {
19251925
uint32_t addr = win->ui.line_array[line_i].addr;
19261926
bool is_pc_line = (addr == pc);
19271927
bool show_dasm = (line_i >= UI_DBG_NUM_BACKTRACE_LINES) || _ui_dbg_heatmap_is_opcode(win, addr);
1928-
const uint16_t start_addr = addr;
1928+
const uint32_t start_addr = addr;
19291929
if (show_dasm) {
19301930
addr = _ui_dbg_disasm(win, addr);
19311931
} else {
@@ -2017,7 +2017,7 @@ static void _ui_dbg_draw_main(ui_dbg_t* win) {
20172017
/* tick count */
20182018
x += glyph_width * (is_pc_line ? 18:20);
20192019
if (win->ui.show_ticks) {
2020-
int ticks = win->heatmap.items[start_addr].ticks;
2020+
int ticks = win->heatmap.items[start_addr&0xFFFFFF].ticks;
20212021
ImGui::SameLine(x);
20222022
if (ticks > 0) {
20232023
if (is_pc_line) {
@@ -2148,13 +2148,15 @@ void ui_dbg_tick(ui_dbg_t* win, uint64_t pins) {
21482148
// evaluate per-op breakpoints
21492149
#if defined(UI_DBG_USE_M6502)
21502150
const bool new_op = pins & M6502_SYNC;
2151+
const uint16_t pc = pins & 0xFFFF;
21512152
#elif defined(UI_DBG_USE_W65C816S)
21522153
const bool new_op = (pins & W65816_VPA) && (pins & W65816_VDA);
2154+
const uint32_t pc = W65816_GET_ADDR(pins);
21532155
#elif defined(UI_DBG_USE_Z80)
21542156
const bool new_op = z80_opdone(win->dbg.z80);
2157+
const uint16_t pc = pins & 0xFFFF;
21552158
#endif
21562159
if (new_op) {
2157-
const uint16_t pc = pins & 0xFFFF;
21582160
trap_id = _ui_dbg_eval_op_breakpoints(win, trap_id, pc);
21592161
_ui_dbg_heatmap_record_op(win, pc);
21602162
_ui_dbg_history_push(win, pc);
@@ -2267,7 +2269,7 @@ void ui_dbg_disassemble(ui_dbg_t* win, const ui_dbg_dasm_request_t* request) {
22672269
// NOTE: this code uses the same strategy as _ui_dbg_update_line_array()
22682270
// it will first scan backward and look for known instructions
22692271
// in the heatmap, and then scan forward
2270-
uint16_t bs_addr = request->addr;
2272+
uint32_t bs_addr = request->addr;
22712273
int line_idx = 0;
22722274
// optional backwards scan
22732275
if (request->offset_lines < 0) {
@@ -2295,7 +2297,7 @@ void ui_dbg_disassemble(ui_dbg_t* win, const ui_dbg_dasm_request_t* request) {
22952297
}
22962298
}
22972299

2298-
uint16_t fwd_addr = request->addr;
2300+
uint32_t fwd_addr = request->addr;
22992301
// if the offset is > 0, skip disassembled instructions
23002302
if (request->offset_lines > 0) {
23012303
for (int i = 0; i < request->offset_lines; i++) {

src/ui/ui_util.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ typedef struct {
5656
void (*menu_cb)(void);
5757
} ui_inject_t;
5858

59+
// draw an 24-bit hex text input field
60+
uint32_t ui_util_input_u24(const char* label, uint32_t val);
5961
// draw an 16-bit hex text input field
6062
uint16_t ui_util_input_u16(const char* label, uint16_t val);
6163
// draw an 8-bit hex text input field
@@ -99,6 +101,26 @@ void ui_util_handle_window_open_dirty(const bool* cur_open, bool* last_open);
99101
#define CHIPS_ASSERT(c) assert(c)
100102
#endif
101103

104+
uint32_t ui_util_input_u24(const char* label, uint32_t val) {
105+
char buf[7];
106+
for (int i = 0; i < 6; i++) {
107+
buf[i] = "0123456789ABCDEF"[val>>((5-i)*4) & 0xF];
108+
}
109+
buf[6] = 0;
110+
const int flags = ImGuiInputTextFlags_CharsHexadecimal|
111+
ImGuiInputTextFlags_CharsUppercase|
112+
ImGuiInputTextFlags_EnterReturnsTrue;
113+
ImGui::PushItemWidth(54);
114+
if (ImGui::InputText(label, buf, sizeof(buf), flags)) {
115+
int res;
116+
if (sscanf(buf, "%X", &res) == 1) {
117+
val = (uint32_t) res & 0xFFFFFF;
118+
}
119+
}
120+
ImGui::PopItemWidth();
121+
return val;
122+
}
123+
102124
uint16_t ui_util_input_u16(const char* label, uint16_t val) {
103125
char buf[5];
104126
for (int i = 0; i < 4; i++) {

0 commit comments

Comments
 (0)