mirror of
https://github.com/rcornwell/sims.git
synced 2026-05-02 22:24:22 +00:00
IBM360: Updated to fix bugs uncovered under diagnostics.
This commit is contained in:
@@ -104,7 +104,7 @@ UNIT cdr_unit[] = {
|
||||
|
||||
MTAB cdr_mod[] = {
|
||||
{MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
&sim_card_set_fmt, &sim_card_show_fmt, NULL,
|
||||
&sim_card_set_fmt, &sim_card_show_fmt, NULL,
|
||||
"Set defualt format for reading cards in"},
|
||||
{MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr,
|
||||
&show_dev_addr, NULL, "Set device address"},
|
||||
|
||||
@@ -154,7 +154,7 @@ UNIT chan_unit[] = {
|
||||
DEVICE chan_dev = {
|
||||
"CH", chan_unit, NULL, chan_mod,
|
||||
MAX_CHAN, 8, 15, 1, 8, 8,
|
||||
NULL, NULL, &chan_reset, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL /*&chan_reset*/, NULL, NULL, NULL,
|
||||
NULL, DEV_DEBUG, 0, dev_debug,
|
||||
NULL, NULL, &chan_help, NULL, NULL, &chan_description
|
||||
};
|
||||
@@ -490,7 +490,7 @@ start_cmd:
|
||||
if (chan->chan_status & STATUS_CEND) {
|
||||
chan->ccw_cmd = 0;
|
||||
chan->ccw_flags |= FLAG_SLI; /* Force SLI for immediate command */
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end(%x load) %x %04x end\n",
|
||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end(%x load) %x %04x end\n",
|
||||
chan->daddr, chan->chan_status, chan->ccw_flags);
|
||||
if (chan->chan_status & (STATUS_DEND)) {
|
||||
irq_pend = 1;
|
||||
@@ -856,10 +856,11 @@ startio(uint16 addr) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (dev_status[addr] == SNS_DEVEND ||
|
||||
dev_status[addr] == (SNS_DEVEND|SNS_CHNEND))
|
||||
dev_status[addr] = 0;
|
||||
/* Check for any pending status for this device */
|
||||
if (dev_status[addr] != 0) {
|
||||
if (dev_status[addr] & SNS_DEVEND)
|
||||
dev_status[addr] |= SNS_BSY;
|
||||
M[0x44 >> 2] = (((uint32)dev_status[addr]) << 24);
|
||||
M[0x40 >> 2] = 0;
|
||||
key[0] |= 0x6;
|
||||
@@ -926,6 +927,18 @@ startio(uint16 addr) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If immediate command and not command chaining */
|
||||
if ((chan->chan_status & (STATUS_CEND)) != 0
|
||||
&& (chan->ccw_flags & FLAG_CC) == 0) {
|
||||
M[0x40 >> 2] = 0;
|
||||
M[0x44 >> 2] = ((uint32)chan->chan_status<<16);
|
||||
key[0] |= 0x6;
|
||||
chan->chan_status = 0;
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %03x %08x\n",
|
||||
addr, M[0x44 >> 2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1167,12 +1180,6 @@ int testchan(uint16 channel) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* If channel has pending status, return 1 */
|
||||
if (chan->chan_status != 0) {
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x cc=1, error\n", channel);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Otherwise return 0. */
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x cc=0, ok\n", channel);
|
||||
return 0;
|
||||
@@ -1192,7 +1199,6 @@ t_stat chan_boot(uint16 addr, DEVICE *dptyr) {
|
||||
|
||||
for (i = 0; i < (MAX_CHAN * 256); i++)
|
||||
dev_status[i] = 0;
|
||||
chan_set_devs();
|
||||
dev = find_device(addr);
|
||||
chan = find_subchan(addr);
|
||||
if (dev == NULL || chan == NULL) {
|
||||
@@ -1307,8 +1313,7 @@ scan_chan(uint16 mask, int irq_en) {
|
||||
/* Disconnect from device */
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Scan(%x %x %x %x %x) end\n", i,
|
||||
chan->daddr, chan->chan_status, imask, mask);
|
||||
if (//(chan->chan_status & STATUS_CEND) != 0 &&
|
||||
((imask & mask) != 0 || loading != 0)) {
|
||||
if (((imask & mask) != 0 || loading != 0)) {
|
||||
pend = chan->daddr;
|
||||
break;
|
||||
}
|
||||
@@ -1398,7 +1403,7 @@ chan_reset(DEVICE * dptr)
|
||||
/*
|
||||
* Scan all devices and create the device mapping.
|
||||
*/
|
||||
t_stat
|
||||
void
|
||||
chan_set_devs()
|
||||
{
|
||||
unsigned i, j;
|
||||
@@ -1423,19 +1428,20 @@ chan_set_devs()
|
||||
n = UNIT_G_SCHAN(uptr->flags)+1;
|
||||
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX)
|
||||
n = 32;
|
||||
/* If no device array, create one */
|
||||
if (uptr->up8 == NULL)
|
||||
uptr->up8 = calloc(256, sizeof(struct _dev));
|
||||
if (uptr->up7 == NULL || (uint32)uptr->schans != n) {
|
||||
if (uptr->up7 != NULL)
|
||||
free(uptr->up7);
|
||||
uptr->up7 = calloc(n, sizeof(struct _chanctl));
|
||||
for (j = 0; j < n; j++) {
|
||||
struct _chanctl *chan = &(chan_ctl[j]);
|
||||
chan->daddr = NO_DEV;
|
||||
}
|
||||
/* Create device table */
|
||||
if (uptr->up8 != NULL)
|
||||
free(uptr->up8);
|
||||
uptr->up8 = calloc(256, sizeof(struct _dev));
|
||||
/* Create subchannel controls */
|
||||
if (uptr->up7 != NULL)
|
||||
free(uptr->up7);
|
||||
uptr->up7 = calloc(n, sizeof(struct _chanctl));
|
||||
for (j = 0; j < n; j++) {
|
||||
struct _chanctl *chan = &(chan_ctl[j]);
|
||||
chan->daddr = NO_DEV;
|
||||
}
|
||||
uptr->schans = n;
|
||||
/* Initialize channel device address table to empty */
|
||||
for (j = 0; j < 256; j++) {
|
||||
struct _dev *dev = &(dev_tab[j]);
|
||||
dev->dibp = NULL;
|
||||
@@ -1473,7 +1479,7 @@ chan_set_devs()
|
||||
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sets the number of subchannels for a channel */
|
||||
|
||||
@@ -129,8 +129,8 @@ uint8 clk_irq; /* Clock compare IRQ */
|
||||
uint8 tod_irq; /* TOD compare IRQ */
|
||||
int clk_state;
|
||||
int timer_tics; /* Interval Timer is ever 3 tics */
|
||||
uint32 idle_stop_msec = 0; // msec allowed after before stop cpu if idle
|
||||
uint32 idle_stop_tm0; // sim_os_msec when start counting for idle time
|
||||
uint32 idle_stop_msec = 0; /* msec allowed after before stop cpu if idle */
|
||||
uint32 idle_stop_tm0; /* sim_os_msec when start counting for idle time */
|
||||
|
||||
|
||||
#define CLOCK_UNSET 0 /* Clock not set */
|
||||
@@ -194,6 +194,7 @@ uint32 idle_stop_tm0; // sim_os_msec when start counting for idle t
|
||||
#define IRC_PER 0x0080 /* Per event */
|
||||
|
||||
#define AMASK 0x00ffffff /* Mask address bits */
|
||||
#define WMASK 0x00fffffc /* Mask address to word boundry */
|
||||
#define MSIGN 0x80000000 /* Minus sign */
|
||||
#define MMASK 0x00ffffff /* Mantissa mask */
|
||||
#define EMASK 0x7f000000 /* Exponent mask */
|
||||
@@ -214,6 +215,8 @@ uint32 idle_stop_tm0; // sim_os_msec when start counting for idle t
|
||||
#define NMASKL 0x00f0000000000000LL
|
||||
#define UMASKL 0x0ffffffffffffff0LL
|
||||
#define SNMASKL 0x0f00000000000000LL
|
||||
#define DMASKL 0x0080000000000000LL
|
||||
#define OMASKL 0xffffffff80000000LL
|
||||
#define LDDBL(r,x) x = (((t_uint64)regs[r]) << 32) | ((t_uint64)regs[r|1]); \
|
||||
if (hst_lnt) { hst[hst_p].src1 = ((x) >> 32); \
|
||||
hst[hst_p].src2 = (x) & FMASK; }
|
||||
@@ -311,7 +314,7 @@ int32 rtc_tps = 300;
|
||||
UNIT cpu_unit[] = { {UDATA (&rtc_srv, UNIT_IDLE|UNIT_BINK|UNIT_FIX, MAXMEMSIZE)} };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
{ HRDATA (PC, PC, 24) },
|
||||
{ HRDATA (PC, PC, 32) },
|
||||
{ HRDATA (CC, cc, 2) },
|
||||
{ HRDATA (PMASK, pmsk, 4) },
|
||||
{ HRDATA (FLAGS, flags, 4) },
|
||||
@@ -358,10 +361,17 @@ MTAB cpu_mod[] = {
|
||||
{ MTAB_VDV, MEMAMOUNT(128), NULL, "2M", &cpu_set_size },
|
||||
{ MTAB_VDV, MEMAMOUNT(256), NULL, "4M", &cpu_set_size },
|
||||
{ MTAB_VDV, MEMAMOUNT(512), NULL, "8M", &cpu_set_size },
|
||||
{ FEAT_370, FEAT_370, "IBM370", "IBM370", NULL, NULL, NULL, "Sets CPU to be a IBM370"},
|
||||
{ FEAT_370, 0, "IBM360", "IBM360", NULL, NULL, NULL, "Sets CPU to be a IBM360"},
|
||||
{ MTAB_VDV, MEMAMOUNT(768), NULL, "12M", &cpu_set_size },
|
||||
{ MTAB_VDV, MEMAMOUNT(1024), NULL, "16M", &cpu_set_size },
|
||||
{ FEAT_370, FEAT_370, "IBM370", "IBM370", NULL, NULL, NULL,
|
||||
"Sets CPU to be a IBM370"},
|
||||
{ FEAT_370, 0, "IBM360", "IBM360", NULL, NULL, NULL,
|
||||
"Sets CPU to be a IBM360"},
|
||||
{ FEAT_PROT, 0, NULL, "NOPROT", NULL, NULL, NULL, "No Storage protection"},
|
||||
{ FEAT_PROT, FEAT_PROT, "PROT", "PROT", NULL, NULL, NULL, "Storage protection"},
|
||||
{ FEAT_FPROT, 0, NULL, "NOFPROT", NULL, NULL, NULL, "No Fetch protection"},
|
||||
{ FEAT_FPROT|FEAT_PROT, FEAT_FPROT|FEAT_PROT, "FPROT", "FPROT", NULL, NULL,
|
||||
NULL, "Fetch protection"},
|
||||
{ FEAT_UNIV, FEAT_UNIV, "UNIV", "UNIV", NULL, NULL, NULL, "Universal instruction"},
|
||||
{ FEAT_UNIV, 0, NULL, "NOUNIV", NULL, NULL, NULL, "Basic instructions"},
|
||||
{ FEAT_UNIV, FEAT_FLOAT, "FLOAT", "FLOAT", NULL, NULL, NULL,
|
||||
@@ -674,16 +684,18 @@ ReadFull(uint32 addr, uint32 *data)
|
||||
|
||||
/* Check storage key */
|
||||
if (st_key != 0) {
|
||||
uint8 k;
|
||||
|
||||
if ((cpu_unit[0].flags & FEAT_PROT) == 0) {
|
||||
if ((cpu_unit[0].flags & (FEAT_PROT|FEAT_DAT)) == 0) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
}
|
||||
k = key[pa >> 11];
|
||||
if ((k & 0x8) != 0 && (k & 0xf0) != st_key) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
|
||||
if ((cpu_unit[0].flags & (FEAT_FPROT|FEAT_DAT)) != 0) {
|
||||
uint8 k = key[pa >> 11];
|
||||
|
||||
if ((k & 0x8) != 0 && (k & 0xf0) != st_key) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -710,10 +722,12 @@ ReadFull(uint32 addr, uint32 *data)
|
||||
return 1;
|
||||
/* Check access protection */
|
||||
if (st_key != 0) {
|
||||
k = key[temp >> 11];
|
||||
if ((k & 0x8) != 0 && (k & 0xf0) != st_key) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
if ((cpu_unit[0].flags & (FEAT_FPROT|FEAT_DAT)) != 0) {
|
||||
uint8 k = key[temp >> 11];
|
||||
if ((k & 0x8) != 0 && (k & 0xf0) != st_key) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -730,7 +744,7 @@ ReadFull(uint32 addr, uint32 *data)
|
||||
/* Update access flag */
|
||||
key[pa >> 11] |= 0x4;
|
||||
|
||||
/* sim_debug(DEBUG_DATA, &cpu_dev, "RD A=%08x %08x\n", addr, *data); */
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "RD A=%08x %08x\n", addr, *data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -830,7 +844,7 @@ WriteFull(uint32 addr, uint32 data)
|
||||
if (st_key != 0) {
|
||||
uint8 k;
|
||||
|
||||
if ((cpu_unit[0].flags & FEAT_PROT) == 0) {
|
||||
if ((cpu_unit[0].flags & (FEAT_PROT|FEAT_DAT)) == 0) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
}
|
||||
@@ -903,7 +917,7 @@ WriteFull(uint32 addr, uint32 data)
|
||||
M[pa2] |= 0xffffff00 & (data << 8);
|
||||
break;
|
||||
}
|
||||
/* sim_debug(DEBUG_DATA, &cpu_dev, "WR A=%08x %08x\n", addr, data); */
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "WR A=%08x %08x\n", addr, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -940,7 +954,7 @@ WriteByte(uint32 addr, uint32 data)
|
||||
if (st_key != 0) {
|
||||
uint8 k;
|
||||
|
||||
if ((cpu_unit[0].flags & FEAT_PROT) == 0) {
|
||||
if ((cpu_unit[0].flags & (FEAT_PROT|FEAT_DAT)) == 0) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
}
|
||||
@@ -959,7 +973,7 @@ WriteByte(uint32 addr, uint32 data)
|
||||
pa >>= 2;
|
||||
mask = 0xff;
|
||||
data &= mask;
|
||||
/* sim_debug(DEBUG_DATA, &cpu_dev, "WR A=%08x %02x\n", addr, data); */
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "WR A=%08x %02x\n", addr, data);
|
||||
data <<= offset;
|
||||
mask <<= offset;
|
||||
M[pa] &= ~mask;
|
||||
@@ -1006,17 +1020,17 @@ WriteHalf(uint32 addr, uint32 data)
|
||||
|
||||
/* Check storage key */
|
||||
if (st_key != 0) {
|
||||
uint8 k;
|
||||
uint8 k;
|
||||
|
||||
if ((cpu_unit[0].flags & FEAT_PROT) == 0) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
}
|
||||
k = key[pa >> 11];
|
||||
if ((k & 0xf0) != st_key) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
}
|
||||
if ((cpu_unit[0].flags & (FEAT_PROT|FEAT_DAT)) == 0) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
}
|
||||
k = key[pa >> 11];
|
||||
if ((k & 0xf0) != st_key) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset == 3) {
|
||||
@@ -1070,7 +1084,7 @@ WriteHalf(uint32 addr, uint32 data)
|
||||
|
||||
mask = 0xffff;
|
||||
data &= mask;
|
||||
/* sim_debug(DEBUG_DATA, &cpu_dev, "WR A=%08x %04x\n", addr, data); */
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "WR A=%08x %04x\n", addr, data);
|
||||
switch (offset) {
|
||||
case 0:
|
||||
M[pa] &= ~(mask << 16);
|
||||
@@ -1115,7 +1129,6 @@ sim_instr(void)
|
||||
t_uint64 src2L;
|
||||
t_uint64 destL; /* 64 bit destination */
|
||||
t_uint64 dest2L; /* Upper 64 bit for product */
|
||||
|
||||
/* Initialize DAT translation values */
|
||||
if (Q370) {
|
||||
switch((cregs[0] >> 22) & 03) {
|
||||
@@ -1233,6 +1246,7 @@ wait_loop:
|
||||
/* CPU IDLE */
|
||||
if (flags & WAIT && irq_en == 0 && ext_en == 0)
|
||||
return STOP_HALT;
|
||||
|
||||
if (idle_stop_msec) {
|
||||
/* check idle time */
|
||||
if (idle_stop_tm0 == 0) {
|
||||
@@ -1543,7 +1557,7 @@ opr:
|
||||
|
||||
case OP_SSK:
|
||||
dest = src1;
|
||||
if ((cpu_unit[0].flags & FEAT_PROT) == 0) {
|
||||
if ((cpu_unit[0].flags & (FEAT_DAT|FEAT_PROT)) == 0) {
|
||||
storepsw(OPPSW, IRC_OPR);
|
||||
goto supress;
|
||||
} else if (flags & PROBLEM) {
|
||||
@@ -1561,14 +1575,16 @@ opr:
|
||||
} else {
|
||||
if ((cpu_unit[0].flags & FEAT_DAT) != 0)
|
||||
key[addr1 >> 11] = src1 & 0xfe;
|
||||
else
|
||||
else if ((cpu_unit[0].flags & FEAT_FPROT) != 0)
|
||||
key[addr1 >> 11] = src1 & 0xf8;
|
||||
else
|
||||
key[addr1 >> 11] = src1 & 0xf0;
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_ISK:
|
||||
dest = src1;
|
||||
if ((cpu_unit[0].flags & FEAT_PROT) == 0) {
|
||||
if ((cpu_unit[0].flags & (FEAT_DAT|FEAT_PROT)) == 0) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
} if (flags & PROBLEM) {
|
||||
/* Try to do quick ISK */
|
||||
@@ -1583,8 +1599,12 @@ opr:
|
||||
dest &= 0xffffff00;
|
||||
if (ec_mode)
|
||||
dest |= key[addr1 >> 11] & 0xfe;
|
||||
else
|
||||
dest |= key[addr1 >> 11] & 0xf8;
|
||||
else {
|
||||
if ((cpu_unit[0].flags & FEAT_FPROT) != 0)
|
||||
dest |= key[addr1 >> 11] & 0xf8;
|
||||
else
|
||||
dest |= key[addr1 >> 11] & 0xf0;
|
||||
}
|
||||
regs[reg1] = dest;
|
||||
per_mod |= 1 << reg1;
|
||||
}
|
||||
@@ -1840,26 +1860,46 @@ set_cc3:
|
||||
goto supress;
|
||||
}
|
||||
fill = 0;
|
||||
LDDBL(reg1, src1L);
|
||||
if (src1L & MSIGNL) {
|
||||
src1 = regs[reg1];
|
||||
src1h = regs[reg1|1];
|
||||
if (src1 & MSIGN) {
|
||||
fill = 3;
|
||||
src1L = NEG(src1L);
|
||||
src1h ^= FMASK;
|
||||
src1 ^= FMASK;
|
||||
if (src1h == FMASK)
|
||||
src1 ++;
|
||||
src1h++;
|
||||
}
|
||||
if (src2 & MSIGN) {
|
||||
fill ^= 1;
|
||||
src2 = NEG(src2);
|
||||
}
|
||||
src2L = src1L % (t_uint64)src2;
|
||||
src1L = src1L / (t_uint64)src2;
|
||||
dest = 0;
|
||||
for (reg = 0; reg < 32; reg++) {
|
||||
/* Shift left by one */
|
||||
src1 <<= 1;
|
||||
if (src1h & MSIGN)
|
||||
src1 |= 1;
|
||||
src1h <<= 1;
|
||||
/* Subtract remainder from divisor */
|
||||
desth = src1 - src2;
|
||||
|
||||
/* Shift quotent left one bit */
|
||||
dest <<= 1;
|
||||
|
||||
/* If remainder larger then divisor replace */
|
||||
if ((desth & MSIGN) == 0) {
|
||||
src1 = desth;
|
||||
dest |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for overflow */
|
||||
if ((src1L & 0xFFFFFFFF80000000LL) != 0) {
|
||||
if ((dest & MSIGN) != 0 && dest != MSIGN) {
|
||||
storepsw(OPPSW, IRC_FIXDIV);
|
||||
goto supress;
|
||||
}
|
||||
|
||||
src1 = (uint32)(src2L & FMASK);
|
||||
dest = (uint32)(src1L & FMASK);
|
||||
if (fill & 1)
|
||||
dest = NEG(dest);
|
||||
if (fill & 2)
|
||||
@@ -1985,7 +2025,11 @@ char_save:
|
||||
dest = regs[reg1];
|
||||
if (hst_lnt)
|
||||
hst[hst_p].src1 = dest;
|
||||
dest = ((uint32)dest) >> (addr1 & 0x3f);
|
||||
addr1 &= 0x3f;
|
||||
if (addr1 > 31)
|
||||
dest = 0;
|
||||
else
|
||||
dest = dest >> (addr1);
|
||||
regs[reg1] = dest;
|
||||
per_mod |= 1 << reg1;
|
||||
break;
|
||||
@@ -1994,7 +2038,11 @@ char_save:
|
||||
dest = regs[reg1];
|
||||
if (hst_lnt)
|
||||
hst[hst_p].src1 = dest;
|
||||
dest = ((uint32)dest) << (addr1 & 0x3f);
|
||||
addr1 &= 0x3f;
|
||||
if (addr1 > 31)
|
||||
dest = 0;
|
||||
else
|
||||
dest = dest << addr1;
|
||||
regs[reg1] = dest;
|
||||
per_mod |= 1 << reg1;
|
||||
break;
|
||||
@@ -2003,7 +2051,12 @@ char_save:
|
||||
dest = regs[reg1];
|
||||
if (hst_lnt)
|
||||
hst[hst_p].src1 = dest;
|
||||
dest = (int32)dest >> (addr1 & 0x3f);
|
||||
addr1 &= 0x3f;
|
||||
if (addr1 > 31) {
|
||||
dest = ((dest & MSIGN) != 0) ? FMASK : 0;
|
||||
} else {
|
||||
dest = (int32)dest >> (addr1 & 0x3f);
|
||||
}
|
||||
goto set_cc;
|
||||
|
||||
case OP_SLA:
|
||||
@@ -2387,11 +2440,10 @@ save_dbl:
|
||||
if (TransAddr(addr1, &src1) ||
|
||||
TransAddr(addr1+reg, &src1) ||
|
||||
TransAddr(addr2, &src1) ||
|
||||
TransAddr(addr2+reg, &src1)) {
|
||||
TransAddr(addr2-reg, &src1)) {
|
||||
goto supress;
|
||||
}
|
||||
}
|
||||
addr2 += reg;
|
||||
do {
|
||||
if (ReadByte(addr2, &src1))
|
||||
goto supress;
|
||||
@@ -2655,6 +2707,11 @@ save_dbl:
|
||||
|
||||
/* Convert packed decimal to binary */
|
||||
case OP_CVB:
|
||||
/* If not on double word boundry and store feature not set */
|
||||
if ((addr1 & 07) != 0 && (cpu_unit[0].flags & FEAT_STOR) == 0) {
|
||||
storepsw(OPPSW, IRC_SPEC);
|
||||
goto supress;
|
||||
}
|
||||
if (ReadFull(addr1, &src1))
|
||||
goto supress;
|
||||
if (ReadFull(addr1+4, &src1h))
|
||||
@@ -2664,7 +2721,7 @@ save_dbl:
|
||||
storepsw(OPPSW, IRC_DATA);
|
||||
goto supress;
|
||||
}
|
||||
dest = 0;
|
||||
destL = 0;
|
||||
/* Convert upper first */
|
||||
for(temp = 28; temp >= 0; temp-=4) {
|
||||
int d = (src1 >> temp) & 0xf;
|
||||
@@ -2672,7 +2729,7 @@ save_dbl:
|
||||
storepsw(OPPSW, IRC_DATA);
|
||||
goto supress;
|
||||
}
|
||||
dest = (dest * 10) + d;
|
||||
destL = (destL * 10) + d;
|
||||
}
|
||||
/* Convert lower */
|
||||
for(temp = 28; temp > 0; temp-=4) {
|
||||
@@ -2681,22 +2738,26 @@ save_dbl:
|
||||
storepsw(OPPSW, IRC_DATA);
|
||||
goto supress;
|
||||
}
|
||||
dest = (dest * 10) + d;
|
||||
destL = (destL * 10) + d;
|
||||
}
|
||||
/* Check if too big */
|
||||
if (dest & MSIGN) {
|
||||
if ((destL & OMASKL) != 0 && destL != (uint64_t)MSIGN) {
|
||||
storepsw(OPPSW, IRC_FIXDIV);
|
||||
regs[reg1] = dest;
|
||||
goto supress;
|
||||
}
|
||||
|
||||
/* Twos compliment if needed */
|
||||
if (fill == 0xB || fill == 0xD)
|
||||
dest = NEG(dest);
|
||||
regs[reg1] = dest;
|
||||
destL = ~destL + 1;
|
||||
regs[reg1] = (uint32)(destL & FMASK);
|
||||
break;
|
||||
|
||||
/* Convert binary to packed decimal */
|
||||
case OP_CVD:
|
||||
/* If not on double word boundry and store feature not set */
|
||||
if ((addr1 & 07) != 0 && (cpu_unit[0].flags & FEAT_STOR) == 0) {
|
||||
storepsw(OPPSW, IRC_SPEC);
|
||||
goto supress;
|
||||
}
|
||||
dest = regs[reg1];
|
||||
src1 = 0;
|
||||
src1h = 0;
|
||||
@@ -2730,14 +2791,19 @@ save_dbl:
|
||||
/* Edit string, mark saves address of significant digit */
|
||||
case OP_ED:
|
||||
case OP_EDMK:
|
||||
if (ReadByte(addr1, &src1))
|
||||
if (ReadFull(addr1 & WMASK, &src1h))
|
||||
goto supress;
|
||||
zone = (flags & ASCII) ? 0x50: 0xf0;
|
||||
src1 = (src1h >> (8 * (3 - (addr1 & 0x3)))) & 0xff;
|
||||
fill = digit = (uint8)src1;
|
||||
temp = 0; /* Hold zero flag */
|
||||
e2 = 0; /* Significance indicator */
|
||||
e1 = 1; /* Need another source char */
|
||||
cc = 0;
|
||||
if (ReadFull(addr2 & WMASK, &src2h)) {
|
||||
goto supress;
|
||||
}
|
||||
src2 = (src2h >> (8 * (3 - (addr2 & 0x3)))) & 0xff;
|
||||
for (;;) {
|
||||
uint8 t;
|
||||
switch(digit) {
|
||||
@@ -2745,11 +2811,15 @@ save_dbl:
|
||||
case 0x20: /* Digit selector */
|
||||
/* If we have not run out of source, grab next pair */
|
||||
if (e1) {
|
||||
if (ReadByte(addr2, &src2))
|
||||
goto supress;
|
||||
if ((addr2 & 0x3) == 0) {
|
||||
if (ReadFull(addr2, &src2h)) {
|
||||
goto supress;
|
||||
}
|
||||
}
|
||||
src2 = (src2h >> (8 * (3 - (addr2 & 0x3)))) & 0xff;
|
||||
addr2++;
|
||||
/* Check if valid */
|
||||
if (src2 > 0xa0) {
|
||||
if (src2 >= 0xa0) {
|
||||
storepsw(OPPSW, IRC_DATA);
|
||||
goto supress;
|
||||
}
|
||||
@@ -2798,14 +2868,19 @@ save_dbl:
|
||||
if (!e2)
|
||||
digit = fill;
|
||||
}
|
||||
if (WriteByte(addr1, digit))
|
||||
if (WriteByte(addr1, digit)) {
|
||||
goto supress;
|
||||
}
|
||||
addr1++;
|
||||
if (reg == 0)
|
||||
break;
|
||||
reg --;
|
||||
if (ReadByte(addr1, &src1))
|
||||
goto supress;
|
||||
if ((addr1 & 0x3) == 0) {
|
||||
if (ReadFull(addr1, &src1h)) {
|
||||
goto supress;
|
||||
}
|
||||
}
|
||||
src1 = (src1h >> (8 * (3 - (addr1 & 0x3)))) & 0xff;
|
||||
digit = src1;
|
||||
}
|
||||
cc = temp;
|
||||
@@ -2968,6 +3043,7 @@ save_dbl:
|
||||
case OP_370:
|
||||
if (Q370) {
|
||||
if (reg > 0x13) {
|
||||
printf("Invalid 0xb2%02x %08x\n\r", reg, addr1);
|
||||
storepsw(OPPSW, IRC_OPR);
|
||||
goto supress;
|
||||
}
|
||||
@@ -3097,14 +3173,14 @@ save_dbl:
|
||||
goto supress;
|
||||
break;
|
||||
case 0xa: /* SPKA */
|
||||
if ((cpu_unit[0].flags & FEAT_PROT) == 0) {
|
||||
if ((cpu_unit[0].flags & (FEAT_DAT|FEAT_PROT)) == 0) {
|
||||
storepsw(OPPSW, IRC_OPR);
|
||||
goto supress;
|
||||
}
|
||||
st_key = 0xf0 & addr1;
|
||||
break;
|
||||
case 0xb: /* IPK */
|
||||
if ((cpu_unit[0].flags & FEAT_PROT) == 0) {
|
||||
if ((cpu_unit[0].flags & (FEAT_DAT|FEAT_PROT)) == 0) {
|
||||
storepsw(OPPSW, IRC_OPR);
|
||||
goto supress;
|
||||
}
|
||||
@@ -3340,7 +3416,6 @@ save_dbl:
|
||||
~page_mask) & AMASK) >> page_shift;
|
||||
intval_en = ((dest & 0x400) != 0);
|
||||
tod_en = ((dest & 0x800) != 0);
|
||||
// temp = 1;
|
||||
break;
|
||||
case 0x1: /* Segment table address and length */
|
||||
temp = 1;
|
||||
@@ -3589,6 +3664,9 @@ save_dbl:
|
||||
case OP_HER:
|
||||
/* Split number apart */
|
||||
e1 = (src2L & EMASKL) >> 56;
|
||||
if ((op & 0x10) != 0) {
|
||||
src2L &= HMASKL;
|
||||
}
|
||||
destL = src2L & MSIGNL;
|
||||
/* Create guard digit */
|
||||
src2L = (src2L & MMASKL) << 4;
|
||||
@@ -3605,7 +3683,8 @@ save_dbl:
|
||||
if (pmsk & EXPUND) {
|
||||
storepsw(OPPSW, IRC_EXPUND);
|
||||
} else {
|
||||
destL = e1 = 0;
|
||||
destL = src2L = 0;
|
||||
e1 = 0;
|
||||
}
|
||||
}
|
||||
/* Remove guard digit */
|
||||
@@ -3613,8 +3692,10 @@ save_dbl:
|
||||
}
|
||||
|
||||
/* Check for zero */
|
||||
if (src2L == 0)
|
||||
destL = e1 = 0;
|
||||
if (src2L == 0) {
|
||||
destL = 0;
|
||||
e1 = 0;
|
||||
}
|
||||
|
||||
/* Restore result */
|
||||
src2L |= (((t_uint64)e1 << 56) & EMASKL) | destL;
|
||||
@@ -3653,7 +3734,7 @@ save_dbl:
|
||||
} else {
|
||||
fpregs[reg1] = (src2L & HMASKL) | (fpregs[reg1] & LMASKL);
|
||||
}
|
||||
if (src1L != 0)
|
||||
if ((src1L & MMASKL) != 0)
|
||||
cc = (src2L & MSIGNL) ? 1 : 2;
|
||||
break;
|
||||
|
||||
@@ -3745,101 +3826,112 @@ save_dbl:
|
||||
case OP_AER: /* 3A */
|
||||
case OP_AUR: /* 3E */
|
||||
/* Extract numbers and adjust */
|
||||
e1 = (src1L & EMASKL) >> 56;
|
||||
e2 = (src2L & EMASKL) >> 56;
|
||||
fill = 0;
|
||||
if (src1L & MSIGNL)
|
||||
fill |= 2;
|
||||
if (src2L & MSIGNL)
|
||||
fill |= 1;
|
||||
/* Make 32 bit and create guard digit */
|
||||
src1 = (uint32)((src1L >> 28) & (MMASK << 4));
|
||||
src2 = (uint32)((src2L >> 28) & (MMASK << 4));
|
||||
temp = e1 - e2;
|
||||
if (temp > 0) {
|
||||
if (temp > 8) {
|
||||
src2 = 0;
|
||||
} else {
|
||||
/* Shift src2 right if src1 larger expo - expo */
|
||||
src2 >>= 4 * temp;
|
||||
}
|
||||
} else if (temp < 0) {
|
||||
if (temp < -8) {
|
||||
src1 = 0;
|
||||
} else {
|
||||
/* Shift src1 right if src2 larger expo - expo */
|
||||
src1 >>= 4 * -temp;
|
||||
}
|
||||
e1 = e2;
|
||||
}
|
||||
|
||||
/* Exponents should be equal now. */
|
||||
|
||||
/* Add results */
|
||||
if (fill == 2 || fill == 1) {
|
||||
/* Different signs do subtract */
|
||||
src2 ^= XMASK;
|
||||
dest = src1 + src2 + 1;
|
||||
if (dest & CMASK)
|
||||
dest &= XMASK;
|
||||
else {
|
||||
fill ^= 2;
|
||||
dest ^= XMASK;
|
||||
dest++;
|
||||
}
|
||||
e1 = (src1L & EMASKL) >> 56;
|
||||
e2 = (src2L & EMASKL) >> 56;
|
||||
fill = 0;
|
||||
if (src1L & MSIGNL)
|
||||
fill |= 2;
|
||||
if (src2L & MSIGNL)
|
||||
fill |= 1;
|
||||
/* Make 32 bit and create guard digit */
|
||||
src1 = (uint32)((src1L >> 28) & (MMASK << 4));
|
||||
src2 = (uint32)((src2L >> 28) & (MMASK << 4));
|
||||
temp = e1 - e2;
|
||||
if (temp > 0) {
|
||||
if (temp > 7) {
|
||||
src2 = 0;
|
||||
} else {
|
||||
dest = src1 + src2;
|
||||
/* Shift src2 right if src1 larger expo - expo */
|
||||
src2 >>= 4 * temp;
|
||||
}
|
||||
/* If overflow, shift right 4 bits */
|
||||
if (dest & CMASK) {
|
||||
dest >>= 4;
|
||||
e1 ++;
|
||||
if (e1 >= 128) {
|
||||
storepsw(OPPSW, IRC_EXPOVR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set condition codes */
|
||||
cc = 0;
|
||||
if ((op & 0xE) != 0xE) {
|
||||
if (dest != 0)
|
||||
cc = (fill & 2) ? 1 : 2;
|
||||
else
|
||||
dest = e1 = fill = 0;
|
||||
} else if (temp < 0) {
|
||||
temp = -temp;
|
||||
if (temp > 7) {
|
||||
src1 = 0;
|
||||
} else {
|
||||
if ((dest & 0xffffff0) != 0)
|
||||
cc = (fill & 2) ? 1 : 2;
|
||||
else
|
||||
dest = e1 = fill = 0;
|
||||
/* Shift src1 right if src2 larger expo - expo */
|
||||
src1 >>= 4 * temp;
|
||||
}
|
||||
e1 = e2;
|
||||
}
|
||||
|
||||
/* Check signifigance exception */
|
||||
if (cc == 0 && pmsk & SIGMSK) {
|
||||
storepsw(OPPSW, IRC_SIGNIF);
|
||||
goto fpstore1;
|
||||
/* Exponents should be equal now. */
|
||||
|
||||
/* Add results */
|
||||
if (fill == 2 || fill == 1) {
|
||||
/* Different signs do subtract */
|
||||
src2 ^= XMASK;
|
||||
dest = src1 + src2 + 1;
|
||||
if (dest & CMASK)
|
||||
dest &= XMASK;
|
||||
else {
|
||||
fill ^= 2;
|
||||
dest ^= XMASK;
|
||||
dest++;
|
||||
}
|
||||
} else {
|
||||
dest = src1 + src2;
|
||||
}
|
||||
|
||||
/* Check if we are normalized addition */
|
||||
if ((op & 0xE) != 0xE) {
|
||||
if (cc != 0) { /* Only if non-zero result */
|
||||
while ((dest & SNMASK) == 0) {
|
||||
dest <<= 4;
|
||||
e1 --;
|
||||
}
|
||||
/* Check if underflow */
|
||||
if (e1 < 0) {
|
||||
if (pmsk & EXPUND) {
|
||||
storepsw(OPPSW, IRC_EXPUND);
|
||||
} else {
|
||||
dest = 0;
|
||||
fill = e1 = 0;
|
||||
}
|
||||
/* If overflow, shift right 4 bits */
|
||||
if (dest & CMASK) {
|
||||
dest >>= 4;
|
||||
e1 ++;
|
||||
if (e1 >= 128) {
|
||||
storepsw(OPPSW, IRC_EXPOVR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set condition codes */
|
||||
cc = 0;
|
||||
if ((op & 0xE) != 0xE) {
|
||||
if (dest != 0) {
|
||||
cc = (fill & 2) ? 1 : 2;
|
||||
} else {
|
||||
if ((pmsk & SIGMSK) == 0) {
|
||||
e1 = 0;
|
||||
}
|
||||
fill = 0;
|
||||
}
|
||||
} else {
|
||||
if ((dest & 0xffffff0) != 0) {
|
||||
cc = (fill & 2) ? 1 : 2;
|
||||
} else {
|
||||
if ((pmsk & SIGMSK) == 0) {
|
||||
e1 = 0;
|
||||
}
|
||||
dest = 0;
|
||||
fill = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check signifigance exception */
|
||||
if (cc == 0 && pmsk & SIGMSK) {
|
||||
storepsw(OPPSW, IRC_SIGNIF);
|
||||
goto fpstore1;
|
||||
}
|
||||
|
||||
/* Check if we are normalized addition */
|
||||
if ((op & 0xE) != 0xE) {
|
||||
if (cc != 0) { /* Only if non-zero result */
|
||||
while ((dest & SNMASK) == 0) {
|
||||
dest <<= 4;
|
||||
e1 --;
|
||||
}
|
||||
/* Check if underflow */
|
||||
if (e1 < 0) {
|
||||
if (pmsk & EXPUND) {
|
||||
storepsw(OPPSW, IRC_EXPUND);
|
||||
} else {
|
||||
dest = 0;
|
||||
fill = e1 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove DP Guard bit */
|
||||
dest >>= 4;
|
||||
/* Remove DP Guard bit */
|
||||
dest >>= 4;
|
||||
|
||||
fpstore1:
|
||||
/* Store result */
|
||||
@@ -3935,18 +4027,19 @@ fpstore1:
|
||||
src2L <<= 4;
|
||||
temp = e1 - e2;
|
||||
if (temp > 0) {
|
||||
if (temp > 17) {
|
||||
if (temp > 15) {
|
||||
src2L = 0;
|
||||
} else {
|
||||
/* Shift src2 right if src1 larger expo - expo */
|
||||
src2L >>= 4 * temp;
|
||||
}
|
||||
} else if (temp < 0) {
|
||||
if (temp < -17) {
|
||||
temp = -temp;
|
||||
if (temp > 15) {
|
||||
src1L = 0;
|
||||
} else {
|
||||
/* Shift src1 right if src2 larger expo - expo */
|
||||
src1L >>= 4 * (-temp);
|
||||
src1L >>= 4 * temp;
|
||||
}
|
||||
e1 = e2;
|
||||
}
|
||||
@@ -3981,22 +4074,29 @@ fpstore1:
|
||||
/* Set condition codes */
|
||||
cc = 0;
|
||||
if ((op & 0xE) != 0xE) {
|
||||
if (destL != 0)
|
||||
if (destL != 0) {
|
||||
cc = (fill & 2) ? 1 : 2;
|
||||
else
|
||||
e1 = fill = 0;
|
||||
} else {
|
||||
if ((pmsk & SIGMSK) == 0) {
|
||||
e1 = 0;
|
||||
}
|
||||
fill = 0;
|
||||
}
|
||||
} else {
|
||||
if ((destL & UMASKL) != 0)
|
||||
if ((destL & UMASKL) != 0) {
|
||||
cc = (fill & 2) ? 1 : 2;
|
||||
else
|
||||
destL = e1 = fill = 0;
|
||||
} else {
|
||||
if ((pmsk & SIGMSK) == 0) {
|
||||
e1 = 0;
|
||||
}
|
||||
destL = 0;
|
||||
fill = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check signifigance exception */
|
||||
if (cc == 0 && pmsk & SIGMSK) {
|
||||
storepsw(OPPSW, IRC_SIGNIF);
|
||||
e1 = fill = 0;
|
||||
destL = 0;
|
||||
goto fpstore;
|
||||
}
|
||||
|
||||
@@ -4063,11 +4163,14 @@ fpstore:
|
||||
}
|
||||
|
||||
/* Compute exponent */
|
||||
e1 = e1 + e2 - 64;
|
||||
e1 = e1 + e2 - 65;
|
||||
|
||||
/* Add in guard digits */
|
||||
src1L <<= 4;
|
||||
src2L <<= 4;
|
||||
destL = 0;
|
||||
/* Do multiply */
|
||||
for (temp = 0; temp < 56; temp++) {
|
||||
for (temp = 0; temp < 60; temp++) {
|
||||
/* Add if we need too */
|
||||
if (src1L & 1)
|
||||
destL += src2L;
|
||||
@@ -4080,9 +4183,11 @@ fpnorm:
|
||||
if (destL & EMASKL) {
|
||||
destL >>= 4;
|
||||
e1 ++;
|
||||
if (e1 >= 128) {
|
||||
storepsw(OPPSW, IRC_EXPOVR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for overflow */
|
||||
if (e1 >= 128) {
|
||||
storepsw(OPPSW, IRC_EXPOVR);
|
||||
}
|
||||
/* Align the results */
|
||||
if ((destL) != 0) {
|
||||
@@ -4162,13 +4267,13 @@ fpnorm:
|
||||
src2L++;
|
||||
destL = 0;
|
||||
/* Do divide */
|
||||
for (temp = 56; temp > 0; temp--) {
|
||||
for (temp = 57; temp > 0; temp--) {
|
||||
t_uint64 t;
|
||||
|
||||
/* Shift left by one */
|
||||
src1L <<= 1;
|
||||
/* Subtract remainder to dividend */
|
||||
t= src1L + src2L;
|
||||
t = src1L + src2L;
|
||||
|
||||
/* Shift quotent left one bit */
|
||||
destL <<= 1;
|
||||
@@ -4178,18 +4283,13 @@ fpnorm:
|
||||
src1L = t;
|
||||
destL |= 1;
|
||||
}
|
||||
src1L &= XMASKL;
|
||||
}
|
||||
|
||||
/* Compute one final set to see if rounding needed */
|
||||
/* Shift left by one */
|
||||
src1L <<= 1;
|
||||
/* Subtract remainder to dividend */
|
||||
src1L += src2L;
|
||||
|
||||
/* If .5 off, round */
|
||||
if ((src1L & MSIGNL) != 0) {
|
||||
if (destL == 0x01ffffffffffffff) {
|
||||
destL++;
|
||||
}
|
||||
destL >>= 1;
|
||||
goto fpnorm;
|
||||
|
||||
/* Decimal operations */
|
||||
@@ -4788,20 +4888,23 @@ int dec_load(uint8 *data, uint32 addr, int len, int *sign)
|
||||
if (ReadByte(addr, &temp))
|
||||
return 1;
|
||||
t = temp & 0xf;
|
||||
if (j != 0 && t > 0x9)
|
||||
if (j != 0 && t > 0x9) {
|
||||
err = 1;
|
||||
}
|
||||
data[j++] = t;
|
||||
t = (temp >> 4) & 0xf;
|
||||
if (t > 0x9)
|
||||
if (t > 0x9) {
|
||||
err = 1;
|
||||
}
|
||||
data[j++] = t;
|
||||
addr--;
|
||||
}
|
||||
/* Check if sign valid and return it */
|
||||
if (data[0] == 0xB || data[0] == 0xD)
|
||||
*sign = 1;
|
||||
else if (data[0] < 0xA)
|
||||
else if (data[0] < 0xA) {
|
||||
err = 1;
|
||||
}
|
||||
else
|
||||
*sign = 0;
|
||||
if (err) {
|
||||
@@ -4906,7 +5009,8 @@ dec_srp(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
|
||||
cc = 0;
|
||||
if (!zero) /* Really not zero */
|
||||
cc = (sa)? 1: 2;
|
||||
dec_store(a, addr1, (int)len1, sa);
|
||||
if (dec_store(a, addr1, (int)len1, sa))
|
||||
return;
|
||||
if (ov)
|
||||
cc = 3;
|
||||
if (ov && pmsk & DECOVR)
|
||||
@@ -5004,7 +5108,8 @@ dec_add(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
|
||||
}
|
||||
}
|
||||
}
|
||||
dec_store(a, addr1, (int)len1, sa);
|
||||
if (dec_store(a, addr1, (int)len1, sa))
|
||||
return;
|
||||
if (ov)
|
||||
cc = 3;
|
||||
if (ov && pmsk & DECOVR)
|
||||
@@ -5036,6 +5141,33 @@ dec_mul(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
|
||||
}
|
||||
if (dec_load(b, addr2, (int)len2, &sb))
|
||||
return;
|
||||
/* Check if we can store the result back in place */
|
||||
if (st_key != 0 && (cpu_unit[0].flags & FEAT_PROT) != 0) {
|
||||
uint8 k;
|
||||
uint32 pa;
|
||||
|
||||
/* Validate address */
|
||||
if (TransAddr(addr1 + len, &pa))
|
||||
return;
|
||||
|
||||
k = key[pa >> 11];
|
||||
if ((k & 0xf0) != 0 && (k & 0xf0) != st_key) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return;
|
||||
}
|
||||
/* Check if start on another page */
|
||||
if (((addr1 & 0x3ff) + len) > 0x3ff) {
|
||||
/* Validate address */
|
||||
if (TransAddr(addr1, &pa))
|
||||
return;
|
||||
|
||||
k = key[pa >> 11];
|
||||
if ((k & 0xf0) != 0 && (k & 0xf0) != st_key) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dec_load(a, addr1, (int)len1, &sa))
|
||||
return;
|
||||
len = (int)len1;
|
||||
@@ -5066,7 +5198,7 @@ dec_mul(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
|
||||
mul--;
|
||||
}
|
||||
}
|
||||
dec_store(a, addr1, len, sa);
|
||||
(void)dec_store(a, addr1, len, sa);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -5090,6 +5222,33 @@ dec_div(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
|
||||
}
|
||||
if (dec_load(b, addr2, (int)len2, &sb))
|
||||
return;
|
||||
/* Check if we can store the result back in place */
|
||||
if (st_key != 0 && (cpu_unit[0].flags & FEAT_PROT) != 0) {
|
||||
uint8 k;
|
||||
uint32 pa;
|
||||
|
||||
/* Validate address */
|
||||
if (TransAddr(addr1 + len, &pa))
|
||||
return;
|
||||
|
||||
k = key[pa >> 11];
|
||||
if ((k & 0xf0) != 0 && (k & 0xf0) != st_key) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return;
|
||||
}
|
||||
/* Check if start on another page */
|
||||
if (((addr1 & 0x3ff) + len) > 0x3ff) {
|
||||
/* Validate address */
|
||||
if (TransAddr(addr1, &pa))
|
||||
return;
|
||||
|
||||
k = key[pa >> 11];
|
||||
if ((k & 0xf0) != 0 && (k & 0xf0) != st_key) {
|
||||
storepsw(OPPSW, IRC_PROT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dec_load(a, addr1, (int)len1, &sa))
|
||||
return;
|
||||
memset(c, 0, 32);
|
||||
@@ -5143,7 +5302,7 @@ dec_div(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2)
|
||||
} else {
|
||||
a[len2] = ((flags & ASCII)? 0xa : 0xc);
|
||||
}
|
||||
dec_store(a, addr1, len, sa);
|
||||
(void)dec_store(a, addr1, len, sa);
|
||||
}
|
||||
|
||||
|
||||
@@ -5154,6 +5313,8 @@ cpu_reset (DEVICE *dptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Make sure devices are mapped correctly */
|
||||
chan_set_devs();
|
||||
sim_vm_fprint_stopped = &cpu_fprint_stopped;
|
||||
/* Create memory array if it does not exist. */
|
||||
if (M == NULL) { /* first time init? */
|
||||
@@ -5197,8 +5358,8 @@ cpu_reset (DEVICE *dptr)
|
||||
}
|
||||
|
||||
if (cpu_unit[0].flags & (FEAT_370|FEAT_TIMER)) {
|
||||
sim_rtcn_init_unit (&cpu_unit[0], cpu_unit[0].wait, TMR_RTC);
|
||||
sim_activate(&cpu_unit[0], 10000);
|
||||
sim_rtcn_init_unit (&cpu_unit[0], 1000, TMR_RTC);
|
||||
sim_activate(&cpu_unit[0], 100);
|
||||
}
|
||||
idle_stop_tm0 = 0;
|
||||
return SCPE_OK;
|
||||
@@ -5211,11 +5372,11 @@ rtc_srv(UNIT * uptr)
|
||||
{
|
||||
(void)sim_rtcn_calb (rtc_tps, TMR_RTC);
|
||||
sim_activate_after(uptr, 1000000/rtc_tps);
|
||||
M[0x50>>2] -= 0x100;
|
||||
if ((M[0x50>>2] & 0xfffff00) == 0) {
|
||||
sim_debug(DEBUG_INST, &cpu_dev, "TIMER IRQ %08x\n", M[0x50>>2]);
|
||||
interval_irq = 1;
|
||||
}
|
||||
M[0x50>>2] -= 0x100;
|
||||
key[0] |= 0x6;
|
||||
sim_debug(DEBUG_INST, &cpu_dev, "TIMER = %08x\n", M[0x50>>2]);
|
||||
/* Time of day clock and timer on IBM 370 */
|
||||
|
||||
@@ -107,7 +107,8 @@ typedef struct dib {
|
||||
#define FEAT_EFP (1 << (UNIT_V_UF + 6)) /* Extended floating point */
|
||||
#define FEAT_370 (1 << (UNIT_V_UF + 7)) /* Is a 370 */
|
||||
#define FEAT_VMA (1 << (UNIT_V_UF + 8)) /* Enable VM assists */
|
||||
#define EXT_IRQ (1 << (UNIT_V_UF + 9)) /* External interrupt */
|
||||
#define FEAT_FPROT (1 << (UNIT_V_UF + 9)) /* Fetch protection */
|
||||
#define EXT_IRQ (1 << (UNIT_V_UF + 10)) /* External interrupt */
|
||||
|
||||
/* low addresses */
|
||||
#define IPSW 0x00 /* IPSW */
|
||||
@@ -358,7 +359,7 @@ int haltio(uint16 addr);
|
||||
int testchan(uint16 channel);
|
||||
uint16 scan_chan(uint16 mask, int irq_en);
|
||||
t_stat chan_boot(uint16 addr, DEVICE *dptr);
|
||||
t_stat chan_set_devs();
|
||||
void chan_set_devs();
|
||||
t_stat set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc);
|
||||
t_stat show_dev_addr(FILE * st, UNIT * uptr, int32 v, CONST void *desc);
|
||||
extern uint16 loading;
|
||||
|
||||
@@ -122,7 +122,7 @@ MTAB lpr_mod[] = {
|
||||
&lpr_setlpp, &lpr_getlpp, NULL, "Number of lines per page"},
|
||||
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr,
|
||||
&show_dev_addr, NULL},
|
||||
{MTAB_XTD|MTAB_VDV|MTAB_VALR|MTAB_NC, 0, "FCB", "FCB={LEGACY|STD1)",
|
||||
{MTAB_XTD|MTAB_VUN|MTAB_VALR|MTAB_NC, 0, "FCB", "FCB={LEGACY|STD1|NONE)",
|
||||
&lpr_setfcb, &lpr_getfcb, NULL, NULL },
|
||||
{0}
|
||||
};
|
||||
@@ -137,7 +137,7 @@ DEVICE lpr_dev = {
|
||||
NULL, NULL, &lpr_help, NULL, NULL, &lpr_description
|
||||
};
|
||||
|
||||
static CONST char *fcb_name[] = { "legacy", "std1", NULL};
|
||||
static CONST char *fcb_name[] = { "LEGACY", "STD1", "NONE", NULL};
|
||||
|
||||
static CONST uint16 legacy[] = {
|
||||
/* 1 2 3 4 5 6 7 8 9 10 lines */
|
||||
@@ -162,7 +162,16 @@ static CONST uint16 std1[] = {
|
||||
0x000, 0x000, 0x000, 0x000, 0x004, 0x000, 0x000, 0x000, 0x000, 0x000, /* 51 - 60 */
|
||||
0x002, 0x000, 0x001, 0x000, 0x000, 0x000, 0x1000 }; /* 61 - 66 */
|
||||
|
||||
static CONST uint16 *fcb_ptr[] = { legacy, std1, NULL, NULL};
|
||||
static CONST uint16 none[] = {
|
||||
/* 1 2 3 4 5 6 7 8 9 10 lines */
|
||||
0x800, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* 1 - 10 */
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* 11 - 20 */
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* 21 - 30 */
|
||||
0x040, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* 31 - 40 */
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* 41 - 50 */
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* 51 - 60 */
|
||||
0x002, 0x000, 0x000, 0x000, 0x000, 0x000, 0x1000 }; /* 61 - 66 */
|
||||
static CONST uint16 *fcb_ptr[] = { legacy, std1, none, NULL};
|
||||
|
||||
|
||||
/* Line printer routines
|
||||
@@ -291,16 +300,18 @@ print_line(UNIT * uptr)
|
||||
f = 1;
|
||||
uptr->pos += 2;
|
||||
if ((uptr->CMD & 03) == 0x1) {
|
||||
if ((lpr_data[u].fcb[uptr->LINE] & (0x1000 >> 9)) != 0)
|
||||
if ((lpr_data[u].fcb[uptr->LINE] & (0x1000 >> 9)) != 0) {
|
||||
uptr->SNS |= SNS_CHN9;
|
||||
if ((lpr_data[u].fcb[uptr->LINE] & (0x1000 >> 12)) != 0)
|
||||
}
|
||||
if ((lpr_data[u].fcb[uptr->LINE] & (0x1000 >> 12)) != 0) {
|
||||
uptr->SNS |= SNS_CHN12;
|
||||
}
|
||||
}
|
||||
if ((lpr_data[u].fcb[uptr->LINE] & 0x1000) != 0 ||
|
||||
((uint32)uptr->LINE) >= uptr->capac) {
|
||||
if (f)
|
||||
sim_fwrite("\r\n", 1, 2, uptr->fileref);
|
||||
sim_fwrite("\f", 1, 1, uptr->fileref);
|
||||
sim_fwrite("\f\r\n", 1, 3, uptr->fileref);
|
||||
uptr->LINE = 0;
|
||||
} else {
|
||||
uptr->LINE++;
|
||||
@@ -319,7 +330,7 @@ print_line(UNIT * uptr)
|
||||
l++;
|
||||
if ((lpr_data[u].fcb[i] & 0x1000) != 0 ||
|
||||
((uint32)i) >= uptr->capac) {
|
||||
sim_fwrite("\r\n\f", 1, 3, uptr->fileref);
|
||||
sim_fwrite("\r\n\f\r\n", 1, 5, uptr->fileref);
|
||||
uptr->pos += 3;
|
||||
f = 1;
|
||||
l = 0;
|
||||
@@ -445,7 +456,7 @@ lpr_srv(UNIT *uptr) {
|
||||
/* Handle UCS Load */
|
||||
if ((uptr->CMD & 0xf7) == 0xf3) {
|
||||
for (l = 0; l < 240; l++) {
|
||||
if(chan_read_byte(addr, &ch))
|
||||
if(chan_read_byte(addr, &ch))
|
||||
break;
|
||||
}
|
||||
uptr->CMD &= ~(LPR_CMDMSK);
|
||||
@@ -454,12 +465,12 @@ lpr_srv(UNIT *uptr) {
|
||||
}
|
||||
|
||||
/* Check if valid form motion */
|
||||
if ((cmd == 1 || cmd == 3) &&
|
||||
if ((cmd == 1 || cmd == 3) &&
|
||||
((l > 3 && l < 0x10) || l > 0x1d)) {
|
||||
uptr->SNS = SNS_CMDREJ;
|
||||
uptr->CMD &= ~(LPR_CMDMSK);
|
||||
sim_debug(DEBUG_DETAIL, &lpr_dev, "%d Invalid skip %x %d", u, l, l);
|
||||
if (cmd == 3)
|
||||
if (cmd == 3)
|
||||
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
|
||||
else
|
||||
chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK);
|
||||
|
||||
@@ -520,7 +520,7 @@ t_stat mt_srv(UNIT * uptr)
|
||||
ch = 0x23; /* Model 3, Support dual density */
|
||||
if ((uptr->flags & MTUF_9TR) == 0) {
|
||||
ch |= 0x80; /* Indicate 7 track */
|
||||
}
|
||||
}
|
||||
chan_write_byte(addr, &ch);
|
||||
/* Sense byte 7 */
|
||||
ch = 0;
|
||||
@@ -885,7 +885,6 @@ t_stat mt_srv(UNIT * uptr)
|
||||
unit, reclen);
|
||||
/* We don't set EOF on BSR */
|
||||
if (r == MTSE_TMK) {
|
||||
uptr->POS++;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
|
||||
sim_activate(uptr, 50);
|
||||
} else {
|
||||
|
||||
@@ -190,7 +190,7 @@ DEVICE scoml_dev = {
|
||||
|
||||
|
||||
/*
|
||||
* Issue a scommand to the 3271 controller.
|
||||
* Issue a command to the 3271 controller.
|
||||
*/
|
||||
uint8 scoml_startcmd(UNIT *uptr, uint8 cmd) {
|
||||
DEVICE *dptr = find_dev_from_unit(uptr);
|
||||
@@ -382,7 +382,7 @@ write:
|
||||
sim_debug(DEBUG_CMD, dptr, "COM: unit=%d send %02x '%c'\n",
|
||||
unit, ch, isprint(data)? data: '^');
|
||||
tmxr_putc_ln( &scom_ldsc[unit], ch);
|
||||
if (ch == IAC)
|
||||
if (ch == IAC)
|
||||
tmxr_putc_ln( &scom_ldsc[unit], ch);
|
||||
sim_activate(uptr, 200);
|
||||
}
|
||||
@@ -430,6 +430,7 @@ t_stat scom_scan(UNIT * uptr)
|
||||
line->CMD |= ENAB|DATA|INIT1;
|
||||
line->CMD &= ~(RECV|SEND);
|
||||
line->SNS = 0;
|
||||
set_devattn(GET_UADDR(line->CMD), SNS_ATTN);
|
||||
sim_activate(line, 20000);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ const char *scon_description(DEVICE *d);
|
||||
UNIT scon_unit[] = {
|
||||
{UDATA(scon_srv, UNIT_ATTABLE|UNIT_DISABLE|UNIT_DIS|UNIT_IDLE, 0), 0, UNIT_ADDR(0x09)}, /* B */
|
||||
{UDATA(scon_srv, UNIT_ATTABLE|UNIT_DISABLE|UNIT_DIS|UNIT_IDLE, 0), 0, UNIT_ADDR(0x2F)}, /* C */
|
||||
{UDATA(scon_srvo, UNIT_DISABLE|UNIT_DIS|UNIT_IDLE, 0) },
|
||||
{UDATA(scon_srvo, UNIT_DISABLE|UNIT_DIS|UNIT_IDLE, 0) },
|
||||
};
|
||||
|
||||
MTAB scon_mod[] = {
|
||||
@@ -319,7 +319,7 @@ scon_srv(UNIT *uptr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Grab next character and send it to CPU */
|
||||
data = scon_data[u].ibuff[uptr->IPTR++];
|
||||
sim_debug(DEBUG_CMD, &scon_dev, "%d: rd %02x\n", u, data);
|
||||
|
||||
Reference in New Issue
Block a user