1
0
mirror of https://github.com/simh/simh.git synced 2026-01-25 19:56:25 +00:00

Notes For V3.5-0

The source set has been extensively overhauled.  For correct
viewing, set Visual C++ or Emacs to have tab stops every 4
characters.

1. New Features in 3.4-1

1.1 All Ethernet devices

- Added Windows user-defined adapter names (from Timothe Litt)

1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors

- Added support for SET <unit>n DISCONNECT

1.3 VAX

- Added latent QDSS support
- Revised autoconfigure to handle QDSS

1.4 PDP-11

- Revised autoconfigure to handle more casees

2. Bugs Fixed in 3.4-1

2.1 SCP and libraries

- Trim trailing spaces on all input (for example, attach file names)
- Fixed sim_sock spurious SIGPIPE error in Unix/Linux
- Fixed sim_tape misallocation of TPC map array for 64b simulators

2.2 1401

- Fixed bug, CPU reset was clearing SSB through SSG

2.3 PDP-11

- Fixed bug in VH vector display routine
- Fixed XU runt packet processing (found by Tim Chapman)

2.4 Interdata

- Fixed bug in SHOW PAS CONN/STATS
- Fixed potential integer overflow exception in divide

2.5 SDS

- Fixed bug in SHOW MUX CONN/STATS

2.6 HP

- Fixed bug in SHOW MUX CONN/STATS

2.7 PDP-8

- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG

2.8 PDP-18b

- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG

2.9 Nova, Eclipse

- Fixed potential integer overflow exception in divide
This commit is contained in:
Bob Supnik
2005-09-09 18:09:00 -07:00
committed by Mark Pizzolato
parent ec60bbf329
commit b7c1eae41f
257 changed files with 107140 additions and 97195 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* pdp1_defs.h: 18b PDP simulator definitions
Copyright (c) 1993-2004, Robert M. Supnik
Copyright (c) 1993-2005, 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,13 +23,14 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
08-Feb-04 PLB Added support for display
08-Dec-03 RMS Added support for parallel drum
18-Oct-03 RMS Added DECtape off reel message
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
22-Jul-05 RMS Fixed definition of CPLS_DPY
08-Feb-04 PLB Added support for display
08-Dec-03 RMS Added support for parallel drum
18-Oct-03 RMS Added DECtape off reel message
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
The PDP-1 was Digital's first computer. The system design evolved during
its life, and as a result, specifications are sketchy or contradictory.
@@ -37,99 +38,104 @@
This simulator implements the following options:
Automatic multiply/divide Type 10
Memory extension control Type 15
Parallel drum Type 23
Serial drum Type 24
Graphic display Type 30
Line printer control Type 62
Microtape (DECtape) control Type 550
Automatic multiply/divide Type 10
Memory extension control Type 15
Parallel drum Type 23
Serial drum Type 24
Graphic display Type 30
Line printer control Type 62
Microtape (DECtape) control Type 550
*/
#ifndef _PDP1_DEFS_H_
#define _PDP1_DEFS_H_ 0
#include "sim_defs.h"
/* Simulator stop codes */
#define STOP_RSRV 1 /* must be 1 */
#define STOP_HALT 2 /* HALT */
#define STOP_IBKPT 3 /* breakpoint */
#define STOP_XCT 4 /* nested XCT's */
#define STOP_IND 5 /* nested indirects */
#define STOP_WAIT 6 /* IO wait hang */
#define STOP_DTOFF 7 /* DECtape off reel */
#define STOP_RSRV 1 /* must be 1 */
#define STOP_HALT 2 /* HALT */
#define STOP_IBKPT 3 /* breakpoint */
#define STOP_XCT 4 /* nested XCT's */
#define STOP_IND 5 /* nested indirects */
#define STOP_WAIT 6 /* IO wait hang */
#define STOP_DTOFF 7 /* DECtape off reel */
/* Memory */
#define ASIZE 16 /* address bits */
#define MAXMEMSIZE (1u << ASIZE) /* max mem size */
#define AMASK (MAXMEMSIZE - 1) /* address mask */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
#define ASIZE 16 /* address bits */
#define MAXMEMSIZE (1u << ASIZE) /* max mem size */
#define AMASK (MAXMEMSIZE - 1) /* address mask */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Architectural constants */
#define DMASK 0777777 /* data mask */
#define DAMASK 0007777 /* direct addr */
#define EPCMASK (AMASK & ~DAMASK) /* extended addr */
#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? */
#define DMASK 0777777 /* data mask */
#define DAMASK 0007777 /* direct addr */
#define EPCMASK (AMASK & ~DAMASK) /* extended addr */
#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 */
#define IOT_V_SKP 18 /* skip */
#define IOT_SKP (1 << IOT_V_SKP)
#define IOT_V_REASON (IOT_V_SKP + 1) /* reason */
#define IOT_REASON (1 << IOT_V_REASON)
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
#define IOT_V_SKP 18 /* skip */
#define IOT_SKP (1 << IOT_V_SKP)
#define IOT_V_REASON (IOT_V_SKP + 1) /* reason */
#define IOT_REASON (1 << IOT_V_REASON)
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
/* I/O status flags */
#define IOS_V_LPN 17 /* light pen */
#define IOS_V_PTR 16 /* paper tape reader */
#define IOS_V_TTO 15 /* typewriter out */
#define IOS_V_TTI 14 /* typewriter in */
#define IOS_V_PTP 13 /* paper tape punch */
#define IOS_V_DRM 12 /* drum */
#define IOS_V_SQB 11 /* sequence break */
#define IOS_V_PNT 2 /* print done */
#define IOS_V_SPC 1 /* space done */
#define IOS_V_DRP 0 /* parallel drum busy */
#define IOS_V_LPN 17 /* light pen */
#define IOS_V_PTR 16 /* paper tape reader */
#define IOS_V_TTO 15 /* typewriter out */
#define IOS_V_TTI 14 /* typewriter in */
#define IOS_V_PTP 13 /* paper tape punch */
#define IOS_V_DRM 12 /* drum */
#define IOS_V_SQB 11 /* sequence break */
#define IOS_V_PNT 2 /* print done */
#define IOS_V_SPC 1 /* space done */
#define IOS_V_DRP 0 /* parallel drum busy */
#define IOS_LPN (1 << IOS_V_LPN)
#define IOS_PTR (1 << IOS_V_PTR)
#define IOS_TTO (1 << IOS_V_TTO)
#define IOS_TTI (1 << IOS_V_TTI)
#define IOS_PTP (1 << IOS_V_PTP)
#define IOS_DRM (1 << IOS_V_DRM)
#define IOS_SQB (1 << IOS_V_SQB)
#define IOS_PNT (1 << IOS_V_PNT)
#define IOS_SPC (1 << IOS_V_SPC)
#define IOS_DRP (1 << IOS_V_DRP)
#define IOS_LPN (1 << IOS_V_LPN)
#define IOS_PTR (1 << IOS_V_PTR)
#define IOS_TTO (1 << IOS_V_TTO)
#define IOS_TTI (1 << IOS_V_TTI)
#define IOS_PTP (1 << IOS_V_PTP)
#define IOS_DRM (1 << IOS_V_DRM)
#define IOS_SQB (1 << IOS_V_SQB)
#define IOS_PNT (1 << IOS_V_PNT)
#define IOS_SPC (1 << IOS_V_SPC)
#define IOS_DRP (1 << IOS_V_DRP)
/* Completion pulses */
#define CPLS_V_PTR 5
#define CPLS_V_PTP 4
#define CPLS_V_TTO 3
#define CPLS_V_LPT 2
#define CPLS_V_DPY 1
#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)
#define CPLS_DPY (1 << CPLS_V_TTY)
#define CPLS_V_PTR 5
#define CPLS_V_PTP 4
#define CPLS_V_TTO 3
#define CPLS_V_LPT 2
#define CPLS_V_DPY 1
#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)
#define CPLS_DPY (1 << CPLS_V_DPY)
/* Sequence break flags */
#define SB_V_IP 0 /* in progress */
#define SB_V_RQ 1 /* request */
#define SB_V_ON 2 /* enabled */
#define SB_V_IP 0 /* in progress */
#define SB_V_RQ 1 /* request */
#define SB_V_ON 2 /* enabled */
#define SB_IP (1 << SB_V_IP)
#define SB_RQ (1 << SB_V_RQ)
#define SB_ON (1 << SB_V_ON)
#define SB_IP (1 << SB_V_IP)
#define SB_RQ (1 << SB_V_RQ)
#define SB_ON (1 << SB_V_ON)
#endif

View File

@@ -7,8 +7,8 @@ Date: 15-Nov-2004
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2004, written by Robert M Supnik
Copyright (c) 1993-2004, Robert M Supnik
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, 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"),
@@ -27,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary:
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
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.
This memorandum documents the PDP-1 simulator.

View File

@@ -1,6 +1,6 @@
/* pdp1_drm.c: PDP-1 drum simulator
Copyright (c) 1993-2004, Robert M Supnik
Copyright (c) 1993-2005, 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"),
@@ -19,18 +19,18 @@
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
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.
drp Type 23 parallel drum
drm Type 24 serial drum
drp Type 23 parallel drum
drm Type 24 serial drum
08-Dec-03 RMS Added parallel drum support
Fixed bug in DBL/DCN decoding
26-Oct-03 RMS Cleaned up buffer copy code
23-Jul-03 RMS Fixed incorrect logical, missing activate
05-Dec-02 RMS Cloned from pdp18b_drm.c
08-Dec-03 RMS Added parallel drum support
Fixed bug in DBL/DCN decoding
26-Oct-03 RMS Cleaned up buffer copy code
23-Jul-03 RMS Fixed incorrect logical, missing activate
05-Dec-02 RMS Cloned from pdp18b_drm.c
*/
#include "pdp1_defs.h"
@@ -38,38 +38,38 @@
/* Serial drum constants */
#define DRM_NUMWDS 256 /* words/sector */
#define DRM_NUMSC 2 /* sectors/track */
#define DRM_NUMTR 256 /* tracks/drum */
#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */
#define DRM_SIZE (DRM_NUMTR * DRM_NUMWDT) /* words/drum */
#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */
#define DRM_NUMWDS 256 /* words/sector */
#define DRM_NUMSC 2 /* sectors/track */
#define DRM_NUMTR 256 /* tracks/drum */
#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */
#define DRM_SIZE (DRM_NUMTR * DRM_NUMWDT) /* words/drum */
#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */
/* Parallel drum constants */
#define DRP_NUMWDT 4096 /* words/track */
#define DRP_NUMTK 32 /* tracks/drum */
#define DRP_SIZE (DRP_NUMWDT * DRP_NUMTK) /* words/drum */
#define DRP_V_RWE 17 /* read/write enable */
#define DRP_V_FLD 12 /* drum field */
#define DRP_M_FLD 037
#define DRP_TAMASK 07777 /* track address */
#define DRP_WCMASK 07777 /* word count */
#define DRP_MAINCM 07777 /* mem addr incr */
#define DRP_GETRWE(x) (((x) >> DRP_V_RWE) & 1)
#define DRP_GETRWF(x) (((x) >> DRP_V_FLD) & DRP_M_FLD)
#define DRP_NUMWDT 4096 /* words/track */
#define DRP_NUMTK 32 /* tracks/drum */
#define DRP_SIZE (DRP_NUMWDT * DRP_NUMTK) /* words/drum */
#define DRP_V_RWE 17 /* read/write enable */
#define DRP_V_FLD 12 /* drum field */
#define DRP_M_FLD 037
#define DRP_TAMASK 07777 /* track address */
#define DRP_WCMASK 07777 /* word count */
#define DRP_MAINCM 07777 /* mem addr incr */
#define DRP_GETRWE(x) (((x) >> DRP_V_RWE) & 1)
#define DRP_GETRWF(x) (((x) >> DRP_V_FLD) & DRP_M_FLD)
/* Parameters in the unit descriptor */
#define FUNC u4 /* function */
#define DRM_READ 000 /* read */
#define DRM_WRITE 010 /* write */
#define DRP_RW 000 /* read/write */
#define DRP_BRK 001 /* break on address */
#define FUNC u4 /* function */
#define DRM_READ 000 /* read */
#define DRM_WRITE 010 /* write */
#define DRP_RW 000 /* read/write */
#define DRP_BRK 001 /* break on address */
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) DRM_NUMWDT)))
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) DRM_NUMWDT)))
extern int32 M[];
extern int32 iosta, sbs;
extern int32 stop_inst;
@@ -77,25 +77,25 @@ extern UNIT cpu_unit;
/* Serial drum variables */
uint32 drm_da = 0; /* track address */
uint32 drm_ma = 0; /* memory address */
uint32 drm_err = 0; /* error flag */
uint32 drm_wlk = 0; /* write lock */
int32 drm_time = 4; /* inter-word time */
int32 drm_stopioe = 1; /* stop on error */
uint32 drm_da = 0; /* track address */
uint32 drm_ma = 0; /* memory address */
uint32 drm_err = 0; /* error flag */
uint32 drm_wlk = 0; /* write lock */
int32 drm_time = 4; /* inter-word time */
int32 drm_stopioe = 1; /* stop on error */
/* Parallel drum variables */
uint32 drp_rde = 0; /* read enable */
uint32 drp_wre = 0; /* write enable */
uint32 drp_rdf = 0; /* read field */
uint32 drp_wrf = 0; /* write field */
uint32 drp_ta = 0; /* track address */
uint32 drp_wc = 0; /* word count */
uint32 drp_ma = 0; /* memory address */
uint32 drp_err = 0; /* error */
int32 drp_time = 2; /* inter-word time */
int32 drp_stopioe = 1; /* stop on error */
uint32 drp_rde = 0; /* read enable */
uint32 drp_wre = 0; /* write enable */
uint32 drp_rdf = 0; /* read field */
uint32 drp_wrf = 0; /* write field */
uint32 drp_ta = 0; /* track address */
uint32 drp_wc = 0; /* word count */
uint32 drp_ma = 0; /* memory address */
uint32 drp_err = 0; /* error */
int32 drp_time = 2; /* inter-word time */
int32 drp_stopioe = 1; /* stop on error */
/* Forward declarations */
@@ -106,64 +106,70 @@ t_stat drp_reset (DEVICE *dptr);
/* DRM data structures
drm_dev DRM device descriptor
drm_unit DRM unit descriptor
drm_reg DRM register list
drm_dev DRM device descriptor
drm_unit DRM unit descriptor
drm_reg DRM register list
*/
UNIT drm_unit =
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
DRM_SIZE) };
UNIT drm_unit = {
UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
DRM_SIZE)
};
REG drm_reg[] = {
{ ORDATA (DA, drm_da, 9) },
{ ORDATA (MA, drm_ma, 16) },
{ FLDATA (DONE, iosta, IOS_V_DRM) },
{ FLDATA (ERR, drm_err, 0) },
{ ORDATA (WLK, drm_wlk, 32) },
{ DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, drm_stopioe, 0) },
{ NULL } };
{ ORDATA (DA, drm_da, 9) },
{ ORDATA (MA, drm_ma, 16) },
{ FLDATA (DONE, iosta, IOS_V_DRM) },
{ FLDATA (ERR, drm_err, 0) },
{ ORDATA (WLK, drm_wlk, 32) },
{ DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, drm_stopioe, 0) },
{ NULL }
};
DEVICE drm_dev = {
"DRM", &drm_unit, drm_reg, NULL,
1, 8, 20, 1, 8, 18,
NULL, NULL, &drm_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE };
"DRM", &drm_unit, drm_reg, NULL,
1, 8, 20, 1, 8, 18,
NULL, NULL, &drm_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE
};
/* DRP data structures
drp_dev DRP device descriptor
drp_unit DRP unit descriptor
drp_reg DRP register list
drp_dev DRP device descriptor
drp_unit DRP unit descriptor
drp_reg DRP register list
*/
UNIT drp_unit =
{ UDATA (&drp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
DRM_SIZE) };
UNIT drp_unit = {
UDATA (&drp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
DRM_SIZE)
};
REG drp_reg[] = {
{ ORDATA (TA, drp_ta, 12) },
{ ORDATA (RDF, drp_rdf, 5) },
{ FLDATA (RDE, drp_rde, 0) },
{ FLDATA (WRF, drp_wrf, 5) },
{ FLDATA (WRE, drp_wre, 0) },
{ ORDATA (MA, drp_ma, 16) },
{ ORDATA (WC, drp_wc, 12) },
{ FLDATA (BUSY, iosta, IOS_V_DRP) },
{ FLDATA (ERR, drp_err, 0) },
{ DRDATA (TIME, drp_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, drp_stopioe, 0) },
{ NULL } };
{ ORDATA (TA, drp_ta, 12) },
{ ORDATA (RDF, drp_rdf, 5) },
{ FLDATA (RDE, drp_rde, 0) },
{ FLDATA (WRF, drp_wrf, 5) },
{ FLDATA (WRE, drp_wre, 0) },
{ ORDATA (MA, drp_ma, 16) },
{ ORDATA (WC, drp_wc, 12) },
{ FLDATA (BUSY, iosta, IOS_V_DRP) },
{ FLDATA (ERR, drp_err, 0) },
{ DRDATA (TIME, drp_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, drp_stopioe, 0) },
{ NULL }
};
DEVICE drp_dev = {
"DRP", &drp_unit, drp_reg, NULL,
1, 8, 20, 1, 8, 18,
NULL, NULL, &drp_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE | DEV_DIS };
"DRP", &drp_unit, drp_reg, NULL,
1, 8, 20, 1, 8, 18,
NULL, NULL, &drp_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE | DEV_DIS
};
/* IOT routines */
int32 drm (int32 IR, int32 dev, int32 dat)
@@ -171,71 +177,85 @@ int32 drm (int32 IR, int32 dev, int32 dat)
int32 t;
int32 pulse = (IR >> 6) & 037;
if ((drm_dev.flags & DEV_DIS) == 0) { /* serial enabled? */
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 = dat & AMASK; /* load mem addr */
drm_unit.FUNC = pulse & DRM_WRITE; /* save function */
break;
case 062: /* DBL, DCN */
if ((pulse & 010) == 0) /* DBL? */
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 (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 (dat | IOT_SKP);
} /* end case */
return dat; } /* end if serial */
if ((drm_dev.flags & DEV_DIS) == 0) { /* serial enabled? */
if ((pulse != 001) && (pulse != 011)) /* invalid pulse? */
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
switch (dev) { /* switch on device */
if ((drp_dev.flags & DEV_DIS) == 0) { /* parallel enabled? */
switch (dev) { /* switch on device */
case 061: /* DIA, DBA */
drp_err = 0; /* clear error */
iosta = iosta & ~IOS_DRP; /* not busy */
drp_rde = DRP_GETRWE (dat); /* set read enable */
drp_rdf = DRP_GETRWF (dat); /* set read field */
drp_ta = dat & DRP_TAMASK; /* set track addr */
if (IR & 02000) { /* DBA? */
t = drp_ta - GET_POS (drp_time); /* delta words */
if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */
sim_activate (&drp_unit, t); /* start operation */
drp_unit.FUNC = DRP_BRK; } /* mark as break */
else drp_unit.FUNC = DRP_RW; /* no, read/write */
break;
case 062: /* DWC, DRA */
if (IR & 02000) dat = GET_POS (drp_time) | /* DRA, get position */
(drp_err? 0400000: 0);
else { /* DWC */
drp_wre = DRP_GETRWE (dat); /* set write enable */
drp_wrf = DRP_GETRWF (dat); /* set write field */
drp_wc = dat & DRP_WCMASK; } /* set word count */
break;
case 063: /* DCL */
drp_ma = dat & AMASK; /* set mem address */
t = drp_ta - GET_POS (drp_time); /* delta words */
if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */
sim_activate (&drp_unit, t); /* start operation */
iosta = iosta | IOS_DRP; /* set busy */
break;
case 064: /* not assigned */
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
} /* end case */
return dat; } /* end if parallel */
case 061: /* DWR, DRD */
drm_ma = dat & AMASK; /* load mem addr */
drm_unit.FUNC = pulse & DRM_WRITE; /* save function */
break;
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
case 062: /* DBL, DCN */
if ((pulse & 010) == 0) /* DBL? */
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 (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 (dat | IOT_SKP);
} /* end case */
return dat;
} /* end if serial */
if ((drp_dev.flags & DEV_DIS) == 0) { /* parallel enabled? */
switch (dev) { /* switch on device */
case 061: /* DIA, DBA */
drp_err = 0; /* clear error */
iosta = iosta & ~IOS_DRP; /* not busy */
drp_rde = DRP_GETRWE (dat); /* set read enable */
drp_rdf = DRP_GETRWF (dat); /* set read field */
drp_ta = dat & DRP_TAMASK; /* set track addr */
if (IR & 02000) { /* DBA? */
t = drp_ta - GET_POS (drp_time); /* delta words */
if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */
sim_activate (&drp_unit, t); /* start operation */
drp_unit.FUNC = DRP_BRK; /* mark as break */
}
else drp_unit.FUNC = DRP_RW; /* no, read/write */
break;
case 062: /* DWC, DRA */
if (IR & 02000) dat = GET_POS (drp_time) | /* DRA, get position */
(drp_err? 0400000: 0);
else { /* DWC */
drp_wre = DRP_GETRWE (dat); /* set write enable */
drp_wrf = DRP_GETRWF (dat); /* set write field */
drp_wc = dat & DRP_WCMASK; /* set word count */
}
break;
case 063: /* DCL */
drp_ma = dat & AMASK; /* set mem address */
t = drp_ta - GET_POS (drp_time); /* delta words */
if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */
sim_activate (&drp_unit, t); /* start operation */
iosta = iosta | IOS_DRP; /* set busy */
break;
case 064: /* not assigned */
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
} /* end case */
return dat;
} /* end if parallel */
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
}
/* Serial unit service - this code assumes the entire drum is buffered */
t_stat drm_svc (UNIT *uptr)
@@ -243,26 +263,31 @@ t_stat drm_svc (UNIT *uptr)
uint32 i, da;
uint32 *fbuf = uptr->filebuf;
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
drm_err = 1; /* set error */
iosta = iosta | IOS_DRM; /* set done */
sbs = sbs | SB_RQ; /* req intr */
return IORETURN (drm_stopioe, SCPE_UNATT); }
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
drm_err = 1; /* set error */
iosta = iosta | IOS_DRM; /* set done */
sbs = sbs | SB_RQ; /* req intr */
return IORETURN (drm_stopioe, SCPE_UNATT);
}
da = drm_da * DRM_NUMWDS; /* compute dev addr */
for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
if (uptr->FUNC == DRM_READ) { /* read? */
if (MEM_ADDR_OK (drm_ma)) /* if !nxm */
M[drm_ma] = fbuf[da]; } /* read word */
else { /* write */
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
else { /* not locked */
fbuf[da] = M[drm_ma]; /* write word */
if (da >= uptr->hwmark) uptr->hwmark = da + 1; } }
drm_ma = (drm_ma + 1) & AMASK; } /* incr mem addr */
drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */
iosta = iosta | IOS_DRM; /* set done */
sbs = sbs | SB_RQ; /* req intr */
da = drm_da * DRM_NUMWDS; /* compute dev addr */
for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
if (uptr->FUNC == DRM_READ) { /* read? */
if (MEM_ADDR_OK (drm_ma)) /* if !nxm */
M[drm_ma] = fbuf[da]; /* read word */
}
else { /* write */
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
else { /* not locked */
fbuf[da] = M[drm_ma]; /* write word */
if (da >= uptr->hwmark) uptr->hwmark = da + 1;
}
}
drm_ma = (drm_ma + 1) & AMASK; /* incr mem addr */
}
drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */
iosta = iosta | IOS_DRM; /* set done */
sbs = sbs | SB_RQ; /* req intr */
return SCPE_OK;
}
@@ -271,14 +296,14 @@ return SCPE_OK;
t_stat drm_reset (DEVICE *dptr)
{
if ((drm_dev.flags & DEV_DIS) == 0)
drp_dev.flags = drp_dev.flags | DEV_DIS;
drp_dev.flags = drp_dev.flags | DEV_DIS;
drm_da = drm_ma = drm_err = 0;
iosta = iosta & ~IOS_DRM;
sim_cancel (&drm_unit);
drm_unit.FUNC = 0;
return SCPE_OK;
}
/* Parallel unit service - this code assumes the entire drum is buffered */
t_stat drp_svc (UNIT *uptr)
@@ -286,25 +311,26 @@ t_stat drp_svc (UNIT *uptr)
uint32 i, lim;
uint32 *fbuf = uptr->filebuf;
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
drp_err = 1; /* set error */
iosta = iosta & ~IOS_DRP; /* clear busy */
if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */
return IORETURN (drp_stopioe, SCPE_UNATT); }
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
drp_err = 1; /* set error */
iosta = iosta & ~IOS_DRP; /* clear busy */
if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */
return IORETURN (drp_stopioe, SCPE_UNATT);
}
if (uptr->FUNC == DRP_RW) { /* read/write? */
lim = drp_wc? drp_wc: DRP_TAMASK + 1; /* eff word count */
for (i = 0; i < lim; i++) { /* do transfer */
if (drp_wre) /* write enabled? */
fbuf[(drp_wrf << DRP_V_FLD) | drp_ta] = M[drp_ma];
if (drp_rde && MEM_ADDR_OK (drp_ma)) /* read enabled? */
M[drp_ma] = fbuf[(drp_rdf << DRP_V_FLD) | drp_ta];
drp_ta = (drp_ta + 1) & DRP_TAMASK; /* incr track addr */
drp_ma = ((drp_ma & ~DRP_MAINCM) | ((drp_ma + 1) & DRP_MAINCM));
} /* end for */
} /* end if */
iosta = iosta & ~IOS_DRP; /* clear busy */
if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */
if (uptr->FUNC == DRP_RW) { /* read/write? */
lim = drp_wc? drp_wc: DRP_TAMASK + 1; /* eff word count */
for (i = 0; i < lim; i++) { /* do transfer */
if (drp_wre) /* write enabled? */
fbuf[(drp_wrf << DRP_V_FLD) | drp_ta] = M[drp_ma];
if (drp_rde && MEM_ADDR_OK (drp_ma)) /* read enabled? */
M[drp_ma] = fbuf[(drp_rdf << DRP_V_FLD) | drp_ta];
drp_ta = (drp_ta + 1) & DRP_TAMASK; /* incr track addr */
drp_ma = ((drp_ma & ~DRP_MAINCM) | ((drp_ma + 1) & DRP_MAINCM));
} /* end for */
} /* end if */
iosta = iosta & ~IOS_DRP; /* clear busy */
if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */
return SCPE_OK;
}
@@ -313,7 +339,7 @@ return SCPE_OK;
t_stat drp_reset (DEVICE *dptr)
{
if ((drp_dev.flags & DEV_DIS) == 0)
drm_dev.flags = drm_dev.flags | DEV_DIS;
drm_dev.flags = drm_dev.flags | DEV_DIS;
drp_ta = 0;
drp_rde = drp_rdf = drp_wre = drp_wrf = 0;
drp_err = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* pdp1_lp.c: PDP-1 line printer simulator
Copyright (c) 1993-2004, Robert M. Supnik
Copyright (c) 1993-2005, 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"),
@@ -19,36 +19,37 @@
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
Except as contained in this notice, the name of Robert M Supnik shall not be
bused in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
lpt Type 62 line printer for the PDP-1
lpt Type 62 line printer for the PDP-1
07-Sep-03 RMS Changed ioc to ios
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
07-Sep-03 RMS Changed ioc to ios
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
*/
#include "pdp1_defs.h"
#define BPTR_MAX 40 /* pointer max */
#define LPT_BSIZE (BPTR_MAX * 3) /* line size */
#define BPTR_MASK 077 /* buf ptr mask */
#define BPTR_MAX 40 /* pointer max */
#define LPT_BSIZE (BPTR_MAX * 3) /* line size */
#define BPTR_MASK 077 /* buf ptr mask */
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 */
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','^','<',
'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','*','.','+',']','|','[' };
' ','1','2','3','4','5','6','7','8','9','\'','~','#','V','^','<',
'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','*','.','+',']','|','['
};
extern int32 ios, cpls, sbs, iosta;
extern int32 stop_inst;
@@ -58,112 +59,127 @@ t_stat lpt_reset (DEVICE *dptr);
/* LPT data structures
lpt_dev LPT device descriptor
lpt_unit LPT unit
lpt_reg LPT register list
lpt_dev LPT device descriptor
lpt_unit LPT unit
lpt_reg LPT register list
*/
UNIT lpt_unit = {
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
};
REG lpt_reg[] = {
{ ORDATA (BUF, lpt_unit.buf, 8) },
{ FLDATA (PNT, iosta, IOS_V_PNT) },
{ FLDATA (SPC, iosta, IOS_V_SPC) },
{ 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) },
{ BRDATA (LBUF, lpt_buf, 8, 8, LPT_BSIZE) },
{ NULL } };
{ ORDATA (BUF, lpt_unit.buf, 8) },
{ FLDATA (PNT, iosta, IOS_V_PNT) },
{ FLDATA (SPC, iosta, IOS_V_SPC) },
{ 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) },
{ BRDATA (LBUF, lpt_buf, 8, 8, LPT_BSIZE) },
{ NULL }
};
DEVICE lpt_dev = {
"LPT", &lpt_unit, lpt_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &lpt_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE };
"LPT", &lpt_unit, lpt_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &lpt_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE
};
/* Line printer IOT routine */
int32 lpt (int32 inst, int32 dev, int32 dat)
{
int32 i;
if (lpt_dev.flags & DEV_DIS) /* disabled? */
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_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? */
ios = 0; /* clear flop */
cpls = cpls | CPLS_LPT; } /* request completion */
if (lpt_dev.flags & DEV_DIS) /* disabled? */
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_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? */
ios = 0; /* clear flop */
cpls = cpls | CPLS_LPT; /* request completion */
}
else cpls = cpls & ~CPLS_LPT;
sim_activate (&lpt_unit, lpt_unit.wait); /* activate */
sim_activate (&lpt_unit, lpt_unit.wait); /* activate */
return dat;
}
/* Unit service, printer is in one of three states
lpt_spc = 000 write buffer to file, set overprint
lpt_iot = 02x space command x, clear overprint
lpt_spc = 000 write buffer to file, set overprint
lpt_iot = 02x space command x, clear overprint
*/
t_stat lpt_svc (UNIT *uptr)
{
int32 i;
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\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\n\n\n\n\n\n\n\n\n\n\n\n",
"\f" };
"\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\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\n\n\n\n\n\n\n\n\n\n\n\n",
"\f"
};
if (cpls & CPLS_LPT) { /* completion pulse? */
ios = 1; /* restart */
cpls = cpls & ~CPLS_LPT; } /* clr pulse pending */
sbs = sbs | SB_RQ; /* req seq break */
if (lpt_spc) { /* space? */
iosta = iosta | IOS_SPC; /* set flag */
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (lpt_stopioe, SCPE_UNATT);
fputs (lpt_cc[lpt_spc & 07], uptr->fileref); /* print cctl */
if (ferror (uptr->fileref)) { /* error? */
perror ("LPT I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR; }
lpt_ovrpr = 0; } /* dont overprint */
else { iosta = iosta | IOS_PNT; /* print */
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (lpt_stopioe, SCPE_UNATT);
if (lpt_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */
fputs (lpt_buf, uptr->fileref); /* print buffer */
if (ferror (uptr->fileref)) { /* test error */
perror ("LPT I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR; }
lpt_bptr = 0;
for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */
lpt_ovrpr = 1; } /* set overprint */
lpt_unit.pos = ftell (uptr->fileref); /* update position */
if (cpls & CPLS_LPT) { /* completion pulse? */
ios = 1; /* restart */
cpls = cpls & ~CPLS_LPT; /* clr pulse pending */
}
sbs = sbs | SB_RQ; /* req seq break */
if (lpt_spc) { /* space? */
iosta = iosta | IOS_SPC; /* set flag */
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (lpt_stopioe, SCPE_UNATT);
fputs (lpt_cc[lpt_spc & 07], uptr->fileref); /* print cctl */
if (ferror (uptr->fileref)) { /* error? */
perror ("LPT I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR;
}
lpt_ovrpr = 0; /* dont overprint */
}
else {
iosta = iosta | IOS_PNT; /* print */
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (lpt_stopioe, SCPE_UNATT);
if (lpt_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */
fputs (lpt_buf, uptr->fileref); /* print buffer */
if (ferror (uptr->fileref)) { /* test error */
perror ("LPT I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR;
}
lpt_bptr = 0;
for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */
lpt_ovrpr = 1; /* set overprint */
}
lpt_unit.pos = ftell (uptr->fileref); /* update position */
return SCPE_OK;
}
@@ -173,12 +189,12 @@ t_stat lpt_reset (DEVICE *dptr)
{
int32 i;
lpt_bptr = 0; /* clear buffer ptr */
for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */
lpt_spc = 0; /* clear state */
lpt_ovrpr = 0; /* clear overprint */
lpt_bptr = 0; /* clear buffer ptr */
for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */
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 */
iosta = iosta & ~(IOS_PNT | IOS_SPC); /* clear flags */
sim_cancel (&lpt_unit); /* deactivate unit */
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* pdp1_stddev.c: PDP-1 standard devices
Copyright (c) 1993-2004, Robert M. Supnik
Copyright (c) 1993-2005, 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"),
@@ -19,30 +19,30 @@
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
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
ptr paper tape reader
ptp paper tape punch
tti keyboard
tto teleprinter
ptr paper tape reader
ptp paper tape punch
tti keyboard
tto teleprinter
29-Oct-03 RMS Added PTR FIODEC-to-ASCII translation (from Phil Budne)
07-Sep-03 RMS Changed ioc to ios
30-Aug-03 RMS Revised PTR to conform to Maintenance Manual;
added deadlock prevention on errors
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)
21-Nov-02 RMS Changed typewriter to half duplex (found by Derek Peschel)
06-Oct-02 RMS Revised for V2.10
30-May-02 RMS Widened POS to 32b
29-Nov-01 RMS Added read only unit support
07-Sep-01 RMS Moved function prototypes
10-Jun-01 RMS Fixed comment
30-Oct-00 RMS Standardized device naming
29-Oct-03 RMS Added PTR FIODEC-to-ASCII translation (from Phil Budne)
07-Sep-03 RMS Changed ioc to ios
30-Aug-03 RMS Revised PTR to conform to Maintenance Manual;
added deadlock prevention on errors
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)
21-Nov-02 RMS Changed typewriter to half duplex (found by Derek Peschel)
06-Oct-02 RMS Revised for V2.10
30-May-02 RMS Widened POS to 32b
29-Nov-01 RMS Added read only unit support
07-Sep-01 RMS Moved function prototypes
10-Jun-01 RMS Fixed comment
30-Oct-00 RMS Standardized device naming
Note: PTP timeout must be >10X faster that TTY output timeout for Macro
to work correctly!
@@ -50,30 +50,30 @@
#include "pdp1_defs.h"
#define FIODEC_STOP 013 /* stop code */
#define FIODEC_UC 074
#define FIODEC_LC 072
#define UC_V 6 /* upper case */
#define UC (1 << UC_V)
#define BOTH (1 << (UC_V + 1)) /* both cases */
#define CW (1 << (UC_V + 2)) /* char waiting */
#define TT_WIDTH 077
#define TTI 0
#define TTO 1
#define UNIT_V_ASCII (UNIT_V_UF + 0) /* ASCII/binary mode */
#define UNIT_ASCII (1 << UNIT_V_ASCII)
#define PTR_LEADER 20 /* ASCII leader chars */
#define FIODEC_STOP 013 /* stop code */
#define FIODEC_UC 074
#define FIODEC_LC 072
#define UC_V 6 /* upper case */
#define UC (1 << UC_V)
#define BOTH (1 << (UC_V + 1)) /* both cases */
#define CW (1 << (UC_V + 2)) /* char waiting */
#define TT_WIDTH 077
#define TTI 0
#define TTO 1
#define UNIT_V_ASCII (UNIT_V_UF + 0) /* ASCII/binary mode */
#define UNIT_ASCII (1 << UNIT_V_ASCII)
#define PTR_LEADER 20 /* ASCII leader chars */
int32 ptr_state = 0;
int32 ptr_wait = 0;
int32 ptr_stopioe = 0;
int32 ptr_uc = 0; /* upper/lower case */
int32 ptr_hold = 0; /* holding buffer */
int32 ptr_leader = PTR_LEADER; /* leader count */
int32 ptr_uc = 0; /* upper/lower case */
int32 ptr_hold = 0; /* holding buffer */
int32 ptr_leader = PTR_LEADER; /* leader count */
int32 ptp_stopioe = 0;
int32 tti_hold = 0; /* tti hold buf */
int32 tty_buf = 0; /* tty buffer */
int32 tty_uc = 0; /* tty uc/lc */
int32 tti_hold = 0; /* tti hold buf */
int32 tty_buf = 0; /* tty buffer */
int32 tty_uc = 0; /* tty uc/lc */
extern int32 sbs, ios, ioh, cpls, iosta;
extern int32 PF, IO, PC, TA;
@@ -89,139 +89,151 @@ t_stat ptp_reset (DEVICE *dptr);
t_stat tty_reset (DEVICE *dptr);
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
t_stat ptr_attach (UNIT *uptr, char *cptr);
/* Character translation tables */
int32 fiodec_to_ascii[128] = {
' ', '1', '2', '3', '4', '5', '6', '7', /* lower case */
'8', '9', 0, 0, 0, 0, 0, 0,
'0', '/', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 0, ',', 0, 0, '\t', 0,
'@', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 0, 0, '-', ')', '\\', '(',
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', '{', '.', '}', '\b', 0, '\r',
' ', '"', '\'', '~', '#', '!', '&', '<', /* upper case */
'>', '^', 0, 0, 0, 0, 0, 0,
'`', '?', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 0, '=', 0, 0, '\t', 0,
'_', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 0, 0, '+', ']', '|', '[',
0, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', '{', '*', '}', '\b', 0, '\r' };
' ', '1', '2', '3', '4', '5', '6', '7', /* lower case */
'8', '9', 0, 0, 0, 0, 0, 0,
'0', '/', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 0, ',', 0, 0, '\t', 0,
'@', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 0, 0, '-', ')', '\\', '(',
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', '{', '.', '}', '\b', 0, '\r',
' ', '"', '\'', '~', '#', '!', '&', '<', /* upper case */
'>', '^', 0, 0, 0, 0, 0, 0,
'`', '?', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 0, '=', 0, 0, '\t', 0,
'_', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 0, 0, '+', ']', '|', '[',
0, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', '{', '*', '}', '\b', 0, '\r'
};
int32 ascii_to_fiodec[128] = {
0, 0, 0, 0, 0, 0, 0, 0,
BOTH+075, BOTH+036, 0, 0, 0, BOTH+077, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
BOTH+0, UC+005, UC+001, UC+004, 0, 0, UC+006, UC+002,
057, 055, UC+073, UC+054, 033, 054, 073, 021,
020, 001, 002, 003, 004, 005, 006, 007,
010, 011, 0, 0, UC+007, UC+033, UC+010, UC+021,
040, UC+061, UC+062, UC+063, UC+064, UC+065, UC+066, UC+067,
UC+070, UC+071, UC+041, UC+042, UC+043, UC+044, UC+045, UC+046,
UC+047, UC+050, UC+051, UC+022, UC+023, UC+024, UC+025, UC+026,
UC+027, UC+030, UC+031, UC+057, 056, UC+055, UC+011, UC+040,
UC+020, 061, 062, 063, 064, 065, 066, 067,
070, 071, 041, 042, 043, 044, 045, 046,
047, 050, 051, 022, 023, 024, 025, 026,
027, 030, 031, 0, UC+056, 0, UC+003, BOTH+075 };
0, 0, 0, 0, 0, 0, 0, 0,
BOTH+075, BOTH+036, 0, 0, 0, BOTH+077, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
BOTH+0, UC+005, UC+001, UC+004, 0, 0, UC+006, UC+002,
057, 055, UC+073, UC+054, 033, 054, 073, 021,
020, 001, 002, 003, 004, 005, 006, 007,
010, 011, 0, 0, UC+007, UC+033, UC+010, UC+021,
040, UC+061, UC+062, UC+063, UC+064, UC+065, UC+066, UC+067,
UC+070, UC+071, UC+041, UC+042, UC+043, UC+044, UC+045, UC+046,
UC+047, UC+050, UC+051, UC+022, UC+023, UC+024, UC+025, UC+026,
UC+027, UC+030, UC+031, UC+057, 056, UC+055, UC+011, UC+040,
UC+020, 061, 062, 063, 064, 065, 066, 067,
070, 071, 041, 042, 043, 044, 045, 046,
047, 050, 051, 022, 023, 024, 025, 026,
027, 030, 031, 0, UC+056, 0, UC+003, BOTH+075
};
/* PTR data structures
ptr_dev PTR device descriptor
ptr_unit PTR unit
ptr_reg PTR register list
ptr_dev PTR device descriptor
ptr_unit PTR unit
ptr_reg PTR register list
*/
UNIT ptr_unit = {
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
SERIAL_IN_WAIT };
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
SERIAL_IN_WAIT
};
REG ptr_reg[] = {
{ ORDATA (BUF, ptr_unit.buf, 18) },
{ FLDATA (UC, ptr_uc, UC_V) },
{ FLDATA (DONE, iosta, IOS_V_PTR) },
{ FLDATA (RPLS, cpls, CPLS_V_PTR) },
{ ORDATA (HOLD, ptr_hold, 9), REG_HRO },
{ ORDATA (STATE, ptr_state, 5), REG_HRO },
{ FLDATA (WAIT, ptr_wait, 0), REG_HRO },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
{ DRDATA (LEADER, ptr_leader, 6), REG_HRO },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ NULL } };
{ ORDATA (BUF, ptr_unit.buf, 18) },
{ FLDATA (UC, ptr_uc, UC_V) },
{ FLDATA (DONE, iosta, IOS_V_PTR) },
{ FLDATA (RPLS, cpls, CPLS_V_PTR) },
{ ORDATA (HOLD, ptr_hold, 9), REG_HRO },
{ ORDATA (STATE, ptr_state, 5), REG_HRO },
{ FLDATA (WAIT, ptr_wait, 0), REG_HRO },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
{ DRDATA (LEADER, ptr_leader, 6), REG_HRO },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ NULL }
};
MTAB ptr_mod[] = {
{ UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL },
{ UNIT_ASCII, 0, "FIODEC", "FIODEC", NULL },
{ 0 } };
{ UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL },
{ UNIT_ASCII, 0, "FIODEC", "FIODEC", NULL },
{ 0 }
};
DEVICE ptr_dev = {
"PTR", &ptr_unit, ptr_reg, ptr_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptr_reset,
&ptr_boot, &ptr_attach, NULL,
NULL, 0 };
"PTR", &ptr_unit, ptr_reg, ptr_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptr_reset,
&ptr_boot, &ptr_attach, NULL,
NULL, 0
};
/* PTP data structures
ptp_dev PTP device descriptor
ptp_unit PTP unit
ptp_reg PTP register list
ptp_dev PTP device descriptor
ptp_unit PTP unit
ptp_reg PTP register list
*/
UNIT ptp_unit = {
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
};
REG ptp_reg[] = {
{ ORDATA (BUF, ptp_unit.buf, 8) },
{ FLDATA (DONE, iosta, IOS_V_PTP) },
{ 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) },
{ NULL } };
{ ORDATA (BUF, ptp_unit.buf, 8) },
{ FLDATA (DONE, iosta, IOS_V_PTP) },
{ 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) },
{ NULL }
};
DEVICE ptp_dev = {
"PTP", &ptp_unit, ptp_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptp_reset,
NULL, NULL, NULL,
NULL, 0 };
"PTP", &ptp_unit, ptp_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptp_reset,
NULL, NULL, NULL,
NULL, 0
};
/* TTY data structures
tty_dev TTY device descriptor
tty_unit TTY unit
tty_reg TTY register list
tty_dev TTY device descriptor
tty_unit TTY unit
tty_reg TTY register list
*/
UNIT tty_unit[] = {
{ UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT },
{ UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT * 10 } };
{ UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT },
{ UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT * 10 }
};
REG tty_reg[] = {
{ ORDATA (BUF, tty_buf, 6) },
{ FLDATA (UC, tty_uc, UC_V) },
{ 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 },
{ DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (TDONE, iosta, IOS_V_TTO) },
{ DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TTIME, tty_unit[TTO].wait, 24), PV_LEFT },
{ NULL } };
{ ORDATA (BUF, tty_buf, 6) },
{ FLDATA (UC, tty_uc, UC_V) },
{ 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 },
{ DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (TDONE, iosta, IOS_V_TTO) },
{ DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TTIME, tty_unit[TTO].wait, 24), PV_LEFT },
{ NULL }
};
DEVICE tty_dev = {
"TTY", tty_unit, tty_reg, NULL,
2, 10, 31, 1, 8, 8,
NULL, NULL, &tty_reset,
NULL, NULL, NULL,
NULL, 0 };
"TTY", tty_unit, tty_reg, NULL,
2, 10, 31, 1, 8, 8,
NULL, NULL, &tty_reset,
NULL, NULL, NULL,
NULL, 0
};
/* Paper tape reader: IOT routine. Points to note:
- RPA (but not RPB) complements the reader clutch control. Thus,
@@ -236,22 +248,25 @@ DEVICE tty_dev = {
int32 ptr (int32 inst, int32 dev, int32 dat)
{
if (dev == 0030) { /* RRB */
iosta = iosta & ~IOS_PTR; /* clear status */
return ptr_unit.buf; } /* return data */
if (dev == 0002) ptr_state = 18; /* RPB, mode = binary */
else if (sim_is_active (&ptr_unit)) { /* RPA, running? */
sim_cancel (&ptr_unit); /* stop reader */
return dat; }
else ptr_state = 0; /* mode = alpha */
ptr_unit.buf = 0; /* clear buffer */
if (inst & IO_WAIT) ptr_wait = 1; /* set ptr wait */
else ptr_wait = 0; /* from IR<5> */
if (GEN_CPLS (inst)) { /* comp pulse? */
ios = 0;
cpls = cpls | CPLS_PTR; }
if (dev == 0030) { /* RRB */
iosta = iosta & ~IOS_PTR; /* clear status */
return ptr_unit.buf; /* return data */
}
if (dev == 0002) ptr_state = 18; /* RPB, mode = binary */
else if (sim_is_active (&ptr_unit)) { /* RPA, running? */
sim_cancel (&ptr_unit); /* stop reader */
return dat;
}
else ptr_state = 0; /* mode = alpha */
ptr_unit.buf = 0; /* clear buffer */
if (inst & IO_WAIT) ptr_wait = 1; /* set ptr wait */
else ptr_wait = 0; /* from IR<5> */
if (GEN_CPLS (inst)) { /* comp pulse? */
ios = 0;
cpls = cpls | CPLS_PTR;
}
else cpls = cpls & ~CPLS_PTR;
sim_activate (&ptr_unit, ptr_unit.wait); /* start reader */
sim_activate (&ptr_unit, ptr_unit.wait); /* start reader */
return dat;
}
@@ -261,36 +276,43 @@ t_stat ptr_svc (UNIT *uptr)
{
int32 temp;
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */
if ((cpls & CPLS_PTR) || ptr_stopioe) return SCPE_UNATT;
return SCPE_OK; }
if ((uptr->flags & UNIT_ASCII) && (ptr_state == 0)) /* ASCII mode, alpha read? */
temp = ptr_get_ascii (uptr); /* get processed char */
else if ((temp = getc (uptr->fileref)) != EOF) /* no, get raw char */
uptr->pos = uptr->pos + 1; /* if not eof, count */
if (temp == EOF) { /* end of file? */
if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */
if (feof (uptr->fileref)) {
if ((cpls & CPLS_PTR) || ptr_stopioe) printf ("PTR end of file\n");
else return SCPE_OK; }
else perror ("PTR I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR; }
if (ptr_state == 0) uptr->buf = temp & 0377; /* alpha */
else if (temp & 0200) { /* binary */
ptr_state = ptr_state - 6;
uptr->buf = uptr->buf | ((temp & 077) << ptr_state); }
if (ptr_state == 0) { /* done? */
if (cpls & CPLS_PTR) { /* completion pulse? */
iosta = iosta & ~IOS_PTR; /* clear flag */
IO = uptr->buf; /* fill IO */
ios = 1; /* restart */
cpls = cpls & ~CPLS_PTR; }
else { /* no, interrupt */
iosta = iosta | IOS_PTR; /* set flag */
sbs = sbs | SB_RQ; } } /* req seq break */
else sim_activate (uptr, uptr->wait); /* get next char */
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */
if ((cpls & CPLS_PTR) || ptr_stopioe) return SCPE_UNATT;
return SCPE_OK;
}
if ((uptr->flags & UNIT_ASCII) && (ptr_state == 0)) /* ASCII mode, alpha read? */
temp = ptr_get_ascii (uptr); /* get processed char */
else if ((temp = getc (uptr->fileref)) != EOF) /* no, get raw char */
uptr->pos = uptr->pos + 1; /* if not eof, count */
if (temp == EOF) { /* end of file? */
if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */
if (feof (uptr->fileref)) {
if ((cpls & CPLS_PTR) || ptr_stopioe) printf ("PTR end of file\n");
else return SCPE_OK;
}
else perror ("PTR I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR;
}
if (ptr_state == 0) uptr->buf = temp & 0377; /* alpha */
else if (temp & 0200) { /* binary */
ptr_state = ptr_state - 6;
uptr->buf = uptr->buf | ((temp & 077) << ptr_state);
}
if (ptr_state == 0) { /* done? */
if (cpls & CPLS_PTR) { /* completion pulse? */
iosta = iosta & ~IOS_PTR; /* clear flag */
IO = uptr->buf; /* fill IO */
ios = 1; /* restart */
cpls = cpls & ~CPLS_PTR;
}
else { /* no, interrupt */
iosta = iosta | IOS_PTR; /* set flag */
sbs = sbs | SB_RQ; /* req seq break */
}
}
else sim_activate (uptr, uptr->wait); /* get next char */
return SCPE_OK;
}
@@ -301,47 +323,52 @@ int ptr_get_ascii (UNIT *uptr)
int c;
int32 in;
if (ptr_leader > 0) { /* leader? */
ptr_leader = ptr_leader - 1; /* count down */
return 0; }
if (ptr_hold & CW) { /* char waiting? */
in = ptr_hold & TT_WIDTH; /* return char */
ptr_hold = 0; } /* not waiting */
else { for (;;) { /* until valid char */
if ((c = getc (uptr->fileref)) == EOF) /* get next char, EOF? */
return FIODEC_STOP; /* return STOP */
uptr->pos = uptr->pos + 1; /* count char */
c = c & 0177; /* cut to 7b */
if (c == '\n') c = '\r'; /* NL -> CR */
else if (c == '\r') continue; /* ignore CR */
in = ascii_to_fiodec[c]; /* convert char */
if ((in == 0) && (c != ' ')) continue; /* ignore unknowns */
if ((in & BOTH) || ((in & UC) == ptr_uc)) /* case match? */
in = in & TT_WIDTH; /* cut to 6b */
else { /* no, case shift */
ptr_hold = in | CW; /* set char waiting */
ptr_uc = in & UC; /* set case */
in = ptr_uc? FIODEC_UC: FIODEC_LC; } /* return case */
break; }
} /* end else */
in = in * 010040201; /* even parity from */
in = in | 027555555400; /* HACKMEM 167 */
if (ptr_leader > 0) { /* leader? */
ptr_leader = ptr_leader - 1; /* count down */
return 0;
}
if (ptr_hold & CW) { /* char waiting? */
in = ptr_hold & TT_WIDTH; /* return char */
ptr_hold = 0; /* not waiting */
}
else {
for (;;) { /* until valid char */
if ((c = getc (uptr->fileref)) == EOF) /* get next char, EOF? */
return FIODEC_STOP; /* return STOP */
uptr->pos = uptr->pos + 1; /* count char */
c = c & 0177; /* cut to 7b */
if (c == '\n') c = '\r'; /* NL -> CR */
else if (c == '\r') continue; /* ignore CR */
in = ascii_to_fiodec[c]; /* convert char */
if ((in == 0) && (c != ' ')) continue; /* ignore unknowns */
if ((in & BOTH) || ((in & UC) == ptr_uc)) /* case match? */
in = in & TT_WIDTH; /* cut to 6b */
else { /* no, case shift */
ptr_hold = in | CW; /* set char waiting */
ptr_uc = in & UC; /* set case */
in = ptr_uc? FIODEC_UC: FIODEC_LC; /* return case */
} /* end else */
break;
} /* end for */
} /* end else */
in = in * 010040201; /* even parity from */
in = in | 027555555400; /* HACKMEM 167 */
in = in % (9 << 7);
return in & 0377;
}
/* Reset routine */
t_stat ptr_reset (DEVICE *dptr)
{
ptr_state = 0; /* clear state */
ptr_state = 0; /* clear state */
ptr_wait = 0;
ptr_hold = 0;
ptr_uc = 0;
ptr_unit.buf = 0;
cpls = cpls & ~CPLS_PTR;
iosta = iosta & ~IOS_PTR; /* clear flag */
sim_cancel (&ptr_unit); /* deactivate unit */
iosta = iosta & ~IOS_PTR; /* clear flag */
sim_cancel (&ptr_unit); /* deactivate unit */
return SCPE_OK;
}
@@ -349,7 +376,7 @@ return SCPE_OK;
t_stat ptr_attach (UNIT *uptr, char *cptr)
{
ptr_leader = PTR_LEADER; /* set up leader */
ptr_leader = PTR_LEADER; /* set up leader */
return attach_unit (uptr, cptr);
}
@@ -360,11 +387,13 @@ int32 ptr_getw (UNIT *uptr)
int32 i, tmp, word;
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++; } }
if ((tmp = getc (uptr->fileref)) == EOF) return -1;
uptr->pos = uptr->pos + 1;
if (tmp & 0200) {
word = (word << 6) | (tmp & 077);
i++;
}
}
return word;
}
@@ -374,31 +403,34 @@ int32 origin, val;
int32 fld = TA & EPCMASK;
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 & DAMASK;
if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT;
M[fld | origin] = val; }
else if ((val & 0760000) == OP_JMP) { /* JMP? */
PC = fld | (val & DAMASK);
break; }
else return SCPE_FMT; /* bad instr */
}
return SCPE_OK; /* done */
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 & DAMASK;
if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT;
M[fld | origin] = val;
}
else if ((val & 0760000) == OP_JMP) { /* JMP? */
PC = fld | (val & DAMASK);
break;
}
else return SCPE_FMT; /* bad instr */
}
return SCPE_OK; /* done */
}
/* Paper tape punch: IOT routine */
int32 ptp (int32 inst, int32 dev, int32 dat)
{
iosta = iosta & ~IOS_PTP; /* clear flag */
iosta = iosta & ~IOS_PTP; /* clear flag */
ptp_unit.buf = (dev == 0006)? ((dat >> 12) | 0200): (dat & 0377);
if (GEN_CPLS (inst)) { /* comp pulse? */
ios = 0;
cpls = cpls | CPLS_PTP; }
if (GEN_CPLS (inst)) { /* comp pulse? */
ios = 0;
cpls = cpls | CPLS_PTP;
}
else cpls = cpls & ~CPLS_PTP;
sim_activate (&ptp_unit, ptp_unit.wait); /* start unit */
sim_activate (&ptp_unit, ptp_unit.wait); /* start unit */
return dat;
}
@@ -406,17 +438,19 @@ return dat;
t_stat ptp_svc (UNIT *uptr)
{
if (cpls & CPLS_PTP) { /* completion pulse? */
ios = 1; /* restart */
cpls = cpls & ~CPLS_PTP; }
iosta = iosta | IOS_PTP; /* set flag */
sbs = sbs | SB_RQ; /* req seq break */
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
return IORETURN (ptp_stopioe, SCPE_UNATT);
if (putc (uptr->buf, uptr->fileref) == EOF) { /* I/O error? */
perror ("PTP I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR; }
if (cpls & CPLS_PTP) { /* completion pulse? */
ios = 1; /* restart */
cpls = cpls & ~CPLS_PTP;
}
iosta = iosta | IOS_PTP; /* set flag */
sbs = sbs | SB_RQ; /* req seq break */
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
return IORETURN (ptp_stopioe, SCPE_UNATT);
if (putc (uptr->buf, uptr->fileref) == EOF) { /* I/O error? */
perror ("PTP I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR;
}
uptr->pos = uptr->pos + 1;
return SCPE_OK;
}
@@ -425,32 +459,33 @@ return SCPE_OK;
t_stat ptp_reset (DEVICE *dptr)
{
ptp_unit.buf = 0; /* clear state */
ptp_unit.buf = 0; /* clear state */
cpls = cpls & ~CPLS_PTP;
iosta = iosta & ~IOS_PTP; /* clear flag */
sim_cancel (&ptp_unit); /* deactivate unit */
iosta = iosta & ~IOS_PTP; /* clear flag */
sim_cancel (&ptp_unit); /* deactivate unit */
return SCPE_OK;
}
/* Typewriter IOT routines */
int32 tti (int32 inst, int32 dev, int32 dat)
{
iosta = iosta & ~IOS_TTI; /* clear flag */
if (inst & (IO_WAIT | IO_CPLS)) /* wait or sync? */
return (STOP_RSRV << IOT_V_REASON) | (tty_buf & 077);
iosta = iosta & ~IOS_TTI; /* clear flag */
if (inst & (IO_WAIT | IO_CPLS)) /* wait or sync? */
return (STOP_RSRV << IOT_V_REASON) | (tty_buf & 077);
return tty_buf & 077;
}
int32 tto (int32 inst, int32 dev, int32 dat)
{
iosta = iosta & ~IOS_TTO; /* clear flag */
tty_buf = dat & TT_WIDTH; /* load buffer */
if (GEN_CPLS (inst)) { /* comp pulse? */
ios = 0;
cpls = cpls | CPLS_TTO; }
iosta = iosta & ~IOS_TTO; /* clear flag */
tty_buf = dat & TT_WIDTH; /* load buffer */
if (GEN_CPLS (inst)) { /* comp pulse? */
ios = 0;
cpls = cpls | CPLS_TTO;
}
else cpls = cpls & ~CPLS_TTO;
sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); /* activate unit */
sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); /* activate unit */
return dat;
}
@@ -460,27 +495,31 @@ t_stat tti_svc (UNIT *uptr)
{
int32 in, temp;
sim_activate (uptr, uptr->wait); /* continue poll */
if (tti_hold & CW) { /* char waiting? */
tty_buf = tti_hold & TT_WIDTH; /* return char */
tti_hold = 0; } /* not waiting */
else { if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp;
if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */
temp = temp & 0177;
if (temp == 0177) temp = '\b'; /* rubout? bs */
sim_putchar (temp); /* echo */
if (temp == '\r') sim_putchar ('\n'); /* cr? add nl */
in = ascii_to_fiodec[temp]; /* translate char */
if (in == 0) return SCPE_OK; /* no xlation? */
if ((in & BOTH) || ((in & UC) == (tty_uc & UC)))
tty_buf = in & TT_WIDTH;
else { /* must shift */
tty_uc = in & UC; /* new case */
tty_buf = tty_uc? FIODEC_UC: FIODEC_LC;
tti_hold = in | CW; } } /* set 2nd waiting */
iosta = iosta | IOS_TTI; /* set flag */
sbs = sbs | SB_RQ; /* req seq break */
PF = PF | 040; /* set prog flag 1 */
sim_activate (uptr, uptr->wait); /* continue poll */
if (tti_hold & CW) { /* char waiting? */
tty_buf = tti_hold & TT_WIDTH; /* return char */
tti_hold = 0; /* not waiting */
}
else {
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp;
if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */
temp = temp & 0177;
if (temp == 0177) temp = '\b'; /* rubout? bs */
sim_putchar (temp); /* echo */
if (temp == '\r') sim_putchar ('\n'); /* cr? add nl */
in = ascii_to_fiodec[temp]; /* translate char */
if (in == 0) return SCPE_OK; /* no xlation? */
if ((in & BOTH) || ((in & UC) == (tty_uc & UC)))
tty_buf = in & TT_WIDTH;
else { /* must shift */
tty_uc = in & UC; /* new case */
tty_buf = tty_uc? FIODEC_UC: FIODEC_LC;
tti_hold = in | CW; /* set 2nd waiting */
}
}
iosta = iosta | IOS_TTI; /* set flag */
sbs = sbs | SB_RQ; /* req seq break */
PF = PF | 040; /* set prog flag 1 */
uptr->pos = uptr->pos + 1;
return SCPE_OK;
}
@@ -490,21 +529,26 @@ t_stat tto_svc (UNIT *uptr)
int32 c;
t_stat r;
if (tty_buf == FIODEC_UC) tty_uc = UC; /* upper case? */
else if (tty_buf == FIODEC_LC) tty_uc = 0; /* lower case? */
else { c = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */
if (c && ((r = sim_putchar_s (c)) != SCPE_OK)) {/* output; error? */
sim_activate (uptr, uptr->wait); /* retry */
return ((r == SCPE_STALL)? SCPE_OK: r); } }
if (cpls & CPLS_TTO) { /* completion pulse? */
ios = 1; /* restart */
cpls = cpls & ~CPLS_TTO; }
iosta = iosta | IOS_TTO; /* set flag */
sbs = sbs | SB_RQ; /* req seq break */
if (tty_buf == FIODEC_UC) tty_uc = UC; /* upper case? */
else if (tty_buf == FIODEC_LC) tty_uc = 0; /* lower case? */
else {
c = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */
if (c && ((r = sim_putchar_s (c)) != SCPE_OK)) { /* output; error? */
sim_activate (uptr, uptr->wait); /* retry */
return ((r == SCPE_STALL)? SCPE_OK: r);
}
}
if (cpls & CPLS_TTO) { /* completion pulse? */
ios = 1; /* restart */
cpls = cpls & ~CPLS_TTO;
}
iosta = iosta | IOS_TTO; /* set flag */
sbs = sbs | SB_RQ; /* req seq break */
uptr->pos = uptr->pos + 1;
if (c == '\r') { /* cr? add lf */
sim_putchar ('\n');
uptr->pos = uptr->pos + 1; }
if (c == '\r') { /* cr? add lf */
sim_putchar ('\n');
uptr->pos = uptr->pos + 1;
}
return SCPE_OK;
}
@@ -512,12 +556,12 @@ return SCPE_OK;
t_stat tty_reset (DEVICE *dptr)
{
tty_buf = 0; /* clear buffer */
tty_uc = 0; /* clear case */
tti_hold = 0; /* clear hold buf */
tty_buf = 0; /* clear buffer */
tty_uc = 0; /* clear case */
tti_hold = 0; /* clear hold buf */
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 */
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 */
return SCPE_OK;
}

View File

@@ -23,23 +23,23 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
06-Apr-04 RMS Fixed bug in binary loader (found by Mark Crispin)
08-Feb-04 PLB Merged display support
08-Dec-03 RMS Added parallel drum support, drum mnemonics
18-Oct-03 RMS Added DECtape off reel message
01-Sep-03 RMS Added support for loading in multiple fields
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
17-Sep-01 RMS Removed multiconsole support
13-Jul-01 RMS Fixed RIM loader format
27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
30-Oct-00 RMS Added support for examine to file
27-Oct-98 RMS V2.4 load interface
20-Oct-97 RMS Fixed endian-dependence in RIM loader
(found by Michael Somos)
06-Apr-04 RMS Fixed bug in binary loader (found by Mark Crispin)
08-Feb-04 PLB Merged display support
08-Dec-03 RMS Added parallel drum support, drum mnemonics
18-Oct-03 RMS Added DECtape off reel message
01-Sep-03 RMS Added support for loading in multiple fields
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
17-Sep-01 RMS Removed multiconsole support
13-Jul-01 RMS Fixed RIM loader format
27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
30-Oct-00 RMS Added support for examine to file
27-Oct-98 RMS V2.4 load interface
20-Oct-97 RMS Fixed endian-dependence in RIM loader
(found by Michael Somos)
*/
#include "pdp1_defs.h"
@@ -64,12 +64,12 @@ extern int32 sim_switches;
/* SCP data structures and interface routines
sim_name simulator name string
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_stop_messages array of pointers to stop messages
sim_load binary loader
sim_name simulator name string
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
char sim_name[] = "PDP-1";
@@ -79,27 +79,29 @@ REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 1;
DEVICE *sim_devices[] = {
&cpu_dev,
&ptr_dev,
&ptp_dev,
&tty_dev,
&lpt_dev,
&dt_dev,
&drm_dev,
&drp_dev,
// &dpy_dev,
NULL };
&cpu_dev,
&ptr_dev,
&ptp_dev,
&tty_dev,
&lpt_dev,
&dt_dev,
&drm_dev,
&drp_dev,
/* &dpy_dev, */
NULL
};
const char *sim_stop_messages[] = {
"Unknown error",
"Undefined instruction",
"HALT instruction",
"Breakpoint",
"Nested XCT's",
"Nested indirect addresses",
"Infinite I/O wait state",
"DECtape off reel" };
"Unknown error",
"Undefined instruction",
"HALT instruction",
"Breakpoint",
"Nested XCT's",
"Nested indirect addresses",
"Infinite I/O wait state",
"DECtape off reel"
};
/* Binary loader - supports both RIM format and Macro block format */
int32 pdp1_getw (FILE *inf)
@@ -108,10 +110,12 @@ int32 i, tmp, word;
word = 0;
for (i = 0; i < 3;) {
if ((tmp = getc (inf)) == EOF) return -1;
if (tmp & 0200) {
word = (word << 6) | (tmp & 077);
i++; } }
if ((tmp = getc (inf)) == EOF) return -1;
if (tmp & 0200) {
word = (word << 6) | (tmp & 077);
i++;
}
}
return word;
}
@@ -120,18 +124,20 @@ t_stat rim_load (FILE *inf, int32 fld)
int32 origin, val;
for (;;) {
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
if (((val & 0760000) == OP_DIO) || /* DIO? */
((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */
origin = val & DAMASK;
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
M[fld | origin] = val; }
else if ((val & 0760000) == OP_JMP) { /* JMP? */
PC = fld | (val & DAMASK);
break; }
else return SCPE_FMT; /* bad instr */
}
return SCPE_OK; /* done */
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
if (((val & 0760000) == OP_DIO) || /* DIO? */
((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */
origin = val & DAMASK;
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
M[fld | origin] = val;
}
else if ((val & 0760000) == OP_JMP) { /* JMP? */
PC = fld | (val & DAMASK);
break;
}
else return SCPE_FMT; /* bad instr */
}
return SCPE_OK; /* done */
}
t_stat blk_load (FILE *inf, int32 fld)
@@ -139,30 +145,33 @@ t_stat blk_load (FILE *inf, int32 fld)
int32 val, start, count, csum;
for (;;) {
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; /* get word, EOF? */
if ((val & 0760000) == OP_DIO) { /* DIO? */
csum = val; /* init checksum */
start = val & DAMASK; /* starting addr */
if ((val = pdp1_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 & DAMASK) - start + 1; /* block count */
if (count <= 0) return SCPE_FMT;
while (count--) { /* loop on data */
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
csum = csum + val;
if (csum > 0777777) csum = (csum + 1) & 0777777;
M[fld | start] = val;
start = (start + 1) & DAMASK; }
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
if (val != csum) return SCPE_CSUM; }
else if ((val & 0760000) == OP_JMP) { /* JMP? */
PC = fld | (val & DAMASK);
break; }
else return SCPE_FMT; /* bad instr */
}
return SCPE_OK; /* done */
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; /* get word, EOF? */
if ((val & 0760000) == OP_DIO) { /* DIO? */
csum = val; /* init checksum */
start = val & DAMASK; /* starting addr */
if ((val = pdp1_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 & DAMASK) - start + 1; /* block count */
if (count <= 0) return SCPE_FMT;
while (count--) { /* loop on data */
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
csum = csum + val;
if (csum > 0777777) csum = (csum + 1) & 0777777;
M[fld | start] = val;
start = (start + 1) & DAMASK;
}
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
if (val != csum) return SCPE_CSUM;
}
else if ((val & 0760000) == OP_JMP) { /* JMP? */
PC = fld | (val & DAMASK);
break;
}
else return SCPE_FMT; /* bad instr */
}
return SCPE_OK; /* done */
}
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
@@ -172,52 +181,54 @@ int32 fld;
if (flag != 0) return SCPE_ARG;
if (cptr && (*cptr != 0)) {
fld = get_uint (cptr, 8, AMASK, &sta);
if (sta != SCPE_OK) return sta;
fld = fld & EPCMASK; }
fld = get_uint (cptr, 8, AMASK, &sta);
if (sta != SCPE_OK) return sta;
fld = fld & EPCMASK;
}
else fld = 0;
sta = rim_load (fileref, fld);
if (sta != SCPE_OK) return sta;
if ((sim_switches & SWMASK ('B')) || match_ext (fnam, "BIN"))
return blk_load (fileref, fld);
return blk_load (fileref, fld);
return SCPE_OK;
}
/* Symbol tables */
#define I_V_FL 18 /* inst class */
#define I_M_FL 07 /* class mask */
#define I_V_NPN 0 /* no operand */
#define I_V_IOT 1 /* IOT */
#define I_V_LAW 2 /* LAW */
#define I_V_MRF 3 /* memory reference */
#define I_V_MRI 4 /* mem ref no ind */
#define I_V_OPR 5 /* OPR */
#define I_V_SKP 6 /* skip */
#define I_V_SHF 7 /* shift */
#define I_NPN (I_V_NPN << I_V_FL) /* no operand */
#define I_IOT (I_V_IOT << I_V_FL) /* IOT */
#define I_LAW (I_V_LAW << I_V_FL) /* LAW */
#define I_MRF (I_V_MRF << I_V_FL) /* memory reference */
#define I_MRI (I_V_MRI << I_V_FL) /* mem ref no ind */
#define I_OPR (I_V_OPR << I_V_FL) /* OPR */
#define I_SKP (I_V_SKP << I_V_FL) /* skip */
#define I_SHF (I_V_SHF << I_V_FL) /* shift */
#define I_V_FL 18 /* inst class */
#define I_M_FL 07 /* class mask */
#define I_V_NPN 0 /* no operand */
#define I_V_IOT 1 /* IOT */
#define I_V_LAW 2 /* LAW */
#define I_V_MRF 3 /* memory reference */
#define I_V_MRI 4 /* mem ref no ind */
#define I_V_OPR 5 /* OPR */
#define I_V_SKP 6 /* skip */
#define I_V_SHF 7 /* shift */
#define I_NPN (I_V_NPN << I_V_FL) /* no operand */
#define I_IOT (I_V_IOT << I_V_FL) /* IOT */
#define I_LAW (I_V_LAW << I_V_FL) /* LAW */
#define I_MRF (I_V_MRF << I_V_FL) /* memory reference */
#define I_MRI (I_V_MRI << I_V_FL) /* mem ref no ind */
#define I_OPR (I_V_OPR << I_V_FL) /* OPR */
#define I_SKP (I_V_SKP << I_V_FL) /* skip */
#define I_SHF (I_V_SHF << I_V_FL) /* shift */
static const int32 masks[] = {
0777777, 0763777, 0760000, 0760000,
0770000, 0760017, 0760077, 0777000 };
0770000, 0760017, 0760077, 0777000
};
static const char *opcode[] = {
"AND", "IOR", "XOR", "XCT", /* mem refs */
"AND", "IOR", "XOR", "XCT", /* mem refs */
"LAC", "LIO", "DAC", "DAP",
"DIP", "DIO", "DZM", "ADD",
"SUB", "IDX", "ISP", "SAD",
"SAS", "MUL", "DIV", "JMP", "JSP",
"CAL", "JDA", /* mem ref no ind */
"CAL", "JDA", /* mem ref no ind */
"IOH", "RPA", "RPB", "RRB", /* I/O instructions */
"IOH", "RPA", "RPB", "RRB", /* I/O instructions */
"PPA", "PPB", "TYO", "TYI",
"DPY",
"LSM", "ESM", "CBS",
@@ -230,12 +241,12 @@ static const char *opcode[] = {
"SKP", "SKP I", "CLO",
"SFT", "LAW", "OPR",
"RAL", "RIL", "RCL", /* shifts */
"RAL", "RIL", "RCL", /* shifts */
"SAL", "SIL", "SCL",
"RAR", "RIR", "RCR",
"SAR", "SIR", "SCR",
"SZF1", "SZF2", "SZF3", /* skips */
"SZF1", "SZF2", "SZF3", /* skips */
"SZF4", "SZF5", "SZF6", "SZF7",
"SZS1", "SZS1 SZF1", "SZS1 SZF2", "SZS1 SZ3",
"SZS1 SZF4", "SZS1 SZF5", "SZS1 SZF6", "SZS1 SZF7",
@@ -252,17 +263,18 @@ static const char *opcode[] = {
"SZS7", "SZS7 SZF1", "SZS7 SZF2", "SZS7 SZ3",
"SZS7 SZF4", "SZS7 SZF5", "SZS7 SZF6", "SZS7 SZF7",
"CLF1", "CLF2", "CLF3", /* operates */
"CLF1", "CLF2", "CLF3", /* operates */
"CLF4", "CLF5", "CLF6", "CLF7",
"STF1", "STF2", "STF3",
"STF4", "STF5", "STF6", "STF7",
"SZA", "SPA", "SMA", /* encode only */
"SZA", "SPA", "SMA", /* encode only */
"SZO", "SPI", "I",
"LAP", "CLA", "HLT",
"CMA", "LAT", "CLI",
NULL, NULL, /* decode only */
NULL };
NULL, NULL, /* decode only */
NULL
};
static const int32 opc_val[] = {
0020000+I_MRF, 0040000+I_MRF, 0060000+I_MRF, 0100000+I_MRF,
@@ -313,48 +325,51 @@ static const int32 opc_val[] = {
0760011+I_OPR, 0760012+I_OPR, 0760013+I_OPR,
0760014+I_OPR, 0760015+I_OPR, 0760016+I_OPR, 0760017+I_OPR,
0640100+I_SKP, 0640200+I_SKP, 0640400+I_SKP, /* encode only */
0640100+I_SKP, 0640200+I_SKP, 0640400+I_SKP, /* encode only */
0641000+I_SKP, 0642000+I_SKP, 0010000+I_SKP,
0760100+I_OPR, 0760200+I_OPR, 0760400+I_OPR,
0761000+I_OPR, 0762000+I_OPR, 0764000+I_OPR,
0640000+I_SKP, 0760000+I_OPR, /* decode only */
-1 };
0640000+I_SKP, 0760000+I_OPR, /* decode only */
-1
};
/* Operate or skip decode
Inputs:
*of = output stream
inst = mask bits
class = instruction class code
sp = space needed?
*of = output stream
inst = mask bits
class = instruction class code
sp = space needed?
Outputs:
status = space needed?
status = space needed?
*/
int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp)
{
int32 i, j;
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
if ((j == class) && (opc_val[i] & inst)) { /* same class? */
inst = inst & ~opc_val[i]; /* mask bit set? */
fprintf (of, (sp? " %s": "%s"), opcode[i]);
sp = 1; } }
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
if ((j == class) && (opc_val[i] & inst)) { /* same class? */
inst = inst & ~opc_val[i]; /* mask bit set? */
fprintf (of, (sp? " %s": "%s"), opcode[i]);
sp = 1;
}
}
return sp;
}
/* Symbolic decode
Inputs:
*of = output stream
addr = current PC
*val = pointer to values
*uptr = pointer to unit
sw = switches
*of = output stream
addr = current PC
*val = pointer to values
*uptr = pointer to unit
sw = switches
Outputs:
return = status code
return = status code
*/
#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
@@ -362,99 +377,113 @@ return sp;
#define ASCTOSIX(x) (ascii_to_fiodec[x] & 077)
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw)
UNIT *uptr, int32 sw)
{
int32 cflag, i, j, sp, inst, disp, ma;
inst = val[0];
cflag = (uptr == NULL) || (uptr == &cpu_unit);
if (sw & SWMASK ('A')) { /* ASCII? */
if (inst > 0377) return SCPE_ARG;
fprintf (of, FMTASC (inst & 0177));
return SCPE_OK; }
if (sw & SWMASK ('C')) { /* character? */
fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077));
fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077));
fprintf (of, "%c", SIXTOASC (inst & 077));
return SCPE_OK; }
if (sw & SWMASK ('A')) { /* ASCII? */
if (inst > 0377) return SCPE_ARG;
fprintf (of, FMTASC (inst & 0177));
return SCPE_OK;
}
if (sw & SWMASK ('C')) { /* character? */
fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077));
fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077));
fprintf (of, "%c", SIXTOASC (inst & 077));
return SCPE_OK;
}
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
/* Instruction decode */
disp = inst & 007777;
ma = (addr & EPCMASK) | disp;
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? */
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? */
switch (j) { /* case on class */
case I_V_NPN: /* no operands */
fprintf (of, "%s", opcode[i]); /* opcode */
break;
case I_V_IOT: /* IOT */
disp = (inst - opc_val[i]) & 017777;
if (disp == IA) fprintf (of, "%s I", opcode[i]);
else if (disp) fprintf (of, "%s %-o", opcode[i], disp);
else fprintf (of, "%s", opcode[i]);
break;
case I_V_LAW: /* LAW */
cflag = 0; /* fall thru to MRF */
case I_V_MRF: /* mem ref */
fprintf (of, "%s%s%-o", opcode[i],
((inst & IA)? " I ": " "), (cflag? ma: disp));
break;
case I_V_MRI: /* mem ref no ind */
fprintf (of, "%s %-o", opcode[i], (cflag? ma: disp));
break;
case I_V_OPR: /* operates */
sp = fprint_opr (of, inst & 007700, j, 0);
if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);
break;
case I_V_SKP: /* skips */
sp = fprint_opr (of, inst & 007700, j, 0);
if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]);
if (inst & IA) fprintf (of, sp? " I": "I");
break;
case I_V_SHF: /* shifts */
fprintf (of, "%s %-d", opcode[i], sc_map[inst & 0777]);
break; } /* end case */
return SCPE_OK; } /* end if */
} /* end for */
switch (j) { /* case on class */
case I_V_NPN: /* no operands */
fprintf (of, "%s", opcode[i]); /* opcode */
break;
case I_V_IOT: /* IOT */
disp = (inst - opc_val[i]) & 017777;
if (disp == IA) fprintf (of, "%s I", opcode[i]);
else if (disp) fprintf (of, "%s %-o", opcode[i], disp);
else fprintf (of, "%s", opcode[i]);
break;
case I_V_LAW: /* LAW */
cflag = 0; /* fall thru to MRF */
case I_V_MRF: /* mem ref */
fprintf (of, "%s%s%-o", opcode[i],
((inst & IA)? " I ": " "), (cflag? ma: disp));
break;
case I_V_MRI: /* mem ref no ind */
fprintf (of, "%s %-o", opcode[i], (cflag? ma: disp));
break;
case I_V_OPR: /* operates */
sp = fprint_opr (of, inst & 007700, j, 0);
if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);
break;
case I_V_SKP: /* skips */
sp = fprint_opr (of, inst & 007700, j, 0);
if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]);
if (inst & IA) fprintf (of, sp? " I": "I");
break;
case I_V_SHF: /* shifts */
fprintf (of, "%s %-d", opcode[i], sc_map[inst & 0777]);
break;
} /* end case */
return SCPE_OK;
} /* end if */
} /* end for */
return SCPE_ARG;
}
/* Get 18b signed number
Inputs:
*cptr = pointer to input string
*sign = pointer to sign
*status = pointer to error status
*cptr = pointer to input string
*sign = pointer to sign
*status = pointer to error status
Outputs:
val = output value
val = output value
*/
t_value get_sint (char *cptr, int32 *sign, t_stat *status)
{
*sign = 1;
if (*cptr == '+') {
*sign = 0;
cptr++; }
*sign = 0;
cptr++;
}
else if (*cptr == '-') {
*sign = -1;
cptr++; }
*sign = -1;
cptr++;
}
return get_uint (cptr, 8, 0777777, status);
}
/* Symbolic input
Inputs:
*cptr = pointer to input string
addr = current PC
uptr = pointer to unit
*val = pointer to output values
sw = switches
*cptr = pointer to input string
addr = current PC
uptr = pointer to unit
*val = pointer to output values
sw = switches
Outputs:
status = error status
status = error status
*/
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
@@ -467,64 +496,72 @@ char gbuf[CBUFSIZE];
cflag = (uptr == NULL) || (uptr == &cpu_unit);
while (isspace (*cptr)) cptr++;
for (i = 1; (i < 3) && (cptr[i] != 0); i++)
if (cptr[i] == 0) for (j = i + 1; j <= 3; j++) cptr[j] = 0;
if (cptr[i] == 0) for (j = i + 1; j <= 3; j++) cptr[j] = 0;
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (t_value) cptr[0];
return SCPE_OK; }
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (t_value) cptr[0];
return SCPE_OK;
}
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (ASCTOSIX (cptr[0] & 077) << 12) |
(ASCTOSIX (cptr[1] & 077) << 6) |
ASCTOSIX (cptr[2] & 077);
return SCPE_OK; }
/* Symbolic input, continued */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (ASCTOSIX (cptr[0] & 077) << 12) |
(ASCTOSIX (cptr[1] & 077) << 6) |
ASCTOSIX (cptr[2] & 077);
return SCPE_OK;
}
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
if (opcode[i] == NULL) return SCPE_ARG;
val[0] = opc_val[i] & 0777777; /* get value */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
val[0] = opc_val[i] & 0777777; /* get value */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
switch (j) { /* case on class */
case I_V_LAW: /* LAW */
cflag = 0; /* fall through */
case I_V_MRF: case I_V_MRI: /* mem ref */
cptr = get_glyph (cptr, gbuf, 0); /* get next field */
if ((j != I_V_MRI) && strcmp (gbuf, "I") == 0) { /* indirect? */
val[0] = val[0] | IA;
cptr = get_glyph (cptr, gbuf, 0); }
d = get_uint (gbuf, 8, AMASK, &r);
if (r != SCPE_OK) return SCPE_ARG;
if (d <= DAMASK) val[0] = val[0] | d;
else if (cflag && (((addr ^ d) & EPCMASK) == 0))
val[0] = val[0] | (d & DAMASK);
else return SCPE_ARG;
break;
case I_V_SHF: /* shift */
cptr = get_glyph (cptr, gbuf, 0);
d = get_uint (gbuf, 10, 9, &r);
if (r != SCPE_OK) return SCPE_ARG;
val[0] = val[0] | sc_enc[d];
break;
case I_V_NPN: case I_V_IOT: case I_V_OPR: case I_V_SKP:
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
cptr = get_glyph (cptr, gbuf, 0)) {
for (i = 0; (opcode[i] != NULL) &&
(strcmp (opcode[i], gbuf) != 0); i++) ;
if (opcode[i] != NULL) {
k = opc_val[i] & 0777777;
if ((k != IA) && (((k ^ val[0]) & 0760000) != 0))
return SCPE_ARG;
val[0] = val[0] | k; }
else {
d = get_sint (gbuf, &sign, &r);
if (r != SCPE_OK) return SCPE_ARG;
if (sign == 0) val[0] = val[0] + d;
else if (sign < 0) val[0] = val[0] - d;
else val[0] = val[0] | d; } }
break; } /* end case */
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
switch (j) { /* case on class */
case I_V_LAW: /* LAW */
cflag = 0; /* fall through */
case I_V_MRF: case I_V_MRI: /* mem ref */
cptr = get_glyph (cptr, gbuf, 0); /* get next field */
if ((j != I_V_MRI) && strcmp (gbuf, "I") == 0) { /* indirect? */
val[0] = val[0] | IA;
cptr = get_glyph (cptr, gbuf, 0);
}
d = get_uint (gbuf, 8, AMASK, &r);
if (r != SCPE_OK) return SCPE_ARG;
if (d <= DAMASK) val[0] = val[0] | d;
else if (cflag && (((addr ^ d) & EPCMASK) == 0))
val[0] = val[0] | (d & DAMASK);
else return SCPE_ARG;
break;
case I_V_SHF: /* shift */
cptr = get_glyph (cptr, gbuf, 0);
d = get_uint (gbuf, 10, 9, &r);
if (r != SCPE_OK) return SCPE_ARG;
val[0] = val[0] | sc_enc[d];
break;
case I_V_NPN: case I_V_IOT: case I_V_OPR: case I_V_SKP:
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
cptr = get_glyph (cptr, gbuf, 0)) {
for (i = 0; (opcode[i] != NULL) &&
(strcmp (opcode[i], gbuf) != 0); i++) ;
if (opcode[i] != NULL) {
k = opc_val[i] & 0777777;
if ((k != IA) && (((k ^ val[0]) & 0760000) != 0))
return SCPE_ARG;
val[0] = val[0] | k;
}
else {
d = get_sint (gbuf, &sign, &r);
if (r != SCPE_OK) return SCPE_ARG;
if (sign == 0) val[0] = val[0] + d;
else if (sign < 0) val[0] = val[0] - d;
else val[0] = val[0] | d;
}
}
break;
} /* end case */
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
return SCPE_OK;
}