From 8c5df1c57edfd103743bf4a4ba5a1efffdabc366 Mon Sep 17 00:00:00 2001 From: Patrick Linstruth Date: Sun, 14 Jan 2024 10:24:25 -0500 Subject: [PATCH] AltairZ80: Adds SET CPU RESIZEMEMORY and other Changing the CPU type or MEMORY size/configuration causes memory resources mapped by other devices to be removed. This is not made clear by "HELP CPU" and the user has no feedback that this is happening. This PR does the following: 1) HELP SET CPU shows that SET CPU MEMORY requires a value. 2) Feedback is provided if the value is omitted or not properly formatted. 3) Unmapped memory resources caused by a SET CPU command are displayed on the SIMH console. 4) Adds a SET CPU RESIZEMEMORY command that resizes system memory without unmapping other device memory resources. --- AltairZ80/altairz80_cpu.c | 64 +++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/AltairZ80/altairz80_cpu.c b/AltairZ80/altairz80_cpu.c index 9afd4ce95..a5c325a92 100644 --- a/AltairZ80/altairz80_cpu.c +++ b/AltairZ80/altairz80_cpu.c @@ -164,12 +164,14 @@ static t_stat cpu_set_nonbanked (UNIT *uptr, int32 value, CONST char *cptr, static t_stat cpu_set_ramtype (UNIT *uptr, int32 value, CONST char *cptr, void *desc); static t_stat cpu_set_chiptype (UNIT *uptr, int32 value, CONST char *cptr, void *desc); static t_stat cpu_set_size (UNIT *uptr, int32 value, CONST char *cptr, void *desc); +static t_stat set_size (uint32 size, t_bool unmap); static t_stat m68k_set_chiptype (UNIT * uptr, int32 value, CONST char* cptr, void* desc); static t_stat cpu_set_memory (UNIT *uptr, int32 value, CONST char *cptr, void *desc); +static t_stat cpu_resize_memory (UNIT *uptr, int32 value, CONST char *cptr, void *desc); static t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc); static t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc); static t_stat cpu_clear_command (UNIT *uptr, int32 value, CONST char *cptr, void *desc); -static void cpu_clear(void); +static void cpu_clear(t_bool unmap); static t_stat cpu_show (FILE *st, UNIT *uptr, int32 val, CONST void *desc); static t_stat chip_show (FILE *st, UNIT *uptr, int32 val, CONST void *desc); static t_stat cpu_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); @@ -536,13 +538,15 @@ static MTAB cpu_mod[] = { { UNIT_CPU_VERBOSE, 0, "QUIET", "QUIET", NULL, NULL, NULL, "Disable verbose messages" }, { MTAB_VDV, 0, NULL, "CLEARMEMORY", &cpu_clear_command, - NULL, NULL, "Clears the RAM" }, + NULL, NULL, "Clears the RAM and removes mapped memory handlers" }, { UNIT_CPU_MMU, UNIT_CPU_MMU, "MMU", "MMU", NULL, NULL, NULL, "Enable the Memory Management Unit for 8080 / Z80" }, { UNIT_CPU_MMU, 0, "NOMMU", "NOMMU", &cpu_set_nommu, NULL, NULL, "Disable the Memory Management Unit for 8080 / Z80" }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "MEMORY", &cpu_set_memory, - NULL, NULL, "Sets the RAM size for 8080 / Z80 / 8086" }, + { MTAB_XTD | MTAB_VDV | MTAB_VALR, 0, NULL, "MEMORY", &cpu_set_memory, + NULL, NULL, "Sets the RAM size and removes mapped memory handlers for 8080 / Z80 / 8086" }, + { MTAB_XTD | MTAB_VDV | MTAB_VALR, 0, NULL, "RESIZEMEMORY", &cpu_resize_memory, + NULL, NULL, "Sets the RAM size without removing mapped memory handlers for 8080 / Z80 / 8086" }, { UNIT_CPU_SWITCHER, UNIT_CPU_SWITCHER, "SWITCHER", "SWITCHER", &cpu_set_switcher, &cpu_show_switcher, NULL, "Sets CPU switcher port for 8080 / Z80 / 8086" }, { UNIT_CPU_SWITCHER, 0, "NOSWITCHER", "NOSWITCHER", &cpu_reset_switcher, &cpu_show_switcher, @@ -6700,14 +6704,19 @@ static t_stat cpu_show(FILE *st, UNIT *uptr, int32 val, CONST void *desc) { return SCPE_OK; } -static void cpu_clear(void) { +static void cpu_clear(t_bool unmap) { uint32 i; for (i = 0; i < MAXMEMORY; i++) M[i] = 0; for (i = 0; i < (MAXMEMORY >> LOG2PAGESIZE); i++) - mmu_table[i] = RAM_PAGE; + if (!mmu_table[i].routine || unmap) { + if (mmu_table[i].routine) + sim_printf("Unmapping memory 0x%05x, handler=%s\n", i << LOG2PAGESIZE, mmu_table[i].name); + mmu_table[i] = RAM_PAGE; + } for (i = (MEMORYSIZE >> LOG2PAGESIZE); i < (MAXMEMORY >> LOG2PAGESIZE); i++) - mmu_table[i] = EMPTY_PAGE; + if (!mmu_table[i].routine || unmap) + mmu_table[i] = EMPTY_PAGE; if (cpu_unit.flags & UNIT_CPU_ALTAIRROM) install_ALTAIRbootROM(); m68k_clear_memory(); @@ -6715,7 +6724,7 @@ static void cpu_clear(void) { } static t_stat cpu_clear_command(UNIT *uptr, int32 value, CONST char *cptr, void *desc) { - cpu_clear(); + cpu_clear(TRUE); return SCPE_OK; } @@ -6754,7 +6763,7 @@ static t_stat cpu_set_banked(UNIT *uptr, int32 value, CONST char *cptr, void *de previousCapacity = MEMORYSIZE; MEMORYSIZE = MAXMEMORY; cpu_dev.awidth = MAXBANKSIZELOG2 + MAXBANKSLOG2; - cpu_clear(); + cpu_clear(TRUE); } else if (chiptype == CHIP_TYPE_8086) { sim_printf("Cannot use banked memory for 8086 CPU.\n"); return SCPE_ARG; @@ -6766,7 +6775,7 @@ static t_stat cpu_set_nonbanked(UNIT *uptr, int32 value, CONST char *cptr, void if ((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80)) { MEMORYSIZE = previousCapacity; cpu_dev.awidth = MAXBANKSIZELOG2; - cpu_clear(); + cpu_clear(TRUE); } return SCPE_OK; } @@ -6904,7 +6913,7 @@ static void cpu_set_chiptype_short(const int32 value) { static t_stat cpu_set_chiptype(UNIT *uptr, int32 value, CONST char *cptr, void *desc) { cpu_set_chiptype_short(value); - cpu_clear(); + cpu_clear(TRUE); return SCPE_OK; } @@ -7037,7 +7046,7 @@ static t_stat cpu_set_ramtype(UNIT *uptr, int32 value, CONST char *cptr, void *d } /* set memory to 'size' kilo byte */ -static t_stat set_size(uint32 size) { +static t_stat set_size(uint32 size, t_bool unmap) { uint32 maxsize; if (chiptype == CHIP_TYPE_M68K) { // ignore for M68K if (cpu_unit.flags & UNIT_CPU_VERBOSE) @@ -7059,23 +7068,40 @@ static t_stat set_size(uint32 size) { cpu_dev.awidth = MAXBANKSIZELOG2; if (size > MAXBANKSIZE) cpu_dev.awidth += MAXBANKSLOG2; - cpu_clear(); + cpu_clear(unmap); return SCPE_OK; } static t_stat cpu_set_size(UNIT *uptr, int32 value, CONST char *cptr, void *desc) { - return set_size(value); + return set_size(value, TRUE); } static t_stat cpu_set_memory(UNIT *uptr, int32 value, CONST char *cptr, void *desc) { uint32 size, result, i; - if (cptr == NULL) - return SCPE_ARG; + if (cptr == NULL) { + sim_printf("Memory size must be provided as SET CPU MEMORY=xK\n"); + return SCPE_ARG | SCPE_NOMESSAGE; + } + result = sscanf(cptr, "%i%n", &size, &i); + if ((result == 1) && (cptr[i] == 'K') && ((cptr[i + 1] == 0) || + ((cptr[i + 1] == 'B') && (cptr[i + 2] == 0)))) + return set_size(size, TRUE); + sim_printf("Memory size must be specified as xK\n"); + return SCPE_ARG | SCPE_NOMESSAGE; +} + +static t_stat cpu_resize_memory(UNIT *uptr, int32 value, CONST char *cptr, void *desc) { + uint32 size, result, i; + if (cptr == NULL) { + sim_printf("Memory size must be provided as SET CPU RESIZEMEMORY=xK\n"); + return SCPE_ARG | SCPE_NOMESSAGE; + } result = sscanf(cptr, "%i%n", &size, &i); if ((result == 1) && (cptr[i] == 'K') && ((cptr[i + 1] == 0) || ((cptr[i + 1] == 'B') && (cptr[i + 2] == 0)))) - return set_size(size); - return SCPE_ARG; + return set_size(size, FALSE); + sim_printf("Memory size must be specified as xK\n"); + return SCPE_ARG | SCPE_NOMESSAGE; } static t_stat m68k_set_chiptype(UNIT* uptr, int32 value, CONST char* cptr, void* desc) { @@ -7233,7 +7259,7 @@ t_value altairz80_pc_value (void) { /* AltairZ80 Simulator initialization */ void altairz80_init(void) { - cpu_clear(); + cpu_clear(TRUE); sim_vm_pc_value = &altairz80_pc_value; /* altairz80_print_tables(); */ }