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:
committed by
Mark Pizzolato
parent
ec60bbf329
commit
b7c1eae41f
1333
PDP1/pdp1_cpu.c
1333
PDP1/pdp1_cpu.c
File diff suppressed because it is too large
Load Diff
164
PDP1/pdp1_defs.h
164
PDP1/pdp1_defs.h
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
418
PDP1/pdp1_drm.c
418
PDP1/pdp1_drm.c
@@ -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;
|
||||
|
||||
1320
PDP1/pdp1_dt.c
1320
PDP1/pdp1_dt.c
File diff suppressed because it is too large
Load Diff
232
PDP1/pdp1_lp.c
232
PDP1/pdp1_lp.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
539
PDP1/pdp1_sys.c
539
PDP1/pdp1_sys.c
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user