mirror of
https://github.com/rcornwell/sims.git
synced 2026-03-04 18:34:53 +00:00
IBM360: Initial commit of IBM370 support.
This commit is contained in:
@@ -79,18 +79,21 @@ extern uint32 *M;
|
||||
extern uint8 key[MAXMEMSIZE / 2048];
|
||||
|
||||
#define MAX_DEV (MAX_CHAN * 256)
|
||||
|
||||
#define SEL_BASE (SUB_CHANS * MAX_MUX)
|
||||
#define CHAN_SZ (SEL_BASE + MAX_CHAN)
|
||||
int channels = MAX_CHAN;
|
||||
int subchannels = SUB_CHANS; /* Number of subchannels */
|
||||
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 */
|
||||
uint32 caw[CHAN_SZ]; /* Channel command address word */
|
||||
uint32 ccw_addr[CHAN_SZ]; /* Channel address */
|
||||
uint16 ccw_count[CHAN_SZ]; /* Channel count */
|
||||
uint8 ccw_cmd[CHAN_SZ]; /* Channel command and flags */
|
||||
uint16 ccw_flags[CHAN_SZ]; /* Channel flags */
|
||||
uint16 chan_status[CHAN_SZ]; /* Channel status */
|
||||
uint16 chan_dev[CHAN_SZ]; /* Device on channel */
|
||||
uint32 chan_buf[CHAN_SZ]; /* Channel data buffer */
|
||||
uint8 chan_byte[CHAN_SZ]; /* Current byte, dirty/full */
|
||||
DIB *dev_unit[MAX_DEV]; /* Pointer to Device info block */
|
||||
uint8 dev_status[MAX_DEV]; /* last device status flags */
|
||||
|
||||
@@ -128,17 +131,40 @@ find_chan_dev(uint16 addr) {
|
||||
int
|
||||
find_subchan(uint16 device) {
|
||||
int chan;
|
||||
int base = 0;
|
||||
if (device > MAX_DEV)
|
||||
return -1;
|
||||
if (device > 0xff) {
|
||||
chan = (device >> 8) & 0x7;
|
||||
if (chan > channels)
|
||||
return -1;
|
||||
return subchannels + chan;
|
||||
chan = (device >> 8) & 0xf;
|
||||
device &= 0xff;
|
||||
if (chan > channels)
|
||||
return -1;
|
||||
switch(chan) {
|
||||
case 4:
|
||||
base += subchannels;
|
||||
case 0: /* Multiplexer channel */
|
||||
if (device >= subchannels)
|
||||
device = ((device - subchannels) >> 4) & 0xf;
|
||||
return base + device;
|
||||
case 1: /* Selector channel */
|
||||
case 2:
|
||||
case 3:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
return SEL_BASE + chan;
|
||||
}
|
||||
if (device < subchannels)
|
||||
return device;
|
||||
return ((device - subchannels)>>4) & 0xf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* find a channel for a given index */
|
||||
int
|
||||
find_chan(int index) {
|
||||
int chan = 0;
|
||||
if (index > SEL_BASE)
|
||||
return index - SEL_BASE;
|
||||
if (index > subchannels)
|
||||
return 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read a full word into memory.
|
||||
@@ -692,11 +718,15 @@ int testio(uint16 addr) {
|
||||
uint16 status;
|
||||
|
||||
/* Find channel this device is on, if no none return cc=3 */
|
||||
if (chan < 0 || dibp == 0)
|
||||
if (chan < 0 || dibp == 0) {
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x cc=3\n", addr, chan);
|
||||
return 3;
|
||||
}
|
||||
uptr = find_chan_dev(addr);
|
||||
if (uptr == 0)
|
||||
if (uptr == 0) {
|
||||
sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x uptr cc=3\n", addr, chan);
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* If any error pending save csw and return cc=1 */
|
||||
if (chan_status[chan] & (STATUS_PCI|STATUS_ATTN|STATUS_CHECK|\
|
||||
@@ -804,7 +834,7 @@ int testchan(uint16 channel) {
|
||||
return 0;
|
||||
if (channel > channels)
|
||||
return 3;
|
||||
st = chan_status[subchannels + channel];
|
||||
st = chan_status[SEL_BASE + channel];
|
||||
if (st & STATUS_BUSY)
|
||||
return 2;
|
||||
if (st & (STATUS_ATTN|STATUS_PCI|STATUS_EXPT|STATUS_CHECK|
|
||||
@@ -870,14 +900,11 @@ scan_chan(uint16 mask) {
|
||||
return 0;
|
||||
irq_pend = 0;
|
||||
/* Start with channel 0 and work through all channels */
|
||||
for (i = 0; i < subchannels + channels; i++) {
|
||||
/* If onto channel 1 or above shift mask */
|
||||
if (i >= subchannels)
|
||||
imask = imask / 2;
|
||||
|
||||
for (i = 0; i < CHAN_SZ; i++) {
|
||||
/* Check if PCI pending */
|
||||
if (chan_status[i] & STATUS_PCI) {
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Scan PCI(%x %x %x %x) end\n", i,
|
||||
imask = 0x8000 >> find_chan(i);
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Scan PCI(%x %x %x %x) end\n", i,
|
||||
chan_status[i], imask, mask);
|
||||
if ((imask & mask) != 0) {
|
||||
pend = chan_dev[i];
|
||||
@@ -893,9 +920,11 @@ scan_chan(uint16 mask) {
|
||||
else
|
||||
irq_pend = 1;
|
||||
} else {
|
||||
imask = 0x8000 >> find_chan(i);
|
||||
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) {
|
||||
if ((chan_status[i] & STATUS_DEND) != 0 &&
|
||||
(imask & mask) != 0 || loading != 0) {
|
||||
pend = chan_dev[i];
|
||||
break;
|
||||
}
|
||||
@@ -1048,7 +1077,7 @@ set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc)
|
||||
uptr->u3 |= UNIT_ADDR(devaddr);
|
||||
fprintf(stderr, "Set dev %s %x\n\r", dptr->name, GET_UADDR(uptr->u3));
|
||||
} else {
|
||||
fprintf(stderr, "Set dev %s0 %x\n\r", dptr->name, GET_UADDR(uptr->u3));
|
||||
fprintf(stderr, "Set dev %s0 %x\n\r", dptr->name, GET_UADDR(uptr->u3));
|
||||
for (i = 0; i < dibp->numunits; i++) {
|
||||
dev_unit[devaddr + i] = dibp;
|
||||
uptr = &((dibp->units)[i]);
|
||||
|
||||
1127
IBM360/ibm360_cpu.c
1127
IBM360/ibm360_cpu.c
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,44 @@
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define MEM_ADDR_OK(x) (((x)) < MEMSIZE)
|
||||
|
||||
/* channel:
|
||||
|
||||
Channels 0 and 4 are multiplexer channels.
|
||||
subchannels = 128
|
||||
0 - 7 0x80-0xff
|
||||
8 - 127 0x00-0x7f
|
||||
256 - +6 0x1xx - 0x6xx
|
||||
|
||||
subchannels = 192
|
||||
0 - 3 0xd0-0xff
|
||||
4 - 192 0x00-0xcf
|
||||
384 - +6 0x1xx - 0x6xx
|
||||
|
||||
Channels 1,2,3,5,6 are selector channels.
|
||||
Devices on channel 0 below number of subchannels have there own
|
||||
virtual channel.
|
||||
Devices on channel 0 above the number of subchannels are mapped in
|
||||
groups of 16 into channels 0 to n.
|
||||
|
||||
Channels 1-n run on channels virtual channels above subchannels.
|
||||
*/
|
||||
|
||||
#define MAX_CHAN 6
|
||||
#define SUB_CHANS 192
|
||||
#define MAX_MUX 2
|
||||
|
||||
/* Define number of supported units for each device type */
|
||||
#define NUM_DEVS_CDP 1
|
||||
#define NUM_DEVS_CDR 1
|
||||
#define NUM_DEVS_CON 1
|
||||
#define NUM_DEVS_LPR 1
|
||||
#define NUM_DEVS_MT 1
|
||||
#define NUM_UNITS_MT 8
|
||||
#define NUM_DEVS_DASD 4
|
||||
#define NUM_UNITS_DASD 8
|
||||
#define NUM_DEVS_COM 1
|
||||
#define NUM_UNITS_COM 16
|
||||
|
||||
/* Device information block */
|
||||
typedef struct dib {
|
||||
uint8 mask; /* Device mask */
|
||||
@@ -60,15 +98,17 @@ typedef struct dib {
|
||||
#define GET_UADDR(x) ((UNIT_ADDR_MASK & x) >> UNIT_V_ADDR)
|
||||
#define UNIT_ADDR(x) ((x) << UNIT_V_ADDR)
|
||||
|
||||
/* CPU options, needed by channel */
|
||||
#define FEAT_PROT (1 << (UNIT_V_UF + 8)) /* Storage protection feature */
|
||||
#define FEAT_DEC (1 << (UNIT_V_UF + 9)) /* Decimal instruction set */
|
||||
#define FEAT_FLOAT (1 << (UNIT_V_UF + 10)) /* Floating point instruction set */
|
||||
#define FEAT_UNIV (3 << (UNIT_V_UF + 9)) /* All instructions */
|
||||
#define FEAT_STOR (1 << (UNIT_V_UF + 11)) /* No alignment restrictions */
|
||||
#define FEAT_TIMER (1 << (UNIT_V_UF + 12)) /* Interval timer */
|
||||
#define FEAT_DAT (1 << (UNIT_V_UF + 13)) /* Dynamic address translation */
|
||||
#define EXT_IRQ (1 << (UNIT_V_UF_31)) /* External interrupt */
|
||||
/* CPU options */
|
||||
#define FEAT_PROT (1 << (UNIT_V_UF + 0)) /* Storage protection feature */
|
||||
#define FEAT_DEC (1 << (UNIT_V_UF + 1)) /* Decimal instruction set */
|
||||
#define FEAT_FLOAT (1 << (UNIT_V_UF + 2)) /* Floating point instruction set */
|
||||
#define FEAT_UNIV (3 << (UNIT_V_UF + 1)) /* All instructions */
|
||||
#define FEAT_STOR (1 << (UNIT_V_UF + 3)) /* No alignment restrictions */
|
||||
#define FEAT_TIMER (1 << (UNIT_V_UF + 4)) /* Interval timer */
|
||||
#define FEAT_DAT (1 << (UNIT_V_UF + 5)) /* Dynamic address translation */
|
||||
#define FEAT_EFP (1 << (UNIT_V_UF + 6)) /* Extended floating point */
|
||||
#define FEAT_370 (1 << (UNIT_V_UF + 7)) /* Is a 370 */
|
||||
#define EXT_IRQ (1 << (UNIT_V_UF + 8)) /* External interrupt */
|
||||
|
||||
/* low addresses */
|
||||
#define IPSW 0x00 /* IPSW */
|
||||
@@ -98,6 +138,8 @@ typedef struct dib {
|
||||
#define OP_ISK 0x09
|
||||
#define OP_SVC 0x0A
|
||||
#define OP_BASR 0x0D
|
||||
#define OP_MVCL 0x0E /* 370 Move long */
|
||||
#define OP_CLCL 0x0F /* 370 Compare logical long */
|
||||
#define OP_LPR 0x10
|
||||
#define OP_LNR 0x11
|
||||
#define OP_LTR 0x12
|
||||
@@ -220,9 +262,21 @@ typedef struct dib {
|
||||
#define OP_TIO 0x9D
|
||||
#define OP_HIO 0x9E
|
||||
#define OP_TCH 0x9F
|
||||
#define OP_STMC 0xB0
|
||||
#define OP_STNSM 0xAC /* 370 Store then and system mask */
|
||||
#define OP_STOSM 0xAD /* 370 Store then or system mask */
|
||||
#define OP_SIGP 0xAE /* 370 Signal processor */
|
||||
#define OP_MC 0xAF /* 370 Monitor call */
|
||||
#define OP_STMC 0xB0 /* 360/67 Store control */
|
||||
#define OP_LRA 0xB1
|
||||
#define OP_LMC 0xB8
|
||||
#define OP_370 0xB2 /* Misc 370 system instructions */
|
||||
#define OP_STCTL 0xB6 /* 370 Store control */
|
||||
#define OP_LCTL 0xB7 /* 370 Load control */
|
||||
#define OP_LMC 0xB8 /* 360/67 Load Control */
|
||||
#define OP_CS 0xBA /* 370 Compare and swap */
|
||||
#define OP_CDS 0xBB /* 370 Compare double and swap */
|
||||
#define OP_CLM 0xBD /* 370 Compare character under mask */
|
||||
#define OP_STCM 0xBE /* 370 Store character under mask */
|
||||
#define OP_ICM 0xBF /* 370 Insert character under mask */
|
||||
#define OP_MVN 0xD1
|
||||
#define OP_MVC 0xD2
|
||||
#define OP_MVZ 0xD3
|
||||
@@ -234,6 +288,7 @@ typedef struct dib {
|
||||
#define OP_TRT 0xDD
|
||||
#define OP_ED 0xDE
|
||||
#define OP_EDMK 0xDF
|
||||
#define OP_SRP 0xF0 /* 370 Shift and round decimal */
|
||||
#define OP_MVO 0xF1
|
||||
#define OP_PACK 0xF2
|
||||
#define OP_UNPK 0xF3
|
||||
@@ -281,23 +336,6 @@ typedef struct dib {
|
||||
#define STATUS_INTER 0x0002 /* Channel interface check */
|
||||
#define STATUS_CHAIN 0x0001 /* Channel chain check */
|
||||
|
||||
/* channel:
|
||||
subchannels = 128
|
||||
0 - 7 0x80-0xff
|
||||
8 - 127 0x00-0x7f
|
||||
128 - +6 0x1xx - 0x6xx
|
||||
|
||||
Devices on channel 0 below number of subchannels have there own
|
||||
virtual channel.
|
||||
Devices on channel 0 above the number of subchannels are mapped in
|
||||
groups of 16 into channels 0 to n.
|
||||
|
||||
Channels 1-n run on channels virtual channels above subchannels.
|
||||
*/
|
||||
|
||||
#define MAX_CHAN 3
|
||||
#define SUB_CHANS 192
|
||||
|
||||
void post_extirq();
|
||||
|
||||
/* look up device to find subchannel device is on */
|
||||
@@ -349,15 +387,4 @@ extern DEVICE coml_dev;
|
||||
extern DEVICE com_dev;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
#define NUM_DEVS_CDP 1
|
||||
#define NUM_DEVS_CDR 1
|
||||
#define NUM_DEVS_CON 1
|
||||
#define NUM_DEVS_LPR 1
|
||||
#define NUM_DEVS_MT 1
|
||||
#define NUM_UNITS_MT 8
|
||||
#define NUM_DEVS_DASD 4
|
||||
#define NUM_UNITS_DASD 8
|
||||
#define NUM_DEVS_COM 1
|
||||
#define NUM_UNITS_COM 16
|
||||
|
||||
extern void fprint_inst(FILE *, uint16 *);
|
||||
|
||||
@@ -247,10 +247,19 @@ lpr_srv(UNIT *uptr) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (cmd == 7) {
|
||||
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
|
||||
uptr->u6 = 0;
|
||||
chan_end(addr, SNS_DEVEND|SNS_CHNEND);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if ((uptr->u3 & LPR_FULL) || cmd == 0x3) {
|
||||
print_line(uptr);
|
||||
uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK);
|
||||
uptr->u6 = 0;
|
||||
if (cmd == 0x3)
|
||||
chan_end(addr, SNS_CHNEND);
|
||||
set_devattn(addr, SNS_DEVEND);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -855,6 +855,7 @@ t_stat mt_srv(UNIT * uptr)
|
||||
sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit);
|
||||
uptr->u3 &= ~(MT_CMDMSK);
|
||||
r = sim_tape_detach(uptr);
|
||||
set_devattn(addr, SNS_DEVEND);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -205,6 +205,7 @@ typedef struct _opcode {
|
||||
#define RS 03
|
||||
#define SI 04
|
||||
#define SS 05
|
||||
#define XX 06
|
||||
#define LNMSK 07
|
||||
#define ONEOP 010
|
||||
#define IMDOP 020
|
||||
@@ -366,11 +367,24 @@ t_opcode optab[] = {
|
||||
{ OP_SP, "SP", SS|TWOOP },
|
||||
{ OP_MP, "MP", SS|TWOOP },
|
||||
{ OP_DP, "DP", SS|TWOOP },
|
||||
{ OP_MVCL, "MVCL", RR },
|
||||
{ OP_CLCL, "CLCL", RR },
|
||||
{ OP_STNSM, "STNSM", SI },
|
||||
{ OP_STOSM, "STOSM", SI },
|
||||
{ OP_SIGP, "SIGP", RS },
|
||||
{ OP_MC, "MC", SI },
|
||||
{ OP_370, "I370", XX },
|
||||
{ OP_STCTL, "STCTL", RS },
|
||||
{ OP_LCTL, "LCTL", RS },
|
||||
{ OP_CS, "CS", RS },
|
||||
{ OP_CDS, "CDS", RS },
|
||||
{ OP_CLM, "CLM", RS },
|
||||
{ OP_STCM, "STCM", RS },
|
||||
{ OP_ICM, "ICM", RS },
|
||||
{ OP_SRP, "SRP", SS|TWOOP },
|
||||
{ 0, NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
void fprint_inst(FILE *of, uint16 *val) {
|
||||
uint8 inst = (val[0] >> 8) & 0xff;
|
||||
int i;
|
||||
|
||||
Reference in New Issue
Block a user