1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-26 04:01:16 +00:00

IBM360: Fixes to better handle storage modification bits.

This commit is contained in:
Richard Cornwell
2024-01-25 18:00:52 -05:00
parent b5153f4fb3
commit 634fff7d5f
7 changed files with 93 additions and 63 deletions

View File

@@ -84,13 +84,7 @@
extern uint32 *M;
extern uint8 key[MAXMEMSIZE / 2048];
#define UNIT_V_TYPE (UNIT_V_UF + 0)
#define UNIT_SEL (1 << UNIT_V_TYPE) /* Selector channel */
#define UNIT_MUX (0 << UNIT_V_TYPE) /* Multiplexer channel */
#define UNIT_BMUX (2 << UNIT_V_TYPE) /* Multiplexer channel */
#define UNIT_M_TYPE (3 << UNIT_V_TYPE)
#define UNIT_V_SUBCHAN (UNIT_V_UF + 2)
#define UNIT_V_SUBCHAN (UNIT_V_CTYPE + 2)
#define UNIT_M_SUBCHAN 0xff
#define UNIT_G_SCHAN(x) ((((x) >> UNIT_V_SUBCHAN) & UNIT_M_SUBCHAN) + 1)
#define UNIT_SCHAN(x) (((x - 1) & UNIT_M_SUBCHAN) << UNIT_V_SUBCHAN)
@@ -103,9 +97,9 @@ t_stat chan_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char
const char *chan_description (DEVICE *dptr);
MTAB chan_mod[] = {
{ UNIT_M_TYPE, UNIT_MUX, NULL, "MUX", NULL, NULL, NULL, "Multiplexer channel"},
{ UNIT_M_TYPE, UNIT_SEL, NULL, "SEL", NULL, NULL, NULL, "Selector channel"},
{ UNIT_M_TYPE, UNIT_BMUX, NULL, "BMUX", NULL, NULL, NULL, "Block Multiplexer channel"},
{ UNIT_M_CTYPE, UNIT_MUX, NULL, "MUX", NULL, NULL, NULL, "Multiplexer channel"},
{ UNIT_M_CTYPE, UNIT_SEL, NULL, "SEL", NULL, NULL, NULL, "Selector channel"},
{ UNIT_M_CTYPE, UNIT_BMUX, NULL, "BMUX", NULL, NULL, NULL, "Block Multiplexer channel"},
{ MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "SUB", "SUB", set_subchan, show_subchan, NULL,
"Number of subchannels"},
{0}
@@ -231,11 +225,11 @@ find_subchan(uint16 device) {
uptr = &chan_unit[chan];
if ((uptr->flags & UNIT_DIS) != 0)
return NULL;
if ((uptr->flags & UNIT_M_TYPE) == UNIT_SEL) {
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_SEL) {
return &(chan_ctl[0]);
}
device &= 0xff;
if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) {
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) {
extern uint32 cregs[16];
if ((cpu_unit[0].flags & FEAT_370) != 0 &&
(cregs[0] & 0x80000000) != 0) {
@@ -1150,13 +1144,13 @@ int testchan(uint16 channel) {
}
/* Multiplexer channels return channel is available */
if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX) {
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX) {
sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x cc=0, mux\n", channel);
return 0;
}
/* Block Multiplexer channels operating in select mode */
if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) {
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) {
extern uint32 cregs[16];
if ((cpu_unit[0].flags & FEAT_370) != 0 &&
(cregs[0] & 0x80000000) != 0) {
@@ -1267,13 +1261,13 @@ scan_chan(uint16 mask, int irq_en) {
if ((uptr->flags & UNIT_DIS) != 0)
continue;
nchan = 1;
if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) {
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) {
extern uint32 cregs[16];
if ((cpu_unit[0].flags & FEAT_370) != 0 &&
(cregs[0] & 0x80000000) != 0) {
nchan = 32;
}
} else if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX) {
} else if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX) {
nchan = UNIT_G_SCHAN(uptr->flags);
}
/* Scan all subchannels on this channel */
@@ -1386,9 +1380,9 @@ chan_reset(DEVICE * dptr)
if (uptr->flags & UNIT_DIS)
continue;
n = 1;
if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX)
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX)
n = UNIT_G_SCHAN(uptr->flags)+1;
if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX)
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX)
n = 32;
uptr->schans = n;
uptr->up7 = calloc(n, sizeof(struct _chanctl));
@@ -1425,9 +1419,9 @@ chan_set_devs()
continue;
}
n = 1;
if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX)
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX)
n = UNIT_G_SCHAN(uptr->flags)+1;
if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX)
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX)
n = 32;
/* If no device array, create one */
if (uptr->up8 == NULL)
@@ -1516,9 +1510,9 @@ show_subchan(FILE * st, UNIT * uptr, int32 v, CONST void *desc)
if (uptr == NULL)
return SCPE_IERR;
if ((uptr->flags & UNIT_M_TYPE) == UNIT_SEL) {
if ((uptr->flags & UNIT_M_CTYPE) == UNIT_SEL) {
fprintf(st, "SEL");
} else if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) {
} else if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) {
fprintf(st, "BMUX");
} else {
n = UNIT_G_SCHAN(uptr->flags);

View File

@@ -40,6 +40,7 @@
#define CON_WR 0x01 /* Write console */
#define CON_ACR 0x09 /* Auto carrage return */
#define CON_RD 0x0a /* Read console */
#define CON_ALR 0x0b /* Control Alarm */
#define CON_NOP 0x03 /* No op command */
#define CON_MSK 0x0f /* Command mask */
@@ -174,6 +175,9 @@ uint8 con_startcmd(UNIT *uptr, uint8 cmd) {
return 0;
case 3: /* Control */
if (cmd == 0xb) {
sim_putchar('\a');
}
sim_debug(DEBUG_CMD, &con_dev, "%d: Cmd NOP\n", u);
if (uptr->CMD & CON_REQ) {
uptr->CMD &= ~CON_REQ;

View File

@@ -609,8 +609,7 @@ TransAddr(uint32 va, uint32 *pa)
}
/* Now we need to fetch the actual entry */
addr = (entry & PTE_ADR) + (page << 1);
addr &= AMASK;
addr = ((entry & PTE_ADR) + (page << 1)) & AMASK;
if (addr >= MEMSIZE) {
storepsw(OPPSW, IRC_ADDR);
return 1;
@@ -650,7 +649,7 @@ TransAddr(uint32 va, uint32 *pa)
page = (va >> page_shift);
entry |= ((page & 0x1f00) << 4) | TLB_VALID;
tlb[page & 0xff] = entry;
*pa = (va & page_mask) | ((entry & TLB_PHY) << page_shift);
*pa = ((va & page_mask) | ((entry & TLB_PHY) << page_shift)) & AMASK;
if (*pa >= MEMSIZE) {
storepsw(OPPSW, IRC_ADDR);
return 1;
@@ -688,9 +687,6 @@ ReadFull(uint32 addr, uint32 *data)
}
}
/* Update access flag */
key[pa >> 11] |= 0x4;
offset = pa & 0x3;
/* If not on word boundry and store feature not set */
@@ -730,6 +726,10 @@ ReadFull(uint32 addr, uint32 *data)
temp >>= 8 * (4 - offset);
*data |= temp;
}
/* Update access flag */
key[pa >> 11] |= 0x4;
/* sim_debug(DEBUG_DATA, &cpu_dev, "RD A=%08x %08x\n", addr, *data); */
return 0;
}
@@ -840,7 +840,6 @@ WriteFull(uint32 addr, uint32 data)
return 1;
}
}
key[pa >> 11] |= 0x6;
pa2 = pa + 4;
/* Check if we handle unaligned access */
@@ -874,6 +873,9 @@ WriteFull(uint32 addr, uint32 data)
}
key[pa2 >> 11] |= 0x6;
}
key[pa >> 11] |= 0x6;
pa >>= 2;
pa2 >>= 2;
@@ -1017,9 +1019,6 @@ WriteHalf(uint32 addr, uint32 data)
}
}
/* Flag as modified */
key[pa >> 11] |= 0x6;
if (offset == 3) {
addr += 4;
/* Check if in storage area */
@@ -1051,8 +1050,10 @@ WriteHalf(uint32 addr, uint32 data)
return 1;
}
}
key[pa2 >> 11] |= 0x6;
}
key[pa >> 11] |= 0x6;
key[pa2 >> 11] |= 0x6;
pa >>= 2;
pa2 >>= 2;
M[pa] &= 0xffffff00;
@@ -1061,6 +1062,10 @@ WriteHalf(uint32 addr, uint32 data)
M[pa2] |= 0xff000000 & (data << 24);
return 0;
}
/* Flag as modified */
key[pa >> 11] |= 0x6;
pa >>= 2;
mask = 0xffff;
@@ -2346,8 +2351,7 @@ save_dbl:
}
/* Now we need to fetch the actual entry */
addr2 = (entry & PTE_ADR) + (page << 1);
addr2 &= AMASK;
addr2 = ((entry & PTE_ADR) + (page << 1)) & AMASK;
if (addr2 >= MEMSIZE) {
storepsw(OPPSW, IRC_ADDR);
goto supress;
@@ -2369,7 +2373,7 @@ save_dbl:
/* Convert to address */
entry >>= pte_shift;
addr2 = (addr1 & page_mask) | ((entry & TLB_PHY) << page_shift);
addr2 = ((addr1 & page_mask) | ((entry & TLB_PHY) << page_shift)) & AMASK;
cc = 0;
regs[reg1] = addr2;
per_mod |= 1 << reg1;
@@ -2963,7 +2967,7 @@ save_dbl:
case OP_370:
if (Q370) {
if (reg < 2 || reg > 0x13) {
if (reg > 0x13) {
storepsw(OPPSW, IRC_OPR);
goto supress;
}
@@ -2975,6 +2979,13 @@ save_dbl:
goto supress;
}
switch(reg) {
case 0x0: /* CONCS */
/* Connect channel set */
case 0x1: /* DISCS */
/* Disconnect channel set */
cc = 3;
break;
case 0x2: /* STIDP */
/* Store CPUID in double word */
dest = 100;
@@ -2987,15 +2998,18 @@ save_dbl:
case 0x3: /* STIDC */
/* Store channel id */
dest = (addr1 >> 8) & 0xff;
if (dest > MAX_CHAN) {
src1 = (addr1 >> 8) & 0xff;
if (src1 > MAX_CHAN) {
cc = 3;
break;
}
if (dest == 0 || dest == 4)
dest = 0;
if ((chan_unit[src1].flags & UNIT_M_CTYPE) == UNIT_MUX) {
dest = 0x10000000;
else
dest = 0;
}
if ((chan_unit[src1].flags & UNIT_M_CTYPE) == UNIT_BMUX) {
dest = 0x20000000;
}
addr1 = 0xA8;
if (WriteFull(addr1, dest))
goto supress;
@@ -3102,9 +3116,7 @@ save_dbl:
storepsw(OPPSW, IRC_OPR);
goto supress;
}
for (addr2 = 0;
addr2 < sizeof(tlb)/sizeof(uint32);
addr2++)
for (addr2 = 0; addr2 < sizeof(tlb)/sizeof(uint32); addr2++)
tlb[addr2] = 0;
break;
case 0x10: /* SPX */
@@ -3118,6 +3130,7 @@ save_dbl:
goto supress;
case 0x13: /* RRB */
/* Set storage block reference bit to zero */
addr1 &= AMASK;
addr1 >>= 11;
dest = key[addr1];
key[addr1] &= 0xfb; /* Clear reference bit */
@@ -3266,6 +3279,7 @@ save_dbl:
break;
case OP_LCTL:
temp = 0;
if (Q360) {
storepsw(OPPSW, IRC_OPR);
} else if (flags & PROBLEM) {
@@ -3326,12 +3340,10 @@ 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 */
for (addr2 = 0;
addr2 < sizeof(tlb)/sizeof(uint32);
addr2++)
tlb[addr2] = 0;
temp = 1;
seg_addr = dest & AMASK;
seg_len = (((dest >> 24) & 0xff) + 1) << 4;
break;
@@ -3363,6 +3375,11 @@ save_dbl:
reg1 &= 0xf;
addr1 += 4;
};
/* Purge TLB if segment pointer updated */
if (temp) {
for (addr2 = 0; addr2 < sizeof(tlb)/sizeof(uint32); addr2++)
tlb[addr2] = 0;
}
}
break;

View File

@@ -212,19 +212,20 @@ struct disk_t
}
disk_type[] =
{
{"2301", 1, 200, 20483, 6, 0x01}, /* 4.1 M */
{"2302", 250, 46, 4984, 6, 0x02}, /* 57.32 M 50ms, 120ms/10, 180ms> 10 */
{"2303", 80, 10, 4984, 6, 0x03}, /* 4.00 M */
{"2305", 48, 8, 14568, 6, 0x05}, /* 5.43 M */
{"2305-2",96, 8, 14858, 6, 0x05}, /* 11.26 M */
{"2311", 203, 10, 3717, 6, 0x11}, /* 7.32 M 156k/s 30 ms 145 full */
{"2314", 202, 20, 7294, 6, 0x14}, /* 29.17 M */
{"3330", 410, 19, 13165, 24, 0x30}, /* 100.00 M */
{"3330-2",815, 19, 13165, 24, 0x30},
{"3340", 349, 12, 8535, 24, 0x40}, /* 34.94 M */
{"3340-2",698, 12, 8535, 24, 0x40}, /* 69.89 M */
{"3350", 559, 30, 19254, 24, 0x50}, /* 304.80 M */
{"5625", 403, 20, 7294, 6, 0x14}, /* 56.00 M */
{"2301", 1, 200, 20483, 6, 0x01}, /* 4.1 M */
{"2302", 250, 46, 4984, 6, 0x02}, /* 57.32 M 50ms, 120ms/10, 180ms> 10 */
{"2303", 80, 10, 4984, 6, 0x03}, /* 4.00 M */
{"2305", 48, 8, 14568, 6, 0x05}, /* 5.43 M */
{"2305-2" ,96, 8, 14858, 6, 0x05}, /* 11.26 M */
{"2311", 203, 10, 3717, 6, 0x11}, /* 7.32 M 156k/s 30 ms 145 full */
{"2314", 202, 20, 7294, 6, 0x14}, /* 29.17 M */
{"3330", 410, 19, 13165, 24, 0x30}, /* 100.00 M */
{"3330-2" ,815, 19, 13165, 24, 0x30}, /* 194.00 M */
{"3340", 349, 12, 8535, 24, 0x40}, /* 34.94 M */
{"3340-2" ,698, 12, 8535, 24, 0x40}, /* 69.89 M */
{"3350", 559, 30, 19254, 24, 0x50}, /* 304.80 M */
{"3375", 962, 12, 36000, 24, 0x75}, /* 369.30 M */
{"5625", 403, 20, 7294, 6, 0x14}, /* 56.00 M */
{NULL, 0}
};

View File

@@ -299,6 +299,13 @@ typedef struct dib {
#define OP_MP 0xFC
#define OP_DP 0xFD
/* Channel type selection */
#define UNIT_V_CTYPE (UNIT_V_UF + 0)
#define UNIT_SEL (0 << UNIT_V_CTYPE) /* Selector channel */
#define UNIT_MUX (1 << UNIT_V_CTYPE) /* Multiplexer channel */
#define UNIT_BMUX (2 << UNIT_V_CTYPE) /* Multiplexer channel */
#define UNIT_M_CTYPE (3 << UNIT_V_CTYPE)
/* Channel sense bytes */
#define SNS_ATTN 0x80 /* Unit attention */
#define SNS_SMS 0x40 /* Status modifier */
@@ -393,6 +400,7 @@ extern DEVICE coml_dev;
extern DEVICE com_dev;
extern DEVICE scoml_dev;
extern DEVICE scom_dev;
extern UNIT cpu_unit[];
extern UNIT cpu_unit[];
extern UNIT chan_unit[];
extern void fprint_inst(FILE *, uint16 *);

View File

@@ -42,6 +42,7 @@
#define CON_WR 0x01 /* Write console */
#define CON_ACR 0x09 /* Auto carrage return */
#define CON_RD 0x0a /* Read console */
#define CON_ALR 0x0b /* Control Alarm */
#define CON_NOP 0x03 /* No op command */
#define CON_MSK 0x0f /* Command mask */
@@ -185,6 +186,9 @@ uint8 scon_startcmd(UNIT *uptr, uint8 cmd) {
return 0;
case 3: /* Control */
if (cmd == CON_ALR) {
tmxr_putc_ln(&scon_ldsc[u], '\a');
}
sim_debug(DEBUG_CMD, &scon_dev, "%d: Cmd NOP\n", u);
if (uptr->CMD & CON_REQ) {
uptr->CMD &= ~CON_REQ;

View File

@@ -407,6 +407,8 @@ t_opcode optab[] = {
};
t_opcode soptab[] = {
{ 0x00, "CONCS", RS },
{ 0x01, "DISCS", RS },
{ 0x02, "STIDP", RS },
{ 0x03, "STIDC", RS },
{ 0x04, "SCK", RS },