1
0
mirror of https://github.com/open-simh/simh.git synced 2026-05-03 06:39:03 +00:00

Notes For V2.9-11

1. New Features

1.1 GRI-909

- This is a new simulator for the GRI-909.
- It has been hand-tested; so far, no software has been discovered.

1.2 VAX

- SET CPU CONHALT will cause a HALT instruction to return to the
  boot ROM console rather than to SIMH.  SET CPU SIMHALT restores
  the default behavior.
- BRB/W self at IPL 1F stops the simulator.  This is the default
  behavior of VMS at exit.

1.3 PDP-18b

- ATTACH -A PTR/PTP attaches the reader and punch in ASCII mode.
  In ASCII mode, the reader automatically sets the high order bit
  of incoming alphabetic data, and the punch clears the high order
  bit of outgoing data.

1.4 SCP

- DO -V echoes commands from the file as they are executed.
- Under Windows, execution priority is set BELOW_NORMAL when the
  simulator is running.

2. Release Notes

2.1 Bugs Fixed

- PDP-11 CPU: fixed updating of MMR0 on a memory management error.
- VAX FPA: changed function names to avoid conflict with C math library.
- 1401 MT: read end of record generates group mark without word mark.
- 1401 DP: fixed address generation and checking.
- SCP: an EXIT within a DO command will cause the simulator to exit.

3. In Progress

- Interdata 16b/32b: coded, not tested.
- SDS 940: coded, not tested.
- IBM 1620: coded, not tested.

If you would like to help with the debugging of the untested simulators,
they can be made available by special request.
This commit is contained in:
Bob Supnik
2002-07-14 15:20:00 -07:00
committed by Mark Pizzolato
parent 701f0fe028
commit df6475181c
179 changed files with 36441 additions and 4464 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 KiB

BIN
Ibm1130/HAND.CUR Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

274
Ibm1130/ibm1130.mak Normal file
View File

@@ -0,0 +1,274 @@
# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
!IF "$(CFG)" == ""
CFG=Win32 Debug
!MESSAGE No configuration specified. Defaulting to Win32 Debug.
!ENDIF
!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE on this makefile
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ibm1130.mak" CFG="Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
!ERROR An invalid configuration is specified.
!ENDIF
################################################################################
# Begin Project
# PROP Target_Last_Scanned "Win32 Debug"
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "WinRel"
# PROP BASE Intermediate_Dir "WinRel"
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "WinRel"
# PROP Intermediate_Dir "WinRel"
OUTDIR=.\WinRel
INTDIR=.\WinRel
ALL : $(OUTDIR)/ibm1130.exe $(OUTDIR)/ibm1130.bsc
$(OUTDIR) :
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
# ADD CPP /nologo /W3 /GX /YX /O2 /I "c:\pdp11\supnik" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR /c
CPP_PROJ=/nologo /W3 /GX /YX /O2 /I "c:\pdp11\supnik" /D "NDEBUG" /D "WIN32" /D\
"_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR$(INTDIR)/ /Fp$(OUTDIR)/"ibm1130.pch"\
/Fo$(INTDIR)/ /c
CPP_OBJS=.\WinRel/
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
RSC_PROJ=/l 0x409 /fo$(INTDIR)/"ibm1130.res" /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o$(OUTDIR)/"ibm1130.bsc"
BSC32_SBRS= \
$(INTDIR)/ibm1130_cpu.sbr \
$(INTDIR)/ibm1130_sys.sbr \
$(INTDIR)/ibm1130_cr.sbr \
$(INTDIR)/ibm1130_stddev.sbr \
$(INTDIR)/ibm1130_disk.sbr \
$(INTDIR)/scp_tty.sbr \
$(INTDIR)/scp.sbr
$(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
$(BSC32) @<<
$(BSC32_FLAGS) $(BSC32_SBRS)
<<
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib\
/NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:$(OUTDIR)/"ibm1130.pdb"\
/MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe"
DEF_FILE=
LINK32_OBJS= \
$(INTDIR)/ibm1130_cpu.obj \
$(INTDIR)/ibm1130_sys.obj \
$(INTDIR)/ibm1130_cr.obj \
$(INTDIR)/ibm1130_stddev.obj \
$(INTDIR)/ibm1130.res \
$(INTDIR)/ibm1130_disk.obj \
$(INTDIR)/scp_tty.obj \
$(INTDIR)/scp.obj
$(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "WinDebug"
# PROP BASE Intermediate_Dir "WinDebug"
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "WinDebug"
# PROP Intermediate_Dir "WinDebug"
OUTDIR=.\WinDebug
INTDIR=.\WinDebug
ALL : $(OUTDIR)/ibm1130.exe $(OUTDIR)/ibm1130.bsc
$(OUTDIR) :
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
# ADD CPP /nologo /W3 /GX /Zi /YX /Od /I "c:\pdp11\supnik" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR /c
CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /I "c:\pdp11\supnik" /D "_DEBUG" /D\
"WIN32" /D "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR$(INTDIR)/\
/Fp$(OUTDIR)/"ibm1130.pch" /Fo$(INTDIR)/ /Fd$(OUTDIR)/"ibm1130.pdb" /c
CPP_OBJS=.\WinDebug/
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
RSC_PROJ=/l 0x409 /fo$(INTDIR)/"ibm1130.res" /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o$(OUTDIR)/"ibm1130.bsc"
BSC32_SBRS= \
$(INTDIR)/ibm1130_cpu.sbr \
$(INTDIR)/ibm1130_sys.sbr \
$(INTDIR)/ibm1130_cr.sbr \
$(INTDIR)/ibm1130_stddev.sbr \
$(INTDIR)/ibm1130_disk.sbr \
$(INTDIR)/scp_tty.sbr \
$(INTDIR)/scp.sbr
$(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
$(BSC32) @<<
$(BSC32_FLAGS) $(BSC32_SBRS)
<<
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib\
/NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:$(OUTDIR)/"ibm1130.pdb" /DEBUG\
/MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe"
DEF_FILE=
LINK32_OBJS= \
$(INTDIR)/ibm1130_cpu.obj \
$(INTDIR)/ibm1130_sys.obj \
$(INTDIR)/ibm1130_cr.obj \
$(INTDIR)/ibm1130_stddev.obj \
$(INTDIR)/ibm1130.res \
$(INTDIR)/ibm1130_disk.obj \
$(INTDIR)/scp_tty.obj \
$(INTDIR)/scp.obj
$(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
.c{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.cpp{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.cxx{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
################################################################################
# Begin Group "Source Files"
################################################################################
# Begin Source File
SOURCE=.\ibm1130_cpu.c
DEP_IBM11=\
.\ibm1130_defs.h\
..\sim_defs.h
$(INTDIR)/ibm1130_cpu.obj : $(SOURCE) $(DEP_IBM11) $(INTDIR)
# End Source File
################################################################################
# Begin Source File
SOURCE=.\ibm1130_sys.c
DEP_IBM113=\
.\ibm1130_defs.h\
..\sim_defs.h
$(INTDIR)/ibm1130_sys.obj : $(SOURCE) $(DEP_IBM113) $(INTDIR)
# End Source File
################################################################################
# Begin Source File
SOURCE=.\ibm1130_cr.c
DEP_IBM1130=\
.\ibm1130_defs.h\
..\sim_defs.h
$(INTDIR)/ibm1130_cr.obj : $(SOURCE) $(DEP_IBM1130) $(INTDIR)
# End Source File
################################################################################
# Begin Source File
SOURCE=.\ibm1130_stddev.c
DEP_IBM1130_=\
.\ibm1130_defs.h\
.\ibm1130_conout.h\
.\ibm1130_conin.h\
.\ibm1130_prtwheel.h\
..\sim_defs.h
$(INTDIR)/ibm1130_stddev.obj : $(SOURCE) $(DEP_IBM1130_) $(INTDIR)
# End Source File
################################################################################
# Begin Source File
SOURCE=.\ibm1130.rc
DEP_IBM1130_R=\
.\1130consoleblank.bmp\
.\HAND.CUR
$(INTDIR)/ibm1130.res : $(SOURCE) $(DEP_IBM1130_R) $(INTDIR)
$(RSC) $(RSC_PROJ) $(SOURCE)
# End Source File
################################################################################
# Begin Source File
SOURCE=.\ibm1130_disk.c
DEP_IBM1130_D=\
.\ibm1130_defs.h\
..\sim_defs.h
$(INTDIR)/ibm1130_disk.obj : $(SOURCE) $(DEP_IBM1130_D) $(INTDIR)
# End Source File
################################################################################
# Begin Source File
SOURCE=..\scp_tty.c
DEP_SCP_T=\
..\sim_defs.h
$(INTDIR)/scp_tty.obj : $(SOURCE) $(DEP_SCP_T) $(INTDIR)
$(CPP) $(CPP_PROJ) $(SOURCE)
# End Source File
################################################################################
# Begin Source File
SOURCE=.\scp.c
DEP_SCP_C=\
.\sim_defs.h\
..\sim_rev.h
$(INTDIR)/scp.obj : $(SOURCE) $(DEP_SCP_C) $(INTDIR)
# End Source File
# End Group
# End Project
################################################################################

61
Ibm1130/ibm1130.rc Normal file
View File

@@ -0,0 +1,61 @@
//Microsoft Visual C++ generated resource script.
//
#include "ibm1130res.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include <windows.h>
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"ibm1130res.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include <windows.h>\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
/////////////////////////////////////////////////////////////////////////////
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_CONSOLE BITMAP DISCARDABLE "1130consoleblank.bmp"
IDC_HAND CURSOR DISCARDABLE "HAND.CUR"
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

30
Ibm1130/ibm1130_conin.h Normal file
View File

@@ -0,0 +1,30 @@
// ctrl-M (Enter) => EOF
// ctrl-U => Erase field
// ctrl-Q => Interrupt request (not here)
// ctrl-C => Program stop (not here)
// \ => "not"
// Del => backspace
// Ctrl-H => backspace
static uint16 ascii_to_conin[] = /* ASCII to ((hollerith << 4) | special key flags) */
{
/* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */
/* 00 */ 0, 0, 0, 0, 0, 0, 0, 0,0x0004, 0, 0, 0, 0,0x0008, 0, 0,
/* 01 */ 0, 0, 0, 0, 0,0x0002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 20 */ 0x0001,0x4820,0x0060,0x0420,0x4420,0x2220,0x8000,0x0120,0x8120,0x4120,0x4220,0x80a0,0x2420,0x4000,0x8420,0x3000,
/* 30 */ 0x2000,0x1000,0x0800,0x0400,0x0200,0x0100,0x0080,0x0040,0x0020,0x0010,0x0820,0x40a0,0x8220,0x00a0,0x20a0,0x2060,
/* 40 */ 0x0220,0x9000,0x8800,0x8400,0x8200,0x8100,0x8080,0x8040,0x8020,0x8010,0x5000,0x4800,0x4400,0x4200,0x4100,0x4080,
/* 50 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010,0xa420, 0,0xc420,0x4060,0x2120,
/* 60 */ 0,0x9000,0x8800,0x8400,0x8200,0x8100,0x8080,0x8040,0x8020,0x8010,0x5000,0x4800,0x4400,0x4200,0x4100,0x4080,
/* 70 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010,0xa420, 0,0x8060, 0,0x0004,
/* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* b0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* c0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* d0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* e0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* f0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x0004,
};

32
Ibm1130/ibm1130_conout.h Normal file
View File

@@ -0,0 +1,32 @@
/* IBM1130 CONSOLE OUTPUT TO ASCII CONVERSION TABLE */
#define _0_ '\0'
#define CENT '\xA2'
#define REST IGNR
#define RDRSTP '?'
#define NOT '\xAC'
#define IGNR '\xFF'
#define CRLF '\r'
static char conout_to_ascii[] = /* console output code to ASCII */
{
/* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */
/* 00 */ '.', _0_, CENT, '\n', '@', REST, '%', _0_, _0_,RDRSTP, _0_, _0_, _0_, _0_, _0_, _0_,
/* 10 */ 'f', '\b', 'F', _0_, 'g', _0_, 'G', _0_, 'b', _0_, 'B', _0_, 'c', _0_, 'C', _0_,
/* 20 */ 'i', ' ', 'I', _0_, 'h', _0_, 'H', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_,
/* 30 */ 'd', _0_, 'D', _0_, 'e', _0_, 'E', _0_, _0_, _0_, _0_, _0_, 'a', _0_, 'A', _0_,
/* 40 */ '$', _0_, '!', _0_, '&', _0_, '>', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_,
/* 50 */ 'o', _0_, 'O', _0_, 'p', _0_, 'P', _0_, 'k', _0_, 'K', _0_, 'l', _0_, 'L', _0_,
/* 60 */ 'r', _0_, 'R', _0_, 'q', _0_, 'Q', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_,
/* 70 */ 'm', _0_, 'M', _0_, 'n', _0_, 'N', _0_, _0_, _0_, _0_, _0_, 'j', _0_, _0_, _0_,
/* 80 */ ',', CRLF, ':', _0_, '-', _0_, '?', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_,
/* 90 */ 'w', _0_, 'W', _0_, 'x', _0_, 'X', _0_, 's', _0_, 'S', _0_, 't', _0_, 'T', _0_,
/* A0 */ 'z', _0_, 'Z', _0_, 'y', _0_, 'Y', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_,
/* B0 */ 'u', _0_, 'U', _0_, 'v', _0_, 'V', _0_, _0_, _0_, _0_, _0_, '/', _0_, '_', _0_,
/* C0 */ '#', _0_, '=', _0_, '0', _0_, '|', _0_, _0_, _0_, _0_, _0_, _0_, _0_, 'J', _0_,
/* D0 */ '6', _0_, ';', _0_, '7', _0_, '*', _0_, '2', _0_, '+', _0_, '3', _0_, '<', _0_,
/* E0 */ '9', _0_, '"', _0_, '8', _0_, '\'', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_,
/* F0 */ '4', _0_, NOT, _0_, '5', _0_, ')', _0_, _0_, _0_, _0_, _0_, '1', _0_, '(', _0_,
};

2324
Ibm1130/ibm1130_cpu.c Normal file

File diff suppressed because it is too large Load Diff

1092
Ibm1130/ibm1130_cr.c Normal file

File diff suppressed because it is too large Load Diff

229
Ibm1130/ibm1130_defs.h Normal file
View File

@@ -0,0 +1,229 @@
/* ibm1130_defs.h: IBM-1130 simulator definitions
*/
#include "sim_defs.h" /* main SIMH defns (include path should include .., or make a copy) */
#include <setjmp.h>
#include <assert.h>
#if defined(VMS)
# include <unistd.h> /* to pick up 'unlink' */
#endif
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
#define MAX(a,b) (((a) >= (b)) ? (a) : (b))
// #define ENABLE_GUI // uncomment to compile the GUI extensions
/* ------------------------------------------------------------------------ */
/* Architectural constants */
#define MAXMEMSIZE (32768) /* 32Kwords */
#define INIMEMSIZE (16384) /* 16Kwords */
#define MEMSIZE (cpu_unit.capac)
#define UNIT_MSIZE (1 << (UNIT_V_UF + 7)) /* flag for memory size setting */
#define ILL_ADR_FLAG 0x40000000 /* an impossible 1130 address */
/* ------------------------------------------------------------------------ */
/* Global state */
extern uint16 M[]; /* core memory, up to 32Kwords */
extern uint16 ILSW[]; /* interrupt level status words */
extern int32 IAR; /* instruction address register */
extern int32 CES; /* console entry switches */
extern int32 ACC, EXT; /* accumulator and extension */
extern int32 ipl; /* current interrupt level (-1 = not handling irq) */
extern int32 iplpending; /* bitfield: interrupted IPL's */
extern int32 tbit; /* trace flag (causes level 5 IRQ after each instr) */
extern int32 V, C; /* condition codes: overflow, carry */
extern int32 wait_state; /* wait state (waiting for an IRQ or processor halted) */
extern int32 int_req; /* bitfield: interrupt request levels active */
extern int32 int_mask; /* current active interrupt mask (ipl sensitive) */
extern int32 SR; /* switch register */
extern int32 DR; /* display register */
extern int32 wait_enable; /* wait state enable */
extern int32 mem_mask; /* mem_mask - valid address mask (memsize-1) */
extern int32 ibkpt_addr; /* breakpoint addr */
extern int32 sim_int_char;
#define WAIT_OP 1 /* wait state causes: wait instruction, invalid instruction*/
#define WAIT_INVALID_OP 2
/* ------------------------------------------------------------------------ */
/* memory IO routines */
int32 ReadW (int32 a);
void WriteW (int32 a, int32 d);
/* ------------------------------------------------------------------------ */
/* handy macros */
#define CLRBIT(v,b) ((v) &= ~(b))
#define SETBIT(v,b) ((v) |= (b))
#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b)))
/* ------------------------------------------------------------------------ */
/* Simulator stop codes */
#define STOP_WAIT 1 /* wait, no events */
#define STOP_INVALID_INSTR 2 /* bad instruction */
#define STOP_IBKPT 3 /* simulator breakpoint */
#define STOP_INCOMPLETE 4 /* simulator coding not complete here */
#define STOP_POWER_OFF 5 /* no power */
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */
#define INT_REQ_0 0x01 /* bits for interrupt levels (ipl, iplpending, int_req, int_mask) */
#define INT_REQ_1 0x02
#define INT_REQ_2 0x04
#define INT_REQ_3 0x08
#define INT_REQ_4 0x10
#define INT_REQ_5 0x20
#define XIO_UNUSED 0x00 /* XIO commands */
#define XIO_WRITE 0x01
#define XIO_READ 0x02
#define XIO_SENSE_IRQ 0x03
#define XIO_CONTROL 0x04
#define XIO_INITW 0x05
#define XIO_INITR 0x06
#define XIO_SENSE_DEV 0x07
#define XIO_FAILED 0x20 /* fake function to record error */
/* ILSW bits - set by appropriate device whenever an interrupt is outstanding */
#define ILSW_0_1442_CARD 0x8000 /* not actually used */
#define ILSW_1_SCA 0x8000
#define ILSW_1_1132_PRINTER 0x4000
#define ILSW_2_1131_DISK 0x8000
#define ILSW_2_2310_DRV_1 0x4000
#define ILSW_2_2310_DRV_2 0x2000
#define ILSW_2_2310_DRV_3 0x1000
#define ILSW_2_2310_DRV_4 0x0800 /* can have 2310 or 2311 */
#define ILSW_2_2311_DRV_1_DISK_1 0x4000
#define ILSW_2_2311_DRV_1_DISK_2 0x2000
#define ILSW_2_2311_DRV_1_DISK_3 0x1000
#define ILSW_2_2311_DRV_1_DISK_4 0x0800
#define ILSW_2_2311_DRV_1_DISK_5 0x0400
#define ILSW_2_2311_DRV_2_DISK_1 0x0200
#define ILSW_2_2311_DRV_2_DISK_2 0x0100
#define ILSW_2_2311_DRV_2_DISK_3 0x0080
#define ILSW_2_2311_DRV_2_DISK_4 0x0040
#define ILSW_2_2311_DRV_2_DISK_5 0x0020
#define ILSW_2_SAC_BIT_11 0x0010
#define ILSW_2_SAC_BIT_12 0x0008
#define ILSW_2_SAC_BIT_13 0x0004
#define ILSW_2_SAC_BIT_14 0x0002
#define ILSW_2_SAC_BIT_15 0x0001
#define ILSW_3_1627_PLOTTER 0x8000
#define ILSW_3_SAC_BIT_01 0x4000
#define ILSW_3_SAC_BIT_02 0x2000
#define ILSW_3_SAC_BIT_03 0x1000
#define ILSW_3_2250_DISPLAY 0x0800
#define ILSW_3_SYSTEM7 0x0800
#define ILSW_3_SAC_BIT_05 0x0400
#define ILSW_3_SAC_BIT_06 0x0200
#define ILSW_3_SAC_BIT_07 0x0100
#define ILSW_3_SAC_BIT_08 0x0080
#define ILSW_3_SAC_BIT_09 0x0040
#define ILSW_3_SAC_BIT_10 0x0020
#define ILSW_3_SAC_BIT_11 0x0010
#define ILSW_3_SAC_BIT_12 0x0008
#define ILSW_3_SAC_BIT_13 0x0004
#define ILSW_3_SAC_BIT_14 0x0002
#define ILSW_3_SAC_BIT_15 0x0001
#define ILSW_4_1134_TAPE 0x8000
#define ILSW_4_1055_TAPE 0x8000
#define ILSW_4_CONSOLE 0x4000
#define ILSW_4_1442_CARD 0x2000
#define ILSW_4_2501_CARD 0x1000
#define ILSW_4_1403_PRINTER 0x0800
#define ILSW_4_1231_MARK 0x0400
#define ILSW_4_SAC_BIT_06 0x0200
#define ILSW_4_SAC_BIT_07 0x0100
#define ILSW_4_SAC_BIT_08 0x0080
#define ILSW_4_SAC_BIT_09 0x0040
#define ILSW_4_SAC_BIT_10 0x0020
#define ILSW_4_SAC_BIT_11 0x0010
#define ILSW_4_SAC_BIT_12 0x0008
#define ILSW_4_SAC_BIT_13 0x0004
#define ILSW_4_SAC_BIT_14 0x0002
#define ILSW_4_SAC_BIT_15 0x0001
#define ILSW_5_INT_RUN 0x8000
#define ILSW_5_PROGRAM_STOP 0x8000
#define ILSW_5_SAC_BIT_01 0x4000
#define ILSW_5_SAC_BIT_02 0x2000
#define ILSW_5_SAC_BIT_03 0x1000
#define ILSW_5_SAC_BIT_04 0x0800
#define ILSW_5_SAC_BIT_05 0x0400
#define ILSW_5_SAC_BIT_06 0x0200
#define ILSW_5_SAC_BIT_07 0x0100
#define ILSW_5_SAC_BIT_08 0x0080
#define ILSW_5_SAC_BIT_09 0x0040
#define ILSW_5_SAC_BIT_10 0x0020
#define ILSW_5_SAC_BIT_11 0x0010
#define ILSW_5_SAC_BIT_12 0x0008
#define ILSW_5_SAC_BIT_13 0x0004
#define ILSW_5_SAC_BIT_14 0x0002
#define ILSW_5_SAC_BIT_15 0x0001
//* console DSW bits
#define CON_DSW_PROGRAM_STOP 0x8000
#define CON_DSW_INT_RUN 0x4000
/* prototypes: xio handlers */
void xio_1131_console (int32 addr, int32 func, int32 modify); // console keyboard and printer
void xio_1142_card (int32 addr, int32 func, int32 modify); // standard card reader/punch
void xio_1134_papertape (int32 addr, int32 func, int32 modify); // paper tape reader/punch
void xio_disk (int32 addr, int32 func, int32 modify, int drv); // internal CPU disk
void xio_1627_plotter (int32 addr, int32 func, int32 modify); // XY plotter
void xio_1132_printer (int32 addr, int32 func, int32 modify); // standard line printer
void xio_1131_switches (int32 addr, int32 func, int32 modify); // console buttons & switches
void xio_1231_optical (int32 addr, int32 func, int32 modify); // optical mark page reader
void xio_2501_card (int32 addr, int32 func, int32 modify); // alternate high-speed card reader
void xio_1131_synch (int32 addr, int32 func, int32 modify); // synchronous communications adapter
void xio_system7 (int32 addr, int32 func, int32 modify); // system/7 interprocessor IO link
void xio_1403_printer (int32 addr, int32 func, int32 modify); // alternate high-speed printer
void xio_2250_display (int32 addr, int32 func, int32 modify); // vector display processor
void xio_error (char *msg);
void bail (char *msg);
t_stat load_cr_boot (int drv);
t_stat cr_boot (int unitno);
void calc_ints (void); /* recalculate interrupt bitmask */
void trace_io (char *fmt, ...); /* debugging printout */
void panic (char *msg); /* bail out of simulator */
char *upcase(char *str);
/* GUI interface routines */
void remark_cmd (char *remark);
void stuff_cmd (char *cmd);
t_bool keyboard_is_locked (void);
void forms_check (int set); /* device notification to console lamp display */
void print_check (int set);
void keyboard_selected (int select);
void disk_ready (int ready);
void disk_unlocked (int unlocked);
#ifdef ENABLE_GUI
# define GUI_BEGIN_CRITICAL_SECTION begin_critical_section();
# define GUI_END_CRITICAL_SECTION end_critical_section();
void begin_critical_section (void);
void end_critical_section (void);
#else
# define GUI_BEGIN_CRITICAL_SECTION
# define GUI_END_CRITICAL_SECTION
#endif

441
Ibm1130/ibm1130_disk.c Normal file
View File

@@ -0,0 +1,441 @@
/* ibm1130_disk.c: IBM 1130 disk IO simulator
NOTE - there is a problem with this code. The Device Status Word (DSW) is
computed from current conditions when requested by an XIO load status
command; the value of DSW available to the simulator's examine & save
commands may NOT be accurate. This should probably be fixed.
Copyright (c) 2002, Brian Knittel
Based on PDP-11 simulator written by Robert M Supnik
Revision History
31July2001 - Derived from pdp11_stddev.c, which carries this disclaimer:
Copyright (c) 1993-2001, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
*/
#include "ibm1130_defs.h"
/* Constants */
#define DSK_NUMWD 321 /* words/sector */
#define DSK_NUMSC 4 /* sectors/surface */
#define DSK_NUMSF 2 /* surfaces/cylinder */
#define DSK_NUMCY 203 /* cylinders/drive */
#define DSK_NUMTR (DSK_NUMCY * DSK_NUMSF) /* tracks/drive */
#define DSK_NUMDR 5 /* drives/controller */
#define DSK_SIZE (DSK_NUMCY * DSK_NUMSF * DSK_NUMSC * DSK_NUMWD) /* words/drive */
#define UNIT_V_RONLY (UNIT_V_UF + 0) /* hwre write lock */
#define UNIT_V_OPERR (UNIT_V_UF + 1) /* operation error flag */
#define UNIT_V_HARDERR (UNIT_V_UF + 2) /* hard error flag (reset on power down) */
#define UNIT_RONLY (1u << UNIT_V_RONLY)
#define UNIT_OPERR (1u << UNIT_V_OPERR)
#define UNIT_HARDERR (1u << UNIT_V_HARDERR)
static int16 dsk_dsw[DSK_NUMDR] = {0}; /* device status words */
static int16 dsk_sec[DSK_NUMDR] = {0}; /* next-sector-up */
int32 dsk_swait = 10; /* seek time */
int32 dsk_rwait = 10; /* rotate time */
#define DSK_DSW_DATA_ERROR 0x8000 /* device status word bits */
#define DSK_DSW_OP_COMPLETE 0x4000
#define DSK_DSW_NOT_READY 0x2000
#define DSK_DSW_DISK_BUSY 0x1000
#define DSK_DSW_CARRIAGE_HOME 0x0800
#define DSK_DSW_SECTOR_MASK 0x0003
static t_stat dsk_svc (UNIT *uptr);
static t_stat dsk_reset (DEVICE *dptr);
static t_stat dsk_attach (UNIT *uptr, char *cptr);
static t_stat dsk_detach (UNIT *uptr);
static t_stat dsk_boot (int unitno);
static void diskfail (UNIT *uptr, int errflag);
/* DSK data structures
dsk_dev disk device descriptor
dsk_unit unit descriptor
dsk_reg register list
*/
UNIT dsk_unit[] = {
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }
};
#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)
/* Parameters in the unit descriptor */
#define CYL u3 /* current cylinder */
#define FUNC u4 /* current function */
REG dsk_reg[] = {
{ HRDATA (DSKDSW0, dsk_dsw[0], 16) },
{ HRDATA (DSKDSW1, dsk_dsw[1], 16) },
{ HRDATA (DSKDSW2, dsk_dsw[2], 16) },
{ HRDATA (DSKDSW3, dsk_dsw[3], 16) },
{ HRDATA (DSKDSW4, dsk_dsw[4], 16) },
{ DRDATA (STIME, dsk_swait, 24), PV_LEFT },
{ DRDATA (RTIME, dsk_rwait, 24), PV_LEFT },
{ NULL } };
MTAB dsk_mod[] = {
{ UNIT_RONLY, 0, "write enabled", "ENABLED", NULL },
{ UNIT_RONLY, UNIT_RONLY, "write locked", "LOCKED", NULL },
{ 0 } };
DEVICE dsk_dev = {
"DSK", dsk_unit, dsk_reg, dsk_mod,
DSK_NUMDR, 16, 16, 1, 16, 16,
NULL, NULL, &dsk_reset,
dsk_boot, dsk_attach, dsk_detach};
static int32 dsk_ilswbit[DSK_NUMDR] = { /* interrupt level status word bits for the drives */
ILSW_2_1131_DISK,
ILSW_2_2310_DRV_1,
ILSW_2_2310_DRV_2,
ILSW_2_2310_DRV_3,
ILSW_2_2310_DRV_4,
};
static int32 dsk_ilswlevel[DSK_NUMDR] =
{
2, /* interrupt levels for the drives */
2, 2, 2, 2
};
/* xio_disk - XIO command interpreter for the disk drives */
/*
* device status word:
*
* 0 data error, occurs when:
* 1. A modulo 4 error is detected during a read, read-check, or write operation.
* 2. The disk storage is in a read or write mode at the leading edge of a sector pulse.
* 3. A seek-incomplete signal is received from the 2311.
* 4. A write select error has occurred in the disk storage drive.
* 5. The power unsafe latch is set in the attachment.
* Conditions 1, 2, and 3 are turned off by a sense device command with modifier bit 15
* set to 1. Conditions 4 and 5 are turned off by powering the drive off and back on.
* 1 operation complete
* 2 not ready, occurs when disk not ready or busy or disabled or off-line or
* power unsafe latch set. Also included in the disk not ready is the write select error,
* which can be a result of power unsafe or write select.
* 3 disk busy
* 4 carriage home (on cyl 0)
* 15-16: number of next sector spinning into position.
*/
void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
{
int i, rev, nsteps, newcyl, sec, nwords;
t_addr newpos;
char msg[80];
UNIT *uptr = dsk_unit+drv;
int16 buf[DSK_NUMWD];
if (! BETWEEN(drv, 0, DSK_NUMDR-1)) { // hmmm, invalid drive */
if (func != XIO_SENSE_DEV) { // tried to use it, too
sprintf(msg, "Op %x on invalid drive number %d", func, drv);
xio_error(msg);
}
return;
}
CLRBIT(uptr->flags, UNIT_OPERR); /* clear pending error flag from previous op, if any */
switch (func) {
case XIO_INITR:
if (! IS_ONLINE(uptr)) { /* disk is offline */
diskfail(uptr, UNIT_HARDERR); /* make error stick till reset or attach */
break;
}
sim_cancel(uptr); /* cancel any pending ops */
dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; /* and mark the disk as busy */
nwords = M[iocc_addr++ & mem_mask]; /* get word count w/o upsetting SAR/SBR */
if (nwords == 0) /* this is bad -- locks up disk controller ! */
break;
nwords &= 1023; /* sanity check */
if (! BETWEEN(nwords, 1, DSK_NUMWD)) { /* count bad */
SETBIT(uptr->flags, UNIT_OPERR); /* set data error DSW bit when op complete */
nwords = DSK_NUMWD; /* limit xfer to proper sector size */
}
sec = modify & 0x07; /* get sector on cylinder */
if ((modify & 0x0080) == 0) { /* it's real if not a read check */
newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD;
if (uptr->pos != newpos)
fseek(uptr->fileref, newpos, SEEK_SET);
fread(buf, 2, DSK_NUMWD, uptr->fileref); // read whole sector so we're in position for next read
uptr->pos = newpos + 2*DSK_NUMWD;
trace_io("* DSK%d read %d words from %d.%d (%x) to M[%04x-%04x]", uptr-dsk_unit, nwords, uptr->CYL, sec, newpos, iocc_addr & mem_mask,
(iocc_addr + nwords - 1) & mem_mask);
for (i = 0; i < nwords; i++)
M[iocc_addr++ & mem_mask] = buf[i];
}
else
trace_io("* DSK%d verify %d.%d", uptr-dsk_unit, uptr->CYL, sec);
uptr->FUNC = func;
sim_activate(uptr, dsk_rwait);
break;
case XIO_INITW:
if (! IS_ONLINE(uptr)) { /* disk is offline */
diskfail(uptr, UNIT_HARDERR); /* make error stick till reset or attach */
break;
}
if (uptr->flags & UNIT_RONLY) { /* oops, write to RO disk? permanent error */
diskfail(uptr, UNIT_HARDERR);
break;
}
sim_cancel(uptr); /* cancel any pending ops */
dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; /* and mark drive as busy */
nwords = M[iocc_addr++ & mem_mask]; /* get word count w/o upsetting SAR/SBR */
if (nwords == 0) /* this is bad -- locks up disk controller ! */
break;
nwords &= 1023; /* sanity check */
if (! BETWEEN(nwords, 1, DSK_NUMWD)) { /* count bad */
SETBIT(uptr->flags, UNIT_OPERR); /* set data error DSW bit when op complete */
nwords = DSK_NUMWD; /* limit xfer to proper sector size */
}
sec = modify & 0x07; /* get sector on cylinder */
newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD;
if (uptr->pos != newpos)
fseek(uptr->fileref, newpos, SEEK_SET);
trace_io("* DSK%d wrote %d words from M[%04x-%04x] to %d.%d (%x)", uptr-dsk_unit, nwords, iocc_addr & mem_mask, (iocc_addr + nwords - 1) & mem_mask, uptr->CYL, sec, newpos);
for (i = 0; i < nwords; i++)
buf[i] = M[iocc_addr++ & mem_mask];
for (; i < DSK_NUMWD; i++) /* rest of sector gets zeroed */
buf[i] = 0;
fwrite(buf, 2, DSK_NUMWD, uptr->fileref);
uptr->pos = newpos + 2*DSK_NUMWD;
uptr->FUNC = func;
sim_activate(uptr, dsk_rwait);
break;
case XIO_CONTROL: /* step fwd/rev */
if (! IS_ONLINE(uptr)) {
diskfail(uptr, UNIT_HARDERR);
break;
}
sim_cancel(uptr);
rev = modify & 4;
nsteps = iocc_addr & 0x00FF;
if (nsteps == 0) /* 0 steps does not cause op complete interrupt */
break;
newcyl = uptr->CYL + (rev ? (-nsteps) : nsteps);
if (newcyl < 0)
newcyl = 0;
else if (newcyl >= DSK_NUMCY)
newcyl = DSK_NUMCY-1;
uptr->FUNC = func;
uptr->CYL = newcyl;
sim_activate(uptr, dsk_swait); /* schedule interrupt */
dsk_dsw[drv] |= DSK_DSW_DISK_BUSY;
trace_io("* DSK%d at cyl %d", uptr-dsk_unit, newcyl);
break;
case XIO_SENSE_DEV:
CLRBIT(dsk_dsw[drv], DSK_DSW_CARRIAGE_HOME|DSK_DSW_NOT_READY);
if ((uptr->flags & UNIT_HARDERR) || (dsk_dsw[drv] & DSK_DSW_DISK_BUSY) || ! IS_ONLINE(uptr))
SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY);
else if (uptr->CYL <= 0) {
SETBIT(dsk_dsw[drv], DSK_DSW_CARRIAGE_HOME);
uptr->CYL = 0;
}
dsk_sec[drv] = (dsk_sec[drv] + 1) % 4; /* advance the "next sector" count every time */
ACC = dsk_dsw[drv] | dsk_sec[drv];
if (modify & 0x01) { /* reset interrupts */
CLRBIT(dsk_dsw[drv], DSK_DSW_OP_COMPLETE|DSK_DSW_DATA_ERROR);
CLRBIT(ILSW[dsk_ilswlevel[drv]], dsk_ilswbit[drv]);
}
break;
default:
sprintf(msg, "Invalid disk XIO function %x", func);
xio_error(msg);
}
}
/* diskfail - schedule an operation complete that sets the error bit */
static void diskfail (UNIT *uptr, int errflag)
{
sim_cancel(uptr); /* cancel any pending ops */
SETBIT(uptr->flags, errflag); /* set the error flag */
uptr->FUNC = XIO_FAILED; /* tell svc routine why it failed */
sim_activate(uptr, 1); /* schedule an immediate op complete interrupt */
}
t_stat dsk_svc (UNIT *uptr)
{
int drv = uptr - dsk_unit;
CLRBIT(dsk_dsw[drv], DSK_DSW_DISK_BUSY); /* activate operation complete interrupt */
SETBIT(dsk_dsw[drv], DSK_DSW_OP_COMPLETE);
if (uptr->flags & (UNIT_OPERR|UNIT_HARDERR)) { /* word count error or data error */
SETBIT(dsk_dsw[drv], DSK_DSW_DATA_ERROR);
CLRBIT(uptr->flags, UNIT_OPERR); /* but don't clear hard error */
}
SETBIT(ILSW[dsk_ilswlevel[drv]], dsk_ilswbit[drv]);
#ifdef XXXX
switch (uptr->FUNC) {
case XIO_CONTROL:
case XIO_INITR:
case XIO_INITW:
case XIO_FAILED:
break;
default:
fprintf(stderr, "Unexpected FUNC %x in dsk_svc(%d)\n", uptr->FUNC, drv);
break;
}
uptr->FUNC = -1; // we're done with this operation
#endif
return SCPE_OK;
}
t_stat dsk_reset (DEVICE *dptr)
{
int drv;
UNIT *uptr;
for (drv = 0, uptr = dsk_dev.units; drv < DSK_NUMDR; drv++, uptr++) {
sim_cancel(uptr);
CLRBIT(ILSW[2], dsk_ilswbit[drv]);
CLRBIT(uptr->flags, UNIT_OPERR|UNIT_HARDERR);
uptr->CYL = 0;
uptr->FUNC = -1;
dsk_dsw[drv] = (uptr->flags & UNIT_ATT) ? DSK_DSW_CARRIAGE_HOME : 0;
}
calc_ints();
return SCPE_OK;
}
static t_stat dsk_attach (UNIT *uptr, char *cptr)
{
int drv = uptr - dsk_unit;
t_stat rval;
sim_cancel(uptr);
if ((rval = attach_unit(uptr, cptr)) != SCPE_OK)
return rval;
CLRBIT(ILSW[2], dsk_ilswbit[drv]);
CLRBIT(uptr->flags, UNIT_OPERR|UNIT_HARDERR);
calc_ints();
uptr->CYL = 0;
uptr->FUNC = -1;
dsk_dsw[drv] = DSK_DSW_CARRIAGE_HOME;
if (drv == 0) {
disk_ready(TRUE);
disk_unlocked(FALSE);
}
return SCPE_OK;
}
static t_stat dsk_detach (UNIT *uptr)
{
t_stat rval;
int drv = uptr - dsk_unit;
sim_cancel(uptr);
if ((rval = detach_unit (uptr)) != SCPE_OK)
return rval;
CLRBIT(ILSW[2], dsk_ilswbit[drv]);
CLRBIT(uptr->flags, UNIT_OPERR|UNIT_HARDERR);
calc_ints();
uptr->CYL = 0;
uptr->FUNC = -1;
dsk_dsw[drv] = 0;
if (drv == 0) {
disk_unlocked(TRUE);
disk_ready(FALSE);
}
return SCPE_OK;
}
// boot routine - if they type BOOT DSK, load the standard boot card.
static t_stat dsk_boot (int unitno)
{
t_stat rval;
if ((rval = reset_all(0)) != SCPE_OK)
return rval;
return load_cr_boot(unitno);
}

View File

@@ -0,0 +1,20 @@
static struct tag_codewheel {
unsigned char ascii;
unsigned char ebcdic;
} codewheel1132[] =
{ /* characters and EBCDIC codes in printwheel order */
'A', 0xC1, 'B', 0xC2, 'C', 0xC3, 'D', 0xC4,
'E', 0xC5, 'F', 0xC6, 'G', 0xC7, 'H', 0xC8,
'I', 0xC9, 'J', 0xD1, 'K', 0xD2, 'L', 0xD3,
'M', 0xD4, 'N', 0xD5, 'O', 0xD6, 'P', 0xD7,
'Q', 0xD8, 'R', 0xD9, 'S', 0xE2, 'T', 0xE3,
'U', 0xE4, 'V', 0xE5, 'W', 0xE6, 'X', 0xE7,
'Y', 0xE8, 'Z', 0xE9, '0', 0xF0, '1', 0xF1,
'2', 0xF2, '3', 0xF3, '4', 0xF4, '5', 0xF5,
'6', 0xF6, '7', 0xF7, '8', 0xF8, '9', 0xF9,
'&', 0x50, '-', 0x60, '/', 0x61, '.', 0x4B,
'$', 0x5B, ',', 0x6B, '*', 0x5C, '(', 0x4D,
')', 0x5D, '\'', 0x7D, '+', 0x4E, '=', 0x7E
};
#define WHEELCHARS (sizeof(codewheel1132)/sizeof(codewheel1132[0]))

748
Ibm1130/ibm1130_stddev.c Normal file
View File

@@ -0,0 +1,748 @@
/* ibm1130_stddev.c: IBM 1130 standard I/O devices simulator
Copyright (c) 2001, Brian Knittel
Based on PDP-11 simulator written by Robert M Supnik
Brian Knittel
Revision History
31July2001 - Derived from pdp11_stddev.c, which carries this disclaimer:
Copyright (c) 1993-2001, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
*/
#include "ibm1130_defs.h"
/* ---------------------------------------------------------------------------- */
static void badio (char *dev)
{
// the real 1130 just ignores attempts to use uninstalled devices. They get tested
// at times, so it's best to be quiet about this
// printf("%s I/O is not yet supported", dev);
// wait_state = WAIT_INVALID_OP;
}
void xio_1134_papertape (int32 addr, int32 func, int32 modify) {badio("papertape");}
void xio_1627_plotter (int32 addr, int32 func, int32 modify) {badio("plotter");}
void xio_1231_optical (int32 addr, int32 func, int32 modify) {badio("optical mark");}
void xio_2501_card (int32 addr, int32 func, int32 modify) {badio("2501 card");}
void xio_1131_synch (int32 addr, int32 func, int32 modify) {badio("SCA");}
void xio_system7 (int32 addr, int32 func, int32 modify) {badio("System 7");}
void xio_1403_printer (int32 addr, int32 func, int32 modify) {badio("1403 printer");}
void xio_2250_display (int32 addr, int32 func, int32 modify)
{
if (func != XIO_CONTROL)
badio("2250 display"); // resmon issues stop control, so ignore XIO_CONTROL
}
/* ---------------------------------------------------------------------------- */
static int32 tti_dsw = 0; /* device status words */
static int32 tto_dsw = 0;
static int32 con_dsw = 0;
static t_stat tti_svc (UNIT *uptr);
static t_stat tto_svc (UNIT *uptr);
static t_stat tti_reset (DEVICE *dptr);
static t_stat tto_reset (DEVICE *dptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_wait_kbd (void);
extern t_stat sim_putchar (int32 out);
extern UNIT *sim_clock_queue;
#define CSET_MASK 1 /* character set */
#define CSET_NORMAL 0
#define CSET_ASCII 1
#define IRQ_KEY 0x11 /* ctrl-Q */
#define PROGRAM_STOP_KEY 0x03 /* ctrl-C */
#include "ibm1130_conout.h" /* conout_to_ascii table */
#include "ibm1130_conin.h" /* ascii_to_conin table */
/* TTI data structures
tti_dev TTI device descriptor
tti_unit TTI unit descriptor
tti_reg TTI register list
*/
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
REG tti_reg[] = {
{ ORDATA (BUF, tti_unit.buf, 8) },
{ ORDATA (DSW, tti_dsw, 16) },
{ DRDATA (POS, tti_unit.pos, 32), PV_LEFT },
{ DRDATA (STIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL } };
MTAB tti_mod[] = {
{ CSET_MASK, CSET_NORMAL, NULL, "1130", NULL},
{ CSET_MASK, CSET_ASCII, NULL, "ASCII", NULL},
{ 0 } };
DEVICE tti_dev = {
"KEYBOARD", &tti_unit, tti_reg, tti_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tti_reset,
NULL, NULL, NULL };
/* TTO data structures
tto_dev TTO device descriptor
tto_unit TTO unit descriptor
tto_reg TTO register list
*/
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, 8) },
{ ORDATA (DSW, tto_dsw, 16) },
{ DRDATA (POS, tto_unit.pos, 32), PV_LEFT },
{ DRDATA (STIME, tto_unit.wait, 24), PV_LEFT },
{ NULL } };
MTAB tto_mod[] = {
{ CSET_MASK, CSET_NORMAL, NULL, "1130", NULL},
{ CSET_MASK, CSET_ASCII, NULL, "ASCII", NULL},
{ 0 } };
DEVICE tto_dev = {
"TTO", &tto_unit, tto_reg, tto_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tto_reset,
NULL, NULL, NULL };
/* Terminal input routines
tti_svc process event (character ready)
tti_reset process reset
tto_svc process event (print character)
tto_reset process reset
*/
#define TT_DSW_PRINTER_RESPONSE 0x8000
#define TT_DSW_KEYBOARD_RESPONSE 0x4000
#define TT_DSW_INTERRUPT_REQUEST 0x2000
#define TT_DSW_KEYBOARD_CONSOLE 0x1000
#define TT_DSW_PRINTER_BUSY 0x0800
#define TT_DSW_PRINTER_NOT_READY 0x0400
#define TT_DSW_KEYBOARD_BUSY 0x0200
void xio_1131_console (int32 iocc_addr, int32 func, int32 modify)
{
int ch;
char msg[80];
switch (func) {
case XIO_CONTROL:
SETBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY);
keyboard_selected(TRUE);
// sim_activate(&tti_unit, tti_unit.wait); /* poll keyboard never stops */
break;
case XIO_READ:
WriteW(iocc_addr, tti_unit.buf);
CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY);
keyboard_selected(FALSE);
break;
case XIO_WRITE:
ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */
if ((tto_unit.flags & CSET_MASK) == CSET_NORMAL)
ch = conout_to_ascii[ch]; /* convert to ASCII */
if (ch == 0)
ch = '?'; /* hmmm, unknown character */
tto_unit.buf = ch; /* save character to write */
SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY);
sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */
break;
case XIO_SENSE_DEV:
ACC = tto_dsw | tti_dsw;
if (modify & 0x01) { /* reset interrupts */
CLRBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE);
CLRBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE);
CLRBIT(ILSW[4], ILSW_4_CONSOLE);
}
break;
default:
sprintf(msg, "Invalid console XIO function %x", func);
xio_error(msg);
}
}
static void Beep (void) // notify user keyboard was locked or key was bad
{
sim_putchar(7);
}
// tti_svc - keyboard polling (never stops)
t_stat tti_svc (UNIT *uptr)
{
int32 temp;
sim_activate(&tti_unit, tti_unit.wait); /* continue polling */
temp = sim_poll_kbd();
if (temp < SCPE_KFLAG)
return temp; /* no char or error? */
temp &= 0xFF; /* remove SCPE_KFLAG */
if (temp == IRQ_KEY) { /* interrupt request key */
SETBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); /* queue interrupt */
SETBIT(ILSW[4], ILSW_4_CONSOLE);
calc_ints();
return SCPE_OK;
}
if (temp == PROGRAM_STOP_KEY) { /* simulate the program stop button */
SETBIT(con_dsw, CON_DSW_PROGRAM_STOP);
SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP);
calc_ints();
return SCPE_OK;
}
if (tti_dsw & TT_DSW_KEYBOARD_BUSY) { /* only store character if it was requested (keyboard unlocked) */
if ((uptr->flags & CSET_MASK) == CSET_NORMAL)
temp = ascii_to_conin[temp];
if (temp == 0) { /* ignore invalid characters */
Beep();
calc_ints();
return SCPE_OK;
}
tti_unit.buf = temp & 0xFFFE; /* save keystroke except last bit (not defined, */
tti_unit.pos = tti_unit.pos + 1; /* but it lets us distinguish 0 from no punch ' ' */
CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* clear busy flag (relock keyboard) */
keyboard_selected(FALSE);
SETBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); /* queue interrupt */
SETBIT(ILSW[4], ILSW_4_CONSOLE);
calc_ints();
}
else
Beep();
return SCPE_OK;
}
t_stat tti_reset (DEVICE *dptr)
{
tti_unit.buf = 0;
tti_dsw = 0;
CLRBIT(ILSW[4], ILSW_4_CONSOLE);
calc_ints();
keyboard_selected(FALSE);
sim_activate(&tti_unit, tti_unit.wait); /* always poll keyboard */
return SCPE_OK;
}
t_bool keyboard_is_locked (void) /* return TRUE if keyboard is not expecting a character */
{
return (tti_dsw & TT_DSW_KEYBOARD_BUSY) == 0;
}
t_stat tto_svc (UNIT *uptr)
{
int32 temp;
int ch;
CLRBIT(tto_dsw, TT_DSW_PRINTER_BUSY);
SETBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE);
SETBIT(ILSW[4], ILSW_4_CONSOLE);
calc_ints();
ch = tto_unit.buf & 0xFF;
switch (ch) {
case IGNR:
break;
case CRLF:
if ((temp = sim_putchar('\r')) != SCPE_OK)
return temp;
if ((temp = sim_putchar('\n')) != SCPE_OK)
return temp;
break;
default:
if ((temp = sim_putchar(ch)) != SCPE_OK)
return temp;
break;
}
tto_unit.pos = tto_unit.pos + 1; /* hmm, why do we count these? */
return SCPE_OK;
}
t_stat tto_reset (DEVICE *dptr)
{
tto_unit.buf = 0;
tto_dsw = 0;
CLRBIT(ILSW[4], ILSW_4_CONSOLE);
calc_ints();
sim_cancel(&tto_unit); /* deactivate unit */
return SCPE_OK;
}
/***************************************************************************************
* 1132 PRINTER
***************************************************************************************/
#define PRT_DSW_READ_EMITTER_RESPONSE 0x8000
#define PRT_DSW_SKIP_RESPONSE 0x4000
#define PRT_DSW_SPACE_RESPONSE 0x2000
#define PRT_DSW_CARRIAGE_BUSY 0x1000
#define PRT_DSW_PRINT_SCAN_CHECK 0x0800
#define PRT_DSW_NOT_READY 0x0400
#define PRT_DSW_PRINTER_BUSY 0x0200
#define PRT_DSW_CHANNEL_MASK 0x00FF
#define PRT_DSW_CHANNEL_1 0x0080
#define PRT_DSW_CHANNEL_2 0x0040
#define PRT_DSW_CHANNEL_3 0x0020
#define PRT_DSW_CHANNEL_4 0x0010
#define PRT_DSW_CHANNEL_5 0x0008
#define PRT_DSW_CHANNEL_6 0x0004
#define PRT_DSW_CHANNEL_9 0x0002
#define PRT_DSW_CHANNEL_12 0x0001
#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)
static t_stat prt_svc (UNIT *uptr);
static t_stat prt_reset (DEVICE *dptr);
static t_stat prt_attach (UNIT *uptr, char *cptr);
static t_stat prt_detach (UNIT *uptr);
static int16 prt_dsw = 0; /* device status word */
static int32 prt_swait = 500; /* line skip wait */
static int32 prt_cwait = 1000; /* character rotation wait */
#define UNIT_V_FORMCHECK (UNIT_V_UF + 0) /* out of paper error */
#define UNIT_V_DATACHECK (UNIT_V_UF + 1) /* printer overrun error */
#define UNIT_V_SKIPPING (UNIT_V_UF + 2) /* printer skipping */
#define UNIT_V_SPACING (UNIT_V_UF + 3) /* printer is spacing */
#define UNIT_V_PRINTING (UNIT_V_UF + 4) /* printer printing */
#define UNIT_FORMCHECK (1u << UNIT_V_FORMCHECK)
#define UNIT_DATACHECK (1u << UNIT_V_DATACHECK)
#define UNIT_SKIPPING (1u << UNIT_V_SKIPPING)
#define UNIT_SPACING (1u << UNIT_V_SPACING)
#define UNIT_PRINTING (1u << UNIT_V_PRINTING)
UNIT prt_unit[] = {
{ UDATA (&prt_svc, UNIT_ATTABLE, 0) },
};
/* Parameter in the unit descriptor */
#define CMD_NONE 0
#define CMD_SPACE 1
#define CMD_SKIP 2
#define CMD_PRINT 3
REG prt_reg[] = {
{ HRDATA (PRTDSW, prt_dsw, 16) }, /* device status word */
{ DRDATA (STIME, prt_swait, 24), PV_LEFT }, /* line skip wait */
{ DRDATA (CTIME, prt_cwait, 24), PV_LEFT }, /* character rotation wait */
{ NULL } };
DEVICE prt_dev = {
"PRT", prt_unit, prt_reg, NULL,
1, 16, 16, 1, 16, 16,
NULL, NULL, &prt_reset,
NULL, prt_attach, prt_detach};
#define PRT_COLUMNS 120
#define PRT_ROWLEN 120
#define MAX_OVPRINT 20
static char prtbuf[PRT_ROWLEN*MAX_OVPRINT];
static int nprint[PRT_COLUMNS], ncol[MAX_OVPRINT], maxnp;
static int prt_nchar, prt_row; /* current printwheel position, current page row */
static int prt_nnl; /* number of queued newlines */
#define CC_CHANNEL_1 0x0080 /* carriage control tape punch values */
#define CC_CHANNEL_2 0x0040
#define CC_CHANNEL_3 0x0020
#define CC_CHANNEL_4 0x0010
#define CC_CHANNEL_5 0x0008
#define CC_CHANNEL_6 0x0004
#define CC_CHANNEL_9 0x0002
#define CC_CHANNEL_12 0x0001
#define PRT_PAGELENGTH 66
// glunk need to fill these two arrays in -- cctape and codewheel1132
static int cctape[PRT_PAGELENGTH]; /* standard carriage control tape */
static struct tag_ccpunches { /* list of rows and punches on tape */
int row, channels;
} ccpunches[] = {
7, CC_CHANNEL_12, /* these came from the tape in our printer */
13, CC_CHANNEL_1 /* modulo 66 */
};
#include "ibm1130_prtwheel.h"
// reset_prt_line - clear the print line following paper advancement
static void reset_prt_line (void)
{
memset(nprint, 0, sizeof(nprint));
memset(ncol, 0, sizeof(ncol));
maxnp = 0;
}
// save_prt_line - fire hammers for character 'ch'
static t_bool save_prt_line (int ch)
{
int i, r, addr = 32;
int32 mask = 0, wd = 0;
for (i = 0; i < PRT_COLUMNS; i++) {
if (mask == 0) { // fetch next word from memory
mask = 0x8000;
wd = M[addr++];
}
if (wd & mask) { // hammer is to fire in this column
if ((r = nprint[i]) < MAX_OVPRINT) {
if (ncol[r] <= i) { // we haven't moved this far yet
if (ncol[r] == 0) // first char in this row?
memset(prtbuf+r*PRT_ROWLEN, ' ', PRT_COLUMNS); // blank out the new row
ncol[r] = i+1; // remember new row length
}
prtbuf[r*PRT_ROWLEN + i] = (char) ch; // save the character
nprint[i]++; // remember max overprintings for this column
maxnp = MAX(maxnp, nprint[i]);
}
}
mask >>= 1; // prepare to examine next bit
}
return wd & 1; // return TRUE if the last word has lsb set, which means all bits had been set
}
// write_line - write collected line to output file. No need to trim spaces as the hammers
// are never fired for them, so ncol[r] is the last printed position on each line.
static void flush_prt_line (FILE *fd, t_bool space)
{
int r;
if (! (space || maxnp)) // nothing to do
return;
prt_row = (prt_row+1) % PRT_PAGELENGTH; // NEXT line
if (space && ! maxnp) { // spacing only
if (prt_row == 0 && prt_nnl) {
putc('\f', fd);
prt_nnl = 0;
}
else
prt_nnl++;
return;
}
if (prt_nnl) { // there are queued newlines
if (prt_row == 0 && prt_nnl) { // we spaced to top of form: use formfeed
putc('\f', fd);
prt_nnl = 0;
}
else {
while (prt_nnl > 0) { // spit out queued newlines
#ifdef WIN32
putc('\r', fd); // DOS/Windows: end with cr/lf
#endif
putc('\n', fd); // otherwise end with lf
prt_nnl--;
}
}
}
for (r = 0; r < maxnp; r++) {
if (r > 0)
putc('\r', fd); // carriage return between overprinted lines
fwrite(&prtbuf[r*PRT_ROWLEN], 1, ncol[r], fd);
}
reset_prt_line();
prt_nnl++; // queue a newline
}
#define PRT_CMD_START_PRINTER 0x0080
#define PRT_CMD_STOP_PRINTER 0x0040
#define PRT_CMD_START_CARRIAGE 0x0004
#define PRT_CMD_STOP_CARRIAGE 0x0002
#define PRT_CMD_SPACE 0x0001
#define PRT_CMD_MASK 0x00C7
/* xio_1132_printer - XIO command interpreter for the 1132 printer */
void xio_1132_printer (int32 iocc_addr, int32 func, int32 modify)
{
char msg[80];
UNIT *uptr = &prt_unit[0];
switch (func) {
case XIO_READ:
M[iocc_addr & mem_mask] = codewheel1132[prt_nchar].ebcdic << 8;
if ((uptr->flags & UNIT_PRINTING) == 0) /* if we're not printing, advance this after every test */
prt_nchar = (prt_nchar + 1) % WHEELCHARS;
break;
case XIO_SENSE_DEV:
ACC = prt_dsw;
if (modify & 0x01) { /* reset interrupts */
CLRBIT(prt_dsw, PRT_DSW_READ_EMITTER_RESPONSE | PRT_DSW_SKIP_RESPONSE | PRT_DSW_SPACE_RESPONSE);
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
}
break;
case XIO_CONTROL:
if (modify & PRT_CMD_START_PRINTER)
SETBIT(uptr->flags, UNIT_PRINTING);
if (modify & PRT_CMD_STOP_PRINTER)
CLRBIT(uptr->flags, UNIT_PRINTING);
if (modify & PRT_CMD_START_CARRIAGE)
SETBIT(uptr->flags, UNIT_SKIPPING);
if (modify & PRT_CMD_STOP_CARRIAGE)
CLRBIT(uptr->flags, UNIT_SKIPPING);
if (modify & PRT_CMD_SPACE)
SETBIT(uptr->flags, UNIT_SPACING);
sim_cancel(uptr);
if (uptr->flags & PRT_CMD_MASK) { // busy bit = doing something
SETBIT(prt_dsw, PRT_DSW_PRINTER_BUSY);
sim_activate(uptr, prt_cwait);
}
else
CLRBIT(prt_dsw, PRT_DSW_PRINTER_BUSY);
if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING))
SETBIT(prt_dsw, PRT_DSW_CARRIAGE_BUSY);
else
CLRBIT(prt_dsw, PRT_DSW_CARRIAGE_BUSY);
if ((uptr->flags & (UNIT_SKIPPING|UNIT_SPACING)) == (UNIT_SKIPPING|UNIT_SPACING)) {
sprintf(msg, "1132 printer skip and space at same time?");
xio_error(msg);
}
break;
default:
sprintf(msg, "Invalid 1132 printer XIO function %x", func);
xio_error(msg);
}
}
#define SET_ACTION(u,a) {(u)->flags &= ~(UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING); (u)->flags |= a;}
static t_stat prt_svc (UNIT *uptr)
{
if (prt_dsw & PRT_DSW_NOT_READY) { // cancel operation if printer went offline
SETBIT(uptr->flags, UNIT_FORMCHECK);
SET_ACTION(uptr, 0);
forms_check(TRUE); // and turn on forms check lamp
return SCPE_OK;
}
if (uptr->flags & UNIT_SPACING) {
flush_prt_line(uptr->fileref, TRUE);
prt_dsw = prt_dsw & ~PRT_DSW_CHANNEL_MASK;
prt_dsw |= cctape[prt_row];
SETBIT(prt_dsw, PRT_DSW_SPACE_RESPONSE);
SETBIT(ILSW[1], ILSW_1_1132_PRINTER);
calc_ints();
CLRBIT(uptr->flags, UNIT_SPACING); // done with this
CLRBIT(prt_dsw, PRT_DSW_PRINTER_BUSY|PRT_DSW_CARRIAGE_BUSY);
}
if (uptr->flags & UNIT_SKIPPING) {
do {
flush_prt_line(uptr->fileref, TRUE);
prt_dsw = (prt_dsw & ~PRT_DSW_CHANNEL_MASK) | cctape[prt_row];
} while (cctape[prt_row] == 0); // slew directly to a cc tape punch
SETBIT(prt_dsw, PRT_DSW_SKIP_RESPONSE);
SETBIT(ILSW[1], ILSW_1_1132_PRINTER);
calc_ints();
}
if (uptr->flags & UNIT_PRINTING) {
if (! save_prt_line(codewheel1132[prt_nchar].ascii)) { // save previous printed line
SETBIT(uptr->flags, UNIT_DATACHECK); // buffer wasn't set in time
SET_ACTION(uptr, 0);
print_check(TRUE); // and turn on forms check lamp
return SCPE_OK;
}
prt_nchar = (prt_nchar + 1) % WHEELCHARS; // advance print drum
SETBIT(prt_dsw, PRT_DSW_READ_EMITTER_RESPONSE); // issue interrupt to tell printer to set buffer
SETBIT(ILSW[1], ILSW_1_1132_PRINTER); // we'll save the printed stuff just before next emitter response (later than on real 1130)
calc_ints();
}
if (uptr->flags & (UNIT_SPACING|UNIT_SKIPPING|UNIT_PRINTING)) { // still doing something
SETBIT(prt_dsw, PRT_DSW_PRINTER_BUSY);
sim_activate(uptr, prt_cwait);
}
else
CLRBIT(prt_dsw, PRT_DSW_PRINTER_BUSY);
return SCPE_OK;
}
static t_stat prt_reset (DEVICE *dptr)
{
UNIT *uptr = &prt_unit[0];
int i;
sim_cancel(uptr);
memset(cctape, 0, sizeof(cctape)); // copy punch list into carriage control tape image
for (i = 0; i < (sizeof(ccpunches)/sizeof(ccpunches[0])); i++)
cctape[ccpunches[i].row-1] |= ccpunches[i].channels;
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK);
SET_ACTION(uptr, 0);
calc_ints();
prt_nchar = 0;
prt_row = 0;
prt_nnl = 0;
prt_dsw = cctape[prt_row];
reset_prt_line();
if (! IS_ONLINE(uptr))
SETBIT(prt_dsw, PRT_DSW_NOT_READY);
forms_check(FALSE);
return SCPE_OK;
}
static t_stat prt_attach (UNIT *uptr, char *cptr)
{
t_stat rval;
if (uptr->flags & UNIT_ATT) {
if ((rval = prt_detach(uptr)) != SCPE_OK) {
prt_dsw |= PRT_DSW_NOT_READY;
return rval;
}
}
sim_cancel(uptr);
if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) {
prt_dsw |= PRT_DSW_NOT_READY;
return rval;
}
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK);
SET_ACTION(uptr, 0);
calc_ints();
prt_nchar = 0;
prt_nnl = 0;
prt_row = 0;
prt_dsw = (prt_dsw & ~PRT_DSW_CHANNEL_MASK) | cctape[prt_row];
if (IS_ONLINE(uptr))
CLRBIT(prt_dsw, PRT_DSW_NOT_READY);
else
SETBIT(prt_dsw, PRT_DSW_NOT_READY);
reset_prt_line();
forms_check(FALSE);
return SCPE_OK;
}
static t_stat prt_detach (UNIT *uptr)
{
t_stat rval;
flush_prt_line(uptr->fileref, FALSE);
if ((rval = detach_unit(uptr)) != SCPE_OK)
return rval;
sim_cancel(uptr);
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK);
SET_ACTION(uptr, 0);
calc_ints();
SETBIT(prt_dsw, PRT_DSW_NOT_READY);
forms_check(FALSE);
return SCPE_OK;
}

416
Ibm1130/ibm1130_sys.c Normal file
View File

@@ -0,0 +1,416 @@
/* ibm1130_sys.c: IBM 1130 simulator interface
Copyright (c) 2002, Brian Knittel
Based on PDP-11 simulator written by Robert M Supnik
Revision History
0.24 2002Mar27 - Fixed BOSC bug; BOSC works in short instructions too
0.23 2002Feb26 - Added @decklist feature for ATTACH CR.
0.22 2002Feb26 - Replaced "strupr" with "upcase" for compatibility.
0.21 2002Feb25 - Some compiler compatibiity changes, couple of compiler-detected
bugs
0.01 2001Jul31 - Derived from pdp11_sys.c, which carries this disclaimer:
Copyright (c) 1993-2001, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
*/
#include "ibm1130_defs.h"
#include <ctype.h>
extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev;
extern DEVICE tti_dev, tto_dev, prt_dev, log_dev;
extern UNIT cpu_unit;
extern REG cpu_reg[];
extern int32 saved_PC;
/* 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
*/
char sim_name[] = "IBM 1130";
char sim_version[] = "V0.24";
REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 4;
DEVICE *sim_devices[] = {
&cpu_dev, /* the cpu */
&log_dev, /* cpu logging virtual device */
#ifdef GUI_SUPPORT
&console_dev, /* console display (windows GUI) */
#endif
&dsk_dev, /* disk drive(s) */
&cr_dev, /* card reader/punch */
&cp_dev,
&tti_dev, /* console keyboard, selectric printer */
&tto_dev,
&prt_dev, /* 1132 printer */
NULL
};
const char *sim_stop_messages[] = {
"Unknown error",
"Wait",
"Invalid command",
"Simulator breakpoint",
"Use of incomplete simulator function",
};
/* Loader. IPL is normally performed by card reader (boot command). This function
* loads hex data from a file for testing purposes. The format is:
*
* blank lines or lines starting with ; / or # are ignored as comments
*
* @XXXX set load addresss to hex value XXXX
* XXXX store hex word value XXXX at current load address and increment address
* ...
* =XXXX set IAR to hex value XXXX
* ZXXXX zero XXXX words and increment load address
* SXXXX set console entry switches to XXXX. This lets a program specify the
* default value for the toggle switches.
*
* Multiple @ and data sections may be entered. If more than one = or S value is specified
* the last one wins.
*
* Note: the load address @XXXX and data values XXXX can be followed by the letter
* R to indicate that the values are relocatable addresses. This is ignored in this loader,
* but the asm1130 cross assembler may put them there.
*/
t_stat my_load (FILE *fileref, char *cptr, char *fnam)
{
char line[150], *c;
int iaddr = -1, runaddr = -1, val, nwords;
while (fgets(line, sizeof(line), fileref) != NULL) {
for (c = line; *c && *c <= ' '; c++) // find first nonblank
;
if (*c == '\0' || *c == '#' || *c == '/' || *c == ';')
continue; // empty line or comment
if (*c == '@') { // set load address
if (sscanf(c+1, "%x", &iaddr) != 1)
return SCPE_FMT;
}
else if (*c == '=') {
if (sscanf(c+1, "%x", &runaddr) != 1)
return SCPE_FMT;
}
else if (*c == 's' || *c == 'S') {
if (sscanf(c+1, "%x", &val) != 1)
return SCPE_FMT;
CES = val & 0xFFFF; // preload console entry switches
}
else if (*c == 'z' || *c == 'Z') {
if (sscanf(c+1, "%x", &nwords) != 1)
return SCPE_FMT;
if (iaddr == -1)
return SCPE_FMT;
while (--nwords >= 0) {
WriteW(iaddr, 0);
iaddr++;
}
}
else if (strchr("0123456789abcdefABCDEF", *c) != NULL) {
if (sscanf(c, "%x", &val) != 1)
return SCPE_FMT;
if (iaddr == -1)
return SCPE_FMT;
WriteW(iaddr, val); // store data
iaddr++;
}
else
return SCPE_FMT; // unexpected data
}
if (runaddr != -1)
IAR = runaddr;
return SCPE_OK;
}
t_stat my_save (FILE *fileref, char *cptr, char *fnam)
{
int iaddr, nzeroes = 0, nwords = (int) (MEMSIZE/2), val;
fprintf(fileref, "=%04x\r\n", IAR);
fprintf(fileref, "@0000\r\n");
for (iaddr = 0; iaddr < nwords; iaddr++) {
val = ReadW(iaddr);
if (val == 0) // queue up zeroes
nzeroes++;
else {
if (nzeroes >= 4) { // spit out a Z directive
fprintf(fileref, "Z%04x\r\n", nzeroes);
nzeroes = 0;
}
else { // write queued zeroes literally
while (nzeroes > 0) {
fprintf(fileref, " 0000\r\n");
nzeroes--;
}
}
fprintf(fileref, " %04x\r\n", val);
}
}
if (nzeroes >= 4) { // emit any queued zeroes
fprintf(fileref, "Z%04x\r\n", nzeroes);
nzeroes = 0;
}
else {
while (nzeroes > 0) {
fprintf(fileref, " 0000\r\n");
nzeroes--;
}
}
return SCPE_OK;
}
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
{
if (flag)
return my_save(fileref, cptr, fnam);
else
return my_load(fileref, cptr, fnam);
}
/* Specifier decode
Inputs:
*of = output stream
addr = current PC
spec = specifier
nval = next word
flag = TRUE if decoding for CPU
iflag = TRUE if decoding integer instruction
Outputs:
count = -number of extra words retired
*/
/* Symbolic decode
Inputs:
*of = output stream
addr = current PC
*val = values to decode
*uptr = pointer to unit
sw = switches
Outputs:
return = if >= 0, error code
if < 0, number of extra words retired
*/
static char *opcode[] = {
"?00 ", "XIO ", "SLA ", "SRA ",
"LDS ", "STS ", "WAIT", "?07 ",
"BSI ", "BSC ", "?0A ", "?0B ",
"LDX ", "STD ", "MDX ", "?0F ",
"A ", "AD ", "S ", "SD ",
"M ", "D ", "?16 ", "?17 ",
"LD ", "LDD ", "STO ", "STD ",
"AND ", "OR ", "EOR ", "?1F ",
};
static char relative[] = { // true if short mode displacements are IAR relative
FALSE, TRUE, FALSE, FALSE,
FALSE, TRUE, FALSE, FALSE,
TRUE, FALSE, FALSE, FALSE,
TRUE, TRUE, TRUE, FALSE,
TRUE, TRUE, TRUE, TRUE,
TRUE, TRUE, FALSE, FALSE,
TRUE, TRUE, TRUE, TRUE,
TRUE, TRUE, TRUE, FALSE
};
static char *lsopcode[] = {"SLA ", "SLCA ", "SLT ", "SLC "};
static char *rsopcode[] = {"SRA ", "?188 ", "SRT ", "RTE "};
static char tagc[] = " 123";
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
{
int32 cflag, c1, c2, OP, F, TAG, INDIR, DSPLC, IR, eaddr;
char *mnem, tst[12];
cflag = (uptr == NULL) || (uptr == &cpu_unit);
c1 = val[0] & 0177;
c2 = (val[0] >> 8) & 0177;
if (sw & SWMASK ('A')) { /* ASCII? */
fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
return SCPE_OK;
}
if (sw & SWMASK ('C')) { /* character? */
fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
return SCPE_OK;
}
if (! (sw & SWMASK ('M')))
return SCPE_ARG;
IR = val[0];
OP = (IR >> 11) & 0x1F; /* opcode */
F = IR & 0x0400; /* format bit: 1 = long instr */
TAG = IR & 0x0300; /* tag bits: index reg select */
if (TAG)
TAG >>= 8;
if (F) { /* long instruction, ASSUME it's valid (have to decrement IAR if not) */
INDIR = IR & 0x0080; /* indirect bit */
DSPLC = IR & 0x007F; /* displacement or modifier */
if (DSPLC & 0x0040)
DSPLC |= ~ 0x7F; /* sign extend */
eaddr = val[1]; /* get reference address */
}
else { /* short instruction, use displacement */
INDIR = 0; /* never indirect */
DSPLC = IR & 0x00FF; /* get displacement */
if (DSPLC & 0x0080)
DSPLC |= ~ 0xFF;
eaddr = DSPLC;
if (relative[OP] && ! TAG)
eaddr += addr+1; /* turn displacement into address */
}
mnem = opcode[OP]; /* get mnemonic */
if (OP == 0x02) { /* left shifts are special */
mnem = lsopcode[(DSPLC >> 6) & 0x0003];
DSPLC &= 0x003F;
eaddr = DSPLC;
}
else if (OP == 0x03) { /* right shifts too */
mnem = rsopcode[(DSPLC >> 6) & 0x0003];
DSPLC &= 0x003F;
eaddr = DSPLC;
}
else if (OP == 0x09) {
if (IR & 0x40)
mnem = "BOSC";
tst[0] = '\0';
if (DSPLC & 0x20) strcat(tst, "Z");
if (DSPLC & 0x10) strcat(tst, "-");
if (DSPLC & 0x08) strcat(tst, "+");
if (DSPLC & 0x04) strcat(tst, "E");
if (DSPLC & 0x02) strcat(tst, "C");
if (DSPLC & 0x01) strcat(tst, "O");
if (F) {
fprintf(of, "%04x %s %c%c %s,%04x ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst, eaddr & 0xFFFF);
return -1;
}
fprintf(of, "%04x %s %c%c %s ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst);
return SCPE_OK;
}
else if (OP == 0x0e && TAG == 0) { // MDX with no tag => MDM or jump
if (F) {
fprintf(of, "%04x %s %c%c %04x,%x (%d) ", IR & 0xFFFF, "MDM ", (INDIR ? 'I' : 'L'), tagc[TAG], eaddr & 0xFFFF, DSPLC & 0xFFFF, DSPLC);
return -1;
}
mnem = "JMP ";
}
fprintf(of, "%04x %s %c%c %04x ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], eaddr & 0xFFFF);
return F ? -1 : SCPE_OK; /* inform how many words we read */
}
int32 get_reg (char *cptr, const char *strings[], char mchar)
{
return -1;
}
/* Number or memory address
Inputs:
*cptr = pointer to input string
*dptr = pointer to output displacement
*pflag = pointer to accumulating flags
Outputs:
cptr = pointer to next character in input string
NULL if parsing error
Flags: 0 (no result), A_NUM (number), A_REL (relative)
*/
char *get_addr (char *cptr, int32 *dptr, int32 *pflag)
{
return 0;
}
/* Specifier decode
Inputs:
*cptr = pointer to input string
addr = current PC
n1 = 0 if no extra word used
-1 if extra word used in prior decode
*sptr = pointer to output specifier
*dptr = pointer to output displacement
cflag = true if parsing for the CPU
iflag = true if integer specifier
Outputs:
status = = -1 extra word decoded
= 0 ok
= +1 error
*/
t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr,
int32 cflag, int32 iflag)
{
return -1;
}
/* Symbolic input
Inputs:
*cptr = pointer to input string
addr = current PC
*uptr = pointer to unit
*val = pointer to output values
sw = switches
Outputs:
status = > 0 error code
<= 0 -number of extra words
*/
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
{
return SCPE_ARG;
}

18
Ibm1130/ibm1130res.h Normal file
View File

@@ -0,0 +1,18 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by ibm1130.rc
//
#define IDB_CONSOLE 101
#define IDC_HAND 102
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

209
Ibm1130/readme1130.txt Normal file
View File

@@ -0,0 +1,209 @@
Here's the 1130 simulator as it stands now.
Status: 10 April 2002
* The 1132 printer now works (at least printing numbers)
and there are some corrections to the assembler. The
Disk Cartridge Initialiation Program (DCIP) is now
included and works. See notes below.
* For updated information about the 1130 and for
future simulator, 1130 OS and application software
developments, check www.ibm1130.org periodically.
Sign up for the mailing list to get updates as they occur!
* I still haven't written any documentation.
* Thanks to Oscar E Wyss (www.cosecans.ch) for
the DMS V12 source code listings and one card
programs, to Douglas W. Jones for the DMS V10, 11 and
12 microfiche (which will end up scanned on IBM1130.org).
* Thanks to Robert Alan Byer for adding the 1130
to the simh makefiles & testing the builds on several
platforms.
* I now have the source code for the 1130 Disk
Monitor System and compilers in the software package.
The asm1130 assembler is not quite up to the task of
compiling it yet. We have located a copy of the binary
disk load deck that will let us build a working disk
image. I hope to have these available online and as part
of this distribution, respectively, by Summer, 2002.
At that point the source code will be included too.
* Assembler has been updated to handle card image input
correctly. The DMS sources seems to mix up @ and '
as a leading symbol in labels, I have to find out why
this is.
* see bug list below
Brian Knittel
brian@ibm1130.org
--------------------------------------------------------------------------
Contents:
There are two programs:
ibm1130 the simulator
asm1130 cross assembler
actual 1130 software:
zdcip.asm "disk cartridge initialization program"
dmsboot.asm the DMS cold start loader
zcrdumpc.asm a cold-start-mode one card memory dump program
And several files in the software (sw) directory:
test.dsk disk image, a formatted but empty 1130 disk
onecard/* one-card programs from Oscar Wyss
boot2 script to boot the 1130
boot2.ldr an older DMS cold start loader
boot1.ldr APL cold start loader
type.asm program to type on console printer
prtcr.asm program to copy card deck to console printer
--------------------------------------------------------------------------
Status of the simulator:
* bugs:
(1) Deck files may not work correctly; have to check. When second deck file
is loaded it appears that the second file is not read correctly?
* the card punch is untested
* the card reader emulator now supports deck files: a list of multiple files from
which to read; this makes it possible to assemble complex decks of mixed
text and binary cards without having to actually combine the components
into one file.
* the card reader, punch and disk don't compute their device status word
until an XIO requests it; this is probably bad as the examine command
will show the wrong value.
* there is a reasonably fun GUI available for Windows builds; this requires
the use of modified scp.c and scp_tty.c. These are enclosed. You should
merge the noted modifications into the current versions of scp and scp_tty.
You will also need to define symbol GUI_SUPPORT during the builds; the Visual
C makefile has this set.
--------------------------------------------------------------------------
Some sample things to run:
* Disk Cartridge Initialization:
asm1130 zdcip.asm
ibm1130
then: attach dsk0 test.dsk
attach prt 1132.lst
load zdcip.out
go
then: on GUI: on console:
---------------- -----------------
raise switch 6 dep ces 0200
program start go
lower 6 dep ces 0
program start go
raise 3, 6, 10, 11, 13 dep ces 1234
program start go
program start go
(this formats the disk)
program start go
lower all switches
raise switch 2 dep ces 2000
program start go
lower all switches dep ces 0
program start go
raise switch 14 dep ces 2
program start go
(this dumps two sectors to printer output file 1132.lst)
(now try to boot the disk)
lower all switches dep ces 0
check reset reset
program load load dmsboot.out
program start go
* echo console keyboard to console printer. This one is really fun
* with the GUI enabled; the lights flash in a pleasing manner.
asm1130 type
ibm1130
load type.out
go
* copy card deck to console printer
asm1130 prtcr
ibm1130
load prtcr.out
attach cr <filename of your choice>
go
--------------------------------------------------------------------------
sample usage
--------------------------------------------------------------------------
asm1130 -l resmon.asm
compiles source file, creates simulator load
file (resmon.out) and listing file (resmon.lst)
I had to type in the resident monitor, so it's missing
the comments. I'll add them later.
The cross assembler wants files either in strict column
layout matching the IBM spec, or, if tabs are present in the
source file,
label<tab>opcode<tab>flags<tab>operand
The output file is in the format used by the 1130 simulator's
load command.
--------------------------------------------------------------------------
cardscan -x image.bmp
where x = b for binary interpretation
a for ascii interpretation
l for boot loader interpretation
--------------------------------------------------------------------------
ibm1130
starts SIMH-based simulator.
Enhancements:
* Displays a console window (you can hide with DISABLE CONSOLE)
with buttons & lights.
* CPU activity log
the command "attach log file.log" will make the simulator
write a detailed log of CPU and IO activity, good for
debugging. Turn off with "detach log".
* DO command
reads file 'filename' for SIMH commands. Lets you write
simh command files to be run from the prompt rather
than just the command line. Bob Supnik has added this to
the main simh code tree.
--------------------------------------------------------------------------
check www.ibm1130.org for updates...

3116
Ibm1130/scp.c Normal file

File diff suppressed because it is too large Load Diff

373
Ibm1130/sim_defs.h Normal file
View File

@@ -0,0 +1,373 @@
/* sim_defs.h: simulator definitions
Copyright (c) 1993-2002, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
30-Dec-01 RMS Generalized timer package, added circular arrays
07-Dec-01 RMS Added breakpoint package
01-Dec-01 RMS Added read-only unit support, extended SET/SHOW features,
improved error messages
24-Nov-01 RMS Added unit-based registers
27-Sep-01 RMS Added queue count prototype
17-Sep-01 RMS Removed multiple console support
07-Sep-01 RMS Removed conditional externs on function prototypes
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
17-Jul-01 RMS Added additional function prototypes
27-May-01 RMS Added multiple console support
15-May-01 RMS Increased string buffer size
25-Feb-01 RMS Revisions for V2.6
15-Oct-00 RMS Editorial revisions for V2.5
11-Jul-99 RMS Added unsigned int data types
14-Apr-99 RMS Converted t_addr to unsigned
04-Oct-98 RMS Additional definitions for V2.4
The interface between the simulator control package (SCP) and the
simulator consists of the following routines and data structures
sim_name simulator name string
sim_devices[] array of pointers to simulated devices
sim_PC pointer to saved PC register descriptor
sim_interval simulator interval to next event
sim_stop_messages[] array of pointers to stop messages
sim_instr() instruction execution routine
sim_load() binary loader routine
sim_emax maximum number of words in an instruction
In addition, the simulator must supply routines to print and parse
architecture specific formats
print_sym print symbolic output
parse_sym parse symbolic input
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
/* Length specific integer declarations */
#define int8 char
#define int16 short
#define int32 int
typedef int t_stat; /* status */
typedef int t_bool; /* boolean */
typedef unsigned int8 uint8;
typedef unsigned int16 uint16;
typedef unsigned int32 uint32, t_addr; /* address */
#if defined (USE_INT64) && defined (_WIN32)
#define t_int64 __int64 /* for Windows */
#elif defined (USE_INT64) && defined (VMS) && defined (__ALPHA)
#define t_int64 __int64 /* for AVMS */
#elif defined (USE_INT64) && defined (__ALPHA) && defined (__unix__)
#define t_int64 long /* for DUNIX */
#elif defined (USE_INT64)
#define t_int64 long long /* for GCC */
#endif
#if defined (t_int64)
typedef unsigned t_int64 t_uint64, t_value; /* value */
typedef t_int64 t_svalue; /* signed value */
#else
typedef unsigned int32 t_value;
typedef int32 t_svalue;
#endif
/* System independent definitions */
typedef int32 t_mtrlnt; /* magtape rec lnt */
#define MTRF(x) ((x) & (1u << 31)) /* record error flg */
#define MTRL(x) ((x) & ((1u << 31) - 1)) /* record length */
#define FLIP_SIZE (1 << 16) /* flip buf size */
#if !defined (PATH_MAX) /* usually in limits */
#define PATH_MAX 512
#endif
#define CBUFSIZE (128 + PATH_MAX) /* string buf size */
#define CONS_SIZE 4096 /* console buffer */
/* Simulator status codes
0 ok
1 - (SCPE_BASE - 1) simulator specific
SCPE_BASE - n general
*/
#define SCPE_OK 0 /* normal return */
#define SCPE_BASE 32 /* base for messages */
#define SCPE_NXM (SCPE_BASE + 0) /* nxm */
#define SCPE_UNATT (SCPE_BASE + 1) /* no file */
#define SCPE_IOERR (SCPE_BASE + 2) /* I/O error */
#define SCPE_CSUM (SCPE_BASE + 3) /* loader cksum */
#define SCPE_FMT (SCPE_BASE + 4) /* loader format */
#define SCPE_NOATT (SCPE_BASE + 5) /* not attachable */
#define SCPE_OPENERR (SCPE_BASE + 6) /* open error */
#define SCPE_MEM (SCPE_BASE + 7) /* alloc error */
#define SCPE_ARG (SCPE_BASE + 8) /* argument error */
#define SCPE_STEP (SCPE_BASE + 9) /* step expired */
#define SCPE_UNK (SCPE_BASE + 10) /* unknown command */
#define SCPE_RO (SCPE_BASE + 11) /* read only */
#define SCPE_INCOMP (SCPE_BASE + 12) /* incomplete */
#define SCPE_STOP (SCPE_BASE + 13) /* sim stopped */
#define SCPE_EXIT (SCPE_BASE + 14) /* sim exit */
#define SCPE_TTIERR (SCPE_BASE + 15) /* console tti err */
#define SCPE_TTOERR (SCPE_BASE + 16) /* console tto err */
#define SCPE_EOF (SCPE_BASE + 17) /* end of file */
#define SCPE_REL (SCPE_BASE + 18) /* relocation error */
#define SCPE_NOPARAM (SCPE_BASE + 19) /* no parameters */
#define SCPE_ALATT (SCPE_BASE + 20) /* already attached */
#define SCPE_TIMER (SCPE_BASE + 21) /* hwre timer err */
#define SCPE_SIGERR (SCPE_BASE + 22) /* signal err */
#define SCPE_TTYERR (SCPE_BASE + 23) /* tty setup err */
#define SCPE_SUB (SCPE_BASE + 24) /* subscript err */
#define SCPE_NOFNC (SCPE_BASE + 25) /* func not imp */
#define SCPE_UDIS (SCPE_BASE + 26) /* unit disabled */
#define SCPE_LOGON (SCPE_BASE + 27) /* logging enabled */
#define SCPE_LOGOFF (SCPE_BASE + 28) /* logging disabled */
#define SCPE_NORO (SCPE_BASE + 29) /* rd only not ok */
#define SCPE_INVSW (SCPE_BASE + 30) /* invalid switch */
#define SCPE_MISVAL (SCPE_BASE + 31) /* missing value */
#define SCPE_2FARG (SCPE_BASE + 32) /* too few arguments */
#define SCPE_2MARG (SCPE_BASE + 33) /* too many arguments */
#define SCPE_NXDEV (SCPE_BASE + 34) /* nx device */
#define SCPE_NXUN (SCPE_BASE + 35) /* nx unit */
#define SCPE_NXREG (SCPE_BASE + 36) /* nx register */
#define SCPE_NXPAR (SCPE_BASE + 37) /* nx parameter */
#define SCPE_NEST (SCPE_BASE + 38) /* nested DO */
#define SCPE_IERR (SCPE_BASE + 39) /* internal error */
#define SCPE_KFLAG 01000 /* tti data flag */
/* Print value format codes */
#define PV_RZRO 0 /* right, zero fill */
#define PV_RSPC 1 /* right, space fill */
#define PV_LEFT 2 /* left justify */
/* Default timing parameters */
#define KBD_POLL_WAIT 5000 /* keyboard poll */
#define SERIAL_IN_WAIT 100 /* serial in time */
#define SERIAL_OUT_WAIT 10 /* serial output */
#define NOQUEUE_WAIT 10000 /* min check time */
/* Convert switch letter to bit mask */
#define SWMASK(x) (1u << (((int) (x)) - ((int) 'A')))
/* String match */
#define MATCH_CMD(ptr,cmd) strncmp ((ptr), (cmd), strlen (ptr))
/* Device data structure */
struct device {
char *name; /* name */
struct unit *units; /* units */
struct reg *registers; /* registers */
struct mtab *modifiers; /* modifiers */
int32 numunits; /* #units */
int32 aradix; /* address radix */
int32 awidth; /* address width */
int32 aincr; /* addr increment */
int32 dradix; /* data radix */
int32 dwidth; /* data width */
t_stat (*examine)(); /* examine routine */
t_stat (*deposit)(); /* deposit routine */
t_stat (*reset)(); /* reset routine */
t_stat (*boot)(); /* boot routine */
t_stat (*attach)(); /* attach routine */
t_stat (*detach)(); /* detach routine */
};
/* Unit data structure
Parts of the unit structure are device specific, that is, they are
not referenced by the simulator control package and can be freely
used by device simulators. Fields starting with 'buf', and flags
starting with 'UF', are device specific. The definitions given here
are for a typical sequential device.
*/
struct unit {
struct unit *next; /* next active */
t_stat (*action)(); /* action routine */
char *filename; /* open file name */
FILE *fileref; /* file reference */
void *filebuf; /* memory buffer */
t_addr hwmark; /* high water mark */
int32 time; /* time out */
int32 flags; /* flags */
t_addr capac; /* capacity */
t_addr pos; /* file position */
int32 buf; /* buffer */
int32 wait; /* wait */
int32 u3; /* device specific */
int32 u4; /* device specific */
};
/* Unit flags */
#define UNIT_ATTABLE 000001 /* attachable */
#define UNIT_RO 000002 /* read only */
#define UNIT_FIX 000004 /* fixed capacity */
#define UNIT_SEQ 000010 /* sequential */
#define UNIT_ATT 000020 /* attached */
#define UNIT_BINK 000040 /* K = power of 2 */
#define UNIT_BUFABLE 000100 /* bufferable */
#define UNIT_MUSTBUF 000200 /* must buffer */
#define UNIT_BUF 000400 /* buffered */
#define UNIT_ROABLE 001000 /* read only ok */
#define UNIT_DISABLE 002000 /* disable-able */
#define UNIT_DIS 004000 /* disabled */
#define UNIT_V_UF 12 /* device specific */
/* must be DIS+1!! */
#define UNIT_V_RSV 31 /* reserved!! */
/* Register data structure */
struct reg {
char *name; /* name */
void *loc; /* location */
int32 radix; /* radix */
int32 width; /* width */
int32 offset; /* starting bit */
int32 depth; /* save depth */
int32 flags; /* flags */
int32 qptr; /* circ q ptr */
};
#define REG_FMT 0003 /* see PV_x */
#define REG_RO 0004 /* read only */
#define REG_HIDDEN 0010 /* hidden */
#define REG_NZ 0020 /* must be non-zero */
#define REG_UNIT 0040 /* in unit struct */
#define REG_CIRC 0100 /* circular array */
#define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */
/* Command table */
struct ctab {
char *name; /* name */
t_stat (*action)(); /* action routine */
int32 arg; /* argument */
};
/* Modifier table - only extended entries have disp, reg, or flags */
struct mtab {
int32 mask; /* mask or radix */
int32 match; /* match or max */
char *pstring; /* print string */
char *mstring; /* match string */
t_stat (*valid)(); /* validation routine */
t_stat (*disp)(); /* display routine */
void *desc; /* value descriptor */
/* REG * if MTAB_VAL */
/* int * if not */
};
#define MTAB_XTD (1u << UNIT_V_RSV) /* ext entry flag */
#define MTAB_VDV 001 /* valid for dev */
#define MTAB_VUN 002 /* valid for unit */
#define MTAB_VAL 004 /* takes a value */
#define MTAB_NMO 010 /* only if named */
/* Search table */
struct schtab {
int logic; /* logical operator */
int bool; /* boolean operator */
t_value mask; /* mask for logical */
t_value comp; /* comparison for boolean */
};
/* The following macros define structure contents */
#define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),(cap),0,0
#if defined (__STDC__) || defined (_WIN32)
#define ORDATA(nm,loc,wd) #nm, &(loc), 8, (wd), 0, 1
#define DRDATA(nm,loc,wd) #nm, &(loc), 10, (wd), 0, 1
#define HRDATA(nm,loc,wd) #nm, &(loc), 16, (wd), 0, 1
#define FLDATA(nm,loc,pos) #nm, &(loc), 2, 1, (pos), 1
#define GRDATA(nm,loc,rdx,wd,pos) #nm, &(loc), (rdx), (wd), (pos), 1
#define BRDATA(nm,loc,rdx,wd,dep) #nm, (loc), (rdx), (wd), 0, (dep)
#define URDATA(nm,loc,rdx,wd,off,dep,fl) \
#nm, &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT)
#else
#define ORDATA(nm,loc,wd) "nm", &(loc), 8, (wd), 0, 1
#define DRDATA(nm,loc,wd) "nm", &(loc), 10, (wd), 0, 1
#define HRDATA(nm,loc,wd) "nm", &(loc), 16, (wd), 0, 1
#define FLDATA(nm,loc,pos) "nm", &(loc), 2, 1, (pos), 1
#define GRDATA(nm,loc,rdx,wd,pos) "nm", &(loc), (rdx), (wd), (pos), 1
#define BRDATA(nm,loc,rdx,wd,dep) "nm", (loc), (rdx), (wd), 0, (dep)
#define URDATA(nm,loc,rdx,wd,off,dep,fl) \
"nm", &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT)
#endif
/* Typedefs for principal structures */
typedef struct device DEVICE;
typedef struct unit UNIT;
typedef struct reg REG;
typedef struct ctab CTAB;
typedef struct mtab MTAB;
typedef struct schtab SCHTAB;
/* Function prototypes */
t_stat sim_process_event (void);
t_stat sim_activate (UNIT *uptr, int32 interval);
t_stat sim_cancel (UNIT *uptr);
int32 sim_is_active (UNIT *uptr);
double sim_gtime (void);
uint32 sim_grtime (void);
int32 sim_qcount (void);
t_stat attach_unit (UNIT *uptr, char *cptr);
t_stat detach_unit (UNIT *uptr);
t_stat reset_all (int start_device);
size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr);
size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr);
t_stat get_yn (char *ques, t_stat deflt);
char *get_glyph (char *iptr, char *optr, char mchar);
char *get_glyph_nc (char *iptr, char *optr, char mchar);
t_value get_uint (char *cptr, int radix, t_value max, t_stat *status);
t_value strtotv (char *cptr, char **endptr, int radix);
DEVICE *find_dev_from_unit (UNIT *uptr);
REG *find_reg (char *ptr, char **optr, DEVICE *dptr);
int32 sim_rtc_init (int32 time);
int32 sim_rtc_calb (int32 ticksper);
int32 sim_rtcn_init (int32 time, int32 tmr);
int32 sim_rtcn_calb (int32 time, int32 tmr);
t_stat sim_poll_kbd (void);
t_stat sim_putchar (int32 out);
t_bool sim_brk_test (t_addr bloc, int32 btyp);
#ifdef GUI_SUPPORT
void update_gui (t_bool force);
#endif