From f9564b81b9580f74ff43aecdf0d1cc1bba5aba2b Mon Sep 17 00:00:00 2001 From: Bob Supnik Date: Thu, 31 Jul 2003 16:17:00 -0700 Subject: [PATCH] Notes For V3.0-1 RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially debugged. Do NOT enable these features for normal operations. 1. New Features in 3.0-1 1.1 PDP-1 - Added block loader format support to LOAD. - Changed BOOT PTR to allow loading of all of the first bank of memory. 1.2 PDP-18b Family - Added PDP-4 EAE support. - Added PDP-15 FP15 support. - Added PDP-15 XVM support. - Added PDP-15 "re-entrancy ECO". - Added PDP-7, PDP-9, PDP-15 hardware RIM loader support in BOOT PTR. 2. Bugs Fixed in 3.0-1 2.1 PDP-11/VAX - Fixed bug in user disk size (found by Chaskiel M Grundman). 2.2 PDP-1 - Updated CPU, line printer, standard devices to detect indefinite I/O wait. - Fixed incorrect logical, missing activate, break in drum simulator. - Fixed bugs in instruction decoding, overprinting for line printer. 2.3 PDP-10 - Fixed bug in RP read header. 2.4 PDP-18b Family - Fixed bug in PDP-4 line printer overprinting. - Fixed bug in PDP-15 memory protect/skip interaction. - Fixed bug in RF set size routine. - Increased PTP TIME for PDP-15 operating systems. 2.5 PDP-8 - Fixed bug in DF, RF set size routine. 2.6 Nova - Fixed bug in DSK set size routine. 2.7 1401 - Revised fetch to model hardware more closely. 2.8 Ibm1130 - Fixed bugs found by APL 1130. 2.9 Altairz80 - Fixed bug in real-time clock on Windows host. 2.10 HP2100 -- Fixed DR drum sizes. -- Fixed DR variable capacity interaction with SAVE/RESTORE. 3. New Features in 3.0 vs prior releases 3.1 SCP and Libraries - Added ASSIGN/DEASSIGN (logical name) commands. - Changed RESTORE to unconditionally detach files. - Added E11 and TPC format support to magtape library. - Fixed bug in SHOW CONNECTIONS. - Added USE_ADDR64 support 3.2 All magtapes - Magtapes support SIMH format, E11 format, and TPC format (read only). - SET FORMAT=format sets the specified tape unit's format. - SHOW FORMAT displays the specified tape unit's format. - Tape format can also be set as part of the ATTACH command, using the -F switch. 3.3 VAX - VAX can be compiled without USE_INT64. - If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support files > 2GB. - VAX ROM has speed control (SET ROM DELAY/NODELAY). 4. Bugs Fixed in 3.0 vs prior releases 4.1 VAX - Fixed CVTfi bug: integer overflow not set if exponent out of range - Fixed EMODx bugs: o First and second operands reversed o Separated fraction received wrong exponent o Overflow calculation on separated integer incorrect o Fraction not set to zero if exponent out of range - Fixed interval timer and ROM access to pass power-up self-test even on very fast host processors (fixes from Mark Pizzolato). 4.2 1401 - Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS. - Fixed MCE bug, BS off by 1 if zero suppress. - Fixed chaining bug, D lost if return to SCP. - Fixed H branch, branch occurs after continue. - Added check for invalid 8 character MCW, LCA. - Fixed magtape load-mode end of record response. 4.3 Nova - Fixed DSK variable size interaction with restore. 4.4 PDP-1 - Fixed DT variable size interaction with restore. 4.5 PDP-11 - Fixed DT variable size interaction with restore. - Fixed bug in MMR1 update (found by Tim Stark). - Added XQ features and fixed bugs: o Corrected XQ interrupts on IE state transition (code by Tom Evans). o Added XQ interrupt clear on soft reset. o Removed XQ interrupt when setting XL or RL (multiple people). o Added SET/SHOW XQ STATS. o Added SHOW XQ FILTERS. o Added ability to split received packet into multiple buffers. o Added explicit runt and giant packet processing. 4.6 PDP-18B - Fixed DT, RF variable size interaction with restore. - Fixed MT bug in MTTR. 4.7 PDP-8 - Fixed DT, DF, RF, RX variable size interaction with restore. - Fixed MT bug in SKTR. 4.8 HP2100 - Fixed bug in DP (13210A controller only), DQ read status. - Fixed bug in DP, DQ seek complete. 4.9 GRI - Fixed bug in SC queue pointer management. --- 0readme_30.txt | 117 ++- AltairZ80/altairZ80_defs.h | 2 +- AltairZ80/altairZ80_sio.c | 41 +- H316/h316_doc.txt | 11 +- HP2100/hp2100_doc.txt | 7 +- HP2100/hp2100_dr.c | 65 +- HP2100/hp2100_fp.c | 5 +- I1401/i1401_cpu.c | 433 +++++--- I1401/i1401_doc.txt | 5 +- I1620/i1620_doc.txt | 4 +- Ibm1130/ibm1130.mak | 22 +- Ibm1130/ibm1130_conin.h | 24 +- Ibm1130/ibm1130_conout.h | 58 +- Ibm1130/ibm1130_cpu.c | 25 +- Ibm1130/ibm1130_cr.c | 1092 ++++++++++++++++--- Ibm1130/ibm1130_defs.h | 8 +- Ibm1130/ibm1130_disk.c | 168 +-- Ibm1130/ibm1130_fmt.c | 303 ++++++ Ibm1130/ibm1130_fmt.h | 17 + Ibm1130/ibm1130_gdu.c | 2 +- Ibm1130/ibm1130_gui.c | 138 ++- Ibm1130/ibm1130_prt.c | 2 +- Ibm1130/ibm1130_stddev.c | 1138 ++++++++++++++++++-- Ibm1130/ibm1130_sys.c | 2 +- Ibm1130/makefile | 6 +- Ibm1130/readme1130.txt | 5 + Ibm1130/readme_update.txt | 6 +- Ibm1130/utils/asm1130.c | 5 +- Ibm1130/utils/bindump.c | 2 +- Ibm1130/utils/mkboot.c | 2 +- Ibm1130/utils/viewdeck.c | 116 +- Interdata/id32_sys.c | 3 +- Interdata/id_doc.txt | 11 +- NOVA/nova_doc.txt | 4 +- NOVA/nova_dsk.c | 21 +- PDP1/pdp1_cpu.c | 47 +- PDP1/pdp1_defs.h | 28 +- PDP1/pdp1_doc.txt | 10 +- PDP1/pdp1_drm.c | 32 +- PDP1/pdp1_dt.c | 18 +- PDP1/pdp1_lp.c | 86 +- PDP1/pdp1_stddev.c | 116 +- PDP1/pdp1_sys.c | 71 +- PDP10/pdp10_doc.txt | 22 +- PDP10/pdp10_rp.c | 37 +- PDP11/pdp11_cpu.c | 10 +- PDP11/pdp11_doc.txt | 50 +- PDP11/pdp11_rq.c | 3 +- PDP18B/pdp18b_cpu.c | 1211 +++++++++++++-------- PDP18B/pdp18b_defs.h | 96 +- PDP18B/pdp18b_doc.txt | 244 +++-- PDP18B/pdp18b_drm.c | 4 +- PDP18B/pdp18b_dt.c | 74 +- PDP18B/pdp18b_fpp.c | 774 ++++++++++++++ PDP18B/pdp18b_lp.c | 120 ++- PDP18B/pdp18b_mt.c | 38 +- PDP18B/pdp18b_rb.c | 4 +- PDP18B/pdp18b_rf.c | 57 +- PDP18B/pdp18b_rp.c | 56 +- PDP18B/pdp18b_stddev.c | 106 +- PDP18B/pdp18b_sys.c | 268 ++++- PDP18B/pdp18b_tt1.c | 20 +- PDP8/pdp8_df.c | 13 +- PDP8/pdp8_rf.c | 13 +- SDS/sds_doc.txt | 23 +- VAX/vax_doc.txt | 93 +- descrip.mms | 2044 ++++++++++++++++++------------------ makefile | 5 +- scp.c | 4 +- scp_tty.c | 4 +- sim_rev.h | 54 +- sim_tape.c | 2 +- simh_doc.txt | 7 +- simh_faq.txt | 16 +- 74 files changed, 6938 insertions(+), 2812 deletions(-) create mode 100644 Ibm1130/ibm1130_fmt.c create mode 100644 Ibm1130/ibm1130_fmt.h create mode 100644 PDP18B/pdp18b_fpp.c diff --git a/0readme_30.txt b/0readme_30.txt index 70551e2d..09517fe9 100644 --- a/0readme_30.txt +++ b/0readme_30.txt @@ -1,11 +1,75 @@ -Notes For V3.0-0 +Notes For V3.0-1 -Because some key files have changed, V3.0 should be unzipped to a -clean directory. +RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially +debugged. Do NOT enable these features for normal operations. -1. New Features in 3.0-0 +1. New Features in 3.0-1 -1.1 SCP and Libraries +1.1 PDP-1 + +- Added block loader format support to LOAD. +- Changed BOOT PTR to allow loading of all of the first bank of memory. + +1.2 PDP-18b Family + +- Added PDP-4 EAE support. +- Added PDP-15 FP15 support. +- Added PDP-15 XVM support. +- Added PDP-15 "re-entrancy ECO". +- Added PDP-7, PDP-9, PDP-15 hardware RIM loader support in BOOT PTR. + +2. Bugs Fixed in 3.0-1 + +2.1 PDP-11/VAX + +- Fixed bug in user disk size (found by Chaskiel M Grundman). + +2.2 PDP-1 + +- Updated CPU, line printer, standard devices to detect indefinite I/O wait. +- Fixed incorrect logical, missing activate, break in drum simulator. +- Fixed bugs in instruction decoding, overprinting for line printer. + +2.3 PDP-10 + +- Fixed bug in RP read header. + +2.4 PDP-18b Family + +- Fixed bug in PDP-4 line printer overprinting. +- Fixed bug in PDP-15 memory protect/skip interaction. +- Fixed bug in RF set size routine. +- Increased PTP TIME for PDP-15 operating systems. + +2.5 PDP-8 + +- Fixed bug in DF, RF set size routine. + +2.6 Nova + +- Fixed bug in DSK set size routine. + +2.7 1401 + +- Revised fetch to model hardware more closely. + +2.8 Ibm1130 + +- Fixed bugs found by APL 1130. + +2.9 Altairz80 + +- Fixed bug in real-time clock on Windows host. + +2.10 HP2100 + +-- Fixed DR drum sizes. +-- Fixed DR variable capacity interaction with SAVE/RESTORE. + + +3. New Features in 3.0 vs prior releases + +3.1 SCP and Libraries - Added ASSIGN/DEASSIGN (logical name) commands. - Changed RESTORE to unconditionally detach files. @@ -13,7 +77,7 @@ clean directory. - Fixed bug in SHOW CONNECTIONS. - Added USE_ADDR64 support -1.2 All magtapes +3.2 All magtapes - Magtapes support SIMH format, E11 format, and TPC format (read only). - SET FORMAT=format sets the specified tape unit's format. @@ -21,16 +85,16 @@ clean directory. - Tape format can also be set as part of the ATTACH command, using the -F switch. -1.3 VAX +3.3 VAX - VAX can be compiled without USE_INT64. - If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support files > 2GB. - VAX ROM has speed control (SET ROM DELAY/NODELAY). -2. Bugs Fixed in 3.01-0 +4. Bugs Fixed in 3.0 vs prior releases -2.1 VAX +4.1 VAX - Fixed CVTfi bug: integer overflow not set if exponent out of range - Fixed EMODx bugs: @@ -41,7 +105,7 @@ clean directory. - Fixed interval timer and ROM access to pass power-up self-test even on very fast host processors (fixes from Mark Pizzolato). -2.2 1401 +4.2 1401 - Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS. - Fixed MCE bug, BS off by 1 if zero suppress. @@ -50,15 +114,15 @@ clean directory. - Added check for invalid 8 character MCW, LCA. - Fixed magtape load-mode end of record response. -2.3 Nova +4.3 Nova - Fixed DSK variable size interaction with restore. -2.4 PDP-1 +4.4 PDP-1 - Fixed DT variable size interaction with restore. -2.5 PDP-11 +4.5 PDP-11 - Fixed DT variable size interaction with restore. - Fixed bug in MMR1 update (found by Tim Stark). @@ -71,40 +135,21 @@ clean directory. o Added ability to split received packet into multiple buffers. o Added explicit runt and giant packet processing. -2.6 PDP-18B +4.6 PDP-18B - Fixed DT, RF variable size interaction with restore. - Fixed MT bug in MTTR. -2.7 PDP-8 +4.7 PDP-8 - Fixed DT, DF, RF, RX variable size interaction with restore. - Fixed MT bug in SKTR. -2.8 HP2100 +4.8 HP2100 - Fixed bug in DP (13210A controller only), DQ read status. - Fixed bug in DP, DQ seek complete. -2.9 GRI +4.9 GRI - Fixed bug in SC queue pointer management. - -3. New Features in 3.0 vs prior releases - -N/A - -4. Bugs Fixed in 3.0 vs prior releases - -N/A - -5. General Notes - -WARNING: The RESTORE command has changed. RESTORE will now -detach an attached file on a unit, if that unit did not have -an attached file in the saved configuration. This is required -to assure that the unit flags and the file state are consistent. - -WARNING: The compilation scheme for the PDP-10, PDP-11, and VAX -has changed. Use one of the supplied build files, or read the -documentation carefully, before compiling any of these simulators. diff --git a/AltairZ80/altairZ80_defs.h b/AltairZ80/altairZ80_defs.h index c693595e..fe5cbc83 100644 --- a/AltairZ80/altairZ80_defs.h +++ b/AltairZ80/altairZ80_defs.h @@ -1,6 +1,6 @@ /* altairz80_defs.h: MITS Altair simulator definitions - Copyright (c) 2002, Peter Schorn + Copyright (c) 2002-2003, Peter Schorn Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/AltairZ80/altairZ80_sio.c b/AltairZ80/altairZ80_sio.c index 489758e4..e640e5df 100644 --- a/AltairZ80/altairZ80_sio.c +++ b/AltairZ80/altairZ80_sio.c @@ -126,13 +126,13 @@ extern UNIT cpu_unit; /* SIMH pseudo device status registers */ /* ZSDOS clock definitions */ -static int32 ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */ +static time_t ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */ static int32 setClockZSDOSPos = 0; /* determines state for receiving address of parameter block */ static int32 setClockZSDOSAdr = 0; /* address in M of 6 byte parameter block for setting time */ static int32 getClockZSDOSPos = 0; /* determines state for sending clock information */ /* CPM3 clock definitions */ -static int32 ClockCPM3Delta = 0; /* delta between real clock and Altair clock */ +static time_t ClockCPM3Delta = 0; /* delta between real clock and Altair clock */ static int32 setClockCPM3Pos = 0; /* determines state for receiving address of parameter block */ static int32 setClockCPM3Adr = 0; /* address in M of 5 byte parameter block for setting time */ static int32 getClockCPM3Pos = 0; /* determines state for sending clock information */ @@ -658,11 +658,12 @@ enum simhPseudoDeviceCommands { /* do not change order or remove commands, add o #define cpmCommandLineLength 128 #define splimit 10 /* stack depth of timer stack */ static uint32 markTime[splimit]; /* timer stack */ -static struct tm *currentTime = NULL; +static struct tm currentTime; +static int32 currentTimeValid = FALSE; static char version[] = "SIMH002"; static t_stat simh_dev_reset(DEVICE *dptr) { - currentTime = NULL; + currentTimeValid = FALSE; ClockZSDOSDelta = 0; setClockZSDOSPos = 0; getClockZSDOSPos = 0; @@ -783,7 +784,7 @@ static void setClockCPM3(void) { } static int32 simh_in(const int32 port) { - int32 result; + int32 result = 0; switch(lastCommand) { case attachPTRCmd: case attachPTPCmd: @@ -791,31 +792,31 @@ static int32 simh_in(const int32 port) { lastCommand = 0; break; case getClockZSDOSCmd: - if (currentTime) { + if (currentTimeValid) { switch(getClockZSDOSPos) { case 0: - result = toBCD(currentTime -> tm_year > 99 ? - currentTime -> tm_year - 100 : currentTime -> tm_year); + result = toBCD(currentTime.tm_year > 99 ? + currentTime.tm_year - 100 : currentTime.tm_year); getClockZSDOSPos = 1; break; case 1: - result = toBCD(currentTime -> tm_mon + 1); + result = toBCD(currentTime.tm_mon + 1); getClockZSDOSPos = 2; break; case 2: - result = toBCD(currentTime -> tm_mday); + result = toBCD(currentTime.tm_mday); getClockZSDOSPos = 3; break; case 3: - result = toBCD(currentTime -> tm_hour); + result = toBCD(currentTime.tm_hour); getClockZSDOSPos = 4; break; case 4: - result = toBCD(currentTime -> tm_min); + result = toBCD(currentTime.tm_min); getClockZSDOSPos = 5; break; case 5: - result = toBCD(currentTime -> tm_sec); + result = toBCD(currentTime.tm_sec); getClockZSDOSPos = lastCommand = 0; break; } @@ -825,7 +826,7 @@ static int32 simh_in(const int32 port) { } break; case getClockCPM3Cmd: - if (currentTime) { + if (currentTimeValid) { switch(getClockCPM3Pos) { case 0: result = daysCPM3SinceOrg & 0xff; @@ -836,15 +837,15 @@ static int32 simh_in(const int32 port) { getClockCPM3Pos = 2; break; case 2: - result = toBCD(currentTime -> tm_hour); + result = toBCD(currentTime.tm_hour); getClockCPM3Pos = 3; break; case 3: - result = toBCD(currentTime -> tm_min); + result = toBCD(currentTime.tm_min); getClockCPM3Pos = 4; break; case 4: - result = toBCD(currentTime -> tm_sec); + result = toBCD(currentTime.tm_sec); getClockCPM3Pos = lastCommand = 0; break; } @@ -1012,7 +1013,8 @@ static int32 simh_out(const int32 port, const int32 data) { case getClockZSDOSCmd: time(&now); now += ClockZSDOSDelta; - currentTime = localtime(&now); + currentTime = *localtime(&now); + currentTimeValid = TRUE; getClockZSDOSPos = 0; break; case setClockZSDOSCmd: @@ -1021,7 +1023,8 @@ static int32 simh_out(const int32 port, const int32 data) { case getClockCPM3Cmd: time(&now); now += ClockCPM3Delta; - currentTime = localtime(&now); + currentTime = *localtime(&now); + currentTimeValid = TRUE; daysCPM3SinceOrg = (now - mkCPM3Origin()) / secondsPerDay; getClockCPM3Pos = 0; break; diff --git a/H316/h316_doc.txt b/H316/h316_doc.txt index 36080cf5..dc56fe0f 100644 --- a/H316/h316_doc.txt +++ b/H316/h316_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: H316 Simulator Usage -Date: 20-Apr-2003 +Date: 15-Jul-2003 COPYRIGHT NOTICE @@ -51,7 +51,7 @@ sim/h316/ h316_defs.h h316_cpu.c h316_lp.c h316_stddev.c - h316_cpu.c + h316_sys.c 2. H316/H516 Features @@ -230,7 +230,7 @@ The clock implements these registers: The real-time clock autocalibrates; the clock interval is adjusted up or down so that the clock tracks actual elapsed time. -2.2.5 316/5116 Line Printer (LPT) +2.2.5 316/516 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, @@ -294,9 +294,8 @@ 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. +address what mode to use. However, when referencing memory outside the CPU, +there is no valid PC, and C must be used to specify current sector addressing. I/O instructions have the format diff --git a/HP2100/hp2100_doc.txt b/HP2100/hp2100_doc.txt index 7f942089..b6440a10 100644 --- a/HP2100/hp2100_doc.txt +++ b/HP2100/hp2100_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik Subj: HP2100 Simulator Usage -Date: 15-Nov-2002 +Date: 15-Jul-2003 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: Original code published in 1993-2002, written by Robert M Supnik - Copyright (c) 1993-2002, Robert M Supnik + Copyright (c) 1993-2003, 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"), @@ -39,10 +39,12 @@ This memorandum documents the HP 2100 simulator. sim/ sim_defs.h sim_rev.h sim_sock.h + sim_tape.h sim_tmxr.h scp.c scp_tty.c sim_sock.c + sim_tape.c sim_tmxr.c sim/hp2100/ hp2100_defs.h @@ -563,7 +565,6 @@ Both IPLI and IPLO implement these registers: TIME 24 polling interval for input STOP_IOE 1 stop on I/O error - 2.5 12557A Disk Controller (DPC, DPD) with 2781 Drives 13210A Disk Controller (DPC, DPD) with 7900 Drives diff --git a/HP2100/hp2100_dr.c b/HP2100/hp2100_dr.c index b913b363..9a02a638 100644 --- a/HP2100/hp2100_dr.c +++ b/HP2100/hp2100_dr.c @@ -35,6 +35,8 @@ The drum control channel does not have any of the traditional flip-flops. + 27-Jul-03 RMS Fixed drum sizes + Fixed variable capacity interaction with SAVE/RESTORE 10-Nov-02 RMS Added BOOT command */ @@ -48,8 +50,21 @@ #define DR_DNUMSC 32 /* drum sec/track */ #define DR_NUMSC ((drc_unit.flags & UNIT_DR)? DR_DNUMSC: DR_FNUMSC) #define DR_SIZE (512 * DR_DNUMSC * DR_NUMWD) /* initial size */ -#define UNIT_V_DR (UNIT_V_UF) /* disk vs drum */ -#define UNIT_DR (1 << UNIT_V_DR) +#define UNIT_V_SZ (UNIT_V_UF) /* disk vs drum */ +#define UNIT_M_SZ 017 /* size */ +#define UNIT_SZ (UNIT_M_SZ << UNIT_V_SZ) +#define UNIT_DR (1 << UNIT_V_SZ) /* low order bit */ +#define SZ_180K 000 /* disks */ +#define SZ_360K 002 +#define SZ_720K 004 +#define SZ_1024K 001 /* drums: default size */ +#define SZ_1536K 003 +#define SZ_384K 005 +#define SZ_512K 007 +#define SZ_640K 011 +#define SZ_768K 013 +#define SZ_896K 015 +#define DR_GETSZ(x) (((x) >> UNIT_V_SZ) & UNIT_M_SZ) /* Command word */ @@ -105,11 +120,16 @@ int32 drd_ptr = 0; /* sector pointer */ int32 dr_stopioe = 1; /* stop on error */ int32 dr_time = 10; /* time per word */ +static int32 sz_tab[16] = { + 184320, 1048576, 368640, 1572864, 737280, 393216, 0, 524288, + 0, 655360, 0, 786432, 0, 917504, 0, 0 }; + DEVICE drd_dev, drc_dev; int32 drdio (int32 inst, int32 IR, int32 dat); int32 drcio (int32 inst, int32 IR, int32 dat); t_stat drc_svc (UNIT *uptr); t_stat drc_reset (DEVICE *dptr); +t_stat drc_attach (UNIT *uptr, char *cptr); t_stat drc_boot (int32 unitno, DEVICE *dptr); int32 dr_incda (int32 trk, int32 sec, int32 ptr); t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); @@ -175,21 +195,22 @@ REG drc_reg[] = { { DRDATA (TIME, dr_time, 24), REG_NZ + PV_LEFT }, { FLDATA (STOP_IOE, dr_stopioe, 0) }, { ORDATA (DEVNO, drc_dib.devno, 6), REG_HRO }, + { DRDATA (CAPAC, drc_unit.capac, 24), REG_HRO }, { NULL } }; MTAB drc_mod[] = { { UNIT_DR, 0, "disk", NULL, NULL }, { UNIT_DR, UNIT_DR, "drum", NULL, NULL }, - { UNIT_DR, 184320, NULL, "180K", &dr_set_size }, - { UNIT_DR, 368640, NULL, "360K", &dr_set_size }, - { UNIT_DR, 737280, NULL, "720K", &dr_set_size }, - { UNIT_DR, 368640+1, NULL, "384K", &dr_set_size }, - { UNIT_DR, 524280+1, NULL, "512K", &dr_set_size }, - { UNIT_DR, 655360+1, NULL, "640K", &dr_set_size }, - { UNIT_DR, 786432+1, NULL, "768K", &dr_set_size }, - { UNIT_DR, 917504+1, NULL, "896K", &dr_set_size }, - { UNIT_DR, 1048576+1, NULL, "1024K", &dr_set_size }, - { UNIT_DR, 1572864+1, NULL, "1536K", &dr_set_size }, + { UNIT_SZ, (SZ_180K << UNIT_V_SZ), NULL, "180K", &dr_set_size }, + { UNIT_SZ, (SZ_360K << UNIT_V_SZ), NULL, "360K", &dr_set_size }, + { UNIT_SZ, (SZ_720K << UNIT_V_SZ), NULL, "720K", &dr_set_size }, + { UNIT_SZ, (SZ_384K << UNIT_V_SZ), NULL, "384K", &dr_set_size }, + { UNIT_SZ, (SZ_512K << UNIT_V_SZ), NULL, "512K", &dr_set_size }, + { UNIT_SZ, (SZ_640K << UNIT_V_SZ), NULL, "640K", &dr_set_size }, + { UNIT_SZ, (SZ_768K << UNIT_V_SZ), NULL, "768K", &dr_set_size }, + { UNIT_SZ, (SZ_896K << UNIT_V_SZ), NULL, "896K", &dr_set_size }, + { UNIT_SZ, (SZ_1024K << UNIT_V_SZ), NULL, "1024K", &dr_set_size }, + { UNIT_SZ, (SZ_1536K << UNIT_V_SZ), NULL, "1536K", &dr_set_size }, { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &drd_dev }, { 0 } }; @@ -198,7 +219,7 @@ DEVICE drc_dev = { "DRC", &drc_unit, drc_reg, drc_mod, 1, 8, 21, 1, 8, 16, NULL, NULL, &drc_reset, - &drc_boot, NULL, NULL, + &drc_boot, &drc_attach, NULL, &drc_dib, DEV_DISABLE }; /* IOT routines */ @@ -336,14 +357,26 @@ sim_cancel (&drc_unit); return SCPE_OK; } +/* Attach routine */ + +t_stat drc_attach (UNIT *uptr, char *cptr) +{ +int32 sz = sz_tab[DR_GETSZ (uptr->flags)]; + +if (sz == 0) return SCPE_IERR; +uptr->capac = sz; +return attach_unit (uptr, cptr); +} /* Set size routine */ t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { +int32 sz; + +if (val < 0) return SCPE_IERR; +if ((sz = sz_tab[DR_GETSZ (val)]) == 0) return SCPE_IERR; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -if (val & 1) uptr->flags = uptr->flags | UNIT_DR; -else uptr->flags = uptr->flags & ~UNIT_DR; -uptr->capac = val & ~1; +uptr->capac = sz; return SCPE_OK; } diff --git a/HP2100/hp2100_fp.c b/HP2100/hp2100_fp.c index 8a9ce4b2..365413b8 100644 --- a/HP2100/hp2100_fp.c +++ b/HP2100/hp2100_fp.c @@ -1,6 +1,6 @@ /* hp2100_fp.c: HP 2100 floating point instructions - Copyright (c) 2003, Robert M. Supnik + Copyright (c) 2002-2003, 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"), @@ -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. + 15-Jul-03 RMS Fixed signed/unsigned warning 21-Oct-02 RMS Recoded for compatibility with 21MX microcode algorithms The HP2100 uses a unique binary floating point format: @@ -153,7 +154,7 @@ UnpackFP (&fop1, FPAB); /* unpack A-B */ UnpackFP (&fop2, opnd); /* get op */ if (sub) { /* subtract? */ fop2.fr = FR_NEG (fop2.fr); /* negate frac */ - if (fop2.fr == FP_SIGN) { /* -1/2? */ + if (fop2.fr == ((uint32) FP_SIGN)) { /* -1/2? */ fop2.fr = fop2.fr >> 1; /* special case */ fop2.exp = fop2.exp + 1; } } if (fop1.fr == 0) fop1 = fop2; /* op1 = 0? res = op2 */ diff --git a/I1401/i1401_cpu.c b/I1401/i1401_cpu.c index 209cfaf1..e34c877a 100644 --- a/I1401/i1401_cpu.c +++ b/I1401/i1401_cpu.c @@ -23,6 +23,9 @@ 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. + 12-Jul-03 RMS Moved ASCII/BCD tables to included file + Revised fetch to model hardware + Removed length checking in fetch phase 16-Mar-03 RMS Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS Fixed MCE bug, BS off by 1 if zero suppress @@ -114,6 +117,7 @@ */ #include "i1401_defs.h" +#include "i1401_dat.h" #define PCQ_SIZE 64 /* must be 2**n */ #define PCQ_MASK (PCQ_SIZE - 1) @@ -268,7 +272,7 @@ const int32 op_table[64] = { L1, /* punch feed */ 0, /* illegal */ L1 | L4 | L7 | AREQ | BREQ | MA, /* modify address */ - L7 | AREQ | BREQ | MDV, /* multiply */ + L1 | L4 | L7 | AREQ | BREQ | MDV, /* multiply */ 0, /* illegal */ 0, /* illegal */ 0, /* illegal */ @@ -284,7 +288,7 @@ const int32 op_table[64] = { L1 | L4 | L7 | AREQ | BREQ, /* move supress zero */ 0, /* illegal */ L1 | L4 | L7 | AREQ | BREQ | NOWM, /* set word mark */ - L7 | AREQ | BREQ | MDV, /* divide */ + L1 | L4 | L7 | AREQ | BREQ | MDV, /* divide */ 0, /* illegal */ 0, /* illegal */ 0, /* illegal */ @@ -293,7 +297,7 @@ const int32 op_table[64] = { L2 | L5, /* select stacker */ L1 | L4 | L7 | L8 | BREQ | MLS | IO, /* load */ L1 | L4 | L7 | L8 | BREQ | MLS | IO, /* move */ - HNOP | L1 | L4 | L7, /* nop */ + HNOP | L1 | L2 | L4 | L5 | L7 | L8, /* nop */ 0, /* illegal */ L1 | L4 | L7 | AREQ | BREQ | MR, /* move to record */ L1 | L4 | AREQ | MLS, /* 50: store A addr */ @@ -315,7 +319,7 @@ const int32 op_table[64] = { L1 | L4 | L7 | AREQ | MLS, /* 70: store B addr */ 0, /* illegal */ L1 | L4 | L7 | AREQ | BREQ, /* zero and add */ - HNOP | L1 | L4 | L7, /* halt */ + HNOP | L1 | L2 | L4 | L5 | L7 | L8, /* halt */ L1 | L4 | L7 | AREQ | BREQ, /* clear word mark */ 0, /* illegal */ 0, /* illegal */ @@ -362,38 +366,6 @@ const int32 bin_to_bcd[16] = { const int32 bcd_to_bin[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 3, 4, 5, 6, 7 }; -/* ASCII to BCD conversion */ - -const char ascii_to_bcd[128] = { - 000, 000, 000, 000, 000, 000, 000, 000, /* 000 - 037 */ - 000, 000, 000, 000, 000, 000, 000, 000, - 000, 000, 000, 000, 000, 000, 000, 000, - 000, 000, 000, 000, 000, 000, 000, 000, - 000, 052, 077, 013, 053, 034, 060, 032, /* 040 - 077 */ - 017, 074, 054, 037, 033, 040, 073, 021, - 012, 001, 002, 003, 004, 005, 006, 007, - 010, 011, 015, 056, 076, 035, 016, 072, - 014, 061, 062, 063, 064, 065, 066, 067, /* 100 - 137 */ - 070, 071, 041, 042, 043, 044, 045, 046, - 047, 050, 051, 022, 023, 024, 025, 026, - 027, 030, 031, 075, 036, 055, 020, 057, - 000, 061, 062, 063, 064, 065, 066, 067, /* 140 - 177 */ - 070, 071, 041, 042, 043, 044, 045, 046, - 047, 050, 051, 022, 023, 024, 025, 026, - 027, 030, 031, 000, 000, 000, 000, 000 }; - -/* BCD to ASCII conversion - also the "full" print chain */ - -char bcd_to_ascii[64] = { - ' ', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '0', '#', '@', ':', '>', '(', - '^', '/', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '\'', ',', '%', '=', '\\', '+', - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', '!', '$', '*', ']', ';', '_', - '&', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', '?', '.', ')', '[', '<', '"' }; - /* Indicator resets - a 1 marks an indicator that resets when tested */ static const int32 ind_table[64] = { @@ -501,9 +473,30 @@ if (sim_brk_summ && sim_brk_test (IS, SWMASK ('E'))) { /* breakpoint? */ sim_interval = sim_interval - 1; -/* Instruction fetch */ +/* Instruction fetch - 1401 fetch works as follows: -if ((M[IS] & WM) == 0) { /* WM under op? */ + - Each character fetched enters the B register. This register is not + visible; the variable t represents the B register. + - Except for the first and last cycles, each character fetched enters + the A register. This register is not visible; the variable D represents + the A register, because this is the instruction modifier for 2, 5, and 8 + character instructions. + - At the start of the second cycle (first address character), the A-address + register and, for most instructions, the B-address register, are cleared + to blanks. The simulator represents addresses in binary and creates the + effect of blanks (address is bad) if less than three A-address characters + are found. Further, the simulator accumulates only the A-address, and + replicates it to the B-address at the appropriate point. + - At the start of the fifth cycle (fourth address character), the B-address + register is cleared to blanks. Again, the simulator creates the effect of + blanks (address is bad) if less than three B-address characters are found. + + The 1401 does explicitly check for valid instruction lengths. Most 2,3,5,6 + character instructions will be invalid because the A-address or B-address + (or both) are invalid. +*/ + +if ((M[IS] & WM) == 0) { /* I-Op: WM under op? */ reason = STOP_NOWM; /* no, error */ break; } op = M[IS] & CHAR; /* get opcode */ @@ -514,25 +507,26 @@ if ((flags == 0) || (flags & ALLOPT & ~cpu_unit.flags)) { if (op == OP_SAR) BS = AS; /* SAR? save ASTAR */ PP (IS); -if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* WM? 1 char inst */ +if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* I-1: WM? 1 char inst */ D = ioind = t; /* could be D char, % */ AS = hun_table[t]; /* could be A addr */ PP (IS); /* if %xy, BA is set */ -if ((t = M[IS]) & WM) { /* WM? 2 char inst */ +if ((t = M[IS]) & WM) { /* I-2: WM? 2 char inst */ AS = AS | BA; /* ASTAR bad */ if (!(flags & MLS)) BS = AS; goto CHECK_LENGTH; } +D = dev = t; /* could be D char, dev */ AS = AS + ten_table[t]; /* build A addr */ -dev = t; /* save char as dev */ PP (IS); -if ((t = M[IS]) & WM) { /* WM? 3 char inst */ +if ((t = M[IS]) & WM) { /* I-3: WM? 3 char inst */ AS = AS | BA; /* ASTAR bad */ if (!(flags & MLS)) BS = AS; goto CHECK_LENGTH; } +D = unit = t; /* could be D char, unit */ +if (unit == BCD_ZERO) unit = 0; /* convert unit to binary */ AS = AS + one_table[t]; /* finish A addr */ -unit = (t == BCD_ZERO)? 0: t; /* save char as unit */ xa = (AS >> V_INDEX) & M_INDEX; /* get index reg */ if (xa && (ioind != BCD_PERCNT) && (cpu_unit.flags & XSA)) { /* indexed? */ AS = AS + hun_table[M[xa] & CHAR] + ten_table[M[xa + 1] & CHAR] + @@ -541,21 +535,23 @@ if (xa && (ioind != BCD_PERCNT) && (cpu_unit.flags & XSA)) { /* indexed? */ if (!(flags & MLS)) BS = AS; /* not MLS? B = A */ PP (IS); -if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* WM? 4 char inst */ +if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* I-4: WM? 4 char inst */ if ((op == OP_B) && (t == BCD_BLANK)) goto CHECK_LENGTH; /* BR + space? */ D = t; /* could be D char */ BS = hun_table[t]; /* could be B addr */ PP (IS); -if ((t = M[IS]) & WM) { /* WM? 5 char inst */ +if ((t = M[IS]) & WM) { /* I-5: WM? 5 char inst */ BS = BS | BA; /* BSTAR bad */ goto CHECK_LENGTH; } +D = t; /* could be D char */ BS = BS + ten_table[t]; /* build B addr */ PP (IS); -if ((t = M[IS]) & WM) { /* WM? 6 char inst */ +if ((t = M[IS]) & WM) { /* I-6: WM? 6 char inst */ BS = BS | BA; /* BSTAR bad */ goto CHECK_LENGTH; } +D = t; /* could be D char */ BS = BS + one_table[t]; /* finish B addr */ xa = (BS >> V_INDEX) & M_INDEX; /* get index reg */ if (xa && (cpu_unit.flags & XSA)) { /* indexed? */ @@ -564,39 +560,43 @@ if (xa && (cpu_unit.flags & XSA)) { /* indexed? */ BS = (BS & INDEXMASK) % MAXMEMSIZE; } PP (IS); -if ((M[IS] & WM) || (flags & NOWM)) goto CHECK_LENGTH; /* WM? 7 chr */ -D = M[IS]; /* last char is D */ -do { PP (IS); } while ((M[IS] & WM) == 0); /* find word mark */ +if (flags & NOWM) goto CHECK_LENGTH; /* I-7: SWM? done */ +if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* WM? 7 char inst */ +D = t; /* last char is D */ +for (;;) { /* I-8: repeats until WM */ + if ((t = M[IS]) & WM) break; /* WM? done */ + D = t; /* last char is D */ + PP (IS); } CHECK_LENGTH: ilnt = IS - saved_IS; /* get lnt */ -if (((flags & len_table [(ilnt <= 8)? ilnt: 8]) == 0) && /* valid lnt? */ - ((flags & HNOP) == 0)) reason = STOP_INVL; +//if (((flags & len_table [(ilnt <= 8)? ilnt: 8]) == 0) && /* valid lnt? */ +// ((flags & HNOP) == 0)) reason = STOP_INVL; if ((flags & BREQ) && ADDR_ERR (BS)) reason = STOP_INVB; /* valid A? */ if ((flags & AREQ) && ADDR_ERR (AS)) reason = STOP_INVA; /* valid B? */ if (reason) break; /* error in fetch? */ switch (op) { /* case on opcode */ -/* Move instructions A check B check +/* Move/load character instructions A check B check - MCW: copy A to B, preserving B WM, here fetch - until either A or B WM - LCA: copy A to B, overwriting B WM, here fetch - until A WM - MCM: copy A to B, preserving B WM, fetch fetch - until record or group mark - MCS: copy A to B, clearing B WM, until A WM; fetch fetch - reverse scan and suppress leading zeroes - MN: copy A char digit to B char digit, fetch fetch - preserving B zone and WM - MZ: copy A char zone to B char zone, fetch fetch - preserving B digit and WM + MCW copy A to B, preserving B WM, here fetch + until either A or B WM + LCA copy A to B, overwriting B WM, here fetch + until A WM + + Instruction lengths: + + 1 chained A and B + 2,3 invalid A-address + 4 chained B address + 5,6 invalid B-address + 7 normal + 8+ normal + modifier */ case OP_MCW: /* move char */ - if (ilnt >= 8) { /* I/O form? */ - if (ioind != BCD_PERCNT) reason = STOP_INVL; - else reason = iodisp (dev, unit, MD_NORM, D); + if ((ilnt >= 4) && (ioind == BCD_PERCNT)) { /* I/O form? */ + reason = iodisp (dev, unit, MD_NORM, D); /* dispatch I/O */ break; } if (ADDR_ERR (AS)) { /* check A addr */ reason = STOP_INVA; @@ -609,9 +609,8 @@ case OP_MCW: /* move char */ break; case OP_LCA: /* load char */ - if (ilnt >= 8) { /* I/O form? */ - if (ioind != BCD_PERCNT) reason = STOP_INVL; - else reason = iodisp (dev, unit, MD_WM, D); + if ((ilnt >= 4) && (ioind == BCD_PERCNT)) { /* I/O form? */ + reason = iodisp (dev, unit, MD_WM, D); break; } if (ADDR_ERR (AS)) { /* check A addr */ reason = STOP_INVA; @@ -621,6 +620,27 @@ case OP_LCA: /* load char */ MM (AS); MM (BS); } /* decr pointers */ while ((wm & WM) == 0); /* stop on A WM */ break; + +/* Other move instructions A check B check + + MCM copy A to B, preserving B WM, fetch fetch + until record or group mark + MCS copy A to B, clearing B WM, until A WM; fetch fetch + reverse scan and suppress leading zeroes + MN copy A char digit to B char digit, fetch fetch + preserving B zone and WM + MZ copy A char zone to B char zone, fetch fetch + preserving B digit and WM + + Instruction lengths: + + 1 chained + 2,3 invalid A-address + 4 self (B-address = A-address) + 5,6 invalid B-address + 7 normal + 8+ normal + ignored modifier +*/ case OP_MCM: /* move to rec/group */ do { @@ -662,38 +682,18 @@ case OP_MZ: /* move zone */ MM (AS); MM (BS); /* decr pointers */ break; -/* Compare - A and B are checked in fetch */ +/* Branch instruction A check B check -case OP_C: /* compare */ - if (ilnt != 1) { /* if not chained */ - ind[IN_EQU] = 1; /* clear indicators */ - ind[IN_UNQ] = ind[IN_HGH] = ind[IN_LOW] = 0; } - do { - a = M[AS]; /* get characters */ - b = M[BS]; - wm = a | b; /* get word marks */ - if ((a & CHAR) != (b & CHAR)) { /* unequal? */ - ind[IN_EQU] = 0; /* set indicators */ - ind[IN_UNQ] = 1; - ind[IN_HGH] = col_table[b & CHAR] > col_table [a & CHAR]; - ind[IN_LOW] = ind[IN_HGH] ^ 1; } - MM (AS); MM (BS); } /* decr pointers */ - while ((wm & WM) == 0); /* stop on A, B WM */ - if ((a & WM) && !(b & WM)) { /* short A field? */ - ind[IN_EQU] = ind[IN_LOW] = 0; - ind[IN_UNQ] = ind[IN_HGH] = 1; } - if (!(cpu_unit.flags & HLE)) /* no HLE? */ - ind[IN_EQU] = ind[IN_LOW] = ind[IN_HGH] = 0; - break; - -/* Branch instructions A check B check + Instruction lengths: - B 1/8 char: branch if B char equals d if branch here - B 4 char: unconditional branch if branch - B 5 char: branch if indicator[d] is set if branch - BWZ: branch if (d<0>: B char WM) if branch here - (d<1>: B char zone = d zone) - BBE: branch if B char & d non-zero if branch here + 1 branch if B char equals d, chained if branch here + 2,3 invalid B-address if branch here + 4 unconditional branch if branch + 5 branch if indicator[d] is set if branch + 6 invalid B-address if branch here + 7 branch if B char equals d, if branch here + d is last character of B-address + 8 branch if B char equals d if branch here */ case OP_B: /* branch */ @@ -701,14 +701,29 @@ case OP_B: /* branch */ else if (ilnt == 5) { /* branch on ind? */ if (ind[D]) { BRANCH; } /* test indicator */ if (ind_table[D]) ind[D] = 0; } /* reset if needed */ - else { - if (ADDR_ERR (BS)) { /* branch char eq */ - reason = STOP_INVB; /* validate B addr */ + else { /* branch char eq */ + if (ADDR_ERR (BS)) { /* validate B addr */ + reason = STOP_INVB; break; } if ((M[BS] & CHAR) == D) { BRANCH; } /* char equal? */ else { MM (BS); } } break; +/* Other branch instructions A check B check + + BWZ branch if (d<0>: B char WM) if branch here + (d<1>: B char zone = d zone) + BBE branch if B char & d non-zero if branch here + + Instruction lengths: + 1 chained + 2,3 invalid A-address and B-address + 4 self (B-address = A-address, d = last character of A-address) + 5,6 invalid B-address + 7 normal, d = last character of B-address + 8+ normal +*/ + case OP_BWZ: /* branch wm or zone */ if (((D & 1) && (M[BS] & WM)) || /* d1? test wm */ ((D & 2) && ((M[BS] & ZONE) == (D & ZONE)))) /* d2? test zone */ @@ -721,14 +736,24 @@ case OP_BBE: /* branch if bit eq */ else { MM (BS); } /* decr pointer */ break; -/* Arithmetic instructions A check B check +/* Arithmetic instructions A check B check - ZA: move A to B, normalizing A sign, fetch fetch - preserving B WM, until B WM - ZS: move A to B, complementing A sign, fetch fetch - preserving B WM, until B WM - A: add A to B fetch fetch - S: subtract A from B fetch fetch + ZA move A to B, normalizing A sign, fetch fetch + preserving B WM, until B WM + ZS move A to B, complementing A sign, fetch fetch + preserving B WM, until B WM + A add A to B fetch fetch + S subtract A from B fetch fetch + C compare A to B fetch fetch + + Instruction lengths: + + 1 chained + 2,3 invalid A-address + 4 self (B-address = A-address) + 5,6 invalid B-address + 7 normal + 8+ normal + ignored modifier */ case OP_ZA: case OP_ZS: /* zero and add/sub */ @@ -787,42 +812,71 @@ case OP_A: case OP_S: /* add/sub */ carry = (t >= 10); M[bsave] = (M[bsave] & ~DIGIT) | sum_table[t]; } } break; - -/* I/O instructions A check B check - R: read a card if branch - W: write to line printer if branch - WR: write and read if branch - P: punch a card if branch - RP: read and punch if branch - WP: write and punch if branch - WRP: write read and punch if branch - RF: read feed (nop) - PF: punch feed (nop) - SS: select stacker if branch - CC: carriage control if branch - MTF: magtape functions +case OP_C: /* compare */ + if (ilnt != 1) { /* if not chained */ + ind[IN_EQU] = 1; /* clear indicators */ + ind[IN_UNQ] = ind[IN_HGH] = ind[IN_LOW] = 0; } + do { + a = M[AS]; /* get characters */ + b = M[BS]; + wm = a | b; /* get word marks */ + if ((a & CHAR) != (b & CHAR)) { /* unequal? */ + ind[IN_EQU] = 0; /* set indicators */ + ind[IN_UNQ] = 1; + ind[IN_HGH] = col_table[b & CHAR] > col_table [a & CHAR]; + ind[IN_LOW] = ind[IN_HGH] ^ 1; } + MM (AS); MM (BS); } /* decr pointers */ + while ((wm & WM) == 0); /* stop on A, B WM */ + if ((a & WM) && !(b & WM)) { /* short A field? */ + ind[IN_EQU] = ind[IN_LOW] = 0; + ind[IN_UNQ] = ind[IN_HGH] = 1; } + if (!(cpu_unit.flags & HLE)) /* no HLE? */ + ind[IN_EQU] = ind[IN_LOW] = ind[IN_HGH] = 0; + break; + +/* I/O instructions A check B check + + R read a card if branch + W write to line printer if branch + WR write and read if branch + P punch a card if branch + RP read and punch if branch + WP : write and punch if branch + WRP write read and punch if branch + RF read feed (nop) + PF punch feed (nop) + SS select stacker if branch + CC carriage control if branch + + Instruction lengths: + + 1 normal + 2,3 normal, with modifier + 4 branch; modifier, if any, is last character of branch address + 5 branch + modifier + 6+ normal, with modifier */ case OP_R: /* read */ if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */ reason = read_card (ilnt, D); /* read card */ BS = CDR_BUF + CDR_WIDTH; - if (ilnt >= 4) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ break; case OP_W: /* write */ if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */ reason = write_line (ilnt, D); /* print line */ BS = LPT_BUF + LPT_WIDTH; - if (ilnt >= 4) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ break; case OP_P: /* punch */ if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */ reason = punch_card (ilnt, D); /* punch card */ BS = CDP_BUF + CDP_WIDTH; - if (ilnt >= 4) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ break; case OP_WR: /* write and read */ @@ -830,7 +884,7 @@ case OP_WR: /* write and read */ reason = write_line (ilnt, D); /* print line */ r1 = read_card (ilnt, D); /* read card */ BS = CDR_BUF + CDR_WIDTH; - if (ilnt >= 4) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ if (reason == SCPE_OK) reason = r1; /* merge errors */ break; @@ -839,7 +893,7 @@ case OP_WP: /* write and punch */ reason = write_line (ilnt, D); /* print line */ r1 = punch_card (ilnt, D); /* punch card */ BS = CDP_BUF + CDP_WIDTH; - if (ilnt >= 4) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ if (reason == SCPE_OK) reason = r1; /* merge errors */ break; @@ -848,7 +902,7 @@ case OP_RP: /* read and punch */ reason = read_card (ilnt, D); /* read card */ r1 = punch_card (ilnt, D); /* punch card */ BS = CDP_BUF + CDP_WIDTH; - if (ilnt >= 4) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ if (reason == SCPE_OK) reason = r1; /* merge errors */ break; @@ -858,24 +912,36 @@ case OP_WRP: /* write, read, punch */ r1 = read_card (ilnt, D); /* read card */ r2 = punch_card (ilnt, D); /* punch card */ BS = CDP_BUF + CDP_WIDTH; - if (ilnt >= 4) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ if (reason == SCPE_OK) reason = (r1 == SCPE_OK)? r2: r1; break; case OP_SS: /* select stacker */ if (reason = iomod (ilnt, D, ss_mod)) break; /* valid modifier? */ if (reason = select_stack (D)) break; /* sel stack, error? */ - if (ilnt >= 4) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ break; case OP_CC: /* carriage control */ if (reason = carriage_control (D)) break; /* car ctrl, error? */ - if (ilnt >= 4) { BRANCH; } /* check for branch */ + if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ break; +/* MTF - magtape functions - must be at least 4 characters + + Instruction lengths: + + 1-3 invalid I/O address + 4 normal, d-character is unit + 5 normal + 6+ normal, d-character is last character +*/ + case OP_MTF: /* magtape function */ - if (reason = iomod (ilnt, D, mtf_mod)) break; /* valid modifier? */ - if (reason = mt_func (unit, D)) break; /* mt func, error? */ + if (ilnt < 4) reason = STOP_INVL; /* too short? */ + else if (ioind != BCD_PERCNT) reason = STOP_INVA; + else if (reason = iomod (ilnt, D, mtf_mod)) break; /* valid modifier? */ + reason = mt_func (unit, D); /* mt func, error? */ break; /* can't branch */ case OP_RF: case OP_PF: /* read, punch feed */ @@ -902,6 +968,15 @@ case OP_RF: case OP_PF: /* read, punch feed */ The first A field character is masked to its digit part, all others are copied intact + + Instruction lengths: + + 1 chained + 2,3 invalid A-address + 4 self (B-address = A-address) + 5,6 invalid B-address + 7 normal + 8+ normal + ignored modifier */ case OP_MCE: /* edit */ @@ -1040,6 +1115,15 @@ case OP_MCE: /* edit */ LD + 1 + length of multiplier. Locate the low order multiplier digit, and at the same time zero out the product field. Then compute the sign of the result. + + Instruction lengths: + + 1 chained + 2,3 invalid A-address + 4 self (B-address = A-address) + 5,6 invalid B-address + 7 normal + 8+ normal + ignored modifier */ case OP_MUL: @@ -1085,7 +1169,7 @@ case OP_MUL: /* Divide. Comments from the PDP-10 based simulator by Len Fehskens. - Divide is done, like multiply, pretty muchy the same way you do it with + Divide is done, like multiply, pretty much the same way you do it with pencil and paper; successive subtraction of the divisor from a substring of the dividend while counting up the corresponding quotient digit. @@ -1106,6 +1190,15 @@ case OP_MUL: Start by locating the high order non-zero digit of the divisor. This also tests for a divide by zero. + + Instruction lengths: + + 1 chained + 2,3 invalid A-address + 4 self (B-address = A-address) + 5,6 invalid B-address + 7 normal + 8+ normal + ignored modifier */ case OP_DIV: @@ -1170,16 +1263,19 @@ case OP_DIV: BS = qs - 2; /* BS = quo 10's pos */ break; -/* Miscellaneous instructions A check B check +/* Word mark instructions A check B check - SWM: set WM on A char and B char fetch fetch - CWM: clear WM on A char and B char fetch fetch - CS: clear from B down to nearest hundreds address if branch fetch - MA: add A addr and B addr, store at B addr fetch fetch - SAR: store A* at A addr fetch - SBR: store B* at A addr fetch - NOP: no operation - H: halt + SWM set WM on A char and B char fetch fetch + CWM clear WM on A char and B char fetch fetch + + Instruction lengths: + + 1 chained + 2,3 invalid A-address + 4 one operand (B-address = A-address) + 5,6 invalid B-address + 7 two operands (SWM cannot be longer than 7) + 8+ two operands + ignored modifier */ case OP_SWM: /* set word mark */ @@ -1194,13 +1290,41 @@ case OP_CWM: /* clear word mark */ MM (AS); MM (BS); /* decr pointers */ break; +/* Clear storage instruction A check B check + + CS clear from B down to nearest hundreds if branch fetch + address + + Instruction lengths: + + 1 chained + 2,3 invalid A-address and B-address + 4 one operand (B-address = A-address) + 5,6 invalid B-address + 7 branch + 8+ one operand, branch ignored +*/ + case OP_CS: /* clear storage */ t = (BS / 100) * 100; /* lower bound */ while (BS >= t) M[BS--] = 0; /* clear region */ if (BS < 0) BS = BS + MEMSIZE; /* wrap if needed */ - if (ilnt >= 7) { BRANCH; } /* branch variant? */ + if (ilnt == 7) { BRANCH; } /* branch variant? */ break; +/* Modify address instruction A check B check + + MA add A addr and B addr, store at B addr fetch fetch + + Instruction lengths: + 1 chained + 2,3 invalid A-address and B-address + 4 self (B-address = A-address) + 5,6 invalid B-address + 7 normal + 8+ normal + ignored modifier +*/ + case OP_MA: /* modify address */ a = one_table[M[AS] & CHAR]; MM (AS); /* get A address */ a = a + ten_table[M[AS] & CHAR]; MM (AS); @@ -1215,15 +1339,32 @@ case OP_MA: /* modify address */ if (((a % 4000) + (b % 4000)) >= 4000) BS = BS + 2; /* carry? */ break; +/* Store address instructions A-check B-check + + SAR store A* at A addr fetch + SBR store B* at A addr fetch + + Instruction lengths: + 1 chained + 2,3 invalid A-address + 4 normal + 5+ B-address overwritten from instruction; + invalid address ignored +*/ + case OP_SAR: case OP_SBR: /* store A, B reg */ M[AS] = (M[AS] & WM) | store_addr_u (BS); MM (AS); M[AS] = (M[AS] & WM) | store_addr_t (BS); MM (AS); M[AS] = (M[AS] & WM) | store_addr_h (BS); MM (AS); break; +/* NOP - no validity checking, all instructions length ok */ + case OP_NOP: /* nop */ break; +/* HALT - unless length = 4 (branch), no validity checking; all lengths ok */ + case OP_H: /* halt */ if (ilnt == 4) hb_pend = 1; /* set pending branch */ reason = STOP_HALT; /* stop simulator */ diff --git a/I1401/i1401_doc.txt b/I1401/i1401_doc.txt index fc69dc66..83d4b9d0 100644 --- a/I1401/i1401_doc.txt +++ b/I1401/i1401_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: IBM 1401 Simulator Usage -Date: 20-Apr-2003 +Date: 15-Jul-2003 COPYRIGHT NOTICE @@ -39,13 +39,16 @@ This memorandum documents the IBM 1401 simulator. sim/ sim_defs.h sim_rev.h sim_sock.h + sim_tape.h sim_tmxr.h scp.c scp_tty.c sim_sock.c + sim_tape.c sim_tmxr.c sim/i1401/ i1401_defs.h + i1401_dat.h i1401_cpu.c i1401_cd.c i1401_iq.c diff --git a/I1620/i1620_doc.txt b/I1620/i1620_doc.txt index 3b64d70b..2f408e54 100644 --- a/I1620/i1620_doc.txt +++ b/I1620/i1620_doc.txt @@ -138,7 +138,7 @@ standard on the Model 2. 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. Initially, the CPU is a Model I, memory size is +portion of memory is lost. Initially, the CPU is a Model 1, memory size is 20K, and indirect addressing, editing instructions, and divide are enabled. Memory is implemented as 5 bit BCD digits, as follows: @@ -393,7 +393,7 @@ controlled by command line switches: -s display as flag terminated numeric string (CPU and DP only) -m display instruction mnemonics - (CPU and only) + (CPU and DP only) -d display 50 characters per line, with word marks denoted by "_" on the line above diff --git a/Ibm1130/ibm1130.mak b/Ibm1130/ibm1130.mak index e9938321..aaf8e0fb 100644 --- a/Ibm1130/ibm1130.mak +++ b/Ibm1130/ibm1130.mak @@ -72,7 +72,8 @@ BSC32_SBRS= \ $(INTDIR)/scp.sbr \ $(INTDIR)/scp_tty.sbr \ $(INTDIR)/sim_tmxr.sbr \ - $(INTDIR)/sim_sock.sbr + $(INTDIR)/sim_sock.sbr \ + $(INTDIR)/ibm1130_fmt.sbr $(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS) $(BSC32) @<< @@ -99,7 +100,8 @@ LINK32_OBJS= \ $(INTDIR)/scp.obj \ $(INTDIR)/scp_tty.obj \ $(INTDIR)/sim_tmxr.obj \ - $(INTDIR)/sim_sock.obj + $(INTDIR)/sim_sock.obj \ + $(INTDIR)/ibm1130_fmt.obj $(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< @@ -149,7 +151,8 @@ BSC32_SBRS= \ $(INTDIR)/scp.sbr \ $(INTDIR)/scp_tty.sbr \ $(INTDIR)/sim_tmxr.sbr \ - $(INTDIR)/sim_sock.sbr + $(INTDIR)/sim_sock.sbr \ + $(INTDIR)/ibm1130_fmt.sbr $(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS) $(BSC32) @<< @@ -176,7 +179,8 @@ LINK32_OBJS= \ $(INTDIR)/scp.obj \ $(INTDIR)/scp_tty.obj \ $(INTDIR)/sim_tmxr.obj \ - $(INTDIR)/sim_sock.obj + $(INTDIR)/sim_sock.obj \ + $(INTDIR)/ibm1130_fmt.obj $(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< @@ -249,7 +253,7 @@ $(INTDIR)/ibm1130_stddev.obj : $(SOURCE) $(DEP_IBM1130_) $(INTDIR) SOURCE=.\ibm1130.rc DEP_IBM1130_R=\ .\1130consoleblank.bmp\ - .\HAND.CUR + .\hand.cur $(INTDIR)/ibm1130.res : $(SOURCE) $(DEP_IBM1130_R) $(INTDIR) $(RSC) $(RSC_PROJ) $(SOURCE) @@ -354,6 +358,14 @@ DEP_SIM_S=\ $(INTDIR)/sim_sock.obj : $(SOURCE) $(DEP_SIM_S) $(INTDIR) $(CPP) $(CPP_PROJ) $(SOURCE) +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\ibm1130_fmt.c + +$(INTDIR)/ibm1130_fmt.obj : $(SOURCE) $(INTDIR) + # End Source File # End Group # End Project diff --git a/Ibm1130/ibm1130_conin.h b/Ibm1130/ibm1130_conin.h index beaef7c9..108e4917 100644 --- a/Ibm1130/ibm1130_conin.h +++ b/Ibm1130/ibm1130_conin.h @@ -9,26 +9,27 @@ * Mail to sim@ibm1130.org */ -// ctrl-M (Enter) => EOF -// ctrl-U => Erase field -// ctrl-Q => Interrupt request (not here) -// ctrl-C => Program stop (not here) -// \ => "not" -// Del => backspace -// Ctrl-H => backspace - +// 03 ctrl-C => Program stop (not handled here) +// 05 ctrl-E => Simulator stop (not handled here) +// 08 ctrl-H => Backspace +// 0D ctrl-M (Enter) => EOF +// 11 ctrl-Q => Interrupt request (not handled here) +// 12 ctrl-R => "cent" (R because that's where cent is on the 1130 keyboard) +// 15 ctrl-U => Erase Field +// 7E ~ => "not" +// FF Del => Backspace again static uint16 ascii_to_conin[] = /* ASCII to ((hollerith << 4) | special key flags) */ { /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0,0x0004, 0, 0, 0, 0,0x0008, 0, 0, - /* 01 */ 0, 0, 0, 0, 0,0x0002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 10 */ 0, 0,0x8820, 0, 0,0x0002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 */ 0x0001,0x4820,0x0060,0x0420,0x4420,0x2220,0x8000,0x0120,0x8120,0x4120,0x4220,0x80a0,0x2420,0x4000,0x8420,0x3000, /* 30 */ 0x2000,0x1000,0x0800,0x0400,0x0200,0x0100,0x0080,0x0040,0x0020,0x0010,0x0820,0x40a0,0x8220,0x00a0,0x20a0,0x2060, /* 40 */ 0x0220,0x9000,0x8800,0x8400,0x8200,0x8100,0x8080,0x8040,0x8020,0x8010,0x5000,0x4800,0x4400,0x4200,0x4100,0x4080, - /* 50 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010,0xa420, 0,0xc420,0x4060,0x2120, + /* 50 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010, 0, 0, 0, 0,0x2120, /* 60 */ 0,0x9000,0x8800,0x8400,0x8200,0x8100,0x8080,0x8040,0x8020,0x8010,0x5000,0x4800,0x4400,0x4200,0x4100,0x4080, - /* 70 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010,0xa420, 0,0x8060, 0,0x0004, + /* 70 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010, 0,0xB060, 0, 0,0x0004, /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -38,4 +39,3 @@ static uint16 ascii_to_conin[] = /* ASCII to ((hollerith << 4) | special key /* e0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x0004, }; - diff --git a/Ibm1130/ibm1130_conout.h b/Ibm1130/ibm1130_conout.h index dc46f765..478e005d 100644 --- a/Ibm1130/ibm1130_conout.h +++ b/Ibm1130/ibm1130_conout.h @@ -12,31 +12,47 @@ #define _0_ '\0' -#define CENT '\xA2' -#define REST IGNR -#define RDRSTP '?' -#define NOT '\xAC' -#define IGNR '\xFF' -#define CRLF '\r' +#define CENT_ '\xA2' /* cent and not: standard DOS mapping */ +#define NOT_ '\xAC' +#define IGNR_ '\xFF' +#define CRLF_ '\r' -static char conout_to_ascii[] = /* console output code to ASCII */ +#define COUT_IS_CTRL 0x01 /* conout characters with bit 1 set are controls: */ + +#define COUT_CTRL_BLACK 0x04 /* none or one of these bits */ +#define COUT_CTRL_RED 0x08 + +#define COUT_CTRL_LINEFEED 0x02 /* plus none or one of these bits */ +#define COUT_CTRL_BACKSPACE 0x10 +#define COUT_CTRL_SPACE 0x20 +#define COUT_CTRL_TAB 0x40 +#define COUT_CTRL_RETURN 0x80 + +#ifdef _MSC_VER +# pragma warning(disable:4245) /* enable int->char demotion warning caused by characters with high-bit set */ +#endif + +static unsigned char conout_to_ascii[] = /* console output code to ASCII */ { /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ - /* 00 */ '.', _0_, CENT, '\n', '@', REST, '%', _0_, _0_,RDRSTP, _0_, _0_, _0_, _0_, _0_, _0_, - /* 10 */ 'f', '\b', 'F', _0_, 'g', _0_, 'G', _0_, 'b', _0_, 'B', _0_, 'c', _0_, 'C', _0_, - /* 20 */ 'i', ' ', 'I', _0_, 'h', _0_, 'H', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 30 */ 'd', _0_, 'D', _0_, 'e', _0_, 'E', _0_, _0_, _0_, _0_, _0_, 'a', _0_, 'A', _0_, - /* 40 */ '$', _0_, '!', _0_, '&', _0_, '>', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 50 */ 'o', _0_, 'O', _0_, 'p', _0_, 'P', _0_, 'k', _0_, 'K', _0_, 'l', _0_, 'L', _0_, - /* 60 */ 'r', _0_, 'R', _0_, 'q', _0_, 'Q', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 70 */ 'm', _0_, 'M', _0_, 'n', _0_, 'N', _0_, _0_, _0_, _0_, _0_, 'j', _0_, _0_, _0_, - /* 80 */ ',', CRLF, ':', _0_, '-', _0_, '?', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 90 */ 'w', _0_, 'W', _0_, 'x', _0_, 'X', _0_, 's', _0_, 'S', _0_, 't', _0_, 'T', _0_, - /* A0 */ 'z', _0_, 'Z', _0_, 'y', _0_, 'Y', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* B0 */ 'u', _0_, 'U', _0_, 'v', _0_, 'V', _0_, _0_, _0_, _0_, _0_, '/', _0_, '_', _0_, - /* C0 */ '#', _0_, '=', _0_, '0', _0_, '|', _0_, _0_, _0_, _0_, _0_, _0_, _0_, 'J', _0_, + /* 00 */ '.', IGNR_,CENT_, '\n', '@', IGNR_,'%', _0_, _0_, IGNR_,_0_, _0_, _0_, _0_, _0_, _0_, + /* 10 */ 'F', '\b', 'f', _0_, 'G', _0_, 'g', _0_, 'B', _0_, 'b', _0_, 'C', _0_, 'c', _0_, + /* 20 */ 'I', ' ', 'i', _0_, 'H', _0_, 'h', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, + /* 30 */ 'D', _0_, 'd', _0_, 'E', _0_, 'e', _0_, _0_, _0_, _0_, _0_, 'A', _0_, 'a', _0_, + /* 40 */ '$', '\t', '!', _0_, '&', _0_, '>', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, + /* 50 */ 'O', _0_, 'o', _0_, 'P', _0_, 'o', _0_, 'K', _0_, 'k', _0_, 'L', _0_, 'l', _0_, + /* 60 */ 'R', _0_, 'r', _0_, 'Q', _0_, 'q', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, + /* 70 */ 'M', _0_, 'm', _0_, 'N', _0_, 'n', _0_, _0_, _0_, _0_, _0_, 'J', _0_, 'j', _0_, + /* 80 */ ',', CRLF_, ':', _0_, '-', _0_, '?', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, + /* 90 */ 'W', _0_, 'w', _0_, 'X', _0_, 'x', _0_, 'S', _0_, 's', _0_, 'T', _0_, 't', _0_, + /* A0 */ 'Z', _0_, 'z', _0_, 'Y', _0_, 'y', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, + /* B0 */ 'U', _0_, 'u', _0_, 'V', _0_, 'v', _0_, _0_, _0_, _0_, _0_, '/', _0_, '_', _0_, + /* C0 */ '#', _0_, '=', _0_, '0', _0_, '|', _0_, _0_, _0_, _0_, _0_, 'J', _0_, 'j', _0_, /* D0 */ '6', _0_, ';', _0_, '7', _0_, '*', _0_, '2', _0_, '+', _0_, '3', _0_, '<', _0_, /* E0 */ '9', _0_, '"', _0_, '8', _0_, '\'', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* F0 */ '4', _0_, NOT, _0_, '5', _0_, ')', _0_, _0_, _0_, _0_, _0_, '1', _0_, '(', _0_, + /* F0 */ '4', _0_, NOT_, _0_, '5', _0_, ')', _0_, _0_, _0_, _0_, _0_, '1', _0_, '(', _0_, }; +#ifdef _MSC_VER +# pragma warning(default:4245) /* enable int->char demotion warning */ +#endif diff --git a/Ibm1130/ibm1130_cpu.c b/Ibm1130/ibm1130_cpu.c index 96f9767c..f258bda8 100644 --- a/Ibm1130/ibm1130_cpu.c +++ b/Ibm1130/ibm1130_cpu.c @@ -9,13 +9,14 @@ * or modifications. * * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org + * Mail to simh@ibm1130.org 25-Jun-01 BLK Written 10-May-02 BLK Fixed bug in MDX instruction 27-Mar-02 BLK Made BOSC work even in short form 16-Aug-02 BLK Fixed bug in multiply instruction; didn't work with negative values 18-Mar-03 BLK Fixed bug in divide instruction; didn't work with negative values + 23-Jul-03 BLK Prevented tti polling in CGI mode The register state for the IBM 1130 CPU is: @@ -470,23 +471,17 @@ t_stat sim_instr (void) if (wait_state) { /* waiting? */ sim_interval = 0; /* run the clock out */ - if (sim_qcount() <= 1) { /* waiting for keyboard only */ - if (keyboard_is_locked()) { /* CPU is not expecting a keystroke */ + if (sim_qcount() <= (cgi ? 0 : 1)) { /* one routine queued? we're waiting for keyboard only */ + if (keyboard_is_busy()) { /* we are actually waiting for a keystroke */ + if ((status = sim_process_event()) != 0) /* get it with wait_state still set */ + reason = status; + } + else { /* CPU is not expecting a keystroke (keyboard interrupt) */ if (wait_state == WAIT_OP) - reason = STOP_WAIT; /* end the simulation */ + reason = STOP_WAIT; /* end the simulation */ else reason = STOP_INVALID_INSTR; } - else { /* we are actually waiting for a keystroke */ - if ((status = sim_process_event()) != 0) /* get it with wait_state still set */ - reason = status; - } - } - else if (sim_clock_queue == NULL) { /* not waiting for anything */ - if (wait_state == WAIT_OP) - reason = STOP_WAIT; /* end the simulation */ - else - reason = STOP_INVALID_INSTR; } if (gdu_active()) /* but don't stop simulator if 2250 GDU is running */ @@ -1254,7 +1249,7 @@ void xio_error (char *msg) * register_cmd - add a command to the extensible command table * ------------------------------------------------------------------------ */ -t_stat register_cmd (char *name, t_stat (*action)(int32, char *), int arg, char *help) +t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help) { int i; diff --git a/Ibm1130/ibm1130_cr.c b/Ibm1130/ibm1130_cr.c index 033f4982..283d107c 100644 --- a/Ibm1130/ibm1130_cr.c +++ b/Ibm1130/ibm1130_cr.c @@ -1,4 +1,5 @@ #include "ibm1130_defs.h" +#include "ibm1130_fmt.h" /* ibm1130_cr.c: IBM 1130 1442 Card Reader simulator @@ -11,7 +12,210 @@ * or modifications. * * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org + * Mail to simh@ibm1130.org + + * Update 2003-07-23: Added autodetect for card decks (029 vs binary), + made this the default. + + * Update 2003-06-21: Fixed bug in XIO_SENSE: op_complete and response + bits were being cleared before the DSW was saved in ACC. Somehow DMS + worked with this, but APL didn't. + + * Update 2002-02-29: Added deck-list option. + + * Update 2003-02-08: Fixed error in declaration of array list_save, pointed + out by Ray Comas. + +* ----------------------------------------------------------------------- +* USAGE NOTES +* ----------------------------------------------------------------------- + +* Attach switches: + + The ATTACH CR command accepts several command-line switches + + -q quiet mode, the simulator will not print the name of each file it opens + while processing deck files (which are discussed below). For example, + + ATTACH -q @deckfile + + -l makes the simulator convert lower case letters in text decks + to the IBM lower-case Hollerith character codes. Normally, the simulator + converts lower case input to the uppercase Hollerith character codes. + (Lowercase codes are used in APL\1130 save decks). + + -d prints a lot of simulator debugging information + + -f converts tabs in an ascii file to spaces according to Fortran column conventions + -a converts tabs in an ascii file to spaces according to 1130 Assembler column conventions + -t converts tabs in an ascii file to spaces, with tab settings every 8 columns + + (See below for a discussion of tab formatting) + + The ATTACH CP command accepts the -d switch. + +* Deck lists + If you issue an attach command and specify the filename as + "@filename", the file is interpreted as a list of filenames to + be read in sequence; the effect is that the reader sees the concatenation + of all of the files listed. The simulator "reset" does NOT rewind the deck list. + + Filenames may be quoted if they contain spaces. + + The strings %1, %2, etc, if they appear, are replaced with arguments passed + on the attach command line after the name of the deckfile. These can be the + arguments to ibm1130, or to the "do" command if a "do" script is executing, if the + attach command is constructed this way: + + attach @deckfile %1 %2 %3 + + This will pass the ibm1130 or do script arguments to attach, which will make + them available in the deckfile. Then, for instance the line + + %1.for + + would be substituted accordingly. + + Blank lines and lines starting with ; # or * are ignored as comments. + + Filenames may be followed by whitespace and one or more mode options: + The mode options are: + + b forces interpration as raw binary + a forces conversion from ascii to 029 coding, tabs are left alone + af forces 029 ascii conversion, and interprets tabs in Fortran mode + aa forces 029 ascii conversion, and interprets tabs in 1130 Assembler mode + at forces 029 ascii conversion, and interprets tabs with settings every 8 spaces + + If "a" or "b" mode is not specified, the device mode setting is used. In this case, + if the mode is "auto", the simulator will select binary or 029 by inspecting each + file in turn. + + If a tab mode is not specified, tabs are left unmolested (and are treated as invalid characters) + + Example: + + attach cr @decklist + + reads filenames from file "decklist," which might contain: + + file01.for xf + file02.dat a + file03 bin b + file04 bin + + ('a' means 029, so, if you need 026 coding, specify the + device default as the correct 026 code and omit the 'a' on the text files lines). + + Literal text cards can be entered in deck files by preceding an input + line with an exclamation point. For example, + + !// JOB + !// FOR + program.for + !// XEQ + program.dat + + looks like two literal supervisor control cards, followed by the contents + of file program.for, followed by an // XEQ card, followed by the contents + of file program.dat. + + %n tokens are not replaced in literal cards. + + The line + + !BREAK + + has a special meaning: when read from a deck file, it stops the + emulator as if "IMMEDIATE STOP" was pressed. This returns control to + the command interpreter or to the current DO command script. + +* Card image format. + Card files can be ascii text or binary. There are several ASCII modes: + CODE_029, CODE_26F, etc, corresponding to different code sets. + Punch and reader modes can be set independently using + + set cr binary set cp binary * + set cr 029 set cp 029 + set cr 026f set cp 026f + set cr 026c set cp 026c + set cr auto * + + (* = default mode) + + In "auto" mode, the card reader will examine the first 160 bytes of + the deck and guess whether the card is binary or 029 text encoded. + When a deck file is used with auto mode, the simulator guesses for + each file named in the deck file. + +* Tab formatting. The attach command and deckfile entries can indicate + that tabs are to be converted to spaces, to help let you write free-form + source files. There are three tab conversion modes, which are set + with the attach command or in a decklist, as discussed earlier + + Fortran mode: + Input lines of the form + + [label]statement + + or + + [label]+continuation + + (where + is any nonalphabetic character) are rearranged in the + appropriate manner: + + 1 2 + 12345678901234567890... + ------------------------ + label statement + label+continuation + + However, you must take care that you don't end up with statement text after column 72. + + Input lines with * or C in column 1 (comments and directives) and lines without tabs + are left alone. + + (The ! escape is not used before Fortran directives as before Assembler directives) + + Assembler mode: + Input lines of the form + + [label][opcode][tag][L][argument] + + are rearranged so that the input fields are placed in the appropriate columns + + The label must start on the first character of the line. If there is no label, + the first character(s) before the opcode must be whitespace. Following the opcode, there + MUST be a tab character, followed by the format and tag. Following the format and tag + may be exactly one whitespace character, and then starts the argument. + + Input lines with * in column 1 and blank lines are turned into Assembler comments, + with the * in the Opcode field. + + Assembler directive lines at the beginning of the deck must be preceded by + ! to indicate that they are not comments. For example, + + !*LIST + * This is a comment + + Plain Tab mode: + Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide, + as is standard for vi, notepad, etc. + +* CGI mode note: The command + + attach cr - + + will attach the card reader to stdin. However, this is not compatible + with the default encoding autodetect feature, so the command must be + preceded with + + set cr 029 + +* ----------------------------------------------------------------------- +* PROGRAMMING NOTES +* ----------------------------------------------------------------------- NOTE - there is a problem with this code. The Device Status Word (DSW) is computed from current conditions when requested by an XIO load status @@ -20,45 +224,6 @@ commands may NOT be accurate. This should probably be fixed. (I think there's a way to have the expression evaluator call a routine? That would be one way to solve the problem, the other is to keep DSW up-to-date all the time). -* Update 2003-02-08: Fixed error in declaration of array list_save, pointed - out by Ray Comas. - -* Update 2002-02-29: Added deck-list option. If you issue an attach - command and specify the filename as "@filename", the named file is interpreted - as a list of filenames to be read in sequence; the effect is that the reader - sees the concatenation of all of the files named. "reset" rewinds the deck - list. Filenames can be followed by whitespace and the letter "a" or "b", - which indicates "ascii to 029" or "binary", respectively. Example: - - attach cr @decklist - - where file "decklist" contains: - - file01 a - file02 b - file03 b - file04 b - - If "a" or "b" is not specified, the device mode setting is used. - - ('a' means 029, so, if you need 026 coding, specify the - device default as the correct 026 code and omit the 'a' on the text files lines). - -* note: I'm not sure but I think we'll need a way to simulate the 'start' - button. What may end up being necessary is to fake this in the 'attach' - command. In a GUI build we may want to wait until they press a button. - Have to research: does DMS issue a read request which is only - satisfied when START is pressed, or does START cause an interrupt that - then asks DMS to issue a read request. I think it's the former but need - to check. After all the status register says "empty" and "not ready" - when the hopper is empty. So what gives? On the 360 I think the start - button causes issues some sort of attention request. - -* Card image format. - Card files can be ascii text or binary. There are several ASCII modes: - CODE_029, CODE_26F, etc, corresponding to different code sets. - Punch and reader modes can be set independently. - The 1442 card read/punch has several cycles: feed cycle: moves card from hopper to read station @@ -85,10 +250,10 @@ way to solve the problem, the other is to keep DSW up-to-date all the time). the appropriate buffer, so you can punch w/o attaching a deck to the card reader. -// -- this may need changing depending on how things work in hardware. TBD. +-- -- this may need changing depending on how things work in hardware. TBD. || A read cycle on an empty deck causes an error. || Hmmm -- what takes the place of the Start button on -\\ the card reader? +-- the card reader? Binary format is stored using fxwrite of short ints, in this format: @@ -127,7 +292,7 @@ way to solve the problem, the other is to keep DSW up-to-date all the time). 9 | +------------------ - - - - 12 11 0 1 2 3 4 5 6 7 8 9 + 12 11 0 1 2 3 4 5 6 7 8 9 <- columns of cold start card | | | | | 0 0 0 / \ | | | | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15| @@ -140,66 +305,88 @@ way to solve the problem, the other is to keep DSW up-to-date all the time). it's a sign bit. Boot command on a binary deck does this. Boot on an unattached - reader loads the standard boot2 card image. Boot with an ASCII - deck will not be very helpful. + reader loads one of the built-in boot card images. Boot with an ASCII + deck isn't allowed. */ #define READ_DELAY 35 // see how small a number we can get away with #define PUNCH_DELAY 35 #define FEED_DELAY 25 +// umm, this is a weird little future project of mine. +// #define ENABLE_PHYSICAL_CARD_READER_SUPPORT + // #define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) extern int32 sim_switches; +extern UNIT cpu_unit; static t_stat cr_svc (UNIT *uptr); static t_stat cr_reset (DEVICE *dptr); static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc); static t_stat cr_attach (UNIT *uptr, char *cptr); static t_stat cr_detach (UNIT *uptr); +static int32 guess_cr_code (void); static t_stat cp_reset (DEVICE *dptr); static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc); +static t_stat cp_attach (UNIT *uptr, char *cptr); static t_stat cp_detach (UNIT *uptr); static int16 cr_dsw = 0; /* device status word */ static int32 cr_wait = READ_DELAY; /* read per-column wait */ static int32 cf_wait = PUNCH_DELAY; /* punch per-column wait */ static int32 cp_wait = FEED_DELAY; /* feed op wait */ +static int32 cr_count= 0; /* read and punch card count */ +static int32 cp_count= 0; #define UNIT_V_OPERATION (UNIT_V_UF + 0) /* operation in progress */ -#define UNIT_V_CODE (UNIT_V_UF + 2) -#define UNIT_V_EMPTY (UNIT_V_UF + 4) -#define UNIT_V_SCRATCH (UNIT_V_UF + 5) -#define UNIT_V_QUIET (UNIT_V_UF + 6) -#define UNIT_V_DEBUG (UNIT_V_UF + 7) - -#define UNIT_V_LASTPUNCH (UNIT_V_UF + 0) /* bit in unit_cp flags */ +#define UNIT_V_CODE (UNIT_V_UF + 2) /* three bits */ +#define UNIT_V_EMPTY (UNIT_V_UF + 5) +#define UNIT_V_SCRATCH (UNIT_V_UF + 6) +#define UNIT_V_QUIET (UNIT_V_UF + 7) +#define UNIT_V_DEBUG (UNIT_V_UF + 8) +#define UNIT_V_PHYSICAL (UNIT_V_UF + 9) +#define UNIT_V_LASTPUNCH (UNIT_V_UF + 10) /* used in unit_cp only */ +#define UNIT_V_LOWERCASE (UNIT_V_UF + 10) /* used in unit_cr only */ +#define UNIT_V_ACTCODE (UNIT_V_UF + 11) /* used in unit_cr only, 3 bits */ #define UNIT_OP (3u << UNIT_V_OPERATION) /* two bits */ -#define UNIT_CODE (3u << UNIT_V_CODE) /* two bits */ +#define UNIT_CODE (7u << UNIT_V_CODE) /* three bits */ #define UNIT_EMPTY (1u << UNIT_V_EMPTY) #define UNIT_SCRATCH (1u << UNIT_V_SCRATCH) /* temp file */ #define UNIT_QUIET (1u << UNIT_V_QUIET) #define UNIT_DEBUG (1u << UNIT_V_DEBUG) - +#define UNIT_PHYSICAL (1u << UNIT_V_PHYSICAL) #define UNIT_LASTPUNCH (1u << UNIT_V_LASTPUNCH) +#define UNIT_LOWERCASE (1u << UNIT_V_LOWERCASE) /* permit lowercase input (needed for APL) */ +#define UNIT_ACTCODE (7u << UNIT_V_ACTCODE) #define OP_IDLE (0u << UNIT_V_OPERATION) #define OP_READING (1u << UNIT_V_OPERATION) #define OP_PUNCHING (2u << UNIT_V_OPERATION) #define OP_FEEDING (3u << UNIT_V_OPERATION) -#define SET_OP(op) {cr_unit.flags &= ~UNIT_OP; cr_unit.flags |= op;} - +#define SET_OP(op) {cr_unit.flags &= ~UNIT_OP; cr_unit.flags |= (op);} #define CURRENT_OP (cr_unit.flags & UNIT_OP) -#define CODE_029 (0u << UNIT_V_CODE) -#define CODE_026F (1u << UNIT_V_CODE) -#define CODE_026C (2u << UNIT_V_CODE) -#define CODE_BINARY (3u << UNIT_V_CODE) +#define CODE_AUTO (0u << UNIT_V_CODE) +#define CODE_029 (1u << UNIT_V_CODE) +#define CODE_026F (2u << UNIT_V_CODE) +#define CODE_026C (3u << UNIT_V_CODE) +#define CODE_BINARY (4u << UNIT_V_CODE) -#define SET_CODE(un,cd) {un.flags &= ~UNIT_CODE; un.flags |= cd;} +#define GET_CODE(un) (un.flags & UNIT_CODE) +#define SET_CODE(un,cd) {un.flags &= ~UNIT_CODE; un.flags |= (cd);} + +#define ACTCODE_029 (CODE_029 << (UNIT_V_ACTCODE-UNIT_V_CODE)) // these are used ONLY in MTAB. Elsewhere +#define ACTCODE_026F (CODE_026F << (UNIT_V_ACTCODE-UNIT_V_CODE)) // we use values CODE_xxx with macros +#define ACTCODE_026C (CODE_026C << (UNIT_V_ACTCODE-UNIT_V_CODE)) // GET_ACTCODE and SET_ACTCODE. +#define ACTCODE_BINARY (CODE_BINARY << (UNIT_V_ACTCODE-UNIT_V_CODE)) + + // get/set macros for actual-code field, these use values like CODE_029 meant for the UNIT_CODE field +#define GET_ACTCODE(un) ((un.flags & UNIT_ACTCODE) >> (UNIT_V_ACTCODE-UNIT_V_CODE)) +#define SET_ACTCODE(un,cd) {un.flags &= ~UNIT_ACTCODE; un.flags |= (cd) << (UNIT_V_ACTCODE-UNIT_V_CODE);} #define COLUMN u4 /* column field in unit record */ @@ -207,10 +394,15 @@ UNIT cr_unit = { UDATA (&cr_svc, UNIT_ATTABLE|UNIT_ROABLE, 0) }; UNIT cp_unit = { UDATA (NULL, UNIT_ATTABLE, 0) }; MTAB cr_mod[] = { - { UNIT_CODE, CODE_029, "029", "029", &cr_set_code}, - { UNIT_CODE, CODE_026F, "026F", "026F", &cr_set_code}, - { UNIT_CODE, CODE_026C, "026C", "026C", &cr_set_code}, - { UNIT_CODE, CODE_BINARY, "BINARY", "BINARY", &cr_set_code}, + { UNIT_CODE, CODE_029, "029", "029", &cr_set_code}, + { UNIT_CODE, CODE_026F, "026F", "026F", &cr_set_code}, + { UNIT_CODE, CODE_026C, "026C", "026C", &cr_set_code}, + { UNIT_CODE, CODE_BINARY, "BINARY", "BINARY", &cr_set_code}, + { UNIT_CODE, CODE_AUTO, "AUTO", "AUTO", &cr_set_code}, + { UNIT_ACTCODE, ACTCODE_029, "(029)", NULL, NULL}, /* display-only, shows current mode */ + { UNIT_ACTCODE, ACTCODE_026F, "(026F)", NULL, NULL}, + { UNIT_ACTCODE, ACTCODE_026C, "(026C)", NULL, NULL}, + { UNIT_ACTCODE, ACTCODE_BINARY, "(BINARY)", NULL, NULL}, { 0 } }; MTAB cp_mod[] = { @@ -224,10 +416,12 @@ REG cr_reg[] = { { HRDATA (CRDSW, cr_dsw, 16) }, /* device status word */ { DRDATA (CRTIME, cr_wait, 24), PV_LEFT }, /* operation wait */ { DRDATA (CFTIME, cf_wait, 24), PV_LEFT }, /* operation wait */ + { DRDATA (CRCOUNT, cr_count, 32),PV_LEFT }, /* number of cards read since last attach cmd */ { NULL } }; REG cp_reg[] = { { DRDATA (CPTIME, cp_wait, 24), PV_LEFT }, /* operation wait */ + { DRDATA (CPCOUNT, cp_count, 32),PV_LEFT }, /* number of cards punched since last attach cmd */ { NULL } }; DEVICE cr_dev = { @@ -240,7 +434,7 @@ DEVICE cp_dev = { "CP", &cp_unit, cp_reg, cp_mod, 1, 16, 16, 1, 16, 16, NULL, NULL, cp_reset, - NULL, NULL, cp_detach}; + NULL, cp_attach, cp_detach}; #define CR_DSW_READ_RESPONSE 0x8000 /* device status word bits */ #define CR_DSW_PUNCH_RESPONSE 0x4000 @@ -252,7 +446,7 @@ DEVICE cp_dev = { #define CR_DSW_NOT_READY 0x0001 typedef struct { - int hollerith; + uint16 hollerith; char ascii; } CPCODE; @@ -304,7 +498,7 @@ static CPCODE cardcode_029[] = 0x0120, '\'', 0x00A0, '=', 0x0060, '"', - 0x8820, 'c', // cent + 0x8820, '\xA2', // cent, in MS-DOS encoding (this is in guess_cr_code as well) 0x8420, '.', 0x8220, '<', // ) in 026 Fortran 0x8120, '(', @@ -315,13 +509,48 @@ static CPCODE cardcode_029[] = 0x4220, '*', 0x4120, ')', 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? + 0x4060, '\xAC', // not, in MS-DOS encoding (this is in guess_cr_code as well) 0x2420, ',', 0x2220, '%', // ( in 026 Fortran 0x2120, '_', 0x20A0, '>', - 0x2060, '>', + 0xB000, 'a', + 0xA800, 'b', + 0xA400, 'c', + 0xA200, 'd', + 0xA100, 'e', + 0xA080, 'f', + 0xA040, 'g', + 0xA020, 'h', + 0xA010, 'i', + 0xD000, 'j', + 0xC800, 'k', + 0xC400, 'l', + 0xC200, 'm', + 0xC100, 'n', + 0xC080, 'o', + 0xC040, 'p', + 0xC020, 'q', + 0xC010, 'r', + 0x6800, 's', + 0x6400, 't', + 0x6200, 'u', + 0x6100, 'v', + 0x6080, 'w', + 0x6040, 'x', + 0x6020, 'y', + 0x6010, 'z', // these odd punch codes are used by APL: + 0x1010, '\001', // no corresponding ASCII using ^A + 0x0810, '\002', // SYN using ^B + 0x0410, '\003', // no corresponding ASCII using ^C + 0x0210, '\004', // PUNCH ON using ^D + 0x0110, '\005', // READER STOP using ^E + 0x0090, '\006', // UPPER CASE using ^F + 0x0050, '\013', // EOT using ^K + 0x0030, '\016', // no corresponding ASCII using ^N + 0x1030, '\017', // no corresponding ASCII using ^O + 0x0830, '\020', // no corresponding ASCII using ^P + }; static CPCODE cardcode_026F[] = // 026 fortran @@ -435,7 +664,6 @@ static int16 ascii_to_card[256]; static CPCODE *cardcode; static int ncardcode; -static int32 active_cr_code; /* the code most recently specified */ static FILE *deckfile = NULL; static char tempfile[128]; static int cardnum; @@ -445,14 +673,24 @@ static int any_punched = 0; #define MAXARGS 10 /* max number of arguments to save */ static char list_save[MAXARGS][MAXARGLEN], *list_arg[MAXARGLEN]; static int list_nargs = 0; +static char* (*tab_proc)(char*) = NULL; /* tab reformatting routine */ -static int16 punchstation[80]; -static int16 readstation[80]; +static uint16 punchstation[80]; +static uint16 readstation[80]; static enum {STATION_EMPTY, STATION_LOADED, STATION_READ, STATION_PUNCHED} punchstate = STATION_EMPTY, readstate = STATION_EMPTY; static t_bool nextdeck (void); static void checkdeck (void); +static t_stat pcr_attach(UNIT *uptr, char *devname); +static t_stat pcr_detach(UNIT *uptr); +static t_stat pcr_svc(UNIT *uptr); +static void pcr_xio_sense(int modify); +static void pcr_xio_feedcycle(void); +static void pcr_xio_startread(void); +static void pcr_reset(void); +static int pcr_read_data(void); + /* lookup_codetable - use code flag setting to get code table pointer and length */ static t_bool lookup_codetable (int32 match, CPCODE **pcode, int *pncode) @@ -490,7 +728,7 @@ t_stat set_active_cr_code (int match) CPCODE *code; int i, ncode; - active_cr_code = match; + SET_ACTCODE(cr_unit, match); if (! lookup_codetable(match, &code, &ncode)) return SCPE_ARG; @@ -498,16 +736,76 @@ t_stat set_active_cr_code (int match) memset(ascii_to_card, 0, sizeof(ascii_to_card)); for (i = 0; i < ncode; i++) // set ascii to card code table - ascii_to_card[code[i].ascii] = (int16) code[i].hollerith; + ascii_to_card[code[i].ascii] = code[i].hollerith; return SCPE_OK; } static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) { + if (match == CODE_AUTO) + match = guess_cr_code(); + return set_active_cr_code(match); } +static int32 guess_cr_code (void) +{ + int i; + long filepos; + int32 guess; + union { + uint16 w[80]; // one card image, viewed as 80 short words + char c[160]; // same, viewed as 160 characters + } line; + + // here, we can see if the attached file is binary or ascii and auto-set the + // mode. If we the file is a binary deck, we should be able to read a record of 80 short + // words, and the low 4 bits of each word must be zero. If the file was an ascii deck, + // then these low 4 bits are the low 4 bits of every other character in the first 160 + // chararacters of the file. They would all only be 0 if all of these characters were + // in the following set: {NUL ^P space 0 @ P ` p} . It seems very unlikely that + // this would happen, as even if the deck consisted of untrimmed card images and + // the first two lines were blank, the 81'st character would be a newline, and it would + // appear at one of the every-other characters seen on little-endian machines, anyway. + // So: if the code mode is AUTO, we can use this test and select either BINARY or 029. + // Might as well also check for the all-blanks and newlines case in case this is a + // big-endian machine. + + + guess = CODE_029; // assume ASCII, 029 + + if ((cr_unit.flags & UNIT_ATT) && (cr_unit.fileref != NULL)) { + filepos = ftell(cr_unit.fileref); // remember current position in file + fseek(cr_unit.fileref, 0, SEEK_SET); // go to first record of file + // read card image; if file too short, leave guess set to 029 + if (fxread(line.w, sizeof(line.w[0]), 80, cr_unit.fileref) == 80) { + guess = CODE_BINARY; // we got a card image, assume binary + + for (i = 0; i < 80; i++) { // make sure low bits are zeroes, which our binary card format promises + if (line.w[i] & 0x000F) { + guess = CODE_029; // low bits set, must be ascii text + break; + } + } + + if (guess == CODE_BINARY) { // if we saw no low bits, it could have been all spaces. + guess = CODE_029; // so now assume file is text + for (i = 0; i < 160; i++) { // ensure all 160 characters are 7-bit ASCII (or not or cent) + if ((strchr("\r\n\t\xA2\xAC", line.c[i]) == NULL) && ! BETWEEN(line.c[i], ' ', '\x7F')) { + guess = CODE_BINARY; // oops, null or weird character, it's binary after all + break; + } + } + } + } + + fseek(cr_unit.fileref, filepos, SEEK_SET); // return to original position + } + + return guess; +} + static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) { CPCODE *code; @@ -522,12 +820,13 @@ static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) return SCPE_OK; } -t_stat load_cr_boot (int drvno) +t_stat load_cr_boot (int drvno, int switches) { - /* this is from the "boot2" cold start card. Columns have been */ - /* expanded already from 12 to 16 bits. */ - - static unsigned short boot2_data[] = { + int i; + char *name, msg[80]; + t_bool expand; + uint16 word, *boot; + static uint16 dms_boot_data[] = { /* DMSV2M12, already expanded to 16 bits */ 0xc80a, 0x18c2, 0xd008, 0xc019, 0x8007, 0xd017, 0xc033, 0x100a, 0xd031, 0x7015, 0x000c, 0xe800, 0x0020, 0x08f8, 0x4828, 0x7035, 0x70fa, 0x4814, 0xf026, 0x2000, 0x8800, 0x9000, 0x9800, 0xa000, @@ -539,41 +838,93 @@ t_stat load_cr_boot (int drvno) 0x080d, 0x08c4, 0x1003, 0x4810, 0x70d9, 0x3000, 0x08df, 0x3000, 0x7010, 0x00d1, 0x0028, 0x000a, 0x70f3, 0x0000, 0x00d0, 0xa0c0 }; - int i; + static uint16 apl_boot_data[] = { /* APLIPL, already expanded */ + 0x7021, 0x3000, 0x7038, 0xa0c0, 0x0002, 0x4808, 0x0003, 0x0026, + 0x0001, 0x0001, 0x000c, 0x0000, 0x0000, 0x0800, 0x48f8, 0x0027, + 0x7002, 0x08f2, 0x3800, 0xe0fe, 0x18cc, 0x100e, 0x10c1, 0x4802, + 0x7007, 0x4828, 0x7005, 0x4804, 0x7001, 0x70f3, 0x08e7, 0x70e1, + 0x08ed, 0x70f1, 0xc0e0, 0x1807, 0xd0de, 0xc0df, 0x1801, 0xd0dd, + 0x800d, 0xd00c, 0xc0e3, 0x1005, 0xe80a, 0xd009, 0xc0d8, 0x1008, + 0xd0d6, 0xc0dd, 0x1008, 0x80d4, 0xd0da, 0x1000, 0xb000, 0x00f6, + 0x70e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9000, 0x4004, 0x40c0, 0x8001, 0x4004, 0x40c0, 0x0000, 0x0000 }; + static uint16 aplp_boot_data[] = { /* APLIPL Privileged, already expanded */ + 0x7021, 0x3000, 0x7038, 0xa0c0, 0x0002, 0x4808, 0x0003, 0x0026, + 0x0001, 0x0001, 0x000c, 0x0000, 0x0000, 0x0800, 0x48f8, 0x0027, + 0x7002, 0x08f2, 0x3800, 0xe0fe, 0x18cc, 0x100e, 0x10c1, 0x4802, + 0x7007, 0x4828, 0x7005, 0x4804, 0x7001, 0x70f3, 0x08e7, 0x70e1, + 0x08ed, 0x70f1, 0xc0e0, 0x1807, 0xd0de, 0xc0df, 0x1801, 0xd0dd, + 0x800d, 0xd00c, 0xc0e3, 0x1005, 0xe80a, 0xd009, 0xc0d8, 0x1008, + 0xd0d6, 0xc0dd, 0x1008, 0x80d4, 0xd0da, 0x1002, 0xb000, 0x00f6, + 0x70e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x9000, 0x4004, 0x40c0, 0x8001, 0x4004, 0x40c0, 0x4004, 0x4001 + }; + + if ((switches & SWMASK('A')) && (switches & SWMASK('P'))) { + boot = aplp_boot_data; + name = "APL\\1130 Privileged"; + expand = FALSE; + } + else if (switches & SWMASK('A')) { + boot = apl_boot_data; + name = "APL\\1130"; + expand = FALSE; + } + else { + boot = dms_boot_data; + name = "DMS V2M12"; + expand = FALSE; + } if (drvno >= 0) /* if specified, set toggle switches to disk drive no */ - CES = drvno; /* so BOOT DSK1 will work correctly */ + CES = drvno; /* so BOOT DSK1 will work correctly (DMS boot uses this) */ IAR = 0; /* clear IAR */ - for (i = 0; i < 80; i++) /* copy memory */ - WriteW(i, boot2_data[i]); + for (i = 0; i < 80; i++) { /* store the boot image to core words 0..79 */ + word = boot[i]; /* expanding the 12-bit card data to 16 bits if not already expanded */ + if (expand) + word = (word & 0xF800) | ((word & 0x0400) ? 0x00C0 : 0x0000) | ((word & 0x03F0) >> 4); + + WriteW(i, word); + } + /* quiet switch or CGI mode inhibit the boot remark */ + if ((switches & SWMASK('Q') == 0) && ! cgi) { + sprintf(msg,"Loaded %s cold start card\n", name); #ifdef GUI_SUPPORT - if (! cgi) - remark_cmd("Loaded BOOT2 cold start card\n"); + remark_cmd(msg); +#else + printf(msg); #endif + } + return SCPE_OK; } t_stat cr_boot (int unitno, DEVICE *dptr) { t_stat rval; - short buf[80]; + uint16 buf[80]; int i; if ((rval = reset_all(0)) != SCPE_OK) return rval; - if (! (cr_unit.flags & UNIT_ATT)) // no deck; load standard boot anyway - return load_cr_boot(-1); + if (! (cr_unit.flags & UNIT_ATT)) /* no deck; load standard boot anyway */ + return load_cr_boot(-1, 0); - if ((active_cr_code & UNIT_CODE) != CODE_BINARY) { + if (GET_ACTCODE(cr_unit) != CODE_BINARY) { printf("Can only boot from card reader when set to BINARY mode"); return SCPE_IOERR; } - if (fxread(buf, sizeof(short), 80, cr_unit.fileref) != 80) + if (cr_unit.fileref == NULL) /* this will happen if no file in deck file can be opened */ + return SCPE_IOERR; + + if (fxread(buf, sizeof(buf[0]), 80, cr_unit.fileref) != 80) return SCPE_IOERR; IAR = 0; /* Program Load sets IAR = 0 */ @@ -584,7 +935,7 @@ t_stat cr_boot (int unitno, DEVICE *dptr) return SCPE_OK; } -char card_to_ascii (int16 hol) +char card_to_ascii (uint16 hol) { int i; @@ -592,12 +943,12 @@ char card_to_ascii (int16 hol) if (cardcode[i].hollerith == hol) return cardcode[i].ascii; - return ' '; + return '?'; } // hollerith_to_ascii - provide a generic conversion for simulator debugging -char hollerith_to_ascii (int16 hol) +char hollerith_to_ascii (uint16 hol) { int i; @@ -612,18 +963,18 @@ char hollerith_to_ascii (int16 hol) static void feedcycle (t_bool load, t_bool punching) { - char buf[84], *x; + char buf[84], *x, *result; int i, nread, nwrite, ch; /* write punched card if punch is attached to a file */ if (cp_unit.flags & UNIT_ATT) { if (any_punched && punchstate != STATION_EMPTY) { - if ((cp_unit.flags & UNIT_CODE) == CODE_BINARY) { - fxwrite(punchstation, sizeof(short), 80, cp_unit.fileref); + if (GET_CODE(cp_unit) == CODE_BINARY) { + fxwrite(punchstation, sizeof(punchstation[0]), 80, cp_unit.fileref); } else { for (i = 80; --i >= 0; ) { /* find last nonblank column */ - if (buf[i] != 0) + if (punchstation[i] != 0) break; } @@ -635,10 +986,15 @@ static void feedcycle (t_bool load, t_bool punching) /* nwrite is now number of characters to output */ +#ifdef WIN32 + buf[nwrite++] = '\r'; /* add CR before NL for microsoft */ +#endif buf[nwrite++] = '\n'; /* append newline */ fxwrite(buf, sizeof(char), nwrite, cp_unit.fileref); } } + + cp_count++; } if (! load) // all we wanted to do was flush the punch @@ -672,17 +1028,17 @@ again: /* jump here if we've loaded a new deck after emptying the previous one if (cr_unit.fileref == NULL) nread = 0; - else if ((active_cr_code & UNIT_CODE) == CODE_BINARY) /* binary read is straightforward */ - nread = fxread(readstation, sizeof(short), 80, cr_unit.fileref); + else if (GET_ACTCODE(cr_unit) == CODE_BINARY) /* binary read is straightforward */ + nread = fxread(readstation, sizeof(readstation[0]), 80, cr_unit.fileref); else if (fgets(buf, sizeof(buf), cr_unit.fileref) == NULL) /* read up to 80 chars */ - nread = 0; /* hmm, end of file */ + nread = 0; /* hmm, end of file */ - else { /* check for newline */ + else { /* check for newline */ if ((x = strchr(buf, '\r')) == NULL) x = strchr(buf, '\n'); - if (x == NULL) { /* there were no delimiters, burn rest of line */ + if (x == NULL) { /* there were no delimiters, burn rest of line */ while ((ch = getc(cr_unit.fileref)) != EOF) { /* get character */ if (ch == '\n') /* newline, done */ break; @@ -700,10 +1056,19 @@ again: /* jump here if we've loaded a new deck after emptying the previous one else nread = x-buf; /* reduce length of string */ - upcase(buf); /* force uppercase */ + if (! (cr_unit.flags & UNIT_LOWERCASE)) + upcase(buf); /* force uppercase */ + + if (tab_proc != NULL) { /* apply tab editing, if specified */ + buf[nread] = '\0'; /* .. be sure string is terminated */ + result = (*tab_proc)(buf); /* .. convert tabs spaces */ + nread = strlen(result); /* .. set new read length */ + } + else + result = buf; for (i = 0; i < nread; i++) /* convert ascii to punch code */ - readstation[i] = ascii_to_card[buf[i]]; + readstation[i] = ascii_to_card[result[i]]; nread = 80; /* even if line was blank consider it present */ } @@ -712,6 +1077,11 @@ again: /* jump here if we've loaded a new deck after emptying the previous one if (deckfile != NULL && nextdeck()) goto again; + if (punching) /* pretend we loaded a blank card */ + nread = 80; + } + + if (nread == 0) { SETBIT(cr_unit.flags, UNIT_EMPTY); readstate = STATION_EMPTY; cardnum = -1; /* nix the card counter */ @@ -720,10 +1090,11 @@ again: /* jump here if we've loaded a new deck after emptying the previous one CLRBIT(cr_unit.flags, UNIT_EMPTY); readstate = STATION_LOADED; cardnum++; /* advance card counter */ + cr_count++; } } - else - readstate = STATION_EMPTY; +// else +// readstate = STATION_EMPTY; cr_unit.COLUMN = -1; /* neither device is currently cycling */ cp_unit.COLUMN = -1; @@ -793,10 +1164,10 @@ static void checkdeck (void) empty = TRUE; } else { - fseek(cr_unit.fileref, 0, SEEK_END); - empty = ftell(cr_unit.fileref) <= 0; /* see if file has anything) */ - fseek(cr_unit.fileref, 0, SEEK_SET); /* rewind deck */ + fseek(cr_unit.fileref, 0, SEEK_END); /* seek to end of file */ + empty = ftell(cr_unit.fileref) <= 0; /* file is empty if there was nothing in it*/ cardnum = 0; /* reset card counter */ + fseek(cr_unit.fileref, 0, SEEK_SET); /* rewind deck */ } if (empty) { @@ -804,15 +1175,16 @@ static void checkdeck (void) if (cr_unit.fileref != NULL) /* real file but it's empty, hmmm, try another */ nextdeck(); } - else + else { CLRBIT(cr_unit.flags, UNIT_EMPTY); + } } /* nextdeck - attempt to load a new file from the deck list into the hopper */ static t_bool nextdeck (void) { - char buf[200], tmpbuf[200], *fname, *mode, *tn; + char buf[200], tmpbuf[200], *fname, *tn, *c, quote, *mode; int code; long fpos; static char white[] = " \t\r\n"; @@ -822,7 +1194,7 @@ static t_bool nextdeck (void) if (deckfile == NULL) /* we can't help */ return FALSE; - code = cr_unit.flags & UNIT_CODE; /* default code */ + code = GET_CODE(cr_unit); /* default code as set */ if (cr_unit.fileref != NULL) { /* this pulls the rug out from under scp */ fclose(cr_unit.fileref); /* since the attach flag is still set. be careful! */ @@ -835,13 +1207,19 @@ static t_bool nextdeck (void) } for (;;) { /* get a filename */ + tab_proc = NULL; /* default: no tab editing */ + if (fgets(buf, sizeof(buf), deckfile) == NULL) break; /* oops, no more names */ - alltrim(buf); + alltrim(buf); /* remove leading and trailing spaces */ + if (! *buf) continue; /* empty line */ + if (*buf == '#' || *buf == '*' || *buf == ';') + continue; /* comment */ + if (strnicmp(buf, "!BREAK", 6) == 0) { /* stop the simulation */ break_simulation(STOP_DECK_BREAK); continue; @@ -866,18 +1244,19 @@ static t_bool nextdeck (void) SETBIT(cr_unit.flags, UNIT_SCRATCH); - for (;;) { /* store literal cards into temporary file */ + for (;;) { /* store literal cards into temporary file */ upcase(buf+1); fputs(buf+1, cr_unit.fileref); putc('\n', cr_unit.fileref); - trace_io("(Literal card %s\n)", buf+1); + if (cpu_unit.flags & UNIT_ATT) + trace_io("(Literal card %s\n)", buf+1); if (! (cr_unit.flags & UNIT_QUIET)) - printf("(Literal card %s)\n", buf+1); + printf( "(Literal card %s)\n", buf+1); fpos = ftell(deckfile); if (fgets(buf, sizeof(buf), deckfile) == NULL) - break; /* oops, end of file */ + break; /* oops, end of file */ if (buf[0] != '!' || strnicmp(buf, "!BREAK", 6) == 0) break; alltrim(buf); @@ -885,47 +1264,102 @@ static t_bool nextdeck (void) fseek(deckfile, fpos, SEEK_SET); /* restore deck file to just before non-literal card */ fseek(cr_unit.fileref, 0, SEEK_SET); /* rewind scratch file for reading */ - code = CODE_029; /* assume keycode 029 */ + code = CODE_029; /* assume literal cards use keycode 029 */ break; } sub_args(buf, tmpbuf, sizeof(buf), list_nargs, list_arg); /* substitute in stuff from the attach command line */ - if ((fname = strtok(buf, white)) == NULL) + fname = c = buf; /* pick filename from string */ + + if (*c == '\'' || *c == '"') { /* quoted string */ + quote = *c; /* remember the quote type */ + strcpy(c, c+1); /* slide string down over the quote */ + while (*c && (*c != quote)) + c++; /* skip to end of quote */ + } + else { /* not quoted; look for terminating whitespace */ + while (*c && (*c > ' ')) + c++; + } + + if (*c) + *c++ = 0; /* term arg at space or closing quote & move to next character */ + + if (! *fname) /* blank line, no filename */ continue; - if (*fname == '#' || *fname == '*' || *fname == ';') - continue; /* comment */ - - if ((mode = strtok(NULL, white)) != NULL) { - if (*mode == 'b' || *mode == 'B') - code = CODE_BINARY; - else if (*mode == 'a' || *mode == 'A') - code = CODE_029; - } - - if ((cr_unit.fileref = fopen(fname, "rb")) == NULL) + if ((cr_unit.fileref = fopen(fname, "rb")) == NULL) { printf("File '%s' specified in deck file '%s' cannot be opened\n", fname, cr_unit.filename+1); - else { - trace_io("(Opened %s deck %s)\n", (code == CODE_BINARY) ? "binary" : "text", fname); - if (! (cr_unit.flags & UNIT_QUIET)) - printf("(Opened %s deck %s)\n", (code == CODE_BINARY) ? "binary" : "text", fname); - break; + continue; } + + mode = c = skipbl(c); /* skip to next token, which would be mode, if present */ + + switch (*c) { + case 'b': + case 'B': + code = CODE_BINARY; /* force code */ + c++; /* accept mode character by moving past it */ + break; + + case 'a': + case 'A': + code = CODE_029; + c++; + + switch (*c) { /* is ascii mode followed by another character? */ + case 'F': + case 'f': + tab_proc = EditToFortran; + c++; + break; + + case 'A': + case 'a': + tab_proc = EditToAsm; + c++; + break; + + case 't': + case 'T': + tab_proc = EditToWhitespace; + c++; + break; + } + } + + if (*skipbl(c)) /* there should be nothing left */ + printf("* Bad mode specifier %s after filename %s in deck file", mode, fname); + + if (code == CODE_AUTO) /* otherwise if mode is auto, guess it, otherwise use default */ + code = guess_cr_code(); + + if (cpu_unit.flags & UNIT_ATT) + trace_io("(Opened %s deck %s%s)\n", (code == CODE_BINARY) ? "binary" : "text", fname, tab_proc ? (*tab_proc)(NULL) : ""); + + if (! (cr_unit.flags & UNIT_QUIET)) + printf( "(Opened %s deck %s%s)\n", (code == CODE_BINARY) ? "binary" : "text", fname, tab_proc ? (*tab_proc)(NULL) : ""); + + break; } checkdeck(); - set_active_cr_code(code); /* set specified code */ + if (code != CODE_AUTO) /* if code was determined, set it */ + set_active_cr_code(code); /* (it may be left at CODE_AUTO when deckfile is exhausted */ return (cr_unit.flags & UNIT_EMPTY) == 0; /* return TRUE if a deck has been loaded */ } static t_stat cr_reset (DEVICE *dptr) { - cr_set_code(&cr_unit, active_cr_code & UNIT_CODE, NULL, NULL); /* reset to specified code table */ + if (GET_ACTCODE(cr_unit) == CODE_AUTO) + SET_ACTCODE(cr_unit, CODE_029); /* if actual code is not yet set, select 029 for now*/ - readstate = STATION_EMPTY; + cr_set_code(&cr_unit, GET_ACTCODE(cr_unit), NULL, NULL); /* reset to specified code table */ + + readstate = STATION_EMPTY; cr_dsw = 0; sim_cancel(&cr_unit); /* cancel any pending ops */ @@ -933,10 +1367,17 @@ static t_stat cr_reset (DEVICE *dptr) SET_OP(OP_IDLE); + cr_unit.COLUMN = -1; /* neither device is currently cycling */ + + if (cr_unit.flags & UNIT_PHYSICAL) { + pcr_reset(); + return SCPE_OK; + } + SETBIT(cr_unit.flags, UNIT_EMPTY); /* assume hopper empty */ if (cr_unit.flags & UNIT_ATT) { -// if (deckfile != NULL) { +// if (deckfile != NULL) { /* do NOT rewind the deck file */ // fseek(deckfile, 0, SEEK_SET); // nextdeck(); // } @@ -947,14 +1388,15 @@ static t_stat cr_reset (DEVICE *dptr) feedcycle(FALSE, FALSE); } - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - return SCPE_OK; } static t_stat cp_reset (DEVICE *dptr) { - cp_set_code(&cp_unit, cp_unit.flags & UNIT_CODE, NULL, NULL); + if (GET_CODE(cp_unit) == CODE_AUTO) + SET_CODE(cp_unit, CODE_BINARY); /* punch is never in auto mode; turn it to binary on startup */ + + cp_set_code(&cp_unit, GET_CODE(cp_unit), NULL, NULL); punchstate = STATION_EMPTY; cp_unit.COLUMN = -1; @@ -970,9 +1412,17 @@ static t_stat cr_attach (UNIT *uptr, char *cptr) // no - don't cancel pending read? // sim_cancel(uptr); /* cancel pending operations */ - CLRBIT(uptr->flags, UNIT_QUIET|UNIT_DEBUG); /* set debug/quiet flags */ + CLRBIT(uptr->flags, UNIT_QUIET|UNIT_DEBUG|UNIT_PHYSICAL|UNIT_LOWERCASE); /* set options */ + + tab_proc = NULL; + if (sim_switches & SWMASK('D')) SETBIT(uptr->flags, UNIT_DEBUG); - else if (sim_switches & SWMASK('Q')) SETBIT(uptr->flags, UNIT_QUIET); + if (sim_switches & SWMASK('Q')) SETBIT(uptr->flags, UNIT_QUIET); + if (sim_switches & SWMASK('L')) SETBIT(uptr->flags, UNIT_LOWERCASE); + + if (sim_switches & SWMASK('F')) tab_proc = EditToFortran; + if (sim_switches & SWMASK('A')) tab_proc = EditToAsm; + if (sim_switches & SWMASK('T')) tab_proc = EditToWhitespace; cr_detach(uptr); /* detach file and possibly deckfile */ CLRBIT(uptr->flags, UNIT_SCRATCH); @@ -1005,11 +1455,22 @@ static t_stat cr_attach (UNIT *uptr, char *cptr) if (list_nargs <= 0) /* need at least 1 */ return SCPE_2FARG; + cardnum = 0; /* reset card counter */ + use_decklist = FALSE; + cptr = list_arg[0]; /* filename is first argument */ - use_decklist = (*cptr == '@'); /* filename starts with @: it's a deck list */ - if (use_decklist) +#ifdef ENABLE_ENABLE_PHYSICAL_CARD_READER_SUPPORT + if (*cptr == '=') { /* open physical card reader device */ + if ((rval = pcr_attach(uptr, ++cptr)) != SCPE_OK) + return rval; + } +#endif + + if (*cptr == '@') { + use_decklist = TRUE; cptr++; + } if (strcmp(cptr, "-") == 0 && ! use_decklist) { /* standard input */ if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ @@ -1028,19 +1489,19 @@ static t_stat cr_attach (UNIT *uptr, char *cptr) cr_unit.fileref = NULL; nextdeck(); } - else + else { checkdeck(); + cr_set_code(&cr_unit, GET_CODE(cr_unit), NULL, NULL); + } // there is a read pending. Pull the card in to make it go if (CURRENT_OP == OP_READING || CURRENT_OP == OP_PUNCHING || CURRENT_OP == OP_FEEDING) - feedcycle(TRUE, CURRENT_OP == OP_PUNCHING); + feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); // no - don't reset the reader // cr_reset(&cr_dev); /* reset the whole thing */ // cp_reset(&cp_dev); - cardnum = 0; /* reset card counter */ - return SCPE_OK; } @@ -1048,6 +1509,11 @@ static t_stat cr_detach (UNIT *uptr) { t_stat rval; + cr_count = 0; /* clear read count */ + + if (cr_unit.flags & UNIT_PHYSICAL) + return pcr_detach(uptr); + if (cr_unit.flags & UNIT_ATT && deckfile != NULL) { if (cr_unit.fileref != NULL) /* close the active card deck */ fclose(cr_unit.fileref); @@ -1072,6 +1538,14 @@ static t_stat cr_detach (UNIT *uptr) return rval; } +static t_stat cp_attach (UNIT *uptr, char *cptr) +{ + /* if -d is specified turn on debugging (bit is in card reader UNIT) */ + if (sim_switches & SWMASK('D')) SETBIT(cr_unit.flags, UNIT_DEBUG); + + return attach_unit(uptr, cptr); +} + static t_stat cp_detach (UNIT *uptr) { if (cp_unit.flags & UNIT_ATT) @@ -1079,6 +1553,7 @@ static t_stat cp_detach (UNIT *uptr) feedcycle(FALSE, FALSE); /* flush out card just punched */ any_punched = 0; /* reset punch detected */ + cp_count = 0; /* clear punch count */ return detach_unit(uptr); } @@ -1096,6 +1571,9 @@ static void op_done (void) static t_stat cr_svc (UNIT *uptr) { + if (uptr->flags & UNIT_PHYSICAL) + return pcr_svc(uptr); + switch (CURRENT_OP) { case OP_IDLE: break; @@ -1134,7 +1612,7 @@ static t_stat cr_svc (UNIT *uptr) punchstate = STATION_PUNCHED; op_done(); } - else { + else if (++cp_unit.COLUMN < 80) { SETBIT(cr_dsw, CR_DSW_PUNCH_RESPONSE); SETBIT(ILSW[0], ILSW_0_1442_CARD); calc_ints(); @@ -1142,6 +1620,10 @@ static t_stat cr_svc (UNIT *uptr) if (cr_unit.flags & UNIT_DEBUG) DEBUG_PRINT("!CR Punch Response"); } + else { + punchstate = STATION_PUNCHED; + op_done(); + } break; } @@ -1157,6 +1639,11 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) switch (func) { case XIO_SENSE_DEV: + if (cr_unit.flags & UNIT_PHYSICAL) { + pcr_xio_sense(modify); + return; + } + if (cp_unit.flags & UNIT_ATT) lastcard = FALSE; /* if punch file is open, assume infinite blank cards in reader */ else if ((cr_unit.flags & UNIT_ATT) == 0) @@ -1184,6 +1671,11 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) else if (readstate == STATION_EMPTY && punchstate == STATION_EMPTY && lastcard) SETBIT(cr_dsw, CR_DSW_NOT_READY); + ACC = cr_dsw; /* return the DSW */ + + if (cr_unit.flags & UNIT_DEBUG) + DEBUG_PRINT("#CR Sense %04x%s%s", cr_dsw & 0xFFFF, (modify & 1) ? " RESET0" : "", (modify & 2) ? " RESET4" : ""); + if (modify & 0x01) { /* reset interrupts */ CLRBIT(cr_dsw, CR_DSW_READ_RESPONSE|CR_DSW_PUNCH_RESPONSE); CLRBIT(ILSW[0], ILSW_0_1442_CARD); @@ -1193,11 +1685,6 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) CLRBIT(cr_dsw, CR_DSW_OP_COMPLETE); CLRBIT(ILSW[4], ILSW_4_1442_CARD); } - - ACC = cr_dsw; /* return the DSW */ - - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Sense %04x%s%s", cr_dsw, (modify & 1) ? " RESET0" : "", (modify & 2) ? " RESET4" : ""); break; case XIO_READ: /* get card data into word pointed to in IOCC packet */ @@ -1216,7 +1703,10 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) } } else { - xio_error("1442: Read when not in a read cycle!"); +// don't complain: APL\1130 issues both reads and writes on every interrupt +// (probably to keep the code small). Apparently it's just ignored if corresponding +// control didn't initiate a read cycle. +// xio_error("1442: Read when not in a read cycle!"); } break; @@ -1243,7 +1733,10 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) } } else { - xio_error("1442: Write when not in a punch cycle!"); +// don't complain: APL\1130 issues both reads and writes on every interrupt +// (probably to keep the code small). Apparently it's just ignored if corresponding +// control didn't initiate a punch cycle. +// xio_error("1442: Write when not in a punch cycle!"); } break; @@ -1269,7 +1762,12 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) case 2: /* feed cycle */ if (cr_unit.flags & UNIT_DEBUG) DEBUG_PRINT("#CR Feed"); - feedcycle(TRUE, FALSE); + + if (cr_unit.flags & UNIT_PHYSICAL) { + pcr_xio_feedcycle(); + return; + } + feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); SET_OP(OP_FEEDING); @@ -1280,8 +1778,14 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) case 4: /* start read */ if (cr_unit.flags & UNIT_DEBUG) DEBUG_PRINT("#CR Start read"); + + if (cp_unit.flags & UNIT_PHYSICAL) { + pcr_xio_startread(); + return; + } + if (readstate != STATION_LOADED) - feedcycle(TRUE, FALSE); + feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); SET_OP(OP_READING); cr_unit.COLUMN = -1; @@ -1309,3 +1813,267 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) break; } } + +#if ! (defined(ENABLE_PHYSICAL_CARD_READER_SUPPORT) && defined(WIN32)) + + /* stub out the physical card reader routines */ + + static t_stat pcr_attach (UNIT *uptr, char *devname) {return SCPE_ARG;} + static t_stat pcr_detach (UNIT *uptr) {return detach_unit(uptr);} + static t_stat pcr_svc (UNIT *uptr) {return SCPE_OK;} + static void pcr_xio_sense (int modify) {} + static void pcr_xio_feedcycle (void) {} + static void pcr_xio_startread (void) {} + static void pcr_reset (void) {} + static int pcr_read_data (void) {return 0;} + +#else + +/* + * This code supports a physical card reader interface I built. Details + * available upon request, write to brian@ibm1130.org + + * NOTE: THIS IS NOT COMPLETE OR EVEN CLOSE, JUST SOME CODE SLAMMED INTO THE FILE + */ + +#include + +#define PCR_STATUS_READY 1 +#define PCR_STATUS_ERROR 2 +#define PCR_STATUS_HEMPTY 4 +#define PCR_STATUS_EOF 8 +#define PCR_STATUS_PICKING 16 + +static char pcr_status = '?'; +static void pcr_cmd (char cmd); + +static t_stat pcr_attach (UNIT *uptr, char *devname) +{ + HANDLE hPort; + DCB dcb; + COMMTIMEOUTS cto; + DWORD nerr; + /* open the COM port */ + hPort = CreateFile(devname, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (hPort == INVALID_HANDLE_VALUE) + return SCPE_OPENERR; + + memset(&dcb, 0, sizeof(dcb)); /* set communications parameters */ + + dcb.DCBlength = sizeof(DCB); + dcb.BaudRate = CBR_115200; /* for the USB virtual com port, baud rate is irrelevant */ + dcb.fBinary = 1; + dcb.fParity = 0; + dcb.fOutxCtsFlow = 0; + dcb.fOutxDsrFlow = 0; + dcb.fDtrControl = DTR_CONTROL_ENABLE; + dcb.fDsrSensitivity = FALSE; + dcb.fTXContinueOnXoff = 0; + dcb.fOutX = 0; + dcb.fInX = 0; + dcb.fErrorChar = 0; + dcb.fNull = 0; + dcb.fRtsControl = RTS_CONTROL_ENABLE; + dcb.fAbortOnError = 0; + dcb.XonLim = 0; + dcb.XoffLim = 0; + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + dcb.XonChar = 0; + dcb.XoffChar = 0; + dcb.ErrorChar = 0; + dcb.EofChar = 0; + dcb.EvtChar = 0; + + if (! SetCommState(hPort, &dcb)) { + CloseHandle(hPort); + printf("Call to SetCommState failed\n"); + return SCPE_OPENERR; + } + + cto.ReadIntervalTimeout = 100; // stop if 100 msec elapses between two received bytes + cto.ReadTotalTimeoutMultiplier = 0; // no length sensitivity + cto.ReadTotalTimeoutConstant = 400; // allow 400 msec for a read (reset command can take a while) + + cto.WriteTotalTimeoutMultiplier = 0; + cto.WriteTotalTimeoutConstant = 200; // allow 200 msec for a write + + if (! SetCommTimeouts(hPort, &cto)) { + CloseHandle(hPort); + printf("Call to SetCommTimeouts failed\n"); + return SCPE_OPENERR; + } + + PurgeComm(hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); + ClearCommError(hPort, &nerr, NULL); + + SETBIT(uptr->flags, UNIT_PHYSICAL|UNIT_ATT); /* mark device as attached */ + uptr->filename = calloc(strlen(devname)+1, sizeof(char)); + strcpy(uptr->filename, devname); + + uptr->fileref = (FILE *) hPort; /* store the handle in the slot for the file pointer */ + + cr_unit.COLUMN = -1; /* neither device is currently cycling */ + return SCPE_OK; +} + +static t_stat pcr_detach (UNIT *uptr) +{ + CLRBIT(cr_unit.flags, UNIT_PHYSICAL|UNIT_ATT); /* drop the attach and physical bits */ + + CloseHandle((HANDLE) (uptr->fileref)); /* close the COM port */ + uptr->fileref = NULL; + + free(uptr->filename); /* release the name copy */ + uptr->filename = NULL; + + return SCPE_OK; +} + +static void pcr_xio_sense (int modify) +{ + CLRBIT(cr_dsw, CR_DSW_LAST_CARD|CR_DSW_BUSY|CR_DSW_NOT_READY|CR_DSW_ERROR_CHECK); + + if (pcr_status & PCR_STATUS_HEMPTY) /* set 1130 status bits based on last status recv'd from */ + SETBIT(cr_dsw, CR_DSW_LAST_CARD); /* the card reader */ + + if (pcr_status & PCR_STATUS_ERROR) + SETBIT(cr_dsw, CR_DSW_ERROR_CHECK); + + if (pcr_status & PCR_STATUS_PICKING) + SETBIT(cr_dsw, CR_DSW_BUSY); + + if (! (pcr_status & PCR_STATUS_READY)) + SETBIT(cr_dsw, CR_DSW_NOT_READY); + + if (modify & 0x01) { /* reset simulated interrupts */ + CLRBIT(cr_dsw, CR_DSW_READ_RESPONSE|CR_DSW_PUNCH_RESPONSE); + CLRBIT(ILSW[0], ILSW_0_1442_CARD); + } + + if (modify & 0x02) { + CLRBIT(cr_dsw, CR_DSW_OP_COMPLETE); + CLRBIT(ILSW[4], ILSW_4_1442_CARD); + } + + ACC = cr_dsw; /* return the DSW */ + + if (cr_unit.flags & UNIT_DEBUG) + DEBUG_PRINT("#CR Sense %04x%s%s", cr_dsw, (modify & 1) ? " RESET0" : "", (modify & 2) ? " RESET4" : ""); +} + +static void pcr_xio_feedcycle (void) +{ + pcr_cmd('P'); // initiate pick + SET_OP(OP_FEEDING); +} + +static void pcr_xio_startread (void) +{ + pcr_cmd('P'); // initiate pick + SET_OP(OP_READING); +} + +static void pcr_reset (void) +{ + pcr_cmd('X'); // cancel pending pick +} + +static t_stat pcr_svc (UNIT *uptr) +{ + switch (CURRENT_OP) { + case OP_IDLE: + break; + + case OP_FEEDING: + op_done(); + break; + + case OP_READING: +/* this needs to poll the usb port for a = or ! */ + + if (readstate == STATION_EMPTY) { /* read active but no cards? hang */ + sim_activate(&cr_unit, cf_wait); + break; + } + + if (++cr_unit.COLUMN < 80) { + SETBIT(cr_dsw, CR_DSW_READ_RESPONSE); + SETBIT(ILSW[0], ILSW_0_1442_CARD); + calc_ints(); + sim_activate(&cr_unit, cr_wait); + if (cr_unit.flags & UNIT_DEBUG) + DEBUG_PRINT("!CR Read Response %d : %d", cardnum, cr_unit.COLUMN+1); + } + else { + readstate = STATION_READ; + op_done(); + } + break; + + case OP_PUNCHING: + return cr_svc(uptr); + } + + return SCPE_OK; +} + +static void pcr_cmd (char cmd) +{ + DWORD nio; + char resp; + int ntries = 10; + BOOL resend = TRUE; + + while (--ntries >= 0) { + if (resend && cmd != 0) { + if (! WriteFile((HANDLE) cr_unit.fileref, &cmd, 1, &nio, NULL)) { + printf("* Error writing to card reader interface\n"); + return; + } + } + + resend = TRUE; + + nio = 0; + ReadFile((HANDLE) cr_unit.fileref, &resp, 1, &nio, NULL); + + if (nio != 1) { + printf("* Timeout reading from card reader interface\n"); + continue; + } + + if (resp == '?') + continue; // it didn't recognize the command + + if (resp >= '@' && resp <= '_') { + pcr_status = resp; + return; + } + + if (resp == '!') { // we were expecting a response, but got a cancellation notice from pending pick + resend = FALSE; // status byte is coming + ntries++; // no penalty + } + else if (resp == '=') { // we were expecting a response, but are getting data from a pending pick + pcr_read_data(); + resend = FALSE; // status byte is coming + ntries++; // no penalty + continue; + } + // else -- just ignore it? + } + + printf("* Card reader interface failed to respond within 10 tries\n"); +} + +static int pcr_read_data (void) +{ + DWORD nio; + + ReadFile((HANDLE) cr_unit.fileref, readstation, 160, &nio, NULL); + return nio == 160; +} + +#endif diff --git a/Ibm1130/ibm1130_defs.h b/Ibm1130/ibm1130_defs.h index 76d81cfe..61b75024 100644 --- a/Ibm1130/ibm1130_defs.h +++ b/Ibm1130/ibm1130_defs.h @@ -258,23 +258,23 @@ void xio_2250_display (int32 addr, int32 func, int32 modify); // vector displ void xio_error (char *msg); void bail (char *msg); -t_stat load_cr_boot (int drv); +t_stat load_cr_boot (int drv, int switches); t_stat cr_boot (int unitno, DEVICE *dptr); void calc_ints (void); /* recalculate interrupt bitmask */ void trace_io (char *fmt, ...); /* debugging printout */ void scp_panic (char *msg); /* bail out of simulator */ char *upcase(char *str); void break_simulation (t_stat reason); /* let a device halt the simulation */ -char hollerith_to_ascii (int16 hol); /* for debugging use only */ +char hollerith_to_ascii (uint16 hol); /* for debugging use only */ t_bool gdu_active (void); void remark_cmd (char *remark); void stuff_cmd (char *cmd); void update_gui (t_bool force); void sim_init (void); -t_stat register_cmd (char *name, t_stat (*action)(int32, char *), int arg, char *help); +t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help); /* GUI interface routines */ -t_bool keyboard_is_locked (void); +t_bool keyboard_is_busy (void); void forms_check (int set); /* device notification to console lamp display */ void print_check (int set); void keyboard_selected (int select); diff --git a/Ibm1130/ibm1130_disk.c b/Ibm1130/ibm1130_disk.c index 6e517e91..756b2e5a 100644 --- a/Ibm1130/ibm1130_disk.c +++ b/Ibm1130/ibm1130_disk.c @@ -13,14 +13,17 @@ commands may NOT be accurate. This should probably be fixed. * usual yada-yada. Please keep this notice and the copyright in any distributions * or modifications. * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - * * Revision History + * 15-jun-03 moved actual read on XIO read to end of time interval, + * as the APL boot card required 2 instructions to run between the + * time read was initiated and the time the data was read (a jump and a wait) + * * 01-sep-02 corrected treatment of -m and -r flags in dsk_attach * in cgi mode, so that file is opened readonly but emulated * disk is writable. * + * This is not a supported product, but I welcome bug reports and fixes. + * Mail to simh@ibm1130.org */ #include "ibm1130_defs.h" @@ -75,6 +78,7 @@ static int16 dsk_sec[DSK_NUMDR] = {0}; /* next-sector-up */ static char dsk_lastio[DSK_NUMDR]; /* last stdio operation: IO_READ or IO_WRITE */ int32 dsk_swait = 50; /* seek time -- see how short a delay we can get away with */ int32 dsk_rwait = 50; /* rotate time */ +static t_bool raw_disk_debug = FALSE; static t_stat dsk_svc (UNIT *uptr); static t_stat dsk_reset (DEVICE *dptr); @@ -141,6 +145,15 @@ static int32 dsk_ilswlevel[DSK_NUMDR] = 2, 2, 2, 2 }; +typedef enum {DSK_FUNC_IDLE, DSK_FUNC_READ, DSK_FUNC_VERIFY, DSK_FUNC_WRITE, DSK_FUNC_SEEK, DSK_FUNC_FAILED} DSK_FUNC; + +static struct tag_dsk_action { /* stores data needed for pending IO activity */ + int32 io_address; + uint32 io_filepos; + int io_nwords; + int io_sector; +} dsk_action[DSK_NUMDR]; + /* xio_disk - XIO command interpreter for the disk drives */ /* * device status word: @@ -167,7 +180,7 @@ extern void void_backtrace (int afrom, int ato); void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv) { int i, rev, nsteps, newcyl, sec, nwords; - t_addr newpos; + uint32 newpos; // changed from t_addr to uint32 in anticipation of simh 64-bit development char msg[80]; UNIT *uptr = dsk_unit+drv; int16 buf[DSK_NUMWD]; @@ -195,7 +208,7 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv) nwords = M[iocc_addr++ & mem_mask]; /* get word count w/o upsetting SAR/SBR */ - if (nwords == 0) /* this is bad -- locks up disk controller ! */ + if (nwords == 0) /* this is bad -- on real 1130, this locks up disk controller ! */ break; if (! BETWEEN(nwords, 1, DSK_NUMWD)) { /* count bad */ @@ -205,49 +218,32 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv) sec = modify & 0x07; /* get sector on cylinder */ - if ((modify & 0x0080) == 0) { /* it's real if not a read check */ + if ((modify & 0x0080) == 0) { /* it's a real read if it's not a read check */ + // ah. We have a problem. The APL boot card counts on there being time for at least one + // more instruction to execute between the XIO read and the time the data starts loading + // into core. So, we have to defer the actual read operation a bit. Might as well wait + // until it's time to issue the operation complete interrupt. This means saving the + // IO information, then performing the actual read in dsk_svc. + newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD; - if (MEM_MAPPED(uptr)) { - memcpy(buf, (char *) uptr->filebuf + newpos, 2*DSK_NUMWD); - } - else { - if (uptr->pos != newpos || dsk_lastio[drv] != IO_READ) { - fseek(uptr->fileref, newpos, SEEK_SET); - dsk_lastio[drv] = IO_READ; - } - fxread(buf, 2, DSK_NUMWD, uptr->fileref); // read whole sector so we're in position for next read - uptr->pos = newpos + 2*DSK_NUMWD; - } + dsk_action[drv].io_address = iocc_addr; + dsk_action[drv].io_nwords = nwords; + dsk_action[drv].io_sector = sec; + dsk_action[drv].io_filepos = newpos; - void_backtrace(iocc_addr, iocc_addr + nwords - 1); // mark prev instruction as altered - - trace_io("* DSK%d read %d words from %d.%d (%x, %x) to M[%04x-%04x]", drv, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask, - (iocc_addr + nwords - 1) & mem_mask); - -// // this will help debug the monitor by letting me watch phase loading -// if (nwords >= 3) -// printf("* DSK%d XIO @ %04x read %d words from %d.%d (%x, %x) to M[%04x-%04x]\n", drv, prev_IAR, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask, -// (iocc_addr + nwords - 1) & mem_mask); - - i = uptr->CYL*8 + sec; - if (buf[0] != i) - printf("*DSK read bad sector#\n"); - - for (i = 0; i < nwords; i++) - M[(iocc_addr+i) & mem_mask] = buf[i]; - -#ifdef TRACE_DMS_IO - if (trace_dms) - tracesector(0, nwords, iocc_addr & mem_mask, uptr->CYL*8 + sec); -#endif + uptr->FUNC = DSK_FUNC_READ; } - else + else { trace_io("* DSK%d verify %d.%d (%x)", drv, uptr->CYL, sec, uptr->CYL*8 + sec); - uptr->FUNC = func; - sim_activate(uptr, dsk_rwait); + if (raw_disk_debug) + printf("* DSK%d verify %d.%d (%x)", drv, uptr->CYL, sec, uptr->CYL*8 + sec); + uptr->FUNC = DSK_FUNC_VERIFY; + } + + sim_activate(uptr, dsk_rwait); break; case XIO_INITW: @@ -279,7 +275,8 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv) trace_io("* DSK%d wrote %d words from M[%04x-%04x] to %d.%d (%x, %x)", drv, nwords, iocc_addr & mem_mask, (iocc_addr + nwords - 1) & mem_mask, uptr->CYL, sec, uptr->CYL*8 + sec, newpos); -// printf("* DSK%d XIO @ %04x wrote %d words from M[%04x-%04x] to %d.%d (%x, %x)\n", drv, prev_IAR, nwords, iocc_addr & mem_mask, (iocc_addr + nwords - 1) & mem_mask, uptr->CYL, sec, uptr->CYL*8 + sec, newpos); + if (raw_disk_debug) + printf("* DSK%d XIO @ %04x wrote %d words from M[%04x-%04x] to %d.%d (%x, %x)\n", drv, prev_IAR, nwords, iocc_addr & mem_mask, (iocc_addr + nwords - 1) & mem_mask, uptr->CYL, sec, uptr->CYL*8 + sec, newpos); #ifdef TRACE_DMS_IO if (trace_dms) @@ -309,7 +306,7 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv) uptr->pos = newpos + 2*DSK_NUMWD; } - uptr->FUNC = func; + uptr->FUNC = DSK_FUNC_WRITE; sim_activate(uptr, dsk_rwait); break; @@ -332,7 +329,7 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv) else if (newcyl >= DSK_NUMCY) newcyl = DSK_NUMCY-1; - uptr->FUNC = func; + uptr->FUNC = DSK_FUNC_SEEK; uptr->CYL = newcyl; sim_activate(uptr, dsk_swait); /* schedule interrupt */ @@ -371,30 +368,78 @@ static void diskfail (UNIT *uptr, int errflag) { sim_cancel(uptr); /* cancel any pending ops */ SETBIT(uptr->flags, errflag); /* set the error flag */ - uptr->FUNC = XIO_FAILED; /* tell svc routine why it failed */ + uptr->FUNC = DSK_FUNC_FAILED; /* tell svc routine why it failed */ sim_activate(uptr, 1); /* schedule an immediate op complete interrupt */ } t_stat dsk_svc (UNIT *uptr) { - int drv = uptr - dsk_unit; + int drv = uptr - dsk_unit, i, nwords, sec; + int16 buf[DSK_NUMWD]; + uint32 newpos; // changed from t_addr to uint32 in anticipation of simh 64-bit development + int32 iocc_addr; + + if (uptr->FUNC == DSK_FUNC_IDLE) /* service function called with no activity? not good, but ignore */ + return SCPE_OK; - CLRBIT(dsk_dsw[drv], DSK_DSW_DISK_BUSY); /* activate operation complete interrupt */ + CLRBIT(dsk_dsw[drv], DSK_DSW_DISK_BUSY); /* activate operation complete interrupt */ SETBIT(dsk_dsw[drv], DSK_DSW_OP_COMPLETE); if (uptr->flags & (UNIT_OPERR|UNIT_HARDERR)) { /* word count error or data error */ SETBIT(dsk_dsw[drv], DSK_DSW_DATA_ERROR); - CLRBIT(uptr->flags, UNIT_OPERR); /* but don't clear hard error */ + CLRBIT(uptr->flags, UNIT_OPERR); /* soft error is one time occurrence; don't clear hard error */ } - + /* schedule interrupt */ SETBIT(ILSW[dsk_ilswlevel[drv]], dsk_ilswbit[drv]); -#ifdef XXXX - switch (uptr->FUNC) { - case XIO_CONTROL: - case XIO_INITR: - case XIO_INITW: - case XIO_FAILED: + switch (uptr->FUNC) { /* take care of business */ + case DSK_FUNC_IDLE: + case DSK_FUNC_VERIFY: + case DSK_FUNC_WRITE: + case DSK_FUNC_SEEK: + case DSK_FUNC_FAILED: + break; + + case DSK_FUNC_READ: /* actually read the data into core */ + iocc_addr = dsk_action[drv].io_address; /* recover saved parameters */ + nwords = dsk_action[drv].io_nwords; + newpos = dsk_action[drv].io_filepos; + sec = dsk_action[drv].io_sector; + + if (MEM_MAPPED(uptr)) { + memcpy(buf, (char *) uptr->filebuf + newpos, 2*DSK_NUMWD); + } + else { + if (uptr->pos != newpos || dsk_lastio[drv] != IO_READ) { + fseek(uptr->fileref, newpos, SEEK_SET); + dsk_lastio[drv] = IO_READ; + uptr->pos = newpos; + } + fxread(buf, 2, DSK_NUMWD, uptr->fileref); // read whole sector so we're in position for next read + uptr->pos = newpos + 2*DSK_NUMWD; + } + + void_backtrace(iocc_addr, iocc_addr + nwords - 1); // mark prev instruction as altered + + trace_io("* DSK%d read %d words from %d.%d (%x, %x) to M[%04x-%04x]", drv, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask, + (iocc_addr + nwords - 1) & mem_mask); + +// // this will help debug the monitor by letting me watch phase loading + if (raw_disk_debug) + printf("* DSK%d XIO @ %04x read %d words from %d.%d (%x, %x) to M[%04x-%04x]\n", drv, prev_IAR, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask, + (iocc_addr + nwords - 1) & mem_mask); + + i = uptr->CYL*8 + sec; + if (buf[0] != i) + printf("*DSK read bad sector #\n"); + + for (i = 0; i < nwords; i++) + M[(iocc_addr+i) & mem_mask] = buf[i]; + +#ifdef TRACE_DMS_IO + if (trace_dms) + tracesector(0, nwords, iocc_addr & mem_mask, uptr->CYL*8 + sec); +#endif break; default: @@ -402,8 +447,8 @@ t_stat dsk_svc (UNIT *uptr) break; } - uptr->FUNC = -1; // we're done with this operation -#endif + + uptr->FUNC = DSK_FUNC_IDLE; // we're done with this operation return SCPE_OK; } @@ -428,7 +473,7 @@ t_stat dsk_reset (DEVICE *dptr) CLRBIT(uptr->flags, UNIT_OPERR|UNIT_HARDERR); uptr->CYL = 0; - uptr->FUNC = -1; + uptr->FUNC = DSK_FUNC_IDLE; dsk_dsw[drv] = (uptr->flags & UNIT_ATT) ? DSK_DSW_CARRIAGE_HOME : 0; } @@ -450,7 +495,7 @@ static t_stat dsk_attach (UNIT *uptr, char *cptr) return rval; uptr->CYL = 0; // reset the device - uptr->FUNC = -1; + uptr->FUNC = DSK_FUNC_IDLE; dsk_dsw[drv] = DSK_DSW_CARRIAGE_HOME; CLRBIT(uptr->flags, UNIT_RO|UNIT_ROABLE|UNIT_BUFABLE|UNIT_BUF|UNIT_RONLY|UNIT_OPERR|UNIT_HARDERR); @@ -479,6 +524,7 @@ static t_stat dsk_attach (UNIT *uptr, char *cptr) } enable_dms_tracing(sim_switches & SWMASK('D')); + raw_disk_debug = sim_switches & SWMASK('G'); return SCPE_OK; } @@ -498,7 +544,7 @@ static t_stat dsk_detach (UNIT *uptr) calc_ints(); uptr->CYL = 0; - uptr->FUNC = -1; + uptr->FUNC = DSK_FUNC_IDLE; dsk_dsw[drv] = DSK_DSW_NOT_READY; if (drv == 0) { @@ -518,7 +564,7 @@ static t_stat dsk_boot (int unitno, DEVICE *dptr) if ((rval = reset_all(0)) != SCPE_OK) return rval; - return load_cr_boot(unitno); + return load_cr_boot(unitno, sim_switches); } #ifdef TRACE_DMS_IO diff --git a/Ibm1130/ibm1130_fmt.c b/Ibm1130/ibm1130_fmt.c new file mode 100644 index 00000000..faccb046 --- /dev/null +++ b/Ibm1130/ibm1130_fmt.c @@ -0,0 +1,303 @@ +// ibm1130_fmt.c : interpret tabs in 1130 Assembler or Fortran source +// Bob Flanders +// ------------------------------------------------------------------------------------------- +// +// These routines are used by ibm1130_cr.c when the user has indicated +// that the input text is formatted with tabs. Input lines are edited +// into the appropriate column format. Three edit modes are recognized: +// +// Assembler mode: +// Input lines of the form +// +// [label][opcode][tag][L][argument] +// +// are rearranged so that the input fields are placed in the appropriate columns +// +// The label must start on the first character of the line. If there is no label, +// the first character(s) before the opcode must be whitespace. Following the opcode, there +// MUST be a tab character, followed by the format and tag. Following the format and tag +// may be exactly one whitespace character, and then starts the argument. +// +// Input lines with * in column 1 and blank lines are turned into Assembler comments, +// with the * in the Opcode field. +// +// Assembler directive lines at the beginning of the deck must be preceded by +// ! to indicate that they are not comments. For example, +// +// !*LIST +// * This is a comment +// +// Fortran mode: +// Input lines of the form +// +// [label]statement +// +// or +// +// [label]Xcontinuation +// +// where X is a non alphabetic contination character are rearranged in the +// appropriate manner: +// +// 1 2 +// 12345678901234567890... +// ------------------------ +// label statement +// labelXcontinuation +// +// However, you must take care that you don't end up with statement text after column 72. +// +// Input lines with * or C in column 1 are left alone (comments and directives) +// +// (The ! escape is not used before Fortran directives as before Assembler directives) +// +// Tab mode: +// Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide, +// as is standard for vi, notepad, etc. +// ------------------------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include "ibm1130_fmt.h" + +#define MAXLINE 81 // maximum output line size +#define WORKSZ 256 // size for tab work area +#define TAGOFFSET 12 // offset for tag field +#define FMTOFFSET 11 // offset for format field + +#define MIN(a,b) ((a < b) ? a : b) +#define AMSG " with Assembler Reformat" +#define FMSG " with FORTRAN Reformat" +#define AFORMAT "%20.20s%-60.60s"," " +#define ACOMMENTFMT "%20.20s%-60.60s"," " +#define ABLANKLINE "%20.20s*"," " +#define FFORMAT "%-5.5s %-74.74s" +#define FCONTFMT "%-5.5s%-75.75s" + +char gszLabel[6]; // work area for label +char gszArg[MAXLINE]; // .. argument +char gszOutput[MAXLINE]; // .. output +short gaiAsmTabs[] = {7,12,15,20,25,30,35,40,45,52,0};// tab stops for assembler + +short gaiPlainTabs[] = {9, 17, 25, 33, 41, 49, 57, 65, 73, 0};// tab stops for just plain tabs + +// /////////////// +// helper routines + +/////////////////////////////////////////////////// +// ExpandTabs: Expand tabs to spaces + +char* ExpandTabs(char* p_szInbuf, // expand tabs .. input buffer + char* p_szOutbuf, // .. output buffer + short* p_aiTabs) // .. array of tab stops (1 based) -- 0 end of array +{ +short iI, // input position + iO, // output position + iT; // next tab stop + +char cX; // character to test + + iI = 0; // init input position + iO = 0; // init output position + iT = 0; // init tab stop + + while (cX = *(p_szInbuf + iI)) // while there are characters + { + if (cX == '\t') // q. tab character? + { // a. yes .. + while ((p_aiTabs[iT] <= iO + 1) // search for next valid stop .. + && (p_aiTabs[iT] != 0)) // .. or end of table + iT++; // .. go to next tab + + if (p_aiTabs[iT] != 0) // q. end of tab array? + { // a. no .. + while (iO < (p_aiTabs[iT] - 1)) // fill to tab with blanks + *(p_szOutbuf + iO++) = ' '; // .. put in a blank + + } + else // Otherwise ... + *(p_szOutbuf + iO++) = ' '; // .. Translate to blank + } + else // Otherwise .. not tab + *(p_szOutbuf + iO++) = cX; // .. save the input char + + iI++; // next input character + } + + *(p_szOutbuf + iO) = 0; // end the string.. + return p_szOutbuf; // .. return output area addr +} + +///////////////////////////////////// +// extract next token, modify pointer + +char* GetToken(char* p_szOut, // output location + int p_iLen, // max output length + char**p_pszToken) // pointer to input token +{ +int iI; // work integer +char* pszX; // work pointer + + pszX = *p_pszToken; // get pointer to token + + for (iI = 0; *(pszX + iI) && (!isspace(*(pszX + iI)));) // while not whitespace & not end + iI++; // .. count token length + + memset(p_szOut, 0, p_iLen); // zero out output area + + if (iI > 0) // q. any chars? + strncpy(p_szOut, *p_pszToken, MIN(iI, p_iLen-1)); // a. yes.. copy max of p_iLen-1 + + *p_pszToken += iI; // point beyond token + return p_szOut; // .. return token pointer +} + +///////////////////////////////////////////////////////// +// EditToAsm - convert tab-formatted text line to 1130 Assembler format + +char *EditToAsm (char* p_pszEdit) // convert line to 1130 assembler +{ +char pszLine[MAXLINE]; // source line +char pszWork[WORKSZ]; // work buffer +char acTFWrk[2]; // tag/format work area +size_t iI; // work integer + + if (p_pszEdit == NULL) // q. null request? + return AMSG; // a. yes .. return display message + + if (*p_pszEdit == '!') // leave lines starting with ! alone + return EditToWhitespace(p_pszEdit+1); + + if (*p_pszEdit == '*') // q. comment line? + { // a. yes.. + strncpy(pszWork, EditToWhitespace(p_pszEdit), MAXLINE); // .. convert any tabs + sprintf(gszOutput, ACOMMENTFMT, pszWork); // .. put the comment out there in the opcode column + return gszOutput; // .. and return it + } + + strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local + + ExpandTabs(pszLine, pszWork, gaiAsmTabs); // expand the tabs + strncpy(pszLine, pszWork, MAXLINE-1); // copy the line back + + for (iI = strlen(pszLine); iI--;) // trim trailing whitespace + { + if (*(pszLine + iI) <= ' ') // q. space or less? + *(pszLine + iI) = 0; // a. yes .. remove it + else // otherwise + break; // .. done. Leave loop. + } + + if (strlen(pszLine) == 0) // q. blank line? + { // a. yes .. Assembler abhors these so + sprintf(gszOutput, ABLANKLINE); // format as comment statement + return gszOutput; // .. and return it + } + + + // TODO: Add code to process a strip switch + // comment? + + if (strlen(pszLine) > (TAGOFFSET + 1)) // q. line long enough? + { // a. yes.. reorder tag/format + memcpy(acTFWrk, pszLine + FMTOFFSET, 2); // get tag/format + memset((pszLine + FMTOFFSET), ' ', 2); // .. blank 'em out + + for (iI = 0; iI < 2; iI ++) + if (isalpha(acTFWrk[iI])) // q. alpha char? + *(pszLine + FMTOFFSET) = acTFWrk[iI]; // a. yes .. make it format + else if (isdigit(acTFWrk[iI])) // q. digit? + *(pszLine + TAGOFFSET) = acTFWrk[iI]; // a. yes .. make it the tag + } + + sprintf(gszOutput, AFORMAT, pszLine); // format the line + + return gszOutput; // return formatted line +} + +///////////////////////////////////////////////////////// +// EditToFortran - convert tab-formatted input text line to FORTRAN format +// (a la DEC Fortran) + +char *EditToFortran(char* p_pszEdit) // convert line to 1130 assembler +{ +char pszLine[MAXLINE]; // source line +char* pszWork; // work pointer +size_t iI; // work integer +char bContinue; // true if continue + + if (p_pszEdit == NULL) // q. null request? + return FMSG; // a. yes .. return display message + + if (strchr(p_pszEdit, '\t') == NULL) // q. no tab in the line? + return p_pszEdit; // a. nope, return line as is, assume it's formatted correctly + + if (*p_pszEdit == 'C' || *p_pszEdit == '*' || *p_pszEdit == '\0') // q. comment or directive or blank line? + { // a. yes.. don't restructure + return EditToWhitespace(p_pszEdit); + } + + strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local + + for (iI = strlen(pszLine); iI--;) // trim trailing whitespace + { + if (*(pszLine + iI) <= ' ') // q. space or less? + *(pszLine + iI) = 0; // a. yes .. remove it + else // otherwise + break; // .. done. Leave loop. + } + + // TODO: Add code to process a strip switch + // comment? + + pszWork = (char*) pszLine; // set pointer to line + GetToken(gszLabel, 6, &pszWork); // get the line, if any. + + pszWork++; // skip tab/whitespace + + // continuation... + bContinue = ((isdigit(*pszWork) && (*pszWork != '0')) // if first char non-zero digit + || (!isspace(*pszWork) && !isalpha(*pszWork))); // .. or non-alpha non-blank + + memset(gszArg, 0, MAXLINE); // .. and arguments + + strncpy(gszArg, pszWork, 75); // copy rest to argument + + sprintf(gszOutput, (bContinue) ? FCONTFMT : FFORMAT, // format the line + gszLabel, // .. statement # + gszArg); // .. code + + return gszOutput; // return formatted line +} + +///////////////////////////////////////////////////////// +// EditToWhitespace - expand tabs at 8 space intervals. + +char* EditToWhitespace(char *p_pszEdit) +{ +int iI; /* work integer */ +char pszLine[MAXLINE]; // source line +char pszWork[WORKSZ]; // work buffer + + if (p_pszEdit == NULL) // q. null request? + return AMSG; // a. yes .. return display message + + strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local + + ExpandTabs(pszLine, pszWork, gaiPlainTabs); // expand the tabs + strncpy(gszOutput, pszWork, MAXLINE-1); // copy the line back + + for (iI = strlen(gszOutput); iI--;) // look at each character + { + if (*(gszOutput + iI) <= ' ') // q. space or less? + *(gszOutput + iI) = 0; // a. yes .. remove it + else // otherwise + break; // .. done. Leave loop. + } + + + return gszOutput; /* ... return buffer */ +} diff --git a/Ibm1130/ibm1130_fmt.h b/Ibm1130/ibm1130_fmt.h new file mode 100644 index 00000000..170d1c88 --- /dev/null +++ b/Ibm1130/ibm1130_fmt.h @@ -0,0 +1,17 @@ +/* + * (C) Copyright 2003, Bob Flander. + * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN + * RISK basis, there is no warranty of fitness for any purpose, and the rest of the + * usual yada-yada. Please keep this notice and the copyright in any distributions + * or modifications. + * + * This is not a supported product, but I welcome bug reports and fixes. + * Mail to bob@jftr.com + */ + +/* ibm1130_asm.h: definition of routines in ibm1130_asm.c + */ + +char* EditToAsm(char*); // convert edit format to 1130 assembler format +char* EditToFortran(char*); // convert edit format to Fortran format +char* EditToWhitespace(char*); // clean white space, tabstops every 8 positions diff --git a/Ibm1130/ibm1130_gdu.c b/Ibm1130/ibm1130_gdu.c index 2a1a155f..a1501609 100644 --- a/Ibm1130/ibm1130_gdu.c +++ b/Ibm1130/ibm1130_gdu.c @@ -18,7 +18,7 @@ * or modifications. * * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org + * Mail to simh@ibm1130.org */ #define BLIT_MODE // normally defined, undefine when debugging generate_image() diff --git a/Ibm1130/ibm1130_gui.c b/Ibm1130/ibm1130_gui.c index ecad18c0..8a1461cb 100644 --- a/Ibm1130/ibm1130_gui.c +++ b/Ibm1130/ibm1130_gui.c @@ -9,7 +9,7 @@ * or modifications. * * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org + * Mail to simh@ibm1130.org * * 17-May-02 BLK Pulled out of ibm1130_cpu.c */ @@ -168,30 +168,30 @@ static int bmwid, bmht; static struct tag_btn { int x, y; char *txt; - BOOL pushable; + BOOL pushable, state; COLORREF clr; HBRUSH hbrLit, hbrDark; HWND hBtn; } btn[] = { - 0, 0, "KEYBOARD\nSELECT", FALSE, RGB(255,255,180), NULL, NULL, NULL, - 0, 1, "DISK\nUNLOCK", FALSE, RGB(255,255,180), NULL, NULL, NULL, - 0, 2, "RUN", FALSE, RGB(0,255,0), NULL, NULL, NULL, - 0, 3, "PARITY\nCHECK", FALSE, RGB(255,0,0), NULL, NULL, NULL, + 0, 0, "KEYBOARD\nSELECT", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, + 0, 1, "DISK\nUNLOCK", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, + 0, 2, "RUN", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, + 0, 3, "PARITY\nCHECK", FALSE, FALSE, RGB(255,0,0), NULL, NULL, NULL, - 1, 0, "", FALSE, RGB(255,255,180), NULL, NULL, NULL, - 1, 1, "FILE\nREADY", FALSE, RGB(0,255,0), NULL, NULL, NULL, - 1, 2, "FORMS\nCHECK", FALSE, RGB(255,255,0), NULL, NULL, NULL, - 1, 3, "POWER\nON", FALSE, RGB(255,255,180), NULL, NULL, NULL, + 1, 0, "", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, + 1, 1, "FILE\nREADY", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, + 1, 2, "FORMS\nCHECK", FALSE, FALSE, RGB(255,255,0), NULL, NULL, NULL, + 1, 3, "POWER\nON", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, - 2, 0, "POWER", TRUE, RGB(255,255,180), NULL, NULL, NULL, - 2, 1, "PROGRAM\nSTART", TRUE, RGB(0,255,0), NULL, NULL, NULL, - 2, 2, "PROGRAM\nSTOP", TRUE, RGB(255,0,0), NULL, NULL, NULL, - 2, 3, "LOAD\nIAR", TRUE, RGB(0,0,255), NULL, NULL, NULL, + 2, 0, "POWER", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, + 2, 1, "PROGRAM\nSTART", TRUE, FALSE, RGB(0,255,0), NULL, NULL, NULL, + 2, 2, "PROGRAM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, + 2, 3, "LOAD\nIAR", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, - 3, 0, "KEYBOARD", TRUE, RGB(255,255,180), NULL, NULL, NULL, - 3, 1, "IMM\nSTOP", TRUE, RGB(255,0,0), NULL, NULL, NULL, - 3, 2, "CHECK\nRESET", TRUE, RGB(0,0,255), NULL, NULL, NULL, - 3, 3, "PROGRAM\nLOAD", TRUE, RGB(0,0,255), NULL, NULL, NULL, + 3, 0, "KEYBOARD", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, + 3, 1, "IMM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, + 3, 2, "CHECK\nRESET", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, + 3, 3, "PROGRAM\nLOAD", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, }; #define NBUTTONS (sizeof(btn) / sizeof(btn[0])) @@ -318,7 +318,8 @@ static void RepaintRegion (HWND hWnd, int left, int top, int right, int bottom) void update_gui (BOOL force) { - int i, sts; + int i; + BOOL state; static int in_here = FALSE; static int32 displayed = 0; @@ -385,25 +386,33 @@ void update_gui (BOOL force) int_lamps = 0; + // this loop works with lamp buttons that are calculated on-the-fly only for (i = 0; i < NBUTTONS; i++) { if (btn[i].pushable) continue; switch (i) { - case IDC_RUN: sts = hFlashTimer || (running && ! wait_state); break; -// case IDC_PARITY_CHECK: sts = FALSE; break; -// case IDC_POWER_ON: sts = TRUE; break; - default: - continue; + case IDC_RUN: + state = hFlashTimer || (running && ! wait_state); + break; -// case IDC_FILE_READY: these windows are enabled&disabled directly + // this button is always off +// case IDC_PARITY_CHECK: + + // these buttons are enabled/disabled directly +// case IDC_POWER_ON: +// case IDC_FILE_READY: // case IDC_FORMS_CHECK: // case IDC_KEYBOARD_SELECT: // case IDC_DISK_UNLOCK: + default: + continue; } - if (sts != IsWindowEnabled(btn[i].hBtn)) // status has changed - EnableWindow(btn[i].hBtn, sts); + if (state != btn[i].state) { // state has changed + EnableWindow(btn[i].hBtn, state); + btn[i].state = state; + } } in_here = FALSE; @@ -423,6 +432,7 @@ LRESULT CALLBACK ButtonProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (! btn[i].pushable) { if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK) return 0; + if (uMsg == WM_CHAR) if ((TCHAR) wParam == ' ') return 0; @@ -622,9 +632,9 @@ static DWORD WINAPI Pump (LPVOID arg) class_defined = TRUE; } - hbWhite = GetStockObject(WHITE_BRUSH); /* create or fetch useful GDI objects */ - hbBlack = GetStockObject(BLACK_BRUSH); /* create or fetch useful GDI objects */ - hbGray = GetStockObject(GRAY_BRUSH); + hbWhite = GetStockObject(WHITE_BRUSH); /* create or fetch useful GDI objects */ + hbBlack = GetStockObject(BLACK_BRUSH); /* create or fetch useful GDI objects */ + hbGray = GetStockObject(GRAY_BRUSH); hSwitchPen = CreatePen(PS_SOLID, 5, RGB(255,255,255)); hWhitePen = GetStockObject(WHITE_PEN); @@ -633,8 +643,8 @@ static DWORD WINAPI Pump (LPVOID arg) hGreyPen = CreatePen(PS_SOLID, 1, RGB(128,128,128)); hDkGreyPen = CreatePen(PS_SOLID, 1, RGB(64,64,64)); - hcArrow = LoadCursor(NULL, IDC_ARROW); - hcHand = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_HAND)); + hcArrow = LoadCursor(NULL, IDC_ARROW); + hcHand = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_HAND)); if (hBitmap == NULL) hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_CONSOLE)); @@ -656,11 +666,12 @@ static DWORD WINAPI Pump (LPVOID arg) bmwid = bm.bmWidth; bmht = bm.bmHeight; - for (i = 0; i < NBUTTONS; i++) + for (i = 0; i < NBUTTONS; i++) { CreateSubclassedButton(hConsoleWnd, i); - EnableWindow(btn[IDC_POWER_ON].hBtn, TRUE); - EnableWindow(btn[IDC_DISK_UNLOCK].hBtn, TRUE); + if (! btn[i].pushable) + EnableWindow(btn[i].hBtn, btn[i].state); + } GetWindowRect(hConsoleWnd, &r); /* get window size as created */ wx = r.right - r.left + 1; @@ -913,12 +924,19 @@ void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam) reset_all(0); if (running && ! power) { /* turning off */ reason = STOP_POWER_OFF; - while (running) - Sleep(10); /* wait for execution thread to exit */ +// this prevents message pump from running, which unfortunately locks up +// the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp +// while (running) +// Sleep(10); /* wait for execution thread to exit */ } + + btn[IDC_POWER_ON].state = power; EnableWindow(btn[IDC_POWER_ON].hBtn, power); - for (i = 0; i < NBUTTONS; i++) - InvalidateRect(btn[i].hBtn, NULL, TRUE); + + for (i = 0; i < NBUTTONS; i++) /* repaint all of the lamps */ + if (! btn[i].pushable) + InvalidateRect(btn[i].hBtn, NULL, TRUE); + break; case IDC_PROGRAM_START: /* begin execution */ @@ -967,8 +985,11 @@ void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam) case IDC_IMM_STOP: if (running) { reason = STOP_WAIT; /* terminate execution without setting wait_mode */ - while (running) - Sleep(10); /* wait for execution thread to exit */ + +// this prevents message pump from running, which unfortunately locks up +// the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp +// while (running) +// Sleep(10); /* wait for execution thread to exit */ } break; @@ -1084,10 +1105,14 @@ void forms_check (int set) btn[IDC_FORMS_CHECK].clr = (printerstatus & PRINT_CHECK) ? RGB(255,0,0) : RGB(255,255,0); - EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus); + btn[IDC_FORMS_CHECK].state = printerstatus; - if (btn[IDC_FORMS_CHECK].clr != oldcolor) - InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case + if (btn[IDC_FORMS_CHECK].hBtn != NULL) { + EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus); + + if (btn[IDC_FORMS_CHECK].clr != oldcolor) + InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case + } } void print_check (int set) @@ -1101,25 +1126,38 @@ void print_check (int set) btn[IDC_FORMS_CHECK].clr = (printerstatus & PRINT_CHECK) ? RGB(255,0,0) : RGB(255,255,0); - EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus); + btn[IDC_FORMS_CHECK].state = printerstatus; - if (btn[IDC_FORMS_CHECK].clr != oldcolor) - InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case + if (btn[IDC_FORMS_CHECK].hBtn != NULL) { + EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus); + + if (btn[IDC_FORMS_CHECK].clr != oldcolor) + InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case + } } void keyboard_selected (int select) { - EnableWindow(btn[IDC_KEYBOARD_SELECT].hBtn, select); + btn[IDC_KEYBOARD_SELECT].state = select; + + if (btn[IDC_KEYBOARD_SELECT].hBtn != NULL) + EnableWindow(btn[IDC_KEYBOARD_SELECT].hBtn, select); } void disk_ready (int ready) { - EnableWindow(btn[IDC_FILE_READY].hBtn, ready); + btn[IDC_FILE_READY].state = ready; + + if (btn[IDC_FILE_READY].hBtn != NULL) + EnableWindow(btn[IDC_FILE_READY].hBtn, ready); } void disk_unlocked (int unlocked) { - EnableWindow(btn[IDC_DISK_UNLOCK].hBtn, unlocked); + btn[IDC_DISK_UNLOCK].state = unlocked; + + if (btn[IDC_DISK_UNLOCK].hBtn != NULL) + EnableWindow(btn[IDC_DISK_UNLOCK].hBtn, unlocked); } CRITICAL_SECTION critsect; diff --git a/Ibm1130/ibm1130_prt.c b/Ibm1130/ibm1130_prt.c index 8340d273..dd3053cc 100644 --- a/Ibm1130/ibm1130_prt.c +++ b/Ibm1130/ibm1130_prt.c @@ -23,7 +23,7 @@ * or modifications. * * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org + * Mail to simh@ibm1130.org */ #include "ibm1130_defs.h" diff --git a/Ibm1130/ibm1130_stddev.c b/Ibm1130/ibm1130_stddev.c index 8d811340..0cc477d4 100644 --- a/Ibm1130/ibm1130_stddev.c +++ b/Ibm1130/ibm1130_stddev.c @@ -5,6 +5,10 @@ Brian Knittel Revision History: + 2003.06.15 - added output translation code to accomodate APL font + added input translation feature to assist emulation of 1130 console keyboard for APL + changes to console input and output IO emulation, fixed bugs exposed by APL interpreter + 2002.09.13 - pulled 1132 printer out of this file into ibm1130_prt.c * (C) Copyright 2002, Brian Knittel. @@ -14,10 +18,68 @@ * or modifications. * * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org + * Mail to simh@ibm1130.org + * + * Notes about overstrike mapping: + * The 1130 console printer used a Selectric typewriter element. The APL interpreter + * used overprinting to construct some APL symbols, for example, a round O overstruck] + * with | to get the greek phi. This doesn't accomodate a glass terminal! Instead, + * modern APL fonts have separate character codes for the complex characters. + * To have APL\1130 output appear correctly, we have to do three things: + * + * use simh's telnet feature to connect to the 1130 console stream + * have the telnet program use an APL font + * detect combinations of overstruck symbols, and generate the approrpiate alternate codes. + * + * There is a built-in table of font mappings and overstrike mappings, for the APLPLUS.TTF + * truetype font widely available on the Internet. An font descriptor file can be used + * to specify alternate mappings. + * + * The APL font codes and overstrike mapping can be enabled with the simh command + * + * set tto apl + * + * and disabled with + * + * set tto ascii (this is the default) + * + * APL also uses the red and black ribbon selection. The emulator will output + * ansi red/black foreground commands with the setting + * + * set tto ansi + * + * The codes can be disabled with + * + * set tto noansi (this is the default) + * + * Finally, when APL mode is active, the emulator does some input key translations + * to let the standard ASCII keyboard more closely match the physical layout of the + * 1130 console keyboard. The numeric and punctuation key don't have their + * traditional meaning under APL. The input mapping lets you use the APL keyboard + * layout shown in the APL documentation. + * + * The translations are: + * FROM + * ASCII Position on keyboard To 1130 Key APL interpretation + * ------------------------------------ -------------------------------- + * [ (key to right of P) \r Enter left arrow + * ; (1st key to right of L) \b Backspace [ + * ' (2nd key to right of L) ^U Erase Fld ] + * 2 (key above Q) @ @ up shift + * 3 (key above W) % % up right shift + * 4 (key above E) * * + + * 5 (key above R) < < multiply + * 8 (key above U) - - Return + * 9 (key above I) / / Backspace + * - (key above P) ^Q INT REQ ATTN + * Enter - - Return + * backsp / / Backspace */ #include "ibm1130_defs.h" +#include + +/* #define DEBUG_CONSOLE */ /* ---------------------------------------------------------------------------- */ @@ -38,25 +100,71 @@ void xio_system7 (int32 addr, int32 func, int32 modify) {badio("System 7");} /* ---------------------------------------------------------------------------- */ -static int32 tti_dsw = 0; /* device status words */ -static int32 tto_dsw = 0; -static int32 con_dsw = 0; - -static t_stat tti_svc (UNIT *uptr); -static t_stat tto_svc (UNIT *uptr); -static t_stat tti_reset (DEVICE *dptr); -static t_stat tto_reset (DEVICE *dptr); +#define MAX_OUTPUT_COLUMNS 100 /* width of 1130 console printer */ +#define MAX_OS_CHARS 4 /* maximum number of overstruck characters that can be mapped */ +#define MAX_OS_MAPPINGS 100 /* maximum number of overstrike mappings */ -extern t_stat sim_poll_kbd (void); -extern t_stat sim_wait_kbd (void); -extern t_stat sim_putchar (int32 out); +typedef struct tag_os_map { /* os_map = overstrike mapping */ + int ch; /* ch = output character */ + int nin; /* nin = number of overstruck characters */ + unsigned char inlist[MAX_OS_CHARS]; /* inlist = overstruck ASCII characters, sorted. NOT NULL TERMINATED */ +} OS_MAP; extern UNIT *sim_clock_queue; extern int cgi; -#define CSET_MASK 1 /* character set */ -#define CSET_NORMAL 0 -#define CSET_ASCII 1 +static int32 tti_dsw = 0; /* device status words */ +static int32 tto_dsw = 0; +static int32 con_dsw = 0; + +static unsigned char conout_map[256]; /* 1130 console code to ASCII translation. 0 = undefined, 0xFF = IGNR_ = no output */ +static unsigned char conin_map[256]; /* input mapping */ +static int curcol = 0; /* current typewriter element column, leftmost = 0 */ +static int maxcol = 0; /* highest curcol seen in this output line */ +static char black_ribbon[30]; /* output escape sequence for black ribbon shift */ +static char red_ribbon[30]; /* output escape sequence for red ribbon shift */ + +static OS_MAP os_buf[MAX_OUTPUT_COLUMNS]; /* current typewriter output line, holds character struck in each column */ +static OS_MAP os_map[MAX_OS_MAPPINGS]; /* overstrike mapping entries */ +static int n_os_mappings; /* number of overstrike mappings */ + +static t_stat tti_svc(UNIT *uptr); +static t_stat tto_svc(UNIT *uptr); +static t_stat tti_reset(DEVICE *dptr); +static t_stat tto_reset(DEVICE *dptr); + +static t_stat emit_conout_character(int ch); +static t_stat map_conout_character(int ch); +static void reset_mapping (void); +static void set_conout_mapping(int32 flags); +static t_stat validate_conout_mapping(UNIT *uptr, int32 match, char *cvptr, void *desc); +static void set_default_mapping(int32 flags); +static void finish_conout_mapping(int32 flags); +static void strsort (int n, unsigned char *s); /* sorts an array of n characters */ +static int os_map_comp (OS_MAP *a, OS_MAP *b); /* compares two mapping entries */ +static t_stat font_cmd(int32 flag, char *cptr); /* handles font command */ +static void read_map_file(FILE *fd); /* reads a font map file */ +static t_bool str_match(char *str, char *keyword); /* keyword/string comparison */ +static char * handle_map_ansi_definition(char **pc); /* input line parsers for map file sections */ +static char * handle_map_input_definition(char **pc); +static char * handle_map_output_definition(char **pc); +static char * handle_map_overstrike_definition(char **pc); + +extern t_stat sim_poll_kbd(void); +extern t_stat sim_wait_kbd(void); +extern t_stat sim_putchar(int32 out); + +#define UNIT_V_CSET (UNIT_V_UF + 0) /* user flag: character set */ +#define UNIT_V_LOCKED (UNIT_V_UF + 2) /* user flag: keyboard locked */ +#define UNIT_V_ANSI (UNIT_V_UF + 3) + +#define CSET_ASCII (0u << UNIT_V_CSET) +#define CSET_1130 (1u << UNIT_V_CSET) +#define CSET_APL (2u << UNIT_V_CSET) +#define CSET_MASK (3u << UNIT_V_CSET) +#define ENABLE_ANSI (1u << UNIT_V_ANSI) + +#define KEYBOARD_LOCKED (1u << UNIT_V_LOCKED) #define IRQ_KEY 0x11 /* ctrl-Q */ #define PROGRAM_STOP_KEY 0x10 /* ctrl-P */ @@ -74,15 +182,15 @@ extern int cgi; UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { ORDATA (DSW, tti_dsw, 16) }, - { DRDATA (POS, tti_unit.pos, 31), PV_LEFT }, + { ORDATA (BUF, tti_unit.buf, 16) }, + { ORDATA (DSW, tti_dsw, 16) }, + { DRDATA (POS, tti_unit.pos, 31), PV_LEFT }, { DRDATA (STIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, { NULL } }; MTAB tti_mod[] = { - { CSET_MASK, CSET_NORMAL, NULL, "1130", NULL}, - { CSET_MASK, CSET_ASCII, NULL, "ASCII", NULL}, + { CSET_MASK, CSET_ASCII, "ASCII", "ASCII", NULL}, + { CSET_MASK, CSET_1130, "1130", "1130", NULL}, { 0 } }; DEVICE tti_dev = { @@ -101,15 +209,18 @@ DEVICE tti_dev = { UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, + { ORDATA (BUF, tto_unit.buf, 16) }, { ORDATA (DSW, tto_dsw, 16) }, { DRDATA (POS, tto_unit.pos, 31), PV_LEFT }, { DRDATA (STIME, tto_unit.wait, 24), PV_LEFT }, { NULL } }; MTAB tto_mod[] = { - { CSET_MASK, CSET_NORMAL, NULL, "1130", NULL}, - { CSET_MASK, CSET_ASCII, NULL, "ASCII", NULL}, + { CSET_MASK, CSET_ASCII, "ASCII", "ASCII", validate_conout_mapping, NULL, NULL}, + { CSET_MASK, CSET_1130, "1130", "1130", validate_conout_mapping, NULL, NULL}, + { CSET_MASK, CSET_APL, "APL", "APL", validate_conout_mapping, NULL, NULL}, + { ENABLE_ANSI,0, "NOANSI", "NOANSI", NULL}, + { ENABLE_ANSI,ENABLE_ANSI, "ANSI", "ANSI", NULL}, { 0 } }; DEVICE tto_dev = { @@ -141,27 +252,24 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify) switch (func) { case XIO_CONTROL: - SETBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); + SETBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* select and unlock the keyboard */ keyboard_selected(TRUE); -// sim_activate(&tti_unit, tti_unit.wait); /* poll keyboard never stops */ + CLRBIT(tti_unit.flags, KEYBOARD_LOCKED); + tti_unit.buf = 0; /* no key character yet */ break; - case XIO_READ: - WriteW(iocc_addr, tti_unit.buf); - CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); + case XIO_READ: + WriteW(iocc_addr, tti_unit.buf); /* return keycode */ + CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* this ends selected mode */ keyboard_selected(FALSE); + SETBIT(tti_unit.flags, KEYBOARD_LOCKED); /* keyboard is locked when not selected */ + tti_unit.buf = 0; /* subsequent reads will return zero */ break; case XIO_WRITE: ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */ + tto_unit.buf = emit_conout_character(ch); /* output character and save write status */ - if ((tto_unit.flags & CSET_MASK) == CSET_NORMAL) - ch = conout_to_ascii[ch]; /* convert to ASCII */ - - if (ch == 0) - ch = '?'; /* hmmm, unknown character */ - - tto_unit.buf = ch; /* save character to write */ SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY); sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */ break; @@ -171,6 +279,7 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify) if (modify & 0x01) { /* reset interrupts */ CLRBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE); CLRBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); + CLRBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); CLRBIT(ILSW[4], ILSW_4_CONSOLE); } break; @@ -181,6 +290,45 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify) } } +// emit_conout_character - write character with 1130 console code 'ch' + +t_stat emit_conout_character (int ch) +{ + t_stat status; + +#ifdef DEBUG_CONSOLE + printf("{%02x}", ch); +#endif + + if ((tto_unit.flags & CSET_MASK) == CSET_1130) /* 1130 (binary) mode, write the raw 8-bit value */ + return sim_putchar(ch); + + if (ch & COUT_IS_CTRL) { + /* red/black shift can be combined with another control */ + /* if present, emit the color shift characters alone */ + + if (ch & COUT_CTRL_BLACK) { + if ((status = map_conout_character(COUT_IS_CTRL|COUT_CTRL_BLACK)) != SCPE_OK) + return status; + } + else if (ch & COUT_CTRL_RED) { + if ((status = map_conout_character(COUT_IS_CTRL|COUT_CTRL_RED)) != SCPE_OK) + return status; + } + + ch &= ~(COUT_CTRL_BLACK|COUT_CTRL_RED); /* remove the ribbon shift bits */ + + if (ch & ~COUT_IS_CTRL) { /* if another control remains, emit it */ + if ((status = map_conout_character(ch)) != SCPE_OK) + return status; + } + + return SCPE_OK; + } + + return map_conout_character(ch); +} + static void Beep (void) // notify user keyboard was locked or key was bad { sim_putchar(7); @@ -192,7 +340,10 @@ static t_stat tti_svc (UNIT *uptr) { int32 temp; - sim_activate(&tti_unit, tti_unit.wait); /* continue polling */ + if (cgi) /* if running in CGI mode, no keyboard and no keyboard polling! */ + return SCPE_OK; + /* otherwise, so ^E can interrupt the simulator, */ + sim_activate(&tti_unit, tti_unit.wait); /* always continue polling keyboard */ temp = sim_poll_kbd(); @@ -201,11 +352,20 @@ static t_stat tti_svc (UNIT *uptr) temp &= 0xFF; /* remove SCPE_KFLAG */ - if (temp == IRQ_KEY) { /* interrupt request key */ + if ((tti_unit.flags & CSET_MASK) == CSET_ASCII) + temp = conin_map[temp] & 0xFF; /* perform input translation */ + + if (temp == IRQ_KEY) { /* INT REQ (interrupt request) key */ SETBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); /* queue interrupt */ SETBIT(ILSW[4], ILSW_4_CONSOLE); calc_ints(); + CLRBIT(tti_unit.flags, KEYBOARD_LOCKED); /* keyboard restore, according to func. char. manual */ + +#ifdef DEBUG_CONSOLE + printf("[*IRQ*]"); +#endif + tti_unit.buf = 0; /* subsequent reads need to return 0 (required by APL\1130) */ return SCPE_OK; } @@ -214,31 +374,42 @@ static t_stat tti_svc (UNIT *uptr) SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP); calc_ints(); +#ifdef DEBUG_CONSOLE + printf("[*PSTOP*]"); +#endif + return SCPE_OK; } - if (tti_dsw & TT_DSW_KEYBOARD_BUSY) { /* only store character if it was requested (keyboard unlocked) */ - if ((uptr->flags & CSET_MASK) == CSET_NORMAL) - temp = ascii_to_conin[temp]; - - if (temp == 0) { /* ignore invalid characters */ - Beep(); - calc_ints(); - return SCPE_OK; - } - - tti_unit.buf = temp & 0xFFFE; /* save keystroke except last bit (not defined, */ - tti_unit.pos = tti_unit.pos + 1; /* but it lets us distinguish 0 from no punch ' ' */ - - CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* clear busy flag (relock keyboard) */ - keyboard_selected(FALSE); - - SETBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); /* queue interrupt */ - SETBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - } - else + if ((tti_unit.flags & KEYBOARD_LOCKED) || ! (tti_dsw & TT_DSW_KEYBOARD_BUSY)) { Beep(); + return SCPE_OK; + } + + if ((tti_unit.flags & CSET_MASK) == CSET_ASCII) + temp = ascii_to_conin[temp]; + + if (temp == 0) { /* ignore invalid characters */ + Beep(); + calc_ints(); + return SCPE_OK; + } + + tti_unit.buf = temp & 0xFFFE; /* save keystroke except last bit (not defined) */ + tti_unit.pos = tti_unit.pos + 1; /* but it lets us distinguish 0 from no punch ' ' */ + +#ifdef DEBUG_CONSOLE + printf("[%04x]", tti_unit.buf & 0xFFFF); +#endif + +// CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* clear busy flag (unselect keyboard) */ +// keyboard_selected(FALSE); + + SETBIT(tti_unit.flags, KEYBOARD_LOCKED); /* prevent further keystrokes */ + + SETBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); /* queue interrupt */ + SETBIT(ILSW[4], ILSW_4_CONSOLE); + calc_ints(); return SCPE_OK; } @@ -252,52 +423,30 @@ static t_stat tti_reset (DEVICE *dptr) calc_ints(); keyboard_selected(FALSE); - sim_activate(&tti_unit, tti_unit.wait); /* always poll keyboard */ + SETBIT(tti_unit.flags, KEYBOARD_LOCKED); + + if (cgi) + sim_cancel(&tti_unit); /* in cgi mode, never poll keyboard */ + else + sim_activate(&tti_unit, tti_unit.wait); /* otherwise, always poll keyboard */ return SCPE_OK; } -t_bool keyboard_is_locked (void) /* return TRUE if keyboard is not expecting a character */ +t_bool keyboard_is_busy (void) /* return TRUE if keyboard is not expecting a character */ { - return (tti_dsw & TT_DSW_KEYBOARD_BUSY) == 0; + return (tti_dsw & TT_DSW_KEYBOARD_BUSY); } static t_stat tto_svc (UNIT *uptr) { - int32 temp; - int ch; - CLRBIT(tto_dsw, TT_DSW_PRINTER_BUSY); SETBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE); SETBIT(ILSW[4], ILSW_4_CONSOLE); calc_ints(); - ch = tto_unit.buf & 0xFF; - - switch (ch) { - case IGNR: - break; - - case CRLF: - if (! cgi) - if ((temp = sim_putchar('\r')) != SCPE_OK) - return temp; - if ((temp = sim_putchar('\n')) != SCPE_OK) - return temp; - - break; - - default: - if ((temp = sim_putchar(ch)) != SCPE_OK) - return temp; - - break; - } - - tto_unit.pos = tto_unit.pos + 1; /* hmm, why do we count these? */ - - return SCPE_OK; + return (t_stat) tto_unit.buf; /* return status saved during output conversion */ } static t_stat tto_reset (DEVICE *dptr) @@ -308,9 +457,818 @@ static t_stat tto_reset (DEVICE *dptr) CLRBIT(ILSW[4], ILSW_4_CONSOLE); calc_ints(); - sim_cancel(&tto_unit); /* deactivate unit */ + sim_cancel(&tto_unit); /* deactivate unit */ + + set_conout_mapping(tto_unit.flags); /* initialize the overstrike mappings */ + /* register the font-mapping command */ + register_cmd("FONT", font_cmd, 0, "font MAPFILE use font mapping definitions in MAPFILE\n"); return SCPE_OK; } +#ifdef _MSC_VER +# pragma warning(disable:4245) /* enable int->char demotion warning caused by characters with high-bit set */ +#endif +static struct { /* default input mapping for APL */ + unsigned char in; + unsigned char out; +} conin_to_APL[] = +{ /* these map input keys to those in like positions on 1130 keyboard */ + '[', '\r', /* enter (EOF) is APL left arrow */ + ';', '\b', /* backspace is APL [ */ + '\'', '\x15', /* ctrl-U, erase field, is APL ]*/ + '2', '@', /* APL upshift */ + '3', '%', /* APL rightshift */ + '4', '*', /* APL + and - */ + '5', '<', /* APL x and divide */ + '8', '-', /* APL return */ + '9', '/', /* APL backspace */ + '-', IRQ_KEY, /* ctrl-q (INT REQ), APL ATTN */ + '\r', '-', /* APL return */ + '\b', '/' /* APL backspace */ +}; + +#define NCONIN_TO_APL (sizeof(conin_to_APL)/sizeof(conin_to_APL[0])) + +static struct { /* default output mapping for APLPLUS font */ + unsigned char in; + unsigned char out; +} conout_to_APL[] = +{ + '\x01', IGNR_, /* controls */ + '\x03', '\n', + '\x05', IGNR_, /* (black and red are handled by ansi sequences) */ + '\x09', IGNR_, + '\x11', '\b', + '\x21', ' ', + '\x41', '\t', + '\x81', CRLF_, + + '\xC4', '\x30', /* (if you're curious, order here is position on APL typeball) */ + '\xE4', '\x38', + '\xD4', '\x37', + '\xF4', '\x35', + '\xDC', '\x33', + '\xFC', '\x31', + '\xC2', '\x29', + '\xE2', '\x9F', + '\xD2', '\x89', + '\xF2', '\x88', + '\xDA', '\xAF', + '\xC6', '\x5E', + '\xE6', '\xAC', + '\xD6', '\x3E', + '\xF6', '\x3D', + '\xDE', '\x3C', + '\xFE', '\xA8', + '\xC0', '\x5D', + '\xE0', '\x39', + '\xD0', '\x36', + '\xF0', '\x34', + '\xD8', '\x32', + + '\x84', '\x84', + '\xA4', '\x59', + '\x94', '\x58', + '\xB4', '\x56', + '\x9C', '\x54', + '\xBC', '\x2F', + '\x82', '\x3B', + '\xA2', '\x9B', + '\x92', '\xBE', + '\xB2', '\x87', + '\x9A', '\x97', + '\x86', '\x85', + '\xA6', '\x86', + '\x96', '\x9C', + '\xB6', '\x9E', + '\x9E', '\x7E', + '\xBE', '\x5C', + '\x80', '\x2C', + '\xA0', '\x5A', + '\x90', '\x57', + '\xB0', '\x55', + '\x98', '\x53', + + '\x44', '\x2B', + '\x64', '\x51', + '\x54', '\x50', + '\x74', '\x4E', + '\x5C', '\x4C', + '\x7C', '\x4A', + '\x42', '\x28', + '\x62', '\xBD', + '\x52', '\xB1', + '\x72', '\x7C', + '\x5A', '\x27', + '\x46', '\x2D', + '\x66', '\x3F', + '\x56', '\x2A', + '\x76', '\x82', + '\x5E', '\x8C', + '\x7E', '\xB0', + '\x40', '\x5B', + '\x60', '\x52', + '\x50', '\x4F', + '\x70', '\x4D', + '\x58', '\x4B', + + '\x04', '\xD7', + '\x24', '\x48', + '\x14', '\x47', + '\x34', '\x45', + '\x1C', '\x43', + '\x3C', '\x41', + '\x02', '\x3A', + '\x22', '\xBC', + '\x12', '\x5F', + '\x32', '\x98', + '\x1A', '\x83', + '\x06', '\xF7', + '\x26', '\x91', + '\x16', '\x92', + '\x36', '\xB9', + '\x1E', '\x9D', + '\x3E', '\xB8', + '\x00', '\x2E', + '\x20', '\x49', + '\x10', '\x46', + '\x30', '\x44', + '\x18', '\x42', +}; + +#define NCONOUT_TO_APL (sizeof(conout_to_APL)/sizeof(conout_to_APL[0])) + +static OS_MAP default_os_map[] = // overstrike mapping for APLPLUS font +{ + '\x8a', 2, "\x5e\x7e", + '\x8b', 2, "\x9f\x7e", + '\x8d', 2, "\x8c\x27", + '\x8e', 3, "\x8c\x2d\x3a", + '\x8f', 2, "\x91\x5f", + '\x90', 2, "\x92\x7e", + '\x93', 2, "\x91\x7c", + '\x94', 2, "\x92\x7c", + '\x95', 2, "\xb0\x82", + '\x96', 2, "\xb0\x83", + '\x99', 2, "\x2d\x5c", + '\x9a', 2, "\x2d\x2f", + '\xae', 2, "\x2c\x2d", + '\xb2', 2, "\xb1\x7c", + '\xb3', 2, "\xb1\x5c", + '\xb4', 2, "\xb1\x2d", + '\xb5', 2, "\xb1\x2a", + '\xba', 2, "\xb9\x5f", + '\xd0', 2, "\x30\x7e", + '\xd8', 2, "\x4f\x2f", + '\x21', 2, "\x27\x2e", + '\xa4', 2, "\xb0\xb1", /* map degree in circle to circle cross (APL uses this as character error symbol) */ + '\xf0', 2, "\xb0\xa8", + '\xfe', 2, "\x3a\xa8", +}; + +#ifdef _MSC_VER +# pragma warning(default:4245) /* enable int->char demotion warning */ +#endif + +/* os_map_comp - compare to OS_MAP entries */ + +static int os_map_comp (OS_MAP *a, OS_MAP *b) +{ + unsigned char *sa, *sb; + int i; + + if (a->nin > b->nin) + return +1; + + if (a->nin < b->nin) + return -1; + + sa = a->inlist; + sb = b->inlist; + + for (i = a->nin; --i >= 0;) { + if (*sa > *sb) + return +1; + + if (*sa < *sb) + return -1; + + sa++; + sb++; + } + + return 0; +} + +/* strsort - sorts the n characters of array 's' using insertion sort */ + +static void strsort (int n, unsigned char *s) +{ + unsigned char temp; + int i, big; + + while (--n > 0) { // repeatedly + big = 0; // find largest value of s[0]...s[n] + for (i = 1; i <= n; i++) + if (s[i] > s[big]) big = i; + + temp = s[n]; // put largest value at end of array + s[n] = s[big]; + s[big] = temp; + } +} + +/* file format: + +[font XXX] // font named XXX +OUT // failure character +OUT IN // single character mapping +OUT IN IN ... // overstrike mapping + +*/ + +static void set_conout_mapping (int32 flags) +{ + curcol = 0; + maxcol = 0; + + // set the default mappings. We may later override them with settings from an ini file + + set_default_mapping(flags); +} + +// finish_conout_mapping - sort the finalized overstrike mapping + +static void finish_conout_mapping (int32 flags) +{ + int i, n, big; + OS_MAP temp; + + for (i = 0; i < n_os_mappings; i++) // sort the inlist strings individually + strsort(os_map[i].nin, os_map[i].inlist); + + for (n = n_os_mappings; --n > 0; ) { // then sort the os_map array itself with insertion sort + big = 0; // find largest value of s[0]...s[n] + for (i = 1; i <= n; i++) + if (os_map_comp(os_map+i, os_map+big) > 0) big = i; + + if (big != n) { + temp = os_map[n]; // put largest value at end of array + os_map[n] = os_map[big]; + os_map[big] = temp; + } + } +} + +// validate_conout_mapping - called when set command gets a new value + +static t_stat validate_conout_mapping (UNIT *uptr, int32 match, char *cvptr, void *desc) +{ + set_conout_mapping(match); + return SCPE_OK; +} + +static void reset_mapping (void) +{ + int i; + + black_ribbon[0] = '\0'; /* erase the ribbon sequences */ + red_ribbon[0] = '\0'; + + memset(conout_map, 0, sizeof(conout_map)); /* erase output mapping */ + + n_os_mappings = 0; /* erase overstrike mapping */ + + for (i = (sizeof(conin_map)/sizeof(conin_map[0])); --i >= 0; ) + conin_map[i] = (unsigned char) i; /* default conin_map is identity map */ +} + +// set_default_mapping - create standard font and overstrike map + +static void set_default_mapping (int32 flags) +{ + int i; + + reset_mapping(); + + strcpy(black_ribbon, "\033[30m"); + strcpy(red_ribbon, "\033[31m"); + + switch (flags & CSET_MASK) { + case CSET_1130: + break; + + case CSET_ASCII: + memcpy(conout_map, conout_to_ascii, sizeof(conout_to_ascii)); + break; + + case CSET_APL: + for (i = NCONOUT_TO_APL; --i >= 0; ) + conout_map[conout_to_APL[i].in] = conout_to_APL[i].out; + + for (i = NCONIN_TO_APL; --i >= 0; ) + conin_map[conin_to_APL[i].in] = conin_to_APL[i].out; + + memcpy(os_map, default_os_map, sizeof(default_os_map)); + n_os_mappings = (sizeof(default_os_map) / sizeof(default_os_map[0])); + break; + } + + finish_conout_mapping(flags); // sort conout mapping if necessary +} + +// sim_putstr - write a string to the console + +t_stat sim_putstr (char *s) +{ + t_stat status; + + while (*s) { + if ((status = sim_putchar(*s)) != SCPE_OK) + return status; + + s++; + } + + return SCPE_OK; +} + +// map_conout_character - translate and write a single character + +static t_stat map_conout_character (int ch) +{ + t_stat status; + int i, cmp; + + if (ch == (COUT_IS_CTRL|COUT_CTRL_BLACK)) + return (tto_unit.flags & ENABLE_ANSI) ? sim_putstr(black_ribbon) : SCPE_OK; + + if (ch == (COUT_IS_CTRL|COUT_CTRL_RED)) + return (tto_unit.flags & ENABLE_ANSI) ? sim_putstr(red_ribbon) : SCPE_OK; + + if ((ch = conout_map[ch & 0xFF]) == 0) + ch = '?'; // unknown character? print ? + + if (ch == '\n') { // newline: reset overstrike buffer + curcol = 0; + maxcol = -1; + } + else if (ch == '\r') { // carriage return: rewind to column 0 + curcol = 0; + maxcol = -1; // assume it advances paper too + } + else if (ch == '\b') { // backspace: back up one character + if (curcol > 0) + curcol--; + } + else if (n_os_mappings && ch != (unsigned char) IGNR_) { + if (curcol > maxcol) { // first time in this column, no overstrike possible yet + os_buf[curcol].nin = 0; + maxcol = curcol; + } + + if (ch != ' ' && ch != 0) { // (if it's not a blank or unknown) + os_buf[curcol].inlist[os_buf[curcol].nin] = (unsigned char) ch; + strsort(++os_buf[curcol].nin, os_buf[curcol].inlist); + } + + if (os_buf[curcol].nin == 0) // if nothing but blanks seen, + ch = ' '; // output is a blank + else if (os_buf[curcol].nin == 1) { // if only one printing character seen, display it + ch = os_buf[curcol].inlist[0]; + } + else { // otherwise look up mapping + ch = '?'; + + for (i = 0; i < n_os_mappings; i++) { + cmp = os_map_comp(&os_buf[curcol], &os_map[i]); + if (cmp == 0) { // a hit + ch = os_map[i].ch; + break; + } + else if (cmp < 0) // not found + break; + } + } + + if (curcol < MAX_OUTPUT_COLUMNS) + curcol++; + } + + switch (ch) { + case IGNR_: + break; + + case CRLF_: + if (! cgi) { + if ((status = sim_putchar('\r')) != SCPE_OK) + return status; + + tto_unit.pos++; + } + + if ((status = sim_putchar('\n')) != SCPE_OK) + return status; + + tto_unit.pos++; /* hmm, why do we count these? */ + break; + + default: + if ((status = sim_putchar(ch)) != SCPE_OK) + return status; + + tto_unit.pos++; + break; + } + + return SCPE_OK; +} + +/* font_cmd - parse a font mapping file. Sets input and output translations */ + +static t_stat font_cmd (int32 flag, char *cptr) +{ + char *fname, quote; + FILE *fd; + + while (*cptr && (*cptr <= ' ')) cptr++; /* skip blanks */ + if (! *cptr) return SCPE_2FARG; /* argument missing */ + + fname = cptr; /* save start */ + while (*cptr && (*cptr > ' ')) { + if (*cptr == '\'' || *cptr == '"') { /* quoted string */ + quote = *cptr; /* remember quote character */ + strcpy(cptr, cptr+1); /* slide string down over the quote */ + + while (*cptr && *cptr != quote) /* find closing quote */ + cptr++; + + if (*cptr == quote) /* if closer was found, slide down over it */ + strcpy(cptr, cptr+1); + } + else /* skip over regular character */ + cptr++; + } + *cptr = '\0'; /* terminate name */ + + if ((fd = fopen(fname, "r")) == NULL) + return SCPE_OPENERR; + + reset_mapping(); /* remove all default mappings */ + + read_map_file(fd); + fclose(fd); + + finish_conout_mapping(tto_unit.flags); + return SCPE_OK; +} + +/* str_match - compare the string str to the keyword, case insensitive */ + +static t_bool str_match (char *str, char *keyword) +{ + char kch, sch; + + while (*keyword) { /* see if str matches the keyword... */ + kch = *keyword++; /* get pair of characters */ + sch = *str++; + + if (BETWEEN(kch, 'A', 'Z')) kch += 32; /* change upper to lower case */ + if (BETWEEN(sch, 'A', 'Z')) sch += 32; + + if (kch != sch) /* characters must match; if not, quit */ + return FALSE; + } + + return *str <= ' ' || *str == ';'; /* success if the input string ended or is in whitespace or comment */ +} + +/* read_map_file - process definition lines in opened mapping file */ + +static void read_map_file (FILE *fd) +{ + char str[256], *c, *errmsg; + int lineno = 0; + enum {SECT_UNDEFINED, SECT_DEFAULT, SECT_ANSI, SECT_INPUT, SECT_OUTPUT, SECT_OVERSTRIKE} + section = SECT_UNDEFINED; + + while (fgets(str, sizeof(str), fd) != NULL) { + ++lineno; /* count input lines */ + + if ((c = strchr(str, '\n')) != NULL) /* terminate at newline */ + *c = '\0'; + + for (c = str; *c && *c <= ' '; c++) /* skip blanks */ + ; + + if (c[0] == '\0' || c[0] == ';') /* ignore blank lines and lines starting with ; */ + continue; + + if (*c == '[') { + if (str_match(c, "[default]")) { /* check for section separators */ + set_default_mapping(tto_unit.flags); + section = SECT_UNDEFINED; + continue; + } + if (str_match(c, "[ansi]")) { + section = SECT_ANSI; + continue; + } + if (str_match(c, "[input]")) { + section = SECT_INPUT; + continue; + } + if (str_match(c, "[output]")) { + section = SECT_OUTPUT; + continue; + } + if (str_match(c, "[overstrike]")) { + section = SECT_OVERSTRIKE; + continue; + } + } + + switch (section) { /* if we get here, we have a definition line */ + case SECT_ANSI: + errmsg = handle_map_ansi_definition(&c); + break; + case SECT_INPUT: + errmsg = handle_map_input_definition(&c); + break; + case SECT_OUTPUT: + errmsg = handle_map_output_definition(&c); + break; + case SECT_OVERSTRIKE: + errmsg = handle_map_overstrike_definition(&c); + break; + default: + errmsg = "line occurs before valid [section]"; + break; + } + + if (errmsg == NULL) { /* if no other error detected, */ + while (*c && *c <= ' ') /* skip past any whitespace */ + c++; + + if (*c && *c != ';') /* if line doesn't end or run into a comment, complain */ + errmsg = "too much stuff on input line"; + } + + if (errmsg != NULL) { /* print error message and offending line */ + printf("* Warning: %s", errmsg); + + switch (section) { /* add section name if possible */ + case SECT_ANSI: errmsg = "ansi"; break; + case SECT_INPUT: errmsg = "input"; break; + case SECT_OUTPUT: errmsg = "output"; break; + case SECT_OVERSTRIKE: errmsg = "overstrike"; break; + default: errmsg = NULL; break; + } + if (errmsg != NULL) + printf(" in [%s] section", errmsg); + + printf(", line %d\n%s\n", lineno, str); + } + } +} + +/* get_num_char - read an octal or hex character specification of exactly 'ndigits' digits + * the input pointers is left pointing to the last character of the number, so that it + * may be incremented by the caller + */ + +static char * get_num_char (char **pc, unsigned char *out, int ndigits, int base, char *errmsg) +{ + unsigned char ch = 0, digit; + char *c = *pc; + + while (--ndigits >= 0) { /* collect specified number of digits */ + if (BETWEEN(*c, '0', '9')) + digit = *c - '0'; + else if (BETWEEN(*c, 'A', 'F')) + digit = *c - 'A' + 10; + else if (BETWEEN(*c, 'a', 'f')) + digit = *c - 'a' + 10; + else + digit = base; + + if (digit >= base) /* bad digit */ + return errmsg; + + ch = ch * base + digit; /* accumulate digit */ + c++; + } + + *out = ch; /* return parsed character */ + *pc = c-1; /* make input pointer point to last character seen */ + return NULL; /* no error */ +} + +/* get_characters - read character specification(s) from input string pointed to + * by *pc. Results stored in outstr; up to nmax characters parsed. Actual number + * found returned in *nout. Returns NULL on success or error message if syntax + * error encountered. *pc is advanced to next whitespace or whatever followed input. + */ + +static char * get_characters (char **pc, char *outstr, int nmax, int *nout) +{ + char *c = *pc, *out = outstr, *errstr; + + while (*c && *c <= ' ') /* skip leading whitespace */ + c++; + + while (--nmax >= 0) { /* get up to maximum number of characters */ + if (*c == ';' || *c <= ' ') /* we ran into a comment, whitespace or end of string: we're done */ + break; + + if (*c == '\\') { /* backslash escape of some sort */ + switch (*++c) { + case 'b': /* backspace */ + case 'B': + *out++ = '\b'; + break; + + case 'e': /* ascii ESCAPE */ + case 'E': + *out++ = '\033'; + break; + + case 'f': /* formfeed */ + case 'F': + *out++ = '\f'; + break; + + case 'n': /* newline */ + case 'N': + *out++ = '\n'; + break; + + case 'r': /* return */ + case 'R': + *out++ = '\r'; + break; + + case 't': /* tab */ + case 'T': + *out++ = '\t'; + break; + + case 'x': /* hex specification */ + case 'X': + c++; + if ((errstr = get_num_char(&c, out, 2, 16, "bad hex character")) != NULL) + return errstr; + + out++; /* advance out pointer */ + break; + + default: /* anything else */ + if (BETWEEN(*c, '0', '7')) { /* octal specification */ + if ((errstr = get_num_char(&c, out, 3, 8, "bad octal character")) != NULL) + return errstr; + + out++; /* advance out pointer */ + } + else if (BETWEEN(*c, 'A', 'Z') || BETWEEN(*c, 'a', 'z')) + return "invalid \\ escape"; /* other \x letters are bad */ + else { + *out++ = *c; /* otherwise, accept \x as literal character x */ + } + break; + } + } + else if (*c == '^') { /* control character */ + c++; + if (BETWEEN(*c, 'A', 'Z')) /* convert alpha, e.g. A -> 1 */ + *out++ = *c - 'A' + 1; + else if (BETWEEN(*c, 'a', 'z')) + *out++ = *c - 'z' + 1; + else /* non alpha is bad */ + return "invalid control letter"; + } + else if (str_match(c, "IGNORE")) { /* magic word: a character that will never be output */ + *out++ = IGNR_; + c += 6; + } + else { + *out++ = *c; /* save literal character */ + } + + c++; + } + + if (*c && *c != ';' && *c > ' ') /* we should be at end of string, whitespace or comment */ + return "too many characters specified"; + + *pc = c; /* save advanced pointer */ + *nout = out-outstr; /* save number of characters stored */ + + return NULL; /* no error */ +} + +/* handle_map_ansi_definition - process line in [ansi] section */ + +static char * handle_map_ansi_definition (char **pc) +{ + char *outstr, *errmsg; + int n; + + if (str_match(*pc, "black")) { /* find which string we're setting */ + outstr = black_ribbon; /* this is where we'll save the output string */ + *pc += 5; /* skip over the token */ + } + else if (str_match(*pc, "red")) { + outstr = red_ribbon; + *pc += 3; + } + else + return "invalid variable name"; + /* get list of characters */ + if ((errmsg = get_characters(pc, outstr, sizeof(black_ribbon)-1, &n)) != NULL) + return errmsg; + + outstr[n] = '\0'; /* null terminate the string */ + + return (n > 0) ? NULL : "missing output string"; /* NULL if OK, error msg if no characters */ +} + +/* handle_map_input_definition - process line in [input] section */ + +static char * handle_map_input_definition (char **pc) +{ + unsigned char cin, cout; + char *errmsg; + int n; + + if ((errmsg = get_characters(pc, &cin, 1, &n)) != NULL) /* get input character */ + return errmsg; + + if (n != 1) + return "missing input character"; + + if ((errmsg = get_characters(pc, &cout, 1, &n)) != NULL) /* get output character */ + return errmsg; + + if (n != 1) + return "missing output character"; + + conin_map[cin] = cout; /* set the mapping */ + return NULL; +} + +/* handle_map_output_definition - process line in [output] section */ + +static char * handle_map_output_definition (char **pc) +{ + unsigned char cin, cout; + char *errmsg; + int n; + + if ((errmsg = get_characters(pc, &cin, 1, &n)) != NULL) /* get input character */ + return errmsg; + + if (n != 1) + return "missing input character"; + + if ((errmsg = get_characters(pc, &cout, 1, &n)) != NULL) /* get output character */ + return errmsg; + + if (n != 1) + return "missing output character"; + + conout_map[cin] = cout; /* set the mapping */ + return NULL; +} + +/* handle_map_overstrike_definition - process line in [overstrike] section */ + +static char * handle_map_overstrike_definition (char **pc) +{ + unsigned char ch, inlist[MAX_OS_CHARS]; + char *errmsg; + int nin; + + if (n_os_mappings >= MAX_OS_MAPPINGS) /* os_map is full, no more room */ + return "too many overstrike mappings"; + /* get output character */ + if ((errmsg = get_characters(pc, &ch, 1, &nin)) != NULL) + return errmsg; + + if (nin != 1) + return "missing output character"; + /* get input list */ + if ((errmsg = get_characters(pc, inlist, MAX_OS_CHARS, &nin)) != NULL) + return errmsg; + + if (nin < 2) /* expect at least two characters overprinted */ + return "missing input list"; + + os_map[n_os_mappings].ch = ch; /* save in next os_map slot */ + os_map[n_os_mappings].nin = nin; + memmove(os_map[n_os_mappings].inlist, inlist, nin); + + n_os_mappings++; + return NULL; +} diff --git a/Ibm1130/ibm1130_sys.c b/Ibm1130/ibm1130_sys.c index 0a382e45..ba3a4f49 100644 --- a/Ibm1130/ibm1130_sys.c +++ b/Ibm1130/ibm1130_sys.c @@ -20,7 +20,7 @@ * or modifications. * * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org + * Mail to simh@ibm1130.org */ #include "ibm1130_defs.h" diff --git a/Ibm1130/makefile b/Ibm1130/makefile index e00a5af5..7aabb801 100644 --- a/Ibm1130/makefile +++ b/Ibm1130/makefile @@ -58,9 +58,11 @@ ibm1130D = ./ ibm1130 = ${ibm1130D}ibm1130_sys.c ${ibm1130D}ibm1130_cpu.c \ ${ibm1130D}ibm1130_cr.c ${ibm1130D}ibm1130_disk.c \ ${ibm1130D}ibm1130_stddev.c ${ibm1130D}ibm1130_gdu.c \ - ${ibm1130D}ibm1130_gui.c ${ibm1130D}ibm1130_prt.c + ${ibm1130D}ibm1130_gui.c ${ibm1130D}ibm1130_prt.c \ + ${ibm1130D}ibm1130_fmt.c + ibm1130_INC = ibm1130res.h ibm1130_conin.h ibm1130_conout.h \ - ibm1130_defs.h ibm1130_prtwheel.h \ + ibm1130_defs.h ibm1130_prtwheel.h ibm1130_fmt.h \ dmsr2v12phases.h dmsr2v12slet.h # diff --git a/Ibm1130/readme1130.txt b/Ibm1130/readme1130.txt index 31c94fd1..e7a20831 100644 --- a/Ibm1130/readme1130.txt +++ b/Ibm1130/readme1130.txt @@ -1,5 +1,10 @@ Here's the 1130 simulator as it stands now. +Status: 22Jul2003 + + * Added support for APL\1130 output translations + and some bug fixes uncovered by APL. + Status: 13Sep2002 * Added support for 1403 printer. It's MUCH faster diff --git a/Ibm1130/readme_update.txt b/Ibm1130/readme_update.txt index 6bb2682e..aab52dbc 100644 --- a/Ibm1130/readme_update.txt +++ b/Ibm1130/readme_update.txt @@ -1,7 +1,11 @@ -Version: 18 March 2003 +Version: 10 July 2003 History (partial): +2003-07-10 Fixed disk and console terminal bugs uncovered by + APL\1130. Added APL keyboard and output font support + to enable use of APL\1130. APL will be released soon. + 2003-03-18 Fixed bug in asm1130 that produced an error message with a (legal) offset of +127 in MDX instructions. diff --git a/Ibm1130/utils/asm1130.c b/Ibm1130/utils/asm1130.c index b1643e91..5cf9e31f 100644 --- a/Ibm1130/utils/asm1130.c +++ b/Ibm1130/utils/asm1130.c @@ -13,6 +13,7 @@ // ASM1130 - IBM 1130 Cross Assembler // // Version +// 1.08 - 2003Mar18 - Fixed bug that complained about valid MDX displacement of +127 // 1.07 - 2003Jan05 - Filenames are now left in lower case. SYMBOLS.SYS stays all upper case // 1.06 - 2002May02 - Fixed bug in ebdic constants (data goes into low byte) // First stab at adding ISS level # info, this is iffy @@ -156,7 +157,7 @@ #define TRUE 1 #define FALSE 0 -#define VERSION "ASM1130 CROSS ASSEMBLER V1.07" +#define VERSION "ASM1130 CROSS ASSEMBLER V1.08" #define ISTV 0x33 // magic number from DMS R2V12 monitorm symbol @ISTV @@ -3392,7 +3393,7 @@ void mdx_op (struct tag_op *op, char *label, char *mods, char *arg) else getexpr(tok, FALSE, &incr); - if (incr.value < -128 || incr.value >= 127) // displacement style + if (incr.value < -128 || incr.value > 127) // displacement style (fixed in ver 1.08) asm_error("Invalid increment value (8 bits signed)"); opcode |= (incr.value & 0xFF); diff --git a/Ibm1130/utils/bindump.c b/Ibm1130/utils/bindump.c index 478f3e3c..332e42ee 100644 --- a/Ibm1130/utils/bindump.c +++ b/Ibm1130/utils/bindump.c @@ -426,7 +426,7 @@ void show_data (void) (reloc == R_LIBF) ? 'L' : '@'; printf("%04x%c ", buf[9+i], ch); - rflag << 2; + rflag <<= 2; nout++; } putchar('\n'); diff --git a/Ibm1130/utils/mkboot.c b/Ibm1130/utils/mkboot.c index d945d63c..115cdad4 100644 --- a/Ibm1130/utils/mkboot.c +++ b/Ibm1130/utils/mkboot.c @@ -337,7 +337,7 @@ void show_data (unsigned short *buf) (reloc == R_LIBF) ? 'L' : '@'; printf("%04x%c ", buf[9+i], ch); - rflag << 2; + rflag <<= 2; nout++; } putchar('\n'); diff --git a/Ibm1130/utils/viewdeck.c b/Ibm1130/utils/viewdeck.c index 5d83483f..1bbcc30d 100644 --- a/Ibm1130/utils/viewdeck.c +++ b/Ibm1130/utils/viewdeck.c @@ -15,25 +15,61 @@ #include #include +#define TRUE 1 +#define FALSE 0 +typedef int BOOL; + int hollerith_to_ascii (unsigned short h); void bail (char *msg); +void format_coldstart (unsigned short *buf); int main (int argc, char **argv) { FILE *fd; - char line[82]; + char *fname = NULL, line[82], *arg; + BOOL coldstart = FALSE; unsigned short buf[80]; int i, lastnb; + static char usestr[] = + "Usage: viewdeck [-c] deckfile\n" + "\n" + "-c: convert cold start card to 16-bit format as a C array initializer\n"; - if (argc != 2) - bail("Usage: viewdeck deckfile"); + for (i = 1; i < argc; i++) { // process command line arguments + arg = argv[i]; - if ((fd = fopen(argv[1], "rb")) == NULL) { - perror(argv[1]); + if (*arg == '-') { + arg++; + while (*arg) { + switch (*arg++) { + case 'c': + coldstart = TRUE; + break; + default: + bail(usestr); + } + } + } + else if (fname == NULL) // first non-switch arg is file name + fname = arg; + else + bail(usestr); // there can be only one name + } + + if (fname == NULL) // there must be a name + bail(usestr); + + if ((fd = fopen(fname, "rb")) == NULL) { + perror(fname); return 1; } while (fread(buf, sizeof(short), 80, fd) == 80) { + if (coldstart) { + format_coldstart(buf); + break; + } + lastnb = -1; for (i = 0; i < 80; i++) { line[i] = hollerith_to_ascii(buf[i]); @@ -45,11 +81,39 @@ int main (int argc, char **argv) fputs(line, stdout); } + if (coldstart) { + if (fread(buf, sizeof(short), 1, fd) == 1) + bail("Coldstart deck has more than one card"); + } + fclose(fd); return 0; } +void format_coldstart (unsigned short *buf) +{ + int i, nout = 0; + unsigned short word; + + for (i = 0; i < 80; i++) { + word = buf[i]; // expand 12-bit card data to 16-bit instruction + word = (word & 0xF800) | ((word & 0x0400) ? 0x00C0 : 0x0000) | ((word & 0x03F0) >> 4); + + if (nout >= 8) { + fputs(",\n", stdout); + nout = 0; + } + else if (i > 0) + fputs(", ", stdout); + + printf("0x%04x", word); + nout++; + } + + putchar('\n'); +} + typedef struct { unsigned short hollerith; char ascii; @@ -103,7 +167,7 @@ static CPCODE cardcode_029[] = 0x0120, '\'', 0x00A0, '=', 0x0060, '"', - 0x8820, 'c', // cent + 0x8820, '\xA2', // cent, in MS-DOS encoding 0x8420, '.', 0x8220, '<', // ) in 026 Fortran 0x8120, '(', @@ -114,13 +178,47 @@ static CPCODE cardcode_029[] = 0x4220, '*', 0x4120, ')', 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? + 0x4060, '\xAC', // not, in MS-DOS encoding 0x2420, ',', 0x2220, '%', // ( in 026 Fortran 0x2120, '_', 0x20A0, '>', - 0x2060, '>', + 0xB000, 'a', + 0xA800, 'b', + 0xA400, 'c', + 0xA200, 'd', + 0xA100, 'e', + 0xA080, 'f', + 0xA040, 'g', + 0xA020, 'h', + 0xA010, 'i', + 0xD000, 'j', + 0xC800, 'k', + 0xC400, 'l', + 0xC200, 'm', + 0xC100, 'n', + 0xC080, 'o', + 0xC040, 'p', + 0xC020, 'q', + 0xC010, 'r', + 0x6800, 's', + 0x6400, 't', + 0x6200, 'u', + 0x6100, 'v', + 0x6080, 'w', + 0x6040, 'x', + 0x6020, 'y', + 0x6010, 'z', // these odd punch codes are used by APL: + 0x1010, '\001', // no corresponding ASCII using ^A + 0x0810, '\002', // SYN using ^B + 0x0410, '\003', // no corresponding ASCII using ^C + 0x0210, '\004', // PUNCH ON using ^D + 0x0110, '\005', // READER STOP using ^E + 0x0090, '\006', // UPPER CASE using ^F + 0x0050, '\013', // EOT using ^K + 0x0030, '\016', // no corresponding ASCII using ^N + 0x1030, '\017', // no corresponding ASCII using ^O + 0x0830, '\020', // no corresponding ASCII using ^P }; int hollerith_to_ascii (unsigned short h) diff --git a/Interdata/id32_sys.c b/Interdata/id32_sys.c index 3e9316f0..40ba1399 100644 --- a/Interdata/id32_sys.c +++ b/Interdata/id32_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. + 15-Jul-03 RMS Fixed signed/unsigned bug in get_imm 27-Feb-03 RMS Added relative addressing support 23-Dec-01 RMS Cloned from ID4 sources */ @@ -481,7 +482,7 @@ return reg; t_stat get_imm (char *cptr, uint32 *imm, uint32 *inst, uint32 max) { char *tptr; -uint32 idx; +int32 idx; errno = 0; *imm = strtoul (cptr, &tptr, 16); /* get immed */ diff --git a/Interdata/id_doc.txt b/Interdata/id_doc.txt index 5c9d677a..22ea0fa5 100644 --- a/Interdata/id_doc.txt +++ b/Interdata/id_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: Interdata 16b/32b Simulator Usage -Date: 15-Mar-2003 +Date: 15-Jul-2003 COPYRIGHT NOTICE @@ -39,10 +39,12 @@ This memorandum documents the Interdata 16b and 32b simulators. sim/ sim_defs.h sim_rev.h sim_sock.h + sim_tape.h sim_tmxr.h scp.c scp_tty.c sim_sock.c + sim_tape.c sim_tmxr.c sim/interdata/ id_defs.h @@ -519,8 +521,7 @@ The programmable interval clock (PIC) implements these registers: IARM 1 clock interrupt armed If the interval requested is an exact multiple of 1 msec, the -programmable clock auto-calibrates; if not, it simply counts -counts instructions. +programmable clock auto-calibrates; if not, it counts instructions. 2.4.7 Floppy Disk Controller (FD) @@ -822,7 +823,7 @@ line switches: alphabetic instruction mnemonic numeric octal number -2.7.1 16b Instruction Input +2.8.1 16b Instruction Input Instruction input uses standard Interdata assembler syntax. There are seven instruction classes: short branch, extended short branch, short @@ -883,7 +884,7 @@ preceded by R, between 0 and F (15), the address is a hex number between 0 and 0xFFFF, and the index register is a hex (decimal) number, optionally preceded by R, between 1 and F (15). -2.7.2 32b Instruction Input +2.8.2 32b Instruction Input Instruction input uses standard Interdata assembler syntax. There are nine instruction classes: short branch, extended short branch, short diff --git a/NOVA/nova_doc.txt b/NOVA/nova_doc.txt index c5fb8a02..b2bd632e 100644 --- a/NOVA/nova_doc.txt +++ b/NOVA/nova_doc.txt @@ -305,8 +305,8 @@ The clock implements these registers: TIME2 24 clock frequency, select = 2 TIME3 24 clock frequency, select = 3 -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. +The real-time clock autocalibrates; the clock interval is adjusted up +or down so that the clock tracks actual elapsed time. 2.2.7 Plotter (PTP) diff --git a/NOVA/nova_dsk.c b/NOVA/nova_dsk.c index c8832e7d..d1fbc04a 100644 --- a/NOVA/nova_dsk.c +++ b/NOVA/nova_dsk.c @@ -25,6 +25,7 @@ dsk fixed head disk + 26-Jul-03 RMS Fixed bug in set size routine 14-Mar-03 RMS Fixed variable capacity interaction with save/restore 03-Mar-03 RMS Fixed variable capacity and autosizing 03-Oct-02 RMS Added DIB @@ -133,14 +134,14 @@ REG dsk_reg[] = { { NULL } }; MTAB dsk_mod[] = { - { UNIT_PLAT, 0, NULL, "1P", &dsk_set_size }, - { UNIT_PLAT, 1, NULL, "2P", &dsk_set_size }, - { UNIT_PLAT, 2, NULL, "3P", &dsk_set_size }, - { UNIT_PLAT, 3, NULL, "4P", &dsk_set_size }, - { UNIT_PLAT, 4, NULL, "5P", &dsk_set_size }, - { UNIT_PLAT, 5, NULL, "6P", &dsk_set_size }, - { UNIT_PLAT, 6, NULL, "7P", &dsk_set_size }, - { UNIT_PLAT, 7, NULL, "8P", &dsk_set_size }, + { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &dsk_set_size }, + { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &dsk_set_size }, + { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &dsk_set_size }, + { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &dsk_set_size }, + { UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &dsk_set_size }, + { UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &dsk_set_size }, + { UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &dsk_set_size }, + { UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &dsk_set_size }, { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, { 0 } }; @@ -289,9 +290,9 @@ return attach_unit (uptr, cptr); t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if ((val < 0) || (val >= DSK_NUMDK)) return SCPE_IERR; +if (val < 0) return SCPE_IERR; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = (val + 1) * DSK_DKSIZE; +uptr->capac = UNIT_GETP (val) * DSK_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; } diff --git a/PDP1/pdp1_cpu.c b/PDP1/pdp1_cpu.c index 21b4988e..acc5f4fa 100644 --- a/PDP1/pdp1_cpu.c +++ b/PDP1/pdp1_cpu.c @@ -25,6 +25,7 @@ cpu PDP-1 central processor + 23-Jul-03 RMS Revised to detect I/O wait hang 05-Dec-02 RMS Added drum support 06-Oct-02 RMS Revised for V2.10 20-Aug-02 RMS Added DECtape support @@ -239,6 +240,7 @@ int32 sbs = 0; /* sequence break */ int32 sbs_init = 0; /* seq break startup */ int32 ioh = 0; /* I/O halt */ int32 ioc = 0; /* I/O completion */ +int32 cpls = 0; /* pending completions */ int32 extm = 0; /* ext mem mode */ int32 extm_init = 0; /* ext mem startup */ int32 stop_inst = 0; /* stop on rsrv inst */ @@ -257,13 +259,13 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_reset (DEVICE *dptr); t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -extern int32 ptr (int32 inst, int32 dev, int32 IO); -extern int32 ptp (int32 inst, int32 dev, int32 IO); -extern int32 tti (int32 inst, int32 dev, int32 IO); -extern int32 tto (int32 inst, int32 dev, int32 IO); -extern int32 lpt (int32 inst, int32 dev, int32 IO); -extern int32 dt (int32 inst, int32 dev, int32 IO); -extern int32 drm (int32 inst, int32 dev, int32 IO); +extern int32 ptr (int32 inst, int32 dev, int32 dat); +extern int32 ptp (int32 inst, int32 dev, int32 dat); +extern int32 tti (int32 inst, int32 dev, int32 dat); +extern int32 tto (int32 inst, int32 dev, int32 dat); +extern int32 lpt (int32 inst, int32 dev, int32 dat); +extern int32 dt (int32 inst, int32 dev, int32 dat); +extern int32 drm (int32 inst, int32 dev, int32 dat); int32 sc_map[512] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, /* 00000xxxx */ @@ -403,7 +405,7 @@ xct_count = 0; /* track nested XCT's */ sim_interval = sim_interval - 1; xct_instr: /* label for XCT */ -if ((IR == 0610001) && ((MA & EPCMASK) == 0) && (sbs & SB_ON)) { +if ((IR == (OP_JMP+IA+1)) && ((MA & EPCMASK) == 0) && (sbs & SB_ON)) { sbs = sbs & ~SB_IP; /* seq debreak */ PCQ_ENTRY; /* save old PC */ OV = (M[1] >> 17) & 1; /* restore OV */ @@ -432,12 +434,15 @@ switch (op) { /* decode IR<0:4> */ case 001: /* AND */ AC = AC & M[MA]; break; + case 002: /* IOR */ AC = AC | M[MA]; break; + case 003: /* XOR */ AC = AC ^ M[MA]; break; + case 004: /* XCT */ if (xct_count >= xct_max) { /* too many XCT's? */ reason = STOP_XCT; @@ -445,6 +450,7 @@ case 004: /* XCT */ xct_count = xct_count + 1; /* count XCT's */ IR = M[MA]; /* get instruction */ goto xct_instr; /* go execute */ + case 007: /* CAL, JDA */ MA = (PC & EPCMASK) | ((IR & IA)? (IR & DAMASK): 0100); PCQ_ENTRY; @@ -452,24 +458,31 @@ case 007: /* CAL, JDA */ AC = EPC_WORD; PC = INCR_ADDR (MA); break; + case 010: /* LAC */ AC = M[MA]; break; + case 011: /* LIO */ IO = M[MA]; break; + case 012: /* DAC */ if (MEM_ADDR_OK (MA)) M[MA] = AC; break; + case 013: /* DAP */ if (MEM_ADDR_OK (MA)) M[MA] = (AC & DAMASK) | (M[MA] & ~DAMASK); break; + case 014: /* DIP */ if (MEM_ADDR_OK (MA)) M[MA] = (AC & ~DAMASK) | (M[MA] & DAMASK); break; + case 015: /* DIO */ if (MEM_ADDR_OK (MA)) M[MA] = IO; break; + case 016: /* DZM */ if (MEM_ADDR_OK (MA)) M[MA] = 0; break; @@ -498,6 +511,7 @@ case 020: /* ADD */ if (((~t ^ M[MA]) & (t ^ AC)) & 0400000) OV = 1; if (AC == 0777777) AC = 0; /* minus 0 cleanup */ break; + case 021: /* SUB */ t = AC ^ 0777777; /* complement AC */ AC = t + M[MA]; /* -AC + MB */ @@ -505,32 +519,39 @@ case 021: /* SUB */ if (((~t ^ M[MA]) & (t ^ AC)) & 0400000) OV = 1; AC = AC ^ 0777777; /* recomplement AC */ break; + case 022: /* IDX */ AC = M[MA] + 1; if (AC >= 0777777) AC = (AC + 1) & 0777777; if (MEM_ADDR_OK (MA)) M[MA] = AC; break; + case 023: /* ISP */ AC = M[MA] + 1; if (AC >= 0777777) AC = (AC + 1) & 0777777; if (MEM_ADDR_OK (MA)) M[MA] = AC; if (AC < 0400000) PC = INCR_ADDR (PC); break; + case 024: /* SAD */ if (AC != M[MA]) PC = INCR_ADDR (PC); break; + case 025: /* SAS */ if (AC == M[MA]) PC = INCR_ADDR (PC); break; + case 030: /* JMP */ PCQ_ENTRY; PC = MA; break; + case 031: /* JSP */ AC = EPC_WORD; PCQ_ENTRY; PC = MA; break; + case 034: /* LAW */ AC = (IR & 07777) ^ ((IR & IA)? 0777777: 0); break; @@ -691,8 +712,11 @@ case 035: if (ioh) { /* I/O halt? */ if (ioc) ioh = 0; /* comp pulse? done */ else { /* wait more */ - sim_interval = 0; /* force event */ - PC = DECR_ADDR (PC); } /* re-execute */ + PC = DECR_ADDR (PC); /* re-execute */ + if (cpls == 0) { /* any pending pulses? */ + reason = STOP_WAIT; /* no, CPU hangs */ + break; } + sim_interval = 0; } /* force event */ break; } /* skip iot */ ioh = 1; /* turn on halt */ PC = DECR_ADDR (PC); } /* re-execute */ @@ -745,6 +769,7 @@ case 035: if (io_data & IOT_SKP) PC = INCR_ADDR (PC); /* skip? */ if (io_data >= IOT_REASON) reason = io_data >> IOT_V_REASON; break; + default: /* undefined */ reason = STOP_RSRV; /* halt */ break; } /* end switch opcode */ @@ -759,7 +784,7 @@ t_stat cpu_reset (DEVICE *dptr) { sbs = sbs_init; extm = extm_init; -ioh = ioc = 0; +ioh = ioc = cpls = 0; OV = 0; PF = 0; pcq_r = find_reg ("PCQ", NULL, dptr); diff --git a/PDP1/pdp1_defs.h b/PDP1/pdp1_defs.h index 3a623e9b..e113db12 100644 --- a/PDP1/pdp1_defs.h +++ b/PDP1/pdp1_defs.h @@ -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. + 22-Jul-03 RMS Updated for "hardware" RIM loader + Revised to detect I/O wait hang 05-Dec-02 RMS Added IOT skip support (required by drum) 14-Apr-99 RMS Changed t_addr to unsigned @@ -34,7 +36,9 @@ Automatic multiply/divide Type 10 Memory extension control Type 15 + Serial drum Type 24 Line printer control Type 62 + Microtape (DECtape) control Type 550 */ #include "sim_defs.h" @@ -46,7 +50,7 @@ #define STOP_IBKPT 3 /* breakpoint */ #define STOP_XCT 4 /* nested XCT's */ #define STOP_IND 5 /* nested indirects */ -#define STOP_WAIT 6 /* wait state */ +#define STOP_WAIT 6 /* IO wait hang */ /* Memory */ @@ -59,11 +63,14 @@ /* Architectural constants */ #define DMASK 0777777 /* data mask */ -#define DAMASK 007777 /* direct addr */ +#define DAMASK 0007777 /* direct addr */ #define EPCMASK (AMASK & ~DAMASK) /* extended addr */ -#define IA 010000 /* indirect flag */ -#define IO_WAIT 010000 /* I/O sync wait */ -#define IO_CPLS 004000 /* completion pulse */ +#define IA 0010000 /* indirect flag */ +#define IO_WAIT 0010000 /* I/O sync wait */ +#define IO_CPLS 0004000 /* completion pulse */ +#define OP_DAC 0240000 /* DAC */ +#define OP_DIO 0320000 /* DIO */ +#define OP_JMP 0600000 /* JMP */ #define GEN_CPLS(x) (((x) ^ ((x) << 1)) & IO_WAIT) /* completion pulse? */ /* IOT subroutine return codes */ @@ -96,6 +103,17 @@ #define IOS_PNT (1 << IOS_V_PNT) #define IOS_SPC (1 << IOS_V_SPC) +/* Completion pulses */ + +#define CPLS_V_PTR 5 +#define CPLS_V_PTP 4 +#define CPLS_V_TTO 3 +#define CPLS_V_LPT 2 +#define CPLS_PTR (1 << CPLS_V_PTR) +#define CPLS_PTP (1 << CPLS_V_PTP) +#define CPLS_TTO (1 << CPLS_V_TTO) +#define CPLS_LPT (1 << CPLS_V_LPT) + /* Sequence break flags */ #define SB_V_IP 0 /* in progress */ diff --git a/PDP1/pdp1_doc.txt b/PDP1/pdp1_doc.txt index 9dbf079d..85029215 100644 --- a/PDP1/pdp1_doc.txt +++ b/PDP1/pdp1_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik Subj: PDP-1 Simulator Usage -Date: 15-Dec-2002 +Date: 15-Jul-2003 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2002, written by Robert M Supnik - Copyright (c) 1993-2002, Robert M Supnik + Original code published in 1993-2003, written by Robert M Supnik + Copyright (c) 1993-2003, 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"), @@ -75,8 +75,8 @@ The PDP-1 simulator implements the following unique stop conditions: memory reference address decoding - more than XCTMAX nested executes are detected during instruction execution - - wait state entered, and no I/O operations outstanding - (ie, no interrupt can ever occur) + - I/O wait, and no I/O operations outstanding (i.e, no I/O + completion will ever occur) The PDP-1 loader supports RIM format tapes. The DUMP command is not implemented. diff --git a/PDP1/pdp1_drm.c b/PDP1/pdp1_drm.c index 9587067f..1d396723 100644 --- a/PDP1/pdp1_drm.c +++ b/PDP1/pdp1_drm.c @@ -1,4 +1,4 @@ -/* pdp1_drm.c: drum/fixed head disk simulator +/* pdp1_drm.c: PDP-1 drum simulator Copyright (c) 1993-2002, Robert M Supnik @@ -25,6 +25,7 @@ drm Type 24 serial drum + 23-Jul-03 RMS Fixed incorrect logical, missing activate 05-Dec-02 RMS Cloned from pdp18b_drm.c */ @@ -95,45 +96,44 @@ DEVICE drm_dev = { /* IOT routines */ -int32 drm (int32 IR, int32 dev, int32 IO) +int32 drm (int32 IR, int32 dev, int32 dat) { int32 t; int32 pulse = (IR >> 6) & 037; if (drm_dev.flags & DEV_DIS) /* disabled? */ - return (stop_inst << IOT_V_REASON) | IO; /* stop if requested */ -if ((pulse != 001) & (pulse != 011)) /* invalid pulse? */ - return (stop_inst << IOT_V_REASON) | IO; /* stop if requested */ + return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ +if ((pulse != 001) && (pulse != 011)) /* invalid pulse? */ + return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ switch (dev) { /* switch on device */ case 061: /* DWR, DRD */ - drm_ma = IO & 0177777; /* load mem addr */ + drm_ma = dat & 0177777; /* load mem addr */ drm_unit.FUNC = pulse & DRM_WRITE; /* save function */ break; case 062: /* DBL, DCN */ - if (pulse & 010) drm_da = IO & DRM_SMASK; /* load sector # */ + if (pulse & 010) drm_da = dat & DRM_SMASK; /* load sector # */ iosta = iosta & ~IOS_DRM; /* clear flags */ drm_err = 0; t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time); if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */ + sim_activate (&drm_unit, t); /* start operation */ break; case 063: /* DTD */ - if (iosta & IOS_DRM) return (IO | IOT_SKP); /* skip if done */ + if (pulse == 011) return (stop_inst << IOT_V_REASON) | dat; + if (iosta & IOS_DRM) return (dat | IOT_SKP); /* skip if done */ + break; case 064: /* DSE, DSP */ if ((drm_err == 0) || (pulse & 010)) /* no error, par test? */ - return (IO | IOT_SKP); + return (dat | IOT_SKP); } -return IO; +return dat; } -/* Unit service - - This code assumes the entire drum is buffered. -*/ +/* Unit service - this code assumes the entire drum is buffered */ t_stat drm_svc (UNIT *uptr) { -int32 i; -uint32 da; +uint32 i, da; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ drm_err = 1; /* set error */ diff --git a/PDP1/pdp1_dt.c b/PDP1/pdp1_dt.c index 2e17f824..bbafc553 100644 --- a/PDP1/pdp1_dt.c +++ b/PDP1/pdp1_dt.c @@ -334,23 +334,23 @@ DEVICE dt_dev = { NULL, &dt_attach, &dt_detach, NULL, DEV_DISABLE }; -int32 dt (int32 IR, int32 dev, int32 IO) +int32 dt (int32 IR, int32 dev, int32 dat) { int32 pulse = (IR >> 6) & 037; int32 fnc, mot, unum; UNIT *uptr = NULL; if (dt_dev.flags & DEV_DIS) /* disabled? */ - return (stop_inst << IOT_V_REASON) | IO; /* stop if requested */ + return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ unum = DTA_GETUNIT (dtsa); /* get unit no */ if (unum >= 0) uptr = dt_dev.units + unum; /* get unit */ if (pulse == 003) { /* MSE */ - if ((dtsa ^ IO) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ - dtsa = (dtsa & ~DTA_UNIT) | (IO & DTA_UNIT); + if ((dtsa ^ dat) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ + dtsa = (dtsa & ~DTA_UNIT) | (dat & DTA_UNIT); dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); } if (pulse == 004) { /* MLC */ - dtsa = (dtsa & ~DTA_RW) | (IO & DTA_RW); /* load dtsa */ + dtsa = (dtsa & ~DTA_RW) | (dat & DTA_RW); /* load dtsa */ dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); fnc = DTA_GETFNC (dtsa); /* get fnc */ if ((uptr == NULL) || /* invalid? */ @@ -361,10 +361,10 @@ if (pulse == 004) { /* MLC */ dt_seterr (uptr, DTB_SEL); /* select err */ else dt_newsa (dtsa); } if (pulse == 005) { /* MRD */ - IO = (IO & ~DMASK) | dtdb; + dat = (dat & ~DMASK) | dtdb; dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } if (pulse == 006) { /* MWR */ - dtdb = IO & DMASK; + dtdb = dat & DMASK; dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } if (pulse == 007) { /* MRS */ dtsb = dtsb & ~(DTB_REV | DTB_GO); /* clr rev, go */ @@ -373,9 +373,9 @@ if (pulse == 007) { /* MRS */ if (mot & DTS_DIR) dtsb = dtsb | DTB_REV; /* rev? set */ if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700)) dtsb = dtsb | DTB_GO; } /* accel? go */ - IO = (IO & ~DMASK) | dtsb; } + dat = (dat & ~DMASK) | dtsb; } DT_UPDINT; -return IO; +return dat; } /* Unit deselect */ diff --git a/PDP1/pdp1_lp.c b/PDP1/pdp1_lp.c index 4b0b8cda..c42b5acf 100644 --- a/PDP1/pdp1_lp.c +++ b/PDP1/pdp1_lp.c @@ -25,6 +25,8 @@ lpt Type 62 line printer for the PDP-1 + 23-Jul-03 RMS Fixed bugs in instruction decoding, overprinting + Revised to detect I/O wait hang 25-Apr-03 RMS Revised for extended file support 30-May-02 RMS Widened POS to 32b 13-Apr-01 RMS Revised for register arrays @@ -36,10 +38,10 @@ #define LPT_BSIZE (BPTR_MAX * 3) /* line size */ #define BPTR_MASK 077 /* buf ptr mask */ -extern int32 ioc, sbs, iosta; -extern int32 stop_inst; - -int32 lpt_rpls = 0, lpt_iot = 0, lpt_stopioe = 0, bptr = 0; +int32 lpt_spc = 0; /* print (0) vs spc */ +int32 lpt_ovrpr = 0; /* overprint */ +int32 lpt_stopioe = 0; /* stop on error */ +int32 lpt_bptr = 0; /* buffer ptr */ char lpt_buf[LPT_BSIZE + 1] = { 0 }; static const unsigned char lpt_trans[64] = { ' ','1','2','3','4','5','6','7','8','9','\'','~','#','V','^','<', @@ -47,6 +49,9 @@ static const unsigned char lpt_trans[64] = { '@','J','K','L','M','N','O','P','Q','R','$','=','-',')','-','(', '_','A','B','C','D','E','F','G','H','I','*','.','+',']','|','[' }; +extern int32 ioc, cpls, sbs, iosta; +extern int32 stop_inst; + t_stat lpt_svc (UNIT *uptr); t_stat lpt_reset (DEVICE *dptr); @@ -64,9 +69,10 @@ REG lpt_reg[] = { { ORDATA (BUF, lpt_unit.buf, 8) }, { FLDATA (PNT, iosta, IOS_V_PNT) }, { FLDATA (SPC, iosta, IOS_V_SPC) }, - { FLDATA (RPLS, lpt_rpls, 0) }, - { DRDATA (BPTR, bptr, 6) }, - { ORDATA (LPT_STATE, lpt_iot, 6), REG_HRO }, + { FLDATA (RPLS, cpls, CPLS_V_LPT) }, + { DRDATA (BPTR, lpt_bptr, 6) }, + { ORDATA (LPT_STATE, lpt_spc, 6), REG_HRO }, + { FLDATA (LPT_OVRPR, lpt_ovrpr, 0), REG_HRO }, { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT }, { FLDATA (STOP_IOE, lpt_stopioe, 0) }, @@ -82,38 +88,39 @@ DEVICE lpt_dev = { /* Line printer IOT routine */ -int32 lpt (int32 inst, int32 dev, int32 data) +int32 lpt (int32 inst, int32 dev, int32 dat) { int32 i; if (lpt_dev.flags & DEV_DIS) /* disabled? */ - return (stop_inst << IOT_V_REASON) | data; /* stop if requested */ -if ((inst & 0700) == 0100) { /* fill buf */ - if (bptr < BPTR_MAX) { /* limit test ptr */ - i = bptr * 3; /* cvt to chr ptr */ - lpt_buf[i] = lpt_trans[(data >> 12) & 077]; - lpt_buf[i + 1] = lpt_trans[(data >> 6) & 077]; - lpt_buf[i + 2] = lpt_trans[data & 077]; } - bptr = (bptr + 1) & BPTR_MASK; - return data; } -lpt_rpls = 0; -if ((inst & 0700) == 0200) { /* space */ + return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ +if ((inst & 07000) == 01000) { /* fill buf */ + if (lpt_bptr < BPTR_MAX) { /* limit test ptr */ + i = lpt_bptr * 3; /* cvt to chr ptr */ + lpt_buf[i] = lpt_trans[(dat >> 12) & 077]; + lpt_buf[i + 1] = lpt_trans[(dat >> 6) & 077]; + lpt_buf[i + 2] = lpt_trans[dat & 077]; } + lpt_bptr = (lpt_bptr + 1) & BPTR_MASK; + return dat; } +if ((inst & 07000) == 02000) { /* space */ iosta = iosta & ~IOS_SPC; /* space, clear flag */ - lpt_iot = (inst >> 6) & 077; } /* state = space n */ -else { iosta = iosta & ~IOS_PNT; /* clear flag */ - lpt_iot = 0; } /* state = print */ + lpt_spc = (inst >> 6) & 077; } /* state = space n */ +else if ((inst & 07000) == 00000) { /* print */ + iosta = iosta & ~IOS_PNT; /* clear flag */ + lpt_spc = 0; } /* state = print */ +else return (stop_inst << IOT_V_REASON) | dat; /* not implemented */ if (GEN_CPLS (inst)) { /* comp pulse? */ ioc = 0; /* clear flop */ - lpt_rpls = 1; } /* request completion */ + cpls = cpls | CPLS_LPT; } /* request completion */ +else cpls = cpls & ~CPLS_LPT; sim_activate (&lpt_unit, lpt_unit.wait); /* activate */ -return data; +return dat; } /* Unit service, printer is in one of three states - lpt_iot = 000 write buffer to file, set state to - lpt_iot = 010 write cr, then write buffer to file - lpt_iot = 02x space command x, then set state to 0 + lpt_spc = 000 write buffer to file, set overprint + lpt_iot = 02x space command x, clear overprint */ t_stat lpt_svc (UNIT *uptr) @@ -129,30 +136,32 @@ static const char *lpt_cc[] = { "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", "\f" }; +if (cpls & CPLS_LPT) { /* completion pulse? */ + ioc = 1; /* restart */ + cpls = cpls & ~CPLS_LPT; } /* clr pulse pending */ sbs = sbs | SB_RQ; /* req seq break */ -ioc = ioc | lpt_rpls; /* restart */ -if (lpt_iot & 020) { /* space? */ +if (lpt_spc) { /* space? */ iosta = iosta | IOS_SPC; /* set flag */ if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (lpt_stopioe, SCPE_UNATT); - fputs (lpt_cc[lpt_iot & 07], lpt_unit.fileref); /* print cctl */ + fputs (lpt_cc[lpt_spc & 07], lpt_unit.fileref); /* print cctl */ if (ferror (lpt_unit.fileref)) { /* error? */ perror ("LPT I/O error"); clearerr (lpt_unit.fileref); return SCPE_IOERR; } - lpt_iot = 0; } /* clear state */ + lpt_ovrpr = 0; } /* dont overprint */ else { iosta = iosta | IOS_PNT; /* print */ if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (lpt_stopioe, SCPE_UNATT); - if (lpt_iot & 010) fputc ('\r', lpt_unit.fileref); + if (lpt_ovrpr) fputc ('\r', lpt_unit.fileref); /* overprint? */ fputs (lpt_buf, lpt_unit.fileref); /* print buffer */ if (ferror (lpt_unit.fileref)) { /* test error */ perror ("LPT I/O error"); clearerr (lpt_unit.fileref); return SCPE_IOERR; } - bptr = 0; + lpt_bptr = 0; for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ - lpt_iot = 010; } /* set state */ + lpt_ovrpr = 1; } /* set overprint */ lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ return SCPE_OK; } @@ -163,11 +172,12 @@ t_stat lpt_reset (DEVICE *dptr) { int32 i; -iosta = iosta & ~(IOS_PNT | IOS_SPC); /* clear flags */ -bptr = 0; /* clear buffer ptr */ +lpt_bptr = 0; /* clear buffer ptr */ for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ -lpt_iot = 0; /* clear state */ -lpt_rpls = 0; +lpt_spc = 0; /* clear state */ +lpt_ovrpr = 0; /* clear overprint */ +cpls = cpls & ~CPLS_LPT; +iosta = iosta & ~(IOS_PNT | IOS_SPC); /* clear flags */ sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/PDP1/pdp1_stddev.c b/PDP1/pdp1_stddev.c index 7a73abd5..d1471d13 100644 --- a/PDP1/pdp1_stddev.c +++ b/PDP1/pdp1_stddev.c @@ -28,6 +28,7 @@ tti keyboard tto teleprinter + 23-Jul-03 RMS Revised to detect I/O wait hang 25-Apr-03 RMS Revised for extended file support 22-Dec-02 RMS Added break support 29-Nov-02 RMS Fixed output flag initialization (found by Derek Peschel) @@ -52,16 +53,16 @@ #define TTI 0 #define TTO 1 -extern int32 sbs, ioc, iosta, PF, IO, PC; -extern int32 M[]; - -int32 ptr_rpls = 0, ptr_stopioe = 0, ptr_state = 0; -int32 ptp_rpls = 0, ptp_stopioe = 0; +int32 ptr_state = 0; +int32 ptr_stopioe = 0; +int32 ptp_stopioe = 0; int32 tti_hold = 0; /* tti hold buf */ -int32 tto_rpls = 0; /* tto restart */ int32 tty_buf = 0; /* tty buffer */ int32 tty_uc = 0; /* tty uc/lc */ +extern int32 sbs, ioc, cpls, iosta, PF, IO, PC; +extern int32 M[]; + t_stat ptr_svc (UNIT *uptr); t_stat ptp_svc (UNIT *uptr); t_stat tti_svc (UNIT *uptr); @@ -123,7 +124,7 @@ UNIT ptr_unit = { REG ptr_reg[] = { { ORDATA (BUF, ptr_unit.buf, 18) }, { FLDATA (DONE, iosta, IOS_V_PTR) }, - { FLDATA (RPLS, ptr_rpls, 0) }, + { FLDATA (RPLS, cpls, CPLS_V_PTR) }, { ORDATA (STATE, ptr_state, 5), REG_HRO }, { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, @@ -150,7 +151,7 @@ UNIT ptp_unit = { REG ptp_reg[] = { { ORDATA (BUF, ptp_unit.buf, 8) }, { FLDATA (DONE, iosta, IOS_V_PTP) }, - { FLDATA (RPLS, ptp_rpls, 0) }, + { FLDATA (RPLS, cpls, CPLS_V_PTP) }, { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, { FLDATA (STOP_IOE, ptp_stopioe, 0) }, @@ -177,7 +178,7 @@ UNIT tty_unit[] = { REG tty_reg[] = { { ORDATA (BUF, tty_buf, 6) }, { FLDATA (UC, tty_uc, UC_V) }, - { FLDATA (RPLS, tto_rpls, 0) }, + { FLDATA (RPLS, cpls, CPLS_V_TTO) }, { ORDATA (HOLD, tti_hold, 9), REG_HRO }, { FLDATA (KDONE, iosta, IOS_V_TTI) }, { DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT }, @@ -196,18 +197,18 @@ DEVICE tty_dev = { /* Paper tape reader: IOT routine */ -int32 ptr (int32 inst, int32 dev, int32 data) +int32 ptr (int32 inst, int32 dev, int32 dat) { iosta = iosta & ~IOS_PTR; /* clear flag */ if (dev == 0030) return ptr_unit.buf; /* RRB */ ptr_state = (dev == 0002)? 18: 0; /* mode = bin/alp */ -ptr_rpls = 0; ptr_unit.buf = 0; /* clear buffer */ -sim_activate (&ptr_unit, ptr_unit.wait); if (GEN_CPLS (inst)) { /* comp pulse? */ ioc = 0; - ptr_rpls = 1; } -return data; + cpls = cpls | CPLS_PTR; } +else cpls = cpls & ~CPLS_PTR; +sim_activate (&ptr_unit, ptr_unit.wait); +return dat; } /* Unit service */ @@ -231,10 +232,12 @@ else if (temp & 0200) { /* binary */ ptr_state = ptr_state - 6; ptr_unit.buf = ptr_unit.buf | ((temp & 077) << ptr_state); } if (ptr_state == 0) { /* done? */ - if (ptr_rpls) IO = ptr_unit.buf; /* restart? fill IO */ + if (cpls & CPLS_PTR) { /* completion pulse? */ + IO = ptr_unit.buf; /* fill IO */ + ioc = 1; /* restart */ + cpls = cpls & ~CPLS_PTR; } iosta = iosta | IOS_PTR; /* set flag */ - sbs = sbs | SB_RQ; /* req seq break */ - ioc = ioc | ptr_rpls; } /* restart */ + sbs = sbs | SB_RQ; } /* req seq break */ else sim_activate (&ptr_unit, ptr_unit.wait); /* get next char */ return SCPE_OK; } @@ -245,7 +248,7 @@ t_stat ptr_reset (DEVICE *dptr) { ptr_state = 0; /* clear state */ ptr_unit.buf = 0; -ptr_rpls = 0; +cpls = cpls & ~CPLS_PTR; iosta = iosta & ~IOS_PTR; /* clear flag */ sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; @@ -253,48 +256,61 @@ return SCPE_OK; /* Bootstrap routine */ -#define BOOT_START 07772 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) +int32 ptr_getw (UNIT *uptr) +{ +int32 i, tmp, word; -static const int32 boot_rom[] = { - 0730002, /* r, rpb + wait */ - 0327776, /* dio x */ - 0107776, /* xct x */ - 0730002, /* rpb + wait */ - 0760400, /* x, halt */ - 0607772 /* jmp r */ -}; +for (i = word = 0; i < 3;) { + if ((tmp = getc (uptr->fileref)) == EOF) return -1; + uptr->pos = uptr->pos + 1; + if (tmp & 0200) { + word = (word << 6) | (tmp & 077); + i++; } } +return word; +} t_stat ptr_boot (int32 unitno, DEVICE *dptr) { -int32 i; +int32 origin, val; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -PC = BOOT_START; -return SCPE_OK; +for (;;) { + if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT; + if (((val & 0760000) == OP_DIO) || /* DIO? */ + ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */ + origin = val & 07777; + if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT; + M[origin] = val; } + else if ((val & 0760000) == OP_JMP) { /* JMP? */ + PC = val & 007777; + break; } + else return SCPE_FMT; /* bad instr */ + } +return SCPE_OK; /* done */ } /* Paper tape punch: IOT routine */ -int32 ptp (int32 inst, int32 dev, int32 data) +int32 ptp (int32 inst, int32 dev, int32 dat) { iosta = iosta & ~IOS_PTP; /* clear flag */ -ptp_rpls = 0; -ptp_unit.buf = (dev == 0006)? ((data >> 12) | 0200): (data & 0377); -sim_activate (&ptp_unit, ptp_unit.wait); /* start unit */ +ptp_unit.buf = (dev == 0006)? ((dat >> 12) | 0200): (dat & 0377); if (GEN_CPLS (inst)) { /* comp pulse? */ ioc = 0; - ptp_rpls = 1; } -return data; + cpls = cpls | CPLS_PTP; } +else cpls = cpls & ~CPLS_PTP; +sim_activate (&ptp_unit, ptp_unit.wait); /* start unit */ +return dat; } /* Unit service */ t_stat ptp_svc (UNIT *uptr) { +if (cpls & CPLS_PTP) { /* completion pulse? */ + ioc = 1; /* restart */ + cpls = cpls & ~CPLS_PTP; } iosta = iosta | IOS_PTP; /* set flag */ sbs = sbs | SB_RQ; /* req seq break */ -ioc = ioc | ptp_rpls; /* process restart */ if ((ptp_unit.flags & UNIT_ATT) == 0) /* not attached? */ return IORETURN (ptp_stopioe, SCPE_UNATT); if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* I/O error? */ @@ -310,7 +326,7 @@ return SCPE_OK; t_stat ptp_reset (DEVICE *dptr) { ptp_unit.buf = 0; /* clear state */ -ptp_rpls = 0; +cpls = cpls & ~CPLS_PTP; iosta = iosta & ~IOS_PTP; /* clear flag */ sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; @@ -318,7 +334,7 @@ return SCPE_OK; /* Typewriter IOT routines */ -int32 tti (int32 inst, int32 dev, int32 data) +int32 tti (int32 inst, int32 dev, int32 dat) { iosta = iosta & ~IOS_TTI; /* clear flag */ if (inst & (IO_WAIT | IO_CPLS)) /* wait or sync? */ @@ -326,16 +342,16 @@ if (inst & (IO_WAIT | IO_CPLS)) /* wait or sync? */ return tty_buf & 077; } -int32 tto (int32 inst, int32 dev, int32 data) +int32 tto (int32 inst, int32 dev, int32 dat) { iosta = iosta & ~IOS_TTO; /* clear flag */ -tto_rpls = 0; -tty_buf = data & TT_WIDTH; /* load buffer */ -sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); /* activate unit */ +tty_buf = dat & TT_WIDTH; /* load buffer */ if (GEN_CPLS (inst)) { /* comp pulse? */ ioc = 0; - tto_rpls = 1; } -return data; + cpls = cpls | CPLS_TTO; } +else cpls = cpls & ~CPLS_TTO; +sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); /* activate unit */ +return dat; } /* Unit service routines */ @@ -373,9 +389,11 @@ t_stat tto_svc (UNIT *uptr) { int32 out; +if (cpls & CPLS_TTO) { /* completion pulse? */ + ioc = 1; /* restart */ + cpls = cpls & ~CPLS_TTO; } iosta = iosta | IOS_TTO; /* set flag */ sbs = sbs | SB_RQ; /* req seq break */ -ioc = ioc | tto_rpls; /* process restart */ if (tty_buf == FIODEC_UC) { /* upper case? */ tty_uc = UC; return SCPE_OK; } @@ -399,7 +417,7 @@ t_stat tty_reset (DEVICE *dptr) tty_buf = 0; /* clear buffer */ tty_uc = 0; /* clear case */ tti_hold = 0; /* clear hold buf */ -tto_rpls = 0; /* clear reset pulse */ +cpls = cpls & ~CPLS_TTO; iosta = (iosta & ~IOS_TTI) | IOS_TTO; /* clear flag */ sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate keyboard */ sim_cancel (&tty_unit[TTO]); /* stop printer */ diff --git a/PDP1/pdp1_sys.c b/PDP1/pdp1_sys.c index 5f14d6e7..09c3388f 100644 --- a/PDP1/pdp1_sys.c +++ b/PDP1/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. + 22-Jul-03 RMS Updated for "hardware" RIM loader 05-Dec-02 RMS Added drum support 21-Nov-02 RMS Changed typewriter to half duplex 20-Aug-02 RMS Added DECtape support @@ -52,6 +53,7 @@ extern int32 M[]; extern int32 PC; extern int32 ascii_to_fiodec[], fiodec_to_ascii[]; extern int32 sc_map[]; +extern int32 sim_switches; /* SCP data structures and interface routines @@ -86,44 +88,83 @@ const char *sim_stop_messages[] = { "Breakpoint", "Nested XCT's", "Nested indirect addresses", - "Infinite wait state" }; + "Infinite I/O wait state" }; -/* Binary loader +/* Binary loader - supports both RIM format and Macro block format */ - At the moment, implements RIM loader format -*/ - -int32 getword (FILE *fileref) +int32 getw (FILE *inf) { int32 i, tmp, word; word = 0; for (i = 0; i < 3;) { - if ((tmp = getc (fileref)) == EOF) return -1; + if ((tmp = getc (inf)) == EOF) return -1; if (tmp & 0200) { word = (word << 6) | (tmp & 077); i++; } } return word; } -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +t_stat rim_load (FILE *inf) { int32 origin, val; -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; for (;;) { - if ((val = getword (fileref)) < 0) return SCPE_FMT; - if (((val & 0770000) == 0320000) || /* DIO? */ - ((val & 0770000) == 0240000)) { /* DAC? - incorrect */ + if ((val = getw (inf)) < 0) return SCPE_FMT; + if (((val & 0760000) == OP_DIO) || /* DIO? */ + ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */ origin = val & 07777; - if ((val = getword (fileref)) < 0) return SCPE_FMT; - if (MEM_ADDR_OK (origin)) M[origin++] = val; } - else if ((val & 0770000) == 0600000) { /* JMP? */ + if ((val = getw (inf)) < 0) return SCPE_FMT; + M[origin] = val; } + else if ((val & 0760000) == OP_JMP) { /* JMP? */ PC = val & 007777; break; } + else return SCPE_FMT; /* bad instr */ } return SCPE_OK; /* done */ } + +t_stat blk_load (FILE *inf) +{ +int32 val, start, count, csum; + +for (;;) { + if ((val = getw (inf)) < 0) return SCPE_FMT; /* get word, EOF? */ + if ((val & 0760000) == OP_DIO) { /* DIO? */ + csum = val; /* init checksum */ + start = val & 07777; /* starting addr */ + if ((val = getw (inf)) < 0) return SCPE_FMT; + if ((val & 0760000) != OP_DIO) return SCPE_FMT; + csum = csum + val; + if (csum > 0777777) csum = (csum + 1) & 0777777; + count = (val & 07777) - start + 1; /* block count */ + if (count <= 0) return SCPE_FMT; + while (count--) { /* loop on data */ + if ((val = getw (inf)) < 0) return SCPE_FMT; + csum = csum + val; + if (csum > 0777777) csum = (csum + 1) & 0777777; + M[start++] = val; } + if ((val = getw (inf)) < 0) return SCPE_FMT; + if (val != csum) return SCPE_CSUM; } + else if ((val & 0760000) == OP_JMP) { /* JMP? */ + PC = val & 007777; + break; } + else return SCPE_FMT; /* bad instr */ + } +return SCPE_OK; /* done */ +} + +t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +{ +t_stat sta; + +if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; +sta = rim_load (fileref); +if (sta != SCPE_OK) return sta; +if ((sim_switches & SWMASK ('B')) || match_ext (fnam, "BIN")) + return blk_load (fileref); +return SCPE_OK; +} /* Symbol tables */ diff --git a/PDP10/pdp10_doc.txt b/PDP10/pdp10_doc.txt index 7a70d0ef..fb31fe4e 100644 --- a/PDP10/pdp10_doc.txt +++ b/PDP10/pdp10_doc.txt @@ -40,15 +40,17 @@ To compile the PDP-10, you must define VM_PDP10 and USE_INT64 as part of the compilation command line. sim/ sim_defs.h + sim_ether.h sim_rev.h sim_sock.h + sim_tape.h sim_tmxr.h - sim_ether.h scp.c scp_tty.c - sim_sock.c - sim_tmxr.c sim_ether.c + sim_sock.c + sim_tape.c + sim_tmxr.c sim/pdp10/ pdp10_defs.h pdp10_cpu.c @@ -117,11 +119,14 @@ the file format to try to determine the file type. The CPU options allow the user to specify standard microcode, standard microcode with a bug fix for a boostrap problem in TOPS-20 V4.1, or ITS -microcode +microcode: SET CPU STANDARD Standard microcode SET CPU TOPS20V41 Standard microcode with TOPS-20 V4.1 bug fix SET CPU ITS ITS compatible microcode + +The CPU implements a SHOW command to display the I/O space address map: + SHOW CPU IOSPACE show I/O space address map CPU registers include the visible state of the processor as well as the @@ -200,7 +205,7 @@ The front end is the system console. The keyboard input is unit 0, the console output is unit 1. It supports two options: SET FE STOP halts the PDP-10 operating system - SET FE CTLC simulates typing ^C (for Windoze) + SET FE CTLC simulates typing ^C The front end has the following registers: @@ -333,7 +338,10 @@ the port to be used: where port is a decimal number between 1 and 65535 that is not being used for other TCP/IP activities. The optional switch -m turns on the DZ11's modem controls; the optional switch -a turns on active disconnects -(disconnect session if computer clears Data Terminal Ready). +(disconnect session if computer clears Data Terminal Ready). Without +modem control, the DZ behaves as though terminals were directly connected; +disconnecting the Telnet session does not cause any operating system- +visible change in line status. Once the DZ is attached and the simulator is running, the DZ will listen for connections on the specified port. It assumes that the incoming @@ -526,8 +534,6 @@ locked, single or double density, or autosized: SET RYn DOUBLE set unit n double density (default) SET RYn AUTOSIZE set unit n autosized -The RX211 supports the BOOT command, but only for double density. - The floppy disk requires an unsupported driver under TOPS-10 and is not supported under TOPS-20 or ITS. diff --git a/PDP10/pdp10_rp.c b/PDP10/pdp10_rp.c index 4e0b2d49..712a6bbc 100644 --- a/PDP10/pdp10_rp.c +++ b/PDP10/pdp10_rp.c @@ -25,6 +25,7 @@ rp RH/RP/RM moving head disks + 23-Jul-03 RMS Fixed bug in read header stub 25-Apr-03 RMS Revised for extended file support 21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson) 29-Sep-02 RMS Added variable vector support @@ -834,14 +835,14 @@ case FNC_READH: /* read headers */ vpn = PAG_GETVPN (pa10); /* map addr */ if ((vpn >= UMAP_MEMSIZE) || (ba & XBA_MBZ) || (rpwc & XWC_MBZ) || ((ubmap[0][vpn] & (UMAP_VLD | UMAP_DSB | UMAP_RRV)) != UMAP_VLD)) { - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } + rpcs2 = rpcs2 | CS2_NEM; /* set error */ + ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ + break; } mpa10 = (ubmap[0][vpn] + PAG_GETOFF (pa10)) & PAMASK; if (MEM_ADDR_NXM (mpa10)) { /* nx memory? */ - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } + rpcs2 = rpcs2 | CS2_NEM; /* set error */ + ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ + break; } dbuf[twc10] = M[mpa10]; /* write to disk */ if ((rpcs2 & CS2_UAI) == 0) ba = ba + 4; } if (fc10 = twc10 & (RP_NUMWD - 1)) { /* fill? */ @@ -850,7 +851,7 @@ case FNC_READH: /* read headers */ fxwrite (dbuf, sizeof (d10), twc10 + fc10, uptr->fileref); err = ferror (uptr->fileref); } /* end if */ - else { /* read, wchk */ + else { /* read, wchk, readh */ awc10 = fxread (dbuf, sizeof (d10), wc10, uptr->fileref); err = ferror (uptr->fileref); for ( ; awc10 < wc10; awc10++) dbuf[awc10] = 0; @@ -859,18 +860,20 @@ case FNC_READH: /* read headers */ vpn = PAG_GETVPN (pa10); /* map addr */ if ((vpn >= UMAP_MEMSIZE) || (ba & XBA_MBZ) || (rpwc & XWC_MBZ) || ((ubmap[0][vpn] & (UMAP_VLD | UMAP_DSB | UMAP_RRV)) != UMAP_VLD)) { - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } + rpcs2 = rpcs2 | CS2_NEM; /* set error */ + ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ + break; } mpa10 = (ubmap[0][vpn] + PAG_GETOFF (pa10)) & PAMASK; if (MEM_ADDR_NXM (mpa10)) { /* nx memory? */ - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } - if (uptr->FUNC == FNC_READ) M[mpa10] = dbuf[twc10]; - else if (M[mpa10] != dbuf[twc10]) { - rpcs2 = rpcs2 | CS2_WCE; /* set error */ - break; } + rpcs2 = rpcs2 | CS2_NEM; /* set error */ + ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ + break; } + if ((uptr->FUNC == FNC_READ) || /* read or */ + (uptr->FUNC == FNC_READH)) /* read header */ + M[mpa10] = dbuf[twc10]; + else if (M[mpa10] != dbuf[twc10]) { /* wchk, mismatch? */ + rpcs2 = rpcs2 | CS2_WCE; /* set error */ + break; } if ((rpcs2 & CS2_UAI) == 0) ba = ba + 4; } } /* end else */ diff --git a/PDP11/pdp11_cpu.c b/PDP11/pdp11_cpu.c index f08eae0a..5e987a4a 100644 --- a/PDP11/pdp11_cpu.c +++ b/PDP11/pdp11_cpu.c @@ -678,7 +678,7 @@ if (trap_req) { /* check traps, ints */ if (t = trap_req & TRAP_ALL) { /* if a trap */ for (trapnum = 0; trapnum < TRAP_V_MAX; trapnum++) { if ((t >> trapnum) & 1) { /* trap set? */ - trapea = trap_vec[trapnum]; /* get vec, clr */ + trapea = trap_vec[trapnum]; /* get vec, clr */ trap_req = trap_req & ~trap_clear[trapnum]; if ((stop_trap >> trapnum) & 1) /* stop on trap? */ reason = trapnum + 1; @@ -785,7 +785,7 @@ case 000: setCPUERR (CPUE_HALT); } break; case 1: /* WAIT */ - if (cm == MD_KER && wait_enable) wait_state = 1; + if ((cm == MD_KER) && wait_enable) wait_state = 1; break; case 3: /* BPT */ setTRAP (TRAP_BPT); @@ -838,8 +838,8 @@ case 000: if ((IR == 000002) && tbit) setTRAP (TRAP_TRC); break; case 7: /* MFPT */ - R[0] = 5; /* report J-11 */ - break; } /* end switch no ops */ + R[0] = 5; /* report J-11 */ + break; } /* end switch no ops */ break; /* end case no ops */ /* Opcode 0: specials, continued */ @@ -1378,7 +1378,7 @@ case 007: case 5: /* FIS - not impl */ setTRAP (TRAP_ILL); break; - case 6: /* CIS - not impl */ + case 6: /* CIS */ if (cpu_unit.flags & UNIT_CIS) cis11 (IR); else setTRAP (TRAP_ILL); break; diff --git a/PDP11/pdp11_doc.txt b/PDP11/pdp11_doc.txt index 7c8a5276..a571af0d 100644 --- a/PDP11/pdp11_doc.txt +++ b/PDP11/pdp11_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: PDP-11 Simulator Usage -Date: 15-Mar-2003 +Date: 15-Jul-2003 COPYRIGHT NOTICE @@ -40,11 +40,13 @@ sim/ sim_defs.h sim_ether.h sim_rev.h sim_sock.h + sim_tape.h sim_tmxr.h scp.c scp_tty.c sim_ether.c sim_sock.c + sim_tape.c sim_tmxr.c sim/pdp11/ pdp11_defs.h @@ -154,6 +156,9 @@ with RH70-style controllers, 22b Unibus with RH11 style controllers, and SET CPU 2048K (or 2M) set memory size = 2048KB SET CPU 3072K (or 3M) set memory size = 3072KB SET CPU 4096K (or 4M) set memory size = 4096KB + +The CPU implements a show command to display the I/O address space map: + SHOW CPU IOSPACE show I/O space address map If memory size is being reduced, and the memory being truncated contains @@ -486,7 +491,7 @@ clock is disabled by default. The DZ11 is an 8-line terminal multiplexor. Up to 4 DZ11's (32 lines) are supported. The number of lines can be changed with the command - SET DZ LINES=n set line count to n + SET DZ LINES=n set line count to n The line count must be a multiple of 8, with a maximum of 32. @@ -501,12 +506,15 @@ The terminal lines perform input and output through Telnet sessions connected to a user-specified port. The ATTACH command specifies the port to be used: - ATTACH {-am} DZ set up listening port + ATTACH {-am} DZ set up listening port where port is a decimal number between 1 and 65535 that is not being used for other TCP/IP activities. The optional switch -m turns on the DZ11's modem controls; the optional switch -a turns on active disconnects -(disconnect session if computer clears Data Terminal Ready). +(disconnect session if computer clears Data Terminal Ready). Without +modem control, the DZ behaves as though terminals were directly connected; +disconnecting the Telnet session does not cause any operating system- +visible change in line status. Once the DZ is attached and the simulator is running, the DZ will listen for connections on the specified port. It assumes that the incoming @@ -876,6 +884,10 @@ of many disk types: SET RQn RAUSER{=n} set type to RA81 with n LBNs The type options can be used only when a unit is not attached to a file. +RAUSER is a "user specified" disk; the user can specify the size of the +disk in logical block numbers (LBN's, 512 bytes each). The minimum size +is 50MB; the maximum size is 2GB. + Units can also be set ONLINE or OFFLINE. Each RQ controller supports the BOOT command. In a Unibus system, an RQ supports 18b addressing. In a Qbus (22B) system, an RQ supports 22b addressing. @@ -928,13 +940,13 @@ crash on boot or to hang during operation. Error handling is as follows: - error processed as + error processed as - not attached disk not ready + not attached disk not ready - end of file assume rest of disk is zero + end of file assume rest of disk is zero - OS I/O error report error and stop + OS I/O error report error and stop 2.8 TC11/TU56 DECtape (DT) @@ -1227,18 +1239,18 @@ controller will behave as though the ethernet cable were unplugged. XQ has the following registers: - name size comments + name size comments - SA0 16 station address word 0 - SA1 16 station address word 1 - SA2 16 station address word 2 - SA3 16 station address word 3 - SA4 16 station address word 4 - SA5 16 station address word 5 - CSR 16 control status register - VAR 16 vector address register - RBDL 32 receive buffer descriptor list - XBDL 32 trans(X)mit buffer descriptorlList + SA0 16 station address word 0 + SA1 16 station address word 1 + SA2 16 station address word 2 + SA3 16 station address word 3 + SA4 16 station address word 4 + SA5 16 station address word 5 + CSR 16 control status register + VAR 16 vector address register + RBDL 32 receive buffer descriptor list + XBDL 32 trans(X)mit buffer descriptorlList One final note: because of it's asynchronous nature, the XQ controller is not limited to the ~1.5Mbit/sec of the real DEQNA/DELQA controllers, diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c index 484b29f7..0007e840 100644 --- a/PDP11/pdp11_rq.c +++ b/PDP11/pdp11_rq.c @@ -26,6 +26,7 @@ rq RQDX3 disk controller + 11-Jul-03 RMS Fixed bug in user disk size (found by Chaskiel M Grundman) 19-May-03 RMS Revised for new conditional compilation scheme 25-Apr-03 RMS Revised for extended file support 14-Mar-03 RMS Fixed variable size interaction with save/restore @@ -2009,7 +2010,7 @@ if ((val < 0) || (val > RA8U_DTYPE) || ((val != RA8U_DTYPE) && cptr)) return SCPE_ARG; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; if (cptr) { - cap = (int32) get_uint (cptr, 10, RA8U_MAXC, &r); + cap = (int32) get_uint (cptr, 10, max, &r); if ((r != SCPE_OK) || (cap < RA8U_MINC)) return SCPE_ARG; drv_tab[val].lbn = cap << (20 - 9); } uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE); diff --git a/PDP18B/pdp18b_cpu.c b/PDP18B/pdp18b_cpu.c index f8236c5e..1a1fbf18 100644 --- a/PDP18B/pdp18b_cpu.c +++ b/PDP18B/pdp18b_cpu.c @@ -25,6 +25,12 @@ cpu PDP-4/7/9/15 central processor + 27-Jul-03 RMS Added FP15 support + Added XVM support + Added EAE option to PDP-4 + Added PDP-15 "re-entrancy ECO" + Fixed memory protect/skip interaction + Fixed CAF not to reset CPU 12-Mar-03 RMS Added logical name support 18-Feb-03 RMS Fixed three EAE bugs (found by Hans Pufal) 05-Oct-02 RMS Added DIBs, device number support @@ -64,6 +70,8 @@ PDP-7 USMD trap mode PDP-9, PDP-15 USMD user mode PDP-9, PDP-15 BR bounds register + PDP-15 RR relocation register + PDP-15 XVM MMR memory management register PDP-15 XR index register PDP-15 LR limit register */ @@ -251,16 +259,25 @@ #include "pdp18b_defs.h" -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC -#define UNIT_V_NOEAE (UNIT_V_UF) /* EAE absent */ -#define UNIT_V_NOAPI (UNIT_V_UF+1) /* API absent */ -#define UNIT_V_MSIZE (UNIT_V_UF+2) /* dummy mask */ +#define SEXT(x) ((int32) (((x) & SIGN)? (x) | ~DMASK: (x) & DMASK)) + +#define UNIT_V_NOEAE (UNIT_V_UF + 0) /* EAE absent */ +#define UNIT_V_NOAPI (UNIT_V_UF + 1) /* API absent */ +#define UNIT_V_PROT (UNIT_V_UF + 2) /* protection */ +#define UNIT_V_RELOC (UNIT_V_UF + 3) /* relocation */ +#define UNIT_V_XVM (UNIT_V_UF + 4) /* XVM */ +#define UNIT_V_MSIZE (UNIT_V_UF + 5) /* dummy mask */ #define UNIT_NOEAE (1 << UNIT_V_NOEAE) #define UNIT_NOAPI (1 << UNIT_V_NOAPI) - +#define UNIT_PROT (1 << UNIT_V_PROT) +#define UNIT_RELOC (1 << UNIT_V_RELOC) +#define UNIT_XVM (1 << UNIT_V_XVM) #define UNIT_MSIZE (1 << UNIT_V_MSIZE) + +#define XVM (cpu_unit.flags & UNIT_XVM) +#define RELOC (cpu_unit.flags & UNIT_RELOC) +#define PROT (cpu_unit.flags & UNIT_PROT) + #if defined (PDP4) #define EAE_DFLT UNIT_NOEAE #else @@ -268,17 +285,22 @@ #endif #if defined (PDP4) || defined (PDP7) #define API_DFLT UNIT_NOAPI +#define PROT_DFLT 0 +#define ASW_DFLT 017763 #else #define API_DFLT UNIT_NOAPI /* for now */ +#define PROT_DFLT UNIT_PROT +#define ASW_DFLT 017720 #endif int32 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 saved_LAC = 0; /* link'AC */ -int32 saved_MQ = 0; /* MQ */ -int32 saved_PC = 0; /* PC */ +int32 LAC = 0; /* link'AC */ +int32 MQ = 0; /* MQ */ +int32 PC = 0; /* PC */ int32 iors = 0; /* IORS */ int32 ion = 0; /* int on */ int32 ion_defer = 0; /* int defer */ +int32 ion_inh = 0; /* int inhibit */ int32 int_pend = 0; /* int pending */ int32 int_hwre[API_HLVL+1] = { 0 }; /* int requests */ int32 api_enb = 0; /* API enable */ @@ -291,16 +313,20 @@ int32 memm_init = 1; /* mem init */ int32 memm_init = 0; #endif int32 usmd = 0; /* user mode */ -int32 usmdbuf = 0; /* user mode buffer */ +int32 usmd_buf = 0; /* user mode buffer */ +int32 usmd_defer = 0; /* user mode defer */ int32 trap_pending = 0; /* trap pending */ int32 emir_pending = 0; /* emir pending */ int32 rest_pending = 0; /* restore pending */ int32 BR = 0; /* mem mgt bounds */ +int32 RR = 0; /* mem mgt reloc */ +int32 MMR = 0; /* XVM mem mgt */ int32 nexm = 0; /* nx mem flag */ int32 prvn = 0; /* priv viol flag */ int32 SC = 0; /* shift count */ int32 eae_ac_sign = 0; /* EAE AC sign */ int32 SR = 0; /* switch register */ +int32 ASW = ASW_DFLT; /* address switches */ int32 XR = 0; /* index register */ int32 LR = 0; /* limit register */ int32 stop_inst = 0; /* stop on rsrv inst */ @@ -326,6 +352,20 @@ t_stat cpu_reset (DEVICE *dptr); t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); int32 upd_iors (void); int32 api_eval (int32 *pend); +t_stat Read (int32 ma, int32 *dat, int32 cyc); +t_stat Write (int32 ma, int32 dat, int32 cyc); +t_stat Ia (int32 ma, int32 *ea, t_bool jmp); +int32 Incr_addr (int32 addr); +int32 Jms_word (int32 t); +#if defined (PDP15) +#define INDEX(i,x) if (!memm && ((i) & I_IDX)) x = ((x) + XR) & AMASK +int32 Prot15 (int32 ma, t_bool bndchk); +int32 Reloc15 (int32 ma, int32 acc); +int32 RelocXVM (int32 ma, int32 acc); +extern t_stat fp15 (int32 ir); +#else +#define INDEX(i,x) +#endif extern clk (int32 pulse, int32 AC); @@ -365,19 +405,18 @@ static const int32 api_vec[API_HLVL][32] = { cpu_mod CPU modifier list */ -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + EAE_DFLT + API_DFLT, +UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK+EAE_DFLT+API_DFLT+PROT_DFLT, MAXMEMSIZE) }; REG cpu_reg[] = { - { ORDATA (PC, saved_PC, ADDRSIZE) }, - { ORDATA (AC, saved_LAC, 18) }, - { FLDATA (L, saved_LAC, 18) }, -#if !defined (PDP4) - { ORDATA (MQ, saved_MQ, 18) }, + { ORDATA (PC, PC, ADDRSIZE) }, + { ORDATA (AC, LAC, 18) }, + { FLDATA (L, LAC, 18) }, + { ORDATA (MQ, MQ, 18) }, { ORDATA (SC, SC, 6) }, { FLDATA (EAE_AC_SIGN, eae_ac_sign, 18) }, -#endif { ORDATA (SR, SR, 18) }, + { ORDATA (ASW, ASW, ADDRSIZE) }, { ORDATA (IORS, iors, 18), REG_RO }, { BRDATA (INT, int_hwre, 8, 32, API_HLVL+1), REG_RO }, { FLDATA (INT_PEND, int_pend, 0), REG_RO }, @@ -396,7 +435,8 @@ REG cpu_reg[] = { { ORDATA (APIACT, api_act, 8) }, { ORDATA (BR, BR, ADDRSIZE) }, { FLDATA (USMD, usmd, 0) }, - { FLDATA (USMDBUF, usmdbuf, 0) }, + { FLDATA (USMDBUF, usmd_buf, 0) }, + { FLDATA (USMDDEF, usmd_defer, 0) }, { FLDATA (NEXM, nexm, 0) }, { FLDATA (PRVN, prvn, 0) }, { FLDATA (TRAPP, trap_pending, 0) }, @@ -407,14 +447,18 @@ REG cpu_reg[] = { { FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) }, #endif #if defined (PDP15) + { FLDATA (ION_INH, ion_inh, 0) }, { FLDATA (APIENB, api_enb, 0) }, { ORDATA (APIREQ, api_req, 8) }, { ORDATA (APIACT, api_act, 8) }, { ORDATA (XR, XR, 18) }, { ORDATA (LR, LR, 18) }, - { ORDATA (BR, BR, ADDRSIZE) }, + { ORDATA (BR, BR, 18) }, + { ORDATA (RR, RR, 18) }, + { ORDATA (MMR, MMR, 18) }, { FLDATA (USMD, usmd, 0) }, - { FLDATA (USMDBUF, usmdbuf, 0) }, + { FLDATA (USMDBUF, usmd_buf, 0) }, + { FLDATA (USMDDEF, usmd_defer, 0) }, { FLDATA (NEXM, nexm, 0) }, { FLDATA (PRVN, prvn, 0) }, { FLDATA (TRAPP, trap_pending, 0) }, @@ -431,15 +475,24 @@ REG cpu_reg[] = { { NULL } }; MTAB cpu_mod[] = { -#if !defined (PDP4) { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL }, { UNIT_NOEAE, 0, "EAE", "EAE", NULL }, -#else - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, -#endif #if defined (PDP9) || defined (PDP15) { UNIT_NOAPI, UNIT_NOAPI, "no API", "NOAPI", NULL }, { UNIT_NOAPI, 0, "API", "API", NULL }, + { UNIT_PROT+UNIT_RELOC+UNIT_XVM, 0, "no memory protect", + "NOPROTECT", NULL }, + { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT, "memory protect", + "PROTECT", NULL }, +#endif +#if defined (PDP15) + { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC, + "memory relocation", "RELOCATION", NULL }, + { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC+UNIT_XVM, + "XVM", "XVM", NULL }, +#endif +#if defined (PDP4) + { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, #endif { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, #if (MAXMEMSIZE > 8192) @@ -468,363 +521,250 @@ DEVICE cpu_dev = { t_stat sim_instr (void) { -int32 PC, LAC, MQ; -int32 api_int, api_cycle, skp; +int32 api_int, api_usmd, skp; int32 iot_data, device, pulse; t_stat reason; extern UNIT clk_unit; -#define JMS_WORD(t) (((LAC & 01000000) >> 1) | ((memm & 1) << 16) | \ - (((t) & 1) << 15) | ((PC) & 077777)) -#define INCR_ADDR(x) (((x) & epcmask) | (((x) + 1) & damask)) -#define SEXT(x) ((int32) (((x) & 0400000)? (x) | ~0777777: (x) & 0777777)) - -/* The following macros implement addressing. They account for autoincrement - addressing, extended addressing, and memory protection, if it exists. - - CHECK_AUTO_INC check auto increment - INDIRECT indirect addressing - CHECK_INDEX check indexing - CHECK_ADDR_R check address for read - CHECK_ADDR_W check address for write - - On the PDP-4 and PDP-7, - There are autoincrement locations in every field. If a field - does not exist, it is impossible to generate an - autoincrement reference (all instructions are CAL). - Indirect addressing range is determined by extend mode. - There is no indexing. - There is no memory protection, nxm reads zero and ignores writes. -*/ - -#if defined (PDP4) || defined (PDP7) -#define CHECK_AUTO_INC \ - if ((IR & 017770) == 010) M[MA] = (M[MA] + 1) & 0777777 -#define INDIRECT \ - MA = memm? M[MA] & IAMASK: (MA & epcmask) | (M[MA] & damask) -#define CHECK_INDEX /* no indexing capability */ -#define CHECK_ADDR_R(x) /* no read protection */ -#define CHECK_ADDR_W(x) \ - if (!MEM_ADDR_OK (x)) break -#endif - -/* On the PDP-9, - The autoincrement registers are in field zero only. Regardless - of extend mode, indirect addressing through 00010-00017 - will access absolute locations 00010-00017. - Indirect addressing range is determined by extend mode. If - extend mode is off, and autoincrementing is used, the - resolved address is in bank 0 (KG09B maintenance manual). - There is no indexing. - Memory protection is implemented for foreground/background operation. -*/ - -#if defined (PDP9) -#define CHECK_AUTO_INC \ - if ((IR & 017770) == 010) { \ - MA = MA & 017; \ - M[MA] = (M[MA] + 1) & 0777777; } -#define INDIRECT \ - MA = memm? M[MA] & IAMASK: (MA & epcmask) | (M[MA] & damask) -#define CHECK_ADDR_R(x) \ - if (usmd) { \ - if (!MEM_ADDR_OK (x)) { \ - nexm = prvn = trap_pending = 1; \ - break; } \ - if ((x) < BR) { \ - prvn = trap_pending = 1; \ - break; } } \ - if (!MEM_ADDR_OK (x)) nexm = 1 -#define CHECK_INDEX /* no indexing capability */ -#define CHECK_ADDR_W(x) \ - CHECK_ADDR_R (x); \ - if (!MEM_ADDR_OK (x)) break -#endif - -/* On the PDP-15, - The autoincrement registers are in page zero only. Regardless - of bank mode, indirect addressing through 00010-00017 - will access absolute locations 00010-00017. - Indirect addressing range is determined by autoincrementing. - Indexing is available if bank mode is off. - Memory protection is implemented for foreground/background operation. -*/ - -#if defined (PDP15) -#define CHECK_AUTO_INC \ - if ((IR & damask & ~07) == 00010) { \ - MA = MA & 017; \ - M[MA] = (M[MA] + 1) & 0777777; } -#define INDIRECT \ - if (rest_pending) { \ - rest_pending = 0; \ - LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777); \ - memm = (M[MA] >> 16) & 1; \ - usmd = (M[MA] >> 15) & 1; } \ - MA = ((IR & damask & ~07) != 00010)? \ - (PC & BLKMASK) | (M[MA] & IAMASK): (M[MA] & ADDRMASK); \ - damask = memm? 017777: 07777; \ - epcmask = ADDRMASK & ~damask -#define CHECK_INDEX \ - if ((IR & 0010000) && (memm == 0)) MA = (MA + XR) & ADDRMASK -#define CHECK_ADDR_R(x) \ - if (usmd) { \ - if (!MEM_ADDR_OK (x)) { \ - nexm = prvn = trap_pending = 1; \ - break; } \ - if ((x) < BR) { \ - prvn = trap_pending = 1; \ - break; } } \ - if (!MEM_ADDR_OK (x)) nexm = 1 -#define CHECK_ADDR_W(x) \ - CHECK_ADDR_R (x); \ - if (!MEM_ADDR_OK (x)) break -#endif - -/* Restore register state */ - -#if defined (PDP15) -int32 epcmask, damask; - -damask = memm? 017777: 07777; /* set dir addr mask */ -epcmask = ADDRMASK & ~damask; /* extended PC mask */ - -#else -#define damask 017777 /* direct addr mask */ -#define epcmask (ADDRMASK & ~damask) /* extended PC mask */ -#endif - if (build_dev_tab ()) return SCPE_STOP; /* build, chk tables */ -PC = saved_PC & ADDRMASK; /* load local copies */ -LAC = saved_LAC & 01777777; -MQ = saved_MQ & 0777777; +PC = PC & AMASK; /* clean variables */ +LAC = LAC & LACMASK; +MQ = MQ & DMASK; reason = 0; sim_rtc_init (clk_unit.wait); /* init calibration */ if (cpu_unit.flags & UNIT_NOAPI) api_enb = api_req = api_act = 0; api_int = api_eval (&int_pend); /* eval API */ -api_cycle = 0; /* not API cycle */ - -/* Main instruction fetch/decode loop: check trap and interrupt */ +api_usmd = 0; /* not API user cycle */ + +/* Main instruction fetch/decode loop */ while (reason == 0) { /* loop until halted */ -int32 IR, MA, esc, t, xct_count; +int32 IR, MA, MB, esc, t, xct_count; int32 link_init, fill; if (sim_interval <= 0) { /* check clock queue */ if (reason = sim_process_event ()) break; api_int = api_eval (&int_pend); } /* eval API */ -/* Protection traps work like interrupts, with these quirks: +/* PDP-4 and PDP-7 traps and interrupts - PDP-7 extend mode forced on, M[0] = PC, PC = 2 - PDP-9 extend mode ???, M[0/20] = PC, PC = 0/21 - PDP-15 bank mode unchanged, M[0/20] = PC, PC = 0/21 -*/ + PDP-4 no trap + PDP-7 trap: extend mode forced on, M[0] = PC, PC = 2 + PDP-4, PDP-7 programmable interrupts only */ +#if defined (PDP4) || defined (PDP7) #if defined (PDP7) if (trap_pending) { /* trap pending? */ PCQ_ENTRY; /* save old PC */ - M[0] = JMS_WORD (1); /* save state */ - PC = 2; /* fetch next from 2 */ + MB = Jms_word (1); /* save state */ ion = 0; /* interrupts off */ memm = 1; /* extend on */ emir_pending = trap_pending = 0; /* emir, trap off */ - usmd = 0; } /* protect off */ + usmd = usmd_buf = 0; /* user mode off */ + Write (0, MB, WR); /* save in 0 */ + PC = 2; } /* fetch next from 2 */ #endif -#if defined (PDP9) || defined (PDP15) -if (trap_pending) { /* trap pending? */ - PCQ_ENTRY; /* save old PC */ - MA = ion? 0: 020; /* save in 0 or 20 */ - M[MA] = JMS_WORD (1); /* save state */ - PC = MA + 1; /* fetch next */ - ion = 0; /* interrupts off */ - emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */ - usmd = 0; } /* protect off */ - -/* PDP-9 and PDP-15 automatic priority interrupt (API) */ - -if (api_int && !ion_defer) { /* API intr? */ - int32 i, lvl = api_int - 1; /* get req level */ - api_act = api_act | (0200 >> lvl); /* set level active */ - if (lvl >= API_HLVL) { /* software req? */ - MA = ACH_SWRE + lvl - API_HLVL; /* vec = 40:43 */ - api_req = api_req & ~(0200 >> lvl); } /* remove request */ - else { - MA = 0; /* assume fails */ - for (i = 0; i < 32; i++) { /* loop hi to lo */ - if ((int_hwre[lvl] >> i) & 1) { /* int req set? */ - MA = api_vec[lvl][i]; /* get vector */ - break; } } } /* and stop */ - if (MA == 0) { /* bad channel? */ - reason = STOP_API; /* API error */ - break; } - api_int = api_eval (&int_pend); /* no API int */ - api_cycle = 1; /* in API cycle */ - emir_pending = rest_pending = 0; /* emir, restore off */ - xct_count = 0; - goto xct_instr; } - -/* Standard program interrupt */ - -if (!(api_enb && api_act) && ion && !ion_defer && int_pend) { -#else if (ion && !ion_defer && int_pend) { /* interrupt? */ -#endif PCQ_ENTRY; /* save old PC */ - M[0] = JMS_WORD (usmd); /* save state */ - PC = 1; /* fetch next from 1 */ + MB = Jms_word (usmd); /* save state */ ion = 0; /* interrupts off */ -#if !defined (PDP15) /* except PDP-15, */ memm = 0; /* extend off */ -#endif emir_pending = rest_pending = 0; /* emir, restore off */ - usmd = 0; } /* protect off */ - -/* Breakpoint */ + usmd = usmd_buf = 0; /* user mode off */ + Write (0, MB, WR); /* physical write */ + PC = 1; } /* fetch next from 1 */ if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ reason = STOP_IBKPT; /* stop simulation */ break; } + +#endif /* end PDP-4/PDP-7 */ -/* Fetch, decode instruction */ +/* PDP-9 and PDP-15 traps and interrupts + + PDP-9 trap: extend mode ???, M[0/20] = PC, PC = 0/21 + PDP-15 trap: bank mode unchanged, M[0/20] = PC, PC = 0/21 + PDP-9, PDP-15 API and program interrupts */ #if defined (PDP9) || defined (PDP15) -if (usmd) { /* user mode? */ - if (!MEM_ADDR_OK (PC)) { /* nxm? */ - nexm = prvn = trap_pending = 1; /* abort fetch */ - continue; } - if (PC < BR) { /* bounds viol? */ - prvn = trap_pending = 1; /* abort fetch */ - continue; } } -else if (!MEM_ADDR_OK (PC)) nexm = 1; /* flag nxm */ -if (!ion_defer) usmd = usmdbuf; /* no IOT? load usmd */ +if (trap_pending) { /* trap pending? */ + PCQ_ENTRY; /* save old PC */ + MB = Jms_word (1); /* save state */ + MA = ion? 0: 020; /* save in 0/20 */ + ion = 0; /* interrupts off */ + emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */ + usmd = usmd_buf = 0; /* user mode off */ + Write (MA, MB, WR); /* physical write */ + PC = MA + 1; } /* fetch next */ + +if (api_int && !ion_defer) { /* API intr? */ + int32 i, lvl = api_int - 1; /* get req level */ + api_act = api_act | (API_ML0 >> lvl); /* set level active */ + if (lvl >= API_HLVL) { /* software req? */ + MA = ACH_SWRE + lvl - API_HLVL; /* vec = 40:43 */ + api_req = api_req & ~(API_ML0 >> lvl); } /* remove request */ + else { + MA = 0; /* assume fails */ + for (i = 0; i < 32; i++) { /* loop hi to lo */ + if ((int_hwre[lvl] >> i) & 1) { /* int req set? */ + MA = api_vec[lvl][i]; /* get vector */ + break; } } } /* and stop */ + if (MA == 0) { /* bad channel? */ + reason = STOP_API; /* API error */ + break; } + api_int = api_eval (&int_pend); /* no API int */ + api_usmd = usmd; /* API user mode cycle */ + usmd = usmd_buf = 0; /* user mode off */ + emir_pending = rest_pending = 0; /* emir, restore off */ + xct_count = 0; + goto xct_instr; } + +if (!(api_enb && api_act) && ion && !ion_defer && int_pend) { + PCQ_ENTRY; /* save old PC */ + MB = Jms_word (usmd); /* save state */ + ion = 0; /* interrupts off */ +#if defined (PDP9) /* PDP-9, */ + memm = 0; /* extend off */ +#else /* PDP-15 */ + if (!(cpu_unit.flags & UNIT_NOAPI)) { /* API? */ + api_act = api_act | API_ML3; /* set lev 3 active */ + api_int = api_eval (&int_pend); } /* re-evaluate */ #endif + emir_pending = rest_pending = 0; /* emir, restore off */ + usmd = usmd_buf = 0; /* user mode off */ + Write (0, MB, WR); /* physical write */ + PC = 1; } /* fetch next from 1 */ + +if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ + reason = STOP_IBKPT; /* stop simulation */ + break; } +if (!usmd_defer) usmd = usmd_buf; /* no IOT? load usmd */ +else usmd_defer = 0; /* cancel defer */ + +#endif /* PDP-9/PDP-15 */ + +/* Instruction fetch and address decode */ + xct_count = 0; /* track nested XCT's */ MA = PC; /* fetch at PC */ -PC = INCR_ADDR (PC); /* increment PC */ +PC = Incr_addr (PC); /* increment PC */ xct_instr: /* label for XCT */ -IR = M[MA]; /* fetch instruction */ +if (Read (MA, &IR, FE)) continue; /* fetch instruction */ if (ion_defer) ion_defer = ion_defer - 1; /* count down defer */ if (sim_interval) sim_interval = sim_interval - 1; -MA = (MA & epcmask) | (IR & damask); /* effective address */ + +#if defined (PDP15) /* PDP15 */ +if (memm) MA = (MA & B_EPCMASK) | (IR & B_DAMASK); /* bank mode dir addr */ +else MA = (MA & P_EPCMASK) | (IR & P_DAMASK); /* page mode dir addr */ +#else /* others */ +MA = (MA & B_EPCMASK) | (IR & B_DAMASK); /* bank mode only */ +#endif switch ((IR >> 13) & 037) { /* decode IR<0:4> */ /* LAC: opcode 20 */ case 011: /* LAC, indir */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 010: /* LAC, dir */ - CHECK_INDEX; - CHECK_ADDR_R (MA); - LAC = (LAC & 01000000) | M[MA]; + INDEX (IR, MA); + if (Read (MA, &MB, RD)) break; + LAC = (LAC & LINK) | MB; break; /* DAC: opcode 04 */ case 003: /* DAC, indir */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 002: /* DAC, dir */ - CHECK_INDEX; - CHECK_ADDR_W (MA); - M[MA] = LAC & 0777777; + INDEX (IR, MA); + Write (MA, LAC & DMASK, WR); break; /* DZM: opcode 14 */ case 007: /* DZM, indir */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 006: /* DZM, direct */ - CHECK_INDEX; - CHECK_ADDR_W (MA); - M[MA] = 0; + INDEX (IR, MA); + Write (MA, 0, WR); break; /* AND: opcode 50 */ case 025: /* AND, ind */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 024: /* AND, dir */ - CHECK_INDEX; - CHECK_ADDR_R (MA); - LAC = LAC & (M[MA] | 01000000); + INDEX (IR, MA); + if (Read (MA, &MB, RD)) break; + LAC = LAC & (MB | LINK); break; /* XOR: opcode 24 */ case 013: /* XOR, ind */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 012: /* XOR, dir */ - CHECK_INDEX; - CHECK_ADDR_R (MA); - LAC = LAC ^ M[MA]; + INDEX (IR, MA); + if (Read (MA, &MB, RD)) break; + LAC = LAC ^ MB; break; /* ADD: opcode 30 */ case 015: /* ADD, indir */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 014: /* ADD, dir */ - CHECK_INDEX; - CHECK_ADDR_R (MA); - t = (LAC & 0777777) + M[MA]; - if (t > 0777777) t = (t + 1) & 0777777; /* end around carry */ - if (((~LAC ^ M[MA]) & (LAC ^ t)) & 0400000) /* overflow? */ - LAC = 01000000 | t; /* set link */ - else LAC = (LAC & 01000000) | t; + INDEX (IR, MA); + if (Read (MA, &MB, RD)) break; + t = (LAC & DMASK) + MB; + if (t > DMASK) t = (t + 1) & DMASK; /* end around carry */ + if (((~LAC ^ MB) & (LAC ^ t)) & SIGN) /* overflow? */ + LAC = LINK | t; /* set link */ + else LAC = (LAC & LINK) | t; break; /* TAD: opcode 34 */ case 017: /* TAD, indir */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 016: /* TAD, dir */ - CHECK_INDEX; - CHECK_ADDR_R (MA); - LAC = (LAC + M[MA]) & 01777777; + INDEX (IR, MA); + if (Read (MA, &MB, RD)) break; + LAC = (LAC + MB) & LACMASK; break; /* ISZ: opcode 44 */ case 023: /* ISZ, indir */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 022: /* ISZ, dir */ - CHECK_INDEX; - CHECK_ADDR_W (MA); - M[MA] = (M[MA] + 1) & 0777777; - if (M[MA] == 0) PC = INCR_ADDR (PC); + INDEX (IR, MA); + if (Read (MA, &MB, RD)) break; + MB = (MB + 1) & DMASK; + if (Write (MA, MB, WR)) break; + if (MB == 0) PC = Incr_addr (PC); break; /* SAD: opcode 54 */ case 027: /* SAD, indir */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 026: /* SAD, dir */ - CHECK_INDEX; - CHECK_ADDR_R (MA); - if ((LAC & 0777777) != M[MA]) PC = INCR_ADDR (PC); + INDEX (IR, MA); + if (Read (MA, &MB, RD)) break; + if ((LAC & DMASK) != MB) PC = Incr_addr (PC); break; /* XCT: opcode 40 */ case 021: /* XCT, indir */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 020: /* XCT, dir */ - CHECK_INDEX; - CHECK_ADDR_R (MA); - if (usmd && (xct_count != 0)) { /* trap and chained? */ - prvn = trap_pending = 1; - break; } + INDEX (IR, MA); + if ((api_usmd | usmd) && (xct_count != 0)) { /* chained and usmd? */ + if (usmd) prvn = trap_pending = 1; /* trap if usmd */ + break; } /* nop if api_usmd */ if (xct_count >= xct_max) { /* too many XCT's? */ reason = STOP_XCT; break; } @@ -834,69 +774,57 @@ case 020: /* XCT, dir */ #endif goto xct_instr; /* go execute */ -/* CAL: opcode 00 +/* CAL: opcode 00 - api_usmd records whether usmd = 1 at start of API cycle On the PDP-4 and PDP-7, CAL (I) is exactly the same as JMS (I) 20 On the PDP-9 and PDP-15, CAL clears user mode On the PDP-9 and PDP-15 with API, CAL activates level 4 - On the PDP-15, CAL goes to absolute 20, regardless of mode -*/ + On the PDP-15, CAL goes to absolute 20, regardless of mode */ case 001: case 000: /* CAL */ - t = usmd; -#if defined (PDP15) - MA = 020; -#else - MA = (memm? 0: PC & epcmask) | 020; /* MA = 20 */ + t = usmd; /* save user mode */ +#if defined (PDP15) /* PDP15 */ + MA = 020; /* MA = abs 20 */ + ion_defer = 1; /* "free instruction" */ +#else /* others */ + if (memm) MA = 020; /* if ext, abs 20 */ + else MA = (PC & B_EPCMASK) | 020; /* else bank-rel 20 */ #endif #if defined (PDP9) || defined (PDP15) - usmd = 0; /* clear user mode */ + usmd = usmd_buf = 0; /* clear user mode */ if ((cpu_unit.flags & UNIT_NOAPI) == 0) { /* if API, act lvl 4 */ api_act = api_act | 010; api_int = api_eval (&int_pend); } #endif - if (IR & 0020000) { INDIRECT; } /* indirect? */ - CHECK_ADDR_W (MA); + if (IR & I_IND) { /* indirect? */ + if (Ia (MA, &MA, 0)) break; } PCQ_ENTRY; - M[MA] = JMS_WORD (t); /* save state */ - PC = INCR_ADDR (MA); + MB = Jms_word (api_usmd | t); /* save state */ + Write (MA, MB, WR); + PC = Incr_addr (MA); break; -/* JMS: opcode 010 */ +/* JMS: opcode 010 - api_usmd records whether usmd = 1 at start of API cycle */ case 005: /* JMS, indir */ - CHECK_AUTO_INC; - INDIRECT; + if (Ia (MA, &MA, 0)) break; case 004: /* JMS, dir */ - CHECK_INDEX; - CHECK_ADDR_W (MA); + INDEX (IR, MA); PCQ_ENTRY; - M[MA] = JMS_WORD (usmd); /* save state */ - PC = INCR_ADDR (MA); +#if defined (PDP15) /* PDP15 */ + if (!usmd) ion_defer = 1; /* "free instruction" */ +#endif + MB = Jms_word (api_usmd | usmd); /* save state */ + if (Write (MA, MB, WR)) break; + PC = Incr_addr (MA); break; - -/* JMP: opcode 60 - Restore quirks: - On the PDP-7 and PDP-9, EMIR can only clear extend - On the PDP-15, any I triggers restore, but JMP I is conventional -*/ +/* JMP: opcode 60 */ case 031: /* JMP, indir */ - CHECK_AUTO_INC; /* check auto inc */ -#if defined (PDP7) || defined (PDP9) - if (emir_pending && (((M[MA] >> 16) & 1) == 0)) memm = 0; -#endif -#if defined (PDP9) - if (rest_pending) { /* restore pending? */ - LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777); - memm = (M[MA] >> 16) & 1; - usmd = (M[MA] >> 15) & 1; } -#endif - INDIRECT; /* complete indirect */ - emir_pending = rest_pending = 0; + if (Ia (MA, &MA, 1)) break; case 030: /* JMP, dir */ - CHECK_INDEX; + INDEX (IR, MA); PCQ_ENTRY; /* save old PC */ PC = MA; break; @@ -904,7 +832,7 @@ case 030: /* JMP, dir */ /* OPR: opcode 74 */ case 037: /* OPR, indir */ - LAC = (LAC & 01000000) | IR; /* LAW */ + LAC = (LAC & LINK) | IR; /* LAW */ break; case 036: /* OPR, dir */ @@ -913,51 +841,51 @@ case 036: /* OPR, dir */ case 0: /* nop */ break; case 1: /* SMA */ - if ((LAC & 0400000) != 0) skp = 1; + if ((LAC & SIGN) != 0) skp = 1; break; case 2: /* SZA */ - if ((LAC & 0777777) == 0) skp = 1; + if ((LAC & DMASK) == 0) skp = 1; break; case 3: /* SZA | SMA */ - if (((LAC & 0777777) == 0) || ((LAC & 0400000) != 0)) + if (((LAC & DMASK) == 0) || ((LAC & SIGN) != 0)) skp = 1; break; case 4: /* SNL */ - if (LAC >= 01000000) skp = 1; + if (LAC >= LINK) skp = 1; break; case 5: /* SNL | SMA */ - if (LAC >= 0400000) skp = 1; + if (LAC >= SIGN) skp = 1; break; case 6: /* SNL | SZA */ - if ((LAC >= 01000000) || (LAC == 0)) skp = 1; + if ((LAC >= LINK) || (LAC == 0)) skp = 1; break; case 7: /* SNL | SZA | SMA */ - if ((LAC >= 0400000) || (LAC == 0)) skp = 1; + if ((LAC >= SIGN) || (LAC == 0)) skp = 1; break; case 010: /* SKP */ skp = 1; break; case 011: /* SPA */ - if ((LAC & 0400000) == 0) skp = 1; + if ((LAC & SIGN) == 0) skp = 1; break; case 012: /* SNA */ - if ((LAC & 0777777) != 0) skp = 1; + if ((LAC & DMASK) != 0) skp = 1; break; case 013: /* SNA & SPA */ - if (((LAC & 0777777) != 0) && ((LAC & 0400000) == 0)) + if (((LAC & DMASK) != 0) && ((LAC & SIGN) == 0)) skp = 1; break; case 014: /* SZL */ - if (LAC < 01000000) skp = 1; + if (LAC < LINK) skp = 1; break; case 015: /* SZL & SPA */ - if (LAC < 0400000) skp = 1; + if (LAC < SIGN) skp = 1; break; case 016: /* SZL & SNA */ - if ((LAC < 01000000) && (LAC != 0)) skp = 1; + if ((LAC < LINK) && (LAC != 0)) skp = 1; break; case 017: /* SZL & SNA & SPA */ - if ((LAC < 0400000) && (LAC != 0)) skp = 1; + if ((LAC < SIGN) && (LAC != 0)) skp = 1; break; } /* end switch skips */ /* OPR, continued */ @@ -966,93 +894,93 @@ case 036: /* OPR, dir */ case 0: /* NOP */ break; case 1: /* CMA */ - LAC = LAC ^ 0777777; + LAC = LAC ^ DMASK; break; case 2: /* CML */ - LAC = LAC ^ 01000000; + LAC = LAC ^ LINK; break; case 3: /* CML CMA */ - LAC = LAC ^ 01777777; + LAC = LAC ^ LACMASK; break; case 4: /* CLL */ - LAC = LAC & 0777777; + LAC = LAC & DMASK; break; case 5: /* CLL CMA */ - LAC = (LAC & 0777777) ^ 0777777; + LAC = (LAC & DMASK) ^ DMASK; break; case 6: /* CLL CML = STL */ - LAC = LAC | 01000000; + LAC = LAC | LINK; break; case 7: /* CLL CML CMA */ - LAC = (LAC | 01000000) ^ 0777777; + LAC = (LAC | LINK) ^ DMASK; break; case 010: /* CLA */ - LAC = LAC & 01000000; + LAC = LAC & LINK; break; case 011: /* CLA CMA = STA */ - LAC = LAC | 0777777; + LAC = LAC | DMASK; break; case 012: /* CLA CML */ - LAC = (LAC & 01000000) ^ 01000000; + LAC = (LAC & LINK) ^ LINK; break; case 013: /* CLA CML CMA */ - LAC = (LAC | 0777777) ^ 01000000; + LAC = (LAC | DMASK) ^ LINK; break; case 014: /* CLA CLL */ LAC = 0; break; case 015: /* CLA CLL CMA */ - LAC = 0777777; + LAC = DMASK; break; case 016: /* CLA CLL CML */ - LAC = 01000000; + LAC = LINK; break; case 017: /* CLA CLL CML CMA */ - LAC = 01777777; + LAC = LACMASK; break; } /* end decode */ /* OPR, continued */ if (IR & 0000004) { /* OAS */ #if defined (PDP9) || defined (PDP15) - if (usmd) prvn = trap_pending = 1; - else + if (usmd) prvn = trap_pending = 1; /* trap if usmd */ + else if (!api_usmd) /* nop if api_usmd */ #endif LAC = LAC | SR; } switch (((IR >> 8) & 04) | ((IR >> 3) & 03)) { /* decode IR<7,13:14> */ case 1: /* RAL */ - LAC = ((LAC << 1) | (LAC >> 18)) & 01777777; + LAC = ((LAC << 1) | (LAC >> 18)) & LACMASK; break; case 2: /* RAR */ - LAC = ((LAC >> 1) | (LAC << 18)) & 01777777; + LAC = ((LAC >> 1) | (LAC << 18)) & LACMASK; break; case 3: /* RAL RAR */ #if defined (PDP15) /* PDP-15 */ - LAC = (LAC + 1) & 01777777; /* IAC */ + LAC = (LAC + 1) & LACMASK; /* IAC */ #else /* PDP-4,-7,-9 */ reason = stop_inst; /* undefined */ #endif break; case 5: /* RTL */ - LAC = ((LAC << 2) | (LAC >> 17)) & 01777777; + LAC = ((LAC << 2) | (LAC >> 17)) & LACMASK; break; case 6: /* RTR */ - LAC = ((LAC >> 2) | (LAC << 17)) & 01777777; + LAC = ((LAC >> 2) | (LAC << 17)) & LACMASK; break; case 7: /* RTL RTR */ #if defined (PDP15) /* PDP-15 */ LAC = ((LAC >> 9) & 0777) | ((LAC & 0777) << 9) | - (LAC & 01000000); /* BSW */ + (LAC & LINK); /* BSW */ #else /* PDP-4,-7,-9 */ reason = stop_inst; /* undefined */ #endif break; } /* end switch rotate */ if (IR & 0000040) { /* HLT */ - if (usmd) prvn = trap_pending = 1; - else reason = STOP_HALT; } - if (skp && !prvn) PC = INCR_ADDR (PC); /* if skip, inc PC */ + if (usmd) prvn = trap_pending = 1; /* trap if usmd */ + else if (!api_usmd) reason = STOP_HALT; } /* nop if api_usmd */ + if (skp) PC = Incr_addr (PC); /* if skip, inc PC */ break; /* end OPR */ /* EAE: opcode 64 @@ -1063,47 +991,45 @@ case 036: /* OPR, dir */ counter is complemented on load and then counted up to zero; timing guarantees an initial increment, which completes the two's complement load. In the simulator, the SC is loaded normally and then counted - down to zero; the read SC command compensates. -*/ + down to zero; the read SC command compensates. */ case 033: case 032: /* EAE */ if (cpu_unit.flags & UNIT_NOEAE) break; /* disabled? */ if (IR & 0020000) /* IR<4>? AC0 to L */ - LAC = ((LAC << 1) & 01000000) | (LAC & 0777777); + LAC = ((LAC << 1) & LINK) | (LAC & DMASK); if (IR & 0010000) MQ = 0; /* IR<5>? clear MQ */ - if ((IR & 0004000) && (LAC & 0400000)) /* IR<6> and minus? */ - eae_ac_sign = 01000000; /* set eae_ac_sign */ + if ((IR & 0004000) && (LAC & SIGN)) /* IR<6> and minus? */ + eae_ac_sign = LINK; /* set eae_ac_sign */ else eae_ac_sign = 0; /* if not, unsigned */ - if (IR & 0002000) MQ = (MQ | LAC) & 0777777; /* IR<7>? or AC */ - else if (eae_ac_sign) LAC = LAC ^ 0777777; /* if not, |AC| */ - if (IR & 0001000) LAC = LAC & 01000000; /* IR<8>? clear AC */ - link_init = LAC & 01000000; /* link temporary */ - fill = link_init? 0777777: 0; /* fill = link */ + if (IR & 0002000) MQ = (MQ | LAC) & DMASK; /* IR<7>? or AC */ + else if (eae_ac_sign) LAC = LAC ^ DMASK; /* if not, |AC| */ + if (IR & 0001000) LAC = LAC & LINK; /* IR<8>? clear AC */ + link_init = LAC & LINK; /* link temporary */ + fill = link_init? DMASK: 0; /* fill = link */ esc = IR & 077; /* get eff SC */ switch ((IR >> 6) & 07) { /* case on IR<9:11> */ case 0: /* setup */ - if (IR & 04) MQ = MQ ^ 0777777; /* IR<15>? ~MQ */ + if (IR & 04) MQ = MQ ^ DMASK; /* IR<15>? ~MQ */ if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */ if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */ break; case 1: /* multiply */ - CHECK_ADDR_R (PC); /* validate PC */ - MA = M[PC]; /* get next word */ - PC = INCR_ADDR (PC); /* increment PC */ - if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */ - LAC = LAC & 0777777; /* clear link */ + if (Read (PC, &MB, FE)) break; /* get next word */ + PC = Incr_addr (PC); /* increment PC */ + if (eae_ac_sign) MQ = MQ ^ DMASK; /* EAE AC sign? ~MQ */ + LAC = LAC & DMASK; /* clear link */ SC = esc; /* init SC */ do { /* loop */ - if (MQ & 1) LAC = LAC + MA; /* MQ<17>? add */ + if (MQ & 1) LAC = LAC + MB; /* MQ<17>? add */ MQ = (MQ >> 1) | ((LAC & 1) << 17); LAC = LAC >> 1; /* shift AC'MQ right */ SC = (SC - 1) & 077; } /* decrement SC */ while (SC != 0); /* until SC = 0 */ if (eae_ac_sign ^ link_init) { /* result negative? */ - LAC = LAC ^ 0777777; - MQ = MQ ^ 0777777; } + LAC = LAC ^ DMASK; + MQ = MQ ^ DMASK; } break; /* EAE, continued @@ -1114,62 +1040,59 @@ case 033: case 032: /* EAE */ The quotient is generated in one's complement form; therefore, the quotient is complemented if the input operands had the same sign - (that is, if the quotient is positive). -*/ + (that is, if the quotient is positive). */ case 3: /* divide */ - CHECK_ADDR_R (PC); /* validate PC */ - MA = M[PC]; /* get next word */ - PC = INCR_ADDR (PC); /* increment PC */ - if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */ - if ((LAC & 0777777) >= MA) { /* overflow? */ - LAC = (LAC - MA) | 01000000; /* set link */ + if (Read (PC, &MB, FE)) break; /* get next word */ + PC = Incr_addr (PC); /* increment PC */ + if (eae_ac_sign) MQ = MQ ^ DMASK; /* EAE AC sign? ~MQ */ + if ((LAC & DMASK) >= MB) { /* overflow? */ + LAC = (LAC - MB) | LINK; /* set link */ break; } - LAC = LAC & 0777777; /* clear link */ + LAC = LAC & DMASK; /* clear link */ t = 0; /* init loop */ SC = esc; /* init SC */ do { /* loop */ - if (t) LAC = (LAC + MA) & 01777777; - else LAC = (LAC - MA) & 01777777; + if (t) LAC = (LAC + MB) & LACMASK; + else LAC = (LAC - MB) & LACMASK; t = (LAC >> 18) & 1; /* quotient bit */ if (SC > 1) LAC = /* skip if last */ - ((LAC << 1) | (MQ >> 17)) & 01777777; - MQ = ((MQ << 1) | t) & 0777777; /* shift in quo bit */ + ((LAC << 1) | (MQ >> 17)) & LACMASK; + MQ = ((MQ << 1) | t) & DMASK; /* shift in quo bit */ SC = (SC - 1) & 077; } /* decrement SC */ while (SC != 0); /* until SC = 0 */ - if (t) LAC = (LAC + MA) & 01777777; - if (eae_ac_sign) LAC = LAC ^ 0777777; /* sgn rem = sgn divd */ - if ((eae_ac_sign ^ link_init) == 0) MQ = MQ ^ 0777777; + if (t) LAC = (LAC + MB) & LACMASK; + if (eae_ac_sign) LAC = LAC ^ DMASK; /* sgn rem = sgn divd */ + if ((eae_ac_sign ^ link_init) == 0) MQ = MQ ^ DMASK; break; /* EAE, continued EAE shifts, whether left or right, fill from the link. If the operand sign has been copied to the link, this provides correct - sign extension for one's complement numbers. -*/ + sign extension for one's complement numbers. */ case 4: /* normalize */ #if defined (PDP15) - if (!usmd) ion_defer = 2; /* free cycles */ + if (!usmd) ion_defer = 2; /* free instructions */ #endif - for (SC = esc; ((LAC & 0400000) == ((LAC << 1) & 0400000)); ) { + for (SC = esc; ((LAC & SIGN) == ((LAC << 1) & SIGN)); ) { LAC = (LAC << 1) | ((MQ >> 17) & 1); MQ = (MQ << 1) | (link_init >> 18); SC = (SC - 1) & 077; if (SC == 0) break; } - LAC = link_init | (LAC & 0777777); /* trim AC, restore L */ - MQ = MQ & 0777777; /* trim MQ */ + LAC = link_init | (LAC & DMASK); /* trim AC, restore L */ + MQ = MQ & DMASK; /* trim MQ */ SC = SC & 077; /* trim SC */ break; case 5: /* long right shift */ if (esc < 18) { - MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & 0777777; - LAC = ((fill << (18 - esc)) | (LAC >> esc)) & 01777777; } + MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & DMASK; + LAC = ((fill << (18 - esc)) | (LAC >> esc)) & LACMASK; } else { if (esc < 36) MQ = - ((fill << (36 - esc)) | (LAC >> (esc - 18))) & 0777777; + ((fill << (36 - esc)) | (LAC >> (esc - 18))) & DMASK; else MQ = fill; LAC = link_init | fill; } SC = 0; /* clear step count */ @@ -1178,11 +1101,11 @@ case 033: case 032: /* EAE */ case 6: /* long left shift */ if (esc < 18) { LAC = link_init | - (((LAC << esc) | (MQ >> (18 - esc))) & 0777777); - MQ = ((MQ << esc) | (fill >> (18 - esc))) & 0777777; } + (((LAC << esc) | (MQ >> (18 - esc))) & DMASK); + MQ = ((MQ << esc) | (fill >> (18 - esc))) & DMASK; } else { if (esc < 36) LAC = link_init | - (((MQ << (esc - 18)) | (fill >> (36 - esc))) & 0777777); + (((MQ << (esc - 18)) | (fill >> (36 - esc))) & DMASK); else LAC = link_init | fill; MQ = fill; } SC = 0; /* clear step count */ @@ -1190,7 +1113,7 @@ case 033: case 032: /* EAE */ case 7: /* AC left shift */ if (esc < 18) LAC = link_init | - (((LAC << esc) | (fill >> (18 - esc))) & 0777777); + (((LAC << esc) | (fill >> (18 - esc))) & DMASK); else LAC = link_init | fill; SC = 0; /* clear step count */ break; } /* end switch IR */ @@ -1203,36 +1126,36 @@ case 035: /* index operates */ t = (IR & 0400)? IR | 0777000: IR & 0377; /* sext immediate */ switch ((IR >> 9) & 017) { /* case on IR<5:8> */ case 000: /* AAS */ - LAC = (LAC & 01000000) | ((LAC + t) & 0777777); - if (SEXT (LAC & 0777777) >= SEXT (LR)) - PC = INCR_ADDR (PC); + LAC = (LAC & LINK) | ((LAC + t) & DMASK); + if (SEXT (LAC & DMASK) >= SEXT (LR)) + PC = Incr_addr (PC); case 001: /* PAX */ - XR = LAC & 0777777; + XR = LAC & DMASK; break; case 002: /* PAL */ - LR = LAC & 0777777; + LR = LAC & DMASK; break; case 003: /* AAC */ - LAC = (LAC & 01000000) | ((LAC + t) & 0777777); + LAC = (LAC & LINK) | ((LAC + t) & DMASK); break; case 004: /* PXA */ - LAC = (LAC & 01000000) | XR; + LAC = (LAC & LINK) | XR; break; case 005: /* AXS */ - XR = (XR + t) & 0777777; - if (SEXT (XR) >= SEXT (LR)) PC = INCR_ADDR (PC); + XR = (XR + t) & DMASK; + if (SEXT (XR) >= SEXT (LR)) PC = Incr_addr (PC); break; case 006: /* PXL */ LR = XR; break; case 010: /* PLA */ - LAC = (LAC & 01000000) | LR; + LAC = (LAC & LINK) | LR; break; case 011: /* PLX */ XR = LR; break; case 014: /* CLAC */ - LAC = LAC & 01000000; + LAC = LAC & LINK; break; case 015: /* CLX */ XR = 0; @@ -1241,7 +1164,7 @@ case 035: /* index operates */ LR = 0; break; case 017: /* AXR */ - XR = (XR + t) & 0777777; + XR = (XR + t) & DMASK; break; } /* end switch IR */ break; /* end case */ #endif @@ -1253,14 +1176,19 @@ case 035: /* index operates */ IOT PDP-4 PDP-7 PDP-9 PDP-15 700002 IOF IOF IOF IOF + 700022 undefined undefined undefined ORMM (XVM) 700042 ION ION ION ION + 700024 undefined undefined undefined LDMM (XVM) 700062 undefined ITON undefined undefined 701701 undefined undefined MPSK MPSK 701741 undefined undefined MPSNE MPSNE 701702 undefined undefined MPCV MPCV + 701722 undefined undefined undefined MPRC (XVM) 701742 undefined undefined MPEU MPEU 701704 undefined undefined MPLD MPLD + 701724 undefined undefined undefined MPLR (KT15, XVM) 701744 undefined undefined MPCNE MPCNE + 701764 undefined undefined undefined IPFH (XVM) 703201 undefined undefined PFSF PFSF 703301 undefined TTS TTS TTS 703341 undefined SKP7 SKP7 SPCO @@ -1268,7 +1196,9 @@ case 035: /* index operates */ 703304 undefined undefined DBK DBK 703344 undefined undefined DBR DBR 705501 undefined undefined SPI SPI + 705521 undefined undefined undefined ENB 705502 undefined undefined RPL RPL + 705522 undefined undefined undefined INH 705504 undefined undefined ISA ISA 707701 undefined SEM SEM undefined 707741 undefined undefined undefined SKP15 @@ -1277,22 +1207,22 @@ case 035: /* index operates */ 707742 undefined EMIR EMIR RES 707762 undefined undefined undefined DBA 707704 undefined LEM LEM undefined - 707764 undefined undefined undefined EBA -*/ + 707764 undefined undefined undefined EBA */ case 034: /* IOT */ #if defined (PDP15) if (IR & 0010000) { /* floating point? */ -/* PC = fp15 (PC, IR); /* process */ + fp15 (IR); /* process */ break; } #endif - if (usmd) { /* user mode? */ - prvn = trap_pending = 1; /* trap */ - break; } + if ((api_usmd | usmd) && /* user, not XVM UIOT? */ + (!XVM || !(MMR & MM_UIOT))) { + if (usmd) prvn = trap_pending = 1; /* trap if user */ + break; } /* nop if api_usmd */ device = (IR >> 6) & 077; /* device = IR<6:11> */ pulse = IR & 067; /* pulse = IR<12:17> */ - if (IR & 0000010) LAC = LAC & 01000000; /* clear AC? */ - iot_data = LAC & 0777777; /* AC unchanged */ + if (IR & 0000010) LAC = LAC & LINK; /* clear AC? */ + iot_data = LAC & DMASK; /* AC unchanged */ /* PDP-4 system IOT's */ @@ -1313,15 +1243,15 @@ case 034: /* IOT */ if (pulse == 002) ion = 0; /* IOF */ else if (pulse == 042) ion = ion_defer = 1; /* ION */ else if (pulse == 062) /* ITON */ - usmd = ion = ion_defer = 1; + usmd = usmd_buf = ion = ion_defer = 1; else iot_data = clk (pulse, iot_data); break; case 033: /* CPU control */ - if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC); - else if (pulse == 002) reset_all (0); /* CAF */ + if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC); + else if (pulse == 002) reset_all (1); /* CAF - skip CPU */ break; case 077: /* extended memory */ - if ((pulse == 001) && memm) PC = INCR_ADDR (PC); + if ((pulse == 001) && memm) PC = Incr_addr (PC); else if (pulse == 002) memm = 1; /* EEM */ else if (pulse == 042) /* EMIR */ memm = emir_pending = 1; /* ext on, restore */ @@ -1329,10 +1259,11 @@ case 034: /* IOT */ break; #endif -/* PDP-9 and PDP-15 system IOT's */ +/* PDP-9 system IOT's */ -#if defined (PDP9) || defined (PDP15) +#if defined (PDP9) ion_defer = 1; /* delay interrupts */ + usmd_defer = 1; /* defer load user */ switch (device) { /* decode IR<6:11> */ case 000: /* CPU and clock */ if (pulse == 002) ion = 0; /* IOF */ @@ -1340,24 +1271,26 @@ case 034: /* IOT */ else iot_data = clk (pulse, iot_data); break; case 017: /* mem protection */ - if ((pulse == 001) && prvn) PC = INCR_ADDR (PC); - else if ((pulse == 041) && nexm) PC = INCR_ADDR (PC); - else if (pulse == 002) prvn = 0; - else if (pulse == 042) usmdbuf = 1; - else if (pulse == 004) BR = LAC & BRMASK; - else if (pulse == 044) nexm = 0; + if (PROT) { /* enabled? */ + if ((pulse == 001) && prvn) PC = Incr_addr (PC); + else if ((pulse == 041) && nexm) PC = Incr_addr (PC); + else if (pulse == 002) prvn = 0; + else if (pulse == 042) usmd_buf = 1; + else if (pulse == 004) BR = LAC & BRMASK; + else if (pulse == 044) nexm = 0; } + else reason = stop_inst; break; case 032: /* power fail */ if ((pulse == 001) && (TST_INT (PWRFL))) - PC = INCR_ADDR (PC); + PC = Incr_addr (PC); break; case 033: /* CPU control */ - if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC); - else if (pulse == 002) reset_all (0); /* CAF */ - else if (pulse == 044) rest_pending = 1; /* DBR */ + if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC); + else if (pulse == 002) reset_all (1); /* CAF - skip CPU */ + else if (pulse == 044) rest_pending = 1; /* DBR */ if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) { int32 t = api_ffo[api_act & 0377]; - api_act = api_act & ~(0200 >> t); } + api_act = api_act & ~(API_ML0 >> t); } break; case 055: /* API control */ if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst; @@ -1373,25 +1306,76 @@ case 034: /* IOT */ api_req = api_req | ((LAC >> 8) & 017); api_act = api_act | (LAC & 0377); } break; -#endif -#if defined (PDP9) case 077: /* extended memory */ - if ((pulse == 001) && memm) PC = INCR_ADDR (PC); + if ((pulse == 001) && memm) PC = Incr_addr (PC); else if (pulse == 002) memm = 1; /* EEM */ else if (pulse == 042) /* EMIR */ memm = emir_pending = 1; /* ext on, restore */ else if (pulse == 004) memm = 0; /* LEM */ break; #endif + +/* PDP-15 system IOT's - includes "re-entrancy ECO" ENB/INH as standard */ + #if defined (PDP15) + ion_defer = 1; /* delay interrupts */ + usmd_defer = 1; /* defer load user */ + switch (device) { /* decode IR<6:11> */ + case 000: /* CPU and clock */ + if (pulse == 002) ion = 0; /* IOF */ + else if (pulse == 042) ion = 1; /* ION */ + else if (XVM && (pulse == 022)) /* ORMM/RDMM */ + iot_data = MMR; + else if (XVM && (pulse == 024)) /* LDMM */ + MMR = iot_data; + else iot_data = clk (pulse, iot_data); + break; + case 017: /* mem protection */ + if (PROT) { /* enabled? */ + t = XVM? BRMASK_XVM: BRMASK; + if ((pulse == 001) && prvn) PC = Incr_addr (PC); + else if ((pulse == 041) && nexm) PC = Incr_addr (PC); + else if (pulse == 002) prvn = 0; + else if (pulse == 042) usmd_buf = 1; + else if (pulse == 004) BR = LAC & t; + else if (RELOC && (pulse == 024)) RR = LAC & t; + else if (pulse == 044) nexm = 0; } + else reason = stop_inst; + break; + case 032: /* power fail */ + if ((pulse == 001) && (TST_INT (PWRFL))) + PC = Incr_addr (PC); + break; + case 033: /* CPU control */ + if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC); + else if (pulse == 002) reset_all (2); /* CAF - skip CPU, FP15 */ + else if (pulse == 044) rest_pending = 1; /* DBR */ + if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) { + int32 t = api_ffo[api_act & 0377]; + api_act = api_act & ~(API_ML0 >> t); } + break; + case 055: /* API control */ + if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst; + else if (pulse == 001) { /* SPI */ + if (((LAC & SIGN) && api_enb) || + ((LAC & 0377) > api_act)) + iot_data = iot_data | IOT_SKP; } + else if (pulse == 002) { /* RPL */ + iot_data = iot_data | (api_enb << 17) | + (api_req << 8) | api_act; } + else if (pulse == 004) { /* ISA */ + api_enb = (iot_data & SIGN)? 1: 0; + api_req = api_req | ((LAC >> 8) & 017); + api_act = api_act | (LAC & 0377); } + else if (pulse == 021) ion_inh = 0; /* ENB */ + else if (pulse == 022) ion_inh = 1; /* INH */ + break; case 077: /* bank addressing */ if ((pulse == 041) || ((pulse == 061) && memm)) - PC = INCR_ADDR (PC); /* SKP15, SBA */ + PC = Incr_addr (PC); /* SKP15, SBA */ else if (pulse == 042) rest_pending = 1; /* RES */ else if (pulse == 062) memm = 0; /* DBA */ else if (pulse == 064) memm = 1; /* EBA */ - damask = memm? 017777: 07777; /* set dir addr mask */ - epcmask = ADDRMASK & ~damask; /* extended PC mask */ break; #endif @@ -1402,23 +1386,17 @@ case 034: /* IOT */ iot_data = dev_tab[device] (pulse, iot_data); else reason = stop_inst; /* stop on flag */ break; } /* end switch device */ - LAC = LAC | (iot_data & 0777777); - if (iot_data & IOT_SKP) PC = INCR_ADDR (PC); + LAC = LAC | (iot_data & DMASK); + if (iot_data & IOT_SKP) PC = Incr_addr (PC); if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON; api_int = api_eval (&int_pend); /* eval API */ break; /* end case IOT */ } /* end switch opcode */ -if (api_cycle) { /* API cycle? */ - api_cycle = 0; /* cycle over */ - usmd = 0; /* exit user mode */ - trap_pending = prvn = 0; } /* no priv viol */ +api_usmd = 0; /* API cycle over */ } /* end while */ /* Simulation halted */ -saved_PC = PC & ADDRMASK; /* save copies */ -saved_LAC = LAC & 01777777; -saved_MQ = MQ & 0777777; iors = upd_iors (); /* get IORS */ pcq_r->qptr = pcq_p; /* update pc q ptr */ return reason; @@ -1430,13 +1408,17 @@ int32 api_eval (int32 *pend) { int32 i, hi; -for (i = *pend = 0; i < API_HLVL+1; i++) { /* any intr? */ +*pend = 0; /* assume no intr */ +#if defined (PDP15) /* PDP15 only */ +if (ion_inh) return 0; /* inhibited? */ +#endif +for (i = 0; i < API_HLVL+1; i++) { /* any intr? */ if (int_hwre[i]) *pend = 1; } if (api_enb == 0) return 0; /* off? no req */ -api_req = api_req & ~0360; /* clr req<0:3> */ +api_req = api_req & ~(API_ML0|API_ML1|API_ML2|API_ML3); /* clr req<0:3> */ for (i = 0; i < API_HLVL; i++) { /* loop thru levels */ if (int_hwre[i]) /* req on level? */ - api_req = api_req | (0200 >> i); } /* set api req */ + api_req = api_req | (API_ML0 >> i); } /* set api req */ hi = api_ffo[api_req & 0377]; /* find hi req */ if (hi < api_ffo[api_act & 0377]) return (hi + 1); return 0; @@ -1454,17 +1436,308 @@ for (p = 0; dev_iors[p] != NULL; p++) { /* loop thru table */ return d; } +#if defined (PDP4) || defined (PDP7) + +/* Read, write, indirect, increment routines + On the PDP-4 and PDP-7, + There are autoincrement locations in every field. If a field + does not exist, it is impossible to generate an + autoincrement reference (all instructions are CAL). + Indirect addressing range is determined by extend mode. + JMP I with EMIR pending can only clear extend + There is no memory protection, nxm reads zero and ignores writes. */ + +t_stat Read (int32 ma, int32 *dat, int32 cyc) +{ +ma = ma & AMASK; +if (MEM_ADDR_OK (ma)) *dat = M[ma] & DMASK; +else *dat = 0; +return MM_OK; +} + +t_stat Write (int32 ma, int32 dat, int32 cyc) +{ +ma = ma & AMASK; +if (MEM_ADDR_OK (ma)) M[ma] = dat & DMASK; +return MM_OK; +} + +t_stat Ia (int32 ma, int32 *ea, t_bool jmp) +{ +int32 t; +t_stat sta = MM_OK; + +if ((ma & B_DAMASK) == 010) { /* autoindex? */ + Read (ma, &t, DF); /* add 1 before use */ + t = (t + 1) & DMASK; + sta = Write (ma, t, DF); } +else sta = Read (ma, &t, DF); /* fetch indirect */ +if (jmp) { /* jmp i? */ + if (emir_pending && (((t >> 16) & 1) == 0)) memm = 0; + emir_pending = rest_pending = 0; } +if (memm) *ea = t & IAMASK; /* extend? 15b ia */ +else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */ +return sta; +} + +int32 Incr_addr (int32 ma) +{ +return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); +} + +int32 Jms_word (int32 t) +{ +return (((LAC & LINK) >> 1) | ((memm & 1) << 16) | + ((t & 1) << 15) | (PC & IAMASK)); +} + +#endif + +#if defined (PDP9) + +/* Read, write, indirect, increment routines + On the PDP-9, + The autoincrement registers are in field zero only. Regardless + of extend mode, indirect addressing through 00010-00017 + will access absolute locations 00010-00017. + Indirect addressing range is determined by extend mode. If + extend mode is off, and autoincrementing is used, the + resolved address is in bank 0 (KG09B maintenance manual). + JMP I with EMIR pending can only clear extend + JMP I with DBK pending restores L, user mode, extend mode + Memory protection is implemented for foreground/background operation. */ + +t_stat Read (int32 ma, int32 *dat, int32 cyc) +{ +ma = ma & AMASK; +if (usmd) { /* user mode? */ + if (!MEM_ADDR_OK (ma)) { /* nxm? */ + nexm = prvn = trap_pending = 1; /* set flags, trap */ + *dat = 0; + return MM_ERR; } + if ((cyc != DF) && (ma < BR)) { /* boundary viol? */ + prvn = trap_pending = 1; /* set flag, trap */ + *dat = 0; + return MM_ERR; } } +if (MEM_ADDR_OK (ma)) *dat = M[ma] & DMASK; /* valid mem? ok */ +else { *dat = 0; /* set flag, no trap */ + nexm = 1; } +return MM_OK; +} + +t_stat Write (int32 ma, int32 dat, int32 cyc) +{ +ma = ma & AMASK; +if (usmd) { + if (!MEM_ADDR_OK (ma)) { /* nxm? */ + nexm = prvn = trap_pending = 1; /* set flags, trap */ + return MM_ERR; } + if ((cyc != DF) && (ma < BR)) { /* boundary viol? */ + prvn = trap_pending = 1; /* set flag, trap */ + return MM_ERR; } } +if (MEM_ADDR_OK (ma)) M[ma] = dat & DMASK; /* valid mem? ok */ +else nexm = 1; /* set flag, no trap */ +return MM_OK; +} + +t_stat Ia (int32 ma, int32 *ea, t_bool jmp) +{ +int32 t; +t_stat sta = MM_OK; + +if ((ma & B_DAMASK) == 010) { /* autoindex? */ + ma = ma & 017; /* always in bank 0 */ + Read (ma, &t, DF); /* +1 before use */ + t = (t + 1) & DMASK; + sta = Write (ma, t, DF); } +else sta = Read (ma, &t, DF); +if (jmp) { /* jmp i? */ + if (emir_pending && (((t >> 16) & 1) == 0)) memm = 0; + if (rest_pending) { /* restore pending? */ + LAC = ((t << 1) & LINK) | (LAC & DMASK); /* restore L */ + memm = (t >> 16) & 1; /* restore extend */ + usmd = usmd_buf = (t >> 15) & 1; } /* restore user */ + emir_pending = rest_pending = 0; } +if (memm) *ea = t & IAMASK; /* extend? 15b ia */ +else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */ +return sta; +} + +int32 Incr_addr (int32 ma) +{ +return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); +} + +int32 Jms_word (int32 t) +{ +return (((LAC & LINK) >> 1) | ((memm & 1) << 16) | + ((t & 1) << 15) | (PC & IAMASK)); +} + +#endif + +#if defined (PDP15) + +/* Read, write, indirect, increment routines + On the PDP-15, + The autoincrement registers are in page zero only. Regardless + of bank mode, indirect addressing through 00010-00017 + will access absolute locations 00010-00017. + Indirect addressing range is determined by autoincrementing. + Any indirect can trigger a restore. + Memory protection is implemented for foreground/background operation. */ + +t_stat Read (int32 ma, int32 *dat, int32 cyc) +{ +int32 pa; + +if (usmd) { /* user mode? */ + if (XVM) pa = RelocXVM (ma, REL_R); /* XVM relocation? */ + else if (RELOC) pa = Reloc15 (ma, REL_R); /* PDP-15 relocation? */ + else pa = Prot15 (ma, cyc == FE); /* just protection */ + if (pa < 0) { /* error? */ + *dat = 0; + return MM_ERR; } } +else pa = ma & AMASK; /* no prot or reloc */ +if (MEM_ADDR_OK (pa)) *dat = M[pa] & DMASK; /* valid mem? ok */ +else { nexm = 1; /* set flag, no trap */ + *dat = 0; } +return MM_OK; +} + +t_stat Write (int32 ma, int32 dat, int32 cyc) +{ +int32 pa; + +if (usmd) { /* user mode? */ + if (XVM) pa = RelocXVM (ma, REL_W); /* XVM relocation? */ + else if (RELOC) pa = Reloc15 (ma, REL_W); /* PDP-15 relocation? */ + else pa = Prot15 (ma, cyc != DF); /* just protection */ + if (pa < 0) return MM_ERR; } /* error? */ +else pa = ma & AMASK; /* no prot or reloc */ +if (MEM_ADDR_OK (pa)) M[pa] = dat & DMASK; /* valid mem? ok */ +else nexm = 1; /* set flag, no trap */ +return MM_OK; +} + +/* XVM will do 18b defers if user_mode and G_Mode != 0 */ + +t_stat Ia (int32 ma, int32 *ea, t_bool jmp) +{ +int32 t; +int32 damask = memm? B_DAMASK: P_DAMASK; +t_stat sta = MM_OK; + +if ((ma & damask & ~07) == 010) { /* autoincrement? */ + ma = ma & 017; /* always in bank 0 */ + Read (ma, &t, DF); /* +1 before use */ + t = (t + 1) & DMASK; + sta = Write (ma, t, DF); } +else sta = Read (ma, &t, DF); +if (rest_pending) { /* restore pending? */ + LAC = ((t << 1) & LINK) | (LAC & DMASK); /* restore L */ + memm = (t >> 16) & 1; /* restore bank */ + usmd = usmd_buf = (t >> 15) & 1; /* restore user */ + emir_pending = rest_pending = 0; } +if (usmd && XVM && (MMR & MM_GM)) *ea = t; /* XVM G_mode? */ +else if ((ma & damask & ~07) == 010) *ea = t & AMASK; /* autoindex? */ +else *ea = (PC & BLKMASK) | (t & IAMASK); /* within 32K */ +return sta; +} + +t_stat Incr_addr (int32 ma) +{ +if (memm) return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); +return ((ma & P_EPCMASK) | ((ma + 1) & P_DAMASK)); +} + +/* XVM will store all 18b of PC if user mode and G_mode != 0 */ + +int32 Jms_word (int32 t) +{ +if (usmd && XVM && (MMR & MM_GM)) return PC; +return (((LAC & LINK) >> 1) | ((memm & 1) << 16) | + ((t & 1) << 15) | (PC & IAMASK)); +} + +/* PDP-15 protection (KM15 option) */ + +int32 Prot15 (int32 ma, t_bool bndchk) +{ +ma = ma & AMASK; /* 17b addressing */ +if (!MEM_ADDR_OK (ma)) { /* nxm? */ + nexm = prvn = trap_pending = 1; /* set flags, trap */ + return -1; } +if (bndchk && (ma < BR)) { /* boundary viol? */ + prvn = trap_pending = 1; /* set flag, trap */ + return -1; } +return ma; /* no relocation */ +} + +/* PDP-15 relocation and protection (KT15 option) */ + +int32 Reloc15 (int32 ma, int32 rc) +{ +int32 pa; + +ma = ma & AMASK; /* 17b addressing */ +if (ma >= (BR | 0377)) { /* boundary viol? */ + if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */ + return -1; } +pa = (ma + RR) & AMASK; /* relocate address */ +if (!MEM_ADDR_OK (pa)) { /* nxm? */ + if (rc != REL_C) nexm = prvn = trap_pending = 1; /* set flags, trap */ + return -1; } +return pa; +} + +/* XVM relocation and protection option */ + +int32 RelocXVM (int32 ma, int32 rc) +{ +int32 pa, gmode, slr; +static const int32 g_mask[4] = { MM_G_W0, MM_G_W1, MM_G_W2, MM_G_W3 }; +static const int32 g_base[4] = { MM_G_B0, MM_G_B1, MM_G_B2, MM_G_B3 }; +static const int32 slr_lnt[4] = { MM_SLR_L0, MM_SLR_L1, MM_SLR_L2, MM_SLR_L3 }; + +gmode = MM_GETGM (MMR); /* get G_mode */ +slr = MM_GETSLR (MMR); /* get segment length */ +ma = ma & g_mask[gmode]; /* mask address */ +if (MMR & MM_RDIS) pa = ma; /* reloc disabled? */ +else if ((MMR & MM_SH) && /* shared enabled and */ + (ma >= g_base[gmode]) && /* >= shared base and */ + (ma < (g_base[gmode] + slr_lnt[slr]))) { /* < shared end? */ + if (ma & 017400) { /* ESAS? */ + if ((rc == REL_W) && (MMR & MM_WP)) { /* write and protected? */ + prvn = trap_pending = 1; /* set flag, trap */ + return -1; } + pa = (((MMR & MM_SBR_MASK) << 8) + ma) & DMASK; } /* ESAS reloc */ + else pa = RR + (ma & 0377); } /* no, ISAS reloc */ +else { if (ma >= (BR | 0377)) { /* normal reloc, viol? */ + if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */ + return -1; } + pa = (RR + ma) & DMASK; } /* relocate address */ +if (!MEM_ADDR_OK (pa)) { /* nxm? */ + if (rc != REL_C) nexm = prvn = trap_pending = 1; /* set flags, trap */ + return -1; } +return pa; +} + +#endif + /* Reset routine */ t_stat cpu_reset (DEVICE *dptr) { SC = 0; eae_ac_sign = 0; -ion = ion_defer = 0; +ion = ion_defer = ion_inh = 0; CLR_INT (PWRFL); api_enb = api_req = api_act = 0; BR = 0; -usmd = usmdbuf = 0; +RR = 0; +MMR = 0; +usmd = usmd_buf = usmd_defer = 0; memm = memm_init; nexm = prvn = trap_pending = 0; emir_pending = rest_pending = 0; @@ -1479,8 +1752,14 @@ return SCPE_OK; t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { +#if defined (PDP15) +if (usmd && (sw & SWMASK ('V'))) { + if (XVM) addr = RelocXVM (addr, REL_C); + else if (RELOC) addr = Reloc15 (addr, REL_C); + if (addr < 0) return STOP_MME; } +#endif if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & 0777777; +if (vptr != NULL) *vptr = M[addr] & DMASK; return SCPE_OK; } @@ -1488,8 +1767,14 @@ return SCPE_OK; t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { +#if defined (PDP15) +if (usmd && (sw & SWMASK ('V'))) { + if (XVM) addr = RelocXVM (addr, REL_C); + else if (RELOC) addr = Reloc15 (addr, REL_C); + if (addr < 0) return STOP_MME; } +#endif if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & 0777777; +M[addr] = val & DMASK; return SCPE_OK; } diff --git a/PDP18B/pdp18b_defs.h b/PDP18B/pdp18b_defs.h index ee058761..a74c1c4c 100644 --- a/PDP18B/pdp18b_defs.h +++ b/PDP18B/pdp18b_defs.h @@ -23,6 +23,9 @@ 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-03 RMS Added FP15 support + Added XVM support + Added EAE option for PDP-4 25-Apr-03 RMS Revised for extended file support 04-Feb-03 RMS Added RB09, LP09 support 22-Nov-02 RMS Added PDP-4 drum support @@ -48,7 +51,7 @@ model memory CPU options I/O options - PDP4 8K ??Type 18 EAE Type 65 KSR-28 Teletype (Baudot) + PDP4 8K Type 18 EAE Type 65 KSR-28 Teletype (Baudot) integral paper tape reader Type 75 paper tape punch integral real time clock @@ -79,19 +82,19 @@ KA15 auto pri intr PC15 paper tape reader and punch KF15 power detection KW15 real time clock KM15 mem protection LP09 line printer - ??KT15 mem relocation LP15 line printer - RP15 disk pack - RF15/RF09 fixed head disk + KT15 mem relocation LP15 line printer + FP15 floating point RP15 disk pack + XVM option RF15/RF09 fixed head disk TC59D magnetic tape TC15/TU56 DECtape LT15 second Teletype - ??Indicates not implemented. The PDP-4 manual refers to both an EAE - ??and a memory extension control; there is no documentation on either. + ??Indicates not implemented. The PDP-4 manual refers to a memory + ??extension control; there is no documentation on it. */ #if !defined (PDP4) && !defined (PDP7) && !defined (PDP9) && !defined (PDP15) -#define PDP9 0 /* default to PDP-9 */ +#define PDP15 0 /* default to PDP-15 */ #endif /* Simulator stop codes */ @@ -102,6 +105,7 @@ #define STOP_XCT 4 /* nested XCT's */ #define STOP_API 5 /* invalid API int */ #define STOP_NONSTD 6 /* non-std dev num */ +#define STOP_MME 7 /* mem mgt error */ /* Peripheral configuration */ @@ -136,17 +140,49 @@ #define TC02 0 /* DECtape */ #define TTY1 0 /* second Teletype */ #define BRMASK 0377400 /* bounds mask */ +#define BRMASK_XVM 0777400 /* bounds mask, XVM */ #endif /* Memory */ -#define ADDRMASK ((1 << ADDRSIZE) - 1) /* address mask */ +#define AMASK ((1 << ADDRSIZE) - 1) /* address mask */ #define IAMASK 077777 /* ind address mask */ -#define BLKMASK (ADDRMASK & (~IAMASK)) /* block mask */ +#define BLKMASK (AMASK & (~IAMASK)) /* block mask */ #define MAXMEMSIZE (1 << ADDRSIZE) /* max memory size */ #define MEMSIZE (cpu_unit.capac) /* actual memory size */ #define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) +/* Instructions */ + +#define I_V_OP 14 /* opcode */ +#define I_M_OP 017 +#define I_V_IND 13 /* indirect */ +#define I_V_IDX 12 /* index */ +#define I_IND (1 << I_V_IND) +#define I_IDX (1 << I_V_IDX) +#define B_DAMASK 017777 /* bank mode address */ +#define B_EPCMASK (AMASK & ~B_DAMASK) +#define P_DAMASK 007777 /* page mode address */ +#define P_EPCMASK (AMASK & ~P_DAMASK) + +/* Memory cycles */ + +#define FE 0 +#define DF 1 +#define RD 2 +#define WR 3 + +/* Memory status codes */ + +#define MM_OK 0 +#define MM_ERR 1 + +/* Memory management relocation checks (PDP-15 KT15 and XVM only) */ + +#define REL_C -1 /* console */ +#define REL_R 0 /* read */ +#define REL_W 1 /* write */ + /* Architectural constants */ #define DMASK 0777777 /* data mask */ @@ -165,6 +201,39 @@ #define IOT_REASON (1 << IOT_V_REASON) #define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ + +/* PC change queue */ + +#define PCQ_SIZE 64 /* must be 2**n */ +#define PCQ_MASK (PCQ_SIZE - 1) +#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC + +/* XVM memory management registers */ + +#define MM_RDIS 0400000 /* reloc disabled */ +#define MM_V_GM 15 /* G mode */ +#define MM_M_GM 03 +#define MM_GM (MM_M_GM << MM_V_GM) +#define MM_G_W0 0077777 /* virt addr width */ +#define MM_G_W1 0177777 +#define MM_G_W2 0777777 +#define MM_G_W3 0377777 +#define MM_G_B0 0060000 /* SAS base */ +#define MM_G_B1 0160000 +#define MM_G_B2 0760000 +#define MM_G_B3 0360000 +#define MM_UIOT 0040000 /* user mode IOT's */ +#define MM_WP 0020000 /* share write prot */ +#define MM_SH 0010000 /* share enabled */ +#define MM_V_SLR 10 /* segment length reg */ +#define MM_M_SLR 03 +#define MM_SLR_L0 001000 /* SAS length */ +#define MM_SLR_L1 002000 +#define MM_SLR_L2 010000 +#define MM_SLR_L3 020000 +#define MM_SBR_MASK 01777 /* share base reg */ +#define MM_GETGM(x) (((x) >> MM_V_GM) & MM_M_GM) +#define MM_GETSLR(x) (((x) >> MM_V_SLR) & MM_M_SLR) /* Device information block */ @@ -239,6 +308,15 @@ typedef struct pdp18b_dib DIB; 37 - */ +#define API_ML0 0200 /* API masks: level 0 */ +#define API_ML1 0100 +#define API_ML2 0040 +#define API_ML3 0020 +#define API_ML4 0010 +#define API_ML5 0004 +#define API_ML6 0002 +#define API_ML7 0001 /* level 7 */ + #define API_HLVL 4 /* hwre levels */ #define ACH_SWRE 040 /* swre int vec */ diff --git a/PDP18B/pdp18b_doc.txt b/PDP18B/pdp18b_doc.txt index 48f47b71..aaa863bd 100644 --- a/PDP18B/pdp18b_doc.txt +++ b/PDP18B/pdp18b_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: 18b PDP Simulator Usage -Date: 01-Feb-2003 +Date: 25-Jul-2003 COPYRIGHT NOTICE @@ -44,29 +44,33 @@ PDP-7/ PDP7 PDP-9/ PDP9 PDP-15/ PDP15 -If no model is specified, the default is the PDP-9. +If no model is specified, the default is the PDP-15. -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tmxr.c + PDP-4 PDP-7 PDP-9 PDP-15 +sim/ sim_defs.h x x x x + sim_rev.h x x x x + sim_sock.h x x x x + sim_tape.h x x + sim_tmxr.h x x x x + scp.c x x x x + scp_tty.c x x x x + sim_sock.c x x x x + sim_tape.c x x + sim_tmxr.c x x x x -sim/pdp18b/ pdp18b_defs.h - pdp18b_cpu.c - pdp18b_drm.c - pdp18b_dt.c - pdp18b_lp.c - pdp18b_mt.c - pdp18b_rb.c - pdp18b_rf.c - pdp18b_rp.c - pdp18b_stddev.c - pdp18b_sys.c - pdp18b_tt1.c +sim/pdp18b/ pdp18b_defs.h x x x x + pdp18b_cpu.c x x x x + pdp18b_drm.c x x + pdp18b_dt.c x x x x + pdp18b_fpp.c x + pdp18b_lp.c x x x x + pdp18b_mt.c x x + pdp18b_rb.c x + pdp18b_rf.c x x + pdp18b_rp.c x + pdp18b_stddev.c x x x x + pdp18b_sys.c x x x x + pdp18b_tt1.c x x 2. 18b PDP Features @@ -77,6 +81,7 @@ system device simulates name(s) PDP-4 CPU PDP-4 CPU with 8KW of memory + - Type 18 extended arithmetic element (EAE) PTR,PTP integral paper tape/Type 75 punch TTI,TTO KSR28 console terminal (Baudot code) LPT Type 62 line printer (Hollerith code) @@ -116,6 +121,9 @@ PDP-15 CPU PDP-15 CPU with 32KW of memory - KA15 automatic priority interrupt (API) - KF15 power detection - KM15 memory protection + - KT15 memory relocation and protection + - XVM memory relocation and protection + FPP FP15 floating point processor PTR,PTP PC15 paper tape reader/punch TTI,TTO KSR 35 console terminal TTI1,TTO1 LT15 second console terminal @@ -145,36 +153,58 @@ The 18b PDP simulators implement several unique stop conditions: - more than XCTMAX nested executes are detected during instruction execution -The PDP-4 and PDP-7 loaders support only RIM format tapes. The PDP-9 -and PDP-15 support both RIM and BIN format tapes. If the file extension -is .RIM, or the -r switch is specified with LOAD, the file is assumed to -be RIM format; if the file extension is not .RIM, or if the -b switch is -specified, the file is assumed to be BIN format. RIM loading requires -that the loading address be specified on the command line. +The PDP-4 and PDP-7 LOAD command supports only "second stage" RIM format +files (alternating DAC address instructions and data): + + LOAD file load PDP-4/PDP-7 RIM format file + +The PDP-9 and PDP-15 LOAD commands upports hardware RIM format (data only), +PDP-4/PDP-7 RIM loader format (for compatability with Macro7), and BIN +loader format: + + LOAD -S file load PDP-4/PDP-7 RIM format file + LOAD -R file address load PDP-9/PDP-15 RIM format + file starting at address + LOAD file.RIM address assume file is PDP-9/PDP-15 + RIM format + LOAD -B file load PDP-9/PDP-15 BIN format file + LOAD file.BIN assume file is PDP-9/PDP-15 + BIN format + +If no address is given for a RIM format load, a starting address of 200 +(octal) is assumed. If no switch is specified, and the file extension is +neither RIM nor BIN, the file format is assumed to be BIN. 2.1 CPU -The CPU options are the presence of the EAE, the presense of the API (for -the PDP-9 and PDP-15), and the size of main memory. +The CPU options are the presence of the EAE, the presense of the API and +memory protection (for the PDP-9 and PDP-15), the presense of relocation +or XVM (PDP-15 only), and the size of main memory. - SET CPU EAE enable EAE - SET CPU NOEAE disable EAE - SET CPU API enable API - SET CPU NOAPI disable API - 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 20K set memory size = 20K - SET CPU 24K set memory size = 24K - SET CPU 28K set memory size = 28K - SET CPU 32K set memory size = 32K - SET CPU 48K set memory size = 48K - SET CPU 64K set memory size = 64K - SET CPU 80K set memory size = 80K - SET CPU 96K set memory size = 96K - SET CPU 112K set memory size = 112K - SET CPU 128K set memory size = 128K + system option comment + + all SET CPU EAE enable EAE + all SET CPU NOEAE disable EAE + 9,15 SET CPU API enable API + 9,15 SET CPU NOAPI disable API + 9,15 SET CPU PROT enable memory protection + 15 SET CPU RELOC enable memory relocation + 15 SET CPU XVM enable XVM relocation + 9,15 SET CPU NOPROT disable protection, relocation, XVM + 4 SET CPU 4K set memory size = 4K + all SET CPU 8K set memory size = 8K + all SET CPU 12K set memory size = 12K + all SET CPU 16K set memory size = 16K + all SET CPU 20K set memory size = 20K + all SET CPU 24K set memory size = 24K + all SET CPU 28K set memory size = 28K + all SET CPU 32K set memory size = 32K + 15 SET CPU 48K set memory size = 48K + 15 SET CPU 64K set memory size = 64K + 15 SET CPU 80K set memory size = 80K + 15 SET CPU 96K set memory size = 96K + 15 SET CPU 112K set memory size = 112K + 15 SET CPU 128K set memory size = 128K Memory sizes greater than 8K are only available on the PDP-7, PDP-9, and PDP-15; memory sizes greater than 32KW are only available on the PDP-15. @@ -183,6 +213,12 @@ non-zero data, the simulator asks for confirmation. Data in the truncated portion of memory is lost. Initial memory size is 8K for the PDP-4, 32K for the PDP-7 and PDP-9, and 128K for the PDP-15. +The PROT option corresponds to the KX09A on the PDP-9 and the KM15 for the +PDP-15. The PROT option is required to run the Foreground/Background +Monitor. The RELOC option corresponds to the KT15 on the PDP-15, and the +XVM option corresponds to the XM15 on the PDP-15. ADSS-15, ADSS-15 Foreground/ +Background, and standard DOS-15 will run if these options are enabled. + CPU registers include the visible state of the processor as well as the control registers for the interrupt system. @@ -191,10 +227,11 @@ control registers for the interrupt system. all PC addr program counter all AC 18 accumulator all L 1 link - 7,9,15 MQ 18 multiplier-quotient - 7,9,15 SC 6 shift counter - 7,9,15 EAE_AC_SIGN 1 EAE AC sign + all MQ 18 multiplier-quotient + all SC 6 shift counter + all EAE_AC_SIGN 1 EAE AC sign all SR 18 front panel switches + all ASW addr address switches for RIM load all INT[0:4] 32 interrupt requests, 0:3 = API levels 0-3 4 = PI level @@ -204,12 +241,15 @@ control registers for the interrupt system. 9,15 APIENB 1 API enable 9,15 APIREQ 8 API requesting levels 9,15 APIACT 8 API active levels - 9,15 BR addr memory protection bounds + 9,15 BR 18 memory protection bounds 15 XR 18 index register 15 LR 18 limit register - 15 BR 17 memory protection bounds + 9,15 BR 18 memory protection bounds + 15 RR 18 memory protection relocation + 15 MMR 18 memory protection control 9,15 USMD 1 user mode 9,15 USMDBUF 1 user mode buffer + 9,15 USMDDEF 1 user mode load defer 9,15 NEXM 1 non-existent memory violation 9,15 PRVN 1 privilege violation 7,9 EXTM 1 extend mode @@ -229,18 +269,49 @@ control registers for the interrupt system. "addr" signifies the address width of the system (13b for the PDP-4, 15b for the PDP-7 and PDP-9, 17b for the PDP-15). -2.2 Programmed I/O Devices +2.2 Floating Point Processor (FPP) -2.2.1 Paper Tape Reader (PTR) +The PDP-15 features an optional floating point processor, the FP15 (FPP). +The FPP can be enabled and disabled; by default it is disabled. + +The FPP implements these registers: + + name size comments + + FIR 12 floating instruction register + EPA 18 EPA (A exponent) + FMAS 1 FMA sign + FMAH 17 FMA<1:17> + FMAL 18 FMA<18:35> + EPB 18 EPB (B exponent) + FMBS 1 FMB sign + FMBH 17 FMB<1:17> + FMBL 18 FMB<18:35> + FGUARD 1 guard bit + FMQH 17 FMQ<1:17> + FMQL 18 FMQ<18:35> + JEA 18 exception address register + +2.3 Programmed I/O Devices + +2.3.1 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. -On the PDP-4 and PDP-7, the paper tape reader supports the BOOT command. -BOOT PTR copies the RIM loader into memory and starts it running, while -BOOT -F PTR copies the funny format binary loader into memory and starts -it running. +The paper tape reader supports the BOOT command. The specific forms +recognized vary from system to system: + + BOOT PTR PDP-4, PDP-7: load RIM loader and start it running + BOOT -F PTR PDP-4, PDP-7: load funny format loader and start + it running + BOOT -H PTR PDP-7: start hardware RIM load at address given + by address switches (ASW) + BOOT {-H} PTR PDP-9, PDP-15: start hardware RIM load at addrss + given by address switches (ASW) + +The PDP-4 did not have a hardware read-in mode load capability. The PTR ATTACH command recognizes one switch, -A for ASCII mode. In ASCII mode, data returned by the read alphabetic command has even parity. @@ -270,7 +341,7 @@ Error handling is as follows: OS I/O error x report error and stop -2.2.2 Paper Tape Punch (PTP) +2.3.2 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. @@ -302,7 +373,7 @@ Error handling is as follows: OS I/O error x report error and stop -2.2.3 Terminal Input (TTI) +2.3.3 Terminal Input (TTI) On the PDP-7, PDP-9, and PDP-15, the terminal interfaces (TTI, TTO) can be set to one of three modes: KSR, 7B, or 8B. In KSR mode, lower @@ -333,7 +404,7 @@ to simulate typing ^C: SET TTI CTRL-C -2.2.4 Terminal Output (TTO) +2.3.4 Terminal Output (TTO) The terminal output (TTO) writes to the simulator console window. It implements these registers: @@ -346,7 +417,7 @@ implements these registers: POS 32 number of chararacters output TIME 24 time from I/O initiation to interrupt -2.2.5 Line Printers (LPT, LP9) +2.3.5 Line Printers (LPT, LP9) The line printers (LPT, LP9) write data to a disk file. The POS register specifies the number of the next data item to be written. @@ -423,7 +494,7 @@ For all printers, error handling is as follows: OS I/O error x report error and stop -2.2.6 Real-Time Clock (CLK) +2.3.6 Real-Time Clock (CLK) The real-time clock (CLK) frequency can be adjusted as follows: @@ -444,7 +515,7 @@ The clock implements these registers: The real-time clock autocalibrates; the clock interval is adjusted up or down so that the clock tracks actual elapsed time. -2.2.7 Second Terminal (TTI1, TTO1) +2.3.7 Second Terminal (TTI1, TTO1) The second terminal consists of two independent devices, TTI1 and TTO1. The second terminal performs input and output through a Telnet session @@ -491,7 +562,7 @@ The second terminal output implements these registers: DONE 1 device done flag TIME 24 time from I/O initiation to interrupt -2.3 RP15/RP02 Disk Pack (RP) +2.4 RP15/RP02 Disk Pack (RP) RP15 options include the ability to make units write enabled or write locked: @@ -526,7 +597,7 @@ Error handling is as follows: OS I/O error x report error and stop -2.4 Type 24 Serial Drum (DRM) +2.5 Type 24 Serial Drum (DRM) The serial drum (DRM) implements these registers: @@ -551,7 +622,7 @@ Error handling is as follows: Drum data files are buffered in memory; therefore, end of file and OS I/O errors cannot occur. -2.5 RB09 Fixed Head Disk (RB) +2.6 RB09 Fixed Head Disk (RB) The RB09 was an early fixed-head disk for the PDP-9. It was superceded by the RF09/RS09. It is disabled by default. @@ -585,7 +656,7 @@ Error handling is as follows: RB09 data files are buffered in memory; therefore, end of file and OS I/O errors cannot occur. -2.5 RF09/RF15/RS09 Fixed Head Disk (RF) +2.7 RF09/RF15/RS09 Fixed Head Disk (RF) RF09/RF15 options include the ability to set the number of platters to a fixed value between 1 and 8, or to autosize the number of platters @@ -632,7 +703,7 @@ Error handling is as follows: RF15/RF09 data files are buffered in memory; therefore, end of file and OS I/O errors cannot occur. -2.6 Type 550/555, TC02/TU55, and TC15/TU56 DECtape (DT) +2.8 Type 550/555, TC02/TU55, and TC15/TU56 DECtape (DT) The PDP-4 and PDP-7 use the Type 550 DECtape, a programmed I/O controller. The PDP-9 uses the TC02, and the PDP-15 uses the TC15. The TC02 and TC15 @@ -693,7 +764,7 @@ operate correctly. - ACTIME must be less than DCTIME, and both need to be at least 100 times LTIME -2.7 TC59/TU10 Magnetic Tape (MT) +2.9 TC59/TU10 Magnetic Tape (MT) Magnetic tape options include the ability to make units write enabled or or write locked. @@ -727,7 +798,7 @@ Error handling is as follows: OS I/O error parity error; if STOP_IOE, stop -2.8 Symbolic Display and Input +2.10 Symbolic Display and Input The 18b PDP simulators implement symbolic display and input. Display is controlled by command line switches: @@ -754,15 +825,18 @@ The PDP-15 also recognizes an additional input mode: # or -p five character packed ASCII string in two 18b words -Instruction input uses standard 18b PDP assembler syntax. There are six +Instruction input uses standard 18b PDP assembler syntax. There are eight instruction classes: memory reference, EAE, index (PDP-15 only), IOT, -operate, and LAW. +operate, LAW, FP15 memory reference (PDP-15 only), and FP15 no operand +(PDP-15 only). Memory reference instructions have the format - memref {I/@} address{,X} + PDP-4, PDP-7: memref {I} address + PDP-9: memref{*} address + PDP-15: memref{*} address{,X} -where I (PDP-4, PDP-7, PDP-9) /@ (PDP-15) signifies indirect reference, +where I (PDP-4, PDP-7) /* (PDP-9, PDP-15) signifies indirect reference, and X signifies indexing (PDP-15 in page mode only). The address is an octal number in the range 0 - 017777 (PDP-4, PDP-7, PDP-9, and PDP-15 in bank mode) or 0 - 07777 (PDP-15 in page mode). @@ -805,13 +879,27 @@ Operate instructions have the format The simulator does not check the legality of the proposed combination. The operands for MUY and DVI must be deposited explicitly. -Finally, the LAW instruction has the format +The LAW instruction has the format LAW immediate where immediate is in the range of 0 to 017777. -2.9 Character Sets +FP15 memory reference instructions occupy two successive words and have +the format + + fpmem{*} address + +where * signifies indirect addressing. The address is a number in the range +0 - 0377777. + +FP15 no operand instructions occupy two successive words and have the format + + fpop + +The second word is ignored on output and set to 0 on input. + +2.11 Character Sets The PDP-4's console was an ASR-28 Teletype; its character encoding was Baudot. The PDP-4's line printer used a modified Hollerith character diff --git a/PDP18B/pdp18b_drm.c b/PDP18B/pdp18b_drm.c index fd882a67..4c3b917f 100644 --- a/PDP18B/pdp18b_drm.c +++ b/PDP18B/pdp18b_drm.c @@ -221,10 +221,10 @@ static const int32 boot_rom[] = { t_stat drm_boot (int32 unitno, DEVICE *dptr) { int32 i; -extern int32 saved_PC; +extern int32 PC; if (drm_dib.dev != DEV_DRM) return STOP_NONSTD; /* non-std addr? */ for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; +PC = BOOT_START; return SCPE_OK; } diff --git a/PDP18B/pdp18b_dt.c b/PDP18B/pdp18b_dt.c index 8224ad5a..1a5620ae 100644 --- a/PDP18B/pdp18b_dt.c +++ b/PDP18B/pdp18b_dt.c @@ -327,8 +327,8 @@ static const int32 map_unit[16] = { /* Type 550 unit map */ 0, -1, -1, -1, -1, -1, -1, -1 }; DEVICE dt_dev; -int32 dt75 (int32 pulse, int32 AC); -int32 dt76 (int32 pulse, int32 AC); +int32 dt75 (int32 pulse, int32 dat); +int32 dt76 (int32 pulse, int32 dat); int32 dt_iors (void); t_stat dt_svc (UNIT *uptr); t_stat dt_reset (DEVICE *dptr); @@ -423,18 +423,18 @@ DEVICE dt_dev = { /* IOT routines */ #if defined (TC02) /* TC02/TC15 */ -int32 dt75 (int32 pulse, int32 AC) +int32 dt75 (int32 pulse, int32 dat) { int32 old_dtsa = dtsa, fnc; UNIT *uptr; if (((pulse & 060) == 040) && (pulse & 05)) { /* select */ if (pulse & 01) dtsa = 0; /* DTCA */ - if (pulse & 02) AC = dtsa; /* DTRA!... */ + if (pulse & 02) dat = dtsa; /* DTRA!... */ if (pulse & 04) { /* DTXA */ - if ((AC & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; - if ((AC & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; - dtsa = dtsa ^ (AC & DTA_RW); } + if ((dat & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; + if ((dat & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; + dtsa = dtsa ^ (dat & DTA_RW); } if ((old_dtsa ^ dtsa) & DTA_UNIT) dt_deselect (old_dtsa); uptr = dt_dev.units + DTA_GETUNIT (dtsa); /* get unit */ fnc = DTA_GETFNC (dtsa); /* get fnc */ @@ -445,41 +445,41 @@ if (((pulse & 060) == 040) && (pulse & 05)) { /* select */ dt_seterr (uptr, DTB_SEL); /* select err */ else dt_newsa (dtsa); /* new func */ DT_UPDINT; - return AC; } + return dat; } if ((pulse & 067) == 042) return dtsa; /* DTRA */ if ((pulse & 067) == 061) /* DTEF */ - return ((dtsb & DTB_ERF)? IOT_SKP + AC: AC); + return ((dtsb & DTB_ERF)? IOT_SKP + dat: dat); if ((pulse & 067) == 062) return dtsb; /* DTRB */ if ((pulse & 067) == 063) /* DTEF!DTRB */ return ((dtsb & DTB_ERF)? IOT_SKP + dtsb: dtsb); -return AC; +return dat; } -int32 dt76 (int32 pulse, int32 AC) +int32 dt76 (int32 pulse, int32 dat) { if ((pulse & 01) && (dtsb & DTB_DTF)) /* DTDF */ - return IOT_SKP + AC; -return AC; + return IOT_SKP + dat; +return dat; } #else /* Type 550 */ -int32 dt75 (int32 pulse, int32 AC) +int32 dt75 (int32 pulse, int32 dat) { if (((pulse & 041) == 001) && (dtsb & DTB_DTF)) /* MMDF */ - AC = AC | IOT_SKP; + dat = dat | IOT_SKP; else if (((pulse & 041) == 041) && (dtsb & DTB_ERF)) /* MMEF */ - AC = AC | IOT_SKP; + dat = dat | IOT_SKP; if (pulse & 002) { /* MMRD */ - AC = (AC & ~DMASK) | dtdb; + dat = (dat & ~DMASK) | dtdb; dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } if (pulse & 004) { /* MMWR */ - dtdb = AC & DMASK; + dtdb = dat & DMASK; dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } DT_UPDINT; -return AC; +return dat; } -int32 dt76 (int32 pulse, int32 AC) +int32 dt76 (int32 pulse, int32 dat) { int32 fnc, mot, unum; UNIT *uptr = NULL; @@ -487,7 +487,7 @@ UNIT *uptr = NULL; unum = DTA_GETUNIT (dtsa); /* get unit no */ if (unum >= 0) uptr = dt_dev.units + unum; /* get unit */ if ((pulse & 001) && (dtsb & DTB_BEF)) /* MMBF */ - AC = AC | IOT_SKP; + dat = dat | IOT_SKP; if (pulse & 002) { /* MMRS */ dtsb = dtsb & ~(DTB_REV | DTB_GO); /* clr rev, go */ if (uptr) { /* valid unit? */ @@ -495,13 +495,13 @@ if (pulse & 002) { /* MMRS */ if (mot & DTS_DIR) dtsb = dtsb | DTB_REV; /* rev? set */ if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700)) dtsb = dtsb | DTB_GO; } /* accel? go */ - AC = (AC & ~DMASK) | dtsb; } + dat = (dat & ~DMASK) | dtsb; } if ((pulse & 044) == 044) { /* MMSE */ - if ((dtsa ^ AC) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ - dtsa = (dtsa & ~DTA_UNIT) | (AC & DTA_UNIT); + if ((dtsa ^ dat) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ + dtsa = (dtsa & ~DTA_UNIT) | (dat & DTA_UNIT); dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); } else if ((pulse & 044) == 004) { /* MMLC */ - dtsa = (dtsa & ~DTA_RW) | (AC & DTA_RW); /* load dtsa */ + dtsa = (dtsa & ~DTA_RW) | (dat & DTA_RW); /* load dtsa */ dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); fnc = DTA_GETFNC (dtsa); /* get fnc */ if ((uptr == NULL) || /* invalid? */ @@ -512,7 +512,7 @@ else if ((pulse & 044) == 004) { /* MMLC */ dt_seterr (uptr, DTB_SEL); /* select err */ else dt_newsa (dtsa); } DT_UPDINT; -return AC; +return dat; } #endif @@ -836,7 +836,7 @@ case FNC_SRCH: /* search */ return SCPE_OK; } sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */ M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* inc WC */ - ma = M[DT_CA] & ADDRMASK; /* get mem addr */ + ma = M[DT_CA] & AMASK; /* get mem addr */ if (MEM_ADDR_OK (ma)) M[ma] = blk; /* store block # */ if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) dtsb = dtsb | DTB_DTF; /* set DTF */ @@ -870,7 +870,7 @@ case FNC_READ: /* read */ case 0: /* normal read */ M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ M[DT_CA] = (M[DT_CA] + 1) & DMASK; - ma = M[DT_CA] & ADDRMASK; /* mem addr */ + ma = M[DT_CA] & AMASK; /* mem addr */ ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ dtdb = bptr[ba]; /* get tape word */ if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ @@ -920,7 +920,7 @@ case FNC_WRIT: /* write */ M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ M[DT_CA] = (M[DT_CA] + 1) & DMASK; case DTO_WCO: /* wc ovflo */ - ma = M[DT_CA] & ADDRMASK; /* mem addr */ + ma = M[DT_CA] & AMASK; /* mem addr */ ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ dtdb = dt_substate? 0: M[ma]; /* get word */ if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */ @@ -955,7 +955,7 @@ case FNC_RALL: relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ M[DT_CA] = (M[DT_CA] + 1) & DMASK; - ma = M[DT_CA] & ADDRMASK; /* mem addr */ + ma = M[DT_CA] & AMASK; /* mem addr */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { wrd = DT_LIN2WD (uptr->pos, uptr); @@ -989,7 +989,7 @@ case FNC_WALL: relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */ M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */ M[DT_CA] = (M[DT_CA] + 1) & DMASK; - ma = M[DT_CA] & ADDRMASK; /* mem addr */ + ma = M[DT_CA] & AMASK; /* mem addr */ if ((relpos >= DT_HTLIN) && /* in data zone? */ (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { dtdb = M[ma]; /* get mem word */ @@ -1122,7 +1122,7 @@ return; int32 dt_comobv (int32 dat) { -dat = dat ^ 0777777; /* compl obverse */ +dat = dat ^ DMASK; /* compl obverse */ dat = ((dat >> 15) & 07) | ((dat >> 9) & 070) | ((dat >> 3) & 0700) | ((dat & 0700) << 3) | ((dat & 070) << 9) | ((dat & 07) << 15); @@ -1140,16 +1140,16 @@ int32 i, csum, wrd; #if defined (TC02) /* TC02/TC15 */ csum = 077; /* init csum */ for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i] ^ 0777777; /* get ~word */ + wrd = bptr[ba + i] ^ DMASK; /* get ~word */ csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; } return (csum & 077); #else /* Type 550 */ -csum = 0777777; +csum = DMASK; for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ wrd = bptr[ba + i]; /* get word */ csum = csum + wrd; /* 1's comp add */ - if (csum > 0777777) csum = (csum + 1) & 0777777; } -return (csum ^ 0777777); /* 1's comp res */ + if (csum > DMASK) csum = (csum + 1) & DMASK; } +return (csum ^ DMASK); /* 1's comp res */ #endif } @@ -1164,7 +1164,7 @@ if (wrd == DT_BLKWD) return blk; /* fwd blknum */ if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ return (dt_csum (uptr, blk) << 12); #else -if (wrd == DT_CSMWD) return 0777777; /* rev csum */ +if (wrd == DT_CSMWD) return DMASK; /* rev csum */ if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ return (dt_csum (uptr, blk)); #endif /* Type 550 */ diff --git a/PDP18B/pdp18b_fpp.c b/PDP18B/pdp18b_fpp.c new file mode 100644 index 00000000..8b52467b --- /dev/null +++ b/PDP18B/pdp18b_fpp.c @@ -0,0 +1,774 @@ +/* pdp18b_fpp.c: FP15 floating point processor simulator + + Copyright (c) 2003, 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. + + fpp PDP-15 floating point processor + + The FP15 instruction format is: + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 1 1 1 0 0 1| subop | microcoded modifiers | floating point + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |in| address | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + Indirection is always single level. + + The FP15 supports four data formats: + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | S| 2's complement integer | A: integer + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | S| 2's complement integer (high) | A: extended integer + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 2's complement integer (low) | A+1 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | fraction (low) |SE|2's complement exponent| A: single floating + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |SF| fraction (high) | A+1 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |SE| 2's complement exponent | A: double floating + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |SF| fraction (high) | A+1 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | fraction (low) | A+2 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + +*/ + +#include "pdp18b_defs.h" + +/* Instruction */ + +#define FI_V_OP 8 /* subopcode */ +#define FI_M_OP 017 +#define FI_GETOP(x) (((x) >> FI_V_OP) & FI_M_OP) +#define FI_NOLOAD 0200 /* don't load */ +#define FI_DP 0100 /* single/double */ +#define FI_FP 0040 /* int/flt point */ +#define FI_NONORM 0020 /* don't normalize */ +#define FI_NORND 0010 /* don't round */ +#define FI_V_SGNOP 0 /* A sign change */ +#define FI_M_SGNOP 03 +#define FI_GETSGNOP(x) (((x) >> FI_V_SGNOP) & FI_M_SGNOP) + +/* Exception register */ + +#define JEA_V_SIGN 17 /* A sign */ +#define JEA_V_GUARD 16 /* guard */ +#define JEA_EAMASK 077777 /* exc address */ +#define JEA_OFF_OVF 0 /* ovf offset */ +#define JEA_OFF_UNF 2 /* unf offset */ +#define JEA_OFF_DIV 4 /* div offset */ +#define JEA_OFF_MM 6 /* mem mgt offset */ + +/* Status codes - must relate directly to JEA offsets */ + +#define FP_OK 0 /* no error - mbz */ +#define FP_OVF (JEA_OFF_OVF + 1) /* overflow */ +#define FP_UNF (JEA_OFF_UNF + 1) /* underflow */ +#define FP_DIV (JEA_OFF_DIV + 1) /* divide exception */ +#define FP_MM (JEA_OFF_MM + 1) /* mem mgt error */ + +/* Unpacked floating point fraction */ + +#define UFP_FH_CARRY 0400000 /* carry out */ +#define UFP_FH_NORM 0200000 /* normalized */ +#define UFP_FH_MASK 0377777 /* hi mask */ +#define UFP_FL_MASK 0777777 /* low mask */ +#define UFP_FL_SMASK 0777000 /* low mask, single */ +#define UFP_FL_SRND 0000400 /* round bit, single */ + +#define GET_SIGN(x) (((x) >> 17) & 1) +#define SEXT18(x) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)) +#define SEXT9(x) (((x) & 0400)? ((x) | ~0377): ((x) & 0377)) + +enum fop { + FOP_TST, FOP_SUB, FOP_RSUB, FOP_MUL, + FOP_DIV, FOP_RDIV, FOP_LD, FOP_ST, + FOP_FLT, FOP_FIX, FOP_LFMQ, FOP_JEA, + FOP_ADD, FOP_BR, FOP_DIAG, FOP_UND }; + +struct ufp { + int32 exp; /* exponent */ + int32 sign; /* sign */ + int32 hi; /* hi frac, 17b */ + int32 lo; }; /* lo frac, 18b */ + +typedef struct ufp UFP; + +static int32 fir; /* instruction */ +static int32 jea; /* exc address */ +static int32 fguard; /* guard bit */ +static UFP fma; /* FMA */ +static UFP fmb; /* FMB */ +static UFP fmq; /* FMQ - hi,lo only */ + +extern int32 M[MAXMEMSIZE]; +extern int32 pcq[PCQ_SIZE]; +extern int32 pcq_p; +extern int32 PC; +extern int32 trap_pending, usmd; + +t_stat fp15_reset (DEVICE *dptr); +t_stat fp15_opnd (int32 ir, int32 addr, UFP *a); +t_stat fp15_store (int32 ir, int32 addr, UFP *a); +t_stat fp15_iadd (int32 ir, UFP *a, UFP *b, t_bool sub); +t_stat fp15_imul (int32 ir, UFP *a, UFP *b); +t_stat fp15_idiv (int32 ir, UFP *a, UFP *b); +t_stat fp15_fadd (int32 ir, UFP *a, UFP *b, t_bool sub); +t_stat fp15_fmul (int32 ir, UFP *a, UFP *b); +t_stat fp15_fdiv (int32 ir, UFP *a, UFP *b); +t_stat fp15_fix (int32 ir, UFP *a); +t_stat fp15_norm (int32 ir, UFP *a, UFP *b, t_bool rnd); +t_stat fp15_exc (int32 sta); +void fp15_asign (int32 ir, UFP *a); +void dp_add (UFP *a, UFP *b); +void dp_sub (UFP *a, UFP *b); +void dp_inc (UFP *a); +int32 dp_cmp (UFP *a, UFP *b); +void dp_mul (UFP *a, UFP *b); +void dp_lsh_1 (UFP *a, UFP *b); +void dp_rsh_1 (UFP *a, UFP *b); +void dp_dnrm_r (int32 ir, UFP *a, int32 sc); +void dp_swap (UFP *a, UFP *b); + +extern t_stat Read (int32 ma, int32 *dat, int32 cyc); +extern t_stat Write (int32 ma, int32 dat, int32 cyc); +extern t_stat Ia (int32 ma, int32 *ea, t_bool jmp); +extern int32 Incr_addr (int32 addr); +extern int32 Jms_word (int32 t); + +/* FPP data structures + + fpp_dev FPP device descriptor + fpp_unit FPP unit + fpp_reg FPP register list + fpp_mod FPP modifier list +*/ + +UNIT fpp_unit = { UDATA (NULL, 0, 0) }; + +REG fpp_reg[] = { + { ORDATA (FIR, fir, 12) }, + { ORDATA (EPA, fma.exp, 18) }, + { FLDATA (FMAS, fma.sign, 0) }, + { ORDATA (FMAH, fma.hi, 17) }, + { ORDATA (FMAL, fma.lo, 18) }, + { ORDATA (EPB, fmb.exp, 18) }, + { FLDATA (FMBS, fmb.sign, 0) }, + { ORDATA (FMBH, fmb.hi, 17) }, + { ORDATA (FMBL, fmb.lo, 18) }, + { FLDATA (FGUARD, fguard, 0) }, + { ORDATA (FMQH, fmq.hi, 17) }, + { ORDATA (FMQL, fmq.lo, 18) }, + { ORDATA (JEA, jea, 18) }, + { NULL } }; + +DEVICE fpp_dev = { + "FPP", &fpp_unit, fpp_reg, NULL, + 1, 8, 1, 1, 8, 18, + NULL, NULL, &fp15_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE | DEV_DIS }; + +/* Instruction decode for FP15 + + The CPU actually fetches the instruction and the word after. If the + instruction is 71XXXX, the CPU executes it as a NOP, and the FP15 fools + the CPU into thinking that the second word is also a NOP. + + Indirect addresses are resolved during fetch, unless the NOLOAD modifier + is set and the instruction is not a store. */ + +t_stat fp15 (int32 ir) +{ +int32 ar, ma, fop, dat; +t_stat sta = FP_OK; + +if (fpp_dev.flags & DEV_DIS) return MM_OK; /* disabled? */ +fir = ir & 07777; /* save subop + mods */ +ma = PC; /* fetch next word */ +PC = Incr_addr (PC); +if (Read (ma, &ar, RD)) return fp15_exc (FP_MM); /* error? MM exc */ +fop = FI_GETOP (fir); /* get subopcode */ +if ((ar & SIGN) && /* indirect? */ + ((fop == FOP_ST) || !(ir & FI_NOLOAD))) { /* store or load? */ + ma = ar & AMASK; /* fetch indirect */ + if (Read (ma, &ar, RD)) return fp15_exc (FP_MM); } +fma.exp = SEXT18 (fma.exp); /* sext exponents */ +fmb.exp = SEXT18 (fmb.exp); +switch (fop) { /* case on subop */ + +case FOP_TST: /* NOP */ + break; + +case FOP_SUB: /* subtract */ + if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ + if (fir & FI_FP) sta = fp15_fadd (fir, &fma, &fmb, 1); /* fp? */ + else sta = fp15_iadd (fir, &fma, &fmb, 1); /* no, int sub */ + break; + +case FOP_RSUB: /* reverse sub */ + fmb = fma; /* FMB <- FMA */ + if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ + if (fir & FI_FP) sta = fp15_fadd (fir, &fma, &fmb, 1); /* fp? */ + else sta = fp15_iadd (fir, &fma, &fmb, 1); /* no, int sub */ + break; + +case FOP_MUL: /* multiply */ + if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ + if (fir & FI_FP) sta = fp15_fmul (fir, &fma, &fmb); /* fp? */ + else sta = fp15_imul (fir, &fma, &fmb); /* no, int mul */ + break; + +case FOP_DIV: /* divide */ + if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ + if (fir & FI_FP) sta = fp15_fdiv (fir, &fma, &fmb); /* fp? */ + else sta = fp15_idiv (fir, &fma, &fmb); /* no, int div */ + break; + +case FOP_RDIV: /* reverse divide */ + fmb = fma; /* FMB <- FMA */ + if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ + if (fir & FI_FP) sta = fp15_fdiv (fir, &fma, &fmb); /* fp? */ + else sta = fp15_idiv (fir, &fma, &fmb); /* no, int div */ + break; + +case FOP_LD: /* load */ + if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ + fp15_asign (fir, &fma); /* modify A sign */ + if (fir & FI_FP) /* fp? */ + sta = fp15_norm (ir, &fma, NULL, 0); /* normalize */ + break; + +case FOP_ST: /* store */ + fp15_asign (fir, &fma); /* modify A sign */ + sta = fp15_store (fir, ar, &fma); /* store result */ + break; + +case FOP_FLT: /* float */ + if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ + fma.exp = 35; + fp15_asign (fir, &fma); /* adjust A sign */ + sta = fp15_norm (ir, &fma, NULL, 0); /* normalize */ + break; + +case FOP_FIX: /* fix */ + if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ + sta = fp15_fix (fir, &fma); /* fix */ + break; + +case FOP_LFMQ: /* load FMQ */ + if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ + dp_swap (&fma, &fmq); /* swap FMA, FMQ */ + fp15_asign (fir, &fma); /* adjust A sign */ + if (fir & FI_FP) /* fp? norm, no rnd */ + sta = fp15_norm (ir | FI_NORND, &fma, &fmq, 0); + break; + +case FOP_JEA: /* JEA */ + if (ir & 0200) { /* store? */ + dat = jea | (fma.sign << JEA_V_SIGN) | (fguard << JEA_V_GUARD); + sta = Write (ar, dat, WR); } + else { /* no, load */ + if (sta = Read (ar, &dat, RD)) break; + fguard = (dat >> JEA_V_GUARD) & 1; + jea = dat; } + break; + +case FOP_ADD: /* add */ + if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ + if (fir & FI_FP) sta = fp15_fadd (fir, &fma, &fmb, 0); /* fp? */ + else sta = fp15_iadd (fir, &fma, &fmb, 0); /* no, int add */ + break; + +case FOP_BR: /* branch */ + if (((fir & 001) && ((fma.hi | fma.lo) == 0)) || + ((fir & 002) && fma.sign) || + ((fir & 004) && !fma.sign) || + ((fir & 010) && ((fma.hi | fma.lo) != 0)) || + ((fir & 020) && fguard)) { /* cond met? */ + PCQ_ENTRY; /* save current PC */ + PC = (PC & BLKMASK) | (ar & IAMASK); } /* branch within 32K */ + break; + +default: + break; } + +fma.exp = fma.exp & DMASK; /* mask exp to 18b */ +fmb.exp = fmb.exp & DMASK; +if (sta != FP_OK) return fp15_exc (sta); /* error? */ +return MM_OK; +} + +/* Operand load and store */ + +t_stat fp15_opnd (int32 ir, int32 addr, UFP *fpn) +{ +int32 i, numwd, wd[3]; + +fguard = 0; /* clear guard */ +if (ir & FI_NOLOAD) return FP_OK; /* no load? */ +if (ir & FI_FP) numwd = 2; /* fp? at least 2 */ +else numwd = 1; /* else at least 1 */ +if (ir & FI_DP) numwd = numwd + 1; /* dp? 1 more */ +for (i = 0; i < numwd; i++) { /* fetch words */ + if (Read (addr, &wd[i], RD)) return FP_MM; + addr = (addr + 1) & AMASK; } +if (ir & FI_FP) { /* fp? */ + fpn->sign = GET_SIGN (wd[1]); /* frac sign */ + fpn->hi = wd[1] & UFP_FH_MASK; /* frac high */ + if (ir & FI_DP) { /* dp? */ + fpn->exp = SEXT18 (wd[0]); /* exponent */ + fpn->lo = wd[2]; } /* frac low */ + else { /* sp */ + fpn->exp = SEXT9 (wd[0]); /* exponent */ + fpn->lo = wd[0] & UFP_FL_SMASK; } /* frac low */ + } +else { fpn->sign = GET_SIGN (wd[0]); /* int, get sign */ + if (ir & FI_DP) { /* dp? */ + fpn->lo = wd[1]; /* 2 words */ + fpn->hi = wd[0]; } + else { /* single */ + fpn->lo = wd[0]; /* 1 word */ + fpn->hi = fpn->sign? DMASK: 0; } /* sign extended */ + if (fpn->sign) { /* negative? */ + fpn->lo = (-fpn->lo) & UFP_FL_MASK; /* take abs val */ + fpn->hi = (~fpn->hi + (fpn->lo == 0)) & UFP_FH_MASK; } + } +return FP_OK; +} + +t_stat fp15_store (int32 ir, int32 addr, UFP *a) +{ +int32 i, numwd, wd[3]; +t_stat sta; + +fguard = 0; /* clear guard */ +if (ir & FI_FP) { /* fp? */ + if (sta = fp15_norm (ir, a, NULL, 0)) return sta; /* normalize */ + wd[1] = (a->sign << 17) | a->hi; /* hi frac */ + if (ir & FI_DP) { /* dp? */ + numwd = 3; /* 3 words */ + wd[0] = a->exp & DMASK; /* exponent */ + wd[2] = a->lo; } /* low frac */ + else { /* single */ + if (!(ir & FI_NORND) && (a->lo & UFP_FL_SRND)) { /* round? */ + a->lo = (a->lo + UFP_FL_SRND) & UFP_FL_SMASK; + a->hi = (a->hi + (a->lo == 0)) & UFP_FH_MASK; + if ((a->hi | a->lo) == 0) { /* carry out? */ + a->hi = UFP_FH_NORM; /* shift back */ + a->exp = a->exp + 1; } } + if (a->exp > 0377) return FP_OVF; /* sp ovf? */ + if (a->exp < -0400) return FP_UNF; /* sp unf? */ + numwd = 2; /* 2 words */ + wd[0] = (a->exp & 0777) | a->lo; } /* low frac'exp */ + } +else { fmb.lo = (-a->lo) & UFP_FL_MASK; /* 2's complement */ + fmb.hi = (~a->hi + (fmb.lo == 0)) & UFP_FH_MASK;/* to FMB */ + if (ir & FI_DP) { /* dp? */ + numwd = 2; /* 2 words */ + if (a->sign) { /* negative? */ + wd[0] = fmb.hi | SIGN; /* store FMB */ + wd[1] = fmb.lo; } + else { /* pos, store FMA */ + wd[0] = a->hi; + wd[1] = a->lo; } } + else { /* single */ + if (a->hi || (a->lo & SIGN)) return FP_OVF; /* check int ovf */ + numwd = 1; /* 1 word */ + if (a->sign) wd[0] = fmb.lo; /* neg? store FMB */ + else wd[0] = a->lo; } /* pos, store FMA */ + } +for (i = 0; i < numwd; i++) { /* store words */ + if (Write (addr, wd[i], WR)) return FP_MM; + addr = (addr + 1) & AMASK; } +return FP_OK; +} + +/* Integer arithmetic routines */ + +/* Integer add - overflow only on add, if carry out of high fraction */ + +t_stat fp15_iadd (int32 ir, UFP *a, UFP *b, t_bool sub) +{ +fmq.hi = fmq.lo = 0; /* clear FMQ */ +if (a->sign ^ b->sign ^ sub) dp_sub (a, b); /* eff subtract? */ +else { dp_add (a, b); /* no, add */ + if (a->hi & UFP_FH_CARRY) { /* carry out? */ + a->hi = a->hi & UFP_FH_MASK; /* mask to 35b */ + return FP_OVF; } } /* overflow */ +fp15_asign (ir, a); /* adjust A sign */ +return FP_OK; +} + +/* Integer multiply - overflow if high result (FMQ after swap) non-zero */ + +t_stat fp15_imul (int32 ir, UFP *a, UFP *b) +{ +a->sign = a->sign ^ b->sign; /* sign of result */ +dp_mul (a, b); /* a'FMQ <- a * b */ +dp_swap (a, &fmq); /* swap a, FMQ */ +if (fmq.hi | fmq.lo) return FP_OVF; /* FMQ != 0? ovf */ +fp15_asign (ir, a); /* adjust A sign */ +return FP_OK; +} + +/* Integer divide - actually done as fraction divide + + - If divisor zero, error + - If dividend zero, done + - Normalize dividend and divisor together + - If divisor normalized but dividend not, result is zero + - If divisor not normalized, normalize and count shifts + - Do fraction divide for number of shifts, +1, steps + + Note that dp_lsh_1 returns a 72b result; the last right shift + guarantees a 71b remainder. The quotient cannot exceed 71b */ + +t_stat fp15_idiv (int32 ir, UFP *a, UFP *b) +{ +int32 i, sc; + +a->sign = a->sign ^ b->sign; /* sign of result */ +fmq.hi = fmq.lo = 0; /* clear quotient */ +a->exp = 0; /* clear a exp */ +if ((b->hi | b->lo) == 0) return FP_DIV; /* div by 0? */ +if ((a->hi | a->lo) == 0) return FP_OK; /* div into 0? */ +while (((a->hi & UFP_FH_NORM) == 0) && /* normalize divd */ + ((b->hi & UFP_FH_NORM) == 0)) { /* and divr */ + dp_lsh_1 (a, NULL); /* lsh divd, divr */ + dp_lsh_1 (b, NULL); } /* can't carry out */ +if (!(a->hi & UFP_FH_NORM) && (b->hi & UFP_FH_NORM)) { /* divr norm, divd not? */ + a->hi = a->lo = 0; /* result is 0 */ + return FP_OK; } +while ((b->hi & UFP_FH_NORM) == 0) { /* normalize divr */ + dp_lsh_1 (b, NULL); /* can't carry out */ + a->exp = a->exp + 1; } /* count steps */ +sc = a->exp; +for (i = 0; i <= sc; i++) { /* n+1 steps */ + dp_lsh_1 (&fmq, NULL); /* left shift quo */ + if (dp_cmp (a, b) >= 0) { /* sub work? */ + dp_sub (a, b); /* a -= b */ + if (i == 0) a->exp = a->exp + 1; /* first step? */ + fmq.lo = fmq.lo | 1; } /* set quo bit */ + dp_lsh_1 (a, NULL); } /* left shift divd */ +dp_rsh_1 (a, NULL); /* shift back */ +dp_swap (a, &fmq); /* swap a, FMQ */ +fp15_asign (ir, a); /* adjust A sign */ +return FP_OK; +} + +/* Floating point arithmetic routines */ + +/* Floating add + - Special add case, overflow if carry out increments exp out of range + - All cases, overflow/underflow detected in normalize */ + +t_stat fp15_fadd (int32 ir, UFP *a, UFP *b, t_bool sub) +{ +int32 ediff; + +fmq.hi = fmq.lo = 0; /* clear FMQ */ +ediff = a->exp - b->exp; /* exp diff */ +if (((a->hi | a->lo) == 0) || (ediff < -35)) { /* a = 0 or "small"? */ + *a = *b; /* rslt is b */ + a->sign = a->sign ^ sub; } /* or -b if sub */ +else if (((b->hi | b->lo) != 0) && (ediff <= 35)) { /* b!=0 && ~"small"? */ + if (ediff > 0) dp_dnrm_r (ir, b, ediff); /* |a| > |b|? dnorm b */ + else if (ediff < 0) { /* |a| < |b|? */ + a->exp = b->exp; /* b exp is rslt */ + dp_dnrm_r (ir, a, -ediff); } /* denorm A */ + if (a->sign ^ b->sign ^ sub) dp_sub (a, b); /* eff sub? */ + else { /* eff add */ + dp_add (a, b); /* add */ + if (a->hi & UFP_FH_CARRY) { /* carry out? */ + fguard = a->lo & 1; /* set guard */ + dp_rsh_1 (a, NULL); /* right shift */ + a->exp = a->exp + 1; /* incr exponent */ + if (!(ir & FI_NORND) && fguard) /* rounding? */ + dp_inc (a); + if (a->exp > 0377777) return FP_OVF; } } + } /* end if b != 0 */ +fp15_asign (ir, a); /* adjust A sign */ +return fp15_norm (ir, a, NULL, 0); /* normalize */ +} + +/* Floating multiply - overflow/underflow detected in normalize */ + +t_stat fp15_fmul (int32 ir, UFP *a, UFP *b) +{ +a->sign = a->sign ^ b->sign; /* sign of result */ +a->exp = a->exp + b->exp; /* exp of result */ +dp_mul (a, b); /* mul fractions */ +fp15_asign (ir, a); /* adjust A sign */ +return fp15_norm (ir, a, &fmq, 1); /* norm and round */ +} + +/* Floating divide - overflow/underflow detected in normalize */ + +t_stat fp15_fdiv (int32 ir, UFP *a, UFP *b) +{ +int32 i; + +a->sign = a->sign ^ b->sign; /* sign of result */ +a->exp = a->exp - b->exp; /* exp of result */ +fmq.hi = fmq.lo = 0; /* clear quotient */ +if (!(b->hi & UFP_FH_NORM)) return FP_DIV; /* divr not norm? */ +if (a->hi | a->lo) { /* divd non-zero? */ + fp15_norm (0, a, NULL, 0); /* normalize divd */ + for (i = 0; (fmq.hi & UFP_FH_NORM) == 0; i++) { /* until quo */ + dp_lsh_1 (&fmq, NULL); /* left shift quo */ + if (dp_cmp (a, b) >= 0) { /* sub work? */ + dp_sub (a, b); /* a -= b */ + if (i == 0) a->exp = a->exp + 1; + fmq.lo = fmq.lo | 1; } /* set quo bit */ + dp_lsh_1 (a, NULL); } /* left shift divd */ + dp_rsh_1 (a, NULL); /* shift back */ + dp_swap (a, &fmq); } /* swap a, FMQ */ +fp15_asign (ir, a); /* adjust A sign */ +return fp15_norm (ir, a, &fmq, 1); /* norm and round */ +} + +/* Floating to integer - overflow only if exponent out of range */ + +t_stat fp15_fix (int32 ir, UFP *a) +{ +int32 i; + +fmq.hi = fmq.lo = 0; /* clear FMQ */ +if (a->exp > 35) return FP_OVF; /* exp > 35? ovf */ +if (a->exp < 0) a->hi = a->lo = 0; /* exp <0 ? rslt 0 */ +else { for (i = a->exp; i < 35; i++) /* denorm frac */ + dp_rsh_1 (a, &fmq); + if (fmq.hi & UFP_FH_NORM) { /* last out = 1? */ + fguard = 1; /* set guard */ + if (!(ir & FI_NORND)) dp_inc (a); } } /* round */ +fp15_asign (ir, a); /* adjust A sign */ +return FP_OK; +} + +/* Double precision routines */ + +/* Double precision add - returns 72b result (including carry) */ + +void dp_add (UFP *a, UFP *b) +{ +int32 a_hi_orig = a->hi; + +a->lo = (a->lo + b->lo) & UFP_FL_MASK; /* add low */ +a->hi = a->hi + b->hi + (a->lo < b->lo); /* add hi + carry */ +return; +} + +/* Double precision increment - returns 72b result (including carry) */ + +void dp_inc (UFP *a) +{ +a->lo = (a->lo + 1) & UFP_FL_MASK; /* inc low */ +a->hi = a->hi + (a->lo == 0); /* propagate carry */ +return; +} + +/* Double precision subtract - result always fits in 71b */ + +void dp_sub (UFP *a, UFP *b) +{ +if (dp_cmp (a,b) >= 0) { /* |a| >= |b|? */ + a->hi = (a->hi - b->hi - (a->lo < b->lo)) & UFP_FH_MASK; + a->lo = (a->lo - b->lo) & UFP_FL_MASK; } /* a - b */ +else { a->hi = (b->hi - a->hi - (b->lo < a->lo)) & UFP_FH_MASK; + a->lo = (b->lo - a->lo) & UFP_FL_MASK; /* b - a */ + a->sign = a->sign ^ 1; } /* change a sign */ +return; +} + +/* Double precision compare - returns +1 (>), 0 (=), -1 (<) */ + +int32 dp_cmp (UFP *a, UFP *b) +{ +if (a->hi < b->hi) return -1; +if (a->hi > b->hi) return +1; +if (a->lo < b->lo) return -1; +if (a->lo > b->lo) return +1; +return 0; +} + +/* Double precision multiply - returns 70b result */ + +void dp_mul (UFP *a, UFP *b) +{ +int32 i; + +fmq.hi = a->hi; /* FMQ <- a */ +fmq.lo = a->lo; +a->hi = a->lo = 0; /* a <- 0 */ +if (((fmq.hi | fmq.lo) == 0) || ((b->hi | b->lo) == 0)) return; +for (i = 0; i < 35; i++) { /* 35 iterations */ + if (fmq.lo & 1) dp_add (a, b); /* FMQ<35>? a += b */ + dp_rsh_1 (a, &fmq); } /* rsh a'FMQ */ +return; +} + +/* Double (quad) precision left shift - returns 72b (143b) result */ + +void dp_lsh_1 (UFP *a, UFP *b) +{ +int32 t = b? b->lo: 0; + +a->hi = (a->hi << 1) | (a->lo >> 17); +a->lo = ((a->lo << 1) | (t >> 16)) & UFP_FL_MASK; +if (b) { + b->hi = ((b->hi << 1) | (b->lo >> 17)) & UFP_FH_MASK; + b->lo = (b->lo << 1) & UFP_FL_MASK; } +return; +} + +/* Double (quad) precision right shift - returns 71b (142b) result */ + +void dp_rsh_1 (UFP *a, UFP *b) +{ +if (b) { + b->lo = (b->lo >> 1) | ((b->hi & 1) << 17); + b->hi = (b->hi >> 1) | ((a->lo & 1) << 16); } +a->lo = (a->lo >> 1) | ((a->hi & 1) << 17); +a->hi = a->hi >> 1; +return; +} + +/* Double precision denormalize and round - returns 71b result */ + +void dp_dnrm_r (int32 ir, UFP *a, int32 sc) +{ +int32 i; + +if (sc <= 0) return; /* legit? */ +for (i = 0; i < sc; i++) dp_rsh_1 (a, &fmq); /* dnorm to fmq */ +if (!(ir & FI_NORND) && (fmq.hi & UFP_FH_NORM)) /* round & fmq<1>? */ + dp_inc (a); /* incr a */ +return; +} + +/* Double precision swap */ + +void dp_swap (UFP *a, UFP *b) +{ +int32 t; + +t = a->hi; /* swap fractions */ +a->hi = b->hi; +b->hi = t; +t = a->lo; +a->lo = b->lo; +b->lo = t; +return; +} + +/* Support routines */ + +void fp15_asign (int32 fir, UFP *a) +{ +int32 sgnop = FI_GETSGNOP (fir); + +switch (sgnop) { /* modify FMA sign */ +case 1: + a->sign = 0; + break; +case 2: + a->sign = 1; + break; +case 3: + a->sign = a->sign ^ 1; + break; +default: + break; } +return; +} + +/* FP15 normalization and rounding + + - Do normalization if enabled (NOR phase, part 1) + Normalization also does zero detect + - Do rounding if enabled (NOR phase, part 2) */ + +t_stat fp15_norm (int32 ir, UFP *a, UFP *b, t_bool rnd) +{ +if (!(ir & FI_NONORM)) { /* norm enabled? */ + if ((a->hi | a->lo) || (b && (b->hi | b->lo))) { /* frac != 0? */ + while ((a->hi & UFP_FH_NORM) == 0) { /* until norm */ + dp_lsh_1 (a, b); /* lsh a'b, no cry */ + a->exp = a->exp - 1; } } /* decr exp */ + else a->sign = a->exp = 0; } /* true zero */ +if (rnd && b && (b->hi & UFP_FH_NORM)) { /* rounding? */ + fguard = 1; /* set guard */ + if (!(ir & FI_NORND)) { /* round enabled? */ + dp_inc (a); /* add 1 */ + if (a->hi & UFP_FH_CARRY) { /* carry out? */ + a->hi = UFP_FH_NORM; /* set hi bit */ + a->exp = a->exp + 1; } } } /* incr exp */ +if (a->exp > 0377777) return FP_OVF; /* overflow? */ +if (a->exp < -0400000) return FP_UNF; /* underflow? */ +return FP_OK; +} + +/* Exception */ + +t_stat fp15_exc (t_stat sta) +{ +int32 ma, mb; + +if (sta == FP_MM) trap_pending = 0; /* if mm, kill trap */ +ma = (jea & JEA_EAMASK) + sta - 1; /* JEA address */ +PCQ_ENTRY; /* record branch */ +PC = Incr_addr (PC); /* PC+1 for "JMS" */ +mb = Jms_word (usmd); /* form JMS word */ +if (Write (ma, mb, WR)) return MM_ERR; /* store */ +PC = (jea + 1) & IAMASK; /* new PC */ +return MM_OK; +} + +/* Reset routine */ + +t_stat fp15_reset (DEVICE *dptr) +{ +jea = 0; +fir = 0; +fguard = 0; +fma.exp = fma.hi = fma.lo = fma.sign = 0; +fmb.exp = fmb.hi = fmb.lo = fmb.sign = 0; +fmq.exp = fmq.hi = fmq.lo = fmq.sign = 0; +return SCPE_OK; +} diff --git a/PDP18B/pdp18b_lp.c b/PDP18B/pdp18b_lp.c index c8ca5053..3ef218a6 100644 --- a/PDP18B/pdp18b_lp.c +++ b/PDP18B/pdp18b_lp.c @@ -28,6 +28,7 @@ lp09 (PDP-9,15) LP09 line printer lp15 (PDP-15) LP15 line printer + 23-Jul-03 RMS Fixed overprint bug in Type 62 25-Apr-03 RMS Revised for extended file support 05-Feb-03 RMS Added LP09, fixed conditionalization 05-Oct-02 RMS Added DIB, device number support @@ -53,7 +54,8 @@ extern int32 int_hwre[API_HLVL+1]; #define BPTR_MAX 40 /* pointer max */ #define BPTR_MASK 077 /* buf ptr max */ -int32 lp62_iot = 0; /* saved state */ +int32 lp62_spc = 0; /* print vs spc */ +int32 lp62_ovrpr = 0; /* overprint */ int32 lp62_stopioe = 0; int32 lp62_bp = 0; /* buffer ptr */ char lp62_buf[LP62_BSIZE + 1] = { 0 }; @@ -73,8 +75,8 @@ static const char *lp62_cc[] = { "\f" }; DEVICE lp62_dev; -int32 lp62_65 (int32 pulse, int32 AC); -int32 lp62_66 (int32 pulse, int32 AC); +int32 lp62_65 (int32 pulse, int32 dat); +int32 lp62_66 (int32 pulse, int32 dat); int32 lp62_iors (void); t_stat lp62_svc (UNIT *uptr); t_stat lp62_reset (DEVICE *dptr); @@ -97,7 +99,8 @@ REG lp62_reg[] = { { FLDATA (DONE, int_hwre[API_LPT], INT_V_LPT) }, { FLDATA (SPC, int_hwre[API_LPTSPC], INT_V_LPTSPC) }, { DRDATA (BPTR, lp62_bp, 6) }, - { ORDATA (STATE, lp62_iot, 6), REG_HRO }, + { ORDATA (STATE, lp62_spc, 6), REG_HRO }, + { FLDATA (OVRPR, lp62_ovrpr, 0), REG_HRO }, { DRDATA (POS, lp62_unit.pos, T_ADDR_W), PV_LEFT }, { DRDATA (TIME, lp62_unit.wait, 24), PV_LEFT }, { FLDATA (STOP_IOE, lp62_stopioe, 0) }, @@ -118,62 +121,62 @@ DEVICE lp62_dev = { /* IOT routines */ -int32 lp62_65 (int32 pulse, int32 AC) +int32 lp62_65 (int32 pulse, int32 dat) { int32 i; -if ((pulse & 01) && TST_INT (LPT)) AC = IOT_SKP | AC; /* LPSF */ +if ((pulse & 01) && TST_INT (LPT)) dat = IOT_SKP | dat; /* LPSF */ if (pulse & 02) { int32 sb = pulse & 060; /* subopcode */ if (sb == 000) CLR_INT (LPT); /* LPCF */ if ((sb == 040) && (lp62_bp < BPTR_MAX)) { /* LPLD */ i = lp62_bp * 3; /* cvt to chr ptr */ - lp62_buf[i] = lp62_trans[(AC >> 12) & 077]; - lp62_buf[i + 1] = lp62_trans[(AC >> 6) & 077]; - lp62_buf[i + 2] = lp62_trans[AC & 077]; + lp62_buf[i] = lp62_trans[(dat >> 12) & 077]; + lp62_buf[i + 1] = lp62_trans[(dat >> 6) & 077]; + lp62_buf[i + 2] = lp62_trans[dat & 077]; lp62_bp = (lp62_bp + 1) & BPTR_MASK; } } -if (pulse & 04) /* LPSE */ - sim_activate (&lp62_unit, lp62_unit.wait); /* activate */ -return AC; +if (pulse & 04) { /* LPSE */ + lp62_spc = 0; /* print */ + sim_activate (&lp62_unit, lp62_unit.wait); } /* activate */ +return dat; } -int32 lp62_66 (int32 pulse, int32 AC) +int32 lp62_66 (int32 pulse, int32 dat) { if ((pulse & 01) && TST_INT (LPTSPC)) /* LSSF */ - AC = IOT_SKP | AC; + dat = IOT_SKP | dat; if (pulse & 02) CLR_INT (LPTSPC); /* LSCF */ if (pulse & 04) { /* LSPR */ - lp62_iot = 020 | (AC & 07); /* space, no print */ + lp62_spc = 020 | (dat & 07); /* space */ sim_activate (&lp62_unit, lp62_unit.wait); } /* activate */ -return AC; +return dat; } -/* Unit service, printer is in one of three states +/* Unit service, action based on lp62_spc - lp62_iot = 0 write buffer to file, set state to - lp62_iot = 10 write cr, then write buffer to file - lp62_iot = 2x space command x, then set state to 0 + lp62_spc = 0 write buffer to file, set overprint + lp62_spc = 2x space command x, clear overprint */ t_stat lp62_svc (UNIT *uptr) { int32 i; -if (lp62_iot & 020) { /* space? */ +if (lp62_spc) { /* space? */ SET_INT (LPTSPC); /* set flag */ if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (lp62_stopioe, SCPE_UNATT); - fputs (lp62_cc[lp62_iot & 07], uptr->fileref); /* print cctl */ + fputs (lp62_cc[lp62_spc & 07], uptr->fileref); /* print cctl */ if (ferror (uptr->fileref)) { /* error? */ perror ("LPT I/O error"); clearerr (uptr->fileref); return SCPE_IOERR; } - lp62_iot = 0; } /* clear state */ + lp62_ovrpr = 0; } /* clear overprint */ else { SET_INT (LPT); /* print */ if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (lp62_stopioe, SCPE_UNATT); - if (lp62_iot & 010) fputc ('\r', uptr->fileref); + if (lp62_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */ fputs (lp62_buf, uptr->fileref); /* print buffer */ if (ferror (uptr->fileref)) { /* test error */ perror ("LPT I/O error"); @@ -181,7 +184,7 @@ else { SET_INT (LPT); /* print */ return SCPE_IOERR; } lp62_bp = 0; for (i = 0; i <= LP62_BSIZE; i++) lp62_buf[i] = 0; /* clear buffer */ - lp62_iot = 010; } /* set state */ + lp62_ovrpr = 1; } /* set overprint */ uptr->pos = ftell (uptr->fileref); /* update position */ return SCPE_OK; } @@ -197,7 +200,8 @@ CLR_INT (LPTSPC); sim_cancel (&lp62_unit); /* deactivate unit */ lp62_bp = 0; /* clear buffer ptr */ for (i = 0; i <= LP62_BSIZE; i++) lp62_buf[i] = 0; /* clear buffer */ -lp62_iot = 0; /* clear state */ +lp62_spc = 0; /* clear state */ +lp62_ovrpr = 0; /* clear overprint */ return SCPE_OK; } @@ -235,8 +239,8 @@ static const char *lp647_cc[] = { "\f" }; DEVICE lp647_dev; -int32 lp647_65 (int32 pulse, int32 AC); -int32 lp647_66 (int32 pulse, int32 AC); +int32 lp647_65 (int32 pulse, int32 dat); +int32 lp647_66 (int32 pulse, int32 dat); int32 lp647_iors (void); t_stat lp647_svc (UNIT *uptr); t_stat lp647_reset (DEVICE *dptr); @@ -285,12 +289,12 @@ DEVICE lp647_dev = { /* IOT routines */ -int32 lp647_65 (int32 pulse, int32 AC) +int32 lp647_65 (int32 pulse, int32 dat) { int32 i, sb; sb = pulse & 060; /* subcode */ -if ((pulse & 01) && lp647_don) AC = IOT_SKP | AC; /* LPSF */ +if ((pulse & 01) && lp647_don) dat = IOT_SKP | dat; /* LPSF */ if (pulse & 02) { /* pulse 02 */ lp647_don = 0; /* clear done */ CLR_INT (LPT); /* clear int req */ @@ -310,32 +314,32 @@ if (pulse & 004) { /* LPDI */ break; case 040: /* LPB3 */ if (lp647_bp < LP647_BSIZE) { - lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((AC >> 12) & 077); + lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((dat >> 12) & 077); lp647_bp = lp647_bp + 1; } case 020: /* LPB2 */ if (lp647_bp < LP647_BSIZE) { - lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((AC >> 6) & 077); + lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((dat >> 6) & 077); lp647_bp = lp647_bp + 1; } case 060: /* LPB1 */ if (lp647_bp < LP647_BSIZE) { - lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | (AC & 077); + lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | (dat & 077); lp647_bp = lp647_bp + 1; } lp647_don = 1; /* set done */ if (lp647_ie) SET_INT (LPT); /* set int */ break; } /* end case */ } -return AC; +return dat; } -int32 lp647_66 (int32 pulse, int32 AC) +int32 lp647_66 (int32 pulse, int32 dat) { -if ((pulse & 01) && lp647_err) AC = IOT_SKP | AC; /* LPSE */ +if ((pulse & 01) && lp647_err) dat = IOT_SKP | dat; /* LPSE */ if (pulse & 02) { /* LPCF */ lp647_don = 0; /* clear done, int */ CLR_INT (LPT); } if (pulse & 04) { if ((pulse & 060) < 060) { /* LPLS, LPPB, LPPS */ - lp647_iot = (pulse & 060) | (AC & 07); /* save parameters */ + lp647_iot = (pulse & 060) | (dat & 07); /* save parameters */ sim_activate (&lp647_unit, lp647_unit.wait); } /* activate */ #if defined (PDP9) else { /* LPEI */ @@ -343,7 +347,7 @@ if (pulse & 04) { if (lp647_don) SET_INT (LPT); } #endif } -return AC; +return dat; } /* Unit service. lp647_iot specifies the action to be taken @@ -442,7 +446,7 @@ int32 lp09_ie = 1; /* int enable */ int32 lp09_stopioe = 0; DEVICE lp09_dev; -int32 lp09_66 (int32 pulse, int32 AC); +int32 lp09_66 (int32 pulse, int32 dat); int32 lp09_iors (void); t_stat lp09_svc (UNIT *uptr); t_stat lp09_reset (DEVICE *dptr); @@ -486,13 +490,13 @@ DEVICE lp09_dev = { /* IOT routines */ -int32 lp09_66 (int32 pulse, int32 AC) +int32 lp09_66 (int32 pulse, int32 dat) { int32 sb = pulse & 060; /* subopcode */ if (pulse & 001) { - if ((sb == 000) && lp09_don) AC = IOT_SKP | AC; /* LSDF */ - if ((sb == 020) && lp09_err) AC = IOT_SKP | AC; /* LSEF */ + if ((sb == 000) && lp09_don) dat = IOT_SKP | dat; /* LSDF */ + if ((sb == 020) && lp09_err) dat = IOT_SKP | dat; /* LSEF */ } if (pulse & 002) { if (sb == 000) { /* LSCF */ @@ -501,11 +505,11 @@ if (pulse & 002) { else if (sb == 020) { /* LPLD */ lp09_don = 0; /* clear done, int */ CLR_INT (LPT); - lp09_unit.buf = AC & 0177; /* load char */ + lp09_unit.buf = dat & 0177; /* load char */ if ((lp09_unit.buf == 015) || (lp09_unit.buf == 014) || (lp09_unit.buf == 012)) sim_activate (&lp09_unit, lp09_unit.wait); - else AC = AC | (lp09_svc (&lp09_unit) << IOT_V_REASON); } + else dat = dat | (lp09_svc (&lp09_unit) << IOT_V_REASON); } } if (pulse & 004) { if (sb == 000) { /* LIOF */ @@ -515,7 +519,7 @@ if (pulse & 004) { lp09_ie = 1; /* set int enab */ if (lp09_don) SET_INT (LPT); } /* if done, set int */ } -return AC; +return dat; } /* Unit service */ @@ -608,8 +612,8 @@ int32 lp15_bp = 0; char lp15_buf[LP15_BSIZE] = { 0 }; DEVICE lp15_dev; -int32 lp15_65 (int32 pulse, int32 AC); -int32 lp15_66 (int32 pulse, int32 AC); +int32 lp15_65 (int32 pulse, int32 dat); +int32 lp15_66 (int32 pulse, int32 dat); int32 lp15_iors (void); t_stat lp15_svc (UNIT *uptr); t_stat lp15_reset (DEVICE *dptr); @@ -656,18 +660,18 @@ DEVICE lp15_dev = { /* IOT routines */ -int32 lp15_65 (int32 pulse, int32 AC) +int32 lp15_65 (int32 pulse, int32 dat) { int32 header, sb; sb = pulse & 060; /* subopcode */ if (pulse & 01) { if ((sb == 000) && (lp15_sta & (STA_ERR | STA_DON))) /* LPSF */ - AC = IOT_SKP | AC; + dat = IOT_SKP | dat; else if ((sb == 020) || (sb == 040)) { /* LPP1, LPPM */ sim_activate (&lp15_unit, lp15_unit.wait); /* activate */ - header = M[(M[LPT_CA] + 1) & ADDRMASK]; /* get first word */ - M[LPT_CA] = (M[LPT_CA] + 2) & 0777777; + header = M[(M[LPT_CA] + 1) & AMASK]; /* get first word */ + M[LPT_CA] = (M[LPT_CA] + 2) & DMASK; lp15_mode = header & 1; /* mode */ if (sb == 040) lp15_lc = 1; /* line count */ else lp15_lc = (header >> 9) & 0377; @@ -675,18 +679,18 @@ if (pulse & 01) { lp15_bp = 0; } /* reset buf ptr */ else if (sb == 060) lp15_ie = 0; /* LPDI */ } -if ((pulse & 02) && (sb == 040)) AC = AC | lp15_updsta (0); /* LPOS, LPRS */ +if ((pulse & 02) && (sb == 040)) dat = dat | lp15_updsta (0); /* LPOS, LPRS */ if ((pulse & 04) && (sb == 040)) lp15_ie = 1; /* LPEI */ lp15_updsta (0); /* update status */ -return AC; +return dat; } -int32 lp15_66 (int32 pulse, int32 AC) +int32 lp15_66 (int32 pulse, int32 dat) { if (pulse == 021) lp15_sta = lp15_sta & ~STA_DON; /* LPCD */ if (pulse == 041) lp15_sta = 0; /* LPCF */ lp15_updsta (0); /* update status */ -return AC; +return dat; } /* Unit service */ @@ -709,9 +713,9 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ return IORETURN (lp15_stopioe, SCPE_UNATT); } for (more = 1; more != 0; ) { /* loop until ctrl */ - w0 = M[(M[LPT_CA] + 1) & ADDRMASK]; /* get first word */ - w1 = M[(M[LPT_CA] + 2) & ADDRMASK]; /* get second word */ - M[LPT_CA] = (M[LPT_CA] + 2) & 0777777; /* advance mem addr */ + w0 = M[(M[LPT_CA] + 1) & AMASK]; /* get first word */ + w1 = M[(M[LPT_CA] + 2) & AMASK]; /* get second word */ + M[LPT_CA] = (M[LPT_CA] + 2) & DMASK; /* advance mem addr */ if (lp15_mode) { /* unpacked? */ c[0] = w0 & 0177; c[1] = w1 & 0177; diff --git a/PDP18B/pdp18b_mt.c b/PDP18B/pdp18b_mt.c index ae2c1ddf..0796035d 100644 --- a/PDP18B/pdp18b_mt.c +++ b/PDP18B/pdp18b_mt.c @@ -131,7 +131,7 @@ int32 mt_log = 0; uint8 *mtxb = NULL; /* transfer buffer */ DEVICE mt_dev; -int32 mt (int32 pulse, int32 AC); +int32 mt (int32 pulse, int32 dat); int32 mt_iors (void); t_stat mt_svc (UNIT *uptr); t_stat mt_reset (DEVICE *dptr); @@ -194,7 +194,7 @@ DEVICE mt_dev = { /* IOT routine */ -int32 mt (int32 pulse, int32 AC) +int32 mt (int32 pulse, int32 dat) { int32 f, sb; UNIT *uptr; @@ -205,21 +205,21 @@ sb = pulse & 060; /* subop */ if (pulse & 01) { if ((sb == 000) && (uptr->flags & UNIT_ATT) && /* MTTR */ !sim_is_active (uptr)) - AC = IOT_SKP | AC; + dat = IOT_SKP | dat; else if ((sb == 020) && !mt_busy ()) /* MTCR */ - AC = IOT_SKP | AC; + dat = IOT_SKP | dat; else if ((sb == 040) && (mt_sta & (STA_ERR | STA_DON))) /* MTSF */ - AC = IOT_SKP | AC; + dat = IOT_SKP | dat; } if ((pulse & 06) && mt_log) printf ("[MT%d: IOT=%o, AC=%o, sta=%o]\n", - GET_UNIT (mt_cu), 0707300 + pulse, AC, mt_sta); + GET_UNIT (mt_cu), 0707300 + pulse, dat, mt_sta); if (pulse & 02) { - if (sb == 000) AC = AC | (mt_cu & 0777700); /* MTRC */ + if (sb == 000) dat = dat | (mt_cu & 0777700); /* MTRC */ else if (sb == 020) { /* MTAF, MTLC */ if (!mt_busy ()) mt_cu = mt_sta = 0; /* if not busy, clr */ mt_sta = mt_sta & ~(STA_ERR | STA_DON); } /* clear flags */ - else if (sb == 040) AC = AC | mt_sta; /* MTRS */ + else if (sb == 040) dat = dat | mt_sta; /* MTRS */ } if (pulse & 04) { if (sb == 000) { /* MTGO */ @@ -236,10 +236,10 @@ if (pulse & 04) { else mt_sta = uptr->USTAT = 0; /* no, clear status */ sim_activate (uptr, mt_time); } } /* start io */ if (sb == 020) /* MTCM, MTLC */ - mt_cu = (mt_cu & 0770700) | (AC & 0777700); /* load status */ + mt_cu = (mt_cu & 0770700) | (dat & 0777700); /* load status */ } mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ -return AC; +return dat; } /* Unit service @@ -289,9 +289,9 @@ case FN_CMPARE: /* read/compare */ cbc = tbc; /* use smaller */ wc = PACKED (mt_cu)? ((tbc + 2) / 3): ((tbc + 1) / 2); } for (i = p = 0; i < wc; i++) { /* copy buffer */ - M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */ - M[MT_CA] = (M[MT_CA] + 1) & 0777777; - xma = M[MT_CA] & ADDRMASK; + M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC, CA */ + M[MT_CA] = (M[MT_CA] + 1) & DMASK; + xma = M[MT_CA] & AMASK; if (PACKED (mt_cu)) { /* packed? */ c1 = mtxb[p++] & 077; c2 = mtxb[p++] & 077; @@ -303,16 +303,16 @@ case FN_CMPARE: /* read/compare */ c = (c1 << 8) | c2; } if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c; else if ((f == FN_CMPARE) && (c != (M[xma] & - (PACKED (mt_cu)? 0777777: 0177777)))) { + (PACKED (mt_cu)? DMASK: 0177777)))) { mt_updcsta (uptr, STA_CPE); break; } } break; case FN_WRITE: /* write */ tbc = PACKED (mt_cu)? wc * 3: wc * 2; - xma = M[MT_CA] & ADDRMASK; /* get mem addr */ + xma = M[MT_CA] & AMASK; /* get mem addr */ for (i = p = 0; i < wc; i++) { /* copy buf to tape */ - xma = (xma + 1) & ADDRMASK; /* incr mem addr */ + xma = (xma + 1) & AMASK; /* incr mem addr */ if (PACKED (mt_cu)) { /* packed? */ mtxb[p++] = (M[xma] >> 12) & 077; mtxb[p++] = (M[xma] >> 6) & 077; @@ -323,7 +323,7 @@ case FN_WRITE: /* write */ if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) /* write rec, err? */ r = mt_map_err (uptr, st); /* map error */ else { - M[MT_CA] = (M[MT_CA] + wc) & 0777777; /* advance mem addr */ + M[MT_CA] = (M[MT_CA] + wc) & DMASK; /* advance mem addr */ M[MT_WC] = 0; } /* clear word cnt */ mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */ break; @@ -339,7 +339,7 @@ case FN_WREOF: case FN_SPACEF: /* space forward */ do { - M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC */ + M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC */ if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */ r = mt_map_err (uptr, st); /* map error */ break; } @@ -349,7 +349,7 @@ case FN_SPACEF: /* space forward */ case FN_SPACER: /* space reverse */ do { - M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC */ + M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC */ if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */ r = mt_map_err (uptr, st); /* map error */ break; } diff --git a/PDP18B/pdp18b_rb.c b/PDP18B/pdp18b_rb.c index f25113ab..e3423225 100644 --- a/PDP18B/pdp18b_rb.c +++ b/PDP18B/pdp18b_rb.c @@ -149,7 +149,7 @@ if (pulse & 001) { if (pulse & 002) { if (sb == 000) AC = AC | rb_make_da (rb_da); /* DBRD */ if (sb == 020) AC = AC | rb_sta; /* DBRS */ - if (sb == 040) rb_ma = AC & ADDRMASK; /* DBLM */ + if (sb == 040) rb_ma = AC & AMASK; /* DBLM */ } if (pulse & 004) { if (sb == 000) rb_da = rb_set_da (AC, rb_da); /* DBLD */ @@ -236,7 +236,7 @@ do { if (rb_sta & RBS_WR) { /* write? */ else if (MEM_ADDR_OK (rb_ma)) /* read, valid addr? */ M[rb_ma] = *(((int32 *) uptr->filebuf) + rb_da); rb_wc = (rb_wc + 1) & 0177777; /* incr word count */ - rb_ma = (rb_ma + 1) & ADDRMASK; /* incr mem addr */ + rb_ma = (rb_ma + 1) & AMASK; /* incr mem addr */ rb_da = rb_da + 1; /* incr disk addr */ if (rb_da > RB_SIZE) rb_da = 0; /* disk wraparound? */ } diff --git a/PDP18B/pdp18b_rf.c b/PDP18B/pdp18b_rf.c index 8636679e..86c2e60c 100644 --- a/PDP18B/pdp18b_rf.c +++ b/PDP18B/pdp18b_rf.c @@ -26,6 +26,7 @@ rf (PDP-9) RF09/RF09 (PDP-15) RF15/RS09 + 26-Jul-03 RMS Fixed bug in set size routine 14-Mar-03 RMS Fixed variable platter interaction with save/restore 03-Mar-03 RMS Fixed autosizing 12-Feb-03 RMS Removed 8 platter sizing hack @@ -113,8 +114,8 @@ int32 rf_burst = 1; /* burst mode flag */ int32 rf_stopioe = 1; /* stop on error */ DEVICE rf_dev; -int32 rf70 (int32 pulse, int32 AC); -int32 rf72 (int32 pulse, int32 AC); +int32 rf70 (int32 pulse, int32 dat); +int32 rf72 (int32 pulse, int32 dat); int32 rf_iors (void); t_stat rf_svc (UNIT *uptr); t_stat rf_reset (DEVICE *dptr); @@ -151,14 +152,14 @@ REG rf_reg[] = { { NULL } }; MTAB rf_mod[] = { - { UNIT_PLAT, 0, NULL, "1P", &rf_set_size }, - { UNIT_PLAT, 1, NULL, "2P", &rf_set_size }, - { UNIT_PLAT, 2, NULL, "3P", &rf_set_size }, - { UNIT_PLAT, 3, NULL, "4P", &rf_set_size }, - { UNIT_PLAT, 4, NULL, "5P", &rf_set_size }, - { UNIT_PLAT, 5, NULL, "6P", &rf_set_size }, - { UNIT_PLAT, 6, NULL, "7P", &rf_set_size }, - { UNIT_PLAT, 7, NULL, "8P", &rf_set_size }, + { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size }, + { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size }, + { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size }, + { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size }, + { UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &rf_set_size }, + { UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &rf_set_size }, + { UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &rf_set_size }, + { UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &rf_set_size }, { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, { 0 } }; @@ -172,14 +173,14 @@ DEVICE rf_dev = { /* IOT routines */ -int32 rf70 (int32 pulse, int32 AC) +int32 rf70 (int32 pulse, int32 dat) { int32 t, sb; sb = pulse & 060; /* subopcode */ if (pulse & 01) { if ((sb == 000) && (rf_sta & (RFS_ERR | RFS_DON))) - AC = IOT_SKP | AC; /* DSSF */ + dat = IOT_SKP | dat; /* DSSF */ else if (sb == 020) rf_reset (&rf_dev); /* DSCC */ else if (sb == 040) { /* DSCF */ if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */ @@ -187,19 +188,19 @@ if (pulse & 01) { } if (pulse & 02) { if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */ - else if (sb == 000) AC = AC | rf_dbuf; /* DRBR */ + else if (sb == 000) dat = dat | rf_dbuf; /* DRBR */ else if (sb == 020) /* DRAL */ - AC = AC | (rf_da & 0777777); + dat = dat | (rf_da & DMASK); else if (sb == 040) /* DSFX */ - rf_sta = rf_sta ^ (AC & (RFS_FNC | RFS_IE)); /* xor func */ + rf_sta = rf_sta ^ (dat & (RFS_FNC | RFS_IE)); /* xor func */ else if (sb == 060) /* DRAH */ - AC = AC | (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0); + dat = dat | (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0); } if (pulse & 04) { if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */ - else if (sb == 000) rf_dbuf = AC & 0777777; /* DLBR */ + else if (sb == 000) rf_dbuf = dat & DMASK; /* DLBR */ else if (sb == 020) /* DLAL */ - rf_da = (rf_da & ~0777777) | (AC & 0777777); + rf_da = (rf_da & ~DMASK) | (dat & DMASK); else if (sb == 040) { /* DSCN */ rf_sta = rf_sta & ~RFS_DON; /* clear done */ if (GET_FNC (rf_sta) != FN_NOP) { @@ -207,20 +208,20 @@ if (pulse & 04) { if (t < 0) t = t + RF_NUMWD; /* wrap around? */ sim_activate (&rf_unit, t * rf_time); } } /* schedule op */ else if (sb == 060) { /* DLAH */ - rf_da = (rf_da & 0777777) | ((AC & 07) << 18); + rf_da = (rf_da & DMASK) | ((dat & 07) << 18); if ((uint32) rf_da >= rf_unit.capac) /* for sizing */ rf_updsta (RFS_NED); } } rf_updsta (0); /* update status */ -return AC; +return dat; } -int32 rf72 (int32 pulse, int32 AC) +int32 rf72 (int32 pulse, int32 dat) { int32 sb = pulse & 060; if (pulse & 02) { - if (sb == 000) AC = AC | GET_POS (rf_time) | /* DLOK */ + if (sb == 000) dat = dat | GET_POS (rf_time) | /* DLOK */ (sim_is_active (&rf_unit)? 0400000: 0); else if (sb == 040) { /* DSCD */ if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */ @@ -228,9 +229,9 @@ if (pulse & 02) { rf_updsta (0); } else if (sb == 060) { /* DSRS */ if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */ - AC = AC | rf_updsta (0); } + dat = dat | rf_updsta (0); } } -return AC; +return dat; } /* Unit service - assumes the entire disk is buffered */ @@ -247,8 +248,8 @@ f = GET_FNC (rf_sta); /* get function */ do { if ((uint32) rf_da >= uptr->capac) { /* disk overflow? */ rf_updsta (RFS_NED); /* nx disk error */ break; } - M[RF_WC] = (M[RF_WC] + 1) & 0777777; /* incr word count */ - pa = M[RF_CA] = (M[RF_CA] + 1) & ADDRMASK; /* incr mem addr */ + M[RF_WC] = (M[RF_WC] + 1) & DMASK; /* incr word count */ + pa = M[RF_CA] = (M[RF_CA] + 1) & AMASK; /* incr mem addr */ if ((f == FN_READ) && MEM_ADDR_OK (pa)) /* read? */ M[pa] = *(((int32 *) uptr->filebuf) + rf_da); if ((f == FN_WCHK) && /* write check? */ @@ -323,9 +324,9 @@ return attach_unit (uptr, cptr); t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if ((val < 0) || (val > RF_NUMDK)) return SCPE_IERR; +if (val < 0) return SCPE_IERR; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = (val + 1) * RF_DKSIZE; +uptr->capac = UNIT_GETP (val) * RF_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; } diff --git a/PDP18B/pdp18b_rp.c b/PDP18B/pdp18b_rp.c index 281a52d1..b4d739c9 100644 --- a/PDP18B/pdp18b_rp.c +++ b/PDP18B/pdp18b_rp.c @@ -144,8 +144,8 @@ int32 rp_swait = 10; /* seek time */ int32 rp_rwait = 10; /* rotate time */ DEVICE rp_dev; -int32 rp63 (int32 pulse, int32 AC); -int32 rp64 (int32 pulse, int32 AC); +int32 rp63 (int32 pulse, int32 dat); +int32 rp64 (int32 pulse, int32 dat); int32 rp_iors (void); t_stat rp_svc (UNIT *uptr); void rp_updsta (int32 newa, int32 newb); @@ -202,7 +202,7 @@ DEVICE rp_dev = { /* IOT routines */ -int32 rp63 (int32 pulse, int32 AC) +int32 rp63 (int32 pulse, int32 dat) { int32 sb = pulse & 060; /* subopcode */ @@ -210,24 +210,24 @@ rp_updsta (0, 0); if (pulse & 01) { if ((sb == 000) && /* DPSF */ ((rp_sta & (STA_DON | STA_ERR)) || (rp_stb & STB_ATTN))) - AC = IOT_SKP | AC; + dat = IOT_SKP | dat; else if ((sb == 020) && (rp_stb & STB_ATTN)) /* DPSA */ - AC = IOT_SKP | AC; + dat = IOT_SKP | dat; else if ((sb == 040) && (rp_sta & STA_DON)) /* DPSJ */ - AC = IOT_SKP | AC; + dat = IOT_SKP | dat; else if ((sb == 060) && (rp_sta & STA_ERR)) /* DPSE */ - AC = IOT_SKP | AC; + dat = IOT_SKP | dat; } if (pulse & 02) { - if (sb == 000) AC = AC | rp_sta; /* DPOSA */ - else if (sb == 020) AC = AC | rp_stb; /* DPOSB */ + if (sb == 000) dat = dat | rp_sta; /* DPOSA */ + else if (sb == 020) dat = dat | rp_stb; /* DPOSB */ } if (pulse & 04) { if (rp_busy) { /* busy? */ rp_updsta (0, STB_PGE); - return AC; } + return dat; } else if (sb == 000) { /* DPLA */ - rp_da = AC & 0777777; + rp_da = dat & DMASK; if (GET_SECT (rp_da) >= RP_NUMSC) rp_updsta (STA_NXS, 0); if (GET_SURF (rp_da) >= RP_NUMSF) rp_updsta (STA_NXF, 0); if (GET_CYL (rp_da) >= RP_NUMCY) rp_updsta (STA_NXC, 0); } @@ -236,38 +236,38 @@ if (pulse & 04) { rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE | STB_TME | STB_PGE | STB_EOP); rp_updsta (0, 0); } - else if (sb == 040) rp_ma = AC & 0777777; /* DPCA */ - else if (sb == 060) rp_wc = AC & 0777777; /* DPWC */ + else if (sb == 040) rp_ma = dat & DMASK; /* DPCA */ + else if (sb == 060) rp_wc = dat & DMASK; /* DPWC */ } -return AC; +return dat; } /* IOT 64 */ -int32 rp64 (int32 pulse, int32 AC) +int32 rp64 (int32 pulse, int32 dat) { int32 u, f, c, sb; UNIT *uptr; sb = pulse & 060; if (pulse & 01) { - if (sb == 020) AC = IOT_SKP | AC; /* DPSN */ + if (sb == 020) dat = IOT_SKP | dat; /* DPSN */ } if (pulse & 02) { - if (sb == 000) AC = AC | rp_unit[GET_UNIT (rp_sta)].CYL; /* DPOU */ - else if (sb == 020) AC = AC | rp_da; /* DPOA */ - else if (sb == 040) AC = AC | rp_ma; /* DPOC */ - else if (sb == 060) AC = AC | rp_wc; /* DPOW */ + if (sb == 000) dat = dat | rp_unit[GET_UNIT (rp_sta)].CYL; /* DPOU */ + else if (sb == 020) dat = dat | rp_da; /* DPOA */ + else if (sb == 040) dat = dat | rp_ma; /* DPOC */ + else if (sb == 060) dat = dat | rp_wc; /* DPOW */ } if (pulse & 04) { if (rp_busy) { /* busy? */ rp_updsta (0, STB_PGE); - return AC; } + return dat; } if (sb == 000) rp_sta = rp_sta & ~STA_RW; /* DPCF */ - else if (sb == 020) rp_sta = rp_sta & (AC | ~STA_RW); /* DPLZ */ - else if (sb == 040) rp_sta = rp_sta | (AC & STA_RW); /* DPLO */ + else if (sb == 020) rp_sta = rp_sta & (dat | ~STA_RW); /* DPLZ */ + else if (sb == 040) rp_sta = rp_sta | (dat & STA_RW); /* DPLO */ else if (sb == 060) /* DPLF */ - rp_sta = (rp_sta & ~STA_RW) | (AC & STA_RW); + rp_sta = (rp_sta & ~STA_RW) | (dat & STA_RW); rp_sta = rp_sta & ~STA_DON; /* clear done */ u = GET_UNIT (rp_sta); /* get unit num */ uptr = rp_dev.units + u; /* select unit */ @@ -286,7 +286,7 @@ if (pulse & 04) { sim_activate (uptr, MAX (RP_MIN, c + rp_rwait)); } } } rp_updsta (0, 0); -return AC; +return dat; } /* Unit service @@ -342,7 +342,7 @@ if (rp_sta & (STA_NXS | STA_NXF | STA_NXC)) { /* or bad disk addr? */ rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */ return SCPE_OK; } -pa = rp_ma & ADDRMASK; /* get mem addr */ +pa = rp_ma & AMASK; /* get mem addr */ da = GET_DA (rp_da) * RP_NUMWD; /* get disk addr */ wc = 01000000 - rp_wc; /* get true wc */ if (((uint32) (pa + wc)) > MEMSIZE) { /* memory overrun? */ @@ -373,8 +373,8 @@ if ((f == FN_WRCHK) && (err == 0)) { /* write check? */ if (comp != M[pa + i]) rp_updsta (0, STB_WCE); } err = ferror (uptr->fileref); } -rp_wc = (rp_wc + wc) & 0777777; /* final word count */ -rp_ma = (rp_ma + wc) & 0777777; /* final mem addr */ +rp_wc = (rp_wc + wc) & DMASK; /* final word count */ +rp_ma = (rp_ma + wc) & DMASK; /* final mem addr */ da = (da + wc + (RP_NUMWD - 1)) / RP_NUMWD; /* final sector num */ cyl = da / (RP_NUMSC * RP_NUMSF); /* get cyl */ if (cyl >= RP_NUMCY) cyl = RP_NUMCY - 1; diff --git a/PDP18B/pdp18b_stddev.c b/PDP18B/pdp18b_stddev.c index 73c24f46..dc36133b 100644 --- a/PDP18B/pdp18b_stddev.c +++ b/PDP18B/pdp18b_stddev.c @@ -29,6 +29,8 @@ tto teleprinter clk clock + 26-Jul-03 RMS Increased PTP, TTO timeouts for PDP-15 operating systems + Added hardware read-in mode support for PDP-7/9/15 25-Apr-03 RMS Revised for extended file support 14-Mar-03 RMS Clean up flags on detach 01-Mar-03 RMS Added SET/SHOW CLK FREQ support, SET TTI CTRL-C support @@ -62,7 +64,7 @@ #define UNIT_PASCII (1 << UNIT_V_PASCII) extern int32 M[]; -extern int32 int_hwre[API_HLVL+1], saved_PC; +extern int32 int_hwre[API_HLVL+1], PC, ASW; extern int32 sim_switches; extern UNIT cpu_unit; @@ -74,10 +76,10 @@ int32 tto_state = 0; int32 clk_tps = 60; /* ticks/second */ int32 tmxr_poll = 16000; /* term mux poll */ -int32 ptr (int32 pulse, int32 AC); -int32 ptp (int32 pulse, int32 AC); -int32 tti (int32 pulse, int32 AC); -int32 tto (int32 pulse, int32 AC); +int32 ptr (int32 pulse, int32 dat); +int32 ptp (int32 pulse, int32 dat); +int32 tti (int32 pulse, int32 dat); +int32 tto (int32 pulse, int32 dat); int32 clk_iors (void); int32 ptr_iors (void); int32 ptp_iors (void); @@ -188,7 +190,7 @@ DEVICE ptr_dev = { DIB ptp_dib = { DEV_PTP, 1, &ptp_iors, { &ptp } }; UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; + UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), 1000 }; REG ptp_reg[] = { { ORDATA (BUF, ptp_unit.buf, 8) }, @@ -327,7 +329,7 @@ static const char tto_trans[64] = { DIB tto_dib = { DEV_TTO, 1, &tto_iors, { &tto } }; -UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }; +UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), 1000 }; REG tto_reg[] = { { ORDATA (BUF, tto_unit.buf, TTO_WIDTH) }, @@ -358,10 +360,10 @@ DEVICE tto_dev = { /* Clock: IOT routine */ -int32 clk (int32 pulse, int32 AC) +int32 clk (int32 pulse, int32 dat) { if (pulse & 001) { /* CLSF */ - if (TST_INT (CLK)) AC = AC | IOT_SKP; } + if (TST_INT (CLK)) dat = dat | IOT_SKP; } if (pulse & 004) { /* CLON/CLOF */ if (pulse & 040) { /* CLON */ CLR_INT (CLK); /* clear flag */ @@ -370,7 +372,7 @@ if (pulse & 004) { /* CLON/CLOF */ sim_activate (&clk_unit, /* start, calibr */ sim_rtc_init (clk_unit.wait)); } else clk_reset (&clk_dev); } /* CLOF */ -return AC; +return dat; } /* Unit service */ @@ -380,7 +382,7 @@ t_stat clk_svc (UNIT *uptr) int32 t; if (clk_state) { /* clock on? */ - M[7] = (M[7] + 1) & 0777777; /* incr counter */ + M[7] = (M[7] + 1) & DMASK; /* incr counter */ if (M[7] == 0) SET_INT (CLK); /* ovrflo? set flag */ t = sim_rtc_calb (clk_tps); /* calibrate clock */ sim_activate (&clk_unit, t); /* reactivate unit */ @@ -426,19 +428,19 @@ return SCPE_OK; /* Paper tape reader: IOT routine */ -int32 ptr (int32 pulse, int32 AC) +int32 ptr (int32 pulse, int32 dat) { if (pulse & 001) { /* RSF */ - if (TST_INT (PTR)) AC = AC | IOT_SKP; } + if (TST_INT (PTR)) dat = dat | IOT_SKP; } if (pulse & 002) { /* RRB, RCF */ CLR_INT (PTR); /* clear done */ - AC = AC | ptr_unit.buf; } /* return buffer */ + dat = dat | ptr_unit.buf; } /* return buffer */ if (pulse & 004) { /* RSA, RSB */ ptr_state = (pulse & 040)? 18: 0; /* set mode */ CLR_INT (PTR); /* clear done */ ptr_unit.buf = 0; /* clear buffer */ sim_activate (&ptr_unit, ptr_unit.wait); } -return AC; +return dat; } /* Unit service */ @@ -526,6 +528,39 @@ ptr_unit.flags = ptr_unit.flags & ~UNIT_RASCII; return detach_unit (uptr); } +/* Hardware RIM loader routines, PDP-7/9/15 */ + +int32 ptr_getw (FILE *fileref, int32 *hi) +{ +int32 word, bits, st, ch; + +word = st = bits = 0; +do { if ((ch = getc (fileref)) == EOF) return -1; + if (ch & 0200) { + word = (word << 6) | (ch & 077); + bits = (bits << 1) | ((ch >> 6) & 1); + st++; } } +while (st < 3); +if (hi != NULL) *hi = bits; +return word; +} + +t_stat ptr_rim_load (FILE *fileref, int32 origin) +{ +int32 bits, val; + +for (;;) { /* word loop */ + if ((val = ptr_getw (fileref, &bits)) < 0) return SCPE_FMT; + if (bits & 1) { /* end of tape? */ + if ((val & 0760000) == OP_JMP) { + PC = ((origin - 1) & 060000) | (val & 017777); + return SCPE_OK; } + else if (val == OP_HLT) return STOP_HALT; + break; } + else if (MEM_ADDR_OK (origin)) M[origin++] = val; } +return SCPE_FMT; +} + #if defined (PDP4) || defined (PDP7) /* Bootstrap routine, PDP-4 and PDP-7 @@ -533,12 +568,11 @@ return detach_unit (uptr); In a 4K system, the boostrap resides at 7762-7776. In an 8K or greater system, the bootstrap resides at 17762-17776. Because the program is so small, simple masking can be - used to remove addr<5> for a 4K system. - */ + used to remove addr<5> for a 4K system. */ #define BOOT_START 017577 -#define BOOT_FPC 017577 -#define BOOT_RPC 017770 +#define BOOT_FPC 017577 /* funny format loader */ +#define BOOT_RPC 017770 /* RIM loader */ #define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) static const int32 boot_rom[] = { @@ -677,6 +711,10 @@ t_stat ptr_boot (int32 unitno, DEVICE *dptr) int32 i, mask, wd; extern int32 sim_switches; +#if defined (PDP7) +if (sim_switches & SWMASK ('H')) /* hardware RIM load? */ + return ptr_rim_load (ptr_unit.fileref, ASW); +#endif if (ptr_dib.dev != DEV_PTR) return STOP_NONSTD; /* non-std addr? */ if (MEMSIZE < 8192) mask = 0767777; /* 4k? */ else mask = 0777777; @@ -684,7 +722,7 @@ for (i = 0; i < BOOT_LEN; i++) { wd = boot_rom[i]; if ((wd >= 0040000) && (wd < 0640000)) wd = wd & mask; M[(BOOT_START & mask) + i] = wd; } -saved_PC = ((sim_switches & SWMASK ('F'))? BOOT_FPC: BOOT_RPC) & mask; +PC = ((sim_switches & SWMASK ('F'))? BOOT_FPC: BOOT_RPC) & mask; return SCPE_OK; } @@ -694,24 +732,24 @@ return SCPE_OK; t_stat ptr_boot (int32 unitno, DEVICE *dptr) { -return SCPE_ARG; +return ptr_rim_load (ptr_unit.fileref, ASW); } #endif /* Paper tape punch: IOT routine */ -int32 ptp (int32 pulse, int32 AC) +int32 ptp (int32 pulse, int32 dat) { if (pulse & 001) { /* PSF */ - if (TST_INT (PTP)) AC = AC | IOT_SKP; } + if (TST_INT (PTP)) dat = dat | IOT_SKP; } if (pulse & 002) CLR_INT (PTP); /* PCF */ if (pulse & 004) { /* PSA, PSB, PLS */ CLR_INT (PTP); /* clear flag */ ptp_unit.buf = (pulse & 040)? /* load punch buf */ - (AC & 077) | 0200: AC & 0377; /* bin or alpha */ + (dat & 077) | 0200: dat & 0377; /* bin or alpha */ sim_activate (&ptp_unit, ptp_unit.wait); } /* activate unit */ -return AC; +return dat; } /* Unit service */ @@ -782,16 +820,16 @@ return detach_unit (uptr); /* Terminal input: IOT routine */ -int32 tti (int32 pulse, int32 AC) +int32 tti (int32 pulse, int32 dat) { if (pulse & 001) { /* KSF */ - if (TST_INT (TTI)) AC = AC | IOT_SKP; } + if (TST_INT (TTI)) dat = dat | IOT_SKP; } if (pulse & 002) { /* KRB */ CLR_INT (TTI); /* clear flag */ - AC = AC | tti_unit.buf & TTI_MASK; } /* return buffer */ + dat = dat | tti_unit.buf & TTI_MASK; } /* return buffer */ if (pulse & 004) { /* IORS */ - AC = AC | upd_iors (); } -return AC; + dat = dat | upd_iors (); } +return dat; } /* Unit service */ @@ -870,15 +908,15 @@ return SCPE_OK; /* Terminal output: IOT routine */ -int32 tto (int32 pulse, int32 AC) +int32 tto (int32 pulse, int32 dat) { if (pulse & 001) { /* TSF */ - if (TST_INT (TTO)) AC = AC | IOT_SKP; } + if (TST_INT (TTO)) dat = dat | IOT_SKP; } if (pulse & 002) CLR_INT (TTO); /* clear flag */ if (pulse & 004) { /* load buffer */ sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ - tto_unit.buf = AC & TTO_MASK; } /* load buffer */ -return AC; + tto_unit.buf = dat & TTO_MASK; } /* load buffer */ +return dat; } /* Unit service */ diff --git a/PDP18B/pdp18b_sys.c b/PDP18B/pdp18b_sys.c index 2850d5b3..ef3240ca 100644 --- a/PDP18B/pdp18b_sys.c +++ b/PDP18B/pdp18b_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. + 30-Jul-03 RMS Fixed FPM class mask + 18-Jul-03 RMS Added FP15 support 02-Mar-03 RMS Split loaders apart for greater flexibility 09-Feb-03 RMS Fixed bug in FMTASC (found by Hans Pufal) 31-Jan-03 RMS Added support for RB09 @@ -47,6 +49,9 @@ #include extern DEVICE cpu_dev; +#if defined (PDP15) +extern DEVICE fpp_dev; +#endif extern DEVICE ptr_dev, ptp_dev; extern DEVICE tti_dev, tto_dev; extern UNIT tti_unit, tto_unit; @@ -87,7 +92,7 @@ extern UNIT cpu_unit; extern REG cpu_reg[]; extern int32 M[]; extern int32 memm; -extern int32 saved_PC; +extern int32 PC; /* SCP data structures and interface routines @@ -111,9 +116,13 @@ char sim_name[] = "PDP-15"; REG *sim_PC = &cpu_reg[0]; -int32 sim_emax = 3; +int32 sim_emax = 2; -DEVICE *sim_devices[] = { &cpu_dev, +DEVICE *sim_devices[] = { + &cpu_dev, +#if defined (PDP15) + &fpp_dev, +#endif &ptr_dev, &ptp_dev, &tti_dev, @@ -159,7 +168,8 @@ const char *sim_stop_messages[] = { "Breakpoint", "Nested XCT's", "Invalid API interrupt", - "Non-standard device number" }; + "Non-standard device number", + "Memory management error" }; /* Binary loaders */ @@ -202,7 +212,7 @@ for (;;) { if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; if (MEM_ADDR_OK (origin)) M[origin++] = val; } else if ((val & 0760000) == OP_JMP) { /* JMP? */ - saved_PC = ((origin - 1) & 060000) | (val & 017777); + PC = ((origin - 1) & 060000) | (val & 017777); return SCPE_OK; } else if (val == OP_HLT) return SCPE_OK; /* HLT? */ else return SCPE_FMT; } /* error */ @@ -226,7 +236,7 @@ t_stat r; if (*cptr != 0) { /* more input? */ cptr = get_glyph (cptr, gbuf, 0); /* get origin */ - origin = get_uint (gbuf, 8, ADDRMASK, &r); + origin = get_uint (gbuf, 8, AMASK, &r); if (r != SCPE_OK) return r; if (*cptr != 0) return SCPE_ARG; } /* no more */ else origin = 0200; /* default 200 */ @@ -234,7 +244,7 @@ else origin = 0200; /* default 200 */ for (;;) { /* word loop */ if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT; if (bits & 1) { /* end of tape? */ - if ((val & 0760000) == OP_JMP) saved_PC = + if ((val & 0760000) == OP_JMP) PC = ((origin - 1) & 060000) | (val & 017777); else if (val != OP_HLT) return SCPE_FMT; break; } @@ -258,16 +268,16 @@ return SCPE_OK; t_stat bin_load_915 (FILE *fileref, char *cptr) { -int32 i, val, origin, count, cksum; +int32 i, val, bits, origin, count, cksum; if (*cptr != 0) return SCPE_2MARG; /* no arguments */ -do { val = getc (fileref); } /* find end RIM */ -while (((val & 0100) == 0) && (val != EOF)); -if (val == EOF) rewind (fileref); /* no RIM? rewind */ +do { val = getword (fileref, & bits); } /* find end RIM */ +while ((val >= 0) && ((bits & 1) == 0)); +if (val < 0) rewind (fileref); /* no RIM? rewind */ for (;;) { /* block loop */ if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; if (val & SIGN) { - if (val != DMASK) saved_PC = val & 077777; + if (val != DMASK) PC = val & 077777; break; } cksum = origin = val; /* save origin */ if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; @@ -328,23 +338,30 @@ return bin_load_915 (fileref, cptr); /* must be BIN */ #define I_V_EST 8 /* EAE setup */ #define I_V_ESH 9 /* EAE shift */ #define I_V_EMD 10 /* EAE mul-div */ -#define I_NPN (I_V_NPN << I_V_FL) /* no operand */ -#define I_NPI (I_V_NPI << I_V_FL) /* no operand IOT */ -#define I_IOT (I_V_IOT << I_V_FL) /* IOT */ -#define I_MRF (I_V_MRF << I_V_FL) /* memory reference */ -#define I_OPR (I_V_OPR << I_V_FL) /* OPR */ -#define I_LAW (I_V_LAW << I_V_FL) /* LAW */ -#define I_XR (I_V_XR << I_V_FL) /* index */ -#define I_XR9 (I_V_XR9 << I_V_FL) /* index literal */ -#define I_EST (I_V_EST << I_V_FL) /* EAE setup */ -#define I_ESH (I_V_ESH << I_V_FL) /* EAE shift */ -#define I_EMD (I_V_EMD << I_V_FL) /* EAE mul-div */ +#define I_V_FPM 11 /* FP15 mem ref */ +#define I_V_FPI 12 /* FP15 indirect */ +#define I_V_FPN 13 /* FP15 no operand */ +#define I_NPN (I_V_NPN << I_V_FL) +#define I_NPI (I_V_NPI << I_V_FL) +#define I_IOT (I_V_IOT << I_V_FL) +#define I_MRF (I_V_MRF << I_V_FL) +#define I_OPR (I_V_OPR << I_V_FL) +#define I_LAW (I_V_LAW << I_V_FL) +#define I_XR (I_V_XR << I_V_FL) +#define I_XR9 (I_V_XR9 << I_V_FL) +#define I_EST (I_V_EST << I_V_FL) +#define I_ESH (I_V_ESH << I_V_FL) +#define I_EMD (I_V_EMD << I_V_FL) +#define I_FPM (I_V_FPM << I_V_FL) +#define I_FPI (I_V_FPI << I_V_FL) +#define I_FPN (I_V_FPN << I_V_FL) #define MD(x) ((I_EMD) + ((x) << I_V_DC)) static const int32 masks[] = { - 0777777, 0777767, 0740000, 0760000, + 0777777, 0777767, 0770000, 0760000, 0763730, 0760000, 0777000, 0777000, - 0740700, 0760700, 0777700 }; + 0740700, 0760700, 0777700, 0777777, + 0777777, 0777777 }; static const char *opcode[] = { "CAL", "DAC", "JMS", "DZM", /* mem refs */ @@ -452,9 +469,75 @@ static const char *opcode[] = { #if defined (PDP15) "SPCO", "SKP15", "RES", "SBA", "DBA", "EBA", + "ORMM", "RDMM", "LDMM", "MPLR", + "ENB", "INH", "MPRC", "IPFH", "AAS", "PAX", "PAL", "AAC", "PXA", "AXS", "PXL", "PLA", "PLX", "CLAC","CLX", "CLLR", "AXR", + + "FPT", /* FP15 */ + "ISB", "ESB", /* mem ref */ + "FSB", "URFSB", "UNFSB", "UUFSB", + "DSB", "URDSB", "UNDSB", "UUDSB", + "IRS", "ERS", + "FRS", "URFRS", "UNFRS", "UUFRS", + "DRS", "URDRS", "UNDRS", "UUDRS", + "IMP", "EMP", + "FMP", "URFMP", "UNFMP", "UUFMP", + "DMP", "URDMP", "UNDMP", "UUDMP", + "IDV", "EDV", + "FDV", "URFDV", "UNFDV", "UUFDV", + "DDV", "URDDV", "UNDDV", "UUDDV", + "IRD", "ERD", + "FRD", "URFRD", "UNFRD", "UUFRD", + "DRD", "URDRD", "UNDRD", "UUDRD", + "ILD", "ELD", + "FLD", "UNFLD", "DLD", "UNDLD", + "IST", "EST", + "FST", "URFST", "UNFST", "UUFST", + "DST", "UNDST", + "ILF", "UNILF", "ELF", "UNELF", + "FLX", "URFLX", "DLX", "URDLX", + "ILQ", "ELQ", + "FLQ", "UNFLQ", "DLQ", "UNDLQ", + "LJE", "SJE", + "IAD", "EAD", + "FAD", "URFAD", "UNFAD", "UUFAD", + "DAD", "URDAD", "UNDAD", "UUDAD", + "BZA", "BMA", "BLE", "BPA", + "BRU", "BNA", "BAC", + "ISB*", "ESB*", /* indirect */ + "FSB*", "URFSB*", "UNFSB*", "UUFSB*", + "DSB*", "URDSB*", "UNDSB*", "UUDSB*", + "IRS*", "ERS*", + "FRS*", "URFRS*", "UNFRS*", "UUFRS*", + "DRS*", "URDRS*", "UNDRS*", "UUDRS*", + "IMP*", "EMP*", + "FMP*", "URFMP*", "UNFMP*", "UUFMP*", + "DMP*", "URDMP*", "UNDMP*", "UUDMP*", + "IDV*", "EDV*", + "FDV*", "URFDV*", "UNFDV*", "UUFDV*", + "DDV*", "URDDV*", "UNDDV*", "UUDDV*", + "IRD*", "ERD", + "FRD*", "URFRD*", "UNFRD*", "UUFRD*", + "DRD*", "URDRD*", "UNDRD*", "UUDRD*", + "ILD*", "ELD", + "FLD*", "UNFLD*", "DLD*", "UNDLD*", + "IST*", "EST", + "FST*", "URFST*", "UNFST*", "UUFST*", + "DST*", "UNDST*", + "ILF*", "UNILF*", "ELF*", "UNELF*", + "FLX*", "URFLX*", "DLX*", "URDLX*", + "ILQ*", "ELQ*", + "FLQ*", "UNFLQ*", "DLQ*", "UNDLQ*", + "LJE*", "SJE*", + "IAD*", "EAD*", + "FAD*", "URFAD*", "UNFAD*", "UUFAD*", + "DAD*", "URDAD*", "UNDAD*", "UUDAD*", + + "FLA", "UNFLA", "FXA", "URFXA", /* no operand */ + "SWQ", "UNSWQ", "FZR", + "FAB", "FNG", "FCM", "FNM", #endif #if defined (PDP9) || defined (PDP15) "MPSK", "MPSNE", "MPCV", "MPEU", @@ -617,9 +700,74 @@ static const int32 opc_val[] = { #if defined (PDP15) 0703341+I_NPI, 0707741+I_NPI, 0707742+I_NPI, 0707761+I_NPI, 0707762+I_NPI, 0707764+I_NPI, + 0700022+I_NPI, 0700032+I_NPN, 0700024+I_NPI, 0701724+I_NPI, + 0705521+I_NPI, 0705522+I_NPI, 0701722+I_NPI, 0701764+I_NPI, 0720000+I_XR9, 0721000+I_XR, 0722000+I_XR, 0723000+I_XR9, 0724000+I_XR, 0725000+I_XR9, 0726000+I_XR, 0730000+I_XR, 0731000+I_XR, 0734000+I_XR, 0735000+I_XR, 0736000+I_XR, 0737000+I_XR9, + + 0710314+I_FPN, + 0710400+I_FPM, 0710500+I_FPM, + 0710440+I_FPM, 0710450+I_FPM, 0710460+I_FPM, 0710470+I_FPM, + 0710540+I_FPM, 0710550+I_FPM, 0710560+I_FPM, 0710570+I_FPM, + 0711000+I_FPM, 0711100+I_FPM, + 0711040+I_FPM, 0711050+I_FPM, 0711060+I_FPM, 0711070+I_FPM, + 0711140+I_FPM, 0711150+I_FPM, 0711160+I_FPM, 0711170+I_FPM, + 0711400+I_FPM, 0711500+I_FPM, + 0711440+I_FPM, 0711450+I_FPM, 0711460+I_FPM, 0711470+I_FPM, + 0711540+I_FPM, 0711550+I_FPM, 0711560+I_FPM, 0711570+I_FPM, + 0712000+I_FPM, 0712100+I_FPM, + 0712040+I_FPM, 0712050+I_FPM, 0712060+I_FPM, 0712070+I_FPM, + 0712140+I_FPM, 0712150+I_FPM, 0712160+I_FPM, 0712170+I_FPM, + 0712400+I_FPM, 0712500+I_FPM, + 0712440+I_FPM, 0712450+I_FPM, 0712460+I_FPM, 0712470+I_FPM, + 0712540+I_FPM, 0712550+I_FPM, 0712560+I_FPM, 0712570+I_FPM, + 0713000+I_FPM, 0713100+I_FPM, + 0713050+I_FPM, 0713070+I_FPM, 0713150+I_FPM, 0713170+I_FPM, + 0713600+I_FPM, 0713700+I_FPM, + 0713640+I_FPM, 0713650+I_FPM, 0713660+I_FPM, 0713670+I_FPM, + 0713750+I_FPM, 0713770+I_FPM, + 0714010+I_FPM, 0714030+I_FPM, 0714110+I_FPM, 0714130+I_FPM, + 0714460+I_FPM, 0714470+I_FPM, 0714560+I_FPM, 0714570+I_FPM, + 0715000+I_FPM, 0715100+I_FPM, + 0715050+I_FPM, 0715070+I_FPM, 0715150+I_FPM, 0715170+I_FPM, + 0715400+I_FPM, 0715600+I_FPM, + 0716000+I_FPM, 0716100+I_FPM, + 0716040+I_FPM, 0716050+I_FPM, 0716060+I_FPM, 0716070+I_FPM, + 0716140+I_FPM, 0716150+I_FPM, 0716160+I_FPM, 0716170+I_FPM, + 0716601+I_FPM, 0716602+I_FPM, 0716603+I_FPM, + 0716604+I_FPM, 0716606+I_FPM, 0716610+I_FPM, 0716620+I_FPM, + 0710400+I_FPI, 0710500+I_FPI, /* indirect */ + 0710440+I_FPI, 0710450+I_FPI, 0710460+I_FPI, 0710470+I_FPI, + 0710540+I_FPI, 0710550+I_FPI, 0710560+I_FPI, 0710570+I_FPI, + 0711000+I_FPI, 0711100+I_FPI, + 0711040+I_FPI, 0711050+I_FPI, 0711060+I_FPI, 0711070+I_FPI, + 0711140+I_FPI, 0711150+I_FPI, 0711160+I_FPI, 0711170+I_FPI, + 0711400+I_FPI, 0711500+I_FPI, + 0711440+I_FPI, 0711450+I_FPI, 0711460+I_FPI, 0711470+I_FPI, + 0711540+I_FPI, 0711550+I_FPI, 0711560+I_FPI, 0711570+I_FPI, + 0712000+I_FPI, 0712100+I_FPI, + 0712040+I_FPI, 0712050+I_FPI, 0712060+I_FPI, 0712070+I_FPI, + 0712140+I_FPI, 0712150+I_FPI, 0712160+I_FPI, 0712170+I_FPI, + 0712400+I_FPI, 0712500+I_FPI, + 0712440+I_FPI, 0712450+I_FPI, 0712460+I_FPI, 0712470+I_FPI, + 0712540+I_FPI, 0712550+I_FPI, 0712560+I_FPI, 0712570+I_FPI, + 0713000+I_FPI, 0713100+I_FPI, + 0713050+I_FPI, 0713070+I_FPI, 0713150+I_FPI, 0713170+I_FPI, + 0713600+I_FPI, 0713700+I_FPI, + 0713640+I_FPI, 0713650+I_FPI, 0713660+I_FPI, 0713670+I_FPI, + 0713750+I_FPI, 0713770+I_FPI, + 0714010+I_FPI, 0714030+I_FPI, 0714110+I_FPI, 0714130+I_FPI, + 0714460+I_FPI, 0714470+I_FPI, 0714560+I_FPI, 0714570+I_FPI, + 0715000+I_FPI, 0715100+I_FPI, + 0715050+I_FPI, 0715070+I_FPI, 0715150+I_FPI, 0715170+I_FPI, + 0715400+I_FPI, 0715600+I_FPI, + 0716000+I_FPI, 0716100+I_FPI, + 0716040+I_FPI, 0716050+I_FPI, 0716060+I_FPI, 0716070+I_FPI, + 0716140+I_FPI, 0716150+I_FPI, 0716160+I_FPI, 0716170+I_FPI, + 0714210+I_FPN, 0714230+I_FPN, 0714660+I_FPN, 0714670+I_FPN, + 0715250+I_FPN, 0715270+I_FPN, 0711200+I_FPN, + 0713271+I_FPN, 0713272+I_FPN, 0713273+I_FPN, 0713250+I_FPN, #endif #if defined (PDP9) || defined (PDP15) 0701701+I_NPI, 0701741+I_NPI, 0701702+I_NPI, 0701742+I_NPI, @@ -741,7 +889,7 @@ if (!(sw & SWMASK ('M'))) return SCPE_ARG; 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] & 0777777) == (inst & masks[j])) { /* match? */ + if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */ switch (j) { /* case on class */ case I_V_NPN: /* no operands */ @@ -758,17 +906,17 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ case I_V_MRF: /* mem ref */ #if defined (PDP15) if (memm) { - disp = inst & 017777; - ma = (addr & 0760000) | disp; } + disp = inst & B_DAMASK; + ma = (addr & (AMASK & ~B_DAMASK)) | disp; } else { - disp = inst & 007777; - ma = (addr & 0770000) | disp; } - fprintf (of, "%s %-o", opcode[i], (cflag? ma & ADDRMASK: disp)); - if (!memm && (inst & 0010000)) fprintf (of, ",X"); + disp = inst & P_DAMASK; + ma = (addr & (AMASK & ~P_DAMASK)) | disp; } + fprintf (of, "%s %-o", opcode[i], (cflag? ma & AMASK: disp)); + if (!memm && (inst & I_IDX)) fprintf (of, ",X"); #else - disp = inst & 017777; - ma = (addr & 0760000) | disp; - fprintf (of, "%s %-o", opcode[i], (cflag? ma & ADDRMASK: disp)); + disp = inst & B_DAMASK; + ma = (addr & (AMASK & ~B_DAMASK)) | disp; + fprintf (of, "%s %-o", opcode[i], (cflag? ma & AMASK: disp)); #endif break; case I_V_OPR: /* operate */ @@ -796,7 +944,15 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ if (disp == k) fprintf (of, "%s", opcode[i]); else if (disp < k) fprintf (of, "%s -%-o", opcode[i], k - disp); else fprintf (of, "%s +%-o", opcode[i], disp - k); - break; } /* end case */ + break; + case I_V_FPM: case I_V_FPI: /* FP15 mem ref */ + fprintf (of, "%s", opcode[i]); + if (val[1] & SIGN) fputc ('*', of); + fprintf (of, " %-o", val[1] & ~SIGN); + return -1; + case I_V_FPN: /* FP15 no operand */ + fprintf (of, "%s", opcode[i]); + return -1; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; @@ -838,8 +994,8 @@ return get_uint (cptr, 8, 0777777, status); t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) { -int32 cflag, d, i, j, k, sign, dmask, epcmask; -t_stat r; +int32 cflag, d, i, j, k, sign, damask, epcmask; +t_stat r, sta = SCPE_OK; char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); @@ -895,31 +1051,31 @@ case I_V_LAW: /* law */ break; case I_V_MRF: /* mem ref */ #if defined (PDP15) - if (memm) dmask = 017777; - else dmask = 07777; + if (memm) damask = B_DAMASK; + else damask = P_DAMASK; cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ #else - dmask = 017777; + damask = B_DAMASK; cptr = get_glyph (cptr, gbuf, 0); /* get next field */ #endif #if defined (PDP4) || defined (PDP7) if (strcmp (gbuf, "I") == 0) { /* indirect? */ - val[0] = val[0] | 020000; + val[0] = val[0] | I_IND; cptr = get_glyph (cptr, gbuf, 0); } #endif - epcmask = ADDRMASK & ~dmask; /* get ePC */ - d = get_uint (gbuf, 8, ADDRMASK, &r); /* get addr */ + epcmask = AMASK & ~damask; /* get ePC */ + d = get_uint (gbuf, 8, AMASK, &r); /* get addr */ if (r != SCPE_OK) return SCPE_ARG; - if (d <= dmask) val[0] = val[0] | d; /* fit in 12/13b? */ + if (d <= damask) val[0] = val[0] | d; /* fit in 12/13b? */ else if (cflag && (((addr ^ d) & epcmask) == 0)) - val[0] = val[0] | (d & dmask); /* hi bits = ePC? */ + val[0] = val[0] | (d & damask); /* hi bits = ePC? */ else return SCPE_ARG; #if defined (PDP15) if (!memm) { cptr = get_glyph (cptr, gbuf, 0); if (gbuf[0] != 0) { if (strcmp (gbuf, "X") != 0) return SCPE_ARG; - val[0] = val[0] | 010000; } } + val[0] = val[0] | I_IDX; } } #endif break; case I_V_EMD: /* or'able */ @@ -940,7 +1096,23 @@ case I_V_NPN: case I_V_NPI: case I_V_IOT: case I_V_OPR: if (sign > 0) val[0] = val[0] + d; else if (sign < 0) val[0] = val[0] - d; else val[0] = val[0] | d; } } + break; +case I_V_FPM: /* FP15 mem ref */ + cptr = get_glyph (cptr, gbuf, 0); /* get next field */ + val[1] = get_uint (gbuf, 8, AMASK, &r); /* get addr */ + if (r != SCPE_OK) return SCPE_ARG; + sta = -1; + break; +case I_V_FPI: /* FP15 ind mem ref */ + cptr = get_glyph (cptr, gbuf, 0); /* get next field */ + val[1] = get_uint (gbuf, 8, AMASK, &r) | SIGN; /* get @addr */ + if (r != SCPE_OK) return SCPE_ARG; + sta = -1; + break; +case I_V_FPN: /* FP15 no operand */ + val[1] = 0; + sta = -1; break; } /* end case */ if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return SCPE_OK; +return sta; } diff --git a/PDP18B/pdp18b_tt1.c b/PDP18B/pdp18b_tt1.c index 5a3912c0..9229bc3d 100644 --- a/PDP18B/pdp18b_tt1.c +++ b/PDP18B/pdp18b_tt1.c @@ -58,8 +58,8 @@ TMLN tt1_ldsc = { 0 }; /* line descriptors */ TMXR tt_desc = { 1, 0, 0, &tt1_ldsc }; /* mux descriptor */ DEVICE tti1_dev, tto1_dev; -int32 tti1 (int32 pulse, int32 AC); -int32 tto1 (int32 pulse, int32 AC); +int32 tti1 (int32 pulse, int32 dat); +int32 tto1 (int32 pulse, int32 dat); t_stat tti1_svc (UNIT *uptr); t_stat tto1_svc (UNIT *uptr); t_stat tti1_reset (DEVICE *dptr); @@ -150,14 +150,14 @@ DEVICE tto1_dev = { /* Terminal input: IOT routine */ -int32 tti1 (int32 pulse, int32 AC) +int32 tti1 (int32 pulse, int32 dat) { if (pulse & 001) { /* KSF1 */ - if (TST_INT (TTI1)) AC = AC | IOT_SKP; } + if (TST_INT (TTI1)) dat = dat | IOT_SKP; } if (pulse & 002) { /* KRB1 */ CLR_INT (TTI1); /* clear flag */ - AC= AC | tti1_unit.buf; } /* return buffer */ -return AC; + dat= dat | tti1_unit.buf; } /* return buffer */ +return dat; } /* Unit service */ @@ -204,15 +204,15 @@ return SCPE_OK; /* Terminal output: IOT routine */ -int32 tto1 (int32 pulse, int32 AC) +int32 tto1 (int32 pulse, int32 dat) { if (pulse & 001) { /* TSF */ - if (TST_INT (TTO1)) AC = AC | IOT_SKP; } + if (TST_INT (TTO1)) dat = dat | IOT_SKP; } if (pulse & 002) CLR_INT (TTO1); /* clear flag */ if (pulse & 004) { /* load buffer */ sim_activate (&tto1_unit, tto1_unit.wait); /* activate unit */ - tto1_unit.buf = AC & 0377; } /* load buffer */ -return AC; + tto1_unit.buf = dat & 0377; } /* load buffer */ +return dat; } /* Unit service */ diff --git a/PDP8/pdp8_df.c b/PDP8/pdp8_df.c index 190ecd4c..3e28847c 100644 --- a/PDP8/pdp8_df.c +++ b/PDP8/pdp8_df.c @@ -25,6 +25,7 @@ df DF32 fixed head disk + 26-Jul-03 RMS Fixed bug in set size routine 14-Mar-03 RMS Fixed variable platter interaction with save/restore 03-Mar-03 RMS Fixed autosizing 02-Feb-03 RMS Added variable platter and autosizing support @@ -142,10 +143,10 @@ REG df_reg[] = { { NULL } }; MTAB df_mod[] = { - { UNIT_PLAT, 0, NULL, "1P", &df_set_size }, - { UNIT_PLAT, 1, NULL, "2P", &df_set_size }, - { UNIT_PLAT, 2, NULL, "3P", &df_set_size }, - { UNIT_PLAT, 3, NULL, "4P", &df_set_size }, + { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &df_set_size }, + { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &df_set_size }, + { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &df_set_size }, + { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &df_set_size }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, { 0 } }; @@ -338,9 +339,9 @@ return attach_unit (uptr, cptr); t_stat df_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if ((val < 0) || (val >= DF_NUMDK)) return SCPE_IERR; +if (val < 0) return SCPE_IERR; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = (val + 1) * DF_DKSIZE; +uptr->capac = UNIT_GETP (val) * DF_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; } diff --git a/PDP8/pdp8_rf.c b/PDP8/pdp8_rf.c index 002c4bb4..c8441147 100644 --- a/PDP8/pdp8_rf.c +++ b/PDP8/pdp8_rf.c @@ -25,6 +25,7 @@ rf RF08 fixed head disk + 26-Jul-03 RMS Fixed bug in set size routine 14-Mar-03 RMS Fixed variable platter interaction with save/restore 03-Mar-03 RMS Fixed autosizing 02-Feb-03 RMS Added variable platter and autosizing support @@ -154,10 +155,10 @@ REG rf_reg[] = { { NULL } }; MTAB rf_mod[] = { - { UNIT_PLAT, 0, NULL, "1P", &rf_set_size }, - { UNIT_PLAT, 1, NULL, "2P", &rf_set_size }, - { UNIT_PLAT, 2, NULL, "3P", &rf_set_size }, - { UNIT_PLAT, 3, NULL, "4P", &rf_set_size }, + { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size }, + { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size }, + { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size }, + { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size }, { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_dev, &show_dev, NULL }, @@ -391,9 +392,9 @@ return attach_unit (uptr, cptr); t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { -if ((val < 0) || (val >= RF_NUMDK)) return SCPE_IERR; +if (val < 0) return SCPE_IERR; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = (val + 1) * RF_DKSIZE; +uptr->capac = UNIT_GETP (val) * RF_DKSIZE; uptr->flags = uptr->flags & ~UNIT_AUTO; return SCPE_OK; } diff --git a/SDS/sds_doc.txt b/SDS/sds_doc.txt index 30241fe9..97ec45c8 100644 --- a/SDS/sds_doc.txt +++ b/SDS/sds_doc.txt @@ -170,8 +170,9 @@ for channel W, entry [1] for channel Y, etc. MODE[0:7] 12 channel mode (from EOM instruction) FLAG[0:7] 9 channel flags -The user can display all the registers in a channel with the command SHOW -CHAN . +The user can display all the registers in a channel with the command: + + SHOW CHAN channel-letter 2.3 Console Input (TTI) @@ -364,7 +365,7 @@ The lines (MUXL) implements these registers: TIME[0:31] 24 transmit time, lines 0 to 31 -The additional terminals do not support save and restore. All open +The terminal multiplexor does not support save and restore. All open connections are lost when the simulator shuts down or MUX is detached. 2.10 Project Genie Drum (DRM) @@ -419,11 +420,8 @@ Error handling is as follows: not attached 1 report error and stop 0 disk not ready - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - -By default, the rapid access disk is assigned to channel E. +The rapid access disk is buffered in memory; end of file and OS I/O errors +cannot occur. By default, the rapid access disk is assigned to channel E. 2.12 Moving Head Disk (DSK) @@ -456,9 +454,12 @@ Error handling is as follows: not attached 1 report error and stop 0 disk not ready -Rapid access disk data files are buffered in memory; therefore, end of file -and OS I/O errors cannot occur. By default, the rapid access disk is -assigned to channel F. + end of file x assume rest of disk is zero + + OS I/O error x report error and stop + + +By default, the moving head disk is assigned to channel F. 2.13 Magnetic Tape (MT) diff --git a/VAX/vax_doc.txt b/VAX/vax_doc.txt index 7afcc27e..a8c12387 100644 --- a/VAX/vax_doc.txt +++ b/VAX/vax_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: VAX Simulator Usage -Date: 15-Jun-2003 +Date: 15-Jul-2003 COPYRIGHT NOTICE @@ -37,17 +37,20 @@ This memorandum documents the VAX simulator. 1. Simulator Files To compile the VAX, you must define VM_VAX and USE_INT64 as part of the compilation -command line. +command line. To enable extended file support (files greater than 2GB), you must +define USE_ADDR64 as part of the command line as well. sim/ sim_defs.h sim_ether.h sim_rev.h sim_sock.h + sim_tape.h sim_tmxr.h scp.c scp_tty.c sim_ether.c sim_sock.c + sim_tape.c sim_tmxr.c sim/vax/ vax_defs.h @@ -59,6 +62,7 @@ sim/vax/ vax_defs.h vax_mmu.c vax_stddev.c vax_sys.c + vax_sysdev.c sim/pdp11/ pdp11_mscp.h pdp11_uqssp.h @@ -90,7 +94,7 @@ PTR,PTP PCV11 paper tape reader/punch TTI,TTO console terminal LPT LPV11 line printer CLK real-time clock -DZ DZV11 8-line terminal multiplexor (up to 4) +DZ DZV11 4-line terminal multiplexor (up to 4) RL RLV12/RL01(2) cartridge disk controller with four drives RQ RQDX3 MSCP controller with four drives RQB second RQDX3 MSCP controller with four drives @@ -130,6 +134,9 @@ HALT instruction. SET CPU 64M set memory size = 64MB SET CPU SIMHALT kernel HALT returns to simulator SET CPU CONHALT kernel HALT returns to boot ROM console + +The CPU implements a show command to display the I/O address map: + SHOW CPU IOSPACE show I/O space address map If memory size is being reduced, and the memory being truncated contains @@ -201,10 +208,10 @@ control registers for the interrupt system. The CPU can maintain a history of the most recently executed instructions. This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands: - SET CPU HISTORY -- clear history buffer - SET CPU HISTORY=0 -- disable history - SET CPU HISTORY=n -- enable history, display length = n - SHOW CPU HISTORY -- print CPU history + SET CPU HISTORY clear history buffer + SET CPU HISTORY=0 disable history + SET CPU HISTORY=n enable history, display length = n + SHOW CPU HISTORY print CPU history The maximum length for the history is 4096 entries. @@ -225,15 +232,15 @@ The boot ROM consists of a single unit, representing the 128KB boot ROM. It has no registers. The boot ROM is loaded with a binary byte stream using the LOAD -r command: - LOAD -r KA655.BIN -- load boot ROM image KA655.BIN + LOAD -r KA655.BIN load boot ROM image KA655.BIN ROM accesses a use a calibrated delay that slows ROM-based execution to about 500K instructions per second. This delay is required to make the power-up self-test routines run correctly on very fast hosts. The delay is controlled with the commands: - SET ROM NODELAY -- ROM runs like RAM - SET ROM DELAY -- ROM runs slowly + SET ROM NODELAY ROM runs like RAM + SET ROM DELAY ROM runs slowly 2.1.4 Non-volatile Memory (NVR) @@ -491,16 +498,16 @@ The clock (CLK) implements these registers: The real-time clock autocalibrates; the clock interval is adjusted up or down so that the clock tracks actual elapsed time. -2.3.7 DZ11 Terminal Multiplexor (DZ) +2.3.7 DZV11 Terminal Multiplexor (DZ) -The DZ11 is an 8-line terminal multiplexor. Up to 4 DZ11's (32 lines) +The DZV11 is an 4-line terminal multiplexor. Up to 4 DZ11's (16 lines) are supported. The number of lines can be changed with the command - SET DZ LINES=n set line count to n + SET DZ LINES=n set line count to n The line count must be a multiple of 4, with a maximum of 16. -The DZ11 supports 8-bit input and output of characters. 8-bit output +The DZV11 supports 8-bit input and output of characters. 8-bit output may be incompatible with certain operating systems. The command SET DZ 7B @@ -511,12 +518,15 @@ The terminal lines perform input and output through Telnet sessions connected to a user-specified port. The ATTACH command specifies the port to be used: - ATTACH {-am} DZ set up listening port + ATTACH {-am} DZ set up listening port where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. The optional switch -m turns on the DZ11's +for other TCP/IP activities. The optional switch -m turns on the DZV11's modem controls; the optional switch -a turns on active disconnects -(disconnect session if computer clears Data Terminal Ready). +(disconnect session if computer clears Data Terminal Ready). Without +modem control, the DZ behaves as though terminals were directly connected; +disconnecting the Telnet session does not cause any operating system- +visible change in line status. Once the DZ is attached and the simulator is running, the DZ will listen for connections on the specified port. It assumes that the incoming @@ -528,7 +538,7 @@ The SHOW DZ CONNECTIONS command displays the current connections to the DZ. The SHOW DZ STATISTICS command displays statistics for active connections. The SET DZ DISCONNECT=linenumber disconnects the specified line. -The DZ11 implements these registers: +The DZV11 implements these registers: name size comments @@ -544,7 +554,7 @@ The DZ11 implements these registers: MDMTCL 1 modem control enabled AUTODS 1 autodisconnect enabled -The DZ11 does not support save and restore. All open connections are +The DZV11 does not support save and restore. All open connections are lost when the simulator shuts down or the DZ is detached. 2.4 RLV12/RL01,RL02 Cartridge Disk (RL) @@ -613,9 +623,14 @@ of many disk types: SET RQn RA72 set type to RA72 SET RQn RA90 set type to RA90 SET RQn RA92 set type to RA92 - SET RQn RA81 set type to RA81 with n LBN's. + SET RQn RAUSER{=n} set type to RA81 with n LBN's The type options can be used only when a unit is not attached to a file. +RAUSER is a "user specified" disk; the user can specify the size of the +disk in logical block numbers (LBN's, 512 bytes each). The minimum size +is 50MB. The maximum size is 2GB if the simulator is compiled without +64b addressing, 1000GB with 64b addressing. + Units can also be set ONLINE or OFFLINE. Each RQ controller implements the following special SHOW commands: @@ -662,13 +677,13 @@ Each RQ controller implements these registers: Error handling is as follows: - error processed as + error processed as - not attached disk not ready + not attached disk not ready - end of file assume rest of disk is zero + end of file assume rest of disk is zero - OS I/O error report error and stop + OS I/O error report error and stop 2.6 TSV11/TSV05 Magnetic Tape (TS) @@ -780,13 +795,13 @@ The TQ controller implements these registers: Error handling is as follows: - error processed as + error processed as - not attached tape not ready + not attached tape not ready - end of file end of medium + end of file end of medium - OS I/O error report error and stop + OS I/O error report error and stop 2.8 DELQA/DEQNA Qbus Ethernet Controllers (XQ, XQB) @@ -840,18 +855,18 @@ controller will behave as though the ethernet cable were unplugged. XQ has the following registers: - name size comments + name size comments - SA0 16 station address word 0 - SA1 16 station address word 1 - SA2 16 station address word 2 - SA3 16 station address word 3 - SA4 16 station address word 4 - SA5 16 station address word 5 - CSR 16 control status register - VAR 16 vector address register - RBDL 32 receive buffer descriptor list - XBDL 32 trans(X)mit buffer descriptorlList + SA0 16 station address word 0 + SA1 16 station address word 1 + SA2 16 station address word 2 + SA3 16 station address word 3 + SA4 16 station address word 4 + SA5 16 station address word 5 + CSR 16 control status register + VAR 16 vector address register + RBDL 32 receive buffer descriptor list + XBDL 32 trans(X)mit buffer descriptorlList One final note: because of it's asynchronous nature, the XQ controller is not limited to the ~1.5Mbit/sec of the real DEQNA/DELQA controllers, diff --git a/descrip.mms b/descrip.mms index bdad29cd..81c7c01e 100644 --- a/descrip.mms +++ b/descrip.mms @@ -1,1021 +1,1023 @@ -# -# DESCRIP.MMS -# Written By: Robert Alan Byer -# byer@mail.ourservers.net -# -# Modified By: Mark Pizzolato -# mark@infocomm.com -# -# This MMS/MMK build script is used to compile the various simulators in -# the SIMH package for OpenVMS using DEC C v6.0-001. -# -# Notes: On VAX, the PDP-10 and VAX simulator will not be built due to the -# fact that INT64 is required for those simulators. -# -# When using DEC's MMS on an Alpha you must use -# /MACRO=("__ALPHA__=1") to compile properly. -# -# This build script will accept the following build options. -# -# ALL Just Build "Everything". -# ALTAIR Just Build The MITS Altair. -# ALTAIRZ80 Just Build The MITS Altair Z80. -# ECLIPSE Just Build The Data General Eclipse. -# GRI Just Build The GRI Corporation GRI-909. -# H316 Just Build The Honewell 316/516. -# HP2100 Just Build The Hewlett-Packard HP-2100. -# I1401 Just Build The IBM 1401. -# IBM1130 Just Build The IBM 1130. -# ID16 Just Build The Interdata 16-bit CPU. -# ID32 Just Build The Interdata 32-bit CPU. -# NOVA Just Build The Data General Nova. -# PDP1 Just Build The DEC PDP-1. -# PDP4 Just Build The DEC PDP-4. -# PDP7 Just Build The DEC PDP-7. -# PDP8 Just Build The DEC PDP-8. -# PDP9 Just Build The DEC PDP-9. -# PDP10 Just Build The DEC PDP-10. -# PDP11 Just Build The DEC PDP-11. -# PDP15 Just Build The DEC PDP-15. -# S3 Just Build The IBM System 3. -# SDS Just Build The SDS 940. -# VAX Just Build The DEC VAX. -# CLEAN Will Clean Files Back To Base Kit. -# -# To build with debugging enabled (which will also enable traceback -# information) use.. -# -# MMK/FORCE/MACRO=(DEBUG=1) -# -# This will produce an executable named {Simulator}-{VAX|AXP}-DBG.EXE -# - -# -# Define The BIN Directory Where The Executables Will Go. -# -BIN_DIR = SYS$DISK:[.BIN] - -# -# Define Our Library Directory. -# -LIB_DIR = SYS$DISK:[.LIB] - -# -# Let's See If We Are Going To Build With DEBUG Enabled. -# -.IFDEF DEBUG -CC_DEBUG = /DEBUG=ALL -LINK_DEBUG = /DEBUG/TRACEBACK -CC_OPTIMIZE = /NOOPTIMIZE -.IFDEF __ALPHA__ -CC_FLAGS = /PREFIX=ALL -ARCH = AXP-DBG -.ELSE -ARCH = VAX-DBG -CC_FLAGS = $(CC_FLAGS) -.ENDIF -.ELSE -CC_DEBUG = /NODEBUG -LINK_DEBUG = /NODEBUG/NOTRACEBACK -.IFDEF __ALPHA__ -CC_OPTIMIZE = /OPTIMIZE=(LEVEL=5,TUNE=HOST)/ARCH=HOST -CC_FLAGS = /PREFIX=ALL -ARCH = AXP -.ELSE -CC_OPTIMIZE = /OPTIMIZE -ARCH = VAX -CC_FLAGS = $(CC_FLAGS) -.ENDIF -.ENDIF - -# -# Define Our Compiler Flags -# -CC_FLAGS = $(CC_FLAGS)$(CC_DEBUG)$(CC_OPTIMIZE)/NEST=PRIMARY/NAME=(AS_IS,SHORTENED) - -# -# Define The Compile Command. -# -CC = CC/DECC$(CC_FLAGS) - -# -# First, Let's Check To Make Sure We Have A SYS$DISK:[.BIN] And -# SYS$DISK:[.LIB] Directory. -# -.FIRST - @ IF (F$SEARCH("SYS$DISK:[]BIN.DIR").EQS."") THEN CREATE/DIRECTORY $(BIN_DIR) - @ IF (F$SEARCH("SYS$DISK:[]LIB.DIR").EQS."") THEN CREATE/DIRECTORY $(LIB_DIR) - -# -# Core SIMH File Definitions. -# -SIMH_DIR = SYS$DISK:[] -SIMH_LIB = $(LIB_DIR)SIMH-$(ARCH).OLB -SIMH_SOURCE = $(SIMH_DIR)SCP_TTY.C,$(SIMH_DIR)SIM_SOCK.C,\ - $(SIMH_DIR)SIM_TMXR.C,$(SIMH_DIR)SIM_ETHER.C,\ - $(SIMH_DIR)SIM_TAPE.C -SIMH_OBJS = $(SIMH_DIR)SCP_TTY.OBJ,$(SIMH_DIR)SIM_SOCK.OBJ,\ - $(SIMH_DIR)SIM_TMXR.OBJ,$(SIMH_DIR)SIM_ETHER.OBJ,\ - $(SIMH_DIR)SIM_TAPE.OBJ - -# -# MITS Altair Simulator Definitions. -# -ALTAIR_DIR = SYS$DISK:[.ALTAIR] -ALTAIR_LIB = $(LIB_DIR)ALTAIR-$(ARCH).OLB -ALTAIR_SOURCE = $(ALTAIR_DIR)ALTAIR_SIO.C,$(ALTAIR_DIR)ALTAIR_CPU.C,\ - $(ALTAIR_DIR)ALTAIR_DSK.C,$(ALTAIR_DIR)ALTAIR_SYS.C -ALTAIR_OBJS = $(ALTAIR_DIR)ALTAIR_SIO.OBJ,$(ALTAIR_DIR)ALTAIR_CPU.OBJ,\ - $(ALTAIR_DIR)ALTAIR_DSK.OBJ,$(ALTAIR_DIR)ALTAIR_SYS.OBJ -ALTAIR_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIR_DIR)) - -# -# MITS Altair Z80 Simulator Definitions. -# -ALTAIRZ80_DIR = SYS$DISK:[.ALTAIRZ80] -ALTAIRZ80_LIB = $(LIB_DIR)ALTAIRZ80-$(ARCH).OLB -ALTAIRZ80_SOURCE = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_DSK.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SIO.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SYS.C,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.C -ALTAIRZ80_OBJS = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_DSK.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SIO.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_SYS.OBJ,\ - $(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.OBJ -ALTAIRZ80_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIRZ80_DIR)) - -# -# Data General Nova Simulator Definitions. -# -NOVA_DIR = SYS$DISK:[.NOVA] -NOVA_LIB = $(LIB_DIR)NOVA-$(ARCH).OLB -NOVA_SOURCE = $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_CPU.C,\ - $(NOVA_DIR)NOVA_DKP.C,$(NOVA_DIR)NOVA_DSK.C,\ - $(NOVA_DIR)NOVA_LP.C,$(NOVA_DIR)NOVA_MTA.C,\ - $(NOVA_DIR)NOVA_PLT.C,$(NOVA_DIR)NOVA_PT.C,\ - $(NOVA_DIR)NOVA_CLK.C,$(NOVA_DIR)NOVA_TT.C,\ - $(NOVA_DIR)NOVA_TT1.C -NOVA_OBJS = $(NOVA_DIR)NOVA_SYS.OBJ,$(NOVA_DIR)NOVA_CPU.OBJ,\ - $(NOVA_DIR)NOVA_DKP.OBJ,$(NOVA_DIR)NOVA_DSK.OBJ,\ - $(NOVA_DIR)NOVA_LP.OBJ,$(NOVA_DIR)NOVA_MTA.OBJ,\ - $(NOVA_DIR)NOVA_PLT.OBJ,$(NOVA_DIR)NOVA_PT.OBJ,\ - $(NOVA_DIR)NOVA_CLK.OBJ,$(NOVA_DIR)NOVA_TT.OBJ,\ - $(NOVA_DIR)NOVA_TT1.OBJ -NOVA_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR)) - -# -# Data General Eclipse Simulator Definitions. -# -ECLIPSE_LIB = $(LIB_DIR)ECLIPSE-$(ARCH).OLB -ECLIPSE_SOURCE = $(NOVA_DIR)ECLIPSE_CPU.C,$(NOVA_DIR)ECLIPSE_TT.C,\ - $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_DKP.C,\ - $(NOVA_DIR)NOVA_DSK.C,$(NOVA_DIR)NOVA_LP.C,\ - $(NOVA_DIR)NOVA_MTA.C,$(NOVA_DIR)NOVA_PLT.C,\ - $(NOVA_DIR)NOVA_PT.C,$(NOVA_DIR)NOVA_CLK.C,\ - $(NOVA_DIR)NOVA_TT1.C -ECLIPSE_OBJS = $(NOVA_DIR)ECLIPSE_CPU.OBJ,$(NOVA_DIR)ECLIPSE_TT.OBJ,\ - $(NOVA_DIR)NOVA_SYS.OBJ,$(NOVA_DIR)NOVA_DKP.OBJ,\ - $(NOVA_DIR)NOVA_DSK.OBJ,$(NOVA_DIR)NOVA_LP.OBJ,\ - $(NOVA_DIR)NOVA_MTA.OBJ,$(NOVA_DIR)NOVA_PLT.OBJ,\ - $(NOVA_DIR)NOVA_PT.OBJ,$(NOVA_DIR)NOVA_CLK.OBJ,\ - $(NOVA_DIR)NOVA_TT1.OBJ -ECLIPSE_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR))/DEFINE=("ECLIPSE=1") - -# -# GRI Corporation GRI-909 Simulator Definitions. -# -GRI_DIR = SYS$DISK:[.GRI] -GRI_LIB = $(LIB_DIR)GRI-$(ARCH).OLB -GRI_SOURCE = $(GRI_DIR)GRI_CPU.C,$(GRI_DIR)GRI_STDDEV.C,$(GRI_DIR)GRI_SYS.C -GRI_OBJS = $(GRI_DIR)GRI_CPU.OBJ,$(GRI_DIR)GRI_STDDEV.OBJ,\ - $(GRI_DIR)GRI_SYS.OBJ -GRI_OPTIONS = /INCLUDE=($(SIMH_DIR),$(GRI_DIR)) - -# -# Honeywell 316/516 Simulator Definitions. -# -H316_DIR = SYS$DISK:[.H316] -H316_LIB = $(LIB_DIR)H316-$(ARCH).OLB -H316_SOURCE = $(H316_DIR)H316_STDDEV.C,$(H316_DIR)H316_LP.C,\ - $(H316_DIR)H316_CPU.C,$(H316_DIR)H316_SYS.C -H316_OBJS = $(H316_DIR)H316_STDDEV.OBJ,$(H316_DIR)H316_LP.OBJ,\ - $(H316_DIR)H316_CPU.OBJ,$(H316_DIR)H316_SYS.OBJ -H316_OPTIONS = /INCLUDE=($(SIMH_DIR),$(H316_DIR)) - -# -# Hewlett-Packard HP-2100 Simulator Definitions. -# -HP2100_DIR = SYS$DISK:[.HP2100] -HP2100_LIB = $(LIB_DIR)HP2100-$(ARCH).OLB -HP2100_SOURCE = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.C,\ - $(HP2100_DIR)HP2100_DQ.C,$(HP2100_DIR)HP2100_DR.C,\ - $(HP2100_DIR)HP2100_LPS.C,$(HP2100_DIR)HP2100_MS.C,\ - $(HP2100_DIR)HP2100_MT.C,$(HP2100_DIR)HP2100_MUX.C,\ - $(HP2100_DIR)HP2100_CPU.C,$(HP2100_DIR)HP2100_FP.C,\ - $(HP2100_DIR)HP2100_SYS.C,$(HP2100_DIR)HP2100_LPT.C,\ - $(HP2100_DIR)HP2100_IPL.C -HP2100_OBJS = $(HP2100_DIR)HP2100_STDDEV.OBJ,$(HP2100_DIR)HP2100_DP.OBJ,\ - $(HP2100_DIR)HP2100_DQ.OBJ,$(HP2100_DIR)HP2100_DR.OBJ,\ - $(HP2100_DIR)HP2100_LPS.OBJ,$(HP2100_DIR)HP2100_MS.OBJ,\ - $(HP2100_DIR)HP2100_MT.OBJ,$(HP2100_DIR)HP2100_MUX.OBJ,\ - $(HP2100_DIR)HP2100_CPU.OBJ,$(HP2100_DIR)HP2100_FP.OBJ,\ - $(HP2100_DIR)HP2100_SYS.OBJ,$(HP2100_DIR)HP2100_LPT.OBJ,\ - $(HP2100_DIR)HP2100_IPL.OBJ -HP2100_OPTIONS = /INCLUDE=($(SIMH_DIR),$(HP2100_DIR)) - -# -# Interdata 16-bit CPU. -# -ID16_DIR = SYS$DISK:[.INTERDATA] -ID16_LIB = $(LIB_DIR)ID16-$(ARCH).OLB -ID16_SOURCE = $(ID16_DIR)ID16_CPU.C,$(ID16_DIR)ID16_SYS.C,$(ID16_DIR)ID_DP.C,\ - $(ID16_DIR)ID_FD.C,$(ID16_DIR)ID_FP.C,$(ID16_DIR)ID_IDC.C,\ - $(ID16_DIR)ID_IO.C,$(ID16_DIR)ID_LP.C,$(ID16_DIR)ID_MT.C,\ - $(ID16_DIR)ID_PAS.C,$(ID16_DIR)ID_PT.C,$(ID16_DIR)ID_TT.C,\ - $(ID16_DIR)ID_UVC.C,$(ID16_DIR)ID16_DBOOT.C,$(ID16_DIR)ID_TTP.C -ID16_OBJS = $(ID16_DIR)ID16_CPU.OBJ,$(ID16_DIR)ID16_SYS.OBJ,\ - $(ID16_DIR)ID_DP.OBJ,$(ID16_DIR)ID_FD.OBJ,$(ID16_DIR)ID_FP.OBJ,\ - $(ID16_DIR)ID_IDC.OBJ,$(ID16_DIR)ID_IO.OBJ,$(ID16_DIR)ID_LP.OBJ,\ - $(ID16_DIR)ID_MT.OBJ,$(ID16_DIR)ID_PAS.OBJ,$(ID16_DIR)ID_PT.OBJ,\ - $(ID16_DIR)ID_TT.OBJ,$(ID16_DIR)ID_UVC.OBJ,\ - $(ID16_DIR)ID16_DBOOT.OBJ,$(ID16_DIR)ID_TTP.OBJ -ID16_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID16_DIR)) - -# -# Interdata 32-bit CPU. -# -ID32_DIR = SYS$DISK:[.INTERDATA] -ID32_LIB = $(LIB_DIR)ID32-$(ARCH).OLB -ID32_SOURCE = $(ID32_DIR)ID32_CPU.C,$(ID32_DIR)ID32_SYS.C,$(ID32_DIR)ID_DP.C,\ - $(ID32_DIR)ID_FD.C,$(ID32_DIR)ID_FP.C,$(ID32_DIR)ID_IDC.C,\ - $(ID32_DIR)ID_IO.C,$(ID32_DIR)ID_LP.C,$(ID32_DIR)ID_MT.C,\ - $(ID32_DIR)ID_PAS.C,$(ID32_DIR)ID_PT.C,$(ID32_DIR)ID_TT.C,\ - $(ID32_DIR)ID_UVC.C,$(ID32_DIR)ID32_DBOOT.C,$(ID32_DIR)ID_TTP.C -ID32_OBJS = $(ID32_DIR)ID32_CPU.OBJ,$(ID32_DIR)ID32_SYS.OBJ,\ - $(ID32_DIR)ID_DP.OBJ,$(ID32_DIR)ID_FD.OBJ,\ - $(ID32_DIR)ID_FP.OBJ,$(ID32_DIR)ID_IDC.OBJ,\ - $(ID32_DIR)ID_IO.OBJ,$(ID32_DIR)ID_LP.OBJ,$(ID32_DIR)ID_MT.OBJ,\ - $(ID32_DIR)ID_PAS.OBJ,$(ID32_DIR)ID_PT.OBJ,$(ID32_DIR)ID_TT.OBJ,\ - $(ID32_DIR)ID_UVC.OBJ,$(ID32_DIR)ID32_DBOOT.OBJ,\ - $(ID32_DIR)ID_TTP.OBJ -ID32_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID32_DIR)) - -# -# IBM 1130 Simulator Definitions. -# -IBM1130_DIR = SYS$DISK:[.IBM1130] -IBM1130_LIB = $(LIB_DIR)IBM1130-$(ARCH).OLB -IBM1130_SOURCE = $(IBM1130_DIR)IBM1130_CPU.C,$(IBM1130_DIR)IBM1130_CR.C,\ - $(IBM1130_DIR)IBM1130_DISK.C,$(IBM1130_DIR)IBM1130_STDDEV.C,\ - $(IBM1130_DIR)IBM1130_SYS.C,$(IBM1130_DIR)IBM1130_GDU.C,\ - $(IBM1130_DIR)IBM1130_GUI.C,$(IBM1130_DIR)IBM1130_PRT.C -IBM1130_OBJS = $(IBM1130_DIR)IBM1130_CPU.OBJ,$(IBM1130_DIR)IBM1130_CR.OBJ,\ - $(IBM1130_DIR)IBM1130_DISK.OBJ,$(IBM1130_DIR)IBM1130_STDDEV.OBJ,\ - $(IBM1130_DIR)IBM1130_SYS.OBJ,$(IBM1130_DIR)IBM1130_GDU.OBJ,\ - $(IBM1130_DIR)IBM1130_GUI.OBJ,$(IBM1130_DIR)IBM1130_PRT.OBJ -IBM1130_OPTIONS = /INCLUDE=($(SIMH_DIR),$(IBM1130_DIR)) - -# -# IBM 1401 Simulator Definitions. -# -I1401_DIR = SYS$DISK:[.I1401] -I1401_LIB = $(LIB_DIR)I1401-$(ARCH).OLB -I1401_SOURCE = $(I1401_DIR)I1401_LP.C,$(I1401_DIR)I1401_CPU.C,\ - $(I1401_DIR)I1401_IQ.C,$(I1401_DIR)I1401_CD.C,\ - $(I1401_DIR)I1401_MT.C,$(I1401_DIR)I1401_DP.C,\ - $(I1401_DIR)I1401_SYS.C -I1401_OBJS = $(I1401_DIR)I1401_LP.OBJ,$(I1401_DIR)I1401_CPU.OBJ,\ - $(I1401_DIR)I1401_IQ.OBJ,$(I1401_DIR)I1401_CD.OBJ,\ - $(I1401_DIR)I1401_MT.OBJ,$(I1401_DIR)I1401_DP.OBJ,\ - $(I1401_DIR)I1401_SYS.OBJ -I1401_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1401_DIR)) - - -# -# IBM 1620 Simulators Definitions. -# -I1620_DIR = SYS$DISK:[.I1620] -I1620_LIB = $(LIB_DIR)I1620-$(ARCH).OLB -I1620_SOURCE = $(I1620_DIR)I1620_CD.C,$(I1620_DIR)I1620_DP.C,\ - $(I1620_DIR)I1620_PT.C,$(I1620_DIR)I1620_TTY.C,\ - $(I1620_DIR)I1620_CPU.C,$(I1620_DIR)I1620_LP.C,\ - $(I1620_DIR)I1620_FP.C,$(I1620_DIR)I1620_SYS.C -I1620_OBJS = $(I1620_DIR)I1620_CD.OBJ,$(I1620_DIR)I1620_DP.OBJ,\ - $(I1620_DIR)I1620_PT.OBJ,$(I1620_DIR)I1620_TTY.OBJ,\ - $(I1620_DIR)I1620_CPU.OBJ,$(I1620_DIR)I1620_LP.OBJ,\ - $(I1620_DIR)I1620_FP.OBJ,$(I1620_DIR)I1620_SYS.OBJ -I1620_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1620_DIR)) - -# -# PDP-1 Simulator Definitions. -# -PDP1_DIR = SYS$DISK:[.PDP1] -PDP1_LIB = $(LIB_DIR)PDP1-$(ARCH).OLB -PDP1_SOURCE = $(PDP1_DIR)PDP1_LP.C,$(PDP1_DIR)PDP1_CPU.C,\ - $(PDP1_DIR)PDP1_STDDEV.C,$(PDP1_DIR)PDP1_SYS.C,\ - $(PDP1_DIR)PDP1_DT.C,$(PDP1_DIR)PDP1_DRM.C -PDP1_OBJS = $(PDP1_DIR)PDP1_LP.OBJ,$(PDP1_DIR)PDP1_CPU.OBJ,\ - $(PDP1_DIR)PDP1_STDDEV.OBJ,$(PDP1_DIR)PDP1_SYS.OBJ,\ - $(PDP1_DIR)PDP1_DT.OBJ,$(PDP1_DIR)PDP1_DRM.OBJ -PDP1_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP1_DIR)) - -# -# Digital Equipment PDP-8 Simulator Definitions. -# -PDP8_DIR = SYS$DISK:[.PDP8] -PDP8_LIB = $(LIB_DIR)PDP8-$(ARCH).OLB -PDP8_SOURCE = $(PDP8_DIR)PDP8_CPU.C,$(PDP8_DIR)PDP8_CLK.C,\ - $(PDP8_DIR)PDP8_DF.C,$(PDP8_DIR)PDP8_DT.C,\ - $(PDP8_DIR)PDP8_LP.C,$(PDP8_DIR)PDP8_MT.C,\ - $(PDP8_DIR)PDP8_PT.C,$(PDP8_DIR)PDP8_RF.C,\ - $(PDP8_DIR)PDP8_RK.C,$(PDP8_DIR)PDP8_RX.C,\ - $(PDP8_DIR)PDP8_SYS.C,$(PDP8_DIR)PDP8_TT.C,\ - $(PDP8_DIR)PDP8_TTX.C,$(PDP8_DIR)PDP8_RL.C -PDP8_OBJS = $(PDP8_DIR)PDP8_CPU.OBJ,$(PDP8_DIR)PDP8_CLK.OBJ,\ - $(PDP8_DIR)PDP8_DF.OBJ,$(PDP8_DIR)PDP8_DT.OBJ,\ - $(PDP8_DIR)PDP8_LP.OBJ,$(PDP8_DIR)PDP8_MT.OBJ,\ - $(PDP8_DIR)PDP8_PT.OBJ,$(PDP8_DIR)PDP8_RF.OBJ,\ - $(PDP8_DIR)PDP8_RK.OBJ,$(PDP8_DIR)PDP8_RX.OBJ,\ - $(PDP8_DIR)PDP8_SYS.OBJ,$(PDP8_DIR)PDP8_TT.OBJ,\ - $(PDP8_DIR)PDP8_TTX.OBJ,$(PDP8_DIR)PDP8_RL.OBJ -PDP8_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP8_DIR)) - -# -# Digital Equipment PDP-4, PDP-7, PDP-9 And PDP-15 Simulator Definitions. -# -PDP18B_DIR = SYS$DISK:[.PDP18B] -PDP4_LIB = $(LIB_DIR)PDP4-$(ARCH).OLB -PDP7_LIB = $(LIB_DIR)PDP7-$(ARCH).OLB -PDP9_LIB = $(LIB_DIR)PDP9-$(ARCH).OLB -PDP15_LIB = $(LIB_DIR)PDP15-$(ARCH).OLB -PDP18B_SOURCE = $(PDP18B_DIR)PDP18B_DT.C,$(PDP18B_DIR)PDP18B_DRM.C,\ - $(PDP18B_DIR)PDP18B_CPU.C,$(PDP18B_DIR)PDP18B_LP.C,\ - $(PDP18B_DIR)PDP18B_MT.C,$(PDP18B_DIR)PDP18B_RF.C,\ - $(PDP18B_DIR)PDP18B_RP.C,$(PDP18B_DIR)PDP18B_STDDEV.C,\ - $(PDP18B_DIR)PDP18B_SYS.C,$(PDP18B_DIR)PDP18B_TT1.C,\ - $(PDP18B_DIR)PDP18B_RB.C -PDP18B_OBJS = $(PDP18B_DIR)PDP18B_DT.OBJ,$(PDP18B_DIR)PDP18B_DRM.OBJ,\ - $(PDP18B_DIR)PDP18B_CPU.OBJ,$(PDP18B_DIR)PDP18B_LP.OBJ,\ - $(PDP18B_DIR)PDP18B_MT.OBJ,$(PDP18B_DIR)PDP18B_RF.OBJ,\ - $(PDP18B_DIR)PDP18B_RP.OBJ,$(PDP18B_DIR)PDP18B_STDDEV.OBJ,\ - $(PDP18B_DIR)PDP18B_SYS.OBJ,$(PDP18B_DIR)PDP18B_TT1.OBJ,\ - $(PDP18B_DIR)PDP18B_RB.OBJ -PDP4_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP4=1") -PDP7_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP7=1") -PDP9_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP9=1") -PDP15_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP15=1") - -# -# Digital Equipment PDP-11 Simulator Definitions. -# -PDP11_DIR = SYS$DISK:[.PDP11] -PDP11_LIB = $(LIB_DIR)PDP11-$(ARCH).OLB -PDP11_SOURCE = $(PDP11_DIR)PDP11_FP.C,$(PDP11_DIR)PDP11_CPU.C,\ - $(PDP11_DIR)PDP11_DZ.C,$(PDP11_DIR)PDP11_CIS.C,\ - $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_RK.C,\ - $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RP.C,\ - $(PDP11_DIR)PDP11_RX.C,$(PDP11_DIR)PDP11_STDDEV.C,\ - $(PDP11_DIR)PDP11_SYS.C,$(PDP11_DIR)PDP11_TC.C,\ - $(PDP11_DIR)PDP11_TM.C,$(PDP11_DIR)PDP11_TS.C,\ - $(PDP11_DIR)PDP11_IO.C,$(PDP11_DIR)PDP11_RQ.C,\ - $(PDP11_DIR)PDP11_TQ.C,$(PDP11_DIR)PDP11_PCLK.C,\ - $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_PT.C,\ - $(PDP11_DIR)PDP11_HK.C,$(PDP11_DIR)PDP11_XQ.C,\ - $(PDP11_DIR)PDP11_XU.C -PDP11_OBJS = $(PDP11_DIR)PDP11_FP.OBJ,$(PDP11_DIR)PDP11_CPU.OBJ,\ - $(PDP11_DIR)PDP11_DZ.OBJ,$(PDP11_DIR)PDP11_CIS.OBJ,\ - $(PDP11_DIR)PDP11_LP.OBJ,$(PDP11_DIR)PDP11_RK.OBJ,\ - $(PDP11_DIR)PDP11_RL.OBJ,$(PDP11_DIR)PDP11_RP.OBJ,\ - $(PDP11_DIR)PDP11_RX.OBJ,$(PDP11_DIR)PDP11_STDDEV.OBJ,\ - $(PDP11_DIR)PDP11_SYS.OBJ,$(PDP11_DIR)PDP11_TC.OBJ,\ - $(PDP11_DIR)PDP11_TM.OBJ,$(PDP11_DIR)PDP11_TS.OBJ,\ - $(PDP11_DIR)PDP11_IO.OBJ,$(PDP11_DIR)PDP11_RQ.OBJ,\ - $(PDP11_DIR)PDP11_TQ.OBJ,$(PDP11_DIR)PDP11_PCLK.OBJ,\ - $(PDP11_DIR)PDP11_RY.OBJ,$(PDP11_DIR)PDP11_PT.OBJ,\ - $(PDP11_DIR)PDP11_HK.OBJ,$(PDP11_DIR)PDP11_XQ.OBJ,\ - $(PDP11_DIR)PDP11_XU.OBJ -PDP11_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP11_DIR))/DEFINE=("VM_PDP11=1") - -# -# Digital Equipment PDP-10 Simulator Definitions. -# -PDP10_DIR = SYS$DISK:[.PDP10] -PDP10_LIB = $(LIB_DIR)PDP10-$(ARCH).OLB -PDP10_SOURCE = $(PDP10_DIR)PDP10_FE.C,\ - $(PDP10_DIR)PDP10_CPU.C,$(PDP10_DIR)PDP10_KSIO.C,\ - $(PDP10_DIR)PDP10_LP20.C,$(PDP10_DIR)PDP10_MDFP.C,\ - $(PDP10_DIR)PDP10_PAG.C,$(PDP10_DIR)PDP10_XTND.C,\ - $(PDP10_DIR)PDP10_RP.C,$(PDP10_DIR)PDP10_SYS.C,\ - $(PDP10_DIR)PDP10_TIM.C,$(PDP10_DIR)PDP10_TU.C,\ - $(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_DZ.C,\ - $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_XU.C -PDP10_OBJS = $(PDP10_DIR)PDP10_FE.OBJ,\ - $(PDP10_DIR)PDP10_CPU.OBJ,$(PDP10_DIR)PDP10_KSIO.OBJ,\ - $(PDP10_DIR)PDP10_LP20.OBJ,$(PDP10_DIR)PDP10_MDFP.OBJ,\ - $(PDP10_DIR)PDP10_PAG.OBJ,$(PDP10_DIR)PDP10_XTND.OBJ,\ - $(PDP10_DIR)PDP10_RP.OBJ,$(PDP10_DIR)PDP10_SYS.OBJ,\ - $(PDP10_DIR)PDP10_TIM.OBJ,$(PDP10_DIR)PDP10_TU.OBJ,\ - $(PDP10_DIR)PDP11_PT.OBJ,$(PDP10_DIR)PDP11_DZ.OBJ,\ - $(PDP10_DIR)PDP11_RY.OBJ,$(PDP10_DIR)PDP11_XU.OBJ -PDP10_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP10_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1","VM_PDP10=1") - -# -# IBM System 3 Simulator Definitions. -# -S3_DIR = SYS$DISK:[.S3] -S3_LIB = $(LIB_DIR)S3-$(ARCH).OLB -S3_SOURCE = $(S3_DIR)S3_CD.C,$(S3_DIR)S3_CPU.C,$(S3_DIR)S3_DISK.C,\ - $(S3_DIR)S3_LP.C,$(S3_DIR)S3_PKB.C,$(S3_DIR)S3_SYS.C -S3_OBJS = $(S3_DIR)S3_CD.OBJ,$(S3_DIR)S3_CPU.OBJ,$(S3_DIR)S3_DISK.OBJ,\ - $(S3_DIR)S3_LP.OBJ,$(S3_DIR)S3_PKB.OBJ,$(S3_DIR)S3_SYS.OBJ -S3_OPTIONS = /INCLUDE=($(SIMH_DIR),$(S3_DIR)) - -# -# SDS 940 -# -SDS_DIR = SYS$DISK:[.SDS] -SDS_LIB = $(LIB_DIR)SDS-$(ARCH).OLB -SDS_SOURCE = $(SDS_DIR)SDS_CPU.C,$(SDS_DIR)SDS_DRM.C,$(SDS_DIR)SDS_DSK.C,\ - $(SDS_DIR)SDS_IO.C,$(SDS_DIR)SDS_LP.C,$(SDS_DIR)SDS_MT.C,\ - $(SDS_DIR)SDS_MUX.C,$(SDS_DIR)SDS_RAD.C,$(SDS_DIR)SDS_STDDEV.C,\ - $(SDS_DIR)SDS_SYS.C -SDS_OBJS = $(SDS_DIR)SDS_CPU.OBJ,$(SDS_DIR)SDS_DRM.OBJ,$(SDS_DIR)SDS_DSK.OBJ,\ - $(SDS_DIR)SDS_IO.OBJ,$(SDS_DIR)SDS_LP.OBJ,$(SDS_DIR)SDS_MT.OBJ,\ - $(SDS_DIR)SDS_MUX.OBJ,$(SDS_DIR)SDS_RAD.OBJ,\ - $(SDS_DIR)SDS_STDDEV.OBJ,$(SDS_DIR)SDS_SYS.OBJ -SDS_OPTIONS = /INCLUDE=($(SIMH_DIR),$(SDS_DIR)) - -# -# Digital Equipment VAX Simulator Definitions. -# -VAX_DIR = SYS$DISK:[.VAX] -VAX_LIB = $(LIB_DIR)VAX-$(ARCH).OLB -VAX_SOURCE = $(VAX_DIR)VAX_CPU1.C,$(VAX_DIR)VAX_CPU.C,\ - $(VAX_DIR)VAX_FPA.C,$(VAX_DIR)VAX_IO.C,\ - $(VAX_DIR)VAX_MMU.C,$(VAX_DIR)VAX_STDDEV.C,\ - $(VAX_DIR)VAX_SYS.C,$(VAX_DIR)VAX_SYSDEV.C,\ - $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ - $(PDP11_DIR)PDP11_TS.C,$(PDP11_DIR)PDP11_DZ.C,\ - $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_TQ.C,\ - $(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_XQ.C -VAX_OBJS = $(VAX_DIR)VAX_CPU1.OBJ,$(VAX_DIR)VAX_CPU.OBJ,\ - $(VAX_DIR)VAX_FPA.OBJ,$(VAX_DIR)VAX_IO.OBJ,\ - $(VAX_DIR)VAX_MMU.OBJ,$(VAX_DIR)VAX_STDDEV.OBJ,\ - $(VAX_DIR)VAX_SYS.OBJ,$(VAX_DIR)VAX_SYSDEV.OBJ,\ - $(VAX_DIR)PDP11_RL.OBJ,$(VAX_DIR)PDP11_RQ.OBJ,\ - $(VAX_DIR)PDP11_TS.OBJ,$(VAX_DIR)PDP11_DZ.OBJ,\ - $(VAX_DIR)PDP11_LP.OBJ,$(VAX_DIR)PDP11_TQ.OBJ,\ - $(VAX_DIR)PDP11_PT.OBJ,$(VAX_DIR)PDP11_XQ.OBJ -# -# If On Alpha, Define "USE_INT64" As We Have INT64. -# -.IFDEF __ALPHA__ -VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1","VM_VAX=1") -.ELSE -# -# We Are On A VAX Platform So Don't Define "USE_INT64" As We Don't Have -# INT64. -# -VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR))/DEFINE=("VM_VAX=1") -.ENDIF - -# -# If On Alpha, Build Everything. -# -.IFDEF __ALPHA__ -ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ - NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP10 PDP11 PDP15 S3 VAX SDS -.ELSE -# -# Else We Are On VAX And Build Everything EXCEPT The PDP-10 Since VAX -# Dosen't Have INT64 -# -ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ - NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 VAX SDS -.ENDIF - -CLEAN : - $! - $! Clean out all targets and building Remnants - $! - $ IF (F$SEARCH("$(BIN_DIR)*.EXE;*").NES."") THEN - - DELETE/NOLOG/NOCONFIRM $(BIN_DIR)*.EXE;* - $ IF (F$SEARCH("$(LIB_DIR)*.EXE;*").NES."") THEN - - DELETE/NOLOG/NOCONFIRM $(LIB_DIR)*.OLB;* - $ IF (F$SEARCH("SYS$DISK:[...]*.OBJ;*").NES."") THEN - - DELETE/NOLOG/NOCONFIRM SYS$DISK:[...]*.OBJ;* - -# -# Build The Libraries. -# -$(LIB_DIR)SIMH-$(ARCH).OLB : $(SIMH_SOURCE) - $! - $! Building The $(SIMH_LIB) Library. - $! - $ $(CC)/OBJECT=$(SIMH_DIR) $(SIMH_SOURCE) - $ IF (F$SEARCH("$(SIMH_LIB)").EQS."") THEN - - LIBRARY/CREATE $(SIMH_LIB) - $ LIBRARY/REPLACE $(SIMH_LIB) $(SIMH_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -$(LIB_DIR)ALTAIR-$(ARCH).OLB : $(ALTAIR_SOURCE) - $! - $! Building The $(ALTAIR_LIB) Library. - $! - $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(ALTAIR_DIR) - - $(ALTAIR_SOURCE) - $ IF (F$SEARCH("$(ALTAIR_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ALTAIR_LIB) - $ LIBRARY/REPLACE $(ALTAIR_LIB) - - $(ALTAIR_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(ALTAIR_DIR)*.OBJ;* - -$(LIB_DIR)ALTAIRZ80-$(ARCH).OLB : $(ALTAIRZ80_SOURCE) - $! - $! Building The $(ALTAIRZ80_LIB) Library. - $! - $ $(CC)$(ALTAIRZ80_OPTIONS) - - /OBJECT=$(ALTAIRZ80_DIR) - - $(ALTAIRZ80_SOURCE) - $ IF (F$SEARCH("$(ALTAIRZ80_LIB)").EQS."") - - THEN LIBRARY/CREATE $(ALTAIRZ80_LIB) - $ LIBRARY/REPLACE $(ALTAIRZ80_LIB) - - $(ALTAIRZ80_OBJS) - $ DELETE/NOLOG/NOCONFIRM - - $(ALTAIRZ80_DIR)*.OBJ;* - -$(LIB_DIR)ECLIPSE-$(ARCH).OLB : $(ECLIPSE_SOURCE) - $! - $! Building The $(ECLIPSE_LIB) Library. - $! - $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(NOVA_DIR) - - $(ECLIPSE_SOURCE) - $ IF (F$SEARCH("$(ECLIPSE_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ECLIPSE_LIB) - $ LIBRARY/REPLACE $(ECLIPSE_LIB) - - $(ECLIPSE_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(NOVA_DIR)*.OBJ;* - -$(LIB_DIR)GRI-$(ARCH).OLB : $(GRI_SOURCE) - $! - $! Building The $(GRI_LIB) Library. - $! - $ $(CC)$(GRI_OPTIONS)/OBJECT=$(GRI_DIR) - - $(GRI_SOURCE) - $ IF (F$SEARCH("$(GRI_LIB)").EQS."") THEN - - LIBRARY/CREATE $(GRI_LIB) - $ LIBRARY/REPLACE $(GRI_LIB) $(GRI_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(GRI_DIR)*.OBJ;* - -$(LIB_DIR)H316-$(ARCH).OLB : $(H316_SOURCE) - $! - $! Building The $(H316_LIB) Library. - $! - $ $(CC)$(H316_OPTIONS)/OBJECT=$(H316_DIR) - - $(H316_SOURCE) - $ IF (F$SEARCH("$(H316_LIB)").EQS."") THEN - - LIBRARY/CREATE $(H316_LIB) - $ LIBRARY/REPLACE $(H316_LIB) $(H316_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(H316_DIR)*.OBJ;* - -$(LIB_DIR)HP2100-$(ARCH).OLB : $(HP2100_SOURCE) - $! - $! Building The $(HP2100_LIB) Library. - $! - $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(HP2100_DIR) - - $(HP2100_SOURCE) - $ IF (F$SEARCH("$(HP2100_LIB)").EQS."") THEN - - LIBRARY/CREATE $(HP2100_LIB) - $ LIBRARY/REPLACE $(HP2100_LIB) $(HP2100_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(HP2100_DIR)*.OBJ;* - -$(LIB_DIR)I1401-$(ARCH).OLB : $(I1401_SOURCE) - $! - $! Building The $(I1401_LIB) Library. - $! - $ $(CC)$(I1401_OPTIONS)/OBJECT=$(I1401_DIR) - - $(I1401_SOURCE) - $ IF (F$SEARCH("$(I1401_LIB)").EQS."") THEN - - LIBRARY/CREATE $(I1401_LIB) - $ LIBRARY/REPLACE $(I1401_LIB) $(I1401_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(I1401_DIR)*.OBJ;* - -$(LIB_DIR)I1620-$(ARCH).OLB : $(I1620_SOURCE) - $! - $! Building The $(I1620_LIB) Library. - $! - $ $(CC)$(I1620_OPTIONS)/OBJECT=$(I1620_DIR) - - $(I1620_SOURCE) - $ IF (F$SEARCH("$(I1620_LIB)").EQS."") THEN - - LIBRARY/CREATE $(I1620_LIB) - $ LIBRARY/REPLACE $(I1620_LIB) $(I1620_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(I1620_DIR)*.OBJ;* - -$(LIB_DIR)IBM1130-$(ARCH).OLB : $(IBM1130_SOURCE) - $! - $! Building The $(IBM1130_LIB) Library. - $! - $ $(CC)$(IBM1130_OPTIONS) - - /OBJECT=$(IBM1130_DIR) - - $(IBM1130_SOURCE) - $ IF (F$SEARCH("$(IBM1130_LIB)").EQS."") THEN - - LIBRARY/CREATE $(IBM1130_LIB) - $ LIBRARY/REPLACE $(IBM1130_LIB) $(IBM1130_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(IBM1130_DIR)*.OBJ;* - -$(LIB_DIR)ID16-$(ARCH).OLB : $(ID16_SOURCE) - $! - $! Building The $(ID16_LIB) Library. - $! - $ $(CC)$(ID16_OPTIONS)/OBJECT=$(ID16_DIR) - - $(ID16_SOURCE) - $ IF (F$SEARCH("$(ID16_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ID16_LIB) - $ LIBRARY/REPLACE $(ID16_LIB) $(ID16_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(ID16_DIR)*.OBJ;* - -$(LIB_DIR)ID32-$(ARCH).OLB : $(ID32_SOURCE) - $! - $! Building The $(ID32_LIB) Library. - $! - $ $(CC)$(ID32_OPTIONS)/OBJECT=$(ID32_DIR) - - $(ID32_SOURCE) - $ IF (F$SEARCH("$(ID32_LIB)").EQS."") THEN - - LIBRARY/CREATE $(ID32_LIB) - $ LIBRARY/REPLACE $(ID32_LIB) $(ID32_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(ID32_DIR)*.OBJ;* - -$(LIB_DIR)NOVA-$(ARCH).OLB : $(NOVA_SOURCE) - $! - $! Building The $(NOVA_LIB) Library. - $! - $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(NOVA_DIR) - - $(NOVA_SOURCE) - $ IF (F$SEARCH("$(NOVA_LIB)").EQS."") THEN - - LIBRARY/CREATE $(NOVA_LIB) - $ LIBRARY/REPLACE $(NOVA_LIB) $(NOVA_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(NOVA_DIR)*.OBJ;* - -$(LIB_DIR)PDP1-$(ARCH).OLB : $(PDP1_SOURCE) - $! - $! Building The $(PDP1_LIB) Library. - $! - $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(PDP1_DIR) - - $(PDP1_SOURCE) - $ IF (F$SEARCH("$(PDP1_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP1_LIB) - $ LIBRARY/REPLACE $(PDP1_LIB) $(PDP1_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP1_DIR)*.OBJ;* - -$(LIB_DIR)PDP4-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP4_LIB) Library. - $! - $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP4_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP4_LIB) - $ LIBRARY/REPLACE $(PDP4_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -$(LIB_DIR)PDP7-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP7_LIB) Library. - $! - $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP7_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP7_LIB) - $ LIBRARY/REPLACE $(PDP7_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -$(LIB_DIR)PDP8-$(ARCH).OLB : $(PDP8_SOURCE) - $! - $! Building The $(PDP8_LIB) Library. - $! - $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(PDP8_DIR) - - $(PDP8_SOURCE) - $ IF (F$SEARCH("$(PDP8_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP8_LIB) - $ LIBRARY/REPLACE $(PDP8_LIB) $(PDP8_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP8_DIR)*.OBJ;* - -$(LIB_DIR)PDP9-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP9_LIB) Library. - $! - $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP9_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP9_LIB) - $ LIBRARY/REPLACE $(PDP9_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -# -# If On Alpha, Build The PDP-10 Library. -# -.IFDEF __ALPHA__ -$(LIB_DIR)PDP10-$(ARCH).OLB : $(PDP10_SOURCE) - $! - $! Building The $(PDP10_LIB) Library. - $! - $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(PDP10_DIR) - - $(PDP10_SOURCE) - $ IF (F$SEARCH("$(PDP10_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP10_LIB) - $ LIBRARY/REPLACE $(PDP10_LIB) $(PDP10_OBJS) - DELETE/NOLOG/NOCONFIRM $(PDP10_DIR)*.OBJ;* -.ELSE -# -# We Are On VAX And Due To The Use of INT64 We Can't Build It. -# -$(LIB_DIR)PDP10-$(ARCH).OLB : - $! - $! Due To The Use Of INT64 We Can't Build The - $! $(LIB_DIR)PDP10-$(ARCH).OLB Library On VAX. - $! -.ENDIF - -$(LIB_DIR)PDP11-$(ARCH).OLB : $(PDP11_SOURCE) - $! - $! Building The $(PDP11_LIB) Library. - $! - $(CC)$(PDP11_OPTIONS)/OBJECT=$(PDP11_DIR) - - $(PDP11_SOURCE) - $ IF (F$SEARCH("$(PDP11_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP11_LIB) - $ LIBRARY/REPLACE $(PDP11_LIB) $(PDP11_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP11_DIR)*.OBJ;* - -$(LIB_DIR)PDP15-$(ARCH).OLB : $(PDP18B_SOURCE) - $! - $! Building The $(PDP15_LIB) Library. - $! - $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(PDP18B_DIR) - - $(PDP18B_SOURCE) - $ IF (F$SEARCH("$(PDP15_LIB)").EQS."") THEN - - LIBRARY/CREATE $(PDP15_LIB) - $ LIBRARY/REPLACE $(PDP15_LIB) $(PDP18B_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* - -$(LIB_DIR)S3-$(ARCH).OLB : $(S3_SOURCE) - $! - $! Building The $(S3_LIB) Library. - $! - $ $(CC)$(S3_OPTIONS)/OBJECT=$(S3_DIR) $(S3_SOURCE) - $ IF (F$SEARCH("$(S3_LIB)").EQS."") THEN - - LIBRARY/CREATE $(S3_LIB) - $ LIBRARY/REPLACE $(S3_LIB) $(S3_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(S3_DIR)*.OBJ;* - -$(LIB_DIR)SDS-$(ARCH).OLB : $(SDS_SOURCE) - $! - $! Building The $(SDS_LIB) Library. - $! - $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SDS_DIR) - - $(SDS_SOURCE) - $ IF (F$SEARCH("$(SDS_LIB)").EQS."") THEN - - LIBRARY/CREATE $(SDS_LIB) - $ LIBRARY/REPLACE $(SDS_LIB) $(SDS_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(SDS_DIR)*.OBJ;* - -# -# If On Alpha, Build The VAX Library. -# -$(LIB_DIR)VAX-$(ARCH).OLB : $(VAX_SOURCE) - $! - $! Building The $(VAX_LIB) Library. - $! - $ $(CC)$(VAX_OPTIONS)/OBJECT=$(VAX_DIR) - - $(VAX_SOURCE) - $ IF (F$SEARCH("$(VAX_LIB)").EQS."") THEN - - LIBRARY/CREATE $(VAX_LIB) - $ LIBRARY/REPLACE $(VAX_LIB) $(VAX_OBJS) - $ DELETE/NOLOG/NOCONFIRM $(VAX_DIR)*.OBJ;* - -# -# Individual Simulator Builds. -# -ALTAIR : $(SIMH_LIB) $(ALTAIR_LIB) - $! - $! Building The $(BIN_DIR)ALTAIR-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIR-$(ARCH).EXE - - SCP.OBJ,$(ALTAIR_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ALTAIRZ80 : $(SIMH_LIB) $(ALTAIRZ80_LIB) - $! - $! Building The $(BIN_DIR)ALTAIRZ80-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ALTAIRZ80_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIRZ80-$(ARCH).EXE - - SCP.OBJ,$(ALTAIRZ80_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ECLIPSE : $(SIMH_LIB) $(ECLIPSE_LIB) - $! - $! Building The $(BIN_DIR)ECLPISE-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ECLIPSE-$(ARCH).EXE - - SCP.OBJ,$(ECLIPSE_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -GRI : $(SIMH_LIB) $(GRI_LIB) - $! - $! Building The $(BIN_DIR)GRI-$(ARCH).EXE Simulator. - $! - $ $(CC)$(GRI_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)GRI-$(ARCH).EXE - - SCP.OBJ,$(GRI_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -H316 : $(SIMH_LIB) $(H316_LIB) - $! - $! Building The $(BIN_DIR)H316-$(ARCH).EXE Simulator. - $! - $ $(CC)$(H316_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)H316-$(ARCH).EXE - - SCP.OBJ,$(H316_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -HP2100 : $(SIMH_LIB) $(HP2100_LIB) - $! - $! Building The $(BIN_DIR)HP2100-$(ARCH).EXE Simulator. - $! - $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)HP2100-$(ARCH).EXE - - SCP.OBJ,$(HP2100_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -I1401 : $(SIMH_LIB) $(I1401_LIB) - $! - $! Building The $(BIN_DIR)I1401-$(ARCH).EXE Simulator. - $! - $ $(CC)$(I1401_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)I1401-$(ARCH).EXE - - SCP.OBJ,$(I1401_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -I1620 : $(SIMH_LIB) $(I1620_LIB) - $! - $! Building The $(BIN_DIR)I1620-$(ARCH).EXE Simulator. - $! - $ $(CC)$(I1620_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)I1620-$(ARCH).EXE - - SCP.OBJ,$(I1620_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -IBM1130 : $(SIMH_LIB) $(IBM1130_LIB) - $! - $! Building The $(BIN_DIR)IBM1130-$(ARCH).EXE Simulator. - $! - $ $(CC)$(IBM1130_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)IBM1130-$(ARCH).EXE - - SCP.OBJ,$(IBM1130_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ID16 : $(SIMH_LIB) $(ID16_LIB) - $! - $! Building The $(BIN_DIR)ID16-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ID16_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ID16-$(ARCH).EXE - - SCP.OBJ,$(ID16_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -ID32 : $(SIMH_LIB) $(ID32_LIB) - $! - $! Building The $(BIN_DIR)ID32-$(ARCH).EXE Simulator. - $! - $ $(CC)$(ID32_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ID32-$(ARCH).EXE - - SCP.OBJ,$(ID32_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -NOVA : $(SIMH_LIB) $(NOVA_LIB) - $! - $! Building The $(BIN_DIR)NOVA-$(ARCH).EXE Simulator. - $! - $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)NOVA-$(ARCH).EXE - - SCP.OBJ,$(NOVA_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP1 : $(SIMH_LIB) $(PDP1_LIB) - $! - $! Building The $(BIN_DIR)PDP1-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP1-$(ARCH).EXE - - SCP.OBJ,$(PDP1_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP4 : $(SIMH_LIB) $(PDP4_LIB) - $! - $! Building The $(BIN_DIR)PDP4-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP4-$(ARCH).EXE - - SCP.OBJ,$(PDP4_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP7 : $(SIMH_LIB) $(PDP7_LIB) - $! - $! Building The $(BIN_DIR)PDP7-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP7-$(ARCH).EXE - - SCP.OBJ,$(PDP7_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP8 : $(SIMH_LIB) $(PDP8_LIB) - $! - $! Building The $(BIN_DIR)PDP8-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP8-$(ARCH).EXE - - SCP.OBJ,$(PDP8_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP9 : $(SIMH_LIB) $(PDP9_LIB) - $! - $! Building The $(BIN_DIR)PDP9-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP9-$(ARCH).EXE - - SCP.OBJ,$(PDP9_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -# -# If On Alpha, Build The PDP-10 Simulator. -# -.IFDEF __ALPHA__ -PDP10 : $(SIMH_LIB) $(PDP10_LIB) - $! - $! Building The $(BIN_DIR)PDP10-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP10-$(ARCH).EXE - - SCP.OBJ,$(PDP10_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* -.ELSE -# -# Else We Are On VAX And Tell The User We Can't Build On VAX -# Due To The Use Of INT64. -# -PDP10 : - $! - $! Sorry, Can't Build $(BIN_DIR)PDP10-$(ARCH).EXE Simulator - $! Because It Requires The Use Of INT64. - $! -.ENDIF - -PDP11 : $(SIMH_LIB) $(PDP11_LIB) - $! - $! Building The $(BIN_DIR)PDP11-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP11_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP11-$(ARCH).EXE - - SCP.OBJ,$(PDP11_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -PDP15 : $(SIMH_LIB) $(PDP15_LIB) - $! - $! Building The $(BIN_DIR)PDP15-$(ARCH).EXE Simulator. - $! - $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP15-$(ARCH).EXE - - SCP.OBJ,$(PDP15_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -S3 : $(SIMH_LIB) $(S3_LIB) - $! - $! Building The $(BIN_DIR)S3-$(ARCH).EXE Simulator. - $! - $ $(CC)$(S3_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)S3-$(ARCH).EXE - - SCP.OBJ,$(S3_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -SDS : $(SIMH_LIB) $(SDS_LIB) - $! - $! Building The $(BIN_DIR)SDS-$(ARCH).EXE Simulator. - $! - $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)SDS-$(ARCH).EXE - - SCP.OBJ,$(SDS_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* - -VAX : $(SIMH_LIB) $(VAX_LIB) - $! - $! Building The $(BIN_DIR)VAX-$(ARCH).EXE Simulator. - $! - $ $(CC)$(VAX_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C - $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)VAX-$(ARCH).EXE - - SCP.OBJ,$(VAX_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY - $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* +# +# DESCRIP.MMS +# Written By: Robert Alan Byer +# byer@mail.ourservers.net +# +# Modified By: Mark Pizzolato +# mark@infocomm.com +# +# This MMS/MMK build script is used to compile the various simulators in +# the SIMH package for OpenVMS using DEC C v6.0-001. +# +# Notes: On VAX, the PDP-10 and VAX simulator will not be built due to the +# fact that INT64 is required for those simulators. +# +# When using DEC's MMS on an Alpha you must use +# /MACRO=("__ALPHA__=1") to compile properly. +# +# This build script will accept the following build options. +# +# ALL Just Build "Everything". +# ALTAIR Just Build The MITS Altair. +# ALTAIRZ80 Just Build The MITS Altair Z80. +# ECLIPSE Just Build The Data General Eclipse. +# GRI Just Build The GRI Corporation GRI-909. +# H316 Just Build The Honewell 316/516. +# HP2100 Just Build The Hewlett-Packard HP-2100. +# I1401 Just Build The IBM 1401. +# IBM1130 Just Build The IBM 1130. +# ID16 Just Build The Interdata 16-bit CPU. +# ID32 Just Build The Interdata 32-bit CPU. +# NOVA Just Build The Data General Nova. +# PDP1 Just Build The DEC PDP-1. +# PDP4 Just Build The DEC PDP-4. +# PDP7 Just Build The DEC PDP-7. +# PDP8 Just Build The DEC PDP-8. +# PDP9 Just Build The DEC PDP-9. +# PDP10 Just Build The DEC PDP-10. +# PDP11 Just Build The DEC PDP-11. +# PDP15 Just Build The DEC PDP-15. +# S3 Just Build The IBM System 3. +# SDS Just Build The SDS 940. +# VAX Just Build The DEC VAX. +# CLEAN Will Clean Files Back To Base Kit. +# +# To build with debugging enabled (which will also enable traceback +# information) use.. +# +# MMK/FORCE/MACRO=(DEBUG=1) +# +# This will produce an executable named {Simulator}-{VAX|AXP}-DBG.EXE +# + +# +# Define The BIN Directory Where The Executables Will Go. +# +BIN_DIR = SYS$DISK:[.BIN] + +# +# Define Our Library Directory. +# +LIB_DIR = SYS$DISK:[.LIB] + +# +# Let's See If We Are Going To Build With DEBUG Enabled. +# +.IFDEF DEBUG +CC_DEBUG = /DEBUG=ALL +LINK_DEBUG = /DEBUG/TRACEBACK +CC_OPTIMIZE = /NOOPTIMIZE +.IFDEF __ALPHA__ +CC_FLAGS = /PREFIX=ALL +ARCH = AXP-DBG +.ELSE +ARCH = VAX-DBG +CC_FLAGS = $(CC_FLAGS) +.ENDIF +.ELSE +CC_DEBUG = /NODEBUG +LINK_DEBUG = /NODEBUG/NOTRACEBACK +.IFDEF __ALPHA__ +CC_OPTIMIZE = /OPTIMIZE=(LEVEL=5,TUNE=HOST)/ARCH=HOST +CC_FLAGS = /PREFIX=ALL +ARCH = AXP +.ELSE +CC_OPTIMIZE = /OPTIMIZE +ARCH = VAX +CC_FLAGS = $(CC_FLAGS) +.ENDIF +.ENDIF + +# +# Define Our Compiler Flags +# +CC_FLAGS = $(CC_FLAGS)$(CC_DEBUG)$(CC_OPTIMIZE)/NEST=PRIMARY/NAME=(AS_IS,SHORTENED) + +# +# Define The Compile Command. +# +CC = CC/DECC$(CC_FLAGS) + +# +# First, Let's Check To Make Sure We Have A SYS$DISK:[.BIN] And +# SYS$DISK:[.LIB] Directory. +# +.FIRST + @ IF (F$SEARCH("SYS$DISK:[]BIN.DIR").EQS."") THEN CREATE/DIRECTORY $(BIN_DIR) + @ IF (F$SEARCH("SYS$DISK:[]LIB.DIR").EQS."") THEN CREATE/DIRECTORY $(LIB_DIR) + +# +# Core SIMH File Definitions. +# +SIMH_DIR = SYS$DISK:[] +SIMH_LIB = $(LIB_DIR)SIMH-$(ARCH).OLB +SIMH_SOURCE = $(SIMH_DIR)SCP_TTY.C,$(SIMH_DIR)SIM_SOCK.C,\ + $(SIMH_DIR)SIM_TMXR.C,$(SIMH_DIR)SIM_ETHER.C,\ + $(SIMH_DIR)SIM_TAPE.C +SIMH_OBJS = $(SIMH_DIR)SCP_TTY.OBJ,$(SIMH_DIR)SIM_SOCK.OBJ,\ + $(SIMH_DIR)SIM_TMXR.OBJ,$(SIMH_DIR)SIM_ETHER.OBJ,\ + $(SIMH_DIR)SIM_TAPE.OBJ + +# +# MITS Altair Simulator Definitions. +# +ALTAIR_DIR = SYS$DISK:[.ALTAIR] +ALTAIR_LIB = $(LIB_DIR)ALTAIR-$(ARCH).OLB +ALTAIR_SOURCE = $(ALTAIR_DIR)ALTAIR_SIO.C,$(ALTAIR_DIR)ALTAIR_CPU.C,\ + $(ALTAIR_DIR)ALTAIR_DSK.C,$(ALTAIR_DIR)ALTAIR_SYS.C +ALTAIR_OBJS = $(ALTAIR_DIR)ALTAIR_SIO.OBJ,$(ALTAIR_DIR)ALTAIR_CPU.OBJ,\ + $(ALTAIR_DIR)ALTAIR_DSK.OBJ,$(ALTAIR_DIR)ALTAIR_SYS.OBJ +ALTAIR_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIR_DIR)) + +# +# MITS Altair Z80 Simulator Definitions. +# +ALTAIRZ80_DIR = SYS$DISK:[.ALTAIRZ80] +ALTAIRZ80_LIB = $(LIB_DIR)ALTAIRZ80-$(ARCH).OLB +ALTAIRZ80_SOURCE = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.C,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_DSK.C,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_SIO.C,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_SYS.C,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.C +ALTAIRZ80_OBJS = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.OBJ,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_DSK.OBJ,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_SIO.OBJ,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_SYS.OBJ,\ + $(ALTAIRZ80_DIR)ALTAIRZ80_HDSK.OBJ +ALTAIRZ80_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIRZ80_DIR)) + +# +# Data General Nova Simulator Definitions. +# +NOVA_DIR = SYS$DISK:[.NOVA] +NOVA_LIB = $(LIB_DIR)NOVA-$(ARCH).OLB +NOVA_SOURCE = $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_CPU.C,\ + $(NOVA_DIR)NOVA_DKP.C,$(NOVA_DIR)NOVA_DSK.C,\ + $(NOVA_DIR)NOVA_LP.C,$(NOVA_DIR)NOVA_MTA.C,\ + $(NOVA_DIR)NOVA_PLT.C,$(NOVA_DIR)NOVA_PT.C,\ + $(NOVA_DIR)NOVA_CLK.C,$(NOVA_DIR)NOVA_TT.C,\ + $(NOVA_DIR)NOVA_TT1.C +NOVA_OBJS = $(NOVA_DIR)NOVA_SYS.OBJ,$(NOVA_DIR)NOVA_CPU.OBJ,\ + $(NOVA_DIR)NOVA_DKP.OBJ,$(NOVA_DIR)NOVA_DSK.OBJ,\ + $(NOVA_DIR)NOVA_LP.OBJ,$(NOVA_DIR)NOVA_MTA.OBJ,\ + $(NOVA_DIR)NOVA_PLT.OBJ,$(NOVA_DIR)NOVA_PT.OBJ,\ + $(NOVA_DIR)NOVA_CLK.OBJ,$(NOVA_DIR)NOVA_TT.OBJ,\ + $(NOVA_DIR)NOVA_TT1.OBJ +NOVA_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR)) + +# +# Data General Eclipse Simulator Definitions. +# +ECLIPSE_LIB = $(LIB_DIR)ECLIPSE-$(ARCH).OLB +ECLIPSE_SOURCE = $(NOVA_DIR)ECLIPSE_CPU.C,$(NOVA_DIR)ECLIPSE_TT.C,\ + $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_DKP.C,\ + $(NOVA_DIR)NOVA_DSK.C,$(NOVA_DIR)NOVA_LP.C,\ + $(NOVA_DIR)NOVA_MTA.C,$(NOVA_DIR)NOVA_PLT.C,\ + $(NOVA_DIR)NOVA_PT.C,$(NOVA_DIR)NOVA_CLK.C,\ + $(NOVA_DIR)NOVA_TT1.C +ECLIPSE_OBJS = $(NOVA_DIR)ECLIPSE_CPU.OBJ,$(NOVA_DIR)ECLIPSE_TT.OBJ,\ + $(NOVA_DIR)NOVA_SYS.OBJ,$(NOVA_DIR)NOVA_DKP.OBJ,\ + $(NOVA_DIR)NOVA_DSK.OBJ,$(NOVA_DIR)NOVA_LP.OBJ,\ + $(NOVA_DIR)NOVA_MTA.OBJ,$(NOVA_DIR)NOVA_PLT.OBJ,\ + $(NOVA_DIR)NOVA_PT.OBJ,$(NOVA_DIR)NOVA_CLK.OBJ,\ + $(NOVA_DIR)NOVA_TT1.OBJ +ECLIPSE_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR))/DEFINE=("ECLIPSE=1") + +# +# GRI Corporation GRI-909 Simulator Definitions. +# +GRI_DIR = SYS$DISK:[.GRI] +GRI_LIB = $(LIB_DIR)GRI-$(ARCH).OLB +GRI_SOURCE = $(GRI_DIR)GRI_CPU.C,$(GRI_DIR)GRI_STDDEV.C,$(GRI_DIR)GRI_SYS.C +GRI_OBJS = $(GRI_DIR)GRI_CPU.OBJ,$(GRI_DIR)GRI_STDDEV.OBJ,\ + $(GRI_DIR)GRI_SYS.OBJ +GRI_OPTIONS = /INCLUDE=($(SIMH_DIR),$(GRI_DIR)) + +# +# Honeywell 316/516 Simulator Definitions. +# +H316_DIR = SYS$DISK:[.H316] +H316_LIB = $(LIB_DIR)H316-$(ARCH).OLB +H316_SOURCE = $(H316_DIR)H316_STDDEV.C,$(H316_DIR)H316_LP.C,\ + $(H316_DIR)H316_CPU.C,$(H316_DIR)H316_SYS.C +H316_OBJS = $(H316_DIR)H316_STDDEV.OBJ,$(H316_DIR)H316_LP.OBJ,\ + $(H316_DIR)H316_CPU.OBJ,$(H316_DIR)H316_SYS.OBJ +H316_OPTIONS = /INCLUDE=($(SIMH_DIR),$(H316_DIR)) + +# +# Hewlett-Packard HP-2100 Simulator Definitions. +# +HP2100_DIR = SYS$DISK:[.HP2100] +HP2100_LIB = $(LIB_DIR)HP2100-$(ARCH).OLB +HP2100_SOURCE = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.C,\ + $(HP2100_DIR)HP2100_DQ.C,$(HP2100_DIR)HP2100_DR.C,\ + $(HP2100_DIR)HP2100_LPS.C,$(HP2100_DIR)HP2100_MS.C,\ + $(HP2100_DIR)HP2100_MT.C,$(HP2100_DIR)HP2100_MUX.C,\ + $(HP2100_DIR)HP2100_CPU.C,$(HP2100_DIR)HP2100_FP.C,\ + $(HP2100_DIR)HP2100_SYS.C,$(HP2100_DIR)HP2100_LPT.C,\ + $(HP2100_DIR)HP2100_IPL.C +HP2100_OBJS = $(HP2100_DIR)HP2100_STDDEV.OBJ,$(HP2100_DIR)HP2100_DP.OBJ,\ + $(HP2100_DIR)HP2100_DQ.OBJ,$(HP2100_DIR)HP2100_DR.OBJ,\ + $(HP2100_DIR)HP2100_LPS.OBJ,$(HP2100_DIR)HP2100_MS.OBJ,\ + $(HP2100_DIR)HP2100_MT.OBJ,$(HP2100_DIR)HP2100_MUX.OBJ,\ + $(HP2100_DIR)HP2100_CPU.OBJ,$(HP2100_DIR)HP2100_FP.OBJ,\ + $(HP2100_DIR)HP2100_SYS.OBJ,$(HP2100_DIR)HP2100_LPT.OBJ,\ + $(HP2100_DIR)HP2100_IPL.OBJ +HP2100_OPTIONS = /INCLUDE=($(SIMH_DIR),$(HP2100_DIR)) + +# +# Interdata 16-bit CPU. +# +ID16_DIR = SYS$DISK:[.INTERDATA] +ID16_LIB = $(LIB_DIR)ID16-$(ARCH).OLB +ID16_SOURCE = $(ID16_DIR)ID16_CPU.C,$(ID16_DIR)ID16_SYS.C,$(ID16_DIR)ID_DP.C,\ + $(ID16_DIR)ID_FD.C,$(ID16_DIR)ID_FP.C,$(ID16_DIR)ID_IDC.C,\ + $(ID16_DIR)ID_IO.C,$(ID16_DIR)ID_LP.C,$(ID16_DIR)ID_MT.C,\ + $(ID16_DIR)ID_PAS.C,$(ID16_DIR)ID_PT.C,$(ID16_DIR)ID_TT.C,\ + $(ID16_DIR)ID_UVC.C,$(ID16_DIR)ID16_DBOOT.C,$(ID16_DIR)ID_TTP.C +ID16_OBJS = $(ID16_DIR)ID16_CPU.OBJ,$(ID16_DIR)ID16_SYS.OBJ,\ + $(ID16_DIR)ID_DP.OBJ,$(ID16_DIR)ID_FD.OBJ,$(ID16_DIR)ID_FP.OBJ,\ + $(ID16_DIR)ID_IDC.OBJ,$(ID16_DIR)ID_IO.OBJ,$(ID16_DIR)ID_LP.OBJ,\ + $(ID16_DIR)ID_MT.OBJ,$(ID16_DIR)ID_PAS.OBJ,$(ID16_DIR)ID_PT.OBJ,\ + $(ID16_DIR)ID_TT.OBJ,$(ID16_DIR)ID_UVC.OBJ,\ + $(ID16_DIR)ID16_DBOOT.OBJ,$(ID16_DIR)ID_TTP.OBJ +ID16_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID16_DIR)) + +# +# Interdata 32-bit CPU. +# +ID32_DIR = SYS$DISK:[.INTERDATA] +ID32_LIB = $(LIB_DIR)ID32-$(ARCH).OLB +ID32_SOURCE = $(ID32_DIR)ID32_CPU.C,$(ID32_DIR)ID32_SYS.C,$(ID32_DIR)ID_DP.C,\ + $(ID32_DIR)ID_FD.C,$(ID32_DIR)ID_FP.C,$(ID32_DIR)ID_IDC.C,\ + $(ID32_DIR)ID_IO.C,$(ID32_DIR)ID_LP.C,$(ID32_DIR)ID_MT.C,\ + $(ID32_DIR)ID_PAS.C,$(ID32_DIR)ID_PT.C,$(ID32_DIR)ID_TT.C,\ + $(ID32_DIR)ID_UVC.C,$(ID32_DIR)ID32_DBOOT.C,$(ID32_DIR)ID_TTP.C +ID32_OBJS = $(ID32_DIR)ID32_CPU.OBJ,$(ID32_DIR)ID32_SYS.OBJ,\ + $(ID32_DIR)ID_DP.OBJ,$(ID32_DIR)ID_FD.OBJ,\ + $(ID32_DIR)ID_FP.OBJ,$(ID32_DIR)ID_IDC.OBJ,\ + $(ID32_DIR)ID_IO.OBJ,$(ID32_DIR)ID_LP.OBJ,$(ID32_DIR)ID_MT.OBJ,\ + $(ID32_DIR)ID_PAS.OBJ,$(ID32_DIR)ID_PT.OBJ,$(ID32_DIR)ID_TT.OBJ,\ + $(ID32_DIR)ID_UVC.OBJ,$(ID32_DIR)ID32_DBOOT.OBJ,\ + $(ID32_DIR)ID_TTP.OBJ +ID32_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID32_DIR)) + +# +# IBM 1130 Simulator Definitions. +# +IBM1130_DIR = SYS$DISK:[.IBM1130] +IBM1130_LIB = $(LIB_DIR)IBM1130-$(ARCH).OLB +IBM1130_SOURCE = $(IBM1130_DIR)IBM1130_CPU.C,$(IBM1130_DIR)IBM1130_CR.C,\ + $(IBM1130_DIR)IBM1130_DISK.C,$(IBM1130_DIR)IBM1130_STDDEV.C,\ + $(IBM1130_DIR)IBM1130_SYS.C,$(IBM1130_DIR)IBM1130_GDU.C,\ + $(IBM1130_DIR)IBM1130_GUI.C,$(IBM1130_DIR)IBM1130_PRT.C,\ + $(IBM1130_DIR)IBM1130_FMT.C +IBM1130_OBJS = $(IBM1130_DIR)IBM1130_CPU.OBJ,$(IBM1130_DIR)IBM1130_CR.OBJ,\ + $(IBM1130_DIR)IBM1130_DISK.OBJ,$(IBM1130_DIR)IBM1130_STDDEV.OBJ,\ + $(IBM1130_DIR)IBM1130_SYS.OBJ,$(IBM1130_DIR)IBM1130_GDU.OBJ,\ + $(IBM1130_DIR)IBM1130_GUI.OBJ,$(IBM1130_DIR)IBM1130_PRT.OBJ,\ + $(IBM1130_DIR)IBM1130_FMT.OBJ +IBM1130_OPTIONS = /INCLUDE=($(SIMH_DIR),$(IBM1130_DIR)) + +# +# IBM 1401 Simulator Definitions. +# +I1401_DIR = SYS$DISK:[.I1401] +I1401_LIB = $(LIB_DIR)I1401-$(ARCH).OLB +I1401_SOURCE = $(I1401_DIR)I1401_LP.C,$(I1401_DIR)I1401_CPU.C,\ + $(I1401_DIR)I1401_IQ.C,$(I1401_DIR)I1401_CD.C,\ + $(I1401_DIR)I1401_MT.C,$(I1401_DIR)I1401_DP.C,\ + $(I1401_DIR)I1401_SYS.C +I1401_OBJS = $(I1401_DIR)I1401_LP.OBJ,$(I1401_DIR)I1401_CPU.OBJ,\ + $(I1401_DIR)I1401_IQ.OBJ,$(I1401_DIR)I1401_CD.OBJ,\ + $(I1401_DIR)I1401_MT.OBJ,$(I1401_DIR)I1401_DP.OBJ,\ + $(I1401_DIR)I1401_SYS.OBJ +I1401_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1401_DIR)) + + +# +# IBM 1620 Simulators Definitions. +# +I1620_DIR = SYS$DISK:[.I1620] +I1620_LIB = $(LIB_DIR)I1620-$(ARCH).OLB +I1620_SOURCE = $(I1620_DIR)I1620_CD.C,$(I1620_DIR)I1620_DP.C,\ + $(I1620_DIR)I1620_PT.C,$(I1620_DIR)I1620_TTY.C,\ + $(I1620_DIR)I1620_CPU.C,$(I1620_DIR)I1620_LP.C,\ + $(I1620_DIR)I1620_FP.C,$(I1620_DIR)I1620_SYS.C +I1620_OBJS = $(I1620_DIR)I1620_CD.OBJ,$(I1620_DIR)I1620_DP.OBJ,\ + $(I1620_DIR)I1620_PT.OBJ,$(I1620_DIR)I1620_TTY.OBJ,\ + $(I1620_DIR)I1620_CPU.OBJ,$(I1620_DIR)I1620_LP.OBJ,\ + $(I1620_DIR)I1620_FP.OBJ,$(I1620_DIR)I1620_SYS.OBJ +I1620_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1620_DIR)) + +# +# PDP-1 Simulator Definitions. +# +PDP1_DIR = SYS$DISK:[.PDP1] +PDP1_LIB = $(LIB_DIR)PDP1-$(ARCH).OLB +PDP1_SOURCE = $(PDP1_DIR)PDP1_LP.C,$(PDP1_DIR)PDP1_CPU.C,\ + $(PDP1_DIR)PDP1_STDDEV.C,$(PDP1_DIR)PDP1_SYS.C,\ + $(PDP1_DIR)PDP1_DT.C,$(PDP1_DIR)PDP1_DRM.C +PDP1_OBJS = $(PDP1_DIR)PDP1_LP.OBJ,$(PDP1_DIR)PDP1_CPU.OBJ,\ + $(PDP1_DIR)PDP1_STDDEV.OBJ,$(PDP1_DIR)PDP1_SYS.OBJ,\ + $(PDP1_DIR)PDP1_DT.OBJ,$(PDP1_DIR)PDP1_DRM.OBJ +PDP1_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP1_DIR)) + +# +# Digital Equipment PDP-8 Simulator Definitions. +# +PDP8_DIR = SYS$DISK:[.PDP8] +PDP8_LIB = $(LIB_DIR)PDP8-$(ARCH).OLB +PDP8_SOURCE = $(PDP8_DIR)PDP8_CPU.C,$(PDP8_DIR)PDP8_CLK.C,\ + $(PDP8_DIR)PDP8_DF.C,$(PDP8_DIR)PDP8_DT.C,\ + $(PDP8_DIR)PDP8_LP.C,$(PDP8_DIR)PDP8_MT.C,\ + $(PDP8_DIR)PDP8_PT.C,$(PDP8_DIR)PDP8_RF.C,\ + $(PDP8_DIR)PDP8_RK.C,$(PDP8_DIR)PDP8_RX.C,\ + $(PDP8_DIR)PDP8_SYS.C,$(PDP8_DIR)PDP8_TT.C,\ + $(PDP8_DIR)PDP8_TTX.C,$(PDP8_DIR)PDP8_RL.C +PDP8_OBJS = $(PDP8_DIR)PDP8_CPU.OBJ,$(PDP8_DIR)PDP8_CLK.OBJ,\ + $(PDP8_DIR)PDP8_DF.OBJ,$(PDP8_DIR)PDP8_DT.OBJ,\ + $(PDP8_DIR)PDP8_LP.OBJ,$(PDP8_DIR)PDP8_MT.OBJ,\ + $(PDP8_DIR)PDP8_PT.OBJ,$(PDP8_DIR)PDP8_RF.OBJ,\ + $(PDP8_DIR)PDP8_RK.OBJ,$(PDP8_DIR)PDP8_RX.OBJ,\ + $(PDP8_DIR)PDP8_SYS.OBJ,$(PDP8_DIR)PDP8_TT.OBJ,\ + $(PDP8_DIR)PDP8_TTX.OBJ,$(PDP8_DIR)PDP8_RL.OBJ +PDP8_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP8_DIR)) + +# +# Digital Equipment PDP-4, PDP-7, PDP-9 And PDP-15 Simulator Definitions. +# +PDP18B_DIR = SYS$DISK:[.PDP18B] +PDP4_LIB = $(LIB_DIR)PDP4-$(ARCH).OLB +PDP7_LIB = $(LIB_DIR)PDP7-$(ARCH).OLB +PDP9_LIB = $(LIB_DIR)PDP9-$(ARCH).OLB +PDP15_LIB = $(LIB_DIR)PDP15-$(ARCH).OLB +PDP18B_SOURCE = $(PDP18B_DIR)PDP18B_DT.C,$(PDP18B_DIR)PDP18B_DRM.C,\ + $(PDP18B_DIR)PDP18B_CPU.C,$(PDP18B_DIR)PDP18B_LP.C,\ + $(PDP18B_DIR)PDP18B_MT.C,$(PDP18B_DIR)PDP18B_RF.C,\ + $(PDP18B_DIR)PDP18B_RP.C,$(PDP18B_DIR)PDP18B_STDDEV.C,\ + $(PDP18B_DIR)PDP18B_SYS.C,$(PDP18B_DIR)PDP18B_TT1.C,\ + $(PDP18B_DIR)PDP18B_RB.C,$(PDP18B_DIR)PDP18B_FPP.C +PDP18B_OBJS = $(PDP18B_DIR)PDP18B_DT.OBJ,$(PDP18B_DIR)PDP18B_DRM.OBJ,\ + $(PDP18B_DIR)PDP18B_CPU.OBJ,$(PDP18B_DIR)PDP18B_LP.OBJ,\ + $(PDP18B_DIR)PDP18B_MT.OBJ,$(PDP18B_DIR)PDP18B_RF.OBJ,\ + $(PDP18B_DIR)PDP18B_RP.OBJ,$(PDP18B_DIR)PDP18B_STDDEV.OBJ,\ + $(PDP18B_DIR)PDP18B_SYS.OBJ,$(PDP18B_DIR)PDP18B_TT1.OBJ,\ + $(PDP18B_DIR)PDP18B_RB.OBJ,$(PDP18B_DIR)PDP18B_FPP.OBJ +PDP4_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP4=1") +PDP7_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP7=1") +PDP9_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP9=1") +PDP15_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=("PDP15=1") + +# +# Digital Equipment PDP-11 Simulator Definitions. +# +PDP11_DIR = SYS$DISK:[.PDP11] +PDP11_LIB = $(LIB_DIR)PDP11-$(ARCH).OLB +PDP11_SOURCE = $(PDP11_DIR)PDP11_FP.C,$(PDP11_DIR)PDP11_CPU.C,\ + $(PDP11_DIR)PDP11_DZ.C,$(PDP11_DIR)PDP11_CIS.C,\ + $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_RK.C,\ + $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RP.C,\ + $(PDP11_DIR)PDP11_RX.C,$(PDP11_DIR)PDP11_STDDEV.C,\ + $(PDP11_DIR)PDP11_SYS.C,$(PDP11_DIR)PDP11_TC.C,\ + $(PDP11_DIR)PDP11_TM.C,$(PDP11_DIR)PDP11_TS.C,\ + $(PDP11_DIR)PDP11_IO.C,$(PDP11_DIR)PDP11_RQ.C,\ + $(PDP11_DIR)PDP11_TQ.C,$(PDP11_DIR)PDP11_PCLK.C,\ + $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_PT.C,\ + $(PDP11_DIR)PDP11_HK.C,$(PDP11_DIR)PDP11_XQ.C,\ + $(PDP11_DIR)PDP11_XU.C +PDP11_OBJS = $(PDP11_DIR)PDP11_FP.OBJ,$(PDP11_DIR)PDP11_CPU.OBJ,\ + $(PDP11_DIR)PDP11_DZ.OBJ,$(PDP11_DIR)PDP11_CIS.OBJ,\ + $(PDP11_DIR)PDP11_LP.OBJ,$(PDP11_DIR)PDP11_RK.OBJ,\ + $(PDP11_DIR)PDP11_RL.OBJ,$(PDP11_DIR)PDP11_RP.OBJ,\ + $(PDP11_DIR)PDP11_RX.OBJ,$(PDP11_DIR)PDP11_STDDEV.OBJ,\ + $(PDP11_DIR)PDP11_SYS.OBJ,$(PDP11_DIR)PDP11_TC.OBJ,\ + $(PDP11_DIR)PDP11_TM.OBJ,$(PDP11_DIR)PDP11_TS.OBJ,\ + $(PDP11_DIR)PDP11_IO.OBJ,$(PDP11_DIR)PDP11_RQ.OBJ,\ + $(PDP11_DIR)PDP11_TQ.OBJ,$(PDP11_DIR)PDP11_PCLK.OBJ,\ + $(PDP11_DIR)PDP11_RY.OBJ,$(PDP11_DIR)PDP11_PT.OBJ,\ + $(PDP11_DIR)PDP11_HK.OBJ,$(PDP11_DIR)PDP11_XQ.OBJ,\ + $(PDP11_DIR)PDP11_XU.OBJ +PDP11_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP11_DIR))/DEFINE=("VM_PDP11=1") + +# +# Digital Equipment PDP-10 Simulator Definitions. +# +PDP10_DIR = SYS$DISK:[.PDP10] +PDP10_LIB = $(LIB_DIR)PDP10-$(ARCH).OLB +PDP10_SOURCE = $(PDP10_DIR)PDP10_FE.C,\ + $(PDP10_DIR)PDP10_CPU.C,$(PDP10_DIR)PDP10_KSIO.C,\ + $(PDP10_DIR)PDP10_LP20.C,$(PDP10_DIR)PDP10_MDFP.C,\ + $(PDP10_DIR)PDP10_PAG.C,$(PDP10_DIR)PDP10_XTND.C,\ + $(PDP10_DIR)PDP10_RP.C,$(PDP10_DIR)PDP10_SYS.C,\ + $(PDP10_DIR)PDP10_TIM.C,$(PDP10_DIR)PDP10_TU.C,\ + $(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_DZ.C,\ + $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_XU.C +PDP10_OBJS = $(PDP10_DIR)PDP10_FE.OBJ,\ + $(PDP10_DIR)PDP10_CPU.OBJ,$(PDP10_DIR)PDP10_KSIO.OBJ,\ + $(PDP10_DIR)PDP10_LP20.OBJ,$(PDP10_DIR)PDP10_MDFP.OBJ,\ + $(PDP10_DIR)PDP10_PAG.OBJ,$(PDP10_DIR)PDP10_XTND.OBJ,\ + $(PDP10_DIR)PDP10_RP.OBJ,$(PDP10_DIR)PDP10_SYS.OBJ,\ + $(PDP10_DIR)PDP10_TIM.OBJ,$(PDP10_DIR)PDP10_TU.OBJ,\ + $(PDP10_DIR)PDP11_PT.OBJ,$(PDP10_DIR)PDP11_DZ.OBJ,\ + $(PDP10_DIR)PDP11_RY.OBJ,$(PDP10_DIR)PDP11_XU.OBJ +PDP10_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP10_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1","VM_PDP10=1") + +# +# IBM System 3 Simulator Definitions. +# +S3_DIR = SYS$DISK:[.S3] +S3_LIB = $(LIB_DIR)S3-$(ARCH).OLB +S3_SOURCE = $(S3_DIR)S3_CD.C,$(S3_DIR)S3_CPU.C,$(S3_DIR)S3_DISK.C,\ + $(S3_DIR)S3_LP.C,$(S3_DIR)S3_PKB.C,$(S3_DIR)S3_SYS.C +S3_OBJS = $(S3_DIR)S3_CD.OBJ,$(S3_DIR)S3_CPU.OBJ,$(S3_DIR)S3_DISK.OBJ,\ + $(S3_DIR)S3_LP.OBJ,$(S3_DIR)S3_PKB.OBJ,$(S3_DIR)S3_SYS.OBJ +S3_OPTIONS = /INCLUDE=($(SIMH_DIR),$(S3_DIR)) + +# +# SDS 940 +# +SDS_DIR = SYS$DISK:[.SDS] +SDS_LIB = $(LIB_DIR)SDS-$(ARCH).OLB +SDS_SOURCE = $(SDS_DIR)SDS_CPU.C,$(SDS_DIR)SDS_DRM.C,$(SDS_DIR)SDS_DSK.C,\ + $(SDS_DIR)SDS_IO.C,$(SDS_DIR)SDS_LP.C,$(SDS_DIR)SDS_MT.C,\ + $(SDS_DIR)SDS_MUX.C,$(SDS_DIR)SDS_RAD.C,$(SDS_DIR)SDS_STDDEV.C,\ + $(SDS_DIR)SDS_SYS.C +SDS_OBJS = $(SDS_DIR)SDS_CPU.OBJ,$(SDS_DIR)SDS_DRM.OBJ,$(SDS_DIR)SDS_DSK.OBJ,\ + $(SDS_DIR)SDS_IO.OBJ,$(SDS_DIR)SDS_LP.OBJ,$(SDS_DIR)SDS_MT.OBJ,\ + $(SDS_DIR)SDS_MUX.OBJ,$(SDS_DIR)SDS_RAD.OBJ,\ + $(SDS_DIR)SDS_STDDEV.OBJ,$(SDS_DIR)SDS_SYS.OBJ +SDS_OPTIONS = /INCLUDE=($(SIMH_DIR),$(SDS_DIR)) + +# +# Digital Equipment VAX Simulator Definitions. +# +VAX_DIR = SYS$DISK:[.VAX] +VAX_LIB = $(LIB_DIR)VAX-$(ARCH).OLB +VAX_SOURCE = $(VAX_DIR)VAX_CPU1.C,$(VAX_DIR)VAX_CPU.C,\ + $(VAX_DIR)VAX_FPA.C,$(VAX_DIR)VAX_IO.C,\ + $(VAX_DIR)VAX_MMU.C,$(VAX_DIR)VAX_STDDEV.C,\ + $(VAX_DIR)VAX_SYS.C,$(VAX_DIR)VAX_SYSDEV.C,\ + $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ + $(PDP11_DIR)PDP11_TS.C,$(PDP11_DIR)PDP11_DZ.C,\ + $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_TQ.C,\ + $(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_XQ.C +VAX_OBJS = $(VAX_DIR)VAX_CPU1.OBJ,$(VAX_DIR)VAX_CPU.OBJ,\ + $(VAX_DIR)VAX_FPA.OBJ,$(VAX_DIR)VAX_IO.OBJ,\ + $(VAX_DIR)VAX_MMU.OBJ,$(VAX_DIR)VAX_STDDEV.OBJ,\ + $(VAX_DIR)VAX_SYS.OBJ,$(VAX_DIR)VAX_SYSDEV.OBJ,\ + $(VAX_DIR)PDP11_RL.OBJ,$(VAX_DIR)PDP11_RQ.OBJ,\ + $(VAX_DIR)PDP11_TS.OBJ,$(VAX_DIR)PDP11_DZ.OBJ,\ + $(VAX_DIR)PDP11_LP.OBJ,$(VAX_DIR)PDP11_TQ.OBJ,\ + $(VAX_DIR)PDP11_PT.OBJ,$(VAX_DIR)PDP11_XQ.OBJ +# +# If On Alpha, Define "USE_INT64" As We Have INT64. +# +.IFDEF __ALPHA__ +VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1","VM_VAX=1") +.ELSE +# +# We Are On A VAX Platform So Don't Define "USE_INT64" As We Don't Have +# INT64. +# +VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR))/DEFINE=("VM_VAX=1") +.ENDIF + +# +# If On Alpha, Build Everything. +# +.IFDEF __ALPHA__ +ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ + NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP10 PDP11 PDP15 S3 VAX SDS +.ELSE +# +# Else We Are On VAX And Build Everything EXCEPT The PDP-10 Since VAX +# Dosen't Have INT64 +# +ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ + NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 VAX SDS +.ENDIF + +CLEAN : + $! + $! Clean out all targets and building Remnants + $! + $ IF (F$SEARCH("$(BIN_DIR)*.EXE;*").NES."") THEN - + DELETE/NOLOG/NOCONFIRM $(BIN_DIR)*.EXE;* + $ IF (F$SEARCH("$(LIB_DIR)*.EXE;*").NES."") THEN - + DELETE/NOLOG/NOCONFIRM $(LIB_DIR)*.OLB;* + $ IF (F$SEARCH("SYS$DISK:[...]*.OBJ;*").NES."") THEN - + DELETE/NOLOG/NOCONFIRM SYS$DISK:[...]*.OBJ;* + +# +# Build The Libraries. +# +$(LIB_DIR)SIMH-$(ARCH).OLB : $(SIMH_SOURCE) + $! + $! Building The $(SIMH_LIB) Library. + $! + $ $(CC)/OBJECT=$(SIMH_DIR) $(SIMH_SOURCE) + $ IF (F$SEARCH("$(SIMH_LIB)").EQS."") THEN - + LIBRARY/CREATE $(SIMH_LIB) + $ LIBRARY/REPLACE $(SIMH_LIB) $(SIMH_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +$(LIB_DIR)ALTAIR-$(ARCH).OLB : $(ALTAIR_SOURCE) + $! + $! Building The $(ALTAIR_LIB) Library. + $! + $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(ALTAIR_DIR) - + $(ALTAIR_SOURCE) + $ IF (F$SEARCH("$(ALTAIR_LIB)").EQS."") THEN - + LIBRARY/CREATE $(ALTAIR_LIB) + $ LIBRARY/REPLACE $(ALTAIR_LIB) - + $(ALTAIR_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(ALTAIR_DIR)*.OBJ;* + +$(LIB_DIR)ALTAIRZ80-$(ARCH).OLB : $(ALTAIRZ80_SOURCE) + $! + $! Building The $(ALTAIRZ80_LIB) Library. + $! + $ $(CC)$(ALTAIRZ80_OPTIONS) - + /OBJECT=$(ALTAIRZ80_DIR) - + $(ALTAIRZ80_SOURCE) + $ IF (F$SEARCH("$(ALTAIRZ80_LIB)").EQS."") - + THEN LIBRARY/CREATE $(ALTAIRZ80_LIB) + $ LIBRARY/REPLACE $(ALTAIRZ80_LIB) - + $(ALTAIRZ80_OBJS) + $ DELETE/NOLOG/NOCONFIRM - + $(ALTAIRZ80_DIR)*.OBJ;* + +$(LIB_DIR)ECLIPSE-$(ARCH).OLB : $(ECLIPSE_SOURCE) + $! + $! Building The $(ECLIPSE_LIB) Library. + $! + $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(NOVA_DIR) - + $(ECLIPSE_SOURCE) + $ IF (F$SEARCH("$(ECLIPSE_LIB)").EQS."") THEN - + LIBRARY/CREATE $(ECLIPSE_LIB) + $ LIBRARY/REPLACE $(ECLIPSE_LIB) - + $(ECLIPSE_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(NOVA_DIR)*.OBJ;* + +$(LIB_DIR)GRI-$(ARCH).OLB : $(GRI_SOURCE) + $! + $! Building The $(GRI_LIB) Library. + $! + $ $(CC)$(GRI_OPTIONS)/OBJECT=$(GRI_DIR) - + $(GRI_SOURCE) + $ IF (F$SEARCH("$(GRI_LIB)").EQS."") THEN - + LIBRARY/CREATE $(GRI_LIB) + $ LIBRARY/REPLACE $(GRI_LIB) $(GRI_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(GRI_DIR)*.OBJ;* + +$(LIB_DIR)H316-$(ARCH).OLB : $(H316_SOURCE) + $! + $! Building The $(H316_LIB) Library. + $! + $ $(CC)$(H316_OPTIONS)/OBJECT=$(H316_DIR) - + $(H316_SOURCE) + $ IF (F$SEARCH("$(H316_LIB)").EQS."") THEN - + LIBRARY/CREATE $(H316_LIB) + $ LIBRARY/REPLACE $(H316_LIB) $(H316_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(H316_DIR)*.OBJ;* + +$(LIB_DIR)HP2100-$(ARCH).OLB : $(HP2100_SOURCE) + $! + $! Building The $(HP2100_LIB) Library. + $! + $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(HP2100_DIR) - + $(HP2100_SOURCE) + $ IF (F$SEARCH("$(HP2100_LIB)").EQS."") THEN - + LIBRARY/CREATE $(HP2100_LIB) + $ LIBRARY/REPLACE $(HP2100_LIB) $(HP2100_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(HP2100_DIR)*.OBJ;* + +$(LIB_DIR)I1401-$(ARCH).OLB : $(I1401_SOURCE) + $! + $! Building The $(I1401_LIB) Library. + $! + $ $(CC)$(I1401_OPTIONS)/OBJECT=$(I1401_DIR) - + $(I1401_SOURCE) + $ IF (F$SEARCH("$(I1401_LIB)").EQS."") THEN - + LIBRARY/CREATE $(I1401_LIB) + $ LIBRARY/REPLACE $(I1401_LIB) $(I1401_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(I1401_DIR)*.OBJ;* + +$(LIB_DIR)I1620-$(ARCH).OLB : $(I1620_SOURCE) + $! + $! Building The $(I1620_LIB) Library. + $! + $ $(CC)$(I1620_OPTIONS)/OBJECT=$(I1620_DIR) - + $(I1620_SOURCE) + $ IF (F$SEARCH("$(I1620_LIB)").EQS."") THEN - + LIBRARY/CREATE $(I1620_LIB) + $ LIBRARY/REPLACE $(I1620_LIB) $(I1620_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(I1620_DIR)*.OBJ;* + +$(LIB_DIR)IBM1130-$(ARCH).OLB : $(IBM1130_SOURCE) + $! + $! Building The $(IBM1130_LIB) Library. + $! + $ $(CC)$(IBM1130_OPTIONS) - + /OBJECT=$(IBM1130_DIR) - + $(IBM1130_SOURCE) + $ IF (F$SEARCH("$(IBM1130_LIB)").EQS."") THEN - + LIBRARY/CREATE $(IBM1130_LIB) + $ LIBRARY/REPLACE $(IBM1130_LIB) $(IBM1130_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(IBM1130_DIR)*.OBJ;* + +$(LIB_DIR)ID16-$(ARCH).OLB : $(ID16_SOURCE) + $! + $! Building The $(ID16_LIB) Library. + $! + $ $(CC)$(ID16_OPTIONS)/OBJECT=$(ID16_DIR) - + $(ID16_SOURCE) + $ IF (F$SEARCH("$(ID16_LIB)").EQS."") THEN - + LIBRARY/CREATE $(ID16_LIB) + $ LIBRARY/REPLACE $(ID16_LIB) $(ID16_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(ID16_DIR)*.OBJ;* + +$(LIB_DIR)ID32-$(ARCH).OLB : $(ID32_SOURCE) + $! + $! Building The $(ID32_LIB) Library. + $! + $ $(CC)$(ID32_OPTIONS)/OBJECT=$(ID32_DIR) - + $(ID32_SOURCE) + $ IF (F$SEARCH("$(ID32_LIB)").EQS."") THEN - + LIBRARY/CREATE $(ID32_LIB) + $ LIBRARY/REPLACE $(ID32_LIB) $(ID32_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(ID32_DIR)*.OBJ;* + +$(LIB_DIR)NOVA-$(ARCH).OLB : $(NOVA_SOURCE) + $! + $! Building The $(NOVA_LIB) Library. + $! + $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(NOVA_DIR) - + $(NOVA_SOURCE) + $ IF (F$SEARCH("$(NOVA_LIB)").EQS."") THEN - + LIBRARY/CREATE $(NOVA_LIB) + $ LIBRARY/REPLACE $(NOVA_LIB) $(NOVA_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(NOVA_DIR)*.OBJ;* + +$(LIB_DIR)PDP1-$(ARCH).OLB : $(PDP1_SOURCE) + $! + $! Building The $(PDP1_LIB) Library. + $! + $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(PDP1_DIR) - + $(PDP1_SOURCE) + $ IF (F$SEARCH("$(PDP1_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP1_LIB) + $ LIBRARY/REPLACE $(PDP1_LIB) $(PDP1_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP1_DIR)*.OBJ;* + +$(LIB_DIR)PDP4-$(ARCH).OLB : $(PDP18B_SOURCE) + $! + $! Building The $(PDP4_LIB) Library. + $! + $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(PDP18B_DIR) - + $(PDP18B_SOURCE) + $ IF (F$SEARCH("$(PDP4_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP4_LIB) + $ LIBRARY/REPLACE $(PDP4_LIB) $(PDP18B_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* + +$(LIB_DIR)PDP7-$(ARCH).OLB : $(PDP18B_SOURCE) + $! + $! Building The $(PDP7_LIB) Library. + $! + $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(PDP18B_DIR) - + $(PDP18B_SOURCE) + $ IF (F$SEARCH("$(PDP7_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP7_LIB) + $ LIBRARY/REPLACE $(PDP7_LIB) $(PDP18B_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* + +$(LIB_DIR)PDP8-$(ARCH).OLB : $(PDP8_SOURCE) + $! + $! Building The $(PDP8_LIB) Library. + $! + $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(PDP8_DIR) - + $(PDP8_SOURCE) + $ IF (F$SEARCH("$(PDP8_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP8_LIB) + $ LIBRARY/REPLACE $(PDP8_LIB) $(PDP8_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP8_DIR)*.OBJ;* + +$(LIB_DIR)PDP9-$(ARCH).OLB : $(PDP18B_SOURCE) + $! + $! Building The $(PDP9_LIB) Library. + $! + $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(PDP18B_DIR) - + $(PDP18B_SOURCE) + $ IF (F$SEARCH("$(PDP9_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP9_LIB) + $ LIBRARY/REPLACE $(PDP9_LIB) $(PDP18B_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* + +# +# If On Alpha, Build The PDP-10 Library. +# +.IFDEF __ALPHA__ +$(LIB_DIR)PDP10-$(ARCH).OLB : $(PDP10_SOURCE) + $! + $! Building The $(PDP10_LIB) Library. + $! + $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(PDP10_DIR) - + $(PDP10_SOURCE) + $ IF (F$SEARCH("$(PDP10_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP10_LIB) + $ LIBRARY/REPLACE $(PDP10_LIB) $(PDP10_OBJS) + DELETE/NOLOG/NOCONFIRM $(PDP10_DIR)*.OBJ;* +.ELSE +# +# We Are On VAX And Due To The Use of INT64 We Can't Build It. +# +$(LIB_DIR)PDP10-$(ARCH).OLB : + $! + $! Due To The Use Of INT64 We Can't Build The + $! $(LIB_DIR)PDP10-$(ARCH).OLB Library On VAX. + $! +.ENDIF + +$(LIB_DIR)PDP11-$(ARCH).OLB : $(PDP11_SOURCE) + $! + $! Building The $(PDP11_LIB) Library. + $! + $(CC)$(PDP11_OPTIONS)/OBJECT=$(PDP11_DIR) - + $(PDP11_SOURCE) + $ IF (F$SEARCH("$(PDP11_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP11_LIB) + $ LIBRARY/REPLACE $(PDP11_LIB) $(PDP11_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP11_DIR)*.OBJ;* + +$(LIB_DIR)PDP15-$(ARCH).OLB : $(PDP18B_SOURCE) + $! + $! Building The $(PDP15_LIB) Library. + $! + $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(PDP18B_DIR) - + $(PDP18B_SOURCE) + $ IF (F$SEARCH("$(PDP15_LIB)").EQS."") THEN - + LIBRARY/CREATE $(PDP15_LIB) + $ LIBRARY/REPLACE $(PDP15_LIB) $(PDP18B_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(PDP18B_DIR)*.OBJ;* + +$(LIB_DIR)S3-$(ARCH).OLB : $(S3_SOURCE) + $! + $! Building The $(S3_LIB) Library. + $! + $ $(CC)$(S3_OPTIONS)/OBJECT=$(S3_DIR) $(S3_SOURCE) + $ IF (F$SEARCH("$(S3_LIB)").EQS."") THEN - + LIBRARY/CREATE $(S3_LIB) + $ LIBRARY/REPLACE $(S3_LIB) $(S3_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(S3_DIR)*.OBJ;* + +$(LIB_DIR)SDS-$(ARCH).OLB : $(SDS_SOURCE) + $! + $! Building The $(SDS_LIB) Library. + $! + $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SDS_DIR) - + $(SDS_SOURCE) + $ IF (F$SEARCH("$(SDS_LIB)").EQS."") THEN - + LIBRARY/CREATE $(SDS_LIB) + $ LIBRARY/REPLACE $(SDS_LIB) $(SDS_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(SDS_DIR)*.OBJ;* + +# +# If On Alpha, Build The VAX Library. +# +$(LIB_DIR)VAX-$(ARCH).OLB : $(VAX_SOURCE) + $! + $! Building The $(VAX_LIB) Library. + $! + $ $(CC)$(VAX_OPTIONS)/OBJECT=$(VAX_DIR) - + $(VAX_SOURCE) + $ IF (F$SEARCH("$(VAX_LIB)").EQS."") THEN - + LIBRARY/CREATE $(VAX_LIB) + $ LIBRARY/REPLACE $(VAX_LIB) $(VAX_OBJS) + $ DELETE/NOLOG/NOCONFIRM $(VAX_DIR)*.OBJ;* + +# +# Individual Simulator Builds. +# +ALTAIR : $(SIMH_LIB) $(ALTAIR_LIB) + $! + $! Building The $(BIN_DIR)ALTAIR-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIR-$(ARCH).EXE - + SCP.OBJ,$(ALTAIR_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +ALTAIRZ80 : $(SIMH_LIB) $(ALTAIRZ80_LIB) + $! + $! Building The $(BIN_DIR)ALTAIRZ80-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ALTAIRZ80_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ALTAIRZ80-$(ARCH).EXE - + SCP.OBJ,$(ALTAIRZ80_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +ECLIPSE : $(SIMH_LIB) $(ECLIPSE_LIB) + $! + $! Building The $(BIN_DIR)ECLPISE-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ECLIPSE-$(ARCH).EXE - + SCP.OBJ,$(ECLIPSE_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +GRI : $(SIMH_LIB) $(GRI_LIB) + $! + $! Building The $(BIN_DIR)GRI-$(ARCH).EXE Simulator. + $! + $ $(CC)$(GRI_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)GRI-$(ARCH).EXE - + SCP.OBJ,$(GRI_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +H316 : $(SIMH_LIB) $(H316_LIB) + $! + $! Building The $(BIN_DIR)H316-$(ARCH).EXE Simulator. + $! + $ $(CC)$(H316_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)H316-$(ARCH).EXE - + SCP.OBJ,$(H316_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +HP2100 : $(SIMH_LIB) $(HP2100_LIB) + $! + $! Building The $(BIN_DIR)HP2100-$(ARCH).EXE Simulator. + $! + $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)HP2100-$(ARCH).EXE - + SCP.OBJ,$(HP2100_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +I1401 : $(SIMH_LIB) $(I1401_LIB) + $! + $! Building The $(BIN_DIR)I1401-$(ARCH).EXE Simulator. + $! + $ $(CC)$(I1401_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)I1401-$(ARCH).EXE - + SCP.OBJ,$(I1401_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +I1620 : $(SIMH_LIB) $(I1620_LIB) + $! + $! Building The $(BIN_DIR)I1620-$(ARCH).EXE Simulator. + $! + $ $(CC)$(I1620_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)I1620-$(ARCH).EXE - + SCP.OBJ,$(I1620_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +IBM1130 : $(SIMH_LIB) $(IBM1130_LIB) + $! + $! Building The $(BIN_DIR)IBM1130-$(ARCH).EXE Simulator. + $! + $ $(CC)$(IBM1130_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)IBM1130-$(ARCH).EXE - + SCP.OBJ,$(IBM1130_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +ID16 : $(SIMH_LIB) $(ID16_LIB) + $! + $! Building The $(BIN_DIR)ID16-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ID16_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ID16-$(ARCH).EXE - + SCP.OBJ,$(ID16_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +ID32 : $(SIMH_LIB) $(ID32_LIB) + $! + $! Building The $(BIN_DIR)ID32-$(ARCH).EXE Simulator. + $! + $ $(CC)$(ID32_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)ID32-$(ARCH).EXE - + SCP.OBJ,$(ID32_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +NOVA : $(SIMH_LIB) $(NOVA_LIB) + $! + $! Building The $(BIN_DIR)NOVA-$(ARCH).EXE Simulator. + $! + $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)NOVA-$(ARCH).EXE - + SCP.OBJ,$(NOVA_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP1 : $(SIMH_LIB) $(PDP1_LIB) + $! + $! Building The $(BIN_DIR)PDP1-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP1-$(ARCH).EXE - + SCP.OBJ,$(PDP1_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP4 : $(SIMH_LIB) $(PDP4_LIB) + $! + $! Building The $(BIN_DIR)PDP4-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP4-$(ARCH).EXE - + SCP.OBJ,$(PDP4_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP7 : $(SIMH_LIB) $(PDP7_LIB) + $! + $! Building The $(BIN_DIR)PDP7-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP7-$(ARCH).EXE - + SCP.OBJ,$(PDP7_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP8 : $(SIMH_LIB) $(PDP8_LIB) + $! + $! Building The $(BIN_DIR)PDP8-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP8-$(ARCH).EXE - + SCP.OBJ,$(PDP8_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP9 : $(SIMH_LIB) $(PDP9_LIB) + $! + $! Building The $(BIN_DIR)PDP9-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP9-$(ARCH).EXE - + SCP.OBJ,$(PDP9_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +# +# If On Alpha, Build The PDP-10 Simulator. +# +.IFDEF __ALPHA__ +PDP10 : $(SIMH_LIB) $(PDP10_LIB) + $! + $! Building The $(BIN_DIR)PDP10-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP10-$(ARCH).EXE - + SCP.OBJ,$(PDP10_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* +.ELSE +# +# Else We Are On VAX And Tell The User We Can't Build On VAX +# Due To The Use Of INT64. +# +PDP10 : + $! + $! Sorry, Can't Build $(BIN_DIR)PDP10-$(ARCH).EXE Simulator + $! Because It Requires The Use Of INT64. + $! +.ENDIF + +PDP11 : $(SIMH_LIB) $(PDP11_LIB) + $! + $! Building The $(BIN_DIR)PDP11-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP11_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP11-$(ARCH).EXE - + SCP.OBJ,$(PDP11_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +PDP15 : $(SIMH_LIB) $(PDP15_LIB) + $! + $! Building The $(BIN_DIR)PDP15-$(ARCH).EXE Simulator. + $! + $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)PDP15-$(ARCH).EXE - + SCP.OBJ,$(PDP15_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +S3 : $(SIMH_LIB) $(S3_LIB) + $! + $! Building The $(BIN_DIR)S3-$(ARCH).EXE Simulator. + $! + $ $(CC)$(S3_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)S3-$(ARCH).EXE - + SCP.OBJ,$(S3_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +SDS : $(SIMH_LIB) $(SDS_LIB) + $! + $! Building The $(BIN_DIR)SDS-$(ARCH).EXE Simulator. + $! + $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)SDS-$(ARCH).EXE - + SCP.OBJ,$(SDS_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* + +VAX : $(SIMH_LIB) $(VAX_LIB) + $! + $! Building The $(BIN_DIR)VAX-$(ARCH).EXE Simulator. + $! + $ $(CC)$(VAX_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)VAX-$(ARCH).EXE - + SCP.OBJ,$(VAX_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(SIMH_DIR)*.OBJ;* diff --git a/makefile b/makefile index 22d1901c..f3c30c92 100644 --- a/makefile +++ b/makefile @@ -61,7 +61,7 @@ PDP18BD = PDP18B/ PDP18B = ${PDP18BD}pdp18b_dt.c ${PDP18BD}pdp18b_drm.c ${PDP18BD}pdp18b_cpu.c \ ${PDP18BD}pdp18b_lp.c ${PDP18BD}pdp18b_mt.c ${PDP18BD}pdp18b_rf.c \ ${PDP18BD}pdp18b_rp.c ${PDP18BD}pdp18b_stddev.c ${PDP18BD}pdp18b_sys.c \ - ${PDP18BD}pdp18b_rb.c ${PDP18BD}pdp18b_tt1.c + ${PDP18BD}pdp18b_rb.c ${PDP18BD}pdp18b_tt1.c ${PDP18BD}pdp18b_fpp.c PDP4_OPT = -DPDP4 -I ${PDP18BD} PDP7_OPT = -DPDP7 -I ${PDP18BD} PDP9_OPT = -DPDP9 -I ${PDP18BD} @@ -150,7 +150,8 @@ IBM1130D = Ibm1130/ IBM1130 = ${IBM1130D}ibm1130_cpu.c ${IBM1130D}ibm1130_cr.c \ ${IBM1130D}ibm1130_disk.c ${IBM1130D}ibm1130_stddev.c \ ${IBM1130D}ibm1130_sys.c ${IBM1130D}ibm1130_gdu.c \ - ${IBM1130D}ibm1130_gui.c ${IBM1130D}ibm1130_prt.c + ${IBM1130D}ibm1130_gui.c ${IBM1130D}ibm1130_prt.c \ + ${IBM1130D}ibm1130_fmt.c IBM1130_OPT = -I ${IBM1130D} diff --git a/scp.c b/scp.c index e2db00d6..dbe12e10 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. + 15-Jul-03 RMS Removed unnecessary test in reset_all 15-Jun-03 RMS Added register flag REG_VMIO 25-Apr-03 RMS Added extended address support (V3.0) Fixed bug in SAVE (found by Peter Schorn) @@ -1324,7 +1325,6 @@ DEVICE *dptr; uint32 i; t_stat reason; -if (start < 0) return SCPE_IERR; for (i = 0; i < start; i++) { if (sim_devices[i] == NULL) return SCPE_IERR; } for (i = start; (dptr = sim_devices[i]) != NULL; i++) { @@ -3729,7 +3729,7 @@ for (i = 0; i < sec; i++) { /* loop */ c = sim_os_poll_kbd (); /* check for stop char */ if ((c == SCPE_STOP) || stop_cpu) return SCPE_STOP; if ((i % 10) == 0) { /* Status every 10 sec */ - printf ("Waiting for console Telnet connnection\n"); + printf ("Waiting for console Telnet connection\n"); fflush (stdout); } sim_os_sleep (1); /* wait 1 second */ } diff --git a/scp_tty.c b/scp_tty.c index b5afd7c6..fe4b7e19 100644 --- a/scp_tty.c +++ b/scp_tty.c @@ -185,9 +185,9 @@ int32 i; sys$gettim (tod); /* time 0.1usec */ -/* To convert to msec, must divide 64b quantity by 10000. This is actually done +/* To convert to msec, must divide a 64b quantity by 10000. This is actually done by dividing the 96b quantity 0'time by 10000, producing 64b of quotient, the - high 32b of which are discared. This can probably be done by a clever multiply... + high 32b of which are discarded. This can probably be done by a clever multiply... */ quo = htod = 0; diff --git a/sim_rev.h b/sim_rev.h index a06c0fae..dd0f9caa 100644 --- a/sim_rev.h +++ b/sim_rev.h @@ -29,12 +29,64 @@ #define SIM_MAJOR 3 #define SIM_MINOR 0 -#define SIM_PATCH 0 +#define SIM_PATCH 1 /* V3.0 revision history patch date module(s) and fix(es) + 1 27-Jul-03 pdp1_cpu.c: updated to detect indefinite I/O wait + + pdp1_drm.c: fixed incorrect logical, missing activate, break + + pdp1_lp.c: + -- fixed bugs in instruction decoding, overprinting + -- updated to detect indefinite I/O wait + + pdp1_stddev.c: + -- changed RIM loader to be "hardware" + -- updated to detect indefinite I/O wait + + pdp1_sys.c: added block loader format support to LOAD + + pdp10_rp.c: fixed bug in read header + + pdp11_rq: fixed bug in user disk size (found by Chaskiel M Grundman) + + pdp18b_cpu.c: + -- added FP15 support + -- added XVM support + -- added EAE support to the PDP-4 + -- added PDP-15 "re-entrancy ECO" + -- fixed memory protect/skip interaction + -- fixed CAF to only reset peripherals + + pdp18b_fpp.c: added FP15 + + pdp18b_lp.c: fixed bug in Type 62 overprinting + + pdp18b_rf.c: fixed bug in set size routine + + pdp18b_stddev.c: + -- increased PTP TIME for PDP-15 operating systems + -- added hardware RIM loader for PDP-7, PDP-9, PDP-15 + + pdp18b_sys.c: added FP15, KT15, XVM instructions + + pdp8b_df.c, pdp8_rf.c: fixed bug in set size routine + + hp2100_dr.c: + -- fixed drum sizes + -- fixed variable capacity interaction with SAVE/RESTORE + + i1401_cpu.c: revised fetch to model hardware more closely + + ibm1130: fixed bugs found by APL 1130 + + nova_dsk.c: fixed bug in set size routine + + altairz80: fixed bug in real-time clock on Windows host + 0 15-Jun-03 scp.c: -- added ASSIGN/DEASSIGN -- changed RESTORE to detach files diff --git a/sim_tape.c b/sim_tape.c index bdb5c13a..ecd38a58 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -528,7 +528,7 @@ if (map) map[objc] = tpos; return objc; } -/* Find the preceding record length in a TPC file */ +/* Find the preceding record in a TPC file */ t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map) { diff --git a/simh_doc.txt b/simh_doc.txt index 85f21956..31a3ebeb 100644 --- a/simh_doc.txt +++ b/simh_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik -Subj: Simulator Usage, V3.0 -Date: 15-May-2004 +Subj: Simulator Usage, V3.1 +Date: 15-Jul-2003 COPYRIGHT NOTICE @@ -155,8 +155,7 @@ Examples: The Windows-specific Ethernet code uses the WinPCAP 3.0 package. This package for windows simulates the libpcap package that is freely -available for Unix systems. Note that WinPCAP DOES NOT SUPPORT dual -CPU environments. +available for Unix systems. WinPCAP must be installed prior to building the PDP-11 and VAX simulators with Ethernet support. diff --git a/simh_faq.txt b/simh_faq.txt index 70f4c8f2..70f0aa27 100644 --- a/simh_faq.txt +++ b/simh_faq.txt @@ -199,25 +199,13 @@ the source kit. 2.2 How do I install SIMH with Ethernet support on Windows? -First, you must download download and install the WinPCAP AutoInstaller and -developer's kit from +The pre-compiled binaries contain Ethernet support. Before running these +binaries, you must download download and install the WinPCAP AutoInstaller from http://winpcap.polito.it This creates a network packet driver in Windows for SIMH to attach to. -Second, you must download the Gnu C compiler. You can get a Windows compatible -GNU C compiler from: - - http://www.mingw.org - -Third, place the include (.h) files from the developer's kit in the C -compiler's include folder, and the libraries from the developer's kit in C -compiler's library folder. - -Then, the batch file build_mingw_ether.bat can be used to build all the -simulators, with Ethernet suport where appropriate. - To use network support, you must either be an administrator on the Windows machine (implied in Windows 9X), or you must set the windows packet driver to autostart when the system boots; see the WinPCAP FAQ page for detailed