From a73ead1c1ab4651e1ffc33ffdaf34a51c1896c8b Mon Sep 17 00:00:00 2001 From: Thomas Eberhardt Date: Fri, 13 Dec 2024 19:51:58 +0100 Subject: [PATCH 01/10] hardware breakpoint, ICE argument parsing, exatoi -> strtol 1. Replace exatoi() with strtol() C99 function. Was already used in some places. 2. Remove simutil.[hc] which only contained exatoi(). 3. Add more sim.h configuration checks. 4. Add a hardware breakpoint to the ICE. Currently only works with z80sim. Can be set for read/write/execute trigger with "bh 1234,rwx", cleared with "bhc" and displayed with "bh". 5. Modify software breakpoints to be set by address and not number, i.e. "b 1234[,x]" set/changes breakpoint at address "1234", "bc 1234" removes it. The ICE will complain if there no free slots anymore. 6. Install/uninstall HALT opcodes for software breakpoints before and after cpu_run()/cpu_step() calls, previously the breakpoints would be destroyed by changing memory at breakpoint addresses inside the ICE. 7. Tighten "b" and "h" ICE command syntax. It was not possible to specify a "c" address. Now "bc" clears all software breakpoints, and "b c" sets a software breakpoint at address "c", and "bc c" clears the software breakpoint at address "c". Similar with "hc" and "h c". 8. Parsing clean-ups (?) all over the ICE. --- altairsim/srcsim/Makefile | 4 +- altairsim/srcsim/simcfg.c | 3 +- cpmsim/srcsim/Makefile | 4 +- cromemcosim/srcsim/Makefile | 4 +- cromemcosim/srcsim/simcfg.c | 3 +- imsaisim/srcsim/Makefile | 4 +- imsaisim/srcsim/simcfg.c | 3 +- intelmdssim/srcsim/Makefile | 4 +- mosteksim/srcsim/Makefile | 4 +- picosim/srcsim/CMakeLists.txt | 1 - picosim/srcsim/simcfg.c | 1 - z80core/sim8080.c | 11 + z80core/simdefs.h | 25 +- z80core/simice.c | 682 ++++++++++++++++++++++++---------- z80core/simice.h | 11 +- z80core/simmain.c | 5 +- z80core/simutil.c | 25 -- z80core/simutil.h | 12 - z80core/simz80.c | 11 + z80sim/srcsim/Makefile | 4 +- z80sim/srcsim/sim.h.debug | 1 + z80sim/srcsim/sim.h.fast | 1 + z80sim/srcsim/simmem.h | 34 +- 23 files changed, 588 insertions(+), 269 deletions(-) delete mode 100644 z80core/simutil.c delete mode 100644 z80core/simutil.h diff --git a/altairsim/srcsim/Makefile b/altairsim/srcsim/Makefile index 7e5151c4..efb03a93 100644 --- a/altairsim/srcsim/Makefile +++ b/altairsim/srcsim/Makefile @@ -123,8 +123,8 @@ INSTALL_DATA = $(INSTALL) -m 644 # core system source files for the CPU simulation CORE_SRCS = sim8080.c simcore.c simdis.c simfun.c simglb.c simice.c simint.c \ - simmain.c simutil.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c \ - simz80-ed.c simz80-fd.c simz80-fdcb.c + simmain.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c simz80-ed.c \ + simz80-fd.c simz80-fdcb.c SRCS = $(CORE_SRCS) $(MACHINE_SRCS) $(IO_SRCS) XXSRCS = $(FP_SRCS) OBJS = $(SRCS:.c=.o) $(XXSRCS:.cpp=.o) diff --git a/altairsim/srcsim/simcfg.c b/altairsim/srcsim/simcfg.c index 2a14f9d8..bd9f7117 100644 --- a/altairsim/srcsim/simcfg.c +++ b/altairsim/srcsim/simcfg.c @@ -40,7 +40,6 @@ #include "simdefs.h" #include "simglb.h" #include "simmem.h" -#include "simutil.h" #include "simcfg.h" #include "altair-88-sio.h" @@ -215,7 +214,7 @@ void config(void) } else if (!strcmp(t1, "sio3_baud_rate")) { sio3_baud_rate = atoi(t2); } else if (!strcmp(t1, "fp_port")) { - fp_port = (BYTE) exatoi(t2); + fp_port = (BYTE) strtol(t2, NULL, 16); } else if (!strcmp(t1, "fp_fps")) { #ifdef FRONTPANEL fp_fps = (float) atoi(t2); diff --git a/cpmsim/srcsim/Makefile b/cpmsim/srcsim/Makefile index b1c7779d..d958bc8a 100644 --- a/cpmsim/srcsim/Makefile +++ b/cpmsim/srcsim/Makefile @@ -82,8 +82,8 @@ INSTALL_DATA = $(INSTALL) -m 644 # core system source files for the CPU simulation CORE_SRCS = sim8080.c simcore.c simdis.c simfun.c simglb.c simice.c simint.c \ - simmain.c simutil.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c \ - simz80-ed.c simz80-fd.c simz80-fdcb.c + simmain.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c simz80-ed.c \ + simz80-fd.c simz80-fdcb.c SRCS = $(CORE_SRCS) $(MACHINE_SRCS) $(IO_SRCS) OBJS = $(SRCS:.c=.o) DEPS = $(SRCS:.c=.d) diff --git a/cromemcosim/srcsim/Makefile b/cromemcosim/srcsim/Makefile index 88cf16e9..6fd50d00 100644 --- a/cromemcosim/srcsim/Makefile +++ b/cromemcosim/srcsim/Makefile @@ -131,8 +131,8 @@ INSTALL_DATA = $(INSTALL) -m 644 # core system source files for the CPU simulation CORE_SRCS = sim8080.c simcore.c simdis.c simfun.c simglb.c simice.c simint.c \ - simmain.c simutil.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c \ - simz80-ed.c simz80-fd.c simz80-fdcb.c + simmain.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c simz80-ed.c \ + simz80-fd.c simz80-fdcb.c SRCS = $(CORE_SRCS) $(MACHINE_SRCS) $(IO_SRCS) XXSRCS = $(FP_SRCS) OBJS = $(SRCS:.c=.o) $(XXSRCS:.cpp=.o) diff --git a/cromemcosim/srcsim/simcfg.c b/cromemcosim/srcsim/simcfg.c index 1f4e754c..ce0bff21 100644 --- a/cromemcosim/srcsim/simcfg.c +++ b/cromemcosim/srcsim/simcfg.c @@ -27,7 +27,6 @@ #include "simdefs.h" #include "simglb.h" #include "simmem.h" -#include "simutil.h" #include "simcfg.h" #include "log.h" @@ -71,7 +70,7 @@ void config(void) continue; } if (!strcmp(t1, "fp_port")) { - fp_port = (BYTE) exatoi(t2); + fp_port = (BYTE) strtol(t2, NULL, 16); } else if (!strcmp(t1, "fp_fps")) { #ifdef FRONTPANEL fp_fps = (float) atoi(t2); diff --git a/imsaisim/srcsim/Makefile b/imsaisim/srcsim/Makefile index cdb9897e..67f99314 100644 --- a/imsaisim/srcsim/Makefile +++ b/imsaisim/srcsim/Makefile @@ -132,8 +132,8 @@ INSTALL_DATA = $(INSTALL) -m 644 # core system source files for the CPU simulation CORE_SRCS = sim8080.c simcore.c simdis.c simfun.c simglb.c simice.c simint.c \ - simmain.c simutil.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c \ - simz80-ed.c simz80-fd.c simz80-fdcb.c + simmain.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c simz80-ed.c \ + simz80-fd.c simz80-fdcb.c SRCS = $(CORE_SRCS) $(MACHINE_SRCS) $(IO_SRCS) XXSRCS = $(FP_SRCS) OBJS = $(SRCS:.c=.o) $(XXSRCS:.cpp=.o) diff --git a/imsaisim/srcsim/simcfg.c b/imsaisim/srcsim/simcfg.c index 5c29aa2b..1bf96edd 100644 --- a/imsaisim/srcsim/simcfg.c +++ b/imsaisim/srcsim/simcfg.c @@ -44,7 +44,6 @@ #include "simdefs.h" #include "simglb.h" #include "simmem.h" -#include "simutil.h" #include "simcfg.h" #include "imsai-sio2.h" @@ -244,7 +243,7 @@ void config(void) } else if (!strcmp(t1, "sio2b_baud_rate")) { sio2b_baud_rate = atoi(t2); } else if (!strcmp(t1, "fp_port")) { - fp_port = (BYTE) exatoi(t2); + fp_port = (BYTE) strtol(t2, NULL, 16); } else if (!strcmp(t1, "fp_fps")) { #ifdef FRONTPANEL fp_fps = (float) atoi(t2); diff --git a/intelmdssim/srcsim/Makefile b/intelmdssim/srcsim/Makefile index eff3fc8c..ae1e6f1d 100644 --- a/intelmdssim/srcsim/Makefile +++ b/intelmdssim/srcsim/Makefile @@ -122,8 +122,8 @@ INSTALL_DATA = $(INSTALL) -m 644 # core system source files for the CPU simulation CORE_SRCS = sim8080.c simcore.c simdis.c simfun.c simglb.c simice.c simint.c \ - simmain.c simutil.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c \ - simz80-ed.c simz80-fd.c simz80-fdcb.c + simmain.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c simz80-ed.c \ + simz80-fd.c simz80-fdcb.c SRCS = $(CORE_SRCS) $(MACHINE_SRCS) $(IO_SRCS) XXSRCS = $(FP_SRCS) OBJS = $(SRCS:.c=.o) $(XXSRCS:.cpp=.o) diff --git a/mosteksim/srcsim/Makefile b/mosteksim/srcsim/Makefile index 65184eee..d061524d 100644 --- a/mosteksim/srcsim/Makefile +++ b/mosteksim/srcsim/Makefile @@ -85,8 +85,8 @@ INSTALL_DATA = $(INSTALL) -m 644 # core system source files for the CPU simulation CORE_SRCS = sim8080.c simcore.c simdis.c simfun.c simglb.c simice.c simint.c \ - simmain.c simutil.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c \ - simz80-ed.c simz80-fd.c simz80-fdcb.c + simmain.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c simz80-ed.c \ + simz80-fd.c simz80-fdcb.c SRCS = $(CORE_SRCS) $(MACHINE_SRCS) $(IO_SRCS) OBJS = $(SRCS:.c=.o) DEPS = $(SRCS:.c=.d) diff --git a/picosim/srcsim/CMakeLists.txt b/picosim/srcsim/CMakeLists.txt index a887c694..3dc798b1 100644 --- a/picosim/srcsim/CMakeLists.txt +++ b/picosim/srcsim/CMakeLists.txt @@ -48,7 +48,6 @@ add_executable(${PROJECT_NAME} ${Z80PACK}/z80core/simdis.c ${Z80PACK}/z80core/simglb.c ${Z80PACK}/z80core/simice.c - ${Z80PACK}/z80core/simutil.c ${Z80PACK}/z80core/simz80-cb.c ${Z80PACK}/z80core/simz80-dd.c ${Z80PACK}/z80core/simz80-ddcb.c diff --git a/picosim/srcsim/simcfg.c b/picosim/srcsim/simcfg.c index f4542e16..af5066cd 100644 --- a/picosim/srcsim/simcfg.c +++ b/picosim/srcsim/simcfg.c @@ -33,7 +33,6 @@ #include "simdefs.h" #include "simglb.h" #include "simcore.h" -#include "simutil.h" #include "simport.h" #include "simio.h" #include "simcfg.h" diff --git a/z80core/sim8080.c b/z80core/sim8080.c index 4b05665e..8bed6805 100644 --- a/z80core/sim8080.c +++ b/z80core/sim8080.c @@ -610,6 +610,8 @@ void cpu_8080(void) } } +#ifdef WANT_ICE + #ifdef WANT_TIM /* do runtime measurement */ if (t_flag) { @@ -619,6 +621,15 @@ void cpu_8080(void) } #endif +#ifdef WANT_HB + if (hb_trig) { + cpu_error = OPHALT; + cpu_state = ST_STOPPED; + } +#endif + +#endif /* WANT_ICE */ + #ifdef WANT_GUI check_gui_break(); #endif diff --git a/z80core/simdefs.h b/z80core/simdefs.h index 7c05b968..7ba37acd 100644 --- a/z80core/simdefs.h +++ b/z80core/simdefs.h @@ -24,6 +24,7 @@ #define I8080 2 #endif +/* check validity of sim.h options */ #if defined(EXCLUDE_I8080) && defined(EXCLUDE_Z80) #error "Only one of EXCLUDE_I8080 or EXCLUDE_Z80 can be used" #endif @@ -38,6 +39,28 @@ #endif #if (defined(ALT_I8080) || defined(ALT_Z80)) && !defined(UNDOC_INST) #error "UNDOC_INST required for alternate simulators" +#endif +#ifdef HISIZE +#ifndef WANT_ICE +#error "WANT_ICE required for HISIZE" +#endif +#if HISIZE < 1 || HISIZE > 1000 +#error "HISIZE must be between 1 and 1000" +#endif +#endif /* HISIZE */ +#ifdef SBSIZE +#ifndef WANT_ICE +#error "WANT_ICE required for SBSIZE" +#endif +#if SBSIZE < 1 || SBSIZE > 10 +#error "SBSIZE must be between 1 and 10" +#endif +#endif /* SBSIZE */ +#if defined(WANT_TIM) && !defined(WANT_ICE) +#error "WANT_ICE required for WANT_TIM" +#endif +#if defined(WANT_HB) && !defined(WANT_ICE) +#error "WANT_ICE required for WANT_HB" #endif /* bit definitions of CPU flags */ @@ -60,7 +83,7 @@ #define CPU_WO 2 /* write or output (active low) */ #define CPU_INTA 1 /* interrupt acknowledge */ -#if defined(FRONTPANEL) || defined(SIMPLEPANEL) +#if defined(FRONTPANEL) || defined(SIMPLEPANEL) || defined(WANT_HB) #define BUS_8080 /* emulate 8080 bus status */ #endif diff --git a/z80core/simice.c b/z80core/simice.c index 9e80322f..6287bdd5 100644 --- a/z80core/simice.c +++ b/z80core/simice.c @@ -9,13 +9,6 @@ * This module is an ICE type user interface to debug Z80/8080 programs * on a host system. It emulates, as acurate as possible and practical, * the Mostek ICE we were using in the 80th and 90th. - * Only feature missing is hardware breakpoint, because here in software - * we need to compare addresses at every memory access. This needs to be - * implemented with conditional compiling sometime. - * bh address,access mode, where access mode is r, w or x. - * If I remember right one could set access mode to combinations like - * rw, so that it would break on every read or write access to an - * address. */ #include @@ -33,7 +26,6 @@ #include "simmem.h" #include "simdis.h" #include "simport.h" -#include "simutil.h" #include "simice.h" #ifndef BAREMETAL @@ -59,7 +51,6 @@ int h_flag; /* flag for trace memory overrun */ */ #ifdef SBSIZE struct softbreak soft[SBSIZE]; /* memory to hold breakpoint information */ -int sb_next; /* index into breakpoint memory */ #endif /* @@ -73,9 +64,21 @@ WORD t_start = 65535; /* start address for measurement */ WORD t_end = 65535; /* end address for measurement */ #endif +/* + * Variables for hardware breakpoint + */ +#ifdef WANT_HB +int hb_flag; /* hardware breakpoint enabled flag */ +WORD hb_addr; /* address of hardware breakpoint */ +int hb_mode; /* access mode of hardware breakpoint */ +int hb_trig; /* hardware breakpoint triggered flag */ +#endif + static void do_step(void); static void do_trace(char *s); static void do_go(char *s); +static void install_softbp(void); +static void uninstall_softbp(void); static int handle_break(void); static void do_dump(char *s); static void do_list(char *s); @@ -234,9 +237,11 @@ void ice_cmd_loop(int go_flag) */ static void do_step(void) { + install_softbp(); step_cpu(); + uninstall_softbp(); if (cpu_error == OPHALT) - handle_break(); + (void) handle_break(); report_cpu_error(); print_head(); print_reg(); @@ -259,18 +264,14 @@ static void do_trace(char *s) count = atoi(s); print_head(); print_reg(); + install_softbp(); for (i = 0; i < count; i++) { step_cpu(); print_reg(); - if (cpu_error) { - if (cpu_error == OPHALT) { - if (!handle_break()) { - break; - } - } else - break; - } + if (cpu_error && (cpu_error != OPHALT || !handle_break())) + break; } + uninstall_softbp(); report_cpu_error(); wrk_addr = PC; } @@ -291,22 +292,18 @@ static void do_go(char *s) s++; } if (isxdigit((unsigned char) *s)) - PC = exatoi(s); + PC = strtol(s, NULL, 16); if (ice_before_go) (*ice_before_go)(); + install_softbp(); start_time = cpu_time; for (;;) { run_cpu(); - if (cpu_error) { - if (cpu_error == OPHALT) { - if (!handle_break()) { - break; - } - } else - break; - } + if (cpu_error && (cpu_error != OPHALT || !handle_break())) + break; } stop_time = cpu_time; + uninstall_softbp(); if (ice_after_go) (*ice_after_go)(); report_cpu_error(); @@ -322,28 +319,74 @@ static void do_go(char *s) } /* - * Handling of software breakpoints (HALT opcode): + * Install software breakpoints (HALT opcode) + */ +static void install_softbp(void) +{ +#ifdef SBSIZE + register int i; + + for (i = 0; i < SBSIZE; i++) + if (soft[i].sb_pass) { + soft[i].sb_oldopc = getmem(soft[i].sb_addr); + putmem(soft[i].sb_addr, 0x76); /* HALT */ + } +#endif +} + +/* + * Uninstall software breakpoints (HALT opcode) + */ +static void uninstall_softbp(void) +{ +#ifdef SBSIZE + register int i; + + for (i = 0; i < SBSIZE; i++) + if (soft[i].sb_pass) + putmem(soft[i].sb_addr, soft[i].sb_oldopc); +#endif +} + +/* + * Handling of software (HALT opcode) / hardware breakpoints: * * Output: 0 breakpoint or other HALT opcode reached (stop) - * 1 breakpoint reached, pass counter not reached (continue) + * 1 breakpoint hit, pass counter not reached (continue) */ static int handle_break(void) { #ifdef SBSIZE register int i; - int break_address; +#endif +#ifdef WANT_HB + if (hb_flag && hb_trig) { + fputs("Hardware breakpoint hit by ", stdout); + if (hb_trig == HB_READ) + fputs("read", stdout); + else if (hb_trig == HB_WRITE) + fputs("write", stdout); + else + fputs("execute", stdout); + printf(" access to %04x\n", hb_addr); + hb_trig = 0; + cpu_error = NONE; + return 0; + } +#endif +#ifdef SBSIZE for (i = 0; i < SBSIZE; i++) /* search for breakpoint */ - if (soft[i].sb_addr == PC - 1) + if (soft[i].sb_pass && soft[i].sb_addr == PC - 1) break; if (i == SBSIZE) /* no breakpoint found */ return 0; #ifdef HISIZE - h_next--; /* correct history */ - if (h_next < 0) - h_next = 0; + if (h_next) /* correct history */ + h_next--; + else + h_next = HISIZE - 1; #endif - break_address = PC - 1; /* store addr of breakpoint */ PC--; /* substitute HALT opcode by */ putmem(PC, soft[i].sb_oldopc); /* original opcode */ step_cpu(); /* and execute it */ @@ -351,12 +394,12 @@ static int handle_break(void) soft[i].sb_passcount++; /* increment pass counter */ if (soft[i].sb_passcount != soft[i].sb_pass) return 1; /* pass not reached, continue */ - printf("Software breakpoint %d reached at %04x\n", i, break_address); + printf("Software breakpoint hit at %04x\n", soft[i].sb_addr); soft[i].sb_passcount = 0; /* reset pass counter */ return 0; /* pass reached, stop */ -#else +#else /* !SBSIZE */ return 0; -#endif +#endif /* !SBSIZE */ } /* @@ -371,13 +414,18 @@ static void do_dump(char *s) while (isspace((unsigned char) *s)) s++; if (isxdigit((unsigned char) *s)) - wrk_addr = exatoi(s) & ~0xf; - while (*s != ',' && *s != '\0') + wrk_addr = strtol(s, &s, 16) & ~0xf; + while (isspace((unsigned char) *s)) s++; - if (*s && isxdigit((unsigned char) *++s)) { - n = ((exatoi(s) & ~0xf) - wrk_addr) / 16 + 1; - if (n <= 0) - n = 1; + if (*s == ',') { + s++; + while (isspace((unsigned char) *s)) + s++; + if (isxdigit((unsigned char) *s)) { + n = ((strtol(s, NULL, 16) & ~0xf) - wrk_addr) / 16 + 1; + if (n <= 0) + n = 1; + } } printf("Addr "); for (i = 0; i < 16; i++) @@ -407,23 +455,28 @@ static void do_list(char *s) while (isspace((unsigned char) *s)) s++; if (isxdigit((unsigned char) *s)) - wrk_addr = exatoi(s); - while (*s != ',' && *s != '\0') + wrk_addr = strtol(s, &s, 16); + while (isspace((unsigned char) *s)) s++; - if (*s && isxdigit((unsigned char) *++s)) { - a = exatoi(s); - if (a < wrk_addr) - a = wrk_addr; - while (wrk_addr <= a) { - printf("%04x - ", (unsigned int) wrk_addr); - wrk_addr += disass(wrk_addr); - } - } else { - for (i = 0; i < 10; i++) { - printf("%04x - ", (unsigned int) wrk_addr); - wrk_addr += disass(wrk_addr); + if (*s == ',') { + s++; + while (isspace((unsigned char) *s)) + s++; + if (isxdigit((unsigned char) *s)) { + a = strtol(s, NULL, 16); + if (a < wrk_addr) + a = wrk_addr; + while (wrk_addr <= a) { + printf("%04x - ", (unsigned int) wrk_addr); + wrk_addr += disass(wrk_addr); + } + return; } } + for (i = 0; i < 10; i++) { + printf("%04x - ", (unsigned int) wrk_addr); + wrk_addr += disass(wrk_addr); + } } /* @@ -434,19 +487,23 @@ static void do_modify(char *s) while (isspace((unsigned char) *s)) s++; if (isxdigit((unsigned char) *s)) - wrk_addr = exatoi(s); + wrk_addr = strtol(s, NULL, 16); for (;;) { printf("%04x = %02x : ", (unsigned int) wrk_addr, getmem(wrk_addr)); if (get_cmdline(arg, LENCMD) || arg[0] == '\0') break; - if (arg[0] == '\n') { + s = arg; + while (isspace((unsigned char) *s)) + s++; + if (*s == '\0') { wrk_addr++; continue; } - if (!isxdigit((unsigned char) arg[0])) + if (isxdigit((unsigned char) *s)) + putmem(wrk_addr++, strtol(s, NULL, 16)); + else break; - putmem(wrk_addr++, exatoi(arg)); } } @@ -461,23 +518,41 @@ static void do_fill(char *s) while (isspace((unsigned char) *s)) s++; - a = exatoi(s); - while (*s != ',' && *s != '\0') + if (!isxdigit((unsigned char) *s)) { + puts("address missing"); + return; + } + a = strtol(s, &s, 16); + while (isspace((unsigned char) *s)) s++; - if (*s) { - i = exatoi(++s); + if (*s == ',') { + s++; + while (isspace((unsigned char) *s)) + s++; + if (!isxdigit((unsigned char) *s)) { + puts("count missing"); + return; + } } else { puts("count missing"); return; } - while (*s != ',' && *s != '\0') + i = strtol(s, &s, 16); + while (isspace((unsigned char) *s)) + s++; + if (*s == ',') { s++; - if (*s) { - val = exatoi(++s); + while (isspace((unsigned char) *s)) + s++; + if (!isxdigit((unsigned char) *s)) { + puts("value missing"); + return; + } } else { puts("value missing"); return; } + val = strtol(s, NULL, 16); while (i--) putmem(a++, val); } @@ -492,23 +567,41 @@ static void do_move(char *s) while (isspace((unsigned char) *s)) s++; - a1 = exatoi(s); - while (*s != ',' && *s != '\0') + if (!isxdigit((unsigned char) *s)) { + puts("from missing"); + return; + } + a1 = strtol(s, &s, 16); + while (isspace((unsigned char) *s)) + s++; + if (*s == ',') { s++; - if (*s) { - a2 = exatoi(++s); + while (isspace((unsigned char) *s)) + s++; + if (!isxdigit((unsigned char) *s)) { + puts("to missing"); + return; + } } else { puts("to missing"); return; } - while (*s != ',' && *s != '\0') + a2 = strtol(s, &s, 16); + while (isspace((unsigned char) *s)) s++; - if (*s) { - count = exatoi(++s); + if (*s == ',') { + s++; + while (isspace((unsigned char) *s)) + s++; + if (!isxdigit((unsigned char) *s)) { + puts("count missing"); + return; + } } else { puts("count missing"); return; } + count = strtol(s, NULL, 16); while (count--) putmem(a2++, getmem(a1++)); } @@ -522,11 +615,19 @@ static void do_port(char *s) while (isspace((unsigned char) *s)) s++; - port = exatoi(s); + if (!isxdigit((unsigned char) *s)) { + puts("port missing"); + return; + } + port = strtol(s, NULL, 16); printf("%02x = %02x : ", port, io_in(port, 0)); - if (!get_cmdline(arg, LENCMD) && - arg[0] != '\0' && (isxdigit((unsigned char) *arg))) - io_out(port, 0, (BYTE) exatoi(arg)); + if (!get_cmdline(arg, LENCMD)) { + s = arg; + while (isspace((unsigned char) *s)) + s++; + if (isxdigit((unsigned char) *s)) + io_out(port, 0, (BYTE) strtol(s, NULL, 16)); + } } /* @@ -623,7 +724,7 @@ static void do_reg(char *s) while (isspace((unsigned char) *s)) s++; - if (*s) { + if (*s != '\0') { for (i = 0, p = regs; i < nregs; i++, p++) { #ifndef EXCLUDE_Z80 if (p->z80 && cpu != Z80) @@ -659,31 +760,37 @@ static void do_reg(char *s) default: break; } - if (!get_cmdline(arg, LENCMD) && - arg[0] != '\0' && arg[0] != '\n') { - w = exatoi(arg); - switch (p->type) { - case R_8: - *(p->r8) = w & 0xff; - break; - case R_88: - *(p->r8h) = (w >> 8) & 0xff; - *(p->r8l) = w & 0xff; - break; - case R_16: - *(p->r16) = w; - break; - case R_R: - *(p->r8h) = *(p->r8l) = w & 0xff; - break; - case R_F: - *(p->rf) = w & 0xff; - break; - case R_M: - F = w ? (F | p->rm) : (F & ~p->rm); - break; - default: - break; + if (!get_cmdline(arg, LENCMD)) { + s = arg; + while (isspace((unsigned char) *s)) + s++; + if (isxdigit((unsigned char) *s)) { + w = strtol(s, NULL, 16); + switch (p->type) { + case R_8: + *(p->r8) = w & 0xff; + break; + case R_88: + *(p->r8h) = (w >> 8) & 0xff; + *(p->r8l) = w & 0xff; + break; + case R_16: + *(p->r16) = w; + break; + case R_R: + *(p->r8h) = *(p->r8l) = + w & 0xff; + break; + case R_F: + *(p->rf) = w & 0xff; + break; + case R_M: + F = w ? (F | p->rm) + : (F & ~p->rm); + break; + default: + break; + } } } } else @@ -757,54 +864,185 @@ static void print_reg(void) */ static void do_break(char *s) { -#ifndef SBSIZE +#if !defined(SBSIZE) && !defined(WANT_HB) UNUSED(s); puts("Sorry, no breakpoints available"); - puts("Please recompile with SBSIZE defined in sim.h"); -#else /* SBSIZE */ + puts("Please recompile with SBSIZE and/or WANT_HB defined in sim.h"); +#else /* SBSIZE || WANT_HB */ + WORD a; + int n; +#ifdef SBSIZE register int i; + int hdr_flag; +#endif +#ifdef WANT_HB + if (*s == 'h') { + s++; + if (*s == '\n') { + if (hb_flag) { + fputs("Hardware breakpoint set with ", stdout); + n = 0; + if (hb_mode & HB_READ) { + fputs("read", stdout); + n = 1; + } + if (hb_mode & HB_WRITE) { + if (n) + putchar('/'); + fputs("write", stdout); + n = 1; + } + if (hb_mode & HB_EXEC) { + if (n) + putchar('/'); + fputs("execute", stdout); + } + printf(" access trigger to %04x\n", hb_addr); + } else + puts("No hardware breakpoint set"); + return; + } + if (tolower((unsigned char) *s) == 'c') { + hb_flag = 0; + return; + } + while (isspace((unsigned char) *s)) + s++; + if (!isxdigit((unsigned char) *s)) { + puts("address missing"); + return; + } + a = strtol(s, &s, 16); + while (isspace((unsigned char) *s)) + s++; + if (*s == ',') { + s++; + while (isspace((unsigned char) *s)) + s++; + n = 0; + if (tolower((unsigned char) *s) == 'r') { + n |= HB_READ; + s++; + } + if (tolower((unsigned char) *s) == 'w') { + n |= HB_WRITE; + s++; + } + if (tolower((unsigned char) *s) == 'x') + n |= HB_EXEC; + } else + n = HB_READ | HB_WRITE | HB_EXEC; +#ifdef SBSIZE + if (n & HB_EXEC) { + for (i = 0; i < SBSIZE; i++) + if (soft[i].sb_pass && soft[i].sb_addr == a) { + puts("Software breakpoint set " + "at same execute access address"); + return; + } + } +#endif + hb_addr = a; + hb_mode = n; + hb_flag = 1; + return; + } +#endif /* WANT_HB */ +#ifdef SBSIZE if (*s == '\n') { - puts("No Addr Pass Counter"); + hdr_flag = 0; for (i = 0; i < SBSIZE; i++) - if (soft[i].sb_pass) - printf("%02d %04x %05d %05d\n", i, + if (soft[i].sb_pass) { + if (!hdr_flag) { + puts("Addr Pass Counter"); + hdr_flag = 1; + } + printf("%04x %05d %05d\n", soft[i].sb_addr, soft[i].sb_pass, soft[i].sb_passcount); + } + if (!hdr_flag) + puts("No software breakpoints set"); return; } - if (isxdigit((unsigned char) *s)) { - i = atoi(s++); - if (i >= SBSIZE) { - printf("breakpoint %d not available\n", i); + if (tolower((unsigned char) *s) == 'c') { + s++; + while (isspace((unsigned char) *s)) + s++; + if (*s == '\0') { + memset((char *) soft, 0, + sizeof(struct softbreak) * SBSIZE); return; } - } else { - i = sb_next++; - if (sb_next == SBSIZE) - sb_next = 0; + if (!isxdigit((unsigned char) *s)) { + puts("address missing"); + return; + } + a = strtol(s, NULL, 16); + for (i = 0; i < SBSIZE; i++) { + if (soft[i].sb_pass && soft[i].sb_addr == a) + break; + } + if (i == SBSIZE) + printf("No software breakpoint at address %04x\n", a); + else + memset((char *) &soft[i], 0, sizeof(struct softbreak)); + return; } while (isspace((unsigned char) *s)) s++; - if (*s == 'c') { - putmem(soft[i].sb_addr, soft[i].sb_oldopc); - memset((char *) &soft[i], 0, sizeof(struct softbreak)); + if (!isxdigit((unsigned char) *s)) { + puts("address missing"); return; } - if (soft[i].sb_pass) - putmem(soft[i].sb_addr, soft[i].sb_oldopc); - soft[i].sb_addr = exatoi(s); - soft[i].sb_oldopc = getmem(soft[i].sb_addr); - putmem(soft[i].sb_addr, 0x76); - while (!iscntrl((unsigned char) *s) && !ispunct((unsigned char) *s)) - s++; - if (*s != ',') - soft[i].sb_pass = 1; - else - soft[i].sb_pass = exatoi(++s); - soft[i].sb_passcount = 0; + a = strtol(s, &s, 16); + /* look for existing breakpoint */ + for (i = 0; i < SBSIZE; i++) { + if (soft[i].sb_pass && soft[i].sb_addr == a) + break; + } + /* if not found, look for free one */ + if (i == SBSIZE) { + for (i = 0; i < SBSIZE; i++) + if (!soft[i].sb_pass) + break; + } + if (i == SBSIZE) + puts("All software breakpoints in use"); + else { + if (!soft[i].sb_pass) { + /* new breakpoint */ +#ifdef WANT_HB + if (hb_flag && (hb_mode & HB_EXEC) && hb_addr == a) { + puts("Hardware execute access breakpoint set " + "at same address"); + return; + } +#endif + soft[i].sb_addr = a; + } + while (isspace((unsigned char) *s)) + s++; + if (*s == ',') { + s++; + while (isspace((unsigned char) *s)) + s++; + if (!isdigit((unsigned char) *s)) + n = 1; + else { + n = atoi(s); + if (n == 0) + n = 1; + } + } else + n = 1; + soft[i].sb_pass = n; + soft[i].sb_passcount = 0; + } #endif /* SBSIZE */ +#endif /* SBSIZE || WANT_HB */ } /* @@ -820,69 +1058,63 @@ static void do_hist(char *s) #else /* HISIZE */ int i, l, b, e, sa; - while (isspace((unsigned char) *s)) - s++; - switch (*s) { - case 'c': + if (tolower((unsigned char) *s) == 'c') { memset((char *) his, 0, sizeof(struct history) * HISIZE); h_next = 0; h_flag = 0; - break; - default: - if ((h_next == 0) && (h_flag == 0)) { - puts("History memory is empty"); - break; + return; + } + if (h_next == 0 && h_flag == 0) { + puts("History memory is empty"); + return; + } + e = h_next; + b = (h_flag) ? h_next + 1 : 0; + l = 0; + while (isspace((unsigned char) *s)) + s++; + if (isxdigit((unsigned char) *s)) + sa = strtol(s, NULL, 16); + else + sa = -1; + for (i = b; i != e; i++) { + if (i == HISIZE) + i = 0; + if (sa != -1) { + if (his[i].h_addr < sa) + continue; + else + sa = -1; } - e = h_next; - b = (h_flag) ? h_next + 1 : 0; - l = 0; - while (isspace((unsigned char) *s)) - s++; - if (*s) - sa = exatoi(s); - else - sa = -1; - for (i = b; i != e; i++) { - if (i == HISIZE) - i = 0; - if (sa != -1) { - if (his[i].h_addr < sa) - continue; - else - sa = -1; - } - switch (his[i].h_cpu) { + switch (his[i].h_cpu) { #ifndef EXCLUDE_Z80 - case Z80: - printf("%04x AF=%04x BC=%04x DE=%04x HL=%04x " - "IX=%04x IY=%04x SP=%04x\n", - his[i].h_addr, his[i].h_af, his[i].h_bc, - his[i].h_de, his[i].h_hl, his[i].h_ix, - his[i].h_iy, his[i].h_sp); - break; + case Z80: + printf("%04x AF=%04x BC=%04x DE=%04x HL=%04x " + "IX=%04x IY=%04x SP=%04x\n", + his[i].h_addr, his[i].h_af, his[i].h_bc, + his[i].h_de, his[i].h_hl, his[i].h_ix, + his[i].h_iy, his[i].h_sp); + break; #endif #ifndef EXCLUDE_I8080 - case I8080: - printf("%04x AF=%04x BC=%04x DE=%04x HL=%04x " - "SP=%04x\n", - his[i].h_addr, his[i].h_af, his[i].h_bc, - his[i].h_de, his[i].h_hl, his[i].h_sp); - break; + case I8080: + printf("%04x AF=%04x BC=%04x DE=%04x HL=%04x " + "SP=%04x\n", + his[i].h_addr, his[i].h_af, his[i].h_bc, + his[i].h_de, his[i].h_hl, his[i].h_sp); + break; #endif - default: - break; - } - if (++l < 20) - continue; - l = 0; - fputs("q = quit, else continue: ", stdout); - fflush(stdout); - if (!get_cmdline(arg, LENCMD) && - (arg[0] == '\0' || - tolower((unsigned char) arg[0]) == 'q')) - break; + default: + break; } - break; + if (++l < 20) + continue; + l = 0; + fputs("q = quit, else continue: ", stdout); + fflush(stdout); + if (!get_cmdline(arg, LENCMD) && + (arg[0] == '\0' || tolower((unsigned char) arg[0]) == 'q')) + break; } #endif /* HISIZE */ } @@ -898,6 +1130,8 @@ static void do_count(char *s) puts("Sorry, no t-state count available"); puts("Please recompile with WANT_TIM defined in sim.h"); #else + WORD start; + while (isspace((unsigned char) *s)) s++; if (*s == '\0') { @@ -905,15 +1139,31 @@ static void do_count(char *s) printf("%04x %04x %s %" PRIu64 "\n", t_start, t_end, t_flag ? "on " : "off", t_states_e - t_states_s); - } else { - t_start = exatoi(s); - while (*s != ',' && *s != '\0') + return; + } + if (!isxdigit((unsigned char) *s)) { + puts("start missing"); + return; + } + start = strtol(s, &s, 16); + while (isspace((unsigned char) *s)) + s++; + if (*s == ',') { + s++; + while (isspace((unsigned char) *s)) s++; - if (*s) - t_end = exatoi(++s); - t_states_s = t_states_e = T; - t_flag = 0; + if (!isxdigit((unsigned char) *s)) { + puts("stop missing"); + return; + } + } else { + puts("stop missing"); + return; } + t_start = start; + t_end = strtol(s, NULL, 16); + t_states_s = t_states_e = T; + t_flag = 0; #endif } @@ -992,6 +1242,12 @@ static void do_show(void) i = 0; #endif printf("No. of software breakpoints: %d\n", i); +#ifdef WANT_HB + i = 1; +#else + i = 0; +#endif + printf("Hardware breakpoint %savailable\n", i ? "" : "not "); #ifdef UNDOC_INST i = u_flag; #else @@ -1022,11 +1278,14 @@ static void do_help(void) puts("return single step program"); puts("x [register] show/modify register"); puts("x f modify flag"); - puts("b[no] address[,pass] set soft breakpoint"); - puts("b show soft breakpoints"); - puts("b[no] c clear soft breakpoint"); + puts("b address[,pass] set software breakpoint"); + puts("b show software breakpoints"); + puts("bc [address] clear software breakpoint(s)"); + puts("bh address[,accmode] set hardware breakpoint"); + puts("bh show hardware breakpoint"); + puts("bhc clear hardware breakpoint"); puts("h [address] show history"); - puts("h c clear history"); + puts("hc clear history"); puts("z start,stop set trigger addr for t-state count"); puts("z show t-state count"); puts("s show settings"); @@ -1065,7 +1324,12 @@ static void do_clock(void) static struct sigaction newact; static struct itimerval tim; const char *s = NULL; +#ifdef WANT_HB + int save_hb_flag; + save_hb_flag = hb_flag; + hb_flag = 0; +#endif save[0] = getmem(0x0000); /* save memory locations */ save[1] = getmem(0x0001); /* 0000H - 0002H */ save[2] = getmem(0x0002); @@ -1089,6 +1353,9 @@ static void do_clock(void) putmem(0x0000, save[0]); /* restore memory locations */ putmem(0x0001, save[1]); /* 0000H - 0002H */ putmem(0x0002, save[2]); +#ifdef WANT_HB + hb_flag = save_hb_flag; +#endif switch (cpu) { #ifndef EXCLUDE_Z80 case Z80: @@ -1136,10 +1403,17 @@ static void do_load(char *s) while (*s != ',' && *s != '\n' && *s != '\0') *pfn++ = *s++; *pfn = '\0'; - if (*s == ',') - load_file(fn, exatoi(++s), -1); - else - load_file(fn, 0, 0); + if (*s == ',') { + s++; + while (isspace((unsigned char) *s)) + s++; + if (isxdigit((unsigned char) *s)) { + load_file(fn, strtol(s, NULL, 16), -1); + wrk_addr = PC; + return; + } + } + load_file(fn, 0, 0); wrk_addr = PC; } diff --git a/z80core/simice.h b/z80core/simice.h index c27bd657..ccbeff77 100644 --- a/z80core/simice.h +++ b/z80core/simice.h @@ -41,7 +41,6 @@ struct softbreak { /* structure of a breakpoint */ }; extern struct softbreak soft[SBSIZE]; -extern int sb_next; #endif #ifdef WANT_TIM @@ -50,6 +49,16 @@ extern int t_flag; extern WORD t_start, t_end; #endif +#ifdef WANT_HB + /* hardware breakpoint access modes */ +#define HB_READ 1 /* read memory */ +#define HB_WRITE 2 /* write memory */ +#define HB_EXEC 4 /* execute (op-code fetch) */ + +extern int hb_flag, hb_mode, hb_trig; +extern WORD hb_addr; +#endif + extern void (*ice_before_go)(void); extern void (*ice_after_go)(void); extern void (*ice_cust_cmd)(char *cmd, WORD *wrk_addr); diff --git a/z80core/simmain.c b/z80core/simmain.c index b2beefc2..3fdb378d 100644 --- a/z80core/simmain.c +++ b/z80core/simmain.c @@ -37,7 +37,6 @@ #include "simport.h" #include "simfun.h" #include "simint.h" -#include "simutil.h" #include "simmain.h" static void save_core(void); @@ -90,14 +89,14 @@ int main(int argc, char *argv[]) case 'm': /* initialize memory */ if (*(s + 1) != '\0') { - m_flag = exatoi(s + 1); + m_flag = strtol(s + 1, NULL, 16); s += strlen(s + 1); } else { if (argc <= 1) goto usage; argc--; argv++; - m_flag = exatoi(argv[0]); + m_flag = strtol(argv[0], NULL, 16); } break; diff --git a/z80core/simutil.c b/z80core/simutil.c deleted file mode 100644 index 453ceeda..00000000 --- a/z80core/simutil.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Z80SIM - a Z80-CPU simulator - * - * Copyright (C) 1987-2024 Udo Munk - */ - -#include - -/* - * atoi for hexadecimal numbers - */ -int exatoi(char *str) -{ - register int num = 0; - - while (isxdigit((unsigned char) *str)) { - num *= 16; - if (*str <= '9') - num += *str - '0'; - else - num += toupper((unsigned char) *str) - '7'; - str++; - } - return num; -} diff --git a/z80core/simutil.h b/z80core/simutil.h deleted file mode 100644 index affd38f9..00000000 --- a/z80core/simutil.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Z80SIM - a Z80-CPU simulator - * - * Copyright (C) 1987-2024 Udo Munk - */ - -#ifndef SIMUTIL_INC -#define SIMUTIL_INC - -extern int exatoi(char *str); - -#endif /* !SIMUTIL_INC */ diff --git a/z80core/simz80.c b/z80core/simz80.c index d06c9a81..a35ec382 100644 --- a/z80core/simz80.c +++ b/z80core/simz80.c @@ -622,6 +622,8 @@ void cpu_z80(void) } } +#ifdef WANT_ICE + #ifdef WANT_TIM /* do runtime measurement */ if (t_flag) { @@ -631,6 +633,15 @@ void cpu_z80(void) } #endif +#ifdef WANT_HB + if (hb_trig) { + cpu_error = OPHALT; + cpu_state = ST_STOPPED; + } +#endif + +#endif /* WANT_ICE */ + #ifdef WANT_GUI check_gui_break(); #endif diff --git a/z80sim/srcsim/Makefile b/z80sim/srcsim/Makefile index 31fdfe04..f40f7eb3 100644 --- a/z80sim/srcsim/Makefile +++ b/z80sim/srcsim/Makefile @@ -77,8 +77,8 @@ INSTALL_DATA = $(INSTALL) -m 644 # core system source files for the CPU simulation CORE_SRCS = sim8080.c simcore.c simdis.c simfun.c simglb.c simice.c simint.c \ - simmain.c simutil.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c \ - simz80-ed.c simz80-fd.c simz80-fdcb.c + simmain.c simz80.c simz80-cb.c simz80-dd.c simz80-ddcb.c simz80-ed.c \ + simz80-fd.c simz80-fdcb.c SRCS = $(CORE_SRCS) $(MACHINE_SRCS) $(IO_SRCS) OBJS = $(SRCS:.c=.o) DEPS = $(SRCS:.c=.d) diff --git a/z80sim/srcsim/sim.h.debug b/z80sim/srcsim/sim.h.debug index 4be0059c..590c2389 100644 --- a/z80sim/srcsim/sim.h.debug +++ b/z80sim/srcsim/sim.h.debug @@ -25,6 +25,7 @@ #define WANT_TIM /* count t-states */ #define HISIZE 100 /* number of entries in history */ #define SBSIZE 4 /* number of software breakpoints */ +#define WANT_HB /* hardware breakpoint */ #endif /*#define HAS_DISKS*/ /* has no disk drives */ diff --git a/z80sim/srcsim/sim.h.fast b/z80sim/srcsim/sim.h.fast index 37b1c163..21b9843e 100644 --- a/z80sim/srcsim/sim.h.fast +++ b/z80sim/srcsim/sim.h.fast @@ -26,6 +26,7 @@ /*#define WANT_TIM*/ /* count t-states */ /*#define HISIZE 100*/ /* number of entries in history */ /*#define SBSIZE 4*/ /* number of software breakpoints */ +/*#define WANT_HB*/ /* hardware breakpoint */ #endif /*#define HAS_DISKS*/ /* has no disk drives */ diff --git a/z80sim/srcsim/simmem.h b/z80sim/srcsim/simmem.h index 0f6f18ba..a23ee569 100644 --- a/z80sim/srcsim/simmem.h +++ b/z80sim/srcsim/simmem.h @@ -17,6 +17,9 @@ #include "sim.h" #include "simdefs.h" +#ifdef WANT_ICE +#include "simice.h" +#endif extern BYTE memory[65536]; @@ -27,12 +30,41 @@ extern void init_memory(void); */ static inline void memwrt(WORD addr, BYTE data) { +#ifdef BUS_8080 + cpu_bus &= ~(CPU_M1 | CPU_WO | CPU_MEMR); +#endif + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr && (hb_mode & HB_WRITE)) + hb_trig = HB_WRITE; +#endif memory[addr] = data; } static inline BYTE memrdr(WORD addr) { - return memory[addr]; + register BYTE data; + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr) { + if (cpu_bus & CPU_M1) { + if (hb_mode & HB_EXEC) + hb_trig = HB_EXEC; + } else { + if (hb_mode & HB_READ) + hb_trig = HB_READ; + } + } +#endif + + data = memory[addr]; + +#ifdef BUS_8080 + cpu_bus |= CPU_WO | CPU_MEMR; + cpu_bus &= ~CPU_M1; +#endif + + return data; } /* From a3484b6c7f0da04300be577aa26b7e24693e107e Mon Sep 17 00:00:00 2001 From: Thomas Eberhardt Date: Fri, 13 Dec 2024 20:42:12 +0100 Subject: [PATCH 02/10] add jpeg dependency to Ubuntu github action --- .github/workflows/makefile-ubuntu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/makefile-ubuntu.yml b/.github/workflows/makefile-ubuntu.yml index e4731cc8..d494158a 100644 --- a/.github/workflows/makefile-ubuntu.yml +++ b/.github/workflows/makefile-ubuntu.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v4 - name: Install dependencies - run: sudo apt install libglu1-mesa-dev + run: sudo apt install libjpeg-turbo8-dev libglu1-mesa-dev - name: Build binaries run: make From a3e8a3227f76d7d725e8489ab099024bba0fde6a Mon Sep 17 00:00:00 2001 From: Thomas Eberhardt Date: Sat, 14 Dec 2024 06:56:00 +0100 Subject: [PATCH 03/10] cleanup sim.h options and checks Guard FAST_BLOCK by !EXCLUDE_Z80. Remove unneeded checks from simdefs.h (already guarded in sim.h) --- altairsim/srcsim/sim.h | 4 +++- cpmsim/srcsim/sim.h | 4 +++- cromemcosim/srcsim/sim.h | 4 +++- imsaisim/srcsim/sim.h | 4 +++- intelmdssim/srcsim/sim.h | 4 +++- mosteksim/srcsim/sim.h | 6 ++++-- picosim/srcsim/sim.h | 4 +++- z80core/simdefs.h | 25 ------------------------- z80sim/srcsim/sim.h.debug | 4 +++- z80sim/srcsim/sim.h.fast | 4 +++- 10 files changed, 28 insertions(+), 35 deletions(-) diff --git a/altairsim/srcsim/sim.h b/altairsim/srcsim/sim.h index 88de8601..d5f472b2 100644 --- a/altairsim/srcsim/sim.h +++ b/altairsim/srcsim/sim.h @@ -38,8 +38,10 @@ #define CPU_SPEED 2 /* default CPU speed */ /*#define ALT_I8080*/ /* use alt. 8080 sim. primarily optimized for size */ /*#define ALT_Z80*/ /* use alt. Z80 sim. primarily optimized for size */ -#define UNDOC_INST /* compile undocumented instructions */ +#define UNDOC_INST /* compile undocumented instrs. (required by ALT_*) */ +#ifndef EXCLUDE_Z80 /*#define FAST_BLOCK*/ /* much faster but not accurate Z80 block instr. */ +#endif /*#define WANT_ICE*/ /* attach ICE to headless machine */ #ifdef WANT_ICE diff --git a/cpmsim/srcsim/sim.h b/cpmsim/srcsim/sim.h index 20e122a4..2cf62769 100644 --- a/cpmsim/srcsim/sim.h +++ b/cpmsim/srcsim/sim.h @@ -15,8 +15,10 @@ #define CPU_SPEED 0 /* default CPU speed 0=unlimited */ /*#define ALT_I8080*/ /* use alt. 8080 sim. primarily optimized for size */ /*#define ALT_Z80*/ /* use alt. Z80 sim. primarily optimized for size */ -#define UNDOC_INST /* compile undocumented instructions */ +#define UNDOC_INST /* compile undocumented instrs. (required by ALT_*) */ +#ifndef EXCLUDE_Z80 #define FAST_BLOCK /* much faster but not accurate Z80 block instr. */ +#endif /*#define WANT_ICE*/ /* attach ICE to machine */ #ifdef WANT_ICE diff --git a/cromemcosim/srcsim/sim.h b/cromemcosim/srcsim/sim.h index 68e22a0e..24ee5c16 100644 --- a/cromemcosim/srcsim/sim.h +++ b/cromemcosim/srcsim/sim.h @@ -39,8 +39,10 @@ #define CPU_SPEED 4 /* default CPU speed */ /*#define ALT_I8080*/ /* use alt. 8080 sim. primarily optimized for size */ /*#define ALT_Z80*/ /* use alt. Z80 sim. primarily optimized for size */ -#define UNDOC_INST /* compile undocumented instructions */ +#define UNDOC_INST /* compile undocumented instrs. (required by ALT_*) */ +#ifndef EXCLUDE_Z80 /*#define FAST_BLOCK*/ /* much faster but not accurate Z80 block instr. */ +#endif /*#define WANT_ICE*/ /* attach ICE to headless machine */ #ifdef WANT_ICE diff --git a/imsaisim/srcsim/sim.h b/imsaisim/srcsim/sim.h index 97e33bfb..b721c334 100644 --- a/imsaisim/srcsim/sim.h +++ b/imsaisim/srcsim/sim.h @@ -39,8 +39,10 @@ #define CPU_SPEED 2 /* default CPU speed */ /*#define ALT_I8080*/ /* use alt. 8080 sim. primarily optimized for size */ /*#define ALT_Z80*/ /* use alt. Z80 sim. primarily optimized for size */ -#define UNDOC_INST /* compile undocumented instructions */ +#define UNDOC_INST /* compile undocumented instrs. (required by ALT_*) */ +#ifndef EXCLUDE_Z80 /*#define FAST_BLOCK*/ /* much faster but not accurate Z80 block instr. */ +#endif /*#define WANT_ICE*/ /* attach ICE to headless machine */ #ifdef WANT_ICE diff --git a/intelmdssim/srcsim/sim.h b/intelmdssim/srcsim/sim.h index 730374e2..d5ba18f4 100644 --- a/intelmdssim/srcsim/sim.h +++ b/intelmdssim/srcsim/sim.h @@ -23,8 +23,10 @@ #define EXCLUDE_Z80 /* Intel Intellec MDS-800 was an 8080 machine */ /*#define ALT_I8080*/ /* use alt. 8080 sim. primarily optimized for size */ /*#define ALT_Z80*/ /* use alt. Z80 sim. primarily optimized for size */ -#define UNDOC_INST /* compile undocumented instructions */ +#define UNDOC_INST /* compile undocumented instrs. (required by ALT_*) */ +#ifndef EXCLUDE_Z80 /*#define FAST_BLOCK*/ /* much faster but not accurate Z80 block instr. */ +#endif /*#define WANT_ICE*/ /* attach ICE to headless machine */ #ifdef WANT_ICE diff --git a/mosteksim/srcsim/sim.h b/mosteksim/srcsim/sim.h index 66f2f91b..0e1cbaf0 100644 --- a/mosteksim/srcsim/sim.h +++ b/mosteksim/srcsim/sim.h @@ -22,11 +22,13 @@ */ #define DEF_CPU Z80 /* default CPU (Z80 or I8080) */ #define CPU_SPEED 0 /* default CPU speed 0=unlimited */ +#define EXCLUDE_I8080 /* this was a Z80 machine */ /*#define ALT_I8080*/ /* use alt. 8080 sim. primarily optimized for size */ /*#define ALT_Z80*/ /* use alt. Z80 sim. primarily optimized for size */ -#define UNDOC_INST /* compile undocumented instructions */ +#define UNDOC_INST /* compile undocumented instrs. (required by ALT_*) */ +#ifndef EXCLUDE_Z80 /*#define FAST_BLOCK*/ /* much faster but not accurate Z80 block instr. */ -#define EXCLUDE_I8080 /* this was a Z80 machine */ +#endif #define WANT_ICE /* attach ICE to headless machine */ #ifdef WANT_ICE diff --git a/picosim/srcsim/sim.h b/picosim/srcsim/sim.h index 018bdaec..f3f0f96d 100644 --- a/picosim/srcsim/sim.h +++ b/picosim/srcsim/sim.h @@ -14,8 +14,10 @@ #define CPU_SPEED 4 /* CPU speed 0=unlimited */ /*#define ALT_I8080*/ /* use alt. 8080 sim. primarily optimized for size */ /*#define ALT_Z80*/ /* use alt. Z80 sim. primarily optimized for size */ -#define UNDOC_INST /* compile undocumented instructions */ +#define UNDOC_INST /* compile undocumented instrs. (required by ALT_*) */ +#ifndef EXCLUDE_Z80 /*#define FAST_BLOCK*/ /* much faster but not accurate Z80 block instr. */ +#endif #define BAREMETAL /* set up the simulator core for bare metal use */ /*#define WANT_ICE*/ /* attach ICE to headless machine */ diff --git a/z80core/simdefs.h b/z80core/simdefs.h index 7ba37acd..e931bb31 100644 --- a/z80core/simdefs.h +++ b/z80core/simdefs.h @@ -34,33 +34,8 @@ #if defined(EXCLUDE_Z80) && DEF_CPU != I8080 #error "DEF_CPU=Z80 and no Z80 simulation included" #endif -#if defined(EXCLUDE_Z80) && defined(FAST_BLOCK) -#error "FAST_BLOCK makes only sense without EXCLUDE_Z80" -#endif #if (defined(ALT_I8080) || defined(ALT_Z80)) && !defined(UNDOC_INST) #error "UNDOC_INST required for alternate simulators" -#endif -#ifdef HISIZE -#ifndef WANT_ICE -#error "WANT_ICE required for HISIZE" -#endif -#if HISIZE < 1 || HISIZE > 1000 -#error "HISIZE must be between 1 and 1000" -#endif -#endif /* HISIZE */ -#ifdef SBSIZE -#ifndef WANT_ICE -#error "WANT_ICE required for SBSIZE" -#endif -#if SBSIZE < 1 || SBSIZE > 10 -#error "SBSIZE must be between 1 and 10" -#endif -#endif /* SBSIZE */ -#if defined(WANT_TIM) && !defined(WANT_ICE) -#error "WANT_ICE required for WANT_TIM" -#endif -#if defined(WANT_HB) && !defined(WANT_ICE) -#error "WANT_ICE required for WANT_HB" #endif /* bit definitions of CPU flags */ diff --git a/z80sim/srcsim/sim.h.debug b/z80sim/srcsim/sim.h.debug index 590c2389..5acb4317 100644 --- a/z80sim/srcsim/sim.h.debug +++ b/z80sim/srcsim/sim.h.debug @@ -17,8 +17,10 @@ #define CPU_SPEED 0 /* default CPU speed 0=unlimited */ /*#define ALT_I8080*/ /* use alt. 8080 sim. primarily optimized for size */ /*#define ALT_Z80*/ /* use alt. Z80 sim. primarily optimized for size */ -/*#define UNDOC_INST*/ /* compile undocumented instructions */ +/*#define UNDOC_INST*/ /* compile undocumented instrs. (required by ALT_*) */ +#ifndef EXCLUDE_Z80 /*#define FAST_BLOCK*/ /* much faster but not accurate Z80 block instr. */ +#endif #define WANT_ICE /* attach ICE to headless machine */ #ifdef WANT_ICE diff --git a/z80sim/srcsim/sim.h.fast b/z80sim/srcsim/sim.h.fast index 21b9843e..73d1d813 100644 --- a/z80sim/srcsim/sim.h.fast +++ b/z80sim/srcsim/sim.h.fast @@ -18,8 +18,10 @@ #define CPU_SPEED 0 /* default CPU speed 0=unlimited */ /*#define ALT_I8080*/ /* use alt. 8080 sim. primarily optimized for size */ /*#define ALT_Z80*/ /* use alt. Z80 sim. primarily optimized for size */ -#define UNDOC_INST /* compile undocumented instructions */ +#define UNDOC_INST /* compile undocumented instrs. (required by ALT_*) */ +#ifndef EXCLUDE_Z80 #define FAST_BLOCK /* much faster but not accurate Z80 block instr. */ +#endif #define WANT_ICE /* attach ICE to headless machine */ #ifdef WANT_ICE From c3e054f2149647210a90486bd22a190909784892 Mon Sep 17 00:00:00 2001 From: Thomas Eberhardt Date: Sat, 14 Dec 2024 07:09:32 +0100 Subject: [PATCH 04/10] simice: clean-up optional features messages --- z80core/simice.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/z80core/simice.c b/z80core/simice.c index 6287bdd5..9cf5b508 100644 --- a/z80core/simice.c +++ b/z80core/simice.c @@ -864,21 +864,20 @@ static void print_reg(void) */ static void do_break(char *s) { -#if !defined(SBSIZE) && !defined(WANT_HB) - UNUSED(s); - - puts("Sorry, no breakpoints available"); - puts("Please recompile with SBSIZE and/or WANT_HB defined in sim.h"); -#else /* SBSIZE || WANT_HB */ +#if defined(SBSIZE) || defined(WANT_HB) WORD a; int n; #ifdef SBSIZE register int i; int hdr_flag; +#endif #endif -#ifdef WANT_HB if (*s == 'h') { +#ifndef WANT_HB + puts("Sorry, no hardware breakpoint available"); + puts("Please recompile with WANT_HB defined in sim.h"); +#else /* WANT_HB */ s++; if (*s == '\n') { if (hb_flag) { @@ -947,10 +946,13 @@ static void do_break(char *s) hb_addr = a; hb_mode = n; hb_flag = 1; +#endif /* WANT_HB */ return; } -#endif /* WANT_HB */ -#ifdef SBSIZE +#ifndef SBSIZE + puts("Sorry, no software breakpoints available"); + puts("Please recompile with SBSIZE defined in sim.h"); +#else /* SBSIZE */ if (*s == '\n') { hdr_flag = 0; for (i = 0; i < SBSIZE; i++) @@ -1042,7 +1044,6 @@ static void do_break(char *s) soft[i].sb_passcount = 0; } #endif /* SBSIZE */ -#endif /* SBSIZE || WANT_HB */ } /* @@ -1259,7 +1260,7 @@ static void do_show(void) #else i = 0; #endif - printf("T-State counting %spossible\n", i ? "" : "im"); + printf("T-State counting %spossible\n", i ? "" : "not "); } /* From 55da80b44bdcbc1ae2ee8611f689a6177351266f Mon Sep 17 00:00:00 2001 From: Thomas Eberhardt Date: Sat, 14 Dec 2024 07:26:25 +0100 Subject: [PATCH 05/10] sync with RP2xxx-GEEK-80 order --- z80sim/srcsim/simmem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/z80sim/srcsim/simmem.h b/z80sim/srcsim/simmem.h index a23ee569..3ce5eca6 100644 --- a/z80sim/srcsim/simmem.h +++ b/z80sim/srcsim/simmem.h @@ -60,8 +60,8 @@ static inline BYTE memrdr(WORD addr) data = memory[addr]; #ifdef BUS_8080 - cpu_bus |= CPU_WO | CPU_MEMR; cpu_bus &= ~CPU_M1; + cpu_bus |= CPU_WO | CPU_MEMR; #endif return data; From 800779e0e89bdceb252e970c28691ac0d3a87f98 Mon Sep 17 00:00:00 2001 From: Thomas Eberhardt Date: Sat, 14 Dec 2024 07:52:27 +0100 Subject: [PATCH 06/10] add hardware breakpoint support to picosim So we can test performance impact. --- picosim/srcsim/sim.h | 1 + picosim/srcsim/simmem.h | 40 ++++++++++++++++++++++++++++++++++++++-- z80sim/srcsim/simmem.h | 4 ++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/picosim/srcsim/sim.h b/picosim/srcsim/sim.h index f3f0f96d..7d5e6192 100644 --- a/picosim/srcsim/sim.h +++ b/picosim/srcsim/sim.h @@ -25,6 +25,7 @@ #define WANT_TIM /* count t-states */ #define HISIZE 100 /* number of entries in history */ #define SBSIZE 4 /* number of software breakpoints */ +#define WANT_HB /* hardware breakpoint */ #endif #if PICO_RP2040 diff --git a/picosim/srcsim/simmem.h b/picosim/srcsim/simmem.h index d00f14c4..7e9714ce 100644 --- a/picosim/srcsim/simmem.h +++ b/picosim/srcsim/simmem.h @@ -15,6 +15,13 @@ #include "sim.h" #include "simdefs.h" +#ifdef WANT_ICE +#include "simice.h" +#endif + +#ifdef BUS_8080 +#include "simglb.h" +#endif extern BYTE bnk0[65536], bnk1[49152]; extern BYTE selbnk; @@ -30,6 +37,15 @@ extern void init_memory(void), reset_memory(void); */ static inline void memwrt(WORD addr, BYTE data) { +#ifdef BUS_8080 + cpu_bus &= ~(CPU_M1 | CPU_WO | CPU_MEMR); +#endif + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr && (hb_mode & HB_WRITE)) + hb_trig = HB_WRITE; +#endif + if ((selbnk == 0) || (addr >= 0xc000)) { if (addr < 0xff00) bnk0[addr] = data; @@ -40,10 +56,30 @@ static inline void memwrt(WORD addr, BYTE data) static inline BYTE memrdr(WORD addr) { + register BYTE data; + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr) { + if (cpu_bus & CPU_M1) { + if (hb_mode & HB_EXEC) + hb_trig = HB_EXEC; + } else { + if (hb_mode & HB_READ) + hb_trig = HB_READ; + } + } +#endif if ((selbnk == 0) || (addr >= 0xc000)) - return bnk0[addr]; + data = bnk0[addr]; else - return bnk1[addr]; + data = bnk1[addr]; + +#ifdef BUS_8080 + cpu_bus &= ~CPU_M1; + cpu_bus |= CPU_WO | CPU_MEMR; +#endif + + return data; } /* diff --git a/z80sim/srcsim/simmem.h b/z80sim/srcsim/simmem.h index 3ce5eca6..08db58ce 100644 --- a/z80sim/srcsim/simmem.h +++ b/z80sim/srcsim/simmem.h @@ -21,6 +21,10 @@ #include "simice.h" #endif +#ifdef BUS_8080 +#include "simglb.h" +#endif + extern BYTE memory[65536]; extern void init_memory(void); From da0f20527ff1c2e0faf547ad2f89512240fd171d Mon Sep 17 00:00:00 2001 From: Thomas Eberhardt Date: Sat, 14 Dec 2024 08:22:43 +0100 Subject: [PATCH 07/10] simice: fixes for picosim Also check for '\0' for 'b' and 'bh'. Don't mix f* stdio calls with non-f*. --- z80core/simice.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/z80core/simice.c b/z80core/simice.c index 9cf5b508..d2ebac9c 100644 --- a/z80core/simice.c +++ b/z80core/simice.c @@ -369,7 +369,7 @@ static int handle_break(void) fputs("write", stdout); else fputs("execute", stdout); - printf(" access to %04x\n", hb_addr); + fprintf(stdout, " access to %04x\n", hb_addr); hb_trig = 0; cpu_error = NONE; return 0; @@ -879,7 +879,7 @@ static void do_break(char *s) puts("Please recompile with WANT_HB defined in sim.h"); #else /* WANT_HB */ s++; - if (*s == '\n') { + if (*s == '\n' || *s == '\0') { if (hb_flag) { fputs("Hardware breakpoint set with ", stdout); n = 0; @@ -889,16 +889,17 @@ static void do_break(char *s) } if (hb_mode & HB_WRITE) { if (n) - putchar('/'); + fputc('/', stdout); fputs("write", stdout); n = 1; } if (hb_mode & HB_EXEC) { if (n) - putchar('/'); + fputc('/', stdout); fputs("execute", stdout); } - printf(" access trigger to %04x\n", hb_addr); + fprintf(stdout, " access trigger to %04x\n", + hb_addr); } else puts("No hardware breakpoint set"); return; @@ -953,7 +954,7 @@ static void do_break(char *s) puts("Sorry, no software breakpoints available"); puts("Please recompile with SBSIZE defined in sim.h"); #else /* SBSIZE */ - if (*s == '\n') { + if (*s == '\n' || *s == '\0') { hdr_flag = 0; for (i = 0; i < SBSIZE; i++) if (soft[i].sb_pass) { From 1ecff8c38f1fdc3a6abeb7b242a3a4bf4097d9e5 Mon Sep 17 00:00:00 2001 From: Thomas Eberhardt Date: Sat, 14 Dec 2024 11:42:58 +0100 Subject: [PATCH 08/10] add hardware breakpoint support to all simulators Add line to CREDITS, and copyright/history for previous commits. --- altairsim/srcsim/sim.h | 4 +++- altairsim/srcsim/simmem.h | 38 +++++++++++++++++++++++++++++--- cpmsim/srcsim/sim.h | 3 ++- cpmsim/srcsim/simmem.h | 44 ++++++++++++++++++++++++++++++++++--- cromemcosim/srcsim/sim.h | 4 +++- cromemcosim/srcsim/simmem.h | 38 +++++++++++++++++++++++++++++--- doc/CREDITS | 1 + imsaisim/srcsim/sim.h | 4 +++- imsaisim/srcsim/simmem.h | 38 +++++++++++++++++++++++++++++--- intelmdssim/srcsim/sim.h | 4 +++- intelmdssim/srcsim/simmem.h | 42 +++++++++++++++++++++++++++++++++-- mosteksim/srcsim/sim.h | 2 ++ mosteksim/srcsim/simmem.h | 42 +++++++++++++++++++++++++++++++++-- picosim/srcsim/simmem.h | 2 ++ z80sim/srcsim/simmem.h | 2 ++ 15 files changed, 247 insertions(+), 21 deletions(-) diff --git a/altairsim/srcsim/sim.h b/altairsim/srcsim/sim.h index d5f472b2..e8643355 100644 --- a/altairsim/srcsim/sim.h +++ b/altairsim/srcsim/sim.h @@ -24,6 +24,7 @@ * 21-AUG-2018 improved memory configuration * 29-AUG-2021 new memory configuration sections * 09-MAY-2024 added more defines for conditional compiling components + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIM_INC @@ -47,7 +48,8 @@ #ifdef WANT_ICE /*#define WANT_TIM*/ /* don't count t-states */ /*#define HISIZE 1000*//* no history */ -/*#define SBSIZE 10*/ /* no breakpoints */ +/*#define SBSIZE 10*/ /* no software breakpoints */ +/*#define WANT_HB*/ /* no hardware breakpoint */ #endif #define HAS_DAZZLER /* has simulated I/O for Cromemco Dazzler */ diff --git a/altairsim/srcsim/simmem.h b/altairsim/srcsim/simmem.h index 539804ea..83d2d16b 100644 --- a/altairsim/srcsim/simmem.h +++ b/altairsim/srcsim/simmem.h @@ -3,6 +3,7 @@ * * Copyright (C) 2016-2021 Udo Munk * Copyright (C) 2021 David McNaughton + * Copyright (C) 2024 Thomas Eberhardt * * This module implements memory management for an Altair 8800 system * @@ -17,6 +18,7 @@ * 04-NOV-2019 add functions for direct memory access * 31-JUL-2021 allow building machine without frontpanel * 29-AUG-2021 new memory configuration sections + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIMMEM_INC @@ -24,11 +26,16 @@ #include "sim.h" #include "simdefs.h" +#ifdef WANT_ICE +#include "simice.h" +#endif #include "tarbell_fdc.h" -#ifdef FRONTPANEL +#if defined(FRONTPANEL) || defined(BUS_8080) #include "simglb.h" +#endif +#ifdef FRONTPANEL #include "simctl.h" #include "frontpanel.h" #endif @@ -67,6 +74,9 @@ extern void init_memory(void); static inline void memwrt(WORD addr, BYTE data) { #ifdef BUS_8080 +#ifndef FRONTPANEL + cpu_bus &= ~CPU_M1; +#endif cpu_bus &= ~(CPU_WO | CPU_MEMR); #endif @@ -77,7 +87,13 @@ static inline void memwrt(WORD addr, BYTE data) fp_led_data = 0xff; fp_sampleData(); wait_step(); - } + } else + cpu_bus &= ~CPU_M1; +#endif + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr && (hb_mode & HB_WRITE)) + hb_trig = HB_WRITE; #endif if (p_tab[addr >> 8] == MEM_RW) { @@ -90,6 +106,18 @@ static inline BYTE memrdr(WORD addr) { register BYTE data; +#ifdef WANT_HB + if (hb_flag && hb_addr == addr) { + if (cpu_bus & CPU_M1) { + if (hb_mode & HB_EXEC) + hb_trig = HB_EXEC; + } else { + if (hb_mode & HB_READ) + hb_trig = HB_READ; + } + } +#endif + if (tarbell_rom_active && tarbell_rom_enabled) { if (addr <= 0x001f) { data = tarbell_rom[addr]; @@ -108,6 +136,9 @@ static inline BYTE memrdr(WORD addr) } #ifdef BUS_8080 +#ifndef FRONTPANEL + cpu_bus &= ~CPU_M1; +#endif cpu_bus |= CPU_WO | CPU_MEMR; #endif @@ -118,7 +149,8 @@ static inline BYTE memrdr(WORD addr) fp_led_data = data; fp_sampleData(); wait_step(); - } + } else + cpu_bus &= ~CPU_M1; #endif return data; diff --git a/cpmsim/srcsim/sim.h b/cpmsim/srcsim/sim.h index 2cf62769..6b1dcde3 100644 --- a/cpmsim/srcsim/sim.h +++ b/cpmsim/srcsim/sim.h @@ -24,7 +24,8 @@ #ifdef WANT_ICE /*#define WANT_TIM*/ /* don't count t-states */ /*#define HISIZE 1000*//* no history */ -/*#define SBSIZE 10*/ /* no breakpoints */ +/*#define SBSIZE 10*/ /* no software breakpoints */ +/*#define WANT_HB*/ /* no hardware breakpoint */ #endif #define HAS_DISKS /* uses disk images */ diff --git a/cpmsim/srcsim/simmem.h b/cpmsim/srcsim/simmem.h index 07c64502..39eb53b3 100644 --- a/cpmsim/srcsim/simmem.h +++ b/cpmsim/srcsim/simmem.h @@ -28,6 +28,7 @@ * 03-FEB-2017 added ROM initialization * 09-APR-2018 modified MMU write protect port as used by Alan Cox for FUZIX * 04-NOV-2019 add functions for direct memory access + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIMMEM_INC @@ -35,6 +36,13 @@ #include "sim.h" #include "simdefs.h" +#ifdef WANT_ICE +#include "simice.h" +#endif + +#ifdef BUS_8080 +#include "simglb.h" +#endif #define MAXSEG 16 /* max. number of memory banks */ #define SEGSIZ 49152 /* default size of one bank = 48 KBytes */ @@ -49,6 +57,15 @@ extern int selbnk, maxbnk, segsize, wp_common; */ static inline void memwrt(WORD addr, BYTE data) { +#ifdef BUS_8080 + cpu_bus &= ~(CPU_M1 | CPU_WO | CPU_MEMR); +#endif + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr && (hb_mode & HB_WRITE)) + hb_trig = HB_WRITE; +#endif + if ((addr >= segsize) && (wp_common != 0)) { wp_common |= 0x80; #ifndef EXCLUDE_Z80 @@ -70,13 +87,34 @@ static inline void memwrt(WORD addr, BYTE data) static inline BYTE memrdr(WORD addr) { + register BYTE data; + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr) { + if (cpu_bus & CPU_M1) { + if (hb_mode & HB_EXEC) + hb_trig = HB_EXEC; + } else { + if (hb_mode & HB_READ) + hb_trig = HB_READ; + } + } +#endif + if (selbnk == 0) - return *(memory[0] + addr); + data = *(memory[0] + addr); if (addr >= segsize) - return *(memory[0] + addr); + data = *(memory[0] + addr); else - return *(memory[selbnk] + addr); + data = *(memory[selbnk] + addr); + +#ifdef BUS_8080 + cpu_bus &= ~CPU_M1; + cpu_bus |= CPU_WO | CPU_MEMR; +#endif + + return data; } /* diff --git a/cromemcosim/srcsim/sim.h b/cromemcosim/srcsim/sim.h index 24ee5c16..4b5c8bce 100644 --- a/cromemcosim/srcsim/sim.h +++ b/cromemcosim/srcsim/sim.h @@ -26,6 +26,7 @@ * 14-JUL-2022 added generic AT modem and HAL * 09-MAY-2024 added more defines for conditional compiling components * 15-MAY-2024 make disk manager standard + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIM_INC @@ -48,7 +49,8 @@ #ifdef WANT_ICE /*#define WANT_TIM*/ /* don't count t-states */ /*#define HISIZE 1000*//* no history */ -/*#define SBSIZE 10*/ /* no breakpoints */ +/*#define SBSIZE 10*/ /* no software breakpoints */ +/*#define WANT_HB*/ /* no hardware breakpoint */ #endif #define HAS_DAZZLER /* has simulated I/O for Cromemco Dazzler */ diff --git a/cromemcosim/srcsim/simmem.h b/cromemcosim/srcsim/simmem.h index 8a4dc59a..ff6b6b21 100644 --- a/cromemcosim/srcsim/simmem.h +++ b/cromemcosim/srcsim/simmem.h @@ -3,6 +3,7 @@ * * Copyright (C) 2016-2022 Udo Munk * Copyright (C) 2021 David McNaughton + * Copyright (C) 2024 Thomas Eberhardt * * This module implements memory management for a Cromemco Z-1 system * @@ -16,6 +17,7 @@ * 17-JUN-2021 allow building machine without frontpanel * 30-AUG-2021 new memory configuration sections * 02-SEP-2021 implement banked ROM + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIMMEM_INC @@ -23,11 +25,16 @@ #include "sim.h" #include "simdefs.h" +#ifdef WANT_ICE +#include "simice.h" +#endif #include "cromemco-fdc.h" -#ifdef FRONTPANEL +#if defined(FRONTPANEL) || defined(BUS_8080) #include "simglb.h" +#endif +#ifdef FRONTPANEL #include "simctl.h" #include "frontpanel.h" #endif @@ -84,6 +91,9 @@ static inline void memwrt(WORD addr, BYTE data) register int i; #ifdef BUS_8080 +#ifndef FRONTPANEL + cpu_bus &= ~CPU_M1; +#endif cpu_bus &= ~(CPU_WO | CPU_MEMR); #endif @@ -94,7 +104,13 @@ static inline void memwrt(WORD addr, BYTE data) fp_led_data = data; fp_sampleData(); wait_step(); - } + } else + cpu_bus &= ~CPU_M1; +#endif + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr && (hb_mode & HB_WRITE)) + hb_trig = HB_WRITE; #endif if (fdc_rom_active && (addr >> 13) == 0x6) { /* Covers C000 to DFFF */ @@ -118,6 +134,18 @@ static inline BYTE memrdr(WORD addr) { register BYTE data; +#ifdef WANT_HB + if (hb_flag && hb_addr == addr) { + if (cpu_bus & CPU_M1) { + if (hb_mode & HB_EXEC) + hb_trig = HB_EXEC; + } else { + if (hb_mode & HB_READ) + hb_trig = HB_READ; + } + } +#endif + if (fdc_rom_active && (addr >> 13) == 0x6) { /* Covers C000 to DFFF */ data = *(fdc_banked_rom + addr - 0xC000); } else if (selbnk || p_tab[addr >> 8] != MEM_NONE) { @@ -127,6 +155,9 @@ static inline BYTE memrdr(WORD addr) } #ifdef BUS_8080 +#ifndef FRONTPANEL + cpu_bus &= ~CPU_M1; +#endif cpu_bus |= CPU_WO | CPU_MEMR; #endif @@ -137,7 +168,8 @@ static inline BYTE memrdr(WORD addr) fp_led_data = data; fp_sampleData(); wait_step(); - } + } else + cpu_bus &= ~CPU_M1; #endif return data; diff --git a/doc/CREDITS b/doc/CREDITS index b61ccc58..079d3df8 100644 --- a/doc/CREDITS +++ b/doc/CREDITS @@ -59,3 +59,4 @@ For a simpler 8080/Z80 DAA instruction implementation that passes regression tests. For the implementation of the Intel Intellec MDS-800 system. For the rewrite of the disassembler. +For the implementation of a hardware breakpoint in the ICE. diff --git a/imsaisim/srcsim/sim.h b/imsaisim/srcsim/sim.h index b721c334..9db1d6fb 100644 --- a/imsaisim/srcsim/sim.h +++ b/imsaisim/srcsim/sim.h @@ -25,6 +25,7 @@ * 29-AUG-2021 new memory configuration sections * 09-MAY-2024 added more defines for conditional compiling components * 15-MAY-2024 make disk manager standard + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIM_INC @@ -48,7 +49,8 @@ #ifdef WANT_ICE /*#define WANT_TIM*/ /* don't count t-states */ /*#define HISIZE 1000*//* no history */ -/*#define SBSIZE 10*/ /* no breakpoints */ +/*#define SBSIZE 10*/ /* no software breakpoints */ +/*#define WANT_HB*/ /* no hardware breakpoint */ #endif #define UNIX_TERMINAL /* uses a UNIX terminal emulation */ diff --git a/imsaisim/srcsim/simmem.h b/imsaisim/srcsim/simmem.h index 22c47839..9ff50f3b 100644 --- a/imsaisim/srcsim/simmem.h +++ b/imsaisim/srcsim/simmem.h @@ -3,6 +3,7 @@ * * Copyright (C) 2016-2021 Udo Munk * Copyright (C) 2018-2021 David McNaughton + * Copyright (C) 2024 Thomas Eberhardt * * This module implements memory management for an IMSAI 8080 system * @@ -20,6 +21,7 @@ * 14-AUG-2020 allow building machine without frontpanel * 20-JUL-2021 log banked memory * 29-AUG-2021 new memory configuration sections + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIMMEM_INC @@ -27,9 +29,14 @@ #include "sim.h" #include "simdefs.h" +#ifdef WANT_ICE +#include "simice.h" +#endif -#ifdef FRONTPANEL +#if defined(FRONTPANEL) || defined(BUS_8080) #include "simglb.h" +#endif +#ifdef FRONTPANEL #include "simctl.h" #include "frontpanel.h" #endif @@ -106,6 +113,9 @@ extern void groupswap(void); static inline void memwrt(WORD addr, BYTE data) { #ifdef BUS_8080 +#ifndef FRONTPANEL + cpu_bus &= ~CPU_M1; +#endif cpu_bus &= ~(CPU_WO | CPU_MEMR); #endif @@ -116,7 +126,13 @@ static inline void memwrt(WORD addr, BYTE data) fp_led_data = data; fp_sampleData(); wait_step(); - } + } else + cpu_bus &= ~CPU_M1; +#endif + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr && (hb_mode & HB_WRITE)) + hb_trig = HB_WRITE; #endif if ((selbnk == 0) || (addr >= SEGSIZ)) { @@ -132,6 +148,18 @@ static inline BYTE memrdr(WORD addr) { register BYTE data; +#ifdef WANT_HB + if (hb_flag && hb_addr == addr) { + if (cpu_bus & CPU_M1) { + if (hb_mode & HB_EXEC) + hb_trig = HB_EXEC; + } else { + if (hb_mode & HB_READ) + hb_trig = HB_READ; + } + } +#endif + if ((selbnk == 0) || (addr >= SEGSIZ)) { if (p_tab[addr >> 8] != MEM_NONE) { data = _MEMMAPPED(addr); @@ -143,6 +171,9 @@ static inline BYTE memrdr(WORD addr) } #ifdef BUS_8080 +#ifndef FRONTPANEL + cpu_bus &= ~CPU_M1; +#endif cpu_bus |= CPU_WO | CPU_MEMR; #endif @@ -153,7 +184,8 @@ static inline BYTE memrdr(WORD addr) fp_led_data = data; fp_sampleData(); wait_step(); - } + } else + cpu_bus &= ~CPU_M1; #endif if (cyclecount && --cyclecount == 0) diff --git a/intelmdssim/srcsim/sim.h b/intelmdssim/srcsim/sim.h index d5ba18f4..3de1cf6f 100644 --- a/intelmdssim/srcsim/sim.h +++ b/intelmdssim/srcsim/sim.h @@ -8,6 +8,7 @@ * * History: * 03-JUN-2024 first version + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIM_INC @@ -32,7 +33,8 @@ #ifdef WANT_ICE /*#define WANT_TIM*/ /* don't count t-states */ /*#define HISIZE 1000*//* no history */ -/*#define SBSIZE 10*/ /* no breakpoints */ +/*#define SBSIZE 10*/ /* no software breakpoints */ +/*#define WANT_HB*/ /* no hardware breakpoint */ #endif #define HAS_DISKS /* uses disk images */ diff --git a/intelmdssim/srcsim/simmem.h b/intelmdssim/srcsim/simmem.h index a726a709..11b3537c 100644 --- a/intelmdssim/srcsim/simmem.h +++ b/intelmdssim/srcsim/simmem.h @@ -9,6 +9,7 @@ * * History: * 03-JUN-2024 first version + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIMMEM_INC @@ -16,8 +17,15 @@ #include "sim.h" #include "simdefs.h" +#ifdef WANT_ICE +#include "simice.h" +#endif #include "simctl.h" +#ifdef BUS_8080 +#include "simglb.h" +#endif + #define BOOT_SIZE 256 /* bootstrap ROM size */ #define MON_SIZE 2048 /* monitor ROM size */ @@ -32,16 +40,46 @@ extern void init_memory(void); */ static inline void memwrt(WORD addr, BYTE data) { +#ifdef BUS_8080 + cpu_bus &= ~(CPU_M1 | CPU_WO | CPU_MEMR); +#endif + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr && (hb_mode & HB_WRITE)) + hb_trig = HB_WRITE; +#endif + if (!mon_enabled || addr < 65536 - MON_SIZE) memory[addr] = data; } static inline BYTE memrdr(WORD addr) { + register BYTE data; + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr) { + if (cpu_bus & CPU_M1) { + if (hb_mode & HB_EXEC) + hb_trig = HB_EXEC; + } else { + if (hb_mode & HB_READ) + hb_trig = HB_READ; + } + } +#endif + if (boot_switch && addr < BOOT_SIZE) - return boot_rom[addr]; + data = boot_rom[addr]; else - return memory[addr]; + data = memory[addr]; + +#ifdef BUS_8080 + cpu_bus &= ~CPU_M1; + cpu_bus |= CPU_WO | CPU_MEMR; +#endif + + return data; } /* diff --git a/mosteksim/srcsim/sim.h b/mosteksim/srcsim/sim.h index 0e1cbaf0..0e936daa 100644 --- a/mosteksim/srcsim/sim.h +++ b/mosteksim/srcsim/sim.h @@ -11,6 +11,7 @@ * computers. * 27-SEP-2019 (Udo Munk) modified for integration into 1.37 * 25-APR-2024 (Udo Munk) this was a Z80 machine and we can exclude 8080 now + * 14-DEC-2024 (Thomas Eberhardt) added hardware breakpoint support */ #ifndef SIM_INC @@ -35,6 +36,7 @@ #define WANT_TIM /* count t-states */ #define HISIZE 100 /* number of entries in history */ #define SBSIZE 4 /* number of software breakpoints */ +#define WANT_HB /* hardware breakpoint */ #endif #define HAS_DISKS /* uses disk images */ diff --git a/mosteksim/srcsim/simmem.h b/mosteksim/srcsim/simmem.h index 8c3e7595..04ec513d 100644 --- a/mosteksim/srcsim/simmem.h +++ b/mosteksim/srcsim/simmem.h @@ -2,6 +2,7 @@ * Z80SIM - a Z80-CPU simulator * * Copyright (C) 2019 by Mike Douglas + * Copyright (C) 2024 Thomas Eberhardt * * This module implements memory management for mosteksim * @@ -10,6 +11,7 @@ * directory. Emulate memory of the Mostek AID-80F and SYS-80FT * computers by treating 0xe000-0xefff as ROM. * 04-NOV-2019 (Udo Munk) add functions for direct memory access + * 14-DEC-2024 (Thomas Eberhardt) added hardware breakpoint support */ #ifndef SIMMEM_INC @@ -17,7 +19,13 @@ #include "sim.h" #include "simdefs.h" -#include "simmem.h" +#ifdef WANT_ICE +#include "simice.h" +#endif + +#ifdef BUS_8080 +#include "simglb.h" +#endif #define MAXMEMSECT 0 @@ -30,13 +38,43 @@ extern void init_memory(void); */ static inline void memwrt(WORD addr, BYTE data) { +#ifdef BUS_8080 + cpu_bus &= ~(CPU_M1 | CPU_WO | CPU_MEMR); +#endif + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr && (hb_mode & HB_WRITE)) + hb_trig = HB_WRITE; +#endif + if ((addr & 0xf000) != 0xe000) memory[addr] = data; } static inline BYTE memrdr(WORD addr) { - return memory[addr]; + register BYTE data; + +#ifdef WANT_HB + if (hb_flag && hb_addr == addr) { + if (cpu_bus & CPU_M1) { + if (hb_mode & HB_EXEC) + hb_trig = HB_EXEC; + } else { + if (hb_mode & HB_READ) + hb_trig = HB_READ; + } + } +#endif + + data = memory[addr]; + +#ifdef BUS_8080 + cpu_bus &= ~CPU_M1; + cpu_bus |= CPU_WO | CPU_MEMR; +#endif + + return data; } /* diff --git a/picosim/srcsim/simmem.h b/picosim/srcsim/simmem.h index 7e9714ce..17781b9d 100644 --- a/picosim/srcsim/simmem.h +++ b/picosim/srcsim/simmem.h @@ -2,12 +2,14 @@ * Z80SIM - a Z80-CPU simulator * * Copyright (C) 2024 by Udo Munk + * Copyright (C) 2024 by Thomas Eberhardt * * This module implements memory management for the Z80/8080 CPU. * * History: * 23-APR-2024 derived from z80sim * 29-JUN-2024 implemented banked memory + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIMMEM_INC diff --git a/z80sim/srcsim/simmem.h b/z80sim/srcsim/simmem.h index 08db58ce..3ad10f7a 100644 --- a/z80sim/srcsim/simmem.h +++ b/z80sim/srcsim/simmem.h @@ -2,6 +2,7 @@ * Z80SIM - a Z80-CPU simulator * * Copyright (C) 2016-2019 by Udo Munk + * Copyright (C) 2024 by Thomas Eberhardt * * This module implements memory management for z80sim * @@ -10,6 +11,7 @@ * 03-FEB-2017 added ROM initialization * 15-AUG-2017 don't use macros, use inline functions that coerce appropriate * 04-NOV-2019 add functions for direct memory access + * 14-DEC-2024 added hardware breakpoint support */ #ifndef SIMMEM_INC From 59551f2fa7c90af31165f7b212fa081c3c0e81c7 Mon Sep 17 00:00:00 2001 From: Thomas Eberhardt Date: Sat, 14 Dec 2024 17:24:28 +0100 Subject: [PATCH 09/10] fix single step software breakpoint handling uninstall_softbp() was in the wrong place, would lead to loss of original instruction... --- z80core/simice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/z80core/simice.c b/z80core/simice.c index d2ebac9c..c4621357 100644 --- a/z80core/simice.c +++ b/z80core/simice.c @@ -239,9 +239,9 @@ static void do_step(void) { install_softbp(); step_cpu(); - uninstall_softbp(); if (cpu_error == OPHALT) (void) handle_break(); + uninstall_softbp(); report_cpu_error(); print_head(); print_reg(); From 5eea509e80df681619f62b117b9c32cac3fb1f97 Mon Sep 17 00:00:00 2001 From: Thomas Eberhardt Date: Sat, 14 Dec 2024 17:29:11 +0100 Subject: [PATCH 10/10] add blank line --- picosim/srcsim/simmem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/picosim/srcsim/simmem.h b/picosim/srcsim/simmem.h index 17781b9d..92174dff 100644 --- a/picosim/srcsim/simmem.h +++ b/picosim/srcsim/simmem.h @@ -71,6 +71,7 @@ static inline BYTE memrdr(WORD addr) } } #endif + if ((selbnk == 0) || (addr >= 0xc000)) data = bnk0[addr]; else