diff --git a/0readme26.txt b/0readme26.txt deleted file mode 100644 index cd0579e8..00000000 --- a/0readme26.txt +++ /dev/null @@ -1,35 +0,0 @@ -Release notes for simh V2.6 - -1. Register arrays - -The simulator has supported register arrays for some time, but their contents -were always hidden, and register arrays had names like *BUF. Register arrays -can now be examined and modified, and the names have changed to normal form. -As a result, SAVE FILES FROM PRIOR RELEASES WILL NOT RESTORE PROPERLY, because -the previous array names won't be found. These errors will occur AFTER main -memory has been restored, so memory contents can be salvaged; but most device -state will be lost. - -2. USE_INT64 instead of _INT64 - -As a #define, _INT64 conflicts with some compiler implementations. Therefore, -the enable switch for 64b has been changed to USE_INT64, e.g., - - % cc -o pdp10 -DUSE_INT64 pdp10_*.c,scp*.c -lm - -3. int64 definition defaults to long long - -If 64b is specified, the default compiler declaration for int64 is 'long long', -with exceptions for Win32 (_int64) and Digital UNIX (long). - -4. Real-time clock calibration - -Many of the simulators now calibrate their real-time clocks to match wall -time. This allows simulated operating systems to track wall time. - -5. Calling sequence change - -The calling sequence for sim_load has been changed to include the file name. -This allows simulator loaders to use different formats depending on the -extension of the load file. - diff --git a/h316_cpu.c b/h316_cpu.c new file mode 100644 index 00000000..2001c2a6 --- /dev/null +++ b/h316_cpu.c @@ -0,0 +1,1046 @@ +/* h316_cpu.c: Honeywell 316/516 CPU simulator + + Copyright (c) 1993-2001, Robert M. Supnik + + 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. + + Except as contained in this notice, the name of Robert M Supnik 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. + + The register state for the Honeywell 316/516 CPU is: + + AR<1:16> A register + BR<1:16> B register + XR<1:16> X register + PC<1:16> P register (program counter) + Y<1:16> memory address register + MB<1:16> memory data register + C overflow flag + EXT extend mode flag + DP double precision mode flag + SC<1:5> shift count + SR[1:4]<0> sense switches 1-4 + + The Honeywell 316/516 has six instruction formats: memory reference, + I/O, control, shift, skip, and operate. + + The memory reference format is: + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |in|xr| op |sc| offset | memory reference + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + <13:10> mnemonic action + + 0000 (other) see control, shift, skip, operate instructions + 0001 JMP P = MA + 0010 LDA A = M[MA] + 0011 ANA A = A & M[MA] + 0100 STA M[MA] = A + 0101 ERA A = A ^ M[MA] + 0110 ADD A = A + M[MA] + 0111 SUB A = A - M[MA] + 1000 JST M[MA] = P, P = MA + 1 + 1001 CAS skip if A == M[MA], double skip if A < M[MA] + 1010 IRS M[MA] = M[MA] + 1, skip if M[MA] == 0 + 1011 IMA A <=> M[MA] + 1100 (I/O) see I/O instructions + 1101 LDX/STX X = M[MA] (xr = 1), M[MA] = x (xr = 0) + 1110 MPY multiply + 1111 DIV divide + + In non-extend mode, memory reference instructions can access an address + space of 16K words. Multiple levels of indirection are supported, and + each indirect word supplies its own indirect and index bits. + + <1,2,7> mode action + + 0,0,0 sector zero direct MA = IR<8:0> + 0,0,1 current direct MA = P<13:9>'IR<8:0> + 0,1,0 sector zero indexed MA = IR<8:0> + X + 0,1,1 current direct MA = P<13:9>'IR<8:0> + X + 1,0,0 sector zero indirect MA = M[IR<8:0>] + 1,0,1 current indirect MA = M[P<13:9>'IR<8:0>] + 1,1,0 sector zero indirect indexed MA = M[IR<8:0> + X] + 1,1,1 current indirect indexed MA = M[MA = P<13:9>'IR<8:0> + X] + + In extend mode, memory reference instructions can access an address + space of 32K words. Multiple levels of indirection are supported, but + only post-indexing, based on the original instruction word index flag, + is allowed. +*/ + +/* The control format is: + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 0 0 0 0 0 0| opcode | control + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + The shift format is: + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 0 1 0 0 0 0|dr|sz|type | shift count | shift + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | \-+-/ + | | | + | | +--------------------- type + | +------------------------- long/A only + +---------------------------- right/left + + The skip format is: + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 1 0 0 0 0 0|rv|po|pe|ev|ze|s1|s2|s3|s4|cz| skip + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | | | | | | | | | + | | | | | | | | | +- skip if C = 0 + | | | | | | | | +---- skip if ssw 4 = 0 + | | | | | | | +------- skip if ssw 3 = 0 + | | | | | | +---------- skip if ssw 2 = 0 + | | | | | +------------- skip if ssw 1 = 0 + | | | | +---------------- skip if A == 0 + | | | +------------------- skip if A<0> == 0 + | | +---------------------- skip if mem par err + | +------------------------- skip if A<15> = 0 + +---------------------------- reverse skip sense + + The operate format is: + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 1 1 0 0 0 0| opcode | operate + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + The I/O format is: + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | op | 1 1 0 0| function | device | I/O transfer + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 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. +*/ + +/* This routine is the instruction decode routine for the Honeywell + 316/516. It is called from the simulator control program to execute + instructions in simulated memory, starting at the simulated PC. + It runs until 'reason' is set non-zero. + + General notes: + + 1. Reasons to stop. The simulator can be stopped by: + + 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 + + 2. Interrupts. Interrupts are maintained by two parallel variables: + + dev_ready device ready flags + dev_enable device interrupt enable flags + + In addition, dev_ready contains the interrupt enable and interrupt no + defer flags. If interrupt enable and interrupt no defer are set, and + at least one interrupt request is pending, then an interrupt occurs. + The order of flags in these variables corresponds to the order + in the SMK instruction. + + 3. Non-existent memory. On the H316/516, 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 actual memory size. + + 4. Adding I/O devices. These modules must be modified: + + h316_defs.h add interrupt request definition + h316_cpu.c add device information table entry + h316_sys.c add sim_devices table entry +*/ + +#include "h316_defs.h" + +#define ILL_ADR_FLAG 0100000 +#define save_ibkpt (cpu_unit.u3) +#define UNIT_V_MSIZE (UNIT_V_UF) /* dummy mask */ +#define UNIT_MSIZE (1 << UNIT_V_MSIZE) +#define m7 0001000 /* for generics */ +#define m8 0000400 +#define m9 0000200 +#define m10 0000100 +#define m11 0000040 +#define m12 0000020 +#define m13 0000010 +#define m14 0000004 +#define m15 0000002 +#define m16 0000001 + +uint16 M[MAXMEMSIZE] = { 0 }; /* memory */ +int32 saved_AR = 0; /* A register */ +int32 saved_BR = 0; /* B register */ +int32 saved_XR = 0; /* X register */ +int32 PC = 0; /* P register */ +int32 C = 0; /* C register */ +int32 ext = 0; /* extend mode */ +int32 pme = 0; /* prev mode extend */ +int32 extoff_pending = 0; /* extend off pending */ +int32 dp = 0; /* double mode */ +int32 sc = 0; /* shift count */ +int32 ss[4]; /* sense switches */ +int32 dev_ready = 0; /* dev ready */ +int32 dev_enable = 0; /* dev enable */ +int32 ind_max = 8; /* iadr nest limit */ +int32 stop_inst = 1; /* stop on ill inst */ +int32 stop_dev = 2; /* stop on ill dev */ +int32 ibkpt_addr = ILL_ADR_FLAG | X_AMASK; /* breakpoint addr */ +int32 old_PC = 0; /* previous PC */ +int32 dlog = 0; /* debug log */ +int32 turnoff = 0; + +extern int32 sim_int_char; +extern FILE *sim_log; +extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, + UNIT *uptr, int32 sw); +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_svc (UNIT *uptr); +t_stat cpu_set_noext (UNIT *uptr, int32 value); +t_stat cpu_set_size (UNIT *uptr, int32 value); + +/* CPU data structures + + cpu_dev CPU device descriptor + cpu_unit CPU unit descriptor + cpu_reg CPU register list + cpu_mod CPU modifiers list +*/ + +UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK + UNIT_EXT, + MAXMEMSIZE) }; + +REG cpu_reg[] = { + { ORDATA (P, PC, 15) }, + { ORDATA (A, saved_AR, 16) }, + { ORDATA (B, saved_BR, 16) }, + { ORDATA (X, XR, 16) }, + { ORDATA (SC, sc, 16) }, + { FLDATA (C, C, 0) }, + { FLDATA (EXT, ext, 0) }, + { FLDATA (PME, pme, 0) }, + { FLDATA (EXT_OFF, extoff_pending, 0) }, + { FLDATA (DP, dp, 0) }, + { FLDATA (SS1, ss[0], 0) }, + { FLDATA (SS2, ss[1], 0) }, + { FLDATA (SS3, ss[2], 0) }, + { FLDATA (SS4, ss[3], 0) }, + { FLDATA (ION, dev_ready, INT_V_ON) }, + { FLDATA (INODEF, dev_ready, INT_V_NODEF) }, + { ORDATA (DEVRDY, dev_ready, 16), REG_RO }, + { ORDATA (DEVENB, dev_enable, 16), REG_RO }, + { FLDATA (MPERDY, dev_ready, INT_V_MPE) }, + { FLDATA (MPEENB, dev_enable, INT_V_MPE) }, + { FLDATA (STOP_INST, stop_inst, 0) }, + { FLDATA (STOP_DEV, stop_dev, 1) }, + { DRDATA (INDMAX, ind_max, 8), REG_NZ + PV_LEFT }, + { ORDATA (OLDP, old_PC, 15), REG_RO }, + { ORDATA (BREAK, ibkpt_addr, 16) }, + { ORDATA (WRU, sim_int_char, 8) }, + { FLDATA (DLOG, dlog, 0) }, + { FLDATA (HEXT, cpu_unit.flags, UNIT_V_EXT), REG_HRO }, + { FLDATA (HSA, cpu_unit.flags, UNIT_V_HSA), REG_HRO }, + { NULL } }; + +MTAB cpu_mod[] = { + { UNIT_EXT, 0, "no extend", "NOEXTEND", &cpu_set_noext }, + { UNIT_EXT, UNIT_EXT, "extend", "EXTEND", NULL }, + { UNIT_HSA, 0, "no HSA", "HSA", NULL }, + { UNIT_HSA, UNIT_HSA, "HSA", "HSA", NULL }, + { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, + { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, + { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, + { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, + { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, + { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, + { 0 } }; + +DEVICE cpu_dev = { + "CPU", &cpu_unit, cpu_reg, cpu_mod, + 1, 8, 15, 1, 8, 16, + &cpu_ex, &cpu_dep, &cpu_reset, + NULL, NULL, NULL }; + +/* I/O dispatch */ + +int32 undio (int32 op, int32 func, int32 AR); +extern int32 ptrio (int32 op, int32 func, int32 AR); +extern int32 ptpio (int32 op, int32 func, int32 AR); +extern int32 lptio (int32 op, int32 func, int32 AR); +extern int32 ttyio (int32 op, int32 func, int32 AR); +extern int32 clkio (int32 op, int32 func, int32 AR); + +int32 (*iotab[64])() = { + &undio, &ptrio, &ptpio, &lptio, &ttyio, &undio, &undio, &undio, + &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, + &clkio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, + &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, + &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, + &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, + &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, + &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio }; + + +t_stat sim_instr (void) +{ +extern int32 sim_interval; +extern UNIT clk_unit; +int32 AR, BR, MB, Y, t1, t2, t3, skip; +unsigned int32 ut; +t_stat reason; +t_stat Ea (int32 inst, int32 *addr); +void Write (int32 val, int32 addr); +int32 Add16 (int32 val1, int32 val2); +int32 Add31 (int32 val1, int32 val2); +int32 Operate (int32 MB, int32 AR); + +#define Read(x) M[(x)] +#define GETDBL_S(h,l) (((h) << 15) | ((l) & MMASK)) +#define GETDBL_U(h,l) (((h) << 16) | (l)) +#define PUTDBL_S(x) AR = ((x) >> 15) & DMASK; \ + BR = (BR & SIGN) | ((x) & MMASK) +#define PUTDBL_U(x) AR = ((x) >> 16) & DMASK; \ + BR = (x) & DMASK +#define SEXT(x) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)) +#define NEWA(c,n) (ext? (((c) & ~X_AMASK) | ((n) & X_AMASK)): \ + (((c) & ~NX_AMASK) | ((n) & NX_AMASK))) + +/* Restore register state */ + +AR = saved_AR & DMASK; /* restore reg */ +BR = saved_BR & DMASK; +XR = saved_XR & DMASK; +PC = PC & ((cpu_unit.flags & UNIT_EXT)? X_AMASK: NX_AMASK); /* mask PC */ +reason = 0; +turnoff = 0; +sim_rtc_init (clk_unit.wait); /* init calibration */ + +/* Main instruction fetch/decode loop */ + +while (reason == 0) { /* loop until halted */ +if (sim_interval <= 0) { /* check clock queue */ + if (reason = sim_process_event ()) break; } + +if ((dev_ready & (INT_PENDING | dev_enable)) > INT_PENDING) { /* int req? */ + pme = ext; /* save extend */ + if (cpu_unit.flags & UNIT_EXT) ext = 1; /* ext opt? extend on */ + dev_ready = dev_ready & ~INT_ON; /* intr off */ + turnoff = 0; + if (dlog && sim_log) fprintf (sim_log, "Interrupt\n"); + MB = 0120000 | M_INT; } /* inst = JST* 63 */ + +else { if (PC == ibkpt_addr) { /* breakpoint? */ + save_ibkpt = ibkpt_addr; /* save address */ + ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */ + sim_activate (&cpu_unit, 1); /* sched re-enable */ + reason = STOP_IBKPT; /* stop simulation */ + break; } + Y = PC; /* set mem addr */ + MB = Read (Y); /* fetch instr */ + PC = NEWA (Y, Y + 1); /* incr PC */ + dev_ready = dev_ready | INT_NODEF; } +sim_interval = sim_interval - 1; +if (dlog && sim_log && !turnoff) { /* cycle log? */ + int32 op = I_GETOP (MB) & 017; /* core opcode */ + t_value val = MB; + fprintf (sim_log, "A= %06o C= %1o P= %05o (", AR, C, PC); + fprint_sym (sim_log, Y, &val, &cpu_unit, SWMASK ('M')); + fprintf (sim_log, ")"); + if ((op == 0) || (op == 014)) fprintf (sim_log, "\n"); } + +/* Memory reference instructions */ + +switch (I_GETOP (MB)) { /* case on <1:6> */ +case 001: case 021: case 041: case 061: /* JMP */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + old_PC = PC; /* save PC */ + PC = NEWA (PC, Y); /* set new PC */ + if (dlog && sim_log) { /* logging? */ + int32 op = I_GETOP (M[PC]) & 017; /* get target */ + if ((op == 014) && (PC == (old_PC - 2))) { /* jmp .-1 to IO? */ + turnoff = 1; /* yes, stop */ + fprintf (sim_log, "Idle loop detected\n"); } + else turnoff = 0; } /* no, log */ + if (extoff_pending) ext = extoff_pending = 0; /* cond ext off */ + break; +case 002: case 022: case 042: case 062: /* LDA */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (dp) { /* double prec? */ + AR = Read (Y & ~1); /* get doubleword */ + BR = Read (Y | 1); + sc = 0; } + else AR = Read (Y); /* no, get word */ + break; +case 003: case 023: case 043: case 063: /* ANA */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + AR = AR & Read (Y); + break; +case 004: case 024: case 044: case 064: /* STA */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (dp) { /* double prec? */ + if ((Y & 1) == 0) Write (AR, Y); /* if even, store A */ + Write (BR, Y | 1); /* store B */ + sc = 0; } + else Write (AR, Y); /* no, store word */ + break; +case 005: case 025: case 045: case 065: /* ERA */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + AR = AR ^ Read (Y); + break; +case 006: case 026: case 046: case 066: /* ADD */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (dp) { /* double prec? */ + t1 = GETDBL_S (AR, BR); /* get A'B */ + t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1)); + t1 = Add31 (t1, t2); /* 31b add */ + PUTDBL_S (t1); + sc = 0; } + else AR = Add16 (AR, Read (Y)); /* no, 16b add */ + break; +case 007: case 027: case 047: case 067: /* SUB */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + if (dp) { /* double prec? */ + t1 = GETDBL_S (AR, BR); /* get A'B */ + t2 = GETDBL_S (Read (Y & ~1), Read (Y | 1)); + t1 = Add31 (t1, -t2); /* 31b sub */ + PUTDBL_S (t1); + sc = 0; } + else AR = Add16 (AR, (-Read (Y)) & DMASK); /* no, 16b sub */ + break; + +/* Memory reference instructions */ + +case 010: case 030: case 050: case 070: /* JST */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + MB = NEWA (Read (Y), PC); /* merge old PC */ + Write (MB, Y); + old_PC = PC; + PC = NEWA (PC, Y + 1); /* set new PC */ + break; +case 011: case 031: case 051: case 071: /* CAS */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + MB = Read (Y); + if (AR == MB) PC = NEWA (PC, PC + 1); + else if (SEXT (AR) < SEXT (MB)) PC = NEWA (PC, PC + 2); + break; +case 012: case 032: case 052: case 072: /* IRS */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + MB = (Read (Y) + 1) & DMASK; /* incr, rewrite */ + Write (MB, Y); + if (MB == 0) PC = NEWA (PC, PC + 1); /* skip if zero */ + break; +case 013: case 033: case 053: case 073: /* IMA */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + MB = Read (Y); + Write (AR, Y); /* A to mem */ + AR = MB; /* mem to A */ + break; +case 015: case 055: /* STX */ + if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */ + Write (XR, Y); /* store XR */ + break; +case 035: case 075: /* LDX */ + if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */ + XR = Read (Y); /* load XR */ + break; +case 016: case 036: case 056: case 076: /* MPY */ + if (cpu_unit.flags & UNIT_HSA) { /* installed? */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + t1 = SEXT (AR) * SEXT (Read (Y)); + PUTDBL_S (t1); + sc = 0; } + else reason = stop_inst; + break; +case 017: case 037: case 057: case 077: /* DIV */ + if (cpu_unit.flags & UNIT_HSA) { /* installed? */ + if (reason = Ea (MB, &Y)) break; /* eff addr */ + t2 = SEXT (Read (Y)); /* divr */ + if (t2) { /* divr != 0? */ + t1 = GETDBL_S (AR, BR); /* get A'B */ + BR = (t1 % t2) & DMASK; /* remainder */ + t1 = t1 / t2; /* quotient */ + AR = t1 & DMASK; + if ((t1 > MMASK) || (t1 < (-SIGN))) C = 1; + else C = 0; + sc = 0; } + else C = 1; } + else reason = stop_inst; + break; + +/* I/O instructions */ + +case 014: /* OCP */ + t2 = iotab[MB & DEVMASK] (ioOCP, I_GETFNC (MB), AR); + reason = t2 >> IOT_V_REASON; + turnoff = 0; + break; +case 034: /* SKS */ + t2 = iotab[MB & DEVMASK] (ioSKS, I_GETFNC (MB), AR); + reason = t2 >> IOT_V_REASON; + if (t2 & IOT_SKIP) { /* skip? */ + PC = NEWA (PC, PC + 1); + turnoff = 0; } + break; +case 054: /* INA */ + if (MB & INCLRA) AR = 0; + t2 = iotab[MB & DEVMASK] (ioINA, I_GETFNC (MB), AR); + reason = t2 >> IOT_V_REASON; + if (t2 & IOT_SKIP) { /* skip? */ + PC = NEWA (PC, PC + 1); + turnoff = 0; } + AR = t2 & DMASK; /* data */ + break; +case 074: /* OTA */ + t2 = iotab[MB & DEVMASK] (ioOTA, I_GETFNC (MB), AR); + reason = t2 >> IOT_V_REASON; + if (t2 & IOT_SKIP) { /* skip? */ + PC = NEWA (PC, PC + 1); + turnoff = 0; } + break; + +/* Control */ + +case 000: + if ((MB & 1) == 0) { /* HLT */ + reason = STOP_HALT; + break; } + if (MB & m14) { /* SGL, DBL */ + if (cpu_unit.flags & UNIT_HSA) dp = (MB & m15)? 1: 0; + else reason = stop_inst; } + if (MB & m13) { /* DXA, EXA */ + if (!(cpu_unit.flags & UNIT_EXT)) reason = stop_inst; + else if (MB & m15) { /* EXA */ + ext = 1; + extoff_pending = 0; } /* DXA */ + else extoff_pending = 1; } + if (MB & m12) /* RMP */ + dev_ready = dev_ready & ~INT_MPE; + if (MB & m11) { /* SCA, INK */ + if (MB & m15) /* INK */ + AR = (C << 15) | (dp << 14) | (pme << 13) | (sc & 037); + else if (cpu_unit.flags & UNIT_HSA) /* SCA */ + AR = sc & 037; + else reason = stop_inst; } + else if (MB & m10) { /* NRM */ + if (cpu_unit.flags & UNIT_HSA) { + for (sc = 0; + (sc <= 32) && ((AR & SIGN) != ((AR << 1) & SIGN)); + sc++) { + AR = (AR & SIGN) | ((AR << 1) & MMASK) | + ((BR >> 14) & 1); + BR = (BR & SIGN) | ((BR << 1) & MMASK); } + sc = sc & 037; } + else reason = stop_inst; } + else if (MB & m9) { /* IAB */ + sc = BR; + BR = AR; + AR = sc; } + if (MB & m8) /* ENB */ + dev_ready = (dev_ready | INT_ON) & ~INT_NODEF; + if (MB & m7) /* INH */ + dev_ready = dev_ready & ~INT_ON; + break; + +/* Shift + + Shifts are microcoded as follows: + + op<7> = right/left + op<8> = long/short + op<9> = shift/rotate (rotate bits "or" into new position) + op<10> = logical/arithmetic + + If !op<7> && op<10> (right arithmetic), A<1> propagates rightward + If op<7> && op<10> (left arithmetic), C is set if A<1> changes state + If !op<8> && op<10> (long arithmetic), B<1> is skipped + + This microcoding "explains" how the 4 undefined opcodes actually work + 003 = long arith rotate right, skip B<1>, propagate A<1>, + bits rotated out "or" into A<1> + 007 = short arith rotate right, propagate A<1>, + bits rotated out "or" into A<1> + 013 = long arith rotate left, skip B<1>, C = overflow + 017 = short arith rotate left, C = overflow +*/ + +case 020: + C = 0; /* clear C */ + sc = 0; /* clear sc */ + if ((t1 = (-MB) & SHFMASK) == 0) break; /* shift count */ + switch (I_GETFNC (MB)) { /* case shift fnc */ + case 000: /* LRL */ + if (t1 > 32) ut = 0; /* >32? all 0 */ + else { ut = GETDBL_U (AR, BR); /* get A'B */ + C = (ut >> (t1 - 1)) & 1; /* C = last out */ + ut = ut >> t1; } /* log right */ + PUTDBL_U (ut); /* store A,B */ + break; + case 001: /* LRS */ + if (t1 > 31) t1 = 31; /* limit to 31 */ + t2 = GETDBL_S (SEXT (AR), BR); /* get A'B signed */ + C = (t2 >> (t1 - 1)) & 1; /* C = last out */ + t2 = t2 >> t1; /* arith right */ + PUTDBL_S (t2); /* store A,B */ + break; + case 002: /* LRR */ + t2 = t1 % 32; /* mod 32 */ + ut = GETDBL_U (AR, BR); /* get A'B */ + ut = (ut >> t2) | (ut << (32 - t2)); /* rot right */ + C = (ut >> 31) & 1; /* C = A<1> */ + PUTDBL_U (ut); /* store A,B */ + break; + case 003: /* "long right arot" */ + if (reason = stop_inst) break; /* stop on undef? */ + for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ + C = BR & 1; /* C = last out */ + BR = (BR & SIGN) | ((AR & 1) << 14) | + ((BR & MMASK) >> 1); + AR = ((AR & SIGN) | (C << 15)) | (AR >> 1); } + break; + case 004: /* LGR */ + if (t1 > 16) AR = 0; /* > 16? all 0 */ + else { C = (AR >> (t1 - 1)) & 1; /* C = last out */ + AR = (AR >> t1) & DMASK; } /* log right */ + break; + case 005: /* ARS */ + if (t1 > 16) t1 = 16; /* limit to 16 */ + C = ((SEXT (AR)) >> (t1 - 1)) & 1; /* C = last out */ + AR = ((SEXT (AR)) >> t1) & DMASK; /* arith right */ + break; + case 006: /* ARR */ + t2 = t1 % 16; /* mod 16 */ + AR = ((AR >> t2) | (AR << (16 - t2))) & DMASK; + C = (AR >> 15) & 1; /* C = A<1> */ + break; + case 007: /* "short right arot" */ + if (reason = stop_inst) break; /* stop on undef? */ + for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ + C = AR & 1; /* C = last out */ + AR = ((AR & SIGN) | (C << 15)) | (AR >> 1); } + break; + +/* Shift, continued */ + + case 010: /* LLL */ + if (t1 > 32) ut = 0; /* > 32? all 0 */ + else { ut = GETDBL_U (AR, BR); /* get A'B */ + C = (ut >> (32 - t1)) & 1; /* C = last out */ + ut = ut << t1; } /* log left */ + PUTDBL_U (ut); /* store A,B */ + break; + case 011: /* LLS */ + if (t1 > 31) t1 = 31; /* limit to 31 */ + t2 = GETDBL_S (SEXT (AR), BR); /* get A'B */ + t3 = t2 << t1; /* "arith" left */ + PUTDBL_S (t3); /* store A'B */ + if ((t2 >> (31 - t1)) != /* shf out = sgn? */ + ((AR & SIGN)? -1: 0)) C = 1; + break; + case 012: /* LLR */ + t2 = t1 % 32; /* mod 32 */ + ut = GETDBL_U (AR, BR); /* get A'B */ + ut = (ut << t2) | (ut >> (32 - t2)); /* rot left */ + C = ut & 1; /* C = B<16> */ + PUTDBL_U (ut); /* store A,B */ + break; + case 013: /* "long left arot" */ + if (reason = stop_inst) break; /* stop on undef? */ + for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ + AR = (AR << 1) | ((BR >> 14) & 1); + BR = (BR & SIGN) | ((BR << 1) & MMASK) | + ((AR >> 16) & 1); + if ((AR & SIGN) != ((AR >> 1) & SIGN)) C = 1; + AR = AR & DMASK; } + break; + case 014: /* LGL */ + if (t1 > 16) AR = 0; /* > 16? all 0 */ + else { C = (AR >> (16 - t1)) & 1; /* C = last out */ + AR = (AR << t1) & DMASK; } /* log left */ + break; + case 015: /* ALS */ + if (t1 > 16) t1 = 16; /* limit to 16 */ + t2 = SEXT (AR); /* save AR */ + AR = (AR << t1) & DMASK; /* "arith" left */ + if ((t2 >> (16 - t1)) != /* shf out + sgn */ + ((AR & SIGN)? -1: 0)) C = 1; + break; + case 016: /* ALR */ + t2 = t1 % 16; /* mod 16 */ + AR = ((AR << t2) | (AR >> (16 - t2))) & DMASK; + C = AR & 1; /* C = A<16> */ + break; + case 017: /* "short left arot" */ + if (reason = stop_inst) break; /* stop on undef? */ + for (t2 = 0; t2 < t1; t2++) { /* bit by bit */ + if ((AR & SIGN) != ((AR << 1) & SIGN)) C = 1; + AR = ((AR << 1) | (AR >> 15)) & DMASK; } + break; } /* end case fnc */ + break; + +/* Skip */ + +case 040: + skip = 0; + if (((MB & 000001) && C) || /* SSC */ + ((MB & 000002) && ss[3]) || /* SS4 */ + ((MB & 000004) && ss[2]) || /* SS3 */ + ((MB & 000010) && ss[1]) || /* SS2 */ + ((MB & 000020) && ss[0]) || /* SS1 */ + ((MB & 000040) && AR) || /* SNZ */ + ((MB & 000100) && (AR & 1)) || /* SLN */ + ((MB & 000200) && (TST_INTREQ (INT_MPE))) || /* SPS */ + ((MB & 000400) && (AR & SIGN))) skip = 1; /* SMI */ + if ((MB & 001000) == 0) skip = skip ^ 1; /* reverse? */ + PC = NEWA (PC, PC + skip); + break; + +/* Operate */ + +case 060: + if (MB == 0140024) AR = AR ^ SIGN; /* CHS */ + else if (MB == 0140040) AR = 0; /* CRA */ + else if (MB == 0140100) AR = AR & ~SIGN; /* SSP */ + else if (MB == 0140200) C = 0; /* RCB */ + else if (MB == 0140320) { /* CSA */ + C = (AR & SIGN) >> 15; + AR = AR & ~SIGN; } + else if (MB == 0140401) AR = AR ^ DMASK; /* CMA */ + else if (MB == 0140407) { /* TCA */ + AR = (-AR) & DMASK; + sc = 0; } + else if (MB == 0140500) AR = AR | SIGN; /* SSM */ + else if (MB == 0140600) C = 1; /* SCB */ + else if (MB == 0141044) AR = AR & 0177400; /* CAR */ + else if (MB == 0141050) AR = AR & 0377; /* CAL */ + else if (MB == 0141140) AR = AR >> 8; /* ICL */ + else if (MB == 0141206) AR = Add16 (AR, 1); /* AOA */ + else if (MB == 0141216) AR = Add16 (AR, C); /* ACA */ + else if (MB == 0141240) AR = (AR << 8) & DMASK; /* ICR */ + else if (MB == 0141340) /* ICA */ + AR = ((AR << 8) | (AR >> 8)) & DMASK; + else if (reason = stop_inst) break; + else AR = Operate (MB, AR); /* undefined */ + break; + } /* end case op */ +} /* end while */ + +saved_AR = AR & DMASK; +saved_BR = BR & DMASK; +saved_XR = XR & DMASK; +return reason; +} + +/* Effective address + + The effective address calculation consists of three phases: + - base address calculation: 0/pagenumber'displacement + - (extend): indirect address resolution + (non-extend): pre-indexing + - (extend): post-indexing + (non-extend): indirect address/post-indexing resolution + + In extend mode, address calculations are carried out to 16b + and masked to 15b at exit. In non-extend mode, address bits + <1:2> are preserved by the NEWA macro; address bit <1> is + masked at exit. +*/ + +t_stat Ea (int32 IR, int32 *addr) +{ +int32 i = 0; +int32 Y = IR & (IA | DISP); /* ind + disp */ + +if (IR & SC) Y = ((PC - 1) & PAGENO) | Y; /* cur sec? + pageno */ +if (ext) { /* extend mode? */ + for (i = 0; (i < ind_max) && (Y & IA); i++) { /* resolve ind addr */ + Y = Read (Y & X_AMASK); } /* get ind addr */ + if (IR & IDX) Y = Y + XR; /* post-index */ + } /* end if ext */ +else { /* non-extend */ + Y = NEWA (PC, Y + ((IR & IDX)? XR: 0)); /* pre-index */ + for (i = 0; (i < ind_max) && (IR & IA); i++) { /* resolve ind addr */ + IR = Read (Y & X_AMASK); /* get ind addr */ + Y = NEWA (Y, IR + ((IR & IDX)? XR: 0)); } /* post-index */ + } /* end else */ +*addr = Y = Y & X_AMASK; /* return addr */ +if (dlog && sim_log && !turnoff) /* cycle log? */ + fprintf (sim_log, " EA= %06o [%06o]\n", Y, M[Y]); +if (i >= ind_max) return STOP_IND; /* too many ind? */ +return SCPE_OK; +} + +/* Write memory */ + +void Write (int32 val, int32 addr) +{ +if (((addr == 0) || (addr >= 020)) && MEM_ADDR_OK (addr)) + M[addr] = val; +return; +} + +/* Add */ + +int32 Add16 (int32 v1, int32 v2) +{ +int32 r = v1 + v2; +C = 0; +if (((v1 ^ ~v2) & (v1 ^ r)) & SIGN) C = 1; +return (r & DMASK); +} + +int32 Add31 (int32 v1, int32 v2) +{ +int32 r = v1 + v2; +C = 0; +if (((v1 ^ ~v2) & (v1 ^ r)) & (1u << 30)) C = 1; +return r; +} + +/* Unimplemented I/O device */ + +int32 undio (int32 op, int32 fnc, int32 val) +{ +return ((stop_dev << IOT_V_REASON) | val); +} + +/* Undefined operate instruction. This code is reached when the + opcode does not correspond to a standard operate instruction. + It simulates the behavior of the actual logic. + + An operate instruction executes in 4 or 6 phases. A 'normal' + instruction takes 4 phases: + + t1 t1 + t2/tlate t2/t2 extended into t3 + t3/tlate t3 + t4 t4 + + A '1.5 cycle' instruction takes 6 phases: + + t1 t1 + t2/tlate t2/t2 extended into t3 + t3/tlate t3 + t2/tlate 'special' t2/t2 extended into t3 + t3/tlate t3 + t4 t4 + + The key signals, by phase, are the following + + tlate EASTL enable A to sum leg 1 (else 0) + (((m12+m16)x!azzzz)+(m9+m11+azzzz) + EASBM enable 0 to sum leg 2 (else 177777) + (m9+m11+azzzz) + JAMKN jam carry network to 0 = force XOR + ((m12+m16)x!azzzz) + EIKI7 force carry into adder + ((m15x(C+!m13))x!JAMKN) + + t3 CLDTR set D to 177777 (always) + ESDTS enable adder sum to D (always) + SETAZ enable repeat cycle = set azzzz + (m8xm15) + + if azzzz { + t2 CLATR clear A register (due to azzzz) + EDAHS enable D high to A high register (due to azzzz) + EDALS enable D low to A low register (due to azzzz) + + tlate, t3 as above + } + + t4 CLATR clear A register + (m11+m15+m16) + CLA1R clear A1 register + (m10+m14) + EDAHS enable D high to A high register + ((m11xm14)+m15+m16) + EDALS enable D low to A low register + ((m11xm13)+m15+m16) + ETAHS enable D transposed to A high register + (m9xm11) + ETALS enable D transposed to A low register + (m10xm11) + EDA1R enable D1 to A1 register + ((m8xm10)+m14) + CBITL clear C, conditionally set C from adder output + (m9x!m11) + CBITG conditionally set C if D1 + (m10xm12xD1) + CBITE unconditionally set C + (m8xm9) +*/ + +int32 Operate (int32 MB, int32 AR) +{ +int32 D, jamkn, eiki7, easbm, eastl, setaz; +int32 clatr, cla1r, edahs, edals, etahs, etals, eda1r; +int32 cbitl, cbitg, cbite; +int32 aleg, bleg, ARx; + +/* Phase tlate */ + +ARx = AR; /* default */ +jamkn = (MB & (m12+m16)) != 0; /* m12+m16 */ +easbm = (MB & (m9+m11)) != 0; /* m9+m11 */ +eastl = jamkn || easbm; /* m9+m11+m12+m16 */ +setaz = (MB & (m8+m15)) == (m8+m15); /* m8xm15*/ +eiki7 = (MB & m15) && (C || !(MB & m13)); /* cin */ +aleg = eastl? AR: 0; /* a input */ +bleg = easbm? 0: DMASK; /* b input */ +if (jamkn) D = aleg ^ bleg; /* jammin? xor */ +else D = (aleg + bleg + eiki7) & DMASK; /* else add */ + +/* Possible repeat at end of tlate - special t2, repeat tlate */ + +if (setaz) { + ARx = D; /* forced: t2 */ + aleg = ARx; /* forced: tlate */ + bleg = 0; /* forced */ + jamkn = 0; /* forced */ + D = (aleg + bleg + eiki7) & DMASK; /* forced add */ + sc = 0; } /* ends repeat */ + +/* Phase t4 */ + +clatr = (MB & (m11+m15+m16)) != 0; /* m11+m15+m16 */ +cla1r = (MB & (m10+m14)) != 0; /* m10+m14 */ +edahs = ((MB & (m11+m14)) == (m11+m14)) || /* (m11xm14)+m15+m16 */ + (MB & (m15+m16)); +edals = ((MB & (m11+m13)) == (m11+m13)) || /* (m11xm13)+m15+m16 */ + (MB & (m15+m16)); +etahs = (MB & (m9+m11)) == (m9+m11); /* m9xm11 */ +etals = (MB & (m10+m11)) == (m10+m11); /* m10xm11 */ +eda1r = ((MB & (m8+m10)) == (m8+m10)) || (MB & m14); /* (m8xm10)+m14 */ +cbitl = (MB & (m9+m11)) == m9; /* m9x!m11 */ +cbite = (MB & (m8+m9)) == (m8+m9); /* m8xm9 */ +cbitg = (MB & (m10+m12)) == (m10+m12); /* m10xm12 */ + +if (clatr) ARx = 0; /* clear A */ +if (cla1r) ARx = ARx & ~SIGN; /* clear A1 */ +if (edahs) ARx = ARx | (D & 0177400); /* D hi to A hi */ +if (edals) ARx = ARx | (D & 0000377); /* D lo to A lo */ +if (etahs) ARx = ARx | ((D << 8) & 0177400); /* D lo to A hi */ +if (etals) ARx = ARx | ((D >> 8) & 0000377); /* D hi to A lo */ +if (eda1r) ARx = ARx | (D & SIGN); /* D1 to A1 */ +if (cbitl) { /* ovflo to C */ + +/* Overflow calculation. Cases: + + aleg bleg cin overflow + + 0 x x can't overflow + A 0 0 can't overflow + A -1 1 can't overflow + A 0 1 overflow if 77777 -> 100000 + A -1 0 overflow if 100000 -> 77777 +*/ + + if (!jamkn && + ((bleg && !eiki7 && (D == 0077777)) || + (!bleg && eiki7 && (D == 0100000)))) C = 1; + else C = 0; } +if (cbite || (cbitg && (D & SIGN))) C = 1; /* C = 1 */ +return ARx; +} + +/* Reset routines */ + +t_stat cpu_reset (DEVICE *dptr) +{ +saved_AR = saved_BR = saved_XR = 0; +C = 0; +dp = 0; +ext = pme = extoff_pending = 0; +dev_ready = dev_ready & ~INT_PENDING; +dev_enable = 0; +return cpu_svc (&cpu_unit); +} + +/* Memory examine */ + +t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) +{ +int32 d; + +if (addr >= MEMSIZE) return SCPE_NXM; +if (addr == 0) d = saved_XR; +else d = M[addr]; +if (vptr != NULL) *vptr = d & DMASK; +return SCPE_OK; +} + +/* Memory deposit */ + +t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) +{ +if (addr >= MEMSIZE) return SCPE_NXM; +if (addr == 0) saved_XR = val & DMASK; +else M[addr] = val & DMASK; +return SCPE_OK; +} + +/* Breakpoint service */ + +t_stat cpu_svc (UNIT *uptr) +{ +if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt; +save_ibkpt = -1; +return SCPE_OK; +} + +/* Option processors */ + +t_stat cpu_set_noext (UNIT *uptr, int32 value) +{ +if (MEMSIZE > (NX_AMASK + 1)) return SCPE_ARG; +return SCPE_OK; +} + +t_stat cpu_set_size (UNIT *uptr, int32 value) +{ +int32 mc = 0; +t_addr i; + +if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0) || + (((cpu_unit.flags & UNIT_EXT) == 0) && (value > (NX_AMASK + 1)))) + return SCPE_ARG; +for (i = value; i < MEMSIZE; i++) mc = mc | M[i]; +if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) + return SCPE_OK; +MEMSIZE = value; +for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; +return SCPE_OK; +} diff --git a/h316_defs.h b/h316_defs.h new file mode 100644 index 00000000..bd6f9e53 --- /dev/null +++ b/h316_defs.h @@ -0,0 +1,142 @@ +/* h316_defs.h: Honeywell 316/516 simulator definitions + + Copyright (c) 1993-2001, Robert M. Supnik + + 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. + + Except as contained in this notice, the name of Robert M Supnik 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. +*/ + +#include "sim_defs.h" /* simulator defns */ + +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_IODV 2 /* must be 2 */ +#define STOP_HALT 3 /* HALT */ +#define STOP_IBKPT 4 /* breakpoint */ +#define STOP_IND 5 /* indirect loop */ + +/* Memory */ + +#define MAXMEMSIZE 32768 /* max memory size */ +#define MEMSIZE (cpu_unit.capac) /* actual memory size */ +#define X_AMASK (MAXMEMSIZE - 1) /* ext address mask */ +#define NX_AMASK ((MAXMEMSIZE / 2) - 1) /* nx address mask */ +#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE) + +/* Architectural constants */ + +#define SIGN 0100000 /* sign */ +#define DMASK 0177777 /* data mask */ +#define MMASK (DMASK & ~SIGN) /* magnitude mask */ +#define XR M[0] +#define M_CLK 061 /* clock location */ +#define M_RSTINT 062 /* restrict int */ +#define M_INT 063 /* int location */ + +/* CPU options */ + +#define UNIT_V_EXT (UNIT_V_UF + 1) /* extended mem */ +#define UNIT_EXT (1 << UNIT_V_EXT) +#define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */ +#define UNIT_HSA (1 << UNIT_V_HSA) + +/* Instruction format */ + +#define I_M_OP 077 /* opcode */ +#define I_V_OP 10 +#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP) +#define I_M_FNC 017 /* function */ +#define I_V_FNC 6 +#define I_GETFNC(x) (((x) >> I_V_FNC) & I_M_FNC) +#define IA 0100000 /* indirect address */ +#define IDX 0040000 /* indexed */ +#define SC 0001000 /* sector */ +#define DISP 0000777 /* page displacement */ +#define PAGENO 0077000 /* page number */ +#define INCLRA (010 << I_V_FNC) /* INA clear A */ +#define DEVMASK 0000077 /* device mask */ +#define SHFMASK 0000077 /* shift mask */ + +/* I/O opcodes */ + +#define ioOCP 0 /* output control */ +#define ioSKS 1 /* skip if set */ +#define ioINA 2 /* input to A */ +#define ioOTA 3 /* output from A */ + +/* I/O devices */ + +#define PTR 001 /* paper tape reader */ +#define PTP 002 /* paper tape punch */ +#define LPT 003 /* line printer */ +#define TTY 004 /* console */ +#define CDR 005 /* card reader */ +#define MT 010 /* mag tape data */ +#define KEYS 020 /* keys (CPU) */ +#define FHD 022 /* fixed head disk */ +#define DMA 024 /* DMA control */ +#define DP 025 /* moving head disk */ +#define OPT 034 /* SKS/OCP option */ + +/* Interrupt flags, definitions correspond to SMK bits */ + +#define INT_V_CLK 0 /* clock */ +#define INT_V_MPE 1 /* parity error */ +#define INT_V_LPT 2 /* line printer */ +#define INT_V_CDR 4 /* card reader */ +#define INT_V_TTY 5 /* teletype */ +#define INT_V_PTP 6 /* paper tape punch */ +#define INT_V_PTR 7 /* paper tape reader */ +#define INT_V_FHD 8 /* fixed head disk */ +#define INT_V_DP 12 /* moving head disk */ +#define INT_V_MT 15 /* mag tape */ +#define INT_V_NODEF 16 /* int not deferred */ +#define INT_V_ON 17 /* int on */ + +/* I/O macros */ + +#define IOT_V_REASON 17 +#define IOT_V_SKIP 16 +#define IOT_SKIP (1u << IOT_V_SKIP) +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ +#define IOBADFNC(x) (((stop_inst) << IOT_V_REASON) | (x)) +#define IOSKIP(x) (IOT_SKIP | (x)) + +#define INT_CLK (1u << INT_V_CLK) +#define INT_MPE (1u << INT_V_MPE) +#define INT_LPT (1u << INT_V_LPT) +#define INT_CDR (1u << INT_V_CDR) +#define INT_TTY (1u << INT_V_TTY) +#define INT_PTP (1u << INT_V_PTP) +#define INT_PTR (1u << INT_V_PTR) +#define INT_FHD (1u << INT_V_FHD) +#define INT_DP (1u << INT_V_DP) +#define INT_MT (1u << INT_V_MT) +#define INT_NODEF (1u << INT_V_NODEF) +#define INT_ON (1u << INT_V_ON) +#define INT_PENDING (INT_ON | INT_NODEF) + +#define SET_READY(x) dev_ready = dev_ready | (x) +#define CLR_READY(x) dev_ready = dev_ready & ~(x) +#define TST_READY(x) ((dev_ready & (x)) != 0) +#define CLR_ENABLE(x) dev_enable = dev_enable & ~(x) +#define TST_INTREQ(x) ((dev_ready & dev_enable & (x)) != 0) diff --git a/h316_lp.c b/h316_lp.c new file mode 100644 index 00000000..b8879845 --- /dev/null +++ b/h316_lp.c @@ -0,0 +1,254 @@ +/* h316_lp.c: Honeywell 316/516 line printer + + Copyright (c) 1993-2001, Robert M. Supnik + + 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. + + Except as contained in this notice, the name of Robert M Supnik 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. + + lpt line printer +*/ + +#include "h316_defs.h" +#define LPT_WIDTH 120 /* width */ +#define LPT_SCAN (LPT_WIDTH / 2) /* words/scan */ +#define LPT_DRUM 64 /* drum rows */ +#define LPT_SVCSH 01 /* shuttle */ +#define LPT_SVCPA 02 /* paper advance */ + +extern int32 dev_ready, dev_enable; +extern int32 stop_inst; +int32 lpt_wdpos = 0; /* word position */ +int32 lpt_drpos = 0; /* drum position */ +int32 lpt_crpos = 0; /* carriage position */ +int32 lpt_svcst = 0; /* service state */ +int32 lpt_svcch = 0; /* service channel */ +int32 lpt_xfer = 0; /* transfer flag */ +int32 lpt_prdn = 1; /* printing done */ +char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */ +int32 lpt_xtime = 5; /* transfer time */ +int32 lpt_etime = 50; /* end of scan time */ +int32 lpt_ptime = 5000; /* paper adv time */ +int32 lpt_stopioe = 0; /* stop on error */ +t_stat lpt_svc (UNIT *uptr); +t_stat lpt_reset (DEVICE *dptr); + +/* The Series 16 line printer is an unbuffered Analex shuttle printer. + Because it was unbuffered, the CPU had to scan out an entire line's + worth of characters (60 words) for every character on the print drum + (64 characters). Because it was a shuttle printer, the entire + process must be repeated first for the odd columns and then for the + even columns. After scanning the odd columns, the printer carriage + shuttled right by one column; after scanning the even columns, the + carriage shuttled left. This halved the number of hammers required, + reducing cost but increasing mechanical complexity. + + The real printer is very timing dependent. If the CPU misses a + scan, then the wrong characters are printed. If the printer protocol + is violated, then results are unpredictable. The simulated printer + is much more forgiving. Rather than simulating the fixed drum and + hammer timing of the real printer, the simulator is driven by the + program's OTA instructions. If the program misses a time slot, the + simulator will still print the "correct" result. A timing based + simulation would be very hard to do in the absense of accurate + instruction timing. + + Printer state is maintained in a set of position and state variables: + + lpt_wdpos word count within a line scan (0-59) + lpt_drpos drum position (0-63) + lpt_crpos carriage position (0-1) + lpt_svcst service state (shuttle, paper advance) + lpt_svcch channel for paper advance (0 = no adv) + lpt_xfer transfer ready flag + lpt_prdn printing done flag + + LPT data structures + + lpt_dev LPT device descriptor + lpt_unit LPT unit descriptor + lpt_mod LPT modifiers + lpt_reg LPT register list +*/ + +UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) }; + +REG lpt_reg[] = { + { DRDATA (WDPOS, lpt_wdpos, 6) }, + { DRDATA (DRPOS, lpt_drpos, 6) }, + { FLDATA (CRPOS, lpt_crpos, 0) }, + { FLDATA (XFER, lpt_xfer, 0) }, + { FLDATA (PRDN, lpt_prdn, 0) }, + { FLDATA (INTREQ, dev_ready, INT_V_LPT) }, + { FLDATA (ENABLE, dev_enable, INT_V_LPT) }, + { ORDATA (SVCST, lpt_svcst, 2) }, + { ORDATA (SVCCH, lpt_svcch, 2) }, + { BRDATA (BUF, lpt_buf, 8, 8, 120) }, + { DRDATA (POS, lpt_unit.pos, 31), PV_LEFT }, + { DRDATA (XTIME, lpt_xtime, 24), PV_LEFT }, + { DRDATA (ETIME, lpt_etime, 24), PV_LEFT }, + { DRDATA (PTIME, lpt_ptime, 24), PV_LEFT }, + { FLDATA (STOP_IOE, lpt_stopioe, 0) }, + { NULL } }; + +DEVICE lpt_dev = { + "LPT", &lpt_unit, lpt_reg, NULL, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &lpt_reset, + NULL, NULL, NULL }; + + +/* IO routine */ + +int32 lptio (int32 inst, int32 fnc, int32 dat) +{ +int32 chr; + +switch (inst) { /* case on opcode */ +case ioOCP: /* OCP */ + switch (fnc) { /* case on fnc */ + case 000: case 002: case 004: /* paper adv */ + lpt_svcst = lpt_svcst | LPT_SVCPA; /* set state */ + lpt_svcch = fnc >> 1; /* save channel */ + sim_activate (&lpt_unit, lpt_ptime); + CLR_READY (INT_LPT); /* clear int */ + break; + case 007: /* init scan */ + lpt_prdn = 0; /* clear pr done */ + lpt_wdpos = 0; /* init scan pos */ + if (!sim_is_active (&lpt_unit)) lpt_xfer = 1; + CLR_READY (INT_LPT); /* clear int */ + break; + default: + return IOBADFNC (dat); } + break; +case ioSKS: /* SKS */ + switch (fnc) { /* case on fnc */ + case 000: /* if xfer rdy */ + if (lpt_xfer) return IOSKIP (dat); + break; + case 002: /* if !alarm */ + if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat); + break; + case 003: /* if odd col */ + if (lpt_crpos) return IOSKIP (dat); + break; + case 004: /* if !interrupt */ + if (!TST_INTREQ (INT_LPT)) return IOSKIP (dat); + break; + case 011: /* if line printed */ + if (lpt_prdn) return IOSKIP (dat); + break; + case 012: /* if !shuttling */ + if (!(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); + break; + case 013: + if (lpt_prdn && !(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); + break; + case 014: /* if !advancing */ + if (!(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); + break; + case 015: + if (lpt_prdn && !(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); + break; + case 016: + if (!(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) return IOSKIP (dat); + break; + case 017: + if (lpt_prdn && !(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) + return IOSKIP (dat); + break; + default: + return IOBADFNC (dat); } + break; +case ioOTA: /* OTA */ + if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (lpt_xfer) { /* xfer ready? */ + lpt_xfer = 0; /* clear xfer */ + chr = (dat >> (lpt_crpos? 0: 8)) & 077; /* get 6b char */ + if (chr == lpt_drpos) { /* match drum pos? */ + if (chr < 040) chr = chr | 0100; + lpt_buf[2 * lpt_wdpos + lpt_crpos] = chr; } + lpt_wdpos++; /* adv scan pos */ + if (lpt_wdpos >= LPT_SCAN) { /* end of scan? */ + lpt_wdpos = 0; /* reset scan pos */ + lpt_drpos++; /* adv drum pos */ + if (lpt_drpos >= LPT_DRUM) { /* end of drum? */ + lpt_drpos = 0; /* reset drum pos */ + lpt_crpos = lpt_crpos ^ 1; /* shuttle */ + lpt_svcst = lpt_svcst | LPT_SVCSH; + sim_activate (&lpt_unit, lpt_ptime); + } /* end if shuttle */ + else sim_activate (&lpt_unit, lpt_etime); + } /* end if endscan */ + else sim_activate (&lpt_unit, lpt_xtime); + return IOSKIP (dat); } /* skip return */ + break; } /* end case op */ +return dat; +} + +/* Unit service */ + +t_stat lpt_svc (UNIT *uptr) +{ +int32 i; +static const char *lpt_cc[] = { + "\r", + "\n", + "\n\f", + "\n" }; + +if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (lpt_stopioe, SCPE_UNATT); +lpt_xfer = 1; +if (lpt_svcst & LPT_SVCSH) { /* shuttling */ + SET_READY (INT_LPT); /* interrupt */ + if (lpt_crpos == 0) lpt_prdn = 1; } +if (lpt_svcst & LPT_SVCPA) { /* paper advance */ + SET_READY (INT_LPT); /* interrupt */ + for (i = LPT_WIDTH - 1; i >= 0; i++) { + if (lpt_buf[i] != ' ') break; } + lpt_buf[i + 1] = 0; + fputs (lpt_buf, uptr -> fileref); /* output buf */ + fputs (lpt_cc[lpt_svcch & 03], uptr -> fileref); /* output eol */ + uptr -> pos = ftell (uptr -> fileref); /* update pos */ + for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buf */ + } +lpt_svcst = 0; +return SCPE_OK; +} + +/* Reset routine */ + +t_stat lpt_reset (DEVICE *dptr) +{ +int32 i; + +lpt_wdpos = lpt_drpos = lpt_crpos = 0; /* clear positions */ +lpt_svcst = lpt_svcch = 0; /* idle state */ +lpt_xfer = 0; /* not rdy to xfer */ +lpt_prdn = 1; /* printing done */ +for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */ +lpt_buf[LPT_WIDTH] = 0; +CLR_READY (INT_LPT); /* clear int, enb */ +CLR_ENABLE (INT_LPT); +sim_cancel (&lpt_unit); /* deactivate unit */ +return SCPE_OK; +} diff --git a/h316_stddev.c b/h316_stddev.c new file mode 100644 index 00000000..c979acff --- /dev/null +++ b/h316_stddev.c @@ -0,0 +1,480 @@ +/* h316_stddev.c: Honeywell 316/516 standard devices + + Copyright (c) 1993-2001, Robert M. Supnik + + 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. + + Except as contained in this notice, the name of Robert M Supnik 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. + + ptr 316/516-50 paper tape reader + ptp 316/516-52 paper tape punch + tty 316/516-33 teleprinter + clk/options 316/516-12 real time clocks/internal options +*/ + +#include "h316_defs.h" +#include +#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ +#define UNIT_UC (1 << UNIT_V_UC) + +extern uint16 M[]; +extern int32 PC; +extern int32 stop_inst; +extern int32 C, dp, ext, extoff_pending, sc; +extern int32 dev_ready, dev_enable; +extern UNIT cpu_unit; +int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ +int32 ptp_power = 0, ptp_ptime; /* punch power, time */ +int32 tty_mode = 0, tty_buf = 0; /* tty mode, buf */ +int32 clk_tps = 60; /* ticks per second */ +t_stat ptr_svc (UNIT *uptr); +t_stat ptr_reset (DEVICE *dptr); +t_stat ptr_boot (int32 unitno); +t_stat ptp_svc (UNIT *uptr); +t_stat ptp_reset (DEVICE *dptr); +t_stat tti_svc (UNIT *uptr); +t_stat tto_svc (UNIT *uptr); +t_stat tty_reset (DEVICE *dptr); +t_stat clk_svc (UNIT *uptr); +t_stat clk_reset (DEVICE *dptr); +extern t_stat sim_poll_kbd (void); +extern t_stat sim_putchar (int32 out); +extern t_bool hp_setdev (UNIT *uptr, int32 val); + +/* PTR data structures + + ptr_dev PTR device descriptor + ptr_unit PTR unit descriptor + ptr_mod PTR modifiers + ptr_reg PTR register list +*/ + +UNIT ptr_unit = { + UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_IN_WAIT }; + +REG ptr_reg[] = { + { ORDATA (BUF, ptr_unit.buf, 8) }, + { FLDATA (READY, dev_ready, INT_V_PTR) }, + { FLDATA (ENABLE, dev_enable, INT_V_PTR) }, + { DRDATA (POS, ptr_unit.pos, 31), PV_LEFT }, + { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, + { FLDATA (STOP_IOE, ptr_stopioe, 0) }, + { NULL } }; + +DEVICE ptr_dev = { + "PTR", &ptr_unit, ptr_reg, NULL, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptr_reset, + &ptr_boot, NULL, NULL }; + +/* PTP data structures + + ptp_dev PTP device descriptor + ptp_unit PTP unit descriptor + ptp_mod PTP modifiers + ptp_reg PTP register list +*/ + +UNIT ptp_unit = { + UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; + +REG ptp_reg[] = { + { ORDATA (BUF, ptp_unit.buf, 8) }, + { FLDATA (READY, dev_ready, INT_V_PTP) }, + { FLDATA (ENABLE, dev_enable, INT_V_PTP) }, + { FLDATA (POWER, ptp_power, 0) }, + { DRDATA (POS, ptp_unit.pos, 31), PV_LEFT }, + { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, + { DRDATA (PWRTIME, ptp_ptime, 24), PV_LEFT }, + { FLDATA (STOP_IOE, ptp_stopioe, 0) }, + { NULL } }; + + +DEVICE ptp_dev = { + "PTP", &ptp_unit, ptp_reg, NULL, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptp_reset, + NULL, NULL, NULL }; + +/* TTY data structures + + tty_dev TTY device descriptor + tty_unit TTY unit descriptor + tty_reg TTY register list + tty_mod TTy modifiers list +*/ + +#define TTI 0 +#define TTO 1 + +UNIT tty_unit[] = { + { UDATA (&tti_svc, UNIT_UC, 0), KBD_POLL_WAIT }, + { UDATA (&tto_svc, UNIT_UC, 0), SERIAL_OUT_WAIT } }; + +REG tty_reg[] = { + { ORDATA (BUF, tty_buf, 8) }, + { FLDATA (MODE, tty_mode, 0) }, + { FLDATA (READY, dev_ready, INT_V_TTY) }, + { FLDATA (ENABLE, dev_enable, INT_V_TTY) }, + { DRDATA (KPOS, tty_unit[TTI].pos, 31), PV_LEFT }, + { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, + { DRDATA (TPOS, tty_unit[TTO].pos, 31), PV_LEFT }, + { DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, + { FLDATA (UC, tty_unit[TTI].flags, UNIT_V_UC), REG_HRO }, + { NULL } }; + +MTAB tty_mod[] = { + { UNIT_UC, 0, "lower case", "LC", NULL }, + { UNIT_UC, UNIT_UC, "upper case", "UC", NULL }, + { 0 } }; + +DEVICE tty_dev = { + "TTY", tty_unit, tty_reg, tty_mod, + 2, 10, 31, 1, 8, 8, + NULL, NULL, &tty_reset, + NULL, NULL, NULL }; + +/* CLK data structures + + clk_dev CLK device descriptor + clk_unit CLK unit descriptor + clk_mod CLK modifiers + clk_reg CLK register list +*/ + +UNIT clk_unit = { + UDATA (&clk_svc, 0, 0), 16000 }; + +REG clk_reg[] = { + { FLDATA (READY, dev_ready, INT_V_CLK) }, + { FLDATA (ENABLE, dev_enable, INT_V_CLK) }, + { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, + { DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT }, + { NULL } }; + +DEVICE clk_dev = { + "CLK", &clk_unit, clk_reg, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &clk_reset, + NULL, NULL, NULL }; + +/* Paper tape reader: IO routine */ + +int32 ptrio (int32 inst, int32 fnc, int32 dat) +{ +switch (inst) { /* case on opcode */ +case ioOCP: /* OCP */ + if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ + if (fnc) sim_cancel (&ptr_unit); /* fnc 1? stop */ + else sim_activate (&ptr_unit, ptr_unit.wait); /* fnc 0? start */ + break; +case ioSKS: /* SKS */ + if (fnc & 013) return IOBADFNC (dat); /* only fnc 0,4 */ + if (((fnc == 0) && TST_READY (INT_PTR)) || /* fnc 0? skip rdy */ + ((fnc == 4) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */ + return IOSKIP (dat); + break; +case ioINA: /* INA */ + if (fnc & 007) return IOBADFNC (dat); /* only fnc 0,10 */ + if (TST_READY (INT_PTR)) { /* ready? */ + CLR_READY (INT_PTR); /* clear ready */ + return IOSKIP (ptr_unit.buf | dat); } /* ret buf, skip */ + break; } /* end case op */ +return dat; +} + +/* Unit service */ + +t_stat ptr_svc (UNIT *uptr) +{ +int32 temp; + +if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (ptr_stopioe, SCPE_UNATT); +if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte */ + if (feof (ptr_unit.fileref)) { + if (ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; } + else perror ("PTR I/O error"); + clearerr (ptr_unit.fileref); + return SCPE_IOERR; } +SET_READY (INT_PTR); /* set ready flag */ +ptr_unit.buf = temp & 0377; /* get byte */ +ptr_unit.pos = ftell (ptr_unit.fileref); /* update pos */ +sim_activate (&ptr_unit, ptr_unit.wait); /* reactivate */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat ptr_reset (DEVICE *dptr) +{ +CLR_READY (INT_PTR); /* clear ready, enb */ +CLR_ENABLE (INT_PTR); +ptr_unit.buf = 0; /* clear buffer */ +sim_cancel (&ptr_unit); /* deactivate unit */ +return SCPE_OK; +} + +/* Paper tape reader bootstrap routine */ + +#define PBOOT_START 1 +#define PBOOT_SIZE (sizeof (pboot) / sizeof (int32)) + +static const int32 pboot[] = { + 0010057, /* STA 57 */ + 0030001, /* OCP 1 */ + 0131001, /* READ, INA 1001 */ + 0002003, /* JMP READ */ + 0101040, /* SNZ */ + 0002003, /* JMP READ */ + 0010000, /* STA 0 */ + 0131001, /* READ1, INA 1001 */ + 0002010, /* JMP READ1 */ + 0041470, /* LGL 8 */ + 0130001, /* READ2, INA 1 */ + 0002013, /* JMP READ2 */ + 0110000, /* STA* 0 */ + 0024000, /* IRS 0 */ + 0100040 /* SZE */ +}; + +t_stat ptr_boot (int32 unit) +{ +int32 i; + +for (i = 0; i < PBOOT_SIZE; i++) /* copy bootstrap */ + M[PBOOT_START + i] = pboot[i]; +PC = PBOOT_START; +return SCPE_OK; +} + +/* Paper tape punch: IO routine */ + +int32 ptpio (int32 inst, int32 fnc, int32 dat) +{ +switch (inst) { /* case on opcode */ +case ioOCP: /* OCP */ + if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ + if (fnc) { /* fnc 1? pwr off */ + CLR_READY (INT_PTP); /* not ready */ + ptp_power = 0; /* turn off power */ + sim_cancel (&ptp_unit); } /* stop punch */ + else if (ptp_power == 0) /* fnc 0? start */ + sim_activate (&ptp_unit, ptp_ptime); + break; +case ioSKS: /* SKS */ + if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */ + return IOBADFNC (dat); + if (((fnc == 00) && TST_READY (INT_PTP)) || /* fnc 0? skip rdy */ + ((fnc == 01) /* fnc 1? skip ptp on */ + && (ptp_power || sim_is_active (&ptp_unit))) || + ((fnc == 04) && !TST_INTREQ (INT_PTP))) /* fnc 4? skip !int */ + return IOSKIP (dat); + break; +case ioOTA: /* OTA */ + if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (TST_READY (INT_PTP)) { /* if ptp ready */ + CLR_READY (INT_PTP); /* clear ready */ + ptp_unit.buf = dat & 0377; /* store byte */ + sim_activate (&ptp_unit, ptp_unit.wait); + return IOSKIP (dat); } /* skip return */ + break; } +return dat; +} + +/* Unit service */ + +t_stat ptp_svc (UNIT *uptr) +{ + +SET_READY (INT_PTP); /* set flag */ +if (ptp_power == 0) { /* power on? */ + ptp_power = 1; /* ptp is ready */ + return SCPE_OK; } +if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (ptp_stopioe, SCPE_UNATT); +if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* output byte */ + perror ("PTP I/O error"); + clearerr (ptp_unit.fileref); + return SCPE_IOERR; } +ptp_unit.pos = ftell (ptp_unit.fileref); /* update pos */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat ptp_reset (DEVICE *dptr) +{ +CLR_READY (INT_PTP); /* clear ready, enb */ +CLR_ENABLE (INT_PTP); +ptp_power = 0; /* power off */ +ptp_unit.buf = 0; /* clear buffer */ +sim_cancel (&ptp_unit); /* deactivate unit */ +return SCPE_OK; +} + +/* Terminal: IO routine */ + +int32 ttyio (int32 inst, int32 fnc, int32 dat) +{ +switch (inst) { /* case on opcode */ +case ioOCP: /* OCP */ + if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ + if (fnc && (tty_mode == 0)) { /* input to output? */ + if (!sim_is_active (&tty_unit[TTO])) SET_READY (INT_TTY); + tty_mode = 1; } /* mode is output */ + else if ((fnc == 0) && tty_mode) { /* output to input? */ + CLR_READY (INT_TTY); /* clear ready */ + tty_mode = 0; } /* mode is input */ + break; +case ioSKS: /* SKS */ + if (fnc & 012) return IOBADFNC (dat); /* fnc 0,1,4,5 */ + if (((fnc == 0) && TST_READY (INT_TTY)) || /* fnc 0? skip rdy */ + ((fnc == 1) && /* fnc 1? skip !busy */ + tty_mode && !sim_is_active (&tty_unit[TTO])) || + ((fnc == 4) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */ + ((fnc == 5) && /* fnc 5? skip !xoff */ + !tty_mode && ((tty_buf & 0177) == 023))) + return IOSKIP (dat); + break; +case ioINA: /* INA */ + if (fnc & 005) return IOBADFNC (dat); /* only 0,2,10,12 */ + if (TST_READY (INT_TTY)) { /* ready? */ + if (tty_mode == 0) CLR_READY (INT_TTY); /* inp? clear rdy */ + return IOSKIP (dat | + (tty_buf & ((fnc & 002)? 077: 0377))); } + break; +case ioOTA: + if (fnc & 015) return IOBADFNC (dat); /* only 0,2 */ + if (TST_READY (INT_TTY)) { /* ready? */ + tty_buf = dat & 0377; /* store char */ + if (fnc & 002) { /* binary mode? */ + tty_buf = tty_buf | 0100; /* set ch 7 */ + if (tty_buf & 040) tty_buf = tty_buf & 0277; } + if (tty_mode) { + sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); + CLR_READY (INT_TTY); } + return IOSKIP (dat); } + break; } /* end case op */ +return dat; +} + +/* Unit service routines */ + +t_stat tti_svc (UNIT *uptr) +{ +int32 temp; + +sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */ +if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ +temp = temp & 0177; +if ((tty_unit[TTI].flags & UNIT_UC) && islower (temp)) /* force upper case? */ + temp = toupper (temp); +if (tty_mode == 0) { /* input mode? */ + tty_buf = temp | 0200; /* put char in buf */ + tty_unit[TTI].pos = tty_unit[TTI].pos + 1; + SET_READY (INT_TTY); /* set flag */ + sim_putchar (temp); } /* echo */ +return SCPE_OK; +} + +t_stat tto_svc (UNIT *uptr) +{ +int32 temp; + +SET_READY (INT_TTY); /* set done flag */ +if ((temp = sim_putchar (tty_buf & 0177)) != SCPE_OK) return temp; +tty_unit[TTO].pos = tty_unit[TTO].pos + 1; +return SCPE_OK; +} + +/* Reset routine */ + +t_stat tty_reset (DEVICE *dptr) +{ +CLR_READY (INT_TTY); /* clear ready, enb */ +CLR_ENABLE (INT_TTY); +tty_mode = 0; /* mode = input */ +tty_buf = 0; +sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ +sim_cancel (&tty_unit[TTO]); /* cancel output */ +return SCPE_OK; +} + +/* Clock/options: IO routine */ + +int32 clkio (int32 inst, int32 fnc, int32 dat) +{ +switch (inst) { /* case on opcode */ +case ioOCP: /* OCP */ + if (fnc & 015) return IOBADFNC (dat); /* only fnc 0,2 */ + CLR_READY (INT_CLK); /* reset ready */ + if (fnc) sim_cancel (&clk_unit); /* fnc = 2? stop */ + else { if (!sim_is_active (&clk_unit)) /* fnc = 0? start */ + sim_activate (&clk_unit, /* activate */ + sim_rtc_init (clk_unit.wait)); } /* init calibr */ + break; +case ioSKS: /* SKS */ + if (fnc == 0) { /* clock skip !int */ + if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); } + else if ((fnc & 007) == 002) { /* mem parity? */ + if (((fnc == 002) && !TST_READY (INT_MPE)) || + ((fnc == 012) && TST_READY (INT_MPE))) + return IOSKIP (dat); } + else return IOBADFNC (dat); /* invalid fnc */ + break; +case ioOTA: /* OTA */ + if (fnc == 000) dev_enable = dat; /* SMK */ + else if (fnc == 010) { /* OTK */ + C = (dat >> 15) & 1; /* set C */ + if (cpu_unit.flags & UNIT_HSA) /* HSA included? */ + dp = (dat >> 14) & 1; /* set dp */ + if (cpu_unit.flags & UNIT_EXT) { /* ext opt? */ + if (dat & 020000) { /* ext set? */ + ext = 1; /* yes, set */ + extoff_pending = 0; } + else extoff_pending = 1; } /* no, clr later */ + sc = dat & 037; } /* set sc */ + else return IOBADFNC (dat); + break; } +return dat; +} + +/* Unit service */ + +t_stat clk_svc (UNIT *uptr) +{ + +M[M_CLK] = M[M_CLK + 1] & DMASK; /* increment mem ctr */ +if (M[M_CLK] == 0) SET_READY (INT_CLK); /* = 0? set flag */ +sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat clk_reset (DEVICE *dptr) +{ +CLR_READY (INT_CLK); /* clear ready, enb */ +CLR_ENABLE (INT_CLK); +sim_cancel (&clk_unit); /* deactivate unit */ +return SCPE_OK; +} diff --git a/h316_sys.c b/h316_sys.c new file mode 100644 index 00000000..2cc66e9b --- /dev/null +++ b/h316_sys.c @@ -0,0 +1,347 @@ +/* h316_sys.c: Honeywell 316/516 simulator interface + + Copyright (c) 1993-2001, Robert M Supnik + + 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. + + Except as contained in this notice, the name of Robert M Supnik 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. +*/ + +#include "h316_defs.h" +#include + +extern DEVICE cpu_dev; +extern UNIT cpu_unit; +extern DEVICE ptr_dev, ptp_dev; +extern DEVICE tty_dev, lpt_dev; +extern DEVICE clk_dev; +extern REG cpu_reg[]; +extern uint16 M[]; +extern int32 sim_switches; + +/* SCP data structures and interface routines + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax maximum number of words for examine/deposit + sim_devices array of pointers to simulated devices + sim_consoles array of pointers to consoles (if more than one) + sim_stop_messages array of pointers to stop messages + sim_load binary loader +*/ + +char sim_name[] = "H316"; + +REG *sim_PC = &cpu_reg[0]; + +int32 sim_emax = 1; + +DEVICE *sim_devices[] = { &cpu_dev, + &ptr_dev, &ptp_dev, + &tty_dev, &lpt_dev, + &clk_dev, + NULL }; + +UNIT *sim_consoles = NULL; + +const char *sim_stop_messages[] = { + "Unknown error", + "Unimplemented instruction", + "Unimplemented I/O device", + "HALT instruction", + "Breakpoint", + "Indirect address loop" }; + +/* Binary loader + + Tbs. +*/ + +t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +{ +return SCPE_FMT; +} + +/* Symbol tables */ + +#define I_V_FL 16 /* flag start */ +#define I_M_FL 07 /* flag mask */ +#define I_V_NPN 0 /* no operand */ +#define I_V_MRF 1 /* mem ref */ +#define I_V_MRX 2 /* mem ref, no idx */ +#define I_V_IOT 3 /* I/O */ +#define I_V_SHF 4 /* shift */ +#define I_V_SK0 5 /* skip 0 */ +#define I_V_SK1 6 /* skip 1 */ +#define I_NPN (I_V_NPN << I_V_FL) +#define I_MRF (I_V_MRF << I_V_FL) +#define I_MRX (I_V_MRX << I_V_FL) +#define I_IOT (I_V_IOT << I_V_FL) +#define I_SHF (I_V_SHF << I_V_FL) +#define I_SK0 (I_V_SK0 << I_V_FL) +#define I_SK1 (I_V_SK1 << I_V_FL) + +static const int32 masks[] = { + 0177777, 0136000, 0176000, 0176000, + 0177700, 0177000, 0177000 }; + +static const char *opcode[] = { + "HLT", "SGL", "DBL", + "DXA", "EXA", "RMP", + "SCA", "INK", "NRM", + "IAB", "ENB", "INH", "ERM", + "CHS", "CRA", "SSP", + "RCB", "CSA", "CMA", + "TCA", "SSM", "SCB", + "CAR", "CAL", "ICL", + "AOA", "ACA", "ICR", "ICA", + "NOP", "SKP", "SSR", "SSS", + "JMP", "JMP*", + "LDA", "LDA*", "ANA", "ANA*", + "STA", "STA*", "ERA", "ERA*", + "ADD", "ADD*", "SUB", "SUB*", + "JST", "JST*", "CAS", "CAS*", + "IRS", "IRS*", "IMA", "IMA*", + "MPY", "MPY*", "DIV", "DIV*", + "STX", "STX*", "LDX", "LDX*", + "LRL", "LRS", "LRR", + "LGR", "ARS", "ARR", + "LLL", "LLS", "LLR", + "LGL", "ALS", "ALR", + "OCP", "SKS", "INA", "OTA", + "SMK", + "SPL", "SPN", "SLZ", /* encode only */ + "SZE", "SR1", "SR2", + "SR3", "SR4", "SRC", + "SMI", "SPS", "SLN", + "SNZ", "SS1", "SS2", + "SS3", "SS4", "SSC", + NULL, NULL, /* decode only */ + NULL }; + +static const int32 opc_val[] = { + 0000000+I_NPN, 0000005+I_NPN, 0000007+I_NPN, + 0000011+I_NPN, 0000013+I_NPN, 0000021+I_NPN, + 0000041+I_NPN, 0000043+I_NPN, 0000101+I_NPN, + 0000201+I_NPN, 0000401+I_NPN, 0001001+I_NPN, 0001401+I_NPN, + 0140024+I_NPN, 0140040+I_NPN, 0140100+I_NPN, + 0140200+I_NPN, 0140320+I_NPN, 0140401+I_NPN, + 0140407+I_NPN, 0140500+I_NPN, 0140600+I_NPN, + 0141044+I_NPN, 0141050+I_NPN, 0141140+I_NPN, + 0141206+I_NPN, 0141216+I_NPN, 0141240+I_NPN, 0141340+I_NPN, + 0101000+I_NPN, 0100000+I_NPN, 0100036+I_NPN, 0101036+I_NPN, + 0002000+I_MRF, 0102000+I_MRF, + 0004000+I_MRF, 0104000+I_MRF, 0006000+I_MRF, 0106000+I_MRF, + 0010000+I_MRF, 0110000+I_MRF, 0012000+I_MRF, 0112000+I_MRF, + 0014000+I_MRF, 0114000+I_MRF, 0016000+I_MRF, 0116000+I_MRF, + 0020000+I_MRF, 0120000+I_MRF, 0022000+I_MRF, 0122000+I_MRF, + 0024000+I_MRF, 0124000+I_MRF, 0026000+I_MRF, 0126000+I_MRF, + 0034000+I_MRF, 0134000+I_MRF, 0036000+I_MRF, 0136000+I_MRF, + 0032000+I_MRX, 0132000+I_MRX, 0072000+I_MRX, 0172000+I_MRX, + 0040000+I_SHF, 0040100+I_SHF, 0040200+I_SHF, + 0040400+I_SHF, 0040500+I_SHF, 0040600+I_SHF, + 0041000+I_SHF, 0041100+I_SHF, 0041200+I_SHF, + 0041400+I_SHF, 0041500+I_SHF, 0041600+I_SHF, + 0030000+I_IOT, 0070000+I_IOT, 0130000+I_IOT, 0170000+I_IOT, + 0170000+I_IOT, + 0100400+I_SK0, 0100200+I_SK0, 0100100+I_SK0, /* encode only */ + 0100040+I_SK0, 0100020+I_SK0, 0100010+I_SK0, + 0100004+I_SK0, 0100002+I_SK0, 0100001+I_SK0, + 0101400+I_SK1, 0101200+I_SK1, 0101100+I_SK1, + 0101040+I_SK1, 0101020+I_SK1, 0101010+I_SK1, + 0101004+I_SK1, 0101002+I_SK1, 0101001+I_SK1, + 0100000+I_SK0, 0101000+I_SK1, /* decode only */ + -1 }; + +/* Operate decode + + Inputs: + *of = output stream + inst = mask bits + class = instruction class code + sp = space needed? + Outputs: + status = space needed +*/ + +int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp) +{ +int32 i, j; + +for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ + j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ + if ((j == class) && (opc_val[i] & inst)) { /* same class? */ + inst = inst & ~opc_val[i]; /* mask bit set? */ + fprintf (of, (sp? " %s": "%s"), opcode[i]); + sp = 1; } } +return sp; +} + +/* Symbolic decode + + Inputs: + *of = output stream + addr = current PC + *val = pointer to data + *uptr = pointer to unit + sw = switches + Outputs: + return = status code +*/ + +#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) + +t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, + UNIT *uptr, int32 sw) +{ +int32 cflag, i, j, inst, disp; + +cflag = (uptr == NULL) || (uptr == &cpu_unit); +inst = val[0]; +if (sw & SWMASK ('A')) { /* ASCII? */ + if (inst > 0377) return SCPE_ARG; + fprintf (of, FMTASC (inst & 0177)); + return SCPE_OK; } +if (sw & SWMASK ('C')) { /* characters? */ + fprintf (of, FMTASC ((inst >> 8) & 0177)); + fprintf (of, FMTASC (inst & 0177)); + return SCPE_OK; } +if (!(sw & SWMASK ('M'))) return SCPE_ARG; + +/* Instruction decode */ + +for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ + j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ + if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */ + + switch (j) { /* case on class */ + case I_V_NPN: /* no operands */ + fprintf (of, "%s", opcode[i]); /* opcode */ + break; + case I_V_MRF: case I_V_MRX: /* mem ref */ + disp = inst & DISP; /* displacement */ + fprintf (of, "%s ", opcode[i]); /* opcode */ + if (inst & SC) { /* current sector? */ + if (cflag) fprintf (of, "%-o", (addr & PAGENO) | disp); + else fprintf (of, "C %-o", disp); } + else fprintf (of, "%-o", disp); /* sector zero */ + if ((j == I_V_MRF) && (inst & IDX)) fprintf (of, ",1"); + break; + case I_V_IOT: /* I/O */ + disp = inst & 01777; /* pulse+dev */ + fprintf (of, "%s %o", opcode[i], disp); + break; + case I_V_SHF: /* shift */ + disp = -inst & SHFMASK; /* shift count */ + fprintf (of, "%s %o", opcode[i], disp); + break; + case I_V_SK0: case I_V_SK1: /* skips */ + fprint_opr (of, inst & 0777, j, 0); /* print skips */ + break; } /* end case */ + return SCPE_OK; } /* end if */ + } /* end for */ +return SCPE_ARG; +} + +/* Symbolic input + + Inputs: + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches + Outputs: + status = error status +*/ + +t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) +{ +int32 cflag, d, i, j, k; +t_stat r; +char gbuf[CBUFSIZE]; + +cflag = (uptr == NULL) || (uptr == &cpu_unit); +while (isspace (*cptr)) cptr++; /* absorb spaces */ +if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + val[0] = (t_value) cptr[0] & 0177; + return SCPE_OK; } +if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* char string? */ + if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ + val[0] = (((t_value) cptr[0] & 0177) << 8) | + ((t_value) cptr[1] & 0177); + return SCPE_OK; } + +/* Instruction parse */ + +cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; +if (opcode[i] == NULL) return SCPE_ARG; +val[0] = opc_val[i] & DMASK; /* get value */ +j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ + +switch (j) { /* case on class */ +case I_V_NPN: /* no operand */ + break; +case I_V_IOT: /* IOT */ + cptr = get_glyph (cptr, gbuf, 0); /* get pulse+dev */ + d = get_uint (gbuf, 8, 01777, &r); + if (r != SCPE_OK) return SCPE_ARG; + val[0] = val[0] | d; + break; +case I_V_SHF: /* shift */ + cptr = get_glyph (cptr, gbuf, 0); /* get shift count */ + d = get_uint (gbuf, 8, SHFMASK, &r); + if (r != SCPE_OK) return SCPE_ARG; + val[0] = val[0] | (-d & SHFMASK); /* store 2's comp */ + break; +case I_V_MRF: case I_V_MRX: /* mem ref */ + cptr = get_glyph (cptr, gbuf, ','); /* get next field */ + if (k = (strcmp (gbuf, "C") == 0)) { /* C specified? */ + val[0] = val[0] | SC; + cptr = get_glyph (cptr, gbuf, 0); } + else if (k = (strcmp (gbuf, "Z") == 0)) { /* Z specified? */ + cptr = get_glyph (cptr, gbuf, ','); } + d = get_uint (gbuf, 8, X_AMASK, &r); /* construe as addr */ + if (r != SCPE_OK) return SCPE_ARG; + if (d <= DISP) val[0] = val[0] | d; /* fits? */ + else if (cflag && !k && (((addr ^ d) & PAGENO) == 0)) + val[0] = val[0] | (d & DISP) | SC; + else return SCPE_ARG; + if ((j == I_V_MRX) || (*cptr == 0)) break; /* indexed? */ + cptr = get_glyph (cptr, gbuf, 0); + d = get_uint (gbuf, 8, 1, &r); /* get tag */ + if (r != SCPE_OK) return SCPE_ARG; + if (d) val[0] = val[0] | IDX; /* or in index */ + break; +case I_V_SK0: case I_V_SK1: /* skips */ + for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; + cptr = get_glyph (cptr, gbuf, 0)) { + for (i = 0; (opcode[i] != NULL) && + (strcmp (opcode[i], gbuf) != 0) ; i++) ; + k = opc_val[i] & DMASK; + if ((opcode[i] == NULL) || (((k ^ val[0]) & 0177000) != 0)) + return SCPE_ARG; + val[0] = val[0] | k; } + break; } /* end case */ +if (*cptr != 0) return SCPE_ARG; /* junk at end? */ +return SCPE_OK; +} diff --git a/hp2100_cpu.c b/hp2100_cpu.c index 9659109f..2cdea58c 100644 --- a/hp2100_cpu.c +++ b/hp2100_cpu.c @@ -23,6 +23,7 @@ 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. + 10-Aug-01 RMS Removed register in declarations 26-Nov-00 RMS Fixed bug in dual device number routine 21-Nov-00 RMS Fixed bug in reset routine 15-Oct-00 RMS Added dynamic device number support @@ -456,7 +457,7 @@ struct hpdev infotab[] = { t_stat sim_instr (void) { extern int32 sim_interval; -register int32 IR, MA, absel, i, t, intrq, dmarq; +int32 IR, MA, absel, i, t, intrq, dmarq; int32 err_PC, M1, dev, iodata, op, sc, q, r, wc; t_stat reason; @@ -694,7 +695,7 @@ else if ((IR & NMROP) == IOT) { /* I/O? */ /* Extended instructions */ else if (cpu_unit.flags & (UNIT_2100 | UNIT_21MX)) { /* ext instr? */ - register int32 awc; + int32 awc; op = (IR >> 4) & 0277; /* get opcode */ if (ext_addr[op]) { /* extended mem ref? */ diff --git a/i1401_cpu.c b/i1401_cpu.c index ad7e37fe..0522cf5b 100644 --- a/i1401_cpu.c +++ b/i1401_cpu.c @@ -23,6 +23,7 @@ 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. + 10-Aug-01 RMS Removed register in declarations 07-Dec-00 RMS Fixed bugs found by Charles Owen -- 4,7 char NOPs are legal -- 1 char B is chained BCE @@ -364,7 +365,7 @@ char bcd_to_ascii[64] = { t_stat sim_instr (void) { extern int32 sim_interval; -register int32 IS, D, ilnt, flags; +int32 IS, D, ilnt, flags; int32 op, xa, t, wm, dev, unit; int32 a, b, i, bsave, carry; int32 qzero, qawm, qbody, qsign, qdollar, qaster, qdecimal; diff --git a/i1401_sys.c b/i1401_sys.c index dec2b080..2f707f10 100644 --- a/i1401_sys.c +++ b/i1401_sys.c @@ -23,6 +23,7 @@ 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. + 13-Jul-01 RMS Fixed bug in symbolic output (found by Peter Schorn) 27-May-01 RMS Added multiconsole support 14-Mar-01 RMS Revised load/dump interface (again) 30-Oct-00 RMS Added support for examine to file @@ -197,14 +198,15 @@ if (sw & SWMASK ('S')) { /* string? */ if ((sw & SWMASK ('M')) == 0) return SCPE_ARG; if ((val[0] & WM) == 0) return STOP_NOWM; /* WM under op? */ -flags = op_table[val[0] & CHAR]; /* get flags */ +op = val[0]& CHAR; /* isolate op */ +flags = op_table[op]; /* get flags */ for (ilnt = 1; ilnt < sim_emax; ilnt++) if (val[ilnt] & WM) break; if (flags & HNOP) ilnt = 1; /* halt, nop? */ else if ((flags & NOWM) && (ilnt > 7)) ilnt = 7; /* cs, swm? */ else if ((op == OP_B) && (ilnt > 4) && (val[4] == BCD_BLANK)) ilnt = 4; else if (ilnt > 8) ilnt = 8; /* cap length */ if ((flags & len_table[ilnt]) == 0) return STOP_INVL; /* legal length? */ -fprintf (of, "%s",opcode[val[0] & CHAR]); /* print opcode */ +fprintf (of, "%s",opcode[op]); /* print opcode */ if (ilnt > 2) { /* A address? */ if ((flags & IO) && (val[1] == BCD_PERCNT)) fprintf (of, " %%%c%c", bcd_to_ascii[val[2]], bcd_to_ascii[val[3]]); diff --git a/id4_cpu.c b/id4_cpu.c index ec4d01b8..0aabf92a 100644 --- a/id4_cpu.c +++ b/id4_cpu.c @@ -23,6 +23,7 @@ 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. + 10-Aug-01 RMS Removed register in declarations 07-Oct-00 RMS Overhauled I/O subsystem 14-Apr-99 RMS Changed t_addr to unsigned @@ -243,10 +244,10 @@ DEVICE cpu_dev = { t_stat sim_instr (void) { extern int32 sim_interval; -register int32 dev, i, j, r, t; -register int32 PC, OP, R1, R2, EA, CC; +int32 dev, i, j, r, t; +int32 PC, OP, R1, R2, EA, CC; int32 inc, lim; -register t_stat reason; +t_stat reason; /* Restore register state */ @@ -638,7 +639,7 @@ case 0x97: /* RBR */ case 0xDF: /* AI */ case 0x9F: /* AIR */ for (i = t = 0; i < INTSZ; i++) { /* loop thru array */ - register unsigned int32 temp; + uint32 temp; if (temp = int_req[i] & int_enb[i]) { /* loop thru word */ for (j = 0; j < 32; j++) { if (temp & INT_V(j)) break; diff --git a/id4_sys.c b/id4_sys.c index fd6ed257..257bac16 100644 --- a/id4_sys.c +++ b/id4_sys.c @@ -23,6 +23,7 @@ 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. + 17-Jul-01 RMS Fixed warning from VC++ 6.0 27-May-01 RMS Added multiconsole support 14-Mar-01 RMS Revised load/dump interface (again) 30-Oct-00 RMS Added support for examine to file @@ -302,7 +303,7 @@ case I_V_R: /* register */ if ((r2 = get_reg (gbuf, 0, regflt)) < 0) return SCPE_ARG; val[0] = val[0] | r2; if (*cptr != 0) return SCPE_ARG; - return SCPE_OK; + break; case I_V_FX: /* float-memory */ regflt = TRUE; /* fall thru */ @@ -319,4 +320,5 @@ case I_V_X: /* memory */ if ((r2 = get_reg (tptr + 1, ')', FALSE)) < 0) return SCPE_ARG; val[0] = val[0] | r2; return -1; } /* end case */ +return SCPE_OK; } diff --git a/nova_clk.c b/nova_clk.c index 324d6d0b..1db97245 100644 --- a/nova_clk.c +++ b/nova_clk.c @@ -25,6 +25,7 @@ clk real-time clock + 17-Mar-01 RMS Moved function prototype 05-Mar-01 RMS Added clock calibration 24-Sep-97 RMS Fixed bug in unit service (found by Charles Owen) */ @@ -37,8 +38,6 @@ int32 clk_time[4] = { 16000, 100000, 10000, 1000 }; /* freq table */ int32 clk_tps[4] = { 60, 10, 100, 1000 }; /* ticks per sec */ t_stat clk_svc (UNIT *uptr); t_stat clk_reset (DEVICE *dptr); -extern int32 sim_rtc_init (int32 time); -extern int32 sim_rtc_calb (int32 tps); /* CLK data structures diff --git a/nova_cpu.c b/nova_cpu.c index c5ff5874..76154d01 100644 --- a/nova_cpu.c +++ b/nova_cpu.c @@ -25,6 +25,8 @@ cpu Nova central processor + 10-Aug-01 RMS Removed register in declarations + 17-Jul-01 RMS Moved function prototype 26-Apr-01 RMS Added device enable/disable support 05-Mar-01 RMS Added clock calibration 22-Dec-00 RMS Added Bruce Ray's second terminal @@ -365,11 +367,10 @@ DEVICE cpu_dev = { t_stat sim_instr (void) { extern int32 sim_interval; -register int32 PC, IR, i; -register t_stat reason; +int32 PC, IR, i; +t_stat reason; void mask_out (int32 mask); extern int32 clk_sel, clk_time[4]; -extern int32 sim_rtc_init (int32 time); /* Restore register state */ @@ -386,7 +387,7 @@ if (sim_interval <= 0) { /* check clock queue */ if (reason = sim_process_event ()) break; } if (int_req > INT_PENDING) { /* interrupt? */ - register int32 MA, indf; + int32 MA, indf; int_req = int_req & ~INT_ION; old_PC = M[INT_SAV] = PC; if (int_req & INT_STK) { /* stack overflow? */ @@ -415,7 +416,7 @@ sim_interval = sim_interval - 1; /* Operate instruction */ if (IR & I_OPR) { /* operate? */ - register int32 src, srcAC, dstAC; + int32 src, srcAC, dstAC; srcAC = I_GETSRC (IR); /* get reg decodes */ dstAC = I_GETDST (IR); switch (I_GETCRY (IR)) { /* decode carry */ @@ -474,7 +475,7 @@ if (IR & I_OPR) { /* operate? */ switch (I_GETSKP (IR)) { /* decode skip */ case 0: /* nop */ if ((IR & I_NLD) && (cpu_unit.flags & UNIT_STK)) { - register int32 indf, MA; /* Nova 3 or 4 trap */ + int32 indf, MA; /* Nova 3 or 4 trap */ old_PC = M[TRP_SAV] = (PC - 1) & AMASK; MA = TRP_JMP; /* jmp @47 */ for (i = 0, indf = 1; indf && (i < ind_max); i++) { @@ -514,7 +515,7 @@ if (IR & I_OPR) { /* operate? */ /* Memory reference instructions */ else if (IR < 060000) { /* mem ref? */ - register int32 src, MA, indf; + int32 src, MA, indf; MA = I_GETDISP (IR); /* get disp */ switch (I_GETMODE (IR)) { /* decode mode */ case 0: /* page zero */ @@ -587,7 +588,7 @@ else if (IR < 060000) { /* mem ref? */ /* IOT instruction */ else { /* IOT */ - register int32 dstAC, pulse, code, device, iodata; + int32 dstAC, pulse, code, device, iodata; dstAC = I_GETDST (IR); /* decode fields */ code = I_GETIOT (IR); pulse = I_GETPULSE (IR); @@ -655,7 +656,7 @@ else { /* IOT */ break; case ioDOB: /* store byte */ if (cpu_unit.flags & UNIT_BYT) { - register int32 MA, val; + int32 MA, val; MA = AC[pulse] >> 1; val = AC[dstAC] & 0377; if (MEM_ADDR_OK (MA)) M[MA] = (AC[pulse] & 1)? @@ -716,7 +717,7 @@ else { /* IOT */ break; case ioDOC: if ((dstAC == 2) && (cpu_unit.flags & UNIT_MDV)) { - register unsigned int32 mddata, uAC0, uAC1, uAC2; + uint32 mddata, uAC0, uAC1, uAC2; uAC0 = (unsigned int32) AC[0]; uAC1 = (unsigned int32) AC[1]; uAC2 = (unsigned int32) AC[2]; @@ -732,7 +733,7 @@ else { /* IOT */ AC[1] = mddata / uAC2; AC[0] = mddata % uAC2; } } } if ((dstAC == 3) && (cpu_unit.flags & UNIT_BYT)) { - register int32 mddata; + int32 mddata; if (pulse == iopC) { /* muls */ mddata = (SEXT (AC[1]) * SEXT (AC[2])) + SEXT (AC[0]); diff --git a/nova_dsk.c b/nova_dsk.c index 55681c9a..3f81042e 100644 --- a/nova_dsk.c +++ b/nova_dsk.c @@ -25,6 +25,7 @@ dsk fixed head disk + 23-Aug-01 RMS Fixed bug in write watermarking 26-Apr-01 RMS Added device enable/disable support 10-Dec-00 RMS Added Eclipse support 15-Oct-00 RMS Editorial changes @@ -159,7 +160,7 @@ if ((pulse == iopP) && ((dsk_wlk >> GET_DISK (dsk_da)) & 1)) { /* wrt lock? */ return rval; } if (pulse & 1) { /* read or write? */ - if (((t_addr) (dsk_da * DSK_NUMWD)) >= dsk_unit.capac) { /* invalid sector? */ + if (((t_addr) (dsk_da * DSK_NUMWD)) >= dsk_unit.capac) { /* inv sev? */ dev_done = dev_done | INT_DSK; /* set done */ int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */ @@ -197,6 +198,8 @@ if (uptr -> FUNC == iopP) { /* write? */ for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */ pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */ *(((int16 *) uptr -> filebuf) + da + i) = M[pa]; } + if (((t_addr) (da + i)) >= uptr -> hwmark) /* past end? */ + uptr -> hwmark = da + i + 1; /* upd hwmark */ dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK; } dsk_stat = 0; /* set status */ diff --git a/pdp10_cpu.c b/pdp10_cpu.c index d799ceb7..67deee66 100644 --- a/pdp10_cpu.c +++ b/pdp10_cpu.c @@ -25,6 +25,8 @@ cpu KS10 central processor + 10-Aug-01 RMS Removed register in declarations + 17-Jul-01 RMS Moved function prototype 19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug 29-Apr-01 RMS Fixed modifier naming conflict Fixed XCTR/XCTRI, UMOVE/UMOVEM, BLTUB/BLTBU for ITS @@ -509,7 +511,6 @@ extern t_bool lpmr (a10 ea, int32 prv); extern int32 pi_ub_vec (int32 lvl, int32 *uba); extern UNIT tim_unit; -extern int32 sim_rtc_init (int32 time); d10 adjsp (d10 val, a10 ea); void ibp (a10 ea, int32 pflgs); @@ -565,9 +566,9 @@ static t_stat jrst_tab[16] = { JRST_U, JRST_U, JRST_U, 0, JRST_E, JRST_U, JRST_E, JRST_E, JRST_UIO, 0, JRST_UIO, 0, JRST_E, JRST_U, 0, 0 }; -register d10 inst; -register a10 PC; -register int32 pflgs; +d10 inst; +a10 PC; +int32 pflgs; int32 pager_flags = 0; /* pager: trap flags */ t_bool pager_pi = FALSE; /* pager: in pi seq */ int abortval = 0; /* abort value */ @@ -602,12 +603,12 @@ if ((abortval > 0) || pager_pi) { /* stop or pi err? */ /* Page fail - checked against KS10 ucode */ else if (abortval == PAGE_FAIL) { /* page fail */ - register d10 mb; + d10 mb; if (rlog) xtcln (rlog); /* clean up extend */ rlog = 0; /* clear log */ if (pflgs & TRAP_CYCLE) flags = pager_flags; /* trap? get flags */ if (!T20 || ITS) { /* TOPS-10 or ITS */ - register a10 ea; + a10 ea; if (ITS) ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3); else ea = upta + UPT_T10_PAG; WriteP (ea, pager_word); /* write page fail wd */ @@ -625,10 +626,9 @@ else PC = pager_PC; /* intr, restore PC */ /* Main instruction fetch/decode loop: check clock queue, intr, trap, bkpt */ for ( ;; ) { /* loop until ABORT */ -register int32 op, ac, i, st, xr, xct_cnt; -register a10 ea; -register d10 mb, indrct; -d10 rs[2]; +int32 op, ac, i, st, xr, xct_cnt; +a10 ea; +d10 mb, indrct, rs[2]; pager_PC = PC; /* update pager PC */ pflgs = 0; /* not in PXCT or trap */ @@ -1548,8 +1548,8 @@ return; a10 calc_ea (d10 inst, int32 prv) { -register int32 i, ea, xr; -register d10 indrct; +int32 i, ea, xr; +d10 indrct; for (indrct = inst, i = 0; i < ind_max; i++) { ea = GET_ADDR (indrct); @@ -1571,8 +1571,8 @@ return ea; a10 calc_ioea (d10 inst, int32 pflgs) { -register int32 xr; -register a10 ea; +int32 xr; +a10 ea; xr = GET_XR (inst); ea = GET_ADDR (inst); @@ -1591,8 +1591,8 @@ return ea; d10 calc_jrstfea (d10 inst, int32 pflgs) { -register int32 i, xr; -register d10 mb; +int32 i, xr; +d10 mb; for (i = 0; i < ind_max; i++) { mb = inst; @@ -1610,8 +1610,8 @@ return (mb & DMASK); void ibp (a10 ea, int32 pflgs) { -register int32 p, s; -register d10 bp; +int32 p, s; +d10 bp; bp = ReadM (ea, MM_OPND); /* get byte ptr */ p = GET_P (bp); /* get P and S */ @@ -1629,9 +1629,9 @@ return; d10 ldb (a10 ea, int32 pflgs) { -register a10 ba; -register int32 p, s; -register d10 bp, wd; +a10 ba; +int32 p, s; +d10 bp, wd; bp = Read (ea, MM_OPND); /* get byte ptr */ p = GET_P (bp); /* get P and S */ @@ -1647,9 +1647,9 @@ return wd; void dpb (d10 val, a10 ea, int32 pflgs) { -register a10 ba; -register int32 p, s; -register d10 bp, wd, mask; +a10 ba; +int32 p, s; +d10 bp, wd, mask; bp = Read (ea, MM_OPND); /* get byte ptr */ p = GET_P (bp); /* get P and S */ diff --git a/pdp10_dz.c b/pdp10_dz.c new file mode 100644 index 00000000..d4f43ed0 --- /dev/null +++ b/pdp10_dz.c @@ -0,0 +1,190 @@ +/* pdp10_dz_stub.c: DZ11 terminal multiplexor simulator stub + + Copyright (c) 2001, Robert M Supnik + + 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. + + Except as contained in this notice, the name of Robert M Supnik 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. + + dz DZ11 terminal multiplexor (stub) + + This version of the DZ11 is a stub to allow operating systems to play + with the device registers. It is required for ITS, and not harmful to + TOPS-10 or TOPS-20. +*/ + +#include "pdp10_defs.h" + +#define DZ_LINES 8 /* lines per DZ11 */ +#define DZ_LMASK (DZ_LINES - 1) +#define DZ_SILO_ALM 16 /* silo alarm level */ +#define MAXBUF 128 /* buffer size */ + +/* DZCSR - 160100 - control/status register */ + +#define CSR_MAINT 0000010 /* maint - NI */ +#define CSR_CLR 0000020 /* clear */ +#define CSR_MSE 0000040 /* master scan enb */ +#define CSR_RIE 0000100 /* rcv int enb */ +#define CSR_RDONE 0000200 /* rcv done - RO */ +#define CSR_V_TLINE 8 /* xmit line - RO */ +#define CSR_TLINE (DZ_LMASK << CSR_V_TLINE) +#define CSR_SAE 0010000 /* silo alm enb */ +#define CSR_SA 0020000 /* silo alm - RO */ +#define CSR_TIE 0040000 /* xmit int enb */ +#define CSR_TRDY 0100000 /* xmit rdy - RO */ +#define CSR_RW (CSR_MSE | CSR_RIE | CSR_SAE | CSR_TIE) +#define CSR_MBZ (0004003 | CSR_CLR | CSR_MAINT) + +#define CSR_GETTL(x) (((x) >> CSR_V_TLINE) & DZ_LMASK) +#define CSR_PUTTL(x,y) x = ((x) & ~CSR_TLINE) | (((y) & DZ_LMASK) << CSR_V_TLINE) + +/* DZRBUF - 160102 - receive buffer, read only */ + +#define RBUF_CHAR 0000377 /* rcv char */ +#define RBUF_V_RLINE 8 /* rcv line */ +#define RBUF_PARE 0010000 /* parity err - NI */ +#define RBUF_FRME 0020000 /* frame err - NI */ +#define RBUF_OVRE 0040000 /* overrun err - NI */ +#define RBUF_VALID 0100000 /* rcv valid */ +#define RBUF_MBZ 0004000 + +/* DZLPR - 160102 - line parameter register, write only, word access only */ + +#define LPR_V_LINE 0 /* line */ +#define LPR_LPAR 0007770 /* line pars - NI */ +#define LPR_RCVE 0010000 /* receive enb */ +#define LPR_GETLN(x) (((x) >> LPR_V_LINE) & DZ_LMASK) + +/* DZTCR - 160104 - transmission control register */ + +#define TCR_V_XMTE 0 /* xmit enables */ +#define TCR_V_DTR 7 /* DTRs */ + +/* DZMSR - 160106 - modem status register, read only */ + +#define MSR_V_RI 0 /* ring indicators */ +#define MSR_V_CD 7 /* carrier detect */ + +/* DZTDR - 160106 - transmit data, write only */ + +#define TDR_CHAR 0000377 /* xmit char */ +#define TDR_V_TBR 7 /* xmit break - NI */ + +extern int32 int_req, dev_enb; +int32 dz_csr = 0; /* csr */ +int32 dz_rbuf = 0; /* rcv buffer */ +int32 dz_lpr = 0; /* line param */ +int32 dz_tcr = 0; /* xmit control */ +int32 dz_msr = 0; /* modem status */ +int32 dz_tdr = 0; /* xmit data */ +int32 dz_mctl = 0; /* modem ctrl enab */ +int32 dz_sa_enb = 1; /* silo alarm enabled */ + +t_stat dz_reset (DEVICE *dptr); +t_stat dz_clear (t_bool flag); + +/* DZ data structures + + dz_dev DZ device descriptor + dz_unit DZ unit list + dz_reg DZ register list +*/ + +UNIT dz_unit = { UDATA (NULL, 0, 0) }; + +REG dz_reg[] = { + { ORDATA (CSR, dz_csr, 16) }, + { ORDATA (RBUF, dz_rbuf, 16) }, + { ORDATA (LPR, dz_lpr, 16) }, + { ORDATA (TCR, dz_tcr, 16) }, + { ORDATA (MSR, dz_msr, 16) }, + { ORDATA (TDR, dz_tdr, 16) }, + { FLDATA (MDMCTL, dz_mctl, 0) }, + { FLDATA (SAENB, dz_sa_enb, 0) }, + { FLDATA (*DEVENB, dev_enb, INT_V_DZ0RX), REG_HRO }, + { NULL } }; + +DEVICE dz_dev = { + "DZ", &dz_unit, dz_reg, NULL, + 1, 8, 13, 1, 8, 8, + NULL, NULL, &dz_reset, + NULL, NULL, NULL }; + +/* IO dispatch routines, I/O addresses 17760100 - 17760107 */ + +t_stat dz0_rd (int32 *data, int32 PA, int32 access) +{ +switch ((PA >> 1) & 03) { /* case on PA<2:1> */ +case 00: /* CSR */ + *data = dz_csr = dz_csr & ~CSR_MBZ; + break; +case 01: /* RBUF */ + dz_csr = dz_csr & ~CSR_SA; /* clr silo alarm */ + *data = dz_rbuf; + break; +case 02: /* TCR */ + *data = dz_tcr; + break; +case 03: /* MSR */ + *data = dz_msr; + break; } +return SCPE_OK; +} + +t_stat dz0_wr (int32 data, int32 PA, int32 access) +{ +switch ((PA >> 1) & 03) { /* case on PA<2:1> */ +case 00: /* CSR */ + if (access == WRITEB) data = (PA & 1)? + (dz_csr & 0377) | (data << 8): (dz_csr & ~0377) | data; + dz_csr = (dz_csr & ~CSR_RW) | (data & CSR_RW); + break; +case 01: /* LPR */ + dz_lpr = data; + break; +case 02: /* TCR */ + if (access == WRITEB) data = (PA & 1)? + (dz_tcr & 0377) | (data << 8): (dz_tcr & ~0377) | data; + dz_tcr = data; + break; +case 03: /* TDR */ + if (PA & 1) { /* odd byte? */ + dz_tdr = (dz_tdr & 0377) | (data << 8); /* just save */ + break; } + dz_tdr = data; + break; } +return SCPE_OK; +} + +/* Device reset */ + +t_stat dz_reset (DEVICE *dptr) +{ +dz_csr = 0; /* clear CSR */ +dz_rbuf = 0; /* silo empty */ +dz_lpr = 0; /* no params */ +dz_tcr = 0; /* clr all */ +dz_tdr = 0; +dz_sa_enb = 1; +int_req = int_req & ~(INT_DZ0RX | INT_DZ0TX); /* clear int */ +sim_cancel (&dz_unit); /* no polling */ +return SCPE_OK; +} diff --git a/pdp10_ksio.c b/pdp10_ksio.c index c38ff0d2..a15e296b 100644 --- a/pdp10_ksio.c +++ b/pdp10_ksio.c @@ -25,7 +25,9 @@ uba Unibus adapters - 1-Jun-01 RMS Updated DZ11 vectors + 25-Aug-01 RMS Enabled DZ11 + 21-Aug-01 RMS Updated DZ11 disable + 01-Jun-01 RMS Updated DZ11 vectors 12-May-01 RMS Fixed typo The KS10 uses the PDP-11 Unibus for its I/O, via adapters. While @@ -75,7 +77,7 @@ int32 ubcs[UBANUM] = { 0 }; /* status registers */ int32 ubmap[UBANUM][UMAP_MEMSIZE] = { 0 }; /* Unibus maps */ int32 int_req = 0; /* interrupt requests */ -int32 dev_enb = -1 & ~(INT_PTR | INT_PTP); /* device enables */ +int32 dev_enb = -1 & ~(INT_PTR | INT_PTP | INT_DZ0RX); /* device enables */ /* Map IO controller numbers to Unibus adapters: -1 = non-existent */ @@ -162,7 +164,7 @@ struct iolink iotable[] = { &rp_rd, &rp_wr }, /* disk */ { IO_UBA3+IO_TMBASE, IO_UBA3+IO_TMBASE+033, 0, &tu_rd, &tu_wr }, /* mag tape */ -/* { IO_UBA3+IO_DZBASE, IO_UBA3+IO_DZBASE+07, INT_DZ, + { IO_UBA3+IO_DZBASE, IO_UBA3+IO_DZBASE+07, INT_DZ0RX, &dz0_rd, &dz0_wr }, /* terminal mux */ { IO_UBA3+IO_LPBASE, IO_UBA3+IO_LPBASE+017, 0, &lp20_rd, &lp20_wr }, /* line printer */ diff --git a/pdp10_mdfp.c b/pdp10_mdfp.c index b7c6865f..f90c3f86 100644 --- a/pdp10_mdfp.c +++ b/pdp10_mdfp.c @@ -90,6 +90,8 @@ The KL10 added extended precision (11-bit exponent) floating point format (so-called G floating). These instructions were not implemented in the KS10 and are treated as MUUO's. + + 10-Aug-01 RMS Removed register in declarations */ #include "pdp10_defs.h" @@ -195,9 +197,9 @@ return TRUE; void mul (d10 s1, d10 s2, d10 *rs) { -register uint64 a = ABS (s1); -register uint64 b = ABS (s2); -register uint64 t, u, r; +uint64 a = ABS (s1); +uint64 b = ABS (s2); +uint64 t, u, r; if ((a == 0) || (b == 0)) { /* operand = 0? */ rs[0] = rs[1] = 0; /* result 0 */ @@ -228,8 +230,8 @@ return; t_bool divi (int32 ac, d10 b, d10 *rs) { -register int32 p1 = ADDAC (ac, 1); -register d10 dvr = ABS (b); /* make divr positive */ +int32 p1 = ADDAC (ac, 1); +d10 dvr = ABS (b); /* make divr positive */ int64 t; int32 i; d10 dvd[2]; @@ -356,7 +358,7 @@ return; d10 fad (d10 op1, d10 op2, t_bool rnd, int32 inv) { -register int32 ediff; +int32 ediff; UFP a, b, t; if (inv) op2 = NEG (op2); /* subtract? -b */ @@ -500,7 +502,7 @@ return; void dfad (int32 ac, d10 *rs, int32 inv) { int32 p1 = ADDAC (ac, 1); -register int32 ediff; +int32 ediff; UFP a, b, t; if (inv) { DMOVN (rs); } /* subtract? -b */ diff --git a/pdp10_pag.c b/pdp10_pag.c index 847a043f..dfac99d4 100644 --- a/pdp10_pag.c +++ b/pdp10_pag.c @@ -25,6 +25,8 @@ pag KS10 pager + 21-Aug-01 RMS Fixed bug in ITS paging (found by Miriam Lennox) + Removed register from declarations 19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug 03-May-01 RMS Fixed bug in indirect page table pointer processing 29-Apr-01 RMS Added CLRCSH for ITS, fixed LPMR @@ -155,7 +157,7 @@ DEVICE pag_dev = { d10 Read (a10 ea, int32 prv) { -register int32 pa, vpn, xpte; +int32 pa, vpn, xpte; if (ea < AC_NUM) return (prv? ac_prv[ea]: ac_cur[ea]); /* AC request */ vpn = PAG_GETVPN (ea); /* get page num */ @@ -168,7 +170,7 @@ return M[pa]; /* return data */ d10 ReadM (a10 ea, int32 prv) { -register int32 pa, vpn, xpte; +int32 pa, vpn, xpte; if (ea < AC_NUM) return (prv? ac_prv[ea]: ac_cur[ea]); /* AC request */ vpn = PAG_GETVPN (ea); /* get page num */ @@ -181,7 +183,7 @@ return M[pa]; /* return data */ d10 ReadE (a10 ea) { -register int32 pa, vpn, xpte; +int32 pa, vpn, xpte; if (ea < AC_NUM) return AC(ea); /* AC? use current */ if (!PAGING) return M[ea]; /* phys? no mapping */ @@ -202,7 +204,7 @@ return M[ea]; /* return data */ void Write (a10 ea, d10 val, int32 prv) { -register int32 pa, vpn, xpte; +int32 pa, vpn, xpte; if (ea < AC_NUM) { /* AC request */ if (prv) ac_prv[ea] = val; /* write AC */ @@ -218,7 +220,7 @@ return; void WriteE (a10 ea, d10 val) { -register int32 pa, vpn, xpte; +int32 pa, vpn, xpte; if (ea < AC_NUM) AC(ea) = val; /* AC? use current */ else if (!PAGING) M[ea] = val; /* phys? no mapping */ @@ -241,7 +243,7 @@ return; t_bool AccViol (a10 ea, int32 prv, int32 mode) { -register int32 vpn, xpte; +int32 vpn, xpte; if (ea < AC_NUM) return FALSE; /* AC request */ vpn = PAG_GETVPN (ea); /* get page num */ @@ -303,7 +305,7 @@ if (ITS) { /* ITS paging */ vpn = ITS_GETVPN (ea); /* get ITS pagno */ if (tbl == uptbl) ptead = ((ea & RSIGN)? dbr2: dbr1) + ((vpn >> 1) & 077); - else ptead = ((ea & RSIGN)? dbr4: dbr3) + ((vpn >> 1) & 077); + else ptead = ((ea & RSIGN)? dbr3: dbr4) + ((vpn >> 1) & 077); ptewd = ReadP (ptead); /* get PTE pair */ pte = (int32) ((ptewd >> ((vpn & 1)? 0: 18)) & RMASK); acc = ITS_GETACC (pte); /* get access */ diff --git a/pdp10_rp.c b/pdp10_rp.c index a34b4bc2..8c5c3c03 100644 --- a/pdp10_rp.c +++ b/pdp10_rp.c @@ -25,6 +25,9 @@ rp RH/RP/RM moving head disks + 23-Aug-01 RMS Added read/write header stubs for ITS + (found by Mirian Crzig Lennox) + 13-Jul-01 RMS Changed fread call to fxread (found by Peter Schorn) 14-May-01 RMS Added check for unattached drive The "Massbus style" disks consisted of several different large @@ -88,7 +91,9 @@ #define FNC_SEARCH 014 /* search */ #define FNC_WCHK 024 /* write check */ #define FNC_WRITE 030 /* write */ +#define FNC_WRITEH 031 /* write w/ headers */ #define FNC_READ 034 /* read */ +#define FNC_READH 035 /* read w/ headers */ #define CS1_IE CSR_IE /* int enable */ #define CS1_DONE CSR_DONE /* ready */ #define CS1_V_UAE 8 /* Unibus addr ext */ @@ -711,9 +716,11 @@ case FNC_SEARCH: /* search */ uptr -> CYL = dc; /* save cylinder */ return; +case FNC_WRITEH: /* write headers */ case FNC_WRITE: /* write */ case FNC_WCHK: /* write check */ case FNC_READ: /* read */ +case FNC_READH: /* read headers */ rpcs2 = rpcs2 & ~CS2_ERR; /* clear errors */ rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE); if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ @@ -790,6 +797,7 @@ case FNC_WRITE: /* write */ break; } case FNC_WCHK: /* write check */ case FNC_READ: /* read */ +case FNC_READH: /* read headers */ ba = GET_UAE (rpcs1) | rpba; /* get byte addr */ wc10 = (0200000 - rpwc) >> 1; /* get PDP-10 wc */ da = GET_DA (rpdc, rpda, dtype) * RP_NUMWD; /* get disk addr */ @@ -822,7 +830,7 @@ case FNC_READ: /* read */ err = ferror (uptr -> fileref); } /* end if */ else { /* read, wchk */ - awc10 = fread (dbuf, sizeof (d10), wc10, uptr -> fileref); + awc10 = fxread (dbuf, sizeof (d10), wc10, uptr -> fileref); err = ferror (uptr -> fileref); for ( ; awc10 < wc10; awc10++) dbuf[awc10] = 0; for (twc10 = 0; twc10 < wc10; twc10++) { @@ -862,6 +870,7 @@ case FNC_READ: /* read */ perror ("RP I/O error"); clearerr (uptr -> fileref); return SCPE_IOERR; } +case FNC_WRITEH: /* write headers stub */ update_rpcs (CS1_DONE, drv); /* set done */ break; } /* end case func */ return SCPE_OK; diff --git a/pdp10_sys.c b/pdp10_sys.c index 9141bfe2..eca757dc 100644 --- a/pdp10_sys.c +++ b/pdp10_sys.c @@ -23,6 +23,7 @@ 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. + 25-Aug-01 RMS Enabled DZ11 27-May-01 RMS Added multiconsole support 29-Apr-01 RMS Fixed format for RDPCST, WRPCST Added CLRCSH for ITS @@ -38,7 +39,7 @@ extern DEVICE cpu_dev, pag_dev; extern DEVICE tim_dev, fe_dev, uba_dev; extern DEVICE ptr_dev, ptp_dev; extern DEVICE rp_dev, tu_dev; -/* extern DEVICE dz_dev; */ +extern DEVICE dz_dev; extern DEVICE lp20_dev; extern UNIT cpu_unit; extern REG cpu_reg[]; @@ -64,11 +65,16 @@ int32 sim_emax = 1; DEVICE *sim_devices[] = { &cpu_dev, - &pag_dev, &tim_dev, - &fe_dev, &uba_dev, - &ptr_dev, &ptp_dev, - &lp20_dev, /* &dz_dev, */ - &rp_dev, &tu_dev, + &pag_dev, + &tim_dev, + &fe_dev, + &uba_dev, + &ptr_dev, + &ptp_dev, + &lp20_dev, + &dz_dev, + &rp_dev, + &tu_dev, NULL }; UNIT *sim_consoles = NULL; diff --git a/pdp10_tim.c b/pdp10_tim.c index 25a8f149..a6c50eef 100644 --- a/pdp10_tim.c +++ b/pdp10_tim.c @@ -22,6 +22,11 @@ Except as contained in this notice, the name of Robert M Supnik 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. + + tim timer subsystem + + 17-Jul-01 RMS Moved function prototype + 04-Jul-01 RMS Added DZ11 support */ #include "pdp10_defs.h" @@ -29,8 +34,10 @@ #define TIM_N_HWRE 12 /* hwre bits */ #define TIM_HWRE 0000000010000 /* hwre incr */ +#define TIM_DELAY 500 +#define TIM_TPS 1001 /* ticks per sec */ +#define DZ_MULT (TIM_TPS / 60) /* DZ poll multiplier */ #define TB_MASK 037777777777777777777; /* 71 - 12 bits */ -#define TPS 1001 /* ticks per sec */ #define UNIT_V_Y2K (UNIT_V_UF) /* Y2K compliant OS */ #define UNIT_Y2K (1u << UNIT_V_Y2K) @@ -43,6 +50,7 @@ d10 ttg = 0; /* time to go */ d10 period = 0; /* period */ d10 quant = 0; /* ITS quantum */ int32 diagflg = 0; /* diagnostics? */ +int32 dz_poll = TIM_DELAY * DZ_MULT; /* DZ11 poll */ t_stat tim_svc (UNIT *uptr); t_stat tim_reset (DEVICE *dptr); @@ -51,7 +59,6 @@ extern d10 ReadM (a10 ea, int32 prv); extern void Write (a10 ea, d10 val, int32 prv); extern void WriteP (a10 ea, d10 val); extern int32 pi_eval (void); -extern sim_rtc_calb (int32 tps); /* TIM data structures @@ -60,7 +67,7 @@ extern sim_rtc_calb (int32 tps); tim_reg TIM register list */ -UNIT tim_unit = { UDATA (&tim_svc, 0, 0), 500 }; +UNIT tim_unit = { UDATA (&tim_svc, 0, 0), TIM_DELAY }; REG tim_reg[] = { { ORDATA (TIMEBASE, timebase, 71 - TIM_N_HWRE) }, @@ -121,8 +128,11 @@ return FALSE; t_stat tim_svc (UNIT *uptr) { -sim_activate (&tim_unit, /* reactivate unit */ - (diagflg? tim_unit.wait: sim_rtc_calb (TPS))); +int32 t; + +t = diagflg? tim_unit.wait: sim_rtc_calb (TIM_TPS); /* calibrate clock */ +sim_activate (&tim_unit, t); /* reactivate unit */ +dz_poll = t * DZ_MULT; /* set DZ poll */ timebase = (timebase + 1) & TB_MASK; /* increment timebase */ ttg = ttg - TIM_HWRE; /* decrement timer */ if (ttg <= 0) { /* timeout? */ @@ -142,6 +152,7 @@ t_stat tim_reset (DEVICE *dptr) period = ttg = 0; /* clear timer */ apr_flg = apr_flg & ~APRF_TIM; /* clear interrupt */ sim_activate (&tim_unit, tim_unit.wait); /* activate unit */ +dz_poll = tim_unit.wait * DZ_MULT; /* set DZ poll */ return SCPE_OK; } diff --git a/pdp11_cpu.c b/pdp11_cpu.c index 7b59a7ce..228e15e6 100644 --- a/pdp11_cpu.c +++ b/pdp11_cpu.c @@ -25,6 +25,8 @@ cpu PDP-11 CPU (J-11 microprocessor) + 10-Aug-01 RMS Removed register from declarations + 17-Jul-01 RMS Fixed warning from VC++ 6.0 01-Jun-01 RMS Added DZ11 support 23-Apr-01 RMS Added RK611 support 05-Apr-01 RMS Added TS11/TSV05 support @@ -564,10 +566,9 @@ t_stat sim_instr (void) extern int32 sim_interval; extern UNIT *sim_clock_queue; extern UNIT clk_unit; -extern int32 sim_rtc_init (int32 time); -register int32 IR, srcspec, srcreg, dstspec, dstreg; -register int32 src, src2, dst; -register int32 i, t, sign, oldrs, trapnum; +int32 IR, srcspec, srcreg, dstspec, dstreg; +int32 src, src2, dst; +int32 i, t, sign, oldrs, trapnum; int32 abortval; volatile int32 trapea; t_stat reason; @@ -2104,16 +2105,17 @@ t_stat SR_MMR012_rd (int32 *data, int32 pa, int32 access) switch ((pa >> 1) & 3) { /* decode pa<2:1> */ case 0: /* SR */ *data = SR; - return SCPE_OK; + break; case 1: /* MMR0 */ *data = MMR0 & MMR0_IMP; - return SCPE_OK; + break; case 2: /* MMR1 */ *data = MMR1; - return SCPE_OK; + break; case 3: /* MMR2 */ *data = MMR2; - return SCPE_OK; } /* end switch pa */ + break; } /* end switch pa */ +return SCPE_OK; } t_stat SR_MMR012_wr (int32 data, int32 pa, int32 access) diff --git a/pdp11_fp.c b/pdp11_fp.c index eb4e3561..0b61e8c3 100644 --- a/pdp11_fp.c +++ b/pdp11_fp.c @@ -529,6 +529,7 @@ case 7: /* @d(R) */ PC = (PC + 2) & 0177777; adr = ReadW (((R[reg] + adr) & 0177777) | dsenable); return (adr | dsenable); } /* end switch */ +return 0; } /* Read integer operand diff --git a/pdp11_rl.c b/pdp11_rl.c index 1d585018..29f00f72 100644 --- a/pdp11_rl.c +++ b/pdp11_rl.c @@ -25,6 +25,8 @@ rl RL11(RLV12)/RL01/RL02 cartridge disk + 20-Aug-01 RMS Added bad block option in attach + 17-Jul-01 RMS Fixed warning from VC++ 6.0 26-Apr-01 RMS Added device enable/disable support 25-Mar-01 RMS Fixed block fill calculation 15-Feb-01 RMS Corrected bootstrap string @@ -262,21 +264,22 @@ case 0: /* RLCS */ if (sim_is_active (uptr)) rlcs = rlcs & ~RLCS_DRDY; else rlcs = rlcs | RLCS_DRDY; /* see if ready */ *data = rlcs; - return SCPE_OK; + break; case 1: /* RLBA */ *data = rlba & RLBA_IMP; - return SCPE_OK; + break; case 2: /* RLDA */ *data = rlda; - return SCPE_OK; + break; case 3: /* RLMP */ *data = rlmp; rlmp = rlmp1; /* ripple data */ rlmp1 = rlmp2; - return SCPE_OK; + break; case 4: /* RLBAE */ *data = rlbae & RLBAE_IMP; - return SCPE_OK; } /* end switch */ + break; } /* end switch */ +return SCPE_OK; } t_stat rl_wr (int32 data, int32 PA, int32 access) @@ -324,29 +327,30 @@ case 0: /* RLCS */ break; default: /* data transfer */ sim_activate (uptr, rl_swait); /* activate unit */ - break; } /* end switch func */ - return SCPE_OK; /* end case RLCS */ + break; } /* end switch func */ + break; /* end case RLCS */ case 1: /* RLBA */ if (access == WRITEB) data = (PA & 1)? (rlba & 0377) | (data << 8): (rlba & ~0377) | data; rlba = data & RLBA_IMP; - return SCPE_OK; + break; case 2: /* RLDA */ if (access == WRITEB) data = (PA & 1)? (rlda & 0377) | (data << 8): (rlda & ~0377) | data; rlda = data; - return SCPE_OK; + break; case 3: /* RLMP */ if (access == WRITEB) data = (PA & 1)? (rlmp & 0377) | (data << 8): (rlmp & ~0377) | data; rlmp = rlmp1 = rlmp2 = data; - return SCPE_OK; + break; case 4: /* RLBAE */ if (PA & 1) return SCPE_OK; rlbae = data & RLBAE_IMP; rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX); - return SCPE_OK; } /* end switch */ + break; } /* end switch */ +return SCPE_OK; } /* Service unit timeout @@ -491,7 +495,8 @@ uptr -> capac = (uptr -> flags & UNIT_RL02)? RL02_SIZE: RL01_SIZE; r = attach_unit (uptr, cptr); if ((r != SCPE_OK) || ((uptr -> flags & UNIT_AUTO) == 0)) return r; if (fseek (uptr -> fileref, 0, SEEK_END)) return SCPE_OK; -if ((p = ftell (uptr -> fileref)) == 0) return SCPE_OK; +if ((p = ftell (uptr -> fileref)) == 0) + return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD); if (p > (RL01_SIZE * sizeof (int16))) { uptr -> flags = uptr -> flags | UNIT_RL02; uptr -> capac = RL02_SIZE; } diff --git a/pdp11_rp.c b/pdp11_rp.c index 8cdd707c..105585c8 100644 --- a/pdp11_rp.c +++ b/pdp11_rp.c @@ -25,6 +25,8 @@ rp RH/RP/RM moving head disks + 20-Aug-01 RMS Added bad block option in attach + 13-Jul-01 RMS Changed fread call to fxread (found by Peter Schorn) 14-May-01 RMS Added check for unattached drive 25-Apr-01 RMS Added device enable/disable support 21-Apr-01 RMS Implemented UAI function @@ -848,7 +850,7 @@ case FNC_READ: /* read */ err = ferror (uptr -> fileref); } /* end if */ else { /* read, wchk */ - awc = fread (dbuf, sizeof (uint16), wc, uptr -> fileref); + awc = fxread (dbuf, sizeof (uint16), wc, uptr -> fileref); err = ferror (uptr -> fileref); for ( ; awc < wc; awc++) dbuf[awc] = 0; for (twc = 0; twc < wc; twc++) { @@ -965,7 +967,8 @@ update_rpcs (CS1_SC, drv); if ((uptr -> flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ if (fseek (uptr -> fileref, 0, SEEK_END)) return SCPE_OK; -if ((p = ftell (uptr -> fileref)) == 0) return SCPE_OK; +if ((p = ftell (uptr -> fileref)) == 0) + return pdp11_bad_block (uptr, drv_tab[GET_DTYPE (uptr -> flags)].sect, RP_NUMWD); for (i = 0; drv_tab[i].sect != 0; i++) { if (p <= (drv_tab[i].size * (int) sizeof (int16))) { uptr -> flags = (uptr -> flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); diff --git a/pdp11_rx.c b/pdp11_rx.c index f064a342..5b035caa 100644 --- a/pdp11_rx.c +++ b/pdp11_rx.c @@ -25,6 +25,7 @@ rx RX11/RX01 floppy disk + 17-Jul-01 RMS Fixed warning from VC++ 6.0 26-Apr-01 RMS Added device enable/disable support 13-Apr-01 RMS Revised for register arrays 15-Feb-01 RMS Corrected bootstrap string @@ -166,13 +167,14 @@ switch ((PA >> 1) & 1) { /* decode PA<1> */ case 0: /* RXCS */ rx_csr = rx_csr & RXCS_IMP; /* clear junk */ *data = rx_csr & RXCS_ROUT; - return SCPE_OK; + break; case 1: /* RXDB */ if (rx_state == EMPTY) { /* empty? */ sim_activate (&rx_unit[0], rx_xwait); rx_csr = rx_csr & ~RXCS_TR; } /* clear xfer */ *data = rx_dbr; /* return data */ - return SCPE_OK; } /* end switch PA */ + break; } /* end switch PA */ +return SCPE_OK; } t_stat rx_wr (int32 data, int32 PA, int32 access) @@ -224,7 +226,7 @@ case 0: /* RXCS */ else if ((rx_csr & (RXCS_DONE + CSR_IE)) == RXCS_DONE) int_req = int_req | INT_RX; rx_csr = (rx_csr & ~RXCS_RW) | (data & RXCS_RW); - return SCPE_OK; /* end case RXCS */ + break; /* end case RXCS */ /* Accessing RXDB, two cases: 1. Write idle, write @@ -243,8 +245,9 @@ case 1: /* RXDB */ sim_activate (&rx_unit[drv], /* sched done */ rx_swait * abs (rx_track - rx_unit[drv].TRACK)); rx_csr = rx_csr & ~RXCS_TR; } /* clear xfer */ - return SCPE_OK; /* end case RXDB */ + break; /* end case RXDB */ } /* end switch PA */ +return SCPE_OK; } /* Unit service; the action to be taken depends on the transfer state: diff --git a/pdp11_stddev.c b/pdp11_stddev.c index 2d96bb33..29fa226e 100644 --- a/pdp11_stddev.c +++ b/pdp11_stddev.c @@ -27,6 +27,8 @@ tti,tto DL11 terminal input/output clk KW11L line frequency clock + 17-Jul-01 RMS Moved function prototype + 04-Jul-01 RMS Added DZ11 support 05-Mar-01 RMS Added clock calibration support 30-Oct-00 RMS Standardized register order 25-Jun-98 RMS Fixed bugs in paper tape error handling @@ -44,6 +46,7 @@ #define TTOCSR_RW (CSR_IE) #define CLKCSR_IMP (CSR_IE) /* real-time clock */ #define CLKCSR_RW (CSR_IE) +#define CLK_DELAY 8000 extern int32 int_req; int32 ptr_csr = 0; /* control/status */ @@ -54,6 +57,8 @@ int32 tti_csr = 0; /* control/status */ int32 tto_csr = 0; /* control/status */ int32 clk_csr = 0; /* control/status */ int32 clk_tps = 60; /* ticks/second */ +int32 dz_poll = CLK_DELAY; /* DZ poll inteval */ + t_stat ptr_svc (UNIT *uptr); t_stat ptp_svc (UNIT *uptr); t_stat tti_svc (UNIT *uptr); @@ -70,7 +75,6 @@ t_stat ptp_attach (UNIT *uptr, char *ptr); t_stat ptp_detach (UNIT *uptr); extern t_stat sim_poll_kbd (void); extern t_stat sim_putchar (int32 out); -extern int32 sim_rtc_calb (int32 ticksper); /* PTR data structures @@ -487,8 +491,12 @@ return SCPE_OK; t_stat clk_svc (UNIT *uptr) { +int32 t; + if (clk_csr & CSR_IE) int_req = int_req | INT_CLK; -sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate unit */ +t = sim_rtc_calb (clk_tps); /* calibrate clock */ +sim_activate (&clk_unit, t); /* reactivate unit */ +dz_poll = t; /* set DZ poll */ return SCPE_OK; } @@ -497,5 +505,6 @@ t_stat clk_reset (DEVICE *dptr) clk_csr = 0; int_req = int_req & ~INT_CLK; sim_activate (&clk_unit, clk_unit.wait); /* activate unit */ +dz_poll = clk_unit.wait; /* set DZ poll */ return SCPE_OK; } diff --git a/pdp11_sys.c b/pdp11_sys.c index 6d5cce72..89546de2 100644 --- a/pdp11_sys.c +++ b/pdp11_sys.c @@ -23,6 +23,8 @@ 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. + 20-Aug-01 RMS Updated bad block inquiry + 17-Jul-01 RMS Fixed warning from VC++ 6.0 27-May-01 RMS Added multiconsole support 05-Apr-01 RMS Added support for TS11/TSV05 14-Mar-01 RMS Revised load/dump interface (again) @@ -207,7 +209,7 @@ int16 *buf; if ((sec < 2) || (wds < 16)) return SCPE_ARG; if ((uptr -> flags & UNIT_ATT) == 0) return SCPE_UNATT; -if (!get_yn ("Overwrite last track? [N]", FALSE)) return SCPE_OK; +if (!get_yn ("Create bad block table on last track? [N]", FALSE)) return SCPE_OK; da = (uptr -> capac - (sec * wds)) * sizeof (int16); if (fseek (uptr -> fileref, da, SEEK_SET)) return SCPE_IOERR; if ((buf = malloc (wds * sizeof (int16))) == NULL) return SCPE_MEM; @@ -429,43 +431,43 @@ static const char *fname [] = int32 fprint_spec (FILE *of, t_addr addr, int32 spec, t_value nval, int32 flag, int32 iflag) { -int32 reg; +int32 reg, mode; +static const int32 rgwd[8] = { 0, 0, 0, 0, 0, 0, -1, -1 }; +static const int32 pcwd[8] = { 0, 0, -1, -1, 0, 0, -1, -1 }; reg = spec & 07; -switch ((spec >> 3) & 07) { +mode = ((spec >> 3) & 07); +switch (mode) { case 0: if (iflag) fprintf (of, "%s", rname[reg]); else fprintf (of, "%s", fname[reg]); - return 0; + break; case 1: fprintf (of, "(%s)", rname[reg]); - return 0; + break; case 2: - if (reg != 7) { - fprintf (of, "(%s)+", rname[reg]); - return 0; } - else { fprintf (of, "#%-o", nval); - return -1; } + if (reg != 7) fprintf (of, "(%s)+", rname[reg]); + else fprintf (of, "#%-o", nval); + break; case 3: - if (reg != 7) { - fprintf (of, "@(%s)+", rname[reg]); - return 0; } - else { fprintf (of, "@#%-o", nval); - return -1; } + if (reg != 7) fprintf (of, "@(%s)+", rname[reg]); + else fprintf (of, "@#%-o", nval); + break; case 4: fprintf (of, "-(%s)", rname[reg]); - return 0; + break; case 5: fprintf (of, "@-(%s)", rname[reg]); - return 0; + break; case 6: if ((reg != 7) || !flag) fprintf (of, "%-o(%s)", nval, rname[reg]); else fprintf (of, "%-o", (nval + addr + 4) & 0177777); - return -1; + break; case 7: if ((reg != 7) || !flag) fprintf (of, "@%-o(%s)", nval, rname[reg]); else fprintf (of, "@%-o", (nval + addr + 4) & 0177777); - return -1; } /* end case */ + break; } /* end case */ +return ((reg == 07)? pcwd[mode]: rgwd[mode]); } /* Symbolic decode diff --git a/pdp11_tc.c b/pdp11_tc.c index c4bd936c..bbfae487 100644 --- a/pdp11_tc.c +++ b/pdp11_tc.c @@ -25,6 +25,7 @@ tc TC11/TU56 DECtape + 17-Jul-01 RMS Moved function prototype 11-May-01 RMS Fixed bug in reset 26-Apr-01 RMS Added device enable/disable support 18-Apr-01 RMS Changed to rewind tape before boot @@ -264,7 +265,6 @@ void dt_stopunit (UNIT *uptr); int32 dt_comobv (int32 val); int32 dt_csum (UNIT *uptr, int32 blk); int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos); -extern uint32 sim_grtime (void); extern int32 sim_is_running; /* DT data structures diff --git a/pdp11_ts.c b/pdp11_ts.c index ddb436d4..d899e8f0 100644 --- a/pdp11_ts.c +++ b/pdp11_ts.c @@ -25,6 +25,8 @@ ts TS11/TSV05 magtape + 13-Jul-01 RMS Fixed bug in space reverse (found by Peter Schorn) + Magnetic tapes are represented as a series of variable 8b records of the form: @@ -425,7 +427,8 @@ t_mtrlnt prvp; t_bool tmkprv = FALSE; msgrfc = fc; -do { tc = ts_spacer (uptr, 0, FALSE); /* space rev */ +do { prvp = uptr -> pos; /* save cur pos */ + tc = ts_spacer (uptr, 0, FALSE); /* space rev */ if (GET_X (tc) & XS0_TMK) { /* tape mark? */ msgrfc = (msgrfc - 1) & DMASK; /* decr wc */ if (tmkprv && (wchopt & WCH_ESS) && diff --git a/pdp18b_cpu.c b/pdp18b_cpu.c index 212fb393..fd06a756 100644 --- a/pdp18b_cpu.c +++ b/pdp18b_cpu.c @@ -25,6 +25,8 @@ cpu PDP-4/7/9/15 central processor + 10-Aug-01 RMS Removed register from declarations + 17-Jul-01 RMS Moved function prototype 27-May-01 RMS Added second Teletype support, fixed bug in API 18-May-01 RMS Added PDP-9,-15 API option 16-May-01 RMS Fixed bugs in protection checks @@ -441,12 +443,11 @@ DEVICE cpu_dev = { t_stat sim_instr (void) { extern int32 sim_interval; -register int32 PC, LAC, MQ; +int32 PC, LAC, MQ; int32 api_int, api_cycle, skp; int32 iot_data, device, pulse; t_stat reason; extern UNIT clk_unit; -extern int32 sim_rtc_init (int32 time); extern int32 tti (int32 pulse, int32 AC); extern int32 tto (int32 pulse, int32 AC); extern int32 ptr (int32 pulse, int32 AC); @@ -589,7 +590,7 @@ extern int32 tto1 (int32 pulse, int32 AC); /* Restore register state */ #if defined (PDP15) -register int32 epcmask, damask; +int32 epcmask, damask; damask = memm? 017777: 07777; /* set dir addr mask */ epcmask = ADDRMASK & ~damask; /* extended PC mask */ @@ -611,8 +612,8 @@ api_cycle = 0; /* not API cycle */ /* Main instruction fetch/decode loop: check trap and interrupt */ while (reason == 0) { /* loop until halted */ -register int32 IR, MA, t, xct_count; -register int32 link_init, fill; +int32 IR, MA, t, xct_count; +int32 link_init, fill; if (sim_interval <= 0) { /* check clock queue */ if (reason = sim_process_event ()) break; diff --git a/pdp18b_dt.c b/pdp18b_dt.c index 75c9a5f2..1d0b4fd7 100644 --- a/pdp18b_dt.c +++ b/pdp18b_dt.c @@ -26,6 +26,7 @@ dt (PDP-9) TC02/TU55 DECtape (PDP-15) TC15/TU56 DECtape + 17-Jul-01 RMS Moved function prototype 11-May-01 RMS Fixed bug in reset 26-Apr-01 RMS Added device enable/disable support 15-Mar-01 RMS Added 129th word to PDP-8 format @@ -254,7 +255,6 @@ void dt_seterr (UNIT *uptr, int32 e); int32 dt_comobv (int32 val); int32 dt_csum (UNIT *uptr, int32 blk); int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos); -extern uint32 sim_grtime (void); extern int32 sim_is_running; /* DT data structures diff --git a/pdp18b_stddev.c b/pdp18b_stddev.c index 7730f43c..dd9568de 100644 --- a/pdp18b_stddev.c +++ b/pdp18b_stddev.c @@ -29,6 +29,7 @@ tto teleprinter clk clock + 17-Jul-01 RMS Moved function prototype 10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware 27-May-01 RMS Added multiconsole support 10-Mar-01 RMS Added funny format loader support @@ -71,8 +72,6 @@ t_stat ptp_attach (UNIT *uptr, char *cptr); t_stat ptr_detach (UNIT *uptr); t_stat ptp_detach (UNIT *uptr); t_stat ptr_boot (int32 unitno); -extern int32 sim_rtc_init (int32 time); -extern int32 sim_rtc_calb (int32 tps); extern t_stat sim_poll_kbd (void); extern t_stat sim_putchar (int32 out); diff --git a/pdp1_sys.c b/pdp1_sys.c index 86faac90..b228e173 100644 --- a/pdp1_sys.c +++ b/pdp1_sys.c @@ -23,6 +23,7 @@ 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. + 13-Jul-01 RMS Fixed RIM loader format 27-May-01 RMS Added multiconsole support 14-Mar-01 RMS Revised load/dump interface (again) 30-Oct-00 RMS Added support for examine to file @@ -102,7 +103,8 @@ int32 origin, val; if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; for (;;) { if ((val = getword (fileref)) < 0) return SCPE_FMT; - if ((val & 0770000) == 0240000) { /* DAC? */ + if (((val & 0770000) == 0320000) || /* DIO? */ + ((val & 0770000) == 0240000)) { /* DAC? - incorrect */ origin = val & 07777; if ((val = getword (fileref)) < 0) return SCPE_FMT; if (MEM_ADDR_OK (origin)) M[origin++] = val; } diff --git a/pdp8_clk.c b/pdp8_clk.c index fa09d9ae..845d7738 100644 --- a/pdp8_clk.c +++ b/pdp8_clk.c @@ -25,6 +25,7 @@ clk real time clock + 17-Jul-01 RMS Moved function prototype 05-Mar-01 RMS Added clock calibration support Note: includes the IOT's for both the PDP-8/E and PDP-8/A clocks @@ -35,7 +36,6 @@ extern int32 int_req, int_enable, dev_done, stop_inst; t_stat clk_svc (UNIT *uptr); t_stat clk_reset (DEVICE *dptr); -extern int32 sim_rtc_calb (int32 tps); int32 clk_tps = 60; /* CLK data structures diff --git a/pdp8_cpu.c b/pdp8_cpu.c index ac393bf2..92ff6d0f 100644 --- a/pdp8_cpu.c +++ b/pdp8_cpu.c @@ -25,6 +25,8 @@ cpu central processor + 10-Aug-01 RMS Removed register from declarations + 17-Jul-01 RMS Moved function prototype 07-Jun-01 RMS Fixed bug in JMS to non-existent memory 25-Apr-01 RMS Added device enable/disable support 18-Mar-01 RMS Added DF32 support @@ -271,12 +273,11 @@ DEVICE cpu_dev = { t_stat sim_instr (void) { extern int32 sim_interval; -register int32 IR, MB, IF, DF, LAC, MQ; -register t_addr PC, MA; +int32 IR, MB, IF, DF, LAC, MQ; +t_addr PC, MA; int32 device, pulse, temp, iot_data; t_stat reason; extern UNIT clk_unit; -extern int32 sim_rtc_init (int32 time); extern int32 tti (int32 pulse, int32 AC); extern int32 tto (int32 pulse, int32 AC); extern int32 ptr (int32 pulse, int32 AC); diff --git a/pdp8_dt.c b/pdp8_dt.c index c7acac3e..cbf3465f 100644 --- a/pdp8_dt.c +++ b/pdp8_dt.c @@ -25,6 +25,7 @@ dt TC08/TU56 DECtape + 17-Jul-01 RMS Moved function prototype 11-May-01 RMS Fixed bug in reset 25-Apr-01 RMS Added device enable/disable support 18-Apr-01 RMS Changed to rewind tape before boot @@ -257,7 +258,6 @@ void dt_seterr (UNIT *uptr, int32 e); int32 dt_comobv (int32 val); int32 dt_csum (UNIT *uptr, int32 blk); int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos, int32 dir); -extern uint32 sim_grtime (void); extern int32 sim_is_running; /* DT data structures diff --git a/pdp8_rx.c b/pdp8_rx.c index bc2976b9..04b80d2d 100644 --- a/pdp8_rx.c +++ b/pdp8_rx.c @@ -25,6 +25,7 @@ rx RX8E/RX01 floppy disk + 17-Jul-01 RMS Fixed warning from VC++ 6 26-Apr-01 RMS Added device enable/disable support 13-Apr-01 RMS Revised for register arrays 14-Apr-99 RMS Changed t_addr to unsigned @@ -161,7 +162,7 @@ int32 drv; switch (pulse) { /* decode IR<9:11> */ case 0: /* unused */ - return AC; + break; case 1: /* LCD */ if (rx_state != IDLE) return AC; /* ignore if busy */ rx_dbr = rx_csr = AC; /* save new command */ @@ -209,31 +210,32 @@ case 2: /* XDR */ sim_activate (&rx_unit[drv], /* sched done */ rx_swait * abs (rx_track - rx_unit[drv].TRACK)); break; } /* end switch state */ - return AC; + break; case 3: /* STR */ if (rx_tr != 0) { rx_tr = 0; return IOT_SKP + AC; } - return AC; + break; case 4: /* SER */ if (rx_err != 0) { rx_err = 0; return IOT_SKP + AC; } - return AC; + break; case 5: /* SDN */ if ((dev_done & INT_RX) != 0) { dev_done = dev_done & ~INT_RX; int_req = int_req & ~INT_RX; return IOT_SKP + AC; } - return AC; + break; case 6: /* INTR */ if (AC & 1) int_enable = int_enable | INT_RX; else int_enable = int_enable & ~INT_RX; int_req = INT_UPDATE; - return AC; + break; case 7: /* INIT */ rx_reset (&rx_dev); /* reset device */ - return AC; } /* end case pulse */ + break; } /* end case pulse */ +return AC; } /* Unit service; the action to be taken depends on the transfer state: diff --git a/scp.c b/scp.c index c7474fed..ac67f413 100644 --- a/scp.c +++ b/scp.c @@ -23,6 +23,7 @@ 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. + 18-Jul-01 RMS Minor changes for Macintosh port 12-Jun-01 RMS Fixed bug in big-endian I/O (found by Dave Conroy) 27-May-01 RMS Added multiple console support 16-May-01 RMS Added logging @@ -303,17 +304,17 @@ static CTAB cmd_table[] = { /* Main command loop */ -printf ("\n%s simulator V2.6a\n", sim_name); -end_test.i = 1; /* test endian-ness */ -sim_end = end_test.c[0]; -if (sim_emax <= 0) sim_emax = 1; -if ((sim_eval = calloc (sim_emax, sizeof (t_value))) == NULL) { - printf ("Unable to allocate examine buffer\n"); - return 0; }; +#if defined (__MWERKS__) && defined (macintosh) +argc = ccommand(&argv); +#endif + if ((stat = ttinit ()) != SCPE_OK) { printf ("Fatal terminal initialization error\n%s\n", scp_error_messages[stat - SCPE_BASE]); return 0; } +printf ("\n%s simulator V2.6b\n", sim_name); +end_test.i = 1; /* test endian-ness */ +sim_end = end_test.c[0]; stop_cpu = 0; sim_interval = 0; sim_time = sim_rtime = 0; @@ -321,6 +322,10 @@ noqueue_time = 0; sim_clock_queue = NULL; sim_is_running = 0; sim_log = NULL; +if (sim_emax <= 0) sim_emax = 1; +if ((sim_eval = calloc (sim_emax, sizeof (t_value))) == NULL) { + printf ("Unable to allocate examine buffer\n"); + return 0; }; if ((stat = reset_all (0)) != SCPE_OK) { printf ("Fatal simulator initialization error\n%s\n", scp_error_messages[stat - SCPE_BASE]); diff --git a/scp_tty.c b/scp_tty.c index bdd968ae..49f73c70 100644 --- a/scp_tty.c +++ b/scp_tty.c @@ -23,9 +23,11 @@ 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. + 20-Jul-01 RMS Added Macintosh support (from Louis Chretien, Peter Schorn, + and Ben Supnik) 15-May-01 RMS Added logging support 05-Mar-01 RMS Added clock calibration support - 08-Dec-00 BKR Added OS/2 support + 08-Dec-00 BKR Added OS/2 support (from Bruce Ray) 18-Aug-98 RMS Added BeOS support 13-Oct-97 RMS Added NetBSD terminal support 25-Jan-97 RMS Added POSIX terminal I/O support @@ -44,7 +46,7 @@ sim_os_msec - return elapsed time in msec - Versions are included for VMS, Windows, OS/2, BSD UNIX, and POSIX UNIX. + Versions are included for VMS, Windows, OS/2, Macintosh, BSD UNIX, and POSIX UNIX. The POSIX UNIX version works with LINUX. */ @@ -53,7 +55,7 @@ int32 sim_int_char = 005; /* interrupt character */ extern FILE *sim_log; -/* VMS routines */ +/* VMS routines, from Ben Thomas */ #if defined (VMS) #define __TTYROUTINES 0 @@ -255,9 +257,9 @@ return GetTickCount (); #endif -/* OS/2 routines */ +/* OS/2 routines, from Bruce Ray */ -#ifdef __OS2__ +#if defined (__OS2__) #define __TTYROUTINES 0 #include @@ -308,6 +310,180 @@ uint32 sim_os_msec () return 0; } +#endif + +/* Metrowerks CodeWarrior Macintosh routines, from Louis Chretien, + Peter Schorn, and Ben Supnik +*/ + +#if defined (__MWERKS__) && defined (macintosh) +#define __TTYROUTINES 0 + +#include +#include +#include +#include +#include +#include +#include + +extern char sim_name[]; +extern pSIOUXWin SIOUXTextWindow; +static CursHandle iBeamCursorH = NULL; /* contains the iBeamCursor */ + +static void updateCursor(void) { + WindowPtr window; + window = FrontWindow(); + if (SIOUXIsAppWindow(window)) { + GrafPtr savePort; + Point localMouse; + GetPort(&savePort); + SetPort(window); + GetGlobalMouse(&localMouse); + GlobalToLocal(&localMouse); + if (PtInRect(localMouse, &(*SIOUXTextWindow->edit)->viewRect) && iBeamCursorH) { + SetCursor(*iBeamCursorH); + } + else { + SetCursor(&qd.arrow); + } + TEIdle(SIOUXTextWindow->edit); + SetPort(savePort); + } + else { + SetCursor(&qd.arrow); + TEIdle(SIOUXTextWindow->edit); + } + return; +} + +int ps_kbhit(void) { + EventRecord event; + int c; + updateCursor(); + SIOUXUpdateScrollbar(); + while (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | + highLevelEventMask | diskEvt, &event)) { + SIOUXHandleOneEvent(&event); + } + if (SIOUXQuitting) { + exit(1); + } + if (EventAvail(keyDownMask,&event)) { + c = event.message&charCodeMask; + if ((event.modifiers & cmdKey) && (c > 0x20)) { + GetNextEvent(keyDownMask, &event); + SIOUXHandleOneEvent(&event); + if (SIOUXQuitting) { + exit(1); + } + return false; + } + return true; + } + else { + return false; + } +} + +int ps_getch(void) { + int c; + EventRecord event; + fflush(stdout); + updateCursor(); + while(!GetNextEvent(keyDownMask,&event)) { + if (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | + highLevelEventMask | diskEvt, &event)) { + SIOUXUpdateScrollbar(); + SIOUXHandleOneEvent(&event); + } + } + if (SIOUXQuitting) { + exit(1); + } + c = event.message&charCodeMask; + if ((event.modifiers & cmdKey) && (c > 0x20)) { + SIOUXUpdateMenuItems(); + SIOUXDoMenuChoice(MenuKey(c)); + } + if (SIOUXQuitting) { + exit(1); + } + return c; +} + +t_stat ttinit (void) { +/* Note that this only works if the call to ttinit comes before any output to the console */ + int i; + char title[50] = " "; /* this blank will later be replaced by the number of characters */ + unsigned char ptitle[50]; + SIOUXSettings.autocloseonquit = TRUE; + SIOUXSettings.asktosaveonclose = FALSE; + SIOUXSettings.showstatusline = FALSE; + SIOUXSettings.columns = 80; + SIOUXSettings.rows = 40; + SIOUXSettings.toppixel = 42; + SIOUXSettings.leftpixel = 6; + iBeamCursorH = GetCursor(iBeamCursor); + strcat(title, sim_name); + strcat(title, " Simulator"); + title[0] = strlen(title) - 1; /* Pascal string done */ + for (i = 0; i <= title[0]; i++) { /* copy to unsigned char */ + ptitle[i] = title[i]; + } + SIOUXSetTitle(ptitle); + return SCPE_OK; +} + +t_stat ttrunstate (void) +{ +return SCPE_OK; +} + +t_stat ttcmdstate (void) +{ +return SCPE_OK; +} + +t_stat ttclose (void) +{ +return SCPE_OK; +} + +t_stat sim_poll_kbd (void) +{ +int c; + +if (!ps_kbhit ()) return SCPE_OK; +c = ps_getch(); +if ((c & 0177) == '\b') c = 0177; +if ((c & 0177) == sim_int_char) return SCPE_STOP; +return c | SCPE_KFLAG; +} + +t_stat sim_putchar (int32 c) +{ +if (c != 0177) { + putchar (c); + fflush (stdout) ; + if (sim_log) fputc (c, sim_log); } +return SCPE_OK; +} + +const t_bool rtc_avail = TRUE; + +uint32 sim_os_msec (void) +{ +unsigned long long micros; +UnsignedWide macMicros; +unsigned long millis; + +Microseconds (&macMicros); +micros = *((unsigned long long *) &macMicros); +millis = micros / 1000LL; +return (uint32) millis; +} + #endif /* BSD UNIX routines */ @@ -406,7 +582,7 @@ return msec; #endif -/* POSIX UNIX routines */ +/* POSIX UNIX routines, from Leendert Van Doorn */ #if !defined (__TTYROUTINES) #include diff --git a/sim_defs.h b/sim_defs.h index e3a92d2b..3d75f78c 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -23,6 +23,7 @@ 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. + 17-Jul-01 RMS Added additional function prototypes 27-May-01 RMS Added multiple console support 15-May-01 RMS Increased string buffer size 25-Feb-01 RMS Revisions for V2.6 @@ -311,6 +312,7 @@ EXTERN t_stat sim_activate (UNIT *uptr, int32 interval); EXTERN t_stat sim_cancel (UNIT *uptr); EXTERN int32 sim_is_active (UNIT *uptr); EXTERN double sim_gtime (void); +EXTERN uint32 sim_grtime (void); EXTERN t_stat attach_unit (UNIT *uptr, char *cptr); EXTERN t_stat detach_unit (UNIT *uptr); EXTERN t_stat reset_all (int start_device); @@ -321,5 +323,8 @@ EXTERN char *get_glyph (char *iptr, char *optr, char mchar); EXTERN char *get_glyph_nc (char *iptr, char *optr, char mchar); EXTERN t_value get_uint (char *cptr, int radix, t_value max, t_stat *status); EXTERN t_value strtotv (char *cptr, char **endptr, int radix); +EXTERN int32 sim_rtc_init (int32 time); +EXTERN int32 sim_rtc_calb (int32 ticksper); EXTERN t_stat set_console (UNIT *uptr, int32 flag); EXTERN t_stat sim_putcons (int32 out, UNIT *uptr); + diff --git a/simh_doc.txt b/simh_doc.txt index 0bab626a..00b0bc99 100644 --- a/simh_doc.txt +++ b/simh_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik -Subj: Simulator Usage, V2.6a -Date: 15-Jun-01 +Subj: Simulator Usage, V2.6b +Date: 15-Sep-01 COPYRIGHT NOTICE @@ -46,9 +46,10 @@ information on each of the individual simulators. 1. Compiling And Running A Simulator The simulators have been tested on VAX VMS, Alpha VMS, Alpha UNIX, Intel -FreeBSD, Intel LINUX, and Windows 95/Windows NT (Visual C++ environment). -Porting to other environments will require changes to the operating system -dependent code in scp_tty.c. +FreeBSD, Intel LINUX, Windows 9x/Me/NT/2000 (Visual C++ environment), +Macintosh 9 and X (CodeWarrior environment), and OS/2. Porting to other +environments will require changes to the operating system dependent code +in scp_tty.c and scp_sock.c. To compile the simulators on VMS, use these commands (note that separate compilations are required for each of the 18b PDP's): @@ -81,8 +82,9 @@ On version of VMS prior to 6.2, the simulators must then be defined as foreign commands so that they can be started by name. To compile the simulators on Alpha UNIX or any UNIX variant which supports -the POSIX compliant TERMIOS interface, use the following commands (note -that separate compilations are required for each of the 18b PDP's): +the POSIX compliant TERMIOS interface (including Linux and Mac OS X), use +the following commands (note that separate compilations are required for +each of the 18b PDP's): % cc pdp8_*.c scp*.c -lm -o pdp8 % cc pdp11_*.c scp*.c -lm -o pdp11 @@ -109,6 +111,17 @@ declarations for Windows (_int64) and Digital UNIX (long). The default is GNU C (long long). If your compiler uses a different convention, you will have to edit sim_defs.h and modify the conditionals. +To compile the simulators on Windows 9x/ME/NT/2000 and Visual C++, +each simulator must be set up as a separate project. Under the VC++ +file menu, select New, select Project Workspace, select Console +Application, and type in the name of the simulator. In the project +files view, select Add Files To Project and add in all the files for +that simulator (e.g., all files beginning nova_ for the Nova), plus +sim_defs.h, scp.c, and scp_tty.c. If the project requires the DZ11, +also add in scp_sock.h and scp_sock.c. If the project requires a +command line switch, add the switches to the C/C++ tab of the +Configuration dialog. The simulator should then build properly. + To start the simulator, simply type its name. The simulator takes one optional argument, a startup command file. If specified, this file should contain a series of non-interactive simulator commands, @@ -4553,6 +4566,259 @@ TIM) or an octal number in the range 0 - 0177. The simulator recognizes the standard MACRO alternate mnemonics (CLEAR for SETZ, OR for IORI), the individual definitions for JRST and JFCL variants, and the extended instruction mnemonics. + +13. H316/H516 Features + +The Honeywell 316/516 simulator is configured as follows: + +device simulates +name(s) + +CPU H316/H516 CPU with 16/32KW memory +PTR 316/516-50 paper tape reader +PTP 316/516-52 paper tape punch +TTY 316/516-33 console terminal +CLK 316/516-12 real time clock +LPT 316/516 line printer + +The H316/H516 simulator implements several unique stop conditions: + + - decode of an undefined instruction, and STOP_INST is et + - reference to an undefined I/O device, and STOP_DEV is set + - more than INDMAX indirect references are detected during + memory reference address decoding + +The H316/H516 loader is not implemented. + +13.1 CPU + +CPU options include choice of instruction set and memory size. + + SET CPU HSA high speed arithmetic instructions + SET CPU NOHSA no high speed arithmetic instructions + SET CPU 4K set memory size = 4K + SET CPU 8K set memory size = 8K + SET CPU 12K set memory size = 12K + SET CPU 16K set memory size = 16K + SET CPU 24K set memory size = 24K + SET CPU 32K set memory size = 32K + +If memory size is being reduced, and the memory being truncated contains +non-zero data, the simulator asks for confirmation. Data in the truncated +portion of memory is lost. Initial memory size is 32K. + +CPU registers include the visible state of the processor as well as the +control registers for the interrupt system. + + name size comments + + P 15 program counter + A 16 A register + B 16 B register + X 16 index register + SC 16 shift count + C 1 carry flag + EXT 1 extend flag + PME 1 previous mode extend flag + EXT_OFF 1 extend off pending flag + DP 1 double precision flag + SS1..4 1 sense switches 1..4 + ION 1 interrupts enabled + INODEF 1 interrupts not deferred + INTREQ 16 interrupt requests + DEVRDY 16 device ready flags (read only) + DEVENB 16 device interrupt enable flags (read only) + STOP_INST 1 stop on undefined instruction + STOP_DEV 1 stop on undefined device + INDMAX 1 indirect address limit + OLDP 15 PC prior to last JMP, JSB, or interrupt + BREAK 16 breakpoint address (177777 to disable) + WRU 8 interrupt character + +13.2 Programmed I/O Devices + +13.2.1 316/516-50 Paper Tape Reader (PTR) + +The paper tape reader (PTR) reads data from a disk file. The POS +register specifies the number of the next data item to be read. +Thus, by changing POS, the user can backspace or advance the reader. + +The paper tape reader supports the BOOT command. BOOT PTR copies the +absolute binary loader into memory and starts it running. + +The paper tape reader implements these registers: + + name size comments + + BUF 8 last data item processed + INTREQ 1 device interrupt request + READY 1 device ready + ENABLE 1 device interrupts enabled + POS 31 position in the input or output file + TIME 24 time from I/O initiation to interrupt + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 out of tape + + end of file 1 report error and stop + 0 out of tape or paper + + OS I/O error x report error and stop + +13.2.2 316/516-52 Paper Tape Punch (PTP) + +The paper tape punch (PTP) writes data to a disk file. The POS +register specifies the number of the next data item to be written. +Thus, by changing POS, the user can backspace or advance the punch. + +The paper tape punch implements these registers: + + name size comments + + BUF 8 last data item processed + INTREQ 1 device interrupt request + READY 1 device ready + ENABLE 1 device interrupts enabled + POWER 1 device powered up + POS 31 position in the input or output file + TIME 24 time from I/O initiation to interrupt + PWRTIME 24 time from I/O request to power up + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 out of tape + + OS I/O error x report error and stop + +13.2.3 316/516-33 Console Teletype (TTY) + +The terminal reads and writes to the controlling console port. It has +one option, UC; when set, it automatically converts lower case input +to upper case. This is on by default. + +The terminal these registers: + + name size comments + + BUF 8 last data item processed + MODE 1 read/write mode + INTREQ 1 device interrupt request + READY 1 device ready + ENABLE 1 device interrupts enabled + KPOS 31 number of characters input + KTIME 24 keyboard polling interval + TPOS 31 number of characters output + TTIME 24 time from I/O initiation to interrupt + +13.2.4 316/516-12 Real Time Clock (CLK) + +The real time clock (CLK) implements these registers: + + name size comments + + INTREQ 1 device interrupt request + READY 1 device ready + ENABLE 1 device interrupts enabled + TIME 24 clock interval + +13.2.5 316/5116 Line Printer (LPT) + +The line printer (LPT) writes data to a disk file. The POS register +specifies the number of the next data item to be written. Thus, +by changing POS, the user can backspace or advance the printer. + +The line printer implements these registers: + + name size comments + + WDPOS 6 word position in current scan + DRPOS 6 drum position + CRPOS 1 carriage position + XFER 1 transfer ready flag + PRDN 1 print done flag + INTREQ 1 device interrupt request + ENABLE 1 device interrupt enable + SVCST 2 service state + SVCCH 2 service channel + BUF 8 buffer + POS 31 number of characters output + XTIME 24 delay between transfers + ETIME 24 delay at end of scan + PTIME 24 delay for shuttle/line advance + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 out of paper + + OS I/O error x report error and stop + +13.3 Symbolic Display and Input + +The H316/H516 simulator implements symbolic display and input. Display is +controlled by command line switches: + + -a display as ASCII character + -c display as two character string + -m display instruction mnemonics + +Input parsing is controlled by the first character typed in or by command +line switches: + + ' or -a ASCII character + " or -c two character sixbit string + alphabetic instruction mnemonic + numeric octal number + +Instruction input uses standard H316/H516 assembler syntax. There are six +instruction classes: memory reference, I/O, control, shift, skip, and +operate. + +Memory reference instructions have the format + + memref{*} {C/Z} address{,1} + +where * signifies indirect, C a current sector reference, Z a sector zero +reference, and 1 indexed. The address is an octal number in the range 0 - +077777; if C or Z is specified, the address is a page offset in the range +0 - 0777. Normally, C is not needed; the simulator figures out from the +address what mode to use. However, when referencing memory outside the CPU +(eg, disks), there is no valid PC, and C must be used to specify current +sector addressing. + +I/O instructions have the format + + io pulse+device + +The pulse+device is an octal number in the range 0 - 01777. + +Control and operate instructions consist of a single opcode + + opcode + +Shift instructions have the format + + shift n + +where n is an octal number in the range 0-77. + +Skip instructions have the format + + sub-op sub-op sub-op... + +The simulator checks that the combination of sub-opcodes is legal. Appendix 1: File Representations @@ -4642,21 +4908,21 @@ floppy disk y y y - - DECtape y y - - d mag tape h y/both y - h - system 1401 2100 Id4 PDP-10 + system 1401 2100 Id4 PDP-10 H316 device -CPU d y h y -FPU - - h y -CIS - - - y -console h y h y -paper tape - h h h -card reader h h - - -line printer h - - y -clock - h - y -hard disk - h - y -fixed disk - h - - -floppy disk - - - - -DECtape - - - - -mag tape h h - y +CPU d y h y h +FPU - - h y - +CIS - - - y - +console h y h y h +paper tape - h h h h +card reader h h - - - +line printer h - - y h +clock - h - y h +hard disk - h - y - +fixed disk - h - - - +floppy disk - - - - - +DECtape - - - - - +mag tape h h - y - legend: y = runs operating system or sample program d = runs diagnostics @@ -4666,6 +4932,19 @@ legend: y = runs operating system or sample program Revision History (since Rev 1.1) +Rev 2.6b, Jul, 01 + Added H316/516 simulator + Added Macintosh support from Louis Chrétien, Peter Schorn, + and Ben Supnik + Added bad block table option to PDP-11 RL, RP + Fixed bugs found by Peter Schorn + Endian error in PDP-10, PDP-11 RP + Space reverse error in PDP-11 TS + Symbolic input in 1401 + Fixed bug in PDP-1 RIM loader found by Derek Peschel + Fixed bug in Nova fixed head disk + Removed register in declarations + Rev 2.6a, Jun, 01 Fixed bug (found by Dave Conroy) in big-endian I/O Fixed DECtape reset in PDP-8, PDP-11, PDP-9/15 @@ -4870,12 +5149,14 @@ Phil Budne Solaris port testing Max Burnet PDP information, documentation, and software James Carpenter LINUX port testing Chip Charlot PDP-11 RT-11, RSTS/E, RSX-11M legal permissions +Louis Chrétien Macintosh porting Dave Conroy HP 21xx documentation L Peter Deutsch PDP-1 LISP software Ethan Dicks PDP-11 2.9 BSD debugging Carl Friend Nova and Interdata documentation, and RDOS software Megan Gentry PDP-11 integer debugging, make file -Dave Gesswein PDP-8/9/15 documentation and diagnostics +Dave Gesswein PDP-8 and PDP-9.15 documentation, PDP-8 DECtape and + paper tape images, PDP-9/15 DECtape images Dick Greeley PDP-8 OS/8 and PDP-10 TOPS-10/20 legal permissions Gordon Greene PDP-1 LISP machine readable source Lynne Grettum PDP-11 RT-11, RSTS/E, RSX-11M legal permissions @@ -4889,39 +5170,44 @@ Mark Hittinger PDP-10 debugging Jay Jaeger IBM 1401 information Doug Jones PDP-8 information, simulator, and software Al Kossow HP 21xx, Varian 620, TI 990, DEC documentation and software +Arthur Krewat DZ11 update for the PDP-10 Don Lewine Nova documentation and legal permissions Tim Litt PDP-10 hardware documentation and schematics, - tape images, and software sources + tape images, and software sources Scott McGregor PDP-11 UNIX legal permissions Jeff Moffatt HP 2100 information, documentation, and software Alec Muffett Solaris port testing Thord Nilson DZ11 implementation Charles Owen Nova moving head disk debugging, Altair simulator, - IBM 1401 diagnostics, debugging, and magtape boot + IBM 1401 diagnostics, debugging, and magtape boot +Derek Peschel PDP-10 debugging Paul Pierce IBM 1401 diagnostics, media recovery Hans Pufal PDP-10 debugging Bruce Ray Software, documentation, bug fixes, and new devices - for the Nova + for the Nova Craig St Clair PDP documentation Richard Schedler Public repository maintenance +Peter Schorn Macintosh porting Stephen Schultz PDP-11 2.11 BSD debugging Olaf Seibert NetBSD port testing Brian & Barry Silverman PDP-1 simulator and software Tim Shoppa Nova documentation, RDOS software, PDP-10 and PDP-11 - software archive + software archive Michael Somos PDP-1 debugging Hans-Michael Stahl OS/2 port testing, TERMIOS implementation Tim Stark PDP-10 simulator Larry Stewart Initial suggestion for the project -Bill Strecker Permission to revert copyrights +Bill Strecker Permission to revert copyrights Chris Suddick PDP-11 floating point debugging +Ben Supnik Macintosh timing routine Ben Thomas VMS character-by-character I/O routines Warren Toomey PDP-11 UNIX software Deb Toivonen DEC documentation -Mike Umbricht DEC documentation +Mike Umbricht DEC documentation, H316 documentation and schematics Leendert Van Doorn PDP-11 UNIX V6 debugging, TERMIOS implementation David Waks PDP-8 ESI-X and PDP-7 SIM8 software Tom West Nova documentation +Adrian Wise H316 simulator, documentation, and software John Wilson PDP-11 simulator and software In addition, the following companies have graciously licensed their