mirror of
https://github.com/simh/simh.git
synced 2026-01-25 19:56:25 +00:00
Notes For V3.5-0
The source set has been extensively overhauled. For correct viewing, set Visual C++ or Emacs to have tab stops every 4 characters. 1. New Features in 3.4-1 1.1 All Ethernet devices - Added Windows user-defined adapter names (from Timothe Litt) 1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors - Added support for SET <unit>n DISCONNECT 1.3 VAX - Added latent QDSS support - Revised autoconfigure to handle QDSS 1.4 PDP-11 - Revised autoconfigure to handle more casees 2. Bugs Fixed in 3.4-1 2.1 SCP and libraries - Trim trailing spaces on all input (for example, attach file names) - Fixed sim_sock spurious SIGPIPE error in Unix/Linux - Fixed sim_tape misallocation of TPC map array for 64b simulators 2.2 1401 - Fixed bug, CPU reset was clearing SSB through SSG 2.3 PDP-11 - Fixed bug in VH vector display routine - Fixed XU runt packet processing (found by Tim Chapman) 2.4 Interdata - Fixed bug in SHOW PAS CONN/STATS - Fixed potential integer overflow exception in divide 2.5 SDS - Fixed bug in SHOW MUX CONN/STATS 2.6 HP - Fixed bug in SHOW MUX CONN/STATS 2.7 PDP-8 - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.8 PDP-18b - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.9 Nova, Eclipse - Fixed potential integer overflow exception in divide
This commit is contained in:
committed by
Mark Pizzolato
parent
ec60bbf329
commit
b7c1eae41f
1104
ALTAIR/altair_cpu.c
1104
ALTAIR/altair_cpu.c
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/* altair_defs.h: MITS Altair simulator definitions
|
||||
|
||||
Copyright (c) 1997-2003, Charles E. Owen
|
||||
Copyright (c) 1997-2005, Charles E. Owen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,24 +19,24 @@
|
||||
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 Charles E. Owen shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
*/
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
/* Memory */
|
||||
|
||||
#define MAXMEMSIZE 65536 /* max memory size */
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */
|
||||
#define MAXMEMSIZE 65536 /* max memory size */
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */
|
||||
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
#define STOP_HALT 2 /* HALT */
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
#define STOP_HALT 2 /* HALT */
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_OPCODE 4
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* altair_dsk.c: MITS Altair 88-DISK Simulator
|
||||
|
||||
Copyright (c) 1997-2003, Charles E. Owen
|
||||
Copyright (c) 1997-2005, Charles E. Owen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,11 +19,11 @@
|
||||
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 Charles E. Owen shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
|
||||
The 88_DISK is a 8-inch floppy controller which can control up
|
||||
The 88_DISK is a 8-inch floppy controller which can control up
|
||||
to 16 daisy-chained Pertec FD-400 hard-sectored floppy drives.
|
||||
Each diskette has physically 77 tracks of 32 137-byte sectors
|
||||
each.
|
||||
@@ -31,15 +31,15 @@
|
||||
The controller is interfaced to the CPU by use of 3 I/O addreses,
|
||||
standardly, these are device numbers 10, 11, and 12 (octal).
|
||||
|
||||
Address Mode Function
|
||||
------- ---- --------
|
||||
Address Mode Function
|
||||
------- ---- --------
|
||||
|
||||
10 Out Selects and enables Controller and Drive
|
||||
10 In Indicates status of Drive and Controller
|
||||
11 Out Controls Disk Function
|
||||
11 In Indicates current sector position of disk
|
||||
12 Out Write data
|
||||
12 In Read data
|
||||
10 Out Selects and enables Controller and Drive
|
||||
10 In Indicates status of Drive and Controller
|
||||
11 Out Controls Disk Function
|
||||
11 In Indicates current sector position of disk
|
||||
12 Out Write data
|
||||
12 In Read data
|
||||
|
||||
Drive Select Out (Device 10 OUT):
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
C = If this bit is 1, the disk controller selected by 'device' is
|
||||
cleared. If the bit is zero, 'device' is selected as the
|
||||
cleared. If the bit is zero, 'device' is selected as the
|
||||
device being controlled by subsequent I/O operations.
|
||||
X = not used
|
||||
Device = value zero thru 15, selects drive to be controlled.
|
||||
@@ -80,8 +80,8 @@
|
||||
E - Enables interrupts (ignored this simulator)
|
||||
D - Disables interrupts (ignored this simulator)
|
||||
C - When 1 lowers head current (ignored this simulator)
|
||||
W - When 1, starts Write Enable sequence: W bit on device 10
|
||||
(see above) will go 1 and data will be read from port 12
|
||||
W - When 1, starts Write Enable sequence: W bit on device 10
|
||||
(see above) will go 1 and data will be read from port 12
|
||||
until 137 bytes have been read by the controller from
|
||||
that port. The W bit will go off then, and the sector data
|
||||
will be written to disk. Before you do this, you must have
|
||||
@@ -100,9 +100,9 @@
|
||||
|
||||
X = Not used
|
||||
Sector number = binary of the sector number currently under the
|
||||
head, 0-31.
|
||||
head, 0-31.
|
||||
T = Sector True, is a 1 when the sector is positioned to read or
|
||||
write.
|
||||
write.
|
||||
|
||||
*/
|
||||
|
||||
@@ -110,8 +110,8 @@
|
||||
|
||||
#include "altair_defs.h"
|
||||
|
||||
#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */
|
||||
#define UNIT_ENABLE (1 << UNIT_V_ENABLE)
|
||||
#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */
|
||||
#define UNIT_ENABLE (1 << UNIT_V_ENABLE)
|
||||
|
||||
#define DSK_SECTSIZE 137
|
||||
#define DSK_SECT 32
|
||||
@@ -128,41 +128,43 @@ extern int32 PCX;
|
||||
|
||||
/* Global data on status */
|
||||
|
||||
int32 cur_disk = 8; /* Currently selected drive */
|
||||
int32 cur_disk = 8; /* Currently selected drive */
|
||||
int32 cur_track[9] = {0, 0, 0, 0, 0, 0, 0, 0, 377};
|
||||
int32 cur_sect[9] = {0, 0, 0, 0, 0, 0, 0, 0, 377};
|
||||
int32 cur_byte[9] = {0, 0, 0, 0, 0, 0, 0, 0, 377};
|
||||
int32 cur_flags[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
char dskbuf[137]; /* Data Buffer */
|
||||
int32 dirty = 0; /* 1 when buffer has unwritten data in it */
|
||||
UNIT *dptr; /* fileref to write dirty buffer to */
|
||||
char dskbuf[137]; /* Data Buffer */
|
||||
int32 dirty = 0; /* 1 when buffer has unwritten data in it */
|
||||
UNIT *dptr; /* fileref to write dirty buffer to */
|
||||
|
||||
int32 dsk_rwait = 100; /* rotate latency */
|
||||
int32 dsk_rwait = 100; /* rotate latency */
|
||||
|
||||
|
||||
/* 88DSK Standard I/O Data Structures */
|
||||
|
||||
UNIT dsk_unit[] = {
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }
|
||||
};
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }
|
||||
};
|
||||
|
||||
REG dsk_reg[] = {
|
||||
{ ORDATA (DISK, cur_disk, 4) },
|
||||
{ NULL } };
|
||||
{ ORDATA (DISK, cur_disk, 4) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE dsk_dev = {
|
||||
"DSK", dsk_unit, dsk_reg, NULL,
|
||||
8, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &dsk_reset,
|
||||
NULL, NULL, NULL };
|
||||
"DSK", dsk_unit, dsk_reg, NULL,
|
||||
8, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &dsk_reset,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
/* Service routines to handle simlulator functions */
|
||||
|
||||
@@ -181,19 +183,19 @@ cur_disk = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* I/O instruction handlers, called from the CPU module when an
|
||||
IN or OUT instruction is issued.
|
||||
/* I/O instruction handlers, called from the CPU module when an
|
||||
IN or OUT instruction is issued.
|
||||
|
||||
Each function is passed an 'io' flag, where 0 means a read from
|
||||
the port, and 1 means a write to the port. On input, the actual
|
||||
Each function is passed an 'io' flag, where 0 means a read from
|
||||
the port, and 1 means a write to the port. On input, the actual
|
||||
input is passed as the return value, on output, 'data' is written
|
||||
to the device.
|
||||
*/
|
||||
|
||||
/* Disk Controller Status/Select */
|
||||
|
||||
/* IMPORTANT: The status flags read by port 8 IN instruction are
|
||||
INVERTED, that is, 0 is true and 1 is false. To handle this, the
|
||||
/* IMPORTANT: The status flags read by port 8 IN instruction are
|
||||
INVERTED, that is, 0 is true and 1 is false. To handle this, the
|
||||
simulator keeps it's own status flags as 0=false, 1=true; and
|
||||
returns the COMPLEMENT of the status flags when read. This makes
|
||||
setting/testing of the flag bits more logical, yet meets the
|
||||
@@ -203,28 +205,28 @@ return SCPE_OK;
|
||||
int32 dsk10(int32 io, int32 data)
|
||||
{
|
||||
|
||||
if (io == 0) { /* IN: return flags */
|
||||
return ((~cur_flags[cur_disk]) & 0xFF); /* Return the COMPLEMENT! */
|
||||
if (io == 0) { /* IN: return flags */
|
||||
return ((~cur_flags[cur_disk]) & 0xFF); /* Return the COMPLEMENT! */
|
||||
}
|
||||
|
||||
/* OUT: Controller set/reset/enable/disable */
|
||||
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
writebuf();
|
||||
|
||||
/*printf("\n[%o] OUT 10: %x", PCX, data);*/
|
||||
cur_disk = data & 0x0F;
|
||||
if (data & 0x80) {
|
||||
cur_flags[cur_disk] = 0; /* Disable drive */
|
||||
cur_flags[cur_disk] = 0; /* Disable drive */
|
||||
cur_sect[cur_disk = 0377];
|
||||
cur_byte[cur_disk = 0377];
|
||||
return (0);
|
||||
}
|
||||
cur_flags[cur_disk] = 0x1A; /* Enable: head move true */
|
||||
cur_sect[cur_disk] = 0377; /* reset internal counters */
|
||||
cur_flags[cur_disk] = 0x1A; /* Enable: head move true */
|
||||
cur_sect[cur_disk] = 0377; /* reset internal counters */
|
||||
cur_byte[cur_disk] = 0377;
|
||||
if (cur_track[cur_disk] == 0)
|
||||
cur_flags[cur_disk] |= 0x40; /* track 0 if there */
|
||||
cur_flags[cur_disk] |= 0x40; /* track 0 if there */
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -232,74 +234,74 @@ int32 dsk10(int32 io, int32 data)
|
||||
|
||||
int32 dsk11(int32 io, int32 data)
|
||||
{
|
||||
int32 stat;
|
||||
int32 stat;
|
||||
|
||||
if (io == 0) { /* Read sector position */
|
||||
/*printf("\n[%o] IN 11", PCX);*/
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
if (cur_flags[cur_disk] & 0x04) { /* head loaded? */
|
||||
if (io == 0) { /* Read sector position */
|
||||
/*printf("\n[%o] IN 11", PCX);*/
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
if (cur_flags[cur_disk] & 0x04) { /* head loaded? */
|
||||
cur_sect[cur_disk]++;
|
||||
if (cur_sect[cur_disk] > 31)
|
||||
cur_sect[cur_disk] = 0;
|
||||
cur_sect[cur_disk] = 0;
|
||||
cur_byte[cur_disk] = 0377;
|
||||
stat = cur_sect[cur_disk] << 1;
|
||||
stat &= 0x3E; /* return 'sector true' bit = 0 (true) */
|
||||
stat |= 0xC0; /* set on 'unused' bits */
|
||||
stat = cur_sect[cur_disk] << 1;
|
||||
stat &= 0x3E; /* return 'sector true' bit = 0 (true) */
|
||||
stat |= 0xC0; /* set on 'unused' bits */
|
||||
return (stat);
|
||||
} else {
|
||||
return (0); /* head not loaded - return 0 */
|
||||
return (0); /* head not loaded - return 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/* Drive functions */
|
||||
|
||||
if (cur_disk > 7)
|
||||
return (0); /* no drive selected - can do nothin */
|
||||
return (0); /* no drive selected - can do nothin */
|
||||
|
||||
/*printf("\n[%o] OUT 11: %x", PCX, data);*/
|
||||
if (data & 0x01) { /* Step head in */
|
||||
cur_track[cur_disk]++;
|
||||
if (data & 0x01) { /* Step head in */
|
||||
cur_track[cur_disk]++;
|
||||
if (cur_track[cur_disk] > 76 )
|
||||
cur_track[cur_disk] = 76;
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
cur_track[cur_disk] = 76;
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
cur_sect[cur_disk] = 0377;
|
||||
cur_byte[cur_disk] = 0377;
|
||||
}
|
||||
|
||||
if (data & 0x02) { /* Step head out */
|
||||
cur_track[cur_disk]--;
|
||||
if (data & 0x02) { /* Step head out */
|
||||
cur_track[cur_disk]--;
|
||||
if (cur_track[cur_disk] < 0) {
|
||||
cur_track[cur_disk] = 0;
|
||||
cur_flags[cur_disk] |= 0x40; /* track 0 if there */
|
||||
cur_track[cur_disk] = 0;
|
||||
cur_flags[cur_disk] |= 0x40; /* track 0 if there */
|
||||
}
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
cur_sect[cur_disk] = 0377;
|
||||
cur_byte[cur_disk] = 0377;
|
||||
}
|
||||
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
writebuf();
|
||||
|
||||
if (data & 0x04) { /* Head load */
|
||||
cur_flags[cur_disk] |= 0x04; /* turn on head loaded bit */
|
||||
cur_flags[cur_disk] |= 0x80; /* turn on 'read data available */
|
||||
if (data & 0x04) { /* Head load */
|
||||
cur_flags[cur_disk] |= 0x04; /* turn on head loaded bit */
|
||||
cur_flags[cur_disk] |= 0x80; /* turn on 'read data available */
|
||||
}
|
||||
|
||||
if (data & 0x08) { /* Head Unload */
|
||||
cur_flags[cur_disk] &= 0xFB; /* off on 'head loaded' */
|
||||
cur_flags[cur_disk] &= 0x7F; /* off on 'read data avail */
|
||||
if (data & 0x08) { /* Head Unload */
|
||||
cur_flags[cur_disk] &= 0xFB; /* off on 'head loaded' */
|
||||
cur_flags[cur_disk] &= 0x7F; /* off on 'read data avail */
|
||||
cur_sect[cur_disk] = 0377;
|
||||
cur_byte[cur_disk] = 0377;
|
||||
}
|
||||
|
||||
/* Interrupts & head current are ignored */
|
||||
|
||||
if (data & 0x80) { /* write sequence start */
|
||||
if (data & 0x80) { /* write sequence start */
|
||||
cur_byte[cur_disk] = 0;
|
||||
cur_flags[cur_disk] |= 0x01; /* enter new write data on */
|
||||
cur_flags[cur_disk] |= 0x01; /* enter new write data on */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -308,19 +310,19 @@ int32 dsk11(int32 io, int32 data)
|
||||
|
||||
int32 dsk12(int32 io, int32 data)
|
||||
{
|
||||
static int32 rtn, i;
|
||||
static int32 rtn, i;
|
||||
static long pos;
|
||||
UNIT *uptr;
|
||||
|
||||
uptr = dsk_dev.units + cur_disk;
|
||||
if (io == 0) {
|
||||
if ((i = cur_byte[cur_disk]) < 138) { /* just get from buffer */
|
||||
cur_byte[cur_disk]++;
|
||||
return (dskbuf[i] & 0xFF);
|
||||
if ((i = cur_byte[cur_disk]) < 138) { /* just get from buffer */
|
||||
cur_byte[cur_disk]++;
|
||||
return (dskbuf[i] & 0xFF);
|
||||
}
|
||||
/* physically read the sector */
|
||||
/*printf("\n[%o] IN 12 (READ) T%d S%d", PCX, cur_track[cur_disk],
|
||||
cur_sect[cur_disk]);*/
|
||||
cur_sect[cur_disk]);*/
|
||||
pos = DSK_TRACSIZE * cur_track[cur_disk];
|
||||
pos += DSK_SECTSIZE * cur_sect[cur_disk];
|
||||
rtn = fseek(uptr -> fileref, pos, 0);
|
||||
@@ -328,9 +330,9 @@ int32 dsk12(int32 io, int32 data)
|
||||
cur_byte[cur_disk] = 1;
|
||||
return (dskbuf[0] & 0xFF);
|
||||
} else {
|
||||
if (cur_byte[cur_disk] > 136) {
|
||||
i = cur_byte[cur_disk];
|
||||
dskbuf[i] = data & 0xFF;
|
||||
if (cur_byte[cur_disk] > 136) {
|
||||
i = cur_byte[cur_disk];
|
||||
dskbuf[i] = data & 0xFF;
|
||||
writebuf();
|
||||
return (0);
|
||||
}
|
||||
@@ -345,21 +347,21 @@ int32 dsk12(int32 io, int32 data)
|
||||
|
||||
void writebuf()
|
||||
{
|
||||
long pos;
|
||||
long pos;
|
||||
int32 rtn, i;
|
||||
|
||||
i = cur_byte[cur_disk]; /* null-fill rest of sector if any */
|
||||
i = cur_byte[cur_disk]; /* null-fill rest of sector if any */
|
||||
while (i < 138) {
|
||||
dskbuf[i] = 0;
|
||||
dskbuf[i] = 0;
|
||||
i++;
|
||||
}
|
||||
/*printf("\n[%o] OUT 12 (WRITE) T%d S%d", PCX, cur_track[cur_disk],
|
||||
cur_sect[cur_disk]); i = getch(); */
|
||||
pos = DSK_TRACSIZE * cur_track[cur_disk]; /* calc file pos */
|
||||
cur_sect[cur_disk]); i = getch(); */
|
||||
pos = DSK_TRACSIZE * cur_track[cur_disk]; /* calc file pos */
|
||||
pos += DSK_SECTSIZE * cur_sect[cur_disk];
|
||||
rtn = fseek(dptr -> fileref, pos, 0);
|
||||
rtn = fwrite(dskbuf, 137, 1, dptr -> fileref);
|
||||
cur_flags[cur_disk] &= 0xFE; /* ENWD off */
|
||||
cur_flags[cur_disk] &= 0xFE; /* ENWD off */
|
||||
cur_byte[cur_disk] = 0377;
|
||||
dirty = 0;
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* altair_sio: MITS Altair serial I/O card
|
||||
|
||||
Copyright (c) 1997-2003, Charles E. Owen
|
||||
Copyright (c) 1997-2005, Charles E. Owen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,11 +19,11 @@
|
||||
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 Charles E. Owen shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
|
||||
These functions support a simulated MITS 2SIO interface card.
|
||||
These functions support a simulated MITS 2SIO interface card.
|
||||
The card had two physical I/O ports which could be connected
|
||||
to any serial I/O device that would connect to a current loop,
|
||||
RS232, or TTY interface. Available baud rates were jumper
|
||||
@@ -35,13 +35,13 @@
|
||||
A read of the status port gets the port status:
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| X X X X X X O I |
|
||||
| X X X X X X O I |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
I - A 1 in this bit position means a character has been received
|
||||
on the data port and is ready to be read.
|
||||
I - A 1 in this bit position means a character has been received
|
||||
on the data port and is ready to be read.
|
||||
O - A 1 in this bit means the port is ready to receive a character
|
||||
on the data port and transmit it out over the serial line.
|
||||
on the data port and transmit it out over the serial line.
|
||||
|
||||
A read to the data port gets the buffered character, a write
|
||||
to the data port writes the character to the device.
|
||||
@@ -51,8 +51,8 @@
|
||||
|
||||
#include "altair_defs.h"
|
||||
|
||||
#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */
|
||||
#define UNIT_ANSI (1 << UNIT_V_ANSI)
|
||||
#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */
|
||||
#define UNIT_ANSI (1 << UNIT_V_ANSI)
|
||||
|
||||
t_stat sio_svc (UNIT *uptr);
|
||||
t_stat sio_reset (DEVICE *dptr);
|
||||
@@ -61,77 +61,81 @@ t_stat ptr_reset (DEVICE *dptr);
|
||||
t_stat ptp_svc (UNIT *uptr);
|
||||
t_stat ptp_reset (DEVICE *dptr);
|
||||
|
||||
int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
|
||||
/* 2SIO Standard I/O Data Structures */
|
||||
|
||||
UNIT sio_unit = { UDATA (&sio_svc, 0, 0),
|
||||
KBD_POLL_WAIT };
|
||||
UNIT sio_unit = { UDATA (&sio_svc, 0, 0), KBD_POLL_WAIT };
|
||||
|
||||
REG sio_reg[] = {
|
||||
{ ORDATA (DATA, sio_unit.buf, 8) },
|
||||
{ ORDATA (STAT, sio_unit.u3, 8) },
|
||||
{ NULL } };
|
||||
{ ORDATA (DATA, sio_unit.buf, 8) },
|
||||
{ ORDATA (STAT, sio_unit.u3, 8) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB sio_mod[] = {
|
||||
{ UNIT_ANSI, 0, "TTY", "TTY", NULL },
|
||||
{ UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL },
|
||||
{ 0 } };
|
||||
{ UNIT_ANSI, 0, "TTY", "TTY", NULL },
|
||||
{ UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE sio_dev = {
|
||||
"2SIO", &sio_unit, sio_reg, sio_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &sio_reset,
|
||||
NULL, NULL, NULL };
|
||||
"2SIO", &sio_unit, sio_reg, sio_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &sio_reset,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ + UNIT_ATTABLE, 0),
|
||||
KBD_POLL_WAIT };
|
||||
UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ + UNIT_ATTABLE, 0), KBD_POLL_WAIT };
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (DATA, ptr_unit.buf, 8) },
|
||||
{ ORDATA (STAT, ptr_unit.u3, 8) },
|
||||
{ ORDATA (POS, ptr_unit.pos, T_ADDR_W) },
|
||||
{ NULL } };
|
||||
{ ORDATA (DATA, ptr_unit.buf, 8) },
|
||||
{ ORDATA (STAT, ptr_unit.u3, 8) },
|
||||
{ ORDATA (POS, ptr_unit.pos, T_ADDR_W) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE ptr_dev = {
|
||||
"PTR", &ptr_unit, ptr_reg, NULL,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptr_reset,
|
||||
NULL, NULL, NULL };
|
||||
"PTR", &ptr_unit, ptr_reg, NULL,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptr_reset,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ + UNIT_ATTABLE, 0),
|
||||
KBD_POLL_WAIT };
|
||||
UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ + UNIT_ATTABLE, 0), KBD_POLL_WAIT };
|
||||
|
||||
REG ptp_reg[] = {
|
||||
{ ORDATA (DATA, ptp_unit.buf, 8) },
|
||||
{ ORDATA (STAT, ptp_unit.u3, 8) },
|
||||
{ ORDATA (POS, ptp_unit.pos, T_ADDR_W) },
|
||||
{ NULL } };
|
||||
{ ORDATA (DATA, ptp_unit.buf, 8) },
|
||||
{ ORDATA (STAT, ptp_unit.u3, 8) },
|
||||
{ ORDATA (POS, ptp_unit.pos, T_ADDR_W) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE ptp_dev = {
|
||||
"PTP", &ptp_unit, ptp_reg, NULL,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptp_reset,
|
||||
NULL, NULL, NULL };
|
||||
"PTP", &ptp_unit, ptp_reg, NULL,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptp_reset,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
/* Service routines to handle simulator functions */
|
||||
/* Service routines to handle simulator functions */
|
||||
|
||||
/* service routine - actually gets char & places in buffer */
|
||||
|
||||
int32 sio_svc (UNIT *uptr)
|
||||
{
|
||||
int32 temp;
|
||||
int32 temp;
|
||||
|
||||
sim_activate (&sio_unit, sio_unit.wait); /* continue poll */
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG)
|
||||
return temp; /* no char or error? */
|
||||
sio_unit.buf = temp & 0377; /* Save char */
|
||||
sio_unit.u3 |= 0x01; /* Set status */
|
||||
sim_activate (&sio_unit, sio_unit.wait); /* continue poll */
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG)
|
||||
return temp; /* no char or error? */
|
||||
sio_unit.buf = temp & 0377; /* Save char */
|
||||
sio_unit.u3 |= 0x01; /* Set status */
|
||||
|
||||
/* Do any special character handling here */
|
||||
/* Do any special character handling here */
|
||||
|
||||
sio_unit.pos++;
|
||||
return SCPE_OK;
|
||||
sio_unit.pos++;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +146,7 @@ int32 ptr_svc (UNIT *uptr)
|
||||
|
||||
int32 ptp_svc (UNIT *uptr)
|
||||
{
|
||||
return SCPE_OK;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -150,60 +154,60 @@ int32 ptp_svc (UNIT *uptr)
|
||||
|
||||
int32 sio_reset (DEVICE *dptr)
|
||||
{
|
||||
sio_unit.buf = 0; /* Data */
|
||||
sio_unit.u3 = 0x02; /* Status */
|
||||
sim_activate (&sio_unit, sio_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
sio_unit.buf = 0; /* Data */
|
||||
sio_unit.u3 = 0x02; /* Status */
|
||||
sim_activate (&sio_unit, sio_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
int32 ptr_reset (DEVICE *dptr)
|
||||
{
|
||||
ptr_unit.buf = 0;
|
||||
ptr_unit.u3 = 0x02;
|
||||
sim_cancel (&ptr_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
ptr_unit.buf = 0;
|
||||
ptr_unit.u3 = 0x02;
|
||||
sim_cancel (&ptr_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
int32 ptp_reset (DEVICE *dptr)
|
||||
{
|
||||
ptp_unit.buf = 0;
|
||||
ptp_unit.u3 = 0x02;
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
ptp_unit.buf = 0;
|
||||
ptp_unit.u3 = 0x02;
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* I/O instruction handlers, called from the CPU module when an
|
||||
IN or OUT instruction is issued.
|
||||
/* I/O instruction handlers, called from the CPU module when an
|
||||
IN or OUT instruction is issued.
|
||||
|
||||
Each function is passed an 'io' flag, where 0 means a read from
|
||||
the port, and 1 means a write to the port. On input, the actual
|
||||
Each function is passed an 'io' flag, where 0 means a read from
|
||||
the port, and 1 means a write to the port. On input, the actual
|
||||
input is passed as the return value, on output, 'data' is written
|
||||
to the device.
|
||||
*/
|
||||
|
||||
int32 sio0s(int32 io, int32 data)
|
||||
{
|
||||
if (io == 0) {
|
||||
if (io == 0) {
|
||||
return (sio_unit.u3);
|
||||
} else {
|
||||
if (data == 0x03) { /* reset port! */
|
||||
sio_unit.u3 = 0x02;
|
||||
if (data == 0x03) { /* reset port! */
|
||||
sio_unit.u3 = 0x02;
|
||||
sio_unit.buf = 0;
|
||||
sio_unit.pos = 0;
|
||||
}
|
||||
return (0);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
int32 sio0d(int32 io, int32 data)
|
||||
{
|
||||
if (io == 0) {
|
||||
if (io == 0) {
|
||||
sio_unit.u3 = sio_unit.u3 & 0xFE;
|
||||
return (sio_unit.buf);
|
||||
} else {
|
||||
sim_putchar(data);
|
||||
sim_putchar(data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -212,46 +216,46 @@ int32 sio0d(int32 io, int32 data)
|
||||
|
||||
int32 sio1s(int32 io, int32 data)
|
||||
{
|
||||
if (io == 0) {
|
||||
if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return 0x02;
|
||||
if (ptr_unit.u3 != 0) /* No more data? */
|
||||
return 0x02;
|
||||
return (0x03); /* ready to read/write */
|
||||
if (io == 0) {
|
||||
if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return 0x02;
|
||||
if (ptr_unit.u3 != 0) /* No more data? */
|
||||
return 0x02;
|
||||
return (0x03); /* ready to read/write */
|
||||
} else {
|
||||
if (data == 0x03) {
|
||||
ptr_unit.u3 = 0;
|
||||
if (data == 0x03) {
|
||||
ptr_unit.u3 = 0;
|
||||
ptr_unit.buf = 0;
|
||||
ptr_unit.pos = 0;
|
||||
ptp_unit.u3 = 0;
|
||||
ptp_unit.u3 = 0;
|
||||
ptp_unit.buf = 0;
|
||||
ptp_unit.pos = 0;
|
||||
}
|
||||
return (0);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
int32 sio1d(int32 io, int32 data)
|
||||
{
|
||||
int32 temp;
|
||||
int32 temp;
|
||||
UNIT *uptr;
|
||||
|
||||
if (io == 0) {
|
||||
if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
if (io == 0) {
|
||||
if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return 0;
|
||||
if (ptr_unit.u3 != 0)
|
||||
return 0;
|
||||
return 0;
|
||||
uptr = ptr_dev.units;
|
||||
if ((temp = getc(uptr -> fileref)) == EOF) { /* end of file? */
|
||||
if ((temp = getc(uptr -> fileref)) == EOF) { /* end of file? */
|
||||
ptr_unit.u3 = 0x01;
|
||||
return 0;
|
||||
}
|
||||
ptr_unit.pos++;
|
||||
ptr_unit.pos++;
|
||||
return (temp & 0xFF);
|
||||
} else {
|
||||
uptr = ptp_dev.units;
|
||||
putc(data, uptr -> fileref);
|
||||
ptp_unit.pos++;
|
||||
uptr = ptp_dev.units;
|
||||
putc(data, uptr -> fileref);
|
||||
ptp_unit.pos++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* altair_sys.c: MITS Altair system interface
|
||||
|
||||
Copyright (c) 1997-2003, Charles E. Owen
|
||||
Copyright (c) 1997-2005, Charles E. Owen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,8 +19,8 @@
|
||||
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 Charles E. Owen shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Charles E. Owen shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Charles E. Owen.
|
||||
*/
|
||||
|
||||
@@ -40,12 +40,12 @@ extern int32 saved_PC;
|
||||
|
||||
/* SCP data structures
|
||||
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words needed for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words needed for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "Altair 8800";
|
||||
@@ -54,81 +54,88 @@ REG *sim_PC = &cpu_reg[0];
|
||||
|
||||
int32 sim_emax = 4;
|
||||
|
||||
DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptr_dev,
|
||||
&ptp_dev, &dsk_dev, NULL };
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&sio_dev,
|
||||
&ptr_dev,
|
||||
&ptp_dev,
|
||||
&dsk_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
"Unknown error",
|
||||
"Unknown error",
|
||||
"Unknown I/O Instruction",
|
||||
"HALT instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Invalid Opcode" };
|
||||
"Invalid Opcode"
|
||||
};
|
||||
|
||||
static const char *opcode[] = {
|
||||
"NOP", "LXI B", "STAX B", "INX B", /* 000-003 */
|
||||
"INR B", "DCR B", "MVI B", "RLC", /* 004-007 */
|
||||
"???", "DAD B", "LDAX B", "DCX B", /* 010-013 */
|
||||
"INR C", "DCR C", "MVI C", "RRC", /* 014-017 */
|
||||
"???", "LXI D", "STAX D", "INX D", /* 020-023 */
|
||||
"INR D", "DCR D", "MVI D", "RAL", /* 024-027 */
|
||||
"???", "DAD D", "LDAX D", "DCX D", /* 030-033 */
|
||||
"INR E", "DCR E", "MVI E", "RAR", /* 034-037 */
|
||||
"???", "LXI H", "SHLD", "INX H", /* 040-043 */
|
||||
"INR H", "DCR H", "MVI H", "DAA", /* 044-047 */
|
||||
"???", "DAD H", "LHLD", "DCX H", /* 050-053 */
|
||||
"INR L", "DCR L", "MVI L", "CMA", /* 054-057 */
|
||||
"???", "LXI SP", "STA", "INX SP", /* 060-063 */
|
||||
"INR M", "DCR M", "MVI M", "STC", /* 064-067 */
|
||||
"???", "DAD SP", "LDA", "DCX SP", /* 070-073 */
|
||||
"INR A", "DCR A", "MVI A", "CMC", /* 074-077 */
|
||||
"MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", /* 100-103 */
|
||||
"MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 104-107 */
|
||||
"MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", /* 110-113 */
|
||||
"MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 114-117 */
|
||||
"MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", /* 120-123 */
|
||||
"MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 124-127 */
|
||||
"MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", /* 130-133 */
|
||||
"MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", /* 134-137 */
|
||||
"MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", /* 140-143 */
|
||||
"MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", /* 144-147 */
|
||||
"MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", /* 150-153 */
|
||||
"MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", /* 154-157 */
|
||||
"MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", /* 160-163 */
|
||||
"MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 164-167 */
|
||||
"MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", /* 170-173 */
|
||||
"MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", /* 174-177 */
|
||||
"ADD B", "ADD C", "ADD D", "ADD E", /* 200-203 */
|
||||
"ADD H", "ADD L", "ADD M", "ADD A", /* 204-207 */
|
||||
"ADC B", "ADC C", "ADC D", "ADC E", /* 210-213 */
|
||||
"ADC H", "ADC L", "ADC M", "ADC A", /* 214-217 */
|
||||
"SUB B", "SUB C", "SUB D", "SUB E", /* 220-223 */
|
||||
"SUB H", "SUB L", "SUB M", "SUB A", /* 224-227 */
|
||||
"SBB B", "SBB C", "SBB D", "SBB E", /* 230-233 */
|
||||
"SBB H", "SBB L", "SBB M", "SBB A", /* 234-237 */
|
||||
"ANA B", "ANA C", "ANA D", "ANA E", /* 240-243 */
|
||||
"ANA H", "ANA L", "ANA M", "ANA A", /* 244-247 */
|
||||
"XRA B", "XRA C", "XRA D", "XRA E", /* 250-253 */
|
||||
"XRA H", "XRA L", "XRA M", "XRA A", /* 254-257 */
|
||||
"ORA B", "ORA C", "ORA D", "ORA E", /* 260-263 */
|
||||
"ORA H", "ORA L", "ORA M", "ORA A", /* 264-267 */
|
||||
"CMP B", "CMP C", "CMP D", "CMP E", /* 270-273 */
|
||||
"CMP H", "CMP L", "CMP M", "CMP A", /* 274-277 */
|
||||
"RNZ", "POP B", "JNZ", "JMP", /* 300-303 */
|
||||
"CNZ", "PUSH B", "ADI", "RST 0", /* 304-307 */
|
||||
"RZ", "RET", "JZ", "???", /* 310-313 */
|
||||
"CZ", "CALL", "ACI", "RST 1", /* 314-317 */
|
||||
"RNC", "POP D", "JNC", "OUT", /* 320-323 */
|
||||
"CNC", "PUSH D", "SUI", "RST 2", /* 324-327 */
|
||||
"RC", "???", "JC", "IN", /* 330-333 */
|
||||
"CC", "???", "SBI", "RST 3", /* 334-337 */
|
||||
"RPO", "POP H", "JPO", "XTHL", /* 340-343 */
|
||||
"CPO", "PUSH H", "ANI", "RST 4", /* 344-347 */
|
||||
"RPE", "PCHL", "JPE", "XCHG", /* 350-353 */
|
||||
"CPE", "???", "XRI", "RST 5", /* 354-357 */
|
||||
"RP", "POP PSW", "JP", "DI", /* 360-363 */
|
||||
"CP", "PUSH PSW", "ORI", "RST 6", /* 364-367 */
|
||||
"RM", "SPHL", "JM", "EI", /* 370-373 */
|
||||
"CM", "???", "CPI", "RST 7", /* 374-377 */
|
||||
"NOP", "LXI B", "STAX B", "INX B", /* 000-003 */
|
||||
"INR B", "DCR B", "MVI B", "RLC", /* 004-007 */
|
||||
"???", "DAD B", "LDAX B", "DCX B", /* 010-013 */
|
||||
"INR C", "DCR C", "MVI C", "RRC", /* 014-017 */
|
||||
"???", "LXI D", "STAX D", "INX D", /* 020-023 */
|
||||
"INR D", "DCR D", "MVI D", "RAL", /* 024-027 */
|
||||
"???", "DAD D", "LDAX D", "DCX D", /* 030-033 */
|
||||
"INR E", "DCR E", "MVI E", "RAR", /* 034-037 */
|
||||
"???", "LXI H", "SHLD", "INX H", /* 040-043 */
|
||||
"INR H", "DCR H", "MVI H", "DAA", /* 044-047 */
|
||||
"???", "DAD H", "LHLD", "DCX H", /* 050-053 */
|
||||
"INR L", "DCR L", "MVI L", "CMA", /* 054-057 */
|
||||
"???", "LXI SP", "STA", "INX SP", /* 060-063 */
|
||||
"INR M", "DCR M", "MVI M", "STC", /* 064-067 */
|
||||
"???", "DAD SP", "LDA", "DCX SP", /* 070-073 */
|
||||
"INR A", "DCR A", "MVI A", "CMC", /* 074-077 */
|
||||
"MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", /* 100-103 */
|
||||
"MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 104-107 */
|
||||
"MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", /* 110-113 */
|
||||
"MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 114-117 */
|
||||
"MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", /* 120-123 */
|
||||
"MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 124-127 */
|
||||
"MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", /* 130-133 */
|
||||
"MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", /* 134-137 */
|
||||
"MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", /* 140-143 */
|
||||
"MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", /* 144-147 */
|
||||
"MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", /* 150-153 */
|
||||
"MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", /* 154-157 */
|
||||
"MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", /* 160-163 */
|
||||
"MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 164-167 */
|
||||
"MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", /* 170-173 */
|
||||
"MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", /* 174-177 */
|
||||
"ADD B", "ADD C", "ADD D", "ADD E", /* 200-203 */
|
||||
"ADD H", "ADD L", "ADD M", "ADD A", /* 204-207 */
|
||||
"ADC B", "ADC C", "ADC D", "ADC E", /* 210-213 */
|
||||
"ADC H", "ADC L", "ADC M", "ADC A", /* 214-217 */
|
||||
"SUB B", "SUB C", "SUB D", "SUB E", /* 220-223 */
|
||||
"SUB H", "SUB L", "SUB M", "SUB A", /* 224-227 */
|
||||
"SBB B", "SBB C", "SBB D", "SBB E", /* 230-233 */
|
||||
"SBB H", "SBB L", "SBB M", "SBB A", /* 234-237 */
|
||||
"ANA B", "ANA C", "ANA D", "ANA E", /* 240-243 */
|
||||
"ANA H", "ANA L", "ANA M", "ANA A", /* 244-247 */
|
||||
"XRA B", "XRA C", "XRA D", "XRA E", /* 250-253 */
|
||||
"XRA H", "XRA L", "XRA M", "XRA A", /* 254-257 */
|
||||
"ORA B", "ORA C", "ORA D", "ORA E", /* 260-263 */
|
||||
"ORA H", "ORA L", "ORA M", "ORA A", /* 264-267 */
|
||||
"CMP B", "CMP C", "CMP D", "CMP E", /* 270-273 */
|
||||
"CMP H", "CMP L", "CMP M", "CMP A", /* 274-277 */
|
||||
"RNZ", "POP B", "JNZ", "JMP", /* 300-303 */
|
||||
"CNZ", "PUSH B", "ADI", "RST 0", /* 304-307 */
|
||||
"RZ", "RET", "JZ", "???", /* 310-313 */
|
||||
"CZ", "CALL", "ACI", "RST 1", /* 314-317 */
|
||||
"RNC", "POP D", "JNC", "OUT", /* 320-323 */
|
||||
"CNC", "PUSH D", "SUI", "RST 2", /* 324-327 */
|
||||
"RC", "???", "JC", "IN", /* 330-333 */
|
||||
"CC", "???", "SBI", "RST 3", /* 334-337 */
|
||||
"RPO", "POP H", "JPO", "XTHL", /* 340-343 */
|
||||
"CPO", "PUSH H", "ANI", "RST 4", /* 344-347 */
|
||||
"RPE", "PCHL", "JPE", "XCHG", /* 350-353 */
|
||||
"CPE", "???", "XRI", "RST 5", /* 354-357 */
|
||||
"RP", "POP PSW", "JP", "DI", /* 360-363 */
|
||||
"CP", "PUSH PSW", "ORI", "RST 6", /* 364-367 */
|
||||
"RM", "SPHL", "JM", "EI", /* 370-373 */
|
||||
"CM", "???", "CPI", "RST 7", /* 374-377 */
|
||||
};
|
||||
|
||||
int32 oplen[256] = {
|
||||
@@ -140,7 +147,7 @@ int32 oplen[256] = {
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,3,3,3,1,2,1,1,1,3,0,3,3,2,1,1,1,3,2,3,1,2,1,1,0,3,2,3,0,2,1,
|
||||
1,1,3,1,3,1,2,1,1,1,3,1,3,0,2,1,1,1,3,1,3,1,2,1,1,1,3,1,3,0,2,1 };
|
||||
|
||||
|
||||
/* This is the binary loader. The input file is considered to be
|
||||
a string of literal bytes with no format special format. The
|
||||
load starts at the current value of the PC.
|
||||
@@ -153,28 +160,28 @@ int32 i, addr = 0, cnt = 0;
|
||||
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
||||
addr = saved_PC;
|
||||
while ((i = getc (fileref)) != EOF) {
|
||||
M[addr] = i;
|
||||
addr++;
|
||||
cnt++;
|
||||
} /* end while */
|
||||
M[addr] = i;
|
||||
addr++;
|
||||
cnt++;
|
||||
} /* end while */
|
||||
printf ("%d Bytes loaded.\n", cnt);
|
||||
return (SCPE_OK);
|
||||
}
|
||||
|
||||
|
||||
/* Symbolic output
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = pointer to values
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = pointer to values
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
status = error code
|
||||
status = error code
|
||||
*/
|
||||
|
||||
int32 fprint_sym (FILE *of, int32 addr, uint32 *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 cflag, c1, c2, inst, adr;
|
||||
|
||||
@@ -182,42 +189,44 @@ cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
c1 = (val[0] >> 8) & 0177;
|
||||
c2 = val[0] & 0177;
|
||||
if (sw & SWMASK ('A')) {
|
||||
fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
|
||||
return SCPE_OK; }
|
||||
fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (sw & SWMASK ('C')) {
|
||||
fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
|
||||
fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
|
||||
return SCPE_OK; }
|
||||
fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
|
||||
fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
|
||||
inst = val[0];
|
||||
fprintf (of, "%s", opcode[inst]);
|
||||
if (oplen[inst] == 2) {
|
||||
if (strchr(opcode[inst], ' ') != NULL)
|
||||
fprintf (of, ",");
|
||||
else fprintf (of, " ");
|
||||
fprintf (of, "%o", val[1]);
|
||||
if (strchr(opcode[inst], ' ') != NULL)
|
||||
fprintf (of, ",");
|
||||
else fprintf (of, " ");
|
||||
fprintf (of, "%o", val[1]);
|
||||
}
|
||||
if (oplen[inst] == 3) {
|
||||
adr = val[1] & 0xFF;
|
||||
adr |= (val[2] << 8) & 0xff00;
|
||||
if (strchr(opcode[inst], ' ') != NULL)
|
||||
fprintf (of, ",");
|
||||
else fprintf (of, " ");
|
||||
if (strchr(opcode[inst], ' ') != NULL)
|
||||
fprintf (of, ",");
|
||||
else fprintf (of, " ");
|
||||
fprintf (of, "%o", adr);
|
||||
}
|
||||
return -(oplen[inst] - 1);
|
||||
}
|
||||
|
||||
|
||||
/* Symbolic input
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*uptr = pointer to unit
|
||||
*val = pointer to output values
|
||||
sw = switches
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*uptr = pointer to unit
|
||||
*val = pointer to output values
|
||||
sw = switches
|
||||
Outputs:
|
||||
status = error status
|
||||
status = error status
|
||||
*/
|
||||
|
||||
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw)
|
||||
@@ -226,25 +235,27 @@ int32 cflag, i = 0, j, r;
|
||||
char gbuf[CBUFSIZE];
|
||||
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = (uint32) cptr[0];
|
||||
return SCPE_OK; }
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = (uint32) cptr[0];
|
||||
return SCPE_OK;
|
||||
}
|
||||
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = ((uint32) cptr[0] << 8) + (uint32) cptr[1];
|
||||
return SCPE_OK; }
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
val[0] = ((uint32) cptr[0] << 8) + (uint32) cptr[1];
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* An instruction: get opcode (all characters until null, comma,
|
||||
or numeric (including spaces).
|
||||
*/
|
||||
|
||||
while (1) {
|
||||
if (*cptr == ',' || *cptr == '\0' ||
|
||||
isdigit(*cptr))
|
||||
break;
|
||||
gbuf[i] = toupper(*cptr);
|
||||
if (*cptr == ',' || *cptr == '\0' ||
|
||||
isdigit(*cptr))
|
||||
break;
|
||||
gbuf[i] = toupper(*cptr);
|
||||
cptr++;
|
||||
i++;
|
||||
}
|
||||
@@ -252,9 +263,9 @@ while (1) {
|
||||
/* Allow for RST which has numeric as part of opcode */
|
||||
|
||||
if (toupper(gbuf[0]) == 'R' &&
|
||||
toupper(gbuf[1]) == 'S' &&
|
||||
toupper(gbuf[1]) == 'S' &&
|
||||
toupper(gbuf[2]) == 'T') {
|
||||
gbuf[i] = toupper(*cptr);
|
||||
gbuf[i] = toupper(*cptr);
|
||||
cptr++;
|
||||
i++;
|
||||
}
|
||||
@@ -262,9 +273,9 @@ if (toupper(gbuf[0]) == 'R' &&
|
||||
/* Allow for 'MOV' which is only opcode that has comma in it. */
|
||||
|
||||
if (toupper(gbuf[0]) == 'M' &&
|
||||
toupper(gbuf[1]) == 'O' &&
|
||||
toupper(gbuf[1]) == 'O' &&
|
||||
toupper(gbuf[2]) == 'V') {
|
||||
gbuf[i] = toupper(*cptr);
|
||||
gbuf[i] = toupper(*cptr);
|
||||
cptr++;
|
||||
i++;
|
||||
gbuf[i] = toupper(*cptr);
|
||||
@@ -275,25 +286,25 @@ if (toupper(gbuf[0]) == 'M' &&
|
||||
/* kill trailing spaces if any */
|
||||
gbuf[i] = '\0';
|
||||
for (j = i - 1; gbuf[j] == ' '; j--) {
|
||||
gbuf[j] = '\0';
|
||||
gbuf[j] = '\0';
|
||||
}
|
||||
|
||||
/* find opcode in table */
|
||||
for (j = 0; j < 256; j++) {
|
||||
if (strcmp(gbuf, opcode[j]) == 0)
|
||||
break;
|
||||
if (strcmp(gbuf, opcode[j]) == 0)
|
||||
break;
|
||||
}
|
||||
if (j > 255) /* not found */
|
||||
return SCPE_ARG;
|
||||
if (j > 255) /* not found */
|
||||
return SCPE_ARG;
|
||||
|
||||
val[0] = j; /* store opcode */
|
||||
if (oplen[j] < 2) /* if 1-byter we are done */
|
||||
return SCPE_OK;
|
||||
val[0] = j; /* store opcode */
|
||||
if (oplen[j] < 2) /* if 1-byter we are done */
|
||||
return SCPE_OK;
|
||||
if (*cptr == ',') cptr++;
|
||||
cptr = get_glyph(cptr, gbuf, 0); /* get address */
|
||||
cptr = get_glyph(cptr, gbuf, 0); /* get address */
|
||||
sscanf(gbuf, "%o", &r);
|
||||
if (oplen[j] == 2) {
|
||||
val[1] = r & 0xFF;
|
||||
val[1] = r & 0xFF;
|
||||
return (-1);
|
||||
}
|
||||
val[1] = r & 0xFF;
|
||||
|
||||
Reference in New Issue
Block a user