ALTAIRZ80: Add "SET CPU HISTORY" and "SHOW CPU HISTORY" for 8080/Z80
This commit is contained in:
parent
7082e212ea
commit
807005553b
1 changed files with 197 additions and 1 deletions
|
@ -41,6 +41,8 @@
|
|||
#define PCQ_MASK (PCQ_SIZE - 1)
|
||||
#define PCQ_ENTRY(PC) if (pcq[pcq_p] != (PC)) { pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = (PC); }
|
||||
|
||||
#define INST_MAX_BYTES 4 /* instruction max bytes */
|
||||
|
||||
#define FLAG_C 1
|
||||
#define FLAG_N 2
|
||||
#define FLAG_P 4
|
||||
|
@ -50,6 +52,7 @@
|
|||
|
||||
#define SETFLAG(f,c) AF = (c) ? AF | FLAG_ ## f : AF & ~FLAG_ ## f
|
||||
#define TSTFLAG(f) ((AF & FLAG_ ## f) != 0)
|
||||
#define TSTFLAG2(a, f) ((a & FLAG_ ## f) != 0)
|
||||
|
||||
#define LOW_DIGIT(x) ((x) & 0xf)
|
||||
#define HIGH_DIGIT(x) (((x) >> 4) & 0xf)
|
||||
|
@ -158,6 +161,8 @@ static t_stat cpu_set_ramtype (UNIT *uptr, int32 value, CONST char *cptr,
|
|||
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 cpu_set_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 t_stat cpu_show (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
|
@ -246,6 +251,30 @@ static uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue
|
|||
static int32 pcq_p = 0; /* PC queue ptr */
|
||||
static REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||
|
||||
#define HIST_MIN 16
|
||||
#define HIST_MAX 8192
|
||||
|
||||
typedef struct {
|
||||
uint8 valid;
|
||||
uint16 af;
|
||||
uint16 bc;
|
||||
uint16 de;
|
||||
uint16 hl;
|
||||
t_addr pc;
|
||||
t_addr sp;
|
||||
uint16 af1;
|
||||
uint16 bc1;
|
||||
uint16 de1;
|
||||
uint16 hl1;
|
||||
uint16 ix;
|
||||
uint16 iy;
|
||||
t_value op[INST_MAX_BYTES];
|
||||
} insthist_t;
|
||||
|
||||
static uint32 hst_p = 0; /* history pointer */
|
||||
static uint32 hst_lnt = 0; /* history length */
|
||||
static insthist_t *hst = NULL; /* instruction history */
|
||||
|
||||
uint32 m68k_registers[M68K_REG_CPU_TYPE + 1]; /* M68K CPU registers */
|
||||
|
||||
|
||||
|
@ -523,6 +552,8 @@ static MTAB cpu_mod[] = {
|
|||
NULL, NULL, "Sets the RAM size to 60KB for 8080 / Z80 / 8086" },
|
||||
{ MTAB_VDV, 64, NULL, "64KB", &cpu_set_size,
|
||||
NULL, NULL, "Sets the RAM size to 64KB for 8080 / Z80 / 8086" },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_VALO|MTAB_SHP, 0, "HISTORY", "HISTORY", &cpu_set_hist, &cpu_show_hist,
|
||||
NULL, "CPU instruction history buffer"},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -2047,6 +2078,7 @@ static t_stat sim_instr_mmu (void) {
|
|||
extern int32 keyboardInterrupt;
|
||||
extern uint32 keyboardInterruptHandler;
|
||||
int32 reason = SCPE_OK;
|
||||
int i;
|
||||
register uint32 specialProcessing;
|
||||
register uint32 AF;
|
||||
register uint32 BC;
|
||||
|
@ -6128,8 +6160,34 @@ static t_stat sim_instr_mmu (void) {
|
|||
PC = 0x38;
|
||||
}
|
||||
|
||||
sim_interval--;
|
||||
/*
|
||||
** Save in instruction history ring buffer?
|
||||
*/
|
||||
if (hst_lnt && ((chiptype == CHIP_TYPE_8080) || (chiptype == CHIP_TYPE_Z80))) {
|
||||
hst[hst_p].valid = 1;
|
||||
hst[hst_p].pc = PCX;
|
||||
hst[hst_p].sp = SP;
|
||||
hst[hst_p].af = AF;
|
||||
hst[hst_p].bc = BC;
|
||||
hst[hst_p].de = DE;
|
||||
hst[hst_p].hl = HL;
|
||||
hst[hst_p].af1 = AF1_S;
|
||||
hst[hst_p].bc1 = BC1_S;
|
||||
hst[hst_p].de1 = DE1_S;
|
||||
hst[hst_p].hl1 = HL1_S;
|
||||
hst[hst_p].ix = IX;
|
||||
hst[hst_p].iy = IY;
|
||||
|
||||
for (i=0; i < INST_MAX_BYTES; i++) {
|
||||
hst[hst_p].op[i] = GetBYTE(PCX+i);
|
||||
}
|
||||
|
||||
if (++hst_p == hst_lnt) {
|
||||
hst_p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sim_interval--;
|
||||
}
|
||||
|
||||
/* It we stopped processing instructions because of a switch to the other
|
||||
|
@ -6794,6 +6852,144 @@ static t_stat cpu_set_memory(UNIT *uptr, int32 value, CONST char *cptr, void *de
|
|||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
static t_stat cpu_set_hist(UNIT *uptr, int32 val, CONST char *cptr, void *desc) {
|
||||
uint32 i, lnt;
|
||||
t_stat r;
|
||||
|
||||
if ((chiptype != CHIP_TYPE_8080) && (chiptype != CHIP_TYPE_Z80)) {
|
||||
sim_printf("History not supported for chiptype: %s\n",
|
||||
(chiptype < NUM_CHIP_TYPE) ? cpu_mod[chiptype].mstring : "????");
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
/*
|
||||
** If cptr is NULL, reset ring buffer ("SET HISTORY")
|
||||
*/
|
||||
if (cptr == NULL) {
|
||||
if (hst==NULL) {
|
||||
sim_printf("History buffer not enabled.\n");
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
for (i = 0; i < hst_lnt; i++) {
|
||||
hst[i].valid = 0;
|
||||
}
|
||||
|
||||
hst_p = 0;
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Enable/Resize ring buffer ("SET HISTORY=<n>")
|
||||
*/
|
||||
lnt = (uint32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||
|
||||
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) {
|
||||
sim_printf("History buffer minimum/maximum size: %d/%d\n", HIST_MIN, HIST_MAX);
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete old history buffer
|
||||
*/
|
||||
if (hst!=NULL) {
|
||||
free (hst);
|
||||
hst_lnt = 0;
|
||||
hst = NULL;
|
||||
}
|
||||
|
||||
hst_p = 0;
|
||||
|
||||
/*
|
||||
** If a length was specified, allocate new buffer ("SET HISTORY=<n>" where n>0)
|
||||
*/
|
||||
if (lnt) {
|
||||
hst = (insthist_t *) calloc (lnt, sizeof (insthist_t));
|
||||
if (hst == NULL) {
|
||||
return SCPE_MEM;
|
||||
}
|
||||
hst_lnt = lnt;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||
{
|
||||
int32 k, di, lnt;
|
||||
CONST char *cptr = (CONST char *) desc;
|
||||
t_stat r;
|
||||
insthist_t *h;
|
||||
|
||||
if ((chiptype != CHIP_TYPE_8080) && (chiptype != CHIP_TYPE_Z80)) {
|
||||
sim_printf("History not supported for chiptype: %s\n",
|
||||
(chiptype < NUM_CHIP_TYPE) ? cpu_mod[chiptype].mstring : "????");
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
if (hst_lnt == 0) {
|
||||
return SCPE_NOFNC; /* enabled? */
|
||||
}
|
||||
|
||||
if (cptr) {
|
||||
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||
|
||||
if ((r != SCPE_OK) || (lnt == 0)) {
|
||||
return SCPE_ARG;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lnt = hst_lnt;
|
||||
}
|
||||
|
||||
di = hst_p - lnt;
|
||||
|
||||
if (di < 0) di = di + hst_lnt;
|
||||
|
||||
for (k = 0; k < lnt; k++) {
|
||||
h = &hst[(di++) % hst_lnt];
|
||||
|
||||
if (h->valid) { /* valid entry? */
|
||||
if (chiptype == CHIP_TYPE_8080) {
|
||||
/*
|
||||
** Use DDT output:
|
||||
** CfZfMfEfIf A=bb B=dddd D=dddd H=dddd S=dddd P=dddd inst
|
||||
*/
|
||||
fprintf(st, "CPU: C%dZ%dM%dE%dI%d A=%02X B=%04X D=%04X H=%04X S=%04X P=%04X ",
|
||||
TSTFLAG2(h->af, C),
|
||||
TSTFLAG2(h->af, Z),
|
||||
TSTFLAG2(h->af, S),
|
||||
TSTFLAG2(h->af, P),
|
||||
TSTFLAG2(h->af, H),
|
||||
HIGH_REGISTER(h->af), h->bc, h->de, h->hl, h->sp, h->pc);
|
||||
fprint_sym (st, h->pc, h->op, &cpu_unit, SWMASK ('M'));
|
||||
fprintf(st, "\n");
|
||||
}
|
||||
else { /* Z80 */
|
||||
/*
|
||||
** Use DDT/Z output:
|
||||
*/
|
||||
fprintf(st, "CPU: C%dZ%dS%dP%dH%dN%d A =%02X BC =%04X DE =%04X HL =%04X S =%04X P =%04X ",
|
||||
TSTFLAG2(h->af, C),
|
||||
TSTFLAG2(h->af, Z),
|
||||
TSTFLAG2(h->af, S),
|
||||
TSTFLAG2(h->af, P),
|
||||
TSTFLAG2(h->af, H),
|
||||
TSTFLAG2(h->af, N),
|
||||
HIGH_REGISTER(h->af), h->bc, h->de, h->hl, h->sp, h->pc);
|
||||
fprint_sym (st, h->pc, h->op, &cpu_unit, SWMASK ('M'));
|
||||
fprintf(st, "\n");
|
||||
fprintf(st, " A'=%02X BC'=%04X DE'=%04X HL'=%04X IX=%04X IY=%04X ",
|
||||
HIGH_REGISTER(h->af1), h->bc1, h->de1, h->hl1, h->ix, h->iy);
|
||||
fprintf(st, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_value altairz80_pc_value (void) {
|
||||
return (t_value)PCX;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue