| 1 |
namespace eval trace { |
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
set_help_text cpu_trace \ |
| 6 |
{cpu_trace <item>... |
| 7 |
|
| 8 |
Enable CPU instruction/register tracing for the given items. |
| 9 |
<item> can be one of the following: |
| 10 |
"instr": to trace instructions |
| 11 |
<reg>: an 8 or 16 bit register name like 'A', 'B' or 'HL', 'PC' |
| 12 |
the same list of registers as accepted by the 'reg' command |
| 13 |
|
| 14 |
For example execute: |
| 15 |
cpu_trace instr A HL |
| 16 |
to trace the instruction together with the A and HL register. |
| 17 |
|
| 18 |
To disable tracing again execute: |
| 19 |
cpu_trace |
| 20 |
so pass no arguments (no enabled items). |
| 21 |
|
| 22 |
Note this can be expensive and/or can quickly consume a lot of memory. The Z80 (and certainly R800) can execute almost 1 million instructions per second. So it's recommended to only enable those items you need and limit the trace duration to less than a minute. |
| 23 |
} |
| 24 |
set_tabcompletion_proc cpu_trace [namespace code cpu_trace_tab] false |
| 25 |
|
| 26 |
variable cond_id |
| 27 |
variable cpu_trace_list [list] |
| 28 |
|
| 29 |
proc get_allowed_items {} { |
| 30 |
variable allowed_items_cache |
| 31 |
if {![info exists allowed_items_cache]} { |
| 32 |
reg A ; |
| 33 |
set allowed_items_cache [lsort [concat [dict keys $::cpuregs::regB] [dict keys $::cpuregs::regW] "INSTR"]] |
| 34 |
} |
| 35 |
return $allowed_items_cache |
| 36 |
} |
| 37 |
|
| 38 |
proc cpu_trace_tab {args} { |
| 39 |
return [get_allowed_items] |
| 40 |
} |
| 41 |
|
| 42 |
proc cpu_trace {args} { |
| 43 |
set allowed_items [get_allowed_items] |
| 44 |
foreach i $args { |
| 45 |
if {[string toupper $i] ni $allowed_items} { |
| 46 |
error "Invalid value for cpu_trace: $i, must be one of $allowed_items" |
| 47 |
} |
| 48 |
} |
| 49 |
|
| 50 |
variable cpu_trace_list |
| 51 |
set cpu_trace_list $args |
| 52 |
|
| 53 |
variable cond_id |
| 54 |
catch { debug condition remove $cond_id } |
| 55 |
if {[llength $cpu_trace_list] != 0} { |
| 56 |
set cond_id [debug condition create -command [namespace code do_cpu_trace]] |
| 57 |
} |
| 58 |
|
| 59 |
foreach e $cpu_trace_list { |
| 60 |
if {$e eq "instr"} { |
| 61 |
set inst [regsub -all { +} [lindex [debug disasm [reg pc]] 0] { }] |
| 62 |
debug trace add $e $inst -type string -description "CPU instructions" |
| 63 |
} else { |
| 64 |
debug trace add $e [reg $e] -type int -format hex -description "CPU register $e" |
| 65 |
} |
| 66 |
} |
| 67 |
} |
| 68 |
namespace export cpu_trace |
| 69 |
|
| 70 |
proc do_cpu_trace {} { |
| 71 |
variable cpu_trace_list |
| 72 |
foreach e $cpu_trace_list { |
| 73 |
if {$e eq "instr"} { |
| 74 |
set inst [regsub -all { +} [lindex [debug disasm [reg pc]] 0] { }] |
| 75 |
debug trace add $e $inst |
| 76 |
} else { |
| 77 |
debug trace add $e -merge [reg $e] |
| 78 |
} |
| 79 |
} |
| 80 |
} |
| 81 |
|
| 82 |
} ; |
| 83 |
|
| 84 |
namespace import trace::* |