diff --git a/HP2100/hp2100_baci.c b/HP2100/hp2100_baci.c index 98079294..3662ea13 100644 --- a/HP2100/hp2100_baci.c +++ b/HP2100/hp2100_baci.c @@ -1,6 +1,6 @@ -/* hp2100_baci.c: HP 12966A buffered asynchronous communications interface simulator +/* hp2100_baci.c: HP 12966A Buffered Asynchronous Communications Interface simulator - Copyright (c) 2007-2016, J. David Bryan + Copyright (c) 2007-2017, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,8 +23,12 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. - BACI 12966A BACI card + BACI 12966A Buffered Asynchronous Communications Interface + 15-Mar-17 JDB Trace flags are now global + Changed DEBUG_PRI calls to tprintfs + 10-Mar-17 JDB Added IOBUS to the debug table + 17-Jan-17 JDB Changed "hp_---sc" and "hp_---dev" to "hp_---_dib" 02-Aug-16 JDB "baci_poll_svc" now calls "tmxr_poll_conn" unilaterally 13-May-16 JDB Modified for revised SCP API function parameter types 24-Dec-14 JDB Added casts for explicit downward conversions @@ -184,14 +188,6 @@ #define UNIT_CAPSLOCK (1 << UNIT_V_CAPSLOCK) -/* Debug flags */ - -#define DEB_CMDS (1 << 0) /* commands and status */ -#define DEB_CPU (1 << 1) /* CPU I/O */ -#define DEB_BUF (1 << 2) /* buffer gets and puts */ -#define DEB_XFER (1 << 3) /* character reads and writes */ - - /* Bit flags */ #define OUT_MR 0100000 /* common master reset */ @@ -418,49 +414,51 @@ UNIT baci_unit[] = { { UDATA (&baci_poll_svc, UNIT_DIS, POLL_FIRST) } /* Telnet poll unit */ }; -REG baci_reg[] = { - { ORDATA (IBUF, baci_ibuf, 16), REG_FIT }, - { ORDATA (OBUF, baci_obuf, 16), REG_FIT }, - { ORDATA (STATUS, baci_status, 16), REG_FIT }, +REG baci_reg [] = { +/* Macro Name Location Radix Width Offset Depth Flags */ +/* ------ -------- -------------------- ----- ----- ------ ---------- --------------- */ + { ORDATA (IBUF, baci_ibuf, 16), REG_FIT | REG_X }, + { ORDATA (OBUF, baci_obuf, 16), REG_FIT | REG_X }, + { GRDATA (STATUS, baci_status, 2, 16, 0), REG_FIT }, - { ORDATA (EDSIW, baci_edsiw, 16), REG_FIT }, - { ORDATA (DSRW, baci_dsrw, 16), REG_FIT }, - { ORDATA (CFCW, baci_cfcw, 16), REG_FIT }, - { ORDATA (ICW, baci_icw, 16), REG_FIT }, - { ORDATA (ISRW, baci_isrw, 16), REG_FIT }, + { ORDATA (EDSIW, baci_edsiw, 16), REG_FIT }, + { ORDATA (DSRW, baci_dsrw, 16), REG_FIT }, + { ORDATA (CFCW, baci_cfcw, 16), REG_FIT }, + { ORDATA (ICW, baci_icw, 16), REG_FIT }, + { ORDATA (ISRW, baci_isrw, 16), REG_FIT }, - { DRDATA (FIFOPUT, baci_fput, 8) }, - { DRDATA (FIFOGET, baci_fget, 8) }, - { DRDATA (FIFOCNTR, baci_fcount, 8) }, - { DRDATA (BRKCNTR, baci_bcount, 16) }, + { DRDATA (FIFOPUT, baci_fput, 8) }, + { DRDATA (FIFOGET, baci_fget, 8) }, + { DRDATA (FIFOCNTR, baci_fcount, 8) }, + { DRDATA (BRKCNTR, baci_bcount, 16) }, - { BRDATA (FIFO, baci_fifo, 8, 8, FIFO_SIZE) }, - { BRDATA (SPCHAR, baci_spchar, 8, 1, 256) }, + { BRDATA (FIFO, baci_fifo, 8, 8, FIFO_SIZE), REG_A }, + { BRDATA (SPCHAR, baci_spchar, 8, 1, 256) }, - { ORDATA (UARTTHR, baci_uart_thr, 16), REG_FIT }, - { ORDATA (UARTTR, baci_uart_tr, 16), REG_NZ }, - { ORDATA (UARTRHR, baci_uart_rhr, 16), REG_FIT }, - { ORDATA (UARTRR, baci_uart_rr, 16), REG_NZ }, - { DRDATA (UARTCLK, baci_uart_clk, 16) }, + { ORDATA (UARTTHR, baci_uart_thr, 16), REG_FIT | REG_X }, + { ORDATA (UARTTR, baci_uart_tr, 16), REG_NZ | REG_X }, + { ORDATA (UARTRHR, baci_uart_rhr, 16), REG_FIT | REG_X }, + { ORDATA (UARTRR, baci_uart_rr, 16), REG_NZ | REG_X }, + { DRDATA (UARTCLK, baci_uart_clk, 16) }, - { DRDATA (CTIME, baci_term.wait, 19), REG_RO }, + { DRDATA (CTIME, baci_term.wait, 19) }, - { FLDATA (ENQFLAG, baci_enq_seen, 0), REG_HRO }, - { DRDATA (ENQCNTR, baci_enq_cntr, 16), REG_HRO }, + { FLDATA (ENQFLAG, baci_enq_seen, 0), REG_HRO }, + { DRDATA (ENQCNTR, baci_enq_cntr, 16), REG_HRO }, - { FLDATA (LKO, baci.lockout, 0) }, - { FLDATA (CTL, baci.control, 0) }, - { FLDATA (FLG, baci.flag, 0) }, - { FLDATA (FBF, baci.flagbuf, 0) }, - { FLDATA (SRQ, baci.srq, 0) }, - { ORDATA (SC, baci_dib.select_code, 6), REG_HRO }, - { ORDATA (DEVNO, baci_dib.select_code, 6), REG_HRO }, + { FLDATA (LKO, baci.lockout, 0) }, + { FLDATA (CTL, baci.control, 0) }, + { FLDATA (FLG, baci.flag, 0) }, + { FLDATA (FBF, baci.flagbuf, 0) }, + { FLDATA (SRQ, baci.srq, 0) }, + { ORDATA (SC, baci_dib.select_code, 6), REG_HRO }, + { ORDATA (DEVNO, baci_dib.select_code, 6), REG_HRO }, { NULL } }; MTAB baci_mod[] = { - { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL, NULL, NULL }, - { UNIT_DIAG, 0, "terminal mode", "TERMINAL", NULL, NULL, NULL }, + { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAGNOSTIC", NULL, NULL, NULL }, + { UNIT_DIAG, 0, "terminal mode", "TERMINAL", NULL, NULL, NULL }, { UNIT_FASTTIME, UNIT_FASTTIME, "fast timing", "FASTTIME", NULL, NULL, NULL }, { UNIT_FASTTIME, 0, "realistic timing", "REALTIME", NULL, NULL, NULL }, @@ -475,17 +473,18 @@ MTAB baci_mod[] = { { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, NULL, &tmxr_show_cstat, &baci_desc }, { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &baci_desc }, - { MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &baci_dev }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &baci_dev }, + { MTAB_XTD | MTAB_VDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &baci_dib }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &baci_dib }, { 0 } }; -DEBTAB baci_deb[] = { - { "CMDS", DEB_CMDS }, - { "CPU", DEB_CPU }, - { "BUF", DEB_BUF }, - { "XFER", DEB_XFER }, - { NULL, 0 } +DEBTAB baci_deb [] = { + { "CMDS", DEB_CMDS }, + { "CPU", DEB_CPU }, + { "BUF", DEB_BUF }, + { "XFER", DEB_XFER }, + { "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */ + { NULL, 0 } }; DEVICE baci_dev = { @@ -560,8 +559,7 @@ while (working_set) { baci.flag = baci.flagbuf = CLEAR; /* clear flag and flag buffer */ baci.srq = CLEAR; /* clear SRQ */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: [CLF] Flag and SRQ cleared\n", sim_deb); + tprintf (baci_dev, DEB_CMDS, "[CLF] Flag and SRQ cleared\n"); update_status (); /* FLG might set when SRQ clears */ break; @@ -572,8 +570,7 @@ while (working_set) { baci.lockout = SET; /* set lockout */ baci.srq = SET; /* set SRQ */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: [STF] Flag, SRQ, and lockout set\n", sim_deb); + tprintf (baci_dev, DEB_CMDS, "[STF] Flag, SRQ, and lockout set\n"); break; @@ -602,15 +599,15 @@ while (working_set) { data = baci_ibuf; /* return received data */ - if (DEBUG_PRI (baci_dev, DEB_CPU)) - fprintf (sim_deb, ">>BACI cpu: [LIx%s] Received data = %06o\n", hold_or_clear, baci_ibuf); + tprintf (baci_dev, DEB_CPU, "[LIx%s] Received data = %06o\n", + hold_or_clear, baci_ibuf); } else { /* control clear? */ data = baci_status; /* return status */ - if (DEBUG_PRI (baci_dev, DEB_CPU)) - fprintf (sim_deb, ">>BACI cpu: [LIx%s] Status = %06o\n", hold_or_clear, baci_status); + tprintf (baci_dev, DEB_CPU, "[LIx%s] Status = %06o\n", + hold_or_clear, baci_status); } stat_data = IORETURN (SCPE_OK, data); /* merge in return status */ @@ -620,15 +617,14 @@ while (working_set) { case ioIOO: /* I/O data output */ baci_obuf = IODATA (stat_data); /* get data value */ - if (DEBUG_PRI (baci_dev, DEB_CPU)) - fprintf (sim_deb, ">>BACI cpu: [OTx%s] Command = %06o\n", hold_or_clear, baci_obuf); + tprintf (baci_dev, DEB_CPU, "[OTx%s] Command = %06o\n", + hold_or_clear, baci_obuf); if (baci_obuf & OUT_MR) { /* master reset? */ master_reset (); /* do before processing */ baci_io (&baci_dib, ioSIR, 0); /* set interrupt request */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fprintf (sim_deb, ">>BACI cmds: [OTx%s] Master reset\n", hold_or_clear); + tprintf (baci_dev, DEB_CMDS, "[OTx%s] Master reset\n", hold_or_clear); } switch (GET_ID (baci_obuf)) { /* isolate ID code */ @@ -639,10 +635,10 @@ while (working_set) { fifo_put (ch); /* queue character */ if (baci_term.flags & UNIT_ATT) { /* attached to network? */ - if (DEBUG_PRI (baci_dev, DEB_CMDS) && /* debugging? */ + if (TRACING (baci_dev, DEB_CMDS) && /* debugging? */ (sim_is_active (&baci_term) == 0)) /* service stopped? */ - fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service scheduled, " - "time = %d\n", hold_or_clear, baci_term.wait); + hp_trace (&baci_dev, DEB_CMDS, "[OTx%s] Terminal service scheduled, " + "time = %d\n", hold_or_clear, baci_term.wait); if (baci_fcount == 1) /* first char to xmit? */ sim_activate_abs (&baci_term, /* start service with full char time */ @@ -683,17 +679,15 @@ while (working_set) { sim_activate (&baci_term, /* activate I/O service */ baci_term.wait); - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service scheduled, " - "time = %d\n", hold_or_clear, baci_term.wait); + tprintf (baci_dev, DEB_CMDS, "[OTx%s] Terminal service scheduled, " + "time = %d\n", hold_or_clear, baci_term.wait); } else { /* external rate */ sim_cancel (&baci_term); /* stop I/O service */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service stopped\n", - hold_or_clear); + tprintf (baci_dev, DEB_CMDS, "[OTx%s] Terminal service stopped\n", + hold_or_clear); } } @@ -724,16 +718,14 @@ while (working_set) { case ioCRS: /* control reset */ master_reset (); /* issue master reset */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: [CRS] Master reset\n", sim_deb); + tprintf (baci_dev, DEB_CMDS, "[CRS] Master reset\n"); break; case ioCLC: /* clear control flip-flop */ baci.control = CLEAR; /* clear control */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fprintf (sim_deb, ">>BACI cmds: [CLC%s] Control cleared\n", hold_or_clear); + tprintf (baci_dev, DEB_CMDS, "[CLC%s] Control cleared\n", hold_or_clear); break; @@ -741,8 +733,7 @@ while (working_set) { baci.control = SET; /* set control */ baci.lockout = CLEAR; /* clear lockout */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fprintf (sim_deb, ">>BACI cmds: [STC%s] Control set and lockout cleared\n", hold_or_clear); + tprintf (baci_dev, DEB_CMDS, "[STC%s] Control set and lockout cleared\n", hold_or_clear); if (!(signal_set & ioCLF)) /* STC without ,C ? */ update_status (); /* clearing lockout might interrupt */ @@ -859,9 +850,8 @@ while (xmit_loop && (baci_uart_thr & IN_VALID)) { /* valid character in UA baci_enq_cntr = baci_enq_cntr + 1; /* bump ENQ counter */ recv_loop = FALSE; /* skip recv to allow time before ACK */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fprintf (sim_deb, ">>BACI xfer: Character ENQ absorbed internally, " - "ENQ count = %d\n", baci_enq_cntr); + tprintf (baci_dev, DEB_XFER, "Character ENQ absorbed internally, " + "ENQ count = %d\n", baci_enq_cntr); } else { /* character is not ENQ or not fast timing */ @@ -871,11 +861,9 @@ while (xmit_loop && (baci_uart_thr & IN_VALID)) { /* valid character in UA status = tmxr_putc_ln (&baci_ldsc, /* transmit the character */ baci_uart_tr); - if ((status == SCPE_OK) && /* transmitted OK? */ - DEBUG_PRI (baci_dev, DEB_XFER)) - fprintf (sim_deb, ">>BACI xfer: Character %s " - "transmitted from UART\n", - fmt_char ((uint8) baci_uart_tr)); + if (status == SCPE_OK) /* transmitted OK? */ + tprintf (baci_dev, DEB_XFER, "Character %s transmitted from the UART\n", + fmt_char ((uint8) baci_uart_tr)); } } @@ -907,9 +895,8 @@ if (recv_loop && /* ok to process? */ baci_uart_rhr = baci_uart_rhr & ~IN_VALID; /* clear valid bit */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fprintf (sim_deb, ">>BACI xfer: Deferred character %s processed\n", - fmt_char ((uint8) baci_uart_rhr)); + tprintf (baci_dev, DEB_XFER, "Deferred character %s processed\n", + fmt_char ((uint8) baci_uart_rhr)); fifo_put ((uint8) baci_uart_rhr); /* move deferred character to FIFO */ baci_uart_rhr = CLEAR_HR; /* clear RHR */ @@ -928,8 +915,7 @@ while (recv_loop) { /* OK to process? */ if (baci_uart_rr & SCPE_BREAK) { /* break detected? */ baci_status = baci_status | IN_BREAK; /* set break status */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fputs (">>BACI xfer: Break detected\n", sim_deb); + tprintf (baci_dev, DEB_XFER, "Break detected\n"); } data_bits = 5 + (baci_cfcw & OUT_CHARSIZE); /* calculate number of data bits */ @@ -937,9 +923,8 @@ while (recv_loop) { /* OK to process? */ baci_uart_rhr = (uint16) (baci_uart_rr & data_mask); /* mask data into holding register */ baci_uart_rr = CLEAR_R; /* clear receiver register */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fprintf (sim_deb, ">>BACI xfer: Character %s received by UART\n", - fmt_char ((uint8) baci_uart_rhr)); + tprintf (baci_dev, DEB_XFER, "Character %s received by the UART\n", + fmt_char ((uint8) baci_uart_rhr)); if (baci_term.flags & UNIT_CAPSLOCK) /* caps lock mode? */ baci_uart_rhr = (uint16) toupper (baci_uart_rhr); /* convert to upper case if lower */ @@ -967,8 +952,7 @@ while (recv_loop) { /* OK to process? */ if (recv_loop && baci_enq_seen) { /* OK to process and ENQ seen? */ baci_enq_seen = FALSE; /* reset flag */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fputs (">>BACI xfer: Character ACK generated internally\n", sim_deb); + tprintf (baci_dev, DEB_XFER, "Character ACK generated internally\n"); fifo_put (ACK); /* fake ACK from terminal */ update_status (); /* update FIFO status */ @@ -981,8 +965,7 @@ if ((baci_uart_thr & IN_VALID) || baci_enq_seen || /* more to transmit? */ tmxr_rqln (&baci_ldsc)) /* or more to receive? */ sim_activate (uptr, uptr->wait); /* reschedule service */ else - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: Terminal service stopped\n", sim_deb); + tprintf (baci_dev, DEB_CMDS, "Terminal service stopped\n"); return status; } @@ -1179,48 +1162,37 @@ if ((baci_status & IN_STDIRQ) || /* standard interrupt? * (baci_edsiw & OUT_ENCM) && /* and char mode */ (baci_fget != baci_fput)) { /* and FIFO not empty? */ - if (baci.lockout) { /* interrupt lockout? */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: Lockout prevents flag set", sim_deb); - } + if (baci.lockout) /* interrupt lockout? */ + tprintf (baci_dev, DEB_CMDS, "Lockout prevents flag set, status = %06o\n", + baci_status); - else if (baci.srq) { /* SRQ set? */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: SRQ prevents flag set", sim_deb); - } + else if (baci.srq) /* SRQ set? */ + tprintf (baci_dev, DEB_CMDS, "SRQ prevents flag set, status = %06o\n", + baci_status); else { baci_io (&baci_dib, ioENF, 0); /* set flag */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: Flag and lockout set", sim_deb); + tprintf (baci_dev, DEB_CMDS, "Flag and lockout set, status = %06o\n", + baci_status); } - - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fprintf (sim_deb, ", status = %06o\n", baci_status); } if ((baci_icw & OUT_DCPC) && /* DCPC enabled? */ ((IO_MODE == XMIT) && (baci_fcount < 128) || /* and xmit and room in FIFO */ - (IO_MODE == RECV) && (baci_fcount > 0))) { /* or recv and data in FIFO? */ - - if (baci.lockout) { /* interrupt lockout? */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: Lockout prevents SRQ set", sim_deb); - } + (IO_MODE == RECV) && (baci_fcount > 0))) /* or recv and data in FIFO? */ + if (baci.lockout) /* interrupt lockout? */ + tprintf (baci_dev, DEB_CMDS, "Lockout prevents SRQ set, status = %06o\n", + baci_status); else { baci.srq = SET; /* set SRQ */ baci_io (&baci_dib, ioSIR, 0); /* set interrupt request */ - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fputs (">>BACI cmds: SRQ set", sim_deb); + tprintf (baci_dev, DEB_CMDS, "SRQ set, status = %06o\n", + baci_status); } - if (DEBUG_PRI (baci_dev, DEB_CMDS)) - fprintf (sim_deb, ", status = %06o\n", baci_status); - } - return; } @@ -1340,10 +1312,9 @@ if ((baci_fget != baci_fput) || (baci_fcount >= 128)) { /* FIFO occupied? */ if (IO_MODE == RECV) /* receive mode? */ baci_fcount = baci_fcount - 1; /* decrement occupancy counter */ - if (DEBUG_PRI (baci_dev, DEB_BUF)) - fprintf (sim_deb, ">>BACI buf: Character %s get from FIFO [%d], " - "character counter = %d\n", - fmt_char ((uint8) data), baci_fget, baci_fcount); + tprintf (baci_dev, DEB_BUF, "Character %s get from FIFO [%d], " + "character counter = %d\n", + fmt_char ((uint8) data), baci_fget, baci_fcount); baci_fget = (baci_fget + 1) % FIFO_SIZE; /* bump index modulo array size */ @@ -1354,9 +1325,8 @@ if ((baci_fget != baci_fput) || (baci_fcount >= 128)) { /* FIFO occupied? */ } else /* FIFO empty */ - if (DEBUG_PRI (baci_dev, DEB_BUF)) - fprintf (sim_deb, ">>BACI buf: Attempted get on empty FIFO, " - "character count = %d\n", baci_fcount); + tprintf (baci_dev, DEB_BUF, "Attempted get on empty FIFO, " + "character count = %d\n", baci_fcount); if (baci_fcount == 0) /* count now zero? */ baci_status = baci_status | IN_BUFEMPTY; /* set buffer empty flag */ @@ -1398,13 +1368,12 @@ else { /* RECV or THR occupied baci_fcount = baci_fcount + 1; /* increment occupancy counter */ -if (DEBUG_PRI (baci_dev, DEB_BUF)) - if (pass_thru) - fprintf (sim_deb, ">>BACI buf: Character %s put to UART transmitter holding register, " - "character counter = 1\n", fmt_char (ch)); - else - fprintf (sim_deb, ">>BACI buf: Character %s put to FIFO [%d], " - "character counter = %d\n", fmt_char (ch), index, baci_fcount); +if (pass_thru) + tprintf (baci_dev, DEB_BUF, "Character %s put to UART transmitter holding register, " + "character counter = 1\n", fmt_char (ch)); +else + tprintf (baci_dev, DEB_BUF, "Character %s put to FIFO [%d], " + "character counter = %d\n", fmt_char (ch), index, baci_fcount); if ((IO_MODE == RECV) && (baci_spchar [ch])) /* receive mode and special character? */ baci_status = baci_status | IN_SPCHAR; /* set special char seen flag */ @@ -1477,8 +1446,7 @@ if (baci_uart_clk > 0) { /* transfer in progress? if (baci_bcount == 160) { /* break held long enough? */ baci_status = baci_status | IN_BREAK; /* set break flag */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fputs (">>BACI xfer: Break detected\n", sim_deb); + tprintf (baci_dev, DEB_XFER, "Break detected\n"); } } @@ -1499,9 +1467,8 @@ if (baci_uart_clk > 0) { /* transfer in progress? baci_uart_thr = fifo_get (); /* get next char into THR */ update_status (); /* update FIFO status */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fprintf (sim_deb, ">>BACI xfer: UART transmitter empty, " - "holding register = %06o\n", baci_uart_thr); + tprintf (baci_dev, DEB_XFER, "UART transmitter empty, " + "holding register = %06o\n", baci_uart_thr); } else if ((IO_MODE == RECV) && /* receive mode? */ @@ -1517,10 +1484,8 @@ if (baci_uart_clk > 0) { /* transfer in progress? baci_uart_rhr = (uint16) (baci_uart_rr >> (16 - uart_bits)); /* position data to right align */ baci_uart_rr = CLEAR_R; /* clear receiver register */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fprintf (sim_deb, ">>BACI xfer: UART receiver = %06o (%s)\n", - baci_uart_rhr, - fmt_char ((uint8) (baci_uart_rhr & data_mask))); + tprintf (baci_dev, DEB_XFER, "UART receiver = %06o (%s)\n", + baci_uart_rhr, fmt_char ((uint8) (baci_uart_rhr & data_mask))); fifo_put ((uint8) (baci_uart_rhr & data_mask)); /* put data in FIFO */ update_status (); /* update FIFO status */ @@ -1539,8 +1504,7 @@ if (baci_uart_clk > 0) { /* transfer in progress? if (parity & 1) { /* parity error? */ baci_status = baci_status | IN_OVRUNPE; /* report it */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fputs (">>BACI xfer: Parity error detected\n", sim_deb); + tprintf (baci_dev, DEB_XFER, "Parity error detected\n"); } } } @@ -1578,19 +1542,17 @@ if ((baci_uart_clk == 0) && /* start of transfer? */ baci_uart_tr = (~data_mask | baci_uart_tr) << 2 | 1; /* form serial data stream */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fprintf (sim_deb, ">>BACI xfer: UART transmitter = %06o (%s), " - "clock count = %d\n", baci_uart_tr & DMASK, - fmt_char ((uint8) (baci_uart_thr & data_mask)), - baci_uart_clk); + tprintf (baci_dev, DEB_XFER, "UART transmitter = %06o (%s), " + "clock count = %d\n", baci_uart_tr & DMASK, + fmt_char ((uint8) (baci_uart_thr & data_mask)), + baci_uart_clk); } else { baci_uart_rr = CLEAR_R; /* clear receiver register */ - if (DEBUG_PRI (baci_dev, DEB_XFER)) - fprintf (sim_deb, ">>BACI xfer: UART receiver empty, " - "clock count = %d\n", baci_uart_clk); + tprintf (baci_dev, DEB_XFER, "UART receiver empty, " + "clock count = %d\n", baci_uart_clk); } } diff --git a/HP2100/hp2100_cpu.c b/HP2100/hp2100_cpu.c index 862a29be..eec1305a 100644 --- a/HP2100/hp2100_cpu.c +++ b/HP2100/hp2100_cpu.c @@ -1,34 +1,55 @@ -/* hp2100_cpu.c: HP 21xx/1000 CPU simulator +/* hp2100_cpu.c: HP 21xx/1000 Central Processing Unit/MEM/MP/DCPC simulator Copyright (c) 1993-2016, Robert M. Supnik + Copyright (c) 2017, J. David Bryan - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - Except as contained in this notice, the name of Robert M Supnik shall not be + Except as contained in this notice, the names of the authors shall not be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Robert M Supnik. + in this Software without prior written authorization from the authors. - CPU 2114C/2115A/2116C/2100A/1000-M/E/F central processing unit - 12731A memory expansion module - MP 12581A/12892B memory protect - DMA1,DMA2 12607B/12578A/12895A direct memory access controller - DCPC1,DCPC2 12897B dual channel port controller + CPU 2114C/2115A/2116C/2100A/1000-M/E/F Central Processing Unit + 12731A Memory Expansion Module + DMA1,DMA2 12607B/12578A/12895A Direct Memory Access + DCPC1,DCPC2 12897B Dual Channel Port Controller + MP 12581A/12892B Memory Protect + 11-Aug-17 JDB MEM must be disabled when DMS is disabled + 01-Aug-17 JDB Changed SET/SHOW CPU [NO]IDLE to use sim_*_idle routines + 22-Jul-17 JDB Renamed "intaddr" to CIR; added IR + 18-Jul-17 JDB Added CPU stops + 11-Jul-17 JDB Moved "hp_enbdis_pair" to hp2100_sys.c + Renamed "ibl_copy" to "cpu_ibl" + 10-Jul-17 JDB Renamed the global routine "iogrp" to "cpu_iog" + 07-Jul-17 JDB Changed "iotrap" from uint32 to t_bool + 26-Jun-17 JDB Moved I/O instruction subopcode constants from hp2100_defs.h + 16-May-17 JDB Changed REG_A, REG_B to REG_X + 19-Apr-17 JDB SET CPU IDLE now omits idle loop tracing + 04-Apr-17 JDB Added "cpu_configuration" for symbolic ex/dep validation + Rejected model change no longer changes options + 21-Mar-17 JDB IOP is now illegal on the 1000 F-Series + 27-Feb-17 JDB Added BBL load for 21xx machines + ibl_copy no longer returns a status code + 22-Feb-17 JDB Added DMA tracing + 21-Feb-17 JDB Added bus tracing to the I/O dispatcher + 19-Jan-17 JDB Added CPU tracing + Consolidated the memory read and write routines 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 13-May-16 JDB Modified for revised SCP API function parameter types 31-Dec-14 JDB Corrected devdisp data parameters @@ -164,988 +185,1773 @@ 15-Oct-00 RMS Added dynamic device number support References: - - 2100A Computer Reference Manual (02100-90001, Dec-1971) - - Model 2100A Computer Installation and Maintenance Manual - (02100-90002, Aug-1972) - - HP 1000 M/E/F-Series Computers Technical Reference Handbook - (5955-0282, Mar-1980) - - HP 1000 M/E/F-Series Computers Engineering and Reference Documentation - (92851-90001, Mar-1981) - - HP 1000 M/E/F-Series Computers I/O Interfacing Guide - (02109-90006, Sep-1980) - - 12607A Direct Memory Access Operating and Service Manual - (12607-90002, Jan-1970) - - 12578A/12578A-01 Direct Memory Access Operating and Service Manual - (12578-9001, Mar-1972) - - 12892B Memory Protect Installation Manual (12892-90007, Jun-1978) + - 2100A Computer Reference Manual + (02100-90001, Dec-1971) + - Model 2100A Computer Installation and Maintenance Manual + (02100-90002, Aug-1972) + - HP 1000 M/E/F-Series Computers Technical Reference Handbook + (5955-0282, Mar-1980) + - HP 1000 M/E/F-Series Computers Engineering and Reference Documentation + (92851-90001, Mar-1981) + - HP 1000 M/E/F-Series Computers I/O Interfacing Guide + (02109-90006, Sep-1980) + - 12607A Direct Memory Access Operating and Service Manual + (12607-90002, Jan-1970) + - 12578A/12578A-01 Direct Memory Access Operating and Service Manual + (12578-9001, Mar-1972) + - 12892B Memory Protect Installation Manual + (12892-90007, Jun-1978) + - HP 1000 Computer Real-Time Systems + (5091-4479, August 1992) - The register state for the HP 2116 CPU is: + Hewlett-Packard sold the HP 21xx/1000 family of real-time computers from 1966 + through 2000. There are three major divisions within this family: the 21xx + core-memory machines, the 1000 (originally 21MX) M/E/F-Series semiconductor- + memory machines, and the 1000 L/A-Series machines. All machines are 16-bit + accumulator-oriented CISC machines running the same base instruction set. A + wide range of operating systems run on these machines, from a simple 4K word + paper-tape-based monitor to a megaword multi-user, multiprogramming disc- + based system and a multi-user time-shared BASIC system. - AR<15:0> A register - addressable as location 0 - BR<15:0> B register - addressable as location 1 - PR<14:0> P register - program counter - SR<15:0> S register - switch register - MR<14:0> M register - memory address - TR<15:0> T register - memory data - E extend flag (carry out) - O overflow flag + This implementation is a simulator for the 2114, 2115, 2116, 2100, and 1000 + M/E/F-Series machines. A large variety of CPU options, device interface + cards, and peripherals are provided. High-speed I/O transfers are performed + by Direct Memory Access and Dual-Channel Port Controller options. This + simulator does not model the 1000 L/A-Series machines. - The 2100 adds memory protection logic: + All of the machines support a 15-bit logical address space, addressing a + maximum of 32 K words, divided into 1K-word pages. Memory-referencing + instructions in the base set can directly address the 1024 words of the base + page (page 0) or the 1024 words of the current page (the page containing the + instruction). The instructions in the extended set directly address the + 32768 words in the full logical address space. The A and B accumulators may + be addressed as logical addresses 0 and 1, respectively. - mp_fence<14:0> memory fence register - mp_viol<15:0> memory protection violation register (F register) + Peripheral devices are connected to the CPU by interface cards installed in + the I/O card cages present in the CPU and optional I/O extender chassis. Each + slot in the card cage is assigned an address, called a select code, that may + be referenced by I/O instructions in the base set. Select codes range from 0 + to 77 octal, with the first eight select codes reserved for the system, + providing connections for 56 possible interfaces. - The 21MX adds a pair of index registers and memory expansion logic: + The 211x machines use a hardwired processor providing 70 basic instructions + and up to 32K of core memory. The base instruction set is divided into the + Memory Reference Group, the Shift-Rotate Group, the Alter-Skip Group, and the + I/O Group. SRG instruction words may contain from one to four suboperation + codes that are executed from left-to-right, and ASG instruction words may + contain from one to eight suboperations. An optional Extended Arithmetic + Unit may be added to the 2115 and 2116 that provides hardware multiply and + divide, double-load and -store, and double-word shift and rotate + instructions. - XR<15:0> X register - YR<15:0> Y register - dms_sr<15:0> dynamic memory system status register - dms_vr<15:0> dynamic memory system violation register + The 2100 machine uses a microprogrammed processor that provides the 80 + instructions of the base set and the EAU as standard equipment. Optional + floating-point microcode adds six two-word single-precision instructions. + User microprogramming is also supported. When used as part of an HP 2000 + Time-Shared BASIC system, the CPU designated as the I/O processor may be + equipped with microcode implementing 18 additional OS accelerator + instructions. - The original HP 2116 has four instruction formats: memory reference, - shift, alter/skip, and I/O. The HP 2100 added extended memory reference - and extended arithmetic. The HP21MX added extended byte, bit, and word - instructions as well as extended memory. + The 1000 M/E-Series machines also use microprogrammed processors and extend + the 2100 instruction set with two new index registers, X and Y, and a new + Extended Instruction Group consisting of 32 index-register instructions and + 10 word-and-byte-manipulation instructions. The six 2100 floating-point + instructions are also standard. The 1000 F-Series adds a hardware + floating-point processor with 18 new triple- and quad-word instructions. A + number of new optional microcode extensions are available with the + M/E/F-Series. - The memory reference format is: + 1000 CPUs offer the optional Dynamic Mapping System, which provides memory + mapping on a page-by-page basis. The 5-bit page number of a logical memory + address selects one of 32 ten-bit map registers containing physical page + numbers. The ten-bit page number combined with the ten-bit page offset + yields a 20-bit physical address capable of accessing a location in a + one-megaword memory. DMS provides separate maps for system and user + programs, as well as for the two DCPC channels, and includes microcode that + implements the 38 Dynamic Mapping Instructions used to manipulate the mapping + system. - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| op |cp| offset | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + Optional memory protection is accomplished by dividing the logical address + space into protected and unprotected parts. When protection is enabled, any + attempt to write below the fence separating the two parts is inhibited, and + an interrupt to the operating system occurs, which aborts the offending user + program. If the DMS option is enabled as well, protection is enhanced by + specifying read and write permissions on a page-by-page basis. - <14:11> mnemonic action + A note on terminology: the 1000 series of computers was originally called the + 21MX at introduction. The 21MX (occasionally, 21MXM) corresponds to the 1000 + M-Series, and the 21MXE (occasionally, 21XE) corresponds to the 1000 + E-Series. The model numbers were changed before the introduction of the 1000 + F-Series, although some internal HP documentation refers to this machine as + the 21MXF. - 0010 AND A = A & M[MA] - 0011 JSB M[MA] = P, P = MA + 1 - 0100 XOR A = A ^ M[MA] - 0101 JMP P = MA - 0110 IOR A = A | M[MA] - 0111 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 1000 ADA A = A + M[MA] - 1001 ADB B = B + M[MA] - 1010 CPA skip if A != M[MA] - 1011 CPB skip if B != M[MA] - 1100 LDA A = M[MA] - 1101 LDB B = M[MA] - 1110 STA M[MA] = A - 1111 STB M[MA] = B - - <15,10> mode action - - 0,0 page zero direct MA = IR<9:0> - 0,1 current page direct MA = PR<14:0>'IR,9:0> - 1,0 page zero indirect MA = M[IR<9:0>] - 1,1 current page indirect MA = M[PR<14:10>'IR<9:0>] - - Memory reference instructions can access an address space of 32K words. - An instruction can directly reference the first 1024 words of memory - (called page zero), as well as 1024 words of the current page; it can - indirectly access all 32K. - - The shift format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0|ab| 0|s1| op1 |ce|s2|sl| op2 | shift - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | \---+---/ | | | \---+---/ - | | | | | | | - | | | | | | +---- shift 2 opcode - | | | | | +---------- skip if low bit == 0 - | | | | +------------- shift 2 enable - | | | +---------------- clear Extend - | | +---------------------- shift 1 opcode - | +---------------------------- shift 1 enable - +---------------------------------- A/B select - - The alter/skip format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0|ab| 1|regop| e op|se|ss|sl|in|sz|rs| alter/skip - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | \-+-/ \-+-/ | | | | | | - | | | | | | | | +- reverse skip sense - | | | | | | | +---- skip if register == 0 - | | | | | | +------- increment register - | | | | | +---------- skip if low bit == 0 - | | | | +------------- skip if sign bit == 0 - | | | +---------------- skip if Extend == 0 - | | +--------------------- clr/com/set Extend - | +--------------------------- clr/com/set register - +---------------------------------- A/B select - - The I/O transfer format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 0 0 0|ab| 1|hc| opcode | device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | \---+---/\-------+-------/ - | | | | - | | | +--------- device select - | | +---------------------- opcode - | +---------------------------- hold/clear flag - +---------------------------------- A/B select - - The IO transfer instruction controls the specified device. - Depending on the opcode, the instruction may set or clear - the device flag, start or stop I/O, or read or write data. - - The 2100 added an extended memory reference instruction; - the 21MX added extended arithmetic, operate, byte, word, - and bit instructions. Note that the HP 21xx is, despite - the right-to-left bit numbering, a big endian system. - Bits <15:8> are byte 0, and bits <7:0> are byte 1. + The terms MEM (Memory Expansion Module), MEU (Memory Expansion Unit), DMI + (Dynamic Mapping Instructions), and DMS (Dynamic Mapping System) are used + somewhat interchangeably to refer to the logical-to-physical memory address + translation option provided on the 1000-Series. DMS consists of the MEM card + (12731A) and the DMI firmware (13307A). However, MEM and MEU have been used + interchangeably to refer to the mapping card, as have DMI and DMS to refer to + the firmware instructions. - The extended memory reference format (HP 2100) is: + These CPU hardware registers are present in all machines: - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0|op| 0| opcode | extended mem ref - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + Name Width Description + ---- ----- ---------------------------------------------- + A 16 accumulator (addressable as memory location 0) + B 16 accumulator (addressable as memory location 1) + P 15 program counter + S 16 switch and display register + M 15 memory address register + T 16 memory data register + E 1 extend flag (carry out) + O 1 overflow flag - The extended arithmetic format (HP 2100) is: + The 1000 Series adds these CPU hardware registers: - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0 0 0|dr| 0 0| opcode |shift count| extended arithmetic - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + Name Width Description + ---- ----- ---------------------------------------------- + X 16 index register + Y 16 index register - The extended operate format (HP 21MX) is: + The data types supported by the base instruction set are: - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0|op| 0| 1 1 1 1 1| opcode | extended operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + - 8-bit unsigned byte + - 16-bit unsigned integer + - 16-bit two's-complement integer + - 32-bit two's-complement integer + - 32-bit two's-complement floating point - The extended byte and word format (HP 21MX) is: + Multi-word values are stored in memory with the most-significant words in the + lowest addresses. Bytes are stored in memory with the most-significant byte + in the upper half of the 16-bit word and the least-significant byte in the + lower half. - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0 1 0 1 1 1 1 1 1| opcode | extended byte/word - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + The instruction set is fairly irregular -- a legacy of its original + implementation in hardware in the 2116 and the accretion of microprogrammed + instructions in the 2100 and 1000 CPUs. Initially, there were five base-set + instruction groups: - The extended bit operate format (HP 21MX) is: + 1. Memory-Reference Group (MRG) + 2. Shift-Rotate Group (SRG) + 3. Alter-Skip Group (ASG) + 4. I/O Group (IOG) + 5. Macroinstruction Group (MAC) - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0 1 0 1 1 1 1 1 1 1| opcode | extended bit operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + All of the instructions added after the 2116 are in the Macroinstruction + Group. - General notes: + The 2116 offered two hardware options that extended the instruction set. The + first is the 12579A Extended Arithmetic Unit. The second is the 2152A + Floating Point Processor, which is interfaced through, and therefore + requires, the EAU. The EAU adds 10 instructions including integer multiply + and divide and double-word loads, stores, shifts, and rotates. The FPP adds + 30 floating-point arithmetic, trigonometric, logarithmic, and exponential + instructions. (The 2116 FFP is not simulated.) - 1. Reasons to stop. The simulator can be stopped by: + The base set groups are decoded from bits 15-12 and 10, as follows: - HALT instruction - breakpoint encountered - infinite indirection loop - unimplemented instruction and stop_inst flag set - unknown I/O device and stop_dev flag set - I/O error in I/O simulator + 15 14-12 10 Group Address Ranges + -- ----- -- ----- ------------------------------- + x nnn x MRG 010000-077777 and 110000-177777 + 0 000 0 SRG 000000-001777 and 004000-005777 + 0 000 1 ASG 002000-003777 and 006000-007777 + 1 000 1 IOG 102000-103777 and 106000-107777 + 1 000 0 MAC 100000-101777 and 104000-105777 - 2. Interrupts. I/O devices are modelled by substituting software states for - I/O backplane signals. Signals generated by I/O instructions and DMA - cycles are dispatched to the target device for action. Backplane signals - are processed sequentially, except for the "clear flag" signal, which may - be generated in parallel with another signal. For example, the "STC sc,C" - instruction generates the "set control" and the "clear flag" signals - concurrently. + Where: - CPU interrupt signals are modelled as three parallel arrays: + x = don't care + n = any combination other than all zeros - - device request priority as bit vector dev_prl [2] [31..0] - - device interrupt requests as bit vector dev_irq [2] [31..0] - - device service requests as bit vector dev_srq [2] [31..0] + The MAC group is subdivided into the Extended Arithmetic Group (EAG) and the + User Instruction Group (UIG), based on bits 11, 9, and 8, as follows: - Each array forms a 64-bit vector, with bits 0-31 of the first element - corresponding to select codes 00-37 octal, and bits 0-31 of the second - element corresponding to select codes 40-77 octal. + 11 9 8 Group Address Range + -- -- -- ----- ------------- + 0 0 0 EAG 100000-100377 + 0 0 1 EAG 100400-100777 + 0 1 0 EAG 101000-101377 + 0 1 1 UIG-1 101400-101777 + 1 0 0 EAG 104000-104377 + 1 0 1 EAG 104400-104777 + 1 1 0 UIG-0 105000-105377 + 1 1 1 UIG-1 105400-105777 - The HP 2100 interrupt structure is based on the PRH, PRL, IRQ, and IAK - signals. PRH indicates that no higher-priority device is interrupting. - PRL indicates to lower-priority devices that a given device is not - interrupting. IRQ indicates that a given device is requesting an - interrupt. IAK indicates that the given device's interrupt request is - being acknowledged. + All of the 2116 FPP instructions are in the UIG sets: 3 use 10144x opcodes + and the rest use 1050xx and 1054xx opcodes. The 2100 decodes only UIG-0 + instructions, whereas the 1000s use both UIG sets. In particular, the + 105740-105777 range is used by the 1000 Extended Instruction Group (EIG), + which is part of the 1000-Series base set. - PRH and PRL form a hardware priority chain that extends from interface to - interface on the backplane. We model just PRL, as PRH is calculated from - the PRLs of higher-priority devices. + The 21xx and 1000 M/E/F-Series machines do not trap unimplemented + instructions. In general, unimplemented EAG instructions cause erroneous + execution, and unimplemented UIG instructions execute as NOP. However, there + are machine-to-machine variations, and some unimplemented instructions + execute as other, defined instructions. - Typical I/O devices have a flag, flag buffer, and control flip-flop. If a - device's flag, flag buffer, and control bits are set, and the device is - the highest priority on the interrupt chain, it requests an interrupt by - asserting IRQ. When the interrupt is acknowledged with IAK, the flag - buffer is cleared, preventing further interrupt requests from that device. - The combination of flag and control set blocks interrupts from lower - priority devices. + The instruction set groups are encoded as follows: - Service requests are used to trigger the DMA service logic. Setting the - device flag typically also sets SRQ, although SRQ may be calculated - independently. + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | I | mem op | P | memory address | MRG + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - 3. Non-existent memory. On the HP 2100, reads to non-existent memory - return zero, and writes are ignored. In the simulator, the - largest possible memory is instantiated and initialized to zero. - Thus, only writes need be checked against memory size. + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | I | mem op | R | P | memory address | MRG + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - On the 21xx machines, doing SET CPU LOADERDISABLE decreases available - memory size by 64 words. + Where: - 4. Adding I/O devices. These modules must be modified: + I = direct/indirect (0/1) + R = A/B register (0/1) + P = base/current page (0/1) - hp2100_defs.h add interrupt request definition - hp2100_sys.c add sim_devices table entry + The "mem ops" are encoded as follows: - 5. Instruction interruptibility. The simulator is fast enough, compared - to the run-time of the longest instructions, for interruptibility not - to matter. But the HP diagnostics explicitly test interruptibility in - EIS and DMS instructions, and long indirect address chains. Accordingly, - the simulator does "just enough" to pass these tests. In particular, if - an interrupt is pending but deferred at the beginning of an interruptible - instruction, the interrupt is taken at the appropriate point; but there - is no testing for new interrupts during execution (that is, the event - timer is not called). + 14-11 Mnemonic Action + ----- -------- ---------------------------------------- + 0010 AND A = A & M [MA] + 0011 JSB M [MA] = P, P = MA + 1 + 0100 XOR A = A ^ M [MA] + 0101 JMP P = MA + 0110 IOR A = A | M [MA] + 0111 ISZ M [MA] = M [MA] + 1, skip if M [MA] == 0 + 1000 ADA A = A + M [MA] + 1001 ADB B = B + M [MA] + 1010 CPA skip if A != M [MA] + 1011 CPB skip if B != M [MA] + 1100 LDA A = M [MA] + 1101 LDB B = M [MA] + 1110 STA M [MA] = A + 1111 STB M [MA] = B - 6. Interrupt deferral. At instruction fetch time, a pending interrupt - request will be deferred if the previous instruction was a JMP indirect, - JSB indirect, STC, CLC, STF, CLF, or was executing from an interrupt trap - cell. In addition, the following instructions will cause deferral on the - 1000 series: SFS, SFC, JRS, DJP, DJS, SJP, SJS, UJP, and UJS. + Bits 15 and 10 encode the type of access, as follows: - On the HP 1000, the request is always deferred until after the current - instruction completes. On the 21xx, the request is deferred unless the - current instruction is an MRG instruction other than JMP or JMP,I or - JSB,I. Note that for the 21xx, SFS and SFC are not included in the - deferral criteria. + 15,10 Access Type Action + ----- --------------------- -------------------------- + 0,0 base page direct MA = I <9:0> + 0,1 current page direct MA = P <14:0>'I <9:0> + 1,0 base page indirect MA = M [I <9:0>] + 1,1 current page indirect MA = M [P <14:10>'I <9:0>] - 7. Terminology. The 1000 series of computers was originally called the 21MX - at introduction. The 21MX (occasionally, 21MXM) corresponds to the 1000 - M-Series, and the 21MXE (occasionally, 21XE) corresponds to the 1000 - E-Series. The model numbers were changed before the introduction of the - 1000 F-Series, although some internal HP documentation refers to a 21MXF. - The terms MEM (Memory Expansion Module), MEU (Memory Expansion Unit), DMI - (Dynamic Mapping Instructions), and DMS (Dynamic Mapping System) are used - somewhat interchangeably to refer to the logical-to-physical memory - address translation option provided on the 1000-Series. DMS consists of - the MEM card (12731A) and the DMI firmware (13307A). However, MEM and MEU - have been used interchangeably to refer to the mapping card, as have DMI - and DMS to refer to the firmware instructions. + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | 0 | 0 0 0 | R | 0 | E | op 1 | C | E | S | op 2 | SRG + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + Where: + + R = A/B register (0/1) + E = disable/enable op + C = CLE + S = SL* + + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | 0 | 0 0 0 | R | 1 | r op | e op | E | S | L | I | Z | V | ASG + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + Where: + + R = A/B register (0/1) + E = SEZ + S = SS* + L = SL* + I = IN* + Z = SZ* + V = RSS + + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | 1 | 0 0 0 | R | 1 | H | I/O op | select code | IOG + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + Where: + + R = A/B register (0/1) + H = hold/clear flag (0/1) + + An I/O group instruction controls the device specified by the select code. + Depending on the opcode, the instruction may set or clear the device flag, + start or stop I/O, or read or write data. + + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | 1 | 0 0 0 | | 0 | eau op | 0 0 0 0 0 0 | EAU + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | 1 | 0 0 0 | | 0 | eau shift/rotate op | shift count | EAU + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + MAC ops decode when bits 15-12 and 10 are 1 000 0. Bits 11 and 9-0 determine + the specific EAU instruction. + + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | 1 | 0 0 0 | R | 0 1 | module | operation | UIG + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + Where: + + R = A/B register (0/1) + + + In simulation, I/O devices are modelled by substituting software states for + I/O backplane signals. The set of signals generated by I/O instructions and + DMA cycles is dispatched to the target device for action. Backplane signals + are processed sequentially. For example, the "STC sc,C" instruction + generates the "set control" and the "clear flag" signals that are processed + in that order. + + CPU interrupt signals are modelled as three parallel arrays: + + - device request priority as bit vector dev_prl [2] [31..0] + - device interrupt requests as bit vector dev_irq [2] [31..0] + - device service requests as bit vector dev_srq [2] [31..0] + + Each array forms a 64-bit vector, with bits 0-31 of the first element + corresponding to select codes 00-37 octal, and bits 0-31 of the second + element corresponding to select codes 40-77 octal. + + The HP 21xx/1000 interrupt structure is based on the PRH, PRL, IRQ, and IAK + signals. PRH indicates that no higher-priority device is interrupting. PRL + indicates to lower-priority devices that a given device is not interrupting. + IRQ indicates that a given device is requesting an interrupt. IAK indicates + that the given device's interrupt request is being acknowledged. + + PRH and PRL form a hardware priority chain that extends from interface to + interface on the backplane. We model just PRL, as PRH is calculated from the + PRLs of higher-priority devices. + + Typical I/O devices have a flag, flag buffer, and control flip-flops. If a + device's flag, flag buffer, and control bits are set, and the device is the + highest priority on the interrupt chain, it requests an interrupt by + asserting IRQ. When the interrupt is acknowledged with IAK, the flag buffer + is cleared, preventing further interrupt requests from that device. The + combination of flag and control set blocks interrupts from lower priority + devices. + + Service requests are used to trigger the DMA service logic. Setting the + device flag typically also sets SRQ, although SRQ may be calculated + independently. + + + The simulator provides three stop conditions related to instruction execution + that may be enabled with a SET CPU STOP= command: + + Action + ------ ------------------------------------------ + UNIMPL stop on an unimplemented instruction + UNDEF stop on an undefined instruction + UNSC stop on an access to an unused select code + IOERR stop on an unreported I/O error + + If an enabled stop condition is detected, execution ceases with the + instruction pending, and control returns to the SCP prompt. When simulation + stops, execution may be resumed in two ways. If the cause of the stop has + not been remedied and the stop has not been disabled, resuming execution with + CONTINUE, STEP, GO, or RUN will cause the stop to occur again. Alternately, + specifying the "-B" switch with any of the preceding commands will resume + execution while bypassing the stop for the current instruction. + + The UNIMPL option stops the simulator if execution is attempted of an + instruction provided by a firmware option that is not currently installed + (e.g., a DAD instruction when the double-integer firmware is not installed) + or of an opcode provided by an installed option but not assigned to an + instruction (e.g., opcode 105335 from the double-integer firmware). + Bypassing the stop will execute the instruction as a NOP (no-operation). + + The UNDEF option stops the simulator if execution is attempted of an + instruction containing a decoded reserved bit pattern other than that defined + in the Operating and Reference manual for the CPU. For example, opcodes + 101700 and 105700 are not listed as DMS instructions, but they execute as + XMM instructions, rather than as NOP. The intent of this stop is to catch + instructions containing reserved fields with values that change the meaning + of those instructions. Bypassing the stop will decode and execute the + instruction in the same manner as the selected CPU. + + The UNSC option stops the simulator if an I/O instruction addresses a select + code that is not assigned to an enabled device (equivalent to an empty + hardware I/O backplane slot). Bypassing the stop will read the floating + S-bus or I/O-bus for LIA/B and MIA/B instructions or do nothing for all other + instructions. + + The IOERR option stops the simulator if an I/O error condition exists for a + device that does not report this status to the CPU. For example, the paper + tape reader device (PTR) does not report "no tape loaded" status, and the + processor interconnect device (IPL) does not report "cable disconnected." In + both cases, I/O to the device will simply hang with no indication of the + problem. Enabling the IOERR option will stop the simulator with an error + indication for these devices. + + In addition, a simulation stop will occur if an indirect addressing chain + exceeds the maximum length specified by a SET CPU INDIR= command. + Memory addresses may be indirect to indicate that the values point to the + target addresses rather than contain the target addresses. The target of an + indirect address may itself be indirect, and the CPU follows this chain of + addresses until it finds a direct address. Indirect addressing is typically + only one or two levels deep, but if the chain loops back on itself (e.g., if + an indirect address points at itself), then instruction execution will hang. + + The limit may be set to any number of levels up to 32,768. This is the + absolute maximum number of levels that can be created without an infinite + loop -- each location in memory points to the next one except for the last, + which contains the target value. In practice, anything over a few levels + likely represents a programming error. The default setting is 16 levels. + + + In addition to the CPU, this module simulates the 12578A/12607B/12895A Direct + Memory Access and 12897B Dual-Channel Port Controller devices (hereafter, + "DMA"). These controllers permit the CPU to transfer data directly between + an I/O device and memory on a cycle-stealing basis. Depending on the CPU, + the device interface, and main memory speed, DMA is capable of transferring + data blocks from 1 to 32,768 words in length at rates between 500,000 and + 1,000,000 words per second. The 2114 supports a single DMA channel. All + other CPUs support two DMA channels. + + DMA is programmed by setting three control words via two select codes: 2 and + 6 for channel 1, and 3 and 7 for channel 2. During simultaneous transfers, + channel 1 has priority over channel 2. Otherwise, the channels are + identical. Channel programming involves setting three control words, as + follows: + + SC 06 Control Word 1 format: + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | S | B | C | - - - - - - - | device select code | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + Where: + + S = assert STC during each cycle + B = enable byte packing and unpacking (12578A only) + C = assert CLC at the end of the block transfer + + SC 02 Control Word 2/3 format: + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | D | starting memory address | word 2 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | negative word count | word 3 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + Where: + + D = transfer direction is out of/into memory (0/1) + + Control word 2 is stored if the control flip-flop of select code 2 is clear, + i.e., if the OTA/B is preceded by CLC; control word 3 is stored if the + flip-flop is set by a preceding STC. + + The 12607B supports 14-bit addresses and 13-bit word counts. The 12578A + supports 15-bit addresses and 14-bit word counts. The 12895A and 12897B + support 15-bit addresses and 16-bit word counts. + + DMA is started by setting the control flip-flop on select code 6. DMA + completion is indicated when the flag flip-flop sets on select code 8, which + causes an interrupt if enabled. + + + This module also simulates the 12581A/12892B Memory Protect devices for the + 2116 and 1000 M/E/F-Series, respectively, and the memory protect feature that + is standard equipment for the 2100. MP is addressed via select code 5 and + provides a fence register that holds the address of the start of unprotected + memory and a violation register that holds the address of the instruction + that has caused a memory protect interrupt, as follows: + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | 0 | starting address of unprotected memory | fence + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | 0 | violating instruction address | violation + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + After setting the fence regiater with an OTA 5 or OTB 5 instruction, MP is + enabled by an STC 5. + + + This module also simulates the 12731A Memory Expansion Module for the 1000 + M/E/F-Series machines. The MEM provides mapping of the 32 1024-word logical + memory pages into a one-megaword physical memory. Four separate maps are + provided: system, user, DCPC port A, and DCPC port B. The MEM is controlled + by the associated Dynamic Mapping System instructions and contains status and + violation registers, as follows: + + MEM Status Register: + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | I | M | E | U | P | B | base page fence address | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + Where: + + I = MEM disabled/enabled (0/1) at last interrupt + M = System/user map (0/1) selected at last interrupt + E = MEM disabled/enabled (0/1) currently + U = System/user map (0/1) selected currently + P = Protected mode disabled/enabled (0/1) currently + B = Base-page portion mapped (0/1 = above/below the fence) + + MEM Violation Register: + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + | R | W | B | P | - - - - | S | E | M | map address | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + Where: + + R = Read violation + W = Write violation + B = Base-page violation + P = Privileged instruction violation + S = ME bus disabled/enabled (0/1) at violation + E = MEM disabled/enabled (0/1) at violation + M = System/user map (0/1) selected at violation + + + The CPU simulator provides extensive tracing capabilities that may be enabled + with the SET DEBUG and SET CPU DEBUG= commands. The trace + options that may be specified are: + + Trace Action + ----- ------------------------------------------- + INSTR trace instructions executed + DATA trace memory data accesses + FETCH trace memory instruction fetches + REG trace registers + OPND trace instruction operands + EXEC trace matching instruction execution states + + A section of an example trace is: + + >>CPU instr: S 0002 05735 103101 CLO + >>CPU fetch: S 0002 05736 000036 instruction fetch + >>CPU reg: - **** 01011 042200 A 177777, B 000000, X 177777, Y 000000, e o i + >>CPU instr: S 0002 05736 000036 SLA,ELA + >>CPU fetch: S 0002 05737 102101 instruction fetch + >>CPU reg: - **** 01011 042200 A 177776, B 000000, X 177777, Y 000000, E o i + >>CPU instr: S 0002 05737 102101 STO + >>CPU fetch: S 0002 05740 002400 instruction fetch + >>CPU reg: - **** 01011 042200 A 177776, B 000000, X 177777, Y 000000, E O i + >>CPU instr: S 0002 05755 102100 STF 0 + >>CPU fetch: S 0002 05756 102705 instruction fetch + >>CPU reg: - **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O I + >>CPU instr: S 0002 05756 102705 STC 5 + >>CPU fetch: S 0002 05757 105736 instruction fetch + >>CPU reg: P **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O I + >>CPU instr: S 0002 05757 105736 UJP 2111 + >>CPU fetch: S 0002 05760 002111 instruction fetch + >>CPU fetch: U 0001 02111 026111 instruction fetch + >>CPU reg: P **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O I + >>CPU instr: U 0001 02111 026111 JMP 2111 + >>CPU instr: U 0001 02111 000011 interrupt + >>CPU fetch: S 0000 00011 115013 instruction fetch + >>CPU reg: - **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O I + >>CPU reg: - **** ***** ****** MPF 000000, MPV 002111, MES 163011, MEV 030000 + >>CPU instr: S 0000 00011 115013 JSB 1013,I + >>CPU data: S 0000 01013 005557 data read + >>CPU data: S 0002 05557 002111 data write + >>CPU fetch: S 0002 05560 103100 instruction fetch + >>CPU reg: - **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O I + >>CPU instr: S 0002 05560 103100 CLF 0 + >>CPU fetch: S 0002 05561 105714 instruction fetch + >>CPU reg: - **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O i + >>CPU exec: ******************** + >>CPU reg: P **** 01567 000000 A 100036, B 000100, X 000100, Y 074000, E o I + >>CPU instr: U 0220 07063 105240 .PMAP + >>CPU data: U 0000 01776 000227 unprotected read + >>CPU data: U 0227 76100 000233 data read + >>CPU opnd: * **** 07065 105240 return location is P+2 (no error) + >>CPU fetch: U 0220 07065 127055 instruction fetch + >>CPU reg: P **** 01567 000000 A 100037, B 000101, X 000100, Y 074000, e o I + + The INSTR option traces instruction executions and interrupts. Each + instruction is printed in symbolic form before it is executed. + + The DATA option traces reads from and writes to memory. Each access is + classified by its usage type as "data" (using the current or alternate map + with access protection) or "unprotected" (using a specified map without + protection). + + The FETCH option traces instruction fetches from memory. Reads of the + additional words in a multiword instruction, such as the target address of a + DLD (double load) instruction, are also classified as fetches. + + The REG option traces register values. Two sets of registers are printed. + After executing each instruction, the working registers (A, B, E, O, S, and, + for 1000 CPUs, X and Y) and the state of the interrupt system (on or off) are + printed. After executing an instruction that may alter the Memory Protect or + Memory Expansion Module state, the MP fence and violation registers, the MEM + status and violation registers, and the current protection state are printed. + + The OPND option traces operand values. Some instructions that take memory + and register operands that are difficult to decode from DATA or REG traces + present the operand values in a higher-level format. The operand data and + value presented are specific to the instruction; see the instruction executor + comments for details. + + The EXEC option traces the execution of instructions that match + user-specified criteria. When a match occurs, all CPU trace options are + turned on for the duration of the execution of the matched instruction. The + prior trace settings are restored when a match fails. This option allows + detailed tracing of specified instructions while minimizing the log file size + compared to a full instruction trace. + + The various trace formats are interpreted as follows: + + >>CPU instr: U 0045 10341 016200 LDA 11200 + ~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~ + | | | | | + | | | | +-- instruction mnemonic + | | | +---------- octal data (instruction opcode) + | | +------------------ octal logical address (P register) + | +----------------------- octal physical page number + +--------------------------- memory map (S/U/- system/user/disabled) + + >>CPU instr: U 0045 10341 000011 interrupt + ~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~ + | | | | | + | | | | +-- interrupt classification + | | | +---------- octal device number (CIR register) + | | +------------------ octal logical address at interrupt (P register) + | +----------------------- octal physical page number at interrupt + +--------------------------- memory map (S/U/- system/user/disabled) + + >>CPU fetch: - 0000 10341 016200 instruction fetch + >>CPU data: U 0013 01200 123003 data read + >>CPU data: S 0013 01200 017200 unprotected write + ~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~ + | | | | | + | | | | +-- memory access classification + | | | +------------ octal data (memory contents) + | | +-------------------- octal logical address (effective address) + | +------------------------- octal physical page number + +----------------------------- memory map (S/U/A/B/- system/user/port A/port B/disabled) + + >>CPU reg: P .... 01535 040013 A 123003, B 001340, X 000000, Y 000000, e O I + ~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | | | | | + | | | | +-- A, B, X, Y, E, O, interrupt system registers + | | | | (lower/upper case = 0/1 or off/on) + | | | +------------ S register + | | +-------------------- MEM fence + | +------------------------- + +----------------------------- protection state (P/- protected/unprotected) + + >>CPU reg: P .... ..... ...... MPF 00000, MPV 000000, MES 000000, MEV 000000 + ~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | | | | | + | | | | +-- memory protect fence and violation registers + | | | | memory expansion status and violation registers + | | | +------------ + | | +-------------------- + | +------------------------- + +----------------------------- protection state (P/- protected/unprotected) + + + + >>CPU opnd: . .... 36002 101475 return location is P+3 (error EM21) + >>CPU opnd: . .... 22067 105355 entry is for a dynamic mapping violation + ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | | | + | | +-- operand-specific value + | +------------ operand-specific octal data + +-------------------- octal logical address (P register) + + + Implementation notes: + + 1. The simulator is fast enough, compared to the run-time of the longest + instructions, for interruptibility not to matter. However, the HP + diagnostics explicitly test interruptibility in the EIS and DMS + instructions and in long indirect address chains. Accordingly, the + simulator does "just enough" to pass these tests. In particular, if an + interrupt is pending but deferred at the beginning of an interruptible + instruction, the interrupt is taken at the appropriate point; but there + is no testing for new interrupts during execution (that is, the event + timer is not called). */ + #include "hp2100_defs.h" #include "hp2100_cpu.h" #include "hp2100_cpu1.h" -/* Memory protect constants */ - -#define UNIT_V_MP_JSB (UNIT_V_UF + 0) /* MP jumper W5 */ -#define UNIT_V_MP_INT (UNIT_V_UF + 1) /* MP jumper W6 */ -#define UNIT_V_MP_SEL1 (UNIT_V_UF + 2) /* MP jumper W7 */ -#define UNIT_MP_JSB (1 << UNIT_V_MP_JSB) /* 1 = W5 is out */ -#define UNIT_MP_INT (1 << UNIT_V_MP_INT) /* 1 = W6 is out */ -#define UNIT_MP_SEL1 (1 << UNIT_V_MP_SEL1) /* 1 = W7 is out */ - -/* DMA channels */ - -typedef enum { ch1, ch2 } CHANNEL; /* channel number */ - -#define DMA_CHAN_COUNT 2 /* number of DMA channels */ - -#define DMA_OE 020000000000 /* byte packing odd/even flag */ -#define DMA1_STC 0100000 /* DMA - issue STC */ -#define DMA1_PB 0040000 /* DMA - pack bytes */ -#define DMA1_CLC 0020000 /* DMA - issue CLC */ -#define DMA2_OI 0100000 /* DMA - output/input */ - -typedef struct { - FLIP_FLOP control; /* control flip-flop */ - FLIP_FLOP flag; /* flag flip-flop */ - FLIP_FLOP flagbuf; /* flag buffer flip-flop */ - FLIP_FLOP xferen; /* transfer enable flip-flop */ - FLIP_FLOP select; /* register select flip-flop */ - - uint32 cw1; /* device select */ - uint32 cw2; /* direction, address */ - uint32 cw3; /* word count */ - uint32 packer; /* byte-packer holding reg */ - } DMA_STATE; - -#define DMA_1_REQ (1 << ch1) /* channel 1 request */ -#define DMA_2_REQ (1 << ch2) /* channel 2 request */ - - -/* Command line switches */ - -#define ALL_BKPTS (SWMASK('E')|SWMASK('N')|SWMASK('S')|SWMASK('U')) -#define ALL_MAPMODES (SWMASK('S')|SWMASK('U')|SWMASK('P')|SWMASK('Q')) - - -/* RTE base-page addresses. */ - -static const uint32 xeqt = 0001717; /* XEQT address */ -static const uint32 tbg = 0001674; /* TBG address */ - -/* DOS base-page addresses. */ - -static const uint32 m64 = 0000040; /* constant -64 address */ -static const uint32 p64 = 0000067; /* constant +64 address */ - -/* CPU local data */ - -static uint32 jsb_plb = 2; /* protected lower bound for JSB */ -static uint32 saved_MR = 0; /* between executions */ -static uint32 fwanxm = 0; /* first word addr of nx mem */ - -/* CPU global data */ - -uint16 *M = NULL; /* memory */ -uint16 ABREG[2]; /* A/B registers */ -uint32 PR = 0; /* P register */ -uint32 SR = 0; /* S register */ -uint32 MR = 0; /* M register */ -uint32 TR = 0; /* T register */ -uint32 XR = 0; /* X register */ -uint32 YR = 0; /* Y register */ -uint32 E = 0; /* E register */ -uint32 O = 0; /* O register */ -FLIP_FLOP ion = CLEAR; /* interrupt enable */ -t_bool ion_defer = FALSE; /* interrupt defer */ -uint32 intaddr = 0; /* interrupt addr */ -uint32 stop_inst = 1; /* stop on ill inst */ -uint32 stop_dev = 0; /* stop on ill dev */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -uint32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ - -uint32 dev_prl [2] = { ~(uint32) 0, ~(uint32) 0 }; /* device priority low bit vector */ -uint32 dev_irq [2] = { 0, 0 }; /* device interrupt request bit vector */ -uint32 dev_srq [2] = { 0, 0 }; /* device service request bit vector */ - -/* Memory protect global data */ - -FLIP_FLOP mp_control = CLEAR; /* MP control flip-flop */ -FLIP_FLOP mp_flag = CLEAR; /* MP flag flip-flop */ -FLIP_FLOP mp_flagbuf = CLEAR; /* MP flag buffer flip-flop */ -FLIP_FLOP mp_mevff = CLEAR; /* memory expansion violation flip-flop */ -FLIP_FLOP mp_evrff = SET; /* enable violation register flip-flop */ - -uint32 mp_fence = 0; /* MP fence register */ -uint32 mp_viol = 0; /* MP violation register */ - -uint32 iop_sp = 0; /* iop stack reg */ -uint32 ind_max = 16; /* iadr nest limit */ -uint32 err_PC = 0; /* error PC */ -jmp_buf save_env; /* MP abort handler */ - -/* DMA global data */ - -DMA_STATE dma [DMA_CHAN_COUNT]; /* per-channel state */ - -/* Dynamic mapping system global data */ - -uint32 dms_enb = 0; /* dms enable */ -uint32 dms_ump = 0; /* dms user map */ -uint32 dms_sr = 0; /* dms status reg */ -uint32 dms_vr = 0; /* dms violation reg */ -uint16 dms_map[MAP_NUM * MAP_LNT] = { 0 }; /* dms maps */ /* External data */ extern DIB clk_dib; /* CLK DIB for idle check */ +extern DIB ptr_dib; /* PTR DIB for BBL configuration */ + extern const BOOT_ROM ptr_rom, dq_rom, ms_rom, ds_rom; /* boot ROMs for cpu_boot routine */ -/* CPU local routines */ -static t_stat Ea (uint32 IR, uint32 *addr, uint32 irq); -static uint16 ReadTAB (uint32 va); -static uint32 dms (uint32 va, uint32 map, uint32 prot); -static uint32 shift (uint32 inval, uint32 flag, uint32 oper); -static t_stat dma_cycle (CHANNEL chan, uint32 map); -static uint32 calc_dma (void); -static t_bool dev_conflict (void); -static uint32 devdisp (uint32 select_code, IOCYCLE signal_set, uint16 data); - -/* CPU global routines */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_boot (int32 unitno, DEVICE *dptr); -t_stat mp_reset (DEVICE *dptr); -t_stat dma_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 new_size, CONST char *cptr, void *desc); -t_stat cpu_set_model (UNIT *uptr, int32 new_model, CONST char *cptr, void *desc); -t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, CONST void *desc); -t_stat cpu_set_opt (UNIT *uptr, int32 option, CONST char *cptr, void *desc); -t_stat cpu_clr_opt (UNIT *uptr, int32 option, CONST char *cptr, void *desc); -t_stat cpu_set_ldr (UNIT *uptr, int32 enable, CONST char *cptr, void *desc); -t_stat cpu_set_idle (UNIT *uptr, int32 option, CONST char *cptr, void *desc); -t_stat cpu_show_idle (FILE *st, UNIT *uptr, int32 val, CONST void *desc); -void hp_post_cmd (t_bool from_scp); - -IOHANDLER cpuio; -IOHANDLER ovflio; -IOHANDLER pwrfio; -IOHANDLER protio; -IOHANDLER dmapio; -IOHANDLER dmasio; -IOHANDLER nullio; +/* CPU program constants */ -/* Table of CPU features by model. +/* Command line switches */ - Fields: - - typ: standard features plus typically configured options. - - opt: complete list of optional features. - - maxmem: maximum configurable memory in 16-bit words. - - Features in the "typical" list are enabled when the CPU model is selected. - If a feature appears in the "typical" list but NOT in the "optional" list, - then it is standard equipment and cannot be disabled. If a feature appears - in the "optional" list, then it may be enabled or disabled as desired by the - user. -*/ - -struct FEATURE_TABLE { /* CPU model feature table: */ - uint32 typ; /* - typical features */ - uint32 opt; /* - optional features */ - uint32 maxmem; /* - maximum memory */ - }; - -static struct FEATURE_TABLE cpu_features[] = { /* features in UNIT_xxxx order*/ - { UNIT_DMA | UNIT_MP, /* UNIT_2116 */ - UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_EAU, - 32768 }, - { UNIT_DMA, /* UNIT_2115 */ - UNIT_PFAIL | UNIT_DMA | UNIT_EAU, - 8192 }, - { UNIT_DMA, /* UNIT_2114 */ - UNIT_PFAIL | UNIT_DMA, - 16384 }, - { 0, 0, 0 }, - { UNIT_PFAIL | UNIT_MP | UNIT_DMA | UNIT_EAU, /* UNIT_2100 */ - UNIT_DMA | UNIT_FP | UNIT_IOP | UNIT_FFP, - 32768 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | UNIT_DMS, /* UNIT_1000_M */ - UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_DMS | - UNIT_IOP | UNIT_FFP | UNIT_DS, - 1048576 }, - { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | UNIT_DMS, /* UNIT_1000_E */ - UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_DMS | - UNIT_IOP | UNIT_FFP | UNIT_DBI | UNIT_DS | UNIT_EMA_VMA, - 1048576 }, - { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | /* UNIT_1000_F */ - UNIT_FFP | UNIT_DBI | UNIT_DMS, - UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_VIS | - UNIT_IOP | UNIT_DS | UNIT_SIGNAL | UNIT_EMA_VMA, - 1048576 } - }; +#define ALL_MAPMODES (SWMASK ('S') | SWMASK ('U') | SWMASK ('P') | SWMASK ('Q')) -/* Null device information block */ +/* RTE base-page addresses */ -DIB null_dib = { &nullio, 0 }; +static const uint32 xeqt = 0001717; /* XEQT address */ +static const uint32 tbg = 0001674; /* TBG address */ -/* CPU data structures +/* DOS base-page addresses */ - cpu_dib CPU device information block - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifiers list - cpu_deb CPU debug flags -*/ +static const uint32 m64 = 0000040; /* constant -64 address */ +static const uint32 p64 = 0000067; /* constant +64 address */ -DIB cpu_dib = { &cpuio, CPU }; -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, 0) }; +/* CPU global SCP data definitions */ -REG cpu_reg[] = { - { ORDATA (P, PR, 15) }, - { ORDATA (A, AR, 16), REG_FIT }, - { ORDATA (B, BR, 16), REG_FIT }, - { ORDATA (M, MR, 15) }, - { ORDATA (T, TR, 16), REG_RO }, - { ORDATA (X, XR, 16) }, - { ORDATA (Y, YR, 16) }, - { ORDATA (S, SR, 16) }, - { FLDATA (E, E, 0) }, - { FLDATA (O, O, 0) }, - { FLDATA (ION, ion, 0) }, - { FLDATA (ION_DEFER, ion_defer, 0) }, - { ORDATA (CIR, intaddr, 6) }, - { FLDATA (DMSENB, dms_enb, 0) }, - { FLDATA (DMSCUR, dms_ump, VA_N_PAG) }, - { ORDATA (DMSSR, dms_sr, 16) }, - { ORDATA (DMSVR, dms_vr, 16) }, - { BRDATA (DMSMAP, dms_map, 8, 16, MAP_NUM * MAP_LNT) }, - { ORDATA (IOPSP, iop_sp, 16) }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { FLDATA (STOP_DEV, stop_dev, 1) }, - { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, - { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (JSBPLB, jsb_plb, 32), REG_HRO }, - { ORDATA (SAVEDMR, saved_MR, 32), REG_HRO }, - { ORDATA (FWANXM, fwanxm, 32), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8), REG_HRO }, - { ORDATA (BRK, sim_brk_char, 8), REG_HRO }, - { ORDATA (DEL, sim_del_char, 8), REG_HRO }, - { BRDATA (PRL, dev_prl, 8, 32, 2), REG_HRO }, - { BRDATA (IRQ, dev_irq, 8, 32, 2), REG_HRO }, - { BRDATA (SRQ, dev_srq, 8, 32, 2), REG_HRO }, - { NULL } - }; +REG *sim_PC = NULL; /* the pointer to the P register */ -/* CPU modifier table. - The 21MX monikers are deprecated in favor of the 1000 designations. See the - "HP 1000 Series Naming History" on the back inside cover of the Technical - Reference Handbook. */ +/* CPU global data structures */ -MTAB cpu_mod[] = { - { UNIT_MODEL_MASK, UNIT_2116, "", "2116", &cpu_set_model, &cpu_show_model, (void *) "2116" }, - { UNIT_MODEL_MASK, UNIT_2115, "", "2115", &cpu_set_model, &cpu_show_model, (void *) "2115" }, - { UNIT_MODEL_MASK, UNIT_2114, "", "2114", &cpu_set_model, &cpu_show_model, (void *) "2114" }, - { UNIT_MODEL_MASK, UNIT_2100, "", "2100", &cpu_set_model, &cpu_show_model, (void *) "2100" }, - { UNIT_MODEL_MASK, UNIT_1000_E, "", "1000-E", &cpu_set_model, &cpu_show_model, (void *) "1000-E" }, - { UNIT_MODEL_MASK, UNIT_1000_E, NULL, "21MX-E", &cpu_set_model, &cpu_show_model, (void *) "1000-E" }, - { UNIT_MODEL_MASK, UNIT_1000_M, "", "1000-M", &cpu_set_model, &cpu_show_model, (void *) "1000-M" }, - { UNIT_MODEL_MASK, UNIT_1000_M, NULL, "21MX-M", &cpu_set_model, &cpu_show_model, (void *) "1000-M" }, -#if defined (HAVE_INT64) - { UNIT_MODEL_MASK, UNIT_1000_F, "", "1000-F", &cpu_set_model, &cpu_show_model, (void *) "1000-F" }, -#endif +/* CPU registers */ - { MTAB_XTD | MTAB_VDV, 1, "IDLE", "IDLE", &cpu_set_idle, &cpu_show_idle, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "NOIDLE", &cpu_set_idle, NULL, NULL }, +HP_WORD ABREG [2] = { 0, 0}; /* A and B registers */ +HP_WORD PR = 0; /* P register */ +HP_WORD SR = 0; /* S register */ +HP_WORD MR = 0; /* M register */ +HP_WORD TR = 0; /* T register */ +HP_WORD XR = 0; /* X register */ +HP_WORD YR = 0; /* Y register */ +uint32 E = 0; /* E register */ +uint32 O = 0; /* O register */ - { MTAB_XTD | MTAB_VDV, 1, NULL, "LOADERENABLE", &cpu_set_ldr, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "LOADERDISABLE", &cpu_set_ldr, NULL, NULL }, +HP_WORD IR = 0; /* Instruction Register */ +HP_WORD CIR = 0; /* Central Interrupt Register */ - { UNIT_EAU, UNIT_EAU, "EAU", "EAU", &cpu_set_opt, NULL, NULL }, - { UNIT_EAU, 0, "no EAU", NULL, NULL, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_EAU, NULL, "NOEAU", &cpu_clr_opt, NULL, NULL }, - { UNIT_FP, UNIT_FP, "FP", "FP", &cpu_set_opt, NULL, NULL }, - { UNIT_FP, 0, "no FP", NULL, NULL, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_FP, NULL, "NOFP", &cpu_clr_opt, NULL, NULL }, +/* CPU global state */ - { UNIT_IOP, UNIT_IOP, "IOP", "IOP", &cpu_set_opt, NULL, NULL }, - { UNIT_IOP, 0, "no IOP", NULL, NULL, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_IOP, NULL, "NOIOP", &cpu_clr_opt, NULL, NULL }, +FLIP_FLOP ion = CLEAR; /* interrupt enable */ +t_bool ion_defer = FALSE; /* interrupt defer */ - { UNIT_DMS, UNIT_DMS, "DMS", "DMS", &cpu_set_opt, NULL, NULL }, - { UNIT_DMS, 0, "no DMS", NULL, NULL, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_DMS, NULL, "NODMS", &cpu_clr_opt, NULL, NULL }, +t_stat cpu_ss_unimpl = SCPE_OK; /* status return for unimplemented instruction execution */ +t_stat cpu_ss_undef = SCPE_OK; /* status return for undefined instruction execution */ +t_stat cpu_ss_unsc = SCPE_OK; /* status return for I/O to an unassigned select code */ +t_stat cpu_ss_ioerr = SCPE_OK; /* status return for an unreported I/O error */ +t_stat cpu_ss_inhibit = SCPE_OK; /* CPU stop inhibition mask */ +UNIT *cpu_ioerr_uptr = NULL; /* pointer to a unit with an unreported I/O error */ - { UNIT_FFP, UNIT_FFP, "FFP", "FFP", &cpu_set_opt, NULL, NULL }, - { UNIT_FFP, 0, "no FFP", NULL, NULL, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_FFP, NULL, "NOFFP", &cpu_clr_opt, NULL, NULL }, +uint16 pcq [PCQ_SIZE] = { 0 }; /* PC queue (must be 16-bits wide for REG array entry) */ +uint32 pcq_p = 0; /* PC queue ptr */ +REG *pcq_r = NULL; /* PC queue reg ptr */ - { UNIT_DBI, UNIT_DBI, "DBI", "DBI", &cpu_set_opt, NULL, NULL }, - { UNIT_DBI, 0, "no DBI", NULL, NULL, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_DBI, NULL, "NODBI", &cpu_clr_opt, NULL, NULL }, +uint32 cpu_configuration; /* the current CPU option set and model */ +uint32 cpu_speed = 1; /* the CPU speed, expressed as a multiplier of a real machine */ - { UNIT_EMA_VMA, UNIT_EMA, "EMA", "EMA", &cpu_set_opt, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_EMA, NULL, "NOEMA", &cpu_clr_opt, NULL, NULL }, +uint32 dev_prl [2] = { ~0u, ~0u }; /* device priority low bit vector */ +uint32 dev_irq [2] = { 0u, 0u }; /* device interrupt request bit vector */ +uint32 dev_srq [2] = { 0u, 0u }; /* device service request bit vector */ - { UNIT_EMA_VMA, UNIT_VMAOS, "VMA", "VMA", &cpu_set_opt, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_VMAOS, NULL, "NOVMA", &cpu_clr_opt, NULL, NULL }, - { UNIT_EMA_VMA, 0, "no EMA/VMA", NULL, &cpu_set_opt, NULL, NULL }, +/* Main memory global state */ -#if defined (HAVE_INT64) - { UNIT_VIS, UNIT_VIS, "VIS", "VIS", &cpu_set_opt, NULL, NULL }, - { UNIT_VIS, 0, "no VIS", NULL, NULL, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_VIS, NULL, "NOVIS", &cpu_clr_opt, NULL, NULL }, +MEMORY_WORD *M = NULL; /* pointer to allocated memory */ - { UNIT_SIGNAL, UNIT_SIGNAL,"SIGNAL", "SIGNAL", &cpu_set_opt, NULL, NULL }, - { UNIT_SIGNAL, 0, "no SIGNAL", NULL, NULL, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_SIGNAL, NULL, "NOSIGNAL", &cpu_clr_opt, NULL, NULL }, -#endif -/* Future microcode support. - { UNIT_DS, UNIT_DS, "DS", "DS", &cpu_set_opt, NULL, NULL }, - { UNIT_DS, 0, "no DS", NULL, NULL, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, UNIT_DS, NULL, "NODS", &cpu_clr_opt, NULL, NULL }, -*/ +/* Memory Expansion Unit global state */ - { MTAB_XTD | MTAB_VDV, 4096, NULL, "4K", &cpu_set_size, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 8192, NULL, "8K", &cpu_set_size, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 12288, NULL, "12K", &cpu_set_size, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 16384, NULL, "16K", &cpu_set_size, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 24576, NULL, "24K", &cpu_set_size, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 32768, NULL, "32K", &cpu_set_size, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 65536, NULL, "64K", &cpu_set_size, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 131072, NULL, "128K", &cpu_set_size, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 262144, NULL, "256K", &cpu_set_size, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 524288, NULL, "512K", &cpu_set_size, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 1048576, NULL, "1024K", &cpu_set_size, NULL, NULL }, - { 0 } - }; +uint32 dms_enb = 0; /* dms enable */ +uint32 dms_ump = 0; /* dms user map */ +HP_WORD dms_sr = 0; /* dms status reg */ -DEBTAB cpu_deb[] = { - { "OS", DEB_OS }, - { "OSTBG", DEB_OSTBG }, - { "VMA", DEB_VMA }, - { "EMA", DEB_EMA }, - { "VIS", DEB_VIS }, - { "SIG", DEB_SIG }, - { NULL, 0 } - }; -DEVICE cpu_dev = { - "CPU", /* device name */ - &cpu_unit, /* unit array */ - cpu_reg, /* register array */ - cpu_mod, /* modifier array */ - 1, /* number of units */ - 8, /* address radix */ - PA_N_SIZE, /* address width */ - 1, /* address increment */ - 8, /* data radix */ - 16, /* data width */ - &cpu_ex, /* examine routine */ - &cpu_dep, /* deposit routine */ - &cpu_reset, /* reset routine */ - &cpu_boot, /* boot routine */ - NULL, /* attach routine */ - NULL, /* detach routine */ - &cpu_dib, /* device information block */ - DEV_DEBUG, /* device flags */ - 0, /* debug control flags */ - cpu_deb, /* debug flag name table */ - NULL, /* memory size change routine */ - NULL }; /* logical device name */ +/* CPU local state */ -/* Overflow device information block */ +static HP_WORD saved_MR = 0; /* M-register value between SCP commands */ +static uint32 fwanxm = 0; /* first word addr of nx mem */ +static uint32 jsb_plb = 2; /* protected lower bound for JSB */ -DIB ovfl_dib = { &ovflio, OVF }; +static uint32 exec_mask = 0; /* the current instruction execution trace mask */ +static uint32 exec_match = D16_UMAX; /* the current instruction execution trace matching value */ +static uint32 indirect_limit = 16; /* the indirect chain length limit */ -/* Powerfail device information block */ -DIB pwrf_dib = { &pwrfio, PWR }; +/* Memory Expansion Unit local state */ -/* Memory protect data structures +static HP_WORD dms_vr = 0; /* dms violation reg */ +static uint16 dms_map [MAP_NUM * MAP_LNT] = { 0 }; /* dms maps (must be 16-bits wide for REG array entry) */ - mp_dib MP device information block - mp_dev MP device descriptor - mp_unit MP unit descriptor - mp_reg MP register list - mp_mod MP modifiers list -*/ -DIB mp_dib = { &protio, PRO }; - -UNIT mp_unit = { UDATA (NULL, UNIT_MP_SEL1, 0) }; /* default is JSB in, INT in, SEL1 out */ - -REG mp_reg[] = { - { FLDATA (CTL, mp_control, 0) }, - { FLDATA (FLG, mp_flag, 0) }, - { FLDATA (FBF, mp_flagbuf, 0) }, - { ORDATA (FR, mp_fence, 15) }, - { ORDATA (VR, mp_viol, 16) }, - { FLDATA (EVR, mp_evrff, 0) }, - { FLDATA (MEV, mp_mevff, 0) }, - { NULL } - }; - -MTAB mp_mod[] = { - { UNIT_MP_JSB, UNIT_MP_JSB, "JSB (W5) out", "JSBOUT", NULL }, - { UNIT_MP_JSB, 0, "JSB (W5) in", "JSBIN", NULL }, - { UNIT_MP_INT, UNIT_MP_INT, "INT (W6) out", "INTOUT", NULL }, - { UNIT_MP_INT, 0, "INT (W6) in", "INTIN", NULL }, - { UNIT_MP_SEL1, UNIT_MP_SEL1, "SEL1 (W7) out", "SEL1OUT", NULL }, - { UNIT_MP_SEL1, 0, "SEL1 (W7) in", "SEL1IN", NULL }, - { 0 } - }; - -DEVICE mp_dev = { - "MP", /* device name */ - &mp_unit, /* unit array */ - mp_reg, /* register array */ - mp_mod, /* modifier array */ - 1, /* number of units */ - 8, /* address radix */ - 1, /* address width */ - 1, /* address increment */ - 8, /* data radix */ - 16, /* data width */ - NULL, /* examine routine */ - NULL, /* deposit routine */ - &mp_reset, /* reset routine */ - NULL, /* boot routine */ - NULL, /* attach routine */ - NULL, /* detach routine */ - &mp_dib, /* device information block */ - DEV_DISABLE | DEV_DIS, /* device flags */ - 0, /* debug control flags */ - NULL, /* debug flag name table */ - NULL, /* memory size change routine */ - NULL }; /* logical device name */ - -/* DMA controller data structures - - dmax_dib DMAx device information block - dmax_dev DMAx device descriptor - dmax_reg DMAx register list -*/ - -DIB dmap1_dib = { &dmapio, DMA1, ch1 }; -DIB dmas1_dib = { &dmasio, DMALT1, ch1 }; - -UNIT dma1_unit = { UDATA (NULL, 0, 0) }; - -REG dma1_reg[] = { - { FLDATA (XFR, dma [ch1].xferen, 0) }, - { FLDATA (CTL, dma [ch1].control, 0) }, - { FLDATA (FLG, dma [ch1].flag, 0) }, - { FLDATA (FBF, dma [ch1].flagbuf, 0) }, - { FLDATA (CTL2, dma [ch1].select, 0) }, - { ORDATA (CW1, dma [ch1].cw1, 16) }, - { ORDATA (CW2, dma [ch1].cw2, 16) }, - { ORDATA (CW3, dma [ch1].cw3, 16) }, - { FLDATA (BYTE, dma [ch1].packer, 31) }, - { ORDATA (PACKER, dma [ch1].packer, 8) }, - { NULL } - }; - -DEVICE dma1_dev = { - "DMA1", /* device name */ - &dma1_unit, /* unit array */ - dma1_reg, /* register array */ - NULL, /* modifier array */ - 1, /* number of units */ - 8, /* address radix */ - 1, /* address width */ - 1, /* address increment */ - 8, /* data radix */ - 16, /* data width */ - NULL, /* examine routine */ - NULL, /* deposit routine */ - &dma_reset, /* reset routine */ - NULL, /* boot routine */ - NULL, /* attach routine */ - NULL, /* detach routine */ - &dmap1_dib, /* device information block */ - DEV_DISABLE, /* device flags */ - 0, /* debug control flags */ - NULL, /* debug flag name table */ - NULL, /* memory size change routine */ - NULL }; /* logical device name */ - -DIB dmap2_dib = { &dmapio, DMA2, ch2 }; -DIB dmas2_dib = { &dmasio, DMALT2, ch2 }; - -UNIT dma2_unit = { UDATA (NULL, 0, 0) }; - -REG dma2_reg[] = { - { FLDATA (XFR, dma [ch2].xferen, 0) }, - { FLDATA (CTL, dma [ch2].control, 0) }, - { FLDATA (FLG, dma [ch2].flag, 0) }, - { FLDATA (FBF, dma [ch2].flagbuf, 0) }, - { FLDATA (CTL2, dma [ch2].select, 0) }, - { ORDATA (CW1, dma [ch2].cw1, 16) }, - { ORDATA (CW2, dma [ch2].cw2, 16) }, - { ORDATA (CW3, dma [ch2].cw3, 16) }, - { FLDATA (BYTE, dma [ch2].packer, 31) }, - { ORDATA (PACKER, dma [ch2].packer, 8) }, - { NULL } - }; - -DEVICE dma2_dev = { - "DMA2", /* device name */ - &dma2_unit, /* unit array */ - dma2_reg, /* register array */ - NULL, /* modifier array */ - 1, /* number of units */ - 8, /* address radix */ - 1, /* address width */ - 1, /* address increment */ - 8, /* data radix */ - 16, /* data width */ - NULL, /* examine routine */ - NULL, /* deposit routine */ - &dma_reset, /* reset routine */ - NULL, /* boot routine */ - NULL, /* attach routine */ - NULL, /* detach routine */ - &dmap2_dib, /* device information block */ - DEV_DISABLE, /* device flags */ - 0, /* debug control flags */ - NULL, /* debug flag name table */ - NULL, /* memory size change routine */ - NULL }; /* logical device name */ - -static DEVICE *dma_dptrs [] = { &dma1_dev, &dma2_dev }; +/* CPU local data structures */ /* Interrupt deferral table (1000 version) */ -/* Deferral for I/O subops: soHLT, soFLG, soSFC, soSFS, soMIX, soLIX, soOTX, soCTL */ -static t_bool defer_tab [] = { FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE }; -/* Device I/O dispatch table */ +static t_bool defer_tab [] = { /* deferral table, indexed by I/O sub-opcode */ + FALSE, /* soHLT */ + TRUE, /* soFLG */ + TRUE, /* soSFC */ + TRUE, /* soSFS */ + FALSE, /* soMIX */ + FALSE, /* soLIX */ + FALSE, /* soOTX */ + TRUE /* soCTL */ + }; -DIB *dtab [64] = { &cpu_dib, &ovfl_dib }; /* init with immutable devices */ +/* Basic Binary Loader */ + +static const BOOT_ROM bbl = { + 0107700, 0063770, 0106501, 0004010, + 0002400, 0006020, 0063771, 0073736, + 0006401, 0067773, 0006006, 0027717, + 0107700, 0102077, 0027700, 0017762, + 0002003, 0027712, 0003104, 0073774, + 0017762, 0017753, 0070001, 0073775, + 0063775, 0043772, 0002040, 0027751, + 0017753, 0044000, 0000000, 0002101, + 0102000, 0037775, 0037774, 0027730, + 0017753, 0054000, 0027711, 0102011, + 0027700, 0102055, 0027700, 0000000, + 0017762, 0001727, 0073776, 0017762, + 0033776, 0127753, 0000000, 0103710, + 0102310, 0027764, 0102510, 0127762, + 0173775, 0153775, 0100100, 0177765, + 0000000, 0000000, 0000000, 0000000 + }; + +#define BBL_FWA 072 /* BBL location to store negative FWA */ + + +/* CPU features table. + + The feature table is used to validate CPU feature changes within the subset + of features supported by a given CPU. Features in the typical list are + enabled when the CPU model is selected. If a feature appears in the typical + list but NOT in the optional list, then it is standard equipment and cannot + be disabled. If a feature appears in the optional list, then it may be + enabled or disabled as desired by the user. +*/ + +struct FEATURE_TABLE { /* CPU model feature table: */ + uint32 typ; /* - typical features */ + uint32 opt; /* - optional features */ + uint32 maxmem; /* - maximum memory */ + }; + +static struct FEATURE_TABLE cpu_features [] = { /* features indexed by CPU model */ + { UNIT_DMA | UNIT_MP, /* UNIT_2116 */ + UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_EAU, + 32 * 1024 + }, + + { UNIT_DMA, /* UNIT_2115 */ + UNIT_PFAIL | UNIT_DMA | UNIT_EAU, + 8 * 1024 + }, + + { UNIT_DMA, /* UNIT_2114 */ + UNIT_PFAIL | UNIT_DMA, + 16 * 1024 }, + + { 0, 0, 0 /* unused model */ + }, + + { UNIT_PFAIL | UNIT_MP | UNIT_DMA | UNIT_EAU, /* UNIT_2100 */ + UNIT_DMA | UNIT_FP | UNIT_IOP | UNIT_FFP, + 32 * 1024 + }, + + { 0, 0, 0 /* unused model */ + }, + { 0, 0, 0 /* unused model */ + }, + { 0, 0, 0 /* unused model */ + }, + + { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | UNIT_DMS, /* UNIT_1000_M */ + UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_DMS | + UNIT_IOP | UNIT_FFP | UNIT_DS, + 1024 * 1024 + }, + + { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | UNIT_DMS, /* UNIT_1000_E */ + UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_DMS | + UNIT_IOP | UNIT_FFP | UNIT_DBI | UNIT_DS | UNIT_EMA_VMA, + 1024 * 1024 + }, + + { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | /* UNIT_1000_F */ + UNIT_FFP | UNIT_DBI | UNIT_DMS, + UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_DMS | + UNIT_VIS | UNIT_DS | UNIT_SIGNAL | UNIT_EMA_VMA, + 1024 * 1024 + } + }; + + +/* CPU local SCP support routine declarations */ + +static IOHANDLER cpuio; +static IOHANDLER ovflio; +static IOHANDLER pwrfio; + +static t_stat cpu_examine (t_value *eval, t_addr address, UNIT *uptr, int32 switches); +static t_stat cpu_deposit (t_value value, t_addr address, UNIT *uptr, int32 switches); + +static t_stat cpu_reset (DEVICE *dptr); +static t_stat cpu_boot (int32 unitno, DEVICE *dptr); + +static t_stat set_stops (UNIT *uptr, int32 option, CONST char *cptr, void *desc); +static t_stat set_size (UNIT *uptr, int32 new_size, CONST char *cptr, void *desc); +static t_stat set_model (UNIT *uptr, int32 new_model, CONST char *cptr, void *desc); +static t_stat set_option (UNIT *uptr, int32 option, CONST char *cptr, void *desc); +static t_stat clear_option (UNIT *uptr, int32 option, CONST char *cptr, void *desc); +static t_stat set_loader (UNIT *uptr, int32 enable, CONST char *cptr, void *desc); +static t_stat set_exec (UNIT *uptr, int32 option, CONST char *cptr, void *desc); + +static t_stat show_stops (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +static t_stat show_model (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +static t_stat show_exec (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +static t_stat show_speed (FILE *st, UNIT *uptr, int32 val, CONST void *desc); + + +/* CPU local utility routine declarations */ + +static t_stat ea (HP_WORD IR, HP_WORD *address, uint32 irq); +static HP_WORD srg_uop (HP_WORD value, HP_WORD operation); +static t_stat machine_instruction (HP_WORD IR, t_bool iotrap, uint32 irq_pending, uint32 *idle_save); +static t_bool check_deferral (uint32 irq_sc); +static uint32 map_address (HP_WORD logical, int32 switches); +static t_bool mem_is_empty (uint32 starting_address); + + +/* Memory Expansion Unit local utility routine declarations */ + +static t_bool is_mapped (uint32 address); +static uint32 meu_map (HP_WORD address, uint32 map, HP_WORD prot); + + +/* CPU SCP data structures */ + + +/* Device information blocks */ + +static DIB cpu_dib = { /* CPU select code 0 */ + &cpuio, /* device interface */ + CPU, /* select code */ + 0 /* card index */ + }; + +static DIB ovfl_dib = { /* Overflow select code 1 */ + &ovflio, /* device interface */ + OVF, /* select code */ + 0 /* card index */ + }; + +static DIB pwrf_dib = { /* Power Fail select code 4 */ + &pwrfio, /* device interface */ + PWR, /* select code */ + 0 /* card index */ + }; + + +/* Unit list. + + The CPU unit holds the main memory capacity. + + + Implementation notes: + + 1. The unit structure must be global for other modules to access the unit + flags, which describe the installed options, and to obtain the memory + size via the MEMSIZE macro, which references the "capac" field. +*/ + +UNIT cpu_unit = { UDATA (NULL, UNIT_FIX | UNIT_BINK, 0) }; + + +/* Register list. + + The CPU register list exposes the machine registers for user inspection and + modification. + + + Implementation notes: + + 1. All registers that reference variables of type HP_WORD must have the + REG_FIT flag for proper access if HP_WORD is a 16-bit type. + + 2. The REG_X flag indicates that the register may be displayed in symbolic + form. +*/ + +static REG cpu_reg [] = { +/* Macro Name Location Radix Width Offset Depth Flags */ +/* ------ --------- ------------------ ----- ----- -------- ----------------- ----------------- */ + { ORDATA (P, PR, 15) }, + { ORDATA (A, AR, 16), REG_X }, + { ORDATA (B, BR, 16), REG_X }, + { ORDATA (M, MR, 15) }, + { ORDATA (T, TR, 16), REG_RO | REG_X }, + { ORDATA (X, XR, 16), REG_X }, + { ORDATA (Y, YR, 16), REG_X }, + { ORDATA (S, SR, 16), REG_X }, + { FLDATA (E, E, 0) }, + { FLDATA (O, O, 0) }, + { ORDATA (CIR, CIR, 6) }, + + { FLDATA (ION, ion, 0) }, + { FLDATA (ION_DEFER, ion_defer, 0) }, + { FLDATA (DMSENB, dms_enb, 0) }, + { FLDATA (DMSCUR, dms_ump, VA_N_PAG) }, + + { ORDATA (DMSSR, dms_sr, 16) }, + { ORDATA (DMSVR, dms_vr, 16) }, + { BRDATA (DMSMAP, dms_map, 8, 16, MAP_NUM * MAP_LNT) }, + + { ORDATA (IOPSP, iop_sp, 16) }, + { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_CIRC | REG_RO }, + + { ORDATA (IR, IR, 16), REG_HRO }, + { ORDATA (PCQP, pcq_p, 6), REG_HRO }, + { ORDATA (JSBPLB, jsb_plb, 32), REG_HRO }, + { ORDATA (SAVEDMR, saved_MR, 32), REG_HRO }, + { ORDATA (FWANXM, fwanxm, 32), REG_HRO }, + { ORDATA (CONFIG, cpu_configuration, 32), REG_HRO }, + + { ORDATA (WRU, sim_int_char, 8), REG_HRO }, + { ORDATA (BRK, sim_brk_char, 8), REG_HRO }, + { ORDATA (DEL, sim_del_char, 8), REG_HRO }, + + { BRDATA (PRL, dev_prl, 8, 32, 2), REG_HRO }, + { BRDATA (IRQ, dev_irq, 8, 32, 2), REG_HRO }, + { BRDATA (SRQ, dev_srq, 8, 32, 2), REG_HRO }, + { NULL } + }; + + +/* Modifier list. + + + Implementation notes: + + 1. The 21MX monikers are deprecated in favor of the 1000 designations. See + the "HP 1000 Series Naming History" on the back inside cover of the + Technical Reference Handbook. + + 2. Each CPU option requires three modifiers. The two regular modifiers + control the setting and printing of the option, while the extended + modifier controls clearing the option. The latter is necessary because + the option must be checked before confirming the change, and so the + option value must be passed to the validation routine. +*/ + +static MTAB cpu_mod [] = { +/* Mask Value Match Value Print String Match String Validation Display Descriptor */ +/* --------------- ----------- ------------ ------------ ------------- ----------- ----------------- */ + { UNIT_MODEL_MASK, UNIT_2116, "", "2116", &set_model, &show_model, (void *) "2116" }, + { UNIT_MODEL_MASK, UNIT_2115, "", "2115", &set_model, &show_model, (void *) "2115" }, + { UNIT_MODEL_MASK, UNIT_2114, "", "2114", &set_model, &show_model, (void *) "2114" }, + { UNIT_MODEL_MASK, UNIT_2100, "", "2100", &set_model, &show_model, (void *) "2100" }, + { UNIT_MODEL_MASK, UNIT_1000_E, "", "1000-E", &set_model, &show_model, (void *) "1000-E" }, + { UNIT_MODEL_MASK, UNIT_1000_E, NULL, "21MX-E", &set_model, &show_model, (void *) "1000-E" }, + { UNIT_MODEL_MASK, UNIT_1000_M, "", "1000-M", &set_model, &show_model, (void *) "1000-M" }, + { UNIT_MODEL_MASK, UNIT_1000_M, NULL, "21MX-M", &set_model, &show_model, (void *) "1000-M" }, + +#if defined (HAVE_INT64) + { UNIT_MODEL_MASK, UNIT_1000_F, "", "1000-F", &set_model, &show_model, (void *) "1000-F" }, +#endif + + { UNIT_EAU, UNIT_EAU, "EAU", "EAU", &set_option, NULL, NULL }, + { UNIT_EAU, 0, "no EAU", NULL, NULL, NULL, NULL }, + { MTAB_XDV, UNIT_EAU, NULL, "NOEAU", &clear_option, NULL, NULL }, + + { UNIT_FP, UNIT_FP, "FP", "FP", &set_option, NULL, NULL }, + { UNIT_FP, 0, "no FP", NULL, NULL, NULL, NULL }, + { MTAB_XDV, UNIT_FP, NULL, "NOFP", &clear_option, NULL, NULL }, + + { UNIT_IOP, UNIT_IOP, "IOP", "IOP", &set_option, NULL, NULL }, + { UNIT_IOP, 0, "no IOP", NULL, NULL, NULL, NULL }, + { MTAB_XDV, UNIT_IOP, NULL, "NOIOP", &clear_option, NULL, NULL }, + + { UNIT_DMS, UNIT_DMS, "DMS", "DMS", &set_option, NULL, NULL }, + { UNIT_DMS, 0, "no DMS", NULL, NULL, NULL, NULL }, + { MTAB_XDV, UNIT_DMS, NULL, "NODMS", &clear_option, NULL, NULL }, + + { UNIT_FFP, UNIT_FFP, "FFP", "FFP", &set_option, NULL, NULL }, + { UNIT_FFP, 0, "no FFP", NULL, NULL, NULL, NULL }, + { MTAB_XDV, UNIT_FFP, NULL, "NOFFP", &clear_option, NULL, NULL }, + + { UNIT_DBI, UNIT_DBI, "DBI", "DBI", &set_option, NULL, NULL }, + { UNIT_DBI, 0, "no DBI", NULL, NULL, NULL, NULL }, + { MTAB_XDV, UNIT_DBI, NULL, "NODBI", &clear_option, NULL, NULL }, + + { UNIT_EMA_VMA, UNIT_EMA, "EMA", "EMA", &set_option, NULL, NULL }, + { MTAB_XDV, UNIT_EMA, NULL, "NOEMA", &clear_option, NULL, NULL }, + + { UNIT_EMA_VMA, UNIT_VMAOS, "VMA", "VMA", &set_option, NULL, NULL }, + { MTAB_XDV, UNIT_VMAOS, NULL, "NOVMA", &clear_option, NULL, NULL }, + + { UNIT_EMA_VMA, 0, "no EMA/VMA", NULL, &set_option, NULL, NULL }, + +#if defined (HAVE_INT64) + { UNIT_VIS, UNIT_VIS, "VIS", "VIS", &set_option, NULL, NULL }, + { UNIT_VIS, 0, "no VIS", NULL, NULL, NULL, NULL }, + { MTAB_XDV, UNIT_VIS, NULL, "NOVIS", &clear_option, NULL, NULL }, + + { UNIT_SIGNAL, UNIT_SIGNAL, "SIGNAL", "SIGNAL", &set_option, NULL, NULL }, + { UNIT_SIGNAL, 0, "no SIGNAL", NULL, NULL, NULL, NULL }, + { MTAB_XDV, UNIT_SIGNAL, NULL, "NOSIGNAL", &clear_option, NULL, NULL }, +#endif + +/* Future microcode support. + { UNIT_DS, UNIT_DS, "DS", "DS", &set_option, NULL, NULL }, + { UNIT_DS, 0, "no DS", NULL, NULL, NULL, NULL }, + { MTAB_XDV, UNIT_DS, NULL, "NODS", &clear_option, NULL, NULL }, +*/ + +/* Entry Flags Value Print String Match String Validation Display Descriptor */ +/* ------------------- ----------- ------------ --------------- ------------- -------------- ---------- */ + { MTAB_XDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle, NULL }, + { MTAB_XDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL, NULL }, + + { MTAB_XDV, 1, NULL, "LOADERENABLE", &set_loader, NULL, NULL }, + { MTAB_XDV, 0, NULL, "LOADERDISABLE", &set_loader, NULL, NULL }, + + { MTAB_XDV, 4 * 1024, NULL, "4K", &set_size, NULL, NULL }, + { MTAB_XDV, 8 * 1024, NULL, "8K", &set_size, NULL, NULL }, + { MTAB_XDV, 12 * 1024, NULL, "12K", &set_size, NULL, NULL }, + { MTAB_XDV, 16 * 1024, NULL, "16K", &set_size, NULL, NULL }, + { MTAB_XDV, 24 * 1024, NULL, "24K", &set_size, NULL, NULL }, + { MTAB_XDV, 32 * 1024, NULL, "32K", &set_size, NULL, NULL }, + { MTAB_XDV, 64 * 1024, NULL, "64K", &set_size, NULL, NULL }, + { MTAB_XDV, 128 * 1024, NULL, "128K", &set_size, NULL, NULL }, + { MTAB_XDV, 256 * 1024, NULL, "256K", &set_size, NULL, NULL }, + { MTAB_XDV, 512 * 1024, NULL, "512K", &set_size, NULL, NULL }, + { MTAB_XDV, 1024 * 1024, NULL, "1024K", &set_size, NULL, NULL }, + + { MTAB_XDV | MTAB_NMO, 1, "STOPS", "STOP", &set_stops, &show_stops, NULL }, + { MTAB_XDV, 0, NULL, "NOSTOP", &set_stops, NULL, NULL }, + { MTAB_XDV | MTAB_NMO, 2, "INDIR", "INDIR", &set_stops, &show_stops, NULL }, + + { MTAB_XDV | MTAB_NMO, 1, "EXEC", "EXEC", &set_exec, &show_exec, NULL }, + { MTAB_XDV, 0, NULL, "NOEXEC", &set_exec, NULL, NULL }, + + { MTAB_XDV | MTAB_NMO, 0, "SPEED", NULL, NULL, &show_speed, NULL }, + + { 0 } + }; + + +/* Debugging trace list */ + +static DEBTAB cpu_deb [] = { + { "INSTR", TRACE_INSTR }, /* trace instruction executions */ + { "DATA", TRACE_DATA }, /* trace memory data accesses */ + { "FETCH", TRACE_FETCH }, /* trace memory instruction fetches */ + { "REG", TRACE_REG }, /* trace register values */ + { "OPND", TRACE_OPND }, /* trace instruction operands */ + { "EXEC", TRACE_EXEC }, /* trace matching instruction execution states */ + { "NOOS", DEBUG_NOOS }, /* RTE-6/VM will not use OS firmware */ + { NULL, 0 } + }; + + +/* Simulation stop list. + + The simulator can be configured to detect certain machine instruction + conditions and stop execution when one of them occurs. Stops may be enabled + or disabled individually with these commands: + + SET CPU STOP=