Notes For V3.7-0
1. New Features 1.1 3.7-0 1.1.1 SCP - Added SET THROTTLE and SET NOTHROTTLE commands to regulate simulator execution rate and host resource utilization. - Added idle support (based on work by Mark Pizzolato). - Added -e to control error processing in nested DO commands (from Dave Bryan). 1.1.2 HP2100 - Added Double Integer instructions, 1000-F CPU, and Floating Point Processor (from Dave Bryan). - Added 2114 and 2115 CPUs, 12607B and 12578A DMA controllers, and 21xx binary loader protection (from Dave Bryan). 1.1.3 Interdata - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state. 1.1.4 PDP-11 - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state (WAIT instruction executed). - Added TA11/TU60 cassette support. 1.1.5 PDP-8 - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state (keyboard poll loop or jump-to-self). - Added TA8E/TU60 cassette support. 1.1.6 PDP-1 - Added support for 16-channel sequence break system. - Added support for PDP-1D extended features and timesharing clock. - Added support for Type 630 data communications subsystem. 1.1.6 PDP-4/7/9/15 - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state (keyboard poll loop or jump-to-self). 1.1.7 VAX, VAX780 - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state (more than 200 cycles at IPL's 0, 1, or 3 in kernel mode). 1.1.8 PDP-10 - Added SET IDLE and SET NOIDLE commands to idle the simulator in wait state (operating system dependent). - Added CD20 (CD11) support. 2. Bugs Fixed Please see the revision history on http://simh.trailing-edge.com or in the source module sim_rev.h.
This commit is contained in:
parent
15919a2dd7
commit
53d02f7fa7
161 changed files with 18604 additions and 6903 deletions
|
@ -1,51 +0,0 @@
|
|||
Notes For V3.6-0
|
||||
|
||||
The save/restore format has been updated to improve its reliability.
|
||||
As a result, save files prior to release 3.0 are no longer supported.
|
||||
|
||||
The text documentation files are obsolete and are no longer included
|
||||
with the distribution. Up-to-date PDF documentation files are
|
||||
available on the SimH web site.
|
||||
|
||||
|
||||
1. New Features
|
||||
|
||||
1.1 3.6-0
|
||||
|
||||
1.1.1 Most magnetic tapes
|
||||
|
||||
- Added support for limiting tape capacity to a particular size in MB
|
||||
|
||||
1.1.2 IBM 7090/7094
|
||||
|
||||
- First release
|
||||
|
||||
1.1.3 VAX-11/780
|
||||
|
||||
- Added FLOAD command, loads system file from console floppy disk
|
||||
|
||||
1.1.4 VAX, VAX-11/780, and PDP-11
|
||||
|
||||
- Added card reader support (from John Dundas)
|
||||
|
||||
1.1.5 PDP-11
|
||||
|
||||
- Added instruction history
|
||||
|
||||
1.2 3.6-1
|
||||
|
||||
1.2.1 PDP-11
|
||||
|
||||
- Added RF11 support
|
||||
- Added multiple KL11/DL11 support
|
||||
- Added upper-case only mode to TTI, TTO
|
||||
|
||||
1.2.2
|
||||
|
||||
- Added binary loader (courtesy of Dave Pitt)
|
||||
|
||||
|
||||
2. Bugs Fixed
|
||||
|
||||
Please see the revision history on http://simh.trailing-edge.com or
|
||||
in the source module sim_rev.h.
|
66
0readme_37.txt
Normal file
66
0readme_37.txt
Normal file
|
@ -0,0 +1,66 @@
|
|||
Notes For V3.7-0
|
||||
|
||||
|
||||
1. New Features
|
||||
|
||||
1.1 3.7-0
|
||||
|
||||
1.1.1 SCP
|
||||
|
||||
- Added SET THROTTLE and SET NOTHROTTLE commands to regulate simulator
|
||||
execution rate and host resource utilization.
|
||||
- Added idle support (based on work by Mark Pizzolato).
|
||||
- Added -e to control error processing in nested DO commands (from
|
||||
Dave Bryan).
|
||||
|
||||
1.1.2 HP2100
|
||||
|
||||
- Added Double Integer instructions, 1000-F CPU, and Floating Point
|
||||
Processor (from Dave Bryan).
|
||||
- Added 2114 and 2115 CPUs, 12607B and 12578A DMA controllers, and
|
||||
21xx binary loader protection (from Dave Bryan).
|
||||
|
||||
1.1.3 Interdata
|
||||
|
||||
- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
|
||||
state.
|
||||
|
||||
1.1.4 PDP-11
|
||||
|
||||
- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
|
||||
state (WAIT instruction executed).
|
||||
- Added TA11/TU60 cassette support.
|
||||
|
||||
1.1.5 PDP-8
|
||||
|
||||
- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
|
||||
state (keyboard poll loop or jump-to-self).
|
||||
- Added TA8E/TU60 cassette support.
|
||||
|
||||
1.1.6 PDP-1
|
||||
|
||||
- Added support for 16-channel sequence break system.
|
||||
- Added support for PDP-1D extended features and timesharing clock.
|
||||
- Added support for Type 630 data communications subsystem.
|
||||
|
||||
1.1.6 PDP-4/7/9/15
|
||||
|
||||
- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
|
||||
state (keyboard poll loop or jump-to-self).
|
||||
|
||||
1.1.7 VAX, VAX780
|
||||
|
||||
- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
|
||||
state (more than 200 cycles at IPL's 0, 1, or 3 in kernel mode).
|
||||
|
||||
1.1.8 PDP-10
|
||||
|
||||
- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
|
||||
state (operating system dependent).
|
||||
- Added CD20 (CD11) support.
|
||||
|
||||
|
||||
2. Bugs Fixed
|
||||
|
||||
Please see the revision history on http://simh.trailing-edge.com or
|
||||
in the source module sim_rev.h.
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/* altairz80_defs.h: MITS Altair simulator definitions
|
||||
|
||||
Copyright (c) 2002-2006, Peter Schorn
|
||||
Copyright (c) 2002-2007, Peter Schorn
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -30,19 +30,19 @@
|
|||
|
||||
#define MAXMEMSIZE 65536 /* maximum memory size */
|
||||
#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */
|
||||
#define bootrom_size 256 /* size of boot rom */
|
||||
#define BOOTROM_SIZE 256 /* size of boot rom */
|
||||
#define MAXBANKS 8 /* max number of memory banks */
|
||||
#define MAXBANKSLOG2 3 /* log2 of MAXBANKS */
|
||||
#define BANKMASK (MAXBANKS-1) /* bank mask */
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define KB 1024 /* kilo byte */
|
||||
#define defaultROMLow 0xff00 /* default for lowest address of ROM */
|
||||
#define defaultROMHigh 0xffff /* default for highest address of ROM */
|
||||
#define DEFAULT_ROM_LOW 0xff00 /* default for lowest address of ROM */
|
||||
#define DEFAULT_ROM_HIGH 0xffff /* default for highest address of ROM */
|
||||
|
||||
#define NUM_OF_DSK 8 /* NUM_OF_DSK must be power of two */
|
||||
#define LDAInstruction 0x3e /* op-code for LD A,<8-bit value> instruction */
|
||||
#define unitNoOffset1 0x37 /* LD A,<unitno> */
|
||||
#define unitNoOffset2 0xb4 /* LD a,80h | <unitno> */
|
||||
#define LDA_INSTRUCTION 0x3e /* op-code for LD A,<8-bit value> instruction */
|
||||
#define UNIT_NO_OFFSET_1 0x37 /* LD A,<unitno> */
|
||||
#define UNIT_NO_OFFSET_2 0xb4 /* LD a,80h | <unitno> */
|
||||
|
||||
#define UNIT_V_OPSTOP (UNIT_V_UF+0) /* stop on invalid operation */
|
||||
#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP)
|
||||
|
@ -59,17 +59,22 @@
|
|||
#define UNIT_V_WARNROM (UNIT_V_UF+6) /* warn if ROM is written to */
|
||||
#define UNIT_WARNROM (1 << UNIT_V_WARNROM)
|
||||
|
||||
#define AddressFormat "[%04xh]"
|
||||
#define PCformat "\n" AddressFormat " "
|
||||
#define message1(p1) \
|
||||
sprintf(messageBuffer,PCformat p1,PCX); printMessage()
|
||||
#define message2(p1,p2) \
|
||||
sprintf(messageBuffer,PCformat p1,PCX,p2); printMessage()
|
||||
#define message3(p1,p2,p3) \
|
||||
sprintf(messageBuffer,PCformat p1,PCX,p2,p3); printMessage()
|
||||
#define message4(p1,p2,p3,p4) \
|
||||
sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4); printMessage()
|
||||
#define message5(p1,p2,p3,p4,p5) \
|
||||
sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4,p5); printMessage()
|
||||
#define message6(p1,p2,p3,p4,p5,p6) \
|
||||
sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4,p5,p6); printMessage()
|
||||
#define UNIX_PLATFORM (defined (__linux) || defined(__NetBSD__) || defined (__OpenBSD__) || \
|
||||
defined (__FreeBSD__) || defined (__APPLE__))
|
||||
|
||||
#define ADDRESS_FORMAT "[%04xh]"
|
||||
#define PC_FORMAT "\n" ADDRESS_FORMAT " "
|
||||
#define MESSAGE_1(p1) \
|
||||
sprintf(messageBuffer,PC_FORMAT p1,PCX); printMessage()
|
||||
#define MESSAGE_2(p1,p2) \
|
||||
sprintf(messageBuffer,PC_FORMAT p1,PCX,p2); printMessage()
|
||||
#define MESSAGE_3(p1,p2,p3) \
|
||||
sprintf(messageBuffer,PC_FORMAT p1,PCX,p2,p3); printMessage()
|
||||
#define MESSAGE_4(p1,p2,p3,p4) \
|
||||
sprintf(messageBuffer,PC_FORMAT p1,PCX,p2,p3,p4); printMessage()
|
||||
#define MESSAGE_5(p1,p2,p3,p4,p5) \
|
||||
sprintf(messageBuffer,PC_FORMAT p1,PCX,p2,p3,p4,p5); printMessage()
|
||||
#define MESSAGE_6(p1,p2,p3,p4,p5,p6) \
|
||||
sprintf(messageBuffer,PC_FORMAT p1,PCX,p2,p3,p4,p5,p6); printMessage()
|
||||
#define MESSAGE_7(p1,p2,p3,p4,p5,p6,p7) \
|
||||
sprintf(messageBuffer,PC_FORMAT p1,PCX,p2,p3,p4,p5,p6,p7); printMessage()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* altairz80_dsk.c: MITS Altair 88-DISK Simulator
|
||||
|
||||
Copyright (c) 2002-2006, Peter Schorn
|
||||
Copyright (c) 2002-2007, Peter Schorn
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -132,7 +132,6 @@ int32 dsk12(const int32 port, const int32 io, const int32 data);
|
|||
static int32 dskseek(const UNIT *xptr);
|
||||
static t_stat dsk_boot(int32 unitno, DEVICE *dptr);
|
||||
static t_stat dsk_reset(DEVICE *dptr);
|
||||
static t_stat dsk_svc(UNIT *uptr);
|
||||
static void writebuf(void);
|
||||
static t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc);
|
||||
static void resetDSKWarningFlags(void);
|
||||
|
@ -142,11 +141,12 @@ static char* selectInOut(const int32 io);
|
|||
extern int32 PCX;
|
||||
extern int32 saved_PC;
|
||||
extern FILE *sim_log;
|
||||
extern void printMessage(void);
|
||||
extern char messageBuffer[];
|
||||
extern int32 install_bootrom(void);
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
extern void printMessage(void);
|
||||
extern int32 install_bootrom(void);
|
||||
|
||||
/* global data on status */
|
||||
|
||||
static int32 current_disk = NUM_OF_DSK; /* currently selected drive (values are 0 .. NUM_OF_DSK)
|
||||
|
@ -170,7 +170,7 @@ static int32 warnDSK12 = 0;
|
|||
static int8 dskbuf[DSK_SECTSIZE]; /* data Buffer */
|
||||
|
||||
/* Altair MITS modified BOOT EPROM, fits in upper 256 byte of memory */
|
||||
int32 bootrom[bootrom_size] = {
|
||||
int32 bootrom[BOOTROM_SIZE] = {
|
||||
0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* ff00-ff07 */
|
||||
0xc2, 0x05, 0xff, 0x3e, 0x16, 0xd3, 0xfe, 0x3e, /* ff08-ff0f */
|
||||
0x12, 0xd3, 0xfe, 0xdb, 0xfe, 0xb7, 0xca, 0x20, /* ff10-ff17 */
|
||||
|
@ -208,14 +208,14 @@ int32 bootrom[bootrom_size] = {
|
|||
/* 88DSK Standard I/O Data Structures */
|
||||
|
||||
static UNIT dsk_unit[] = {
|
||||
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }
|
||||
};
|
||||
|
||||
static REG dsk_reg[] = {
|
||||
|
@ -290,13 +290,6 @@ static char* selectInOut(const int32 io) {
|
|||
}
|
||||
|
||||
/* service routines to handle simulator functions */
|
||||
|
||||
/* service routine - actually gets char & places in buffer */
|
||||
|
||||
static t_stat dsk_svc(UNIT *uptr) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* reset routine */
|
||||
|
||||
static t_stat dsk_reset(DEVICE *dptr) {
|
||||
|
@ -317,16 +310,16 @@ static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
|
|||
printf("ALTAIR boot ROM installed.\n");
|
||||
}
|
||||
/* check whether we are really modifying an LD A,<> instruction */
|
||||
if ((bootrom[unitNoOffset1 - 1] == LDAInstruction) && (bootrom[unitNoOffset2 - 1] == LDAInstruction)) {
|
||||
bootrom[unitNoOffset1] = unitno & 0xff; /* LD A,<unitno> */
|
||||
bootrom[unitNoOffset2] = 0x80 | (unitno & 0xff); /* LD a,80h | <unitno> */
|
||||
if ((bootrom[UNIT_NO_OFFSET_1 - 1] == LDA_INSTRUCTION) && (bootrom[UNIT_NO_OFFSET_2 - 1] == LDA_INSTRUCTION)) {
|
||||
bootrom[UNIT_NO_OFFSET_1] = unitno & 0xff; /* LD A,<unitno> */
|
||||
bootrom[UNIT_NO_OFFSET_2] = 0x80 | (unitno & 0xff); /* LD a,80h | <unitno> */
|
||||
}
|
||||
else { /* Attempt to modify non LD A,<> instructions is refused. */
|
||||
printf("Incorrect boot ROM offsets detected.\n");
|
||||
return SCPE_IERR;
|
||||
}
|
||||
}
|
||||
saved_PC = defaultROMLow;
|
||||
saved_PC = DEFAULT_ROM_LOW;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -356,7 +349,7 @@ int32 dsk10(const int32 port, const int32 io, const int32 data) {
|
|||
if (current_disk >= NUM_OF_DSK) {
|
||||
if (hasVerbose() && (warnDSK10 < warnLevelDSK)) {
|
||||
warnDSK10++;
|
||||
/*01*/ message1("Attempt of IN 0x08 on unattached disk - ignored.");
|
||||
/*01*/ MESSAGE_1("Attempt of IN 0x08 on unattached disk - ignored.");
|
||||
}
|
||||
return 0xff; /* no drive selected - can do nothing */
|
||||
}
|
||||
|
@ -368,14 +361,14 @@ int32 dsk10(const int32 port, const int32 io, const int32 data) {
|
|||
writebuf();
|
||||
}
|
||||
if (trace_flag & TRACE_IN_OUT) {
|
||||
message2("OUT 0x08: %x", data);
|
||||
MESSAGE_2("OUT 0x08: %x", data);
|
||||
}
|
||||
current_disk = data & NUM_OF_DSK_MASK; /* 0 <= current_disk < NUM_OF_DSK */
|
||||
current_disk_flags = (dsk_dev.units + current_disk) -> flags;
|
||||
if ((current_disk_flags & UNIT_ATT) == 0) { /* nothing attached? */
|
||||
if ( (current_disk_flags & UNIT_DSK_VERBOSE) && (warnAttached[current_disk] < warnLevelDSK) ) {
|
||||
warnAttached[current_disk]++;
|
||||
/*02*/message2("Attempt to select unattached DSK%d - ignored.", current_disk);
|
||||
/*02*/MESSAGE_2("Attempt to select unattached DSK%d - ignored.", current_disk);
|
||||
}
|
||||
current_disk = NUM_OF_DSK;
|
||||
}
|
||||
|
@ -395,7 +388,7 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
|
|||
if (current_disk >= NUM_OF_DSK) {
|
||||
if (hasVerbose() && (warnDSK11 < warnLevelDSK)) {
|
||||
warnDSK11++;
|
||||
/*03*/ message2("Attempt of %s 0x09 on unattached disk - ignored.", selectInOut(io));
|
||||
/*03*/ MESSAGE_2("Attempt of %s 0x09 on unattached disk - ignored.", selectInOut(io));
|
||||
}
|
||||
return 0; /* no drive selected - can do nothing */
|
||||
}
|
||||
|
@ -405,10 +398,10 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
|
|||
in9_count++;
|
||||
if ((trace_flag & TRACE_SECTOR_STUCK) && (in9_count > 2 * DSK_SECT) && (!in9_message)) {
|
||||
in9_message = TRUE;
|
||||
message2("Looping on sector find %d.", current_disk);
|
||||
MESSAGE_2("Looping on sector find %d.", current_disk);
|
||||
}
|
||||
if (trace_flag & TRACE_IN_OUT) {
|
||||
message1("IN 0x09");
|
||||
MESSAGE_1("IN 0x09");
|
||||
}
|
||||
if (dirty) {/* implies that current_disk < NUM_OF_DSK */
|
||||
writebuf();
|
||||
|
@ -430,12 +423,12 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
|
|||
/* drive functions */
|
||||
|
||||
if (trace_flag & TRACE_IN_OUT) {
|
||||
message2("OUT 0x09: %x", data);
|
||||
MESSAGE_2("OUT 0x09: %x", data);
|
||||
}
|
||||
if (data & 0x01) { /* step head in */
|
||||
if (trace_flag & TRACE_TRACK_STUCK) {
|
||||
if (current_track[current_disk] == (tracks[current_disk] - 1)) {
|
||||
message2("Unnecessary step in for disk %d", current_disk);
|
||||
MESSAGE_2("Unnecessary step in for disk %d", current_disk);
|
||||
}
|
||||
}
|
||||
current_track[current_disk]++;
|
||||
|
@ -452,7 +445,7 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
|
|||
if (data & 0x02) { /* step head out */
|
||||
if (trace_flag & TRACE_TRACK_STUCK) {
|
||||
if (current_track[current_disk] == 0) {
|
||||
message2("Unnecessary step out for disk %d", current_disk);
|
||||
MESSAGE_2("Unnecessary step out for disk %d", current_disk);
|
||||
}
|
||||
}
|
||||
current_track[current_disk]--;
|
||||
|
@ -506,7 +499,7 @@ int32 dsk12(const int32 port, const int32 io, const int32 data) {
|
|||
if (current_disk >= NUM_OF_DSK) {
|
||||
if (hasVerbose() && (warnDSK12 < warnLevelDSK)) {
|
||||
warnDSK12++;
|
||||
/*04*/ message2("Attempt of %s 0x0a on unattached disk - ignored.", selectInOut(io));
|
||||
/*04*/ MESSAGE_2("Attempt of %s 0x0a on unattached disk - ignored.", selectInOut(io));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -518,7 +511,7 @@ int32 dsk12(const int32 port, const int32 io, const int32 data) {
|
|||
if (current_byte[current_disk] >= DSK_SECTSIZE) {
|
||||
/* physically read the sector */
|
||||
if (trace_flag & TRACE_READ_WRITE) {
|
||||
message4("IN 0x0a (READ) D%d T%d S%d", current_disk, current_track[current_disk], current_sector[current_disk]);
|
||||
MESSAGE_4("IN 0x0a (READ) D%d T%d S%d", current_disk, current_track[current_disk], current_sector[current_disk]);
|
||||
}
|
||||
for (i = 0; i < DSK_SECTSIZE; i++) {
|
||||
dskbuf[i] = 0;
|
||||
|
@ -552,20 +545,20 @@ static void writebuf(void) {
|
|||
uptr = dsk_dev.units + current_disk;
|
||||
if (((uptr -> flags) & UNIT_DSKWLK) == 0) { /* write enabled */
|
||||
if (trace_flag & TRACE_READ_WRITE) {
|
||||
message4("OUT 0x0a (WRITE) D%d T%d S%d", current_disk, current_track[current_disk], current_sector[current_disk]);
|
||||
MESSAGE_4("OUT 0x0a (WRITE) D%d T%d S%d", current_disk, current_track[current_disk], current_sector[current_disk]);
|
||||
}
|
||||
if (dskseek(uptr)) {
|
||||
message4("fseek failed D%d T%d S%d", current_disk, current_track[current_disk], current_sector[current_disk]);
|
||||
MESSAGE_4("fseek failed D%d T%d S%d", current_disk, current_track[current_disk], current_sector[current_disk]);
|
||||
}
|
||||
rtn = fwrite(dskbuf, DSK_SECTSIZE, 1, uptr -> fileref);
|
||||
if (rtn != 1) {
|
||||
message4("fwrite failed T%d S%d Return=%d", current_track[current_disk], current_sector[current_disk], rtn);
|
||||
MESSAGE_4("fwrite failed T%d S%d Return=%d", current_track[current_disk], current_sector[current_disk], rtn);
|
||||
}
|
||||
}
|
||||
else if ( ((uptr -> flags) & UNIT_DSK_VERBOSE) && (warnLock[current_disk] < warnLevelDSK) ) {
|
||||
/* write locked - print warning message if required */
|
||||
warnLock[current_disk]++;
|
||||
/*05*/ message2("Attempt to write to locked DSK%d - ignored.", current_disk);
|
||||
/*05*/ MESSAGE_2("Attempt to write to locked DSK%d - ignored.", current_disk);
|
||||
}
|
||||
current_flag[current_disk] &= 0xfe; /* ENWD off */
|
||||
current_byte[current_disk] = 0xff;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/* altairz80_sys.c: MITS Altair system interface
|
||||
|
||||
Copyright (c) 2002-2006, Peter Schorn
|
||||
Copyright (c) 2002-2007, Peter Schorn
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -39,6 +39,7 @@ extern DEVICE sio_dev;
|
|||
extern DEVICE simh_device;
|
||||
extern DEVICE ptr_dev;
|
||||
extern DEVICE ptp_dev;
|
||||
extern DEVICE net_dev;
|
||||
extern int32 saved_PC;
|
||||
|
||||
int32 fprint_sym(FILE *of, int32 addr, uint32 *val, UNIT *uptr, int32 sw);
|
||||
|
@ -65,7 +66,7 @@ char sim_name[] = "Altair 8800 (Z80)";
|
|||
REG *sim_PC = &cpu_reg[0];
|
||||
int32 sim_emax = 4;
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev, &sio_dev, &simh_device, &ptr_dev, &ptp_dev, &dsk_dev, &hdsk_dev, NULL
|
||||
&cpu_dev, &sio_dev, &simh_device, &ptr_dev, &ptp_dev, &dsk_dev, &hdsk_dev, &net_dev, NULL
|
||||
};
|
||||
|
||||
char memoryAccessMessage[80];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* altairz80_hdsk.c: simulated hard disk device to increase capacity
|
||||
|
||||
Copyright (c) 2002-2006, Peter Schorn
|
||||
Copyright (c) 2002-2007, Peter Schorn
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -22,28 +22,39 @@
|
|||
Except as contained in this notice, the name of Peter Schorn shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Peter Schorn.
|
||||
|
||||
Contains code from Howard M. Harte for defining and changing disk geometry.
|
||||
*/
|
||||
|
||||
#include "altairz80_defs.h"
|
||||
|
||||
/* the following routines provided courtesy of Howard M. Harte */
|
||||
t_stat set_geom (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat show_geom (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat set_format (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat show_format (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat hdsk_attach (UNIT *uptr, char *cptr);
|
||||
|
||||
#define UNIT_V_HDSKWLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_HDSKWLK (1 << UNIT_V_HDSKWLK)
|
||||
#define UNIT_V_HDSK_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
|
||||
#define UNIT_HDSK_VERBOSE (1 << UNIT_V_HDSK_VERBOSE)
|
||||
#define HDSK_SECTOR_SIZE 128 /* size of sector */
|
||||
#define HDSK_SECTORS_PER_TRACK 32 /* sectors per track */
|
||||
#define HDS_MAX_TRACKS 2048 /* number of tracks */
|
||||
#define HDSK_TRACK_SIZE (HDSK_SECTOR_SIZE * HDSK_SECTORS_PER_TRACK)
|
||||
#define HDSK_CAPACITY (HDSK_TRACK_SIZE * HDS_MAX_TRACKS)
|
||||
#define HDSK_MAX_SECTOR_SIZE 1024 /* size of sector */
|
||||
#define HDSK_SECTOR_SIZE u5 /* size of sector */
|
||||
#define HDSK_SECTORS_PER_TRACK u4 /* sectors per track */
|
||||
#define HDSK_MAX_TRACKS u3 /* number of tracks */
|
||||
#define HDSK_FORMAT_TYPE u6 /* Disk Format Type */
|
||||
#define HDSK_CAPACITY (2048*32*128) /* Default Altair HDSK Capacity */
|
||||
#define HDSK_NUMBER 8 /* number of hard disks */
|
||||
#define CPM_OK 0 /* indicates to CP/M everything ok */
|
||||
#define CPM_ERROR 1 /* indicates to CP/M an error condition */
|
||||
#define CPM_EMPTY 0xe5 /* default value for non-existing bytes */
|
||||
#define hdsk_none 0
|
||||
#define hdsk_reset 1
|
||||
#define hdsk_read 2
|
||||
#define hdsk_write 3
|
||||
#define hdsk_boot_address 0x5c00
|
||||
#define HDSK_NONE 0
|
||||
#define HDSK_RESET 1
|
||||
#define HDSK_READ 2
|
||||
#define HDSK_WRITE 3
|
||||
#define HDSK_PARAM 4
|
||||
#define HDSK_BOOT_ADDRESS 0x5c00
|
||||
|
||||
extern char messageBuffer[];
|
||||
extern int32 PCX;
|
||||
|
@ -57,9 +68,8 @@ extern void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Valu
|
|||
extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value);
|
||||
extern void protect(const int32 l, const int32 h);
|
||||
extern uint8 GetBYTEWrapper(const uint32 Addr);
|
||||
extern int32 bootrom[bootrom_size];
|
||||
extern int32 bootrom[BOOTROM_SIZE];
|
||||
|
||||
static t_stat hdsk_svc(UNIT *uptr);
|
||||
static t_stat hdsk_boot(int32 unitno, DEVICE *dptr);
|
||||
static int32 hdsk_hasVerbose(void);
|
||||
int32 hdsk_io(const int32 port, const int32 io, const int32 data);
|
||||
|
@ -70,23 +80,50 @@ static int32 doSeek(void);
|
|||
static int32 doRead(void);
|
||||
static int32 doWrite(void);
|
||||
|
||||
static int32 hdskLastCommand = hdsk_none;
|
||||
static int32 hdskLastCommand = HDSK_NONE;
|
||||
static int32 hdskCommandPosition = 0;
|
||||
static int32 paramcount = 0;
|
||||
static int32 selectedDisk;
|
||||
static int32 selectedSector;
|
||||
static int32 selectedTrack;
|
||||
static int32 selectedDMA;
|
||||
static int32 hdskTrace;
|
||||
|
||||
typedef struct {
|
||||
char name[16];
|
||||
t_addr capac;
|
||||
uint16 spt;
|
||||
uint8 bsh;
|
||||
uint8 blm;
|
||||
uint8 exm;
|
||||
uint16 dsm;
|
||||
uint16 drm;
|
||||
uint8 al0;
|
||||
uint8 al1;
|
||||
uint16 cks;
|
||||
uint16 off;
|
||||
uint8 psh;
|
||||
uint8 phm;
|
||||
} DPB;
|
||||
|
||||
static DPB dpb[] = {
|
||||
/* NAME CAPAC SPT BSH BLM EXM DSM DRM AL0 AL1 CKS OFF PSH PHM */
|
||||
{ "HDSK", HDSK_CAPACITY, 32, 0x05, 0x1F, 0x01, 0x07f9, 0x03FF, 0xFF, 0x00, 0x8000, 0x0006, 0x00, 0x00 }, /* AZ80 HDSK */
|
||||
{ "EZ80FL", 131072, 32, 0x03, 0x07, 0x00, 127, 0x003E, 0xC0, 0x00, 0x0000, 0x0000, 0x02, 0x03 }, /* 128K FLASH */
|
||||
{ "P112", 1474560, 72, 0x04, 0x0F, 0x00, 710, 0x00FE, 0xF0, 0x00, 0x0000, 0x0002, 0x02, 0x03 }, /* 1.44M P112 */
|
||||
{ "SU720", 737280, 36, 0x04, 0x0F, 0x00, 354, 0x007E, 0xC0, 0x00, 0x0020, 0x0002, 0x02, 0x03 }, /* 720K Super I/O */
|
||||
{ "", 0 }
|
||||
};
|
||||
|
||||
static UNIT hdsk_unit[] = {
|
||||
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
|
||||
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }
|
||||
};
|
||||
|
||||
static REG hdsk_reg[] = {
|
||||
|
@ -101,12 +138,14 @@ static REG hdsk_reg[] = {
|
|||
};
|
||||
|
||||
static MTAB hdsk_mod[] = {
|
||||
{ UNIT_HDSKWLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_HDSKWLK, UNIT_HDSKWLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_VAL, 0, "FORMAT", "FORMAT", &set_format, &show_format, NULL },
|
||||
{ UNIT_HDSKWLK, 0, "WRTENB", "WRTENB", NULL },
|
||||
{ UNIT_HDSKWLK, UNIT_HDSKWLK, "WRTLCK", "WRTLCK", NULL },
|
||||
/* quiet, no warning messages */
|
||||
{ UNIT_HDSK_VERBOSE, 0, "QUIET", "QUIET", NULL },
|
||||
/* verbose, show warning messages */
|
||||
{ UNIT_HDSK_VERBOSE, UNIT_HDSK_VERBOSE, "VERBOSE", "VERBOSE", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_VAL, 0, "GEOM", "GEOM", &set_geom, &show_geom, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -114,16 +153,127 @@ DEVICE hdsk_dev = {
|
|||
"HDSK", hdsk_unit, hdsk_reg, hdsk_mod,
|
||||
8, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, NULL,
|
||||
&hdsk_boot, NULL, NULL,
|
||||
&hdsk_boot, &hdsk_attach, NULL,
|
||||
NULL, 0, 0,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static t_stat hdsk_svc(UNIT *uptr) {
|
||||
/* Attach routine */
|
||||
t_stat hdsk_attach (UNIT *uptr, char *cptr) {
|
||||
uint32 flen;
|
||||
t_stat r;
|
||||
int32 i;
|
||||
|
||||
r = attach_unit (uptr, cptr); /* attach unit */
|
||||
if (r != SCPE_OK) return r; /* error? */
|
||||
if ((flen = sim_fsize (uptr->fileref)) == 0) { /* new disk image? */
|
||||
if (uptr->flags & UNIT_RO) return SCPE_OK; /* if ro, done */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if(flen>0) {
|
||||
uptr->capac = flen;
|
||||
|
||||
uptr->HDSK_FORMAT_TYPE = -1; /* Default to unknown format type */
|
||||
|
||||
for(i=0; dpb[i].spt != 0; i++) {
|
||||
if(dpb[i].capac == uptr->capac) {
|
||||
uptr->HDSK_FORMAT_TYPE = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(uptr->HDSK_FORMAT_TYPE == -1) {
|
||||
uptr->HDSK_FORMAT_TYPE = 0;
|
||||
uptr->capac = dpb[uptr->HDSK_FORMAT_TYPE].capac;
|
||||
printf("HDSK: WARNING: Unsupported disk capacity, assuming HDSK type.\n");
|
||||
uptr->flags |= UNIT_HDSKWLK;
|
||||
printf("HDSK: WARNING: Forcing WRTLCK.\n");
|
||||
if(uptr->capac != (uptr->HDSK_MAX_TRACKS * uptr->HDSK_SECTORS_PER_TRACK * uptr->HDSK_SECTOR_SIZE)) {
|
||||
printf("HDSK: WARNING: Geometry may be incorrect.\n");
|
||||
}
|
||||
}
|
||||
|
||||
uptr->HDSK_SECTOR_SIZE = (128 << dpb[uptr->HDSK_FORMAT_TYPE].psh);
|
||||
uptr->HDSK_SECTORS_PER_TRACK = dpb[uptr->HDSK_FORMAT_TYPE].spt >> dpb[uptr->HDSK_FORMAT_TYPE].psh;
|
||||
uptr->HDSK_MAX_TRACKS = uptr->capac / (uptr->HDSK_SECTORS_PER_TRACK * uptr->HDSK_SECTOR_SIZE);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static const int32 hdskBoot[bootrom_size] = {
|
||||
/* Set disk geometry routine */
|
||||
t_stat set_geom (UNIT *uptr, int32 val, char *cptr, void *desc) {
|
||||
DEVICE *dptr;
|
||||
|
||||
uint32 ncyl, nsect, ssize;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
if (uptr == NULL) return SCPE_IERR;
|
||||
dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
|
||||
sscanf(cptr, "%d/%d/%d", &ncyl, &nsect, &ssize);
|
||||
uptr->HDSK_MAX_TRACKS = ncyl;
|
||||
uptr->HDSK_SECTORS_PER_TRACK = nsect;
|
||||
uptr->HDSK_SECTOR_SIZE = ssize;
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show disk geometry routine */
|
||||
t_stat show_geom (FILE *st, UNIT *uptr, int32 val, void *desc) {
|
||||
DEVICE *dptr;
|
||||
if (uptr == NULL) return SCPE_IERR;
|
||||
dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
fprintf (st, "T:%d/N:%d/S:%d", uptr->HDSK_MAX_TRACKS, uptr->HDSK_SECTORS_PER_TRACK, uptr->u5);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set disk format routine */
|
||||
t_stat set_format (UNIT *uptr, int32 val, char *cptr, void *desc) {
|
||||
DEVICE *dptr;
|
||||
|
||||
char fmtname[16];
|
||||
int32 i;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
if (uptr == NULL) return SCPE_IERR;
|
||||
dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
|
||||
sscanf(cptr, "%s", fmtname);
|
||||
|
||||
for(i=0;dpb[i].spt != 0;i++) {
|
||||
if(!strncmp(fmtname, dpb[i].name, strlen(fmtname))) {
|
||||
uptr->HDSK_FORMAT_TYPE = i;
|
||||
uptr->capac = dpb[i].capac; /* Set capacity */
|
||||
|
||||
/* Configure physical disk geometry */
|
||||
uptr->HDSK_SECTOR_SIZE = (128 << dpb[uptr->HDSK_FORMAT_TYPE].psh);
|
||||
uptr->HDSK_SECTORS_PER_TRACK = dpb[uptr->HDSK_FORMAT_TYPE].spt >> dpb[uptr->HDSK_FORMAT_TYPE].psh;
|
||||
uptr->HDSK_MAX_TRACKS = uptr->capac / (uptr->HDSK_SECTORS_PER_TRACK * uptr->HDSK_SECTOR_SIZE);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
/* Show disk format routine */
|
||||
t_stat show_format (FILE *st, UNIT *uptr, int32 val, void *desc) {
|
||||
DEVICE *dptr;
|
||||
if (uptr == NULL) return SCPE_IERR;
|
||||
dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
fprintf (st, "%s", dpb[uptr->HDSK_FORMAT_TYPE].name);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static const int32 hdskBoot[BOOTROM_SIZE] = {
|
||||
0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* 5c00-5c07 */
|
||||
0xc2, 0x05, 0x5c, 0x3e, 0x16, 0xd3, 0xfe, 0x3e, /* 5c08-5c0f */
|
||||
0x12, 0xd3, 0xfe, 0xdb, 0xfe, 0xb7, 0xca, 0x20, /* 5c10-5c17 */
|
||||
|
@ -169,19 +319,19 @@ static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
|
|||
printf("ALTAIR boot ROM installed.\n");
|
||||
}
|
||||
/* check whether we are really modifying an LD A,<> instruction */
|
||||
if (bootrom[unitNoOffset1 - 1] == LDAInstruction) {
|
||||
bootrom[unitNoOffset1] = (unitno + NUM_OF_DSK) & 0xff; /* LD A,<unitno> */
|
||||
if (bootrom[UNIT_NO_OFFSET_1 - 1] == LDA_INSTRUCTION) {
|
||||
bootrom[UNIT_NO_OFFSET_1] = (unitno + NUM_OF_DSK) & 0xff; /* LD A,<unitno> */
|
||||
}
|
||||
else { /* Attempt to modify non LD A,<> instructions is refused. */
|
||||
printf("Incorrect boot ROM offset detected.\n");
|
||||
return SCPE_IERR;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < bootrom_size; i++) {
|
||||
PutBYTEBasic(i + hdsk_boot_address, 0, hdskBoot[i] & 0xff);
|
||||
for (i = 0; i < BOOTROM_SIZE; i++) {
|
||||
PutBYTEBasic(i + HDSK_BOOT_ADDRESS, 0, hdskBoot[i] & 0xff);
|
||||
}
|
||||
saved_PC = hdsk_boot_address;
|
||||
protect(hdsk_boot_address, hdsk_boot_address + bootrom_size - 1);
|
||||
saved_PC = HDSK_BOOT_ADDRESS;
|
||||
protect(HDSK_BOOT_ADDRESS, HDSK_BOOT_ADDRESS + BOOTROM_SIZE - 1);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -200,14 +350,14 @@ static int32 hdsk_hasVerbose(void) {
|
|||
|
||||
1. Reset
|
||||
ld b,32
|
||||
ld a,hdsk_reset
|
||||
ld a,HDSK_RESET
|
||||
l: out (0fdh),a
|
||||
dec b
|
||||
jp nz,l
|
||||
|
||||
2. Read / write
|
||||
; parameter block
|
||||
cmd: db hdsk_read or hdsk_write
|
||||
cmd: db HDSK_READ or HDSK_WRITE
|
||||
hd: db 0 ; 0 .. 7, defines hard disk to be used
|
||||
sector: db 0 ; 0 .. 31, defines sector
|
||||
track: dw 0 ; 0 .. 2047, defines track
|
||||
|
@ -223,43 +373,65 @@ static int32 hdsk_hasVerbose(void) {
|
|||
jp nz,l ; again, if not done
|
||||
in a,(0fdh) ; get result code
|
||||
|
||||
3. Retrieve Disk Parameters from controller (Howard M. Harte)
|
||||
Reads a 19-byte parameter block from the disk controller.
|
||||
This parameter block is in CP/M DPB format for the first 17 bytes,
|
||||
and the last two bytes are the lsb/msb of the disk's physical
|
||||
sector size.
|
||||
|
||||
; routine to execute
|
||||
ld a,hdskParam ; hdskParam = 4
|
||||
out (hdskPort),a ; Send 'get parameters' command, hdskPort = 0fdh
|
||||
ld a,(diskno)
|
||||
out (hdskPort),a ; Send selected HDSK number
|
||||
ld b,17
|
||||
1: in a,(hdskPort) ; Read 17-bytes of DPB
|
||||
ld (hl), a
|
||||
inc hl
|
||||
djnz 1
|
||||
in a,(hdskPort) ; Read LSB of disk's physical sector size.
|
||||
ld (hsecsiz), a
|
||||
in a,(hdskPort) ; Read MSB of disk's physical sector size.
|
||||
ld (hsecsiz+1), a
|
||||
|
||||
*/
|
||||
|
||||
/* check the parameters and return TRUE iff parameters are correct or have been repaired */
|
||||
static int32 checkParameters(void) {
|
||||
UNIT *uptr = hdsk_dev.units + selectedDisk;
|
||||
int32 currentFlag;
|
||||
if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) {
|
||||
if (hdsk_hasVerbose()) {
|
||||
message2("HDSK%d does not exist, will use HDSK0 instead.", selectedDisk);
|
||||
MESSAGE_2("HDSK%d does not exist, will use HDSK0 instead.", selectedDisk);
|
||||
}
|
||||
selectedDisk = 0;
|
||||
}
|
||||
currentFlag = (hdsk_dev.units + selectedDisk) -> flags;
|
||||
if ((currentFlag & UNIT_ATT) == 0) {
|
||||
if (currentFlag & UNIT_HDSK_VERBOSE) {
|
||||
message2("HDSK%d is not attached.", selectedDisk);
|
||||
MESSAGE_2("HDSK%d is not attached.", selectedDisk);
|
||||
}
|
||||
return FALSE; /* cannot read or write */
|
||||
}
|
||||
if ((selectedSector < 0) || (selectedSector >= HDSK_SECTORS_PER_TRACK)) {
|
||||
if ((selectedSector < 0) || (selectedSector >= uptr->HDSK_SECTORS_PER_TRACK)) {
|
||||
if (currentFlag & UNIT_HDSK_VERBOSE) {
|
||||
message4("HDSK%d: 0 <= Sector=%02d < %d violated, will use 0 instead.",
|
||||
selectedDisk, selectedSector, HDSK_SECTORS_PER_TRACK);
|
||||
MESSAGE_4("HDSK%d: 0 <= Sector=%02d < %d violated, will use 0 instead.",
|
||||
selectedDisk, selectedSector, uptr->HDSK_SECTORS_PER_TRACK);
|
||||
}
|
||||
selectedSector = 0;
|
||||
}
|
||||
if ((selectedTrack < 0) || (selectedTrack >= HDS_MAX_TRACKS)) {
|
||||
if ((selectedTrack < 0) || (selectedTrack >= uptr->HDSK_MAX_TRACKS)) {
|
||||
if (currentFlag & UNIT_HDSK_VERBOSE) {
|
||||
message4("HDSK%d: 0 <= Track=%04d < %04d violated, will use 0 instead.",
|
||||
selectedDisk, selectedTrack, HDS_MAX_TRACKS);
|
||||
MESSAGE_4("HDSK%d: 0 <= Track=%04d < %04d violated, will use 0 instead.",
|
||||
selectedDisk, selectedTrack, uptr->HDSK_MAX_TRACKS);
|
||||
}
|
||||
selectedTrack = 0;
|
||||
}
|
||||
selectedDMA &= ADDRMASK;
|
||||
if (hdskTrace) {
|
||||
message6("%s HDSK%d Sector=%02d Track=%04d DMA=%04x",
|
||||
(hdskLastCommand == hdsk_read) ? "Read" : "Write",
|
||||
selectedDisk, selectedSector, selectedTrack, selectedDMA);
|
||||
MESSAGE_7("%s HDSK%d Track=%04d Sector=%02d Len=%04d DMA=%04x\n",
|
||||
(hdskLastCommand == HDSK_READ) ? "Read" : "Write",
|
||||
selectedDisk, selectedTrack, selectedSector, uptr->HDSK_SECTOR_SIZE, selectedDMA);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -267,9 +439,9 @@ static int32 checkParameters(void) {
|
|||
static int32 doSeek(void) {
|
||||
UNIT *uptr = hdsk_dev.units + selectedDisk;
|
||||
if (fseek(uptr -> fileref,
|
||||
HDSK_TRACK_SIZE * selectedTrack + HDSK_SECTOR_SIZE * selectedSector, SEEK_SET)) {
|
||||
(uptr->HDSK_SECTORS_PER_TRACK * uptr->HDSK_SECTOR_SIZE) * selectedTrack + (uptr->HDSK_SECTOR_SIZE * selectedSector), SEEK_SET)) {
|
||||
if ((uptr -> flags) & UNIT_HDSK_VERBOSE) {
|
||||
message4("Could not access HDSK%d Sector=%02d Track=%04d.",
|
||||
MESSAGE_4("Could not access HDSK%d Sector=%02d Track=%04d.",
|
||||
selectedDisk, selectedSector, selectedTrack);
|
||||
}
|
||||
return CPM_ERROR;
|
||||
|
@ -279,24 +451,26 @@ static int32 doSeek(void) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE]; /* data buffer */
|
||||
|
||||
static int32 doRead(void) {
|
||||
int32 i;
|
||||
uint8 hdskbuf[HDSK_SECTOR_SIZE]; /* data buffer */
|
||||
UNIT *uptr = hdsk_dev.units + selectedDisk;
|
||||
if (doSeek()) {
|
||||
return CPM_ERROR;
|
||||
}
|
||||
if (fread(hdskbuf, HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) {
|
||||
for (i = 0; i < HDSK_SECTOR_SIZE; i++) {
|
||||
|
||||
if (fread(hdskbuf, uptr->HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) {
|
||||
for (i = 0; i < uptr->HDSK_SECTOR_SIZE; i++) {
|
||||
hdskbuf[i] = CPM_EMPTY;
|
||||
}
|
||||
if ((uptr -> flags) & UNIT_HDSK_VERBOSE) {
|
||||
message4("Could not read HDSK%d Sector=%02d Track=%04d.",
|
||||
MESSAGE_4("Could not read HDSK%d Sector=%02d Track=%04d.",
|
||||
selectedDisk, selectedSector, selectedTrack);
|
||||
}
|
||||
return CPM_OK; /* allows the creation of empty hard disks */
|
||||
}
|
||||
for (i = 0; i < HDSK_SECTOR_SIZE; i++) {
|
||||
for (i = 0; i < uptr->HDSK_SECTOR_SIZE; i++) {
|
||||
PutBYTEWrapper(selectedDMA + i, hdskbuf[i]);
|
||||
}
|
||||
return CPM_OK;
|
||||
|
@ -304,18 +478,18 @@ static int32 doRead(void) {
|
|||
|
||||
static int32 doWrite(void) {
|
||||
int32 i;
|
||||
uint8 hdskbuf[HDSK_SECTOR_SIZE]; /* data buffer */
|
||||
|
||||
UNIT *uptr = hdsk_dev.units + selectedDisk;
|
||||
if (((uptr -> flags) & UNIT_HDSKWLK) == 0) { /* write enabled */
|
||||
if (doSeek()) {
|
||||
return CPM_ERROR;
|
||||
}
|
||||
for (i = 0; i < HDSK_SECTOR_SIZE; i++) {
|
||||
for (i = 0; i < uptr->HDSK_SECTOR_SIZE; i++) {
|
||||
hdskbuf[i] = GetBYTEWrapper(selectedDMA + i);
|
||||
}
|
||||
if (fwrite(hdskbuf, HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) {
|
||||
if (fwrite(hdskbuf, uptr->HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) {
|
||||
if ((uptr -> flags) & UNIT_HDSK_VERBOSE) {
|
||||
message4("Could not write HDSK%d Sector=%02d Track=%04d.",
|
||||
MESSAGE_4("Could not write HDSK%d Sector=%02d Track=%04d.",
|
||||
selectedDisk, selectedSector, selectedTrack);
|
||||
}
|
||||
return CPM_ERROR;
|
||||
|
@ -323,7 +497,7 @@ static int32 doWrite(void) {
|
|||
}
|
||||
else {
|
||||
if ((uptr -> flags) & UNIT_HDSK_VERBOSE) {
|
||||
message4("Could not write to locked HDSK%d Sector=%02d Track=%04d.",
|
||||
MESSAGE_4("Could not write to locked HDSK%d Sector=%02d Track=%04d.",
|
||||
selectedDisk, selectedSector, selectedTrack);
|
||||
}
|
||||
return CPM_ERROR;
|
||||
|
@ -332,15 +506,44 @@ static int32 doWrite(void) {
|
|||
}
|
||||
|
||||
static int32 hdsk_in(const int32 port) {
|
||||
UNIT *uptr = hdsk_dev.units + selectedDisk;
|
||||
|
||||
int32 result;
|
||||
if ((hdskCommandPosition == 6) && ((hdskLastCommand == hdsk_read) || (hdskLastCommand == hdsk_write))) {
|
||||
result = checkParameters() ? ((hdskLastCommand == hdsk_read) ? doRead() : doWrite()) : CPM_ERROR;
|
||||
hdskLastCommand = hdsk_none;
|
||||
if ((hdskCommandPosition == 6) && ((hdskLastCommand == HDSK_READ) || (hdskLastCommand == HDSK_WRITE))) {
|
||||
result = checkParameters() ? ((hdskLastCommand == HDSK_READ) ? doRead() : doWrite()) : CPM_ERROR;
|
||||
hdskLastCommand = HDSK_NONE;
|
||||
hdskCommandPosition = 0;
|
||||
return result;
|
||||
} else if (hdskLastCommand == HDSK_PARAM) {
|
||||
DPB current = dpb[uptr->HDSK_FORMAT_TYPE];
|
||||
uint8 params[17];
|
||||
params[ 0] = current.spt & 0xff; params[ 1] = (current.spt >> 8) & 0xff;
|
||||
params[ 2] = current.bsh;
|
||||
params[ 3] = current.blm;
|
||||
params[ 4] = current.exm;
|
||||
params[ 5] = current.dsm & 0xff; params[ 6] = (current.dsm >> 8) & 0xff;
|
||||
params[ 7] = current.drm & 0xff; params[ 8] = (current.drm >> 8) & 0xff;
|
||||
params[ 9] = current.al0;
|
||||
params[10] = current.al1;
|
||||
params[11] = current.cks & 0xff; params[12] = (current.cks >> 8) & 0xff;
|
||||
params[13] = current.off & 0xff; params[14] = (current.off >> 8) & 0xff;
|
||||
params[15] = current.psh;
|
||||
params[16] = current.phm;
|
||||
if (++paramcount >= 19) {
|
||||
hdskLastCommand = HDSK_NONE;
|
||||
}
|
||||
if (paramcount <= 17)
|
||||
return params[paramcount - 1];
|
||||
else if (paramcount == 18)
|
||||
return (uptr->HDSK_SECTOR_SIZE & 0xff);
|
||||
else if (paramcount == 19)
|
||||
return (uptr->HDSK_SECTOR_SIZE >> 8);
|
||||
else
|
||||
MESSAGE_2("HDSK%d Get parameter error.", selectedDisk);
|
||||
|
||||
}
|
||||
else if (hdsk_hasVerbose()) {
|
||||
message4("Illegal IN command detected (port=%03xh, cmd=%d, pos=%d).",
|
||||
MESSAGE_4("Illegal IN command detected (port=%03xh, cmd=%d, pos=%d).",
|
||||
port, hdskLastCommand, hdskCommandPosition);
|
||||
}
|
||||
return CPM_OK;
|
||||
|
@ -349,9 +552,14 @@ static int32 hdsk_in(const int32 port) {
|
|||
static int32 hdsk_out(const int32 data) {
|
||||
switch(hdskLastCommand) {
|
||||
|
||||
case hdsk_read:
|
||||
case HDSK_PARAM:
|
||||
paramcount = 0;
|
||||
selectedDisk = data;
|
||||
break;
|
||||
|
||||
case hdsk_write:
|
||||
case HDSK_READ:
|
||||
|
||||
case HDSK_WRITE:
|
||||
switch(hdskCommandPosition) {
|
||||
|
||||
case 0:
|
||||
|
@ -385,7 +593,7 @@ static int32 hdsk_out(const int32 data) {
|
|||
break;
|
||||
|
||||
default:
|
||||
hdskLastCommand = hdsk_none;
|
||||
hdskLastCommand = HDSK_NONE;
|
||||
hdskCommandPosition = 0;
|
||||
}
|
||||
break;
|
||||
|
|
292
AltairZ80/altairz80_net.c
Normal file
292
AltairZ80/altairz80_net.c
Normal file
|
@ -0,0 +1,292 @@
|
|||
/* altairz80_net.c: networking capability
|
||||
|
||||
Copyright (c) 2002-2007, Peter Schorn
|
||||
|
||||
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
|
||||
PETER SCHORN 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 Peter Schorn shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Peter Schorn.
|
||||
*/
|
||||
|
||||
#include "altairz80_defs.h"
|
||||
#include "sim_sock.h"
|
||||
|
||||
#define UNIT_V_SERVER (UNIT_V_UF + 0) /* define machine as a server */
|
||||
#define UNIT_SERVER (1 << UNIT_V_SERVER)
|
||||
#define NET_INIT_POLL_SERVER 16000
|
||||
#define NET_INIT_POLL_CLIENT 15000
|
||||
|
||||
/*#define DEBUG_NETWORK TRUE*/
|
||||
|
||||
static t_stat net_attach (UNIT *uptr, char *cptr);
|
||||
static t_stat net_detach (UNIT *uptr);
|
||||
static t_stat net_reset (DEVICE *dptr);
|
||||
static t_stat net_svc (UNIT *uptr);
|
||||
static t_stat set_net (UNIT *uptr, int32 value, char *cptr, void *desc);
|
||||
int32 netStatus (const int32 port, const int32 io, const int32 data);
|
||||
int32 netData (const int32 port, const int32 io, const int32 data);
|
||||
|
||||
#define MAX_CONNECTIONS 2 /* maximal number of server connections */
|
||||
#define BUFFER_LENGTH 512 /* length of input and output buffer */
|
||||
|
||||
static struct {
|
||||
int32 Z80StatusPort; /* Z80 status port associated with this ioSocket, read only */
|
||||
int32 Z80DataPort; /* Z80 data port associated with this ioSocket, read only */
|
||||
SOCKET masterSocket; /* server master socket, only defined at [1] */
|
||||
SOCKET ioSocket; /* accepted server socket or connected client socket, 0 iff free */
|
||||
char inputBuffer[BUFFER_LENGTH]; /* buffer for input characters read from ioSocket */
|
||||
int32 inputPosRead; /* position of next character to read from buffer */
|
||||
int32 inputPosWrite; /* position of next character to append to input buffer from ioSocket */
|
||||
int32 inputSize; /* number of characters in circular input buffer */
|
||||
char outputBuffer[BUFFER_LENGTH];/* buffer for output characters to be written to ioSocket */
|
||||
int32 outputPosRead; /* position of next character to write to ioSocket */
|
||||
int32 outputPosWrite; /* position of next character to append to output buffer */
|
||||
int32 outputSize; /* number of characters in circular output buffer */
|
||||
} serviceDescriptor[MAX_CONNECTIONS+1] = { /* serviceDescriptor[0] holds the information for a client */
|
||||
/* stat dat ms ios in inPR inPW inS out outPR outPW outS */
|
||||
{50, 51, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* client Z80 port 50 and 51 */
|
||||
{40, 41, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0}, /* server Z80 port 40 and 41 */
|
||||
{42, 43, 0, 0, {0}, 0, 0, 0, {0}, 0, 0, 0} /* server Z80 port 42 and 43 */
|
||||
};
|
||||
|
||||
static UNIT net_unit = {
|
||||
UDATA (&net_svc, UNIT_ATTABLE, 0),
|
||||
0, /* wait, set in attach */
|
||||
0, /* u3 = Port */
|
||||
0, /* u4 = IP of host */
|
||||
0, /* u5, unused */
|
||||
0, /* u6, unused */
|
||||
};
|
||||
|
||||
static REG net_reg[] = {
|
||||
{ DRDATA (POLL, net_unit.wait, 32) },
|
||||
{ HRDATA (IPHOST, net_unit.u4, 32), REG_RO },
|
||||
{ DRDATA (PORT, net_unit.u3, 32), REG_RO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static MTAB net_mod[] = {
|
||||
{ UNIT_SERVER, 0, "CLIENT", "CLIENT", &set_net}, /* machine is a client */
|
||||
{ UNIT_SERVER, UNIT_SERVER, "SERVER", "SERVER", &set_net}, /* machine is a server */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE net_dev = {
|
||||
"NET", &net_unit, net_reg, net_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &net_reset,
|
||||
NULL, &net_attach, &net_detach,
|
||||
NULL, 0, 0,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static t_stat set_net(UNIT *uptr, int32 value, char *cptr, void *desc) {
|
||||
char temp[CBUFSIZE];
|
||||
if ((net_unit.flags & UNIT_ATT) && ((net_unit.flags & UNIT_SERVER) != value)) {
|
||||
strncpy(temp, net_unit.filename, CBUFSIZE); /* save name for later attach */
|
||||
net_detach(&net_unit);
|
||||
net_unit.flags ^= UNIT_SERVER; /* now switch from client to server and vice versa */
|
||||
net_attach(uptr, temp);
|
||||
return SCPE_OK;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static void serviceDescriptor_reset(const uint32 i) {
|
||||
serviceDescriptor[i].inputPosRead = 0;
|
||||
serviceDescriptor[i].inputPosWrite = 0;
|
||||
serviceDescriptor[i].inputSize = 0;
|
||||
serviceDescriptor[i].outputPosRead = 0;
|
||||
serviceDescriptor[i].outputPosWrite = 0;
|
||||
serviceDescriptor[i].outputSize = 0;
|
||||
}
|
||||
|
||||
static t_stat net_reset(DEVICE *dptr) {
|
||||
uint32 i;
|
||||
if (net_unit.flags & UNIT_ATT)
|
||||
sim_activate(&net_unit, net_unit.wait); /* start poll */
|
||||
for (i = 0; i <= MAX_CONNECTIONS; i++)
|
||||
serviceDescriptor_reset(i);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static t_stat net_attach(UNIT *uptr, char *cptr) {
|
||||
uint32 i, ipa, ipp;
|
||||
t_stat r = get_ipaddr(cptr, &ipa, &ipp);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
if (ipa == 0) ipa = 0x7F000001; /* localhost = 127.0.0.1 */
|
||||
if (ipp == 0) ipp = 3000;
|
||||
net_unit.u3 = ipp;
|
||||
net_unit.u4 = ipa;
|
||||
net_reset(&net_dev);
|
||||
for (i = 0; i <= MAX_CONNECTIONS; i++) serviceDescriptor[i].ioSocket = 0;
|
||||
if (net_unit.flags & UNIT_SERVER) {
|
||||
net_unit.wait = NET_INIT_POLL_SERVER;
|
||||
serviceDescriptor[1].masterSocket = sim_master_sock(ipp);
|
||||
if (serviceDescriptor[1].masterSocket == INVALID_SOCKET) return SCPE_IOERR;
|
||||
}
|
||||
else {
|
||||
net_unit.wait = NET_INIT_POLL_CLIENT;
|
||||
serviceDescriptor[0].ioSocket = sim_connect_sock(ipa, ipp);
|
||||
if (serviceDescriptor[0].ioSocket == INVALID_SOCKET) return SCPE_IOERR;
|
||||
}
|
||||
net_unit.flags |= UNIT_ATT;
|
||||
net_unit.filename = (char *) calloc(CBUFSIZE, sizeof (char)); /* alloc name buf */
|
||||
if (net_unit.filename == NULL) return SCPE_MEM;
|
||||
strncpy(net_unit.filename, cptr, CBUFSIZE); /* save name */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static t_stat net_detach(UNIT *uptr) {
|
||||
uint32 i;
|
||||
if (!(net_unit.flags & UNIT_ATT)) return SCPE_OK; /* if not attached simply return */
|
||||
if (net_unit.flags & UNIT_SERVER)
|
||||
sim_close_sock(serviceDescriptor[1].masterSocket, TRUE);
|
||||
for (i = 0; i <= MAX_CONNECTIONS; i++)
|
||||
if (serviceDescriptor[i].ioSocket)
|
||||
sim_close_sock(serviceDescriptor[i].ioSocket, FALSE);
|
||||
free(net_unit.filename); /* free port string */
|
||||
net_unit.filename = NULL;
|
||||
net_unit.flags &= ~UNIT_ATT; /* not attached */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* cannot use sim_check_conn to check whether read will return an error */
|
||||
static t_stat net_svc(UNIT *uptr) {
|
||||
int32 i, j, k, r;
|
||||
SOCKET s;
|
||||
static char svcBuffer[BUFFER_LENGTH];
|
||||
if (net_unit.flags & UNIT_ATT) {
|
||||
sim_activate(&net_unit, net_unit.wait); /* continue poll */
|
||||
if (net_unit.flags & UNIT_SERVER) {
|
||||
for (i = 1; i <= MAX_CONNECTIONS; i++)
|
||||
if (serviceDescriptor[i].ioSocket == 0) {
|
||||
s = sim_accept_conn(serviceDescriptor[1].masterSocket, NULL);
|
||||
if (s != INVALID_SOCKET) {
|
||||
serviceDescriptor[i].ioSocket = s;
|
||||
#ifdef DEBUG_NETWORK
|
||||
printf("Accepted connection %i with socket %i.\n\r", i, s);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (serviceDescriptor[0].ioSocket == 0) {
|
||||
serviceDescriptor[0].ioSocket = sim_connect_sock(net_unit.u4, net_unit.u3);
|
||||
if (serviceDescriptor[0].ioSocket == INVALID_SOCKET) return SCPE_IOERR;
|
||||
printf("\rWaiting for server ... Type g<return> (possibly twice) when ready\n\r");
|
||||
return SCPE_STOP;
|
||||
}
|
||||
for (i = 0; i <= MAX_CONNECTIONS; i++)
|
||||
if (serviceDescriptor[i].ioSocket) {
|
||||
if (serviceDescriptor[i].inputSize < BUFFER_LENGTH) { /* there is space left in inputBuffer */
|
||||
r = sim_read_sock(serviceDescriptor[i].ioSocket, svcBuffer,
|
||||
BUFFER_LENGTH - serviceDescriptor[i].inputSize);
|
||||
if (r == -1) {
|
||||
#ifdef DEBUG_NETWORK
|
||||
printf("Drop connection %i with socket %i.\n\r", i, serviceDescriptor[i].ioSocket);
|
||||
#endif
|
||||
sim_close_sock(serviceDescriptor[i].ioSocket, FALSE);
|
||||
serviceDescriptor[i].ioSocket = 0;
|
||||
serviceDescriptor_reset(i);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < r; j++) {
|
||||
serviceDescriptor[i].inputBuffer[serviceDescriptor[i].inputPosWrite++] = svcBuffer[j];
|
||||
if (serviceDescriptor[i].inputPosWrite == BUFFER_LENGTH)
|
||||
serviceDescriptor[i].inputPosWrite = 0;
|
||||
}
|
||||
serviceDescriptor[i].inputSize += r;
|
||||
}
|
||||
}
|
||||
if (serviceDescriptor[i].outputSize > 0) { /* there is something to write in outputBuffer */
|
||||
k = serviceDescriptor[i].outputPosRead;
|
||||
for (j = 0; j < serviceDescriptor[i].outputSize; j++) {
|
||||
svcBuffer[j] = serviceDescriptor[i].outputBuffer[k++];
|
||||
if (k == BUFFER_LENGTH) k = 0;
|
||||
}
|
||||
r = sim_write_sock(serviceDescriptor[i].ioSocket, svcBuffer, serviceDescriptor[i].outputSize);
|
||||
if (r >= 0) {
|
||||
serviceDescriptor[i].outputSize -= r;
|
||||
serviceDescriptor[i].outputPosRead += r;
|
||||
if (serviceDescriptor[i].outputPosRead >= BUFFER_LENGTH)
|
||||
serviceDescriptor[i].outputPosRead -= BUFFER_LENGTH;
|
||||
}
|
||||
else printf("write %i\r\n", r);
|
||||
}
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
int32 netStatus(const int32 port, const int32 io, const int32 data) {
|
||||
uint32 i;
|
||||
net_svc(&net_unit);
|
||||
if (io == 0) { /* IN */
|
||||
for (i = 0; i <= MAX_CONNECTIONS; i++)
|
||||
if (serviceDescriptor[i].Z80StatusPort == port)
|
||||
return (serviceDescriptor[i].inputSize > 0 ? 1 : 0) |
|
||||
(serviceDescriptor[i].outputSize < BUFFER_LENGTH ? 2 : 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 netData(const int32 port, const int32 io, const int32 data) {
|
||||
uint32 i;
|
||||
char result;
|
||||
net_svc(&net_unit);
|
||||
for (i = 0; i <= MAX_CONNECTIONS; i++)
|
||||
if (serviceDescriptor[i].Z80DataPort == port)
|
||||
if (io == 0) { /* IN */
|
||||
if (serviceDescriptor[i].inputSize == 0) {
|
||||
printf("re-read from %i\r\n", port);
|
||||
result = serviceDescriptor[i].inputBuffer[serviceDescriptor[i].inputPosRead > 0 ?
|
||||
serviceDescriptor[i].inputPosRead - 1 : BUFFER_LENGTH - 1];
|
||||
}
|
||||
else {
|
||||
result = serviceDescriptor[i].inputBuffer[serviceDescriptor[i].inputPosRead++];
|
||||
if (serviceDescriptor[i].inputPosRead == BUFFER_LENGTH)
|
||||
serviceDescriptor[i].inputPosRead = 0;
|
||||
serviceDescriptor[i].inputSize--;
|
||||
}
|
||||
#ifdef DEBUG_NETWORK
|
||||
printf(" IN(%i)=%03xh (%c)\r\n", port, (result & 0xff),
|
||||
(32 <= (result & 0xff)) && ((result & 0xff) <= 127) ? (result & 0xff) : '?');
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
else { /* OUT */
|
||||
if (serviceDescriptor[i].outputSize == BUFFER_LENGTH) {
|
||||
printf("over-write %i to %i\r\n", data, port);
|
||||
serviceDescriptor[i].outputBuffer[serviceDescriptor[i].outputPosWrite > 0 ?
|
||||
serviceDescriptor[i].outputPosWrite - 1 : BUFFER_LENGTH - 1] = data;
|
||||
}
|
||||
else {
|
||||
serviceDescriptor[i].outputBuffer[serviceDescriptor[i].outputPosWrite++] = data;
|
||||
if (serviceDescriptor[i].outputPosWrite== BUFFER_LENGTH)
|
||||
serviceDescriptor[i].outputPosWrite = 0;
|
||||
serviceDescriptor[i].outputSize++;
|
||||
}
|
||||
#ifdef DEBUG_NETWORK
|
||||
printf("OUT(%i)=%03xh (%c)\r\n", port, data, (32 <= data) && (data <= 127) ? data : '?');
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* gri_stddev.c: GRI-909 standard devices
|
||||
|
||||
Copyright (c) 2001-2005, Robert M Supnik
|
||||
Copyright (c) 2001-2006, 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"),
|
||||
|
@ -29,6 +29,7 @@
|
|||
hsp S42-006 high speed punch
|
||||
rtc real time clock
|
||||
|
||||
30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode
|
||||
22-Nov-05 RMS Revised for new terminal processing routines
|
||||
29-Dec-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
|
@ -254,7 +255,7 @@ t_stat tto_svc (UNIT *uptr)
|
|||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags));
|
||||
c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags) | TTUF_KSR);
|
||||
if (c >= 0) {
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
tty 316/516-33 teleprinter
|
||||
clk/options 316/516-12 real time clocks/internal options
|
||||
|
||||
30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode
|
||||
03-Apr-06 RMS Fixed bugs in punch state handling (from Theo Engel)
|
||||
22-Nov-05 RMS Revised for new terminal processing routines
|
||||
05-Feb-05 RMS Fixed bug in OCP '0001 (found by Philipp Hachtmann)
|
||||
|
@ -688,7 +689,7 @@ t_stat tto_write (int32 c)
|
|||
{
|
||||
UNIT *tuptr = &tty_unit[TTO];
|
||||
|
||||
c = sim_tt_outcvt (c, TT_GET_MODE (tuptr->flags));
|
||||
c = sim_tt_outcvt (c, TT_GET_MODE (tuptr->flags) | TTUF_KSR);
|
||||
tuptr->pos = tuptr->pos + 1;
|
||||
if (c >= 0) return sim_putchar_s (c);
|
||||
else return SCPE_OK;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_cpu.h: HP 2100 CPU definitions
|
||||
|
||||
Copyright (c) 2005, Robert M. Supnik
|
||||
Copyright (c) 2005-2006, 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,72 +23,175 @@
|
|||
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.
|
||||
|
||||
16-Dec-06 JDB Added UNIT_2115 and UNIT_2114
|
||||
16-Oct-06 JDB Moved ReadF to hp2100_cpu1.c
|
||||
26-Sep-06 JDB Added CPU externs for microcode simulators
|
||||
16-Aug-06 JDB Added UNIT_EMA for future RTE-4 EMA microcode
|
||||
Added UNIT_VMA for future RTE-6 VMA and OS microcode
|
||||
Added UNIT_1000_F for future F-Series support
|
||||
09-Aug-06 JDB Added UNIT_DBI for double integer microcode
|
||||
21-Jan-05 JDB Reorganized CPU option flags
|
||||
14-Jan-05 RMS Cloned from hp2100_cpu.c
|
||||
|
||||
CPU models are broken down into type and series to facilitate option
|
||||
validation. Bits 3:2 encode the type, and bits 1:0 encode the series
|
||||
within the type.
|
||||
CPU models are broken down into family, type, and series to facilitate option
|
||||
validation. Bit 3 encodes the family, bit 2 encodes the type, and bits 1:0
|
||||
encode the series within the type.
|
||||
*/
|
||||
|
||||
#ifndef _HP2100_CPU_H_
|
||||
#define _HP2100_CPU_H_ 0
|
||||
|
||||
/* CPU model definition flags */
|
||||
|
||||
#define CPU_V_SERIES 0
|
||||
#define CPU_V_TYPE 2
|
||||
#define CPU_V_FAMILY 3
|
||||
|
||||
#define TYPE_211X 0 /* 2114, 2115, 2116 */
|
||||
#define TYPE_2100 1 /* 2100A, 2100S */
|
||||
#define TYPE_21MX 2 /* 21MX-M, 21MX-E, 21MX-F */
|
||||
#define TYPE_1000A 3 /* A600, A700, A900, A990 */
|
||||
#define FAMILY_21XX (0 << CPU_V_FAMILY)
|
||||
#define FAMILY_1000 (1 << CPU_V_FAMILY)
|
||||
|
||||
#define CPU_2116 (TYPE_211X << CPU_V_TYPE | 0)
|
||||
#define CPU_2100 (TYPE_2100 << CPU_V_TYPE | 0)
|
||||
#define CPU_21MX_M (TYPE_21MX << CPU_V_TYPE | 0)
|
||||
#define CPU_21MX_E (TYPE_21MX << CPU_V_TYPE | 1)
|
||||
#define TYPE_211X (0 << CPU_V_TYPE) /* 2114, 2115, 2116 */
|
||||
#define TYPE_2100 (1 << CPU_V_TYPE) /* 2100A, 2100S */
|
||||
#define TYPE_1000MEF (0 << CPU_V_TYPE) /* 1000-M, 1000-E, 1000-F */
|
||||
#define TYPE_1000AL (1 << CPU_V_TYPE) /* 1000-L, A600, A700, A900, A990 */
|
||||
|
||||
#define SERIES_16 (0 << CPU_V_SERIES) /* 211X */
|
||||
#define SERIES_15 (1 << CPU_V_SERIES) /* 211X */
|
||||
#define SERIES_14 (2 << CPU_V_SERIES) /* 211X */
|
||||
#define SERIES_00 (0 << CPU_V_SERIES) /* 2100 */
|
||||
#define SERIES_M (0 << CPU_V_SERIES) /* 1000 */
|
||||
#define SERIES_E (1 << CPU_V_SERIES) /* 1000 */
|
||||
#define SERIES_F (2 << CPU_V_SERIES) /* 1000 */
|
||||
|
||||
/* CPU unit flags */
|
||||
|
||||
#define UNIT_M_CPU 017 /* CPU model mask [3:0] */
|
||||
#define UNIT_M_TYPE 014 /* CPU type mask [3:2] */
|
||||
#define UNIT_M_FAMILY 010 /* CPU family mask [3:3] */
|
||||
|
||||
#define UNIT_V_CPU (UNIT_V_UF + 0) /* CPU model bits 0-3 */
|
||||
#define UNIT_M_CPU 017 /* CPU model mask */
|
||||
#define UNIT_M_TYPE 014 /* CPU type mask */
|
||||
#define UNIT_V_EAU (UNIT_V_UF + 4) /* EAU installed */
|
||||
#define UNIT_V_FP (UNIT_V_UF + 5) /* FP installed */
|
||||
#define UNIT_V_IOP (UNIT_V_UF + 6) /* IOP installed */
|
||||
#define UNIT_V_DMS (UNIT_V_UF + 7) /* DMS installed */
|
||||
#define UNIT_V_FFP (UNIT_V_UF + 8) /* FFP installed */
|
||||
#define UNIT_V_DBI (UNIT_V_UF + 9) /* DBI installed */
|
||||
#define UNIT_V_EMA (UNIT_V_UF + 10) /* RTE-4 EMA installed */
|
||||
#define UNIT_V_VMAOS (UNIT_V_UF + 11) /* RTE-6 VMA/OS installed */
|
||||
/* Future microcode expansion; reuse flags bottom-up if needed */
|
||||
#define UNIT_V_VIS (UNIT_V_UF + 12) /* VIS installed */
|
||||
#define UNIT_V_DS (UNIT_V_UF + 13) /* DS installed */
|
||||
#define UNIT_V_SIGNAL (UNIT_V_UF + 14) /* SIGNAL/1000 installed */
|
||||
|
||||
#define UNIT_CPU_MASK (UNIT_M_CPU << UNIT_V_CPU)
|
||||
#define UNIT_2116 (CPU_2116 << UNIT_V_CPU)
|
||||
#define UNIT_2100 (CPU_2100 << UNIT_V_CPU)
|
||||
#define UNIT_21MX_M (CPU_21MX_M << UNIT_V_CPU)
|
||||
#define UNIT_21MX_E (CPU_21MX_E << UNIT_V_CPU)
|
||||
/* Unit models */
|
||||
|
||||
#define UNIT_MODEL_MASK (UNIT_M_CPU << UNIT_V_CPU)
|
||||
|
||||
#define UNIT_2116 ((FAMILY_21XX | TYPE_211X | SERIES_16) << UNIT_V_CPU)
|
||||
#define UNIT_2115 ((FAMILY_21XX | TYPE_211X | SERIES_15) << UNIT_V_CPU)
|
||||
#define UNIT_2114 ((FAMILY_21XX | TYPE_211X | SERIES_14) << UNIT_V_CPU)
|
||||
#define UNIT_2100 ((FAMILY_21XX | TYPE_2100 | SERIES_00) << UNIT_V_CPU)
|
||||
#define UNIT_1000_M ((FAMILY_1000 | TYPE_1000MEF | SERIES_M) << UNIT_V_CPU)
|
||||
#define UNIT_1000_E ((FAMILY_1000 | TYPE_1000MEF | SERIES_E) << UNIT_V_CPU)
|
||||
#define UNIT_1000_F ((FAMILY_1000 | TYPE_1000MEF | SERIES_F) << UNIT_V_CPU)
|
||||
|
||||
/* Unit types */
|
||||
|
||||
#define UNIT_TYPE_MASK (UNIT_M_TYPE << UNIT_V_CPU)
|
||||
#define UNIT_TYPE_211X ((TYPE_211X << CPU_V_TYPE) << UNIT_V_CPU)
|
||||
#define UNIT_TYPE_2100 ((TYPE_2100 << CPU_V_TYPE) << UNIT_V_CPU)
|
||||
#define UNIT_TYPE_21MX ((TYPE_21MX << CPU_V_TYPE) << UNIT_V_CPU)
|
||||
|
||||
#define UNIT_CPU_MODEL (cpu_unit.flags & UNIT_CPU_MASK)
|
||||
#define UNIT_TYPE_211X ((FAMILY_21XX | TYPE_211X) << UNIT_V_CPU)
|
||||
#define UNIT_TYPE_2100 ((FAMILY_21XX | TYPE_2100) << UNIT_V_CPU)
|
||||
#define UNIT_TYPE_1000 ((FAMILY_1000 | TYPE_1000MEF) << UNIT_V_CPU)
|
||||
|
||||
/* Unit families */
|
||||
|
||||
#define UNIT_FAMILY_MASK (UNIT_M_FAMILY << UNIT_V_CPU)
|
||||
|
||||
#define UNIT_FAMILY_21XX (FAMILY_21XX << UNIT_V_CPU)
|
||||
#define UNIT_FAMILY_1000 (FAMILY_1000 << UNIT_V_CPU)
|
||||
|
||||
/* Unit accessors */
|
||||
|
||||
#define UNIT_CPU_MODEL (cpu_unit.flags & UNIT_MODEL_MASK)
|
||||
#define UNIT_CPU_TYPE (cpu_unit.flags & UNIT_TYPE_MASK)
|
||||
#define CPU_TYPE (UNIT_CPU_TYPE >> (UNIT_V_CPU + CPU_V_TYPE))
|
||||
#define UNIT_CPU_FAMILY (cpu_unit.flags & UNIT_FAMILY_MASK)
|
||||
|
||||
#define CPU_MODEL_INDEX (UNIT_CPU_MODEL >> UNIT_V_CPU)
|
||||
|
||||
/* Unit features */
|
||||
|
||||
#define UNIT_EAU (1 << UNIT_V_EAU)
|
||||
#define UNIT_FP (1 << UNIT_V_FP)
|
||||
#define UNIT_IOP (1 << UNIT_V_IOP)
|
||||
#define UNIT_DMS (1 << UNIT_V_DMS)
|
||||
#define UNIT_FFP (1 << UNIT_V_FFP)
|
||||
#define UNIT_DBI (1 << UNIT_V_DBI)
|
||||
#define UNIT_EMA (1 << UNIT_V_EMA)
|
||||
#define UNIT_VMAOS (1 << UNIT_V_VMAOS)
|
||||
#define UNIT_VIS (1 << UNIT_V_VIS)
|
||||
#define UNIT_DS (1 << UNIT_V_DS)
|
||||
#define UNIT_SIGNAL (1 << UNIT_V_SIGNAL)
|
||||
|
||||
#define UNIT_OPTS (UNIT_EAU | UNIT_FP | UNIT_IOP | UNIT_DMS | UNIT_FFP)
|
||||
#define UNIT_EMA_VMA (UNIT_EMA | UNIT_VMAOS)
|
||||
|
||||
#define UNIT_OPTS (UNIT_EAU | UNIT_FP | UNIT_IOP | \
|
||||
UNIT_DMS | UNIT_FFP | UNIT_DBI | \
|
||||
UNIT_EMA | UNIT_VMAOS | \
|
||||
UNIT_VIS | UNIT_DS | UNIT_SIGNAL)
|
||||
|
||||
/* "Pseudo-option" flags used only for option testing; never set into UNIT structure. */
|
||||
|
||||
#define UNIT_V_PFAIL (UNIT_V_UF - 1) /* Power fail installed */
|
||||
#define UNIT_V_DMA (UNIT_V_UF - 2) /* DMA installed */
|
||||
#define UNIT_V_MP (UNIT_V_UF - 3) /* Memory protect installed */
|
||||
|
||||
#define UNIT_PFAIL (1 << UNIT_V_PFAIL)
|
||||
#define UNIT_DMA (1 << UNIT_V_DMA)
|
||||
#define UNIT_MP (1 << UNIT_V_MP)
|
||||
|
||||
#define UNIT_NONE 0 /* no options */
|
||||
|
||||
|
||||
/* PC queue. */
|
||||
|
||||
#define PCQ_SIZE 64 /* must be 2**n */
|
||||
#define PCQ_MASK (PCQ_SIZE - 1)
|
||||
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = err_PC
|
||||
|
||||
/* CPU registers */
|
||||
|
||||
extern uint16 ABREG[2]; /* A/B regs (use AR/BR) */
|
||||
extern uint32 PC; /* P register */
|
||||
extern uint32 SR; /* S register */
|
||||
extern uint32 MR; /* M register */
|
||||
extern uint32 TR; /* T register */
|
||||
extern uint32 XR; /* X register */
|
||||
extern uint32 YR; /* Y register */
|
||||
extern uint32 E; /* E register */
|
||||
extern uint32 O; /* O register */
|
||||
|
||||
/* CPU state */
|
||||
|
||||
extern uint32 err_PC;
|
||||
extern uint32 dms_enb;
|
||||
extern uint32 dms_ump;
|
||||
extern uint32 dms_sr;
|
||||
extern uint32 dms_vr;
|
||||
extern uint32 mp_fence;
|
||||
extern uint32 iop_sp;
|
||||
extern uint32 ion_defer;
|
||||
extern uint16 pcq[PCQ_SIZE];
|
||||
extern uint32 pcq_p;
|
||||
extern uint32 stop_inst;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
/* CPU functions */
|
||||
|
||||
t_stat resolve (uint32 MA, uint32 *addr, uint32 irq);
|
||||
uint8 ReadB (uint32 addr);
|
||||
uint8 ReadBA (uint32 addr);
|
||||
uint16 ReadW (uint32 addr);
|
||||
uint16 ReadWA (uint32 addr);
|
||||
uint32 ReadF (uint32 addr);
|
||||
void WriteB (uint32 addr, uint32 dat);
|
||||
void WriteBA (uint32 addr, uint32 dat);
|
||||
void WriteW (uint32 addr, uint32 dat);
|
||||
|
|
557
HP2100/hp2100_cpu0.c
Normal file
557
HP2100/hp2100_cpu0.c
Normal file
|
@ -0,0 +1,557 @@
|
|||
/* hp2100_cpu0.c: HP 1000 unimplemented instruction set stubs
|
||||
|
||||
Copyright (c) 2006, J. David Bryan
|
||||
|
||||
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
|
||||
THE AUTHOR 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 the author shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
CPU0 Unimplemented firmware option instructions
|
||||
|
||||
01-Dec-06 JDB Removed and implemented "cpu_sis".
|
||||
26-Sep-06 JDB Created
|
||||
|
||||
This file contains template simulations for the firmware options that have
|
||||
not yet been implemented. When a given firmware option is implemented, it
|
||||
should be moved out of this file and into another (or its own, depending on
|
||||
complexity).
|
||||
|
||||
Primary references:
|
||||
- HP 1000 M/E/F-Series Computers Technical Reference Handbook
|
||||
(5955-0282, Mar-1980)
|
||||
- HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
|
||||
(92851-90001, Mar-1981)
|
||||
- Macro/1000 Reference Manual (92059-90001, Dec-1992)
|
||||
|
||||
Additional references are listed with the associated firmware
|
||||
implementations, as are the HP option model numbers pertaining to the
|
||||
applicable CPUs.
|
||||
*/
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
#include "hp2100_cpu1.h"
|
||||
|
||||
|
||||
t_stat cpu_rte_ema (uint32 IR, uint32 intrq); /* RTE-4 EMA */
|
||||
t_stat cpu_rte_vma (uint32 IR, uint32 intrq); /* RTE-6 VMA */
|
||||
t_stat cpu_rte_os (uint32 IR, uint32 intrq, uint32 iotrap); /* RTE-6 OS */
|
||||
t_stat cpu_ds (uint32 IR, uint32 intrq); /* Distributed System */
|
||||
t_stat cpu_vis (uint32 IR, uint32 intrq); /* Vector Instruction Set */
|
||||
t_stat cpu_signal (uint32 IR, uint32 intrq); /* SIGNAL/1000 Instructions */
|
||||
|
||||
|
||||
/* RTE-IV Extended Memory Area Instructions
|
||||
|
||||
The RTE-IV operating system (HP product number 92067A) introduced the
|
||||
Extended Memory Area (EMA) instructions. EMA provided a mappable data area
|
||||
up to one megaword in size. These three instructions accelerated data
|
||||
accesses to variables stored in EMA partitions. Support was limited to
|
||||
E/F-Series machines; M-Series machines used software equivalents.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A N/A 92067A 92067A
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Instr. 1000-E/F Description
|
||||
------ -------- ----------------------------------------------
|
||||
.EMIO 105240 EMA I/O
|
||||
MMAP 105241 Map physical to logical memory
|
||||
[test] 105242 [self test]
|
||||
.EMAP 105257 Resolve array element address
|
||||
|
||||
Notes:
|
||||
|
||||
1. RTE-IV EMA and RTE-6 VMA instructions share the same address space, so a
|
||||
given machine can run one or the other, but not both.
|
||||
|
||||
Additional references:
|
||||
- RTE-IVB Programmer's Reference Manual (92068-90004, Dec-1983).
|
||||
- RTE-IVB Technical Specifications (92068-90013, Jan-1980).
|
||||
*/
|
||||
|
||||
static const OP_PAT op_ema[16] = {
|
||||
OP_A, OP_AKK, OP_N, OP_N, /* .EMIO MMAP [test] --- */
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_A /* --- --- --- .EMAP */
|
||||
};
|
||||
|
||||
t_stat cpu_rte_ema (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
uint32 entry;
|
||||
|
||||
if ((cpu_unit.flags & UNIT_EMA) == 0) /* EMA option installed? */
|
||||
return stop_inst;
|
||||
|
||||
entry = IR & 017; /* mask to entry point */
|
||||
|
||||
if (op_ema[entry] != OP_N)
|
||||
if (reason = cpu_ops (op_ema[entry], op, intrq)) /* get instruction operands */
|
||||
return reason;
|
||||
|
||||
switch (entry) { /* decode IR<3:0> */
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
|
||||
/* RTE-6/VM Virtual Memory Area Instructions
|
||||
|
||||
RTE-6/VM (product number 92084A) introduced Virtual Memory Area (VMA)
|
||||
instructions -- a superset of the RTE-IV EMA instructions. Different
|
||||
microcode was supplied with the operating system that replaced the microcode
|
||||
used with RTE-IV. Microcode was limited to the E/F-Series, and the M-Series
|
||||
used software equivalents.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A N/A 92084A 92084A
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Instr. 1000-E/F Description
|
||||
------ -------- ----------------------------------------------
|
||||
.PMAP 105240 Map VMA page into map register
|
||||
$LOC 105241 Load on call
|
||||
[test] 105242 [self test]
|
||||
.SWP 105243 [Swap A and B registers]
|
||||
.STAS 105244 [STA B; LDA SP]
|
||||
.LDAS 105245 [LDA SP]
|
||||
.MYAD 105246 [NOP in microcode]
|
||||
.UMPY 105247 [Unsigned multiply and add]
|
||||
|
||||
.IMAP 105250 Integer element resolve address and map
|
||||
.IMAR 105251 Integer element resolve address
|
||||
.JMAP 105252 Double integer element resolve address and map
|
||||
.JMAR 105253 Double integer element resolve address
|
||||
.LPXR 105254 Map pointer in P+1 plus offset in P+2
|
||||
.LPX 105255 Map pointer in A/B plus offset in P+1
|
||||
.LBPR 105256 Map pointer in P+1
|
||||
.LBP 105257 Map pointer in A/B registers
|
||||
|
||||
Notes:
|
||||
|
||||
1. The opcodes 105243-247 are undocumented and do not appear to be used in
|
||||
any HP software.
|
||||
|
||||
2. The opcode list in the CE Handbook incorrectly shows 105246 as ".MYAD -
|
||||
multiply 2 signed integers." The microcode listing shows that this
|
||||
instruction was deleted, and the opcode is now a NOP.
|
||||
|
||||
3. RTE-IV EMA and RTE-6 VMA instructions shared the same address space, so
|
||||
a given machine could run one or the other, but not both.
|
||||
|
||||
Additional references:
|
||||
- RTE-6/VM VMA/EMA Microcode Source (92084-18828, revision 3).
|
||||
- RTE-6/VM Technical Specifications (92084-90015, Apr-1983).
|
||||
- M/E/F-Series Computer Systems CE Handbook (5950-3767, Jul-1984).
|
||||
*/
|
||||
|
||||
static const OP_PAT op_vma[16] = {
|
||||
OP_N, OP_KKKAKK, OP_N, OP_N, /* .PMAP $LOC [test] .SWAP */
|
||||
OP_N, OP_N, OP_N, OP_K, /* .STAS .LDAS .MYAD .UMPY */
|
||||
OP_A, OP_A, OP_A, OP_A, /* .IMAP .IMAR .JMAP .JMAR */
|
||||
OP_FF, OP_F, OP_F, OP_N /* .LPXR .LPX .LBPR .LBP */
|
||||
};
|
||||
|
||||
t_stat cpu_rte_vma (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
uint32 entry;
|
||||
|
||||
if ((cpu_unit.flags & UNIT_VMAOS) == 0) /* VMA/OS option installed? */
|
||||
return cpu_rte_ema (IR, intrq); /* try EMA */
|
||||
|
||||
entry = IR & 017; /* mask to entry point */
|
||||
|
||||
if (op_vma[entry] != OP_N)
|
||||
if (reason = cpu_ops (op_vma[entry], op, intrq)) /* get instruction operands */
|
||||
return reason;
|
||||
|
||||
switch (entry) { /* decode IR<3:0> */
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
|
||||
/* RTE-6/VM Operating System Instructions
|
||||
|
||||
The OS instructions were added to acccelerate certain time-consuming
|
||||
operations of the RTE-6/VM operating system, HP product number 92084A.
|
||||
Microcode was available for the E- and F-Series; the M-Series used software
|
||||
equivalents.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A N/A 92084A 92084A
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Instr. 1000-E/F Description
|
||||
------ -------- ----------------------------------------------
|
||||
$LIBR 105340 Enter privileged/reentrant library routine
|
||||
$LIBX 105341 Exit privileged/reentrant library routine
|
||||
.TICK 105342 TBG tick interrupt handler
|
||||
.TNAM 105343 Find ID segment that matches name
|
||||
.STIO 105344 Configure I/O instructions
|
||||
.FNW 105345 Find word with user increment
|
||||
.IRT 105346 Interrupt return processing
|
||||
.LLS 105347 Linked list search
|
||||
|
||||
.SIP 105350 Skip if interrupt pending
|
||||
.YLD 105351 .SIP completion return point
|
||||
.CPM 105352 Compare words LT/EQ/GT
|
||||
.ETEQ 105353 Set up EQT pointers in base page
|
||||
.ENTN 105354 Transfer parameter addresses (utility)
|
||||
[test] 105355 [self test]
|
||||
.ENTC 105356 Transfer parameter addresses (priv/reent)
|
||||
.DSPI 105357 Set display indicator
|
||||
|
||||
Opcodes 105354-105357 are "dual use" instructions that take different
|
||||
actions, depending on whether they are executed from a trap cell during an
|
||||
interrupt. When executed from a trap cell, they have these actions:
|
||||
|
||||
Instr. 1000-E/F Description
|
||||
------ -------- ----------------------------------------------
|
||||
[dma] 105354 DCPC channel interrupt processing
|
||||
[dms] 105355 DMS/MP/PE interrupt processing
|
||||
[dev] 105356 Standard device interrupt processing
|
||||
[tbg] 105357 TBG interrupt processing
|
||||
|
||||
Notes:
|
||||
|
||||
1. The microcode differentiates between interrupt processing and normal
|
||||
execution of the "dual use" instructions by testing the CPU flag.
|
||||
Interrupt vectoring sets the flag; a normal instruction fetch clears it.
|
||||
Under simulation, interrupt vectoring is indicated by the value of the
|
||||
"iotrap" parameter.
|
||||
|
||||
2. The operand patterns for .ENTN and .ENTC normally would be coded as
|
||||
"OP_A", as each takes a single address as a parameter. However, because
|
||||
they might also be executed from a trap cell, we cannot assume that P+1
|
||||
is an address, or we might cause a DM abort when trying to access
|
||||
memory. Therefore, "OP_A" handling is done within each routine, once
|
||||
the type of use is determined.
|
||||
|
||||
Additional references:
|
||||
- RTE-6/VM O/S Microcode Source (92084-18831, revision 6).
|
||||
- RTE-6/VM Technical Specifications (92084-90015, Apr-1983).
|
||||
*/
|
||||
|
||||
static const OP_PAT op_os[16] = {
|
||||
OP_A, OP_A, OP_N, OP_N, /* $LIBR $LIBX .TICK .TNAM */
|
||||
OP_A, OP_K, OP_A, OP_KK, /* .STIO .FNW .IRT .LLS */
|
||||
OP_N, OP_CC, OP_KK, OP_N, /* .SIP .YLD .CPM .ETEQ */
|
||||
OP_N, OP_N, OP_N, OP_N /* .ENTN [test] .ENTC .DSPI */
|
||||
};
|
||||
|
||||
t_stat cpu_rte_os (uint32 IR, uint32 intrq, uint32 iotrap)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
uint32 entry;
|
||||
|
||||
if ((cpu_unit.flags & UNIT_VMAOS) == 0) /* VMA/OS option installed? */
|
||||
return stop_inst;
|
||||
|
||||
entry = IR & 017; /* mask to entry point */
|
||||
|
||||
if (op_os[entry] != OP_N)
|
||||
if (reason = cpu_ops (op_os[entry], op, intrq)) /* get instruction operands */
|
||||
return reason;
|
||||
|
||||
switch (entry) { /* decode IR<3:0> */
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
|
||||
/* Distributed System
|
||||
|
||||
Distributed System firmware was provided with the HP 91740A DS/1000 product
|
||||
for use with the HP 12771A (12665A) Serial Interface and 12773A Modem
|
||||
Interface system interconnection kits. Firmware permitted high-speed
|
||||
transfers with minimum impact to the processor. The advent of the
|
||||
"intelligent" 12794A and 12825A HDLC cards, the 12793A and 12834A Bisync
|
||||
cards, and the 91750A DS-1000/IV software obviated the need for CPU firmware,
|
||||
as essentially the firmware was moved onto the I/O cards.
|
||||
|
||||
Primary documentation for the DS instructions has not been located. However,
|
||||
examination of the DS/1000 sources reveals that two instruction were used by
|
||||
the DVA65 Serial Interface driver (91740-18071) and placed in the trap cells
|
||||
of the communications interfaces. Presumably they handled interrupts from
|
||||
the cards.
|
||||
|
||||
Implementation of the DS instructions will also require simulation of the
|
||||
12665A Hardwired Serial Data Interface Card and the 12620A RTE Privileged
|
||||
Interrupt Fence. These are required for DS/1000.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A 91740A 91740B 91740B
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Instr. 1000-M 1000-E/F Description
|
||||
------ ------ -------- ----------------------------------------------
|
||||
105520 105300 "Open loop" (trap cell handler)
|
||||
105521 105301 "Closed loop" (trap cell handler)
|
||||
105522 105302 [unknown]
|
||||
[test] 105524 105304 [self test]
|
||||
|
||||
Notes:
|
||||
|
||||
1. The E/F-Series opcodes were moved from 105340-357 to 105300-317 at
|
||||
revision 1813.
|
||||
|
||||
2. DS/1000 ROM data are available from Bitsavers.
|
||||
|
||||
Additional references (documents unavailable):
|
||||
- HP 91740A M-Series Distributed System (DS/1000) Firmware Installation
|
||||
Manual (91740-90007).
|
||||
- HP 91740B Distributed System (DS/1000) Firmware Installation Manual
|
||||
(91740-90009).
|
||||
*/
|
||||
|
||||
static const OP_PAT op_ds[16] = {
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N /* --- --- --- --- */
|
||||
};
|
||||
|
||||
t_stat cpu_ds (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
uint32 entry;
|
||||
|
||||
if ((cpu_unit.flags & UNIT_DS) == 0) /* DS option installed? */
|
||||
return stop_inst;
|
||||
|
||||
entry = IR & 017; /* mask to entry point */
|
||||
|
||||
if (op_ds[entry] != OP_N)
|
||||
if (reason = cpu_ops (op_ds[entry], op, intrq)) /* get instruction operands */
|
||||
return reason;
|
||||
|
||||
switch (entry) { /* decode IR<3:0> */
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
|
||||
/* Vector Instruction Set
|
||||
|
||||
The VIS provides instructions that operate on one-dimensional arrays of
|
||||
floating-point values. Both single- and double-precision operations are
|
||||
supported.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A N/A N/A 12824A
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Single-Precision Double-Precision
|
||||
Instr. Opcode Subcod Instr. Opcode Subcod Description
|
||||
------ ------ ------ ------ ------ ------ -----------------------------
|
||||
VADD 101460 000000 DVADD 105460 004002 Vector add
|
||||
VSUB 101460 000020 DVSUB 105460 004022 Vector subtract
|
||||
VMPY 101460 000040 DVMPY 105460 004042 Vector multiply
|
||||
VDIV 101460 000060 DVDIV 105460 004062 Vector divide
|
||||
VSAD 101460 000400 DVSAD 105460 004402 Scalar-vector add
|
||||
VSSB 101460 000420 DVSSB 105460 004422 Scalar-vector subtract
|
||||
VSMY 101460 000440 DVSMY 105460 004442 Scalar-vector multiply
|
||||
VSDV 101460 000460 DVSDV 105460 004462 Scalar-vector divide
|
||||
VPIV 101461 0xxxxx DVPIV 105461 0xxxxx Vector pivot
|
||||
VABS 101462 0xxxxx DVABS 105462 0xxxxx Vector absolute value
|
||||
VSUM 101463 0xxxxx DVSUM 105463 0xxxxx Vector sum
|
||||
VNRM 101464 0xxxxx DVNRM 105464 0xxxxx Vector norm
|
||||
VDOT 101465 0xxxxx DVDOT 105465 0xxxxx Vector dot product
|
||||
VMAX 101466 0xxxxx DVMAX 105466 0xxxxx Vector maximum value
|
||||
VMAB 101467 0xxxxx DVMAB 105467 0xxxxx Vector maximum absolute value
|
||||
VMIN 101470 0xxxxx DVMIN 105470 0xxxxx Vector minimum value
|
||||
VMIB 101471 0xxxxx DVMIB 105471 0xxxxx Vector minimum absolute value
|
||||
VMOV 101472 0xxxxx DVMOV 105472 0xxxxx Vector move
|
||||
VSWP 101473 0xxxxx DVSWP 105473 0xxxxx Vector swap
|
||||
.ERES 101474 -- -- -- -- Resolve array element address
|
||||
.ESEG 101475 -- -- -- -- Load MSEG maps
|
||||
.VSET 101476 -- -- -- -- Vector setup
|
||||
[test] -- -- -- 105477 -- [self test]
|
||||
|
||||
Instructions use IR bit 11 to select single- or double-precision format. The
|
||||
double-precision instruction names begin with "D" (e.g., DVADD vs. VADD).
|
||||
Most VIS instructions are two words in length, with a sub-opcode immediately
|
||||
following the primary opcode.
|
||||
|
||||
Notes:
|
||||
|
||||
1. The .VECT (101460) and .DVCT (105460) opcodes preface a single- or
|
||||
double-precision arithmetic operation that is determined by the
|
||||
sub-opcode value. The remainder of the dual-precision sub-opcode values
|
||||
are "don't care," except for requiring a zero in bit 15.
|
||||
|
||||
2. The VIS uses the hardware FPP of the F-Series. FPP malfunctions are
|
||||
detected by the VIS firmware and are indicated by a memory-protect
|
||||
violation and setting the overflow flag. Under simulation,
|
||||
malfunctions cannot occur.
|
||||
|
||||
3. VIS ROM data are available from Bitsavers.
|
||||
|
||||
Additional references:
|
||||
- 12824A Vector Instruction Set User's Manual (12824-90001, Jun-1979).
|
||||
*/
|
||||
|
||||
static const OP_PAT op_vis[16] = {
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N /* --- --- --- --- */
|
||||
};
|
||||
|
||||
t_stat cpu_vis (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
uint32 entry;
|
||||
|
||||
if ((cpu_unit.flags & UNIT_VIS) == 0) /* VIS option installed? */
|
||||
return stop_inst;
|
||||
|
||||
entry = IR & 017; /* mask to entry point */
|
||||
|
||||
if (op_vis[entry] != OP_N)
|
||||
if (reason = cpu_ops (op_vis[entry], op, intrq)) /* get instruction operands */
|
||||
return reason;
|
||||
|
||||
switch (entry) { /* decode IR<3:0> */
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
|
||||
/* SIGNAL/1000 Instructions
|
||||
|
||||
The SIGNAL/1000 instructions provide fast Fourier transforms and complex
|
||||
arithmetic. They utilize the F-Series floating-point processor and the
|
||||
Vector Instruction Set.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A N/A N/A 92835A
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Instr. 1000-F Description
|
||||
------ ------ ----------------------------------------------
|
||||
BITRV 105600 Bit reversal
|
||||
BTRFY 105601 Butterfly algorithm
|
||||
UNSCR 105602 Unscramble for phasor MPY
|
||||
PRSCR 105603 Unscramble for phasor MPY
|
||||
BITR1 105604 Swap two elements in array (alternate format)
|
||||
BTRF1 105605 Butterfly algorithm (alternate format)
|
||||
.CADD 105606 Complex number addition
|
||||
.CSUB 105607 Complex number subtraction
|
||||
.CMPY 105610 Complex number multiplication
|
||||
.CDIV 105611 Complex number division
|
||||
CONJG 105612 Complex conjugate
|
||||
..CCM 105613 Complex complement
|
||||
AIMAG 105614 Return imaginary part
|
||||
CMPLX 105615 Form complex number
|
||||
[nop] 105616 [no operation]
|
||||
[test] 105617 [self test]
|
||||
|
||||
Notes:
|
||||
|
||||
1. SIGNAL/1000 ROM data are available from Bitsavers.
|
||||
|
||||
Additional references (documents unavailable):
|
||||
- HP Signal/1000 User Reference and Installation Manual (92835-90002).
|
||||
*/
|
||||
|
||||
static const OP_PAT op_signal[16] = {
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N, /* --- --- --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N /* --- --- --- --- */
|
||||
};
|
||||
|
||||
t_stat cpu_signal (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
uint32 entry;
|
||||
|
||||
if ((cpu_unit.flags & UNIT_SIGNAL) == 0) /* SIGNAL option installed? */
|
||||
return stop_inst;
|
||||
|
||||
entry = IR & 017; /* mask to entry point */
|
||||
|
||||
if (op_signal[entry] != OP_N)
|
||||
if (reason = cpu_ops (op_signal[entry], op, intrq)) /* get instruction operands */
|
||||
return reason;
|
||||
|
||||
switch (entry) { /* decode IR<3:0> */
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
1906
HP2100/hp2100_cpu1.c
1906
HP2100/hp2100_cpu1.c
File diff suppressed because it is too large
Load diff
215
HP2100/hp2100_cpu1.h
Normal file
215
HP2100/hp2100_cpu1.h
Normal file
|
@ -0,0 +1,215 @@
|
|||
/* hp2100_cpu1.h: HP 2100/1000 firmware dispatcher definitions
|
||||
|
||||
Copyright (c) 2006, J. David Bryan
|
||||
|
||||
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
|
||||
THE AUTHOR 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 the author shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
16-Oct-06 JDB Generalized operands for F-Series FP types
|
||||
26-Sep-06 JDB Split from hp2100_cpu1.c
|
||||
*/
|
||||
|
||||
#ifndef _HP2100_CPU1_H_
|
||||
#define _HP2100_CPU1_H_
|
||||
|
||||
|
||||
/* Operand processing encoding. */
|
||||
|
||||
/* Base operand types. Note that all address encodings must be grouped together
|
||||
after OP_ADR. */
|
||||
|
||||
#define OP_NUL 0 /* no operand */
|
||||
#define OP_IAR 1 /* 1-word int in A reg */
|
||||
#define OP_JAB 2 /* 2-word int in A/B regs */
|
||||
#define OP_FAB 3 /* 2-word FP const in A/B regs */
|
||||
#define OP_CON 4 /* inline 1-word constant */
|
||||
#define OP_VAR 5 /* inline 1-word variable */
|
||||
|
||||
#define OP_ADR 6 /* inline address */
|
||||
#define OP_ADK 7 /* addr of 1-word int const */
|
||||
#define OP_ADD 8 /* addr of 2-word int const */
|
||||
#define OP_ADF 9 /* addr of 2-word FP const */
|
||||
#define OP_ADX 10 /* addr of 3-word FP const */
|
||||
#define OP_ADT 11 /* addr of 4-word FP const */
|
||||
#define OP_ADE 12 /* addr of 5-word FP const */
|
||||
|
||||
#define OP_N_FLAGS 4 /* number of bits needed for flags */
|
||||
#define OP_M_FLAGS ((1 << OP_N_FLAGS) - 1) /* mask for flag bits */
|
||||
|
||||
#define OP_N_F (8 * sizeof (uint32) / OP_N_FLAGS) /* max number of op fields */
|
||||
|
||||
#define OP_V_F1 (0 * OP_N_FLAGS) /* 1st operand field */
|
||||
#define OP_V_F2 (1 * OP_N_FLAGS) /* 2nd operand field */
|
||||
#define OP_V_F3 (2 * OP_N_FLAGS) /* 3rd operand field */
|
||||
#define OP_V_F4 (3 * OP_N_FLAGS) /* 4th operand field */
|
||||
#define OP_V_F5 (4 * OP_N_FLAGS) /* 5th operand field */
|
||||
#define OP_V_F6 (5 * OP_N_FLAGS) /* 6th operand field */
|
||||
#define OP_V_F7 (6 * OP_N_FLAGS) /* 7th operand field */
|
||||
#define OP_V_F8 (7 * OP_N_FLAGS) /* 8th operand field */
|
||||
|
||||
/* Operand processing patterns. */
|
||||
|
||||
#define OP_N (OP_NUL << OP_V_F1)
|
||||
#define OP_I (OP_IAR << OP_V_F1)
|
||||
#define OP_J (OP_JAB << OP_V_F1)
|
||||
#define OP_R (OP_FAB << OP_V_F1)
|
||||
#define OP_C (OP_CON << OP_V_F1)
|
||||
#define OP_V (OP_VAR << OP_V_F1)
|
||||
#define OP_A (OP_ADR << OP_V_F1)
|
||||
#define OP_K (OP_ADK << OP_V_F1)
|
||||
#define OP_D (OP_ADD << OP_V_F1)
|
||||
#define OP_F (OP_ADF << OP_V_F1)
|
||||
#define OP_X (OP_ADX << OP_V_F1)
|
||||
#define OP_T (OP_ADT << OP_V_F1)
|
||||
#define OP_E (OP_ADE << OP_V_F1)
|
||||
|
||||
#define OP_IA ((OP_IAR << OP_V_F1) | (OP_ADR << OP_V_F2))
|
||||
#define OP_JA ((OP_JAB << OP_V_F1) | (OP_ADR << OP_V_F2))
|
||||
#define OP_JD ((OP_JAB << OP_V_F1) | (OP_ADD << OP_V_F2))
|
||||
#define OP_RC ((OP_FAB << OP_V_F1) | (OP_CON << OP_V_F2))
|
||||
#define OP_RK ((OP_FAB << OP_V_F1) | (OP_ADK << OP_V_F2))
|
||||
#define OP_RF ((OP_FAB << OP_V_F1) | (OP_ADF << OP_V_F2))
|
||||
#define OP_CC ((OP_CON << OP_V_F1) | (OP_CON << OP_V_F2))
|
||||
#define OP_CV ((OP_CON << OP_V_F1) | (OP_VAR << OP_V_F2))
|
||||
#define OP_AC ((OP_ADR << OP_V_F1) | (OP_CON << OP_V_F2))
|
||||
#define OP_AA ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2))
|
||||
#define OP_AK ((OP_ADR << OP_V_F1) | (OP_ADK << OP_V_F2))
|
||||
#define OP_AX ((OP_ADR << OP_V_F1) | (OP_ADX << OP_V_F2))
|
||||
#define OP_AT ((OP_ADR << OP_V_F1) | (OP_ADT << OP_V_F2))
|
||||
#define OP_KV ((OP_ADK << OP_V_F1) | (OP_VAR << OP_V_F2))
|
||||
#define OP_KA ((OP_ADK << OP_V_F1) | (OP_ADR << OP_V_F2))
|
||||
#define OP_KK ((OP_ADK << OP_V_F1) | (OP_ADK << OP_V_F2))
|
||||
#define OP_FF ((OP_ADF << OP_V_F1) | (OP_ADF << OP_V_F2))
|
||||
|
||||
#define OP_IIF ((OP_IAR << OP_V_F1) | (OP_IAR << OP_V_F2) | \
|
||||
(OP_ADF << OP_V_F3))
|
||||
|
||||
#define OP_IAT ((OP_IAR << OP_V_F1) | (OP_ADR << OP_V_F2) | \
|
||||
(OP_ADT << OP_V_F3))
|
||||
|
||||
#define OP_CVA ((OP_CON << OP_V_F1) | (OP_VAR << OP_V_F2) | \
|
||||
(OP_ADR << OP_V_F3))
|
||||
|
||||
#define OP_AAF ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2) | \
|
||||
(OP_ADF << OP_V_F3))
|
||||
|
||||
#define OP_AAX ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2) | \
|
||||
(OP_ADX << OP_V_F3))
|
||||
|
||||
#define OP_AAT ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2) | \
|
||||
(OP_ADT << OP_V_F3))
|
||||
|
||||
#define OP_AKK ((OP_ADR << OP_V_F1) | (OP_ADK << OP_V_F2) | \
|
||||
(OP_ADK << OP_V_F3))
|
||||
|
||||
#define OP_AXX ((OP_ADR << OP_V_F1) | (OP_ADX << OP_V_F2) | \
|
||||
(OP_ADX << OP_V_F3))
|
||||
|
||||
#define OP_ATT ((OP_ADR << OP_V_F1) | (OP_ADT << OP_V_F2) | \
|
||||
(OP_ADT << OP_V_F3))
|
||||
|
||||
#define OP_AEE ((OP_ADR << OP_V_F1) | (OP_ADE << OP_V_F2) | \
|
||||
(OP_ADE << OP_V_F3))
|
||||
|
||||
#define OP_AAXX ((OP_ADR << OP_V_F1) | (OP_ADR << OP_V_F2) | \
|
||||
(OP_ADX << OP_V_F3) | (OP_ADX << OP_V_F4))
|
||||
|
||||
#define OP_KKKK ((OP_ADK << OP_V_F1) | (OP_ADK << OP_V_F2) | \
|
||||
(OP_ADK << OP_V_F3) | (OP_ADK << OP_V_F4))
|
||||
|
||||
#define OP_CATAKK ((OP_CON << OP_V_F1) | (OP_ADR << OP_V_F2) | \
|
||||
(OP_ADT << OP_V_F3) | (OP_ADR << OP_V_F4) | \
|
||||
(OP_ADK << OP_V_F5) | (OP_ADK << OP_V_F6))
|
||||
|
||||
#define OP_KKKAKK ((OP_ADK << OP_V_F1) | (OP_ADK << OP_V_F2) | \
|
||||
(OP_ADK << OP_V_F3) | (OP_ADR << OP_V_F4) | \
|
||||
(OP_ADK << OP_V_F5) | (OP_ADK << OP_V_F6))
|
||||
|
||||
#define OP_CCACACCA ((OP_CON << OP_V_F1) | (OP_CON << OP_V_F2) | \
|
||||
(OP_ADR << OP_V_F3) | (OP_CON << OP_V_F4) | \
|
||||
(OP_ADR << OP_V_F5) | (OP_CON << OP_V_F6) | \
|
||||
(OP_CON << OP_V_F7) | (OP_ADR << OP_V_F8))
|
||||
|
||||
|
||||
/* Operand precisions (compatible with F-Series FPP):
|
||||
|
||||
- S = 1-word integer
|
||||
- D = 2-word integer
|
||||
- F = 2-word single-precision floating-point
|
||||
- X = 3-word extended-precision floating-point
|
||||
- T = 4-word double-precision floating-point
|
||||
- E = 5-word expanded-exponent floating-point
|
||||
- A = null operand (operand is in FPP accumulator)
|
||||
|
||||
5-word floating-point numbers are supported by the F-Series Floating-Point
|
||||
Processor hardware, but the instruction codes are not documented.
|
||||
|
||||
Note that ordering is important, as we depend on the "fp" type codes to
|
||||
reflect the number of words needed.
|
||||
*/
|
||||
|
||||
typedef enum { in_s, in_d, fp_f, fp_x, fp_t, fp_e, fp_a } OPSIZE;
|
||||
|
||||
|
||||
/* Conversion from operand size to word count. */
|
||||
|
||||
#define TO_COUNT(s) ((s == fp_a) ? 0 : s + (s < fp_f))
|
||||
|
||||
|
||||
/* HP in-memory representation of a packed floating-point number.
|
||||
Actual value will use two, three, four, or five words, as needed. */
|
||||
|
||||
typedef uint16 FPK[5];
|
||||
|
||||
|
||||
/* Operand processing types.
|
||||
|
||||
NOTE: Microsoft VC++ 6.0 does not support the C99 standard, so we cannot
|
||||
initialize unions by arbitrary variant ("designated initializers").
|
||||
Therefore, we follow the C90 form of initializing via the first named
|
||||
variant. The FPK variant must appear first in the OP structure, as we define
|
||||
a number of FPK constants in other modules.
|
||||
*/
|
||||
|
||||
typedef union { /* general operand */
|
||||
FPK fpk; /* floating-point value */
|
||||
uint16 word; /* 16-bit integer */
|
||||
uint32 dword; /* 32-bit integer */
|
||||
} OP;
|
||||
|
||||
typedef OP OPS[OP_N_F]; /* operand array */
|
||||
|
||||
typedef uint32 OP_PAT; /* operand pattern */
|
||||
|
||||
|
||||
/* Microcode dispatcher functions. */
|
||||
|
||||
t_stat cpu_eau (uint32 IR, uint32 intrq); /* EAU group simulator */
|
||||
t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap); /* UIG group 0 dispatcher */
|
||||
t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap); /* UIG group 1 dispatcher */
|
||||
|
||||
/* Microcode helper functions. */
|
||||
|
||||
OP ReadOp (uint32 va, OPSIZE precision); /* generalized operand read */
|
||||
void WriteOp (uint32 va, OP operand, OPSIZE precision); /* generalized operand write */
|
||||
t_stat cpu_ops (OP_PAT pattern, OPS op, uint32 irq); /* operand processor */
|
||||
|
||||
#endif
|
1125
HP2100/hp2100_cpu2.c
Normal file
1125
HP2100/hp2100_cpu2.c
Normal file
File diff suppressed because it is too large
Load diff
819
HP2100/hp2100_cpu3.c
Normal file
819
HP2100/hp2100_cpu3.c
Normal file
|
@ -0,0 +1,819 @@
|
|||
/* hp2100_cpu3.c: HP 2100/1000 FFP/DBI instructions
|
||||
|
||||
Copyright (c) 2005-2006, J. David Bryan
|
||||
|
||||
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
|
||||
THE AUTHOR 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 the author shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
CPU3 Fast FORTRAN and Double Integer instructions
|
||||
|
||||
16-Oct-06 JDB Calls FPP for extended-precision math
|
||||
12-Oct-06 JDB Altered DBLE, DDINT for F-Series FFP compatibility
|
||||
26-Sep-06 JDB Moved from hp2100_cpu1.c to simplify extensions
|
||||
09-Aug-06 JDB Added double-integer instruction set
|
||||
18-Feb-05 JDB Add 2100/21MX Fast FORTRAN Processor instructions
|
||||
|
||||
Primary references:
|
||||
- HP 1000 M/E/F-Series Computers Technical Reference Handbook
|
||||
(5955-0282, Mar-1980)
|
||||
- HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
|
||||
(92851-90001, Mar-1981)
|
||||
- Macro/1000 Reference Manual (92059-90001, Dec-1992)
|
||||
|
||||
Additional references are listed with the associated firmware
|
||||
implementations, as are the HP option model numbers pertaining to the
|
||||
applicable CPUs.
|
||||
*/
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
#include "hp2100_cpu1.h"
|
||||
|
||||
#if defined (HAVE_INT64) /* int64 support available */
|
||||
#include "hp2100_fp1.h"
|
||||
#else /* int64 support unavailable */
|
||||
#include "hp2100_fp.h"
|
||||
#endif /* end of int64 support */
|
||||
|
||||
|
||||
t_stat cpu_ffp (uint32 IR, uint32 intrq); /* Fast FORTRAN Processor */
|
||||
t_stat cpu_dbi (uint32 IR, uint32 intrq); /* Double-Integer instructions */
|
||||
|
||||
|
||||
/* Fast FORTRAN Processor.
|
||||
|
||||
The Fast FORTRAN Processor (FFP) is a set of FORTRAN language accelerators
|
||||
and extended-precision (three-word) floating point routines. Although the
|
||||
FFP is an option for the 2100 and later CPUs, each implements the FFP in a
|
||||
slightly different form.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A 12907A 12977B 13306B std
|
||||
|
||||
The instruction codes are mapped to routines as follows:
|
||||
|
||||
Instr. 2100 1000-M 1000-E 1000-F Instr. 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------ ------ ------ ------
|
||||
105200 -- [nop] [nop] [test] 105220 .XFER .XFER .XFER .XFER
|
||||
105201 DBLE DBLE DBLE DBLE 105221 .GOTO .GOTO .GOTO .GOTO
|
||||
105202 SNGL SNGL SNGL SNGL 105222 ..MAP ..MAP ..MAP ..MAP
|
||||
105203 .XMPY .XMPY .XMPY .DNG 105223 .ENTR .ENTR .ENTR .ENTR
|
||||
105204 .XDIV .XDIV .XDIV .DCO 105224 .ENTP .ENTP .ENTP .ENTP
|
||||
105205 .DFER .DFER .DFER .DFER 105225 -- .PWR2 .PWR2 .PWR2
|
||||
105206 -- .XPAK .XPAK .XPAK 105226 -- .FLUN .FLUN .FLUN
|
||||
105207 -- XADD XADD .BLE 105227 $SETP $SETP $SETP $SETP
|
||||
|
||||
105210 -- XSUB XSUB .DIN 105230 -- .PACK .PACK .PACK
|
||||
105211 -- XMPY XMPY .DDE 105231 -- -- .CFER .CFER
|
||||
105212 -- XDIV XDIV .DIS 105232 -- -- -- ..FCM
|
||||
105213 .XADD .XADD .XADD .DDS 105233 -- -- -- ..TCM
|
||||
105214 .XSUB .XSUB .XSUB .NGL 105234 -- -- -- --
|
||||
105215 -- .XCOM .XCOM .XCOM 105235 -- -- -- --
|
||||
105216 -- ..DCM ..DCM ..DCM 105236 -- -- -- --
|
||||
105217 -- DDINT DDINT DDINT 105237 -- -- -- --
|
||||
|
||||
The F-Series maps different instructions to several of the standard FFP
|
||||
opcodes. We first look for these and dispatch them appropriately before
|
||||
falling into the handler for the common instructions.
|
||||
|
||||
The math functions use the F-Series FPP for implementation. The FPP requires
|
||||
that the host compiler support 64-bit integers. Therefore, if 64-bit
|
||||
integers are not available, the math instructions of the FFP are disabled.
|
||||
We allow this partial implementation as an aid in running systems generated
|
||||
for the FFP. Most system programs did not use the math instructions, but
|
||||
almost all use .ENTR. Supporting the latter even on systems that do not
|
||||
support the former still allows such systems to boot.
|
||||
|
||||
Notes:
|
||||
|
||||
1. The "$SETP" instruction is sometimes listed as ".SETP" in the
|
||||
documentation.
|
||||
|
||||
2. Extended-precision arithmetic routines (e.g., .XMPY) exist on the
|
||||
1000-F, but they are assigned instruction codes in the single-precision
|
||||
floating-point module range. They are replaced by several double
|
||||
integer instructions, which we dispatch to the double integer handler.
|
||||
|
||||
3. The software implementation of ..MAP supports 1-, 2-, or 3-dimensional
|
||||
arrays, designated by setting A = -1, 0, and +1, respectively. The
|
||||
firmware implementation supports only 2- and 3-dimensional access.
|
||||
|
||||
4. The documentation for ..MAP for the 2100 FFP shows A = 0 or -1 for two
|
||||
or three dimensions, respectively, but the 1000 FFP shows A = 0 or +1.
|
||||
The firmware actually only checks the LSB of A.
|
||||
|
||||
5. The .DFER and .XFER implementations for the 2100 FFP return X+4 and Y+4
|
||||
in the A and B registers, whereas the 1000 FFP returns X+3 and Y+3.
|
||||
|
||||
6. The .XFER implementation for the 2100 FFP returns to P+2, whereas the
|
||||
1000 implementation returns to P+1.
|
||||
|
||||
7. The firmware implementations of DBLE, .BLE, and DDINT clear the overflow
|
||||
flag. The software implementations do not change overflow.
|
||||
|
||||
8. The M/E-Series FFP arithmetic instructions (.XADD, etc.) return negative
|
||||
infinity on negative overflow and positive infinity on positive
|
||||
overflow. The equivalent F-Series instructions return positive infinity
|
||||
on both.
|
||||
|
||||
Additional references:
|
||||
- DOS/RTE Relocatable Library Reference Manual (24998-90001, Oct-1981)
|
||||
- Implementing the HP 2100 Fast FORTRAN Processor (12907-90010, Nov-1974)
|
||||
*/
|
||||
|
||||
static const OP_PAT op_ffp_f[32] = { /* patterns for F-Series only */
|
||||
OP_N, OP_AAF, OP_AX, OP_N, /* [tst] DBLE SNGL .DNG */
|
||||
OP_N, OP_AA, OP_A, OP_AAF, /* .DCO .DFER .XPAK .BLE */
|
||||
OP_N, OP_N, OP_N, OP_N, /* .DIN .DDE .DIS .DDS */
|
||||
OP_AT, OP_A, OP_A, OP_AAX, /* .NGL .XCOM ..DCM DDINT */
|
||||
OP_N, OP_AK, OP_KKKK, OP_A, /* .XFER .GOTO ..MAP .ENTR */
|
||||
OP_A, OP_RK, OP_R, OP_K, /* .ENTP .PWR2 .FLUN $SETP */
|
||||
OP_RC, OP_AA, OP_R, OP_A, /* .PACK .CFER ..FCM ..TCM */
|
||||
OP_N, OP_N, OP_N, OP_N /* --- --- --- --- */
|
||||
};
|
||||
|
||||
static const OP_PAT op_ffp_e[32] = { /* patterns for 2100/M/E-Series */
|
||||
OP_N, OP_AAF, OP_AX, OP_AXX, /* [nop] DBLE SNGL .XMPY */
|
||||
OP_AXX, OP_AA, OP_A, OP_AAXX, /* .XDIV .DFER .XPAK XADD */
|
||||
OP_AAXX, OP_AAXX, OP_AAXX, OP_AXX, /* XSUB XMPY XDIV .XADD */
|
||||
OP_AXX, OP_A, OP_A, OP_AAX, /* .XSUB .XCOM ..DCM DDINT */
|
||||
OP_N, OP_AK, OP_KKKK, OP_A, /* .XFER .GOTO ..MAP .ENTR */
|
||||
OP_A, OP_RK, OP_R, OP_K, /* .ENTP .PWR2 .FLUN $SETP */
|
||||
OP_RC, OP_AA, OP_N, OP_N, /* .PACK .CFER --- --- */
|
||||
OP_N, OP_N, OP_N, OP_N /* --- --- --- --- */
|
||||
};
|
||||
|
||||
t_stat cpu_ffp (uint32 IR, uint32 intrq)
|
||||
{
|
||||
OP fpop;
|
||||
OPS op, op2;
|
||||
uint32 entry;
|
||||
uint32 j, sa, sb, sc, da, dc, ra, MA;
|
||||
int32 expon;
|
||||
t_stat reason = SCPE_OK;
|
||||
|
||||
#if defined (HAVE_INT64) /* int64 support available */
|
||||
|
||||
int32 i;
|
||||
|
||||
#endif /* end of int64 support */
|
||||
|
||||
if ((cpu_unit.flags & UNIT_FFP) == 0) /* FFP option installed? */
|
||||
return stop_inst;
|
||||
|
||||
entry = IR & 037; /* mask to entry point */
|
||||
|
||||
if (UNIT_CPU_MODEL != UNIT_1000_F) { /* 2100/M/E-Series? */
|
||||
if (op_ffp_e[entry] != OP_N)
|
||||
if (reason = cpu_ops (op_ffp_e[entry], op, intrq)) /* get instruction operands */
|
||||
return reason;
|
||||
}
|
||||
|
||||
#if defined (HAVE_INT64) /* int64 support available */
|
||||
|
||||
else { /* F-Series */
|
||||
if (op_ffp_f[entry] != OP_N)
|
||||
if (reason = cpu_ops (op_ffp_f[entry], op, intrq)) /* get instruction operands */
|
||||
return reason;
|
||||
|
||||
switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
case 000: /* [tst] 105200 (OP_N) */
|
||||
XR = 4; /* firmware revision */
|
||||
SR = 0102077; /* test passed code */
|
||||
AR = 0; /* test clears A/B */
|
||||
BR = 0;
|
||||
PC = (PC + 1) & VAMASK; /* P+2 return for firmware w/DBI */
|
||||
return reason;
|
||||
|
||||
case 003: /* .DNG 105203 (OP_N) */
|
||||
return cpu_dbi (0105323, intrq); /* remap to double int handler */
|
||||
|
||||
case 004: /* .DCO 105204 (OP_N) */
|
||||
return cpu_dbi (0105324, intrq); /* remap to double int handler */
|
||||
|
||||
case 007: /* .BLE 105207 (OP_AAF) */
|
||||
O = fp_cvt (&op[2], fp_f, fp_t); /* convert value and clear overflow */
|
||||
WriteOp (op[1].word, op[2], fp_t); /* write double-precision value */
|
||||
return reason;
|
||||
|
||||
case 010: /* .DIN 105210 (OP_N) */
|
||||
return cpu_dbi (0105330, intrq); /* remap to double int handler */
|
||||
|
||||
case 011: /* .DDE 105211 (OP_N) */
|
||||
return cpu_dbi (0105331, intrq); /* remap to double int handler */
|
||||
|
||||
case 012: /* .DIS 105212 (OP_N) */
|
||||
return cpu_dbi (0105332, intrq); /* remap to double int handler */
|
||||
|
||||
case 013: /* .DDS 105213 (OP_N) */
|
||||
return cpu_dbi (0105333, intrq); /* remap to double int handler */
|
||||
|
||||
case 014: /* .NGL 105214 (OP_AT) */
|
||||
O = fp_cvt (&op[1], fp_t, fp_f); /* convert value */
|
||||
AR = op[1].fpk[0]; /* move MSB to A */
|
||||
BR = op[1].fpk[1]; /* move LSB to B */
|
||||
return reason;
|
||||
|
||||
case 032: /* ..FCM 105232 (OP_R) */
|
||||
O = fp_pcom (&op[0], fp_f); /* complement value */
|
||||
AR = op[0].fpk[0]; /* return result */
|
||||
BR = op[0].fpk[1]; /* to A/B registers */
|
||||
return reason;
|
||||
|
||||
case 033: /* ..TCM 105233 (OP_A) */
|
||||
fpop = ReadOp (op[0].word, fp_t); /* read 4-word value */
|
||||
O = fp_pcom (&fpop, fp_t); /* complement it */
|
||||
WriteOp (op[0].word, fpop, fp_t); /* write 4-word value */
|
||||
return reason;
|
||||
} /* fall thru if not special to F */
|
||||
}
|
||||
|
||||
#endif /* end of int64 support */
|
||||
|
||||
switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
/* FFP module 1 */
|
||||
|
||||
case 000: /* [nop] 105200 (OP_N) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 M/E-series */
|
||||
return stop_inst; /* trap if not */
|
||||
break;
|
||||
|
||||
#if defined (HAVE_INT64) /* int64 support available */
|
||||
|
||||
case 001: /* DBLE 105201 (OP_AAF) */
|
||||
O = fp_cvt (&op[2], fp_f, fp_x); /* convert value and clear overflow */
|
||||
WriteOp (op[1].word, op[2], fp_x); /* write extended-precision value */
|
||||
break;
|
||||
|
||||
case 002: /* SNGL 105202 (OP_AX) */
|
||||
O = fp_cvt (&op[1], fp_x, fp_f); /* convert value */
|
||||
AR = op[1].fpk[0]; /* move MSB to A */
|
||||
BR = op[1].fpk[1]; /* move LSB to B */
|
||||
break;
|
||||
|
||||
case 003: /* .XMPY 105203 (OP_AXX) */
|
||||
i = 0; /* params start at op[0] */
|
||||
goto XMPY; /* process as XMPY */
|
||||
|
||||
case 004: /* .XDIV 105204 (OP_AXX) */
|
||||
i = 0; /* params start at op[0] */
|
||||
goto XDIV; /* process as XDIV */
|
||||
|
||||
#endif /* end of int64 support */
|
||||
|
||||
case 005: /* .DFER 105205 (OP_AA) */
|
||||
BR = op[0].word; /* get destination address */
|
||||
AR = op[1].word; /* get source address */
|
||||
goto XFER; /* do transfer */
|
||||
|
||||
#if defined (HAVE_INT64) /* int64 support available */
|
||||
|
||||
case 006: /* .XPAK 105206 (OP_A) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
|
||||
if (intrq) { /* interrupt pending? */
|
||||
PC = err_PC; /* restart instruction */
|
||||
break;
|
||||
}
|
||||
|
||||
fpop = ReadOp (op[0].word, fp_x); /* read unpacked */
|
||||
O = fp_nrpack (&fpop, fpop, (int16) AR, fp_x); /* nrm/rnd/pack mantissa, exponent */
|
||||
WriteOp (op[0].word, fpop, fp_x); /* write result */
|
||||
break;
|
||||
|
||||
case 007: /* XADD 105207 (OP_AAXX) */
|
||||
i = 1; /* params start at op[1] */
|
||||
XADD: /* enter here from .XADD */
|
||||
if (intrq) { /* interrupt pending? */
|
||||
PC = err_PC; /* restart instruction */
|
||||
break;
|
||||
}
|
||||
|
||||
O = fp_exec (001, &fpop, op[i + 1], op[i + 2]); /* three-word add */
|
||||
WriteOp (op[i].word, fpop, fp_x); /* write sum */
|
||||
break;
|
||||
|
||||
case 010: /* XSUB 105210 (OP_AAXX) */
|
||||
i = 1; /* params start at op[1] */
|
||||
XSUB: /* enter here from .XSUB */
|
||||
if (intrq) { /* interrupt pending? */
|
||||
PC = err_PC; /* restart instruction */
|
||||
break;
|
||||
}
|
||||
|
||||
O = fp_exec (021, &fpop, op[i + 1], op[i + 2]); /* three-word subtract */
|
||||
WriteOp (op[i].word, fpop, fp_x); /* write difference */
|
||||
break;
|
||||
|
||||
case 011: /* XMPY 105211 (OP_AAXX) */
|
||||
i = 1; /* params start at op[1] */
|
||||
XMPY: /* enter here from .XMPY */
|
||||
if (intrq) { /* interrupt pending? */
|
||||
PC = err_PC; /* restart instruction */
|
||||
break;
|
||||
}
|
||||
|
||||
O = fp_exec (041, &fpop, op[i + 1], op[i + 2]); /* three-word multiply */
|
||||
WriteOp (op[i].word, fpop, fp_x); /* write product */
|
||||
break;
|
||||
|
||||
case 012: /* XDIV 105212 (OP_AAXX) */
|
||||
i = 1; /* params start at op[1] */
|
||||
XDIV: /* enter here from .XDIV */
|
||||
if (intrq) { /* interrupt pending? */
|
||||
PC = err_PC; /* restart instruction */
|
||||
break;
|
||||
}
|
||||
|
||||
O = fp_exec (061, &fpop, op[i + 1], op[i + 2]); /* three-word divide */
|
||||
WriteOp (op[i].word, fpop, fp_x); /* write quotient */
|
||||
break;
|
||||
|
||||
case 013: /* .XADD 105213 (OP_AXX) */
|
||||
i = 0; /* params start at op[0] */
|
||||
goto XADD; /* process as XADD */
|
||||
|
||||
case 014: /* .XSUB 105214 (OP_AXX) */
|
||||
i = 0; /* params start at op[0] */
|
||||
goto XSUB; /* process as XSUB */
|
||||
|
||||
case 015: /* .XCOM 105215 (OP_A) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
|
||||
fpop = ReadOp (op[0].word, fp_x); /* read unpacked */
|
||||
AR = fp_ucom (&fpop, fp_x); /* complement and rtn exp adj */
|
||||
WriteOp (op[0].word, fpop, fp_x); /* write result */
|
||||
break;
|
||||
|
||||
case 016: /* ..DCM 105216 (OP_A) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
|
||||
if (intrq) { /* interrupt pending? */
|
||||
PC = err_PC; /* restart instruction */
|
||||
break;
|
||||
}
|
||||
|
||||
fpop = ReadOp (op[0].word, fp_x); /* read operand */
|
||||
O = fp_pcom (&fpop, fp_x); /* complement (can't ovf neg) */
|
||||
WriteOp (op[0].word, fpop, fp_x); /* write result */
|
||||
break;
|
||||
|
||||
case 017: /* DDINT 105217 (OP_AAX) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
|
||||
if (intrq) { /* interrupt pending? */
|
||||
PC = err_PC; /* restart instruction */
|
||||
break;
|
||||
}
|
||||
|
||||
O = fp_trun (&fpop, op[2], fp_x); /* truncate operand (can't ovf) */
|
||||
WriteOp (op[1].word, fpop, fp_x); /* write result */
|
||||
break;
|
||||
|
||||
#endif /* end of int64 support */
|
||||
|
||||
/* FFP module 2 */
|
||||
|
||||
case 020: /* .XFER 105220 (OP_N) */
|
||||
if (UNIT_CPU_TYPE == UNIT_TYPE_2100)
|
||||
PC = (PC + 1) & VAMASK; /* 2100 .XFER returns to P+2 */
|
||||
XFER: /* enter here from .DFER */
|
||||
sc = 3; /* set count for 3-wd xfer */
|
||||
goto CFER; /* do transfer */
|
||||
|
||||
case 021: /* .GOTO 105221 (OP_AK) */
|
||||
if ((int16) op[1].word < 1) /* index < 1? */
|
||||
op[1].word = 1; /* reset min */
|
||||
|
||||
sa = PC + op[1].word - 1; /* point to jump target */
|
||||
if (sa >= op[0].word) /* must be <= last target */
|
||||
sa = op[0].word - 1;
|
||||
|
||||
da = ReadW (sa); /* get jump target */
|
||||
if (reason = resolve (da, &MA, intrq)) { /* resolve indirects */
|
||||
PC = err_PC; /* irq restarts instruction */
|
||||
break;
|
||||
}
|
||||
|
||||
mp_dms_jmp (MA); /* validate jump addr */
|
||||
PCQ_ENTRY; /* record last PC */
|
||||
PC = MA; /* jump */
|
||||
BR = op[0].word; /* (for 2100 FFP compat) */
|
||||
break;
|
||||
|
||||
case 022: /* ..MAP 105222 (OP_KKKK) */
|
||||
op[1].word = op[1].word - 1; /* decrement 1st subscr */
|
||||
|
||||
if ((AR & 1) == 0) /* 2-dim access? */
|
||||
op[1].word = op[1].word + /* compute element offset */
|
||||
(op[2].word - 1) * op[3].word;
|
||||
else { /* 3-dim access */
|
||||
if (reason = cpu_ops (OP_KK, op2, intrq)) { /* get 1st, 2nd ranges */
|
||||
PC = err_PC; /* irq restarts instruction */
|
||||
break;
|
||||
}
|
||||
op[1].word = op[1].word + /* offset */
|
||||
((op[3].word - 1) * op2[1].word +
|
||||
op[2].word - 1) * op2[0].word;
|
||||
}
|
||||
|
||||
AR = (op[0].word + op[1].word * BR) & DMASK; /* return element address */
|
||||
break;
|
||||
|
||||
case 023: /* .ENTR 105223 (OP_A) */
|
||||
MA = PC - 3; /* get addr of entry point */
|
||||
ENTR: /* enter here from .ENTP */
|
||||
da = op[0].word; /* get addr of 1st formal */
|
||||
dc = MA - da; /* get count of formals */
|
||||
sa = ReadW (MA); /* get addr of return point */
|
||||
ra = ReadW (sa++); /* get rtn, ptr to 1st actual */
|
||||
WriteW (MA, ra); /* stuff rtn into caller's ent */
|
||||
sc = ra - sa; /* get count of actuals */
|
||||
if (sc > dc) /* use min (actuals, formals) */
|
||||
sc = dc;
|
||||
|
||||
for (j = 0; j < sc; j++) {
|
||||
MA = ReadW (sa++); /* get addr of actual */
|
||||
if (reason = resolve (MA, &MA, intrq)) { /* resolve indirect */
|
||||
PC = err_PC; /* irq restarts instruction */
|
||||
break;
|
||||
}
|
||||
WriteW (da++, MA); /* put addr into formal */
|
||||
}
|
||||
|
||||
AR = ra; /* return address */
|
||||
BR = da; /* addr of 1st unused formal */
|
||||
break;
|
||||
|
||||
case 024: /* .ENTP 105224 (OP_A) */
|
||||
MA = PC - 5; /* get addr of entry point */
|
||||
goto ENTR;
|
||||
|
||||
case 025: /* .PWR2 105225 (OP_RK) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
|
||||
fp_unpack (&fpop, &expon, op[0], fp_f); /* unpack value */
|
||||
expon = expon + (int16) (op[1].word); /* multiply by 2**n */
|
||||
fp_pack (&fpop, fpop, expon, fp_f); /* repack value */
|
||||
AR = fpop.fpk[0]; /* return result */
|
||||
BR = fpop.fpk[1]; /* to A/B registers */
|
||||
break;
|
||||
|
||||
case 026: /* .FLUN 105226 (OP_R) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
|
||||
fp_unpack (&fpop, &expon, op[0], fp_f); /* unpack value */
|
||||
AR = (int16) expon; /* return expon to A */
|
||||
BR = fpop.fpk[1]; /* and low mant to B */
|
||||
break;
|
||||
|
||||
case 027: /* $SETP 105227 (OP_K) */
|
||||
j = sa = AR; /* save initial value */
|
||||
sb = BR; /* save initial address */
|
||||
AR = 0; /* AR will return = 0 */
|
||||
BR = BR & VAMASK; /* addr must be direct */
|
||||
|
||||
do {
|
||||
WriteW (BR, j); /* write value to address */
|
||||
j = (j + 1) & DMASK; /* incr value */
|
||||
BR = (BR + 1) & VAMASK; /* incr address */
|
||||
op[0].word = op[0].word - 1; /* decr count */
|
||||
if (op[0].word && intrq) { /* more and intr? */
|
||||
AR = sa; /* restore A */
|
||||
BR = sb; /* restore B */
|
||||
PC = err_PC; /* restart instruction */
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (op[0].word != 0); /* loop until count exhausted */
|
||||
break;
|
||||
|
||||
case 030: /* .PACK 105230 (OP_RC) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
|
||||
O = fp_nrpack (&fpop, op[0], /* nrm/rnd/pack value */
|
||||
(int16) (op[1].word), fp_f);
|
||||
AR = fpop.fpk[0]; /* return result */
|
||||
BR = fpop.fpk[1]; /* to A/B registers */
|
||||
break;
|
||||
|
||||
case 031: /* .CFER 105231 (OP_AA) */
|
||||
if ((UNIT_CPU_MODEL != UNIT_1000_E) && /* must be 1000 E-series */
|
||||
(UNIT_CPU_MODEL != UNIT_1000_F)) /* or 1000 F-series */
|
||||
return stop_inst; /* trap if not */
|
||||
|
||||
BR = op[0].word; /* get destination address */
|
||||
AR = op[1].word; /* get source address */
|
||||
sc = 4; /* set for 4-wd xfer */
|
||||
CFER: /* enter here from .XFER */
|
||||
for (j = 0; j < sc; j++) { /* xfer loop */
|
||||
WriteW (BR, ReadW (AR)); /* transfer word */
|
||||
AR = (AR + 1) & VAMASK; /* bump source addr */
|
||||
BR = (BR + 1) & VAMASK; /* bump destination addr */
|
||||
}
|
||||
|
||||
E = 0; /* routine clears E */
|
||||
|
||||
if (UNIT_CPU_TYPE == UNIT_TYPE_2100) { /* 2100 (and .DFER/.XFER)? */
|
||||
AR = (AR + 1) & VAMASK; /* 2100 FFP returns X+4, Y+4 */
|
||||
BR = (BR + 1) & VAMASK;
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
|
||||
/* Double-Integer Instructions.
|
||||
|
||||
The double-integer instructions were added to the HP instruction set at
|
||||
revision 1920 of the 1000-F. They were immediately adopted in a number of HP
|
||||
software products, most notably the RTE file management package (FMP)
|
||||
routines. As these routines are used in nearly every RTE program, F-Series
|
||||
programs were almost always a few hundred bytes smaller than their M- and
|
||||
E-Series counterparts. This became significant as RTE continued to grow in
|
||||
size, and some customer programs ran out of address space on E-Series
|
||||
machines.
|
||||
|
||||
While HP never added double-integer instructions to the standard E-Series, a
|
||||
product from the HP "specials group," HP 93585A, provided microcoded
|
||||
replacements for the E-Series. This could provide just enough address-space
|
||||
savings to allow programs to load in E-Series systems, in addition to
|
||||
accelerating these common operations.
|
||||
|
||||
M-Series microcode was never offered by HP. However, it costs us nothing to
|
||||
enable double-integer instructions for M-Series simulations. This has the
|
||||
concomitant advantage that it allows RTE-6/VM to run under SIMH (for
|
||||
simulation, we must SET CPU 1000-M, because RTE-6/VM looks for the OS and VM
|
||||
microcode -- which we do not implement yet -- if it detects an E- or F-Series
|
||||
machine).
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A N/A 93575A std
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Instr. 1000-E 1000-F Description
|
||||
------ ------ ------ -----------------------------------------
|
||||
[test] 105320 -- [self test]
|
||||
.DAD 105321 105014 Double integer add
|
||||
.DMP 105322 105054 Double integer multiply
|
||||
.DNG 105323 105203 Double integer negate
|
||||
.DCO 105324 105204 Double integer compare
|
||||
.DDI 105325 105074 Double integer divide
|
||||
.DDIR 105326 105134 Double integer divide (reversed)
|
||||
.DSB 105327 105034 Double integer subtract
|
||||
.DIN 105330 105210 Double integer increment
|
||||
.DDE 105331 105211 Double integer decrement
|
||||
.DIS 105332 105212 Double integer increment and skip if zero
|
||||
.DDS 105333 105213 Double integer decrement and skip if zero
|
||||
.DSBR 105334 105114 Double integer subtraction (reversed)
|
||||
|
||||
On the F-Series, the double-integer instruction codes are split among the
|
||||
floating-point processor and the Fast FORTRAN Processor ranges. They are
|
||||
dispatched from those respective simulators for processing here.
|
||||
|
||||
Notes:
|
||||
|
||||
1. The E-Series opcodes are listed in Appendix C of the Macro/1000 manual.
|
||||
These should be the same opcodes as given in the 93585A manual listed
|
||||
below, but no copy of the reference below has been located to confirm
|
||||
the proper opcodes. This module should be corrected if needed when such
|
||||
documentation is found.
|
||||
|
||||
2. The action of the self-test instruction (105320) is unknown. At the
|
||||
moment, we take an unimplemented instruction trap for this. When
|
||||
documentation explaining the action is located, it will be implemented.
|
||||
|
||||
3. The F-Series firmware executes .DMP and .DDI/.DDIR by floating the
|
||||
32-bit double integer to a 48-bit extended-precision number, calling the
|
||||
FPP to execute the extended-precision multiply/divide, and then fixing
|
||||
the product to a 32-bit double integer. We simulate these directly with
|
||||
64- or 32-bit integer arithmetic.
|
||||
|
||||
Additional references:
|
||||
- 93575A Double Integer Instructions Installation and Reference Manual
|
||||
(93575-90007)
|
||||
*/
|
||||
|
||||
static const OP_PAT op_dbi[16] = {
|
||||
OP_N, OP_JD, OP_JD, OP_J, /* [test] .DAD .DMP .DNG */
|
||||
OP_JD, OP_JD, OP_JD, OP_JD, /* .DCO .DDI .DDIR .DSB */
|
||||
OP_J, OP_J, OP_A, OP_A, /* .DIN .DDE .DIS .DDS */
|
||||
OP_JD, OP_N, OP_N, OP_N /* .DSBR --- --- --- */
|
||||
};
|
||||
|
||||
t_stat cpu_dbi (uint32 IR, uint32 intrq)
|
||||
{
|
||||
OP din;
|
||||
OPS op;
|
||||
uint32 entry, t;
|
||||
t_stat reason = SCPE_OK;
|
||||
|
||||
if ((cpu_unit.flags & UNIT_DBI) == 0) /* DBI option installed? */
|
||||
return stop_inst;
|
||||
|
||||
entry = IR & 017; /* mask to entry point */
|
||||
|
||||
if (op_dbi[entry] != OP_N)
|
||||
if (reason = cpu_ops (op_dbi[entry], op, intrq)) /* get instruction operands */
|
||||
return reason;
|
||||
|
||||
switch (entry) { /* decode IR<3:0> */
|
||||
|
||||
case 000: /* [test] 105320 (OP_N) */
|
||||
t = (AR << 16) | BR; /* set t for nop */
|
||||
reason = stop_inst; /* function unknown; not impl. */
|
||||
break;
|
||||
|
||||
case 001: /* .DAD 105321 (OP_JD) */
|
||||
t = op[0].dword + op[1].dword; /* add values */
|
||||
E = E | (t < op[0].dword); /* carry if result smaller */
|
||||
O = (((~op[0].dword ^ op[1].dword) & /* overflow if sign wrong */
|
||||
(op[0].dword ^ t) & SIGN32) != 0);
|
||||
break;
|
||||
|
||||
case 002: /* .DMP 105322 (OP_JD) */
|
||||
{
|
||||
|
||||
#if defined (HAVE_INT64) /* int64 support available */
|
||||
|
||||
t_int64 t64;
|
||||
|
||||
t64 = (t_int64) op[0].dword * /* multiply values */
|
||||
(t_int64) op[1].dword;
|
||||
O = ((t64 < -(t_int64) 0x80000000) || /* overflow if out of range */
|
||||
(t64 > (t_int64) 0x7FFFFFFF));
|
||||
if (O)
|
||||
t = ~SIGN32; /* if overflow, rtn max pos */
|
||||
else
|
||||
t = (uint32) (t64 & DMASK32); /* else lower 32 bits of result */
|
||||
|
||||
#else /* int64 support unavailable */
|
||||
|
||||
uint32 sign, xu, yu, rh, rl;
|
||||
|
||||
sign = ((int32) op[0].dword < 0) ^ /* save sign of result */
|
||||
((int32) op[1].dword < 0);
|
||||
|
||||
xu = (uint32) abs ((int32) op[0].dword); /* make operands pos */
|
||||
yu = (uint32) abs ((int32) op[1].dword);
|
||||
|
||||
if ((xu & 0xFFFF0000) == 0 && /* 16 x 16 multiply? */
|
||||
(yu & 0xFFFF0000) == 0) {
|
||||
t = xu * yu; /* do it */
|
||||
O = 0; /* can't overflow */
|
||||
}
|
||||
|
||||
else if ((xu & 0xFFFF0000) != 0 && /* 32 x 32 multiply? */
|
||||
(yu & 0xFFFF0000) != 0)
|
||||
O = 1; /* always overflows */
|
||||
|
||||
else { /* 16 x 32 or 32 x 16 */
|
||||
rl = (xu & 0xFFFF) * (yu & 0xFFFF); /* form 1st partial product */
|
||||
|
||||
if ((xu & 0xFFFF0000) == 0)
|
||||
rh = xu * (yu >> 16) + (rl >> 16); /* 16 x 32 2nd partial */
|
||||
else
|
||||
rh = (xu >> 16) * yu + (rl >> 16); /* 32 x 16 2nd partial */
|
||||
|
||||
O = (rh > 0x7FFF + sign); /* check for out of range */
|
||||
if (O == 0)
|
||||
t = (rh << 16) | (rl & 0xFFFF); /* combine partials */
|
||||
}
|
||||
|
||||
if (O)
|
||||
t = ~SIGN32; /* if overflow, rtn max pos */
|
||||
else if (sign)
|
||||
t = ~t + 1; /* if result neg, 2s compl */
|
||||
|
||||
#endif /* end of int64 support */
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 003: /* .DNG 105323 (OP_J) */
|
||||
t = ~op[0].dword + 1; /* negate value */
|
||||
O = (op[0].dword == SIGN32); /* overflow if max neg */
|
||||
if (op[0].dword == 0) /* borrow if result zero */
|
||||
E = 1;
|
||||
break;
|
||||
|
||||
case 004: /* .DCO 105324 (OP_JD) */
|
||||
t = op[0].dword; /* copy for later store */
|
||||
if ((int32) op[0].dword < (int32) op[1].dword)
|
||||
PC = (PC + 1) & VAMASK; /* < rtns to P+2 */
|
||||
else if ((int32) op[0].dword > (int32) op[1].dword)
|
||||
PC = (PC + 2) & VAMASK; /* > rtns to P+3 */
|
||||
break; /* = rtns to P+1 */
|
||||
|
||||
case 005: /* .DDI 105325 (OP_JD) */
|
||||
DDI:
|
||||
O = ((op[1].dword == 0) || /* overflow if div 0 */
|
||||
((op[0].dword == SIGN32) && /* or max neg div -1 */
|
||||
((int32) op[1].dword == -1)));
|
||||
if (O)
|
||||
t = ~SIGN32; /* rtn max pos for ovf */
|
||||
else
|
||||
t = op[0].dword / op[1].dword; /* else return quotient */
|
||||
break;
|
||||
|
||||
case 006: /* .DDIR 105326 (OP_JD) */
|
||||
t = op[0].dword; /* swap operands */
|
||||
op[0].dword = op[1].dword;
|
||||
op[1].dword = t;
|
||||
goto DDI; /* continue at .DDI */
|
||||
|
||||
case 007: /* .DSB 105327 (OP_JD) */
|
||||
DSB:
|
||||
t = op[0].dword - op[1].dword; /* subtract values */
|
||||
E = E | (op[0].dword < op[1].dword); /* borrow if minu < subtr */
|
||||
O = (((op[0].dword ^ op[1].dword) & /* overflow if sign wrong */
|
||||
(op[0].dword ^ t) & SIGN32) != 0);
|
||||
break;
|
||||
|
||||
case 010: /* .DIN 105330 (OP_J) */
|
||||
t = op[0].dword + 1; /* increment value */
|
||||
O = (t == SIGN32); /* overflow if sign flipped */
|
||||
if (t == 0)
|
||||
E = 1; /* carry if result zero */
|
||||
break;
|
||||
|
||||
case 011: /* .DDE 105331 (OP_J) */
|
||||
t = op[0].dword - 1; /* decrement value */
|
||||
O = (t == ~SIGN32); /* overflow if sign flipped */
|
||||
if ((int32) t == -1)
|
||||
E = 1; /* borrow if result -1 */
|
||||
break;
|
||||
|
||||
case 012: /* .DIS 105332 (OP_A) */
|
||||
din = ReadOp (op[0].word, in_d); /* get value */
|
||||
t = din.dword = din.dword + 1; /* increment value */
|
||||
WriteOp (op[0].word, din, in_d); /* store it back */
|
||||
if (t == 0)
|
||||
PC = (PC + 1) & VAMASK; /* skip if result zero */
|
||||
break;
|
||||
|
||||
case 013: /* .DDS 105333 (OP_A) */
|
||||
din = ReadOp (op[0].word, in_d); /* get value */
|
||||
t = din.dword = din.dword - 1; /* decrement value */
|
||||
WriteOp (op[0].word, din, in_d); /* write it back */
|
||||
if (t == 0)
|
||||
PC = (PC + 1) & VAMASK; /* skip if result zero */
|
||||
break;
|
||||
|
||||
case 014: /* .DSBR 105334 (OP_JD) */
|
||||
t = op[0].dword; /* swap operands */
|
||||
op[0].dword = op[1].dword;
|
||||
op[1].dword = t;
|
||||
goto DSB; /* continue at .DSB */
|
||||
|
||||
default: /* others undefined */
|
||||
t = (AR << 16) | BR; /* set t for nop */
|
||||
reason = stop_inst;
|
||||
}
|
||||
|
||||
if (reason == SCPE_OK) { /* if return OK */
|
||||
AR = (t >> 16) & DMASK; /* break result */
|
||||
BR = t & DMASK; /* into A and B */
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
1125
HP2100/hp2100_cpu4.c
Normal file
1125
HP2100/hp2100_cpu4.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_defs.h: HP 2100 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2004, Robert M. Supnik
|
||||
Copyright (c) 1993-2007, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,12 @@
|
|||
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.
|
||||
|
||||
11-Jan-07 JDB Added 12578A DMA byte packing to DMA structure
|
||||
28-Dec-06 JDB Added CRS backplane signal as I/O pseudo-opcode
|
||||
Added DMASK32 32-bit mask value
|
||||
21-Dec-06 JDB Changed MEM_ADDR_OK for 21xx loader support
|
||||
12-Sep-06 JDB Define NOTE_IOG to recalc interrupts after instr exec
|
||||
Rename STOP_INDINT to NOTE_INDINT (not a stop condition)
|
||||
30-Dec-04 JDB Added IBL_DS_HEAD head number mask
|
||||
19-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF stop codes
|
||||
25-Apr-04 RMS Added additional IBL definitions
|
||||
|
@ -45,24 +51,25 @@
|
|||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
/* Simulator stop codes */
|
||||
/* Simulator stop and notification codes */
|
||||
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
#define STOP_IODV 2 /* must be 2 */
|
||||
#define STOP_HALT 3 /* HALT */
|
||||
#define STOP_IBKPT 4 /* breakpoint */
|
||||
#define STOP_IND 5 /* indirect loop */
|
||||
#define STOP_INDINT 6 /* indirect intr */
|
||||
#define NOTE_INDINT 6 /* indirect intr */
|
||||
#define STOP_NOCONN 7 /* no connection */
|
||||
#define STOP_OFFLINE 8 /* device offline */
|
||||
#define STOP_PWROFF 9 /* device powered off */
|
||||
#define NOTE_IOG 10 /* I/O instr executed */
|
||||
|
||||
#define ABORT_PRO 1 /* protection abort */
|
||||
|
||||
/* Memory */
|
||||
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
|
||||
#define MEM_ADDR_OK(x) (((uint32) (x)) < fwanxm)
|
||||
#define VA_N_SIZE 15 /* virtual addr size */
|
||||
#define VASIZE (1 << VA_N_SIZE)
|
||||
#define VAMASK 077777 /* virt addr mask */
|
||||
|
@ -73,8 +80,10 @@
|
|||
/* Architectural constants */
|
||||
|
||||
#define SIGN32 020000000000 /* 32b sign */
|
||||
#define DMASK32 037777777777 /* 32b data mask */
|
||||
#define SIGN 0100000 /* 16b sign */
|
||||
#define DMASK 0177777 /* 16b data mask */
|
||||
#define DMASK8 0377 /* 8b data mask */
|
||||
#define AR ABREG[0] /* A = reg 0 */
|
||||
#define BR ABREG[1] /* B = reg 1 */
|
||||
#define SEXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)))
|
||||
|
@ -101,7 +110,9 @@
|
|||
|
||||
/* DMA channels */
|
||||
|
||||
#define DMA_OE 020000000000 /* byte packing odd/even flag */
|
||||
#define DMA1_STC 0100000 /* DMA - issue STC */
|
||||
#define DMA1_PB 0040000 /* DMA - pack bytes */
|
||||
#define DMA1_CLC 0020000 /* DMA - issue CLC */
|
||||
#define DMA2_OI 0100000 /* DMA - output/input */
|
||||
|
||||
|
@ -109,6 +120,8 @@ struct DMA { /* DMA channel */
|
|||
uint32 cw1; /* device select */
|
||||
uint32 cw2; /* direction, address */
|
||||
uint32 cw3; /* word count */
|
||||
uint32 latency; /* 1st cycle delay */
|
||||
uint32 packer; /* byte-packer holding reg */
|
||||
};
|
||||
|
||||
/* Memory management */
|
||||
|
@ -182,6 +195,7 @@ struct DMA { /* DMA channel */
|
|||
#define ioOTX 6 /* output from A/B */
|
||||
#define ioCTL 7 /* set/clear control */
|
||||
#define ioEDT 8 /* DMA: end data transfer */
|
||||
#define ioCRS 9 /* control reset ("CLC 0") */
|
||||
|
||||
/* I/O devices - fixed assignments */
|
||||
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
SIMH/HP 21XX DIAGNOSTICS PERFORMANCE
|
||||
====================================
|
||||
Last update: 2005-03-22
|
||||
Last update: 2007-01-12
|
||||
|
||||
|
||||
The HP 24396 diagnostic suite has been run against the SIMH HP 21xx simulation.
|
||||
Diagnostic programs were obtained from magnetic tape, HP 24396-13601 Rev. 2040.
|
||||
For each diagnostic, the recommended standard tests were selected, plus any
|
||||
available optional tests that broadened the test coverage.
|
||||
Diagnostic programs were obtained from two magnetic tapes, HP 24396-13601 Rev.
|
||||
1713 and Rev. 2326, plus a few standalone paper tapes. For each diagnostic, the
|
||||
recommended standard tests were selected, plus any available optional tests that
|
||||
broadened the test coverage.
|
||||
|
||||
The test system configuration is the default SIMH configuration with these
|
||||
alterations (except where noted in the individual diagnostic reports):
|
||||
Except where noted in the individual diagnostic reports, the test system
|
||||
configuration is the default SIMH configuration with these alterations:
|
||||
|
||||
* All I/O devices are enabled.
|
||||
* The CPU is configured as a 21MX-E with 128KW of memory.
|
||||
* The CPU is configured as a 1000-E with 128KW of memory.
|
||||
|
||||
Detailed diagnostic configuration, operation, and results are given after the
|
||||
summary table. These may be used to duplicate the diagnostic results.
|
||||
|
@ -33,19 +34,23 @@ The results of the diagnostic runs are summarized below:
|
|||
|
||||
101004 EAU Instruction Group 1431 3.2-3 Passed
|
||||
101207 Floating Point Instruction Group 1551 3.2-3 Passed
|
||||
102001 Memory Protect 1431 3.7-0 Passed
|
||||
102002 Memory Parity Check 1431 - No simulation
|
||||
102305 Memory Protect/Parity Error 1705 3.3-0 Partial
|
||||
|
||||
101206 Power Fail/Auto Restart 1635 - No simulation
|
||||
141103 I/O Instruction Group 1810 3.2-3 Passed
|
||||
143300 General Purpose Register 1813 3.2-3 Passed
|
||||
101220 Direct Memory Access 1705 3.2-3 Passed
|
||||
101105 Direct Memory Access (2114/15/16) 1502 3.7-0 Passed
|
||||
101220 Direct Memory Access (2100/21MX) 1705 3.2-3 Passed
|
||||
|
||||
101011 Extended Instruction Group (Index) 1432 3.2-3 Passed
|
||||
101112 Extended Instruction Group (Word, Byte) 1728 3.2-3 Passed
|
||||
101110 2100 Fast FORTRAN Package 1632 3.4-0 Partial
|
||||
101213 M/E-Series Fast FORTRAN Package 1 1822 3.4-0 Passed
|
||||
101114 M/E-Series Fast FORTRAN Package 2 1632 3.4-0 Passed
|
||||
101121 F-Series FPP/SIS/FFP 1926 - No simulation
|
||||
101121 F-Series FPP/SIS/FFP 1926 3.7-0 Passed
|
||||
101016 2000/Access Comm Processor for 2100 1526 3.2-3 Partial
|
||||
|
||||
102103 Memory Expansion Unit 1830 3.2-3 Passed
|
||||
102103 Semiconductor Memory Microcoded 21MX 1644 - No simulation
|
||||
|
@ -66,13 +71,26 @@ The results of the diagnostic runs are summarized below:
|
|||
103121 12968 Asynchronous Comm. Interface 1602 - No simulation
|
||||
103024 12821 ICD Disc Interface 1928 - No simulation
|
||||
|
||||
104000 2600 Keyboard Display Terminal 1615 - No simulation
|
||||
104003 Teleprinter 1509 3.2-3 Partial
|
||||
144105 2762A/B Terminal (Terminet) 1546 - No simulation
|
||||
104007 2615 Video Terminal 1347 - No simulation
|
||||
104011 2640 Interactive Terminal 1502 - No simulation
|
||||
104012 2644 Mini Data Station (non CTU) 1542 - No simulation
|
||||
104013 2644 Mini Data Station (CTU Only) 1542 - No simulation
|
||||
104017 92900 Terminal Subsystem (3070, 40280) 1643 - No simulation
|
||||
|
||||
105000 2610/14 Line Printer 1451 - No simulation
|
||||
105101 2767 Line Printer 1611 3.3-0 Passed
|
||||
105102 2607 Line Printer 1446 3.3-0 Passed
|
||||
145103 2613/17/18 Line Printer 1633 - No simulation
|
||||
105104 9866 Line Printer 1541 - No simulation
|
||||
105106 2631 Printer 1913 - No simulation
|
||||
105107 2635 Printing Terminal 1913 - No simulation
|
||||
105105 2608 Line Printer 2026 - No simulation
|
||||
105104 9866 Line Printer 1541 - No simulation
|
||||
|
||||
111001 Disc File (2883) 1451 3.3-0 Partial
|
||||
111104 12732 Flexible Disc Subsystem 1708 - No simulation
|
||||
151302 7900/01 Cartridge Disc 1805 3.2-3 Partial
|
||||
151403 7905/06/20/25 Disc 1805 3.3-1 Partial
|
||||
|
@ -86,8 +104,7 @@ The results of the diagnostic runs are summarized below:
|
|||
107000 Digital Plotter Interface (CALCOMP) 1540 - No simulation
|
||||
113100 2892 Card Reader 1537 - No simulation
|
||||
113001 2894 Card Reader Punch 1728 - No simulation
|
||||
104003 Teleprinter 1509 3.2-3 Partial
|
||||
104007 2615 Video Terminal 1347 - No simulation
|
||||
113003 7261 Card Reader 1546 - No simulation
|
||||
103006 12909B PROM Writer 1420 - No simulation
|
||||
|
||||
|
||||
|
@ -97,12 +114,9 @@ not supported by the 24396 suite:
|
|||
Paper Tape Date SIMH
|
||||
Part Number DSN Diagnostic Name Code Vers. Result
|
||||
----------- ------ --------------------------------------- ---- ----- ----------
|
||||
12984-16001 105101 2767 Diagnostic 1611 3.3-0 Passed
|
||||
24203-60001 -- HP2100A Cartridge Disc Memory (2871) A 3.3-0 Partial
|
||||
12965-16001 111001 HP2100A Disc File (2883) 1451 3.3-0 Partial
|
||||
22682-16017 177777 HP 2100 Fixed Head Disc/Drum (277x) 1612 3.3-0 Passed
|
||||
13206-16001 101016 2100 2000/Access Comm. Proc. Firmware 1526 3.2-3 Partial
|
||||
13207-16001 101217 21MX 2000/Access Comm. Proc. Firmware 1728 3.2-3 Passed
|
||||
13207-16001 101217 2000/Access Comm Processor for 21MX 1728 3.2-3 Passed
|
||||
20433-????? -- HP 3030 Magnetic Tape Subsystem -- - Not tested
|
||||
|
||||
|
||||
|
@ -144,7 +158,7 @@ For all runs other than the diagnostic configurator pretest, the configurator
|
|||
was used in automatic mode to load the target diagnostic via its Diagnostic
|
||||
Serial Number (DSN), as follows:
|
||||
|
||||
sim> attach -r MSC0 24396-13601-REV-2040.tape
|
||||
sim> attach -r MSC0 24396-13601_Rev-2326.abin.tape
|
||||
sim> deposit S 000000
|
||||
sim> boot MSC0
|
||||
|
||||
|
@ -233,6 +247,7 @@ TESTED DEVICE: CPU (hp2100_cpu.c)
|
|||
|
||||
CONFIGURATION: sim> set CPU 2100
|
||||
sim> set CPU 32K
|
||||
|
||||
sim> deposit S 000000
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
@ -273,7 +288,7 @@ TEST NOTES: The standard tests 00-10, plus optional tests 13, 14, and 16 are
|
|||
DSN 101004 - EAU Instruction Group
|
||||
----------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu.c)
|
||||
TESTED DEVICE: CPU (hp2100_cpu1.c)
|
||||
|
||||
CONFIGURATION: sim> deposit S 000000
|
||||
sim> reset
|
||||
|
@ -292,7 +307,7 @@ TEST RESULT: Passed.
|
|||
DSN 101207 - Floating Point Instruction Group
|
||||
---------------------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_fp.c)
|
||||
TESTED DEVICE: CPU (hp2100_cpu2.c)
|
||||
|
||||
CONFIGURATION: sim> deposit S 000000
|
||||
sim> reset
|
||||
|
@ -307,6 +322,44 @@ TEST RESULT: Passed.
|
|||
|
||||
|
||||
|
||||
---------------------------
|
||||
DSN 102001 - Memory Protect
|
||||
---------------------------
|
||||
|
||||
TESTED DEVICE: MP (hp2100_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> set CPU 2100
|
||||
sim> set CPU 32K
|
||||
|
||||
sim> deposit S 000000
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
TEST REPORT: HP 2100 SERIES MEMORY PROTECT DIAGNOSTIC
|
||||
H07. PRESS PRESET (EXT/INT), RUN
|
||||
|
||||
HALT instruction 102007
|
||||
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
H13. PRESS HALT, PRESET(INT), RUN
|
||||
IN LESS THAN 15 SEC.
|
||||
|
||||
[CTRL+E]
|
||||
Simulation stopped
|
||||
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
PASS 000001
|
||||
|
||||
HALT instruction 102077
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
----------------------------------------
|
||||
DSN 102305 - Memory Protect/Parity Error
|
||||
----------------------------------------
|
||||
|
@ -454,12 +507,47 @@ TEST RESULT: Passed.
|
|||
|
||||
|
||||
|
||||
---------------------------------
|
||||
DSN 101220 - Direct Memory Access
|
||||
---------------------------------
|
||||
----------------------------------------------
|
||||
DSN 101105 - Direct Memory Access (2114/15/16)
|
||||
----------------------------------------------
|
||||
|
||||
TESTED DEVICE: DMA0/DMA1 (hp2100_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> set CPU 2116
|
||||
sim> set CPU 16K
|
||||
sim> set LPS diag
|
||||
|
||||
sim> deposit S 000014
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
HALT instruction 102074
|
||||
|
||||
sim> deposit S 040000
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
TEST REPORT: H0. START DMA DIAGNOSTIC
|
||||
|
||||
HALT instruction 102027
|
||||
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
H77. END DIAGNOSTIC
|
||||
|
||||
HALT instruction 102077
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
---------------------------------------------
|
||||
DSN 101220 - Direct Memory Access (2100/21MX)
|
||||
---------------------------------------------
|
||||
|
||||
TESTED DEVICE: DCPC0/DCPC1 (hp2100_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> set LPS diag
|
||||
sim> deposit S 000014
|
||||
sim> reset
|
||||
|
@ -492,7 +580,7 @@ TEST RESULT: Passed.
|
|||
DSN 101011 - Extended Instruction Group (Index)
|
||||
-----------------------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu1.c)
|
||||
TESTED DEVICE: CPU (hp2100_cpu2.c)
|
||||
|
||||
CONFIGURATION: sim> deposit S 000000
|
||||
sim> reset
|
||||
|
@ -511,7 +599,7 @@ TEST RESULT: Passed.
|
|||
DSN 101112 - Extended Instruction Group (Word, Byte, Bit)
|
||||
---------------------------------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu1.c)
|
||||
TESTED DEVICE: CPU (hp2100_cpu2.c)
|
||||
|
||||
CONFIGURATION: sim> set LPS diag
|
||||
sim> deposit S 000014
|
||||
|
@ -537,7 +625,7 @@ TEST RESULT: Passed.
|
|||
DSN 101110 - 2100 Fast FORTRAN Package
|
||||
--------------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu1.c)
|
||||
TESTED DEVICE: CPU (hp2100_cpu3.c)
|
||||
|
||||
CONFIGURATION: sim> set CPU 2100
|
||||
sim> set CPU 32K
|
||||
|
@ -598,7 +686,7 @@ TEST NOTES: Tests 07 and 11 test the interruptibility of the .XADD and .XMPY
|
|||
DSN 101213 - M/E-Series Fast FORTRAN Package 1
|
||||
----------------------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu1.c)
|
||||
TESTED DEVICE: CPU (hp2100_cpu3.c)
|
||||
|
||||
CONFIGURATION: sim> set CPU FFP
|
||||
sim> set LPS diag
|
||||
|
@ -636,10 +724,10 @@ TEST RESULT: Passed.
|
|||
|
||||
|
||||
----------------------------------------------
|
||||
DSN 101115 - M/E-Series Fast FORTRAN Package 2
|
||||
DSN 101114 - M/E-Series Fast FORTRAN Package 2
|
||||
----------------------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu1.c)
|
||||
TESTED DEVICE: CPU (hp2100_cpu3.c)
|
||||
|
||||
CONFIGURATION: sim> set CPU FFP
|
||||
sim> set LPS diag
|
||||
|
@ -675,11 +763,127 @@ TEST RESULT: Passed.
|
|||
|
||||
|
||||
|
||||
---------------------------------
|
||||
DSN 101121 - F-Series FPP/SIS/FFP
|
||||
---------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu3.c)
|
||||
|
||||
CONFIGURATION: sim> set CPU 1000-F
|
||||
sim> set LPS diag
|
||||
|
||||
sim> deposit S 000014
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
HALT instruction 102074
|
||||
|
||||
sim> deposit S 000000
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
TEST REPORT: FPP-SIS-FFP DIAGNOSTIC DSN 101121
|
||||
BEGIN BASIC CONTROL TEST
|
||||
OVFL TEST
|
||||
CONF TEST
|
||||
BASE RETN TEST
|
||||
SIS1 RETN TEST
|
||||
SIS2 RETN TEST
|
||||
SIS3 RETN TEST
|
||||
FPP1 RETN TEST
|
||||
FFP2 RETN TEST
|
||||
FFP3 RETN TEST
|
||||
END BASIC CONTROL TEST
|
||||
LONG PASSES
|
||||
FIXS TEST
|
||||
FIXD TEST
|
||||
FLTS TEST
|
||||
FLTD TEST
|
||||
ADD TEST
|
||||
SUB TEST
|
||||
MPY TEST
|
||||
DIV TEST
|
||||
ACC TEST
|
||||
SIS1 TEST
|
||||
SIS2 TEST
|
||||
SIS3 TEST
|
||||
FFP1 TEST
|
||||
FFP2 TEST
|
||||
FFP3 TEST
|
||||
PASS 00001
|
||||
|
||||
HALT instruction 102077
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
------------------------------------------------
|
||||
DSN 101016 - 2000/Access Comm Processor for 2100
|
||||
------------------------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu2.c)
|
||||
|
||||
BINARY TAPE: 13206-16001 Rev. 1526
|
||||
|
||||
CONFIGURATION: sim> set CPU 2100
|
||||
sim> set CPU 32K
|
||||
sim> set CPU IOP
|
||||
|
||||
sim> deposit S 000013
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
HALT instruction 102074
|
||||
|
||||
sim> deposit S 000000
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
TEST REPORT: 2100 2000-ACCESS COMM. PROC. FIRMWARE DIAGNOSTIC
|
||||
H030 CRC TEST
|
||||
H040 ENQ, DEQ AND PENQ TESTS
|
||||
H060 IAL TEST
|
||||
H110 READF, SAVE AND RESTR TESTS
|
||||
H120 LAI AND SAI TESTS
|
||||
H130 PFREX TEST
|
||||
H140 PFREI TEST
|
||||
H150 PFRIO TEST
|
||||
H160 STORE-LOAD BYTE, TRSLT
|
||||
AND BYTE MOVE TEST
|
||||
|
||||
TEST 10
|
||||
E165 TRSLT NOT INTERRUPTIBLE
|
||||
|
||||
HALT instruction 106065
|
||||
|
||||
sim> go
|
||||
|
||||
H230 WORD MOVE TEST
|
||||
|
||||
TEST 11
|
||||
E234 WORD MOVE NOT INTERRUPTIBLE
|
||||
|
||||
HALT instruction 103034
|
||||
|
||||
sim> go
|
||||
|
||||
PASS 000001
|
||||
|
||||
HALT instruction 102077
|
||||
|
||||
TEST RESULT: Partially passed.
|
||||
|
||||
TEST NOTES: Tests 10 and 11 test the interruptibility of the TRSLT and MWORD
|
||||
instructions. These features are not simulated.
|
||||
|
||||
|
||||
|
||||
----------------------------------
|
||||
DSN 102103 - Memory Expansion Unit
|
||||
----------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu.c)
|
||||
TESTED DEVICE: CPU (hp2100_cpu2.c)
|
||||
|
||||
CONFIGURATION: sim> set LPS diag
|
||||
sim> deposit S 000014
|
||||
|
@ -812,6 +1016,109 @@ TEST RESULT: Not tested.
|
|||
|
||||
|
||||
|
||||
------------------------------
|
||||
DSN 105101 - 2767 Line Printer
|
||||
------------------------------
|
||||
|
||||
TESTED DEVICE: LPS (hp2100_lps.c)
|
||||
|
||||
BINARY TAPE: 12984-16001 Rev. 1611
|
||||
|
||||
CONFIGURATION: sim> set LPS realtime
|
||||
sim> attach LPS scratch.2767.printer
|
||||
sim> deposit S 000014
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
HALT instruction 102074
|
||||
|
||||
sim> deposit S 000000
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
TEST REPORT: 2767 L.P. DIAGNOSTIC
|
||||
H024 PRESS PRESET (EXT&INT),RUN
|
||||
|
||||
HALT instruction 102024
|
||||
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
H025 BI-O COMP
|
||||
H035 TURN OFF L.P. POWER
|
||||
|
||||
HALT instruction 102035
|
||||
|
||||
sim> set LPS poweroff
|
||||
sim> go
|
||||
|
||||
H036 TURN ON L.P. POWER
|
||||
|
||||
HALT instruction 102036
|
||||
|
||||
sim> set LPS poweron
|
||||
sim> go
|
||||
|
||||
H033 PUT L.P. ON-LINE
|
||||
|
||||
HALT instruction 102033
|
||||
|
||||
sim> set LPS online
|
||||
sim> go
|
||||
|
||||
H034 MASTER CLEAR L.P.
|
||||
|
||||
HALT instruction 102034
|
||||
|
||||
sim> set LPS offline
|
||||
sim> go
|
||||
|
||||
H033 PUT L.P. ON-LINE
|
||||
|
||||
HALT instruction 102033
|
||||
|
||||
sim> set LPS online
|
||||
sim> go
|
||||
|
||||
H040 PUT L.P. OFF-LINE. TOGGLE TOP-OF-FORM SWITCH
|
||||
|
||||
HALT instruction 102040
|
||||
|
||||
sim> set LPS offline
|
||||
sim> go
|
||||
|
||||
H033 PUT L.P. ON-LINE
|
||||
|
||||
HALT instruction 102033
|
||||
|
||||
sim> set LPS online
|
||||
sim> go
|
||||
|
||||
H041 PUT L.P. OFF-LINE. TOGGLE PAPER-STEP 5 TIMES
|
||||
|
||||
HALT instruction 102041
|
||||
|
||||
sim> set LPS offline
|
||||
sim> go
|
||||
|
||||
H033 PUT L.P. ON-LINE
|
||||
|
||||
HALT instruction 102033
|
||||
|
||||
sim> set LPS online
|
||||
sim> go
|
||||
|
||||
PASS 000001
|
||||
|
||||
HALT instruction 102077
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
TEST NOTES: The simulation provides no manual Master Clear, Top of Form, or
|
||||
Paper Step functions, so these are merely presumed above.
|
||||
|
||||
|
||||
|
||||
------------------------------
|
||||
DSN 105102 - 2607 Line Printer
|
||||
------------------------------
|
||||
|
@ -2125,7 +2432,7 @@ Each execution note below presumes that the target diagnostic has been loaded.
|
|||
For all runs, the diagnostic configurator was used in automatic mode to load the
|
||||
target diagnostic from a paper tape image, as follows:
|
||||
|
||||
sim> attach -r MSC0 24396-13601-REV-2040.tape
|
||||
sim> attach -r MSC0 24396-13601_Rev-2236.abin.tape
|
||||
sim> deposit S 000000
|
||||
sim> boot MSC0
|
||||
|
||||
|
@ -2138,109 +2445,6 @@ target diagnostic from a paper tape image, as follows:
|
|||
|
||||
|
||||
|
||||
------------------------------
|
||||
DSN 105101 - 2767 Line Printer
|
||||
------------------------------
|
||||
|
||||
TESTED DEVICE: LPS (hp2100_lps.c)
|
||||
|
||||
BINARY TAPE: 12984-16001 Rev. 1611
|
||||
|
||||
CONFIGURATION: sim> set LPS realtime
|
||||
sim> attach LPS scratch.2767.printer
|
||||
sim> deposit S 000014
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
HALT instruction 102074
|
||||
|
||||
sim> deposit S 000000
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
TEST REPORT: 2767 L.P. DIAGNOSTIC
|
||||
H024 PRESS PRESET (EXT&INT),RUN
|
||||
|
||||
HALT instruction 102024
|
||||
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
H025 BI-O COMP
|
||||
H035 TURN OFF L.P. POWER
|
||||
|
||||
HALT instruction 102035
|
||||
|
||||
sim> set LPS poweroff
|
||||
sim> go
|
||||
|
||||
H036 TURN ON L.P. POWER
|
||||
|
||||
HALT instruction 102036
|
||||
|
||||
sim> set LPS poweron
|
||||
sim> go
|
||||
|
||||
H033 PUT L.P. ON-LINE
|
||||
|
||||
HALT instruction 102033
|
||||
|
||||
sim> set LPS online
|
||||
sim> go
|
||||
|
||||
H034 MASTER CLEAR L.P.
|
||||
|
||||
HALT instruction 102034
|
||||
|
||||
sim> set LPS offline
|
||||
sim> go
|
||||
|
||||
H033 PUT L.P. ON-LINE
|
||||
|
||||
HALT instruction 102033
|
||||
|
||||
sim> set LPS online
|
||||
sim> go
|
||||
|
||||
H040 PUT L.P. OFF-LINE. TOGGLE TOP-OF-FORM SWITCH
|
||||
|
||||
HALT instruction 102040
|
||||
|
||||
sim> set LPS offline
|
||||
sim> go
|
||||
|
||||
H033 PUT L.P. ON-LINE
|
||||
|
||||
HALT instruction 102033
|
||||
|
||||
sim> set LPS online
|
||||
sim> go
|
||||
|
||||
H041 PUT L.P. OFF-LINE. TOGGLE PAPER-STEP 5 TIMES
|
||||
|
||||
HALT instruction 102041
|
||||
|
||||
sim> set LPS offline
|
||||
sim> go
|
||||
|
||||
H033 PUT L.P. ON-LINE
|
||||
|
||||
HALT instruction 102033
|
||||
|
||||
sim> set LPS online
|
||||
sim> go
|
||||
|
||||
PASS 000001
|
||||
|
||||
HALT instruction 102077
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
TEST NOTES: The simulation provides no manual Master Clear, Top of Form, or
|
||||
Paper Step functions, so these are merely presumed above.
|
||||
|
||||
|
||||
|
||||
-----------------------------------------------------------------
|
||||
DSN (none) - HP2100A Cartridge Disc Memory (2871) (multiple unit)
|
||||
-----------------------------------------------------------------
|
||||
|
@ -2876,75 +3080,16 @@ TEST RESULT: Passed.
|
|||
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
DSN 101016 - 2000/Access Comm. Processor Firmware
|
||||
-------------------------------------------------
|
||||
------------------------------------------------
|
||||
DSN 101217 - 2000/Access Comm Processor for 21MX
|
||||
------------------------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu.c)
|
||||
|
||||
BINARY TAPE: 13206-16001 Rev. 1526
|
||||
|
||||
CONFIGURATION: sim> set CPU 2100
|
||||
sim> set CPU 32K
|
||||
sim> set CPU IOP
|
||||
sim> deposit S 000013
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
HALT instruction 102074
|
||||
|
||||
sim> deposit S 000000
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
TEST REPORT: 2100 2000-ACCESS COMM. PROC. FIRMWARE DIAGNOSTIC
|
||||
H030 CRC TEST
|
||||
H040 ENQ, DEQ AND PENQ TESTS
|
||||
H060 IAL TEST
|
||||
H110 READF, SAVE AND RESTR TESTS
|
||||
H120 LAI AND SAI TESTS
|
||||
H130 PFREX TEST
|
||||
H140 PFREI TEST
|
||||
H150 PFRIO TEST
|
||||
H160 STORE-LOAD BYTE, TRSLT
|
||||
AND BYTE MOVE TEST
|
||||
|
||||
TEST 10
|
||||
E165 TRSLT NOT INTERRUPTIBLE
|
||||
|
||||
HALT instruction 106065
|
||||
|
||||
sim> go
|
||||
|
||||
H230 WORD MOVE TEST
|
||||
|
||||
TEST 11
|
||||
E234 WORD MOVE NOT INTERRUPTIBLE
|
||||
|
||||
HALT instruction 103034
|
||||
|
||||
sim> go
|
||||
|
||||
PASS 000001
|
||||
|
||||
HALT instruction 102077
|
||||
|
||||
TEST RESULT: Partially passed.
|
||||
|
||||
TEST NOTES: Tests 10 and 11 test the interruptibility of the TRSLT and MWORD
|
||||
instructions. These features are not simulated.
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
DSN 101217 - 2000/Access Comm. Processor Firmware
|
||||
-------------------------------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp2100_cpu.c)
|
||||
TESTED DEVICE: CPU (hp2100_cpu2.c)
|
||||
|
||||
BINARY TAPE: 13207-16001 Rev. 1728
|
||||
|
||||
CONFIGURATION: sim> set CPU IOP
|
||||
|
||||
sim> deposit S 000013
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_dp.c: HP 2100 12557A/13210A disk simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2006, 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"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
dp 12557A 2871 disk subsystem
|
||||
13210A 7900 disk subsystem
|
||||
|
||||
28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
|
||||
01-Mar-05 JDB Added SET UNLOAD/LOAD
|
||||
07-Oct-04 JDB Fixed enable/disable from either device
|
||||
Fixed ANY ERROR status for 12557A interface
|
||||
|
@ -395,6 +396,7 @@ switch (inst) { /* case on opcode */
|
|||
dat = dpd_ibuf;
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCTL (devd); /* clr ctl, cmd */
|
||||
|
@ -449,6 +451,7 @@ switch (inst) { /* case on opcode */
|
|||
if (!dp_ctype) break;
|
||||
IR = IR | I_CTL; /* 13210 OTx causes CLC */
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC? */
|
||||
clrCTL (devc); /* clr cmd, ctl */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_dq.c: HP 2100 12565A disk simulator
|
||||
|
||||
Copyright (c) 1993-2005, Bill McDermith
|
||||
Copyright (c) 1993-2006, Bill McDermith
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
dq 12565A 2883 disk system
|
||||
|
||||
28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
|
||||
01-Mar-05 JDB Added SET UNLOAD/LOAD
|
||||
07-Oct-04 JDB Fixed enable/disable from either device
|
||||
Shortened xtime from 5 to 3 (drive avg 156KW/second)
|
||||
|
@ -313,6 +314,7 @@ switch (inst) { /* case on opcode */
|
|||
dat = dqd_ibuf;
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCTL (devd); /* clr ctl, cmd */
|
||||
|
@ -363,6 +365,7 @@ switch (inst) { /* case on opcode */
|
|||
case ioMIX: /* merge */
|
||||
break; /* no data */
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC? */
|
||||
clrCMD (devc); /* clr cmd, ctl */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_dr.c: HP 2100 12606B/12610B fixed head disk/drum simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2006, 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"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
dr 12606B 2770/2771 fixed head disk
|
||||
12610B 2773/2774/2775 drum
|
||||
|
||||
28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
|
||||
07-Oct-04 JDB Fixed enable/disable from either device
|
||||
Fixed sector return in status word
|
||||
Provided protected tracks and "Writing Enabled" status bit
|
||||
|
@ -331,6 +332,7 @@ switch (inst) { /* case on opcode */
|
|||
dat = drd_ibuf;
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_AB) { /* CLC */
|
||||
clrCMD (devd); /* clr "ctl" */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_ds.c: HP 2100 13037 disk controller simulator
|
||||
|
||||
Copyright (c) 2004-2005, Robert M. Supnik
|
||||
Copyright (c) 2004-2006, 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"),
|
||||
|
@ -25,6 +25,9 @@
|
|||
|
||||
ds 13037 disk controller
|
||||
|
||||
28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
|
||||
03-Aug-06 JDB Fixed REQUEST STATUS command to clear status-1
|
||||
Removed redundant attached test in "ds_detach"
|
||||
18-Mar-05 RMS Added attached test to detach routine
|
||||
01-Mar-05 JDB Added SET UNLOAD/LOAD
|
||||
|
||||
|
@ -595,6 +598,7 @@ switch (inst) { /* case on opcode */
|
|||
dat = ds_fifo_read ();
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCTL (dev); /* clear control */
|
||||
|
@ -705,7 +709,8 @@ switch (op) {
|
|||
|
||||
case DSC_RSTA: /* read status */
|
||||
dsxb[1] = ds_sr1; /* return SR1 */
|
||||
if (unum < DS_NUMDR) { /* and SR2 */
|
||||
ds_sr1 = 0; /* clear SR1 */
|
||||
if (unum < DS_NUMDR) { /* return SR2 */
|
||||
dsxb[0] = ds_updds2 (&ds_unit[unum]);
|
||||
ds_unit[unum].STA &= ~DS2_FS; /* clear 1st */
|
||||
}
|
||||
|
@ -1460,8 +1465,7 @@ return SCPE_OK;
|
|||
|
||||
t_stat ds_detach (UNIT *uptr)
|
||||
{
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
|
||||
ds_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */
|
||||
ds_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads if attached */
|
||||
return detach_unit (uptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_fp.c: HP 2100 floating point instructions
|
||||
|
||||
Copyright (c) 2002-2005, Robert M. Supnik
|
||||
Copyright (c) 2002-2006, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
01-Dec-06 JDB Reworked FFP helpers for 1000-F support, deleted f_pwr2
|
||||
22-Jul-05 RMS Fixed compiler warning in Solaris (from Doug Glyn)
|
||||
25-Feb-05 JDB Added FFP helpers f_pack, f_unpack, f_pwr2
|
||||
11-Feb-05 JDB Fixed missing negative overflow renorm in StoreFP
|
||||
|
@ -30,6 +31,16 @@
|
|||
15-Jul-03 RMS Fixed signed/unsigned warning
|
||||
21-Oct-02 RMS Recoded for compatibility with 21MX microcode algorithms
|
||||
|
||||
|
||||
Implementation note: The 2100/1000-M/E Fast FORTRAN Processor (FFP) and 1000
|
||||
F-Series Floating Point Processor (FPP) simulations require that the host
|
||||
compiler support 64-bit integers and the HAVE_INT64 symbol be defined during
|
||||
compilation. If this symbol is defined, two-word floating-point operations
|
||||
are handled in the FPP code, and this module is not used. If it is not
|
||||
defined, then FFP and FPP operations are not available, and this module
|
||||
provides the floating-point support.
|
||||
|
||||
|
||||
The HP2100 uses a unique binary floating point format:
|
||||
|
||||
15 14 0
|
||||
|
@ -69,6 +80,10 @@
|
|||
*/
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu1.h"
|
||||
#include "hp2100_fp.h"
|
||||
|
||||
#if !defined (HAVE_INT64) /* int64 support unavailable */
|
||||
|
||||
struct ufp { /* unpacked fp */
|
||||
int32 exp; /* exp */
|
||||
|
@ -98,8 +113,6 @@ struct ufp { /* unpacked fp */
|
|||
|
||||
#define FPAB ((((uint32) AR) << 16) | ((uint32) BR))
|
||||
|
||||
#define DMASK32 0xFFFFFFFF
|
||||
|
||||
/* Fraction shift; 0 < shift < 32 */
|
||||
|
||||
#define FR_ARS(v,s) (((v) >> (s)) | (((v) & FP_SIGN)? \
|
||||
|
@ -112,6 +125,7 @@ extern uint16 ABREG[2];
|
|||
uint32 UnpackFP (struct ufp *fop, uint32 opnd);
|
||||
void NegFP (struct ufp *fop);
|
||||
void NormFP (struct ufp *fop);
|
||||
uint32 PackFP (struct ufp *fop);
|
||||
uint32 StoreFP (struct ufp *fop);
|
||||
|
||||
/* Floating to integer conversion */
|
||||
|
@ -275,47 +289,6 @@ if (fop1.fr) { /* dvd != 0? */
|
|||
return StoreFP (&quo); /* store result */
|
||||
}
|
||||
|
||||
/* Fast FORTRAN Processor helpers. */
|
||||
|
||||
/* Pack mantissa in A/B and exponent and return fp in A/B */
|
||||
|
||||
uint32 f_pack (int32 expon)
|
||||
{
|
||||
struct ufp fop;
|
||||
|
||||
fop.fr = FPAB;
|
||||
fop.exp = expon;
|
||||
return StoreFP (&fop);
|
||||
}
|
||||
|
||||
/* Unpack fp number in A/B into A (exponent) and B (lower mantissa) */
|
||||
|
||||
void f_unpack (void)
|
||||
{
|
||||
AR = FP_GETEXP (BR); /* get exponent */
|
||||
if (FP_GETEXPS (BR)) AR = (AR | ~FP_M_EXP) & DMASK; /* < 0? sext */
|
||||
BR = BR & (uint16) ~(FP_EXP | FP_EXPS); /* clear exp */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Multiply fp number in A/B by 2**n and return in A/B.
|
||||
Exponent overflow or underflow wraps around. */
|
||||
|
||||
void f_pwr2 (int32 n)
|
||||
{
|
||||
uint32 save_a;
|
||||
|
||||
if (AR | BR) { /* microcode test */
|
||||
save_a = AR;
|
||||
f_unpack (); /* unpack exponent */
|
||||
AR = AR + n; /* multiply */
|
||||
BR = BR | ((AR & FP_M_EXP) << FP_V_EXP) | /* merge exponent */
|
||||
((AR & SIGN)? (1 << FP_V_EXPS): 0); /* and exponent sign */
|
||||
AR = save_a;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Utility routines */
|
||||
|
||||
/* Unpack operand */
|
||||
|
@ -343,6 +316,15 @@ else fop->exp = 0; /* clean 0 */
|
|||
return;
|
||||
}
|
||||
|
||||
/* Pack fp number */
|
||||
|
||||
uint32 PackFP (struct ufp *fop)
|
||||
{
|
||||
return (fop->fr & FP_FR) | /* merge frac */
|
||||
((fop->exp & FP_M_EXP) << FP_V_EXP) | /* and exp */
|
||||
((fop->exp < 0)? (1 << FP_V_EXPS): 0); /* add exp sign */
|
||||
}
|
||||
|
||||
/* Round fp number, store, generate overflow */
|
||||
|
||||
uint32 StoreFP (struct ufp *fop)
|
||||
|
@ -367,10 +349,58 @@ else if (fop->exp > FP_M_EXP) { /* overflow? */
|
|||
hi = 0x7FFFFFFE; /* all 1's */
|
||||
ov = 1;
|
||||
}
|
||||
else hi = (fop->fr & FP_FR) | /* merge frac */
|
||||
((fop->exp & FP_M_EXP) << FP_V_EXP) | /* and exp */
|
||||
((fop->exp < 0)? (1 << FP_V_EXPS): 0); /* add exp sign */
|
||||
else hi = PackFP (fop); /* pack mant and exp */
|
||||
AR = (hi >> 16) & DMASK;
|
||||
BR = hi & DMASK;
|
||||
return ov;
|
||||
}
|
||||
|
||||
|
||||
/* Single-precision Fast FORTRAN Processor helpers. */
|
||||
|
||||
/* Pack mantissa and exponent and return fp value. */
|
||||
|
||||
uint32 fp_pack (OP *result, OP mantissa, int32 exponent, OPSIZE precision)
|
||||
{
|
||||
struct ufp fop;
|
||||
uint32 val;
|
||||
|
||||
fop.fr = ((uint32) mantissa.fpk[0] << 16) | mantissa.fpk[1];
|
||||
fop.exp = exponent;
|
||||
val = PackFP (&fop);
|
||||
result->fpk[0] = (int16) (val >> 16);
|
||||
result->fpk[1] = (int16) val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Normalize, round, and pack mantissa and exponent and return fp value. */
|
||||
|
||||
uint32 fp_nrpack (OP *result, OP mantissa, int32 exponent, OPSIZE precision)
|
||||
{
|
||||
struct ufp fop;
|
||||
uint32 ovf;
|
||||
|
||||
fop.fr = ((uint32) mantissa.fpk[0] << 16) | mantissa.fpk[1];
|
||||
fop.exp = exponent;
|
||||
ovf = StoreFP (&fop);
|
||||
result->fpk[0] = AR;
|
||||
result->fpk[1] = BR;
|
||||
return ovf;
|
||||
}
|
||||
|
||||
/* Unpack fp number in into mantissa and exponent. */
|
||||
|
||||
uint32 fp_unpack (OP *mantissa, int32 *exponent, OP packed, OPSIZE precision)
|
||||
{
|
||||
struct ufp fop;
|
||||
uint32 operand;
|
||||
|
||||
operand = ((uint32) packed.fpk[0] << 16) | packed.fpk[1];
|
||||
UnpackFP (&fop, operand);
|
||||
mantissa->fpk[0] = (uint16) fop.fr >> 16;
|
||||
mantissa->fpk[1] = (uint16) fop.fr;
|
||||
*exponent = fop.exp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* int64 support unavailable */
|
||||
|
|
47
HP2100/hp2100_fp.h
Normal file
47
HP2100/hp2100_fp.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* hp2100_fp.h: HP 2100/21MX floating point definitions
|
||||
|
||||
Copyright (c) 2002-2006, 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.
|
||||
|
||||
01-Dec-06 JDB Reworked FFP helpers for 1000-F support, deleted f_pwr2
|
||||
26-Sep-06 JDB Moved from hp2100_fp.c to simplify extensions
|
||||
*/
|
||||
|
||||
#ifndef _HP2100_FP_H_
|
||||
#define _HP2100_FP_H_
|
||||
|
||||
/* Firmware floating-point routines */
|
||||
|
||||
uint32 f_as (uint32 op, t_bool sub); /* FAD/FSB */
|
||||
uint32 f_mul (uint32 op); /* FMP */
|
||||
uint32 f_div (uint32 op); /* FDV */
|
||||
uint32 f_fix (void); /* FIX */
|
||||
uint32 f_flt (void); /* FLT */
|
||||
|
||||
/* Firmware FFP helpers */
|
||||
|
||||
uint32 fp_pack (OP *result, OP mantissa, int32 exponent, OPSIZE precision);
|
||||
uint32 fp_nrpack (OP *result, OP mantissa, int32 exponent, OPSIZE precision);
|
||||
uint32 fp_unpack (OP *mantissa, int32 *exponent, OP packed, OPSIZE precision);
|
||||
|
||||
#endif
|
1476
HP2100/hp2100_fp1.c
1476
HP2100/hp2100_fp1.c
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_fp1.h: HP 2100/21MX extended-precision floating point definitions
|
||||
/* hp2100_fp1.h: HP 2100/1000 multiple-precision floating point definitions
|
||||
|
||||
Copyright (c) 2005, J. David Bryan
|
||||
Copyright (c) 2005-2006, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -15,38 +15,39 @@
|
|||
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
|
||||
THE AUTHOR 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 the author shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
Except as contained in this notice, the name of the author shall not be used
|
||||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
16-Oct-06 JDB Generalized FP calling sequences for F-Series
|
||||
12-Oct-06 JDB Altered x_trun for F-Series FFP compatibility
|
||||
*/
|
||||
|
||||
#ifndef _HP2100_FP1_H_
|
||||
#define _HP2100_FP1_H_ 0
|
||||
|
||||
/* HP memory representation of an extended-precision number */
|
||||
|
||||
typedef struct {
|
||||
uint32 high;
|
||||
uint32 low;
|
||||
} XPN;
|
||||
/* Special operands. */
|
||||
|
||||
#define ACCUM NULL /* result not returned */
|
||||
static const OP NOP = { { 0, 0, 0, 0, 0 } }; /* unneeded operand */
|
||||
|
||||
|
||||
#define AS_XPN(x) (*(XPN *) &(x)) /* view as XPN */
|
||||
/* Generalized floating-point handlers. */
|
||||
|
||||
XPN ReadX (uint32 va);
|
||||
void WriteX (uint32 va, XPN packed);
|
||||
|
||||
uint32 x_add (XPN *sum, XPN augend, XPN addend);
|
||||
uint32 x_sub (XPN *difference, XPN minuend, XPN subtrahend);
|
||||
uint32 x_mpy (XPN *product, XPN multiplicand, XPN multiplier);
|
||||
uint32 x_div (XPN *quotient, XPN dividend, XPN divisor);
|
||||
uint32 x_pak (XPN *result, XPN mantissa, int32 exponent);
|
||||
uint32 x_com (XPN *mantissa);
|
||||
uint32 x_dcm (XPN *packed);
|
||||
void x_trun (XPN *result, XPN source);
|
||||
void fp_prec (uint16 opcode, OPSIZE *operand_l, OPSIZE *operand_r, OPSIZE *result);
|
||||
uint32 fp_exec (uint16 opcode, OP *result, OP operand_l, OP operand_r);
|
||||
OP fp_accum (const OP *operand, OPSIZE precision);
|
||||
uint32 fp_pack (OP *result, OP mantissa, int32 exponent, OPSIZE precision);
|
||||
uint32 fp_nrpack (OP *result, OP mantissa, int32 exponent, OPSIZE precision);
|
||||
uint32 fp_unpack (OP *mantissa, int32 *exponent, OP packed, OPSIZE precision);
|
||||
uint32 fp_ucom (OP *mantissa, OPSIZE precision);
|
||||
uint32 fp_pcom (OP *packed, OPSIZE precision);
|
||||
uint32 fp_trun (OP *result, OP source, OPSIZE precision);
|
||||
uint32 fp_cvt (OP *result, OPSIZE source_precision, OPSIZE dest_precision);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_ipl.c: HP 2000 interprocessor link simulator
|
||||
|
||||
Copyright (c) 2002-2005, Robert M Supnik
|
||||
Copyright (c) 2002-2006, 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"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
ipli, iplo 12566B interprocessor link pair
|
||||
|
||||
28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
07-Oct-04 JDB Fixed enable/disable from either device
|
||||
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
||||
|
@ -201,6 +202,7 @@ switch (inst) { /* case on opcode */
|
|||
dat = dat | uptr->IBUF; /* get return data */
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCMD (dev); /* clear ctl, cmd */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_lps.c: HP 2100 12653A line printer simulator
|
||||
/* hp2100_lps.c: HP 2100 12653A/2767 line printer simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2007, 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"),
|
||||
|
@ -24,8 +24,10 @@
|
|||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
lps 12653A 2767 line printer
|
||||
(based on 12566B microcircuit interface)
|
||||
12566B microcircuit interface with loopback diagnostic connector
|
||||
|
||||
11-Jan-07 JDB CLC cancels I/O event if DIAG (jumper W9 in "A" pos)
|
||||
Added ioCRS state to I/O decoders
|
||||
19-Nov-04 JDB Added restart when set online, etc.
|
||||
Fixed col count for non-printing chars
|
||||
01-Oct-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON
|
||||
|
@ -47,6 +49,18 @@
|
|||
Added command flop
|
||||
15-Oct-00 RMS Added variable device number support
|
||||
|
||||
This module simulates two different devices. In "diagnostic mode," it
|
||||
simulates a 12566B microcircuit interface card with a loopback connector and
|
||||
the jumpers set as required for execution of the General Purpose Register
|
||||
diagnostic. In non-diagnostic mode, it simulates a 12653A line printer
|
||||
interface card and a 2767 line printer.
|
||||
|
||||
The 12566B interface with the loopback connector ties the device command
|
||||
output to the device flag input. Setting control therefore causes device
|
||||
flag to set almost immediately. Device command is active only during that
|
||||
interim. Under simulation, the loopback occurs within the STC handler, and
|
||||
CMD is never set.
|
||||
|
||||
The 2767 impact printer has a rotating drum with 80 columns of 64 raised
|
||||
characters. ASCII codes 32 through 95 (SPACE through "_") form the print
|
||||
repertoire. The printer responds to the control characters FF, LF, and CR.
|
||||
|
@ -103,6 +117,7 @@
|
|||
*/
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
|
||||
#define LPS_ZONECNT 20 /* zone char count */
|
||||
#define LPS_PAGECNT 80 /* page char count */
|
||||
|
@ -148,6 +163,13 @@ uint32 lps_power = LPS_ON; /* power state */
|
|||
NOTE: the printer acknowledges before the print motion has stopped to allow
|
||||
for continuous slew, so the set times are a bit less than the calculated
|
||||
operation time from the manual.
|
||||
|
||||
NOTE: the 2767 diagnostic checks completion times, so the realistic timing
|
||||
must be used. Because simulator timing is in instructions, and because the
|
||||
diagnostic uses the TIMER instruction (~1580 executions per millisecond) when
|
||||
running on a 1000-E/F but a software timing loop (~400-600 executions per
|
||||
millisecond) when running on anything else, realistic timings are decreased by
|
||||
three-fourths when not executing on an E/F.
|
||||
*/
|
||||
|
||||
int32 lps_ctime = 0; /* char xfer time */
|
||||
|
@ -280,16 +302,28 @@ switch (inst) { /* case on opcode */
|
|||
fprintf (sim_deb, ">>LPS LIx: Status %06o returned\n", dat);
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset */
|
||||
clrCTL (dev); /* clear control */
|
||||
clrCMD (dev); /* clear command */
|
||||
sim_cancel (&lps_unit); /* deactivate unit */
|
||||
break;
|
||||
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCMD (dev); /* clear ctl, cmd */
|
||||
clrCTL (dev);
|
||||
clrCTL (dev); /* clear control */
|
||||
if (lps_unit.flags & UNIT_DIAG) { /* diagnostic mode? */
|
||||
clrCMD (dev); /* clear command (jumper W9-A) */
|
||||
if (IR & I_HC) /* clear flag too? */
|
||||
sim_cancel (&lps_unit); /* prevent FLG/SRQ */
|
||||
}
|
||||
}
|
||||
else { /* STC */
|
||||
setCMD (dev); /* set ctl, cmd */
|
||||
setCTL (dev);
|
||||
if (lps_unit.flags & UNIT_DIAG) /* diagnostic? */
|
||||
sim_activate (&lps_unit, 1); /* loop back */
|
||||
setCTL (dev); /* set ctl */
|
||||
setCMD (dev); /* set cmd */
|
||||
if (lps_unit.flags & UNIT_DIAG) { /* diagnostic? */
|
||||
lps_sta = lps_unit.buf; /* loop back data */
|
||||
sim_activate (&lps_unit, 2); /* schedule flag */
|
||||
}
|
||||
else { /* real lpt, sched */
|
||||
if (DEBUG_PRS (lps_dev)) fprintf (sim_deb,
|
||||
">>LPS STC: Character %06o scheduled for line %d, column %d, ",
|
||||
|
@ -349,7 +383,6 @@ if (lps_power == LPS_TURNING_ON) { /* printer warmed up? */
|
|||
}
|
||||
dev = lps_dib.devno; /* get dev no */
|
||||
if (uptr->flags & UNIT_DIAG) { /* diagnostic? */
|
||||
lps_sta = uptr->buf; /* loop back */
|
||||
clrCMD (dev); /* clear cmd */
|
||||
setFSR (dev); /* set flag, fbf */
|
||||
return SCPE_OK; /* done */
|
||||
|
@ -465,15 +498,22 @@ lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung *
|
|||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Set printer timing */
|
||||
/* Set printer timing
|
||||
|
||||
Realistic timing is factored, depending on CPU model, to account for the
|
||||
timing method employed by the diagnostic. */
|
||||
|
||||
t_stat lps_set_timing (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 i;
|
||||
uint32 i, factor = 1;
|
||||
|
||||
lps_timing = (val != 0); /* determine choice */
|
||||
if ((lps_timing == 0) && /* calc speed factor */
|
||||
(UNIT_CPU_MODEL != UNIT_1000_E) &&
|
||||
(UNIT_CPU_MODEL != UNIT_1000_F))
|
||||
factor = 4;
|
||||
for (i = 0; i < (sizeof (lps_timers) / sizeof (lps_timers[0])); i++)
|
||||
*lps_timers[i] = lps_times[lps_timing][i]; /* assign times */
|
||||
*lps_timers[i] = lps_times[lps_timing][i] / factor; /* assign times */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_lpt.c: HP 2100 12845B line printer simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2006, 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"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
lpt 12845B 2607 line printer
|
||||
|
||||
28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
|
||||
19-Nov-04 JDB Added restart when set online, etc.
|
||||
29-Sep-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON
|
||||
Fixed status returns for error conditions
|
||||
|
@ -190,6 +191,7 @@ switch (inst) { /* case on opcode */
|
|||
}
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCMD (dev); /* clear ctl, cmd */
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
ms 13181A 7970B 800bpi nine track magnetic tape
|
||||
13183A 7970E 1600bpi nine track magnetic tape
|
||||
|
||||
28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
|
||||
18-Sep-06 JDB Fixed 2nd CLR after WC causing another write
|
||||
Improve debug reporting, add debug flags
|
||||
14-Sep-06 JDB Removed local BOT flag, now uses sim_tape_bot
|
||||
30-Aug-06 JDB Added erase gap support, improved tape lib err reporting
|
||||
07-Jul-06 JDB Added CAPACITY as alternate for REEL
|
||||
Fixed EOT test for unlimited reel size
|
||||
16-Feb-06 RMS Revised for new EOT test
|
||||
|
@ -90,7 +95,17 @@
|
|||
#define UST u4 /* unit status */
|
||||
#define REEL u5 /* tape reel size */
|
||||
|
||||
#define TCAP (300 * 12 * 800) /* 300 ft capacity at 800bpi */
|
||||
#define BPI_13181 800 /* 800 bpi for 13181 cntlr */
|
||||
#define BPI_13183 1600 /* 1600 bpi for 13183 cntlr */
|
||||
#define GAP_13181 48 /* gap is 4.8 inches for 13181 cntlr */
|
||||
#define GAP_13183 30 /* gap is 3.0 inches for 13183 cntlr */
|
||||
#define TCAP (300 * 12 * 800) /* 300 ft capacity at 800 bpi */
|
||||
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_CMDS (1 << 0) /* command init and compl */
|
||||
#define DEB_CPU (1 << 1) /* CPU I/O */
|
||||
#define DEB_RWS (1 << 2) /* tape reads, writes, status */
|
||||
|
||||
/* Command - msc_fnc */
|
||||
|
||||
|
@ -106,7 +121,8 @@
|
|||
#define FNC_REW 00101 /* rewind */
|
||||
#define FNC_RWS 00105 /* rewind and offline */
|
||||
#define FNC_WFM 00211 /* write file mark */
|
||||
#define FNC_RFF 00223 /* "read file fwd" */
|
||||
#define FNC_RFF 00223 /* read file fwd (diag) */
|
||||
#define FNC_RRR 00061 /* read record rev (diag) */
|
||||
#define FNC_CMPL 00400 /* completion state */
|
||||
#define FNC_V_SEL 9 /* select */
|
||||
#define FNC_M_SEL 017
|
||||
|
@ -132,14 +148,15 @@
|
|||
#define STA_TBSY 0001000 /* transport busy (d) */
|
||||
#define STA_BUSY 0000400 /* ctrl busy */
|
||||
#define STA_EOF 0000200 /* end of file */
|
||||
#define STA_BOT 0000100 /* beg of tape (u) */
|
||||
#define STA_BOT 0000100 /* beg of tape (d) */
|
||||
#define STA_EOT 0000040 /* end of tape (d) */
|
||||
#define STA_TIM 0000020 /* timing error */
|
||||
#define STA_REJ 0000010 /* programming error */
|
||||
#define STA_WLK 0000004 /* write locked (d) */
|
||||
#define STA_PAR 0000002 /* parity error */
|
||||
#define STA_LOCAL 0000001 /* local (d) */
|
||||
#define STA_DYN (STA_PE|STA_SEL|STA_TBSY|STA_WLK|STA_LOCAL)
|
||||
#define STA_DYN (STA_PE | STA_SEL | STA_TBSY | STA_BOT | \
|
||||
STA_EOT | STA_WLK | STA_LOCAL)
|
||||
|
||||
extern uint32 PC, SR;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
|
||||
|
@ -151,7 +168,7 @@ int32 ms_timing = 1; /* timing type */
|
|||
int32 msc_sta = 0; /* status */
|
||||
int32 msc_buf = 0; /* buffer */
|
||||
int32 msc_usl = 0; /* unit select */
|
||||
int32 msc_1st = 0;
|
||||
int32 msc_1st = 0; /* first service */
|
||||
int32 msc_stopioe = 1; /* stop on error */
|
||||
int32 msd_buf = 0; /* data buffer */
|
||||
uint8 msxb[DBSIZE] = { 0 }; /* data buffer */
|
||||
|
@ -201,6 +218,7 @@ t_stat msc_attach (UNIT *uptr, char *cptr);
|
|||
t_stat msc_detach (UNIT *uptr);
|
||||
t_stat msc_online (UNIT *uptr, int32 value, char *cptr, void *desc);
|
||||
t_stat msc_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat ms_write_gap (UNIT *uptr);
|
||||
t_stat ms_map_err (UNIT *uptr, t_stat st);
|
||||
t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
@ -209,6 +227,7 @@ t_stat ms_show_timing (FILE *st, UNIT *uptr, int32 val, void *desc);
|
|||
t_stat ms_set_reelsize (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat ms_show_reelsize (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
void ms_config_timing (void);
|
||||
char *ms_cmd_name (uint32 cmd);
|
||||
|
||||
/* MSD data structures
|
||||
|
||||
|
@ -261,6 +280,7 @@ DEVICE msd_dev = {
|
|||
msc_unit MSC unit list
|
||||
msc_reg MSC register list
|
||||
msc_mod MSC modifier list
|
||||
msc_deb MSC debug flags
|
||||
*/
|
||||
|
||||
UNIT msc_unit[] = {
|
||||
|
@ -329,12 +349,20 @@ MTAB msc_mod[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
DEBTAB msc_deb[] = {
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "RWS", DEB_RWS },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
DEVICE msc_dev = {
|
||||
"MSC", msc_unit, msc_reg, msc_mod,
|
||||
MS_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &msc_reset,
|
||||
&msc_boot, &msc_attach, &msc_detach,
|
||||
&msc_dib, DEV_DISABLE | DEV_DEBUG
|
||||
&msc_dib, DEV_DISABLE | DEV_DEBUG,
|
||||
0, msc_deb, NULL, NULL
|
||||
};
|
||||
|
||||
/* IO instructions */
|
||||
|
@ -370,6 +398,7 @@ switch (inst) { /* case on opcode */
|
|||
dat = msd_buf;
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCTL (devd); /* clr ctl, cmd */
|
||||
|
@ -420,7 +449,7 @@ switch (inst) { /* case on opcode */
|
|||
break;
|
||||
|
||||
case ioOTX: /* output */
|
||||
if (DEBUG_PRS (msc_dev))
|
||||
if (DEBUG_PRI (msc_dev, DEB_CPU))
|
||||
fprintf (sim_deb, ">>MSC OTx: Command = %06o\n", dat);
|
||||
msc_buf = dat;
|
||||
msc_sta = msc_sta & ~STA_REJ; /* clear reject */
|
||||
|
@ -432,9 +461,11 @@ switch (inst) { /* case on opcode */
|
|||
if (dat & FNF_CHS) { /* select change */
|
||||
msc_usl = map_sel[FNC_GETSEL (dat)]; /* is immediate */
|
||||
uptr = msc_dev.units + msc_usl;
|
||||
if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>MSC OTx: Unit %d selected\n", msc_usl);
|
||||
}
|
||||
if (((dat & FNF_MOT) && sim_is_active (uptr)) ||
|
||||
((dat & FNF_REV) && (uptr->UST & STA_BOT)) ||
|
||||
((dat & FNF_REV) && sim_tape_bot (uptr)) ||
|
||||
((dat & FNF_WRT) && sim_tape_wrp (uptr)))
|
||||
msc_sta = msc_sta | STA_REJ; /* reject? */
|
||||
break;
|
||||
|
@ -445,30 +476,39 @@ switch (inst) { /* case on opcode */
|
|||
dat = dat | (msc_sta & ~STA_DYN); /* get card status */
|
||||
if ((uptr->flags & UNIT_OFFLINE) == 0) { /* online? */
|
||||
dat = dat | uptr->UST; /* add unit status */
|
||||
if (sim_tape_bot (uptr)) /* BOT? */
|
||||
dat = dat | STA_BOT;
|
||||
if (sim_is_active (uptr) && /* TBSY unless RWD at BOT */
|
||||
!((uptr->FNC & FNF_RWD) && (uptr->UST & STA_BOT)))
|
||||
!((uptr->FNC & FNF_RWD) && sim_tape_bot (uptr)))
|
||||
dat = dat | STA_TBSY;
|
||||
if (sim_tape_wrp (uptr)) /* write prot? */
|
||||
dat = dat | STA_WLK;
|
||||
if (sim_tape_eot (uptr))
|
||||
if (sim_tape_eot (uptr)) /* EOT? */
|
||||
dat = dat | STA_EOT;
|
||||
}
|
||||
else dat = dat | STA_TBSY | STA_LOCAL;
|
||||
if (ms_ctype) dat = dat | STA_PE | /* 13183A? */
|
||||
(msc_usl << STA_V_SEL);
|
||||
if (DEBUG_PRS (msc_dev))
|
||||
if (DEBUG_PRI (msc_dev, DEB_CPU))
|
||||
fprintf (sim_deb, ">>MSC LIx: Status = %06o\n", dat);
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { clrCTL (devc); } /* CLC */
|
||||
else if (!(msc_sta & STA_REJ)) { /* STC, last cmd rejected? */
|
||||
if ((msc_buf & 0377) == FNC_CLR) { /* clear? */
|
||||
for (i = 0; i < MS_NUMDR; i++) { /* loop thru units */
|
||||
if (sim_is_active (&msc_unit[i]) && /* write in prog? */
|
||||
(msc_unit[i].FNC == FNC_WC) && (ms_ptr > 0)) {
|
||||
for (i = 0; i < MS_NUMDR; i++) { /* look for write in progr */
|
||||
if (sim_is_active (&msc_unit[i]) && /* unit active? */
|
||||
(msc_unit[i].FNC == FNC_WC) && /* last cmd write? */
|
||||
(ms_ptr > 0)) { /* partial buffer? */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC STC: Unit %d wrote %d word partial record\n",
|
||||
i, ms_ptr / 2);
|
||||
if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF))
|
||||
ms_map_err (uptr, st);
|
||||
ms_map_err (uptr, st); /* discard any error */
|
||||
ms_ptr = 0; /* clear partial */
|
||||
}
|
||||
if ((msc_unit[i].UST & STA_REW) == 0)
|
||||
sim_cancel (&msc_unit[i]); /* stop if not rew */
|
||||
|
@ -476,34 +516,35 @@ switch (inst) { /* case on opcode */
|
|||
setCTL (devc); /* set CTL for STC */
|
||||
setFSR (devc); /* set FLG for completion */
|
||||
msc_sta = msc_1st = 0; /* clr ctlr status */
|
||||
if (DEBUG_PRS (msc_dev))
|
||||
if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fputs (">>MSC STC: Controller cleared\n", sim_deb);
|
||||
return SCPE_OK;
|
||||
}
|
||||
uptr->FNC = msc_buf & 0377; /* save function */
|
||||
if (uptr->FNC & FNF_RWD) { /* rewind? */
|
||||
if (!(uptr->UST & STA_BOT)) /* not at BOT? */
|
||||
if (!sim_tape_bot (uptr)) /* not at BOT? */
|
||||
uptr->UST = STA_REW; /* set rewinding */
|
||||
sched_time = msc_rtime; /* set response time */
|
||||
}
|
||||
else {
|
||||
if (uptr-> UST & STA_BOT) /* at BOT? */
|
||||
if (sim_tape_bot (uptr)) /* at BOT? */
|
||||
sched_time = msc_btime; /* use BOT start time */
|
||||
else if ((uptr->FNC == FNC_GAP) || (uptr->FNC == FNC_GFM))
|
||||
sched_time = msc_gtime; /* use gap traversal time */
|
||||
else sched_time = 0;
|
||||
if (uptr->FNC != FNC_GAP)
|
||||
sched_time += msc_ctime; /* add base command time */
|
||||
if (uptr->FNC & FNF_MOT) /* motion command? */
|
||||
uptr->UST = 0; /* clear BOT status */
|
||||
}
|
||||
if (msc_buf & ~FNC_SEL) { /* NOP for unit sel alone */
|
||||
sim_activate (uptr, sched_time); /* else schedule op */
|
||||
if (DEBUG_PRS (msc_dev)) fprintf (sim_deb,
|
||||
">>MSC STC: Unit %d command %03o scheduled, time = %d\n",
|
||||
msc_usl, uptr->FNC, sched_time);
|
||||
if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC STC: Unit %d command %03o (%s) scheduled, "
|
||||
"pos = %d, time = %d\n",
|
||||
msc_usl, uptr->FNC, ms_cmd_name (uptr->FNC),
|
||||
uptr->pos, sched_time);
|
||||
}
|
||||
else if (DEBUG_PRS (msc_dev))
|
||||
else if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fputs (">>MSC STC: Unit select (NOP)\n", sim_deb);
|
||||
msc_sta = STA_BUSY; /* ctrl is busy */
|
||||
msc_1st = 1;
|
||||
|
@ -526,9 +567,17 @@ return dat;
|
|||
/* Unit service
|
||||
|
||||
If rewind done, reposition to start of tape, set status
|
||||
else, do operation, set done, interrupt
|
||||
else, do operation, set done, interrupt.
|
||||
|
||||
Can't be write locked, can only write lock detached unit
|
||||
In addition to decreasing the timing intervals, the FASTTIME option enables
|
||||
two additional optimizations: WFM for GFM substitution, and BOT gap
|
||||
elimination. If FASTTIME is selected, gap and file mark (GFM) commands are
|
||||
processed as WFM (write file mark) commands. That is, the preceding GAP is
|
||||
not performed. Also, the initial gap that normally precedes the first data
|
||||
record or EOF mark at the beginning of the tape is omitted. These omissions
|
||||
result in smaller tape image files. If REALTIME is selected, the gaps are
|
||||
included. Note that the gaps (and realistic timing) are necessary to pass
|
||||
the 7970 diagnostics.
|
||||
*/
|
||||
|
||||
t_stat msc_svc (UNIT *uptr)
|
||||
|
@ -552,7 +601,7 @@ switch (uptr->FNC) { /* case on function */
|
|||
case FNC_RWS: /* rewind offline */
|
||||
sim_tape_rewind (uptr); /* rewind tape */
|
||||
uptr->flags = uptr->flags | UNIT_OFFLINE; /* set offline */
|
||||
uptr->UST = STA_BOT; /* BOT when online again */
|
||||
uptr->UST = 0; /* clear REW status */
|
||||
break; /* we're done */
|
||||
|
||||
case FNC_REW: /* rewind */
|
||||
|
@ -564,19 +613,43 @@ switch (uptr->FNC) { /* case on function */
|
|||
|
||||
case FNC_REW | FNC_CMPL: /* complete rewind */
|
||||
sim_tape_rewind (uptr); /* rewind tape */
|
||||
uptr->UST = STA_BOT; /* set BOT status */
|
||||
uptr->UST = 0; /* clear REW status */
|
||||
return SCPE_OK; /* drive is free */
|
||||
|
||||
case FNC_GFM: /* gap file mark */
|
||||
case FNC_GFM: /* gap + file mark */
|
||||
if (ms_timing == 1) /* fast timing? */
|
||||
goto DO_WFM; /* do plain file mark */
|
||||
/* else fall into GAP */
|
||||
case FNC_GAP: /* erase gap */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote gap\n",
|
||||
unum);
|
||||
if ((r = ms_write_gap (uptr)) || /* write tape gap; error? */
|
||||
(uptr->FNC != FNC_GFM)) /* not GFM? */
|
||||
break; /* bail out now */
|
||||
/* else drop into WFM */
|
||||
case FNC_WFM: /* write file mark */
|
||||
if ((ms_timing == 0) && sim_tape_bot (uptr)) { /* realistic timing + BOT? */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote initial gap\n",
|
||||
unum);
|
||||
if (st = ms_write_gap (uptr)) { /* write initial gap; error? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
break; /* terminate operation */
|
||||
}
|
||||
}
|
||||
DO_WFM:
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote file mark\n",
|
||||
unum);
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
msc_sta = STA_EOF; /* set EOF status */
|
||||
break;
|
||||
|
||||
case FNC_GAP: /* erase gap */
|
||||
break;
|
||||
|
||||
case FNC_FSR: /* space forward */
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
|
@ -606,8 +679,12 @@ switch (uptr->FNC) { /* case on function */
|
|||
case FNC_RFF: /* diagnostic read */
|
||||
case FNC_RC: /* read */
|
||||
if (msc_1st) { /* first svc? */
|
||||
msc_1st = ms_ptr = 0; /* clr 1st flop */
|
||||
msc_1st = ms_ptr = ms_max = 0; /* clr 1st flop */
|
||||
st = sim_tape_rdrecf (uptr, msxb, &ms_max, DBSIZE); /* read rec */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d read %d word record\n",
|
||||
unum, ms_max / 2);
|
||||
if (st == MTSE_RECE) msc_sta = msc_sta | STA_PAR; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
|
@ -619,8 +696,6 @@ switch (uptr->FNC) { /* case on function */
|
|||
break; /* err, done */
|
||||
}
|
||||
if (ms_ctype) msc_sta = msc_sta | STA_ODD; /* set ODD for 13183A */
|
||||
if (DEBUG_PRS (msc_dev)) fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d read %d word record\n", unum, ms_max / 2);
|
||||
}
|
||||
if (CTL (devd) && (ms_ptr < ms_max)) { /* DCH on, more data? */
|
||||
if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR;
|
||||
|
@ -638,14 +713,29 @@ switch (uptr->FNC) { /* case on function */
|
|||
else uptr->FNC |= FNC_CMPL; /* set completion */
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_RFF | FNC_CMPL: /* diagnostic read completion */
|
||||
case FNC_RC | FNC_CMPL: /* read completion */
|
||||
break;
|
||||
|
||||
case FNC_WC: /* write */
|
||||
if (msc_1st) msc_1st = ms_ptr = 0; /* no xfer on first */
|
||||
if (msc_1st) { /* first service? */
|
||||
msc_1st = ms_ptr = 0; /* no data xfer on first svc */
|
||||
if ((ms_timing == 0) && sim_tape_bot (uptr)) { /* realistic timing + BOT? */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote initial gap\n",
|
||||
unum);
|
||||
if (st = ms_write_gap (uptr)) { /* write initial gap; error? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
break; /* terminate operation */
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* not 1st, next char */
|
||||
if (ms_ptr < DBSIZE) { /* room in buffer? */
|
||||
msxb[ms_ptr] = msd_buf >> 8; /* store 2 char */
|
||||
msxb[ms_ptr + 1] = msd_buf & 0377;
|
||||
ms_ptr = ms_ptr + 2;
|
||||
uptr->UST = 0;
|
||||
}
|
||||
else msc_sta = msc_sta | STA_PAR;
|
||||
}
|
||||
|
@ -655,8 +745,10 @@ switch (uptr->FNC) { /* case on function */
|
|||
return SCPE_OK;
|
||||
}
|
||||
if (ms_ptr) { /* any data? write */
|
||||
if (DEBUG_PRS (msc_dev)) fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote %d word record\n", unum, ms_ptr / 2);
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote %d word record\n",
|
||||
unum, ms_ptr / 2);
|
||||
if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr)) { /* write, err? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
@ -666,31 +758,63 @@ switch (uptr->FNC) { /* case on function */
|
|||
uptr->FNC |= FNC_CMPL; /* set completion */
|
||||
return SCPE_OK;
|
||||
|
||||
default: /* unknown */
|
||||
case FNC_WC | FNC_CMPL: /* write completion */
|
||||
break;
|
||||
|
||||
case FNC_RRR: /* not supported */
|
||||
default: /* unknown command */
|
||||
if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d command %03o is unknown (NOP)\n",
|
||||
unum, uptr->FNC);
|
||||
break;
|
||||
}
|
||||
|
||||
setFSR (devc); /* set cch flg */
|
||||
msc_sta = msc_sta & ~STA_BUSY; /* update status */
|
||||
if (DEBUG_PRS (msc_dev)) fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d command %03o complete\n", unum, uptr->FNC & 0377);
|
||||
if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d command %03o (%s) complete\n",
|
||||
unum, uptr->FNC & 0377, ms_cmd_name (uptr->FNC));
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Write an erase gap */
|
||||
|
||||
t_stat ms_write_gap (UNIT *uptr)
|
||||
{
|
||||
t_stat st;
|
||||
uint32 gap_len = ms_ctype ? GAP_13183 : GAP_13181; /* establish gap length */
|
||||
uint32 tape_bpi = ms_ctype ? BPI_13183 : BPI_13181; /* establish nominal bpi */
|
||||
|
||||
if (st = sim_tape_wrgap (uptr, gap_len, tape_bpi)) /* write gap */
|
||||
return ms_map_err (uptr, st); /* map error if failure */
|
||||
else
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Map tape error status */
|
||||
|
||||
t_stat ms_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
int32 unum = uptr - msc_dev.units; /* get unit number */
|
||||
|
||||
if (DEBUG_PRS (msc_dev)) fprintf (sim_deb,
|
||||
">>MSC err: Unit %d tape library status = %d\n", unum, st);
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC err: Unit %d tape library status = %d\n",
|
||||
unum, st);
|
||||
|
||||
switch (st) {
|
||||
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
msc_sta = msc_sta | STA_REJ; /* reject cmd */
|
||||
return SCPE_FMT; /* format error */
|
||||
|
||||
case MTSE_UNATT: /* unattached */
|
||||
msc_sta = msc_sta | STA_REJ; /* reject */
|
||||
msc_detach (uptr); /* resync status (ignore rtn) */
|
||||
msc_sta = msc_sta | STA_REJ; /* reject cmd */
|
||||
return SCPE_UNATT; /* unit unattached */
|
||||
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR; /* never get here! */
|
||||
|
||||
|
@ -712,10 +836,6 @@ switch (st) {
|
|||
msc_sta = msc_sta | STA_PAR; /* error */
|
||||
break;
|
||||
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
msc_sta = msc_sta | STA_BOT; /* set BOT status */
|
||||
break;
|
||||
|
||||
case MTSE_WRP: /* write protect */
|
||||
msc_sta = msc_sta | STA_REJ; /* reject */
|
||||
break;
|
||||
|
@ -745,9 +865,7 @@ for (i = 0; i < MS_NUMDR; i++) {
|
|||
uptr = msc_dev.units + i;
|
||||
sim_tape_reset (uptr);
|
||||
sim_cancel (uptr);
|
||||
if ((uptr->flags & UNIT_ATT) && sim_tape_bot (uptr))
|
||||
uptr->UST = STA_BOT;
|
||||
else uptr->UST = 0;
|
||||
uptr->UST = 0;
|
||||
}
|
||||
ms_config_timing ();
|
||||
return SCPE_OK;
|
||||
|
@ -760,10 +878,8 @@ t_stat msc_attach (UNIT *uptr, char *cptr)
|
|||
t_stat r;
|
||||
|
||||
r = sim_tape_attach (uptr, cptr); /* attach unit */
|
||||
if (r == SCPE_OK) {
|
||||
if (r == SCPE_OK)
|
||||
uptr->flags = uptr->flags & ~UNIT_OFFLINE; /* set online */
|
||||
uptr->UST = STA_BOT; /* tape starts at BOT */
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -771,7 +887,7 @@ return r;
|
|||
|
||||
t_stat msc_detach (UNIT* uptr)
|
||||
{
|
||||
uptr->UST = 0; /* update status */
|
||||
uptr->UST = 0; /* clear status */
|
||||
uptr->flags = uptr->flags | UNIT_OFFLINE; /* set offline */
|
||||
return sim_tape_detach (uptr); /* detach unit */
|
||||
}
|
||||
|
@ -788,7 +904,7 @@ else return SCPE_UNATT;
|
|||
|
||||
void ms_config_timing (void)
|
||||
{
|
||||
int32 i, tset;
|
||||
uint32 i, tset;
|
||||
|
||||
tset = (ms_timing << 1) | (ms_timing? 0 : ms_ctype); /* select timing set */
|
||||
for (i = 0; i < (sizeof (timers) / sizeof (timers[0])); i++)
|
||||
|
@ -898,6 +1014,34 @@ if (val == 1) fputc ('\n', st); /* MTAB_NMO omits \n */
|
|||
return status;
|
||||
}
|
||||
|
||||
/* Translate command to mnemonic for debug logging
|
||||
|
||||
The command names and descriptions are taken from the 13181 interface
|
||||
manual. */
|
||||
|
||||
char *ms_cmd_name (uint32 cmd)
|
||||
{
|
||||
|
||||
switch (cmd & 0377) {
|
||||
case FNC_WC: return "WCC"; /* Write command */
|
||||
case FNC_WFM: return "WFM"; /* Write file mark */
|
||||
case FNC_RC: return "RRF"; /* Read record forward */
|
||||
case FNC_FSR: return "FSR"; /* Forward space record */
|
||||
case FNC_FSF: return "FSF"; /* Forward space file */
|
||||
case FNC_GAP: return "GAP"; /* Write gap */
|
||||
case FNC_BSR: return "BSR"; /* Backspace record */
|
||||
case FNC_BSF: return "BSF"; /* Backspace file */
|
||||
case FNC_REW: return "REW"; /* Rewind */
|
||||
case FNC_RWS: return "RWO"; /* Rewind off-line */
|
||||
case FNC_CLR: return "CLR"; /* Clear controller */
|
||||
case FNC_GFM: return "GFM"; /* Gap file mark */
|
||||
case FNC_RFF: return "RFF"; /* Read forward until file mark (diag) */
|
||||
case FNC_RRR: return "RRR"; /* Read record in reverse (diag) */
|
||||
|
||||
default: return "???"; /* Unknown command */
|
||||
}
|
||||
}
|
||||
|
||||
/* 7970B/7970E bootstrap routine (HP 12992D ROM) */
|
||||
|
||||
const uint16 ms_rom[IBL_LNT] = {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_mt.c: HP 2100 12559A magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M. Supnik
|
||||
Copyright (c) 1993-2006, 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"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
mt 12559A 3030 nine track magnetic tape
|
||||
|
||||
28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
|
||||
07-Oct-04 JDB Allow enable/disable from either device
|
||||
14-Aug-04 RMS Modified handling of end of medium (suggested by Dave Bryan)
|
||||
06-Jul-04 RMS Fixed spurious timing error after CLC (found by Dave Bryan)
|
||||
|
@ -243,6 +244,7 @@ switch (inst) { /* case on opcode */
|
|||
dat = mtc_unit.buf;
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) mtc_dtf = 0; /* CLC: clr xfer flop */
|
||||
break;
|
||||
|
@ -257,7 +259,8 @@ return dat;
|
|||
|
||||
int32 mtcio (int32 inst, int32 IR, int32 dat)
|
||||
{
|
||||
int32 i, devc, devd, valid;
|
||||
uint32 i;
|
||||
int32 devc, devd, valid;
|
||||
t_stat st;
|
||||
|
||||
devc = IR & I_DEVMASK; /* get device no */
|
||||
|
@ -325,6 +328,7 @@ switch (inst) { /* case on opcode */
|
|||
else dat = dat | STA_BUSY | STA_LOCAL;
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { clrCTL (devc); } /* CLC */
|
||||
else { setCTL (devc); } /* STC */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_mux.c: HP 2100 12920A terminal multiplexor simulator
|
||||
|
||||
Copyright (c) 2002-2005, Robert M Supnik
|
||||
Copyright (c) 2002-2006, 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"),
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
mux,muxl,muxc 12920A terminal multiplexor
|
||||
|
||||
28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
|
||||
02-Jun-06 JDB Fixed compiler warning for mux_ldsc init
|
||||
22-Nov-05 RMS Revised for new terminal processing routines
|
||||
29-Jun-05 RMS Added SET MUXLn DISCONNECT
|
||||
07-Oct-04 JDB Allow enable/disable from any device
|
||||
|
@ -157,7 +159,7 @@ uint32 muxu_obuf = 0; /* upr out: chan */
|
|||
uint32 muxc_chan = 0; /* ctrl chan */
|
||||
uint32 muxc_scan = 0; /* ctrl scan */
|
||||
|
||||
TMLN mux_ldsc[MUX_LINES] = { 0 }; /* line descriptors */
|
||||
TMLN mux_ldsc[MUX_LINES] = { { 0 } }; /* line descriptors */
|
||||
TMXR mux_desc = { MUX_LINES, 0, 0, mux_ldsc }; /* mux descriptor */
|
||||
|
||||
DEVICE muxl_dev, muxu_dev, muxc_dev;
|
||||
|
@ -393,6 +395,7 @@ switch (inst) { /* case on opcode */
|
|||
dat = muxl_ibuf;
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { clrCTL (dev); } /* CLC */
|
||||
else { /* STC */
|
||||
|
@ -503,6 +506,7 @@ switch (inst) { /* case on opcode */
|
|||
muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* incr channel */
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* ctrl clear/set */
|
||||
if (IR & I_CTL) { clrCTL (dev); } /* CLC */
|
||||
else { setCTL (dev); } /* STC */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_stddev.c: HP2100 standard devices simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2006, 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"),
|
||||
|
@ -28,6 +28,7 @@
|
|||
tty 12531C buffered teleprinter interface
|
||||
clk 12539C time base generator
|
||||
|
||||
28-Dec-06 JDB Added ioCRS state to I/O decoders (action unverified)
|
||||
22-Nov-05 RMS Revised for new terminal processing routines
|
||||
13-Sep-04 JDB Added paper tape loop mode, DIAG/READER modifiers to PTR
|
||||
Added PV_LEFT to PTR TRLLIM register
|
||||
|
@ -383,6 +384,7 @@ switch (inst) { /* case on opcode */
|
|||
dat = ptr_unit.buf;
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCMD (dev); /* clear cmd, ctl */
|
||||
|
@ -560,6 +562,7 @@ switch (inst) { /* case on opcode */
|
|||
ptp_unit.buf = dat;
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCMD (dev); /* clear cmd, ctl */
|
||||
|
@ -645,6 +648,7 @@ switch (inst) { /* case on opcode */
|
|||
tty_buf = dat & 0377;
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { clrCTL (dev); } /* CLC */
|
||||
else { /* STC */
|
||||
|
@ -783,9 +787,9 @@ t_stat tty_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc)
|
|||
int32 u = uptr - tty_dev.units;
|
||||
|
||||
if (u > TTO) return SCPE_NOFNC;
|
||||
tty_unit[TTO].flags = (tty_unit[TTO].flags & ~TT_MODE) | val;
|
||||
if (val == TT_MODE_7P) val = TT_MODE_7B;
|
||||
tty_unit[TTI].flags = (tty_unit[TTI].flags & ~TT_MODE) | val;
|
||||
if ((u == TTI) && (val == TT_MODE_7P))
|
||||
val = TT_MODE_7B;
|
||||
tty_unit[u].flags = (tty_unit[u].flags & ~TT_MODE) | val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -832,6 +836,7 @@ switch (inst) { /* case on opcode */
|
|||
clrCTL (dev); /* clear control */
|
||||
break;
|
||||
|
||||
case ioCRS: /* control reset (action unverif) */
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCTL (dev); /* turn off clock */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
21-Dec-06 JDB Added "fwanxm" external for sim_load check
|
||||
19-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF messages
|
||||
25-Sep-04 JDB Added memory protect device
|
||||
Fixed display of CCA/CCB/CCE instructions
|
||||
|
@ -61,6 +62,7 @@ extern DEVICE muxl_dev, muxu_dev, muxc_dev;
|
|||
extern DEVICE ipli_dev, iplo_dev;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 *M;
|
||||
extern uint32 fwanxm;
|
||||
|
||||
/* SCP data structures and interface routines
|
||||
|
||||
|
|
|
@ -1569,7 +1569,8 @@ int32 a, b, c, r;
|
|||
|
||||
c = 0; /* init carry */
|
||||
do {
|
||||
a = M[ap]; b = M[bp]; /* get operands */
|
||||
a = M[ap]; /* get operands */
|
||||
b = M[bp];
|
||||
r = bcd_to_bin[b & DIGIT] + /* sum digits + c */
|
||||
bcd_to_bin[a & DIGIT] + c;
|
||||
c = (r >= 10); /* set carry out */
|
||||
|
@ -1671,8 +1672,10 @@ for (i = 0; i < 64; i++) { /* clr indicators */
|
|||
if ((i < IN_SSB) || (i > IN_SSG)) ind[i] = 0; /* except SSB-SSG */
|
||||
}
|
||||
ind[IN_UNC] = 1; /* ind[0] always on */
|
||||
AS = 0; as_err = 1; /* clear AS */
|
||||
BS = 0; bs_err = 1; /* clear BS */
|
||||
AS = 0; /* clear AS */
|
||||
BS = 0; /* clear BS *
|
||||
as_err = 1;
|
||||
bs_err = 1;/
|
||||
D = 0; /* clear D */
|
||||
hb_pend = 0; /* no halt br */
|
||||
pcq_r = find_reg ("ISQ", NULL, dptr);
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
cpu 7094 central processor
|
||||
|
||||
29-Oct-06 RMS Added additional expanded core instructions
|
||||
17-Oct-06 RMS Fixed the fix in halt IO wait loop
|
||||
16-Jun-06 RMS Fixed bug in halt IO wait loop
|
||||
|
||||
The register state for the 7094 is:
|
||||
|
@ -1576,11 +1578,22 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
reason = op_mse (ea);
|
||||
break;
|
||||
|
||||
case 01761: /* (CTSS) SEA, SEB */
|
||||
case 01761: /* (CTSS) ext core */
|
||||
if (prot_trap (0)) break; /* user mode? */
|
||||
if (ea == 041) data_base = 0;
|
||||
else if (ea == 042) data_base = BCORE_BASE;
|
||||
else if (stop_illop) reason = STOP_ILLEG;
|
||||
if (ea == 041) /* SEA? */
|
||||
data_base = 0;
|
||||
else if (ea == 042) /* SEB? */
|
||||
data_base = BCORE_BASE;
|
||||
else if (ea == 043) { /* IFT? */
|
||||
if (inst_base == 0)
|
||||
PC = (PC + 1) & eamask;
|
||||
}
|
||||
else if (ea == 044) { /* EFT? */
|
||||
if (data_base == 0)
|
||||
PC = (PC + 1) & eamask;
|
||||
}
|
||||
else if (stop_illop)
|
||||
reason = STOP_ILLEG;
|
||||
break;
|
||||
|
||||
case 01763: /* LGL */
|
||||
|
@ -1775,7 +1788,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
if (r = sim_process_event ()) return r; /* process events */
|
||||
chtr_pend = chtr_eval (NULL); /* eval chan traps */
|
||||
while (ch_req) { /* until no ch req */
|
||||
for (j = 0; i < NUM_CHAN; j++) { /* loop thru channels */
|
||||
for (j = 0; j < NUM_CHAN; j++) { /* loop thru channels */
|
||||
if (ch_req & REQ_CH (j)) { /* channel request? */
|
||||
if (r = ch_proc (j)) return r;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
29-Oct-06 RMS Added additional expanded core instructions
|
||||
08-Jun-06 RMS Added Dave Pitts' binary loader
|
||||
*/
|
||||
|
||||
|
@ -362,6 +363,7 @@ static const char *opcode[] = {
|
|||
"TIA", "TIB",
|
||||
"LRI", "LPI",
|
||||
"SEA", "SEB",
|
||||
"IFT", "EFT",
|
||||
|
||||
"IOCD", "IOCDN", "TCH",
|
||||
"IORP", "IORPN",
|
||||
|
@ -523,6 +525,7 @@ static const t_uint64 opc_v[] = {
|
|||
0010100000000+I_MXN, 0410100000000+I_MXN,
|
||||
0056200000000+I_MXN, 0456400000000+I_MXN,
|
||||
0476100000041+I_SNS, 0476100000042+I_SNS,
|
||||
0476100000043+I_SNS, 0476100000044+I_SNS,
|
||||
|
||||
01000000000000+I_IOX, 01000000200000+I_IOX, 01100000000000+I_TCH,
|
||||
01200000000000+I_IOX, 01200000200000+I_IOX,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// DMS R2V12 SLET without RPG, for debugging only
|
||||
/* DMS R2V12 SLET without RPG, for debugging only */
|
||||
|
||||
0x0001, 0x7c50, 0x032f, 0x0008,
|
||||
0x0002, 0x11de, 0x05a2, 0x000b,
|
||||
|
|
|
@ -9,15 +9,17 @@
|
|||
* Mail to sim@ibm1130.org
|
||||
*/
|
||||
|
||||
// 03 ctrl-C => Program stop (not handled here)
|
||||
// 05 ctrl-E => Simulator stop (not handled here)
|
||||
// 08 ctrl-H => Backspace
|
||||
// 0D ctrl-M (Enter) => EOF
|
||||
// 11 ctrl-Q => Interrupt request (not handled here)
|
||||
// 12 ctrl-R => "cent" (R because that's where cent is on the 1130 keyboard)
|
||||
// 15 ctrl-U => Erase Field
|
||||
// 7E ~ => "not"
|
||||
// FF Del => Backspace again
|
||||
/*
|
||||
* 03 ctrl-C => Program stop (not handled here)
|
||||
* 05 ctrl-E => Simulator stop (not handled here)
|
||||
* 08 ctrl-H => Backspace
|
||||
* 0D ctrl-M (Enter) => EOF
|
||||
* 11 ctrl-Q => Interrupt request (not handled here)
|
||||
* 12 ctrl-R => "cent" (R because that's where cent is on the 1130 keyboard)
|
||||
* 15 ctrl-U => Erase Field
|
||||
* 7E ~ => "not"
|
||||
* FF Del => Backspace again
|
||||
*/
|
||||
|
||||
static uint16 ascii_to_conin[] = /* ASCII to ((hollerith << 4) | special key flags) */
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -27,11 +27,11 @@
|
|||
#define MAX(a,b) (((a) >= (b)) ? (a) : (b))
|
||||
|
||||
#ifndef _WIN32
|
||||
int strnicmp (char *a, char *b, int n);
|
||||
int strcmpi (char *a, char *b);
|
||||
int strnicmp (const char *a, const char *b, int n);
|
||||
int strcmpi (const char *a, const char *b);
|
||||
#endif
|
||||
|
||||
// #define GUI_SUPPORT // uncomment to compile the GUI extensions. It's defined in the windows ibm1130.mak makefile
|
||||
/* #define GUI_SUPPORT uncomment to compile the GUI extensions. It's defined in the windows ibm1130.mak makefile */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Architectural constants */
|
||||
|
@ -40,14 +40,13 @@
|
|||
#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 int cgi; // TRUE if we are running as a CGI program
|
||||
extern int cgi; /* TRUE if we are running as a CGI program */
|
||||
extern int cgiwritable; /* TRUE if we can write the disk images back to the image file in CGI mode */
|
||||
extern int sim_gui;
|
||||
|
||||
extern uint16 M[]; /* core memory, up to 32Kwords (note: don't even think about trying 64K) */
|
||||
|
@ -58,6 +57,7 @@ extern int32 SAR, SBR; /* storage address/buffer registers */
|
|||
extern int32 OP, TAG, CCC; /* instruction decoded pieces */
|
||||
extern int32 CES; /* console entry switches */
|
||||
extern int32 ACC, EXT; /* accumulator and extension */
|
||||
extern int32 ARF; /* arithmetic factor register, a nonaddressable internal CPU register */
|
||||
extern int32 RUNMODE; /* processor run/step mode */
|
||||
extern int32 ipl; /* current interrupt level (-1 = not handling irq) */
|
||||
extern int32 iplpending; /* interrupted IPL's */
|
||||
|
@ -71,9 +71,11 @@ extern int32 int_mask; /* current active interrupt mask (ipl sensitive) */
|
|||
extern int32 mem_mask;
|
||||
extern int32 cpu_dsw; /* CPU device status word */
|
||||
extern int32 sim_int_char; /* interrupt character */
|
||||
extern int32 con_dsw; /* has program stop and int run bits */
|
||||
extern t_bool running;
|
||||
extern t_bool power;
|
||||
extern t_bool cgi; /* TRUE if we are running as a CGI program */
|
||||
extern t_bool cgiwritable; /* TRUE if we can write to the disk image file in CGI mode */
|
||||
extern t_stat reason; /* CPU execution loop control */
|
||||
|
||||
#define WAIT_OP 1 /* wait state causes: wait instruction, invalid instruction*/
|
||||
|
@ -131,15 +133,19 @@ void WriteW (int32 a, int32 d);
|
|||
#define STOP_PHASE_BREAK 7 /* phase load break */
|
||||
#define STOP_CRASH 8 /* program has crashed badly */
|
||||
#define STOP_TIMED_OUT 9 /* simulation time limit exceeded */
|
||||
#define STOP_IMMEDIATE 10 /* simulator stop key pressed (immediate stop) */
|
||||
#define STOP_BREAK 11 /* simulator break key pressed */
|
||||
#define STOP_STEP 12 /* step count expired */
|
||||
#define STOP_OTHER 13 /* other reason, probably error returned by sim_process_event() */
|
||||
|
||||
#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 INT_REQ_5 0x01 /* bits for interrupt levels (ipl, iplpending, int_req, int_mask) */
|
||||
#define INT_REQ_4 0x02
|
||||
#define INT_REQ_3 0x04
|
||||
#define INT_REQ_2 0x08
|
||||
#define INT_REQ_1 0x10
|
||||
#define INT_REQ_0 0x20
|
||||
|
||||
#define XIO_UNUSED 0x00 /* XIO commands */
|
||||
#define XIO_WRITE 0x01
|
||||
|
@ -156,7 +162,7 @@ void WriteW (int32 a, int32 d);
|
|||
|
||||
#define ILSW_0_1442_CARD 0x8000 /* ILSW 0 is not really defined on the 1130 */
|
||||
|
||||
#define ILSW_1_1132_PRINTER 0x8000 // had these backwards!
|
||||
#define ILSW_1_1132_PRINTER 0x8000 /* had these backwards! */
|
||||
#define ILSW_1_SCA 0x4000
|
||||
|
||||
#define ILSW_2_1131_DISK 0x8000
|
||||
|
@ -215,13 +221,13 @@ void WriteW (int32 a, int32 d);
|
|||
#define ILSW_4_SAC_BIT_09 0x0040
|
||||
#define ILSW_4_SAC_BIT_10 0x0020
|
||||
#define ILSW_4_SAC_BIT_11 0x0010
|
||||
#define ILSW_4_T2741_TERMINAL 0x0010 /* APL\1130 nonstandard serial interface uses this bit */
|
||||
#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_INT_RUN_PROGRAM_STOP 0x8000 /* this replaces both ILSW_5_INT_RUN and ILSW_5_PROGRAM_STOP */
|
||||
#define ILSW_5_SAC_BIT_01 0x4000
|
||||
#define ILSW_5_SAC_BIT_02 0x2000
|
||||
#define ILSW_5_SAC_BIT_03 0x1000
|
||||
|
@ -238,26 +244,27 @@ void WriteW (int32 a, int32 d);
|
|||
#define ILSW_5_SAC_BIT_14 0x0002
|
||||
#define ILSW_5_SAC_BIT_15 0x0001
|
||||
|
||||
//* CPU DSW bits
|
||||
/* CPU DSW bits */
|
||||
|
||||
#define CPU_DSW_PROGRAM_STOP 0x8000
|
||||
#define CPU_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_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_sca (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_t2741_terminal (int32 addr, int32 func, int32 modify); /* IO selectric via nonstandard serial interface for APL */
|
||||
void xio_error (char *msg);
|
||||
|
||||
void bail (char *msg);
|
||||
|
@ -267,6 +274,8 @@ t_stat cr_rewind (void);
|
|||
t_stat cr_detach (UNIT *uptr);
|
||||
void calc_ints (void); /* recalculate interrupt bitmask */
|
||||
void trace_io (char *fmt, ...); /* debugging printout */
|
||||
void trace_both (char *fmt, ...); /* debugging printout */
|
||||
t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help);
|
||||
void scp_panic (char *msg); /* bail out of simulator */
|
||||
char *upcase(char *str);
|
||||
void break_simulation (t_stat reason); /* let a device halt the simulation */
|
||||
|
|
|
@ -14,6 +14,13 @@ commands may NOT be accurate. This should probably be fixed.
|
|||
* or modifications.
|
||||
*
|
||||
* Revision History
|
||||
* 05-dec-06 Added cgiwritable mode
|
||||
*
|
||||
* 19-Dec-05 We no longer issue an operation complete interrupt if an INITR, INITW
|
||||
* or CONTROL operation is attemped on a drive that is not online. DATA_ERROR
|
||||
* is now only indicated in the DSW when
|
||||
*
|
||||
* 02-Nov-04 Addes -s option to boot to leave switches alone.
|
||||
* 15-jun-03 moved actual read on XIO read to end of time interval,
|
||||
* as the APL boot card required 2 instructions to run between the
|
||||
* time read was initiated and the time the data was read (a jump and a wait)
|
||||
|
@ -29,7 +36,7 @@ commands may NOT be accurate. This should probably be fixed.
|
|||
#include "ibm1130_defs.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define TRACE_DMS_IO // define to enable debug of DMS phase IO
|
||||
#define TRACE_DMS_IO /* define to enable debug of DMS phase IO */
|
||||
|
||||
#ifdef TRACE_DMS_IO
|
||||
extern int32 sim_switches;
|
||||
|
@ -86,7 +93,7 @@ static t_stat dsk_attach (UNIT *uptr, char *cptr);
|
|||
static t_stat dsk_detach (UNIT *uptr);
|
||||
static t_stat dsk_boot (int unitno, DEVICE *dptr);
|
||||
|
||||
static void diskfail (UNIT *uptr, int errflag);
|
||||
static void diskfail (UNIT *uptr, int dswflag, int unitflag, t_bool do_interrupt);
|
||||
|
||||
/* DSK data structures
|
||||
|
||||
|
@ -180,16 +187,17 @@ extern void void_backtrace (int afrom, int ato);
|
|||
void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
||||
{
|
||||
int i, rev, nsteps, newcyl, sec, nwords;
|
||||
uint32 newpos; // changed from t_addr to uint32 in anticipation of simh 64-bit development
|
||||
uint32 newpos; /* changed from t_addr to uint32 in anticipation of simh 64-bit development */
|
||||
char msg[80];
|
||||
UNIT *uptr = dsk_unit+drv;
|
||||
int16 buf[DSK_NUMWD];
|
||||
|
||||
if (! BETWEEN(drv, 0, DSK_NUMDR-1)) { // hmmm, invalid drive */
|
||||
if (func != XIO_SENSE_DEV) { // tried to use it, too
|
||||
// just do nothing, as if the controller isn't there. NAMCRA at N0116300 tests for drives by attempting reads
|
||||
// sprintf(msg, "Op %x on invalid drive number %d", func, drv);
|
||||
// xio_error(msg);
|
||||
if (! BETWEEN(drv, 0, DSK_NUMDR-1)) { /* hmmm, invalid drive */
|
||||
if (func != XIO_SENSE_DEV) { /* tried to use it, too */
|
||||
/* just do nothing, as if the controller isn't there. NAMCRA at N0116300 tests for drives by attempting reads
|
||||
sprintf(msg, "Op %x on invalid drive number %d", func, drv);
|
||||
xio_error(msg);
|
||||
*/
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -199,7 +207,7 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
|||
switch (func) {
|
||||
case XIO_INITR:
|
||||
if (! IS_ONLINE(uptr)) { /* disk is offline */
|
||||
diskfail(uptr, UNIT_HARDERR); /* make error stick till reset or attach */
|
||||
diskfail(uptr, 0, 0, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -219,11 +227,12 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
|||
sec = modify & 0x07; /* get sector on cylinder */
|
||||
|
||||
if ((modify & 0x0080) == 0) { /* it's a real read if it's not a read check */
|
||||
// ah. We have a problem. The APL boot card counts on there being time for at least one
|
||||
// more instruction to execute between the XIO read and the time the data starts loading
|
||||
// into core. So, we have to defer the actual read operation a bit. Might as well wait
|
||||
// until it's time to issue the operation complete interrupt. This means saving the
|
||||
// IO information, then performing the actual read in dsk_svc.
|
||||
/* ah. We have a problem. The APL boot card counts on there being time for at least one
|
||||
* more instruction to execute between the XIO read and the time the data starts loading
|
||||
* into core. So, we have to defer the actual read operation a bit. Might as well wait
|
||||
* until it's time to issue the operation complete interrupt. This means saving the
|
||||
* IO information, then performing the actual read in dsk_svc.
|
||||
*/
|
||||
|
||||
newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD;
|
||||
|
||||
|
@ -248,12 +257,12 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
|||
|
||||
case XIO_INITW:
|
||||
if (! IS_ONLINE(uptr)) { /* disk is offline */
|
||||
diskfail(uptr, UNIT_HARDERR); /* make error stick till reset or attach */
|
||||
diskfail(uptr, 0, 0, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (uptr->flags & UNIT_RONLY) { /* oops, write to RO disk? permanent error */
|
||||
diskfail(uptr, UNIT_HARDERR);
|
||||
if (uptr->flags & UNIT_RONLY) { /* oops, write to RO disk? permanent error until disk is powered off/on */
|
||||
diskfail(uptr, DSK_DSW_DATA_ERROR, UNIT_HARDERR, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -312,7 +321,7 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
|||
|
||||
case XIO_CONTROL: /* step fwd/rev */
|
||||
if (! IS_ONLINE(uptr)) {
|
||||
diskfail(uptr, UNIT_HARDERR);
|
||||
diskfail(uptr, 0, 0, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -364,11 +373,16 @@ void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv)
|
|||
|
||||
/* diskfail - schedule an operation complete that sets the error bit */
|
||||
|
||||
static void diskfail (UNIT *uptr, int errflag)
|
||||
static void diskfail (UNIT *uptr, int dswflag, int unitflag, t_bool do_interrupt)
|
||||
{
|
||||
int drv = uptr - dsk_unit;
|
||||
|
||||
sim_cancel(uptr); /* cancel any pending ops */
|
||||
SETBIT(uptr->flags, errflag); /* set the error flag */
|
||||
SETBIT(dsk_dsw[drv], dswflag); /* set any specified DSW bits */
|
||||
SETBIT(uptr->flags, unitflag); /* set any specified unit flag bits */
|
||||
uptr->FUNC = DSK_FUNC_FAILED; /* tell svc routine why it failed */
|
||||
|
||||
if (do_interrupt)
|
||||
sim_activate(uptr, 1); /* schedule an immediate op complete interrupt */
|
||||
}
|
||||
|
||||
|
@ -376,7 +390,7 @@ t_stat dsk_svc (UNIT *uptr)
|
|||
{
|
||||
int drv = uptr - dsk_unit, i, nwords, sec;
|
||||
int16 buf[DSK_NUMWD];
|
||||
uint32 newpos; // changed from t_addr to uint32 in anticipation of simh 64-bit development
|
||||
uint32 newpos; /* changed from t_addr to uint32 in anticipation of simh 64-bit development */
|
||||
int32 iocc_addr;
|
||||
|
||||
if (uptr->FUNC == DSK_FUNC_IDLE) /* service function called with no activity? not good, but ignore */
|
||||
|
@ -415,16 +429,16 @@ t_stat dsk_svc (UNIT *uptr)
|
|||
dsk_lastio[drv] = IO_READ;
|
||||
uptr->pos = newpos;
|
||||
}
|
||||
fxread(buf, 2, DSK_NUMWD, uptr->fileref); // read whole sector so we're in position for next read
|
||||
fxread(buf, 2, DSK_NUMWD, uptr->fileref); /* read whole sector so we're in position for next read */
|
||||
uptr->pos = newpos + 2*DSK_NUMWD;
|
||||
}
|
||||
|
||||
void_backtrace(iocc_addr, iocc_addr + nwords - 1); // mark prev instruction as altered
|
||||
void_backtrace(iocc_addr, iocc_addr + nwords - 1); /* mark prev instruction as altered */
|
||||
|
||||
trace_io("* DSK%d read %d words from %d.%d (%x, %x) to M[%04x-%04x]", drv, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask,
|
||||
(iocc_addr + nwords - 1) & mem_mask);
|
||||
|
||||
// // this will help debug the monitor by letting me watch phase loading
|
||||
/* this will help debug the monitor by letting me watch phase loading */
|
||||
if (raw_disk_debug)
|
||||
printf("* DSK%d XIO @ %04x read %d words from %d.%d (%x, %x) to M[%04x-%04x]\n", drv, prev_IAR, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask,
|
||||
(iocc_addr + nwords - 1) & mem_mask);
|
||||
|
@ -448,7 +462,7 @@ t_stat dsk_svc (UNIT *uptr)
|
|||
|
||||
}
|
||||
|
||||
uptr->FUNC = DSK_FUNC_IDLE; // we're done with this operation
|
||||
uptr->FUNC = DSK_FUNC_IDLE; /* we're done with this operation */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -459,8 +473,8 @@ t_stat dsk_reset (DEVICE *dptr)
|
|||
UNIT *uptr;
|
||||
|
||||
#ifdef TRACE_DMS_IO
|
||||
// add the WHERE command. It finds the phase that was loaded at given address and indicates
|
||||
// the offset in the phase
|
||||
/* add the WHERE command. It finds the phase that was loaded at given address and indicates */
|
||||
/* the offset in the phase */
|
||||
register_cmd("WHERE", &where_cmd, 0, "w{here} address find phase and offset of an address\n");
|
||||
register_cmd("PHDEBUG", &phdebug_cmd, 0, "ph{debug} off|phlo phhi break on phase load\n");
|
||||
register_cmd("FDUMP", &fdump_cmd, 0, NULL);
|
||||
|
@ -487,14 +501,14 @@ static t_stat dsk_attach (UNIT *uptr, char *cptr)
|
|||
int drv = uptr - dsk_unit;
|
||||
t_stat rval;
|
||||
|
||||
sim_cancel(uptr); // cancel current IO
|
||||
sim_cancel(uptr); /* cancel current IO */
|
||||
dsk_lastio[drv] = IO_NONE;
|
||||
|
||||
if (uptr->flags & UNIT_ATT) // dismount current disk
|
||||
if (uptr->flags & UNIT_ATT) /* dismount current disk */
|
||||
if ((rval = dsk_detach(uptr)) != SCPE_OK)
|
||||
return rval;
|
||||
|
||||
uptr->CYL = 0; // reset the device
|
||||
uptr->CYL = 0; /* reset the device */
|
||||
uptr->FUNC = DSK_FUNC_IDLE;
|
||||
dsk_dsw[drv] = DSK_DSW_CARRIAGE_HOME;
|
||||
|
||||
|
@ -502,18 +516,18 @@ static t_stat dsk_attach (UNIT *uptr, char *cptr)
|
|||
CLRBIT(ILSW[2], dsk_ilswbit[drv]);
|
||||
calc_ints();
|
||||
|
||||
if (sim_switches & SWMASK('M')) // if memory mode (e.g. for CGI), buffer the file
|
||||
SETBIT(uptr->flags, UNIT_BUFABLE);
|
||||
if (sim_switches & SWMASK('M')) /* if memory mode (e.g. for CGI), buffer the file */
|
||||
SETBIT(uptr->flags, UNIT_BUFABLE|UNIT_MUSTBUF);
|
||||
|
||||
if (sim_switches & SWMASK('R')) // read lock mode
|
||||
if (sim_switches & SWMASK('R')) /* read lock mode */
|
||||
SETBIT(uptr->flags, UNIT_RO|UNIT_ROABLE|UNIT_RONLY);
|
||||
|
||||
if (cgi && (sim_switches & SWMASK('M'))) { // if cgi and memory mode,
|
||||
sim_switches |= SWMASK('R'); // have attach_unit open file in readonly mode
|
||||
SETBIT(uptr->flags, UNIT_ROABLE|UNIT_MUSTBUF); // but don't set the UNIT_RONLY flag so DMS can write to the buffered image
|
||||
if (cgi && (sim_switches & SWMASK('M')) && ! cgiwritable) { /* if cgi and memory mode, but writable option not specified */
|
||||
sim_switches |= SWMASK('R'); /* have attach_unit open file in readonly mode */
|
||||
SETBIT(uptr->flags, UNIT_ROABLE); /* but don't set the UNIT_RONLY flag so DMS can write to the buffered image */
|
||||
}
|
||||
|
||||
if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK) { // mount new disk
|
||||
if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK) { /* mount new disk */
|
||||
SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY);
|
||||
return rval;
|
||||
}
|
||||
|
@ -536,7 +550,7 @@ static t_stat dsk_detach (UNIT *uptr)
|
|||
|
||||
sim_cancel(uptr);
|
||||
|
||||
if ((rval = detach_unit (uptr)) != SCPE_OK)
|
||||
if ((rval = detach_unit(uptr)) != SCPE_OK)
|
||||
return rval;
|
||||
|
||||
CLRBIT(ILSW[2], dsk_ilswbit[drv]);
|
||||
|
@ -555,7 +569,7 @@ static t_stat dsk_detach (UNIT *uptr)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// boot routine - if they type BOOT DSK, load the standard boot card.
|
||||
/* boot routine - if they type BOOT DSK, load the standard boot card. */
|
||||
|
||||
static t_stat dsk_boot (int unitno, DEVICE *dptr)
|
||||
{
|
||||
|
@ -585,7 +599,7 @@ struct tag_slet {
|
|||
int16 nwords;
|
||||
int16 sector;
|
||||
} slet[MAXSLET] = {
|
||||
# include "dmsr2v12slet.h" // without RPG, use this info until overwritten by actual data from disk
|
||||
# include "dmsr2v12slet.h" /* without RPG, use this info until overwritten by actual data from disk */
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
@ -599,7 +613,7 @@ int nseg = 0;
|
|||
|
||||
static void enable_dms_tracing (int newsetting)
|
||||
{
|
||||
nseg = 0; // clear the segment map
|
||||
nseg = 0; /* clear the segment map */
|
||||
|
||||
if ((newsetting && trace_dms) || ! (newsetting || trace_dms))
|
||||
return;
|
||||
|
@ -678,7 +692,7 @@ static t_stat where_cmd (int flag, char *ptr)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// savesector - save info on a sector just read. THIS IS NOT YET TESTED
|
||||
/* savesector - save info on a sector just read. THIS IS NOT YET TESTED */
|
||||
|
||||
static void addseg (int i)
|
||||
{
|
||||
|
@ -713,14 +727,14 @@ static void savesector (int addr, int offset, int len, int phid, char *name)
|
|||
if (! trace_dms)
|
||||
return;
|
||||
|
||||
addr++; // first word is sector address, so account for that
|
||||
addr++; /* first word is sector address, so account for that */
|
||||
len--;
|
||||
|
||||
for (i = 0; i < nseg; i++) {
|
||||
if (addr >= (mseg[i].addr+mseg[i].len)) // entirely after this entry
|
||||
if (addr >= (mseg[i].addr+mseg[i].len)) /* entirely after this entry */
|
||||
continue;
|
||||
|
||||
if (mseg[i].addr < addr) { // old one starts before this. split it
|
||||
if (mseg[i].addr < addr) { /* old one starts before this. split it */
|
||||
addseg(i);
|
||||
mseg[i].len = addr-mseg[i].addr;
|
||||
i++;
|
||||
|
@ -731,7 +745,7 @@ static void savesector (int addr, int offset, int len, int phid, char *name)
|
|||
break;
|
||||
}
|
||||
|
||||
addseg(i); // add new segment. Old one ends up after this
|
||||
addseg(i); /* add new segment. Old one ends up after this */
|
||||
|
||||
if (i >= MAXMSEG)
|
||||
return;
|
||||
|
@ -742,12 +756,12 @@ static void savesector (int addr, int offset, int len, int phid, char *name)
|
|||
mseg[i].len = len;
|
||||
mseg[i].name = name;
|
||||
|
||||
i++; // delete any segments completely covered
|
||||
i++; /* delete any segments completely covered */
|
||||
|
||||
while (i < nseg && (mseg[i].addr+mseg[i].len) <= (addr+len))
|
||||
delseg(i);
|
||||
|
||||
if (i < nseg && mseg[i].addr < (addr+len)) { // old one extends past this. Retain the end
|
||||
if (i < nseg && mseg[i].addr < (addr+len)) { /* old one extends past this. Retain the end */
|
||||
mseg[i].len = (mseg[i].addr+mseg[i].len) - (addr+len);
|
||||
mseg[i].addr = addr+len;
|
||||
}
|
||||
|
@ -755,19 +769,19 @@ static void savesector (int addr, int offset, int len, int phid, char *name)
|
|||
|
||||
static void tracesector (int iswrite, int nwords, int addr, int sector)
|
||||
{
|
||||
int i, phid = 0, sletind = -1, offset = 0;
|
||||
int i, phid = 0, offset = 0;
|
||||
char *name = NULL;
|
||||
|
||||
if (nwords < 3 || ! trace_dms)
|
||||
return;
|
||||
|
||||
switch (sector) { // explicitly known sector name
|
||||
switch (sector) { /* explicitly known sector name */
|
||||
case 0: name = "ID/COLD START"; break;
|
||||
case 1: name = "DCOM"; break;
|
||||
case 2: name = "RESIDENT IMAGE"; break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5: name = "SLET"; // save just-read or written SLET info
|
||||
case 5: name = "SLET"; /* save just-read or written SLET info */
|
||||
memmove(&slet[(320/4)*(sector-3)], &M[addr+1], nwords*2);
|
||||
break;
|
||||
case 6: name = "RELOAD TABLE"; break;
|
||||
|
@ -777,9 +791,9 @@ static void tracesector (int iswrite, int nwords, int addr, int sector)
|
|||
printf("* %04x: %3d /%04x %c %3d.%d ",
|
||||
prev_IAR, nwords, addr, iswrite ? 'W' : 'R', sector/8, sector%8);
|
||||
|
||||
if (name == NULL) { // look up sector in SLET
|
||||
if (name == NULL) { /* look up sector in SLET */
|
||||
for (i = 0; i < MAXSLET; i++) {
|
||||
if (slet[i].phid == 0) // not found
|
||||
if (slet[i].phid == 0) /* not found */
|
||||
goto done;
|
||||
else if (slet[i].sector > sector) {
|
||||
if (--i >= 0) {
|
||||
|
@ -792,17 +806,17 @@ static void tracesector (int iswrite, int nwords, int addr, int sector)
|
|||
goto done;
|
||||
}
|
||||
if (slet[i].sector == sector) {
|
||||
phid = slet[i].phid; // we found the starting sector
|
||||
phid = slet[i].phid; /* we found the starting sector */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= MAXSLET) // was not found
|
||||
if (i >= MAXSLET) /* was not found */
|
||||
goto done;
|
||||
|
||||
name = "?";
|
||||
for (i = sizeof(phase)/sizeof(phase[0]); --i >= 0; ) {
|
||||
if (phase[i].phid == phid) { // look up name
|
||||
if (phase[i].phid == phid) { /* look up name */
|
||||
name = phase[i].name;
|
||||
break;
|
||||
}
|
||||
|
@ -816,7 +830,7 @@ done:
|
|||
putchar('\n');
|
||||
|
||||
if (phid >= phdebug_lo && phid <= phdebug_hi && offset == 0)
|
||||
break_simulation(STOP_PHASE_BREAK); // break on read of first sector of indicated phases
|
||||
break_simulation(STOP_PHASE_BREAK); /* break on read of first sector of indicated phases */
|
||||
|
||||
if (name != NULL && *name != '?' && ! iswrite)
|
||||
savesector(addr, offset, nwords, phid, name);
|
||||
|
@ -824,12 +838,12 @@ done:
|
|||
|
||||
static t_stat fdump_cmd (int flags, char *cptr)
|
||||
{
|
||||
int addr = 0x7a24; // address of next statement;
|
||||
int addr = 0x7a24; /* address of next statement */
|
||||
int sofst = 0x7a26, symaddr;
|
||||
int cword, nwords, stype, has_stnum, strel = 1, laststno = 0;
|
||||
|
||||
addr = M[addr & mem_mask] & mem_mask; // get address of first statement
|
||||
sofst = M[sofst & mem_mask] & mem_mask; // get address of symbol table
|
||||
addr = M[addr & mem_mask] & mem_mask; /* get address of first statement */
|
||||
sofst = M[sofst & mem_mask] & mem_mask ; /* get address of symbol table */
|
||||
|
||||
for (;;) {
|
||||
cword = M[addr];
|
||||
|
@ -851,7 +865,7 @@ static t_stat fdump_cmd (int flags, char *cptr)
|
|||
printf(" [%04x %04x %04x]", M[symaddr], M[symaddr+1], M[symaddr+2]);
|
||||
}
|
||||
|
||||
if (stype == 0x5000) { // error record
|
||||
if (stype == 0x5000) { /* error record */
|
||||
printf(" (err %d)", M[addr+1]);
|
||||
}
|
||||
|
||||
|
@ -872,4 +886,4 @@ static t_stat fdump_cmd (int flags, char *cptr)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#endif // TRACE_DMS_IO
|
||||
#endif /* TRACE_DMS_IO */
|
||||
|
|
|
@ -1,60 +1,61 @@
|
|||
// ibm1130_fmt.c : interpret tabs in 1130 Assembler or Fortran source
|
||||
// Bob Flanders
|
||||
// -------------------------------------------------------------------------------------------
|
||||
//
|
||||
// These routines are used by ibm1130_cr.c when the user has indicated
|
||||
// that the input text is formatted with tabs. Input lines are edited
|
||||
// into the appropriate column format. Three edit modes are recognized:
|
||||
//
|
||||
// Assembler mode:
|
||||
// Input lines of the form
|
||||
//
|
||||
// [label]<whitespace>[opcode]<tab>[tag][L]<tab>[argument]
|
||||
//
|
||||
// are rearranged so that the input fields are placed in the appropriate columns
|
||||
//
|
||||
// The label must start on the first character of the line. If there is no label,
|
||||
// the first character(s) before the opcode must be whitespace. Following the opcode, there
|
||||
// MUST be a tab character, followed by the format and tag. Following the format and tag
|
||||
// may be exactly one whitespace character, and then starts the argument.
|
||||
//
|
||||
// Input lines with * in column 1 and blank lines are turned into Assembler comments,
|
||||
// with the * in the Opcode field.
|
||||
//
|
||||
// Assembler directive lines at the beginning of the deck must be preceded by
|
||||
// ! to indicate that they are not comments. For example,
|
||||
//
|
||||
// !*LIST
|
||||
// * This is a comment
|
||||
//
|
||||
// Fortran mode:
|
||||
// Input lines of the form
|
||||
//
|
||||
// [label]<tab>statement
|
||||
//
|
||||
// or
|
||||
//
|
||||
// [label]<tab>Xcontinuation
|
||||
//
|
||||
// where X is a non alphabetic contination character are rearranged in the
|
||||
// appropriate manner:
|
||||
//
|
||||
// 1 2
|
||||
// 12345678901234567890...
|
||||
// ------------------------
|
||||
// label statement
|
||||
// labelXcontinuation
|
||||
//
|
||||
// However, you must take care that you don't end up with statement text after column 72.
|
||||
//
|
||||
// Input lines with * or C in column 1 are left alone (comments and directives)
|
||||
//
|
||||
// (The ! escape is not used before Fortran directives as before Assembler directives)
|
||||
//
|
||||
// Tab mode:
|
||||
// Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide,
|
||||
// as is standard for vi, notepad, etc.
|
||||
// -------------------------------------------------------------------------------------------
|
||||
/*********************************************************************************************
|
||||
* ibm1130_fmt.c : interpret tabs in 1130 Assembler or Fortran source
|
||||
* Bob Flanders
|
||||
* -------------------------------------------------------------------------------------------
|
||||
*
|
||||
* These routines are used by ibm1130_cr.c when the user has indicated
|
||||
* that the input text is formatted with tabs. Input lines are edited
|
||||
* into the appropriate column format. Three edit modes are recognized:
|
||||
*
|
||||
* Assembler mode:
|
||||
* Input lines of the form
|
||||
*
|
||||
* [label]<whitespace>[opcode]<tab>[tag][L]<tab>[argument]
|
||||
*
|
||||
* are rearranged so that the input fields are placed in the appropriate columns
|
||||
*
|
||||
* The label must start on the first character of the line. If there is no label,
|
||||
* the first character(s) before the opcode must be whitespace. Following the opcode, there
|
||||
* MUST be a tab character, followed by the format and tag. Following the format and tag
|
||||
* may be exactly one whitespace character, and then starts the argument.
|
||||
*
|
||||
* Input lines with * in column 1 and blank lines are turned into Assembler comments,
|
||||
* with the * in the Opcode field.
|
||||
*
|
||||
* Assembler directive lines at the beginning of the deck must be preceded by
|
||||
* ! to indicate that they are not comments. For example,
|
||||
*
|
||||
* !*LIST
|
||||
* * This is a comment
|
||||
*
|
||||
* Fortran mode:
|
||||
* Input lines of the form
|
||||
*
|
||||
* [label]<tab>statement
|
||||
*
|
||||
* or
|
||||
*
|
||||
* [label]<tab>Xcontinuation
|
||||
*
|
||||
* where X is a non alphabetic contination character are rearranged in the
|
||||
* appropriate manner:
|
||||
*
|
||||
* 1 2
|
||||
* 12345678901234567890...
|
||||
* ------------------------
|
||||
* label statement
|
||||
* labelXcontinuation
|
||||
*
|
||||
* However, you must take care that you don't end up with statement text after column 72.
|
||||
*
|
||||
* Input lines with * or C in column 1 are left alone (comments and directives)
|
||||
*
|
||||
* (The ! escape is not used before Fortran directives as before Assembler directives)
|
||||
*
|
||||
* Tab mode:
|
||||
* Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide,
|
||||
* as is standard for vi, notepad, etc.
|
||||
*********************************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -63,10 +64,10 @@
|
|||
#include <string.h>
|
||||
#include "ibm1130_fmt.h"
|
||||
|
||||
#define MAXLINE 81 // maximum output line size
|
||||
#define WORKSZ 256 // size for tab work area
|
||||
#define TAGOFFSET 12 // offset for tag field
|
||||
#define FMTOFFSET 11 // offset for format field
|
||||
#define MAXLINE 81 /* maximum output line size */
|
||||
#define WORKSZ 256 /* size for tab work area */
|
||||
#define TAGOFFSET 12 /* offset for tag field */
|
||||
#define FMTOFFSET 11 /* offset for format field */
|
||||
|
||||
#define MIN(a,b) ((a < b) ? a : b)
|
||||
#define AMSG " with Assembler Reformat"
|
||||
|
@ -77,225 +78,234 @@
|
|||
#define FFORMAT "%-5.5s %-74.74s"
|
||||
#define FCONTFMT "%-5.5s%-75.75s"
|
||||
|
||||
char gszLabel[6]; // work area for label
|
||||
char gszArg[MAXLINE]; // .. argument
|
||||
char gszOutput[MAXLINE]; // .. output
|
||||
short gaiAsmTabs[] = {7,12,15,20,25,30,35,40,45,52,0};// tab stops for assembler
|
||||
char gszLabel[6]; /* work area for label */
|
||||
char gszArg[MAXLINE]; /* .. argument */
|
||||
char gszOutput[MAXLINE]; /* .. output */
|
||||
short gaiAsmTabs[] = {7,12,15,20,25,30,35,40,45,52,0};/* tab stops for assembler */
|
||||
|
||||
short gaiPlainTabs[] = {9, 17, 25, 33, 41, 49, 57, 65, 73, 0};// tab stops for just plain tabs
|
||||
short gaiPlainTabs[] = {9, 17, 25, 33, 41, 49, 57, 65, 73, 0};/* tab stops for just plain tabs */
|
||||
|
||||
// ///////////////
|
||||
// helper routines
|
||||
/*
|
||||
* helper routines
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// ExpandTabs: Expand tabs to spaces
|
||||
/*************************************************
|
||||
* ExpandTabs: Expand tabs to spaces
|
||||
*/
|
||||
|
||||
char* ExpandTabs(char* p_szInbuf, // expand tabs .. input buffer
|
||||
char* p_szOutbuf, // .. output buffer
|
||||
short* p_aiTabs) // .. array of tab stops (1 based) -- 0 end of array
|
||||
char* ExpandTabs(char* p_szInbuf, /* expand tabs .. input buffer */
|
||||
char* p_szOutbuf, /* .. output buffer */
|
||||
short* p_aiTabs) /* .. array of tab stops (1 based) -- 0 end of array */
|
||||
{
|
||||
short iI, // input position
|
||||
iO, // output position
|
||||
iT; // next tab stop
|
||||
short iI, /* input position */
|
||||
iO, /* output position */
|
||||
iT; /* next tab stop */
|
||||
|
||||
char cX; // character to test
|
||||
char cX; /* character to test */
|
||||
|
||||
iI = 0; // init input position
|
||||
iO = 0; // init output position
|
||||
iT = 0; // init tab stop
|
||||
iI = 0; /* init input position */
|
||||
iO = 0; /* init output position */
|
||||
iT = 0; /* init tab stop */
|
||||
|
||||
while ((cX = *(p_szInbuf + iI)) != 0) // while there are characters
|
||||
while ((cX = *(p_szInbuf + iI)) != 0) /* while there are characters */
|
||||
{
|
||||
if (cX == '\t') // q. tab character?
|
||||
{ // a. yes ..
|
||||
while ((p_aiTabs[iT] <= iO + 1) // search for next valid stop ..
|
||||
&& (p_aiTabs[iT] != 0)) // .. or end of table
|
||||
iT++; // .. go to next tab
|
||||
if (cX == '\t') /* q. tab character? */
|
||||
{ /* a. yes .. */
|
||||
while ((p_aiTabs[iT] <= iO + 1) /* search for next valid stop .. */
|
||||
&& (p_aiTabs[iT] != 0)) /* .. or end of table */
|
||||
iT++; /* .. go to next tab */
|
||||
|
||||
if (p_aiTabs[iT] != 0) // q. end of tab array?
|
||||
{ // a. no ..
|
||||
while (iO < (p_aiTabs[iT] - 1)) // fill to tab with blanks
|
||||
*(p_szOutbuf + iO++) = ' '; // .. put in a blank
|
||||
if (p_aiTabs[iT] != 0) /* q. end of tab array? */
|
||||
{ /* a. no .. */
|
||||
while (iO < (p_aiTabs[iT] - 1)) /* fill to tab with blanks */
|
||||
*(p_szOutbuf + iO++) = ' '; /* .. put in a blank */
|
||||
|
||||
}
|
||||
else // Otherwise ...
|
||||
*(p_szOutbuf + iO++) = ' '; // .. Translate to blank
|
||||
else /* Otherwise ... */
|
||||
*(p_szOutbuf + iO++) = ' '; /* .. Translate to blank */
|
||||
}
|
||||
else // Otherwise .. not tab
|
||||
*(p_szOutbuf + iO++) = cX; // .. save the input char
|
||||
else /* Otherwise .. not tab */
|
||||
*(p_szOutbuf + iO++) = cX; /* .. save the input char */
|
||||
|
||||
iI++; // next input character
|
||||
iI++; /* next input character */
|
||||
}
|
||||
|
||||
*(p_szOutbuf + iO) = 0; // end the string..
|
||||
return p_szOutbuf; // .. return output area addr
|
||||
*(p_szOutbuf + iO) = 0; /* end the string.. */
|
||||
return p_szOutbuf; /* .. return output area addr */
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// extract next token, modify pointer
|
||||
/*************************************************
|
||||
* extract next token, modify pointer
|
||||
*/
|
||||
|
||||
char* GetToken(char* p_szOut, // output location
|
||||
int p_iLen, // max output length
|
||||
char**p_pszToken) // pointer to input token
|
||||
char* GetToken(char* p_szOut, /* output location */
|
||||
int p_iLen, /* max output length */
|
||||
char**p_pszToken) /* pointer to input token */
|
||||
{
|
||||
int iI; // work integer
|
||||
char* pszX; // work pointer
|
||||
int iI; /* work integer */
|
||||
char* pszX; /* work pointer */
|
||||
|
||||
pszX = *p_pszToken; // get pointer to token
|
||||
pszX = *p_pszToken; /* get pointer to token */
|
||||
|
||||
for (iI = 0; *(pszX + iI) && (!isspace(*(pszX + iI)));) // while not whitespace & not end
|
||||
iI++; // .. count token length
|
||||
for (iI = 0; *(pszX + iI) && (!isspace(*(pszX + iI)));) /* while not whitespace & not end */
|
||||
iI++; /* .. count token length */
|
||||
|
||||
memset(p_szOut, 0, p_iLen); // zero out output area
|
||||
memset(p_szOut, 0, p_iLen); /* zero out output area */
|
||||
|
||||
if (iI > 0) // q. any chars?
|
||||
strncpy(p_szOut, *p_pszToken, MIN(iI, p_iLen-1)); // a. yes.. copy max of p_iLen-1
|
||||
if (iI > 0) /* q. any chars? */
|
||||
strncpy(p_szOut, *p_pszToken, MIN(iI, p_iLen-1)); /* a. yes.. copy max of p_iLen-1 */
|
||||
|
||||
*p_pszToken += iI; // point beyond token
|
||||
return p_szOut; // .. return token pointer
|
||||
*p_pszToken += iI; /* point beyond token */
|
||||
return p_szOut; /* .. return token pointer */
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// EditToAsm - convert tab-formatted text line to 1130 Assembler format
|
||||
/*************************************************
|
||||
* EditToAsm - convert tab-formatted text line to 1130 Assembler format
|
||||
*/
|
||||
|
||||
char *EditToAsm (char* p_pszEdit) // convert line to 1130 assembler
|
||||
char *EditToAsm (char* p_pszEdit) /* convert line to 1130 assembler */
|
||||
{
|
||||
char pszLine[MAXLINE]; // source line
|
||||
char pszWork[WORKSZ]; // work buffer
|
||||
char acTFWrk[2]; // tag/format work area
|
||||
size_t iI; // work integer
|
||||
char pszLine[MAXLINE]; /* source line */
|
||||
char pszWork[WORKSZ]; /* work buffer */
|
||||
char acTFWrk[2]; /* tag/format work area */
|
||||
size_t iI; /* work integer */
|
||||
|
||||
if (p_pszEdit == NULL) // q. null request?
|
||||
return AMSG; // a. yes .. return display message
|
||||
if (p_pszEdit == NULL) /* q. null request? */
|
||||
return AMSG; /* a. yes .. return display message */
|
||||
|
||||
if (*p_pszEdit == '!') // leave lines starting with ! alone
|
||||
if (*p_pszEdit == '!') /* leave lines starting with ! alone */
|
||||
return EditToWhitespace(p_pszEdit+1);
|
||||
|
||||
if (*p_pszEdit == '*') // q. comment line?
|
||||
{ // a. yes..
|
||||
strncpy(pszWork, EditToWhitespace(p_pszEdit), MAXLINE); // .. convert any tabs
|
||||
sprintf(gszOutput, ACOMMENTFMT, pszWork); // .. put the comment out there in the opcode column
|
||||
return gszOutput; // .. and return it
|
||||
if (*p_pszEdit == '*') /* q. comment line? */
|
||||
{ /* a. yes.. */
|
||||
strncpy(pszWork, EditToWhitespace(p_pszEdit), MAXLINE); /* .. convert any tabs */
|
||||
sprintf(gszOutput, ACOMMENTFMT, pszWork); /* .. put the comment out there in the opcode column */
|
||||
return gszOutput; /* .. and return it */
|
||||
}
|
||||
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); /* copy the line local */
|
||||
|
||||
ExpandTabs(pszLine, pszWork, gaiAsmTabs); // expand the tabs
|
||||
strncpy(pszLine, pszWork, MAXLINE-1); // copy the line back
|
||||
ExpandTabs(pszLine, pszWork, gaiAsmTabs); /* expand the tabs */
|
||||
strncpy(pszLine, pszWork, MAXLINE-1); /* copy the line back */
|
||||
|
||||
for (iI = strlen(pszLine); iI--;) // trim trailing whitespace
|
||||
for (iI = strlen(pszLine); iI--;) /* trim trailing whitespace */
|
||||
{
|
||||
if (*(pszLine + iI) <= ' ') // q. space or less?
|
||||
*(pszLine + iI) = 0; // a. yes .. remove it
|
||||
else // otherwise
|
||||
break; // .. done. Leave loop.
|
||||
if (*(pszLine + iI) <= ' ') /* q. space or less? */
|
||||
*(pszLine + iI) = 0; /* a. yes .. remove it */
|
||||
else /* otherwise */
|
||||
break; /* .. done. Leave loop. */
|
||||
}
|
||||
|
||||
if (strlen(pszLine) == 0) // q. blank line?
|
||||
{ // a. yes .. Assembler abhors these so
|
||||
sprintf(gszOutput, ABLANKLINE); // format as comment statement
|
||||
return gszOutput; // .. and return it
|
||||
if (strlen(pszLine) == 0) /* q. blank line? */
|
||||
{ /* a. yes .. Assembler abhors these so */
|
||||
sprintf(gszOutput, ABLANKLINE); /* format as comment statement */
|
||||
return gszOutput; /* .. and return it */
|
||||
}
|
||||
|
||||
|
||||
// TODO: Add code to process a strip switch
|
||||
// comment?
|
||||
/* TODO: Add code to process a strip switch
|
||||
* comment?
|
||||
*/
|
||||
|
||||
if (strlen(pszLine) > (TAGOFFSET + 1)) // q. line long enough?
|
||||
{ // a. yes.. reorder tag/format
|
||||
memcpy(acTFWrk, pszLine + FMTOFFSET, 2); // get tag/format
|
||||
memset((pszLine + FMTOFFSET), ' ', 2); // .. blank 'em out
|
||||
if (strlen(pszLine) > (TAGOFFSET + 1)) /* q. line long enough? */
|
||||
{ /* a. yes.. reorder tag/format */
|
||||
memcpy(acTFWrk, pszLine + FMTOFFSET, 2); /* get tag/format */
|
||||
memset((pszLine + FMTOFFSET), ' ', 2); /* .. blank 'em out */
|
||||
|
||||
for (iI = 0; iI < 2; iI ++)
|
||||
if (isalpha(acTFWrk[iI])) // q. alpha char?
|
||||
*(pszLine + FMTOFFSET) = acTFWrk[iI]; // a. yes .. make it format
|
||||
else if (isdigit(acTFWrk[iI])) // q. digit?
|
||||
*(pszLine + TAGOFFSET) = acTFWrk[iI]; // a. yes .. make it the tag
|
||||
if (isalpha(acTFWrk[iI])) /* q. alpha char? */
|
||||
*(pszLine + FMTOFFSET) = acTFWrk[iI]; /* a. yes .. make it format */
|
||||
else if (isdigit(acTFWrk[iI])) /* q. digit? */
|
||||
*(pszLine + TAGOFFSET) = acTFWrk[iI]; /* a. yes .. make it the tag */
|
||||
}
|
||||
|
||||
sprintf(gszOutput, AFORMAT, pszLine); // format the line
|
||||
sprintf(gszOutput, AFORMAT, pszLine); /* format the line */
|
||||
|
||||
return gszOutput; // return formatted line
|
||||
return gszOutput; /* return formatted line */
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// EditToFortran - convert tab-formatted input text line to FORTRAN format
|
||||
// (a la DEC Fortran)
|
||||
/*************************************************
|
||||
* EditToFortran - convert tab-formatted input text line to FORTRAN format
|
||||
* (a la DEC Fortran)
|
||||
*/
|
||||
|
||||
char *EditToFortran(char* p_pszEdit) // convert line to 1130 assembler
|
||||
char *EditToFortran(char* p_pszEdit) /* convert line to 1130 assembler */
|
||||
{
|
||||
char pszLine[MAXLINE]; // source line
|
||||
char* pszWork; // work pointer
|
||||
size_t iI; // work integer
|
||||
int bContinue; // true if continue
|
||||
char pszLine[MAXLINE]; /* source line */
|
||||
char* pszWork; /* work pointer */
|
||||
size_t iI; /* work integer */
|
||||
int bContinue; /* true if continue */
|
||||
|
||||
if (p_pszEdit == NULL) // q. null request?
|
||||
return FMSG; // a. yes .. return display message
|
||||
if (p_pszEdit == NULL) /* q. null request? */
|
||||
return FMSG; /* a. yes .. return display message */
|
||||
|
||||
if (strchr(p_pszEdit, '\t') == NULL) // q. no tab in the line?
|
||||
return p_pszEdit; // a. nope, return line as is, assume it's formatted correctly
|
||||
if (strchr(p_pszEdit, '\t') == NULL) /* q. no tab in the line? */
|
||||
return p_pszEdit; /* a. nope, return line as is, assume it's formatted correctly */
|
||||
|
||||
if (*p_pszEdit == 'C' || *p_pszEdit == '*' || *p_pszEdit == '\0') // q. comment or directive or blank line?
|
||||
{ // a. yes.. don't restructure
|
||||
if (*p_pszEdit == 'C' || *p_pszEdit == '*' || *p_pszEdit == '\0') /* q. comment or directive or blank line? */
|
||||
{ /* a. yes.. don't restructure */
|
||||
return EditToWhitespace(p_pszEdit);
|
||||
}
|
||||
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); /* copy the line local */
|
||||
|
||||
for (iI = strlen(pszLine); iI--;) // trim trailing whitespace
|
||||
for (iI = strlen(pszLine); iI--;) /* trim trailing whitespace */
|
||||
{
|
||||
if (*(pszLine + iI) <= ' ') // q. space or less?
|
||||
*(pszLine + iI) = 0; // a. yes .. remove it
|
||||
else // otherwise
|
||||
break; // .. done. Leave loop.
|
||||
if (*(pszLine + iI) <= ' ') /* q. space or less? */
|
||||
*(pszLine + iI) = 0; /* a. yes .. remove it */
|
||||
else /* otherwise */
|
||||
break; /* .. done. Leave loop. */
|
||||
}
|
||||
|
||||
// TODO: Add code to process a strip switch
|
||||
// comment?
|
||||
/*
|
||||
* TODO: Add code to process a strip switch
|
||||
* comment?
|
||||
*/
|
||||
|
||||
pszWork = (char*) pszLine; // set pointer to line
|
||||
GetToken(gszLabel, 6, &pszWork); // get the line, if any.
|
||||
pszWork = (char*) pszLine; /* set pointer to line */
|
||||
GetToken(gszLabel, 6, &pszWork); /* get the line, if any. */
|
||||
|
||||
pszWork++; // skip tab/whitespace
|
||||
pszWork++; /* skip tab/whitespace */
|
||||
|
||||
// continuation...
|
||||
bContinue = ((isdigit(*pszWork) && (*pszWork != '0')) // if first char non-zero digit
|
||||
|| (!isspace(*pszWork) && !isalpha(*pszWork))); // .. or non-alpha non-blank
|
||||
/* continuation... */
|
||||
bContinue = ((isdigit(*pszWork) && (*pszWork != '0')) /* if first char non-zero digit */
|
||||
|| (!isspace(*pszWork) && !isalpha(*pszWork))); /* .. or non-alpha non-blank */
|
||||
|
||||
memset(gszArg, 0, MAXLINE); // .. and arguments
|
||||
memset(gszArg, 0, MAXLINE); /* .. and arguments */
|
||||
|
||||
strncpy(gszArg, pszWork, 75); // copy rest to argument
|
||||
strncpy(gszArg, pszWork, 75); /* copy rest to argument */
|
||||
|
||||
sprintf(gszOutput, (bContinue) ? FCONTFMT : FFORMAT, // format the line
|
||||
gszLabel, // .. statement #
|
||||
gszArg); // .. code
|
||||
sprintf(gszOutput, (bContinue) ? FCONTFMT : FFORMAT, /* format the line */
|
||||
gszLabel, /* .. statement # */
|
||||
gszArg); /* .. code */
|
||||
|
||||
return gszOutput; // return formatted line
|
||||
return gszOutput; /* return formatted line */
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// EditToWhitespace - expand tabs at 8 space intervals.
|
||||
/*************************************************
|
||||
* EditToWhitespace - expand tabs at 8 space intervals.
|
||||
*/
|
||||
|
||||
char* EditToWhitespace(char *p_pszEdit)
|
||||
{
|
||||
int iI; /* work integer */
|
||||
char pszLine[MAXLINE]; // source line
|
||||
char pszWork[WORKSZ]; // work buffer
|
||||
char pszLine[MAXLINE]; /* source line */
|
||||
char pszWork[WORKSZ]; /* work buffer */
|
||||
|
||||
if (p_pszEdit == NULL) // q. null request?
|
||||
return AMSG; // a. yes .. return display message
|
||||
if (p_pszEdit == NULL) /* q. null request? */
|
||||
return AMSG; /* a. yes .. return display message */
|
||||
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local
|
||||
strncpy(pszLine, p_pszEdit, MAXLINE-1); /* copy the line local */
|
||||
|
||||
ExpandTabs(pszLine, pszWork, gaiPlainTabs); // expand the tabs
|
||||
strncpy(gszOutput, pszWork, MAXLINE-1); // copy the line back
|
||||
ExpandTabs(pszLine, pszWork, gaiPlainTabs); /* expand the tabs */
|
||||
strncpy(gszOutput, pszWork, MAXLINE-1); /* copy the line back */
|
||||
|
||||
for (iI = strlen(gszOutput); iI--;) // look at each character
|
||||
for (iI = strlen(gszOutput); iI--;) /* look at each character */
|
||||
{
|
||||
if (*(gszOutput + iI) <= ' ') // q. space or less?
|
||||
*(gszOutput + iI) = 0; // a. yes .. remove it
|
||||
else // otherwise
|
||||
break; // .. done. Leave loop.
|
||||
if (*(gszOutput + iI) <= ' ') /* q. space or less? */
|
||||
*(gszOutput + iI) = 0; /* a. yes .. remove it */
|
||||
else /* otherwise */
|
||||
break; /* .. done. Leave loop. */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
/* ibm1130_asm.h: definition of routines in ibm1130_asm.c
|
||||
*/
|
||||
|
||||
char* EditToAsm(char*); // convert edit format to 1130 assembler format
|
||||
char* EditToFortran(char*); // convert edit format to Fortran format
|
||||
char* EditToWhitespace(char*); // clean white space, tabstops every 8 positions
|
||||
char* EditToAsm(char*); /* convert edit format to 1130 assembler format */
|
||||
char* EditToFortran(char*); /* convert edit format to Fortran format */
|
||||
char* EditToWhitespace(char*); /* clean white space, tabstops every 8 positions */
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
/* ibm1130_gdu.c: IBM 1130 2250 Graphical Display Unit
|
||||
|
||||
(Under construction)
|
||||
// stuff to fix:
|
||||
// "store revert" might be backwards?
|
||||
// alpha keyboard is not implemented
|
||||
// pushbuttons are not implemented
|
||||
// there is something about interrupts being deferred during a subroutine transition?
|
||||
stuff to fix:
|
||||
"store revert" might be backwards?
|
||||
alpha keyboard is not implemented
|
||||
pushbuttons are not implemented
|
||||
there is something about interrupts being deferred during a subroutine transition?
|
||||
|
||||
Based on the SIMH package written by Robert M Supnik
|
||||
|
||||
|
@ -21,13 +21,13 @@
|
|||
* Mail to simh@ibm1130.org
|
||||
*/
|
||||
|
||||
#define BLIT_MODE // normally defined, undefine when debugging generate_image()
|
||||
//#define DEBUG_LIGHTPEN // normally undefined, define to visualize light-pen sensing
|
||||
#define BLIT_MODE /* define for better performance, undefine when debugging generate_image() */
|
||||
/* #define DEBUG_LIGHTPEN */ /* define to debug light-pen sensing */
|
||||
|
||||
#define DEFAULT_GDU_RATE 20 // default frame rate
|
||||
#define DEFAULT_PEN_THRESHOLD 3 // default looseness of light-pen hit
|
||||
#define INDWIDTH 32 // width of an indicator (there are two columns of these)
|
||||
#define INITSIZE 512 // initial window size
|
||||
#define DEFAULT_GDU_RATE 20 /* default frame rate */
|
||||
#define DEFAULT_PEN_THRESHOLD 3 /* default looseness of light-pen hit */
|
||||
#define INDWIDTH 32 /* width of an indicator (there are two columns of these) */
|
||||
#define INITSIZE 512 /* initial window size */
|
||||
|
||||
#define GDU_DSW_ORDER_CONTROLLED_INTERRUPT 0x8000
|
||||
#define GDU_DSW_KEYBOARD_INTERUPT 0x4000
|
||||
|
@ -109,7 +109,7 @@ static t_stat gdu_reset (DEVICE *dptr)
|
|||
|
||||
void xio_2250_display (int32 addr, int32 func, int32 modify)
|
||||
{
|
||||
// ignore commands to nonexistent device
|
||||
/* ignore commands if device is nonexistent */
|
||||
}
|
||||
|
||||
t_bool gdu_active (void)
|
||||
|
@ -118,7 +118,7 @@ t_bool gdu_active (void)
|
|||
}
|
||||
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
#else // GUI_SUPPORT defined
|
||||
#else /* GUI_SUPPORT defined */
|
||||
|
||||
/******* PLATFORM INDEPENDENT CODE ********************************************************/
|
||||
|
||||
|
@ -127,7 +127,6 @@ static int xmouse, ymouse, lpen_dist, lpen_dist2; // current mouse pointer, scal
|
|||
static double sfactor; // current scaling factor
|
||||
static t_bool last_abs = TRUE; // last positioning instruction was absolute
|
||||
static t_bool mouse_present = FALSE; // mouse is/is not in the window
|
||||
|
||||
static void clear_interrupts (void);
|
||||
static void set_indicators (int32 new_inds);
|
||||
static void start_regeneration (void);
|
||||
|
@ -239,23 +238,27 @@ static void start_regeneration (void)
|
|||
{
|
||||
SETBIT(gdu_dsw, GDU_DSW_BUSY);
|
||||
|
||||
if (gdu_unit.flags & UNIT_DISPLAYED) {
|
||||
StartGDUUpdates();
|
||||
}
|
||||
else {
|
||||
if ((gdu_unit.flags & UNIT_DISPLAYED) == 0) {
|
||||
if (! CreateGDUWindow())
|
||||
return;
|
||||
|
||||
SETBIT(gdu_unit.flags, UNIT_DISPLAYED);
|
||||
}
|
||||
|
||||
StartGDUUpdates();
|
||||
}
|
||||
|
||||
static void halt_regeneration (void)
|
||||
{
|
||||
// halt_regeneration gets called at end of every refresh interation, so it should NOT black out the
|
||||
// screen -- this is why it was flickering so badly. The lower level code (called on a timer)
|
||||
// should check to see if GDU_DSW_BUSY is clear, and if it it still zero after several msec,
|
||||
// only then should it black out the screen and call StopGDUUpdates.
|
||||
if (gdu_dsw & GDU_DSW_BUSY) {
|
||||
StopGDUUpdates();
|
||||
// StopGDUUpdates(); // let lower level code discover this during next refresh
|
||||
CLRBIT(gdu_dsw, GDU_DSW_BUSY);
|
||||
}
|
||||
EraseGDUScreen();
|
||||
// EraseGDUScreen(); // let cessation of regeneration erase it (eventually)
|
||||
}
|
||||
|
||||
static void notify_window_closed (void)
|
||||
|
@ -264,7 +267,9 @@ static void notify_window_closed (void)
|
|||
StopGDUUpdates();
|
||||
CLRBIT(gdu_dsw, GDU_DSW_BUSY);
|
||||
}
|
||||
|
||||
CLRBIT(gdu_unit.flags, UNIT_DISPLAYED);
|
||||
|
||||
gdu_reset(&gdu_dev);
|
||||
}
|
||||
|
||||
|
@ -671,7 +676,7 @@ static HPEN hRedPen = NULL;
|
|||
#endif
|
||||
static HBRUSH hGrayBrush, hDarkBrush;
|
||||
static HPEN hBlackPen;
|
||||
|
||||
static int halted = 0; // number of time intervals that GDU has been halted w/o a regeneration
|
||||
static LRESULT APIENTRY GDUWndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
|
||||
static DWORD WINAPI GDUPump (LPVOID arg);
|
||||
|
||||
|
@ -719,11 +724,6 @@ static t_bool CreateGDUWindow (void)
|
|||
{
|
||||
static BOOL did_atexit = FALSE;
|
||||
|
||||
if (hwGDU != NULL) { // window already exists
|
||||
StartGDUUpdates();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
hInstance = GetModuleHandle(NULL);
|
||||
|
||||
if (hGDUPump == INVALID_HANDLE_VALUE)
|
||||
|
@ -878,7 +878,7 @@ static void gdu_WM_PAINT (HWND hWnd)
|
|||
|
||||
static void gdu_WM_SIZE (HWND hWnd, UINT state, int cx, int cy)
|
||||
{
|
||||
InvalidateRect(hWnd, NULL, FALSE);
|
||||
InvalidateRect(hWnd, NULL, TRUE);
|
||||
}
|
||||
|
||||
// tweak the sizing rectangle during a resize to guarantee a square window
|
||||
|
@ -912,6 +912,16 @@ static void gdu_WM_TIMER (HWND hWnd, UINT id)
|
|||
HDC hDC;
|
||||
|
||||
if (running) { // if CPU is running, update picture
|
||||
if ((gdu_dsw & GDU_DSW_BUSY) == 0) { // regeneration is not to occur
|
||||
if (++halted >= 4) { // stop the timer if four timer intervals go by with the display halted
|
||||
EraseGDUScreen(); // screen goes black due to cessation of refreshing
|
||||
StopGDUUpdates(); // might as well kill the timer
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
halted = 0;
|
||||
|
||||
#ifdef BLIT_MODE
|
||||
hDC = GetDC(hWnd); // blit the new image right over the old
|
||||
PaintImage(hDC, FALSE);
|
||||
|
@ -964,7 +974,7 @@ static void DrawPoint (int x, int y)
|
|||
static void UpdateGDUIndicators(void)
|
||||
{
|
||||
if (hwGDU != NULL)
|
||||
InvalidateRect(hwGDU, NULL, TRUE);
|
||||
InvalidateRect(hwGDU, NULL, FALSE); // no need to erase the background -- the draw routine fully paints the indicator
|
||||
}
|
||||
|
||||
static void CheckGDUKeyboard (void)
|
||||
|
@ -981,6 +991,7 @@ static void StartGDUUpdates (void)
|
|||
msec = (gdu_rate == 0) ? (1000 / DEFAULT_GDU_RATE) : 1000/gdu_rate;
|
||||
idTimer = SetTimer(hwGDU, 1, msec, NULL);
|
||||
}
|
||||
halted = 0;
|
||||
}
|
||||
|
||||
static void StopGDUUpdates (void)
|
||||
|
@ -988,6 +999,7 @@ static void StopGDUUpdates (void)
|
|||
if (idTimer != 0) {
|
||||
KillTimer(hwGDU, 1);
|
||||
idTimer = 0;
|
||||
halted = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1086,8 +1098,6 @@ static DWORD WINAPI GDUPump (LPVOID arg)
|
|||
ShowWindow(hwGDU, SW_SHOWNOACTIVATE); /* display it */
|
||||
UpdateWindow(hwGDU);
|
||||
|
||||
StartGDUUpdates();
|
||||
|
||||
while (GetMessage(&msg, hwGDU, 0, 0)) { /* message pump - this basically loops forevermore */
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
* This is not a supported product, but I welcome bug reports and fixes.
|
||||
* Mail to simh@ibm1130.org
|
||||
*
|
||||
* 30-Dec-05 BLK Fixed mask for IAR and SAR register display and added display
|
||||
* of Arithmetic Factor, per Carl Claunch.
|
||||
*
|
||||
* 09-Apr-04 BLK Changed code to use stock windows cursor IDC_HAND if available
|
||||
*
|
||||
* 02-Dec-02 BLK Changed display, added printer and card reader icons
|
||||
|
@ -33,9 +36,9 @@
|
|||
#define UPDATE_BY_TIMER
|
||||
|
||||
#ifdef UPDATE_BY_TIMER
|
||||
# define UPDATE_INTERVAL 20 // set to desired number of updates/second
|
||||
# define UPDATE_INTERVAL 20 /* set to desired number of updates/second */
|
||||
#else
|
||||
# define UPDATE_INTERVAL 5000 // GUI: set to 100000/f where f = desired updates/second of 1130 time
|
||||
# define UPDATE_INTERVAL 5000 /* GUI: set to 100000/f where f = desired updates/second of 1130 time */
|
||||
#endif
|
||||
|
||||
#define UNIT_V_CR_EMPTY (UNIT_V_UF + 5) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_cr.c */
|
||||
|
@ -46,8 +49,9 @@
|
|||
#define UNIT_V_PHYSICAL_PTR (UNIT_V_UF + 10) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_prt.c */
|
||||
#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR)
|
||||
|
||||
// I think I had it wrong; Program Load actually does start the processor after
|
||||
// reading in the card?
|
||||
/* I think I had it wrong; Program Load actually does start the processor after
|
||||
* reading in the card?
|
||||
*/
|
||||
|
||||
#define PROGRAM_LOAD_STARTS_CPU
|
||||
|
||||
|
@ -86,7 +90,7 @@ DEVICE console_dev = {
|
|||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
// reset for the "console" display device
|
||||
/* reset for the "console" display device */
|
||||
|
||||
extern char *read_line (char *cptr, int size, FILE *stream);
|
||||
extern FILE *sim_log;
|
||||
|
@ -117,8 +121,8 @@ extern UNIT prt_unit;
|
|||
t_stat console_reset (DEVICE *dptr)
|
||||
{
|
||||
if (! sim_gui) {
|
||||
SETBIT(console_unit.flags, UNIT_DIS); // disable the GUI
|
||||
CLRBIT(console_unit.flags, UNIT_DISPLAY); // turn the GUI off
|
||||
SETBIT(console_unit.flags, UNIT_DIS); /* disable the GUI */
|
||||
CLRBIT(console_unit.flags, UNIT_DISPLAY); /* turn the GUI off */
|
||||
}
|
||||
|
||||
update_gui(FALSE);
|
||||
|
@ -158,19 +162,19 @@ void scp_panic (char *msg)
|
|||
#define IDC_RESET 14
|
||||
#define IDC_PROGRAM_LOAD 15
|
||||
|
||||
#define IDC_TEAR 16 // standard button
|
||||
#define IDC_1442 17 // device images
|
||||
#define IDC_TEAR 16 /* standard button */
|
||||
#define IDC_1442 17 /* device images */
|
||||
#define IDC_1132 18
|
||||
|
||||
#define LAMPTIME 500 // 500 msec delay on updating
|
||||
#define LAMPTIME 500 /* 500 msec delay on updating */
|
||||
#define FLASH_TIMER_ID 1
|
||||
#define UPDATE_TIMER_ID 2
|
||||
|
||||
#define RUNSWITCH_X 689 // center of the run mode switch dial
|
||||
#define RUNSWITCH_X 689 /* center of the run mode switch dial */
|
||||
#define RUNSWITCH_Y 107
|
||||
#define TOGGLES_X 122 // left edge of series of toggle switches
|
||||
#define TOGGLES_X 122 /* left edge of series of toggle switches */
|
||||
|
||||
#define TXTBOX_X 200 // text labels showing attached devices
|
||||
#define TXTBOX_X 200 /* text labels showing attached devices */
|
||||
#define TXTBOX_Y 300
|
||||
#define TXTBOX_WIDTH 195
|
||||
#define TXTBOX_HEIGHT 12
|
||||
|
@ -238,19 +242,18 @@ static struct tag_btn {
|
|||
TXTBOX_X+40, TXTBOX_Y+25, 35, 12, "Tear", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
635, 238, 110, 110, "EMPTY_1442", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
635, 366, 110, 110, "EMPTY_1132", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
// 635, 366, 110, 110, "EMPTY_1132", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
};
|
||||
#define NBUTTONS (sizeof(btn) / sizeof(btn[0]))
|
||||
|
||||
#define STATE_1442_EMPTY 0 // no cards (no file attached)
|
||||
#define STATE_1442_FULL 1 // cards in hopper (file attached at BOF)
|
||||
#define STATE_1442_MIDDLE 2 // cards in hopper and stacker (file attached, neither EOF nor BOF)
|
||||
#define STATE_1442_EOF 3 // cards in stacker (file attached, at EOF)
|
||||
#define STATE_1442_HIDDEN 4 // simulator is attached to physical card reader
|
||||
#define STATE_1442_EMPTY 0 /* no cards (no file attached) */
|
||||
#define STATE_1442_FULL 1 /* cards in hopper (file attached at BOF) */
|
||||
#define STATE_1442_MIDDLE 2 /* cards in hopper and stacker (file attached, neither EOF nor BOF) */
|
||||
#define STATE_1442_EOF 3 /* cards in stacker (file attached, at EOF) */
|
||||
#define STATE_1442_HIDDEN 4 /* simulator is attached to physical card reader */
|
||||
|
||||
#define STATE_1132_EMPTY 0 // no paper hanging out of printer
|
||||
#define STATE_1132_FULL 1 // paper hanging out of printer
|
||||
#define STATE_1132_HIDDEN 2 // printer is attached to physical printer
|
||||
#define STATE_1132_EMPTY 0 /* no paper hanging out of printer */
|
||||
#define STATE_1132_FULL 1 /* paper hanging out of printer */
|
||||
#define STATE_1132_HIDDEN 2 /* printer is attached to physical printer */
|
||||
|
||||
static struct tag_txtbox {
|
||||
int x, y;
|
||||
|
@ -309,9 +312,9 @@ static void destroy_console_window (void)
|
|||
int i;
|
||||
|
||||
if (hConsoleWnd != NULL)
|
||||
SendMessage(hConsoleWnd, WM_CLOSE, 0, 0); // cross thread call is OK
|
||||
SendMessage(hConsoleWnd, WM_CLOSE, 0, 0); /* cross thread call is OK */
|
||||
|
||||
if (hPump != INVALID_HANDLE_VALUE) { // this is not the most graceful way to do it
|
||||
if (hPump != INVALID_HANDLE_VALUE) { /* this is not the most graceful way to do it */
|
||||
TerminateThread(hPump, 0);
|
||||
hPump = INVALID_HANDLE_VALUE;
|
||||
PumpID = 0;
|
||||
|
@ -338,10 +341,11 @@ static void destroy_console_window (void)
|
|||
NIXOBJECT(btn[i].hbrDark);
|
||||
}
|
||||
|
||||
// if (class_defined) {
|
||||
// UnregisterClass(hInstance, szConsoleClassName);
|
||||
// class_defined = FALSE;
|
||||
// }
|
||||
/* if (class_defined) {
|
||||
UnregisterClass(hInstance, szConsoleClassName);
|
||||
class_defined = FALSE;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
|
@ -350,7 +354,7 @@ static void destroy_console_window (void)
|
|||
|
||||
static int shown_iar = 0, shown_sar = 0, shown_sbr = 0, shown_afr = 0, shown_acc = 0, shown_ext = 0;
|
||||
static int shown_op = 0, shown_tag = 0, shown_irq = 0, shown_ccc = 0, shown_cnd = 0, shown_wait = 0;
|
||||
static int shown_ces = 0, shown_runmode = MODE_RUN;
|
||||
static int shown_ces = 0, shown_arf = 0, shown_runmode = MODE_RUN;
|
||||
static int CND;
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
|
@ -402,7 +406,7 @@ void update_gui (BOOL force)
|
|||
static int32 displayed = 0;
|
||||
RECT xin;
|
||||
|
||||
if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { // setting has changed
|
||||
if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { /* setting has changed */
|
||||
displayed = console_unit.flags & UNIT_DISPLAY;
|
||||
if (displayed)
|
||||
init_console_window();
|
||||
|
@ -438,6 +442,8 @@ void update_gui (BOOL force)
|
|||
{shown_iar = IAR; RedrawRegion(hConsoleWnd, 75, 8, 364, 32);} /* lamps: don't bother erasing bkgnd */
|
||||
if (SAR != shown_sar)
|
||||
{shown_sar = SAR; RedrawRegion(hConsoleWnd, 75, 42, 364, 65);}
|
||||
if (ARF != shown_arf)
|
||||
{shown_arf = ARF; RedrawRegion(hConsoleWnd, 75, 114, 364, 136);}
|
||||
if (ACC != shown_acc)
|
||||
{shown_acc = ACC; RedrawRegion(hConsoleWnd, 75, 141, 364, 164);}
|
||||
if (EXT != shown_ext)
|
||||
|
@ -465,7 +471,7 @@ void update_gui (BOOL force)
|
|||
|
||||
int_lamps = 0;
|
||||
|
||||
// this loop works with lamp buttons that are calculated on-the-fly only
|
||||
/* this loop works with lamp buttons that are calculated on-the-fly only */
|
||||
for (i = 0; i < NBUTTONS; i++) {
|
||||
if (btn[i].pushable)
|
||||
continue;
|
||||
|
@ -475,26 +481,28 @@ void update_gui (BOOL force)
|
|||
state = hFlashTimer || (running && ! wait_state);
|
||||
break;
|
||||
|
||||
// this button is always off
|
||||
// case IDC_PARITY_CHECK:
|
||||
/* this button is always off
|
||||
case IDC_PARITY_CHECK
|
||||
*/
|
||||
|
||||
// these buttons are enabled/disabled directly
|
||||
// case IDC_POWER_ON:
|
||||
// case IDC_FILE_READY:
|
||||
// case IDC_FORMS_CHECK:
|
||||
// case IDC_KEYBOARD_SELECT:
|
||||
// case IDC_DISK_UNLOCK:
|
||||
/* these buttons are enabled/disabled directly
|
||||
case IDC_POWER_ON:
|
||||
case IDC_FILE_READY:
|
||||
case IDC_FORMS_CHECK:
|
||||
case IDC_KEYBOARD_SELECT:
|
||||
case IDC_DISK_UNLOCK:
|
||||
*/
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state != btn[i].state) { // state has changed
|
||||
if (state != btn[i].state) { /* state has changed */
|
||||
EnableWindow(btn[i].hBtn, state);
|
||||
btn[i].state = state;
|
||||
}
|
||||
}
|
||||
|
||||
if (force) { // if force flag is set, update text region
|
||||
if (force) { /* if force flag is set, update text region */
|
||||
SetRect(&xin, TXTBOX_X, TXTBOX_Y, TXTBOX_X+TXTBOX_WIDTH, TXTBOX_BOTTOM+2*TXTBOX_HEIGHT);
|
||||
InvalidateRect(hConsoleWnd, &xin, TRUE);
|
||||
}
|
||||
|
@ -584,9 +592,9 @@ static int occurs (char *txt, char ch)
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
// turns out to get properly colored buttons you have to paint them yourself. Sheesh.
|
||||
// On the plus side, this lets do a better job of aligning the button text than
|
||||
// the button would by itself.
|
||||
* turns out to get properly colored buttons you have to paint them yourself. Sheesh.
|
||||
* On the plus side, this lets do a better job of aligning the button text than
|
||||
* the button would by itself.
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
void PaintButton (LPDRAWITEMSTRUCT dis)
|
||||
|
@ -616,7 +624,7 @@ void PaintButton (LPDRAWITEMSTRUCT dis)
|
|||
LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top);
|
||||
}
|
||||
else if (down) {
|
||||
// do the three-D thing
|
||||
/* do the three-D thing */
|
||||
hOldPen = SelectObject(dis->hDC, hDkGreyPen);
|
||||
MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-2, NULL);
|
||||
LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top);
|
||||
|
@ -776,7 +784,7 @@ static DWORD WINAPI Pump (LPVOID arg)
|
|||
|
||||
hcArrow = LoadCursor(NULL, IDC_ARROW);
|
||||
#ifdef IDC_HAND
|
||||
hcHand = LoadCursor(NULL, IDC_HAND); // use stock object provided by Windows
|
||||
hcHand = LoadCursor(NULL, IDC_HAND); /* use stock object provided by Windows */
|
||||
if (hcHand == NULL)
|
||||
hcHand = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_MYHAND));
|
||||
#else
|
||||
|
@ -816,12 +824,13 @@ static DWORD WINAPI Pump (LPVOID arg)
|
|||
EnableWindow(btn[i].hBtn, btn[i].state);
|
||||
}
|
||||
|
||||
// This isn't needed anymore, now that we have the big printer icon -- it acts like a button now
|
||||
// i = IDC_TEAR;
|
||||
// btn[i].hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER,
|
||||
// btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL);
|
||||
//
|
||||
// SendMessage(btn[i].hBtn, WM_SETFONT, (WPARAM) hTinyFont, TRUE);
|
||||
/* This isn't needed anymore, now that we have the big printer icon -- it acts like a button now
|
||||
* i = IDC_TEAR;
|
||||
* btn[i].hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER,
|
||||
* btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL);
|
||||
*
|
||||
* SendMessage(btn[i].hBtn, WM_SETFONT, (WPARAM) hTinyFont, TRUE);
|
||||
*/
|
||||
|
||||
hbm1442_full = LoadBitmap(hInstance, "FULL_1442");
|
||||
hbm1442_empty = LoadBitmap(hInstance, "EMPTY_1442");
|
||||
|
@ -836,7 +845,6 @@ static DWORD WINAPI Pump (LPVOID arg)
|
|||
btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL);
|
||||
btn[i].state = STATE_1442_EMPTY;
|
||||
|
||||
// wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1442_full);
|
||||
wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1442_empty);
|
||||
|
||||
i = IDC_1132;
|
||||
|
@ -847,13 +855,6 @@ static DWORD WINAPI Pump (LPVOID arg)
|
|||
|
||||
wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1132_empty);
|
||||
|
||||
// for (i = 0; i < NTXTBOXES; i++) {
|
||||
// txtbox[i].hBox = CreateWindow("EDIT", txtbox[i].txt,
|
||||
// WS_CHILD|WS_VISIBLE|ES_LEFT|ES_READONLY,
|
||||
// txtbox[i].x, txtbox[i].y, TXTBOX_WIDTH, TXTBOX_HEIGHT, hConsoleWnd, (HMENU) (i+100), hInstance, NULL);
|
||||
// SendMessage(txtbox[i].hBox, WM_SETFONT, (WPARAM) hTinyFont, TRUE);
|
||||
// }
|
||||
|
||||
GetWindowRect(hConsoleWnd, &r); /* get window size as created */
|
||||
wx = r.right - r.left + 1;
|
||||
wy = r.bottom - r.top + 1;
|
||||
|
@ -991,7 +992,7 @@ void DrawRunmode (HDC hDC, int mode)
|
|||
* than a mouse-region test. Return value TRUE means the cursor is over a hotspot.
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual)
|
||||
static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual, BOOL rightclick)
|
||||
{
|
||||
int b, x, r, ang, i;
|
||||
|
||||
|
@ -1054,9 +1055,10 @@ static void DrawConsole (HDC hDC, PAINTSTRUCT *ps)
|
|||
|
||||
SetBkMode(hDC, TRANSPARENT); /* overlay letters w/o changing background */
|
||||
|
||||
DrawBits(hDC, 76, 15, shown_iar, 16, 0x3FFF, digits);
|
||||
DrawBits(hDC, 76, 48, shown_sar, 16, 0x3FFF, digits);
|
||||
DrawBits(hDC, 76, 15, shown_iar, 16, mem_mask, digits); /* register holds only 15 bits */
|
||||
DrawBits(hDC, 76, 48, shown_sar, 16, mem_mask, digits); /* but let's display only used bits */
|
||||
DrawBits(hDC, 76, 81, shown_sbr, 16, 0xFFFF, digits);
|
||||
DrawBits(hDC, 76, 114, shown_arf, 16, 0xFFFF, digits);
|
||||
DrawBits(hDC, 76, 147, shown_acc, 16, 0xFFFF, digits);
|
||||
DrawBits(hDC, 76, 180, shown_ext, 16, 0xFFFF, digits);
|
||||
|
||||
|
@ -1124,10 +1126,10 @@ static void DrawConsole (HDC hDC, PAINTSTRUCT *ps)
|
|||
|
||||
void flash_run (void)
|
||||
{
|
||||
EnableWindow(btn[IDC_RUN].hBtn, TRUE); // enable the run lamp
|
||||
EnableWindow(btn[IDC_RUN].hBtn, TRUE); /* enable the run lamp */
|
||||
|
||||
if (hFlashTimer != 0)
|
||||
KillTimer(hConsoleWnd, FLASH_TIMER_ID); // (re)schedule lamp update
|
||||
KillTimer(hConsoleWnd, FLASH_TIMER_ID); /* (re)schedule lamp update */
|
||||
|
||||
hFlashTimer = SetTimer(hConsoleWnd, FLASH_TIMER_ID, LAMPTIME, NULL);
|
||||
}
|
||||
|
@ -1154,10 +1156,12 @@ void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl)
|
|||
reset_all(0);
|
||||
if (running && ! power) { /* turning off */
|
||||
reason = STOP_POWER_OFF;
|
||||
// this prevents message pump from running, which unfortunately locks up
|
||||
// the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp
|
||||
// while (running)
|
||||
// Sleep(10); /* wait for execution thread to exit */
|
||||
/* wait for execution thread to exit */
|
||||
/* this prevents message pump from running, which unfortunately locks up
|
||||
* the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp
|
||||
* while (running)
|
||||
* Sleep(10);
|
||||
*/
|
||||
}
|
||||
|
||||
btn[IDC_POWER_ON].state = power;
|
||||
|
@ -1175,7 +1179,7 @@ void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl)
|
|||
case MODE_INT_RUN:
|
||||
case MODE_RUN:
|
||||
case MODE_SI:
|
||||
stuff_cmd("go");
|
||||
stuff_cmd("cont");
|
||||
break;
|
||||
|
||||
case MODE_DISP: /* display core and advance IAR */
|
||||
|
@ -1196,16 +1200,17 @@ void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl)
|
|||
case IDC_PROGRAM_STOP:
|
||||
if (running) { /* potential race condition here */
|
||||
GUI_BEGIN_CRITICAL_SECTION
|
||||
SETBIT(cpu_dsw, CPU_DSW_PROGRAM_STOP);
|
||||
SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP);
|
||||
int_req |= INT_REQ_5;
|
||||
SETBIT(con_dsw, CPU_DSW_PROGRAM_STOP);
|
||||
SETBIT(ILSW[5], ILSW_5_INT_RUN_PROGRAM_STOP);
|
||||
int_req |= INT_REQ_5; /* note: calc_ints() is not needed in this case */
|
||||
int_lamps |= INT_REQ_5;
|
||||
GUI_END_CRITICAL_SECTION
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_LOAD_IAR:
|
||||
if (! running) {
|
||||
IAR = CES & 0x3FFF; /* set IAR from console entry switches */
|
||||
IAR = CES & mem_mask; /* set IAR from console entry switches */
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1214,12 +1219,13 @@ void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl)
|
|||
|
||||
case IDC_IMM_STOP:
|
||||
if (running) {
|
||||
reason = STOP_WAIT; /* terminate execution without setting wait_mode */
|
||||
|
||||
// this prevents message pump from running, which unfortunately locks up
|
||||
// the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp
|
||||
// while (running)
|
||||
// Sleep(10); /* wait for execution thread to exit */
|
||||
reason = STOP_IMMEDIATE; /* terminate execution without setting wait_mode */
|
||||
/* wait for execution thread to exit */
|
||||
/* this prevents message pump from running, which unfortunately locks up
|
||||
* the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp
|
||||
* while (running)
|
||||
* Sleep(10);
|
||||
*/
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1290,10 +1296,6 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
|||
SetRect(&rbmp, 0, 0, bmwid, bmht);
|
||||
if (IntersectRect(&xsect, &clip, &rbmp))
|
||||
BitBlt(hDC, xsect.left, xsect.top, xsect.right-xsect.left+1, xsect.bottom-xsect.top+1, hCDC, xsect.left, xsect.top, SRCCOPY);
|
||||
// rbmp.top = rbmp.bottom;
|
||||
// rbmp.bottom += 200;
|
||||
// if (IntersectRect(&xsect, &clip, &rbmp))
|
||||
// FillRect(hDC, &xsect, hbBlack);
|
||||
return TRUE; /* let Paint do this so we know what the update region is (ps.rcPaint) */
|
||||
|
||||
case WM_PAINT:
|
||||
|
@ -1318,11 +1320,15 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
|||
case WM_SETCURSOR:
|
||||
GetCursorPos(&p);
|
||||
ScreenToClient(hWnd, &p);
|
||||
SetCursor(HandleClick(hWnd, p.x, p.y, FALSE) ? hcHand : hcArrow);
|
||||
SetCursor(HandleClick(hWnd, p.x, p.y, FALSE, FALSE) ? hcHand : hcArrow);
|
||||
return TRUE;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
HandleClick(hWnd, LOWORD(lParam), HIWORD(lParam), TRUE);
|
||||
HandleClick(hWnd, LOWORD(lParam), HIWORD(lParam), TRUE, FALSE);
|
||||
break;
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
HandleClick(hWnd, LOWORD(lParam), HIWORD(lParam), TRUE, TRUE);
|
||||
break;
|
||||
|
||||
case WM_CTLCOLORBTN:
|
||||
|
@ -1339,7 +1345,7 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
|||
break;
|
||||
|
||||
case WM_DROPFILES:
|
||||
accept_dropped_file((HANDLE) wParam); // console window - dragged file is a script or card deck
|
||||
accept_dropped_file((HANDLE) wParam); /* console window - dragged file is a script or card deck */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1368,7 +1374,7 @@ void forms_check (int set)
|
|||
EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus);
|
||||
|
||||
if (btn[IDC_FORMS_CHECK].clr != oldcolor)
|
||||
InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case
|
||||
InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); /* change color in any case */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1389,7 +1395,7 @@ void print_check (int set)
|
|||
EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus);
|
||||
|
||||
if (btn[IDC_FORMS_CHECK].clr != oldcolor)
|
||||
InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case
|
||||
InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); /* change color in any case */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1425,34 +1431,34 @@ static void accept_dropped_file (HANDLE hDrop)
|
|||
POINT pt;
|
||||
HWND hWndDrop;
|
||||
|
||||
nfiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); // get file count,
|
||||
DragQueryFile(hDrop, 0, fname, sizeof(fname)); // get first filename
|
||||
DragQueryPoint(hDrop, &pt); // get location of drop
|
||||
nfiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); /* get file count, */
|
||||
DragQueryFile(hDrop, 0, fname, sizeof(fname)); /* get first filename */
|
||||
DragQueryPoint(hDrop, &pt); /* get location of drop */
|
||||
DragFinish(hDrop);
|
||||
|
||||
if (nfiles <= 0) // hmm, this seems unlikely to occur, but better check
|
||||
if (nfiles <= 0) /* hmm, this seems unlikely to occur, but better check */
|
||||
return;
|
||||
|
||||
if (running) { // can only accept a drop while processor is stopped
|
||||
if (running) { /* can only accept a drop while processor is stopped */
|
||||
MessageBeep(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hWndDrop = ChildWindowFromPoint(hConsoleWnd, pt)) == btn[IDC_1442].hBtn)
|
||||
cardreader = TRUE; // file was dropped onto 1442 card reader
|
||||
cardreader = TRUE; /* file was dropped onto 1442 card reader */
|
||||
else if (hWndDrop == NULL || hWndDrop == hConsoleWnd)
|
||||
cardreader = FALSE; // file was dropped onto console window, not a button
|
||||
cardreader = FALSE; /* file was dropped onto console window, not a button */
|
||||
else {
|
||||
MessageBeep(0); // file was dropped onto another button
|
||||
MessageBeep(0); /* file was dropped onto another button */
|
||||
return;
|
||||
}
|
||||
|
||||
if (nfiles > 1) { // oops, we wouldn't know what order to read them in
|
||||
if (nfiles > 1) { /* oops, we wouldn't know what order to read them in */
|
||||
MessageBox(hConsoleWnd, "You may only drop one file at a time", "", MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
// if shift key is down, prepend @ to name (make it a deck file)
|
||||
/* if shift key is down, prepend @ to name (make it a deck file) */
|
||||
deckfile = ((GetKeyState(VK_SHIFT) & 0x8000) && cardreader) ? "@" : "";
|
||||
|
||||
sprintf(cmd, "%s \"%s%s\"", cardreader ? "attach cr" : "do", deckfile, fname);
|
||||
|
@ -1466,22 +1472,18 @@ static void tear_printer (void)
|
|||
if ((prt_unit.flags & UNIT_ATT) == 0)
|
||||
return;
|
||||
|
||||
strcpy(filename, prt_unit.filename); // save current attached filename
|
||||
strcpy(filename, prt_unit.filename); /* save current attached filename */
|
||||
|
||||
if (! stuff_and_wait("detach prt", 1000, 0)) // detach it
|
||||
if (! stuff_and_wait("detach prt", 1000, 0)) /* detach it */
|
||||
return;
|
||||
|
||||
sprintf(cmd, "view \"%s\"", filename); // spawn notepad to view it
|
||||
sprintf(cmd, "view \"%s\"", filename); /* spawn notepad to view it */
|
||||
if (! stuff_and_wait(cmd, 3000, 500))
|
||||
return;
|
||||
|
||||
// no, now we have them click the card reader icon twice to unload the deck. more flexible that way
|
||||
// if (! stuff_and_wait("detach cr", 1000, 0)) // detach the card reader so they can edit the deck file
|
||||
// return;
|
||||
remove(filename); /* delete the file */
|
||||
|
||||
remove(filename); // delete the file
|
||||
|
||||
sprintf(cmd, "attach prt \"%s\"", filename); // reattach
|
||||
sprintf(cmd, "attach prt \"%s\"", filename); /* reattach */
|
||||
stuff_cmd(cmd);
|
||||
}
|
||||
|
||||
|
@ -1582,24 +1584,25 @@ void stuff_cmd (char *cmd)
|
|||
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
|
||||
}
|
||||
|
||||
// my_yield - process GUI messages. It's not apparent why stuff_and_wait would block,
|
||||
// since it sleeps in the GUI thread while scp runs in the main thread. However,
|
||||
// at the end of every command scp calls update_gui, which can result in messages
|
||||
// being sent to the GUI thread. So, the GUI thread has to process messages while
|
||||
// stuff_and_wait is waiting.
|
||||
|
||||
/* my_yield - process GUI messages. It's not apparent why stuff_and_wait would block,
|
||||
* since it sleeps in the GUI thread while scp runs in the main thread. However,
|
||||
* at the end of every command scp calls update_gui, which can result in messages
|
||||
* being sent to the GUI thread. So, the GUI thread has to process messages while
|
||||
* stuff_and_wait is waiting.
|
||||
*/
|
||||
static void my_yield (void)
|
||||
{
|
||||
MSG msg;
|
||||
// multitask
|
||||
/* multitask */
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
// stuff_and_wait -- stuff a command and wait for the emulator to process the command
|
||||
// and come back to prompt for another
|
||||
/* stuff_and_wait -- stuff a command and wait for the emulator to process the command
|
||||
* and come back to prompt for another
|
||||
*/
|
||||
|
||||
t_bool stuff_and_wait (char *cmd, int timeout, int delay)
|
||||
{
|
||||
|
@ -1650,5 +1653,5 @@ void remark_cmd (char *remark)
|
|||
}
|
||||
}
|
||||
|
||||
#endif // _WIN32 defined
|
||||
#endif // GUI_SUPPORT defined
|
||||
#endif /* _WIN32 defined */
|
||||
#endif /* GUI_SUPPORT defined */
|
||||
|
|
634
Ibm1130/ibm1130_plot.c
Normal file
634
Ibm1130/ibm1130_plot.c
Normal file
|
@ -0,0 +1,634 @@
|
|||
/* ibm1130_plot.c: IBM 1130 1627 plotter emulation
|
||||
|
||||
Based on the SIMH simulator package written by Robert M Supnik
|
||||
|
||||
Brian Knittel
|
||||
Revision History
|
||||
|
||||
2004.10.22 - Written.
|
||||
2006.1.2 - Rewritten as plotter routine by Carl V Claunch
|
||||
|
||||
* (C) Copyright 2004, Brian Knittel.
|
||||
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
||||
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
||||
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
||||
* or modifications.
|
||||
*
|
||||
* This is not a supported product, but I welcome bug reports and fixes.
|
||||
* Mail to simh@ibm1130.org
|
||||
*/
|
||||
|
||||
#include "ibm1130_defs.h"
|
||||
|
||||
#ifndef ENABLE_PLOT_SUPPORT
|
||||
|
||||
DEVICE plot_dev = {
|
||||
"PLOT", NULL, NULL, NULL,
|
||||
0, 16, 16, 1, 16, 16,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL};
|
||||
|
||||
void xio_1627_plotter (int32 addr, int32 func, int32 modify)
|
||||
{
|
||||
/* silently eat any plotter commands */
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "gd.h"
|
||||
|
||||
/***************************************************************************************
|
||||
* 1627 model 1 plotter (based on Calcomp 535 which was sold as IBM 1627)
|
||||
*
|
||||
* - 11" wide carriage, addressible in .01" steps
|
||||
* - continous sheet paper up to 120' in length
|
||||
* - sheet moveable in .01" steps, either direction
|
||||
* - switchable pen, in various colors and line widths
|
||||
*
|
||||
* Simulator implementation will create a JPEG image corresponding to a
|
||||
* landscape mode sheet of paper, the width of the carriage at 11".
|
||||
* A diagram of more than 8" of paper travel will span printed pages
|
||||
* in landscape mode.
|
||||
*
|
||||
* When an 'att plot' command is issued a file is created based on the
|
||||
* default or currently set values of paper length, starting
|
||||
* position of the pen in both X and Y axes, pen color and pen width.
|
||||
* Based on the number of logical pages of paper, the command will create
|
||||
* the proper size canvas internally and create the output JPEG file.
|
||||
*
|
||||
* When a 'det plot' command is issued, the plotter image will be converted
|
||||
* into the file that was specified during the attach process. The
|
||||
* image is not viewable until this point, unless an examine plot is
|
||||
* issued which will dump the current state of the paper into the file.
|
||||
*
|
||||
* The 'set plot' command can set pen width, paper length, pen color,
|
||||
* current carriage X and Y coordinates. Paper length can be set
|
||||
* to alter the default of 800 (8"); changes are ignored until
|
||||
* the next 'attach' command. The current carriage x and y positions
|
||||
* can be set at any time and will go into effect immediately, just
|
||||
* as the pen color and pen width can be altered on the fly.
|
||||
*
|
||||
* NOTE: requires gd library and definition of ENABLE_PLOT_SUPPORT in makefile or Visual C configuration
|
||||
* gd is not included in the main simh and ibm1130.org distributions at the present time.
|
||||
***************************************************************************************/
|
||||
|
||||
#define PLOT1627_DSW_OP_COMPLETE 0x8000
|
||||
#define PLOT1627_DSW_BUSY 0x0200
|
||||
#define PLOT1627_DSW_NOT_READY 0x0100
|
||||
|
||||
#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)
|
||||
#define IS_DEBUG ((plot_unit->flags & UNIT_DEBUG) == UNIT_DEBUG)
|
||||
#define IS_PENDOWN ((plot_unit->flags & UNIT_PEN) == UNIT_PEN)
|
||||
|
||||
static t_stat plot_svc (UNIT *uptr); /* activity routine */
|
||||
static t_stat plot_reset (DEVICE *dptr); /* reset of 1130 */
|
||||
static t_stat plot_attach (UNIT *uptr, char *cptr); /* attach, loads plotter */
|
||||
static t_stat plot_detach (UNIT *uptr); /* detach and save image */
|
||||
static t_stat plot_examine (UNIT *uptr); /* update file with current canvas */
|
||||
static t_stat plot_set_length (UNIT *uptr, int32 val, char * ptr, void *desc); /* set paper length */
|
||||
static t_stat plot_set_pos (UNIT *uptr, int32 val, char * ptr, void *desc); /* reset current X/Y position */
|
||||
static t_stat plot_show_vals(FILE *fp, UNIT *uptr, int32 val, void *descrip); /* print x, y and length */
|
||||
static t_stat plot_show_nl(FILE *fp, UNIT *uptr, int32 val, void *descrip); /* overcome wacky simh behavior */
|
||||
static void update_pen(void); /* will ensure pen action is correct when changes made */
|
||||
static t_stat plot_validate_change (UNIT *uptr, int32 val, char * ptr, void *desc); /* when set command issued */
|
||||
static void process_cmd(void); /* does actual drawing for plotter */
|
||||
|
||||
extern int32 sim_switches; /* switches set on simh command */
|
||||
static int16 plot_dsw = 0; /* device status word */
|
||||
static int16 plot_cmd = 0; /* the command to process */
|
||||
static int32 plot_wait = 1000; /* plotter movement wait */
|
||||
static int32 plot_xpos = 0; /* current X position */
|
||||
static int32 plot_xmax = 799; /* end of paper */
|
||||
static int32 plot_ypos = 0; /* current Y position */
|
||||
static int32 plot_ymax = 1099; /* right edge of carriage */
|
||||
|
||||
#define PEN_DOWN 0x80000000
|
||||
#define PEN_UP 0x00000000
|
||||
static int32 plot_pen = PEN_UP; /* current pen position */
|
||||
|
||||
static int black_pen; /* holds color black */
|
||||
static int blue_pen; /* holds color blue */
|
||||
static int red_pen; /* holds color red */
|
||||
static int green_pen; /* holds color green */
|
||||
static int yellow_pen; /* holds yellow color */
|
||||
static int purple_pen; /* holds color purple */
|
||||
static int ltgrey_pen; /* holds light grey */
|
||||
static int grey_pen; /* holds grey */
|
||||
static int white_background; /* holds white of paper roll */
|
||||
static int plot_pwidth; /* set and display variable */
|
||||
static int plot_pcolor; /* set and display variable */
|
||||
static int need_update = 0; /* flag to force and update_pen() */
|
||||
static gdImagePtr image; /* pointer to our canvas */
|
||||
|
||||
#define UNIT_V_COLOR (UNIT_V_UF + 0) /* color of selected pen - 3 bits */
|
||||
#define UNIT_V_WIDTH (UNIT_V_UF + 3) /* width of pen - two bits */
|
||||
#define UNIT_V_NOOP (UNIT_V_UF + 5) /* dummy for set/show commands */
|
||||
#define UNIT_V_DEBUG (UNIT_V_UF + 6) /* for -d switch on attach command */
|
||||
#define UNIT_V_PEN (UNIT_V_UF + 7) /* track pen state */
|
||||
|
||||
#define UNIT_WIDTH (3u << UNIT_V_WIDTH) /* two bits */
|
||||
#define UNIT_COLOR (7u << UNIT_V_COLOR) /* three bits */
|
||||
#define UNIT_NOOP (1u << UNIT_V_NOOP) /* dummy for set/show */
|
||||
#define UNIT_DEBUG (1u << UNIT_V_DEBUG) /* shows debug mode on */
|
||||
#define UNIT_PEN (1u << UNIT_V_PEN) /* the pen state bit */
|
||||
|
||||
#define PEN_BLACK (0u << UNIT_V_COLOR)
|
||||
#define PEN_RED (1u << UNIT_V_COLOR)
|
||||
#define PEN_BLUE (2u << UNIT_V_COLOR)
|
||||
#define PEN_GREEN (3u << UNIT_V_COLOR)
|
||||
#define PEN_YELLOW (4u << UNIT_V_COLOR)
|
||||
#define PEN_PURPLE (5u << UNIT_V_COLOR)
|
||||
#define PEN_LTGREY (6u << UNIT_V_COLOR)
|
||||
#define PEN_GREY (7u << UNIT_V_COLOR)
|
||||
|
||||
#define SET_COLOR(op) {plot_unit[0].flags &= ~UNIT_COLOR; plot_unit[0].flags |= (op);}
|
||||
#define GET_COLOR (plot_unit[0].flags & UNIT_COLOR)
|
||||
|
||||
#define BLACK 0,0,0
|
||||
#define BLUE 0,0,255
|
||||
#define RED 255,0,0
|
||||
#define GREEN 0,255,0
|
||||
#define YELLOW 200,200,0
|
||||
#define PURPLE 150,0,150
|
||||
#define LTGREY 200,200,200
|
||||
#define GREY 120,120,120
|
||||
#define WHITE 255,255,255
|
||||
|
||||
#define PEN_SINGLE (0u << UNIT_V_WIDTH)
|
||||
#define PEN_DOUBLE (1u << UNIT_V_WIDTH)
|
||||
#define PEN_TRIPLE (2u << UNIT_V_WIDTH)
|
||||
#define PEN_QUAD (3u << UNIT_V_WIDTH)
|
||||
|
||||
#define GET_WIDTH() (plot_unit[0].flags & UNIT_WIDTH)
|
||||
#define SET_WIDTH(cd) {plot_unit[0].flags &= ~UNIT_WIDTH; un.flags |= (cd);}
|
||||
|
||||
UNIT plot_unit[] = {
|
||||
{ UDATA (&plot_svc, UNIT_ATTABLE, 0) },
|
||||
};
|
||||
|
||||
REG plot_reg[] = {
|
||||
{ HRDATA (DSW, plot_dsw, 16) }, /* device status word */
|
||||
{ DRDATA (WTIME, plot_wait, 24), PV_LEFT }, /* plotter movement wait */
|
||||
{ DRDATA (Xpos, plot_xpos, 32), PV_LEFT }, /* Current X Position*/
|
||||
{ DRDATA (Ypos, plot_ypos, 32), PV_LEFT }, /* Current Y Position*/
|
||||
{ FLDATA (PenDown, plot_pen, 0)}, /* Current pen position - 1 = down */
|
||||
{ DRDATA (PaperSize, plot_xmax, 32), PV_LEFT }, /* Length of paper in inches */
|
||||
{ NULL } };
|
||||
|
||||
MTAB plot_mod[] = {
|
||||
{ UNIT_COLOR, PEN_BLACK, "black", "BLACK", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_RED, "red", "RED", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_BLUE, "blue", "BLUE", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_GREEN, "green", "GREEN", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_YELLOW, "yellow", "YELLOW", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_PURPLE, "purple", "PURPLE", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_LTGREY, "ltgrey", "LTGREY", &plot_validate_change},
|
||||
{ UNIT_COLOR, PEN_GREY, "grey", "GREY", &plot_validate_change},
|
||||
{ UNIT_WIDTH, PEN_SINGLE, "1.0", "1.0", &plot_validate_change},
|
||||
{ UNIT_WIDTH, PEN_DOUBLE, "2.0", "2.0", &plot_validate_change},
|
||||
{ UNIT_WIDTH, PEN_TRIPLE, "3.0", "3.0", &plot_validate_change},
|
||||
{ UNIT_WIDTH, PEN_QUAD, "4.0", "4.0", &plot_validate_change},
|
||||
{ UNIT_PEN, UNIT_PEN, "pendown", "PENDOWN", &plot_validate_change},
|
||||
{ UNIT_PEN, 0, "penup", "PENUP", &plot_validate_change},
|
||||
/* below is dummy entry to trigger the show routine and print extended values */
|
||||
{ UNIT_NOOP, 0, "", NULL, NULL, &plot_show_vals},
|
||||
/* extended entries must allow parm for both unit and dev, but
|
||||
* then they will print the value twice for a 'show plot' command
|
||||
* therefore they are set to not display unless explicity requested
|
||||
* and the special dummy NOOP entry will cause the print of these values */
|
||||
{ MTAB_XTD | MTAB_VAL | MTAB_VUN | MTAB_VDV | MTAB_NMO, 2,
|
||||
"length", "LENGTH", &plot_set_length, &plot_show_nl, &plot_reg[5]},
|
||||
{ MTAB_XTD | MTAB_VAL | MTAB_VDV | MTAB_VUN | MTAB_NMO, 0,
|
||||
"Xpos", "XPOS", &plot_set_pos, &plot_show_nl, &plot_reg[2]},
|
||||
{ MTAB_XTD | MTAB_VAL | MTAB_VDV | MTAB_VUN | MTAB_NMO, 1,
|
||||
"Ypos", "YPOS", &plot_set_pos, &plot_show_nl, &plot_reg[3]},
|
||||
{ 0 } };
|
||||
|
||||
DEVICE plot_dev = {
|
||||
"PLOT", plot_unit, plot_reg, plot_mod,
|
||||
1, 16, 16, 1, 16, 16,
|
||||
NULL, NULL, plot_reset,
|
||||
NULL, plot_attach, plot_detach};
|
||||
|
||||
/* xio_1627_plotter - XIO command interpreter for the 1627 plotter model 1 */
|
||||
|
||||
void xio_1627_plotter (iocc_addr, iocc_func, iocc_mod)
|
||||
{
|
||||
char msg[80];
|
||||
|
||||
if (! IS_ONLINE(plot_unit) ) {
|
||||
SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* set not ready */
|
||||
if (IS_DEBUG) printf("Plotter has no paper, ignored\n");
|
||||
return; /* and ignore */
|
||||
}
|
||||
|
||||
switch (iocc_func) {
|
||||
case XIO_READ: /* read XIO */
|
||||
xio_error("Read XIO not supported by 1627 plotter");
|
||||
break;
|
||||
|
||||
case XIO_WRITE: /* write: do one plotter operation */
|
||||
if ((plot_dsw & PLOT1627_DSW_NOT_READY)) {
|
||||
if (IS_DEBUG) printf("Wrote to non-ready Plotter\n");
|
||||
break;
|
||||
}
|
||||
plot_cmd = (uint16) ( M[iocc_addr & mem_mask] >> 10 ); /* pick up command */
|
||||
process_cmd(); /* interpret command */
|
||||
sim_activate(plot_unit, plot_wait); /* schedule interrupt */
|
||||
SETBIT(plot_dsw, PLOT1627_DSW_BUSY); /* mark it busy */
|
||||
break;
|
||||
|
||||
case XIO_SENSE_DEV: /* sense device status */
|
||||
ACC = plot_dsw; /* get current status */
|
||||
if (iocc_mod & 0x01) { /* reset interrupts */
|
||||
CLRBIT(plot_dsw, PLOT1627_DSW_OP_COMPLETE);
|
||||
CLRBIT(ILSW[3], ILSW_3_1627_PLOTTER);
|
||||
}
|
||||
break;
|
||||
|
||||
case XIO_CONTROL: /* control XIO */
|
||||
xio_error("Control XIO not supported by 1627 plotter");
|
||||
break;
|
||||
|
||||
default:
|
||||
sprintf(msg, "Invalid 1627 Plotter XIO function %x", iocc_func);
|
||||
xio_error(msg);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// plot_svc - 1627 plotter operation complete
|
||||
|
||||
static t_stat plot_svc (UNIT *uptr)
|
||||
{
|
||||
CLRBIT(plot_dsw, PLOT1627_DSW_BUSY); /* clear reader busy flag */
|
||||
|
||||
SETBIT(plot_dsw, PLOT1627_DSW_OP_COMPLETE); /* indicate read complete */
|
||||
|
||||
SETBIT(ILSW[3], ILSW_3_1627_PLOTTER); /* initiate interrupt */
|
||||
calc_ints();
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* plot_reset - reset emulated plotter */
|
||||
|
||||
static t_stat plot_reset (DEVICE *dptr)
|
||||
{
|
||||
char * buf;
|
||||
int32 size;
|
||||
|
||||
sim_cancel(plot_unit);
|
||||
|
||||
CLRBIT(plot_dsw, PLOT1627_DSW_BUSY | PLOT1627_DSW_OP_COMPLETE);
|
||||
|
||||
if (IS_DEBUG) printf("reset routine for Plotter\n");
|
||||
|
||||
CLRBIT(ILSW[3], ILSW_3_1627_PLOTTER);
|
||||
calc_ints();
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* plot_attach - attach file to simulated plotter */
|
||||
|
||||
static t_stat plot_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat result;
|
||||
|
||||
CLRBIT(uptr->flags, UNIT_DEBUG);
|
||||
if (sim_switches & SWMASK('D')) SETBIT(uptr->flags, UNIT_DEBUG);
|
||||
|
||||
/* get the output file by using regular attach routine */
|
||||
result = attach_unit(uptr, cptr);
|
||||
|
||||
if (result != SCPE_OK) {
|
||||
if (IS_DEBUG) printf("problem attaching file\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* assume failure */
|
||||
|
||||
/* set up our canvas at the desired size */
|
||||
image = gdImageCreate(plot_ymax+1,plot_xmax+1); /* create our canvas */
|
||||
if (image == NULL) {
|
||||
if (IS_DEBUG) printf("problem creating image canvas\n");
|
||||
return SCPE_MEM;
|
||||
}
|
||||
|
||||
/* set up the basic colors after image created */
|
||||
white_background = gdImageColorAllocate(image,WHITE); /* white is background */
|
||||
black_pen = gdImageColorAllocate(image,BLACK); /* load up black color */
|
||||
blue_pen = gdImageColorAllocate(image,BLUE); /* load up blue color */
|
||||
red_pen = gdImageColorAllocate(image,RED); /* load up red color */
|
||||
green_pen = gdImageColorAllocate(image,GREEN); /* load up green color */
|
||||
yellow_pen = gdImageColorAllocate(image,YELLOW); /* load up yellow color */
|
||||
purple_pen = gdImageColorAllocate(image,PURPLE); /* load up purple color */
|
||||
ltgrey_pen = gdImageColorAllocate(image,LTGREY); /* load up light grey color */
|
||||
grey_pen = gdImageColorAllocate(image,GREY); /* load up grey color */
|
||||
|
||||
if ( (white_background == -1) || (black_pen == -1) ||
|
||||
(red_pen == -1) || (blue_pen == -1) || (green_pen == -1) ||
|
||||
(purple_pen == -1) || (ltgrey_pen == -1) || (grey_pen == -1) ) {
|
||||
if (IS_DEBUG) printf("problem allocating pen colors\n");
|
||||
return SCPE_MEM;
|
||||
}
|
||||
|
||||
CLRBIT(plot_dsw, PLOT1627_DSW_NOT_READY); /* we're in business */
|
||||
|
||||
update_pen(); /* routine to ensure pen is okay */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* pen updating routine, called at attach and whenever we reset the values */
|
||||
|
||||
void update_pen (void)
|
||||
{
|
||||
int color;
|
||||
int width;
|
||||
|
||||
if (!IS_ONLINE(plot_unit)) return; /* only do this if attached */
|
||||
|
||||
/* pick up latest color as active pen */
|
||||
color = GET_COLOR;
|
||||
switch (color) {
|
||||
case PEN_BLACK:
|
||||
plot_pcolor = black_pen;
|
||||
break;
|
||||
|
||||
case PEN_RED:
|
||||
plot_pcolor = red_pen;
|
||||
break;
|
||||
|
||||
case PEN_BLUE:
|
||||
plot_pcolor = blue_pen;
|
||||
break;
|
||||
|
||||
case PEN_GREEN:
|
||||
plot_pcolor = green_pen;
|
||||
break;
|
||||
|
||||
case PEN_YELLOW:
|
||||
plot_pcolor = yellow_pen;
|
||||
break;
|
||||
|
||||
case PEN_PURPLE:
|
||||
plot_pcolor = purple_pen;
|
||||
break;
|
||||
|
||||
case PEN_LTGREY:
|
||||
plot_pcolor = ltgrey_pen;
|
||||
break;
|
||||
|
||||
case PEN_GREY:
|
||||
plot_pcolor = grey_pen;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (IS_DEBUG) printf("invalid pen color state\n");
|
||||
plot_pcolor = black_pen;
|
||||
break;
|
||||
}
|
||||
|
||||
/* set up anti-aliasing for the line */
|
||||
gdImageSetAntiAliased(image, plot_pcolor);
|
||||
|
||||
/* pick up latest width for pen */
|
||||
width = GET_WIDTH();
|
||||
switch (width) {
|
||||
case PEN_SINGLE:
|
||||
plot_pwidth = 1;
|
||||
gdImageSetThickness(image, 1);
|
||||
break;
|
||||
|
||||
case PEN_TRIPLE:
|
||||
plot_pwidth = 3;
|
||||
gdImageSetThickness(image, 3);
|
||||
break;
|
||||
|
||||
case PEN_DOUBLE:
|
||||
plot_pwidth = 2;
|
||||
gdImageSetThickness(image, 2);
|
||||
break;
|
||||
|
||||
case PEN_QUAD:
|
||||
plot_pwidth = 4;
|
||||
gdImageSetThickness(image, 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (IS_DEBUG) printf("invalid pen width\n");
|
||||
plot_pwidth = 1;
|
||||
gdImageSetThickness(image, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* now ensure the pen state is accurate */
|
||||
plot_pen = IS_PENDOWN ? PEN_DOWN : PEN_UP;
|
||||
return;
|
||||
}
|
||||
|
||||
/* plot_detach - detach file from simulated plotter */
|
||||
static t_stat plot_detach (UNIT *uptr)
|
||||
{
|
||||
char * buf;
|
||||
int32 size;
|
||||
FILE * fp;
|
||||
int32 result;
|
||||
|
||||
SETBIT(plot_dsw, PLOT1627_DSW_NOT_READY);
|
||||
|
||||
/* copy images to files, close files, set device to detached, free gd memory */
|
||||
|
||||
buf = gdImageGifPtr(image,&size);
|
||||
if (! buf) {
|
||||
if (IS_DEBUG) printf("failure creating GIF in-memory\n");
|
||||
return SCPE_MEM;
|
||||
}
|
||||
|
||||
fp = uptr->fileref; /* get file attached to unit */
|
||||
|
||||
if (! fseek(fp,0,SEEK_SET)) { /* first we reset to begin of file */
|
||||
if (IS_DEBUG) printf("wrote out GIF to file\n");
|
||||
result = fwrite(buf,1,size,fp); /* write out our image to the file */
|
||||
}
|
||||
|
||||
gdFree(buf); /* free up the memory of GIF format */
|
||||
gdImageDestroy(image); /* free up the canvas memory */
|
||||
|
||||
if (result != size) { /* some problem writing it */
|
||||
if (IS_DEBUG) printf("error in write of image file\n");
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
|
||||
return detach_unit(uptr); /* have simh close the file */
|
||||
}
|
||||
|
||||
/* process_cmd - implement the drawing actions of the plotter */
|
||||
|
||||
static void process_cmd (void)
|
||||
{
|
||||
int32 oldx, oldy;
|
||||
|
||||
/* first see if we set any changes to pen or position, do an update */
|
||||
if (need_update) {
|
||||
update_pen();
|
||||
need_update = 0;
|
||||
}
|
||||
|
||||
/* will move pen one step or flip pen up or down */
|
||||
oldx = plot_xpos;
|
||||
oldy = plot_ypos;
|
||||
|
||||
switch (plot_cmd) {
|
||||
case 1: /* raise pen command */
|
||||
plot_pen = PEN_UP;
|
||||
plot_unit->flags = plot_unit->flags & (~UNIT_PEN);
|
||||
return;
|
||||
break;
|
||||
|
||||
case 2: /* +Y command */
|
||||
plot_ypos = plot_ypos + 1;
|
||||
break;
|
||||
|
||||
case 4: /* -Y command */
|
||||
plot_ypos = plot_ypos - 1;
|
||||
break;
|
||||
|
||||
case 8: /* -X command */
|
||||
plot_xpos = plot_xpos - 1;
|
||||
break;
|
||||
|
||||
case 10: /* -X +Y command */
|
||||
plot_xpos = plot_xpos - 1;
|
||||
plot_ypos = plot_ypos + 1;
|
||||
break;
|
||||
|
||||
case 12: /* -X -Y command */
|
||||
plot_xpos = plot_xpos - 1;
|
||||
plot_ypos = plot_ypos - 1;
|
||||
break;
|
||||
|
||||
case 16: /* +X command */
|
||||
plot_xpos = plot_xpos + 1;
|
||||
break;
|
||||
|
||||
case 18: /* +X +Y command */
|
||||
plot_xpos = plot_xpos + 1;
|
||||
plot_ypos = plot_ypos + 1;
|
||||
break;
|
||||
|
||||
case 20: /* +X -Y pen command */
|
||||
plot_xpos = plot_xpos + 1;
|
||||
plot_ypos = plot_ypos - 1;
|
||||
break;
|
||||
|
||||
case 32: /* lower pen command */
|
||||
plot_pen = PEN_DOWN;
|
||||
plot_unit->flags = plot_unit->flags | UNIT_PEN;
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (IS_DEBUG) printf("invalid plotter command\n");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
/* check to see if carriage has moved off any edge */
|
||||
if ((plot_xpos > (plot_xmax+1)) || (plot_ypos > (plot_ymax+1)) ||
|
||||
(plot_xpos < 0) || (plot_ypos < 0)) {
|
||||
/* if so, ignore as 1627 has no way of signalling error */
|
||||
if (IS_DEBUG) printf(
|
||||
"attempted to move carriage off paper edge %d %d for command %d\n",
|
||||
plot_xpos,plot_ypos,plot_cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* only draw a line if the pen was down during the movement command */
|
||||
if (plot_pen) {
|
||||
gdImageLine(image, plot_ymax-plot_ypos, plot_xmax-plot_xpos, plot_ymax-oldy, plot_xmax-oldx, gdAntiAliased);
|
||||
/* semantics are 0,0 point is lower right */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* plot_set_length - validate and store the length of the paper */
|
||||
|
||||
static t_stat plot_set_length (UNIT *uptr, int32 set, char *ptr, void *desc)
|
||||
{
|
||||
char *cptr;
|
||||
int32 val;
|
||||
|
||||
#define LONGEST_ROLL 1440000 /* longest is 120', 14400", 1,440,000 .01"s */
|
||||
|
||||
val = strtotv (ptr, &cptr, (uint32) 10); /* sim routine to get value */
|
||||
if ((val < 1) | (val >= LONGEST_ROLL)) { /* check valid range */
|
||||
if (IS_DEBUG) printf("setting paper more than 120' or less than 1 inch\n");
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
/* origin zero drawing, reduce by 1 but show command will fudge by adding it back */
|
||||
*((int32 *)((REG *) desc)->loc) = val - 1;
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* plot_set_pos - validate and store the new position of the carriage */
|
||||
|
||||
static t_stat plot_set_pos (UNIT *uptr, int32 set, char *ptr, void *desc)
|
||||
{
|
||||
char *cptr;
|
||||
int32 val;
|
||||
int32 max;
|
||||
|
||||
max = (set == 1) ? plot_ymax : plot_xmax;
|
||||
val = strtotv (ptr, &cptr, (uint32) 10);
|
||||
if ((val < 0) | (val > max)) {
|
||||
if (IS_DEBUG) printf("error moving carriage off paper edge\n");
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
*((int32 *)((REG *) desc)->loc) = val;
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* routine to display the paper length and carriage position
|
||||
* cannot use regular simh routine because it prints values twice,
|
||||
* once for device and once for unit
|
||||
*/
|
||||
|
||||
static t_stat plot_show_vals (FILE *fp, UNIT *uptr, int32 val, void *descrip)
|
||||
{
|
||||
fprintf(fp, "length=%d, Xpos=%d, Ypos=%d",plot_xmax+1, plot_xpos,plot_ypos);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* routine to add a terminating NL character when 'show plot length'
|
||||
* or equivalent for xpos or ypos is issued, as simh will not append for us */
|
||||
|
||||
static t_stat plot_show_nl(FILE *fp, UNIT *uptr, int32 val, void *descrip)
|
||||
{
|
||||
int32 disp;
|
||||
char *label;
|
||||
|
||||
disp = (val == 2) ? plot_xmax + 1 : ((val == 1) ? plot_ypos : plot_xpos);
|
||||
label = (val == 2) ? "length=" : ((val == 1) ? "Ypos=" : "Xpos=");
|
||||
|
||||
fprintf(fp, "%s%d\n", label, disp);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* plot_validate_change - force the update_pen routine to be called after user changes pen setting */
|
||||
|
||||
static t_stat plot_validate_change (UNIT *uptr, int32 set, char *ptr, void *desc)
|
||||
{
|
||||
need_update = 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#endif /* ENABLE_PLOT_SUPPORT */
|
|
@ -5,6 +5,17 @@
|
|||
Brian Knittel
|
||||
Revision History
|
||||
|
||||
2006.12.06 - Moved CGI stuff out of this routine into cgi1130 main() module.
|
||||
|
||||
2006.07.06 - Made 1403 printer 132 columns wide, was 120 previously
|
||||
|
||||
2006.01.03 - Fixed bug in prt_attach, found and fixed by Carl Claunch. Detach followed
|
||||
by reattach of 1403-mode printer left device permanently not-ready.
|
||||
|
||||
2004.11.08 - HACK for demo mode: in physical (-p) mode, multiple consecutive formfeeds are suppressed.
|
||||
This lets us do a formfeed at the end of a job to kick the last page out
|
||||
without getting another blank page at the beginning of the next job.
|
||||
|
||||
2003.12.02 - Added -p option for physical line printer output (flushes
|
||||
output buffer after each line). When using a physical printer on
|
||||
Windows, be sure to set printer to "send output directly to printer"
|
||||
|
@ -36,6 +47,7 @@
|
|||
*/
|
||||
|
||||
#include "ibm1130_defs.h"
|
||||
#include <stdlib.h> /* needed for atexit, for cgi mode */
|
||||
|
||||
/***************************************************************************************
|
||||
* 1132 PRINTER
|
||||
|
@ -87,6 +99,8 @@ static int32 prt_fwait = 100; /* fast wait, for 1403 operations */
|
|||
static int32 prt_twait = 50; /* transfer wait, for 1403 operations */
|
||||
#define SKIPTARGET (uptr->u4) /* target for skip operation */
|
||||
|
||||
static t_bool formfed = FALSE; /* last line printed was a formfeed */
|
||||
|
||||
#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 */
|
||||
|
@ -145,12 +159,13 @@ DEVICE prt_dev = {
|
|||
NULL, NULL, &prt_reset,
|
||||
NULL, prt_attach, prt_detach};
|
||||
|
||||
#define PRT_COLUMNS 120
|
||||
#define PRT_ROWLEN 120
|
||||
#define MAX_COLUMNS 120
|
||||
#define MAX_OVPRINT 20
|
||||
#define PRT1132_COLUMNS 120
|
||||
#define PRT1403_COLUMNS 120 /* the 1130's version of the 1403 printed in 120 columns only (see Functional Characteristics) */
|
||||
|
||||
static char prtbuf[PRT_ROWLEN*MAX_OVPRINT];
|
||||
static int nprint[PRT_COLUMNS], ncol[MAX_OVPRINT], maxnp;
|
||||
static char prtbuf[MAX_COLUMNS*MAX_OVPRINT];
|
||||
static int nprint[MAX_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 */
|
||||
|
||||
|
@ -178,18 +193,18 @@ static struct tag_ccpunches { /* list of rows and punches on tape */
|
|||
int row, channels;
|
||||
}
|
||||
ccpunches[] = {
|
||||
2, CC_CHANNEL_1, // channel 1 = top of form
|
||||
62, CC_CHANNEL_12 // channel 12 = bottom of form
|
||||
2, CC_CHANNEL_1, /* channel 1 = top of form */
|
||||
62, CC_CHANNEL_12 /* channel 12 = bottom of form */
|
||||
},
|
||||
cccgi[] = {
|
||||
2, CC_CHANNEL_1 // channel 1 = top of form; no bottom of form
|
||||
2, CC_CHANNEL_1 /* channel 1 = top of form; no bottom of form */
|
||||
};
|
||||
|
||||
#include "ibm1130_prtwheel.h"
|
||||
|
||||
extern int32 sim_switches;
|
||||
|
||||
// cc_format_1132 and cc_format_1403 - turn cctape bits into proper format for DSW or status read
|
||||
/* cc_format_1132 and cc_format_1403 - turn cctape bits into proper format for DSW or status read */
|
||||
|
||||
static int cc_format_1132 (int bits)
|
||||
{
|
||||
|
@ -200,7 +215,7 @@ static int cc_format_1132 (int bits)
|
|||
|
||||
#define cc_format_1403(bits) (bits)
|
||||
|
||||
// reset_prt_line - clear the print line following paper advancement
|
||||
/* reset_prt_line - clear the print line following paper advancement */
|
||||
|
||||
static void reset_prt_line (void)
|
||||
{
|
||||
|
@ -209,116 +224,116 @@ static void reset_prt_line (void)
|
|||
maxnp = 0;
|
||||
}
|
||||
|
||||
// save_1132_prt_line - fire hammers for character 'ch'
|
||||
/* save_1132_prt_line - fire hammers for character 'ch' */
|
||||
|
||||
static t_bool save_1132_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
|
||||
for (i = 0; i < PRT1132_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 (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
|
||||
if (ncol[r] <= i) { /* we haven't moved this far yet */
|
||||
if (ncol[r] == 0) /* first char in this row? */
|
||||
memset(prtbuf+r*MAX_COLUMNS, ' ', PRT1132_COLUMNS); /* blank out the new row */
|
||||
ncol[r] = i+1; /* remember new row length */
|
||||
}
|
||||
prtbuf[r*PRT_ROWLEN + i] = (char) ch; // save the character
|
||||
prtbuf[r*MAX_COLUMNS + i] = (char) ch; /* save the character */
|
||||
|
||||
nprint[i]++; // remember max overprintings for this column
|
||||
nprint[i]++; /* remember max overprintings for this column */
|
||||
maxnp = MAX(maxnp, nprint[i]);
|
||||
}
|
||||
}
|
||||
|
||||
mask >>= 1; // prepare to examine next bit
|
||||
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
|
||||
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.
|
||||
/* 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 newpage (FILE *fd)
|
||||
static void newpage (FILE *fd, t_bool physical_printer)
|
||||
{
|
||||
if (cgi)
|
||||
fputs("<HR>\n", fd);
|
||||
else
|
||||
putc('\f', fd); // formfeed
|
||||
else if (! formfed) {
|
||||
putc('\f', fd);
|
||||
if (physical_printer) {
|
||||
fflush(fd); /* send the ff out to the printer immediately */
|
||||
formfed = TRUE; /* hack: inhibit consecutive ff's */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void flush_prt_line (FILE *fd, int spacemode, t_bool phys_flush)
|
||||
static void flush_prt_line (FILE *fd, int spacemode, t_bool physical_printer)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (! (spacemode || maxnp)) // nothing to do
|
||||
if (! (spacemode || maxnp)) /* nothing to do */
|
||||
return;
|
||||
|
||||
prt_row = (prt_row+1) % PRT_PAGELENGTH; // NEXT line
|
||||
prt_row = (prt_row+1) % PRT_PAGELENGTH; /* NEXT line */
|
||||
|
||||
if (spacemode && ! maxnp) { // spacing only
|
||||
if (spacemode && ! maxnp) { /* spacing only */
|
||||
if (prt_row == 0 && prt_nnl) {
|
||||
#ifdef _WIN32
|
||||
if (! cgi)
|
||||
putc('\r', fd); // DOS/Windows: end with cr/lf
|
||||
putc('\r', fd); /* DOS/Windows: end with cr/lf */
|
||||
#endif
|
||||
putc('\n', fd); // otherwise end with lf
|
||||
if (spacemode & UNIT_SKIPPING) // add formfeed if we crossed page boundary while skipping
|
||||
newpage(fd);
|
||||
putc('\n', fd); /* otherwise end with lf */
|
||||
if (spacemode & UNIT_SKIPPING) /* add formfeed if we crossed page boundary while skipping */
|
||||
newpage(fd, physical_printer);
|
||||
|
||||
prt_nnl = 0;
|
||||
}
|
||||
else
|
||||
else {
|
||||
prt_nnl++;
|
||||
formfed = FALSE;
|
||||
}
|
||||
|
||||
prt_unit->pos++; // note something written
|
||||
prt_unit->pos++; /* note something written */
|
||||
return;
|
||||
}
|
||||
|
||||
if (prt_nnl) { // there are queued newlines
|
||||
// if we spaced to top of form, don't emit formfeed. We'd only ever emit the formfeed if we skipped via control tape channels
|
||||
// if (prt_row == 0 && prt_nnl) { // we spaced to top of form
|
||||
//#ifdef _WIN32
|
||||
// if (! cgi)
|
||||
// putc('\r', fd); // DOS/Windows: end with cr/lf
|
||||
//#endif
|
||||
// putc('\n', fd); // otherwise end with lf
|
||||
// newpage(fd);
|
||||
// prt_nnl = 0;
|
||||
// }
|
||||
// else {
|
||||
while (prt_nnl > 0) { // spit out queued newlines
|
||||
if (prt_nnl) { /* there are queued newlines */
|
||||
while (prt_nnl > 0) { /* spit out queued newlines */
|
||||
#ifdef _WIN32
|
||||
if (! cgi)
|
||||
putc('\r', fd); // DOS/Windows: end with cr/lf
|
||||
putc('\r', fd); /* DOS/Windows: end with cr/lf */
|
||||
#endif
|
||||
putc('\n', fd); // otherwise end with lf
|
||||
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
|
||||
fxwrite(&prtbuf[r*PRT_ROWLEN], 1, ncol[r], fd);
|
||||
putc('\r', fd); /* carriage return between overprinted lines */
|
||||
|
||||
fxwrite(&prtbuf[r*MAX_COLUMNS], 1, ncol[r], fd);
|
||||
}
|
||||
|
||||
reset_prt_line();
|
||||
|
||||
prt_unit->pos++; // note something written
|
||||
prt_nnl++; // queue a newline
|
||||
prt_unit->pos++; /* note something written */
|
||||
prt_nnl++; /* queue a newline */
|
||||
|
||||
if (phys_flush) // if physical printer, send buffered output to device
|
||||
if (physical_printer) /* if physical printer, send buffered output to device */
|
||||
fflush(fd);
|
||||
|
||||
formfed = FALSE; /* note that something is now on the page */
|
||||
}
|
||||
|
||||
// 1132 printer commands
|
||||
/* 1132 printer commands */
|
||||
|
||||
#define PRT_CMD_START_PRINTER 0x0080
|
||||
#define PRT_CMD_STOP_PRINTER 0x0040
|
||||
|
@ -347,7 +362,7 @@ void xio_1132_printer (int32 iocc_addr, int32 func, int32 modify)
|
|||
|
||||
switch (func) {
|
||||
case XIO_READ:
|
||||
M[iocc_addr & mem_mask] = (uint16) (codewheel1132[prt_nchar].ebcdic << 8);
|
||||
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_1132;
|
||||
|
@ -364,31 +379,31 @@ void xio_1132_printer (int32 iocc_addr, int32 func, int32 modify)
|
|||
case XIO_CONTROL:
|
||||
if (modify & PRT_CMD_START_PRINTER) {
|
||||
SETBIT(uptr->flags, UNIT_PRINTING);
|
||||
// mytrace(1, "printing");
|
||||
/* mytrace(1, "printing"); */
|
||||
}
|
||||
|
||||
if (modify & PRT_CMD_STOP_PRINTER) {
|
||||
CLRBIT(uptr->flags, UNIT_PRINTING);
|
||||
// mytrace(0, "printing");
|
||||
/* mytrace(0, "printing"); */
|
||||
}
|
||||
|
||||
if (modify & PRT_CMD_START_CARRIAGE) {
|
||||
SETBIT(uptr->flags, UNIT_SKIPPING);
|
||||
// mytrace(1, "skipping");
|
||||
/* mytrace(1, "skipping"); */
|
||||
}
|
||||
|
||||
if (modify & PRT_CMD_STOP_CARRIAGE) {
|
||||
CLRBIT(uptr->flags, UNIT_SKIPPING);
|
||||
// mytrace(0, "skipping");
|
||||
/* mytrace(0, "skipping"); */
|
||||
}
|
||||
|
||||
if (modify & PRT_CMD_SPACE) {
|
||||
SETBIT(uptr->flags, UNIT_SPACING);
|
||||
// mytrace(1, "space");
|
||||
/* mytrace(1, "space"); */
|
||||
}
|
||||
|
||||
sim_cancel(uptr);
|
||||
if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING)) { // busy bits = doing something
|
||||
if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING)) { /* busy bits = doing something */
|
||||
SETBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY);
|
||||
sim_activate(uptr, prt_cwait);
|
||||
}
|
||||
|
@ -419,14 +434,14 @@ static t_stat prt_svc (UNIT *uptr)
|
|||
return IS_1403(uptr) ? prt1403_svc(uptr) : prt1132_svc(uptr);
|
||||
}
|
||||
|
||||
// prt1132_svc - emulated timeout for 1132 operation
|
||||
/* prt1132_svc - emulated timeout for 1132 operation */
|
||||
|
||||
static t_stat prt1132_svc (UNIT *uptr)
|
||||
{
|
||||
if (PRT_DSW & PRT1132_DSW_NOT_READY) { // cancel operation if printer went offline
|
||||
if (PRT_DSW & PRT1132_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
|
||||
forms_check(TRUE); /* and turn on forms check lamp */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -436,7 +451,7 @@ static t_stat prt1132_svc (UNIT *uptr)
|
|||
CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK|PRT1132_DSW_PRINTER_BUSY|PRT1132_DSW_CARRIAGE_BUSY);
|
||||
SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SPACE_RESPONSE);
|
||||
SETBIT(ILSW[1], ILSW_1_1132_PRINTER);
|
||||
CLRBIT(uptr->flags, UNIT_SPACING); // done with this
|
||||
CLRBIT(uptr->flags, UNIT_SPACING); /* done with this */
|
||||
calc_ints();
|
||||
}
|
||||
|
||||
|
@ -445,7 +460,7 @@ static t_stat prt1132_svc (UNIT *uptr)
|
|||
flush_prt_line(uptr->fileref, UNIT_SKIPPING, IS_PHYSICAL(uptr));
|
||||
CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK);
|
||||
SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]));
|
||||
} while ((cctape[prt_row] & CC_1132_BITS) == 0); // slew directly to a cc tape punch
|
||||
} while ((cctape[prt_row] & CC_1132_BITS) == 0); /* slew directly to a cc tape punch */
|
||||
|
||||
SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SKIP_RESPONSE);
|
||||
SETBIT(ILSW[1], ILSW_1_1132_PRINTER);
|
||||
|
@ -453,21 +468,21 @@ static t_stat prt1132_svc (UNIT *uptr)
|
|||
}
|
||||
|
||||
if (uptr->flags & UNIT_PRINTING) {
|
||||
if (! save_1132_prt_line(codewheel1132[prt_nchar].ascii)) { // save previous printed line
|
||||
SETBIT(uptr->flags, UNIT_DATACHECK); // buffer wasn't set in time
|
||||
if (! save_1132_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
|
||||
print_check(TRUE); /* and turn on forms check lamp */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132; // advance print drum
|
||||
prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132; /* advance print drum */
|
||||
|
||||
SETBIT(PRT_DSW, PRT1132_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)
|
||||
SETBIT(PRT_DSW, PRT1132_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
|
||||
if (uptr->flags & (UNIT_SPACING|UNIT_SKIPPING|UNIT_PRINTING)) { /* still doing something */
|
||||
SETBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY);
|
||||
sim_activate(uptr, prt_cwait);
|
||||
}
|
||||
|
@ -483,18 +498,18 @@ void save_1403_prt_line (int32 addr)
|
|||
unsigned char ebcdic;
|
||||
int32 wd;
|
||||
|
||||
for (i = 0; i < PRT_COLUMNS; i++) {
|
||||
if (even) { // fetch next word from memory
|
||||
for (i = 0; i < PRT1403_COLUMNS; i++) {
|
||||
if (even) { /* fetch next word from memory */
|
||||
wd = M[addr++];
|
||||
ebcdic = (unsigned char) ((wd >> 8) & 0x7F);
|
||||
even = FALSE;
|
||||
}
|
||||
else {
|
||||
ebcdic = (unsigned char) (wd & 0x7F); // use low byte of previously fetched word
|
||||
ebcdic = (unsigned char) (wd & 0x7F); /* use low byte of previously fetched word */
|
||||
even = TRUE;
|
||||
}
|
||||
|
||||
ch = ' '; // translate ebcdic to ascii. Don't bother checking for parity errors
|
||||
ch = ' '; /* translate ebcdic to ascii. Don't bother checking for parity errors */
|
||||
for (j = 0; j < WHEELCHARS_1403; j++) {
|
||||
if (codewheel1403[j].ebcdic == ebcdic) {
|
||||
ch = codewheel1403[j].ascii;
|
||||
|
@ -504,14 +519,14 @@ void save_1403_prt_line (int32 addr)
|
|||
|
||||
if (ch > ' ') {
|
||||
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
|
||||
if (ncol[r] <= i) { /* we haven't moved this far yet */
|
||||
if (ncol[r] == 0) /* first char in this row? */
|
||||
memset(prtbuf+r*MAX_COLUMNS, ' ', PRT1403_COLUMNS); /* blank out the new row */
|
||||
ncol[r] = i+1; /* remember new row length */
|
||||
}
|
||||
prtbuf[r*PRT_ROWLEN + i] = (char) ch; // save the character
|
||||
prtbuf[r*MAX_COLUMNS + i] = (char) ch; /* save the character */
|
||||
|
||||
nprint[i]++; // remember max overprintings for this column
|
||||
nprint[i]++; /* remember max overprintings for this column */
|
||||
maxnp = MAX(maxnp, nprint[i]);
|
||||
}
|
||||
}
|
||||
|
@ -568,15 +583,15 @@ void xio_1403_printer (int32 iocc_addr, int32 func, int32 modify)
|
|||
|
||||
static t_stat prt1403_svc(UNIT *uptr)
|
||||
{
|
||||
if (PRT_DSW & PRT1403_DSW_NOT_READY) { // cancel operation if printer went offline
|
||||
if (PRT_DSW & PRT1403_DSW_NOT_READY) { /* cancel operation if printer went offline */
|
||||
SET_ACTION(uptr, 0);
|
||||
forms_check(TRUE); // and turn on forms check lamp
|
||||
forms_check(TRUE); /* and turn on forms check lamp */
|
||||
}
|
||||
else if (uptr->flags & UNIT_TRANSFERRING) { // end of transfer
|
||||
else if (uptr->flags & UNIT_TRANSFERRING) { /* end of transfer */
|
||||
CLRBIT(uptr->flags, UNIT_TRANSFERRING);
|
||||
SETBIT(uptr->flags, UNIT_PRINTING); // schedule "print complete"
|
||||
SETBIT(uptr->flags, UNIT_PRINTING); /* schedule "print complete" */
|
||||
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_TRANSFER_COMPLETE); // issue transfer complete interrupt
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_TRANSFER_COMPLETE); /* issue transfer complete interrupt */
|
||||
SETBIT(ILSW[4], ILSW_4_1403_PRINTER);
|
||||
}
|
||||
else if (uptr->flags & UNIT_PRINTING) {
|
||||
|
@ -584,14 +599,14 @@ static t_stat prt1403_svc(UNIT *uptr)
|
|||
CLRBIT(PRT_DSW, PRT1403_DSW_PRINTER_BUSY);
|
||||
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_PRINT_COMPLETE);
|
||||
SETBIT(ILSW[4], ILSW_4_1403_PRINTER); // issue print complete interrupt
|
||||
SETBIT(ILSW[4], ILSW_4_1403_PRINTER); /* issue print complete interrupt */
|
||||
}
|
||||
else if (uptr->flags & UNIT_SKIPPING) {
|
||||
do { // find line with exact match of tape punches
|
||||
do { /* find line with exact match of tape punches */
|
||||
flush_prt_line(uptr->fileref, UNIT_SKIPPING, IS_PHYSICAL(uptr));
|
||||
} while (cctape[prt_row] != SKIPTARGET); // slew directly to requested cc tape punch
|
||||
} while (cctape[prt_row] != SKIPTARGET); /* slew directly to requested cc tape punch */
|
||||
|
||||
CLRBIT(uptr->flags, UNIT_SKIPPING); // done with this
|
||||
CLRBIT(uptr->flags, UNIT_SKIPPING); /* done with this */
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY);
|
||||
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_COMPLETE);
|
||||
|
@ -600,7 +615,7 @@ static t_stat prt1403_svc(UNIT *uptr)
|
|||
else if (uptr->flags & UNIT_SPACING) {
|
||||
flush_prt_line(uptr->fileref, UNIT_SPACING, IS_PHYSICAL(uptr));
|
||||
|
||||
CLRBIT(uptr->flags, UNIT_SPACING); // done with this
|
||||
CLRBIT(uptr->flags, UNIT_SPACING); /* done with this */
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY);
|
||||
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_COMPLETE);
|
||||
|
@ -610,7 +625,7 @@ static t_stat prt1403_svc(UNIT *uptr)
|
|||
if (uptr->flags & (UNIT_PRINTING|UNIT_SKIPPING|UNIT_SPACING|UNIT_TRANSFERRING))
|
||||
sim_activate(uptr, prt_fwait);
|
||||
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_CH9|PRT1403_DSW_CH12); // set the two CC bits in the DSW
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_CH9|PRT1403_DSW_CH12); /* set the two CC bits in the DSW */
|
||||
if (cctape[prt_row] & CC_CHANNEL_9)
|
||||
SETBIT(PRT_DSW, PRT1403_DSW_CH9);
|
||||
if (cctape[prt_row] & CC_CHANNEL_12)
|
||||
|
@ -646,16 +661,17 @@ static t_stat prt_reset (DEVICE *dptr)
|
|||
UNIT *uptr = &prt_unit[0];
|
||||
int i;
|
||||
|
||||
// add a DELETE filename command so we can be sure to have clean listings
|
||||
/* add a DELETE filename command so we can be sure to have clean listings */
|
||||
register_cmd("DELETE", &delete_cmd, 0, "del{ete} filename remove file\n");
|
||||
|
||||
sim_cancel(uptr);
|
||||
|
||||
memset(cctape, 0, sizeof(cctape)); // copy punch list into carriage control tape image
|
||||
memset(cctape, 0, sizeof(cctape)); /* copy punch list into carriage control tape image */
|
||||
|
||||
if (cgi)
|
||||
if (cgi) {
|
||||
for (i = 0; i < (sizeof(cccgi)/sizeof(cccgi[0])); i++)
|
||||
cctape[cccgi[i].row-1] |= cccgi[i].channels;
|
||||
}
|
||||
else
|
||||
for (i = 0; i < (sizeof(ccpunches)/sizeof(ccpunches[0])); i++)
|
||||
cctape[ccpunches[i].row-1] |= ccpunches[i].channels;
|
||||
|
@ -697,6 +713,7 @@ static t_stat prt_attach (UNIT *uptr, char *cptr)
|
|||
t_stat rval;
|
||||
/* assume failure */
|
||||
SETBIT(PRT_DSW, IS_1132(uptr) ? PRT1132_DSW_NOT_READY : PRT1403_DSW_NOT_READY);
|
||||
formfed = FALSE;
|
||||
|
||||
if (uptr->flags & UNIT_ATT) {
|
||||
if ((rval = prt_detach(uptr)) != SCPE_OK) {
|
||||
|
@ -745,7 +762,7 @@ static t_stat prt_attach (UNIT *uptr, char *cptr)
|
|||
reset_prt_line();
|
||||
|
||||
if (IS_1132(uptr)) {
|
||||
PRT_DSW = (uint16) ((PRT_DSW & ~PRT1132_DSW_CHANNEL_MASK) | cc_format_1132(cctape[prt_row]));
|
||||
PRT_DSW = (PRT_DSW & ~PRT1132_DSW_CHANNEL_MASK) | cc_format_1132(cctape[prt_row]);
|
||||
|
||||
if (IS_ONLINE(uptr))
|
||||
CLRBIT(PRT_DSW, PRT1132_DSW_NOT_READY);
|
||||
|
@ -758,10 +775,11 @@ static t_stat prt_attach (UNIT *uptr, char *cptr)
|
|||
SETBIT(PRT_DSW, PRT1403_DSW_CH12);
|
||||
|
||||
if (IS_ONLINE(uptr))
|
||||
CLRBIT(PRT_DSW, PRT1132_DSW_NOT_READY);
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_NOT_READY); /* fixed by Carl Claunch */
|
||||
}
|
||||
|
||||
forms_check(FALSE);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -769,6 +787,7 @@ static t_stat prt_detach (UNIT *uptr)
|
|||
{
|
||||
t_stat rval;
|
||||
|
||||
if (uptr->flags & UNIT_ATT)
|
||||
flush_prt_line(uptr->fileref, TRUE, TRUE);
|
||||
|
||||
if (uptr->fileref == stdout) {
|
||||
|
@ -797,3 +816,4 @@ static t_stat prt_detach (UNIT *uptr)
|
|||
forms_check(FALSE);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ DEVICE ptp_dev = {
|
|||
|
||||
/* xio_1134_papertape - XIO command interpreter for the 1134 paper tape reader and 1055 paper tape punch */
|
||||
|
||||
void xio_1134_papertape (int iocc_addr, int iocc_func, int iocc_mod)
|
||||
void xio_1134_papertape (int32 iocc_addr, int32 iocc_func, int32 iocc_mod)
|
||||
{
|
||||
char msg[80];
|
||||
|
||||
|
@ -118,7 +118,7 @@ void xio_1134_papertape (int iocc_addr, int iocc_func, int iocc_mod)
|
|||
}
|
||||
}
|
||||
|
||||
// ptr_svc - emulated timeout - 1134 read operation complete
|
||||
/* ptr_svc - emulated timeout - 1134 read operation complete */
|
||||
|
||||
static t_stat ptr_svc (UNIT *uptr)
|
||||
{
|
||||
|
@ -141,7 +141,7 @@ static t_stat ptr_svc (UNIT *uptr)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// ptp_svc - emulated timeout -- 1055 punch operation complete
|
||||
/* ptp_svc - emulated timeout -- 1055 punch operation complete */
|
||||
|
||||
static t_stat ptp_svc (UNIT *uptr)
|
||||
{
|
||||
|
@ -245,37 +245,37 @@ static t_stat ptr_boot (int unitno, DEVICE *dptr)
|
|||
}
|
||||
|
||||
if (leader) {
|
||||
if ((ch & 0x7F) == 0x7F) // ignore leading rubouts or "delete" characters
|
||||
if ((ch & 0x7F) == 0x7F) /* ignore leading rubouts or "delete" characters */
|
||||
continue;
|
||||
|
||||
leader = FALSE; // after first nonrubout, any punch in channel 5 terminates load
|
||||
leader = FALSE; /* after first nonrubout, any punch in channel 5 terminates load */
|
||||
}
|
||||
|
||||
// this is untested -- not sure of actual byte ordering
|
||||
/* this is untested -- not sure of actual byte ordering */
|
||||
|
||||
val = (val << 4) | (ch & 0x0F); // get next nybble
|
||||
val = (val << 4) | (ch & 0x0F); /* get next nybble */
|
||||
|
||||
if (++nch == 4) { // if we now have four nybbles, store the word
|
||||
if (++nch == 4) { /* if we now have four nybbles, store the word */
|
||||
M[addr & mem_mask] = (uint16) val;
|
||||
|
||||
addr++; // prepare for next word
|
||||
addr++; /* prepare for next word */
|
||||
nch = 0;
|
||||
val = 0;
|
||||
}
|
||||
|
||||
if (ch & 0x10) { // channel 5 punch terminates load
|
||||
if (ch & 0x10) { /* channel 5 punch terminates load */
|
||||
start = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! start) // if we didn't get a valid load, report EOF error
|
||||
if (! start) /* if we didn't get a valid load, report EOF error */
|
||||
return SCPE_EOF;
|
||||
|
||||
if ((rval = reset_all(0)) != SCPE_OK) // force a reset
|
||||
if ((rval = reset_all(0)) != SCPE_OK) /* force a reset */
|
||||
return rval;
|
||||
|
||||
IAR = 0; // start running at address 0
|
||||
IAR = 0; /* start running at address 0 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
1164
Ibm1130/ibm1130_sca.c
Normal file
1164
Ibm1130/ibm1130_sca.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -91,16 +91,13 @@
|
|||
|
||||
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 just be quiet about this
|
||||
// printf("%s I/O is not yet supported", dev);
|
||||
/* the real 1130 just ignores attempts to use uninstalled devices. They get tested
|
||||
* at times, so it's best to just be quiet about this
|
||||
* printf("%s I/O is not yet supported", dev);
|
||||
*/
|
||||
}
|
||||
|
||||
// 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");}
|
||||
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
|
@ -120,7 +117,7 @@ extern int cgi;
|
|||
|
||||
static int32 tti_dsw = 0; /* device status words */
|
||||
static int32 tto_dsw = 0;
|
||||
static int32 con_dsw = 0;
|
||||
int32 con_dsw = 0;
|
||||
|
||||
static unsigned char conout_map[256]; /* 1130 console code to ASCII translation. 0 = undefined, 0xFF = IGNR_ = no output */
|
||||
static unsigned char conin_map[256]; /* input mapping */
|
||||
|
@ -211,9 +208,10 @@ DEVICE tti_dev = {
|
|||
tto_reg TTO register list
|
||||
*/
|
||||
|
||||
// 14-Nov-03 -- the wait time was SERIAL_OUT_WAIT, but recent versions of SIMH reduced
|
||||
// this to 100, and wouldn't you know it, APL\1130 has about 120 instructions between the XIO WRITE
|
||||
// to the console and the associated WAIT.
|
||||
/* 14-Nov-03 -- the wait time was SERIAL_OUT_WAIT, but recent versions of SIMH reduced
|
||||
* this to 100, and wouldn't you know it, APL\1130 has about 120 instructions between the XIO WRITE
|
||||
* to the console and the associated WAIT.
|
||||
*/
|
||||
|
||||
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), 200 };
|
||||
|
||||
|
@ -279,7 +277,7 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify)
|
|||
ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */
|
||||
tto_unit.buf = emit_conout_character(ch); /* output character and save write status */
|
||||
|
||||
// fprintf(stderr, "[CONOUT] %02x\n", ch);
|
||||
/* fprintf(stderr, "[CONOUT] %02x\n", ch); */
|
||||
|
||||
SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY);
|
||||
sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */
|
||||
|
@ -300,10 +298,10 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify)
|
|||
xio_error(msg);
|
||||
}
|
||||
|
||||
// fprintf(stderr, "After XIO %04x %04x\n", tti_dsw, tto_dsw);
|
||||
/* fprintf(stderr, "After XIO %04x %04x\n", tti_dsw, tto_dsw); */
|
||||
}
|
||||
|
||||
// emit_conout_character - write character with 1130 console code 'ch'
|
||||
/* emit_conout_character - write character with 1130 console code 'ch' */
|
||||
|
||||
t_stat emit_conout_character (int ch)
|
||||
{
|
||||
|
@ -342,12 +340,12 @@ t_stat emit_conout_character (int ch)
|
|||
return map_conout_character(ch);
|
||||
}
|
||||
|
||||
static void Beep (void) // notify user keyboard was locked or key was bad
|
||||
static void Beep (void) /* notify user keyboard was locked or key was bad */
|
||||
{
|
||||
sim_putchar(7);
|
||||
}
|
||||
|
||||
// tti_svc - keyboard polling (never stops)
|
||||
/* tti_svc - keyboard polling (never stops) */
|
||||
|
||||
static t_stat tti_svc (UNIT *uptr)
|
||||
{
|
||||
|
@ -386,7 +384,7 @@ static t_stat tti_svc (UNIT *uptr)
|
|||
|
||||
if (temp == PROGRAM_STOP_KEY) { /* simulate the program stop button */
|
||||
SETBIT(con_dsw, CPU_DSW_PROGRAM_STOP);
|
||||
SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP);
|
||||
SETBIT(ILSW[5], ILSW_5_INT_RUN_PROGRAM_STOP);
|
||||
calc_ints();
|
||||
|
||||
#ifdef DEBUG_CONSOLE
|
||||
|
@ -417,16 +415,13 @@ static t_stat tti_svc (UNIT *uptr)
|
|||
printf("[%04x]", tti_unit.buf & 0xFFFF);
|
||||
#endif
|
||||
|
||||
// CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* clear busy flag (unselect keyboard) */
|
||||
// keyboard_selected(FALSE);
|
||||
|
||||
SETBIT(tti_unit.flags, KEYBOARD_LOCKED); /* prevent further keystrokes */
|
||||
|
||||
SETBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); /* queue interrupt */
|
||||
SETBIT(ILSW[4], ILSW_4_CONSOLE);
|
||||
calc_ints();
|
||||
|
||||
// fprintf(stderr, "TTI interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw);
|
||||
/* fprintf(stderr, "TTI interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw); */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -450,14 +445,14 @@ static t_stat tti_reset (DEVICE *dptr)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// basic_attach - fix quotes in filename, then call standard unit attach routine
|
||||
/* basic_attach - fix quotes in filename, then call standard unit attach routine */
|
||||
|
||||
t_stat basic_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */
|
||||
}
|
||||
|
||||
// quotefix - strip off quotes around filename, if present
|
||||
/* quotefix - strip off quotes around filename, if present */
|
||||
|
||||
char * quotefix (char * cptr)
|
||||
{
|
||||
|
@ -492,7 +487,7 @@ static t_stat tto_svc (UNIT *uptr)
|
|||
SETBIT(ILSW[4], ILSW_4_CONSOLE);
|
||||
calc_ints();
|
||||
|
||||
// fprintf(stderr, "TTO interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw);
|
||||
/* fprintf(stderr, "TTO interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw); */
|
||||
|
||||
return (t_stat) tto_unit.buf; /* return status saved during output conversion */
|
||||
}
|
||||
|
@ -648,7 +643,7 @@ static struct { /* default output mapping for APLPLUS font */
|
|||
|
||||
#define NCONOUT_TO_APL (sizeof(conout_to_APL)/sizeof(conout_to_APL[0]))
|
||||
|
||||
static OS_MAP default_os_map[] = // overstrike mapping for APLPLUS font
|
||||
static OS_MAP default_os_map[] = /* overstrike mapping for APLPLUS font */
|
||||
{
|
||||
'\x8a', 2, "\x5e\x7e",
|
||||
'\x8b', 2, "\x9f\x7e",
|
||||
|
@ -717,12 +712,12 @@ static void strsort (int n, unsigned char *s)
|
|||
unsigned char temp;
|
||||
int i, big;
|
||||
|
||||
while (--n > 0) { // repeatedly
|
||||
big = 0; // find largest value of s[0]...s[n]
|
||||
while (--n > 0) { /* repeatedly */
|
||||
big = 0; /* find largest value of s[0]...s[n] */
|
||||
for (i = 1; i <= n; i++)
|
||||
if (s[i] > s[big]) big = i;
|
||||
|
||||
temp = s[n]; // put largest value at end of array
|
||||
temp = s[n]; /* put largest value at end of array */
|
||||
s[n] = s[big];
|
||||
s[big] = temp;
|
||||
}
|
||||
|
@ -730,10 +725,10 @@ static void strsort (int n, unsigned char *s)
|
|||
|
||||
/* file format:
|
||||
|
||||
[font XXX] // font named XXX
|
||||
OUT // failure character
|
||||
OUT IN // single character mapping
|
||||
OUT IN IN ... // overstrike mapping
|
||||
[font XXX] font named XXX
|
||||
OUT failure character
|
||||
OUT IN single character mapping
|
||||
OUT IN IN ... overstrike mapping
|
||||
|
||||
*/
|
||||
|
||||
|
@ -742,35 +737,35 @@ static void set_conout_mapping (int32 flags)
|
|||
curcol = 0;
|
||||
maxcol = 0;
|
||||
|
||||
// set the default mappings. We may later override them with settings from an ini file
|
||||
/* set the default mappings. We may later override them with settings from an ini file */
|
||||
|
||||
set_default_mapping(flags);
|
||||
}
|
||||
|
||||
// finish_conout_mapping - sort the finalized overstrike mapping
|
||||
/* finish_conout_mapping - sort the finalized overstrike mapping */
|
||||
|
||||
static void finish_conout_mapping (int32 flags)
|
||||
{
|
||||
int i, n, big;
|
||||
OS_MAP temp;
|
||||
|
||||
for (i = 0; i < n_os_mappings; i++) // sort the inlist strings individually
|
||||
for (i = 0; i < n_os_mappings; i++) /* sort the inlist strings individually */
|
||||
strsort(os_map[i].nin, os_map[i].inlist);
|
||||
|
||||
for (n = n_os_mappings; --n > 0; ) { // then sort the os_map array itself with insertion sort
|
||||
big = 0; // find largest value of s[0]...s[n]
|
||||
for (n = n_os_mappings; --n > 0; ) { /* then sort the os_map array itself with insertion sort */
|
||||
big = 0; /* find largest value of s[0]...s[n] */
|
||||
for (i = 1; i <= n; i++)
|
||||
if (os_map_comp(os_map+i, os_map+big) > 0) big = i;
|
||||
|
||||
if (big != n) {
|
||||
temp = os_map[n]; // put largest value at end of array
|
||||
temp = os_map[n]; /* put largest value at end of array */
|
||||
os_map[n] = os_map[big];
|
||||
os_map[big] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate_conout_mapping - called when set command gets a new value
|
||||
/* validate_conout_mapping - called when set command gets a new value */
|
||||
|
||||
static t_stat validate_conout_mapping (UNIT *uptr, int32 match, char *cvptr, void *desc)
|
||||
{
|
||||
|
@ -793,7 +788,7 @@ static void reset_mapping (void)
|
|||
conin_map[i] = (unsigned char) i; /* default conin_map is identity map */
|
||||
}
|
||||
|
||||
// set_default_mapping - create standard font and overstrike map
|
||||
/* set_default_mapping - create standard font and overstrike map */
|
||||
|
||||
static void set_default_mapping (int32 flags)
|
||||
{
|
||||
|
@ -824,10 +819,10 @@ static void set_default_mapping (int32 flags)
|
|||
break;
|
||||
}
|
||||
|
||||
finish_conout_mapping(flags); // sort conout mapping if necessary
|
||||
finish_conout_mapping(flags); /* sort conout mapping if necessary */
|
||||
}
|
||||
|
||||
// sim_putstr - write a string to the console
|
||||
/* sim_putstr - write a string to the console */
|
||||
|
||||
t_stat sim_putstr (char *s)
|
||||
{
|
||||
|
@ -843,7 +838,7 @@ t_stat sim_putstr (char *s)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// map_conout_character - translate and write a single character
|
||||
/* map_conout_character - translate and write a single character */
|
||||
|
||||
static t_stat map_conout_character (int ch)
|
||||
{
|
||||
|
@ -857,54 +852,54 @@ static t_stat map_conout_character (int ch)
|
|||
return (tto_unit.flags & ENABLE_ANSI) ? sim_putstr((char *) red_ribbon) : SCPE_OK;
|
||||
|
||||
if ((ch = conout_map[ch & 0xFF]) == 0)
|
||||
ch = '?'; // unknown character? print ?
|
||||
ch = '?'; /* unknown character? print ? */
|
||||
|
||||
if (ch == '\n') { // newline: reset overstrike buffer
|
||||
if (ch == '\n') { /* newline: reset overstrike buffer */
|
||||
curcol = 0;
|
||||
maxcol = -1;
|
||||
}
|
||||
else if (ch == '\r') { // carriage return: rewind to column 0
|
||||
else if (ch == '\r') { /* carriage return: rewind to column 0 */
|
||||
curcol = 0;
|
||||
maxcol = -1; // assume it advances paper too
|
||||
maxcol = -1; /* assume it advances paper too */
|
||||
}
|
||||
else if (ch == '\b') { // backspace: back up one character
|
||||
else if (ch == '\b') { /* backspace: back up one character */
|
||||
if (curcol > 0)
|
||||
curcol--;
|
||||
}
|
||||
else if (n_os_mappings && ch != (unsigned char) IGNR_) {
|
||||
if (curcol >= MAX_OUTPUT_COLUMNS)
|
||||
map_conout_character('\x81'); // precede with automatic carriage return/line feed, I guess
|
||||
map_conout_character('\x81'); /* precede with automatic carriage return/line feed, I guess */
|
||||
|
||||
if (curcol > maxcol) { // first time in this column, no overstrike possible yet
|
||||
if (curcol > maxcol) { /* first time in this column, no overstrike possible yet */
|
||||
os_buf[curcol].nin = 0;
|
||||
maxcol = curcol;
|
||||
}
|
||||
|
||||
if (ch != ' ' && ch != 0) { // (if it's not a blank or unknown)
|
||||
if (ch != ' ' && ch != 0) { /* (if it's not a blank or unknown) */
|
||||
os_buf[curcol].inlist[os_buf[curcol].nin] = (unsigned char) ch;
|
||||
strsort(++os_buf[curcol].nin, os_buf[curcol].inlist);
|
||||
}
|
||||
|
||||
if (os_buf[curcol].nin == 0) // if nothing but blanks seen,
|
||||
ch = ' '; // output is a blank
|
||||
else if (os_buf[curcol].nin == 1) { // if only one printing character seen, display it
|
||||
if (os_buf[curcol].nin == 0) /* if nothing but blanks seen, */
|
||||
ch = ' '; /* output is a blank */
|
||||
else if (os_buf[curcol].nin == 1) { /* if only one printing character seen, display it */
|
||||
ch = os_buf[curcol].inlist[0];
|
||||
}
|
||||
else { // otherwise look up mapping
|
||||
else { /* otherwise look up mapping */
|
||||
ch = '?';
|
||||
|
||||
for (i = 0; i < n_os_mappings; i++) {
|
||||
cmp = os_map_comp(&os_buf[curcol], &os_map[i]);
|
||||
if (cmp == 0) { // a hit
|
||||
if (cmp == 0) { /* a hit */
|
||||
ch = os_map[i].ch;
|
||||
break;
|
||||
}
|
||||
else if (cmp < 0) // not found
|
||||
else if (cmp < 0) /* not found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (curcol < MAX_OUTPUT_COLUMNS) // this should now never happen, as we automatically return
|
||||
if (curcol < MAX_OUTPUT_COLUMNS) /* this should now never happen, as we automatically return */
|
||||
curcol++;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
Based on PDP-11 simulator written by Robert M Supnik
|
||||
|
||||
Revision History
|
||||
0.27 2005Mar08 - Added sca device
|
||||
0.26 2002Apr24 - Added !BREAK in card deck file to stop simulator
|
||||
0.25 2002Apr18 - Fixed some card reader problems. It starts the reader
|
||||
properly if you attach a deck while it's waiting to a read.
|
||||
|
@ -27,9 +28,9 @@
|
|||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev, ptr_dev, ptp_dev;
|
||||
extern DEVICE tti_dev, tto_dev, prt_dev, log_dev;
|
||||
extern DEVICE gdu_dev, console_dev;
|
||||
extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev, ptr_dev, ptp_dev, t2741_dev;
|
||||
extern DEVICE tti_dev, tto_dev, prt_dev, log_dev, sca_dev;
|
||||
extern DEVICE gdu_dev, console_dev, plot_dev;
|
||||
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
|
@ -61,8 +62,11 @@ DEVICE *sim_devices[] = {
|
|||
&prt_dev, /* 1132 printer */
|
||||
&ptr_dev, /* 1134 paper tape reader */
|
||||
&ptp_dev, /* 1055 paper tape punch */
|
||||
&sca_dev, /* Synchronous communications adapter option */
|
||||
&console_dev, /* console display (windows GUI) */
|
||||
&gdu_dev, /* 2250 display */
|
||||
&t2741_dev, /* nonstandard serial interface used by APL\1130 */
|
||||
&plot_dev, /* plotter device, in ibm1130_plot.c */
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -76,7 +80,11 @@ const char *sim_stop_messages[] = {
|
|||
"!BREAK in card deck file",
|
||||
"Phase load break",
|
||||
"Program has run amok",
|
||||
"Run time limit exceeded"
|
||||
"Run time limit exceeded",
|
||||
"Immediate Stop key requested",
|
||||
"Simulator break key pressed",
|
||||
"Simulator step count expired",
|
||||
"Simulator IO error",
|
||||
};
|
||||
|
||||
/* Loader. IPL is normally performed by card reader (boot command). This function
|
||||
|
@ -106,13 +114,13 @@ t_stat my_load (FILE *fileref, char *cptr, char *fnam)
|
|||
int iaddr = -1, runaddr = -1, val, nwords;
|
||||
|
||||
while (fgets(line, sizeof(line), fileref) != NULL) {
|
||||
for (c = line; *c && *c <= ' '; c++) // find first nonblank
|
||||
for (c = line; *c && *c <= ' '; c++) /* find first nonblank */
|
||||
;
|
||||
|
||||
if (*c == '\0' || *c == '#' || *c == '/' || *c == ';')
|
||||
continue; // empty line or comment
|
||||
continue; /* empty line or comment */
|
||||
|
||||
if (*c == '@') { // set load address
|
||||
if (*c == '@') { /* set load address */
|
||||
if (sscanf(c+1, "%x", &iaddr) != 1)
|
||||
return SCPE_FMT;
|
||||
}
|
||||
|
@ -124,7 +132,7 @@ t_stat my_load (FILE *fileref, char *cptr, char *fnam)
|
|||
if (sscanf(c+1, "%x", &val) != 1)
|
||||
return SCPE_FMT;
|
||||
|
||||
CES = val & 0xFFFF; // preload console entry switches
|
||||
CES = val & 0xFFFF; /*preload console entry switches */
|
||||
}
|
||||
else if (*c == 'z' || *c == 'Z') {
|
||||
if (sscanf(c+1, "%x", &nwords) != 1)
|
||||
|
@ -145,11 +153,11 @@ t_stat my_load (FILE *fileref, char *cptr, char *fnam)
|
|||
if (iaddr == -1)
|
||||
return SCPE_FMT;
|
||||
|
||||
WriteW(iaddr, val); // store data
|
||||
WriteW(iaddr, val); /*store data */
|
||||
iaddr++;
|
||||
}
|
||||
else
|
||||
return SCPE_FMT; // unexpected data
|
||||
return SCPE_FMT; /*unexpected data */
|
||||
}
|
||||
|
||||
if (runaddr != -1)
|
||||
|
@ -166,14 +174,14 @@ t_stat my_save (FILE *fileref, char *cptr, char *fnam)
|
|||
fprintf(fileref, "@0000\r\n");
|
||||
for (iaddr = 0; iaddr < nwords; iaddr++) {
|
||||
val = ReadW(iaddr);
|
||||
if (val == 0) // queue up zeroes
|
||||
if (val == 0) /*queue up zeroes */
|
||||
nzeroes++;
|
||||
else {
|
||||
if (nzeroes >= 4) { // spit out a Z directive
|
||||
if (nzeroes >= 4) { /*spit out a Z directive */
|
||||
fprintf(fileref, "Z%04x\r\n", nzeroes);
|
||||
nzeroes = 0;
|
||||
}
|
||||
else { // write queued zeroes literally
|
||||
else { /*write queued zeroes literally */
|
||||
while (nzeroes > 0) {
|
||||
fprintf(fileref, " 0000\r\n");
|
||||
nzeroes--;
|
||||
|
@ -182,7 +190,7 @@ t_stat my_save (FILE *fileref, char *cptr, char *fnam)
|
|||
fprintf(fileref, " %04x\r\n", val);
|
||||
}
|
||||
}
|
||||
if (nzeroes >= 4) { // emit any queued zeroes
|
||||
if (nzeroes >= 4) { /*emit any queued zeroes */
|
||||
fprintf(fileref, "Z%04x\r\n", nzeroes);
|
||||
nzeroes = 0;
|
||||
}
|
||||
|
@ -241,7 +249,7 @@ static char *opcode[] = {
|
|||
"AND ", "OR ", "EOR ", "?1F ",
|
||||
};
|
||||
|
||||
static char relative[] = { // true if short mode displacements are IAR relative
|
||||
static char relative[] = { /*true if short mode displacements are IAR relative */
|
||||
FALSE, TRUE, FALSE, FALSE,
|
||||
FALSE, TRUE, FALSE, FALSE,
|
||||
TRUE, FALSE, FALSE, FALSE,
|
||||
|
@ -287,10 +295,11 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
|||
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
|
||||
// if (sw & SWMASK ('A')) { /* ASCII? not useful */
|
||||
// fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
|
||||
// return SCPE_OK;
|
||||
// }
|
||||
/* if (sw & SWMASK ('A')) { // ASCII? not useful
|
||||
fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
|
||||
return SCPE_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
if (sw & SWMASK ('C')) /* character? not useful -- make it EBCDIC */
|
||||
sw |= SWMASK('E');
|
||||
|
@ -349,7 +358,7 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
|||
DSPLC &= 0x003F;
|
||||
eaddr = DSPLC;
|
||||
}
|
||||
else if ((OP == 0x08 && F)|| OP == 0x09) { // BSI L and BSC any
|
||||
else if ((OP == 0x08 && F)|| OP == 0x09) { /* BSI L and BSC any */
|
||||
if (OP == 0x09 && (IR & 0x40))
|
||||
mnem = "BOSC";
|
||||
|
||||
|
@ -368,7 +377,7 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
|||
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
|
||||
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;
|
||||
|
@ -446,47 +455,47 @@ t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
|||
|
||||
#ifndef _WIN32
|
||||
|
||||
int strnicmp (char *a, char *b, int n)
|
||||
int strnicmp (const char *a, const char *b, int n)
|
||||
{
|
||||
int ca, cb;
|
||||
|
||||
for (;;) {
|
||||
if (--n < 0) // still equal after n characters? quit now
|
||||
if (--n < 0) /* still equal after n characters? quit now */
|
||||
return 0;
|
||||
|
||||
if ((ca = *a) == 0) // get character, stop on null terminator
|
||||
if ((ca = *a) == 0) /* get character, stop on null terminator */
|
||||
return *b ? -1 : 0;
|
||||
|
||||
if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase
|
||||
if (ca >= 'a' && ca <= 'z') /* fold lowercase to uppercase */
|
||||
ca -= 32;
|
||||
|
||||
cb = *b;
|
||||
if (cb >= 'a' && cb <= 'z')
|
||||
cb -= 32;
|
||||
|
||||
if ((ca -= cb) != 0) // if different, return comparison
|
||||
if ((ca -= cb) != 0) /* if different, return comparison */
|
||||
return ca;
|
||||
|
||||
a++, b++;
|
||||
}
|
||||
}
|
||||
|
||||
int strcmpi (char *a, char *b)
|
||||
int strcmpi (const char *a, const char *b)
|
||||
{
|
||||
int ca, cb;
|
||||
|
||||
for (;;) {
|
||||
if ((ca = *a) == 0) // get character, stop on null terminator
|
||||
if ((ca = *a) == 0) /* get character, stop on null terminator */
|
||||
return *b ? -1 : 0;
|
||||
|
||||
if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase
|
||||
if (ca >= 'a' && ca <= 'z') /* fold lowercase to uppercase */
|
||||
ca -= 32;
|
||||
|
||||
cb = *b;
|
||||
if (cb >= 'a' && cb <= 'z')
|
||||
cb -= 32;
|
||||
|
||||
if ((ca -= cb) != 0) // if different, return comparison
|
||||
if ((ca -= cb) != 0) /* if different, return comparison */
|
||||
return ca;
|
||||
|
||||
a++, b++;
|
||||
|
|
388
Ibm1130/ibm1130_t2741.c
Normal file
388
Ibm1130/ibm1130_t2741.c
Normal file
|
@ -0,0 +1,388 @@
|
|||
/***************************************************************************************
|
||||
* Nonstandard serial attachment for remote 2741 terminal (IO selectric) used by APL\1130
|
||||
* This implementation may be incomplete and/or incorrect
|
||||
***************************************************************************************/
|
||||
|
||||
#include "ibm1130_defs.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#define DEBUG_T2741
|
||||
|
||||
static TMLN t2741_ldsc = { 0 }; /* line descr for telnet attachment */
|
||||
static TMXR t2741_tmxr = { 1, 0, 0, &t2741_ldsc }; /* line mux for telnet attachment */
|
||||
|
||||
#define T2741_DSW_TRANSMIT_NOT_READY 0x4000
|
||||
#define T2741_DSW_READ_RESPONSE 0x1000
|
||||
#define T2741_DSW_READ_OVERRUN 0x0800
|
||||
#define T2741_DSW_ATTENTION 0x0010
|
||||
|
||||
#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)
|
||||
|
||||
#define UNIT_V_PHYSICAL_TERM (UNIT_V_UF + 0) /* indicates not telnet but attachment to real terminal */
|
||||
#define UNIT_V_UPCASE (UNIT_V_UF + 1) /* indicates upshift performed */
|
||||
#define UNIT_V_SENDING (UNIT_V_UF + 2) /* indicates not telnet but attachment to real terminal */
|
||||
#define UNIT_V_RECEIVING (UNIT_V_UF + 3) /* indicates not telnet but attachment to real terminal */
|
||||
|
||||
#define UNIT_PHYSICAL_TERM (1u << UNIT_V_PHYSICAL_TERM)
|
||||
#define UNIT_UPCASE (1u << UNIT_V_UPCASE)
|
||||
#define UNIT_SENDING (1u << UNIT_V_SENDING)
|
||||
#define UNIT_RECEIVING (1u << UNIT_V_RECEIVING)
|
||||
|
||||
#define CODE_SHIFTUP 0x1C00
|
||||
#define CODE_SHIFTDOWN 0x7C00
|
||||
#define CODE_CIRCLEC 0x1F00
|
||||
#define CODE_CIRCLED 0x1600
|
||||
#define CODE_RETURN 0x5B00
|
||||
#define CODE_LINEFEED 0x3B00
|
||||
#define CODE_ATTENTION 0x0001 /* pseudocode, never really returned as a received character */
|
||||
#define CODE_UNKNOWN 0x0000
|
||||
|
||||
static t_stat t2741_svc (UNIT *uptr);
|
||||
static t_stat t2741_reset (DEVICE *dptr);
|
||||
static t_stat t2741_attach (UNIT *uptr, char *cptr);
|
||||
static t_stat t2741_detach (UNIT *uptr);
|
||||
static uint16 ascii_to_t2741 (int ascii);
|
||||
static char * t2741_to_ascii (uint16 code);
|
||||
static void set_transmit_notready (void);
|
||||
|
||||
static uint16 t2741_dsw = T2741_DSW_TRANSMIT_NOT_READY; /* device status word */
|
||||
static uint32 t2741_swait = 200; /* character send wait */
|
||||
static uint32 t2741_rwait = 2000; /* character receive wait */
|
||||
static uint16 t2741_char = 0; /* last character received */
|
||||
static int overrun = FALSE;
|
||||
static uint32 t2741_socket = 1130;
|
||||
|
||||
UNIT t2741_unit[1] = {
|
||||
{ UDATA (&t2741_svc, UNIT_ATTABLE, 0) },
|
||||
};
|
||||
|
||||
REG t2741_reg[] = {
|
||||
{ HRDATA (DSW, t2741_dsw, 16) }, /* device status word */
|
||||
{ DRDATA (RTIME, t2741_rwait, 24), PV_LEFT }, /* character receive wait */
|
||||
{ DRDATA (STIME, t2741_swait, 24), PV_LEFT }, /* character send wait */
|
||||
{ DRDATA (SOCKET, t2741_socket,16), PV_LEFT }, /* socket number */
|
||||
{ HRDATA (LASTCHAR, t2741_char, 16), PV_LEFT }, /* last character read */
|
||||
{ NULL } };
|
||||
|
||||
DEVICE t2741_dev = {
|
||||
"T2741", t2741_unit, t2741_reg, NULL,
|
||||
1, 16, 16, 1, 16, 16,
|
||||
NULL, NULL, t2741_reset,
|
||||
NULL, t2741_attach, t2741_detach};
|
||||
|
||||
/* xio_t2741_terminal - XIO command interpreter for the terminal adapter */
|
||||
|
||||
void xio_t2741_terminal (int32 iocc_addr, int32 iocc_func, int32 iocc_mod)
|
||||
{
|
||||
char msg[80];
|
||||
uint16 code;
|
||||
|
||||
switch (iocc_func) {
|
||||
case XIO_READ: /* read: return last character read */
|
||||
code = t2741_char & 0xFF00;
|
||||
M[iocc_addr & mem_mask] = code;
|
||||
overrun = FALSE;
|
||||
#ifdef DEBUG_T2741
|
||||
/* trace_both("T2741 %04x READ %02x %s", prev_IAR, code >> 8, t2741_to_ascii(code)); */
|
||||
#endif
|
||||
break;
|
||||
|
||||
case XIO_WRITE: /* write: initiate character send */
|
||||
code = M[iocc_addr & mem_mask] & 0xFF00;
|
||||
#ifdef DEBUG_T2741
|
||||
trace_both("T2741 %04x SEND %02x %s", prev_IAR, code >> 8, t2741_to_ascii(code));
|
||||
#endif
|
||||
SETBIT(t2741_dsw, T2741_DSW_TRANSMIT_NOT_READY);
|
||||
SETBIT(t2741_unit->flags, UNIT_SENDING);
|
||||
|
||||
if (code == CODE_SHIFTUP)
|
||||
SETBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
else if (code == CODE_SHIFTDOWN)
|
||||
CLRBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
|
||||
sim_activate(t2741_unit, t2741_swait); /* schedule interrupt */
|
||||
break;
|
||||
|
||||
case XIO_SENSE_DEV: /* sense device status */
|
||||
ACC = t2741_dsw;
|
||||
#ifdef DEBUG_T2741
|
||||
/* trace_both("T2741 %04x SENS %04x%s", prev_IAR, t2741_dsw, (iocc_mod & 0x01) ? " reset" : ""); */
|
||||
#endif
|
||||
if (iocc_mod & 0x01) { /* reset interrupts */
|
||||
CLRBIT(t2741_dsw, T2741_DSW_READ_RESPONSE);
|
||||
CLRBIT(ILSW[4], ILSW_4_T2741_TERMINAL);
|
||||
}
|
||||
break;
|
||||
|
||||
case XIO_CONTROL: /* control: do something to interface */
|
||||
#ifdef DEBUG_T2741
|
||||
trace_both("T2741 %04x CTRL %04x", prev_IAR, iocc_mod &0xFF);
|
||||
#endif
|
||||
SETBIT(t2741_unit->flags, UNIT_RECEIVING); /* set mode to receive mode */
|
||||
if (IS_ONLINE(t2741_unit) && (t2741_char != 0 || ! feof(t2741_unit->fileref))) {
|
||||
sim_activate(t2741_unit, t2741_rwait);
|
||||
t2741_char = (CODE_CIRCLED >> 8); /* first character received after turnaround is circled */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sprintf(msg, "Invalid T2741 XIO function %x", iocc_func);
|
||||
xio_error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_transmit_notready (void)
|
||||
{
|
||||
if (IS_ONLINE(t2741_unit) && ! (t2741_unit->flags & UNIT_SENDING))
|
||||
CLRBIT(t2741_dsw, T2741_DSW_TRANSMIT_NOT_READY);
|
||||
else
|
||||
SETBIT(t2741_dsw, T2741_DSW_TRANSMIT_NOT_READY);
|
||||
}
|
||||
|
||||
static t_stat t2741_svc (UNIT *uptr)
|
||||
{
|
||||
int ch = EOF;
|
||||
uint16 code;
|
||||
|
||||
if (uptr->flags & UNIT_SENDING) { /* xmit: no interrupt, as far as I know. just clr busy bit */
|
||||
CLRBIT(uptr->flags, UNIT_SENDING);
|
||||
set_transmit_notready();
|
||||
}
|
||||
|
||||
if (uptr->flags & UNIT_RECEIVING) { /* rcv: fire interrupt */
|
||||
t2741_char <<= 8;
|
||||
|
||||
if (t2741_char == 0) { /* there is no 2nd character from previous ascii input */
|
||||
if ((ch = getc(t2741_unit->fileref)) == EOF)
|
||||
t2741_char = 0;
|
||||
else {
|
||||
if (ch == '\r') { /* if we get CR, jump to LF */
|
||||
if ((ch = getc(t2741_unit->fileref)) != '\n') {
|
||||
ungetc(ch, t2741_unit->fileref);
|
||||
ch = '\r';
|
||||
}
|
||||
}
|
||||
|
||||
if (ch == '\027') {
|
||||
t2741_char = CODE_LINEFEED; /* attention key sends line feed character */
|
||||
#ifdef DEBUG_T2741
|
||||
trace_both("T2741 ---- ATTENTION");
|
||||
#endif
|
||||
SETBIT(t2741_dsw, T2741_DSW_ATTENTION); /* no character returned ? */
|
||||
}
|
||||
else {
|
||||
t2741_char = ascii_to_t2741(ch); /* translate to 2741 code(s) */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
code = t2741_char & 0xFF00;
|
||||
|
||||
if (t2741_char != 0) {
|
||||
if (overrun) /* previous character was not picked up! */
|
||||
SETBIT(t2741_dsw, T2741_DSW_READ_OVERRUN);
|
||||
|
||||
SETBIT(t2741_dsw, T2741_DSW_READ_RESPONSE);
|
||||
SETBIT(ILSW[4], ILSW_4_T2741_TERMINAL); /* issue interrupt */
|
||||
calc_ints();
|
||||
|
||||
#ifdef DEBUG_T2741
|
||||
trace_both("T2741 ---- RCVD %02x '%s' RDRESP%s%s", code >> 8, t2741_to_ascii(code),
|
||||
(t2741_dsw & T2741_DSW_READ_OVERRUN) ? "|OVERRUN" : "",
|
||||
(t2741_dsw & T2741_DSW_ATTENTION) ? "|ATTENTION" : "");
|
||||
#endif
|
||||
|
||||
overrun = TRUE; /* arm overrun flag */
|
||||
}
|
||||
|
||||
if (t2741_char == CODE_CIRCLEC) /* end of line (CIRCLEC after RETURN) auto downshifts */
|
||||
CLRBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
|
||||
if (t2741_char == 0 || code == CODE_CIRCLEC)
|
||||
CLRBIT(uptr->flags, UNIT_RECEIVING); /* on enter or EOF, stop typing */
|
||||
else
|
||||
sim_activate(t2741_unit, t2741_rwait); /* schedule next character to arrive */
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static t_stat t2741_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if ((rval = attach_unit(uptr, cptr)) == SCPE_OK) { /* use standard attach */
|
||||
t2741_char = 0;
|
||||
overrun = FALSE;
|
||||
|
||||
CLRBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
|
||||
if ((t2741_unit->flags & UNIT_RECEIVING) && ! feof(t2741_unit->fileref))
|
||||
sim_activate(t2741_unit, t2741_rwait); /* schedule interrupt */
|
||||
}
|
||||
|
||||
set_transmit_notready();
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static t_stat t2741_detach (UNIT *uptr)
|
||||
{
|
||||
t_stat rval;
|
||||
|
||||
if (t2741_unit->flags & UNIT_RECEIVING) /* if receive was pending, cancel interrupt */
|
||||
sim_cancel(t2741_unit);
|
||||
|
||||
t2741_char = 0;
|
||||
overrun = FALSE;
|
||||
|
||||
rval = detach_unit(uptr); /* use standard detach */
|
||||
|
||||
set_transmit_notready();
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static t_stat t2741_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_cancel(t2741_unit);
|
||||
|
||||
CLRBIT(t2741_unit->flags, UNIT_SENDING|UNIT_RECEIVING|UNIT_UPCASE);
|
||||
|
||||
t2741_char = 0;
|
||||
t2741_dsw = 0;
|
||||
overrun = FALSE;
|
||||
|
||||
set_transmit_notready();
|
||||
|
||||
CLRBIT(ILSW[4], ILSW_4_T2741_TERMINAL);
|
||||
calc_ints();
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static struct tag_t2741_map {
|
||||
int code;
|
||||
int lcase, ucase;
|
||||
t_bool shifts;
|
||||
} t2741_map[] = {
|
||||
{0x4F00, 'A', 'a', TRUE},
|
||||
{0x3700, 'B', 'b', TRUE},
|
||||
{0x2F00, 'C', 'c', TRUE},
|
||||
{0x2A00, 'D', 'd', TRUE},
|
||||
{0x2900, 'E', 'e', TRUE},
|
||||
{0x6700, 'F', '_', TRUE},
|
||||
{0x6200, 'G', 'g', TRUE},
|
||||
{0x3200, 'H', 'h', TRUE},
|
||||
{0x4C00, 'I', 'i', TRUE},
|
||||
{0x6100, 'J', 'j', TRUE},
|
||||
{0x2C00, 'K', '\'', TRUE},
|
||||
{0x3100, 'L', 'l', TRUE},
|
||||
{0x4300, 'M', '|', TRUE},
|
||||
{0x2500, 'N', 'n', TRUE},
|
||||
{0x5100, 'O', 'o', TRUE},
|
||||
{0x6800, 'P', '*', TRUE},
|
||||
{0x6D00, 'Q', '?', TRUE},
|
||||
{0x4A00, 'R', 'r', TRUE},
|
||||
{0x5200, 'S', 's', TRUE},
|
||||
{0x2000, 'T', '~', TRUE},
|
||||
{0x2600, 'U', 'u', TRUE},
|
||||
{0x4600, 'V', 'v', TRUE},
|
||||
{0x5700, 'W', 'w', TRUE},
|
||||
{0x2300, 'X', 'x', TRUE},
|
||||
{0x7300, 'Y', 'y', TRUE},
|
||||
{0x1500, 'Z', 'z', TRUE},
|
||||
{0x1300, '0', '&', TRUE},
|
||||
{0x0200, '1', '?', TRUE},
|
||||
{0x0400, '2', '?', TRUE},
|
||||
{0x0700, '3', '<', TRUE},
|
||||
{0x1000, '4', '?', TRUE},
|
||||
{0x0800, '5', '=', TRUE},
|
||||
{0x0D00, '6', '?', TRUE},
|
||||
{0x0B00, '7', '>', TRUE},
|
||||
{0x0E00, '8', '?', TRUE},
|
||||
{0x1600, '9', '|', TRUE},
|
||||
{0x7000, '/', '\\', TRUE},
|
||||
{0x7600, '+', '-', TRUE},
|
||||
{0x6400, '?', '?', TRUE},
|
||||
{0x4000, '<', '>', TRUE},
|
||||
{0x6B00, '[', '(', TRUE},
|
||||
{0x4900, ']', ')', TRUE},
|
||||
{0x6E00, ',', ';', TRUE},
|
||||
{0x4500, '.', ':', TRUE},
|
||||
{0x0100, ' ', 0, FALSE},
|
||||
{0x5B00, '\r', 0, FALSE},
|
||||
{0x3B00, '\n', 0, FALSE},
|
||||
{0x5D00, '\b', 0, FALSE},
|
||||
{0x5E00, '\t', 0, FALSE},
|
||||
{0x0001, '\027', 0, FALSE},
|
||||
};
|
||||
|
||||
static uint16 ascii_to_t2741 (int ascii)
|
||||
{
|
||||
int i;
|
||||
uint16 rval = 0;
|
||||
|
||||
ascii &= 0xFF;
|
||||
|
||||
if (ascii == '\n') /* turn newlines into returns + CIRCLED? */
|
||||
return CODE_RETURN | (CODE_CIRCLEC >> 8);
|
||||
|
||||
for (i = sizeof(t2741_map)/sizeof(t2741_map[0]); --i >= 0; ) {
|
||||
if (t2741_map[i].shifts) {
|
||||
if (t2741_map[i].lcase == ascii) {
|
||||
rval = t2741_map[i].code;
|
||||
if (t2741_unit->flags & UNIT_UPCASE) {
|
||||
CLRBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
rval = CODE_SHIFTDOWN | (rval >> 8);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
if (t2741_map[i].ucase == ascii) {
|
||||
rval = t2741_map[i].code;
|
||||
if (! (t2741_unit->flags & UNIT_UPCASE)) {
|
||||
SETBIT(t2741_unit->flags, UNIT_UPCASE);
|
||||
rval = CODE_SHIFTUP | (rval >> 8);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
else if (t2741_map[i].lcase == ascii)
|
||||
return t2741_map[i].code;
|
||||
}
|
||||
|
||||
return CODE_UNKNOWN;
|
||||
}
|
||||
|
||||
static char * t2741_to_ascii (uint16 code)
|
||||
{
|
||||
int i;
|
||||
static char string[2] = {'?', '\0'};
|
||||
|
||||
switch (code) {
|
||||
case CODE_SHIFTUP: return "SHIFTUP";
|
||||
case CODE_SHIFTDOWN: return "SHIFTDN";
|
||||
case CODE_CIRCLEC: return "CIRCLEC";
|
||||
case CODE_CIRCLED: return "CIRCLED";
|
||||
}
|
||||
|
||||
for (i = sizeof(t2741_map)/sizeof(t2741_map[0]); --i >= 0; ) {
|
||||
if (t2741_map[i].code == code) {
|
||||
if (t2741_map[i].shifts) {
|
||||
string[0] = (t2741_unit->flags & UNIT_UPCASE) ? t2741_map[i].ucase : t2741_map[i].lcase;
|
||||
return string;
|
||||
}
|
||||
switch (t2741_map[i].lcase) {
|
||||
case ' ': return " ";
|
||||
case '\r': return "RETURN";
|
||||
case '\n': return "LINEFEED";
|
||||
case '\b': return "BS";
|
||||
case '\t': return "IDLE";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return "?";
|
||||
}
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
cpu Interdata 16b CPU
|
||||
|
||||
27-Oct-06 RMS Added idle support
|
||||
Removed separate PASLA clock
|
||||
06-Feb-06 RMS Fixed bug in DH (found by Mark Hittinger)
|
||||
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
||||
25-Aug-05 RMS Fixed DH integer overflow cases
|
||||
|
@ -219,7 +221,8 @@ uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL };
|
|||
extern int32 sim_interval;
|
||||
extern int32 sim_int_char;
|
||||
extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
extern UNIT pic_unit, lfc_unit, pas_unit; /* timers */
|
||||
extern t_bool sim_idle_enab;
|
||||
extern UNIT pic_unit, lfc_unit; /* timers */
|
||||
|
||||
uint32 ReadB (uint32 loc);
|
||||
uint32 ReadH (uint32 loc);
|
||||
|
@ -445,7 +448,7 @@ static uint32 s1_rel_const[16] = { /* addr 8000-FFFF */
|
|||
DIB cpu_dib = { d_DS, -1, v_DS, NULL, &display, NULL };
|
||||
|
||||
UNIT cpu_unit = {
|
||||
UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_716, MAXMEMSIZE16)
|
||||
UDATA (NULL, UNIT_FIX | UNIT_BINK | UNIT_716, MAXMEMSIZE16)
|
||||
};
|
||||
|
||||
REG cpu_reg[] = {
|
||||
|
@ -513,6 +516,13 @@ REG cpu_reg[] = {
|
|||
};
|
||||
|
||||
MTAB cpu_mod[] = {
|
||||
{ UNIT_TYPE, 0, "I3", "I3", &cpu_set_model },
|
||||
{ UNIT_TYPE, UNIT_ID4, "I4", "I4", &cpu_set_model },
|
||||
{ UNIT_TYPE, UNIT_716, "7/16", "716", &cpu_set_model },
|
||||
{ UNIT_TYPE, UNIT_816, "8/16", "816", &cpu_set_model },
|
||||
{ UNIT_TYPE, UNIT_816E, "8/16E", "816E", &cpu_set_model },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
|
||||
{ UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
|
||||
|
@ -521,11 +531,6 @@ MTAB cpu_mod[] = {
|
|||
{ UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size },
|
||||
{ UNIT_TYPE, 0, "I3", "I3", &cpu_set_model },
|
||||
{ UNIT_TYPE, UNIT_ID4, "I4", "I4", &cpu_set_model },
|
||||
{ UNIT_TYPE, UNIT_716, "7/16", "716", &cpu_set_model },
|
||||
{ UNIT_TYPE, UNIT_816, "8/16", "816", &cpu_set_model },
|
||||
{ UNIT_TYPE, UNIT_816E, "8/16E", "816E", &cpu_set_model },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
|
||||
&cpu_set_consint, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||
|
@ -584,7 +589,6 @@ int_eval (); /* eval interrupts */
|
|||
cc = newPSW (PSW & psw_mask); /* split PSW, eval wait */
|
||||
sim_rtcn_init (lfc_unit.wait, TMR_LFC); /* init clock */
|
||||
sim_rtcn_init (pic_unit.wait, TMR_PIC); /* init timer */
|
||||
sim_rtcn_init (pas_unit.wait, TMR_PAS); /* init pas */
|
||||
reason = 0;
|
||||
|
||||
/* Process events */
|
||||
|
@ -641,10 +645,9 @@ while (reason == 0) { /* loop until halted */
|
|||
}
|
||||
|
||||
if (PSW & PSW_WAIT) { /* wait state? */
|
||||
t = sim_qcount (); /* events in queue */
|
||||
if ((t == 0) || ((t == 1) && stop_wait)) /* empty, or kbd only? */
|
||||
reason = STOP_WAIT; /* then stop */
|
||||
else sim_interval = 0; /* force check */
|
||||
if (sim_idle_enab) /* idling enabled? */
|
||||
sim_idle (TMR_LFC, TRUE);
|
||||
else sim_interval = sim_interval - 1; /* no, count cycle */
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id16_sys.c: Interdata 16b simulator interface
|
||||
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
Copyright (c) 2000-2006, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
18-Oct-06 RMS Re-ordered device list
|
||||
26-Mar-04 RMS Fixed warning with -std=c99
|
||||
27-Feb-03 RMS Added relative addressing support
|
||||
*/
|
||||
|
@ -69,13 +70,13 @@ int32 sim_emax = 2;
|
|||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&sch_dev,
|
||||
&pic_dev,
|
||||
&lfc_dev,
|
||||
&pt_dev,
|
||||
&tt_dev,
|
||||
&ttp_dev,
|
||||
&pas_dev,
|
||||
&pasl_dev,
|
||||
&pic_dev,
|
||||
&lfc_dev,
|
||||
&lpt_dev,
|
||||
&dp_dev,
|
||||
&idc_dev,
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
cpu Interdata 32b CPU
|
||||
|
||||
27-Oct-06 RMS Added idle support
|
||||
Removed separate PASLA clock
|
||||
09-Mar-06 RMS Added 8 register bank support for 8/32
|
||||
06-Feb-06 RMS Fixed bug in DH (found by Mark Hittinger)
|
||||
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
||||
|
@ -249,7 +251,8 @@ uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL };
|
|||
extern int32 sim_interval;
|
||||
extern int32 sim_int_char;
|
||||
extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
extern UNIT pic_unit, lfc_unit, pas_unit; /* timers */
|
||||
extern t_bool sim_idle_enab;
|
||||
extern UNIT pic_unit, lfc_unit; /* timers */
|
||||
extern FILE *sim_deb;
|
||||
|
||||
uint32 ReadB (uint32 loc, uint32 rel);
|
||||
|
@ -566,11 +569,6 @@ REG cpu_reg[] = {
|
|||
};
|
||||
|
||||
MTAB cpu_mod[] = {
|
||||
{ UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 1048756, NULL, "1M", &cpu_set_size },
|
||||
{ UNIT_8RS|UNIT_TYPE, 0, NULL, "732", NULL },
|
||||
{ UNIT_DPFP, UNIT_DPFP, NULL, "DPFP", NULL },
|
||||
{ UNIT_TYPE, 0, "7/32, single precision fp", "732", NULL },
|
||||
|
@ -579,6 +577,13 @@ MTAB cpu_mod[] = {
|
|||
{ UNIT_8RS, 0, NULL, "2RS", NULL },
|
||||
{ UNIT_8RS|UNIT_TYPE, UNIT_8RS|UNIT_DPFP|UNIT_832, "832, 8 register sets", NULL, NULL },
|
||||
{ UNIT_8RS|UNIT_TYPE, UNIT_DPFP|UNIT_832, "832, 2 register sets", NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
|
||||
{ UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 1048756, NULL, "1M", &cpu_set_size },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
|
||||
&cpu_set_consint, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||
|
@ -624,7 +629,6 @@ int_eval (); /* eval interrupts */
|
|||
cc = newPSW (PSW & PSW_MASK); /* split PSW, eval wait */
|
||||
sim_rtcn_init (lfc_unit.wait, TMR_LFC); /* init clock */
|
||||
sim_rtcn_init (pic_unit.wait, TMR_PIC); /* init timer */
|
||||
sim_rtcn_init (pas_unit.wait, TMR_PAS); /* init pas */
|
||||
reason = 0;
|
||||
|
||||
/* Abort handling
|
||||
|
@ -703,10 +707,9 @@ while (reason == 0) { /* loop until halted */
|
|||
}
|
||||
|
||||
if (PSW & PSW_WAIT) { /* wait state? */
|
||||
t = sim_qcount (); /* events in queue */
|
||||
if ((t == 0) || ((t == 1) && stop_wait)) /* empty, or kbd only? */
|
||||
reason = STOP_WAIT; /* then stop */
|
||||
else sim_interval = 0; /* force check */
|
||||
if (sim_idle_enab) /* idling enabled? */
|
||||
sim_idle (TMR_LFC, TRUE);
|
||||
else sim_interval = sim_interval - 1; /* no, count cycle */
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id32_sys.c: Interdata 32b simulator interface
|
||||
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
Copyright (c) 2000-2007, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,8 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
25-Jan-07 RMS Fixed conflict between -h (hex) and -h (halfword)
|
||||
18-Oct-06 RMS Re-ordered device list
|
||||
02-Jul-04 RMS Fixed missing type in declaration
|
||||
15-Jul-03 RMS Fixed signed/unsigned bug in get_imm
|
||||
27-Feb-03 RMS Added relative addressing support
|
||||
|
@ -72,13 +74,13 @@ int32 sim_emax = 6;
|
|||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&sch_dev,
|
||||
&pic_dev,
|
||||
&lfc_dev,
|
||||
&pt_dev,
|
||||
&tt_dev,
|
||||
&ttp_dev,
|
||||
&pas_dev,
|
||||
&pasl_dev,
|
||||
&pic_dev,
|
||||
&lfc_dev,
|
||||
&lpt_dev,
|
||||
&dp_dev,
|
||||
&idc_dev,
|
||||
|
@ -365,7 +367,7 @@ if (sw & SWMASK ('C')) { /* string? */
|
|||
fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
|
||||
return -1;
|
||||
}
|
||||
if (sw & SWMASK ('H')) { /* halfword? */
|
||||
if (sw & SWMASK ('W')) { /* halfword? */
|
||||
fprint_val (of, val[0], rdx, 16, PV_RZRO);
|
||||
return -1;
|
||||
}
|
||||
|
@ -584,7 +586,7 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */
|
|||
val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1];
|
||||
return -1;
|
||||
}
|
||||
if (sw & SWMASK ('H')) { /* halfword? */
|
||||
if (sw & SWMASK ('W')) { /* halfword? */
|
||||
val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
return -1;
|
||||
|
|
|
@ -451,7 +451,6 @@ typedef struct {
|
|||
|
||||
#define TMR_LFC 0 /* LFC = timer 0 */
|
||||
#define TMR_PIC 1 /* PIC = timer 1 */
|
||||
#define TMR_PAS 2 /* PAS = timer 2 */
|
||||
#define LPT_WIDTH 132
|
||||
#define VFU_LNT 132
|
||||
#define MIN(x,y) (((x) < (y))? (x): (y))
|
||||
|
|
|
@ -128,8 +128,8 @@
|
|||
#define HCYL_V_HD 10 /* head/cyl word */
|
||||
#define HCYL_V_CYL 0
|
||||
|
||||
#define GET_SA(cy,sf,sc,t) (((((cy)*drv_tab[t].surf)+(sf))* \
|
||||
IDC_NUMSC)+(sc))
|
||||
#define GET_SA(cy,sf,sc,t) \
|
||||
(((((cy)*drv_tab[t].surf)+(sf))*IDC_NUMSC)+(sc))
|
||||
|
||||
/* The MSM (IDC) controller supports (two) six different disk drive types:
|
||||
|
||||
|
|
|
@ -167,7 +167,8 @@ if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
|||
t = uptr->buf; /* get character */
|
||||
if (lpt_spnd || ((t >= LF) && (t < CR))) { /* spc pend or spc op? */
|
||||
lpt_spnd = 0;
|
||||
if (lpt_bufout (uptr) != SCPE_OK) return SCPE_IOERR; /* print */
|
||||
if (lpt_bufout (uptr) != SCPE_OK) /* print */
|
||||
return SCPE_IOERR;
|
||||
if ((t == 1) || (t == LF)) lpt_spc (uptr, 1); /* single space */
|
||||
else if (t == VT) r = lpt_vfu (uptr, VT_VFU - 1); /* VT->VFU */
|
||||
else if (t == 0xC) r = lpt_vfu (uptr, FF_VFU - 1); /* FF->VFU */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id_pas.c: Interdata programmable async line adapter simulator
|
||||
|
||||
Copyright (c) 2001-2005, Robert M Supnik
|
||||
Copyright (c) 2001-2006, 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"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
pas Programmable asynchronous line adapter(s)
|
||||
|
||||
18-Oct-06 RMS Synced PASLA to clock
|
||||
22-Nov-05 RMS Revised for new terminal processing routines
|
||||
29-Jun-05 RMS Added SET PASLn DISCONNECT
|
||||
21-Jun-05 RMS Fixed bug in SHOW CONN/STATS
|
||||
|
@ -49,7 +50,6 @@
|
|||
#define UNIT_V_MDM (TTUF_V_UF + 0) /* modem control */
|
||||
#define UNIT_MDM (1 << UNIT_V_MDM)
|
||||
|
||||
#define PAS_INIT_POLL 8000
|
||||
#define PASL_WAIT 500
|
||||
|
||||
/* Status byte */
|
||||
|
@ -88,6 +88,7 @@
|
|||
#define CMD_TYP 0x01 /* command type */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
extern int32 lfc_poll;
|
||||
|
||||
uint8 pas_sta[PAS_LINES]; /* status */
|
||||
uint16 pas_cmd[PAS_LINES]; /* command */
|
||||
|
@ -96,7 +97,6 @@ uint8 pas_xbuf[PAS_LINES]; /* xmt buf */
|
|||
uint8 pas_rarm[PAS_LINES]; /* rcvr int armed */
|
||||
uint8 pas_xarm[PAS_LINES]; /* xmt int armed */
|
||||
uint8 pas_rchp[PAS_LINES]; /* rcvr chr pend */
|
||||
uint32 pas_tps = 50; /* polls/second */
|
||||
uint8 pas_tplte[PAS_LINES * 2 + 1]; /* template */
|
||||
|
||||
TMLN pas_ldsc[PAS_LINES] = { 0 }; /* line descriptors */
|
||||
|
@ -126,7 +126,7 @@ void pas_reset_ln (int32 i);
|
|||
|
||||
DIB pas_dib = { d_PAS, -1, v_PAS, pas_tplte, &pas, &pas_ini };
|
||||
|
||||
UNIT pas_unit = { UDATA (&pasi_svc, UNIT_ATTABLE, 0), PAS_INIT_POLL };
|
||||
UNIT pas_unit = { UDATA (&pasi_svc, UNIT_ATTABLE, 0), 0 };
|
||||
|
||||
REG pas_nlreg = { DRDATA (NLINES, PAS_ENAB, 6), PV_LEFT };
|
||||
|
||||
|
@ -312,11 +312,10 @@ return 0;
|
|||
|
||||
t_stat pasi_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ln, c, out, t;
|
||||
int32 ln, c, out;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
t = sim_rtcn_calb (pas_tps, TMR_PAS); /* calibrate */
|
||||
sim_activate (uptr, t); /* continue poll */
|
||||
sim_activate (uptr, lfc_poll); /* continue poll */
|
||||
ln = tmxr_poll_conn (&pas_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? */
|
||||
if ((pasl_unit[ln].flags & UNIT_MDM) && /* modem control */
|
||||
|
@ -448,7 +447,7 @@ return c & 0xFF;
|
|||
|
||||
t_stat pas_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i, t;
|
||||
int32 i;
|
||||
|
||||
if (dptr->flags & DEV_DIS) { /* disabled? */
|
||||
pas_dev.flags = pas_dev.flags | DEV_DIS; /* disable lines */
|
||||
|
@ -458,12 +457,8 @@ else {
|
|||
pas_dev.flags = pas_dev.flags & ~DEV_DIS; /* enable lines */
|
||||
pasl_dev.flags = pasl_dev.flags & ~DEV_DIS;
|
||||
}
|
||||
if (pas_unit.flags & UNIT_ATT) { /* master att? */
|
||||
if (!sim_is_active (&pas_unit)) {
|
||||
t = sim_rtcn_init (pas_unit.wait, TMR_PAS);
|
||||
sim_activate (&pas_unit, t); /* activate */
|
||||
}
|
||||
}
|
||||
if (pas_unit.flags & UNIT_ATT) /* master att? */
|
||||
sim_activate_abs (&pas_unit, lfc_poll); /* cosched with clock */
|
||||
else sim_cancel (&pas_unit); /* else stop */
|
||||
for (i = 0; i < PAS_LINES; i++) pas_reset_ln (i);
|
||||
return SCPE_OK;
|
||||
|
@ -477,8 +472,7 @@ t_stat r;
|
|||
|
||||
r = tmxr_attach (&pas_desc, uptr, cptr); /* attach */
|
||||
if (r != SCPE_OK) return r; /* error */
|
||||
sim_rtcn_init (pas_unit.wait, TMR_PAS);
|
||||
sim_activate (uptr, 100); /* quick poll */
|
||||
sim_activate_abs (uptr, 100); /* quick poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id_tt.c: Interdata teletype
|
||||
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
Copyright (c) 2000-2006, 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"),
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
tt console
|
||||
|
||||
18-Oct-06 RMS Sync keyboard to LFC clock
|
||||
30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode
|
||||
22-Nov-05 RMS Revised for new terminal processing routines
|
||||
29-Dec-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
|
@ -49,6 +51,7 @@
|
|||
#define CMD_V_RD 2 /* read/write */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
extern int32 lfc_poll;
|
||||
|
||||
uint32 tt_sta = STA_BSY; /* status */
|
||||
uint32 tt_fdpx = 1; /* tt mode */
|
||||
|
@ -74,7 +77,7 @@ t_stat tt_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc);
|
|||
DIB tt_dib = { d_TT, -1, v_TT, NULL, &tt, NULL };
|
||||
|
||||
UNIT tt_unit[] = {
|
||||
{ UDATA (&tti_svc, TT_MODE_KSR, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&tti_svc, TT_MODE_KSR, 0), 0 },
|
||||
{ UDATA (&tto_svc, TT_MODE_KSR, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
|
@ -82,7 +85,7 @@ REG tt_reg[] = {
|
|||
{ HRDATA (STA, tt_sta, 8) },
|
||||
{ HRDATA (KBUF, tt_unit[TTI].buf, 8) },
|
||||
{ DRDATA (KPOS, tt_unit[TTI].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (KTIME, tt_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (KTIME, tt_unit[TTI].wait, 24), PV_LEFT },
|
||||
{ HRDATA (TBUF, tt_unit[TTO].buf, 8) },
|
||||
{ DRDATA (TPOS, tt_unit[TTO].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TTIME, tt_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
|
||||
|
@ -175,7 +178,7 @@ t_stat tti_svc (UNIT *uptr)
|
|||
{
|
||||
int32 out, temp;
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
sim_activate (uptr, KBD_WAIT (uptr->wait, lfc_poll)); /* continue poll */
|
||||
tt_sta = tt_sta & ~STA_BRK; /* clear break */
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
|
||||
if (tt_rd) { /* read mode? */
|
||||
|
@ -192,7 +195,7 @@ if (temp & SCPE_BREAK) { /* break? */
|
|||
else uptr->buf = sim_tt_inpcvt (temp, TT_GET_MODE (uptr->flags) | TTUF_KSR);
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
if (!tt_fdpx) { /* half duplex? */
|
||||
out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags));
|
||||
out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags) | TTUF_KSR);
|
||||
if (out >= 0) { /* valid echo? */
|
||||
sim_putchar (out); /* write char */
|
||||
tt_unit[TTO].pos = tt_unit[TTO].pos + 1;
|
||||
|
@ -206,7 +209,7 @@ t_stat tto_svc (UNIT *uptr)
|
|||
int32 ch;
|
||||
t_stat r;
|
||||
|
||||
ch = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags));
|
||||
ch = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags) | TTUF_KSR);
|
||||
if (ch >= 0) {
|
||||
if ((r = sim_putchar_s (ch)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
|
@ -226,7 +229,7 @@ return SCPE_OK;
|
|||
t_stat tt_reset (DEVICE *dptr)
|
||||
{
|
||||
if (dptr->flags & DEV_DIS) sim_cancel (&tt_unit[TTI]); /* dis? cancel poll */
|
||||
else sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* activate input */
|
||||
else sim_activate_abs (&tt_unit[TTI], KBD_WAIT (tt_unit[TTI].wait, lfc_poll));
|
||||
sim_cancel (&tt_unit[TTO]); /* cancel output */
|
||||
tt_rd = tt_fdpx = 1; /* read, full duplex */
|
||||
tt_chp = 0; /* no char */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id_ttp.c: Interdata PASLA console interface
|
||||
|
||||
Copyright (c) 2000-2005, Robert M. Supnik
|
||||
Copyright (c) 2000-2006, 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"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
ttp console (on PAS)
|
||||
|
||||
18-Oct-06 RMS Sync keyboard to LFC clock
|
||||
22-Nov-05 RMS Revised for new terminal processing routines
|
||||
29-Dec-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
|
@ -52,6 +53,8 @@
|
|||
#define CMD_TYP 0x01 /* command type */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
extern int32 pas_par (int32 cmd, int32 c);
|
||||
extern int32 lfc_poll;
|
||||
|
||||
uint32 ttp_sta = 0; /* status */
|
||||
uint32 ttp_cmd = 0; /* command */
|
||||
|
@ -68,14 +71,12 @@ t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
|||
t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat ttp_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
extern int32 pas_par (int32 cmd, int32 c);
|
||||
|
||||
/* TTP data structures */
|
||||
|
||||
DIB ttp_dib = { d_TTP, -1, v_TTP, ttp_tplte, &ttp, NULL };
|
||||
|
||||
UNIT ttp_unit[] = {
|
||||
{ UDATA (&ttpi_svc, 0, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&ttpi_svc, 0, 0), 0 },
|
||||
{ UDATA (&ttpo_svc, 0, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
|
@ -83,7 +84,7 @@ REG ttp_reg[] = {
|
|||
{ HRDATA (CMD, ttp_cmd, 16) },
|
||||
{ HRDATA (KBUF, ttp_unit[TTI].buf, 8) },
|
||||
{ DRDATA (KPOS, ttp_unit[TTI].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (KTIME, ttp_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (KTIME, ttp_unit[TTI].wait, 24), REG_NZ + PV_LEFT + REG_HRO },
|
||||
{ FLDATA (KIREQ, int_req[l_TTP], i_TTP) },
|
||||
{ FLDATA (KIENB, int_enb[l_TTP], i_TTP) },
|
||||
{ FLDATA (KARM, ttp_karm, 0) },
|
||||
|
@ -175,7 +176,7 @@ t_stat ttpi_svc (UNIT *uptr)
|
|||
{
|
||||
int32 c, out;
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
sim_activate (uptr, KBD_WAIT (uptr->wait, lfc_poll)); /* continue poll */
|
||||
ttp_sta = ttp_sta & ~STA_FR; /* clear break */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
ttp_sta = ttp_sta & ~STA_PF; /* clear parity err */
|
||||
|
@ -227,7 +228,7 @@ return SCPE_OK;
|
|||
t_stat ttp_reset (DEVICE *dptr)
|
||||
{
|
||||
if (dptr->flags & DEV_DIS) sim_cancel (&ttp_unit[TTI]);
|
||||
else sim_activate (&ttp_unit[TTI], ttp_unit[TTI].wait);
|
||||
else sim_activate_abs (&ttp_unit[TTI], KBD_WAIT (ttp_unit[TTI].wait, lfc_poll));
|
||||
sim_cancel (&ttp_unit[TTO]);
|
||||
CLR_INT (v_TTP); /* clear int */
|
||||
CLR_ENB (v_TTP);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id_uvc.c: Interdata universal clock
|
||||
|
||||
Copyright (c) 2001-2005, Robert M. Supnik
|
||||
Copyright (c) 2001-2006, 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"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
pic precision incremental clock
|
||||
lfc line frequency clock
|
||||
|
||||
18-Oct-06 RMS Changed LFC to be free running, export tmr_poll
|
||||
23-Jul-05 RMS Fixed {} error in OC
|
||||
01-Mar-03 RMS Added SET/SHOW LFC FREQ support
|
||||
Changed precision clock algorithm for V7 UNIX
|
||||
|
@ -75,6 +76,7 @@ void pic_sched (t_bool strt);
|
|||
uint32 pic_rd_cic (void);
|
||||
|
||||
int32 lfc_tps = 120; /* ticks per */
|
||||
int32 lfc_poll = 8000;
|
||||
uint32 lfc_arm = 0; /* int arm */
|
||||
|
||||
DEVICE lfc_dev;
|
||||
|
@ -314,8 +316,6 @@ return SCPE_OK;
|
|||
|
||||
uint32 lfc (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
|
||||
case IO_ADR: /* select */
|
||||
|
@ -323,10 +323,6 @@ switch (op) { /* case IO op */
|
|||
|
||||
case IO_OC: /* command */
|
||||
lfc_arm = int_chg (v_LFC, dat, lfc_arm); /* upd int ctrl */
|
||||
if (lfc_arm && !sim_is_active (&lfc_unit)) { /* starting? */
|
||||
t = sim_rtcn_init (lfc_unit.wait, TMR_LFC);
|
||||
sim_activate (&lfc_unit, t); /* init clock */
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -336,13 +332,10 @@ return 0;
|
|||
|
||||
t_stat lfc_svc (UNIT *uptr)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
lfc_poll = sim_rtcn_calb (lfc_tps, TMR_LFC); /* calibrate */
|
||||
sim_activate (uptr, lfc_poll); /* reactivate */
|
||||
if (lfc_arm) { /* armed? */
|
||||
SET_INT (v_LFC); /* req intr */
|
||||
if (pic_unit.flags & UNIT_DIAG) t = uptr->wait; /* diag? fixed delay */
|
||||
else t = sim_rtcn_calb (lfc_tps, TMR_LFC); /* else calibrate */
|
||||
sim_activate (uptr, t); /* reactivate */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -351,7 +344,8 @@ return SCPE_OK;
|
|||
|
||||
t_stat lfc_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_cancel (&lfc_unit); /* cancel unit */
|
||||
lfc_poll = sim_rtcn_init (lfc_unit.wait, TMR_LFC);
|
||||
sim_activate_abs (&lfc_unit, lfc_poll); /* init clock */
|
||||
CLR_INT (v_LFC); /* clear int */
|
||||
CLR_ENB (v_LFC); /* disable int */
|
||||
lfc_arm = 0; /* disarm int */
|
||||
|
|
|
@ -59,7 +59,8 @@
|
|||
#define DSK_NUMSC 8 /* sectors/track */
|
||||
#define DSK_NUMTR 128 /* tracks/disk */
|
||||
#define DSK_DKSIZE (DSK_NUMTR*DSK_NUMSC*DSK_NUMWD) /* words/disk */
|
||||
#define DSK_AMASK ((DSK_NUMDK*DSK_NUMTR*DSK_NUMSC) - 1) /* address mask */
|
||||
#define DSK_AMASK ((DSK_NUMDK*DSK_NUMTR*DSK_NUMSC) - 1)
|
||||
/* address mask */
|
||||
#define DSK_NUMDK 8 /* disks/controller */
|
||||
#define GET_DISK(x) (((x) / (DSK_NUMSC * DSK_NUMTR)) & (DSK_NUMDK - 1))
|
||||
|
||||
|
|
125
PDP1/pdp1_clk.c
Normal file
125
PDP1/pdp1_clk.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/* pdp1_clk.c: PDP-1D clock simulator
|
||||
|
||||
Copyright (c) 2006, 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
|
||||
bused in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
clk PDP-1D clock
|
||||
|
||||
Note that the clock is run at 1/8 of real speed (125Hz instead of 1Khz), to
|
||||
provide for eventual implementation of idling.
|
||||
*/
|
||||
|
||||
#include "pdp1_defs.h"
|
||||
|
||||
#define CLK_HWRE_TPS 1000 /* hardware freq */
|
||||
#define CLK_TPS 125 /* sim freq */
|
||||
#define CLK_CNTS (CLK_HWRE_TPS / CLK_TPS) /* counts per tick */
|
||||
#define CLK_C1MIN (1000 * 60) /* counts per min */
|
||||
#define CLK_C32MS 32 /* counts per 32ms */
|
||||
|
||||
int32 clk32ms_sbs = 0; /* 32ms SBS level */
|
||||
int32 clk1min_sbs = 0; /* 1min SBS level */
|
||||
int32 clk_cntr = 0;
|
||||
int32 tmxr_poll = 5000;
|
||||
|
||||
extern int32 stop_inst;
|
||||
|
||||
t_stat clk_svc (UNIT *uptr);
|
||||
t_stat clk_reset (DEVICE *dptr);
|
||||
|
||||
/* CLK data structures
|
||||
|
||||
clk_dev CLK device descriptor
|
||||
clk_unit CLK unit
|
||||
clk_reg CLK register list
|
||||
*/
|
||||
|
||||
UNIT clk_unit = {
|
||||
UDATA (&clk_svc, 0, 0), 5000
|
||||
};
|
||||
|
||||
REG clk_reg[] = {
|
||||
{ ORDATA (CNTR, clk_cntr, 16) },
|
||||
{ DRDATA (SBS32LVL, clk32ms_sbs, 4), REG_HRO },
|
||||
{ DRDATA (SBS1MLVL, clk1min_sbs, 4), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB clk_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SBS32MSLVL", "SBS32MSLVL",
|
||||
&dev_set_sbs, &dev_show_sbs, (void *) &clk32ms_sbs },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SBS1MINLVL", "SBS1MINLVL",
|
||||
&dev_set_sbs, &dev_show_sbs, (void *) &clk1min_sbs },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE clk_dev = {
|
||||
"CLK", &clk_unit, clk_reg, clk_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &clk_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, DEV_DISABLE | DEV_DIS
|
||||
};
|
||||
|
||||
/* Clock IOT routine */
|
||||
|
||||
int32 clk (int32 inst, int32 dev, int32 dat)
|
||||
{
|
||||
int32 used, incr;
|
||||
|
||||
if (clk_dev.flags & DEV_DIS) /* disabled? */
|
||||
return (stop_inst << IOT_V_REASON) | dat; /* illegal inst */
|
||||
used = tmxr_poll - (sim_is_active (&clk_unit) - 1);
|
||||
incr = (used * CLK_CNTS) / tmxr_poll;
|
||||
return clk_cntr + incr;
|
||||
}
|
||||
|
||||
/* Unit service, generate appropriate interrupts */
|
||||
|
||||
t_stat clk_svc (UNIT *uptr)
|
||||
{
|
||||
if (clk_dev.flags & DEV_DIS) return SCPE_OK; /* disabled? */
|
||||
tmxr_poll = sim_rtcn_calb (CLK_TPS, TMR_CLK); /* calibrate clock */
|
||||
sim_activate (&clk_unit, tmxr_poll); /* reactivate unit */
|
||||
clk_cntr = clk_cntr + CLK_CNTS; /* incr counter */
|
||||
if ((clk_cntr % CLK_C32MS) == 0) /* 32ms interval? */
|
||||
dev_req_int (clk32ms_sbs); /* req intr */
|
||||
if (clk_cntr >= CLK_C1MIN) { /* 1min interval? */
|
||||
dev_req_int (clk1min_sbs); /* req intr */
|
||||
clk_cntr = 0; /* reset counter */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat clk_reset (DEVICE *dptr)
|
||||
{
|
||||
if (clk_dev.flags & DEV_DIS) sim_cancel (&clk_unit); /* disabled? */
|
||||
else {
|
||||
tmxr_poll = sim_rtcn_init (clk_unit.wait, TMR_CLK);
|
||||
sim_activate_abs (&clk_unit, tmxr_poll); /* activate unit */
|
||||
}
|
||||
clk_cntr = 0; /* clear counter */
|
||||
return SCPE_OK;
|
||||
}
|
936
PDP1/pdp1_cpu.c
936
PDP1/pdp1_cpu.c
File diff suppressed because it is too large
Load diff
431
PDP1/pdp1_dcs.c
Normal file
431
PDP1/pdp1_dcs.c
Normal file
|
@ -0,0 +1,431 @@
|
|||
/* pdp1_dcs.c: PDP-1D terminal multiplexor simulator
|
||||
|
||||
Copyright (c) 2006, 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.
|
||||
|
||||
dcs Type 630 data communications subsystem
|
||||
|
||||
This module implements up to 32 individual serial interfaces.
|
||||
*/
|
||||
|
||||
#include "pdp1_defs.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#define DCS_LINES 32 /* lines */
|
||||
#define DCS_LINE_MASK (DCS_LINES - 1)
|
||||
#define DCSL_WAIT 1000 /* output wait */
|
||||
#define DCS_NUMLIN dcs_desc.lines
|
||||
|
||||
int32 dcs_sbs = 0; /* SBS level */
|
||||
uint32 dcs_send = 0; /* line for send */
|
||||
uint32 dcs_scan = 0; /* line for scanner */
|
||||
uint8 dcs_flg[DCS_LINES]; /* line flags */
|
||||
uint8 dcs_buf[DCS_LINES]; /* line bufffers */
|
||||
|
||||
extern int32 iosta, stop_inst;
|
||||
extern int32 tmxr_poll;
|
||||
|
||||
TMLN dcs_ldsc[DCS_LINES] = { 0 }; /* line descriptors */
|
||||
TMXR dcs_desc = { DCS_LINES, 0, 0, dcs_ldsc }; /* mux descriptor */
|
||||
|
||||
t_stat dcsi_svc (UNIT *uptr);
|
||||
t_stat dcso_svc (UNIT *uptr);
|
||||
t_stat dcs_reset (DEVICE *dptr);
|
||||
t_stat dcs_attach (UNIT *uptr, char *cptr);
|
||||
t_stat dcs_detach (UNIT *uptr);
|
||||
t_stat dcs_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat dcs_show (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat dcs_vlines (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
void dcs_reset_ln (int32 ln);
|
||||
void dcs_scan_next (t_bool unlk);
|
||||
|
||||
/* DCS data structures
|
||||
|
||||
dcs_dev DCS device descriptor
|
||||
dcs_unit DCS unit descriptor
|
||||
dcs_reg DCS register list
|
||||
dcs_mod DCS modifiers list
|
||||
*/
|
||||
|
||||
REG dcs_nlreg = { DRDATA (NLINES, DCS_NUMLIN, 6), PV_LEFT };
|
||||
|
||||
UNIT dcs_unit = { UDATA (&dcsi_svc, UNIT_ATTABLE, 0) };
|
||||
|
||||
REG dcs_reg[] = {
|
||||
{ BRDATA (BUF, dcs_buf, 8, 8, DCS_LINES) },
|
||||
{ BRDATA (FLAGS, dcs_flg, 8, 1, DCS_LINES) },
|
||||
{ FLDATA (SCNF, iosta, IOS_V_DCS) },
|
||||
{ ORDATA (SCAN, dcs_scan, 5) },
|
||||
{ ORDATA (SEND, dcs_send, 5) },
|
||||
{ DRDATA (SBSLVL, dcs_sbs, 4), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB dcs_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
|
||||
&dev_set_sbs, &dev_show_sbs, (void *) &dcs_sbs },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES",
|
||||
&dcs_vlines, NULL, &dcs_nlreg },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &dcs_desc },
|
||||
{ UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &dcs_summ },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &dcs_show, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &dcs_show, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE dcs_dev = {
|
||||
"DCS", &dcs_unit, dcs_reg, dcs_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
&tmxr_ex, &tmxr_dep, &dcs_reset,
|
||||
NULL, &dcs_attach, &dcs_detach,
|
||||
NULL, DEV_NET | DEV_DISABLE | DEV_DIS
|
||||
};
|
||||
|
||||
/* DCSL data structures
|
||||
|
||||
dcsl_dev DCSL device descriptor
|
||||
dcsl_unit DCSL unit descriptor
|
||||
dcsl_reg DCSL register list
|
||||
dcsl_mod DCSL modifiers list
|
||||
*/
|
||||
|
||||
UNIT dcsl_unit[] = {
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT },
|
||||
{ UDATA (&dcso_svc, TT_MODE_UC, 0), DCSL_WAIT }
|
||||
};
|
||||
|
||||
MTAB dcsl_mod[] = {
|
||||
{ TT_MODE, TT_MODE_UC, "UC", "UC", NULL },
|
||||
{ TT_MODE, TT_MODE_7B, "7b", "7B", NULL },
|
||||
{ TT_MODE, TT_MODE_8B, "8b", "8B", NULL },
|
||||
{ TT_MODE, TT_MODE_7P, "7p", "7P", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &dcs_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
|
||||
&tmxr_set_log, &tmxr_show_log, &dcs_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
|
||||
&tmxr_set_nolog, NULL, &dcs_desc },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
REG dcsl_reg[] = {
|
||||
{ URDATA (TIME, dcsl_unit[0].wait, 10, 24, 0,
|
||||
DCS_LINES, REG_NZ + PV_LEFT) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE dcsl_dev = {
|
||||
"DCSL", dcsl_unit, dcsl_reg, dcsl_mod,
|
||||
DCS_LINES, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &dcs_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, DEV_DIS
|
||||
};
|
||||
|
||||
/* DCS IOT routine */
|
||||
|
||||
int32 dcs (int32 inst, int32 dev, int32 dat)
|
||||
{
|
||||
int32 pls = (inst >> 6) & 077;
|
||||
|
||||
if (dcs_dev.flags & DEV_DIS) /* disabled? */
|
||||
return (stop_inst << IOT_V_REASON) | dat; /* illegal inst */
|
||||
if (pls & 020) dat = 0; /* pulse 20? clr IO */
|
||||
|
||||
switch (pls & 057) { /* case IR<6,8:11> */
|
||||
|
||||
case 000: /* RCH */
|
||||
dat |= dcs_buf[dcs_scan]; /* return line buf */
|
||||
dcs_flg[dcs_scan] = 0; /* clr line flag */
|
||||
break;
|
||||
|
||||
case 001: /* RRC */
|
||||
dat |= dcs_scan; /* return line num */
|
||||
break;
|
||||
|
||||
case 010: /* RCC */
|
||||
dat |= dcs_buf[dcs_scan]; /* return line buf */
|
||||
dcs_flg[dcs_scan] = 0; /* clr line flag */
|
||||
/* fall through */
|
||||
case 011: /* RSC */
|
||||
dcs_scan_next (TRUE); /* unlock scanner */
|
||||
break;
|
||||
|
||||
case 040: /* TCB */
|
||||
dcs_buf[dcs_send] = dat & 0377; /* load buffer */
|
||||
dcs_flg[dcs_send] = 0; /* clr line flag */
|
||||
sim_activate (&dcsl_unit[dcs_send], dcsl_unit[dcs_send].wait);
|
||||
break;
|
||||
|
||||
case 041: /* SSB */
|
||||
dcs_send = dat & DCS_LINE_MASK; /* load line num */
|
||||
break;
|
||||
|
||||
case 050: /* TCC */
|
||||
dcs_buf[dcs_scan] = dat & 0377; /* load buffer */
|
||||
dcs_flg[dcs_scan] = 0; /* clr line flag */
|
||||
sim_activate (&dcsl_unit[dcs_scan], dcsl_unit[dcs_scan].wait);
|
||||
dcs_scan_next (TRUE); /* unlock scanner */
|
||||
break;
|
||||
|
||||
default:
|
||||
return (stop_inst << IOT_V_REASON) | dat; /* illegal inst */
|
||||
} /* end case */
|
||||
|
||||
return dat;
|
||||
}
|
||||
|
||||
/* Unit service - receive side
|
||||
|
||||
Poll all active lines for input
|
||||
Poll for new connections
|
||||
*/
|
||||
|
||||
t_stat dcsi_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ln, c, out;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
if (dcs_dev.flags & DEV_DIS) return SCPE_OK;
|
||||
sim_activate (uptr, tmxr_poll); /* continue poll */
|
||||
ln = tmxr_poll_conn (&dcs_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? */
|
||||
dcs_ldsc[ln].rcve = 1; /* set rcv enable */
|
||||
}
|
||||
tmxr_poll_rx (&dcs_desc); /* poll for input */
|
||||
for (ln = 0; ln < DCS_NUMLIN; ln++) { /* loop thru lines */
|
||||
if (dcs_ldsc[ln].conn) { /* connected? */
|
||||
if (c = tmxr_getc_ln (&dcs_ldsc[ln])) { /* get char */
|
||||
if (c & SCPE_BREAK) c = 0; /* break? */
|
||||
else c = sim_tt_inpcvt (c, TT_GET_MODE (dcsl_unit[ln].flags)|TTUF_KSR);
|
||||
dcs_buf[ln] = c; /* save char */
|
||||
dcs_flg[ln] = 1; /* set line flag */
|
||||
dcs_scan_next (FALSE); /* kick scanner */
|
||||
out = sim_tt_outcvt (c & 0177, TT_GET_MODE (dcsl_unit[ln].flags));
|
||||
if (out >= 0) {
|
||||
tmxr_putc_ln (&dcs_ldsc[ln], out); /* echo char */
|
||||
tmxr_poll_tx (&dcs_desc); /* poll xmt */
|
||||
}
|
||||
}
|
||||
}
|
||||
else dcs_ldsc[ln].rcve = 0; /* disconnected */
|
||||
} /* end for */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Unit service - transmit side */
|
||||
|
||||
t_stat dcso_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
uint32 ln = uptr - dcsl_unit; /* line # */
|
||||
|
||||
if (dcs_dev.flags & DEV_DIS) return SCPE_OK;
|
||||
if (dcs_ldsc[ln].conn) { /* connected? */
|
||||
if (dcs_ldsc[ln].xmte) { /* xmt enabled? */
|
||||
c = sim_tt_outcvt (dcs_buf[ln] & 0177, TT_GET_MODE (uptr->flags));
|
||||
if (c >= 0) tmxr_putc_ln (&dcs_ldsc[ln], c); /* output char */
|
||||
tmxr_poll_tx (&dcs_desc); /* poll xmt */
|
||||
}
|
||||
else { /* buf full */
|
||||
tmxr_poll_tx (&dcs_desc); /* poll xmt */
|
||||
sim_activate (uptr, uptr->wait); /* reschedule */
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
dcs_flg[ln] = 1; /* set line flag */
|
||||
dcs_scan_next (FALSE); /* kick scanner */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Kick scanner */
|
||||
|
||||
void dcs_scan_next (t_bool unlk)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
if (unlk) iosta &= ~IOS_DCS; /* unlock? */
|
||||
else if (iosta & IOS_DCS) return; /* no, locked? */
|
||||
for (i = 0; i < DCS_LINES; i++) { /* scan flags */
|
||||
dcs_scan = (dcs_scan + 1) & DCS_LINE_MASK; /* next flag */
|
||||
if (dcs_flg[dcs_scan] != 0) { /* flag set? */
|
||||
iosta |= IOS_DCS; /* lock scanner */
|
||||
dev_req_int (dcs_sbs); /* request intr */
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat dcs_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
if (dcs_dev.flags & DEV_DIS) /* master disabled? */
|
||||
dcsl_dev.flags = dcsl_dev.flags | DEV_DIS; /* disable lines */
|
||||
else dcsl_dev.flags = dcsl_dev.flags & ~DEV_DIS;
|
||||
if (dcs_unit.flags & UNIT_ATT) /* master att? */
|
||||
sim_activate_abs (&dcs_unit, tmxr_poll); /* activate */
|
||||
else sim_cancel (&dcs_unit); /* else stop */
|
||||
for (i = 0; i < DCS_LINES; i++) dcs_reset_ln (i); /* reset lines */
|
||||
dcs_send = 0;
|
||||
dcs_scan = 0;
|
||||
iosta &= ~IOS_DCS; /* clr intr req */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach master unit */
|
||||
|
||||
t_stat dcs_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_attach (&dcs_desc, uptr, cptr); /* attach */
|
||||
if (r != SCPE_OK) return r; /* error */
|
||||
sim_activate_abs (uptr, tmxr_poll); /* start poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Detach master unit */
|
||||
|
||||
t_stat dcs_detach (UNIT *uptr)
|
||||
{
|
||||
int32 i;
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_detach (&dcs_desc, uptr); /* detach */
|
||||
for (i = 0; i < DCS_LINES; i++) dcs_ldsc[i].rcve = 0; /* disable rcv */
|
||||
sim_cancel (uptr); /* stop poll */
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Show summary processor */
|
||||
|
||||
t_stat dcs_summ (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i, t;
|
||||
|
||||
for (i = t = 0; i < DCS_LINES; i++) t = t + (dcs_ldsc[i].conn != 0);
|
||||
if (t == 1) fprintf (st, "1 connection");
|
||||
else fprintf (st, "%d connections", t);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* SHOW CONN/STAT processor */
|
||||
|
||||
t_stat dcs_show (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i, t;
|
||||
|
||||
for (i = t = 0; i < DCS_LINES; i++) t = t + (dcs_ldsc[i].conn != 0);
|
||||
if (t) {
|
||||
for (i = 0; i < DCS_LINES; i++) {
|
||||
if (dcs_ldsc[i].conn) {
|
||||
if (val) tmxr_fconns (st, &dcs_ldsc[i], i);
|
||||
else tmxr_fstats (st, &dcs_ldsc[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else fprintf (st, "all disconnected\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Change number of lines */
|
||||
|
||||
t_stat dcs_vlines (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 newln, i, t;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
newln = get_uint (cptr, 10, DCS_LINES, &r);
|
||||
if ((r != SCPE_OK) || (newln == DCS_NUMLIN)) return r;
|
||||
if (newln == 0) return SCPE_ARG;
|
||||
if (newln < DCS_LINES) {
|
||||
for (i = newln, t = 0; i < DCS_NUMLIN; i++) t = t | dcs_ldsc[i].conn;
|
||||
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
|
||||
return SCPE_OK;
|
||||
for (i = newln; i < DCS_NUMLIN; i++) {
|
||||
if (dcs_ldsc[i].conn) {
|
||||
tmxr_linemsg (&dcs_ldsc[i], "\r\nOperator disconnected line\r\n");
|
||||
tmxr_reset_ln (&dcs_ldsc[i]); /* reset line */
|
||||
}
|
||||
dcsl_unit[i].flags = dcsl_unit[i].flags | UNIT_DIS;
|
||||
dcs_reset_ln (i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = DCS_NUMLIN; i < newln; i++) {
|
||||
dcsl_unit[i].flags = dcsl_unit[i].flags & ~UNIT_DIS;
|
||||
dcs_reset_ln (i);
|
||||
}
|
||||
}
|
||||
DCS_NUMLIN = newln;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset an individual line */
|
||||
|
||||
void dcs_reset_ln (int32 ln)
|
||||
{
|
||||
sim_cancel (&dcsl_unit[ln]);
|
||||
dcs_buf[ln] = 0;
|
||||
dcs_flg[ln] = 0;
|
||||
return;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp1_defs.h: 18b PDP simulator definitions
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2006, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
21-Dec-06 RMS Added 16-channel sequence break support
|
||||
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
|
||||
|
@ -61,6 +62,7 @@
|
|||
#define STOP_IND 5 /* nested indirects */
|
||||
#define STOP_WAIT 6 /* IO wait hang */
|
||||
#define STOP_DTOFF 7 /* DECtape off reel */
|
||||
#define ERR_RMV 10 /* restrict mode viol */
|
||||
|
||||
/* Memory */
|
||||
|
||||
|
@ -72,6 +74,7 @@
|
|||
|
||||
/* Architectural constants */
|
||||
|
||||
#define SIGN 0400000 /* sign */
|
||||
#define DMASK 0777777 /* data mask */
|
||||
#define DAMASK 0007777 /* direct addr */
|
||||
#define EPCMASK (AMASK & ~DAMASK) /* extended addr */
|
||||
|
@ -83,6 +86,37 @@
|
|||
#define OP_JMP 0600000 /* JMP */
|
||||
#define GEN_CPLS(x) (((x) ^ ((x) << 1)) & IO_WAIT) /* completion pulse? */
|
||||
|
||||
/* Program flags/sense switches */
|
||||
|
||||
#define PF_V_L 7
|
||||
#define PF_V_RNG 6
|
||||
#define PF_L (1u << PF_V_L)
|
||||
#define PF_RNG (1u << PF_V_RNG)
|
||||
#define PF_SS_1 0040
|
||||
#define PF_SS_2 0020
|
||||
#define PF_SS_3 0010
|
||||
#define PF_SS_4 0004
|
||||
#define PF_SS_5 0002
|
||||
#define PF_SS_6 0001
|
||||
#define PF_VR_ALL 0377
|
||||
#define PF_SS_ALL 0077
|
||||
|
||||
/* Restict mode */
|
||||
|
||||
#define RTB_IOT 0400000
|
||||
#define RTB_ILL 0200000
|
||||
#define RTB_HLT 0100000
|
||||
#define RTB_DBK 0040000
|
||||
#define RTB_CHR 0020000
|
||||
#define RTB_MB_MASK 0017777
|
||||
|
||||
#define RM45_V_BNK 14
|
||||
#define RM45_M_BNK 003
|
||||
#define RM48_V_BNK 12
|
||||
#define RM48_M_BNK 017
|
||||
|
||||
#define RN45_SIZE 4
|
||||
|
||||
/* IOT subroutine return codes */
|
||||
|
||||
#define IOT_V_SKP 18 /* skip */
|
||||
|
@ -100,8 +134,9 @@
|
|||
#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_PNT 3 /* print done */
|
||||
#define IOS_V_SPC 2 /* space done */
|
||||
#define IOS_V_DCS 1 /* data comm sys */
|
||||
#define IOS_V_DRP 0 /* parallel drum busy */
|
||||
|
||||
#define IOS_LPN (1 << IOS_V_LPN)
|
||||
|
@ -113,6 +148,7 @@
|
|||
#define IOS_SQB (1 << IOS_V_SQB)
|
||||
#define IOS_PNT (1 << IOS_V_PNT)
|
||||
#define IOS_SPC (1 << IOS_V_SPC)
|
||||
#define IOS_DCS (1 << IOS_V_DCS)
|
||||
#define IOS_DRP (1 << IOS_V_DRP)
|
||||
|
||||
/* Completion pulses */
|
||||
|
@ -128,7 +164,7 @@
|
|||
#define CPLS_LPT (1 << CPLS_V_LPT)
|
||||
#define CPLS_DPY (1 << CPLS_V_DPY)
|
||||
|
||||
/* Sequence break flags */
|
||||
/* One channel sequence break */
|
||||
|
||||
#define SB_V_IP 0 /* in progress */
|
||||
#define SB_V_RQ 1 /* request */
|
||||
|
@ -138,4 +174,21 @@
|
|||
#define SB_RQ (1 << SB_V_RQ)
|
||||
#define SB_ON (1 << SB_V_ON)
|
||||
|
||||
/* 16 channel sequence break */
|
||||
|
||||
#define SBS_LVLS 16 /* num levels */
|
||||
#define SBS_LVL_MASK (SBS_LVLS - 1)
|
||||
#define SBS_LVL_RMV 14 /* restrict level */
|
||||
#define SBS_MASK(x) (1u << (SBS_LVLS - 1 - (x))) /* level to mask */
|
||||
|
||||
/* Timers */
|
||||
|
||||
#define TMR_CLK 0
|
||||
|
||||
/* Device routines */
|
||||
|
||||
t_stat dev_req_int (int32 lvl);
|
||||
t_stat dev_set_sbs (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat dev_show_sbs (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp1_drm.c: PDP-1 drum simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M Supnik
|
||||
Copyright (c) 1993-2006, 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"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
drp Type 23 parallel drum
|
||||
drm Type 24 serial drum
|
||||
|
||||
21-Dec-06 RMS Added 16-chan SBS support
|
||||
08-Dec-03 RMS Added parallel drum support
|
||||
Fixed bug in DBL/DCN decoding
|
||||
26-Oct-03 RMS Cleaned up buffer copy code
|
||||
|
@ -71,7 +72,7 @@
|
|||
((double) DRM_NUMWDT)))
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 iosta, sbs;
|
||||
extern int32 iosta;
|
||||
extern int32 stop_inst;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
|
@ -82,6 +83,7 @@ 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_sbs = 0; /* SBS level */
|
||||
int32 drm_stopioe = 1; /* stop on error */
|
||||
|
||||
/* Parallel drum variables */
|
||||
|
@ -123,12 +125,19 @@ REG drm_reg[] = {
|
|||
{ FLDATA (ERR, drm_err, 0) },
|
||||
{ ORDATA (WLK, drm_wlk, 32) },
|
||||
{ DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (SBSLVL, drm_sbs, 4), REG_HRO },
|
||||
{ FLDATA (STOP_IOE, drm_stopioe, 0) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB drm_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "APILVL", "APILVL",
|
||||
&dev_set_sbs, &dev_show_sbs, (void *) &drm_sbs },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE drm_dev = {
|
||||
"DRM", &drm_unit, drm_reg, NULL,
|
||||
"DRM", &drm_unit, drm_reg, drm_mod,
|
||||
1, 8, 20, 1, 8, 18,
|
||||
NULL, NULL, &drm_reset,
|
||||
NULL, NULL, NULL,
|
||||
|
@ -159,6 +168,7 @@ REG drp_reg[] = {
|
|||
{ FLDATA (ERR, drp_err, 0) },
|
||||
{ DRDATA (TIME, drp_time, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, drp_stopioe, 0) },
|
||||
{ DRDATA (SBSLVL, drm_sbs, 4), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -266,7 +276,7 @@ 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 */
|
||||
dev_req_int (drm_sbs); /* req intr */
|
||||
return IORETURN (drm_stopioe, SCPE_UNATT);
|
||||
}
|
||||
|
||||
|
@ -287,7 +297,7 @@ for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
|
|||
}
|
||||
drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */
|
||||
iosta = iosta | IOS_DRM; /* set done */
|
||||
sbs = sbs | SB_RQ; /* req intr */
|
||||
dev_req_int (drm_sbs); /* req intr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -314,7 +324,7 @@ 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 */
|
||||
if (uptr->FUNC) dev_req_int (drm_sbs); /* req intr */
|
||||
return IORETURN (drp_stopioe, SCPE_UNATT);
|
||||
}
|
||||
|
||||
|
@ -330,7 +340,7 @@ if (uptr->FUNC == DRP_RW) { /* read/write? */
|
|||
} /* end for */
|
||||
} /* end if */
|
||||
iosta = iosta & ~IOS_DRP; /* clear busy */
|
||||
if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */
|
||||
if (uptr->FUNC) dev_req_int (drm_sbs); /* req intr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
dt Type 550/555 DECtape
|
||||
|
||||
21-Dec-06 RMS Added 16-channel SBS support
|
||||
23-Jun-06 RMS Fixed conflict in ATTACH switches
|
||||
Revised header format
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
|
@ -179,7 +180,7 @@
|
|||
#define DTA_RW 077
|
||||
#define DTA_GETUNIT(x) map_unit[(((x) >> DTA_V_UNIT) & DTA_M_UNIT)]
|
||||
#define DT_UPDINT if (dtsb & (DTB_DTF | DTB_BEF | DTB_ERF)) \
|
||||
sbs = sbs | SB_RQ;
|
||||
dev_req_int (dt_sbs);
|
||||
|
||||
#define DTA_GETMOT(x) (((x) >> DTA_V_MOT) & DTA_M_MOT)
|
||||
#define DTA_GETFNC(x) (((x) >> DTA_V_FNC) & DTA_M_FNC)
|
||||
|
@ -247,7 +248,6 @@
|
|||
#define ABS(x) (((x) < 0)? (-(x)): (x))
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 sbs;
|
||||
extern int32 stop_inst;
|
||||
extern UNIT cpu_unit;
|
||||
extern int32 sim_switches;
|
||||
|
@ -257,6 +257,7 @@ extern FILE *sim_deb;
|
|||
int32 dtsa = 0; /* status A */
|
||||
int32 dtsb = 0; /* status B */
|
||||
int32 dtdb = 0; /* data buffer */
|
||||
int32 dt_sbs = 0; /* SBS level */
|
||||
int32 dt_ltime = 12; /* interline time */
|
||||
int32 dt_dctime = 40000; /* decel time */
|
||||
int32 dt_substate = 0;
|
||||
|
@ -326,10 +327,13 @@ REG dt_reg[] = {
|
|||
{ URDATA (LASTT, dt_unit[0].LASTT, 10, 32, 0,
|
||||
DT_NUMDR, REG_HRO) },
|
||||
{ FLDATA (STOP_OFFR, dt_stopoffr, 0) },
|
||||
{ DRDATA (SBSLVL, dt_sbs, 4), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB dt_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
|
||||
&dev_set_sbs, &dev_show_sbs, (void *) &dt_sbs },
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ UNIT_8FMT + UNIT_11FMT, 0, "18b", NULL, NULL },
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp1_lp.c: PDP-1 line printer simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2006, 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"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
lpt Type 62 line printer for the PDP-1
|
||||
|
||||
21-Dec-06 RMS Added 16-channel SBS support
|
||||
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
|
||||
|
@ -43,6 +44,7 @@ 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_sbs = 0; /* SBS level */
|
||||
char lpt_buf[LPT_BSIZE + 1] = { 0 };
|
||||
static const unsigned char lpt_trans[64] = {
|
||||
' ','1','2','3','4','5','6','7','8','9','\'','~','#','V','^','<',
|
||||
|
@ -51,7 +53,7 @@ static const unsigned char lpt_trans[64] = {
|
|||
'_','A','B','C','D','E','F','G','H','I','*','.','+',']','|','['
|
||||
};
|
||||
|
||||
extern int32 ios, cpls, sbs, iosta;
|
||||
extern int32 ios, cpls, iosta;
|
||||
extern int32 stop_inst;
|
||||
|
||||
t_stat lpt_svc (UNIT *uptr);
|
||||
|
@ -80,11 +82,18 @@ REG lpt_reg[] = {
|
|||
{ DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
|
||||
{ BRDATA (LBUF, lpt_buf, 8, 8, LPT_BSIZE) },
|
||||
{ DRDATA (SBSLVL, lpt_sbs, 4), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB lpt_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
|
||||
&dev_set_sbs, &dev_show_sbs, (void *) &lpt_sbs },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE lpt_dev = {
|
||||
"LPT", &lpt_unit, lpt_reg, NULL,
|
||||
"LPT", &lpt_unit, lpt_reg, lpt_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &lpt_reset,
|
||||
NULL, NULL, NULL,
|
||||
|
@ -151,7 +160,7 @@ if (cpls & CPLS_LPT) { /* completion pulse? */
|
|||
ios = 1; /* restart */
|
||||
cpls = cpls & ~CPLS_LPT; /* clr pulse pending */
|
||||
}
|
||||
sbs = sbs | SB_RQ; /* req seq break */
|
||||
dev_req_int (lpt_sbs); /* req interrupt */
|
||||
if (lpt_spc) { /* space? */
|
||||
iosta = iosta | IOS_SPC; /* set flag */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp1_stddev.c: PDP-1 standard devices
|
||||
|
||||
Copyright (c) 1993-2005, Robert M. Supnik
|
||||
Copyright (c) 1993-2006, 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"),
|
||||
|
@ -28,6 +28,7 @@
|
|||
tti keyboard
|
||||
tto teleprinter
|
||||
|
||||
21-Dec-06 RMS Added 16-channel sequence break support
|
||||
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;
|
||||
|
@ -58,8 +59,6 @@
|
|||
#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 */
|
||||
|
@ -70,12 +69,16 @@ 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_sbs = 0; /* SBS level */
|
||||
int32 ptp_stopioe = 0;
|
||||
int32 ptp_sbs = 0; /* SBS level */
|
||||
int32 tti_hold = 0; /* tti hold buf */
|
||||
int32 tti_sbs = 0; /* SBS level */
|
||||
int32 tty_buf = 0; /* tty buffer */
|
||||
int32 tty_uc = 0; /* tty uc/lc */
|
||||
int32 tto_sbs = 0;
|
||||
|
||||
extern int32 sbs, ios, ioh, cpls, iosta;
|
||||
extern int32 ios, ioh, cpls, iosta;
|
||||
extern int32 PF, IO, PC, TA;
|
||||
extern int32 M[];
|
||||
|
||||
|
@ -154,10 +157,13 @@ REG ptr_reg[] = {
|
|||
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
||||
{ DRDATA (LEADER, ptr_leader, 6), REG_HRO },
|
||||
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
||||
{ DRDATA (SBSLVL, ptr_sbs, 4), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ptr_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
|
||||
&dev_set_sbs, &dev_show_sbs, (void *) &ptr_sbs },
|
||||
{ UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL },
|
||||
{ UNIT_ASCII, 0, "FIODEC", "FIODEC", NULL },
|
||||
{ 0 }
|
||||
|
@ -189,46 +195,87 @@ REG ptp_reg[] = {
|
|||
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
|
||||
{ DRDATA (SBSLVL, ptp_sbs, 4), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ptp_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
|
||||
&dev_set_sbs, &dev_show_sbs, (void *) &ptp_sbs },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ptp_dev = {
|
||||
"PTP", &ptp_unit, ptp_reg, NULL,
|
||||
"PTP", &ptp_unit, ptp_reg, ptp_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptp_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, 0
|
||||
};
|
||||
|
||||
/* TTY data structures
|
||||
/* TTI data structures
|
||||
|
||||
tty_dev TTY device descriptor
|
||||
tty_unit TTY unit
|
||||
tty_reg TTY register list
|
||||
tti_dev TTI device descriptor
|
||||
tti_unit TTI unit
|
||||
tti_reg TTI register list
|
||||
*/
|
||||
|
||||
UNIT tty_unit[] = {
|
||||
{ UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT * 10 }
|
||||
};
|
||||
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
|
||||
|
||||
REG tty_reg[] = {
|
||||
REG tti_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 },
|
||||
{ FLDATA (DONE, iosta, IOS_V_TTI) },
|
||||
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (SBSLVL, tti_sbs, 4), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE tty_dev = {
|
||||
"TTY", tty_unit, tty_reg, NULL,
|
||||
2, 10, 31, 1, 8, 8,
|
||||
MTAB tti_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
|
||||
&dev_set_sbs, &dev_show_sbs, (void *) &tti_sbs },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE tti_dev = {
|
||||
"TTI", &tti_unit, tti_reg, tti_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tty_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, 0
|
||||
};
|
||||
|
||||
/* TTO data structures
|
||||
|
||||
tto_dev TTO device descriptor
|
||||
tto_unit TTO unit
|
||||
tto_reg TTO register list
|
||||
*/
|
||||
|
||||
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT * 10 };
|
||||
|
||||
REG tto_reg[] = {
|
||||
{ ORDATA (BUF, tty_buf, 6) },
|
||||
{ FLDATA (UC, tty_uc, UC_V) },
|
||||
{ FLDATA (RPLS, cpls, CPLS_V_TTO) },
|
||||
{ FLDATA (DONE, iosta, IOS_V_TTO) },
|
||||
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
|
||||
{ DRDATA (SBSLVL, tto_sbs, 4), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB tto_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
|
||||
&dev_set_sbs, &dev_show_sbs, (void *) &tto_sbs },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE tto_dev = {
|
||||
"TTO", &tto_unit, tto_reg, tto_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tty_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, 0
|
||||
|
@ -309,7 +356,7 @@ if (ptr_state == 0) { /* done? */
|
|||
}
|
||||
else { /* no, interrupt */
|
||||
iosta = iosta | IOS_PTR; /* set flag */
|
||||
sbs = sbs | SB_RQ; /* req seq break */
|
||||
dev_req_int (ptr_sbs); /* req interrupt */
|
||||
}
|
||||
}
|
||||
else sim_activate (uptr, uptr->wait); /* get next char */
|
||||
|
@ -443,7 +490,7 @@ if (cpls & CPLS_PTP) { /* completion pulse? */
|
|||
cpls = cpls & ~CPLS_PTP;
|
||||
}
|
||||
iosta = iosta | IOS_PTP; /* set flag */
|
||||
sbs = sbs | SB_RQ; /* req seq break */
|
||||
dev_req_int (ptp_sbs); /* req interrupt */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
||||
return IORETURN (ptp_stopioe, SCPE_UNATT);
|
||||
if (putc (uptr->buf, uptr->fileref) == EOF) { /* I/O error? */
|
||||
|
@ -485,7 +532,7 @@ if (GEN_CPLS (inst)) { /* comp pulse? */
|
|||
cpls = cpls | CPLS_TTO;
|
||||
}
|
||||
else cpls = cpls & ~CPLS_TTO;
|
||||
sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); /* activate unit */
|
||||
sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
|
||||
return dat;
|
||||
}
|
||||
|
||||
|
@ -518,8 +565,8 @@ else {
|
|||
}
|
||||
}
|
||||
iosta = iosta | IOS_TTI; /* set flag */
|
||||
sbs = sbs | SB_RQ; /* req seq break */
|
||||
PF = PF | 040; /* set prog flag 1 */
|
||||
dev_req_int (tti_sbs); /* req interrupt */
|
||||
PF = PF | PF_SS_1; /* set prog flag 1 */
|
||||
uptr->pos = uptr->pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -543,7 +590,7 @@ if (cpls & CPLS_TTO) { /* completion pulse? */
|
|||
cpls = cpls & ~CPLS_TTO;
|
||||
}
|
||||
iosta = iosta | IOS_TTO; /* set flag */
|
||||
sbs = sbs | SB_RQ; /* req seq break */
|
||||
dev_req_int (tto_sbs); /* req interrupt */
|
||||
uptr->pos = uptr->pos + 1;
|
||||
if (c == '\r') { /* cr? add lf */
|
||||
sim_putchar ('\n');
|
||||
|
@ -561,7 +608,7 @@ 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 */
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* activate keyboard */
|
||||
sim_cancel (&tto_unit); /* stop printer */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
118
PDP1/pdp1_sys.c
118
PDP1/pdp1_sys.c
|
@ -1,6 +1,6 @@
|
|||
/* pdp1_sys.c: PDP-1 simulator interface
|
||||
|
||||
Copyright (c) 1993-2004, Robert M. Supnik
|
||||
Copyright (c) 1993-2007, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,8 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
03-Jan-07 RMS Fixed bugs in block loader, char input
|
||||
21-Dec-06 RMS Added 16-channel sequence break support, PDP-1D support
|
||||
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
|
||||
|
@ -46,13 +48,16 @@
|
|||
#include <ctype.h>
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE clk_dev;
|
||||
extern DEVICE ptr_dev;
|
||||
extern DEVICE ptp_dev;
|
||||
extern DEVICE tty_dev;
|
||||
extern DEVICE tti_dev;
|
||||
extern DEVICE tto_dev;
|
||||
extern DEVICE lpt_dev;
|
||||
extern DEVICE dt_dev;
|
||||
extern DEVICE drm_dev;
|
||||
extern DEVICE drp_dev;
|
||||
extern DEVICE dcs_dev, dcsl_dev;
|
||||
extern DEVICE dpy_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
|
@ -80,13 +85,17 @@ int32 sim_emax = 1;
|
|||
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&clk_dev,
|
||||
&ptr_dev,
|
||||
&ptp_dev,
|
||||
&tty_dev,
|
||||
&tti_dev,
|
||||
&tto_dev,
|
||||
&lpt_dev,
|
||||
&dt_dev,
|
||||
&drm_dev,
|
||||
&drp_dev,
|
||||
&dcs_dev,
|
||||
&dcsl_dev,
|
||||
/* &dpy_dev, */
|
||||
NULL
|
||||
};
|
||||
|
@ -152,13 +161,13 @@ for (;;) {
|
|||
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 (csum > DMASK) csum = (csum + 1) & DMASK;
|
||||
count = (val & DAMASK) - start; /* 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;
|
||||
if (csum > DMASK) csum = (csum + 1) & DMASK;
|
||||
M[fld | start] = val;
|
||||
start = (start + 1) & DAMASK;
|
||||
}
|
||||
|
@ -196,7 +205,7 @@ return SCPE_OK;
|
|||
/* Symbol tables */
|
||||
|
||||
#define I_V_FL 18 /* inst class */
|
||||
#define I_M_FL 07 /* class mask */
|
||||
#define I_M_FL 017 /* class mask */
|
||||
#define I_V_NPN 0 /* no operand */
|
||||
#define I_V_IOT 1 /* IOT */
|
||||
#define I_V_LAW 2 /* LAW */
|
||||
|
@ -205,6 +214,7 @@ return SCPE_OK;
|
|||
#define I_V_OPR 5 /* OPR */
|
||||
#define I_V_SKP 6 /* skip */
|
||||
#define I_V_SHF 7 /* shift */
|
||||
#define I_V_SPC 8 /* special */
|
||||
#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 */
|
||||
|
@ -213,10 +223,12 @@ return SCPE_OK;
|
|||
#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_SPC (I_V_SPC << I_V_FL)
|
||||
|
||||
static const int32 masks[] = {
|
||||
0777777, 0763777, 0760000, 0760000,
|
||||
0770000, 0760017, 0760077, 0777000
|
||||
0777777, 0760077, 0760000, 0760000,
|
||||
0770000, 0760017, 0760077, 0777000,
|
||||
0760003
|
||||
};
|
||||
|
||||
static const char *opcode[] = {
|
||||
|
@ -224,22 +236,30 @@ static const char *opcode[] = {
|
|||
"LAC", "LIO", "DAC", "DAP",
|
||||
"DIP", "DIO", "DZM", "ADD",
|
||||
"SUB", "IDX", "ISP", "SAD",
|
||||
"SAS", "MUL", "DIV", "JMP", "JSP",
|
||||
"SAS", "MUL", "DIV", "JMP",
|
||||
"JSP", "LCH", "DCH", "TAD",
|
||||
|
||||
"CAL", "JDA", /* mem ref no ind */
|
||||
|
||||
"LAW",
|
||||
|
||||
"IOH", "RPA", "RPB", "RRB", /* I/O instructions */
|
||||
"PPA", "PPB", "TYO", "TYI",
|
||||
"DPY",
|
||||
"DSC", "ASC", "ISC", "CAC",
|
||||
"LSM", "ESM", "CBS",
|
||||
"LEM", "EEM", "CKS",
|
||||
"MSE", "MLC", "MRD", "MWR", "MRS",
|
||||
"DIA", "DBA", "DWC", "DRA", "DCL",
|
||||
"DRD", "DWR", "DBL", "DCN",
|
||||
"DTD", "DSE", "DSP",
|
||||
"LRG", "ERG", "LRM", "ERM",
|
||||
"RNM", "RSM", "RCK", "CTB",
|
||||
"RCH", "RCC", "TCC", "TCB",
|
||||
"RRC", "SSB", "RSC",
|
||||
|
||||
"SKP", "SKP I", "CLO",
|
||||
"SFT", "LAW", "OPR",
|
||||
"SKP", "SKP I", "CLO", /* base as NPNs */
|
||||
"SFT", "SPC", "OPR",
|
||||
|
||||
"RAL", "RIL", "RCL", /* shifts */
|
||||
"SAL", "SIL", "SCL",
|
||||
|
@ -268,12 +288,24 @@ static const char *opcode[] = {
|
|||
"STF1", "STF2", "STF3",
|
||||
"STF4", "STF5", "STF6", "STF7",
|
||||
|
||||
"SZA", "SPA", "SMA", /* encode only */
|
||||
"SZO", "SPI", "I",
|
||||
"FF1", "FF2", "FF3", /* specials */
|
||||
|
||||
"SZA", "SPA", "SMA", /* uprog skips */
|
||||
"SZO", "SPI", "SNI",
|
||||
"I", /* encode only */
|
||||
|
||||
"LIA", "LAI", "SWP", /* uprog opers */
|
||||
"LAP", "CLA", "HLT",
|
||||
"CMA", "LAT", "CLI",
|
||||
NULL, NULL, /* decode only */
|
||||
NULL
|
||||
"CMI",
|
||||
|
||||
"CML", "CLL", "SZL", /* uprog specials */
|
||||
"SCF", "SCI", "SCM",
|
||||
"IDA", "IDC", "IFI",
|
||||
"IIF",
|
||||
|
||||
NULL, NULL, NULL, /* decode only */
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const int32 opc_val[] = {
|
||||
|
@ -281,22 +313,30 @@ static const int32 opc_val[] = {
|
|||
0200000+I_MRF, 0220000+I_MRF, 0240000+I_MRF, 0260000+I_MRF,
|
||||
0300000+I_MRF, 0320000+I_MRF, 0340000+I_MRF, 0400000+I_MRF,
|
||||
0420000+I_MRF, 0440000+I_MRF, 0460000+I_MRF, 0500000+I_MRF,
|
||||
0520000+I_MRF, 0540000+I_MRF, 0560000+I_MRF, 0600000+I_MRF, 0620000+I_MRF,
|
||||
0520000+I_MRF, 0540000+I_MRF, 0560000+I_MRF, 0600000+I_MRF,
|
||||
0620000+I_MRF, 0120000+I_MRF, 0140000+I_MRF, 0360000+I_MRF,
|
||||
|
||||
0160000+I_MRI, 0170000+I_MRI,
|
||||
|
||||
0700000+I_LAW,
|
||||
|
||||
0730000+I_NPN, 0720001+I_IOT, 0720002+I_IOT, 0720030+I_IOT,
|
||||
0720005+I_IOT, 0720006+I_IOT, 0720003+I_IOT, 0720004+I_IOT,
|
||||
0720007+I_IOT,
|
||||
0720050+I_IOT, 0720051+I_IOT, 0720052+I_IOT, 0720053+I_NPN,
|
||||
0720054+I_NPN, 0720055+I_NPN, 0720056+I_NPN,
|
||||
0720074+I_NPN, 0724074+I_NPN, 0720033+I_NPN,
|
||||
0720301+I_NPN, 0720401+I_NPN, 0720501+I_NPN, 0720601+I_NPN, 0720701+I_NPN,
|
||||
0720061+I_NPN, 0722061+I_NPN, 0720062+I_NPN, 0722062+I_NPN, 0720063+I_NPN,
|
||||
0720161+I_NPN, 0721161+I_NPN, 0720162+I_NPN, 0721162+I_NPN,
|
||||
0720163+I_NPN, 0720164+I_NPN, 0721164+I_NPN,
|
||||
0720010+I_NPN, 0720011+I_NPN, 0720064+I_NPN, 0720065+I_NPN,
|
||||
0720066+I_IOT, 0720067+I_NPN, 0720032+I_NPN, 0720035+I_NPN,
|
||||
0720022+I_NPN, 0721022+I_NPN, 0725022+I_NPN, 0724022+I_NPN,
|
||||
0720122+I_NPN, 0724122+I_NPN, 0721122+I_NPN,
|
||||
|
||||
0640000+I_NPN, 0650000+I_NPN, 0651600+I_NPN,
|
||||
0660000+I_NPN, 0700000+I_LAW, 0760000+I_NPN,
|
||||
0660000+I_NPN, 0740000+I_NPN, 0760000+I_NPN,
|
||||
|
||||
0661000+I_SHF, 0662000+I_SHF, 0663000+I_SHF,
|
||||
0665000+I_SHF, 0666000+I_SHF, 0667000+I_SHF,
|
||||
|
@ -325,12 +365,23 @@ 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 */
|
||||
0641000+I_SKP, 0642000+I_SKP, 0010000+I_SKP,
|
||||
0740001+I_SPC, 0740002+I_SPC, 0740003+I_OPR,
|
||||
|
||||
0640100+I_SKP, 0640200+I_SKP, 0640400+I_SKP,
|
||||
0641000+I_SKP, 0642000+I_SKP, 0644000+I_SKP,
|
||||
0010000+I_SKP, /* encode only */
|
||||
|
||||
0760020+I_OPR, 0760040+I_OPR, 0760060+I_NPN,
|
||||
0760100+I_OPR, 0760200+I_OPR, 0760400+I_OPR,
|
||||
0761000+I_OPR, 0762000+I_OPR, 0764000+I_OPR,
|
||||
0770000+I_OPR,
|
||||
|
||||
0640000+I_SKP, 0760000+I_OPR, /* decode only */
|
||||
0740004+I_SPC, 0740010+I_SPC, 0740020+I_SPC,
|
||||
0740040+I_SPC, 0740100+I_SPC, 0740200+I_SPC,
|
||||
0740400+I_SPC, 0741000+I_SPC, 0742000+I_SPC,
|
||||
0744000+I_SPC,
|
||||
|
||||
0640000+I_SKP, 0740000+I_SPC, 0760000+I_OPR, /* decode only */
|
||||
-1
|
||||
};
|
||||
|
||||
|
@ -406,7 +457,7 @@ 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? */
|
||||
if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */
|
||||
|
||||
switch (j) { /* case on class */
|
||||
|
||||
|
@ -433,7 +484,7 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
|||
break;
|
||||
|
||||
case I_V_OPR: /* operates */
|
||||
sp = fprint_opr (of, inst & 007700, j, 0);
|
||||
sp = fprint_opr (of, inst & 017760, j, 0);
|
||||
if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);
|
||||
break;
|
||||
|
||||
|
@ -443,6 +494,12 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
|||
if (inst & IA) fprintf (of, sp? " I": "I");
|
||||
break;
|
||||
|
||||
case I_V_SPC: /* specials */
|
||||
sp = fprint_opr (of, inst & 007774, 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;
|
||||
|
@ -475,7 +532,7 @@ else if (*cptr == '-') {
|
|||
*sign = -1;
|
||||
cptr++;
|
||||
}
|
||||
return get_uint (cptr, 8, 0777777, status);
|
||||
return get_uint (cptr, 8, DMASK, status);
|
||||
}
|
||||
|
||||
/* Symbolic input
|
||||
|
@ -508,16 +565,16 @@ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
|||
}
|
||||
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);
|
||||
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 */
|
||||
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 */
|
||||
val[0] = opc_val[i] & DMASK; /* get value */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
|
||||
switch (j) { /* case on class */
|
||||
|
@ -545,13 +602,14 @@ switch (j) { /* case on class */
|
|||
val[0] = val[0] | sc_enc[d];
|
||||
break;
|
||||
|
||||
case I_V_NPN: case I_V_IOT: case I_V_OPR: case I_V_SKP:
|
||||
case I_V_NPN: case I_V_IOT:
|
||||
case I_V_OPR: case I_V_SKP: case I_V_SPC:
|
||||
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;
|
||||
k = opc_val[i] & DMASK;
|
||||
if ((k != IA) && (((k ^ val[0]) & 0760000) != 0))
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | k;
|
||||
|
|
|
@ -136,8 +136,6 @@
|
|||
#define PCQ_SIZE 64 /* must be 2**n */
|
||||
#define PCQ_MASK (PCQ_SIZE - 1)
|
||||
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
|
||||
#define UNIT_V_MSIZE (UNIT_V_T20V41 + 1) /* dummy mask */
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
|
||||
#define HIST_PC 0x40000000
|
||||
#define HIST_MIN 64
|
||||
|
@ -188,6 +186,7 @@ int32 stop_op0 = 0; /* stop on 0 */
|
|||
int32 rlog = 0; /* extend fixup log */
|
||||
int32 ind_max = 32; /* nested ind limit */
|
||||
int32 xct_max = 32; /* nested XCT limit */
|
||||
int32 t20_idlelock = 0; /* TOPS-20 idle lock */
|
||||
a10 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||
int32 pcq_p = 0; /* PC queue ptr */
|
||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||
|
@ -321,6 +320,7 @@ extern t_bool wrpcst (a10 ea, int32 prv);
|
|||
extern t_bool spm (a10 ea, int32 prv);
|
||||
extern t_bool lpmr (a10 ea, int32 prv);
|
||||
extern int32 pi_ub_vec (int32 lvl, int32 *uba);
|
||||
extern t_stat tim_set_mod (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* CPU data structures
|
||||
|
||||
|
@ -390,9 +390,14 @@ REG cpu_reg[] = {
|
|||
};
|
||||
|
||||
MTAB cpu_mod[] = {
|
||||
{ UNIT_ITS+UNIT_T20V41, 0, "Standard microcode", "STANDARD", NULL },
|
||||
{ UNIT_ITS+UNIT_T20V41, UNIT_T20V41, "TOPS-20 V4.1", "TOPS20V41", NULL },
|
||||
{ UNIT_ITS+UNIT_T20V41, UNIT_ITS, "ITS microcode", "ITS", NULL },
|
||||
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, 0, "TOPS-10", "TOPS-10", &tim_set_mod },
|
||||
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, 0, NULL , "TOPS10", &tim_set_mod },
|
||||
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_T20, "TOPS-20", "TOPS-20", &tim_set_mod },
|
||||
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_T20, NULL, "TOPS20", &tim_set_mod },
|
||||
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_ITS, "ITS", "ITS", &tim_set_mod },
|
||||
{ UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_KLAD, "diagnostic mode", "KLAD", &tim_set_mod },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,
|
||||
NULL, &show_iospace },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||
|
@ -593,11 +598,11 @@ static t_stat jrst_tab[16] = {
|
|||
#define T__N if ((AC(ac) & mb) != 0) INCPC
|
||||
#define T__A INCPC
|
||||
#define IOC if (TSTF (F_USR) && !TSTF (F_UIO)) goto MUUO;
|
||||
#define IO7(x,y) IOC; fptr = ((ITS)? x[ac]: y[ac]); \
|
||||
#define IO7(x,y) IOC; fptr = ((Q_ITS)? x[ac]: y[ac]); \
|
||||
if (fptr == NULL) goto MUUO; \
|
||||
if (fptr (ea, MM_OPND)) INCPC; break;
|
||||
#define IOA IOC; if (!ITS) ea = calc_ioea (inst, pflgs)
|
||||
#define IOAM IOC; ea = ((ITS)? ((a10) Read (ea, MM_OPND)): \
|
||||
#define IOA IOC; if (!Q_ITS) ea = calc_ioea (inst, pflgs)
|
||||
#define IOAM IOC; ea = ((Q_ITS)? ((a10) Read (ea, MM_OPND)): \
|
||||
calc_ioea (inst, pflgs))
|
||||
|
||||
/* Flag tests */
|
||||
|
@ -629,7 +634,8 @@ pager_pi = FALSE; /* not in pi sequence */
|
|||
rlog = 0; /* not in extend */
|
||||
pi_eval (); /* eval pi system */
|
||||
sim_rtc_init (tim_unit.wait); /* init calibration */
|
||||
if (!ITS) its_1pr = 0; /* ~ITS, clr 1-proc */
|
||||
if (!Q_ITS) its_1pr = 0; /* ~ITS, clr 1-proc */
|
||||
t20_idlelock = 0; /* clr T20 idle lock */
|
||||
|
||||
/* Abort handling
|
||||
|
||||
|
@ -656,7 +662,7 @@ else if (abortval == PAGE_FAIL) { /* page fail */
|
|||
if (rlog) xtcln (rlog); /* clean up extend */
|
||||
rlog = 0; /* clear log */
|
||||
if (pager_tc) flags = pager_flags; /* trap? get flags */
|
||||
if (T20) { /* TOPS-20 */
|
||||
if (T20PAG) { /* TOPS-20 paging? */
|
||||
WriteP (upta + UPT_T20_PFL, pager_word); /* write page fail wd */
|
||||
WriteP (upta + UPT_T20_OFL, XWD (flags, 0));
|
||||
WriteP (upta + UPT_T20_OPC, pager_PC);
|
||||
|
@ -664,7 +670,7 @@ else if (abortval == PAGE_FAIL) { /* page fail */
|
|||
}
|
||||
else {
|
||||
a10 ea; /* TOPS-10 or ITS */
|
||||
if (ITS) { /* ITS? */
|
||||
if (Q_ITS) { /* ITS? */
|
||||
ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3);
|
||||
if (its_1pr) flags = flags | F_1PR; /* store 1-proc */
|
||||
its_1pr = 0; /* clear 1-proc */
|
||||
|
@ -715,7 +721,7 @@ if (qintr) {
|
|||
else inst = ReadP (epta + EPT_PIIT + (2 * qintr));
|
||||
op = GET_OP (inst); /* get opcode */
|
||||
ac = GET_AC (inst); /* get ac */
|
||||
if (its_1pr && ITS) { /* 1-proc set? */
|
||||
if (its_1pr && Q_ITS) { /* 1-proc set? */
|
||||
flags = flags | F_1PR; /* store 1-proc */
|
||||
its_1pr = 0; /* clear 1-proc */
|
||||
}
|
||||
|
@ -846,12 +852,12 @@ case 0037: Write (040, UUOWORD, MM_CUR); /* store op, ac, ea */
|
|||
|
||||
/* case 0100: MUUO /* UJEN */
|
||||
/* case 0101: MUUO /* unassigned */
|
||||
case 0102: if (ITS && !TSTF (F_USR)) { /* GFAD (KL), XCTRI (ITS) */
|
||||
case 0102: if (Q_ITS && !TSTF (F_USR)) { /* GFAD (KL), XCTRI (ITS) */
|
||||
inst = Read (ea, MM_OPND);
|
||||
pflgs = pflgs | ac; goto XCT;
|
||||
}
|
||||
goto MUUO;
|
||||
case 0103: if (ITS && !TSTF (F_USR)) { /* GFSB (KL), XCTR (ITS) */
|
||||
case 0103: if (Q_ITS && !TSTF (F_USR)) { /* GFSB (KL), XCTR (ITS) */
|
||||
inst = Read (ea, MM_OPND);
|
||||
pflgs = pflgs | ac; goto XCT;
|
||||
}
|
||||
|
@ -977,7 +983,7 @@ case 0243: AC(P1) = jffo (AC(ac)); /* JFFO */
|
|||
case 0244: ashc (ac, ea); break; /* ASHC */
|
||||
case 0245: rotc (ac, ea); break; /* ROTC */
|
||||
case 0246: lshc (ac, ea); break; /* LSHC */
|
||||
case 0247: if (ITS) circ (ac, ea); break; /* (ITS) CIRC */
|
||||
case 0247: if (Q_ITS) circ (ac, ea); break; /* (ITS) CIRC */
|
||||
case 0250: RM; WRAC; AC(ac) = mb; break; /* EXCH */
|
||||
case 0251: blt (ac, ea, pflgs); break; /* BLT */
|
||||
case 0252: AOBAC; if (TGE (AC(ac))) JUMP (ea); break; /* AOBJP */
|
||||
|
@ -991,9 +997,10 @@ case 0255: if (flags & (ac << 14)) { /* JFCL */
|
|||
case 0256: if (xct_cnt++ >= xct_max) /* XCT */
|
||||
ABORT (STOP_XCT);
|
||||
inst = Read (ea, MM_OPND);
|
||||
if (ac && !TSTF (F_USR) && !ITS) pflgs = pflgs | ac;
|
||||
if (ac && !TSTF (F_USR) && !Q_ITS)
|
||||
pflgs = pflgs | ac;
|
||||
goto XCT;
|
||||
case 0257: if (ITS) goto MUUO; /* MAP */
|
||||
case 0257: if (Q_ITS) goto MUUO; /* MAP */
|
||||
AC(ac) = map (ea, MM_OPND); break;
|
||||
case 0260: WRP (FLPC); AOBAC; /* PUSHJ */
|
||||
SUBJ (ea); PUSHF; break;
|
||||
|
@ -1054,7 +1061,12 @@ case 0340: AOJ; break; /* AOJ */
|
|||
case 0341: AOJ; if (TL (AC(ac))) JUMP (ea); break; /* AOJL */
|
||||
case 0342: AOJ; if (TE (AC(ac))) JUMP (ea); break; /* AOJE */
|
||||
case 0343: AOJ; if (TLE (AC(ac))) JUMP (ea); break; /* AOJLE */
|
||||
case 0344: AOJ; JUMP(ea); break; /* AOJA */
|
||||
case 0344: AOJ; JUMP(ea); /* AOJA */
|
||||
if (Q_ITS && Q_IDLE && /* ITS idle? */
|
||||
TSTF (F_USR) && (pager_PC == 017) && /* user mode, loc 17? */
|
||||
(ac == 0) && (ea == 017)) /* AOJA 0,17? */
|
||||
sim_idle (0, FALSE);
|
||||
break;
|
||||
case 0345: AOJ; if (TGE (AC(ac))) JUMP (ea); break; /* AOJGE */
|
||||
case 0346: AOJ; if (TN (AC(ac))) JUMP (ea); break; /* AOJN */
|
||||
case 0347: AOJ; if (TG (AC(ac))) JUMP (ea); break; /* AOJG */
|
||||
|
@ -1073,7 +1085,22 @@ case 0363: SOJ; if (TLE (AC(ac))) JUMP (ea); break; /* SOJLE */
|
|||
case 0364: SOJ; JUMP(ea); break; /* SOJA */
|
||||
case 0365: SOJ; if (TGE (AC(ac))) JUMP (ea); break; /* SOJGE */
|
||||
case 0366: SOJ; if (TN (AC(ac))) JUMP (ea); break; /* SOJN */
|
||||
case 0367: SOJ; if (TG (AC(ac))) JUMP (ea); break; /* SOJG */
|
||||
case 0367: SOJ; if (TG (AC(ac))) JUMP (ea); /* SOJG */
|
||||
if ((ea == pager_PC) && Q_IDLE) { /* to self, idle enab? */
|
||||
extern int32 tmr_poll;
|
||||
if ((ac == 6) && (ea == 1) && /* SOJG 6,1? */
|
||||
TSTF (F_USR) && Q_T10) /* T10, user mode? */
|
||||
sim_idle (0, FALSE);
|
||||
else if (!t20_idlelock && /* interlock off? */
|
||||
(ac == 2) && (ea == 3) && /* SOJG 2,3? */
|
||||
!TSTF (F_USR) && Q_T20 && /* T20, mon mode? */
|
||||
(sim_interval > (tmr_poll >> 1))) { /* >= half clock? */
|
||||
t20_idlelock = 1; /* set interlock */
|
||||
if (sim_os_ms_sleep (1)) /* sleep 1ms */
|
||||
sim_interval = 0; /* if ok, sched event */
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0370: SOS; break; /* SOS */
|
||||
case 0371: SOS; if (TL (mb)) INCPC; break; /* SOSL */
|
||||
case 0372: SOS; if (TE (mb)) INCPC; break; /* SOSE */
|
||||
|
@ -1331,7 +1358,7 @@ case 0725: IOA; io725 (AC(ac), ea); break; /* BCIOB, IOWRBQ */
|
|||
default:
|
||||
MUUO:
|
||||
its_2pr = 0; /* clear trap */
|
||||
if (T20) { /* TOPS20? */
|
||||
if (T20PAG) { /* TOPS20 paging? */
|
||||
int32 tf = (op << (INST_V_OP - 18)) | (ac << (INST_V_AC - 18));
|
||||
WriteP (upta + UPT_MUUO, XWD ( /* store flags,,op+ac */
|
||||
flags & ~(F_T2 | F_T1), tf)); /* traps clear */
|
||||
|
@ -1425,7 +1452,7 @@ case 0254: /* JRST */
|
|||
break;
|
||||
|
||||
case 015: /* JRST 15 = XJRST */
|
||||
if (!T20) goto MUUO; /* only in TOPS20 */
|
||||
if (!T20PAG) goto MUUO; /* only in TOPS20 paging */
|
||||
JUMP (Read (ea, MM_OPND)); /* jump to M[ea] */
|
||||
break;
|
||||
} /* end case subop */
|
||||
|
@ -1434,7 +1461,7 @@ case 0254: /* JRST */
|
|||
|
||||
if (its_2pr) { /* 1-proc trap? */
|
||||
its_1pr = its_2pr = 0; /* clear trap */
|
||||
if (ITS) { /* better be ITS */
|
||||
if (Q_ITS) { /* better be ITS */
|
||||
WriteP (upta + UPT_1PO, FLPC); /* wr old flgs, PC */
|
||||
mb = ReadP (upta + UPT_1PN); /* rd new flgs, PC */
|
||||
JUMP (mb); /* set PC */
|
||||
|
@ -2017,7 +2044,7 @@ return;
|
|||
|
||||
t_bool aprid (a10 ea, int32 prv)
|
||||
{
|
||||
Write (ea, (ITS)? UC_AIDITS: UC_AIDDEC, prv);
|
||||
Write (ea, (Q_ITS)? UC_AIDITS: UC_AIDDEC, prv);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -2069,7 +2096,7 @@ if (jrst && TSTF (F_USR)) { /* if in user now */
|
|||
fl = fl | F_USR; /* can't clear user */
|
||||
if (!TSTF (F_UIO)) fl = fl & ~F_UIO; /* if !UIO, can't set */
|
||||
}
|
||||
if (ITS && (fl & F_1PR)) { /* ITS 1-proceed? */
|
||||
if (Q_ITS && (fl & F_1PR)) { /* ITS 1-proceed? */
|
||||
its_1pr = 1; /* set flag */
|
||||
fl = fl & ~F_1PR; /* vanish bit */
|
||||
}
|
||||
|
@ -2177,7 +2204,7 @@ pi_enb = pi_act = pi_prq = 0; /* clear PI */
|
|||
apr_enb = apr_flg = apr_lvl = 0; /* clear APR */
|
||||
pcst = 0; /* clear PC samp */
|
||||
rlog = 0; /* clear reg log */
|
||||
hsb = (ITS)? UC_HSBITS: UC_HSBDEC; /* set HSB */
|
||||
hsb = (Q_ITS)? UC_HSBITS: UC_HSBDEC; /* set HSB */
|
||||
set_dyn_ptrs ();
|
||||
set_ac_display (ac_cur);
|
||||
pi_eval ();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp10_defs.h: PDP-10 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2005, Robert M Supnik
|
||||
Copyright (c) 1993-2007, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,8 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
01-Feb-07 RMS Added CD support
|
||||
29-Oct-06 RMS Added clock coscheduling function
|
||||
29-Dec-03 RMS Added Q18 definition for PDP11 compatibility
|
||||
19-May-03 RMS Revised for new conditional compilation scheme
|
||||
09-Jan-03 RMS Added DEUNA/DELUA support
|
||||
|
@ -122,10 +124,16 @@ typedef t_int64 d10; /* PDP-10 data (36b) */
|
|||
/* Operating system flags, kept in cpu_unit.flags */
|
||||
|
||||
#define UNIT_V_ITS (UNIT_V_UF) /* ITS */
|
||||
#define UNIT_V_T20 (UNIT_V_UF + 1) /* TOPS-20 */
|
||||
#define UNIT_V_KLAD (UNIT_V_UF + 2) /* diagnostics */
|
||||
#define UNIT_ITS (1 << UNIT_V_ITS)
|
||||
#define UNIT_V_T20V41 (UNIT_V_UF + 1) /* TOPS-20 V4.1 */
|
||||
#define UNIT_T20V41 (1 << UNIT_V_T20V41)
|
||||
#define ITS (cpu_unit.flags & UNIT_ITS)
|
||||
#define UNIT_T20 (1 << UNIT_V_T20)
|
||||
#define UNIT_KLAD (1 << UNIT_V_KLAD)
|
||||
#define Q_T10 ((cpu_unit.flags & (UNIT_ITS|UNIT_T20|UNIT_KLAD)) == 0)
|
||||
#define Q_ITS (cpu_unit.flags & UNIT_ITS)
|
||||
#define Q_T20 (cpu_unit.flags & UNIT_T20)
|
||||
#define Q_KLAD (cpu_unit.flags & UNIT_KLAD)
|
||||
#define Q_IDLE (sim_idle_enab)
|
||||
|
||||
/* Architectural constants */
|
||||
|
||||
|
@ -384,7 +392,7 @@ typedef t_int64 d10; /* PDP-10 data (36b) */
|
|||
#define EBR_MASK (EBR_T20P | EBR_PGON | (EBR_M_EBR << EBR_V_EBR))
|
||||
#define EBR_GETEBR(x) ((int32) (((x) >> EBR_V_EBR) & PAG_M_PPN))
|
||||
#define PAGING (ebr & EBR_PGON)
|
||||
#define T20 (ebr & EBR_T20P)
|
||||
#define T20PAG (ebr & EBR_T20P)
|
||||
|
||||
/* AC and mapping contexts
|
||||
|
||||
|
@ -647,6 +655,8 @@ typedef struct pdp_dib DIB;
|
|||
#define IOLN_UBMNT3 001
|
||||
#define IOBA_XU (IO_UBA3 + 0774510) /* DEUNA/DELUA */
|
||||
#define IOLN_XU 010
|
||||
#define IOBA_CR (IO_UBA3 + 0777160) /* CD/CR/CM */
|
||||
#define IOLN_CR 010
|
||||
#define IOBA_RY (IO_UBA3 + 0777170) /* RX211 */
|
||||
#define IOLN_RY 004
|
||||
#define IOBA_TU (IO_UBA3 + 0772440) /* RH11/tape */
|
||||
|
@ -689,6 +699,7 @@ typedef struct pdp_dib DIB;
|
|||
#define INT_V_PTR 24 /* PC11 */
|
||||
#define INT_V_PTP 25
|
||||
#define INT_V_LP20 26 /* LPT20 */
|
||||
#define INT_V_CR 27 /* CD20 (CD11) */
|
||||
|
||||
#define INT_RP (1u << INT_V_RP)
|
||||
#define INT_TU (1u << INT_V_TU)
|
||||
|
@ -699,6 +710,7 @@ typedef struct pdp_dib DIB;
|
|||
#define INT_PTR (1u << INT_V_PTR)
|
||||
#define INT_PTP (1u << INT_V_PTP)
|
||||
#define INT_LP20 (1u << INT_V_LP20)
|
||||
#define INT_CR (1u << INT_V_CR)
|
||||
|
||||
#define IPL_RP 6 /* int levels */
|
||||
#define IPL_TU 6
|
||||
|
@ -709,6 +721,7 @@ typedef struct pdp_dib DIB;
|
|||
#define IPL_PTR 4
|
||||
#define IPL_PTP 4
|
||||
#define IPL_LP20 4
|
||||
#define IPL_CR 4
|
||||
|
||||
#define INT_UB1 INT_RP /* on Unibus 1 */
|
||||
#define INT_UB3 (0xFFFFFFFFu & ~INT_UB1) /* on Unibus 3 */
|
||||
|
@ -723,6 +736,7 @@ typedef struct pdp_dib DIB;
|
|||
#define VEC_PTP 0074
|
||||
#define VEC_XU 0120
|
||||
#define VEC_TU 0224
|
||||
#define VEC_CR 0230
|
||||
#define VEC_RP 0254
|
||||
#define VEC_RY 0264
|
||||
#define VEC_DZRX 0340
|
||||
|
@ -748,4 +762,10 @@ t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc);
|
|||
t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat auto_config (char *name, int32 num);
|
||||
|
||||
int32 clk_cosched (int32 wait);
|
||||
|
||||
/* Global data */
|
||||
|
||||
extern t_bool sim_idle_enab;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp10_fe.c: PDP-10 front end (console terminal) simulator
|
||||
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
Copyright (c) 1993-2006, 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"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
fe KS10 console front end
|
||||
|
||||
17-Oct-06 RMS Synced keyboard to clock for idling
|
||||
28-May-04 RMS Removed SET FE CTRL-C
|
||||
29-Dec-03 RMS Added console backpressure support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
|
@ -40,6 +41,7 @@
|
|||
|
||||
extern d10 *M;
|
||||
extern int32 apr_flg;
|
||||
extern int32 tmxr_poll;
|
||||
t_stat fei_svc (UNIT *uptr);
|
||||
t_stat feo_svc (UNIT *uptr);
|
||||
t_stat fe_reset (DEVICE *dptr);
|
||||
|
@ -56,14 +58,14 @@ t_stat fe_stop_os (UNIT *uptr, int32 val, char *cptr, void *desc);
|
|||
#define feo_unit fe_unit[1]
|
||||
|
||||
UNIT fe_unit[] = {
|
||||
{ UDATA (&fei_svc, 0, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&fei_svc, 0, 0), 0 },
|
||||
{ UDATA (&feo_svc, 0, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
REG fe_reg[] = {
|
||||
{ ORDATA (IBUF, fei_unit.buf, 8) },
|
||||
{ DRDATA (ICOUNT, fei_unit.pos, T_ADDR_W), REG_RO + PV_LEFT },
|
||||
{ DRDATA (ITIME, fei_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (ITIME, fei_unit.wait, 24), PV_LEFT },
|
||||
{ ORDATA (OBUF, feo_unit.buf, 8) },
|
||||
{ DRDATA (OCOUNT, feo_unit.pos, T_ADDR_W), REG_RO + PV_LEFT },
|
||||
{ DRDATA (OTIME, feo_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
|
@ -139,12 +141,12 @@ t_stat fei_svc (UNIT *uptr)
|
|||
{
|
||||
int32 temp;
|
||||
|
||||
sim_activate (&fei_unit, fei_unit.wait); /* continue poll */
|
||||
sim_activate (uptr, KBD_WAIT (uptr->wait, tmxr_poll)); /* continue poll */
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
|
||||
if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */
|
||||
fei_unit.buf = temp & 0177;
|
||||
fei_unit.pos = fei_unit.pos + 1;
|
||||
M[FE_CTYIN] = fei_unit.buf | FE_CVALID; /* put char in mem */
|
||||
uptr->buf = temp & 0177;
|
||||
uptr->pos = uptr->pos + 1;
|
||||
M[FE_CTYIN] = uptr->buf | FE_CVALID; /* put char in mem */
|
||||
apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -156,7 +158,7 @@ t_stat fe_reset (DEVICE *dptr)
|
|||
fei_unit.buf = feo_unit.buf = 0;
|
||||
M[FE_CTYIN] = M[FE_CTYOUT] = 0;
|
||||
apr_flg = apr_flg & ~(APRF_ITC | APRF_CON);
|
||||
sim_activate (&fei_unit, fei_unit.wait); /* start input poll */
|
||||
sim_activate_abs (&fei_unit, KBD_WAIT (fei_unit.wait, tmxr_poll));
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ t_bool io710 (int32 ac, a10 ea)
|
|||
{
|
||||
d10 val;
|
||||
|
||||
if (ITS) AC(ac) = ReadIO (IO_UBA3 | ea); /* IORDI */
|
||||
if (Q_ITS) AC(ac) = ReadIO (IO_UBA3 | ea); /* IORDI */
|
||||
else { /* TIOE */
|
||||
val = ReadIO (ea); /* read word */
|
||||
if ((AC(ac) & val) == 0) return TRUE;
|
||||
|
@ -212,7 +212,7 @@ t_bool io711 (int32 ac, a10 ea)
|
|||
{
|
||||
d10 val;
|
||||
|
||||
if (ITS) AC(ac) = ReadIO (IO_UBA1 | ea); /* IORDQ */
|
||||
if (Q_ITS) AC(ac) = ReadIO (IO_UBA1 | ea); /* IORDQ */
|
||||
else { /* TION */
|
||||
val = ReadIO (ea); /* read word */
|
||||
if ((AC(ac) & val) != 0) return TRUE;
|
||||
|
@ -248,7 +248,7 @@ void io714 (d10 val, a10 ea)
|
|||
d10 temp;
|
||||
|
||||
val = val & 0177777;
|
||||
if (ITS) WriteIO (IO_UBA3 | ea, val, WRITE); /* IOWRI */
|
||||
if (Q_ITS) WriteIO (IO_UBA3 | ea, val, WRITE); /* IOWRI */
|
||||
else {
|
||||
temp = ReadIO (ea); /* BSIO */
|
||||
temp = temp | val;
|
||||
|
@ -266,7 +266,7 @@ void io715 (d10 val, a10 ea)
|
|||
d10 temp;
|
||||
|
||||
val = val & 0177777;
|
||||
if (ITS) WriteIO (IO_UBA1 | ea, val, WRITE); /* IOWRQ */
|
||||
if (Q_ITS) WriteIO (IO_UBA1 | ea, val, WRITE); /* IOWRQ */
|
||||
else {
|
||||
temp = ReadIO (ea); /* BCIO */
|
||||
temp = temp & ~val;
|
||||
|
@ -284,7 +284,7 @@ t_bool io720 (int32 ac, a10 ea)
|
|||
{
|
||||
d10 val;
|
||||
|
||||
if (ITS) { /* IORDBI */
|
||||
if (Q_ITS) { /* IORDBI */
|
||||
val = ReadIO (IO_UBA3 | eaRB);
|
||||
AC(ac) = GETBYTE (ea, val);
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ t_bool io721 (int32 ac, a10 ea)
|
|||
{
|
||||
d10 val;
|
||||
|
||||
if (ITS) { /* IORDBQ */
|
||||
if (Q_ITS) { /* IORDBQ */
|
||||
val = ReadIO (IO_UBA1 | eaRB);
|
||||
AC(ac) = GETBYTE (ea, val);
|
||||
}
|
||||
|
@ -348,7 +348,7 @@ void io724 (d10 val, a10 ea)
|
|||
d10 temp;
|
||||
|
||||
val = val & 0377;
|
||||
if (ITS) WriteIO (IO_UBA3 | ea, val, WRITEB); /* IOWRBI */
|
||||
if (Q_ITS) WriteIO (IO_UBA3 | ea, val, WRITEB); /* IOWRBI */
|
||||
else {
|
||||
temp = ReadIO (eaRB); /* BSIOB */
|
||||
temp = GETBYTE (ea, temp);
|
||||
|
@ -367,7 +367,7 @@ void io725 (d10 val, a10 ea)
|
|||
d10 temp;
|
||||
|
||||
val = val & 0377;
|
||||
if (ITS) WriteIO (IO_UBA1 | ea, val, WRITEB); /* IOWRBQ */
|
||||
if (Q_ITS) WriteIO (IO_UBA1 | ea, val, WRITEB); /* IOWRBQ */
|
||||
else {
|
||||
temp = ReadIO (eaRB); /* BCIOB */
|
||||
temp = GETBYTE (ea, temp);
|
||||
|
|
|
@ -312,7 +312,7 @@ int32 ptbl_fill (a10 ea, int32 *tbl, int32 mode)
|
|||
ITS has no MAP instruction, therefore, physical NXM traps are ok.
|
||||
*/
|
||||
|
||||
if (ITS) { /* ITS paging */
|
||||
if (Q_ITS) { /* ITS paging */
|
||||
int32 acc, decvpn, pte, vpn, ptead, xpte;
|
||||
d10 ptewd;
|
||||
|
||||
|
@ -349,7 +349,7 @@ if (ITS) { /* ITS paging */
|
|||
user process tables.
|
||||
*/
|
||||
|
||||
else if (!T20) { /* TOPS-10 paging */
|
||||
else if (!T20PAG) { /* TOPS-10 paging */
|
||||
int32 pte, vpn, ptead, xpte;
|
||||
d10 ptewd;
|
||||
|
||||
|
@ -377,7 +377,7 @@ else if (!T20) { /* TOPS-10 paging */
|
|||
PAGE_FAIL_TRAP;
|
||||
} /* end TOPS10 paging */
|
||||
|
||||
/* TOPS-20 paging - checked against KS10 ucode.
|
||||
/* TOPS-20 paging - checked against KS10 microcode
|
||||
|
||||
TOPS-20 paging has three phases:
|
||||
|
||||
|
@ -549,7 +549,7 @@ else {
|
|||
}
|
||||
t = EBR_GETEBR (ebr);
|
||||
epta = t << PAG_V_PN;
|
||||
if (ITS) upta = (int32) ubr & PAMASK;
|
||||
if (Q_ITS) upta = (int32) ubr & PAMASK;
|
||||
else {
|
||||
t = UBR_GETUBR (ubr);
|
||||
upta = t << PAG_V_PN;
|
||||
|
@ -601,7 +601,7 @@ t_bool clrpt (a10 ea, int32 prv)
|
|||
{
|
||||
int32 vpn = PAG_GETVPN (ea); /* get page num */
|
||||
|
||||
if (ITS) { /* ITS? */
|
||||
if (Q_ITS) { /* ITS? */
|
||||
uptbl[vpn & ~1] = 0; /* clear double size */
|
||||
uptbl[vpn | 1] = 0; /* entries in */
|
||||
eptbl[vpn & ~1] = 0; /* both page tables */
|
||||
|
@ -631,7 +631,7 @@ return FALSE;
|
|||
t_bool wrubr (a10 ea, int32 prv)
|
||||
{
|
||||
d10 val = Read (ea, prv);
|
||||
d10 ubr_mask = (ITS)? PAMASK: UBR_UBRMASK; /* ITS: ubr is wd addr */
|
||||
d10 ubr_mask = (Q_ITS)? PAMASK: UBR_UBRMASK; /* ITS: ubr is wd addr */
|
||||
|
||||
if (val & UBR_SETACB) ubr = ubr & ~UBR_ACBMASK; /* set AC's? */
|
||||
else val = val & ~UBR_ACBMASK; /* no, keep old val */
|
||||
|
@ -647,7 +647,7 @@ return FALSE;
|
|||
|
||||
t_bool rdubr (a10 ea, int32 prv)
|
||||
{
|
||||
ubr = ubr & (UBR_ACBMASK | (ITS? PAMASK: UBR_UBRMASK));
|
||||
ubr = ubr & (UBR_ACBMASK | (Q_ITS? PAMASK: UBR_UBRMASK));
|
||||
Write (ea, UBRWORD, prv);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -705,7 +705,7 @@ return FALSE;
|
|||
t_bool wrcstm (a10 ea, int32 prv)
|
||||
{
|
||||
cstm = Read (ea, prv);
|
||||
if ((cpu_unit.flags & UNIT_T20V41) && (ea == 040127))
|
||||
if ((cpu_unit.flags & UNIT_T20) && (ea == 040127))
|
||||
cstm = 0770000000000;
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -1256,7 +1256,7 @@ extern a10 saved_PC;
|
|||
|
||||
M[FE_UNIT] = unitno & CS2_M_UNIT;
|
||||
for (i = 0; i < BOOT_LEN; i++)
|
||||
M[BOOT_START + i] = ITS? boot_rom_its[i]: boot_rom_dec[i];
|
||||
M[BOOT_START + i] = Q_ITS? boot_rom_its[i]: boot_rom_dec[i];
|
||||
saved_PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp10_sys.c: PDP-10 simulator interface
|
||||
|
||||
Copyright (c) 1993-2005, Robert M Supnik
|
||||
Copyright (c) 1993-2007, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
01-Feb-07 RMS Added CD support
|
||||
22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn)
|
||||
09-Jan-03 RMS Added DEUNA/DELUA support
|
||||
12-Sep-02 RMS Added RX211 support
|
||||
|
@ -40,11 +41,18 @@
|
|||
#include "pdp10_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
extern DEVICE cpu_dev, pag_dev;
|
||||
extern DEVICE tim_dev, fe_dev, uba_dev;
|
||||
extern DEVICE ptr_dev, ptp_dev;
|
||||
extern DEVICE rp_dev, tu_dev;
|
||||
extern DEVICE dz_dev, ry_dev;
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE pag_dev;
|
||||
extern DEVICE tim_dev;
|
||||
extern DEVICE fe_dev;
|
||||
extern DEVICE uba_dev;
|
||||
extern DEVICE ptr_dev;
|
||||
extern DEVICE ptp_dev;
|
||||
extern DEVICE rp_dev;
|
||||
extern DEVICE tu_dev;
|
||||
extern DEVICE dz_dev;
|
||||
extern DEVICE ry_dev;
|
||||
extern DEVICE cr_dev;
|
||||
extern DEVICE lp20_dev;
|
||||
extern DEVICE xu_dev;
|
||||
extern UNIT cpu_unit;
|
||||
|
@ -78,6 +86,7 @@ DEVICE *sim_devices[] = {
|
|||
&ptp_dev,
|
||||
&ry_dev,
|
||||
&lp20_dev,
|
||||
&cr_dev,
|
||||
&rp_dev,
|
||||
&tu_dev,
|
||||
&dz_dev,
|
||||
|
@ -693,7 +702,7 @@ dev = GET_DEV (inst);
|
|||
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||
j = (int32) ((opc_val[i] >> I_V_FL) & I_M_FL); /* get class */
|
||||
if (((opc_val[i] & DMASK) == (inst & masks[j])) && /* match? */
|
||||
(((opc_val[i] & I_ITS) == 0) || ITS)) {
|
||||
(((opc_val[i] & I_ITS) == 0) || Q_ITS)) {
|
||||
fprintf (of, "%s ", opcode[i]); /* opcode */
|
||||
switch (j) { /* case on class */
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp10_tim.c: PDP-10 tim subsystem simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M Supnik
|
||||
Copyright (c) 1993-2006, 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"),
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
tim timer subsystem
|
||||
|
||||
03-Nov-06 RMS Rewritten to support idling
|
||||
29-Oct-06 RMS Added clock coscheduling function
|
||||
02-Feb-04 RMS Exported variables needed by Ethernet simulator
|
||||
29-Jan-02 RMS New data structures
|
||||
06-Jan-02 RMS Added enable/disable support
|
||||
|
@ -37,41 +39,61 @@
|
|||
#include "pdp10_defs.h"
|
||||
#include <time.h>
|
||||
|
||||
#define TIM_N_HWRE 12 /* hwre bits */
|
||||
#define TIM_HWRE 0000000010000 /* hwre incr */
|
||||
#define TIM_DELAY 500
|
||||
#define TIM_TPS 1001 /* ticks per sec */
|
||||
#define DZ_MULT (TIM_TPS / 60) /* DZ poll multiplier */
|
||||
#define TB_MASK 037777777777777777777; /* 71 - 12 bits */
|
||||
#define UNIT_V_Y2K (UNIT_V_UF) /* Y2K compliant OS */
|
||||
/* Invariants */
|
||||
|
||||
#define TIM_HW_FREQ 4100000 /* 4.1Mhz */
|
||||
#define TIM_HWRE_MASK 07777
|
||||
#define UNIT_V_Y2K (UNIT_V_UF + 0) /* Y2K compliant OS */
|
||||
#define UNIT_Y2K (1u << UNIT_V_Y2K)
|
||||
|
||||
/* Clock mode TOPS-10/ITS */
|
||||
|
||||
#define TIM_TPS_T10 60
|
||||
#define TIM_WAIT_T10 8000
|
||||
#define TIM_MULT_T10 1
|
||||
#define TIM_ITS_QUANT (TIM_HW_FREQ / TIM_TPS_T10)
|
||||
|
||||
/* Clock mode TOPS-20/KLAD */
|
||||
|
||||
#define TIM_TPS_T20 1001
|
||||
#define TIM_WAIT_T20 500
|
||||
#define TIM_MULT_T20 16
|
||||
|
||||
/* Probability function for TOPS-20 idlelock */
|
||||
|
||||
#define PROB(x) (((rand() * 100) / RAND_MAX) >= (x))
|
||||
|
||||
d10 tim_base[2] = { 0, 0 }; /* 71b timebase */
|
||||
d10 tim_ttg = 0; /* time to go */
|
||||
d10 tim_period = 0; /* period */
|
||||
d10 quant = 0; /* ITS quantum */
|
||||
int32 tim_mult = TIM_MULT_T10; /* tmxr poll mult */
|
||||
int32 tim_t20_prob = 33; /* TOPS-20 prob */
|
||||
|
||||
/* Exported variables */
|
||||
|
||||
int32 clk_tps = TIM_TPS_T10; /* clock ticks/sec */
|
||||
int32 tmr_poll = TIM_WAIT_T10; /* clock poll */
|
||||
int32 tmxr_poll = TIM_WAIT_T10 * TIM_MULT_T10; /* term mux poll */
|
||||
|
||||
extern int32 apr_flg, pi_act;
|
||||
extern UNIT cpu_unit;
|
||||
extern d10 pcst;
|
||||
extern a10 pager_PC;
|
||||
t_int64 timebase = 0; /* 71b timebase */
|
||||
d10 ttg = 0; /* time to go */
|
||||
d10 period = 0; /* period */
|
||||
d10 quant = 0; /* ITS quantum */
|
||||
int32 diagflg = 0; /* diagnostics? */
|
||||
int32 tmxr_poll = TIM_DELAY * DZ_MULT; /* term mux poll */
|
||||
|
||||
/* Exported variables */
|
||||
|
||||
int32 clk_tps = TIM_TPS; /* clock ticks/sec */
|
||||
int32 tmr_poll = TIM_DELAY; /* clock poll */
|
||||
extern int32 t20_idlelock;
|
||||
|
||||
DEVICE tim_dev;
|
||||
t_stat tcu_rd (int32 *data, int32 PA, int32 access);
|
||||
extern t_stat wr_nop (int32 data, int32 PA, int32 access);
|
||||
t_stat tim_svc (UNIT *uptr);
|
||||
t_stat tim_reset (DEVICE *dptr);
|
||||
void tim_incr_base (d10 *base, d10 incr);
|
||||
|
||||
extern d10 Read (a10 ea, int32 prv);
|
||||
extern d10 ReadM (a10 ea, int32 prv);
|
||||
extern void Write (a10 ea, d10 val, int32 prv);
|
||||
extern void WriteP (a10 ea, d10 val);
|
||||
extern int32 pi_eval (void);
|
||||
extern t_stat wr_nop (int32 data, int32 PA, int32 access);
|
||||
|
||||
/* TIM data structures
|
||||
|
||||
|
@ -82,16 +104,19 @@ extern int32 pi_eval (void);
|
|||
|
||||
DIB tcu_dib = { IOBA_TCU, IOLN_TCU, &tcu_rd, &wr_nop, 0 };
|
||||
|
||||
UNIT tim_unit = { UDATA (&tim_svc, 0, 0), TIM_DELAY };
|
||||
UNIT tim_unit = { UDATA (&tim_svc, 0, 0), TIM_WAIT_T10 };
|
||||
|
||||
REG tim_reg[] = {
|
||||
{ ORDATA (TIMEBASE, timebase, 71 - TIM_N_HWRE) },
|
||||
{ ORDATA (TTG, ttg, 36) },
|
||||
{ ORDATA (PERIOD, period, 36) },
|
||||
{ BRDATA (TIMEBASE, tim_base, 8, 36, 2) },
|
||||
{ ORDATA (TTG, tim_ttg, 36) },
|
||||
{ ORDATA (PERIOD, tim_period, 36) },
|
||||
{ ORDATA (QUANT, quant, 36) },
|
||||
{ DRDATA (TIME, tim_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (DIAG, diagflg, 0) },
|
||||
{ FLDATA (Y2K, tim_unit.flags, UNIT_V_Y2K), REG_HRO },
|
||||
{ DRDATA (PROB, tim_t20_prob, 6), REG_NZ + PV_LEFT + REG_HIDDEN },
|
||||
{ DRDATA (POLL, tmr_poll, 32), REG_HRO + PV_LEFT },
|
||||
{ DRDATA (MUXPOLL, tmxr_poll, 32), REG_HRO + PV_LEFT },
|
||||
{ DRDATA (MULT, tim_mult, 6), REG_HRO + PV_LEFT },
|
||||
{ DRDATA (TPS, clk_tps, 12), REG_HRO + PV_LEFT },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -108,79 +133,135 @@ DEVICE tim_dev = {
|
|||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &tim_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tcu_dib, DEV_DISABLE | DEV_UBUS
|
||||
&tcu_dib, DEV_UBUS
|
||||
};
|
||||
|
||||
/* Timer instructions */
|
||||
|
||||
/* Timer - if the timer is running at less than hardware frequency,
|
||||
need to interpolate the value by calculating how much of the current
|
||||
clock tick has elapsed, and what that equates to in msec. */
|
||||
|
||||
t_bool rdtim (a10 ea, int32 prv)
|
||||
{
|
||||
ReadM (INCA (ea), prv);
|
||||
Write (ea, (timebase >> (35 - TIM_N_HWRE)) & DMASK, prv);
|
||||
Write (INCA(ea), (timebase << TIM_N_HWRE) & MMASK, prv);
|
||||
d10 tempbase[2];
|
||||
|
||||
ReadM (INCA (ea), prv); /* check 2nd word */
|
||||
tempbase[0] = tim_base[0]; /* copy time base */
|
||||
tempbase[1] = tim_base[1];
|
||||
if (tim_mult != TIM_MULT_T20) { /* interpolate? */
|
||||
int32 used;
|
||||
d10 incr;
|
||||
used = tmr_poll - (sim_is_active (&tim_unit) - 1);
|
||||
incr = (d10) (((double) used * TIM_HW_FREQ) /
|
||||
((double) tmr_poll * (double) clk_tps));
|
||||
tim_incr_base (tempbase, incr);
|
||||
}
|
||||
tempbase[0] = tempbase[0] & ~((d10) TIM_HWRE_MASK); /* clear low 12b */
|
||||
Write (ea, tempbase[0], prv);
|
||||
Write (INCA(ea), tempbase[1], prv);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_bool wrtim (a10 ea, int32 prv)
|
||||
{
|
||||
timebase = (Read (ea, prv) << (35 - TIM_N_HWRE)) |
|
||||
(CLRS (Read (INCA (ea), prv)) >> TIM_N_HWRE);
|
||||
tim_base[0] = Read (ea, prv);
|
||||
tim_base[1] = CLRS (Read (INCA (ea), prv));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_bool rdint (a10 ea, int32 prv)
|
||||
{
|
||||
Write (ea, period, prv);
|
||||
Write (ea, tim_period, prv);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_bool wrint (a10 ea, int32 prv)
|
||||
{
|
||||
period = Read (ea, prv);
|
||||
ttg = period;
|
||||
tim_period = Read (ea, prv);
|
||||
tim_ttg = tim_period;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Timer routines
|
||||
|
||||
tim_svc process event (timer tick)
|
||||
tim_reset process reset
|
||||
*/
|
||||
/* Timer service - the timer is only serviced when the 'ttg' register
|
||||
has reached 0 based on the expected frequency of clock interrupts. */
|
||||
|
||||
t_stat tim_svc (UNIT *uptr)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
t = diagflg? tim_unit.wait: sim_rtc_calb (TIM_TPS); /* calibrate clock */
|
||||
sim_activate (&tim_unit, t); /* reactivate unit */
|
||||
tmr_poll = t; /* set timer poll */
|
||||
tmxr_poll = t * DZ_MULT; /* set mux poll */
|
||||
timebase = (timebase + 1) & TB_MASK; /* increment timebase */
|
||||
ttg = ttg - TIM_HWRE; /* decrement timer */
|
||||
if (ttg <= 0) { /* timeout? */
|
||||
ttg = period; /* reload */
|
||||
apr_flg = apr_flg | APRF_TIM; /* request interrupt */
|
||||
}
|
||||
if (ITS) { /* ITS? */
|
||||
if (pi_act == 0) quant = (quant + TIM_HWRE) & DMASK;
|
||||
if (cpu_unit.flags & UNIT_KLAD) /* diags? */
|
||||
tmr_poll = uptr->wait; /* fixed clock */
|
||||
else tmr_poll = sim_rtc_calb (clk_tps); /* else calibrate */
|
||||
sim_activate (uptr, tmr_poll); /* reactivate unit */
|
||||
tmxr_poll = tmr_poll * tim_mult; /* set mux poll */
|
||||
tim_incr_base (tim_base, tim_period); /* incr time base */
|
||||
tim_ttg = tim_period; /* reload */
|
||||
apr_flg = apr_flg | APRF_TIM; /* request interrupt */
|
||||
if (Q_ITS) { /* ITS? */
|
||||
if (pi_act == 0)
|
||||
quant = (quant + TIM_ITS_QUANT) & DMASK;
|
||||
if (TSTS (pcst)) { /* PC sampling? */
|
||||
WriteP ((a10) pcst & AMASK, pager_PC); /* store sample */
|
||||
pcst = AOB (pcst); /* add 1,,1 */
|
||||
}
|
||||
} /* end ITS */
|
||||
else if (t20_idlelock && PROB (100 - tim_t20_prob))
|
||||
t20_idlelock = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat tim_reset (DEVICE *dptr)
|
||||
/* Clock coscheduling routine */
|
||||
|
||||
int32 clk_cosched (int32 wait)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
period = ttg = 0; /* clear timer */
|
||||
if (tim_mult == TIM_MULT_T20) return wait;
|
||||
t = sim_is_active (&tim_unit);
|
||||
return (t? t - 1: wait);
|
||||
}
|
||||
|
||||
void tim_incr_base (d10 *base, d10 incr)
|
||||
{
|
||||
base[1] = base[1] + incr; /* add on incr */
|
||||
base[0] = base[0] + (base[1] >> 35); /* carry to high */
|
||||
base[0] = base[0] & DMASK; /* mask high */
|
||||
base[1] = base[1] & MMASK; /* mask low */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Timer reset */
|
||||
|
||||
t_stat tim_reset (DEVICE *dptr)
|
||||
{
|
||||
tim_period = 0; /* clear timer */
|
||||
tim_ttg = 0;
|
||||
apr_flg = apr_flg & ~APRF_TIM; /* clear interrupt */
|
||||
t = sim_rtc_init (tim_unit.wait); /* init timer */
|
||||
sim_activate (&tim_unit, t); /* activate unit */
|
||||
tmr_poll = t; /* set timer poll */
|
||||
tmxr_poll = t * DZ_MULT; /* set mux poll */
|
||||
tmr_poll = sim_rtc_init (tim_unit.wait); /* init timer */
|
||||
sim_activate_abs (&tim_unit, tmr_poll); /* activate unit */
|
||||
tmxr_poll = tmr_poll * tim_mult; /* set mux poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set timer parameters from CPU model */
|
||||
|
||||
t_stat tim_set_mod (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (val & (UNIT_T20|UNIT_KLAD)) {
|
||||
clk_tps = TIM_TPS_T20;
|
||||
uptr->wait = TIM_WAIT_T20;
|
||||
tmr_poll = TIM_WAIT_T20;
|
||||
tim_mult = TIM_MULT_T20;
|
||||
uptr->flags = uptr->flags | UNIT_Y2K;
|
||||
}
|
||||
else {
|
||||
clk_tps = TIM_TPS_T10;
|
||||
uptr->wait = TIM_WAIT_T10;
|
||||
tmr_poll = TIM_WAIT_T10;
|
||||
tim_mult = TIM_MULT_T10;
|
||||
if (Q_ITS) uptr->flags = uptr->flags | UNIT_Y2K;
|
||||
else uptr->flags = uptr->flags & ~UNIT_Y2K;
|
||||
}
|
||||
tmxr_poll = tmr_poll * tim_mult;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1225,7 +1225,7 @@ M[FE_UNIT] = 0;
|
|||
M[FE_MTFMT] = (unitno & TC_M_UNIT) | (TC_1600 << TC_V_DEN) | (TC_10C << TC_V_FMT);
|
||||
tu_unit[unitno].pos = 0;
|
||||
for (i = 0; i < BOOT_LEN; i++)
|
||||
M[BOOT_START + i] = ITS? boot_rom_its[i]: boot_rom_dec[i];
|
||||
M[BOOT_START + i] = Q_ITS? boot_rom_its[i]: boot_rom_dec[i];
|
||||
saved_PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -1192,15 +1192,18 @@ return TestDstr (src); /* clean -0 */
|
|||
dsrc = decimal string descriptor
|
||||
src = decimal string structure
|
||||
flag = numeric/packed flag
|
||||
|
||||
PSW.NZ are also set to their proper values
|
||||
PSW.V will be set on overflow; it must be initialized elsewhere
|
||||
(to allow for external overflow calculations)
|
||||
|
||||
The rules for the stored sign and the PSW sign are:
|
||||
|
||||
- Stored sign is negative if input is negative, string type
|
||||
is signed, and the result is non-zero or there was overflow
|
||||
- PSW sign is negative if input is negative, string type is
|
||||
signed, and the result is non-zero
|
||||
|
||||
Thus, the stored sign and the PSW sign will differ in one case:
|
||||
a negative zero generated by overflow is stored with a negative
|
||||
sign, but PSW.N is clear
|
||||
|
@ -1265,16 +1268,18 @@ return;
|
|||
cy = carry in
|
||||
Output = 1 if carry, 0 if no carry
|
||||
|
||||
This algorithm courtesy Anton Chernoff, circa 1992 or even earlier
|
||||
This algorithm courtesy Anton Chernoff, circa 1992 or even earlier.
|
||||
|
||||
We trace the history of a pair of adjacent digits to see how the
|
||||
carry is fixed; each parenthesized item is a 4b digit.
|
||||
|
||||
Assume we are adding:
|
||||
|
||||
(a)(b) I
|
||||
+ (x)(y) J
|
||||
|
||||
First compute I^J:
|
||||
|
||||
(a^x)(b^y) TMP
|
||||
|
||||
Note that the low bit of each digit is the same as the low bit of
|
||||
|
@ -1283,6 +1288,7 @@ return;
|
|||
|
||||
Now compute I+J+66 to get decimal addition with carry forced left
|
||||
one digit:
|
||||
|
||||
(a+x+6+carry mod 16)(b+y+6 mod 16) SUM
|
||||
|
||||
Note that if there was a carry from b+y+6, then the low bit of the
|
||||
|
@ -1357,6 +1363,7 @@ return 0;
|
|||
|
||||
Arguments:
|
||||
dsrc = decimal string structure
|
||||
|
||||
Returns the non-zero length of the string, in int32 units
|
||||
If the string is zero, the sign is cleared
|
||||
*/
|
||||
|
@ -1395,8 +1402,8 @@ return ((nz - 1) * 8) + i;
|
|||
mtable[10] = array of decimal string structures
|
||||
|
||||
Note that dsrc has a high order zero nibble; this
|
||||
guarantees that the largest multiple won't overflow
|
||||
Also note that mtable[0] is not filled in
|
||||
guarantees that the largest multiple won't overflow.
|
||||
Also note that mtable[0] is not filled in.
|
||||
*/
|
||||
|
||||
void CreateTable (DSTR *dsrc, DSTR mtable[10])
|
||||
|
@ -1560,7 +1567,7 @@ fpd = 0; /* instr done */
|
|||
return;
|
||||
}
|
||||
|
||||
/* Test for CIS mid-instruction interrupt - stub for now */
|
||||
/* Test for CIS mid-instruction interrupt */
|
||||
|
||||
t_bool cis_int_test (int32 cycles, int32 oldpc, t_stat *st)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
cpu PDP-11 CPU
|
||||
|
||||
27-Oct-06 RMS Added idle support
|
||||
18-Oct-06 RMS Fixed bug in ASH -32 C value
|
||||
24-May-06 RMS Added instruction history
|
||||
03-May-06 RMS Fixed XOR operand fetch order for 11/70-style systems
|
||||
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
||||
|
@ -220,8 +222,8 @@
|
|||
#define calc_is(md) ((md) << VA_V_MODE)
|
||||
#define calc_ds(md) (calc_is((md)) | ((MMR3 & dsmask[(md)])? VA_DS: 0))
|
||||
#define calc_MMR1(val) ((MMR1)? (((val) << 8) | MMR1): (val))
|
||||
#define GET_SIGN_W(v) ((v) >> 15)
|
||||
#define GET_SIGN_B(v) ((v) >> 7)
|
||||
#define GET_SIGN_W(v) (((v) >> 15) & 1)
|
||||
#define GET_SIGN_B(v) (((v) >> 7) & 1)
|
||||
#define GET_Z(v) ((v) == 0)
|
||||
#define JMP_PC(x) PCQ_ENTRY; PC = (x)
|
||||
#define BRANCH_F(x) PCQ_ENTRY; PC = (PC + (((x) + (x)) & 0377)) & 0177777
|
||||
|
@ -300,6 +302,7 @@ extern UNIT clk_unit, pclk_unit;
|
|||
extern int32 sim_int_char;
|
||||
extern uint32 sim_switches;
|
||||
extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
extern t_bool sim_idle_enab;
|
||||
extern DEVICE *sim_devices[];
|
||||
extern CPUTAB cpu_tab[];
|
||||
|
||||
|
@ -376,7 +379,7 @@ int32 trap_clear[TRAP_V_MAX] = { /* trap clears */
|
|||
cpu_mod CPU modifier list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, INIMEMSIZE) };
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX|UNIT_BINK, INIMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
{ ORDATA (PC, saved_PC, 16) },
|
||||
|
@ -533,7 +536,7 @@ REG cpu_reg[] = {
|
|||
{ BRDATA (IREQ, int_req, 8, 32, IPL_HLVL), REG_RO },
|
||||
{ ORDATA (TRAPS, trap_req, TRAP_V_MAX) },
|
||||
{ FLDATA (WAIT, wait_state, 0) },
|
||||
{ FLDATA (WAIT_ENABLE, wait_enable, 0) },
|
||||
{ FLDATA (WAIT_ENABLE, wait_enable, 0), REG_HIDDEN },
|
||||
{ ORDATA (STOP_TRAPS, stop_trap, TRAP_V_MAX) },
|
||||
{ FLDATA (STOP_VECA, stop_vecabort, 0) },
|
||||
{ FLDATA (STOP_SPA, stop_spabort, 0) },
|
||||
|
@ -583,6 +586,8 @@ MTAB cpu_mod[] = {
|
|||
{ MTAB_XTD|MTAB_VDV, OPT_CIS, NULL, "NOCIS", &cpu_clr_opt },
|
||||
{ MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "MMU", &cpu_set_opt },
|
||||
{ MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "NOMMU", &cpu_clr_opt },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
|
||||
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size},
|
||||
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size},
|
||||
{ UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size},
|
||||
|
@ -786,8 +791,11 @@ while (reason == 0) {
|
|||
|
||||
if (tbit) setTRAP (TRAP_TRC);
|
||||
if (wait_state) { /* wait state? */
|
||||
if (sim_qcount () != 0) sim_interval = 0; /* force check */
|
||||
else reason = STOP_WAIT;
|
||||
if (sim_idle_enab) /* idle enabled? */
|
||||
sim_idle (TMR_CLK, TRUE);
|
||||
else if (wait_enable) /* old style idle? */
|
||||
sim_interval = 0; /* force check */
|
||||
else sim_interval = sim_interval - 1; /* count cycle */
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -846,7 +854,7 @@ while (reason == 0) {
|
|||
else setTRAP (TRAP_ILL); /* no, ill inst */
|
||||
break;
|
||||
case 1: /* WAIT */
|
||||
if (wait_enable) wait_state = 1;
|
||||
wait_state = 1;
|
||||
break;
|
||||
case 3: /* BPT */
|
||||
setTRAP (TRAP_BPT);
|
||||
|
@ -1374,7 +1382,7 @@ while (reason == 0) {
|
|||
else PWriteW (dst, last_pa);
|
||||
break;
|
||||
|
||||
/* Opcode 07: EIS, FIS (not implemented), CIS
|
||||
/* Opcode 07: EIS, FIS, CIS
|
||||
|
||||
Notes:
|
||||
- The code assumes that the host int length is at least 32 bits.
|
||||
|
@ -1471,7 +1479,8 @@ while (reason == 0) {
|
|||
}
|
||||
else if (src2 == 32) { /* [32] = -32 */
|
||||
dst = -sign;
|
||||
V = C = 0;
|
||||
V = 0;
|
||||
C = sign;
|
||||
}
|
||||
else { /* [33,63] = -31,-1 */
|
||||
dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
|
||||
|
@ -1505,7 +1514,7 @@ while (reason == 0) {
|
|||
else if (src2 == 32) { /* [32] = -32 */
|
||||
dst = -sign;
|
||||
V = 0;
|
||||
C = (src >> 31) & 1;
|
||||
C = sign;
|
||||
}
|
||||
else { /* [33,63] = -31,-1 */
|
||||
dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
|
||||
|
@ -2136,7 +2145,7 @@ if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
|
|||
}
|
||||
pa = relocR (va); /* relocate */
|
||||
if (ADDR_IS_MEM (pa)) return (M[pa >> 1]); /* memory address? */
|
||||
if ((pa < IOPAGEBASE) || /* I/O address */
|
||||
if ((pa < IOPAGEBASE) || /* not I/O address */
|
||||
(CPUT (CPUT_J) && (pa >= IOBA_CPU))) { /* or J11 int reg? */
|
||||
setCPUERR (CPUE_NXM);
|
||||
ABORT (TRAP_NXM);
|
||||
|
@ -2158,7 +2167,7 @@ if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
|
|||
}
|
||||
pa = relocR (va); /* relocate */
|
||||
if (ADDR_IS_MEM (pa)) return (M[pa >> 1]); /* memory address? */
|
||||
if (pa < IOPAGEBASE) { /* I/O address? */
|
||||
if (pa < IOPAGEBASE) { /* not I/O address? */
|
||||
setCPUERR (CPUE_NXM);
|
||||
ABORT (TRAP_NXM);
|
||||
}
|
||||
|
@ -2175,7 +2184,7 @@ int32 pa, data;
|
|||
|
||||
pa = relocR (va); /* relocate */
|
||||
if (ADDR_IS_MEM (pa)) return (va & 1? M[pa >> 1] >> 8: M[pa >> 1]) & 0377;
|
||||
if (pa < IOPAGEBASE) { /* I/O address? */
|
||||
if (pa < IOPAGEBASE) { /* not I/O address? */
|
||||
setCPUERR (CPUE_NXM);
|
||||
ABORT (TRAP_NXM);
|
||||
}
|
||||
|
@ -2196,7 +2205,7 @@ if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
|
|||
}
|
||||
last_pa = relocW (va); /* reloc, wrt chk */
|
||||
if (ADDR_IS_MEM (last_pa)) return (M[last_pa >> 1]); /* memory address? */
|
||||
if (last_pa < IOPAGEBASE) { /* I/O address? */
|
||||
if (last_pa < IOPAGEBASE) { /* not I/O address? */
|
||||
setCPUERR (CPUE_NXM);
|
||||
ABORT (TRAP_NXM);
|
||||
}
|
||||
|
@ -2214,7 +2223,7 @@ int32 data;
|
|||
last_pa = relocW (va); /* reloc, wrt chk */
|
||||
if (ADDR_IS_MEM (last_pa))
|
||||
return (va & 1? M[last_pa >> 1] >> 8: M[last_pa >> 1]) & 0377;
|
||||
if (last_pa < IOPAGEBASE) { /* I/O address? */
|
||||
if (last_pa < IOPAGEBASE) { /* not I/O address? */
|
||||
setCPUERR (CPUE_NXM);
|
||||
ABORT (TRAP_NXM);
|
||||
}
|
||||
|
@ -2247,7 +2256,7 @@ if (ADDR_IS_MEM (pa)) { /* memory address? */
|
|||
M[pa >> 1] = data;
|
||||
return;
|
||||
}
|
||||
if (pa < IOPAGEBASE) { /* I/O address? */
|
||||
if (pa < IOPAGEBASE) { /* not I/O address? */
|
||||
setCPUERR (CPUE_NXM);
|
||||
ABORT (TRAP_NXM);
|
||||
}
|
||||
|
@ -2268,7 +2277,7 @@ if (ADDR_IS_MEM (pa)) { /* memory address? */
|
|||
else M[pa >> 1] = (M[pa >> 1] & ~0377) | data;
|
||||
return;
|
||||
}
|
||||
if (pa < IOPAGEBASE) { /* I/O address? */
|
||||
if (pa < IOPAGEBASE) { /* not I/O address? */
|
||||
setCPUERR (CPUE_NXM);
|
||||
ABORT (TRAP_NXM);
|
||||
}
|
||||
|
@ -2285,7 +2294,7 @@ if (ADDR_IS_MEM (pa)) { /* memory address? */
|
|||
M[pa >> 1] = data;
|
||||
return;
|
||||
}
|
||||
if (pa < IOPAGEBASE) { /* I/O address? */
|
||||
if (pa < IOPAGEBASE) { /* not I/O address? */
|
||||
setCPUERR (CPUE_NXM);
|
||||
ABORT (TRAP_NXM);
|
||||
}
|
||||
|
@ -2303,7 +2312,7 @@ if (ADDR_IS_MEM (pa)) { /* memory address? */
|
|||
else M[pa >> 1] = (M[pa >> 1] & ~0377) | data;
|
||||
return;
|
||||
}
|
||||
if (pa < IOPAGEBASE) { /* I/O address? */
|
||||
if (pa < IOPAGEBASE) { /* not I/O address? */
|
||||
setCPUERR (CPUE_NXM);
|
||||
ABORT (TRAP_NXM);
|
||||
}
|
||||
|
@ -2574,8 +2583,8 @@ switch ((pa >> 1) & 3) { /* decode pa<2:1> */
|
|||
case 3: /* MMR2 */
|
||||
*data = MMR2;
|
||||
break;
|
||||
}
|
||||
/* end switch pa */
|
||||
} /* end switch pa */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_cr.c: CR/CM/CD-11 card reader simulator
|
||||
|
||||
Copyright (c) 2005, John A. Dundas III
|
||||
Copyright (c) 2005-2007, John A. Dundas III
|
||||
Portions derived from work by Douglas W. Jones, jones@cs.uiowa.edu
|
||||
Portions derived from work by Robert M Supnik
|
||||
|
||||
|
@ -51,8 +51,8 @@
|
|||
http://www.cs.uiowa.edu/~jones/cards/
|
||||
Paul Mattes' x026 keypunch simulator
|
||||
http://x3270.bgp.nu/x026.html
|
||||
CDRSER.MAC - TOPS card reader driver source
|
||||
http://pdp-10.trailing-edge.com/custsupcuspmar86_bb-x130b-sb/02/cdrser.mac
|
||||
CD2SER.MAC - TOPS card reader driver source
|
||||
http://pdp-10.trailing-edge.com/custsupcuspmar86_bb-x130b-sb/02/cd2ser.mac
|
||||
|
||||
The Card Image format code and documentation is adapted from Prof.
|
||||
Jones's site, with his permission. Please see his site for additional
|
||||
|
@ -66,14 +66,13 @@
|
|||
3. No testing under RSX; volunteers needed
|
||||
4. No testing under Ultrix or Unix for PDP-11; volunteers needed
|
||||
5. No testing under Ultrix or Unix for VAX; volunteers needed
|
||||
6. No PDP-10 support; volunteers needed
|
||||
7. The simulator implements a single controller/reader combination
|
||||
6. The simulator implements a single controller/reader combination
|
||||
|
||||
Operating System Notes
|
||||
|
||||
RT-11 (and CTS-300) support one CR11 or CM11, but no CD11.
|
||||
|
||||
VMS supports multiple CR11 controllers.
|
||||
VMS supports multiple CR11 controllers, but no CD11.
|
||||
|
||||
RSTS/E supports either the CR11/CM11 or CD11 but not both in
|
||||
the same SIL. It appears to support only one unit.
|
||||
|
@ -84,12 +83,11 @@
|
|||
Don't have any information about Unix or Ultrix-11 yet. Same
|
||||
for VAX Unices.
|
||||
|
||||
TOPS: it appears that both the CD11 and CR11 were supported.
|
||||
I don't have any knowledge on how to make this work with the
|
||||
PDP-10 simulation, though.
|
||||
TOPS: only the CD11 is supported, under the name CD20.
|
||||
|
||||
Revision History:
|
||||
|
||||
01-Feb-07 RMS Added PDP-10 support
|
||||
12-May-06 JAD Modify the DEBUG code to use the SIMH DEBUG_x
|
||||
macros. Modify the UNIT structure to include
|
||||
the DEBUG bit.
|
||||
|
@ -168,14 +166,23 @@
|
|||
#if defined (VM_PDP10) /* PDP10 version */
|
||||
#include "pdp10_defs.h"
|
||||
extern int32 int_req;
|
||||
#define DFLT_DIS (DEV_DIS)
|
||||
#define DFLT_CR11 (0) /* CD11 only */
|
||||
#define DFLT_CPM 1000
|
||||
|
||||
#elif defined (VM_VAX) /* VAX version */
|
||||
#include "vax_defs.h"
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
#define DFLT_DIS (0)
|
||||
#define DFLT_CR11 (UNIT_CR11)
|
||||
#define DFLT_CPM 285
|
||||
|
||||
#else /* PDP-11 version */
|
||||
#include "pdp11_defs.h"
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
#define DFLT_DIS (0)
|
||||
#define DFLT_CR11 (UNIT_CR11)
|
||||
#define DFLT_CPM 285
|
||||
#endif
|
||||
|
||||
extern FILE *sim_deb; /* sim_console.c */
|
||||
|
@ -294,7 +301,7 @@ static int32 blowerState = BLOW_OFF; /* reader vacuum/blower
|
|||
static int32 spinUp = 3000; /* blower spin-up time: 3 seconds */
|
||||
static int32 spinDown = 2000; /* blower spin-down time: 2 seconds */
|
||||
static t_bool EOFcard = FALSE; /* played special card yet? */
|
||||
static int32 cpm = 285; /* reader rate: cards per minute */
|
||||
static int32 cpm = DFLT_CPM; /* reader rate: cards per minute */
|
||||
/* card image in various formats */
|
||||
static int16 hcard[82]; /* Hollerith format */
|
||||
static char ccard[82]; /* DEC compressed format */
|
||||
|
@ -343,8 +350,8 @@ static DIB cr_dib = { IOBA_CR, IOLN_CR, &cr_rd, &cr_wr,
|
|||
static UNIT cr_unit = {
|
||||
UDATA (&cr_svc,
|
||||
UNIT_ATTABLE+UNIT_SEQ+UNIT_ROABLE+UNIT_DISABLE+
|
||||
UNIT_CR11+UNIT_AUTOEOF, 0),
|
||||
(60 * 1000) / 285 };
|
||||
DFLT_CR11+UNIT_AUTOEOF, 0),
|
||||
(60 * 1000) / DFLT_CPM };
|
||||
|
||||
static const REG cr_reg[] = {
|
||||
{ GRDATA (BUF, cr_unit.buf, DEV_RDX, 8, 0) },
|
||||
|
@ -367,8 +374,13 @@ static const REG cr_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
static const MTAB cr_mod[] = {
|
||||
#if defined (VM_PDP11)
|
||||
{ UNIT_CR11, UNIT_CR11, "CR11", "CR11", &cr_set_type },
|
||||
{ UNIT_CR11, 0, "CD11", "CD11", &cr_set_type },
|
||||
#else
|
||||
{ UNIT_CR11, UNIT_CR11, "CR11", NULL },
|
||||
{ UNIT_CR11, 0, "CD11", NULL },
|
||||
#endif
|
||||
{ UNIT_AUTOEOF, UNIT_AUTOEOF, "auto EOF", "AUTOEOF", NULL },
|
||||
{ UNIT_AUTOEOF, 0, "no auto EOF", "NOAUTOEOF", NULL },
|
||||
/* card reader RESET switch */
|
||||
|
@ -395,7 +407,7 @@ DEVICE cr_dev = {
|
|||
1, 10, 31, 1, DEV_RDX, 8,
|
||||
NULL, NULL, &cr_reset,
|
||||
NULL, &cr_attach, &cr_detach,
|
||||
&cr_dib, DEV_DISABLE | DEV_UBUS | DEV_DEBUG };
|
||||
&cr_dib, DEV_DISABLE | DFLT_DIS | DEV_UBUS | DEV_DEBUG };
|
||||
|
||||
/* Utility routines */
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||
and John Wilson in resolving questions about the PDP-11
|
||||
|
||||
16-Dec-06 RMS Added TA11 support
|
||||
29-Oct-06 RMS Added clock coscheduling
|
||||
06-Jul-06 RMS Added multiple KL11/DL11 support
|
||||
26-Jun-06 RMS Added RF11 support
|
||||
24-May-06 RMS Added 11/44 DR support (from CIS diagnostic)
|
||||
|
@ -569,6 +571,8 @@ typedef struct pdp_dib DIB;
|
|||
#define IOLN_HK 040
|
||||
#define IOBA_RF (IOPAGEBASE + 017460) /* RF11 */
|
||||
#define IOLN_RF 020
|
||||
#define IOBA_TA (IOPAGEBASE + 017500) /* TA11 */
|
||||
#define IOLN_TA 004
|
||||
#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */
|
||||
#define IOLN_LPT 004
|
||||
#define IOBA_CTL (IOPAGEBASE + 017520) /* board ctrl */
|
||||
|
@ -613,7 +617,8 @@ typedef struct pdp_dib DIB;
|
|||
#define INT_V_CLK 0 /* BR6 */
|
||||
#define INT_V_PCLK 1
|
||||
#define INT_V_DTA 2
|
||||
#define INT_V_PIR6 3
|
||||
#define INT_V_TA 3
|
||||
#define INT_V_PIR6 4
|
||||
|
||||
#define INT_V_RK 0 /* BR5 */
|
||||
#define INT_V_RL 1
|
||||
|
@ -653,6 +658,7 @@ typedef struct pdp_dib DIB;
|
|||
#define INT_CLK (1u << INT_V_CLK)
|
||||
#define INT_PCLK (1u << INT_V_PCLK)
|
||||
#define INT_DTA (1u << INT_V_DTA)
|
||||
#define INT_TA (1u << INT_V_TA)
|
||||
#define INT_PIR6 (1u << INT_V_PIR6)
|
||||
#define INT_RK (1u << INT_V_RK)
|
||||
#define INT_RL (1u << INT_V_RL)
|
||||
|
@ -689,6 +695,7 @@ typedef struct pdp_dib DIB;
|
|||
#define IPL_CLK 6 /* int pri levels */
|
||||
#define IPL_PCLK 6
|
||||
#define IPL_DTA 6
|
||||
#define IPL_TA 6
|
||||
#define IPL_RK 5
|
||||
#define IPL_RL 5
|
||||
#define IPL_RX 5
|
||||
|
@ -749,6 +756,7 @@ typedef struct pdp_dib DIB;
|
|||
#define VEC_CR 0230
|
||||
#define VEC_RP 0254
|
||||
#define VEC_TQ 0260
|
||||
#define VEC_TA 0260
|
||||
#define VEC_RX 0264
|
||||
#define VEC_RY 0264
|
||||
#define VEC_TTIX 0300
|
||||
|
@ -810,4 +818,6 @@ void mba_set_don (uint32 mbus);
|
|||
void mba_set_enbdis (uint32 mb, t_bool dis);
|
||||
t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
int32 clk_cosched (int32 wait);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_dz.c: DZ11 terminal multiplexor simulator
|
||||
|
||||
Copyright (c) 2001-2005, Robert M Supnik
|
||||
Copyright (c) 2001-2006, 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"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
dz DZ11 terminal multiplexor
|
||||
|
||||
29-Oct-06 RMS Synced poll and clock
|
||||
22-Nov-05 RMS Revised for new terminal processing routines
|
||||
07-Jul-05 RMS Removed extraneous externs
|
||||
15-Jun-05 RMS Revised for new autoconfigure interface
|
||||
|
@ -304,7 +305,8 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */
|
|||
(dz_csr[dz] & 0377) | (data << 8):
|
||||
(dz_csr[dz] & ~0377) | data;
|
||||
if (data & CSR_CLR) dz_clear (dz, FALSE); /* clr? reset */
|
||||
if (data & CSR_MSE) sim_activate (&dz_unit, tmxr_poll);
|
||||
if (data & CSR_MSE) /* MSE? start poll */
|
||||
sim_activate (&dz_unit, clk_cosched (tmxr_poll));
|
||||
else dz_csr[dz] &= ~(CSR_SA | CSR_RDONE | CSR_TRDY);
|
||||
if ((data & CSR_RIE) == 0) dz_clr_rxint (dz); /* RIE = 0? */
|
||||
else if (((dz_csr[dz] & CSR_IE) == 0) && /* RIE 0->1? */
|
||||
|
|
|
@ -145,17 +145,25 @@
|
|||
|
||||
/* Double precision operations on 64b quantities */
|
||||
|
||||
#define F_LOAD(qd,ac,ds) ds.h = ac.h; ds.l = (qd)? ac.l: 0
|
||||
#define F_LOAD_P(qd,ac,ds) ds->h = ac.h; ds->l = (qd)? ac.l: 0
|
||||
#define F_LOAD_FRAC(qd,ac,ds) ds.h = (ac.h & FP_FRACH) | FP_HB; \
|
||||
#define F_LOAD(qd,ac,ds) \
|
||||
ds.h = ac.h; ds.l = (qd)? ac.l: 0
|
||||
#define F_LOAD_P(qd,ac,ds) \
|
||||
ds->h = ac.h; ds->l = (qd)? ac.l: 0
|
||||
#define F_LOAD_FRAC(qd,ac,ds) \
|
||||
ds.h = (ac.h & FP_FRACH) | FP_HB; \
|
||||
ds.l = (qd)? ac.l: 0
|
||||
#define F_STORE(qd,sr,ac) ac.h = sr.h; if ((qd)) ac.l = sr.l
|
||||
#define F_STORE_P(qd,sr,ac) ac.h = sr->h; if ((qd)) ac.l = sr->l
|
||||
#define F_GET_FRAC_P(sr,ds) ds.l = sr->l; \
|
||||
#define F_STORE(qd,sr,ac) \
|
||||
ac.h = sr.h; if ((qd)) ac.l = sr.l
|
||||
#define F_STORE_P(qd,sr,ac) \
|
||||
ac.h = sr->h; if ((qd)) ac.l = sr->l
|
||||
#define F_GET_FRAC_P(sr,ds) \
|
||||
ds.l = sr->l; \
|
||||
ds.h = (sr->h & FP_FRACH) | FP_HB
|
||||
#define F_ADD(s2,s1,ds) ds.l = (s1.l + s2.l) & 0xFFFFFFFF; \
|
||||
#define F_ADD(s2,s1,ds) \
|
||||
ds.l = (s1.l + s2.l) & 0xFFFFFFFF; \
|
||||
ds.h = (s1.h + s2.h + (ds.l < s2.l)) & 0xFFFFFFFF
|
||||
#define F_SUB(s2,s1,ds) ds.h = (s1.h - s2.h - (s1.l < s2.l)) & 0xFFFFFFFF; \
|
||||
#define F_SUB(s2,s1,ds) \
|
||||
ds.h = (s1.h - s2.h - (s1.l < s2.l)) & 0xFFFFFFFF; \
|
||||
ds.l = (s1.l - s2.l) & 0xFFFFFFFF
|
||||
#define F_LT(x,y) ((x.h < y.h) || ((x.h == y.h) && (x.l < y.l)))
|
||||
#define F_LT_AP(x,y) (((x->h & ~FP_SIGN) < (y->h & ~FP_SIGN)) || \
|
||||
|
@ -252,7 +260,8 @@ int32 i, qdouble, lenf, leni;
|
|||
int32 newV, exp, sign;
|
||||
fpac_t fac, fsrc, modfrac;
|
||||
static const uint32 i_limit[2][2] = {
|
||||
{ 0x80000000, 0x80010000 }, { 0x80000000, 0x80000001 }
|
||||
{ 0x80000000, 0x80010000 },
|
||||
{ 0x80000000, 0x80000001 }
|
||||
};
|
||||
|
||||
backup_PC = PC; /* save PC for FEA */
|
||||
|
@ -602,7 +611,8 @@ return 0;
|
|||
uint32 ReadI (int32 VA, int32 spec, int32 len)
|
||||
{
|
||||
if ((len == WORD) || (spec == 027)) return (ReadW (VA) << 16);
|
||||
return ((ReadW (VA) << 16) | ReadW ((VA & ~0177777) | ((VA + 2) & 0177777)));
|
||||
return ((ReadW (VA) << 16) |
|
||||
ReadW ((VA & ~0177777) | ((VA + 2) & 0177777)));
|
||||
}
|
||||
|
||||
/* Read floating operand
|
||||
|
|
|
@ -705,6 +705,7 @@ switch (fnc) { /* case on function */
|
|||
case FNC_NOP: /* no operation */
|
||||
update_hkcs (CS1_DONE, drv); /* done */
|
||||
break;
|
||||
|
||||
case FNC_PACK: /* pack acknowledge */
|
||||
hkds[drv] = hkds[drv] | DS_VV; /* set volume valid */
|
||||
update_hkcs (CS1_DONE, drv); /* done */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
rf RF11 fixed head disk
|
||||
|
||||
25-Dec-06 RMS Fixed bug in unit mask (found by John Dundas)
|
||||
26-Jun-06 RMS Cloned from RF08 simulator
|
||||
|
||||
The RF11 is a head-per-track disk. To minimize overhead, the entire RF11
|
||||
|
@ -42,7 +43,7 @@
|
|||
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||
#define UNIT_M_PLAT 03
|
||||
#define UNIT_M_PLAT (RF_NUMDK - 1)
|
||||
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
|
|
|
@ -31,12 +31,15 @@
|
|||
WARNING: The interupt logic of the RH11/RH70 is unusual and must be
|
||||
simulated with great precision. The RH11 has an internal interrupt
|
||||
request flop, CSTB INTR, which is controlled as follows:
|
||||
|
||||
- Writing IE and DONE simultaneously sets CSTB INTR
|
||||
- Controller clear, INIT, and interrupt acknowledge clear CSTB INTR
|
||||
(and also clear IE)
|
||||
- A transition of DONE from 0 to 1 sets CSTB INTR from IE
|
||||
|
||||
The output of CSTB INTR is OR'd with the AND of RPCS1<SC,DONE,IE> to
|
||||
create the interrupt request signal. Thus,
|
||||
|
||||
- The DONE interrupt is edge sensitive, but the SC interrupt is
|
||||
level sensitive.
|
||||
- The DONE interrupt, once set, is not disabled if IE is cleared,
|
||||
|
|
|
@ -75,7 +75,8 @@
|
|||
#define RK_NUMTR (RK_NUMCY * RK_NUMSF) /* tracks/drive */
|
||||
#define RK_NUMDR 8 /* drives/controller */
|
||||
#define RK_M_NUMDR 07
|
||||
#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD) /* words/drive */
|
||||
#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD)
|
||||
/* words/drive */
|
||||
#define RK_CTLI 1 /* controller int */
|
||||
#define RK_SCPI(x) (2u << (x)) /* drive int */
|
||||
#define RK_MAXFR (1 << 16) /* max transfer */
|
||||
|
@ -297,8 +298,10 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
|
|||
rkds = (rkds & RKDS_ID) | RKDS_RK05 | RKDS_SC_OK |
|
||||
(rand () % RK_NUMSC); /* random sector */
|
||||
uptr = rk_dev.units + GET_DRIVE (rkda); /* selected unit */
|
||||
if (uptr->flags & UNIT_ATT) rkds = rkds | RKDS_RDY; /* attached? */
|
||||
if (!sim_is_active (uptr)) rkds = rkds | RKDS_RWS; /* idle? */
|
||||
if (uptr->flags & UNIT_ATT) /* attached? */
|
||||
rkds = rkds | RKDS_RDY;
|
||||
if (!sim_is_active (uptr)) /* idle? */
|
||||
rkds = rkds | RKDS_RWS;
|
||||
if (uptr->flags & UNIT_WPRT) rkds = rkds | RKDS_WLK;
|
||||
if (GET_SECT (rkda) == (rkds & RKDS_SC)) rkds = rkds | RKDS_ON_SC;
|
||||
*data = rkds;
|
||||
|
@ -356,7 +359,8 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
|
|||
SET_INT (RK); /* set int request */
|
||||
}
|
||||
rkcs = (rkcs & ~RKCS_RW) | (data & RKCS_RW);
|
||||
if ((rkcs & CSR_DONE) && (data & CSR_GO)) rk_go (); /* new function? */
|
||||
if ((rkcs & CSR_DONE) && (data & CSR_GO)) /* new function? */
|
||||
rk_go ();
|
||||
return SCPE_OK;
|
||||
|
||||
case 3: /* RKWC */
|
||||
|
@ -410,8 +414,9 @@ if (uptr->flags & UNIT_DIS) { /* not present? */
|
|||
rk_set_done (RKER_NXD);
|
||||
return;
|
||||
}
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || sim_is_active (uptr)) {
|
||||
rk_set_done (RKER_DRE); /* not att or busy */
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || /* not att or busy? */
|
||||
sim_is_active (uptr)) {
|
||||
rk_set_done (RKER_DRE);
|
||||
return;
|
||||
}
|
||||
if ((rkcs & RKCS_FMT) && /* format and */
|
||||
|
@ -419,8 +424,9 @@ if ((rkcs & RKCS_FMT) && /* format and */
|
|||
rk_set_done (RKER_PGE);
|
||||
return;
|
||||
}
|
||||
if ((func == RKCS_WRITE) && (uptr->flags & UNIT_WPRT)) {
|
||||
rk_set_done (RKER_WLK); /* write and locked? */
|
||||
if ((func == RKCS_WRITE) && /* write and locked? */
|
||||
(uptr->flags & UNIT_WPRT)) {
|
||||
rk_set_done (RKER_WLK);
|
||||
return;
|
||||
}
|
||||
if (func == RKCS_WLK) { /* write lock? */
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
tti,tto DL11 terminal input/output
|
||||
clk KW11L (and other) line frequency clock
|
||||
|
||||
29-Oct-06 RMS Synced keyboard and clock
|
||||
Added clock coscheduling support
|
||||
05-Jul-06 RMS Added UC only support for early DOS/RSTS
|
||||
22-Nov-05 RMS Revised for new terminal processing routines
|
||||
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
||||
|
@ -107,7 +109,7 @@ DIB tti_dib = {
|
|||
1, IVCL (TTI), VEC_TTI, { NULL }
|
||||
};
|
||||
|
||||
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
|
||||
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), 0 };
|
||||
|
||||
REG tti_reg[] = {
|
||||
{ ORDATA (BUF, tti_unit.buf, 8) },
|
||||
|
@ -117,7 +119,7 @@ REG tti_reg[] = {
|
|||
{ FLDATA (DONE, tti_csr, CSR_V_DONE) },
|
||||
{ FLDATA (IE, tti_csr, CSR_V_IE) },
|
||||
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TIME, tti_unit.wait, 24), PV_LEFT },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -153,7 +155,7 @@ DIB tto_dib = {
|
|||
1, IVCL (TTO), VEC_TTO, { NULL }
|
||||
};
|
||||
|
||||
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
|
||||
UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_7P, 0), SERIAL_OUT_WAIT };
|
||||
|
||||
REG tto_reg[] = {
|
||||
{ ORDATA (BUF, tto_unit.buf, 8) },
|
||||
|
@ -281,7 +283,7 @@ t_stat tti_svc (UNIT *uptr)
|
|||
{
|
||||
int32 c;
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
sim_activate (uptr, KBD_WAIT (uptr->wait, tmr_poll)); /* continue poll */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
if (c & SCPE_BREAK) uptr->buf = 0; /* break? */
|
||||
else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags));
|
||||
|
@ -298,7 +300,7 @@ t_stat tti_reset (DEVICE *dptr)
|
|||
tti_unit.buf = 0;
|
||||
tti_csr = 0;
|
||||
CLR_INT (TTI);
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||
sim_activate_abs (&tti_unit, KBD_WAIT (tti_unit.wait, tmr_poll));
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -434,6 +436,16 @@ if (CPUT (CPUT_24)) clk_csr = clk_csr & ~CSR_DONE;
|
|||
return clk_dib.vec;
|
||||
}
|
||||
|
||||
/* Clock coscheduling routine */
|
||||
|
||||
int32 clk_cosched (int32 wait)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
t = sim_is_active (&clk_unit);
|
||||
return (t? t - 1: wait);
|
||||
}
|
||||
|
||||
/* Clock reset */
|
||||
|
||||
t_stat clk_reset (DEVICE *dptr)
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
20-Dec-06 RMS Added TA11 support
|
||||
12-Nov-06 RMS Fixed operand order in EIS instructions (found by W.F.J. Mueller)
|
||||
14-Jul-06 RMS Reordered device list
|
||||
06-Jul-06 RMS Added multiple KL11/DL11 support
|
||||
26-Jun-06 RMS Added RF11 support
|
||||
|
@ -85,6 +87,7 @@ extern DEVICE tm_dev;
|
|||
extern DEVICE tq_dev;
|
||||
extern DEVICE ts_dev;
|
||||
extern DEVICE tu_dev;
|
||||
extern DEVICE ta_dev;
|
||||
extern DEVICE xq_dev, xqb_dev;
|
||||
extern DEVICE xu_dev, xub_dev;
|
||||
extern UNIT cpu_unit;
|
||||
|
@ -141,6 +144,7 @@ DEVICE *sim_devices[] = {
|
|||
&ts_dev,
|
||||
&tq_dev,
|
||||
&tu_dev,
|
||||
&ta_dev,
|
||||
&xq_dev,
|
||||
&xqb_dev,
|
||||
&xu_dev,
|
||||
|
@ -311,7 +315,7 @@ return SCPE_OK;
|
|||
/* Warning: for literals, the class number MUST equal the field width!! */
|
||||
|
||||
#define I_V_CL 18 /* class bits */
|
||||
#define I_M_CL 017 /* class mask */
|
||||
#define I_M_CL 037 /* class mask */
|
||||
#define I_V_NPN 0 /* no operands */
|
||||
#define I_V_REG 1 /* reg */
|
||||
#define I_V_SOP 2 /* operand */
|
||||
|
@ -328,6 +332,7 @@ return SCPE_OK;
|
|||
#define I_V_DOP 13 /* double operand */
|
||||
#define I_V_CCC 14 /* CC clear */
|
||||
#define I_V_CCS 15 /* CC set */
|
||||
#define I_V_SOPR 16 /* operand, reg */
|
||||
#define I_NPN (I_V_NPN << I_V_CL)
|
||||
#define I_REG (I_V_REG << I_V_CL)
|
||||
#define I_3B (I_V_3B << I_V_CL)
|
||||
|
@ -344,12 +349,14 @@ return SCPE_OK;
|
|||
#define I_DOP (I_V_DOP << I_V_CL)
|
||||
#define I_CCC (I_V_CCC << I_V_CL)
|
||||
#define I_CCS (I_V_CCS << I_V_CL)
|
||||
#define I_SOPR (I_V_SOPR << I_V_CL)
|
||||
|
||||
static const int32 masks[] = {
|
||||
0177777, 0177770, 0177700, 0177770,
|
||||
0177700+I_D, 0177400+I_D, 0177700, 0177400,
|
||||
0177400, 0177000, 0177000, 0177400,
|
||||
0177400+I_D+I_L, 0170000, 0177777, 0177777
|
||||
0177400+I_D+I_L, 0170000, 0177777, 0177777,
|
||||
0177000
|
||||
};
|
||||
|
||||
static const char *opcode[] = {
|
||||
|
@ -443,7 +450,7 @@ static const int32 opc_val[] = {
|
|||
0007000+I_SOP, 0007200+I_SOP, 0007300+I_SOP,
|
||||
0010000+I_DOP, 0020000+I_DOP, 0030000+I_DOP, 0040000+I_DOP,
|
||||
0050000+I_DOP, 0060000+I_DOP,
|
||||
0070000+I_RSOP, 0071000+I_RSOP, 0072000+I_RSOP, 0073000+I_RSOP,
|
||||
0070000+I_SOPR, 0071000+I_SOPR, 0072000+I_SOPR, 0073000+I_SOPR,
|
||||
0074000+I_RSOP,
|
||||
0075000+I_REG, 0075010+I_REG, 0075020+I_REG, 0075030+I_REG,
|
||||
0076020+I_REG,
|
||||
|
@ -684,6 +691,12 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
|||
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
|
||||
break;
|
||||
|
||||
case I_V_SOPR: /* sopr */
|
||||
fprintf (of, "%s ", opcode[i]);
|
||||
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
|
||||
fprintf (of, ",%s", rname[srcr]);
|
||||
break;
|
||||
|
||||
case I_V_ASOP: case I_V_ASMD: /* asop, asmd */
|
||||
fprintf (of, "%s %s,", opcode[i], fname[fac]);
|
||||
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
|
||||
|
@ -994,6 +1007,16 @@ switch (j) { /* case on class */
|
|||
val[0] = val[0] | spec;
|
||||
break;
|
||||
|
||||
case I_V_SOPR: /* dop, reg */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
|
||||
if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | spec;
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
|
||||
if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
|
||||
val[0] = val[0] | (reg << 6);
|
||||
break;
|
||||
|
||||
case I_V_AFOP: case I_V_ASOP: case I_V_ASMD: /* fac, (s)fop */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
|
||||
if ((reg = get_reg (gbuf, fname, 0)) < 0) return SCPE_ARG;
|
||||
|
|
584
PDP11/pdp11_ta.c
Normal file
584
PDP11/pdp11_ta.c
Normal file
|
@ -0,0 +1,584 @@
|
|||
/* pdp11_ta.c: PDP-11 cassette tape simulator
|
||||
|
||||
Copyright (c) 2006, 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 ATAION OF CONTRATA, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNETAION 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.
|
||||
|
||||
ta TA11/TU60 cassette tape
|
||||
|
||||
Magnetic tapes are represented as a series of variable records
|
||||
of the form:
|
||||
|
||||
32b byte count
|
||||
byte 0
|
||||
byte 1
|
||||
:
|
||||
byte n-2
|
||||
byte n-1
|
||||
32b byte count
|
||||
|
||||
If the byte count is odd, the record is padded with an extra byte
|
||||
of junk. File marks are represented by a byte count of 0.
|
||||
|
||||
Cassette format differs in one very significant way: it has file gaps
|
||||
rather than file marks. If the controller spaces or reads into a file
|
||||
gap and then reverses direction, the file gap is not seen again. This
|
||||
is in contrast to magnetic tapes, where the file mark is a character
|
||||
sequence and is seen again if direction is reversed.
|
||||
*/
|
||||
|
||||
#include "pdp11_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define TA_NUMDR 2 /* #drives */
|
||||
#define FNC u3 /* unit function */
|
||||
#define UST u4 /* unit status */
|
||||
#define TA_SIZE 93000 /* chars/tape */
|
||||
#define TA_MAXFR (TA_SIZE) /* max record lnt */
|
||||
|
||||
/* Control/status - TACS */
|
||||
|
||||
#define TACS_ERR (1 << CSR_V_ERR) /* error */
|
||||
#define TACS_CRC 0040000 /* CRC */
|
||||
#define TACS_BEOT 0020000 /* BOT/EOT */
|
||||
#define TACS_WLK 0010000 /* write lock */
|
||||
#define TACS_EOF 0004000 /* end file */
|
||||
#define TACS_TIM 0002000 /* timing */
|
||||
#define TACS_EMP 0001000 /* empty */
|
||||
#define TACS_V_UNIT 8 /* unit */
|
||||
#define TACS_M_UNIT (TA_NUMDR - 1)
|
||||
#define TACS_UNIT (TACS_M_UNIT << TACS_V_UNIT)
|
||||
#define TACS_TR (1 << CSR_V_DONE) /* transfer req */
|
||||
#define TACS_IE (1 << CSR_V_IE) /* interrupt enable */
|
||||
#define TACS_RDY 0000040 /* ready */
|
||||
#define TACS_ILBS 0000020 /* start CRC */
|
||||
#define TACS_V_FNC 1 /* function */
|
||||
#define TACS_M_FNC 07
|
||||
#define TACS_WFG 00
|
||||
#define TACS_WRITE 01
|
||||
#define TACS_READ 02
|
||||
#define TACS_SRF 03
|
||||
#define TACS_SRB 04
|
||||
#define TACS_SFF 05
|
||||
#define TACS_SFB 06
|
||||
#define TACS_REW 07
|
||||
#define TACS_2ND 010
|
||||
#define TACS_3RD 030
|
||||
#define TACS_FNC (TACS_M_FNC << TACS_V_FNC)
|
||||
#define TACS_GO (1 << CSR_V_GO) /* go */
|
||||
#define TACS_W (TACS_UNIT|TACS_IE|TACS_ILBS|TACS_FNC)
|
||||
#define TACS_XFRERR (TACS_ERR|TACS_CRC|TACS_WLK|TACS_EOF|TACS_TIM)
|
||||
#define GET_UNIT(x) (((x) >> TACS_V_UNIT) & TACS_M_UNIT)
|
||||
#define GET_FNC(x) (((x) >> TACS_V_FNC) & TACS_M_FNC)
|
||||
|
||||
/* Function code flags */
|
||||
|
||||
#define OP_WRI 01 /* op is a write */
|
||||
#define OP_REV 02 /* op is rev motion */
|
||||
#define OP_FWD 04 /* op is fwd motion */
|
||||
|
||||
/* Unit status flags */
|
||||
|
||||
#define UST_REV (OP_REV) /* last op was rev */
|
||||
#define UST_GAP 01 /* last op hit gap */
|
||||
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern FILE *sim_deb;
|
||||
|
||||
uint32 ta_cs = 0; /* control/status */
|
||||
uint32 ta_idb = 0; /* input data buf */
|
||||
uint32 ta_odb = 0; /* output data buf */
|
||||
uint32 ta_write = 0; /* TU60 write flag */
|
||||
uint32 ta_bptr = 0; /* buf ptr */
|
||||
uint32 ta_blnt = 0; /* buf length */
|
||||
int32 ta_stime = 1000; /* start time */
|
||||
int32 ta_ctime = 100; /* char latency */
|
||||
uint32 ta_stopioe = 1; /* stop on error */
|
||||
uint8 *ta_xb = NULL; /* transfer buffer */
|
||||
static uint8 ta_fnc_tab[TACS_M_FNC + 1] = {
|
||||
OP_WRI|OP_FWD, OP_WRI|OP_FWD, OP_FWD, OP_REV,
|
||||
OP_REV , OP_FWD, OP_FWD, 0
|
||||
};
|
||||
|
||||
DEVICE ta_dev;
|
||||
t_stat ta_rd (int32 *data, int32 PA, int32 access);
|
||||
t_stat ta_wr (int32 data, int32 PA, int32 access);
|
||||
t_stat ta_svc (UNIT *uptr);
|
||||
t_stat ta_reset (DEVICE *dptr);
|
||||
t_stat ta_attach (UNIT *uptr, char *cptr);
|
||||
t_stat ta_detach (UNIT *uptr);
|
||||
void ta_go (void);
|
||||
t_stat ta_map_err (UNIT *uptr, t_stat st);
|
||||
UNIT *ta_busy (void);
|
||||
void ta_set_tr (void);
|
||||
uint32 ta_updsta (UNIT *uptr);
|
||||
uint32 ta_crc (uint8 *buf, uint32 cnt);
|
||||
|
||||
/* TA data structures
|
||||
|
||||
ta_dev TA device descriptor
|
||||
ta_unit TA unit list
|
||||
ta_reg TA register list
|
||||
ta_mod TA modifier list
|
||||
*/
|
||||
|
||||
DIB ta_dib = {
|
||||
IOBA_TA, IOLN_TA, &ta_rd, &ta_wr,
|
||||
1, IVCL (TA), VEC_TA, { NULL }
|
||||
};
|
||||
|
||||
UNIT ta_unit[] = {
|
||||
{ UDATA (&ta_svc, UNIT_ATTABLE+UNIT_ROABLE, TA_SIZE) },
|
||||
{ UDATA (&ta_svc, UNIT_ATTABLE+UNIT_ROABLE, TA_SIZE) },
|
||||
};
|
||||
|
||||
REG ta_reg[] = {
|
||||
{ ORDATA (TACS, ta_cs, 16) },
|
||||
{ ORDATA (TAIDB, ta_idb, 8) },
|
||||
{ ORDATA (TAODB, ta_odb, 8) },
|
||||
{ FLDATA (WRITE, ta_write, 0) },
|
||||
{ FLDATA (INT, IREQ (TA), INT_V_TA) },
|
||||
{ FLDATA (ERR, ta_cs, CSR_V_ERR) },
|
||||
{ FLDATA (TR, ta_cs, CSR_V_DONE) },
|
||||
{ FLDATA (IE, ta_cs, CSR_V_IE) },
|
||||
{ DRDATA (BPTR, ta_bptr, 17) },
|
||||
{ DRDATA (BLNT, ta_blnt, 17) },
|
||||
{ DRDATA (STIME, ta_stime, 24), PV_LEFT + REG_NZ },
|
||||
{ DRDATA (CTIME, ta_ctime, 24), PV_LEFT + REG_NZ },
|
||||
{ FLDATA (STOP_IOE, ta_stopioe, 0) },
|
||||
{ URDATA (UFNC, ta_unit[0].FNC, 8, 5, 0, TA_NUMDR, 0), REG_HRO },
|
||||
{ URDATA (UST, ta_unit[0].UST, 8, 2, 0, TA_NUMDR, 0), REG_HRO },
|
||||
{ URDATA (POS, ta_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
TA_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ ORDATA (DEVADDR, ta_dib.ba, 32), REG_HRO },
|
||||
{ ORDATA (DEVVEC, ta_dib.vec, 16), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ta_mod[] = {
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
// { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
// &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", NULL,
|
||||
NULL, &sim_tape_show_capac, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, IOLN_TA, "ADDRESS", "ADDRESS",
|
||||
&set_addr, &show_addr, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
|
||||
&set_vec, &show_vec, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ta_dev = {
|
||||
"TA", ta_unit, ta_reg, ta_mod,
|
||||
TA_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ta_reset,
|
||||
NULL, &ta_attach, &ta_detach,
|
||||
&ta_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG
|
||||
};
|
||||
|
||||
/* I/O dispatch routines, I/O addresses 17777500 - 17777503
|
||||
|
||||
17777500 TACS read/write
|
||||
17777502 TADB read/write
|
||||
*/
|
||||
|
||||
t_stat ta_rd (int32 *data, int32 PA, int32 access)
|
||||
{
|
||||
switch ((PA >> 1) & 01) { /* decode PA<1> */
|
||||
|
||||
case 0: /* TACSR */
|
||||
*data = ta_updsta (NULL); /* update status */
|
||||
break;
|
||||
|
||||
case 1: /* TADB */
|
||||
*data = ta_idb; /* return byte */
|
||||
ta_cs &= ~TACS_TR; /* clear tra req */
|
||||
ta_updsta (NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ta_wr (int32 data, int32 PA, int32 access)
|
||||
{
|
||||
switch ((PA >> 1) & 01) { /* decode PA<1> */
|
||||
|
||||
case 0: /* TACS */
|
||||
if (access == WRITEB) data = (PA & 1)? /* byte write? */
|
||||
(ta_cs & 0377) | (data << 8): /* merge old */
|
||||
(ta_cs & ~0377) | data;
|
||||
ta_cs = (ta_cs & ~TACS_W) | (data & TACS_W); /* merge new */
|
||||
if ((data & CSR_GO) && !ta_busy ()) /* go, not busy? */
|
||||
ta_go (); /* start operation */
|
||||
if (ta_cs & TACS_ILBS) ta_cs &= ~TACS_TR; /* ILBS inhibits TR */
|
||||
break;
|
||||
|
||||
case 1: /* TADB */
|
||||
if (PA & 1) break; /* ignore odd byte */
|
||||
ta_odb = data; /* return byte */
|
||||
ta_cs &= ~TACS_TR; /* clear tra req */
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
ta_updsta (NULL); /* update status */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Start a new operation - cassette is not busy */
|
||||
|
||||
void ta_go (void)
|
||||
{
|
||||
UNIT *uptr = ta_dev.units + GET_UNIT (ta_cs);
|
||||
uint32 fnc = GET_FNC (ta_cs);
|
||||
uint32 flg = ta_fnc_tab[fnc];
|
||||
uint32 old_ust = uptr->UST;
|
||||
|
||||
if (DEBUG_PRS (ta_dev)) fprintf (sim_deb,
|
||||
">>TA start: op=%o, old_sta = %o, pos=%d\n",
|
||||
fnc, uptr->UST, uptr->pos);
|
||||
ta_cs &= ~(TACS_XFRERR|TACS_EMP|TACS_TR|TACS_RDY); /* clr err, tr, rdy */
|
||||
ta_bptr = 0; /* init buffer */
|
||||
ta_blnt = 0;
|
||||
if ((uptr->flags & UNIT_ATT) == 0) {
|
||||
ta_cs |= TACS_ERR|TACS_EMP|TACS_RDY;
|
||||
return;
|
||||
}
|
||||
if (flg & OP_WRI) { /* write op? */
|
||||
if (sim_tape_wrp (uptr)) { /* locked? */
|
||||
ta_cs |= TACS_ERR|TACS_WLK|TACS_RDY; /* don't start */
|
||||
return;
|
||||
}
|
||||
ta_odb = 0;
|
||||
ta_write = 1;
|
||||
}
|
||||
else {
|
||||
ta_idb = 0;
|
||||
ta_write = 0;
|
||||
}
|
||||
ta_cs &= ~TACS_BEOT; /* tape in motion */
|
||||
uptr->FNC = fnc; /* save function */
|
||||
if ((fnc != TACS_REW) && !(flg & OP_WRI)) { /* read cmd? */
|
||||
uptr->UST = flg & UST_REV; /* save direction */
|
||||
if ((old_ust ^ uptr->UST) == (UST_REV|UST_GAP)) { /* reverse in gap? */
|
||||
t_mtrlnt t; /* skip file mark */
|
||||
if (uptr->UST) sim_tape_rdrecr (uptr, ta_xb, &t, TA_MAXFR);
|
||||
else sim_tape_rdrecf (uptr, ta_xb, &t, TA_MAXFR);
|
||||
if (DEBUG_PRS (ta_dev)) fprintf (sim_deb,
|
||||
">>TA skip gap: op=%o, old_sta = %o, pos=%d\n",
|
||||
fnc, uptr->UST, uptr->pos);
|
||||
}
|
||||
}
|
||||
else uptr->UST = 0;
|
||||
sim_activate (uptr, ta_stime); /* schedule op */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat ta_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 i, crc;
|
||||
uint32 flg = ta_fnc_tab[uptr->FNC & TACS_M_FNC];
|
||||
t_mtrlnt tbc;
|
||||
t_stat st, r;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
ta_cs |= TACS_ERR|TACS_EMP|TACS_RDY;
|
||||
ta_updsta (uptr); /* update status */
|
||||
return (ta_stopioe? SCPE_UNATT: SCPE_OK);
|
||||
}
|
||||
if (((flg & OP_FWD) && sim_tape_eot (uptr)) || /* illegal motion? */
|
||||
((flg & OP_REV) && sim_tape_bot (uptr))) {
|
||||
ta_cs |= TACS_ERR|TACS_BEOT|TACS_RDY; /* error */
|
||||
ta_updsta (uptr);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
r = SCPE_OK;
|
||||
switch (uptr->FNC) { /* case on function */
|
||||
|
||||
case TACS_READ: /* read start */
|
||||
st = sim_tape_rdrecf (uptr, ta_xb, &ta_blnt, TA_MAXFR); /* get rec */
|
||||
if (st == MTSE_RECE) ta_cs |= TACS_ERR|TACS_CRC; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
r = ta_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
}
|
||||
crc = ta_crc (ta_xb, ta_blnt); /* calculate CRC */
|
||||
ta_xb[ta_blnt++] = (crc >> 8) & 0377; /* append to buffer */
|
||||
ta_xb[ta_blnt++] = crc & 0377;
|
||||
uptr->FNC |= TACS_2ND; /* next state */
|
||||
sim_activate (uptr, ta_ctime); /* sched next char */
|
||||
return SCPE_OK;
|
||||
|
||||
case TACS_READ|TACS_2ND: /* read char */
|
||||
if (ta_bptr < ta_blnt) /* more chars? */
|
||||
ta_idb = ta_xb[ta_bptr++];
|
||||
else { /* no */
|
||||
ta_idb = 0;
|
||||
ta_cs |= TACS_ERR|TACS_CRC; /* overrun */
|
||||
break; /* tape stops */
|
||||
}
|
||||
if (ta_cs & TACS_ILBS) { /* CRC seq? */
|
||||
uptr->FNC |= TACS_3RD; /* next state */
|
||||
sim_activate (uptr, ta_stime); /* sched CRC chk */
|
||||
}
|
||||
else {
|
||||
ta_set_tr (); /* set tra req */
|
||||
sim_activate (uptr, ta_ctime); /* sched next char */
|
||||
}
|
||||
return SCPE_OK;
|
||||
|
||||
case TACS_READ|TACS_3RD: /* second read CRC */
|
||||
if (ta_bptr != ta_blnt) { /* partial read? */
|
||||
crc = ta_crc (ta_xb, ta_bptr + 2); /* actual CRC */
|
||||
if (crc != 0) ta_cs |= TACS_ERR|TACS_CRC; /* must be zero */
|
||||
}
|
||||
break; /* read done */
|
||||
|
||||
case TACS_WRITE: /* write start */
|
||||
for (i = 0; i < TA_MAXFR; i++) ta_xb[i] = 0; /* clear buffer */
|
||||
ta_set_tr (); /* set tra req */
|
||||
uptr->FNC |= TACS_2ND; /* next state */
|
||||
sim_activate (uptr, ta_ctime); /* sched next char */
|
||||
return SCPE_OK;
|
||||
|
||||
case TACS_WRITE|TACS_2ND: /* write char */
|
||||
if (ta_cs & TACS_ILBS) { /* CRC seq? */
|
||||
uptr->FNC |= TACS_3RD; /* next state */
|
||||
sim_activate (uptr, ta_stime); /* sched wri done */
|
||||
}
|
||||
else {
|
||||
if ((ta_bptr < TA_MAXFR) && /* room in buf? */
|
||||
((uptr->pos + ta_bptr) < uptr->capac)) /* room on tape? */
|
||||
ta_xb[ta_bptr++] = ta_odb; /* store char */
|
||||
ta_set_tr (); /* set tra req */
|
||||
sim_activate (uptr, ta_ctime); /* sched next char */
|
||||
}
|
||||
return SCPE_OK;
|
||||
|
||||
case TACS_WRITE|TACS_3RD: /* write CRC */
|
||||
if (ta_bptr) { /* anything to write? */
|
||||
if (st = sim_tape_wrrecf (uptr, ta_xb, ta_bptr)) /* write, err? */
|
||||
r = ta_map_err (uptr, st); /* map error */
|
||||
}
|
||||
break; /* op done */
|
||||
|
||||
case TACS_WFG: /* write file gap */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = ta_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case TACS_REW: /* rewind */
|
||||
sim_tape_rewind (uptr);
|
||||
ta_cs |= TACS_BEOT; /* bot, no error */
|
||||
break;
|
||||
|
||||
case TACS_SRB: /* space rev blk */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rev, err? */
|
||||
r = ta_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case TACS_SRF: /* space rev file */
|
||||
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
|
||||
if (st == MTSE_TMK) /* if tape mark, */
|
||||
ta_cs |= TACS_EOF; /* set EOF, no err */
|
||||
else r = ta_map_err (uptr, st); /* else map error */
|
||||
break;
|
||||
|
||||
case TACS_SFB: /* space fwd blk */
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rev, err? */
|
||||
r = ta_map_err (uptr, st); /* map error */
|
||||
ta_cs |= TACS_CRC; /* CRC sets, no err */
|
||||
break;
|
||||
|
||||
case TACS_SFF: /* space fwd file */
|
||||
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
|
||||
if (st == MTSE_TMK) /* if tape mark, */
|
||||
ta_cs |= TACS_EOF; /* set EOF, no err */
|
||||
else r = ta_map_err (uptr, st); /* else map error */
|
||||
break;
|
||||
|
||||
default: /* never get here! */
|
||||
return SCPE_IERR;
|
||||
} /* end case */
|
||||
|
||||
ta_cs |= TACS_RDY; /* set ready */
|
||||
ta_updsta (uptr); /* update status */
|
||||
if (DEBUG_PRS (ta_dev)) fprintf (sim_deb,
|
||||
">>TA done: op=%o, status = %o, pos=%d\n",
|
||||
uptr->FNC, ta_cs, uptr->pos);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Update controller status */
|
||||
|
||||
uint32 ta_updsta (UNIT *uptr)
|
||||
{
|
||||
if (uptr == NULL) { /* unit specified? */
|
||||
if ((uptr = ta_busy ()) == NULL) /* use busy */
|
||||
uptr = ta_dev.units + GET_UNIT (ta_cs); /* use sel unit */
|
||||
}
|
||||
else if (ta_cs & TACS_EOF) uptr->UST |= UST_GAP; /* save EOF */
|
||||
if (uptr->flags & UNIT_ATT) ta_cs &= ~TACS_EMP; /* attached? */
|
||||
else ta_cs |= TACS_EMP|TACS_RDY; /* no, empty, ready */
|
||||
if ((ta_cs & TACS_IE) && /* int enabled? */
|
||||
(ta_cs & (TACS_TR|TACS_RDY))) /* req or ready? */
|
||||
SET_INT (TA); /* set int req */
|
||||
else CLR_INT (TA); /* no, clr int req */
|
||||
return ta_cs;
|
||||
}
|
||||
|
||||
/* Set transfer request */
|
||||
|
||||
void ta_set_tr (void)
|
||||
{
|
||||
if (ta_cs & TACS_TR) ta_cs |= (TACS_ERR|TACS_TIM); /* flag still set? */
|
||||
else ta_cs |= TACS_TR; /* set xfr req */
|
||||
if (ta_cs & TACS_IE) SET_INT (TA); /* if ie, int req */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test if controller busy */
|
||||
|
||||
UNIT *ta_busy (void)
|
||||
{
|
||||
uint32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
for (u = 0; u < TA_NUMDR; u++) { /* loop thru units */
|
||||
uptr = ta_dev.units + u;
|
||||
if (sim_is_active (uptr)) return uptr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Calculate CRC on buffer */
|
||||
|
||||
uint32 ta_crc (uint8 *buf, uint32 cnt)
|
||||
{
|
||||
uint32 crc, i, j;
|
||||
|
||||
crc = 0;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
crc = crc ^ (((uint32) buf[i]) << 8);
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (crc & 1) crc = (crc >> 1) ^ 0xA001;
|
||||
else crc = crc >> 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
/* Map error status */
|
||||
|
||||
t_stat ta_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
switch (st) {
|
||||
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* unattached */
|
||||
ta_cs |= TACS_ERR|TACS_CRC;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR; /* never get here! */
|
||||
|
||||
case MTSE_TMK: /* end of file */
|
||||
ta_cs |= TACS_ERR|TACS_EOF;
|
||||
break;
|
||||
|
||||
case MTSE_IOERR: /* IO error */
|
||||
ta_cs |= TACS_ERR|TACS_CRC; /* set crc err */
|
||||
if (ta_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
ta_cs |= TACS_ERR|TACS_CRC; /* set crc err */
|
||||
return SCPE_MTRLNT;
|
||||
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
ta_cs |= TACS_ERR|TACS_CRC; /* set crc err */
|
||||
break;
|
||||
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
ta_cs |= TACS_ERR|TACS_BEOT; /* set bot */
|
||||
break;
|
||||
|
||||
case MTSE_WRP: /* write protect */
|
||||
ta_cs |= TACS_ERR|TACS_WLK; /* set wlk err */
|
||||
break;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat ta_reset (DEVICE *dptr)
|
||||
{
|
||||
uint32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
ta_cs = 0;
|
||||
ta_idb = 0;
|
||||
ta_odb = 0;
|
||||
ta_write = 0;
|
||||
ta_bptr = 0;
|
||||
ta_blnt = 0;
|
||||
CLR_INT (TA); /* clear interrupt */
|
||||
for (u = 0; u < TA_NUMDR; u++) { /* loop thru units */
|
||||
uptr = ta_dev.units + u;
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
sim_tape_reset (uptr); /* reset tape */
|
||||
}
|
||||
if (ta_xb == NULL) ta_xb = (uint8 *) calloc (TA_MAXFR + 2, sizeof (uint8));
|
||||
if (ta_xb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat ta_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = sim_tape_attach (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
ta_updsta (NULL);
|
||||
uptr->UST = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Detach routine */
|
||||
|
||||
t_stat ta_detach (UNIT* uptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* check attached */
|
||||
r = sim_tape_detach (uptr);
|
||||
ta_updsta (NULL);
|
||||
uptr->UST = 0;
|
||||
return r;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue