mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-13 23:35:30 +00:00
SEL32: Initial commit.
This commit is contained in:
parent
ba534e8d1f
commit
5decc40fa5
733
SEL32/sel32_chan.c
Normal file
733
SEL32/sel32_chan.c
Normal file
@ -0,0 +1,733 @@
|
||||
/* sel32_chan.c: Sel 32 Channel functions.
|
||||
|
||||
Copyright (c) 2018, Richard Cornwell
|
||||
|
||||
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
|
||||
RICHARD CORNWELL 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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* Handle Class E and F channel I/O operations */
|
||||
#include "sel32_defs.h"
|
||||
#include "sim_defs.h"
|
||||
|
||||
/* Class F channel bits */
|
||||
#define CCMDMSK 0xff000000 /* Mask for command */
|
||||
#define CDADRMSK 0x00ffffff /* Mask for data address */
|
||||
#define CCNTMSK 0x0000ffff /* Mask for data count */
|
||||
#define CD 0x80000000 /* Chain data */
|
||||
#define CC 0x40000000 /* Chain command */
|
||||
#define SLI 0x20000000 /* Suppress length indication */
|
||||
#define SKIP 0x10000000 /* Skip flag */
|
||||
#define PCI 0x08000000 /* Program controlled interuption */
|
||||
|
||||
/* Command masks */
|
||||
#define CMD_TYPE 0x3 /* Type mask */
|
||||
#define CMD_CHAN 0x0 /* Channel command */
|
||||
#define CMD_WRITE 0x1 /* Write command */
|
||||
#define CMD_READ 0x2 /* Read command */
|
||||
#define CMD_CTL 0x3 /* Control command */
|
||||
#define CMD_SENSE 0x4 /* Sense channel command */
|
||||
#define CMD_TIC 0x8 /* Transfer in channel */
|
||||
#define CMD_RDBWD 0xc /* Read backward */
|
||||
|
||||
#define STATUS_ATTN 0x8000 /* Device raised attention */
|
||||
#define STATUS_MOD 0x4000 /* Status modifier */
|
||||
#define STATUS_CTLEND 0x2000 /* Control end */
|
||||
#define STATUS_BUSY 0x1000 /* Device busy */
|
||||
#define STATUS_CEND 0x0800 /* Channel end */
|
||||
#define STATUS_DEND 0x0400 /* Device end */
|
||||
#define STATUS_CHECK 0x0200 /* Unit check */
|
||||
#define STATUS_EXPT 0x0100 /* Unit excpetion */
|
||||
#define STATUS_PCI 0x0080 /* Program interupt */
|
||||
#define STATUS_LENGTH 0x0040 /* Incorrect lenght */
|
||||
#define STATUS_PCHK 0x0020 /* Program check */
|
||||
#define STATUS_PROT 0x0010 /* Protection check */
|
||||
#define STATUS_CDATA 0x0008 /* Channel data check */
|
||||
#define STATUS_CCNTL 0x0004 /* Channel control check */
|
||||
#define STATUS_INTER 0x0002 /* Channel interface check */
|
||||
#define STATUS_CHAIN 0x0001 /* Channel chain check */
|
||||
|
||||
#define FLAG_CD 0x8000 /* Chain data */
|
||||
#define FLAG_CC 0x4000 /* Chain command */
|
||||
#define FLAG_SLI 0x2000 /* Suppress length indicator */
|
||||
#define FLAG_SKIP 0x1000 /* Suppress memory write */
|
||||
#define FLAG_PCI 0x0800 /* Program controled interrupt */
|
||||
|
||||
#define BUFF_EMPTY 0x4 /* Buffer is empty */
|
||||
#define BUFF_DIRTY 0x8 /* Buffer is dirty flag */
|
||||
#define BUFF_NEWCMD 0x10 /* Channel ready for new command */
|
||||
#define BUFF_CHNEND 0x20 /* Channel end */
|
||||
|
||||
#define AMASK 0x00ffffff
|
||||
#define PMASK 0xf0000000 /* Storage protection mask */
|
||||
extern uint32 *M;
|
||||
|
||||
int irq_pend = 0;
|
||||
uint32 caw[256]; /* Channel command address word */
|
||||
uint32 ccw_addr[256]; /* Channel address */
|
||||
uint16 ccw_count[256]; /* Channel count */
|
||||
uint8 ccw_cmd[256]; /* Channel command and flags */
|
||||
uint16 ccw_flags[256]; /* Channel flags */
|
||||
uint16 chan_status[256]; /* Channel status */
|
||||
uint16 chan_dev[256]; /* Device on channel */
|
||||
uint32 chan_buf[256]; /* Channel data buffer */
|
||||
uint8 chan_byte[256]; /* Current byte, dirty/full */
|
||||
DIB *dev_unit[256]; /* Pointer to Device info block */
|
||||
uint8 dev_status[256]; /* last device status flags */
|
||||
|
||||
/* Find unit pointer for given device */
|
||||
UNIT *
|
||||
find_chan_dev(uint16 addr) {
|
||||
struct dib *dibp;
|
||||
UNIT *uptr;
|
||||
int i;
|
||||
|
||||
dibp = dev_unit[addr];
|
||||
if (dibp == 0)
|
||||
return NULL;
|
||||
uptr = dibp->units;
|
||||
if (dibp->mask == 0) {
|
||||
for (i = 0; i < dibp->numunits; i++) {
|
||||
if (addr == GET_UADDR(uptr->u3))
|
||||
return uptr;
|
||||
uptr++;
|
||||
}
|
||||
} else {
|
||||
return uptr + (addr & ~dibp->mask & 0xff);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Read a full word into memory.
|
||||
* Return 1 if fail.
|
||||
* Return 0 if success.
|
||||
*/
|
||||
int
|
||||
readfull(int chan, uint32 addr, uint32 *word) {
|
||||
int sk, k;
|
||||
if ((addr & AMASK) > MEMSIZE) {
|
||||
chan_status[chan] |= STATUS_PCHK;
|
||||
return 1;
|
||||
}
|
||||
addr &= AMASK;
|
||||
addr >>= 2;
|
||||
*word = M[addr];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read a word into the channel buffer.
|
||||
* Return 1 if fail.
|
||||
* Return 0 if success.
|
||||
*/
|
||||
int
|
||||
readbuff(int chan) {
|
||||
int k;
|
||||
uint32 addr = ccw_addr[chan];
|
||||
if ((addr & AMASK) > MEMSIZE) {
|
||||
chan_status[chan] |= STATUS_PCHK;
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
irq_pend = 1;
|
||||
return 1;
|
||||
}
|
||||
addr &= AMASK;
|
||||
addr >>= 2;
|
||||
chan_buf[chan] = M[addr];
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "Channel write %02x %06x %08x %08x '",
|
||||
chan, ccw_addr[chan] & 0xFFFFFC, chan_buf[chan], ccw_count[chan]);
|
||||
for(k = 24; k >= 0; k -= 8) {
|
||||
char ch = (chan_buf[chan] >> k) & 0xFF;
|
||||
if (ch < 0x20 || ch == 0xff)
|
||||
ch = '.';
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch);
|
||||
}
|
||||
|
||||
sim_debug(DEBUG_DATA, & cpu_dev, "'\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write channel buffer to memory.
|
||||
* Return 1 if fail.
|
||||
* Return 0 if success.
|
||||
*/
|
||||
int
|
||||
writebuff(int chan) {
|
||||
int k;
|
||||
uint32 addr = ccw_addr[chan];
|
||||
if ((addr & AMASK) > MEMSIZE) {
|
||||
chan_status[chan] |= STATUS_PCHK;
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
irq_pend = 1;
|
||||
return 1;
|
||||
}
|
||||
addr &= AMASK;
|
||||
addr >>= 2;
|
||||
M[addr] = chan_buf[chan];
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "Channel readf %02x %06x %08x %08x '",
|
||||
chan, ccw_addr[chan] & 0xFFFFFC, chan_buf[chan], ccw_count[chan]);
|
||||
for(k = 24; k >= 0; k -= 8) {
|
||||
char ch = (chan_buf[chan] >> k) & 0xFF;
|
||||
if (ch < 0x20 || ch == 0xff)
|
||||
ch = '.';
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch);
|
||||
}
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "'\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
load_ccw(uint16 chan, int tic_ok) {
|
||||
uint32 word;
|
||||
int cmd = 0;
|
||||
UNIT *uptr;
|
||||
|
||||
loop:
|
||||
/* Abort if channel not on double boundry */
|
||||
if ((caw[chan] & 0x7) != 0) {
|
||||
chan_status[chan] |= STATUS_PCHK;
|
||||
return 1;
|
||||
}
|
||||
/* Abort if we have any errors */
|
||||
if (chan_status[chan] & 0x7f)
|
||||
return 1;
|
||||
/* Check if we have status modifier set */
|
||||
if (chan_status[chan] & STATUS_MOD) {
|
||||
caw[chan]+=8;
|
||||
caw[chan] &= PMASK|AMASK; /* Mask overflow bits */
|
||||
chan_status[chan] &= ~STATUS_MOD;
|
||||
}
|
||||
/* Read in next CCW */
|
||||
readfull(chan, caw[chan], &word);
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "Channel read ccw %02x %06x %08x\n",
|
||||
chan, caw[chan], word);
|
||||
/* TIC can't follow TIC nor be first in chain */
|
||||
if (((word >> 24) & 0xf) == CMD_TIC) {
|
||||
if (tic_ok) {
|
||||
caw[chan] = (caw[chan] & PMASK) | (word & AMASK);
|
||||
tic_ok = 0;
|
||||
goto loop;
|
||||
}
|
||||
chan_status[chan] |= STATUS_PCHK;
|
||||
irq_pend = 1;
|
||||
return 1;
|
||||
}
|
||||
caw[chan] += 4;
|
||||
caw[chan] &= PMASK|AMASK; /* Mask overflow bits */
|
||||
/* Check if not chaining data */
|
||||
if ((ccw_flags[chan] & FLAG_CD) == 0) {
|
||||
ccw_cmd[chan] = (word >> 24) & 0xff;
|
||||
cmd = 1;
|
||||
}
|
||||
/* Set up for this command */
|
||||
ccw_addr[chan] = word & AMASK;
|
||||
ccw_addr[chan] |= caw[chan] & PMASK; /* Copy key */
|
||||
readfull(chan, caw[chan], &word);
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "Channel read ccw2 %02x %06x %08x\n",
|
||||
chan, caw[chan], word);
|
||||
caw[chan]+=4;
|
||||
caw[chan] &= PMASK|AMASK; /* Mask overflow bits */
|
||||
ccw_count[chan] = word & 0xffff;
|
||||
ccw_flags[chan] = (word >> 16) & 0xffff;
|
||||
chan_byte[chan] = BUFF_EMPTY;
|
||||
if (ccw_flags[chan] & FLAG_PCI) {
|
||||
chan_status[chan] |= STATUS_PCI;
|
||||
irq_pend = 1;
|
||||
}
|
||||
/* Check invalid count */
|
||||
if (ccw_count[chan] == 0) {
|
||||
chan_status[chan] |= STATUS_PCHK;
|
||||
irq_pend = 1;
|
||||
return 1;
|
||||
}
|
||||
if (cmd) {
|
||||
DIB *dibp = dev_unit[chan_dev[chan]];
|
||||
/* Check if invalid command */
|
||||
if ((ccw_cmd[chan] & 0xF) == 0) {
|
||||
chan_status[chan] |= STATUS_PCHK;
|
||||
irq_pend = 1;
|
||||
return 1;
|
||||
}
|
||||
uptr = find_chan_dev(chan_dev[chan]);
|
||||
if (uptr == 0)
|
||||
return 1;
|
||||
chan_status[chan] &= 0xff;
|
||||
chan_status[chan] |= dibp->start_cmd(uptr, chan, ccw_cmd[chan]) << 8;
|
||||
if (chan_status[chan] & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) {
|
||||
chan_status[chan] |= STATUS_CEND;
|
||||
ccw_flags[chan] = 0;
|
||||
ccw_cmd[chan] = 0;
|
||||
irq_pend = 1;
|
||||
return 1;
|
||||
}
|
||||
if (chan_status[chan] & (STATUS_DEND|STATUS_CEND)) {
|
||||
chan_status[chan] |= STATUS_CEND;
|
||||
chan_byte[chan] = BUFF_NEWCMD;
|
||||
ccw_cmd[chan] = 0;
|
||||
irq_pend = 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* read byte from memory */
|
||||
int
|
||||
chan_read_byte(uint16 addr, uint8 *data) {
|
||||
int chan = find_subchan(addr);
|
||||
int byte;
|
||||
int k;
|
||||
|
||||
/* Abort if we have any errors */
|
||||
if (chan < 0)
|
||||
return 1;
|
||||
if (chan_status[chan] & 0x7f)
|
||||
return 1;
|
||||
if ((ccw_cmd[chan] & 0x1) == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (chan_byte[chan] == BUFF_CHNEND)
|
||||
return 1;
|
||||
if (ccw_count[chan] == 0) {
|
||||
if ((ccw_flags[chan] & FLAG_CD) == 0) {
|
||||
chan_status[chan] |= STATUS_CEND;
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_read_end\n");
|
||||
return 1;
|
||||
} else {
|
||||
if (load_ccw(chan, 1))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (chan_byte[chan] == BUFF_EMPTY) {
|
||||
if (readbuff(chan))
|
||||
return 1;
|
||||
chan_byte[chan] = ccw_addr[chan] & 0x3;
|
||||
ccw_addr[chan] += 4 - chan_byte[chan];
|
||||
}
|
||||
ccw_count[chan]--;
|
||||
byte = (chan_buf[chan] >> (8 * (3 - (chan_byte[chan] & 0x3)))) & 0xff;
|
||||
chan_byte[chan]++;
|
||||
*data = byte;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* write byte to memory */
|
||||
int
|
||||
chan_write_byte(uint16 addr, uint8 *data) {
|
||||
int chan = find_subchan(addr);
|
||||
int byte;
|
||||
int offset;
|
||||
int k;
|
||||
uint32 mask;
|
||||
|
||||
/* Abort if we have any errors */
|
||||
if (chan < 0)
|
||||
return 1;
|
||||
if (chan_status[chan] & 0x7f)
|
||||
return 1;
|
||||
if ((ccw_cmd[chan] & 0x1) != 0) {
|
||||
return 1;
|
||||
}
|
||||
if (chan_byte[chan] == BUFF_CHNEND) {
|
||||
if ((ccw_flags[chan] & FLAG_SLI) == 0) {
|
||||
chan_status[chan] |= STATUS_LENGTH;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (ccw_count[chan] == 0) {
|
||||
if (chan_byte[chan] & BUFF_DIRTY) {
|
||||
if (writebuff(chan))
|
||||
return 1;
|
||||
}
|
||||
if ((ccw_flags[chan] & FLAG_CD) == 0) {
|
||||
chan_byte[chan] = BUFF_CHNEND;
|
||||
if ((ccw_flags[chan] & FLAG_SLI) == 0) {
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_ length\n");
|
||||
chan_status[chan] |= STATUS_LENGTH;
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_end\n");
|
||||
return 1;
|
||||
}
|
||||
if (load_ccw(chan, 1))
|
||||
return 1;
|
||||
}
|
||||
if (ccw_flags[chan] & FLAG_SKIP) {
|
||||
ccw_count[chan]--;
|
||||
chan_byte[chan] = BUFF_EMPTY;
|
||||
if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD)
|
||||
ccw_addr[chan]--;
|
||||
else
|
||||
ccw_addr[chan]++;
|
||||
return 0;
|
||||
}
|
||||
if (chan_byte[chan] == (BUFF_EMPTY|BUFF_DIRTY)) {
|
||||
if (writebuff(chan))
|
||||
return 1;
|
||||
if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD)
|
||||
ccw_addr[chan] -= 1 + (ccw_addr[chan] & 0x3);
|
||||
else
|
||||
ccw_addr[chan] += 4 - (ccw_addr[chan] & 0x3);
|
||||
chan_byte[chan] = BUFF_EMPTY;
|
||||
}
|
||||
if (chan_byte[chan] == BUFF_EMPTY) {
|
||||
if (readbuff(chan))
|
||||
return 1;
|
||||
chan_byte[chan] = ccw_addr[chan] & 0x3;
|
||||
}
|
||||
ccw_count[chan]--;
|
||||
offset = 8 * (chan_byte[chan] & 0x3);
|
||||
mask = 0xff000000 >> offset;
|
||||
chan_buf[chan] &= ~mask;
|
||||
chan_buf[chan] |= ((uint32)(*data)) << (24 - offset);
|
||||
if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD) {
|
||||
if (chan_byte[chan] & 0x3)
|
||||
chan_byte[chan]--;
|
||||
else
|
||||
chan_byte[chan] = BUFF_EMPTY;
|
||||
} else
|
||||
chan_byte[chan]++;
|
||||
chan_byte[chan] |= BUFF_DIRTY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
set_devattn(uint16 addr, uint8 flags) {
|
||||
int chan = find_subchan(addr);
|
||||
|
||||
if (chan < 0)
|
||||
return;
|
||||
if (chan_dev[chan] == addr && (chan_status[chan] & STATUS_CEND) != 0 &&
|
||||
(flags & SNS_DEVEND) != 0) {
|
||||
chan_status[chan] |= ((uint16)flags) << 8;
|
||||
} else
|
||||
dev_status[addr] = flags;
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "set_devattn(%x, %x) %x\n",
|
||||
addr, flags, chan_dev[chan]);
|
||||
irq_pend = 1;
|
||||
}
|
||||
|
||||
void
|
||||
chan_end(uint16 addr, uint8 flags) {
|
||||
int chan = find_subchan(addr);
|
||||
|
||||
if (chan < 0)
|
||||
return;
|
||||
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end(%x, %x) %x\n", addr, flags, ccw_count[chan]);
|
||||
if (chan_byte[chan] & BUFF_DIRTY) {
|
||||
if (writebuff(chan))
|
||||
return;
|
||||
chan_byte[chan] = BUFF_EMPTY;
|
||||
}
|
||||
chan_status[chan] |= STATUS_CEND;
|
||||
chan_status[chan] |= ((uint16)flags) << 8;
|
||||
ccw_cmd[chan] = 0;
|
||||
if (ccw_count[chan] != 0 && (ccw_flags[chan] & FLAG_SLI) == 0) {
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end length\n");
|
||||
chan_status[chan] |= STATUS_LENGTH;
|
||||
ccw_flags[chan] = 0;
|
||||
}
|
||||
if (flags & (SNS_ATTN|SNS_UNITCHK|SNS_UNITEXP)) {
|
||||
ccw_flags[chan] = 0;
|
||||
}
|
||||
|
||||
if (chan_status[chan] & (STATUS_DEND|STATUS_CEND)) {
|
||||
chan_byte[chan] = BUFF_NEWCMD;
|
||||
|
||||
while ((ccw_flags[chan] & FLAG_CD)) {
|
||||
if (load_ccw(chan, 1))
|
||||
break;
|
||||
if ((ccw_flags[chan] & FLAG_SLI) == 0) {
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end length\n");
|
||||
chan_status[chan] |= STATUS_LENGTH;
|
||||
ccw_flags[chan] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
irq_pend = 1;
|
||||
}
|
||||
|
||||
|
||||
int startio(uint16 addr) {
|
||||
int chan = find_subchan(addr);
|
||||
DIB *dibp = dev_unit[addr];
|
||||
UNIT *uptr;
|
||||
uint8 status;
|
||||
|
||||
/* Needs to be redone for Sel32 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testio(uint16 addr) {
|
||||
int chan = find_subchan(addr);
|
||||
DIB *dibp = dev_unit[addr];
|
||||
UNIT *uptr;
|
||||
uint8 status;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int haltio(uint16 addr) {
|
||||
int chan = find_subchan(addr);
|
||||
DIB *dibp = dev_unit[addr];
|
||||
UNIT *uptr;
|
||||
uint8 status;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
t_stat chan_boot(uint16 addr, DEVICE *dptyr) {
|
||||
int chan = find_subchan(addr);
|
||||
DIB *dibp = dev_unit[addr];
|
||||
UNIT *uptr;
|
||||
uint8 status;
|
||||
int i;
|
||||
|
||||
if (chan < 0 || dibp == 0)
|
||||
return SCPE_IOERR;
|
||||
for (i = 0; i < MAX_DEV; i++) {
|
||||
dev_status[i] = 0;
|
||||
}
|
||||
for (i = 0; i < 256; i++) {
|
||||
ccw_cmd[i] = 0;
|
||||
ccw_flags[i] = 0;
|
||||
}
|
||||
uptr = find_chan_dev(addr);
|
||||
chan_status[chan] = 0;
|
||||
dev_status[addr] = 0;
|
||||
caw[chan] = 0x8;
|
||||
chan_dev[chan] = addr;
|
||||
ccw_count[chan] = 24;
|
||||
ccw_flags[chan] = FLAG_CC|FLAG_SLI;
|
||||
ccw_addr[chan] = 0;
|
||||
chan_byte[chan] = BUFF_EMPTY;
|
||||
ccw_cmd[chan] = 0x2;
|
||||
chan_status[chan] &= 0xff;
|
||||
chan_status[chan] |= dibp->start_cmd(uptr, chan, ccw_cmd[chan]) << 8;
|
||||
if (chan_status[chan] & (STATUS_ATTN|STATUS_CHECK|STATUS_EXPT)) {
|
||||
ccw_flags[chan] = 0;
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
loading = addr;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Scan all channels and see if one is ready to start or has
|
||||
interrupt pending.
|
||||
*/
|
||||
uint16 scan_chan(uint8 mask) {
|
||||
int i;
|
||||
int pend = 0; /* No device */
|
||||
int imask = 0x80;
|
||||
|
||||
if (irq_pend == 0)
|
||||
return 0;
|
||||
irq_pend = 0;
|
||||
for (i = 0; i < subchannels + channels; i++) {
|
||||
if (i >= subchannels)
|
||||
imask = imask / 2;
|
||||
|
||||
/* If channel end, check if we should continue */
|
||||
if (chan_status[i] & STATUS_CEND) {
|
||||
if (ccw_flags[i] & FLAG_CC) {
|
||||
if (chan_status[i] & STATUS_DEND)
|
||||
(void)load_ccw(i, 1);
|
||||
else
|
||||
irq_pend = 1;
|
||||
} else {
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Scan(%x %x %x %x) end\n", i,
|
||||
chan_status[i], imask, mask);
|
||||
if ((imask & mask) != 0 || loading != 0) {
|
||||
pend = chan_dev[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pend) {
|
||||
irq_pend = 1;
|
||||
i = find_subchan(pend);
|
||||
if (i >= 0) {
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Scan end (%x %x)\n", chan_dev[i], pend);
|
||||
store_csw(i);
|
||||
}
|
||||
dev_status[pend] = 0;
|
||||
} else {
|
||||
for (pend = 0; pend < MAX_DEV; pend++) {
|
||||
if (dev_status[pend] != 0) {
|
||||
i = find_subchan(pend);
|
||||
if (i >= 0 && ccw_cmd[i] == 0 && mask & (0x80 >> (pend >> 8))) {
|
||||
irq_pend = 1;
|
||||
M[0x44 >> 2] = (((uint32)dev_status[pend]) << 24);
|
||||
M[0x40>>2] = 0;
|
||||
sim_debug(DEBUG_EXP, &cpu_dev,
|
||||
"Set atten %03x %02x [%08x] %08x\n",
|
||||
i, dev_status[pend], M[0x40 >> 2], M[0x44 >> 2]);
|
||||
dev_status[pend] = 0;
|
||||
return pend;
|
||||
}
|
||||
}
|
||||
}
|
||||
pend = 0;
|
||||
}
|
||||
/* Only return loading unit on loading */
|
||||
if (loading != 0 && loading != pend)
|
||||
return 0;
|
||||
return pend;
|
||||
}
|
||||
|
||||
|
||||
t_stat
|
||||
chan_set_devs()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for(i = 0; i < MAX_DEV; i++) {
|
||||
dev_unit[i] = NULL; /* Device pointer */
|
||||
}
|
||||
/* Build channel array */
|
||||
for (i = 0; sim_devices[i] != NULL; i++) {
|
||||
DEVICE *dptr = sim_devices[i];
|
||||
UNIT *uptr = dptr->units;
|
||||
DIB *dibp = (DIB *) dptr->ctxt;
|
||||
int addr;
|
||||
int chan;
|
||||
|
||||
/* If no DIB, not channel device */
|
||||
if (dibp == NULL)
|
||||
continue;
|
||||
/* Skip disabled devices */
|
||||
if (dptr->flags & DEV_DIS)
|
||||
continue;
|
||||
/* Check if address is in unit or dev entry */
|
||||
for (j = 0; j < dptr->numunits; j++) {
|
||||
addr = GET_UADDR(uptr->u3);
|
||||
if ((uptr->flags & UNIT_DIS) == 0)
|
||||
dev_unit[addr] = dibp;
|
||||
if (dibp->dev_ini != NULL)
|
||||
dibp->dev_ini(uptr, 1);
|
||||
uptr++;
|
||||
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Sets the device onto a given channel */
|
||||
t_stat
|
||||
set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
t_value newdev;
|
||||
t_stat r;
|
||||
int num;
|
||||
int type;
|
||||
int i;
|
||||
int devaddr;
|
||||
|
||||
if (cptr == NULL)
|
||||
return SCPE_ARG;
|
||||
if (uptr == NULL)
|
||||
return SCPE_IERR;
|
||||
dptr = find_dev_from_unit(uptr);
|
||||
if (dptr == NULL)
|
||||
return SCPE_IERR;
|
||||
|
||||
dibp = (DIB *) dptr->ctxt;
|
||||
if (dibp == NULL)
|
||||
return SCPE_IERR;
|
||||
|
||||
newdev = get_uint (cptr, 16, 0xfff, &r);
|
||||
|
||||
if (r != SCPE_OK)
|
||||
return r;
|
||||
|
||||
if ((newdev >> 8) > channels)
|
||||
return SCPE_ARG;
|
||||
|
||||
if (newdev >= MAX_DEV)
|
||||
return SCPE_ARG;
|
||||
|
||||
devaddr = GET_UADDR(uptr->u3);
|
||||
|
||||
/* Clear out existing entry */
|
||||
if (dptr->flags & DEV_UADDR) {
|
||||
dev_unit[devaddr] = NULL;
|
||||
} else {
|
||||
devaddr &= dibp->mask | 0x700;
|
||||
for (i = 0; i < dibp->numunits; i++)
|
||||
dev_unit[devaddr + i] = NULL;
|
||||
}
|
||||
|
||||
/* Check if device already at newdev */
|
||||
if (dptr->flags & DEV_UADDR) {
|
||||
if (dev_unit[newdev] != NULL)
|
||||
r = SCPE_ARG;
|
||||
} else {
|
||||
newdev &= dibp->mask | 0x700;
|
||||
for (i = 0; i < dibp->numunits; i++) {
|
||||
if (dev_unit[newdev + i] != NULL)
|
||||
r = SCPE_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
/* If not, point to new dev, else restore old */
|
||||
if (r == SCPE_OK)
|
||||
devaddr = newdev;
|
||||
|
||||
/* Update device entry */
|
||||
if (dptr->flags & DEV_UADDR) {
|
||||
dev_unit[devaddr] = dibp;
|
||||
uptr->u3 &= ~UNIT_ADDR(0x7ff);
|
||||
uptr->u3 |= UNIT_ADDR(devaddr);
|
||||
fprintf(stderr, "Set dev %x\n\r", GET_UADDR(uptr->u3));
|
||||
} else {
|
||||
for (i = 0; i < dibp->numunits; i++) {
|
||||
dev_unit[devaddr + i] = dibp;
|
||||
uptr = &((dibp->units)[i]);
|
||||
uptr->u3 &= ~UNIT_ADDR(0x7ff);
|
||||
uptr->u3 |= UNIT_ADDR(devaddr + i);
|
||||
fprintf(stderr, "Set dev %x\n\r", GET_UADDR(uptr->u3));
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
t_stat
|
||||
show_dev_addr(FILE * st, UNIT * uptr, int32 v, CONST void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
int addr;
|
||||
|
||||
|
||||
if (uptr == NULL)
|
||||
return SCPE_IERR;
|
||||
dptr = find_dev_from_unit(uptr);
|
||||
if (dptr == NULL)
|
||||
return SCPE_IERR;
|
||||
addr = GET_UADDR(uptr->u3);
|
||||
fprintf(st, "%03x", addr);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
1759
SEL32/sel32_cpu.c
Normal file
1759
SEL32/sel32_cpu.c
Normal file
File diff suppressed because it is too large
Load Diff
259
SEL32/sel32_defs.h
Normal file
259
SEL32/sel32_defs.h
Normal file
@ -0,0 +1,259 @@
|
||||
/* sel32_defs.h: Gould Concept/32 (orignal SEL32) simulator definitions
|
||||
|
||||
Copyright (c) 2017, Richard Cornwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_IONRDY 1 /* I/O dev not ready */
|
||||
#define STOP_HALT 2 /* HALT */
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_UUO 4 /* invalid opcode */
|
||||
#define STOP_INVINS 5 /* invalid instr */
|
||||
#define STOP_INVIOP 6 /* invalid I/O op */
|
||||
#define STOP_INDLIM 7 /* indirect limit */
|
||||
#define STOP_XECLIM 8 /* XEC limit */
|
||||
#define STOP_IOCHECK 9 /* IOCHECK */
|
||||
#define STOP_MMTRP 10 /* mm in trap */
|
||||
#define STOP_TRPINS 11 /* trap inst not BRM */
|
||||
#define STOP_RTCINS 12 /* rtc inst not MIN/SKR */
|
||||
#define STOP_ILLVEC 13 /* zero vector */
|
||||
#define STOP_CCT 14 /* runaway CCT */
|
||||
|
||||
/* Conditional error returns */
|
||||
|
||||
/* Memory */
|
||||
|
||||
#define MAXMEMSIZE ((16*1024*1024)/4) /* max memory size */
|
||||
#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define MEM_ADDR_OK(x) (((x)) < MEMSIZE)
|
||||
|
||||
/* Device information block */
|
||||
typedef struct dib {
|
||||
uint8 dev_addr; /* Device address */
|
||||
uint8 dev_class; /* Device class */
|
||||
/* Start I/O */
|
||||
uint8 (*start_io)(UNIT *uptr, uint16 chan);
|
||||
/* Start a command */
|
||||
uint8 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd);
|
||||
/* Stop I/O */
|
||||
uint8 (*halt_io)(UNIT *uptr);
|
||||
} DIB;
|
||||
|
||||
|
||||
/* Opcode definitions */
|
||||
#define OP_HALT 0x0000 /* Halt # * */
|
||||
#define OP_WAIT 0x0001 /* Wait # * */
|
||||
#define OP_NOP 0x0002 /* Nop # */
|
||||
#define OP_LCS 0x0003 /* Load Control Switches */
|
||||
#define OP_ES 0x0004 /* Extend Sign # */
|
||||
#define OP_RND 0x0005 /* Round Register # */
|
||||
#define OP_BEI 0x0006 /* Block External Interrupts # */
|
||||
#define OP_UEI 0x0007 /* Unblock External Interrupts # */
|
||||
#define OP_EAE 0x0008 /* Enable Arithmetic Exception Trap # */
|
||||
#define OP_RDSTS 0x0009 /* Read CPU Status Word * */
|
||||
#define OP_SIPU 0x000A /* Signal IPU # */
|
||||
#define OP_SEA 0x000D /* Set Extended Addressing # NBR */
|
||||
#define OP_DAE 0x000E /* Disable Arithmetic Exception Trap # */
|
||||
#define OP_CEA 0x000F /* Clear Extended Addressing # NBR */
|
||||
#define OP_ANR 0x0400 /* And Register # */
|
||||
#define OP_CMC 0x040A /* Cache Memory Control # */
|
||||
#define OP_SMC 0x0407 /* Shared Memory Control # */
|
||||
#define OP_RPSWT 0x040B /* Read Processor Status Word two # */
|
||||
#define OP_ORR 0x0800 /* Or Register # */
|
||||
#define OP_ORRM 0x0808 /* Or Register Masked # */
|
||||
#define OP_ZR 0x0C00 /* Zero Register # */
|
||||
#define OP_EOR 0x0C00 /* Exclusive Or Register # */
|
||||
#define OP_EORM 0x0C08 /* Exclusive Or Register Masked # */
|
||||
#define OP_CAR 0x1000 /* Compare Register # */
|
||||
#define OP_SACZ 0x1008 /* Shift and Count Zeros # BR */
|
||||
#define OP_CMR 0x1400 /* Compare masked with register */
|
||||
#define OP_SBR 0x1800 /* Set Bit in Register # */
|
||||
#define OP_ZBR 0x1804 /* Zero Bit In register # BR */
|
||||
#define OP_ABR 0x1808 /* Add Bit In Register # BR */
|
||||
#define OP_TBR 0x180C /* Test Bit in Register # BR */
|
||||
#define OP_SRABR 0x1C00 /* Shift Right Arithmetic # BR */
|
||||
#define OP_SRLBR 0x1C20 /* Shift Right Logical # BR */
|
||||
#define OP_SLABR 0x1C40 /* Shift Left Arithmetic # BR */
|
||||
#define OP_SLLBR 0x1C60 /* Shift Left Logical # BR */
|
||||
#define OP_SRADBR 0x2000 /* Shift Right Arithmetic Double # BR */
|
||||
#define OP_SRLDBR 0x2020 /* Shift Left Logical Double # BR */
|
||||
#define OP_SLADBR 0x2040 /* Shift Right Arithmetic Double # BR */
|
||||
#define OP_SLLDBR 0x2060 /* Shift Left Logical Double # BR */
|
||||
#define OP_SRCBR 0x2400 /* Shift Right Circular # BR */
|
||||
#define OP_ZBM 0x1C00 /* Zero Bit in Register # NBR */
|
||||
#define OP_ABR 0x2000 /* Add Bit in Register # NBR */
|
||||
#define OP_TBR 0x2400 /* Test Bit in Register # NBR */
|
||||
#define OP_TRSW 0x2800 /* Transfer GPR to PSD */
|
||||
#define OP_TRBR 0x2801 /* Transfer GPR to BR # BR */
|
||||
#define OP_XCBR 0x2802 /* Exchange Base Registers # BR */
|
||||
#define OP_TCCR 0x2802 /* Transfer CC to GPR # BR */
|
||||
#define OP_TRCC 0x2804 /* Transfer GPR to CC # BR */
|
||||
#define OP_BSUB 0x2805 /* Branch Subroutine # BR */
|
||||
#define OP_CALL 0x2808 /* Procedure Call # BR */
|
||||
#define OP_TPCBR 0x280C /* Transfer Program Counter to Base # BR */
|
||||
#define OP_RETURN 0x280E /* Procedure Return # BR */
|
||||
#define OP_TRR 0x2C00 /* Transfer Register to Register # */
|
||||
#define OP_TRDR 0x2C01 /* Transfer GPR to BR # */
|
||||
#define OP_TBRR 0x2C02 /* Transfer BR to GPR BR # */
|
||||
#define OP_TRC 0x2C03 /* Transfer Register Complement # */
|
||||
#define OP_TRN 0x2C04 /* Transfer Register Negative # */
|
||||
#define OP_XCR 0x2C05 /* Exchange Registers # */
|
||||
#define OP_LMAP 0x2C07 /* Load MAP * */
|
||||
#define OP_TRRM 0x2C08 /* Transfer Register to Register Masked # */
|
||||
#define OP_SETCPU 0x2C09 /* Set CPU Mode # * */
|
||||
#define OP_TMAPR 0x2C0A /* Transfer MAP to Register # * */
|
||||
#define OP_XCRM 0x2C0D /* Exchange Registers Masked # */
|
||||
#define OP_TRCM 0x2C0B /* Transfer Register Complement Masked # */
|
||||
#define OP_TRNM 0x2C0C /* Transfer Register Negative Masked # */
|
||||
#define OP_TRSC 0x2C0E /* Transfer Register to Scratchpad # * */
|
||||
#define OP_TSCR 0x2C0F /* Transfer Scratchpad to Register # * */
|
||||
#define OP_CALM 0x3000 /* Call Monitor # */
|
||||
#define OP_LA 0x3400 /* Load Address NBR */
|
||||
#define OP_ADR 0x3800 /* Add Register to Register # */
|
||||
#define OP_ADRFW 0x3801 /* Add Floating Point to Register # BR? */
|
||||
#define OP_MPRBR 0x3802 /* Multiply Register BR # */
|
||||
#define OP_SURFW 0x3803 /* Subtract Floating Point Register BR? # */
|
||||
#define OP_DVRFW 0x3804 /* Divide Floating Point Register BR? # */
|
||||
#define OP_FIXW 0x3805 /* Fix Floating Point Register BR? # */
|
||||
#define OP_MPRFW 0x3806 /* Multiply Floating Point Register BR? # */
|
||||
#define OP_FLTW 0x3807 /* Float Floating Point Register BR? # */
|
||||
#define OP_ADRM 0x3808 /* Add Register to Register Masked # */
|
||||
#define OP_DVRBR 0x380A /* Divide Register by Registier BR # */
|
||||
#define OP_SURFD 0x380B /* Subtract Floating Point Double # BR? */
|
||||
#define OP_DVRFD 0x380C /* Divide Floating Point Double # BR? */
|
||||
#define OP_FIXD 0x380D /* Fix Double Register # BR? */
|
||||
#define OP_MPRFD 0x380E /* Multiply Double Register # BR? */
|
||||
#define OP_FLTD 0x380F /* Float Double # BR? */
|
||||
#define OP_SUR 0x3C00 /* Subtract Register to Register # */
|
||||
#define OP_SURM 0x3C08 /* Subtract Register to Register Masked # */
|
||||
#define OP_MPR 0x4000 /* Multiply Register to Register # NBR */
|
||||
#define OP_DVR 0x4400 /* Divide Register to Register # NBR */
|
||||
#define OP_LA 0x5000 /* Load Address BR */
|
||||
#define OP_STWBR 0x5400 /* Store Base Register BR */
|
||||
#define OP_SUABR 0x5800 /* Subtract Base Register BR */
|
||||
#define OP_LABR 0x5808 /* Load Address Base Register BR */
|
||||
#define OP_LWBR 0x5C00 /* Load Base Register BR */
|
||||
#define OP_BSUBM 0x5C08 /* Branch Subroutine Memory BR */
|
||||
#define OP_CALLM 0x5C08 /* Call Memory BR */
|
||||
#define OP_NOR 0x6000 /* Normalize # NBR */
|
||||
#define OP_NORD 0x6400 /* Normalize Double # NBR*/
|
||||
#define OP_SCZ 0x6800 /* Shift and Count Zeros # */
|
||||
#define OP_SRA 0x6C00 /* Shift Right Arithmetic # NBR */
|
||||
#define OP_SLA 0x6C40 /* Shift Left Arithmetic # NBR */
|
||||
#define OP_SRL 0x7000 /* Shift Right Logical # NBR */
|
||||
#define OP_SLL 0x7040 /* Shift Left Logical # NBR */
|
||||
#define OP_SRC 0x7400 /* Shift Right Circular # NBR */
|
||||
#define OP_SLC 0x7440 /* Shift Left Circular # NBR */
|
||||
#define OP_SRAD 0x7800 /* Shift Right Arithmetic Double # NBR */
|
||||
#define OP_SLAD 0x7840 /* Shift Left Arithmetic Double # NBR */
|
||||
#define OP_SRLD 0x7C00 /* Shift Right Logical Double # NBR */
|
||||
#define OP_SLLD 0x7C40 /* Shift Left Logical Double # NBR */
|
||||
#define OP_LEAR 0x8000 /* Load Effective Address Real * */
|
||||
#define OP_ANMx 0x8400 /* And Memory B,H,W,D */
|
||||
#define OP_ORMx 0x8800 /* Or Memory B,H,W,D */
|
||||
#define OP_EOMx 0x8C00 /* Exclusive Or Memory */
|
||||
#define OP_CAMx 0x9000 /* Compare Arithmetic with Memory */
|
||||
#define OP_CMMx 0x9400 /* Compare Masked with Memory */
|
||||
#define OP_SBM 0x9800 /* Set Bit in Memory */
|
||||
#define OP_ZBM 0x9C00 /* Zero Bit in Memory */
|
||||
#define OP_ABM 0xA000 /* Add Bit in Memory */
|
||||
#define OP_TBM 0xA400 /* Test Bit in Memory */
|
||||
#define OP_EXM 0xA800 /* Execute Memory */
|
||||
#define OP_Lx 0xAC00 /* Load B,H,W,D */
|
||||
#define OP_LMx 0xB000 /* Load Masked B,H,W,D */
|
||||
#define OP_LNx 0xB400 /* Load Negative B,H,W,D */
|
||||
#define OP_ADMx 0xB800 /* Add Memory B,H,W,D */
|
||||
#define OP_SUMx 0xBC00 /* Subtract Memory B,H,W,D */
|
||||
#define OP_MPMx 0xC000 /* Multiply Memory B,H,W,D */
|
||||
#define OP_DVMx 0xC400 /* Divide Memory B,H,W,D */
|
||||
#define OP_LI 0xC800 /* Load Immediate */
|
||||
#define OP_ADI 0xC801 /* Add Immediate */
|
||||
#define OP_SUI 0xC802 /* Subtract Immediate */
|
||||
#define OP_MPI 0xC803 /* Multiply Immediate */
|
||||
#define OP_DVI 0xC804 /* Divide Immediate */
|
||||
#define OP_CI 0xC805 /* Compare Immediate */
|
||||
#define OP_SVC 0xC806 /* Supervisor Call */
|
||||
#define OP_EXR 0xC807 /* Execute Register/ Right */
|
||||
#define OP_SEM 0xC808 /* Store External Map * */
|
||||
#define OP_LEM 0xC809 /* Load External Map * */
|
||||
#define OP_CEMA 0xC80A /* Convert External Map * */
|
||||
#define OP_LF 0xCC00 /* Load File */
|
||||
#define OP_LEA 0xD000 /* Load Effective Address */
|
||||
#define OP_STx 0xD400 /* Store B,H,W,D */
|
||||
#define OP_STMx 0xD800 /* Store Masked B,H,W,D */
|
||||
#define OP_ADFx 0xE008 /* Add Floating Memory D,W */
|
||||
#define OP_SUFx 0xE000 /* Subtract Floating Memory D,W */
|
||||
#define OP_MPFx 0xE408 /* Multiply Floating Memory D,W */
|
||||
#define OP_DVFx 0xE400 /* Divide Floating Memory D,W */
|
||||
#define OP_ARMx 0xE800 /* Add Register to Memory B,H,W,D */
|
||||
#define OP_BU 0xEC00 /* Branch Unconditional */
|
||||
#define OP_BCT 0xEC00 /* Branch Condition True */
|
||||
#define OP_BCF 0xF000 /* Branch Condition False */
|
||||
#define OP_BIB 0xF400 /* Branch after Incrementing Byte */
|
||||
#define OP_BIW 0xF420 /* Branch after Incrementing Word */
|
||||
#define OP_BIH 0xF440 /* Branch after Incrementing Half */
|
||||
#define OP_BID 0xF460 /* Branch after Incrementing Double */
|
||||
#define OP_ZMx 0xF800 /* Zero Memory B,H,W,D */
|
||||
#define OP_BL 0xF880 /* Branch and Link */
|
||||
#define OP_BRI 0xF900 /* Branch and Reset Interrupt * */
|
||||
#define OP_LPSD 0xF980 /* Load Program Status Double * */
|
||||
#define OP_LPSDCM 0xFA80 /* LPSD and Change Map * */
|
||||
#define OP_TPR 0xFB80 /* Transfer Protect Register to Register */
|
||||
#define OP_TRP 0xFB00 /* Transfer Register to Protect Register */
|
||||
#define OP_EI 0xFC00 /* Enable Interrupt */
|
||||
#define OP_DI 0xFC01 /* Disable Interrupt */
|
||||
#define OP_RI 0xFC02 /* Request Interrupt */
|
||||
#define OP_AI 0xFC03 /* Activate Interrupt */
|
||||
#define OP_DAI 0xFC04 /* Deactivate Interrupt */
|
||||
#define OP_TD 0xFC05 /* Test Device */
|
||||
#define OP_CD 0xFC06 /* Command Device */
|
||||
#define OP_SIO 0xFC17 /* Start I/O */
|
||||
#define OP_TIO 0xFC1F /* Test I/O */
|
||||
#define OP_STPIO 0xFC27 /* Stop I/O */
|
||||
#define OP_RSCHNL 0xFC2F /* Reset Channel */
|
||||
#define OP_HIO 0xFC37 /* Halt I/O */
|
||||
#define OP_GRIO 0xFC3F /* Grab Controller */
|
||||
#define OP_RSCTL 0xFC47 /* Reset Controller */
|
||||
#define OP_ECI 0xFC67 /* Enable Channel Interrupt */
|
||||
#define OP_DCI 0xFC6F /* Disable Channel Interrupt */
|
||||
#define OP_ACI 0xFC77 /* Activate Channel Interrupt */
|
||||
#define OP_DACI 0xFC7F /* Deactivate Channel Interrupt */
|
||||
|
||||
|
||||
|
||||
/* Debuging controls */
|
||||
#define DEBUG_CMD 0x0000001 /* Show device commands */
|
||||
#define DEBUG_DATA 0x0000002 /* Show data transfers */
|
||||
#define DEBUG_DETAIL 0x0000004 /* Show details */
|
||||
#define DEBUG_EXP 0x0000008 /* Show error conditions */
|
||||
#define DEBUG_CONI 0x0000020 /* Show CONI instructions */
|
||||
#define DEBUG_CONO 0x0000040 /* Show CONO instructions */
|
||||
#define DEBUG_DATAIO 0x0000080 /* Show DATAI/O instructions */
|
||||
#define DEBUG_IRQ 0x0000100 /* Show IRQ requests */
|
||||
|
||||
extern DEBTAB dev_debug[];
|
||||
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
876
SEL32/sel32_sys.c
Normal file
876
SEL32/sel32_sys.c
Normal file
@ -0,0 +1,876 @@
|
||||
/* sel32_sys.c: SEL 32 Gould Concept/32 (orignal SEL32) Simulator system interface.
|
||||
|
||||
Copyright (c) 2018, Richard Cornwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "sel32_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern uint32 M[MAXMEMSIZE];
|
||||
|
||||
/* SCP data structures and interface routines
|
||||
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "SEL 32";
|
||||
|
||||
REG *sim_PC = &cpu_reg[0];
|
||||
|
||||
int32 sim_emax = 16;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
#ifdef NUM_DEVS_CON
|
||||
&con_dev,
|
||||
#endif
|
||||
#ifdef NUM_DEVS_CDR
|
||||
&cdr_dev,
|
||||
#endif
|
||||
#ifdef NUM_DEVS_CDP
|
||||
&cdp_dev,
|
||||
#endif
|
||||
#ifdef NUM_DEVS_LPR
|
||||
&lpr_dev,
|
||||
#endif
|
||||
#ifdef NUM_DEVS_MT
|
||||
&mta_dev,
|
||||
#if NUM_DEVS_MT > 1
|
||||
&mtb_dev,
|
||||
#endif
|
||||
#endif
|
||||
#ifdef NUM_DEVS_DASD
|
||||
&dda_dev,
|
||||
#if NUM_DEVS_DASD > 1
|
||||
&ddb_dev,
|
||||
#endif
|
||||
#endif
|
||||
#ifdef NUM_DEVS_COM
|
||||
&com_dev,
|
||||
#endif
|
||||
NULL };
|
||||
|
||||
|
||||
/* Simulator debug controls */
|
||||
DEBTAB dev_debug[] = {
|
||||
{"CMD", DEBUG_CMD, "Show command execution to devices"},
|
||||
{"DATA", DEBUG_DATA, "Show data transfers"},
|
||||
{"DETAIL", DEBUG_DETAIL, "Show details about device"},
|
||||
{"EXP", DEBUG_EXP, "Show exception information"},
|
||||
{"INST", DEBUG_INST, "Show instruction execution"},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Load a card image file into memory. */
|
||||
|
||||
t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
|
||||
{
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
/* Symbol tables */
|
||||
|
||||
/*
|
||||
* The SEL 32 supports the following instruction formats.
|
||||
*
|
||||
* TYPE Format Normal Base Mode
|
||||
* A ADR d,[*]o,x d,o[(b)],x FC = extra
|
||||
* B BRA [*]o,x o[(b)],x
|
||||
* C IMM d,o d,o
|
||||
* D BIT d,[*]o,x d,o[(b)],x
|
||||
* E ADR [*]o,x o[(b)],x FC = extra
|
||||
* F REG s,d s,d Half Word
|
||||
* G RG1 s s
|
||||
* H HLF
|
||||
* I SHF d,v d,v
|
||||
* K RBT d,b d,b
|
||||
* L EXR s s
|
||||
* M IOP n,b n,b
|
||||
*/
|
||||
|
||||
#define TYPE_A 0
|
||||
#define TYPE_B 1
|
||||
#define TYPE_C 2
|
||||
#define TYPE_D 3
|
||||
#define TYPE_E 4
|
||||
#define TYPE_F 5
|
||||
#define TYPE_G 6
|
||||
#define TYPE_H 7
|
||||
#define TYPE_I 8
|
||||
#define TYPE_K 9
|
||||
#define TYPE_L 10
|
||||
#define TYPE_M 11
|
||||
#define H 0x10
|
||||
|
||||
typedef struct _opcode {
|
||||
uint16 opbase;
|
||||
uint16 mask;
|
||||
uint8 type;
|
||||
char *name;
|
||||
} t_opcode;
|
||||
|
||||
|
||||
t_opcode optab[] {
|
||||
{ OP_HALT, 0xFFFF, H|TYPE_H, "HALT", }, /* Halt # * */
|
||||
{ OP_WAIT, 0xFFFF, H|TYPE_H, "WAIT", }, /* Wait # * */
|
||||
{ OP_NOP, 0xFFFF, H|TYPE_H, "NOP", }, /* Nop # */
|
||||
{ OP_LCS, 0xFFFF, H|TYPE_G, "LCS", }, /* Load Control Switches */
|
||||
{ OP_ES, 0xFC0F, H|TYPE_G, "ES", }, /* Extend Sign # */
|
||||
{ OP_SIPU, 0xFFFF, H|TYPE_H, "SIPU", }, /* Signal IPU # */
|
||||
{ OP_RND, 0xFC0F, H|TYPE_G, "RND", }, /* Round Register # */
|
||||
{ OP_BEI, 0xFC0F, H|TYPE_H, "BEI", }, /* Block External Interrupts # */
|
||||
{ OP_UEI, 0xFC0F, H|TYPE_H, "UEI", }, /* Unblock External Interrupts # */
|
||||
{ OP_EAE, 0xFC0F, H|TYPE_H, "EAE", }, /* Enable Arithmetic Exception Trap # */
|
||||
{ OP_RDSTS, 0xFC0F, H|TYPE_G, "RDSTS", }, /* Read CPU Status Word * */
|
||||
{ OP_SEA, 0xFFFF, H|TYPE_H, "SEA", }, /* Set Extended Addressing # NBR */
|
||||
{ OP_DAE, 0xFC0F, H|TYPE_H, "DAE", }, /* Disable Arithmetic Exception Trap # */
|
||||
{ OP_CEA, 0xFFFF, H|TYPE_H, "CEA", }, /* Clear Extended Addressing # NBR */
|
||||
{ OP_CMC, 0xFC0F, H|TYPE_G, "CMC", }, /* Cache Memory Control # */
|
||||
{ OP_SMC, 0xFC0F, H|TYPE_G, "SMC", }, /* Shared Memory Control # */
|
||||
{ OP_ANR, 0xFC0F, H|TYPE_F, "ANR", }, /* And Register # */
|
||||
{ OP_RPSWT, 0xFC0F, H|TYPE_G, "RPSWT", }, /* Read Processor Status Word Two # */
|
||||
{ OP_ORR, 0xFC0F, H|TYPE_F, "ORR", }, /* Or Register # */
|
||||
{ OP_ORRM, 0xFC0F, H|TYPE_F, "ORRM", }, /* Or Register Masked # */
|
||||
{ OP_EOR, 0xFC0F, H|TYPE_F, "EOR", }, /* Exclusive Or Register # */
|
||||
{ OP_EORM, 0xFC0F, H|TYPE_F, "EORM", }, /* Exclusive Or Register Masked # */
|
||||
{ OP_CAR, 0xFC0F, H|TYPE_F, "CAR", }, /* Compare Register # */
|
||||
{ OP_CMR, 0xFC0F, H|TYPE_F, "CMR", }, /* Compare masked with register */
|
||||
{ OP_SACZ, 0xFC0F, H|TYPE_F, "SACZ", }, /* Shift and Count Zeros # BR */
|
||||
{ OP_SBR, 0xFC0F, H|TYPE_K, "SBR", }, /* Set Bit in Register # */
|
||||
{ OP_ZBR, 0xFC0F, H|TYPE_K, "ZBR", }, /* Zero Bit In register # BR */
|
||||
{ OP_ABR, 0xFC0F, H|TYPE_K, "ABR", }, /* Add Bit In Register # BR */
|
||||
{ OP_TBR, 0xFC0F, H|TYPE_K, "TBR", }, /* Test Bit in Register # BR */
|
||||
{ OP_SRABR, 0xFC0F, H|TYPE_I, "SRABR", }, /* Shift Right Arithmetic # BR */
|
||||
{ OP_SRLBR, 0xFC0F, H|TYPE_I, "SRLBR", }, /* Shift Right Logical # BR */
|
||||
{ OP_SLABR, 0xFC0F, H|TYPE_I, "SLABR", }, /* Shift Left Arithmetic # BR */
|
||||
{ OP_SLLBR, 0xFC0F, H|TYPE_I, "SLLBR", }, /* Shift Left Logical # BR */
|
||||
{ OP_SRADBR, 0xFC0F, H|TYPE_I, "SRADBR", }, /* Shift Right Arithmetic Double # BR */
|
||||
{ OP_SRLDBR, 0xFC0F, H|TYPE_I, "SRLDBR", }, /* Shift Left Logical Double # BR */
|
||||
{ OP_SLADBR, 0xFC0F, H|TYPE_I, "SLADBR", }, /* Shift Right Arithmetic Double # BR */
|
||||
{ OP_SLLDBR, 0xFC0F, H|TYPE_I, "SLLDBR", }, /* Shift Left Logical Double # BR */
|
||||
{ OP_SRCBR, 0xFC0F, H|TYPE_I, "SRCBR", }, /* Shift Right Circular # BR */
|
||||
{ OP_ZBR, 0xFC0F, H|TYPE_K, "ZBR", }, /* Zero Bit in Register # NBR */
|
||||
{ OP_ABR, 0xFC0F, H|TYPE_K, "ABR", }, /* Add Bit in Register # NBR */
|
||||
{ OP_TBR, 0xFC0F, H|TYPE_K, "TBR", }, /* Test Bit in Register # NBR */
|
||||
{ OP_TRSW, 0xFC0F, H|TYPE_F, "TRSW", }, /* Transfer GPR to PSD */
|
||||
{ OP_TRBR, 0xFC0F, H|TYPE_F, "TRBR", }, /* Transfer GPR to BR # BR */
|
||||
{ OP_XCBR, 0xFC0F, H|TYPE_F, "XCBR", }, /* Exchange Base Registers # BR */
|
||||
{ OP_TCCR, 0xFC0F, H|TYPE_G, "TCCR", }, /* Transfer CC to GPR # BR */
|
||||
{ OP_TRCC, 0xFC0F, H|TYPE_G, "TRCC", }, /* Transfer GPR to CC # BR */
|
||||
{ OP_BSUB, 0xFC0F, H|TYPE_F, "BSUB", }, /* Branch Subroutine # BR */
|
||||
{ OP_CALL, 0xFC0F, H|TYPE_F, "CALL", }, /* Procedure Call # BR */
|
||||
{ OP_TPCBR, 0xFC0F, H|TYPE_G, "TPCBR", }, /* Transfer Program Counter to Base # BR */
|
||||
{ OP_RETURN, 0xFC7F, H|TYPE_G, "RETURN", }, /* Procedure Return # BR */
|
||||
{ OP_TRR, 0xFC0F, H|TYPE_F, "TRR", }, /* Transfer Register to Register # */
|
||||
{ OP_TRDR, 0xFC0F, H|TYPE_F, "TRDR", }, /* Transfer GPR to BR # */
|
||||
{ OP_TBRR, 0xFC0F, H|TYPE_A, "TBRR", }, /* Transfer BR to GPR BR # */
|
||||
{ OP_TRC, 0xFC0F, H|TYPE_F, "TRC", }, /* Transfer Register Complement # */
|
||||
{ OP_TRN, 0xFC0F, H|TYPE_F, "TRN", }, /* Transfer Register Negative # */
|
||||
{ OP_XCR, 0xFC0F, H|TYPE_F, "XCR", }, /* Exchange Registers # */
|
||||
{ OP_LMAP, 0xFC0F, H|TYPE_G, "LMAP", }, /* Load MAP * */
|
||||
{ OP_TRRM, 0xFC0F, H|TYPE_F, "TRRM", }, /* Transfer Register to Register Masked # */
|
||||
{ OP_SETCPU, 0xFC0F, H|TYPE_G, "SETCPU", }, /* Set CPU Mode # * */
|
||||
{ OP_TMAPR, 0xFC0F, H|TYPE_F, "TMAPR", }, /* Transfer MAP to Register # * */
|
||||
{ OP_XCRM, 0xFC0F, H|TYPE_F, "XCRM", }, /* Exchange Registers Masked # */
|
||||
{ OP_TRCM, 0xFC0F, H|TYPE_F, "TRCM", }, /* Transfer Register Complement Masked # */
|
||||
{ OP_TRNM, 0xFC0F, H|TYPE_F, "TRNM", }, /* Transfer Register Negative Masked # */
|
||||
{ OP_TRSC, 0xFC0F, H|TYPE_F, "TRSC", }, /* Transfer Register to Scratchpad # * */
|
||||
{ OP_TSCR, 0xFC0F, H|TYPE_F, "TSCR", }, /* Transfer Scratchpad to Register # * */
|
||||
{ OP_CALM, 0xFC0F, H|TYPE_F, "CALM", }, /* Call Monitor # */
|
||||
{ OP_LA, 0xFC0F, H|TYPE_F, "LA", }, /* Load Address NBR */
|
||||
{ OP_ADR, 0xFC0F, H|TYPE_F, "ADR", }, /* Add Register to Register # */
|
||||
{ OP_ADRFW, 0xFC0F, H|TYPE_F, "ADRFW", }, /* Add Floating Point to Register # BR? */
|
||||
{ OP_MPRBR, 0xFC0F, H|TYPE_F, "MPRBR", }, /* Multiply Register BR # */
|
||||
{ OP_SURFW, 0xFC0F, H|TYPE_F, "SURFW", }, /* Subtract Floating Point Register BR? # */
|
||||
{ OP_DVRFW, 0xFC0F, H|TYPE_F, "DVRFW", }, /* Divide Floating Point Register BR? # */
|
||||
{ OP_FIXW, 0xFC0F, H|TYPE_F, "FIXW", /* Fix Floating Point Register BR? # */
|
||||
{ OP_MPRFW, 0xFC0F, H|TYPE_F, "MPRFW", }, /* Multiply Floating Point Register BR? # */
|
||||
{ OP_FLTW, 0xFC0F, H|TYPE_F, "FLTW", }, /* Float Floating Point Register BR? # */
|
||||
{ OP_ADRM, 0xFC0F, H|TYPE_F, "ADRM", /* Add Register to Register Masked # */
|
||||
{ OP_DVRBR, 0xFC0F, H|TYPE_F, "DVRBR", /* Divide Register by Registier BR # */
|
||||
{ OP_SURFD, 0xFC0F, H|TYPE_F, "SURFD", }, /* Subtract Floating Point Double # BR? */
|
||||
{ OP_DVRFD, 0xFC0F, H|TYPE_F, "DVRFD", }, /* Divide Floating Point Double # BR? */
|
||||
{ OP_FIXD, 0xFC0F, H|TYPE_F, "FIXD", }, /* Fix Double Register # BR? */
|
||||
{ OP_MPRFD, 0xFC0F, H|TYPE_F, "MPRFD", }, /* Multiply Double Register # BR? */
|
||||
{ OP_FLTD, 0xFC0F, H|TYPE_F, "FLTD", }, /* Float Double # BR? */
|
||||
{ OP_SUR, 0xFC0F, H|TYPE_F, "SUR", }, /* Subtract Register to Register # */
|
||||
{ OP_SURM, 0xFC0F, H|TYPE_F, "SURM", }, /* Subtract Register to Register Masked # */
|
||||
{ OP_MPR, 0xFC0F, H|TYPE_F, "MPR", }, /* Multiply Register to Register # NBR */
|
||||
{ OP_DVR, 0xFC0F, H|TYPE_F, "DVR", /* Divide Register to Register # NBR */
|
||||
{ OP_LA, 0xFC0F, H|TYPE_F, "LA", }, /* Load Address BR */
|
||||
{ OP_STWBR, 0xFC0F, H|TYPE_F, "STWBR", }, /* Store Base Register BR */
|
||||
{ OP_SUABR, 0xFC0F, H|TYPE_F, "SUABR", }, /* Subtract Base Register BR */
|
||||
{ OP_LABR, 0xFC0F, H|TYPE_F, "LABR", }, /* Load Address Base Register BR */
|
||||
{ OP_LWBR, 0xFC0F, H|TYPE_F, "WBR", }, /* Load Base Register BR */
|
||||
{ OP_BSUBM, 0xFC0F, H|TYPE_F, "BSUBM", }, /* Branch Subroutine Memory BR */
|
||||
{ OP_CALLM, 0xFC0F, H|TYPE_F, "CALLM", }, /* Call Memory BR */
|
||||
{ OP_NOR, 0xFC0F, H|TYPE_F, "NOR", }, /* Normalize # NBR */
|
||||
{ OP_NORD, 0xFC0F, H|TYPE_F, "NORD", }, /* Normalize Double # NBR*/
|
||||
{ OP_SCZ, 0xFC0F, H|TYPE_F, "SCZ", }, /* Shift and Count Zeros # */
|
||||
{ OP_SRA, 0xFC0F, H|TYPE_I, "SRA", }, /* Shift Right Arithmetic # NBR */
|
||||
{ OP_SLA, 0xFC40, H|TYPE_I, "SLA", }, /* Shift Left Arithmetic # NBR */
|
||||
{ OP_SRL, 0xFC40, H|TYPE_I, "SRL", }, /* Shift Right Logical # NBR */
|
||||
{ OP_SLL, 0xFC40, H|TYPE_I, "SLL", }, /* Shift Left Logical # NBR */
|
||||
{ OP_SRC, 0xFC40, H|TYPE_I, "SRC", }, /* Shift Right Circular # NBR */
|
||||
{ OP_SLC, 0xFC40, H|TYPE_I, "SLC", }, /* Shift Left Circular # NBR */
|
||||
{ OP_SRAD, 0xFC40, H|TYPE_I, "SRAD", }, /* Shift Right Arithmetic Double # NBR */
|
||||
{ OP_SLAD, 0xFC40, H|TYPE_I, "SLAD", }, /* Shift Left Arithmetic Double # NBR */
|
||||
{ OP_SRLD, 0xFC40, H|TYPE_I, "SRLD", }, /* Shift Right Logical Double # NBR */
|
||||
{ OP_SLLD, 0xFC40, H|TYPE_I, "SLLD", }, /* Shift Left Logical Double # NBR */
|
||||
{ OP_LEAR, 0xFC00, TYPE_A, "LEAR", }, /* Load Effective Address Real * */
|
||||
{ OP_ANMx, 0xFC00, TYPE_A, "ANM", }, /* And Memory B,H,W,D */
|
||||
{ OP_ORMx, 0xFC00, TYPE_A, "ORM", }, /* Or Memory B,H,W,D */
|
||||
{ OP_EOMx, 0xFC00, TYPE_A, "EOM", }, /* Exclusive Or Memory */
|
||||
{ OP_CAMx, 0xFC00, TYPE_A, "CAM", }, /* Compare Arithmetic with Memory */
|
||||
{ OP_CMMx, 0xFC00, TYPE_A, "CMM", }, /* Compare Masked with Memory */
|
||||
{ OP_SBM, 0xFC00, TYPE_A, "SBM", }, /* Set Bit in Memory */
|
||||
{ OP_ZBM, 0xFC00, TYPE_A, "ZBM", }, /* Zero Bit in Memory */
|
||||
{ OP_ABM, 0xFC00, TYPE_A, "ABM", }, /* Add Bit in Memory */
|
||||
{ OP_TBM, 0xFC00, TYPE_A, "TBM", }, /* Test Bit in Memory */
|
||||
{ OP_EXM, 0xFC00, TYPE_B, "EXM", }, /* Execute Memory */
|
||||
{ OP_Lx, 0xFC00, TYPE_A, "L", }, /* Load B,H,W,D */
|
||||
{ OP_LMx, 0xFC00, TYPE_A, "LM", }, /* Load Masked B,H,W,D */
|
||||
{ OP_LNx, 0xFC00, TYPE_A, "LN", }, /* Load Negative B,H,W,D */
|
||||
{ OP_ADMx, 0xFC00, TYPE_A, "ADM", }, /* Add Memory B,H,W,D */
|
||||
{ OP_SUMx, 0xFC00, TYPE_A, "SUM", }, /* Subtract Memory B,H,W,D */
|
||||
{ OP_MPMx, 0xFC00, TYPE_A, "MPM", }, /* Multiply Memory B,H,W,D */
|
||||
{ OP_DVMx, 0xFC00, TYPE_A, "DVM", }, /* Divide Memory B,H,W,D */
|
||||
{ OP_LI, 0xFC0F, TYPE_C, "LI", }, /* Load Immediate */
|
||||
{ OP_ADI, 0xFC0F, TYPE_C, "ADI", }, /* Add Immediate */
|
||||
{ OP_SUI, 0xFC0F, TYPE_C, "SUI", }, /* Subtract Immediate */
|
||||
{ OP_MPI, 0xFC0F, TYPE_C, "MPI", }, /* Multiply Immediate */
|
||||
{ OP_DVI, 0xFC0F, TYPE_C, "DVI", }, /* Divide Immediate */
|
||||
{ OP_CI, 0xFC0F, TYPE_C, "CI", }, /* Compare Immediate */
|
||||
{ OP_SVC, 0xFC0F, TYPE_C, "SVC", }, /* Supervisor Call */
|
||||
{ OP_EXR, 0xFC0F, TYPE_L, "EXR", }, /* Execute Register/ Right */
|
||||
{ OP_SEM, 0xFC0F, TYPE_A, "SEM", }, /* Store External Map * */
|
||||
{ OP_LEM, 0xFC0F, TYPE_A, "LEM", }, /* Load External Map * */
|
||||
{ OP_CEMA, 0xFC0F, TYPE_A, "CEMA", }, /* Convert External Map * */
|
||||
{ OP_LF, 0xFC00, TYPE_A, "LF", }, /* Load File */
|
||||
{ OP_LEA, 0xFC00, TYPE_A, "LEA", }, /* Load Effective Address */
|
||||
{ OP_STx, 0xFC00, TYPE_A, "ST", }, /* Store B,H,W,D */
|
||||
{ OP_STMx, 0xFC00, TYPE_A, "STM", }, /* Store Masked B,H,W,D */
|
||||
{ OP_ADFx, 0xFC0F, TYPE_A, "ADF", }, /* Add Floating Memory D,W */
|
||||
{ OP_SUFx, 0xFC0F, TYPE_A, "SUF", }, /* Subtract Floating Memory D,W */
|
||||
{ OP_MPFx, 0xFC0F, TYPE_A, "MPF", }, /* Multiply Floating Memory D,W */
|
||||
{ OP_DVFx, 0xFC0F, TYPE_A, "DVF", }, /* Divide Floating Memory D,W */
|
||||
{ OP_ARMx, 0xFC00, TYPE_A, "ARM", }, /* Add Register to Memory B,H,W,D */
|
||||
{ OP_BU, 0xFC00, TYPE_F, "BU", }, /* Branch Unconditional */
|
||||
{ 0xF000, 0XFF80, TYPE_B, "BFT", }, /* Branch Function True */
|
||||
{ 0xEC80, 0xFF80, TYPE_B, "BS", }, /* Branch Condition True CC1 = 1 */
|
||||
{ 0xED00, 0xFF80, TYPE_B, "BGT", }, /* Branch Condition True CC2 = 1 */
|
||||
{ 0xED80, 0xFF80, TYPE_B, "BLT", }, /* Branch Condition True CC3 = 1 */
|
||||
{ 0xEE00, 0xFF80, TYPE_B, "BEQ", }, /* Branch Condition True CC4 = 1 */
|
||||
{ 0xEE80, 0xFF80, TYPE_B, "BGE", }, /* Branch Condition True CC2|CC4 = 1 */
|
||||
{ 0xEF00, 0xFF80, TYPE_B, "BLE", }, /* Branch Condition True CC3|CC4 = 1*/
|
||||
{ 0xEF80, 0xFF80, TYPE_B, "BANY", }, /* Branch Condition True CC1|CC2|CC3|CC4 */
|
||||
{ 0xF080, 0xFF80, TYPE_B, "BNS", }, /* Branch Condition False CC1 = 0 */
|
||||
{ 0xF100, 0xFF80, TYPE_B, "BNP", }, /* Branch Condition False CC2 = 0 */
|
||||
{ 0xF180, 0xFF80, TYPE_B, "BNN", }, /* Branch Condition False CC3 = 0 */
|
||||
{ 0xF200, 0xFF80, TYPE_B, "BNE", }, /* Branch Condition False CC4 = 0 */
|
||||
{ 0xF380, 0xFF80, TYPE_B, "BAZ", }, /* Branch Condition False CC1|CC2|CC3|CC4=0*/
|
||||
{ OP_BCT, 0xFC00, TYPE_A, "BCT", }, /* Branch Condition True CC1 == 1 */
|
||||
{ OP_BCF, 0xFC00, TYPE_A, "BCF", }, /* Branch Condition False */
|
||||
{ OP_BIB, 0xFC70, TYPE_D, "BIB", }, /* Branch after Incrementing Byte */
|
||||
{ OP_BIW, 0xFC70, TYPE_D, "BIW", }, /* Branch after Incrementing Word */
|
||||
{ OP_BIH, 0xFC70, TYPE_D, "BIH", }, /* Branch after Incrementing Half */
|
||||
{ OP_BID, 0xFC70, TYPE_D, "BID", }, /* Branch after Incrementing Double */
|
||||
{ OP_ZMx, 0xFCC0, TYPE_E, "ZM", }, /* Zero Memory B,H,W,D */
|
||||
{ OP_BL, 0xFF80, TYPE_B, "BL", }, /* Branch and Link */
|
||||
{ OP_BRI, 0xFCC0, TYPE_A, "BRI", }, /* Branch and Reset Interrupt * */
|
||||
{ OP_LPSD, 0xFCC0, TYPE_A, "LPSD", }, /* Load Program Status Double * */
|
||||
{ OP_LPSDCM, 0xFCC0, TYPE_A, "LPSDCM", }, /* LPSD and Change Map * */
|
||||
{ OP_TPR, 0xFCC0, TYPE_A, "TPR", }, /* Transfer Protect Register to Register */
|
||||
{ OP_TRP, 0xFCC0, TYPE_A, "TRP", }, /* Transfer Register to Protect Register */
|
||||
{ OP_EI, 0xFC0F, TYPE_L, "EI", }, /* Enable Interrupt */
|
||||
{ OP_DI, 0xFC0F, TYPE_L, "DI", }, /* Disable Interrupt */
|
||||
{ OP_RI, 0xFC0F, TYPE_L, "RI", }, /* Request Interrupt */
|
||||
{ OP_AI, 0xFC0F, TYPE_L, "AI", }, /* Activate Interrupt */
|
||||
{ OP_DAI, 0xFC0F, TYPE_L, "DAI", }, /* Deactivate Interrupt */
|
||||
{ OP_TD, 0xFC0F, TYPE_M, "TD", }, /* Test Device */
|
||||
{ OP_CD, 0xFC0F, TYPE_M, "CD", }, /* Command Device */
|
||||
{ OP_SIO, 0xFC7F, TYPE_C, "SIO", }, /* Start I/O */
|
||||
{ OP_TIO, 0xFC7F, TYPE_C, "TIO", }, /* Test I/O */
|
||||
{ OP_STPIO, 0xFC7F, TYPE_C, "STPIO", }, /* Stop I/O */
|
||||
{ OP_RSCHNL, 0xFC7F, TYPE_C, "RSCHNL", }, /* Reset Channel */
|
||||
{ OP_HIO, 0xFC7F, TYPE_C, "HIO", }, /* Halt I/O */
|
||||
{ OP_GRIO, 0xFC7F, TYPE_C, "GRIO", }, /* Grab Controller */
|
||||
{ OP_RSCTL, 0xFC7F, TYPE_C, "RSCTL", }, /* Reset Controller */
|
||||
{ OP_ECI, 0xFC7F, TYPE_C, "ECI", }, /* Enable Channel Interrupt */
|
||||
{ OP_DCI, 0xFC7F, TYPE_C, "DCI", }, /* Disable Channel Interrupt */
|
||||
{ OP_ACI, 0xFC7F, TYPE_C, "ACI", }, /* Activate Channel Interrupt */
|
||||
{ OP_DACI, 0xFC7F, TYPE_C, "DACI", }, /* Deactivate Channel Interrupt */
|
||||
};
|
||||
|
||||
|
||||
/* Register change decode
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
inst = mask bits
|
||||
*/
|
||||
char *fc_type = "WHHDBBBB";
|
||||
|
||||
int fprint_inst(FILE *of, uint32 val, int32 sw) {
|
||||
uint16 inst = (val >> 16) & 0xFFFF;
|
||||
uint32 v = 0;;
|
||||
int i;
|
||||
int l = 1;
|
||||
int mode = 0;
|
||||
|
||||
|
||||
if (sw & SWMASK ('M')) /* Base mode printing */
|
||||
mode = 1;
|
||||
for (tab = optab; tab->name != NULL; tab++) {
|
||||
if (tab->opbase == (inst & tab->mask)) {
|
||||
fputs(tab->name, of);
|
||||
switch(tab->type & 0xF) {
|
||||
case TYPE_A: /* c r,[*]o[,x] or r,o[(b)][,x] */
|
||||
case TYPE_E: /* c [*]o[,x] or o[(b)][,x] */
|
||||
i = (*val & 3) | ((inst >> 1) & 04);
|
||||
fputc(fc_type[i], of);
|
||||
/* Fall through */
|
||||
|
||||
case TYPE_F: /* r,[*]o[,x] or r,o[(b)],[,x] */
|
||||
fputc(' ', of);
|
||||
if ((tab->type & 0xf) != TYPE_E) {
|
||||
fputc('0'+((inst>>7) & 07), of);
|
||||
fputc(',', of);
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case TYPE_B: /* [*]o[,x] or o[(b)],[,x] */
|
||||
if (mode) {
|
||||
fprint_val(of, *val, 16, 16, PV_RZRO);
|
||||
if (inst & 07) {
|
||||
fputc('(', of);
|
||||
fputc('0' + (inst & 07));
|
||||
fputc(')', of);
|
||||
}
|
||||
if (inst & 0x70) {
|
||||
fputc(',', of);
|
||||
fputc('0'+(inst >> 4) & 07);
|
||||
}
|
||||
} else {
|
||||
if (inst & 0x10)
|
||||
fputc('*', of);
|
||||
fprint_val(of, *val, 16, 19, PV_RZRO);
|
||||
if (inst & 0x60) {
|
||||
fputc(',', of);
|
||||
fputc('0'+(inst >> 5) & 03);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_C: /* r,v */
|
||||
i = (*val & 3) | ((inst >> 1) & 04);
|
||||
fputc(fc_type[i], of);
|
||||
fputc(' ', of);
|
||||
fputc('0'+((inst>>7) & 07), of);
|
||||
fputc(',', of);
|
||||
fprint_val(of, *val, 16, 16, PV_RZRO);
|
||||
break;
|
||||
|
||||
case TYPE_D: /* r,r */
|
||||
fputc(' ', of);
|
||||
fputc('0'+((inst>>7) & 07), of);
|
||||
fputc(',', of);
|
||||
fputc('0'+((inst>>4) & 07), of);
|
||||
break;
|
||||
|
||||
case TYPE_G: /* r */
|
||||
fputc(' ', of);
|
||||
fputc('0'+((inst>>7) & 07), of);
|
||||
break;
|
||||
|
||||
case TYPE_H: /* empty */
|
||||
break;
|
||||
|
||||
case TYPE_I: /* r,b */
|
||||
fputc(' ', of);
|
||||
fputc('0'+((inst>>7) & 07), of);
|
||||
fputc(',', of);
|
||||
fprint_val(of, inst, 16, 5, PV_RZRO);
|
||||
break;
|
||||
|
||||
case TYPE_K: /* r,rb */
|
||||
fputc(' ', of);
|
||||
fputc('0'+((inst>>4) & 07), of);
|
||||
fputc(',', of);
|
||||
i = ((inst & 3) << 3) | ((inst >> 7) & 07);
|
||||
fprint_val(of, i, 16, 5, PV_RZRO);
|
||||
break;
|
||||
|
||||
case TYPE_L: /* i */
|
||||
fputc(' ', of);
|
||||
fprint_val(of, inst>>3, 16, 7, PV_RZRO);
|
||||
break;
|
||||
|
||||
case TYPE_M: /* i,v */
|
||||
fputc(' ', of);
|
||||
fprint_val(of, inst>>3, 16, 7, PV_RZRO);
|
||||
fputc(',', of);
|
||||
fprint_val(of, *val, 16, 16, PV_RZRO);
|
||||
break;
|
||||
|
||||
}
|
||||
return (tab->type & H) ? 2 : 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Symbolic decode
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = pointer to values
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
return = status code
|
||||
*/
|
||||
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int i;
|
||||
int l = 1;
|
||||
int rdx = 16;
|
||||
t_opcode *tab;
|
||||
uint32 num;
|
||||
|
||||
if (sw & SWMASK ('D'))
|
||||
rdx = 10;
|
||||
else if (sw & SWMASK ('O'))
|
||||
rdx = 8;
|
||||
else if (sw & SWMASK ('H'))
|
||||
rdx = 16;
|
||||
if (sw & SWMASK ('M')) {
|
||||
sw &= ~ SWMASK('F'); /* Can't do F and M at same time */
|
||||
} else if (sw & SWMASK('F')) {
|
||||
l = 4;
|
||||
} else if (sw & SWMASK('W')) {
|
||||
l = 2;
|
||||
} else if (sw & SWMASK('B')) {
|
||||
l = 1;
|
||||
}
|
||||
|
||||
if (sw & SWMASK ('C')) {
|
||||
fputc('\'', of);
|
||||
for(i = 0; i < l; i++) {
|
||||
char ch = val[i] & 0xff;
|
||||
if (ch >= 0x20 && ch <= 0x7f)
|
||||
fprintf(of, "%c", ch);
|
||||
else
|
||||
fputc('_', of);
|
||||
}
|
||||
fputc('\'', of);
|
||||
} else if ((addr & 1) == 0 && sw & (SWMASK ('M')|SWMASK('N'))) {
|
||||
num = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
num |= (uint32)val[i] << ((3-i) * 8);
|
||||
l = fprint_inst(of, num, sw);
|
||||
} else {
|
||||
num = 0;
|
||||
for (i = 0; i < l && i < 4; i++)
|
||||
num |= (uint32)val[i] << ((l-i-1) * 8);
|
||||
fprint_val(of, num, rdx, l*8, PV_RZRO);
|
||||
}
|
||||
|
||||
return -(l-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Collect offset in radix.
|
||||
*/
|
||||
t_stat get_off (CONST char *cptr, CONST char **tptr, uint32 radix, uint32 *val, char *m)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = SCPE_OK;
|
||||
*m = 0;
|
||||
*val = (uint32)strtotv (cptr, tptr, radix);
|
||||
if (cptr == *tptr)
|
||||
r = SCPE_ARG;
|
||||
else {
|
||||
cptr = *tptr;
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ == '(') {
|
||||
*m = 1;
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
}
|
||||
*tptr = cptr;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Collect immediate in radix.
|
||||
*/
|
||||
t_stat get_imm (CONST char *cptr, CONST char **tptr, uint32 radix, uint32 *val)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = SCPE_OK;
|
||||
*val = (uint32)strtotv (cptr, tptr, radix);
|
||||
if ((cptr == *tptr) || (*val > 0xffff))
|
||||
r = SCPE_ARG;
|
||||
else {
|
||||
cptr = *tptr;
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
*tptr = cptr;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Symbolic input
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
uptr = pointer to unit
|
||||
*val = pointer to output values
|
||||
sw = switches
|
||||
Outputs:
|
||||
status = error status
|
||||
*/
|
||||
|
||||
t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
int l = 1;
|
||||
int rdx = 16;
|
||||
char mod = 0;
|
||||
t_opcode *tab;
|
||||
t_stat r;
|
||||
uint32 num;
|
||||
uint32 val;
|
||||
uint32 max[5] = { 0, 0xff, 0xffff, 0, 0xffffffff };
|
||||
CONST char *tptr;
|
||||
char gbuf[CBUFSIZE];
|
||||
|
||||
if (sw & SWMASK ('D'))
|
||||
rdx = 10;
|
||||
else if (sw & SWMASK ('O'))
|
||||
rdx = 8;
|
||||
else if (sw & SWMASK ('H'))
|
||||
rdx = 16;
|
||||
if (sw & SWMASK('F')) {
|
||||
l = 4;
|
||||
} else if (sw & SWMASK('W')) {
|
||||
l = 2;
|
||||
}
|
||||
|
||||
if (sw & SWMASK ('C')) {
|
||||
cptr = get_glyph_quoted(cptr, gbuf, 0); /* Get string */
|
||||
for(i = 0; gbuf[i] != 0; i++) {
|
||||
val[i] = gbuf[i];
|
||||
}
|
||||
return -(i - 1);
|
||||
}
|
||||
|
||||
if (sw & SWMASK ('N')) {
|
||||
cptr = get_glyph(cptr, gbuf, 0); /* Get opcode */
|
||||
l = strlen(gbuf);
|
||||
for (tab = optab; tab->name != NULL; tab++) {
|
||||
i = tab->type & 0xf;
|
||||
if (i == TYPE_A || i == TYPE_E) {
|
||||
if (sim_strncasecmp(tab->name, gbuf, l - 1) == 0)
|
||||
break;
|
||||
} else if (sim_strcasecmp(tab->name, gbuf) == 0)
|
||||
break;
|
||||
}
|
||||
if (tab->name == NULL)
|
||||
return SCPE_ARG;
|
||||
num = tab->opbase;
|
||||
switch(i) {
|
||||
case TYPE_A: /* c r,[*]o[,x] */
|
||||
case TYPE_E: /* c [*]o[,x] */
|
||||
switch(gbuf[l]) {
|
||||
case 'B': num |= 0x80000; break;
|
||||
case 'H': num |= 0x00001; break;
|
||||
case 'W': num |= 0x00000; break;
|
||||
case 'D': num |= 0x00002; break;
|
||||
default:
|
||||
return SCPE_ARG;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case TYPE_F: /* r,[*]o[,x] */
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (i != TYPE_E) {
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ',')
|
||||
return SCPE_ARG;
|
||||
num |= x << 23;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case TYPE_B: /* [*]o[,x] */
|
||||
if (*cptr == '*') {
|
||||
num |= 0x100000;
|
||||
cptr++;
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
}
|
||||
if (r = get_off (cptr, &tptr, 16, &val, &mod))
|
||||
return r;
|
||||
cptr = tptr;
|
||||
if (val > 0x7FFFF)
|
||||
return SCPE_ARG;
|
||||
num |= val;
|
||||
if (mod) {
|
||||
return SCPE_ARG;
|
||||
}
|
||||
if (*cptr++ == ",") {
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
num |= x << 20;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_C: /* r,v */
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ',')
|
||||
return SCPE_ARG;
|
||||
num |= x << 23;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (r = get_imm (cptr, &tptr, rd, &val))
|
||||
return r;
|
||||
num |= val;
|
||||
break;
|
||||
|
||||
case TYPE_D: /* r,r */
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ',')
|
||||
return SCPE_ARG;
|
||||
num |= x << 23;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ',')
|
||||
return SCPE_ARG;
|
||||
num |= x << 20;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
|
||||
case TYPE_G: /* r */
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ',')
|
||||
return SCPE_ARG;
|
||||
num |= x << 23;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
|
||||
case TYPE_H:
|
||||
break;
|
||||
|
||||
case TYPE_I:
|
||||
break;
|
||||
|
||||
case TYPE_K:
|
||||
break;
|
||||
|
||||
case TYPE_L:
|
||||
break;
|
||||
|
||||
case TYPE_M:
|
||||
break;
|
||||
|
||||
}
|
||||
return (tab->type & H) ? 2 : 4;
|
||||
}
|
||||
if (sw & SWMASK ('M')) {
|
||||
cptr = get_glyph(cptr, gbuf, 0); /* Get opcode */
|
||||
l = strlen(gbuf);
|
||||
for (tab = optab; tab->name != NULL; tab++) {
|
||||
i = tab->type & 0xf;
|
||||
if (i == TYPE_A || i == TYPE_E) {
|
||||
if (sim_strncasecmp(tab->name, gbuf, l - 1) == 0)
|
||||
break;
|
||||
} else if (sim_strcasecmp(tab->name, gbuf) == 0)
|
||||
break;
|
||||
}
|
||||
if (tab->name == NULL)
|
||||
return SCPE_ARG;
|
||||
num = tab->opbase << 16;
|
||||
switch(i) {
|
||||
case TYPE_A: /* c r,o[(b)][,x] */
|
||||
case TYPE_E: /* c o[(b)][,x] */
|
||||
switch(gbuf[l]) {
|
||||
case 'B': num |= 0x80000; break;
|
||||
case 'H': num |= 0x00001; break;
|
||||
case 'W': num |= 0x00000; break;
|
||||
case 'D': num |= 0x00002; break;
|
||||
default:
|
||||
return SCPE_ARG;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case TYPE_F: /* r,o[(b)],[,x] */
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (i != TYPE_E) {
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ',')
|
||||
return SCPE_ARG;
|
||||
num |= x << 23;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case TYPE_B: /* o[(b)],[,x] */
|
||||
if (r = get_off (cptr, &tptr, 16, &val, &mod))
|
||||
return r;
|
||||
cptr = tptr;
|
||||
if (val > 0xFFFF)
|
||||
return SCPE_ARG;
|
||||
num |= val;
|
||||
if (mod) {
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ')')
|
||||
return SCPE_ARG;
|
||||
num |= x << 16;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
}
|
||||
if (*cptr++ == ",") {
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
num |= x << 20;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_C: /* r,v */
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ',')
|
||||
return SCPE_ARG;
|
||||
num |= x << 23;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (r = get_imm (cptr, &tptr, rd, &val))
|
||||
return r;
|
||||
num |= val;
|
||||
break;
|
||||
|
||||
case TYPE_D: /* r,r */
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ',')
|
||||
return SCPE_ARG;
|
||||
num |= x << 23;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ',')
|
||||
return SCPE_ARG;
|
||||
num |= x << 20;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
|
||||
case TYPE_G: /* r */
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr >= '0' || *cptr <= '7') {
|
||||
x = *cptr++ - '0';
|
||||
while (sim_isspace (*cptr)) cptr++;
|
||||
if (*cptr++ != ',')
|
||||
return SCPE_ARG;
|
||||
num |= x << 23;
|
||||
} else
|
||||
return SCPE_ARG;
|
||||
break;
|
||||
|
||||
case TYPE_H:
|
||||
break;
|
||||
|
||||
case TYPE_I:
|
||||
break;
|
||||
|
||||
case TYPE_K:
|
||||
break;
|
||||
|
||||
case TYPE_L:
|
||||
break;
|
||||
|
||||
case TYPE_M:
|
||||
break;
|
||||
}
|
||||
return (tab->type & H) ? 2 : 4;
|
||||
}
|
||||
num = get_uint(cptr, rdx, max[l], &r);
|
||||
for (i = 0; i < l && i < 4; i++)
|
||||
val[i] = (num >> (i * 8)) & 0xff;
|
||||
return -(l-1);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user