1
0
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:
Richard Cornwell 2019-07-17 21:39:18 -04:00
parent ba534e8d1f
commit 5decc40fa5
4 changed files with 3627 additions and 0 deletions

733
SEL32/sel32_chan.c Normal file
View 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

File diff suppressed because it is too large Load Diff

259
SEL32/sel32_defs.h Normal file
View 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
View 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);
}