Mercurial > repos > blastem
comparison z80_to_x86.c @ 2400:c97609fe8315
Implement watchpoints in Z80 debugger
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 23 Dec 2023 23:03:31 -0800 |
parents | 3e591869d135 |
children | ed7b4d869989 |
comparison
equal
deleted
inserted
replaced
2399:68eba54b60f7 | 2400:c97609fe8315 |
---|---|
3199 options->gen.address_size = SZ_W; | 3199 options->gen.address_size = SZ_W; |
3200 options->gen.address_mask = 0xFFFF; | 3200 options->gen.address_mask = 0xFFFF; |
3201 options->gen.max_address = 0x10000; | 3201 options->gen.max_address = 0x10000; |
3202 options->gen.bus_cycles = 3; | 3202 options->gen.bus_cycles = 3; |
3203 options->gen.clock_divider = clock_divider; | 3203 options->gen.clock_divider = clock_divider; |
3204 options->gen.watchpoint_range_off = offsetof(z80_context, watchpoint_min); | |
3204 options->gen.mem_ptr_off = offsetof(z80_context, mem_pointers); | 3205 options->gen.mem_ptr_off = offsetof(z80_context, mem_pointers); |
3205 options->gen.ram_flags_off = offsetof(z80_context, ram_code_flags); | 3206 options->gen.ram_flags_off = offsetof(z80_context, ram_code_flags); |
3206 options->gen.ram_flags_shift = 7; | 3207 options->gen.ram_flags_shift = 7; |
3207 | 3208 |
3208 options->flags = 0; | 3209 options->flags = 0; |
3864 if (native) { | 3865 if (native) { |
3865 zbreakpoint_patch(context, address, native); | 3866 zbreakpoint_patch(context, address, native); |
3866 } | 3867 } |
3867 } | 3868 } |
3868 } | 3869 } |
3869 | |
3870 void zremove_breakpoint(z80_context * context, uint16_t address) | 3870 void zremove_breakpoint(z80_context * context, uint16_t address) |
3871 { | 3871 { |
3872 context->breakpoint_flags[address / 8] &= ~(1 << (address % 8)); | 3872 context->breakpoint_flags[address / 8] &= ~(1 << (address % 8)); |
3873 uint8_t * native = z80_get_native_address(context, address); | 3873 uint8_t * native = z80_get_native_address(context, address); |
3874 if (native) { | 3874 if (native) { |
3876 code_info tmp_code = opts->gen.code; | 3876 code_info tmp_code = opts->gen.code; |
3877 opts->gen.code.cur = native; | 3877 opts->gen.code.cur = native; |
3878 opts->gen.code.last = native + 128; | 3878 opts->gen.code.last = native + 128; |
3879 check_cycles_int(&opts->gen, address); | 3879 check_cycles_int(&opts->gen, address); |
3880 opts->gen.code = tmp_code; | 3880 opts->gen.code = tmp_code; |
3881 } | |
3882 } | |
3883 | |
3884 static void *z80_watchpoint_check(uint32_t address, void *vcontext, uint8_t value) | |
3885 { | |
3886 z80_context *context = vcontext; | |
3887 z80_watchpoint *watch = NULL; | |
3888 address &= 0xFFFF; | |
3889 for (uint32_t i = 0; i < context->num_watchpoints; i++) | |
3890 { | |
3891 if (address >= context->watchpoints[i].start && address <= context->watchpoints[i].end) { | |
3892 watch = context->watchpoints + i; | |
3893 break; | |
3894 } | |
3895 } | |
3896 if (!watch) { | |
3897 return vcontext; | |
3898 } | |
3899 if (watch->check_change) { | |
3900 uint8_t old = read_byte(address, (void **)context->mem_pointers, &context->options->gen, context); | |
3901 if (old == value) { | |
3902 return vcontext; | |
3903 } | |
3904 context->wp_old_value = old; | |
3905 } else { | |
3906 context->wp_old_value = value; | |
3907 } | |
3908 context->wp_hit_address = address; | |
3909 context->wp_hit_value = value; | |
3910 context->wp_hit = 1; | |
3911 context->target_cycle = context->sync_cycle = context->current_cycle; | |
3912 system_header *system = context->system; | |
3913 system->enter_debugger = 1; | |
3914 return vcontext; | |
3915 } | |
3916 | |
3917 static void z80_enable_watchpoints(z80_context *context) | |
3918 { | |
3919 if (context->options->gen.check_watchpoints_8) { | |
3920 //already enabled | |
3921 return; | |
3922 } | |
3923 context->watchpoint_min = 0xFFFF; | |
3924 context->watchpoint_max = 0; | |
3925 context->options->gen.check_watchpoints_8 = z80_watchpoint_check; | |
3926 //re-generate write handlers with watchpoints enabled | |
3927 code_ptr new_write8 = gen_mem_fun(&context->options->gen, context->options->gen.memmap, context->options->gen.memmap_chunks, WRITE_8, NULL); | |
3928 | |
3929 //patch old write handlers to point to the new ones | |
3930 code_info code = { | |
3931 .cur = context->options->write_8, | |
3932 .last = context->options->write_8 + 256 | |
3933 }; | |
3934 jmp(&code, new_write8); | |
3935 context->options->write_8 = new_write8; | |
3936 } | |
3937 | |
3938 void z80_add_watchpoint(z80_context *context, uint16_t address, uint16_t size) | |
3939 { | |
3940 uint32_t end = address + size - 1; | |
3941 for (uint32_t i = 0; i < context->num_watchpoints; i++) | |
3942 { | |
3943 if (context->watchpoints[i].start == address && context->watchpoints[i].end == end) { | |
3944 return; | |
3945 } | |
3946 } | |
3947 z80_enable_watchpoints(context); | |
3948 if (context->wp_storage == context->num_watchpoints) { | |
3949 context->wp_storage = context->wp_storage ? context->wp_storage * 2 : 4; | |
3950 context->watchpoints = realloc(context->watchpoints, context->wp_storage * sizeof(z80_watchpoint)); | |
3951 } | |
3952 const memmap_chunk *chunk = find_map_chunk(address, &context->options->gen, 0, NULL); | |
3953 context->watchpoints[context->num_watchpoints++] = (z80_watchpoint){ | |
3954 .start = address, | |
3955 .end = end, | |
3956 .check_change = chunk && (chunk->flags & MMAP_READ) | |
3957 }; | |
3958 if (context->watchpoint_min > address) { | |
3959 context->watchpoint_min = address; | |
3960 } | |
3961 if (context->watchpoint_max < end) { | |
3962 context->watchpoint_max = end; | |
3963 } | |
3964 } | |
3965 | |
3966 void z80_remove_watchpoint(z80_context *context, uint32_t address, uint32_t size) | |
3967 { | |
3968 uint32_t end = address + size - 1; | |
3969 for (uint32_t i = 0; i < context->num_watchpoints; i++) | |
3970 { | |
3971 if (context->watchpoints[i].start == address && context->watchpoints[i].end == end) { | |
3972 context->watchpoints[i] = context->watchpoints[context->num_watchpoints-1]; | |
3973 context->num_watchpoints--; | |
3974 return; | |
3975 } | |
3881 } | 3976 } |
3882 } | 3977 } |
3883 | 3978 |
3884 void z80_serialize(z80_context *context, serialize_buffer *buf) | 3979 void z80_serialize(z80_context *context, serialize_buffer *buf) |
3885 { | 3980 { |