diff --git a/Visual Studio Projects/swtp6800mp-a.vcproj b/Visual Studio Projects/swtp6800mp-a.vcproj
index ed54076c..14a0cbb6 100644
--- a/Visual Studio Projects/swtp6800mp-a.vcproj
+++ b/Visual Studio Projects/swtp6800mp-a.vcproj
@@ -199,6 +199,10 @@
RelativePath="..\swtp6800\common\dc-4.c"
>
+
+
diff --git a/Visual Studio Projects/swtp6800mp-a2.vcproj b/Visual Studio Projects/swtp6800mp-a2.vcproj
index 85543fcd..5f0d5721 100644
--- a/Visual Studio Projects/swtp6800mp-a2.vcproj
+++ b/Visual Studio Projects/swtp6800mp-a2.vcproj
@@ -199,6 +199,10 @@
RelativePath="..\swtp6800\common\dc-4.c"
>
+
+
diff --git a/descrip.mms b/descrip.mms
index f51d924c..482ef691 100644
--- a/descrip.mms
+++ b/descrip.mms
@@ -739,7 +739,7 @@ SWTP6800MP_A_LIB = $(LIB_DIR)SWTP6800MP-A-$(ARCH).OLB
SWTP6800MP_A_SOURCE = $(SWTP6800MP_A_COMMON)mp-a.c,$(SWTP6800MP_A_COMMON)m6800.c,\
$(SWTP6800MP_A_COMMON)m6810.c,$(SWTP6800MP_A_COMMON)bootrom.c,$(SWTP6800MP_A_COMMON)dc-4.c,\
$(SWTP6800MP_A_COMMON)mp-s.c,$(SWTP6800MP_A_DIR)mp-a_sys.c,$(SWTP6800MP_A_COMMON)mp-b2.c,\
- $(SWTP6800MP_A_COMMON)mp-8m.c
+ $(SWTP6800MP_A_COMMON)mp-8m.c,$(SWTP6800MP_A_COMMON)fd400.c
SWTP6800MP_A_OPTIONS = /INCL=($(SIMH_DIR),$(SWTP6800MP_A_DIR))/DEF=($(CC_DEFS))
#
@@ -751,7 +751,7 @@ SWTP6800MP_A2_LIB = $(LIB_DIR)SWTP6800MP-A2-$(ARCH).OLB
SWTP6800MP_A2_SOURCE = $(SWTP6800MP_A2_COMMON)mp-a2.c,$(SWTP6800MP_A2_COMMON)m6800.c,\
$(SWTP6800MP_A2_COMMON)m6810.c,$(SWTP6800MP_A2_COMMON)bootrom.c,$(SWTP6800MP_A2_COMMON)dc-4.c,\
$(SWTP6800MP_A2_COMMON)mp-s.c,$(SWTP6800MP_A2_DIR)mp-a2_sys.c,$(SWTP6800MP_A2_COMMON)mp-b2.c,\
- $(SWTP6800MP_A2_COMMON)mp-8m.c,$(SWTP6800MP_A2_COMMON)i2716.c
+ $(SWTP6800MP_A2_COMMON)mp-8m.c,$(SWTP6800MP_A2_COMMON)i2716.c,,$(SWTP6800MP_A_COMMON)fd400.c
SWTP6800MP_A2_OPTIONS = /INCL=($(SIMH_DIR),$(SWTP6800MP_A2_DIR))/DEF=($(CC_DEFS))
#
diff --git a/doc/swtp6800_doc.doc b/doc/swtp6800_doc.doc
index 315e3e02..2660ed18 100644
Binary files a/doc/swtp6800_doc.doc and b/doc/swtp6800_doc.doc differ
diff --git a/makefile b/makefile
index aee48b36..46905a58 100644
--- a/makefile
+++ b/makefile
@@ -1806,11 +1806,13 @@ SDS_OPT = -I ${SDSD} -DUSE_SIM_CARD
SWTP6800D = ${SIMHD}/swtp6800/swtp6800
SWTP6800C = ${SIMHD}/swtp6800/common
SWTP6800MP-A = ${SWTP6800C}/mp-a.c ${SWTP6800C}/m6800.c ${SWTP6800C}/m6810.c \
- ${SWTP6800C}/bootrom.c ${SWTP6800C}/dc-4.c ${SWTP6800C}/mp-s.c ${SWTP6800D}/mp-a_sys.c \
- ${SWTP6800C}/mp-b2.c ${SWTP6800C}/mp-8m.c
+ ${SWTP6800C}/bootrom.c ${SWTP6800C}/dc-4.c ${SWTP6800D}/mp-a_sys.c \
+ ${SWTP6800C}/mp-8m.c ${SWTP6800C}/fd400.c ${SWTP6800C}/mp-b2.c \
+ ${SWTP6800C}/mp-s.c
SWTP6800MP-A2 = ${SWTP6800C}/mp-a2.c ${SWTP6800C}/m6800.c ${SWTP6800C}/m6810.c \
- ${SWTP6800C}/bootrom.c ${SWTP6800C}/dc-4.c ${SWTP6800C}/mp-s.c ${SWTP6800D}/mp-a2_sys.c \
- ${SWTP6800C}/mp-b2.c ${SWTP6800C}/mp-8m.c ${SWTP6800C}/i2716.c
+ ${SWTP6800C}/bootrom.c ${SWTP6800C}/dc-4.c ${SWTP6800D}/mp-a2_sys.c \
+ ${SWTP6800C}/mp-8m.c ${SWTP6800C}/i2716.c ${SWTP6800C}/fd400.c \
+ ${SWTP6800C}/mp-s.c ${SWTP6800C}/mp-b2.c
SWTP6800_OPT = -I ${SWTP6800D}
INTELSYSD = ${SIMHD}/Intel-Systems
diff --git a/swtp6800/common/dc-4.c b/swtp6800/common/dc-4.c
index 7dad6842..64c86ff3 100644
--- a/swtp6800/common/dc-4.c
+++ b/swtp6800/common/dc-4.c
@@ -1,4 +1,4 @@
-/* dc4.c: SWTP DC-4 FDC Simulator
+/* c: SWTP DC-4 FDC Simulator
Copyright (c) 2005-2012, William A. Beech
@@ -25,7 +25,8 @@
MODIFICATIONS:
- 23 Apr 15 -- Modified to use simh_debug
+ 28 May 22 -- Roberto Sancho Villa (RSV) fixes for other disk formats
+ and operating systems.
NOTES:
@@ -186,6 +187,7 @@
Writes the 8-bit value to the data register.
A FLEX disk is defined as follows:
+ (first sector on track is number 1)
Track Sector Use
0 1 Boot sector
@@ -197,7 +199,7 @@
1 1 First available data sector
last-1 last Last available data sector
- System Identity Record
+ System Identity Record (SIR)
Byte Use
0x00 Two bytes of zeroes (Clears forward link)
@@ -230,15 +232,26 @@
#define NUM_DISK 4 /* standard 1797 maximum */
#define SECT_SIZE 256 /* standard FLEX sector */
-#define NUM_SECT 72 /* sectors/track */
+#define NUM_SECT 36 //sectors/track
#define TRAK_SIZE (SECT_SIZE * NUM_SECT) /* trk size (bytes) */
-#define HEADS 1 /* handle as SS with twice the sectors */
-#define NUM_CYL 80 /* maximum tracks */
+#define HEADS 2 //handle as DS
+#define NUM_CYL 80 /* maximum cylinders */
#define DSK_SIZE (NUM_SECT * HEADS * NUM_CYL * SECT_SIZE) /* dsk size (bytes) */
-/* SIR offsets */
-#define MAXCYL 0x26 /* last cylinder # */
-#define MAXSEC 0x27 /* last sector # */
+//SIR offsets TK 0, SEC 3
+
+#define LABEL 0x10 //disk label (11 char)
+#define VOLNUM 0x1B //volume number (word)
+#define FSTUSRTRK 0x1D //first user track (byte)
+#define FSTUSRSEC 0x1E //first user sector (byte)
+#define LSTUSRTRK 0x1F //last user track (byte)
+#define LSTUSRSEC 0x20 //last user sector (byte)
+#define TOTSEC 0x21 //total sectors (word)
+#define CREMON 0x23 //creation month (byte)
+#define CREDAY 0x24 //creation day (byte)
+#define CREYR 0x25 //creation year (byte)
+#define MAXCYL 0x26 //last cylinder #
+#define MAXSEC 0x27 //last sector #
/* 1797 status bits type I commands*/
@@ -248,7 +261,7 @@
#define SEEKERR 0x10
#define CRCERR 0x08
#define LOST 0x04
-#define DRQ 0x02
+#define INDEX 0x02
#define BUSY 0x01
/* 1797 status bits type II/III commands*/
@@ -264,28 +277,34 @@
/* function prototypes */
-t_stat dsk_reset (DEVICE *dptr);
+t_stat dsk_reset (DEVICE *dptr);
+t_stat dsk_attach (UNIT *uptr, CONST char *cptr);
/* SS-50 I/O address space functions */
-int32 fdcdrv(int32 io, int32 data);
-int32 fdccmd(int32 io, int32 data);
-int32 fdctrk(int32 io, int32 data);
-int32 fdcsec(int32 io, int32 data);
-int32 fdcdata(int32 io, int32 data);
+int32 fdcdrv(int32 io, int32 data);
+int32 fdccmd(int32 io, int32 data);
+int32 fdctrk(int32 io, int32 data);
+int32 fdcsec(int32 io, int32 data);
+int32 fdcdata(int32 io, int32 data);
/* Local Variables */
-int32 fdcbyte;
-int32 intrq = 0; /* interrupt request flag */
-int32 cur_dsk; /* Currently selected drive */
-int32 wrt_flag = 0; /* FDC write flag */
+int32 fdcbyte;
+int32 intrq; /* interrupt request flag */
+int32 cur_dsk; /* Currently selected drive */
+int32 wrt_flag; /* FDC write flag */
int32 spt; /* sectors/track */
int32 trksiz; /* trk size (bytes) */
int32 heds; /* number of heads */
int32 cpd; /* cylinders/disk */
int32 dsksiz; /* dsk size (bytes) */
+int32 sectsize; // Sector size (bytes)
+
+int32 multiple_sector; // multiple read-write flag
+int32 index_countdown; // index countdown for type I commands
+int32 sector_base; // indicates is first sector on track is sector 1 or sector 0
/* Floppy Disk Controller data structures
@@ -296,21 +315,21 @@ int32 dsksiz; /* dsk size (bytes) */
*/
UNIT dsk_unit[] = {
- { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) },
- { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) },
- { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) },
- { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, 0) }
+ { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
+ { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
+ { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
+ { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }
};
REG dsk_reg[] = {
- { HRDATA (DISK, cur_dsk, 4) },
- { NULL }
+ { HRDATA (DISK, cur_dsk, 4) },
+ { NULL }
};
MTAB dsk_mod[] = {
- { UNIT_ENABLE, UNIT_ENABLE, "RW", "RW", NULL },
- { UNIT_ENABLE, 0, "RO", "RO", NULL },
- { 0 }
+ { UNIT_ENABLE, UNIT_ENABLE, "RW", "RW", NULL },
+ { UNIT_ENABLE, 0, "RO", "RO", NULL },
+ { 0 }
};
DEBTAB dsk_debug[] = {
@@ -336,10 +355,10 @@ DEVICE dsk_dev = {
NULL, //deposit
&dsk_reset, //reset
NULL, //boot
- NULL, //attach
+ dsk_attach, //attach
NULL, //detach
NULL, //ctxt
- DEV_DEBUG, //flags
+ DEV_DISABLE|DEV_DEBUG, //flags
0, //dctrl
dsk_debug, //debflags
NULL, //msize
@@ -350,18 +369,18 @@ DEVICE dsk_dev = {
t_stat dsk_reset (DEVICE *dptr)
{
- int i;
+ uint32 i;
cur_dsk = 5; /* force initial SIR read */
- for (i=0; inumunits; i++) {
+ dptr->units[i].u3 = NOTRDY; /* current flags = NOTRDY*/
+ dptr->units[i].u4 = 0; /* clear current cylinder # */
+ dptr->units[i].u5 = 0; /* clear current sector # */
+ dptr->units[i].pos = 0; /* clear current byte ptr */
+ if (dptr->units[i].filebuf == NULL) {
+ dptr->units[i].filebuf = calloc(SECT_SIZE, sizeof(uint8)); /* allocate buffer */
+ if (dptr->units[i].filebuf == NULL) {
+ printf("dc-4_reset: Calloc error\n");
return SCPE_MEM;
}
}
@@ -371,11 +390,31 @@ t_stat dsk_reset (DEVICE *dptr)
heds = 0;
cpd = 0;
dsksiz = 0;
+ //RSV - for hansling multiple disk formats and OSs
+ sectsize = SECT_SIZE;
+ multiple_sector=0;
+ index_countdown=0;
+ sector_base=1;
+ return SCPE_OK;
+}
+
+/* dsk attach - attach an .IMG file to an FDD */
+
+t_stat dsk_attach (UNIT *uptr, CONST char *cptr)
+{
+ t_stat r;
+
+ if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
+ sim_printf("dsk_attach: Attach error %d\n", r);
+ return r;
+ }
+ uptr->u3 &= ~NOTRDY; //reset FDD to ready
+ uptr->capac = sim_fsize(uptr->fileref); //file size
return SCPE_OK;
}
/* I/O instruction handlers, called from the MP-B2 module when a
- read or write occur to addresses 0x8004-0x8007. */
+ read or write occur to addresses 0x8014-0x801B. */
/* DC-4 drive select register routine - this register is not part of the 1797
*/
@@ -384,47 +423,59 @@ int32 fdcdrv(int32 io, int32 data)
{
static long pos;
static int32 err;
+ uint8 *SIR;
+ int32 disk_image_size;
- if (io) { /* write to DC-4 drive register */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Drive selected %d cur_dsk=%d",
- data & 0x03, cur_dsk);
- if (cur_dsk == (data & 0x03))
- return 0; /* already selected */
- cur_dsk = data & 0x03; /* only 2 drive select bits */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Drive set to %d", cur_dsk);
- dsk_unit[cur_dsk].flags &= ~LOST;
- if ((dsk_unit[cur_dsk].flags & UNIT_ENABLE) == 0) {
- dsk_unit[cur_dsk].u3 |= WRPROT; /* set 1797 WPROT */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Drive write protected");
- } else {
- dsk_unit[cur_dsk].u3 &= ~WRPROT; /* set 1797 not WPROT */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Drive NOT write protected");
- }
- pos = 0x200; /* Read in SIR */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Read pos = %ld ($%04X)",
- pos, (unsigned int) pos);
- err = sim_fseek(dsk_unit[cur_dsk].fileref, pos, SEEK_SET); /* seek to offset */
- if (err) {
- sim_printf("\nfdccmd: Seek error read in SIR\n");
- return SCPE_IOERR;
- }
- err = sim_fread(dsk_unit[cur_dsk].filebuf, SECT_SIZE, 1, dsk_unit[cur_dsk].fileref); /* read in buffer */
- if (err != 1) {
- sim_printf("\nfdccmd: File error read in SIR\n");
- return SCPE_IOERR;
- }
+ if (io) { // write to DC-4 drive register
+ if (cur_dsk == (data & 0x03)) // already selected?
+ return 0; //yes
+ cur_dsk = data & 0x03; // only 2 drive select bits/
+ dsk_unit[cur_dsk].u3 &= ~LOST; //RSV - reset LOST flag
+ if ((dsk_unit[cur_dsk].flags & UNIT_ENABLE) == 0) //RO?
+ dsk_unit[cur_dsk].u3 |= WRPROT; /* Set WPROT */
+ else
+ dsk_unit[cur_dsk].u3 &= ~WRPROT; /* SET not WPROT */
+ if (dsk_unit[cur_dsk].fileref == 0) // no file attached
+ return 0;
+ /* RSV - Read in SIR */
+ pos = 0x200;
+ sim_fseek(dsk_unit[cur_dsk].fileref, pos, SEEK_SET); /* seek to SIR */
+ sim_fread(dsk_unit[cur_dsk].filebuf, SECT_SIZE, 1, dsk_unit[cur_dsk].fileref); /* read in SIR */
dsk_unit[cur_dsk].u3 |= BUSY | DRQ; /* set DRQ & BUSY */
dsk_unit[cur_dsk].pos = 0; /* clear counter */
- spt = *((uint8 *)(dsk_unit[cur_dsk].filebuf) + MAXSEC) & 0xFF;
- heds = 0;
- cpd = *((uint8 *)(dsk_unit[cur_dsk].filebuf) + MAXCYL) & 0xFF;
- trksiz = spt * SECT_SIZE;
+ SIR = (uint8 * )(dsk_unit[cur_dsk].filebuf);
+ // detect disk type based on image geometry or SIR record
+ disk_image_size = sim_fsize(dsk_unit[cur_dsk].fileref); //get actual file size
+ if (disk_image_size == 35 * 10 * 256) { // 89600 bytes -> FDOS image
+ // FDOS disc has no SIR record.
+ spt = 10; // 10 sectors
+ cpd = 35; // 35 tracks
+ sectsize = 256;
+ sector_base = 0; // first sector in track is number ZERO
+ } else if (disk_image_size == 35 * 18 * 128) { // 80640 bytes -> FLEX 1.0 image
+ spt = 18; // 18 sectors
+ cpd = 35; // 35 tracks
+ sectsize = 128;
+ sector_base = 1; // first sector in track is number ONE
+ } else if ((SIR[0] == 0) && (SIR[1] == 0)) {
+ // FLEX disc has SIR record. on disk image offset $200
+ spt = SIR[MAXSEC]; // Highest number of tracks. As in FLEX sectors are numbered as
+ // 1,2,..Hi this is also the number of sectors per track
+ cpd = SIR[MAXCYL] + 1; // highest track number . On FLEX, first track is track zero
+ sectsize = 256;
+ sector_base = 1; // first sector in track is number ONE
+ } else {
+ spt = 18;
+ sectsize = 128;
+ cpd = disk_image_size / (spt * sectsize);
+ sector_base = 1; // first sector in track is number ONE
+ }
+ heds = 0; //RSV - always SS
+ trksiz = spt * sectsize;
dsksiz = trksiz * cpd;
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: spt=%d heds=%d cpd=%d trksiz=%d dsksiz=%d flags=%08X u3=%08X",
- spt, heds, cpd, trksiz, dsksiz, dsk_unit[cur_dsk].flags, dsk_unit[cur_dsk].u3);
+
return 0;
} else { /* read from DC-4 drive register */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdrv: Drive read as %02X", intrq);
return intrq;
}
}
@@ -438,83 +489,88 @@ int32 fdccmd(int32 io, int32 data)
static int32 err;
if ((dsk_unit[cur_dsk].flags & UNIT_ATT) == 0) { /* not attached */
- dsk_unit[cur_dsk].u3 |= NOTRDY; /* set not ready flag */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Drive %d is not attached", cur_dsk);
- return 0;
+ val = dsk_unit[cur_dsk].u3 |= NOTRDY; /* set not ready flag */
+ return SEEKERR; // RSV - return SEEK ERROR STATUS bit
} else {
dsk_unit[cur_dsk].u3 &= ~(NOTRDY); /* clear not ready flag */
}
if (io) { /* write command to fdc */
+ // RSV - on commands type I ...
+ if ((data & 0x80) == 0) {
+ // ... set bits h V r1r0 to h=1 (home drive), V=0 (verify off), r1r0=11 (40msec track stepping)
+ data = ((data & 0xF0) | 0x0B);
+ // and starts countdown for index status bit
+ index_countdown = 10;
+ } else {
+ index_countdown = 0;
+ }
+ // process command
switch(data) {
case 0x8C: //read sector command type II
case 0x9C: //read multiple sectors command type II
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Read of disk %d, track %d, sector %d",
- cur_dsk, dsk_unit[cur_dsk].u4, dsk_unit[cur_dsk].u5);
+ if ((dsk_unit[cur_dsk].u5 - sector_base >= spt) || (dsk_unit[cur_dsk].u5 < sector_base)) {
+ dsk_unit[cur_dsk].u3 |= RECNF; /* RSV - set RECORD NOT FOUND */
+ break;
+ }
dsk_unit[cur_dsk].u3 |= BUSY; /* set BUSY */
pos = trksiz * dsk_unit[cur_dsk].u4; /* calculate file offset */
- pos += SECT_SIZE * (dsk_unit[cur_dsk].u5 - 1);
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Read pos = %ld ($%08X)",
- pos, (unsigned int) pos);
+ pos += sectsize * (dsk_unit[cur_dsk].u5 - sector_base);
err = sim_fseek(dsk_unit[cur_dsk].fileref, pos, SEEK_SET); /* seek to offset */
if (err) {
- sim_printf("\nfdccmd: Seek error in read command\n");
+ sim_printf("fdccmd: Seek error in read command\n");
return SCPE_IOERR;
- }
- err = sim_fread(dsk_unit[cur_dsk].filebuf, SECT_SIZE, 1, dsk_unit[cur_dsk].fileref); /* read in buffer */
+ }
+ /* read in buffer */
+ err = sim_fread(dsk_unit[cur_dsk].filebuf, sectsize, 1, dsk_unit[cur_dsk].fileref);
if (err != 1) {
- sim_printf("\nfdccmd: File error in read command\n");
+ sim_printf("fdccmd: File error in read command\n");
return SCPE_IOERR;
}
dsk_unit[cur_dsk].u3 |= DRQ; /* set DRQ */
dsk_unit[cur_dsk].pos = 0; /* clear counter */
+ multiple_sector = (data == 0x9C) ? 1:0; // RSV = set multiple sector TYPE II cmds
break;
case 0xAC: //write command type II
case 0xBC: //write multiple sectors command type II
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Write of disk %d, track %d, sector %d",
- cur_dsk, dsk_unit[cur_dsk].u4, dsk_unit[cur_dsk].u5);
if (dsk_unit[cur_dsk].u3 & WRPROT) {
- printf("\nfdccmd: Drive %d is write-protected", cur_dsk);
} else {
dsk_unit[cur_dsk].u3 |= BUSY;/* set BUSY */
pos = trksiz * dsk_unit[cur_dsk].u4; /* calculate file offset */
- pos += SECT_SIZE * (dsk_unit[cur_dsk].u5 - 1);
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Write pos = %ld ($%08X)",
- pos, (unsigned int) pos);
+ pos += sectsize * (dsk_unit[cur_dsk].u5 - sector_base);
err = sim_fseek(dsk_unit[cur_dsk].fileref, pos, SEEK_SET); /* seek to offset */
if (err) {
- sim_printf("\nfdccmd: Seek error in write command\n");
+ sim_printf("fdccmd: Seek error in write command\n");
return SCPE_IOERR;
}
dsk_unit[cur_dsk].u3 |= DRQ;/* set DRQ */
- wrt_flag = 1; /* set write flag */
+ wrt_flag = 1; /* RSV - set write flag */
dsk_unit[cur_dsk].pos = 0; /* clear counter */
}
break;
- case 0x18: //seek command type I
case 0x1B: //seek command type I
- dsk_unit[cur_dsk].u4 = fdcbyte; /* set track */
+ dsk_unit[cur_dsk].u4 = fdcbyte; /* set track */
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Seek of disk %d, track %d",
- cur_dsk, fdcbyte);
break;
- case 0x0B: //restore command type I
- dsk_unit[cur_dsk].u4 = 0; /* home the drive */
- dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Drive %d homed", cur_dsk);
+ case 0x0B: //restore command type I
+ dsk_unit[cur_dsk].u4 = 0; /* home the drive */
+ dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ | RECNF); /* clear flags */
break;
case 0xF0: //write track command type III
case 0xF4: //write track command type III
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Write track command for drive %d",
- cur_dsk);
+ break;
+ case 0xD0: //Force Interrupt - terminate current command
+ dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
break;
default:
- printf("Unknown FDC command %02XH\n\r", data);
+ sim_printf("Unknown FDC command %02X\n\r", data);
}
} else { /* read status from fdc */
val = dsk_unit[cur_dsk].u3; /* set return value */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdccmd: Exit Drive %d status=%02X",
- cur_dsk, val);
- sim_debug (DEBUG_flow, &dsk_dev, "\n%02X", val); //even this short fails it!
+ if (index_countdown) { // RSV - Handle INDEX flag
+ index_countdown--;
+ // if index countdoen expires, set index flag in status returned to cpu
+ if (index_countdown==0) val |= INDEX;
+ }
}
return val;
}
@@ -524,12 +580,9 @@ int32 fdccmd(int32 io, int32 data)
int32 fdctrk(int32 io, int32 data)
{
if (io) {
- dsk_unit[cur_dsk].u4 = data & 0xFF;
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdctrk: Drive %d track set to %d",
- cur_dsk, dsk_unit[cur_dsk].u4);
+ dsk_unit[cur_dsk].u3 &= ~(RECNF); /* reset RECNF flag */
+ dsk_unit[cur_dsk].u4 = data & BYTEMASK;
}
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdctrk: Drive %d track read as %d",
- cur_dsk, dsk_unit[cur_dsk].u4);
return dsk_unit[cur_dsk].u4;
}
@@ -538,14 +591,12 @@ int32 fdctrk(int32 io, int32 data)
int32 fdcsec(int32 io, int32 data)
{
if (io) {
- dsk_unit[cur_dsk].u5 = data & 0xFF;
- if (dsk_unit[cur_dsk].u5 == 0) /* fix for swtp boot! */
- dsk_unit[cur_dsk].u5 = 1;
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcsec: Drive %d sector set to %d",
- cur_dsk, dsk_unit[cur_dsk].u5);
+ dsk_unit[cur_dsk].u3 &= ~(RECNF); /* reset RECNF flag */
+ dsk_unit[cur_dsk].u5 = data & BYTEMASK;
+ if (dsk_unit[cur_dsk].u5 < sector_base) //RSV - force to sector 1
+ dsk_unit[cur_dsk].u5 = sector_base;
+ return 0;
}
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcsec: Drive %d sector read as %d",
- cur_dsk, dsk_unit[cur_dsk].u5);
return dsk_unit[cur_dsk].u5;
}
@@ -553,38 +604,48 @@ int32 fdcsec(int32 io, int32 data)
int32 fdcdata(int32 io, int32 data)
{
- int32 val;
+ int32 val, err;
+ if (cur_dsk >= NUM_DISK) // RSV - illegal disk
+ return 0;
if (io) { /* write byte to fdc */
fdcbyte = data; /* save for seek */
- if (dsk_unit[cur_dsk].pos < SECT_SIZE) { /* copy bytes to buffer */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdata: Writing byte %d of %02X",
- dsk_unit[cur_dsk].pos, data);
+ if (dsk_unit[cur_dsk].pos < (t_addr) sectsize) { /* copy bytes to buffer */
*((uint8 *)(dsk_unit[cur_dsk].filebuf) + dsk_unit[cur_dsk].pos) = data; /* byte into buffer */
dsk_unit[cur_dsk].pos++; /* step counter */
- if (dsk_unit[cur_dsk].pos == SECT_SIZE) {
+ if (dsk_unit[cur_dsk].pos == sectsize) {
dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ);
if (wrt_flag) { /* if initiated by FDC write command */
- sim_fwrite(dsk_unit[cur_dsk].filebuf, SECT_SIZE, 1, dsk_unit[cur_dsk].fileref); /* write it */
+ sim_fwrite(dsk_unit[cur_dsk].filebuf, sectsize, 1, dsk_unit[cur_dsk].fileref); /* write it */
wrt_flag = 0; /* clear write flag */
}
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdata: Sector write complete");
}
}
return 0;
} else { /* read byte from fdc */
- if (dsk_unit[cur_dsk].pos < SECT_SIZE) { /* copy bytes from buffer */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdata: Reading byte %d u3=%02X",
- dsk_unit[cur_dsk].pos, dsk_unit[cur_dsk].u3);
- val = *((uint8 *)(dsk_unit[cur_dsk].filebuf) + dsk_unit[cur_dsk].pos) & 0xFF;
- dsk_unit[cur_dsk].pos++; /* step counter */
- if (dsk_unit[cur_dsk].pos == SECT_SIZE) { /* done? */
- dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
- sim_debug (DEBUG_flow, &dsk_dev, "\nfdcdata: Sector read complete");
+ if (dsk_unit[cur_dsk].pos < (t_addr) sectsize) { /* copy bytes from buffer */
+ val = *((uint8 *)(dsk_unit[cur_dsk].filebuf) + dsk_unit[cur_dsk].pos) & BYTEMASK;
+ dsk_unit[cur_dsk].pos++; /* step counter */
+ if (dsk_unit[cur_dsk].pos == sectsize) { // sector finished
+ if ((multiple_sector) && (dsk_unit[cur_dsk].u5-sector_base < spt-1)) { // read multiple in progress
+ dsk_unit[cur_dsk].u5++;
+ err = sim_fread(dsk_unit[cur_dsk].filebuf, sectsize, 1, dsk_unit[cur_dsk].fileref); /* read in buffer */
+ if (err != 1) {
+ sim_printf("fdccmd: File error in read command\n");
+ return SCPE_IOERR;
+ }
+ dsk_unit[cur_dsk].pos = 0;
+ } else { // RSV - handle multiple sector disk read
+ dsk_unit[cur_dsk].u5++;
+ dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
+ if (multiple_sector) {
+ multiple_sector=0;
+ }
+ }
}
return val;
} else
- return 0;
+ return 0;
}
}
diff --git a/swtp6800/common/fd400.c b/swtp6800/common/fd400.c
new file mode 100644
index 00000000..31323f41
--- /dev/null
+++ b/swtp6800/common/fd400.c
@@ -0,0 +1,519 @@
+/* fd400.c: Percom LFD-400 FDC Simulator
+
+ Copyright (c) 2022, Roberto Sancho
+
+ 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
+ WILLIAM A BEECH 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 Roberto Sancho shall not
+ be used in advertising or otherwise to promote the sale, use or other dealings
+ in this Software without prior written authorization from Roberto Sancho .
+
+ MODIFICATIONS:
+
+ NOTES:
+
+ The FDC-400 is a 5-1/4"-inch floppy controller which can control up
+ to four 5-1/4inch floppy drives.
+ This file only emulates the minimum functionality to interface with
+ the virtual disk file.
+
+ The floppy controller is interfaced to the CPU by use of 7 memory
+ addreses (0xCC00-0xCC06).
+
+ Address Mode Function
+ ------- ---- --------
+
+ 0xCC00 Read CONTROLLER STATUS
+ 0xCC00 Write SYNC WORD PORT
+ 0xCC01 Read RECEIVED DATA
+ 0xCC01 Write WRITE DATA PORT
+ 0xCC02 Read SECTOR COUNTER
+ 0xCC02 Write FILL WORD PORT
+ 0xCC03 Read DRIVE STATUS
+ 0xCC03 Write DRIVE AND TRACK SELECT
+ 0xCC04 Read RECEIVER RESTART PULSE
+ 0xCC04 Write WRITE PULSE
+ 0xCC05 Read MOTOR ON PULSE
+ 0xCC06 Read MOTOR OFF PULSE
+
+
+ CONTROLLER STATUS (Read 0xCC00):
+
+ +---+---+---+---+---+---+---+---+
+ | B | x | x | x | x | x | x | R |
+ +---+---+---+---+---+---+---+---+
+
+ B = Controller Ready (0=Busy, 1=Ready)
+ R = Read byte ready (1=can retrieve read byte)
+
+
+ RECEIVED DATA (Read 0xCC01):
+ WRITE DATA PORT (Write 0xCC01):
+
+ +---+---+---+---+---+---+---+---+
+ | byte |
+ +---+---+---+---+---+---+---+---+
+
+ Data byte from retrieved sector being read
+ Data byte to store in sector being write
+
+
+ CURRENT SECTOR (Read 0xCC02):
+ WRITE FILL CHAR (Write 0xCC02):
+
+ +---+---+---+---+---+---+---+---+
+ | x | Sector |
+ +---+---+---+---+---+---+---+---+
+
+ Return current Sector
+ Set the fill char for write sector
+
+
+ DRIVE STATUS (Read 0xCC03):
+
+ +---+---+---+---+---+---+---+---+
+ | DD | I | S | W | M | T | P |
+ +---+---+---+---+---+---+---+---+
+
+ P = Write allowed Bit (0=disk is write protected)
+ T = Track Zero Bit (1=head is NOT positioned in track zero)
+ M = Motor Test Bit (1=motor stopped)
+ W = Write Gate Bit (1=drive gate door is closed)
+ S = Sector Pulse Bit (1=head at start of sector)
+ I = Index Pulse bit (???)
+ DD = Current selected drive (0..3)
+
+
+ DRIVE AND TRACK SELECT (Write 0xCC03):
+
+ +---+---+---+---+---+---+---+---+
+ | DD | S | D | x | x | x | x |
+ +---+---+---+---+---+---+---+---+
+
+ D = Direction bit (1=Track In=increment track number)
+ S = Step Bit (1=Move disk head one track using direction D)
+ DD = Select drive (0..3)
+
+ LFD-400 Disck supports these operating systems (1977)
+
+ - MINIDOS: Just Load/Save ram starting at given sector in disk.
+ No files. No sector allocation management. Rom based
+ - MPX (also know as MiniDOS Plus or MiniDOS/MPX or MiniDOS-PlusX):
+ Based on MiniDOS, add named files, contiguos allocation management. Transient disk command
+ - MiniDisk+ DOS:
+ Based on MiniDOS, add named files, contiguos allocation management. More disk commands
+
+
+ MiniDOS files have 40 track (0..39) with 10 sectors (0..9) each with 256 bytes of data
+
+ The following unit registers are used by this controller emulation:
+
+ fd400_dsk_unit[cur_drv].u4 unit current track
+ fd400_dsk_unit[cur_drv].u5 unit current sector
+ fd400_dsk_unit[cur_drv].pos unit current sector byte index into buffer
+ fd400_dsk_unit[cur_drv].filebuf unit current sector buffer
+ fd400_dsk_unit[cur_drv].fileref unit current attached file reference
+
+ At start, units discs from controller are dissabled
+ To use it, befor attaching the disk image, it is mecessary to do "set lfd-4000 enabled"
+ (for unit 0), and optionally "set lfd-4001 enabled" (for unit 1) and so on.
+*/
+
+#include
+#include "swtp_defs.h"
+
+#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */
+#define UNIT_ENABLE (1 << UNIT_V_ENABLE)
+
+/* emulate a Disk disk with 10 sectors and 40 tracks */
+
+#define NUM_DISK 4
+#define SECT_SIZE (8+4+256) /* sector size=header (10 bytes) + data (256 bytes) + CRC (2 bytes) */
+#define NUM_SECT 10 /* sectors/track */
+#define TRAK_SIZE (SECT_SIZE * NUM_SECT) /* trk size (bytes) */
+#define HEADS 1 /* handle as SS with twice the sectors */
+#define NUM_CYL 40 /* maximum tracks */
+#define DSK_SIZE (NUM_SECT * HEADS * NUM_CYL * SECT_SIZE) /* dsk size (bytes) */
+
+#define TRK fd400_dsk_unit[fd400.cur_dsk].u4 // current disk track and sector
+#define SECT fd400_dsk_unit[fd400.cur_dsk].u5
+
+#define BUF_SIZE (SECT_SIZE+16) // sector buffer in memory
+
+/* function prototypes */
+
+t_stat fd400_dsk_reset (DEVICE *dptr);
+t_stat fd400_attach (UNIT *, CONST char *);
+
+/* SS-50 I/O address space functions */
+
+int32 fd400_fdcstatus(int32 io, int32 data);
+int32 fd400_cstatus(int32 io, int32 data);
+int32 fd400_data(int32 io, int32 data);
+int32 fd400_cursect(int32 io, int32 data);
+int32 fd400_startrw(int32 io, int32 data);
+
+/* Local Variables */
+
+struct {
+ int32 cur_dsk; /* Currently selected drive */
+ int32 SectorPulse; // Head positioned at beginning of sector
+ int32 StepBit;
+ uint8 FillChar;
+} fd400 = {0};
+
+/* Floppy Disk Controller data structures
+
+ fd400_dsk_dev Disk Controller device descriptor
+ fd400_dsk_unit Disk Controller unit descriptor
+ fd400_dsk_reg Disk Controller register list
+ fd400_dsk_mod Disk Controller modifiers list
+*/
+
+UNIT fd400_dsk_unit[] = {
+ { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
+ { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
+ { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
+ { UDATA (NULL, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+UNIT_DIS, 0) }
+};
+
+REG fd400_dsk_reg[] = {
+ { HRDATA (DISK, fd400.cur_dsk, 4) },
+ { NULL }
+};
+
+DEBTAB fd400_dsk_debug[] = {
+ { "ALL", DEBUG_all, "All debug bits" },
+ { "FLOW", DEBUG_flow, "Flow control" },
+ { "READ", DEBUG_read, "Read Command" },
+ { "WRITE", DEBUG_write, "Write Command"},
+ { NULL }
+};
+
+DEVICE fd400_dsk_dev = {
+ "LFD-400", //name
+ fd400_dsk_unit, //units
+ fd400_dsk_reg, //registers
+ NULL, //modifiers
+ NUM_DISK, //numunits
+ 16, //aradix
+ 16, //awidth
+ 1, //aincr
+ 16, //dradix
+ 8, //dwidth
+ NULL, //examine
+ NULL, //deposit
+ &fd400_dsk_reset, //reset
+ NULL, //boot
+ &fd400_attach, //attach
+ NULL, //detach
+ NULL, //ctxt
+ DEV_DISABLE|DEV_DIS|DEV_DEBUG, //flags
+ 0, //dctrl
+ fd400_dsk_debug, //debflags
+ NULL, //msize
+ NULL //lname
+};
+
+/* Reset routine */
+
+t_stat fd400_dsk_reset (DEVICE *dptr)
+{
+ int i;
+
+ for (i=0; iflags & UNIT_ATT) == 0) {
+ sim_debug (DEBUG_flow, &fd400_dsk_dev, "Current Drive %d has no file attached \n", fd400.cur_dsk);
+ } else {
+ // file attached = disk inserted into unit
+ if ((uptr->flags & UNIT_RO) == 0) val |= 1; // unit is read/write
+ if (TRK!=0) val |= 2; // head is NOT in track zero
+ if (fd400.SectorPulse) {
+ val |= 16;
+ fd400.SectorPulse--;
+ } else {
+ // set sector pulse and incr current sector
+ // Simulates somewhat disk rotation whitout having to set up _svr and sim_activate
+ fd400.SectorPulse=2;
+ SECT++; if (SECT >= NUM_SECT) SECT = 0;
+ uptr->pos=0; // init sector read
+ }
+ if (SECT==0) val |= 32; // index pulse: head is positioned in sector zero
+ }
+ sim_debug (DEBUG_flow, &fd400_dsk_dev, "Status Returned %02X, Current Drive %d TRK %d SECT %d \n",
+ val, fd400.cur_dsk, TRK, SECT);
+ return val;
+ }
+ // io=1 -> writing data to i/o register,
+ fd400.cur_dsk = data >> 6; // select current disk
+ fd400.SectorPulse = 0; // init sector pulse
+ if (data & 32) {
+ fd400.StepBit=1; // Step bit set to one
+ } else if ((data & 32)==0) { // Step bit set to zero
+ if (fd400.StepBit==0) {
+ // but was already zero -> no action
+ } else {
+ // StepBit changing from 1 to 0 -> step track motot
+ fd400.StepBit=0;
+ // step track depending on direction bit
+ if (data & 16) TRK++; else TRK--;
+ if (TRK < 0) TRK=0;
+ if (TRK >= NUM_CYL) TRK = NUM_CYL-1;
+ // on changing track also incr sect num, but not issue sector pulse (landed on middle of sector)
+ SECT++; if (SECT >= NUM_SECT) SECT = 0;
+ uptr->pos=0; // init sector read
+ }
+ }
+ sim_debug (DEBUG_flow, &fd400_dsk_dev, "Set Drive and Track %02X, Current Drive %d TRK %d SECT %d \n",
+ data, fd400.cur_dsk, TRK, SECT);
+ return 0;
+}
+
+/* CONTROLLER STATUS register (read $CC00)*/
+
+int32 fd400_cstatus(int32 io, int32 data)
+{
+ // controller allways ready, byte read from sector allways ready
+ // writing to is set the sync byte. This is not implemented
+ return 128+1;
+}
+
+/* DATA register */
+
+int32 fd400_data(int32 io, int32 data)
+{
+ uint32 loc;
+ UNIT * uptr = &fd400_dsk_unit[fd400.cur_dsk];
+ uint8 dsk_sect[SECT_SIZE]; // image of sector read/saved in disk image
+ uint8 * p = (uint8 *)(uptr->filebuf); // sector byte stream as seen by program
+ int i, n;
+
+ if ((uptr->flags & UNIT_ATT) == 0) return 0; // not attached
+ if (io==0) {
+ // io=0 when reading from io register (return data read from i/o device register)
+ // read data from sector
+ if (uptr->pos==0) {
+ // read new sector buffer
+ // init buffer to zero
+ memset(uptr->filebuf, 0, SECT_SIZE);
+ // calculate location of current sector in disk image file
+ loc=(TRK * NUM_SECT + SECT) * SECT_SIZE;
+ if (loc >= uptr->capac) {
+ // reading past image file current size -> read as zeroes
+ } else {
+ // read sector
+ sim_fseek(uptr->fileref, loc, SEEK_SET);
+ sim_fread(dsk_sect, 1, SECT_SIZE, uptr->fileref);
+ // reorganize buffer to match the byte order expected by MiniDOS
+ //
+ // Data in MiniDOS MPX disk image:
+ // BT BS FT FS NN AH AL TY CH CL PH PL [256 data bytes] = 268 bytes
+ // where BT=Backward link track, DS=Backward link sector,
+ // FT=Forward link track, FS=Forward link sector. = 00 00 if this is last sector of file
+ // NN=Number of data bytes (00=256 bytes)
+ // AH AL=Addr in RAM where to load sector data bytes (H=High byte, L=Low byte)
+ // TY=file type
+ // CH CL=CheckSum Hi/Low byte
+ // PH PL=Postamble Hi/Low byte. Holds program start addr on last sector
+ //
+ // Data as expected by MiniDOS ROM when reading a sector
+ // SY TR SE BT BS FT FS NN AH AL TY [NN data bytes] CH CL PH PL
+ // where SY=Sync Byte=$FD
+ // TR SE=This track and sector
+ // BT BS FT FS NN AH AL TY=same as above
+ // CH CL=same as above
+ //
+ // so we create the filebuf (p pointer) reordering data read from disk image file (dsk_sect)
+ p[0]=0xFB; // sync byte
+ p[1]=TRK; p[2]=SECT; // this sector track and sector number
+ for (i=0; i<8; i++) p[3+i]=dsk_sect[i]; // 8 byte header with bytes BT ... TY
+ n=dsk_sect[4]; if (n==0) n=256; // number of data bytes
+ for (i=0; ipos=0;
+ }
+ // retrieve read byte from sector buffer
+ if (uptr->pos>=BUF_SIZE) {
+ sim_debug (DEBUG_write, &fd400_dsk_dev, "Sector overrun - do not read data\n");
+ return 0;
+ }
+ data=p[uptr->pos];
+ sim_debug (DEBUG_read, &fd400_dsk_dev, "Read byte %02X (dec=%d char='%c'), Current Drive %d TRK %d SECT %d POS %d\n",
+ data, data, (data < 32) ? '?':data, fd400.cur_dsk, TRK, SECT, uptr->pos);
+ uptr->pos++;
+
+ return data;
+ }
+ // io=1 -> writing data to i/o register,
+ // write data to sector
+ if (uptr->flags & UNIT_RO) {
+ sim_debug (DEBUG_write, &fd400_dsk_dev, "Write data %02X, but Current Drive %d is Read Only\n",
+ data, fd400.cur_dsk);
+ return 0;
+ }
+ sim_debug (DEBUG_write, &fd400_dsk_dev, "Write data %02X, Current Drive %d TRK %d SECT %d POS %d\n",
+ data, fd400.cur_dsk, TRK, SECT, uptr->pos);
+ // store byte into sector buffer
+ if (uptr->pos==0) {
+ if (data==0) return 0; // ignore zero bytes before sync byte
+ }
+ if (uptr->pos >= BUF_SIZE) {
+ sim_debug (DEBUG_write, &fd400_dsk_dev, "Sector overrun - do not write data\n");
+ return 0;
+ }
+ // save byte to buffer
+ p[uptr->pos]=data;
+ uptr->pos++;
+ // calculate location of current sector in disk image file
+ loc=(TRK * NUM_SECT + SECT) * SECT_SIZE;
+ if (loc >= uptr->capac) {
+ // writing past image file current size -> extend disk image size
+ uint8 buf[SECT_SIZE];
+ memset(buf, 0, sizeof(buf));
+ sim_fseek(uptr->fileref, uptr->capac, SEEK_SET);
+ while (uptr->capac <= loc) {
+ sim_fwrite(buf, 1, SECT_SIZE, uptr->fileref);
+ uptr->capac += SECT_SIZE;
+ }
+ sim_debug (DEBUG_write, &fd400_dsk_dev, "Disk image extended up to %d bytes \n", uptr->capac);
+ }
+ // convert byte stream into sector format to save to disk.
+ // reorganize buffer to match the byte order expected by MiniDOS
+ //
+ // Data as sent to controller by MiniDOS ROM when writing a sector
+ // SY TR SE BT BS FT FS NN AH AL TY [NN data bytes] CH CL PH PL
+ // where SY=Sync Byte=$FD
+ // TR SE=This track and sector
+ // BT BS FT FS NN AH AL TY=same as below
+ // CH CL=same as below
+ //
+ // Data in MiniDOS MPX disk image:
+ // BT BS FT FS NN AH AL TY CH CL PH PL [256 data bytes] = 268 bytes
+ // where BT=Backward link track, DS=Backward link sector,
+ // FT=Forward link track, FS=Forward link sector. = 00 00 if this is last sector of file
+ // NN=Number of data bytes (00=256 bytes)
+ // AH AL=Addr in RAM where to load sector data bytes (H=High byte, L=Low byte)
+ // TY=file type
+ // CH CL=CheckSum Hi/Low byte
+ // PH PL=Postamble Hi/Low byte. Holds program start addr on last sector
+ //
+ // so we create the sector to write in disk image file (dsk_sect) reordering data from filebuf (p pointer)
+
+ memset(dsk_sect, 255, sizeof(dsk_sect));
+ for (i=0; i<8; i++) dsk_sect[i]=p[3+i]; // disk sector start with 8 byte header with bytes BT BS FT FS NN AH AL TY
+ n=uptr->pos-11; // number of data bytes
+ if (n>256+4) n=256+4;
+ if (n>4) {
+ for (i=0; i<4; i++) dsk_sect[i+8]=p[3+8+n+i-4]; // copy checksum and postamble
+ for (i=0; ifileref, loc, SEEK_SET);
+ sim_fwrite(dsk_sect, 1, SECT_SIZE, uptr->fileref);
+ return 0;
+}
+
+/* CURRENT SECTOR / FILL CHAR REGISTER */
+
+int32 fd400_cursect(int32 io, int32 data)
+{
+ UNIT * uptr;
+
+ uptr = &fd400_dsk_unit[fd400.cur_dsk];
+ if ((uptr->flags & UNIT_ATT) == 0) return 0; // not attached
+ if (io==0) {
+ // io=0 when reading from io register (return data read from i/o device register)
+ // return current sector
+ sim_debug (DEBUG_flow, &fd400_dsk_dev, "Current Drive %d TRK %d SECT %d \n",
+ fd400.cur_dsk, TRK, SECT);
+ return SECT;
+ }
+ // io=1 -> writing data to i/o register,
+ // set fill char
+ fd400.FillChar=data;
+ return 0;
+}
+
+/* RECEIVER RESTART / WRITE PULSE $CC00 */
+
+int32 fd400_startrw(int32 io, int32 data)
+{
+ UNIT * uptr;
+
+ uptr = &fd400_dsk_unit[fd400.cur_dsk];
+ if ((uptr->flags & UNIT_ATT) == 0) return 0; // not attached
+ if (io==0) {
+ // io=0 when reading from io register (return data read from i/o device register)
+ // start read from sector -> init received so it will return sync char and tracks
+ uptr->pos=0;
+ return 0;
+ }
+ // io=1 -> writing data to i/o register,
+ // start write to sector
+ uptr->pos=0;
+ return 0;
+}
+
+t_stat fd400_attach (UNIT * uptr, CONST char * file)
+{
+ t_stat r;
+
+ if ((r = attach_unit(uptr, file)) != SCPE_OK) return r;
+ uptr->u4 = uptr->u5 = 0;
+ uptr->capac = sim_fsize(uptr->fileref);
+ uptr->pos = 0;
+ return SCPE_OK;
+}
+
+/* end of fd400.c */
diff --git a/swtp6800/common/i2716.c b/swtp6800/common/i2716.c
index dd5c1365..c2ac92f3 100644
--- a/swtp6800/common/i2716.c
+++ b/swtp6800/common/i2716.c
@@ -25,8 +25,6 @@
MODIFICATIONS:
- 24 Apr 15 -- Modified to use simh_debug
-
NOTES:
These functions support a simulated 2704 to 2764 EPROMs device on an 8-bit
@@ -114,19 +112,15 @@ t_stat i2716_attach (UNIT *uptr, CONST char *cptr)
t_stat r;
FILE *fp;
- sim_debug (DEBUG_flow, &i2716_dev, "i2716_attach: cptr=%s\n", cptr);
if ((r = attach_unit (uptr, cptr)) != SCPE_OK) {
- sim_debug (DEBUG_flow, &i2716_dev, "i2716_attach: Error\n");
return r;
}
- sim_debug (DEBUG_read, &i2716_dev, "\tOpen file\n");
fp = fopen(uptr->filename, "rb"); /* open EPROM file */
if (fp == NULL) {
printf("i2716%d: Unable to open ROM file %s\n", (int)(uptr - i2716_dev.units), uptr->filename);
printf("\tNo ROM image loaded!!!\n");
return SCPE_OK;
}
- sim_debug (DEBUG_read, &i2716_dev, "\tRead file\n");
j = 0; /* load EPROM file */
c = fgetc(fp);
while (c != EOF) {
@@ -137,10 +131,7 @@ t_stat i2716_attach (UNIT *uptr, CONST char *cptr)
break;
}
}
- sim_debug (DEBUG_read, &i2716_dev, "\tClose file\n");
fclose(fp);
-// printf("i2716%d: %d bytes of ROM image %s loaded\n",uptr - i2716_dev.units, j, uptr->filename);
- sim_debug (DEBUG_flow, &i2716_dev, "i2716_attach: Done\n");
return SCPE_OK;
}
@@ -151,32 +142,21 @@ t_stat i2716_reset (DEVICE *dptr)
int32 i, base;
UNIT *uptr;
- sim_debug (DEBUG_flow, &i2716_dev, "i2716_reset: \n");
for (i = 0; i < I2716_NUM; i++) { /* init all units */
uptr = i2716_dev.units + i;
- sim_debug (DEBUG_flow, &i2716_dev, "i2716 %d unit.flags=%08X\n",
- i, uptr->flags);
uptr->capac = 2048;
uptr->u3 = 2048 * i;
base = get_base();
if (uptr->filebuf == NULL) { /* no buffer allocated */
- uptr->filebuf = malloc(2048); /* allocate EPROM buffer */
+ uptr->filebuf = calloc(2048, sizeof(uint8)); /* allocate EPROM buffer */
if (uptr->filebuf == NULL) {
- sim_debug (DEBUG_flow, &i2716_dev, "i2716_reset: Malloc error\n");
return SCPE_MEM;
}
}
if (base == 0) {
-// printf("i2716%d: Not enabled on MP-A2\n", i);
continue;
}
-// printf("i2716%d: Initializing [%04X-%04XH]\n",
-// i, base+uptr->u3, base+uptr->u3 + uptr->capac);
-// if ((uptr->flags & UNIT_ATT) == 0) {
-// printf("i2716%d: No file attached\n", i);
-// }
}
- sim_debug (DEBUG_flow, &i2716_dev, "i2716_reset: Done\n");
return SCPE_OK;
}
@@ -197,16 +177,13 @@ int32 i2716_get_mbyte(int32 offset)
len = uptr->capac - 1;
if ((offset >= org) && (offset < (org + len))) {
if (uptr->filebuf == NULL) {
- sim_debug (DEBUG_read, &i2716_dev, "i2716_get_mbyte: EPROM not configured\n");
return 0xFF;
} else {
val = *((uint8 *)(uptr->filebuf) + (offset - org));
- sim_debug (DEBUG_read, &i2716_dev, " val=%04X\n", val);
return (val & 0xFF);
}
}
}
- sim_debug (DEBUG_read, &i2716_dev, "i2716_get_mbyte: Out of range\n");
return 0xFF;
}
diff --git a/swtp6800/common/m6800.c b/swtp6800/common/m6800.c
index a63c8635..df755638 100644
--- a/swtp6800/common/m6800.c
+++ b/swtp6800/common/m6800.c
@@ -25,8 +25,8 @@
MODIFICATIONS:
- 23 Apr 15 -- Modified to use simh_debug
- 21 Apr 20 -- Richard Brinegar numerous fixes for flag errors
+ 21 Apr 20 -- Richard Brinegar numerous fixes for condition code errors
+ 28 May 22 -- Roberto Sancho Villa (RSV)some more fixes for condition code errors
NOTES:
cpu Motorola M6800 CPU
@@ -36,7 +36,7 @@
A<0:7> Accumulator A
B<0:7> Accumulator B
IX<0:15> Index Register
- CC<0:7> Condition Code Register
+ CC<0:7> Condition Code Register
HF half-carry flag
IF interrupt flag
NF negative flag
@@ -111,23 +111,47 @@
#define COND_SET_FLAG_V(COND) \
if (COND) SET_FLAG(VF); else CLR_FLAG(VF)
-/* local global variables */
+#define m6800_NAME "Motorola M6800 Processor Chip"
+#define HIST_MIN 64
+#define HIST_MAX (1u << 18)
+#define HIST_ILNT 3 /* max inst length */
+
+typedef struct {
+ uint16 pc;
+ uint16 sp;
+ uint8 cc;
+ uint8 a;
+ uint8 b;
+ uint16 ix;
+ t_value inst[HIST_ILNT];
+ } InstHistory;
+
+/* local global variables */
int32 A = 0; /* Accumulator A */
int32 B = 0; /* Accumulator B */
int32 IX = 0; /* Index register */
int32 SP = 0; /* Stack pointer */
-int32 CC = CC_ALWAYS_ON | IF; /* Condition Code Register */
-int32 saved_PC = 0; /* Program counter */
-int32 PC; /* global for the helper routines */
-
-int32 mem_fault = 0; /* memory fault flag */
-int32 NMI = 0, IRQ = 0;
+int32 CC = CC_ALWAYS_ON | IF; /* Condition Code Register */
+int32 saved_PC = 0xffff; /* Program counter */
+int32 PC; /* global for the helper routines */
+int32 NMI = 0, IRQ = 0; //interrupt flags
+int32 hst_p = 0; /* history pointer */
+int32 hst_lnt = 0; /* history length */
+InstHistory *hst = NULL; /* instruction history */
+int32 reason; //reason for halting processor
+static const char* m6800_desc(DEVICE *dptr) {
+ return m6800_NAME;
+}
/* function prototypes */
+t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
+t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat m6800_reset (DEVICE *dptr);
-t_stat m6800_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches);
+t_stat m6800_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
+t_stat m6800_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw);
+
void dump_regs(void);
int32 fetch_byte(void);
int32 fetch_word(void);
@@ -154,70 +178,70 @@ extern int32 CPU_BD_get_mbyte(int32 addr);
extern int32 CPU_BD_get_mword(int32 addr);
static const char *opcode[] = {
-"???", "NOP", "???", "???", //0x00
-"???", "???", "TAP", "TPA",
-"INX", "DEX", "CLV", "SEV",
-"CLC", "SEC", "CLI", "SEI",
-"SBA", "CBA", "???", "???", //0x10
-"???", "???", "TAB", "TBA",
-"???", "DAA", "???", "ABA",
-"???", "???", "???", "???",
-"BRA", "???", "BHI", "BLS", //0x20
-"BCC", "BCS", "BNE", "BEQ",
-"BVC", "BVS", "BPL", "BMI",
-"BGE", "BLT", "BGT", "BLE",
-"TSX", "INS", "PULA", "PULB", //0x30
-"DES", "TXS", "PSHA", "PSHB",
-"???", "RTS", "???", "RTI",
-"???", "???", "WAI", "SWI",
-"NEGA", "???", "???", "COMA", //0x40
-"LSRA", "???", "RORA", "ASRA",
-"ASLA", "ROLA", "DECA", "???",
-"INCA", "TSTA", "???", "CLRA",
-"NEGB", "???", "???", "COMB", //0x50
-"LSRB", "???", "RORB", "ASRB",
-"ASLB", "ROLB", "DECB", "???",
-"INCB", "TSTB", "???", "CLRB",
-"NEG", "???", "???", "COM", //0x60
-"LSR", "???", "ROR", "ASR",
-"ASL", "ROL", "DEC", "???",
-"INC", "TST", "JMP", "CLR",
-"NEG", "???", "???", "COM", //0x70
-"LSR", "???", "ROR", "ASR",
-"ASL", "ROL", "DEC", "???",
-"INC", "TST", "JMP", "CLR",
-"SUBA", "CMPA", "SBCA", "???", //0x80
-"ANDA", "BITA", "LDAA", "???",
-"EORA", "ADCA", "ORAA", "ADDA",
-"CPX", "BSR", "LDS", "???",
-"SUBA", "CMPA", "SBCA", "???", //0x90
-"ANDA", "BITA", "LDAA", "STAA",
-"EORA", "ADCA", "ORAA", "ADDA",
-"CPX", "???", "LDS", "STS",
-"SUBA", "CMPA", "SBCA", "???", //0xA0
-"ANDA", "BITA", "LDAA", "STAA",
-"EORA", "ADCA", "ORAA", "ADDA",
+"??? ", "NOP ", "??? ", "??? ", //0x00
+"??? ", "??? ", "TAP ", "TPA ",
+"INX ", "DEX ", "CLV ", "SEV ",
+"CLC ", "SEC ", "CLI ", "SEI ",
+"SBA ", "CBA ", "??? ", "??? ", //0x10
+"??? ", "??? ", "TAB ", "TBA ",
+"??? ", "DAA ", "??? ", "ABA ",
+"??? ", "??? ", "??? ", "??? ",
+"BRA ", "??? ", "BHI ", "BLS ", //0x20
+"BCC ", "BCS ", "BNE ", "BEQ ",
+"BVC ", "BVS ", "BPL ", "BMI ",
+"BGE ", "BLT ", "BGT ", "BLE ",
+"TSX ", "INS ", "PUL A", "PUL B", //0x30
+"DES ", "TXS ", "PSH A", "PSH B",
+"??? ", "RTS ", "??? ", "RTI ",
+"??? ", "??? ", "WAI ", "SWI ",
+"NEG A", "??? ", "??? ", "COM A", //0x40
+"LSR A", "??? ", "ROR A", "ASR A",
+"ASL A", "ROL A", "DEC A", "??? ",
+"INC A", "TST A", "??? ", "CLR A",
+"NEG B", "??? ", "??? ", "COM B", //0x50
+"LSR B", "??? ", "ROR B", "ASR B",
+"ASL B", "ROL B", "DEC B", "??? ",
+"INC B", "TST B", "??? ", "CLR B",
+"NEG ", "??? ", "??? ", "COM ", //0x60
+"LSR ", "??? ", "ROR ", "ASR ",
+"ASL ", "ROL ", "DEC ", "??? ",
+"INC ", "TST ", "JMP ", "CLR ",
+"NEG ", "??? ", "??? ", "COM ", //0x70
+"LSR ", "??? ", "ROR ", "ASR ",
+"ASL ", "ROL ", "DEC ", "??? ",
+"INC ", "TST ", "JMP ", "CLR ",
+"SUB A", "CMP A", "SBC A", "??? ", //0x80
+"AND A", "BIT A", "LDA A", "??? ",
+"EOR A", "ADC A", "ORA A", "ADD A",
+"CPX ", "BSR ", "LDS ", "??? ",
+"SUB A", "CMP A", "SBC A", "??? ", //0x90
+"AND A", "BIT A", "LDA A", "STA A",
+"EOR A", "ADC A", "ORA A", "ADD A",
+"CPX ", "??? ", "LDS ", "STS ",
+"SUB A", "CMP A", "SBC A", "??? ", //0xA0
+"AND A", "BIT A", "LDA A", "STA A",
+"EOR A", "ADC A", "ORA A", "ADD A",
"CPX X", "JSR X", "LDS X", "STS X",
-"SUBA", "CMPA", "SBCA", "???", //0xB0
-"ANDA", "BITA", "LDAA", "STAA",
-"EORA", "ADCA", "ORAA", "ADDA",
-"CPX", "JSR", "LDS", "STS",
-"SUBB", "CMPB", "SBCB", "???", //0xC0
-"ANDB", "BITB", "LDAB", "???",
-"EORB", "ADCB", "ORAB", "ADDB",
-"???", "???", "LDX", "???",
-"SUBB", "CMPB", "SBCB", "???", //0xD0
-"ANDB", "BITB", "LDAB", "STAB",
-"EORB", "ADCB", "ORAB", "ADDB",
-"???", "???", "LDX", "STX",
-"SUBB", "CMPB", "SBCB", "???", //0xE0
-"ANDB", "BITB", "LDAB", "STAB",
-"EORB", "ADCB", "ORAB", "ADDB",
-"???", "???", "LDX", "STX",
-"SUBB", "CMPB", "SBCB", "???", //0xF0
-"ANDB", "BITB", "LDAB", "STAB",
-"EORB", "ADCB", "ORAB", "ADDB",
-"???", "???", "LDX", "STX",
+"SUB A", "CMP A", "SBC A", "??? ", //0xB0
+"AND A", "BIT A", "LDA A", "STA A",
+"EOR A", "ADC A", "ORA A", "ADD A",
+"CPX ", "JSR ", "LDS ", "STS ",
+"SUB B", "CMP B", "SBC B", "??? ", //0xC0
+"AND B", "BIT B", "LDA B", "??? ",
+"EOR B", "ADC B", "ORA B", "ADD B",
+"??? ", "??? ", "LDX ", "??? ",
+"SUB B", "CMP B", "SBC B", "??? ", //0xD0
+"AND B", "BIT B", "LDA B", "STA B",
+"EOR B", "AD CB", "ORA B", "ADD B",
+"??? ", "??? ", "LDX ", "STX ",
+"SUB B", "CMP B", "SBC B", "??? ", //0xE0
+"AND B", "BIT B", "LDA B", "STA B",
+"EOR B", "ADC B", "ORA B", "ADD B",
+"??? ", "??? ", "LDX ", "STX ",
+"SUB B", "CMP B", "SBC B", "??? ", //0xF0
+"AND B", "BIT B", "LDA B", "STA B",
+"EOR B", "ADC B", "ORA B", "ADD B",
+"??? ", "??? ", "LDX ", "STX ",
};
int32 oplen[256] = {
@@ -256,14 +280,18 @@ REG m6800_reg[] = {
{ HRDATA (SP, SP, 16) },
{ HRDATA (CC, CC, 8) },
{ ORDATA (WRU, sim_int_char, 8) },
- { NULL } };
+ { NULL }
+};
MTAB m6800_mod[] = {
{ UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL },
{ UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL },
{ UNIT_MSTOP, UNIT_MSTOP, "MTRAP", "MTRAP", NULL },
{ UNIT_MSTOP, 0, "NOMTRAP", "NOMTRAP", NULL },
- { 0 } };
+ { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP|MTAB_NC, 0, "HISTORY", "HISTORY=n",
+ &cpu_set_hist, &cpu_show_hist, NULL, "Enable/Display instruction history" },
+ { 0 }
+};
DEBTAB m6800_debug[] = {
{ "ALL", DEBUG_all, "All debug bits" },
@@ -284,8 +312,8 @@ DEVICE m6800_dev = {
1, //aincr
16, //dradix
8, //dwidth
- &m6800_examine, //examine
- NULL, //deposit
+ &m6800_ex, //examine
+ &m6800_dep, //deposit
&m6800_reset, //reset
NULL, //boot
NULL, //attach
@@ -295,12 +323,17 @@ DEVICE m6800_dev = {
0, //dctrl
m6800_debug, //debflags
NULL, //msize
- NULL //lname
+ NULL, //lname
+ NULL, //help routine
+ NULL, //attach help routine
+ NULL, //help context
+ &m6800_desc //device description
};
t_stat sim_instr (void)
{
- int32 IR, EA, reason, hi, lo, op1;
+ int32 IR, EA, hi, lo, op1, i, sw = 0;
+ InstHistory *hst_ent = NULL;
PC = saved_PC & ADDRMASK; /* load local PC */
reason = 0;
@@ -311,11 +344,6 @@ t_stat sim_instr (void)
if (sim_interval <= 0) /* check clock queue */
if ((reason = sim_process_event ()))
break;
- //if (mem_fault) { /* memory fault? */
- //mem_fault = 0; /* reset fault flag */
- //reason = STOP_MEMORY;
- //break;
- //}
if (NMI > 0) { //* NMI? */
push_word(PC);
push_word(IX);
@@ -331,6 +359,7 @@ t_stat sim_instr (void)
push_byte(A);
push_byte(B);
push_byte(CC);
+ SET_FLAG(IF); //rsv fix
PC = get_vec_val(0xFFF8);
}
} /* end IRQ */
@@ -340,13 +369,27 @@ t_stat sim_instr (void)
break;
}
+ if (hst_lnt) { /* record history? */
+ hst_ent = &hst[hst_p];
+ hst_ent->pc = PC;
+ hst_ent->sp = SP;
+ hst_ent->cc = CC;
+ hst_ent->a = A;
+ hst_ent->b = B;
+ hst_ent->ix = IX;
+ for (i = 0; i < HIST_ILNT; i++)
+ hst_ent->inst[i] = (t_value)CPU_BD_get_mbyte (PC + i);
+ hst_p = (hst_p + 1);
+ if (hst_p >= hst_lnt)
+ hst_p = 0;
+ }
+
sim_interval--;
IR = fetch_byte(); /* fetch instruction */
/* The Big Instruction Decode Switch */
switch (IR) {
-
case 0x01: /* NOP */
break;
case 0x06: /* TAP */
@@ -385,7 +428,7 @@ t_stat sim_instr (void)
op1 = A;
A = A - B;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVs(op1, B);
@@ -393,7 +436,7 @@ t_stat sim_instr (void)
case 0x11: /* CBA */
lo = A - B;
COND_SET_FLAG_C(lo);
- lo &= 0xFF ;
+ lo &= BYTEMASK;
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
condevalVs(A, B);
@@ -423,7 +466,7 @@ t_stat sim_instr (void)
A = (A & 0x0F) | (EA << 4) | 0x100;
}
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
@@ -431,7 +474,7 @@ t_stat sim_instr (void)
op1 = A ;
A += B;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
condevalHa(op1, B);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
@@ -540,15 +583,15 @@ t_stat sim_instr (void)
PC = get_vec_val(0xFFFA);
break;
case 0x40: /* NEG A */
- COND_SET_FLAG_V(A == 0x80);
- A = (0 - A);
- COND_SET_FLAG_C(A);
- A &= 0xFF;
+ op1 = A;
+ A = (0 - A) & BYTEMASK;
+ condevalVs(A, op1); //RSV - fixed boundry condition
+ COND_SET_FLAG(A,CF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0x43: /* COM A */
- A = ~A & 0xFF;
+ A = ~A & BYTEMASK;
CLR_FLAG(VF);
SET_FLAG(CF);
COND_SET_FLAG_N(A);
@@ -556,7 +599,7 @@ t_stat sim_instr (void)
break;
case 0x44: /* LSR A */
COND_SET_FLAG(A & 0x01,CF);
- A = (A >> 1) & 0xFF;
+ A = (A >> 1) & BYTEMASK;
CLR_FLAG(NF);
COND_SET_FLAG_Z(A);
COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
@@ -564,7 +607,7 @@ t_stat sim_instr (void)
case 0x46: /* ROR A */
hi = get_flag(CF);
COND_SET_FLAG(A & 0x01,CF);
- A = (A >> 1) & 0xFF;
+ A = (A >> 1) & BYTEMASK;
if (hi)
A |= 0x80;
COND_SET_FLAG_N(A);
@@ -574,7 +617,7 @@ t_stat sim_instr (void)
case 0x47: /* ASR A */
COND_SET_FLAG(A & 0x01,CF);
lo = A & 0x80;
- A = (A >> 1) & 0xFF;
+ A = (A >> 1) & BYTEMASK;
A |= lo;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
@@ -582,7 +625,7 @@ t_stat sim_instr (void)
break;
case 0x48: /* ASL A */
COND_SET_FLAG(A & 0x80,CF);
- A = (A << 1) & 0xFF;
+ A = (A << 1) & BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
@@ -590,7 +633,7 @@ t_stat sim_instr (void)
case 0x49: /* ROL A */
hi = get_flag(CF);
COND_SET_FLAG(A & 0x80,CF);
- A = (A << 1) & 0xFF;
+ A = (A << 1) & BYTEMASK;
if (hi)
A |= 0x01;
COND_SET_FLAG_N(A);
@@ -599,18 +642,18 @@ t_stat sim_instr (void)
break;
case 0x4A: /* DEC A */
COND_SET_FLAG_V(A == 0x80);
- A = (A - 1) & 0xFF;
+ A = (A - 1) & BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0x4C: /* INC A */
COND_SET_FLAG_V(A == 0x7F);
- A = (A + 1) & 0xFF;
+ A = (A + 1) & BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0x4D: /* TST A */
- lo = (A - 0) & 0xFF;
+ lo = (A - 0) & BYTEMASK;
CLR_FLAG(VF);
CLR_FLAG(CF);
COND_SET_FLAG_N(lo);
@@ -624,16 +667,16 @@ t_stat sim_instr (void)
SET_FLAG(ZF);
break;
case 0x50: /* NEG B */
- COND_SET_FLAG_V(B == 0x80);
- B = (0 - B);
- COND_SET_FLAG_C(B);
- B &= 0xFF;
+ op1 = B;
+ B = (0 - B) & BYTEMASK;
+ condevalVs(B, op1); //RSV - fixed boundry condition
+ COND_SET_FLAG(B,CF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0x53: /* COM B */
B = ~B;
- B &= 0xFF;
+ B &= BYTEMASK;
CLR_FLAG(VF);
SET_FLAG(CF);
COND_SET_FLAG_N(B);
@@ -641,7 +684,7 @@ t_stat sim_instr (void)
break;
case 0x54: /* LSR B */
COND_SET_FLAG(B & 0x01,CF);
- B = (B >> 1) & 0xFF;
+ B = (B >> 1) & BYTEMASK;
CLR_FLAG(NF);
COND_SET_FLAG_Z(B);
COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
@@ -649,7 +692,7 @@ t_stat sim_instr (void)
case 0x56: /* ROR B */
hi = get_flag(CF);
COND_SET_FLAG(B & 0x01,CF);
- B = (B >> 1) & 0xFF;
+ B = (B >> 1) & BYTEMASK;
if (hi)
B |= 0x80;
COND_SET_FLAG_N(B);
@@ -659,7 +702,7 @@ t_stat sim_instr (void)
case 0x57: /* ASR B */
COND_SET_FLAG(B & 0x01,CF);
lo = B & 0x80;
- B = (B >> 1) & 0xFF;
+ B = (B >> 1) & BYTEMASK;
B |= lo;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
@@ -667,7 +710,7 @@ t_stat sim_instr (void)
break;
case 0x58: /* ASL B */
COND_SET_FLAG(B & 0x80,CF);
- B = (B << 1) & 0xFF;
+ B = (B << 1) & BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
@@ -675,7 +718,7 @@ t_stat sim_instr (void)
case 0x59: /* ROL B */
hi = get_flag(CF);
COND_SET_FLAG(B & 0x80,CF);
- B = (B << 1) & 0xFF;
+ B = (B << 1) & BYTEMASK;
if (hi)
B |= 0x01;
COND_SET_FLAG_N(B);
@@ -684,18 +727,18 @@ t_stat sim_instr (void)
break;
case 0x5A: /* DEC B */
COND_SET_FLAG_V(B == 0x80);
- B = (B - 1) & 0xFF;
+ B = (B - 1) & BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0x5C: /* INC B */
COND_SET_FLAG_V(B == 0x7F);
- B = (B + 1) & 0xFF;
+ B = (B + 1) & BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0x5D: /* TST B */
- lo = (B - 0) & 0xFF;
+ lo = (B - 0) & BYTEMASK;
CLR_FLAG(VF);
CLR_FLAG(CF);
COND_SET_FLAG_N(lo);
@@ -711,18 +754,17 @@ t_stat sim_instr (void)
case 0x60: /* NEG ind */
EA = (fetch_byte() + IX) & ADDRMASK;
op1 = CPU_BD_get_mbyte(EA);
- COND_SET_FLAG_V(op1 == 0x80);
- lo = (0 - op1);
- COND_SET_FLAG_C(lo);
- lo &= 0xFF;
+ lo = (0 - op1) & BYTEMASK;
CPU_BD_put_mbyte(EA, lo);
+ condevalVs(lo, op1); //RSV - fixed boundry condition
+ COND_SET_FLAG(lo,CF);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
break;
case 0x63: /* COM ind */
EA = (fetch_byte() + IX) & ADDRMASK;
lo = ~CPU_BD_get_mbyte(EA);
- lo &= 0xFF;
+ lo &= BYTEMASK;
CPU_BD_put_mbyte(EA, lo);
CLR_FLAG(VF);
SET_FLAG(CF);
@@ -766,7 +808,7 @@ t_stat sim_instr (void)
EA = (fetch_byte() + IX) & ADDRMASK;
lo = CPU_BD_get_mbyte(EA);
COND_SET_FLAG(lo & 0x80,CF);
- lo = (lo << 1) & 0xFF;
+ lo = (lo << 1) & BYTEMASK;
CPU_BD_put_mbyte(EA, lo);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -777,7 +819,7 @@ t_stat sim_instr (void)
lo = CPU_BD_get_mbyte(EA);
hi = get_flag(CF);
COND_SET_FLAG(lo & 0x80,CF);
- lo = (lo << 1) &0xFF;
+ lo = (lo << 1) &BYTEMASK;
if (hi) lo |= 0x01;
CPU_BD_put_mbyte(EA, lo);
COND_SET_FLAG_N(lo);
@@ -788,7 +830,7 @@ t_stat sim_instr (void)
EA = (fetch_byte() + IX) & ADDRMASK;
lo = CPU_BD_get_mbyte(EA);
COND_SET_FLAG_V(lo == 0x80);
- lo = (lo - 1) & 0xFF;
+ lo = (lo - 1) & BYTEMASK;
CPU_BD_put_mbyte(EA, lo);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -797,13 +839,13 @@ t_stat sim_instr (void)
EA= (fetch_byte() + IX) & ADDRMASK;
lo = CPU_BD_get_mbyte(EA);
COND_SET_FLAG_V(lo == 0x7F);
- lo = (lo + 1) & 0xFF;
+ lo = (lo + 1) & BYTEMASK;
CPU_BD_put_mbyte(EA, lo);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
break;
case 0x6D: /* TST ind */
- lo = (get_indir_val() - 0) & 0xFF;
+ lo = (get_indir_val() - 0) & BYTEMASK;
CLR_FLAG(VF);
CLR_FLAG(CF);
COND_SET_FLAG_N(lo);
@@ -822,17 +864,19 @@ t_stat sim_instr (void)
case 0x70: /* NEG ext */
EA = fetch_word();
op1 = CPU_BD_get_mbyte(EA);
- COND_SET_FLAG_V(op1 == 0x80) ;
- COND_SET_FLAG(op1 != 0, CF);
- lo = (0 - op1) & 0xFF;
+ lo = (0 - op1) & BYTEMASK;
CPU_BD_put_mbyte(EA, lo);
+ condevalVs(lo, op1); //RSV - fixed boundry condition
+ CLR_FLAG(CF);
+ if (lo)
+ SET_FLAG(CF);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
break;
case 0x73: /* COM ext */
EA = fetch_word();
lo = ~CPU_BD_get_mbyte(EA);
- lo &= 0xFF;
+ lo &= BYTEMASK;
CPU_BD_put_mbyte(EA, lo);
CLR_FLAG(VF);
SET_FLAG(CF);
@@ -878,7 +922,7 @@ t_stat sim_instr (void)
EA = fetch_word();
lo = CPU_BD_get_mbyte(EA);
COND_SET_FLAG(lo & 0x80,CF);
- lo = (lo << 1) & 0xFF;
+ lo = (lo << 1) & BYTEMASK;
CPU_BD_put_mbyte(EA, lo);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -889,7 +933,7 @@ t_stat sim_instr (void)
lo = CPU_BD_get_mbyte(EA);
hi = get_flag(CF);
COND_SET_FLAG(lo & 0x80,CF);
- lo = (lo << 1) & 0xFF;
+ lo = (lo << 1) & BYTEMASK;
if (hi) lo |= 0x01;
CPU_BD_put_mbyte(EA, lo);
COND_SET_FLAG_N(lo);
@@ -900,7 +944,7 @@ t_stat sim_instr (void)
EA = fetch_word();
lo = CPU_BD_get_mbyte(EA);
COND_SET_FLAG_V(lo == 0x80);
- lo = (lo - 1) & 0xFF;
+ lo = (lo - 1) & BYTEMASK;
CPU_BD_put_mbyte(EA, lo);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -909,7 +953,7 @@ t_stat sim_instr (void)
EA = fetch_word();
lo = CPU_BD_get_mbyte(EA);
COND_SET_FLAG_V(lo == 0x7F);
- lo = (lo + 1) & 0xFF;
+ lo = (lo + 1) & BYTEMASK;
CPU_BD_put_mbyte(EA, lo);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -919,7 +963,7 @@ t_stat sim_instr (void)
CLR_FLAG(VF);
CLR_FLAG(CF);
COND_SET_FLAG_N(lo);
- lo &= 0xFF;
+ lo &= BYTEMASK;
COND_SET_FLAG_Z(lo);
break;
case 0x7E: /* JMP ext */
@@ -933,81 +977,81 @@ t_stat sim_instr (void)
SET_FLAG(ZF);
break;
case 0x80: /* SUB A imm */
- lo = fetch_byte() & 0xFF;
+ lo = fetch_byte();
op1 = A;
A = A - lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break;
case 0x81: /* CMP A imm */
- op1 = fetch_byte() & 0xFF;
+ op1 = fetch_byte();
lo = A - op1;
COND_SET_FLAG_C(lo);
- lo &= 0xFF;
+ lo &= BYTEMASK;
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
condevalVs(A, op1);
break;
case 0x82: /* SBC A imm */
- lo = fetch_byte() & 0xFF + get_flag(CF);
+ lo = (fetch_byte() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
op1 = A;
A = A - lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break;
case 0x84: /* AND A imm */
- A = (A & fetch_byte() & 0xFF) & 0xFF;
+ A = (A & fetch_byte()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0x85: /* BIT A imm */
- lo = (A & fetch_byte() & 0xFF) & 0xFF;
+ lo = (A & fetch_byte()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
break;
case 0x86: /* LDA A imm */
- A = fetch_byte() & 0xFF;
+ A = fetch_byte();
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0x88: /* EOR A imm */
- A = (A ^ fetch_byte() & 0xFF) & 0xFF;
+ A = (A ^ fetch_byte()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0x89: /* ADC A imm */
- lo = fetch_byte() & 0xFF + get_flag(CF);
+ lo = (fetch_byte() + get_flag(CF)) & BYTEMASK;
op1 = A;
A = A + lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break;
case 0x8A: /* ORA A imm */
- A = (A | fetch_byte() & 0xFF) & 0xFF;
+ A = (A | fetch_byte()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0x8B: /* ADD A imm */
- lo = fetch_byte() & 0xFF;
+ lo = fetch_byte();
op1 = A;
A = A + lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
@@ -1039,7 +1083,7 @@ t_stat sim_instr (void)
op1 = A;
A = A - lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
@@ -1050,27 +1094,26 @@ t_stat sim_instr (void)
COND_SET_FLAG_N(lo);
COND_SET_FLAG_C(lo);
condevalVs(A, op1);
- lo &= 0xFF;
+ lo &= BYTEMASK;
COND_SET_FLAG_Z(lo);
break;
case 0x92: /* SBC A dir */
- lo = get_dir_val() + get_flag(CF);
- op1 = A;
+ lo = (get_dir_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
A = A - lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break;
case 0x94: /* AND A dir */
- A = (A & get_dir_val()) & 0xFF;
+ A = (A & get_dir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0x95: /* BIT A dir */
- lo = (A & get_dir_val()) & 0xFF;
+ lo = (A & get_dir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -1082,30 +1125,30 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A);
break;
case 0x97: /* STA A dir */
- CPU_BD_put_mbyte(fetch_byte() & 0xFF, A);
+ CPU_BD_put_mbyte(fetch_byte(), A);
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0x98: /* EOR A dir */
- A = (A ^ get_dir_val()) & 0xFF;
+ A = (A ^ get_dir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0x99: /* ADC A dir */
- lo = get_dir_val() + get_flag(CF);
+ lo = (get_dir_val() + get_flag(CF)) & BYTEMASK;
op1 = A;
A = A + lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break;
case 0x9A: /* ORA A dir */
- A = (A | get_dir_val()) & 0xFF;
+ A = (A | get_dir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
@@ -1115,26 +1158,26 @@ t_stat sim_instr (void)
op1 = A;
A = A + lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break;
case 0x9C: /* CPX dir */
- op1 = IX - CPU_BD_get_mword(fetch_byte() & 0xFF);
+ op1 = IX - CPU_BD_get_mword(fetch_byte());
COND_SET_FLAG_Z(op1);
COND_SET_FLAG_N(op1 >> 8);
COND_SET_FLAG_V(op1 & 0x10000);
break;
case 0x9E: /* LDS dir */
- SP = CPU_BD_get_mword(fetch_byte() & 0xFF);
+ SP = CPU_BD_get_mword(fetch_byte());
COND_SET_FLAG_N(SP >> 8);
COND_SET_FLAG_Z(SP);
CLR_FLAG(VF);
break;
case 0x9F: /* STS dir */
- CPU_BD_put_mword(fetch_byte() & 0xFF, SP);
+ CPU_BD_put_mword(fetch_byte(), SP);
COND_SET_FLAG_N(SP >> 8);
COND_SET_FLAG_Z(SP);
CLR_FLAG(VF);
@@ -1144,7 +1187,7 @@ t_stat sim_instr (void)
op1 = A;
A = A - lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
@@ -1155,27 +1198,26 @@ t_stat sim_instr (void)
COND_SET_FLAG_N(lo);
COND_SET_FLAG_C(lo);
condevalVs(A, op1);
- lo &= 0xFF;
+ lo &= BYTEMASK;
COND_SET_FLAG_Z(lo);
break;
case 0xA2: /* SBC A ind */
- lo = get_indir_val() + get_flag(CF);
- op1 = A;
+ lo = (get_indir_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
A = A - lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break;
case 0xA4: /* AND A ind */
- A = (A & get_indir_val()) & 0xFF;
+ A = (A & get_indir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0xA5: /* BIT A ind */
- lo = (A & get_indir_val()) & 0xFF;
+ lo = (A & get_indir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -1193,24 +1235,24 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A);
break;
case 0xA8: /* EOR A ind */
- A = (A ^ get_indir_val()) & 0xFF;
+ A = (A ^ get_indir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0xA9: /* ADC A ind */
- lo = get_indir_val() + get_flag(CF);
+ lo = (get_indir_val() + get_flag(CF)) & BYTEMASK;
op1 = A;
A = A + lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break;
case 0xAA: /* ORA A ind */
- A = (A | get_indir_val()) & 0xFF;
+ A = (A | get_indir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
@@ -1220,7 +1262,7 @@ t_stat sim_instr (void)
op1 = A;
A = A + lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
@@ -1254,7 +1296,7 @@ t_stat sim_instr (void)
op1 = A;
A = A - lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
@@ -1265,27 +1307,27 @@ t_stat sim_instr (void)
COND_SET_FLAG_N(lo);
COND_SET_FLAG_C(lo);
condevalVs(A, op1);
- lo &= 0xFF;
+ lo &= BYTEMASK;
COND_SET_FLAG_Z(lo);
break;
case 0xB2: /* SBC A ext */
- lo = get_ext_val() + get_flag(CF);
+ lo = (get_ext_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
op1 = A;
A = A - lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVs(op1, lo);
break;
case 0xB4: /* AND A ext */
- A = (A & get_ext_val()) & 0xFF;
+ A = (A & get_ext_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0xB5: /* BIT A ext */
- lo = (A & get_ext_val()) & 0xFF;
+ lo = (A & get_ext_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -1303,24 +1345,24 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(A);
break;
case 0xB8: /* EOR A ext */
- A = (A ^ get_ext_val()) & 0xFF;
+ A = (A ^ get_ext_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
break;
case 0xB9: /* ADC A ext */
- lo = get_ext_val() + get_flag(CF);
+ lo = (get_ext_val() + get_flag(CF)) & BYTEMASK;
op1 = A;
A = A + lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
condevalVa(op1, lo);
break;
case 0xBA: /* ORA A ext */
- A = (A | get_ext_val()) & 0xFF;
+ A = (A | get_ext_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
@@ -1330,7 +1372,7 @@ t_stat sim_instr (void)
op1 = A;
A = A + lo;
COND_SET_FLAG_C(A);
- A &= 0xFF;
+ A &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(A);
COND_SET_FLAG_Z(A);
@@ -1360,81 +1402,81 @@ t_stat sim_instr (void)
CLR_FLAG(VF);
break;
case 0xC0: /* SUB B imm */
- lo = fetch_byte() & 0xFF;
+ lo = fetch_byte();
op1 = B;
B = B - lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break;
case 0xC1: /* CMP B imm */
- op1 = fetch_byte() & 0xFF;
+ op1 = fetch_byte();
lo = B - op1;
COND_SET_FLAG_N(lo);
COND_SET_FLAG_C(lo);
condevalVs(B, op1);
- lo &= 0xFF;
+ lo &= BYTEMASK;
COND_SET_FLAG_Z(lo);
break;
case 0xC2: /* SBC B imm */
- lo = fetch_byte() & 0xFF + get_flag(CF);
+ lo = (fetch_byte() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
op1 = B;
B = B - lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break;
case 0xC4: /* AND B imm */
- B = (B & fetch_byte() & 0xFF) & 0xFF;
+ B = (B & fetch_byte()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xC5: /* BIT B imm */
- lo = (B & fetch_byte() & 0xFF) & 0xFF;
+ lo = (B & fetch_byte()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
break;
case 0xC6: /* LDA B imm */
- B = fetch_byte() & 0xFF;
+ B = fetch_byte();
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xC8: /* EOR B imm */
- B = (B ^ fetch_byte() & 0xFF) & 0xFF;
+ B = (B ^ fetch_byte()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xC9: /* ADC B imm */
- lo = fetch_byte() & 0xFF + get_flag(CF);
+ lo = (fetch_byte() + get_flag(CF)) & BYTEMASK;
op1 = B;
B = B + lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break;
case 0xCA: /* ORA B imm */
- B = (B | fetch_byte() & 0xFF) & 0xFF;
+ B = (B | fetch_byte()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xCB: /* ADD B imm */
- lo = fetch_byte() & 0xFF;
+ lo = fetch_byte();
op1 = B;
B = B + lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
@@ -1451,7 +1493,7 @@ t_stat sim_instr (void)
op1 = B;
B = B - lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
@@ -1460,29 +1502,29 @@ t_stat sim_instr (void)
lo = get_dir_val();
op1 = B - lo;
COND_SET_FLAG_C(op1);
- op1 &= 0xFF;
+ op1 &= BYTEMASK;
COND_SET_FLAG_N(op1);
COND_SET_FLAG_Z(op1);
condevalVs(B, lo);
break;
case 0xD2: /* SBC B dir */
- lo = get_dir_val() + get_flag(CF);
+ lo = (get_dir_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
op1 = B;
B = B - lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break;
case 0xD4: /* AND B dir */
- B = (B & get_dir_val()) & 0xFF;
+ B = (B & get_dir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xD5: /* BIT B dir */
- lo = (B & get_dir_val()) & 0xFF;
+ lo = (B & get_dir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -1494,30 +1536,30 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B);
break;
case 0xD7: /* STA B dir */
- CPU_BD_put_mbyte(fetch_byte() & 0xFF, B);
+ CPU_BD_put_mbyte(fetch_byte(), B);
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xD8: /* EOR B dir */
- B = (B ^ get_dir_val()) & 0xFF;
+ B = (B ^ get_dir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xD9: /* ADC B dir */
- lo = get_dir_val() + get_flag(CF);
+ lo = (get_dir_val() + get_flag(CF)) & BYTEMASK;
op1 = B;
B = B + lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break;
case 0xDA: /* ORA B dir */
- B = (B | get_dir_val()) & 0xFF;
+ B = (B | get_dir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
@@ -1527,20 +1569,20 @@ t_stat sim_instr (void)
op1 = B;
B = B + lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break;
case 0xDE: /* LDX dir */
- IX = CPU_BD_get_mword(fetch_byte() & 0xFF);
+ IX = CPU_BD_get_mword(fetch_byte());
COND_SET_FLAG_N(IX >> 8);
COND_SET_FLAG_Z(IX);
CLR_FLAG(VF);
break;
case 0xDF: /* STX dir */
- CPU_BD_put_mword(fetch_byte() & 0xFF, IX);
+ CPU_BD_put_mword(fetch_byte(), IX);
COND_SET_FLAG_N(IX >> 8);
COND_SET_FLAG_Z(IX);
CLR_FLAG(VF);
@@ -1550,7 +1592,7 @@ t_stat sim_instr (void)
op1 = B;
B = B - lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
@@ -1561,27 +1603,27 @@ t_stat sim_instr (void)
COND_SET_FLAG_N(lo);
COND_SET_FLAG_C(lo);
condevalVs(B, op1);
- lo &= 0xFF;
+ lo &= BYTEMASK;
COND_SET_FLAG_Z(lo);
break;
case 0xE2: /* SBC B ind */
- lo = get_indir_val() + get_flag(CF);
+ lo = (get_indir_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
op1 = B;
B = B - lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break;
case 0xE4: /* AND B ind */
- B = (B & get_indir_val()) & 0xFF;
+ B = (B & get_indir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xE5: /* BIT B ind */
- lo = (B & get_indir_val()) & 0xFF;
+ lo = (B & get_indir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -1599,24 +1641,24 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B);
break;
case 0xE8: /* EOR B ind */
- B = (B ^ get_indir_val()) & 0xFF;
+ B = (B ^ get_indir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xE9: /* ADC B ind */
- lo = get_indir_val() + get_flag(CF);
+ lo = (get_indir_val() + get_flag(CF)) & BYTEMASK;
op1 = B;
B = B + lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break;
case 0xEA: /* ORA B ind */
- B = (B | get_indir_val()) & 0xFF;
+ B = (B | get_indir_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
@@ -1626,7 +1668,7 @@ t_stat sim_instr (void)
op1 = B;
B = B + lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
@@ -1649,7 +1691,7 @@ t_stat sim_instr (void)
op1 = B;
B = B - lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
@@ -1660,27 +1702,27 @@ t_stat sim_instr (void)
COND_SET_FLAG_N(lo);
COND_SET_FLAG_C(lo);
condevalVs(B, op1);
- lo &= 0xFF;
+ lo &= BYTEMASK;
COND_SET_FLAG_Z(lo);
break;
case 0xF2: /* SBC B ext */
- lo = get_ext_val() + get_flag(CF);
+ lo = (get_ext_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
op1 = B;
B = B - lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVs(op1, lo);
break;
case 0xF4: /* AND B ext */
- B = (B & get_ext_val()) & 0xFF;
+ B = (B & get_ext_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xF5: /* BIT B ext */
- lo = (B & get_ext_val()) & 0xFF;
+ lo = (B & get_ext_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(lo);
COND_SET_FLAG_Z(lo);
@@ -1698,24 +1740,24 @@ t_stat sim_instr (void)
COND_SET_FLAG_Z(B);
break;
case 0xF8: /* EOR B ext */
- B = (B ^ get_ext_val()) & 0xFF;
+ B = (B ^ get_ext_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
break;
case 0xF9: /* ADC B ext */
- lo = get_ext_val() + get_flag(CF);
+ lo = (get_ext_val() + get_flag(CF)) & BYTEMASK;
op1 = B;
B = B + lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
condevalVa(op1, lo);
break;
case 0xFA: /* ORA B ext */
- B = (B | get_ext_val()) & 0xFF;
+ B = (B | get_ext_val()) & BYTEMASK;
CLR_FLAG(VF);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
@@ -1725,7 +1767,7 @@ t_stat sim_instr (void)
op1 = B;
B = B + lo;
COND_SET_FLAG_C(B);
- B &= 0xFF;
+ B &= BYTEMASK;
condevalHa(op1, lo);
COND_SET_FLAG_N(B);
COND_SET_FLAG_Z(B);
@@ -1754,7 +1796,6 @@ t_stat sim_instr (void)
}
}
/* Simulation halted - lets dump all the registers! */
- dump_regs();
saved_PC = PC;
return reason;
}
@@ -1772,7 +1813,8 @@ int32 fetch_byte(void)
{
uint8 val;
- val = CPU_BD_get_mbyte(PC) & 0xFF; /* fetch byte */
+ val = CPU_BD_get_mbyte(PC) & BYTEMASK; /* fetch byte */
+ //rsv fix on opernd order but moved the "& BYTEMASK" here
PC = (PC + 1) & ADDRMASK; /* increment PC */
return val;
}
@@ -1783,7 +1825,7 @@ int32 fetch_word(void)
uint16 val;
val = CPU_BD_get_mbyte(PC) << 8; /* fetch high byte */
- val |= CPU_BD_get_mbyte(PC + 1) & 0xFF; /* fetch low byte */
+ val |= CPU_BD_get_mbyte(PC + 1) & BYTEMASK; /* fetch low byte */
PC = (PC + 2) & ADDRMASK; /* increment PC */
return val;
}
@@ -1791,14 +1833,15 @@ int32 fetch_word(void)
/* push a byte to the stack */
void push_byte(uint8 val)
{
- CPU_BD_put_mbyte(SP, val & 0xFF);
+ CPU_BD_put_mbyte(SP, val & BYTEMASK);
+ //rsv fix on opernd order but moved the "& BYTEMASK" here
SP = (SP - 1) & ADDRMASK;
}
/* push a word to the stack */
void push_word(uint16 val)
{
- push_byte(val & 0xFF);
+ push_byte(val & BYTEMASK);
push_byte(val >> 8);
}
@@ -1848,14 +1891,14 @@ int32 get_vec_val(int32 vec)
int32 get_imm_val(void)
{
- return (fetch_byte() & 0xFF);
+ return fetch_byte();
}
/* returns the value at the direct address pointed to by PC */
int32 get_dir_val(void)
{
- return CPU_BD_get_mbyte(fetch_byte() & 0xFF);
+ return CPU_BD_get_mbyte(fetch_byte());
}
/* returns the value at the indirect address pointed to by PC */
@@ -1918,16 +1961,16 @@ void condevalHa(int32 op1, int32 op2)
/* Reset routine */
-t_stat m6800_reset (DEVICE *dptr)
+t_stat m6800_reset(DEVICE *dptr)
{
CC = CC_ALWAYS_ON | IF;
NMI = 0, IRQ = 0;
sim_brk_types = sim_brk_dflt = SWMASK ('E');
saved_PC = CPU_BD_get_mword(0xFFFE);
-// if (saved_PC == 0xFFFF)
-// printf("No EPROM image found - M6800 reset incomplete!\n");
-// else
-// printf("EPROM vector=%04X\n", saved_PC);
+ if ((saved_PC == 0xFFFF) && ((sim_switches & SWMASK ('P')) == 0)) {
+ printf("No EPROM image found\n");
+ reason = STOP_MEMORY; /* stop simulation - no ROM*/
+ }
return SCPE_OK;
}
@@ -1936,19 +1979,113 @@ t_stat m6800_reset (DEVICE *dptr)
takes the address from the hex record or the current PC for binary.
*/
-t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
-{
- int32 i, addr = 0, cnt = 0;
+#define HLEN 16
- if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
- addr = saved_PC;
- while ((i = getc (fileref)) != EOF) {
- CPU_BD_put_mbyte(addr, i);
- addr++;
- cnt++;
- } // end while
- printf ("%d Bytes loaded.\n", cnt);
- return (SCPE_OK);
+int32 sim_load(FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
+{
+ int32 i, addr = 0, addr0 = 0, cnt = 0, cnt0 = 0, start = 0x10000;
+ int32 addr1 = 0, end = 0, byte, chk, rtype, flag0 = 1;
+ char buf[128], data[128], *p;
+
+ cnt = sscanf(cptr, " %04X %04X", &start, &end);
+ addr=start;
+ if (flag == 0) { //load
+ if (sim_switches & SWMASK ('H')) { //hex
+ if (cnt > 1) //2 arguments - error
+ return SCPE_ARG;
+ cnt = 0;
+ while (fgets(buf, sizeof(buf)-1, fileref)) {
+ sscanf(buf, " S%1d%02x%04x%s", &rtype, &cnt0, &addr, data);
+ if (flag0) {
+ addr1 = addr;
+ flag0 = 0;
+ }
+ if (rtype == 1) {
+ chk = 0;
+ chk += cnt0;
+ cnt0 -= 3;
+ chk += addr & BYTEMASK;
+ chk += addr >> 8;
+ p = (char *) data;
+ for (i=0; i 1) //2 arguments - error
+ return SCPE_ARG;
+ cnt = 0;
+ addr1 = addr;
+ while ((i = getc (fileref)) != EOF) {
+ CPU_BD_put_mbyte(addr, i);
+ addr++; cnt++;
+ }
+ }
+ printf ("%d Bytes loaded at %04X\n", cnt, addr1);
+ return (SCPE_OK);
+ } else { //dump
+ if (cnt != 2) //must be 2 arguments
+ return SCPE_ARG;
+ cnt = 0;
+ addr0 = addr;
+ if (sim_switches & SWMASK ('H')) { //hex
+ while((addr + HLEN) <= end) { //full records
+ fprintf(fileref,"S1%02X%04X", HLEN + 3, addr);
+ chk = 0;
+ chk += HLEN + 3;
+ chk += addr & BYTEMASK;
+ chk += addr >> 8;
+ for (i=0; i> 8;
+ for (i=0; i<=(end - addr); i++) {
+ byte = CPU_BD_get_mbyte(addr + i);
+ fprintf(fileref, "%02X", byte);
+ chk += byte; chk &= BYTEMASK;
+ cnt++;
+ }
+ chk = (~chk) & BYTEMASK;
+ fprintf(fileref, "%02X\n", chk);
+ addr = end;
+ }
+ fprintf(fileref,"S9\n"); //EOF record
+ } else { //binary
+ while (addr <= end) {
+ i = CPU_BD_get_mbyte(addr);
+ putc(i, fileref);
+ addr++; cnt++;
+ }
+ }
+ printf ("%d Bytes dumped from %04X\n", cnt, addr0);
+ }
+ return SCPE_OK;
}
/* Symbolic output
@@ -1963,9 +2100,9 @@ t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
status = error code
for M6800
*/
-t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
+t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
{
- int32 i, inst, inst1;
+ int i, inst, inst1;
if (sw & SWMASK ('D')) { // dump memory
for (i=0; i<16; i++)
@@ -2018,14 +2155,94 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
status = error status
*/
-t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
+t_stat parse_sym(CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
{
- return (-2);
+ return (1);
}
-t_stat m6800_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches)
+/* Set history */
+
+t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
- return SCPE_OK;
+ int i, lnt;
+ t_stat r;
+
+ if (cptr == NULL) {
+ for (i = 0; i < hst_lnt; i++)
+ hst[i].pc = 0;
+ hst_p = 0;
+ return SCPE_OK;
+ }
+ lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
+ if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN)))
+ return SCPE_ARG;
+ hst_p = 0;
+ if (hst_lnt) {
+ free (hst);
+ hst_lnt = 0;
+ hst = NULL;
+ }
+ if (lnt) {
+ hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
+ if (hst == NULL)
+ return SCPE_MEM;
+ hst_lnt = lnt;
+ }
+ return SCPE_OK;
+}
+
+/* Show history */
+
+t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
+{
+ int k, di, lnt, ir;
+ const char *cptr = (const char *) desc;
+ t_stat r;
+ InstHistory *h;
+
+ if (hst_lnt == 0) /* enabled? */
+ return SCPE_NOFNC;
+ if (cptr) {
+ lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
+ if ((r != SCPE_OK) || (lnt == 0))
+ return SCPE_ARG;
+ }
+ else lnt = hst_lnt;
+ di = hst_p - lnt; /* work forward */
+ if (di < 0)
+ di = di + hst_lnt;
+ fprintf (st, "PC SP CC A B IX Instruction\n\n");
+ for (k = 0; k < lnt; k++) { /* print specified */
+ h = &hst[(di++) % hst_lnt]; /* entry pointer */
+ ir = h->inst[0];
+ fprintf (st, "%04X %04X %02X ", h->pc , h->sp, h->cc);
+ fprintf (st, "%02X %02X %04X ", h->a, h->b, h->ix);
+ if ((fprint_sym (st, h->pc, h->inst, &m6800_unit, SWMASK ('M'))) > 0)
+ fprintf (st, "(undefined) %02X", h->inst[0]);
+ fputc ('\n', st); /* end line */
+ }
+ return SCPE_OK;
+}
+
+/* Memory examine */
+
+t_stat m6800_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
+{
+ if (addr >= MAXMEMSIZE)
+ return SCPE_NXM;
+ if (vptr != NULL)
+ *vptr = CPU_BD_get_mbyte(addr);
+ return SCPE_OK;
+}
+
+/* Memory deposit */
+
+t_stat m6800_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw)
+{
+ if (addr >= MAXMEMSIZE)
+ return SCPE_NXM;
+ CPU_BD_put_mbyte(addr, val);
+ return SCPE_OK;
}
/* end of m6800.c */
diff --git a/swtp6800/common/m6810.c b/swtp6800/common/m6810.c
index cb50a3cc..a1af1c9b 100644
--- a/swtp6800/common/m6810.c
+++ b/swtp6800/common/m6810.c
@@ -25,8 +25,6 @@
MODIFICATIONS:
- 24 Apr 15 -- Modified to use simh_debug
-
NOTES:
These functions support a simulated m6810 RAM device on a CPU board. The
@@ -43,13 +41,12 @@
t_stat m6810_reset (DEVICE *dptr);
int32 m6810_get_mbyte(int32 offset);
void m6810_put_mbyte(int32 offset, int32 val);
-t_stat m6810_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches);
-t_stat m6810_deposit(t_value value, t_addr addr, UNIT *uptr, int32 switches);
/* SIMH RAM Standard I/O Data Structures */
-UNIT m6810_unit = { UDATA (NULL, UNIT_BINK, 128),
- 0 };
+UNIT m6810_unit = {
+ UDATA (NULL, UNIT_BINK, 128),
+ 0 };
MTAB m6810_mod[] = {
{ 0 }
@@ -74,8 +71,8 @@ DEVICE m6810_dev = {
1, //aincr
16, //dradix
8, //dwidth
- &m6810_examine, //examine
- &m6810_deposit, //deposit
+ NULL, //examine
+ NULL, //deposit
&m6810_reset, //reset
NULL, //boot
NULL, //attach
@@ -94,16 +91,14 @@ DEVICE m6810_dev = {
t_stat m6810_reset (DEVICE *dptr)
{
- sim_debug (DEBUG_flow, &m6810_dev, "m6810_reset: \n");
if (m6810_unit.filebuf == NULL) {
- m6810_unit.filebuf = malloc(128);
+ m6810_unit.filebuf = calloc(128, sizeof(uint8));
if (m6810_unit.filebuf == NULL) {
- printf("m6810_reset: Malloc error\n");
+ printf("m6810_reset: Calloc error\n");
return SCPE_MEM;
}
m6810_unit.capac = 128;
}
- sim_debug (DEBUG_flow, &m6810_dev, "m6810_reset: Done\n");
return SCPE_OK;
}
@@ -117,13 +112,10 @@ int32 m6810_get_mbyte(int32 offset)
{
int32 val;
- sim_debug (DEBUG_read, &m6810_dev, "m6810_get_mbyte: offset=%04X\n", offset);
if (((t_addr)offset) < m6810_unit.capac) {
val = *((uint8 *)(m6810_unit.filebuf) + offset) & 0xFF;
- sim_debug (DEBUG_read, &m6810_dev, "val=%04X\n", val);
return val;
} else {
- sim_debug (DEBUG_read, &m6810_dev, "m6810_get_mbyte: out of range\n");
return 0xFF;
}
}
@@ -132,30 +124,12 @@ int32 m6810_get_mbyte(int32 offset)
void m6810_put_mbyte(int32 offset, int32 val)
{
- sim_debug (DEBUG_write, &m6810_dev, "m6810_put_mbyte: offset=%04X, val=%02X\n",
- offset, val);
if ((t_addr)offset < m6810_unit.capac) {
*((uint8 *)(m6810_unit.filebuf) + offset) = val & 0xFF;
return;
- } else {
- sim_debug (DEBUG_write, &m6810_dev, "m6810_put_mbyte: out of range\n");
- return;
}
+ return;
}
/* end of m6810.c */
-t_stat m6810_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches)
-{
- int32 i;
-
- for (i=0; i
#include "swtp_defs.h"
-#define MP_8M_NUM 6 /* number of MP-*m boards */
+#define MP_8M_NUM 6 /* number of MP-8M boards */
/* prototypes */
@@ -105,11 +103,8 @@ t_stat mp_8m_reset (DEVICE *dptr)
int32 i;
UNIT *uptr;
- sim_debug (DEBUG_flow, &mp_8m_dev, "mp_8m_reset: \n");
for (i = 0; i < MP_8M_NUM; i++) { /* init all units */
uptr = mp_8m_dev.units + i;
- sim_debug (DEBUG_flow, &mp_8m_dev, "MP-8M %d unit.flags=%08X\n",
- i, uptr->flags);
uptr->capac = 0x2000;
if (i < 4)
uptr->u3 = 0x2000 * i;
@@ -121,15 +116,8 @@ t_stat mp_8m_reset (DEVICE *dptr)
printf("mp_8m_reset: Calloc error\n");
return SCPE_MEM;
}
-// for (j=0; j<8192; j++) { /* fill pattern for testing */
-// val = (0xA0 | i);
-// *((uint8 *)(uptr->filebuf) + j) = val & 0xFF;
-// }
}
- sim_debug (DEBUG_flow, &mp_8m_dev, "MP-8M %d initialized at [%04X-%04XH]\n",
- i, uptr->u3, uptr->u3 + uptr->capac - 1);
}
- sim_debug (DEBUG_flow, &mp_8m_dev, "mp_8m_reset: Done\n");
return SCPE_OK;
}
@@ -145,19 +133,16 @@ int32 mp_8m_get_mbyte(int32 addr)
int32 i;
UNIT *uptr;
- sim_debug (DEBUG_read, &mp_8m_dev, "mp_8m_get_mbyte: addr=%04X", addr);
for (i = 0; i < MP_8M_NUM; i++) { /* find addressed unit */
uptr = mp_8m_dev.units + i;
org = uptr->u3;
len = uptr->capac - 1;
if ((addr >= org) && (addr <= org + len)) {
val = *((uint8 *)(uptr->filebuf) + (addr - org));
- sim_debug (DEBUG_read, &mp_8m_dev, " val=%04X\n", val);
- return (val & 0xFF);
+ return (val & BYTEMASK);
}
}
- sim_debug (DEBUG_read, &mp_8m_dev, "mp_8m_get_mbyte: Out of range\n");
- return 0xFF; /* multibus has active high pullups */
+ return 0xFF;
}
/* get a word from memory */
@@ -179,19 +164,15 @@ void mp_8m_put_mbyte(int32 addr, int32 val)
int32 i;
UNIT *uptr;
- sim_debug (DEBUG_write, &mp_8m_dev, "mp_8m_put_mbyte: addr=%04X, val=%02X",
- addr, val);
for (i = 0; i < MP_8M_NUM; i++) { /* find addressed unit */
uptr = mp_8m_dev.units + i;
org = uptr->u3;
len = uptr->capac - 1;
if ((addr >= org) && (addr <= org + len)) {
- *((uint8 *)(uptr->filebuf) + (addr - org)) = val & 0xFF;
- sim_debug (DEBUG_write, &mp_8m_dev, "\n");
+ *((uint8 *)(uptr->filebuf) + (addr - org)) = val & BYTEMASK;
return;
}
}
- sim_debug (DEBUG_write, &mp_8m_dev, "mp_8m_put_mbyte: Out of range\n");
}
/* put a word into memory */
diff --git a/swtp6800/common/mp-a.c b/swtp6800/common/mp-a.c
index 36a3678f..d9200259 100644
--- a/swtp6800/common/mp-a.c
+++ b/swtp6800/common/mp-a.c
@@ -55,12 +55,10 @@ int32 CPU_BD_get_mbyte(int32 addr);
int32 CPU_BD_get_mword(int32 addr);
void CPU_BD_put_mbyte(int32 addr, int32 val);
void CPU_BD_put_mword(int32 addr, int32 val);
-t_stat mpa_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches);
-t_stat mpa_deposit(t_value value, t_addr addr, UNIT *uptr, int32 switches);
/* external routines */
-/* MP-B2 bus routines */
+/* MP-B2 MB routines */
extern int32 MB_get_mbyte(int32 addr);
extern int32 MB_get_mword(int32 addr);
extern void MB_put_mbyte(int32 addr, int32 val);
@@ -114,8 +112,8 @@ DEVICE CPU_BD_dev = {
1, //aincr
16, //dradix
8, //dwidth
- mpa_examine, //examine
- mpa_deposit, //deposit
+ NULL, //examine
+ NULL, //deposit
NULL, //reset
NULL, //boot
NULL, //attach
@@ -132,30 +130,27 @@ DEVICE CPU_BD_dev = {
int32 CPU_BD_get_mbyte(int32 addr)
{
- int32 val;
+ int32 val = 0, EA = 0, EA1 = 0;
sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: addr=%04X\n", addr);
switch(addr & 0xF000) {
case 0xA000:
if (CPU_BD_unit.flags & UNIT_RAM) {
- val = m6810_get_mbyte(addr - 0xA000) & 0xFF;
- sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: m6810 val=%02X\n", val);
+ val = m6810_get_mbyte(addr - 0xA000) & BYTEMASK;
} else {
- val = MB_get_mbyte(addr) & 0xFF;
- sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: m6810 val=%02X\n", val);
+ val = MB_get_mbyte(addr) & BYTEMASK;
}
break;
case 0xE000:
- val = BOOTROM_get_mbyte(addr - 0xE000) & 0xFF;
- sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: EPROM=%02X\n", val);
+ val = BOOTROM_get_mbyte(addr - 0xE000) & BYTEMASK;
break;
case 0xF000:
- val = BOOTROM_get_mbyte(addr - (0x10000 - BOOTROM_unit.capac)) & 0xFF;
- sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: EPROM=%02X\n", val);
+ EA1 = 0x10000 - BOOTROM_unit.capac;
+ EA = addr - EA1;
+ val = BOOTROM_get_mbyte(EA) & BYTEMASK;
break;
default:
- val = MB_get_mbyte(addr) & 0xFF;
- sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mbyte: mp_b2 val=%02X\n", val);
+ val = MB_get_mbyte(addr) & BYTEMASK;
}
return val;
}
@@ -166,11 +161,9 @@ int32 CPU_BD_get_mword(int32 addr)
{
int32 val;
- sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mword: addr=%04X\n", addr);
val = (CPU_BD_get_mbyte(addr) << 8);
val |= CPU_BD_get_mbyte(addr+1);
val &= 0xFFFF;
- sim_debug (DEBUG_read, &CPU_BD_dev, "CPU_BD_get_mword: val=%04X\n", val);
return val;
}
@@ -178,8 +171,6 @@ int32 CPU_BD_get_mword(int32 addr)
void CPU_BD_put_mbyte(int32 addr, int32 val)
{
- sim_debug (DEBUG_write, &CPU_BD_dev, "CPU_BD_put_mbyte: addr=%04X, val=%02X\n",
- addr, val);
switch(addr & 0xF000) {
case 0xA000:
if (CPU_BD_unit.flags & UNIT_RAM)
@@ -196,25 +187,8 @@ void CPU_BD_put_mbyte(int32 addr, int32 val)
void CPU_BD_put_mword(int32 addr, int32 val)
{
- sim_debug (DEBUG_write, &CPU_BD_dev, "CPU_BD_put_mword: addr=%04X, val=%04X\n",
- addr, val);
CPU_BD_put_mbyte(addr, val >> 8);
CPU_BD_put_mbyte(addr+1, val);
}
-t_stat mpa_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches)
-{
- int32 i;
-
- for (i=0; i> 8);
CPU_BD_put_mbyte(addr+1, val);
}
-t_stat mpa2_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches)
-{
- int32 i;
-
- for (i=0; i> 8);
MB_put_mbyte(addr+1, val);
}
-t_stat mpb2_examine(t_value *eval_array, t_addr addr, UNIT *uptr, int32 switches)
-{
- int32 i;
-
- for (i=0; i