From 4c180510180d43838305217046ce0645ee060d1d Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sat, 3 Jul 2021 14:43:56 -0400 Subject: [PATCH] IBM360: Added VMAssist to speed up VM/370. --- IBM360/ibm360_cpu.c | 114 +++++-- IBM360/ibm360_defs.h | 5 +- IBM360/ibm360_sys.c | 10 + IBM360/ibm360_vma.c | 731 +++++++++++++++++++++++++++++++++++++++++++ doc/ibm360.doc | Bin 120320 -> 121856 bytes makefile | 2 +- 6 files changed, 839 insertions(+), 23 deletions(-) create mode 100644 IBM360/ibm360_vma.c diff --git a/IBM360/ibm360_cpu.c b/IBM360/ibm360_cpu.c index 14dd526..6f80d7b 100644 --- a/IBM360/ibm360_cpu.c +++ b/IBM360/ibm360_cpu.c @@ -1,6 +1,6 @@ /* ibm360_cpu.c: ibm 360 cpu simulator. - Copyright (c) 2019-2020, Richard Cornwell + Copyright (c) 2019-2021, Richard Cornwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -242,6 +242,9 @@ int timer_tics; /* Interval Timer is ever 3 tics */ #define Q360 (cpu_unit[0].flags & FEAT_370) == 0 #define Q370 (cpu_unit[0].flags & FEAT_370) != 0 +#define QVMA ((cpu_unit[0].flags & (FEAT_370|FEAT_VMA)) == (FEAT_370|FEAT_VMA) && \ + ((cregs[6] & 0xc0000000) == 0x80000000)) + int hst_lnt; int hst_p; struct InstHistory @@ -277,6 +280,16 @@ void dec_srp(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2); void dec_add(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2); void dec_mul(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2); void dec_div(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2); +extern int vma_370(int reg, uint32 addr1); +extern int vma_ssm(uint32 addr1); +extern int vma_lpsw(uint32 addr1); +extern int vma_stssk(uint32 src1, uint32 addr1); +extern int vma_stisk(uint8 reg1, uint32 addr1); +extern int vma_stsvc(uint8 reg); +extern int vma_lra(uint8 reg, uint32 addr1); +extern int vma_stnsm(uint8 reg, uint32 addr1); +extern int vma_stosm(uint8 reg, uint32 addr1); +extern int vma_stctl(uint8 reg, uint32 addr1); void check_tod_irq(); t_bool build_dev_tab (void); @@ -365,6 +378,8 @@ MTAB cpu_mod[] = { { FEAT_TIMER, 0, NULL, "NOTIMER", NULL, NULL}, { FEAT_DAT, FEAT_DAT, "DAT", "DAT", NULL, NULL, NULL, "DAT /67"}, { FEAT_DAT, 0, NULL, "NODAT", NULL, NULL}, + { FEAT_VMA, FEAT_VMA, "VMA", "VMA", NULL, NULL, NULL, "Enable VM Assists"}, + { FEAT_VMA, 0, NULL, "NOVMA", NULL, NULL}, { EXT_IRQ, 0, "NOEXT", NULL, NULL, NULL}, { EXT_IRQ, EXT_IRQ, "EXT", "EXT", NULL, NULL, NULL, "SET CPU EXT causes external interrupt"}, @@ -377,16 +392,20 @@ DEVICE cpu_dev = { "CPU", cpu_unit, cpu_reg, cpu_mod, 1, 16, 24, 1, 16, 8, &cpu_ex, &cpu_dep, &cpu_reset, NULL, NULL, NULL, - NULL, DEV_DEBUG, 0, dev_debug, + NULL, DEV_DEBUG, 0, cpu_debug, NULL, NULL, &cpu_help, NULL, NULL, &cpu_description }; -void post_extirq() { +void +post_extirq() +{ cpu_unit[0].flags |= EXT_IRQ; } -void storepsw(uint32 addr, uint16 ircode) { +void +storepsw(uint32 addr, uint16 ircode) +{ uint32 word; uint32 word2; irqaddr = addr + 0x40; @@ -508,7 +527,9 @@ void storepsw(uint32 addr, uint16 ircode) { /* * Translate an address from virtual to physical. */ -int TransAddr(uint32 va, uint32 *pa) { +int +TransAddr(uint32 va, uint32 *pa) +{ uint32 seg; uint32 page; uint32 entry; @@ -640,7 +661,9 @@ int TransAddr(uint32 va, uint32 *pa) { * and alignment restrictions. Return 1 if failure, 0 if * success. */ -int ReadFull(uint32 addr, uint32 *data) { +int +ReadFull(uint32 addr, uint32 *data) +{ uint32 pa; int offset; @@ -713,7 +736,9 @@ int ReadFull(uint32 addr, uint32 *data) { * and alignment restrictions. Return 1 if failure, 0 if * success. */ -int ReadByte(uint32 addr, uint32 *data) { +int +ReadByte(uint32 addr, uint32 *data) +{ if (ReadFull(addr & (~0x3), data)) return 1; @@ -727,7 +752,9 @@ int ReadByte(uint32 addr, uint32 *data) { * and alignment restrictions. Return 1 if failure, 0 if * success. */ -int ReadHalf(uint32 addr, uint32 *data) { +int +ReadHalf(uint32 addr, uint32 *data) +{ /* Check if unaligned access */ if (addr & 0x1) { @@ -766,7 +793,9 @@ int ReadHalf(uint32 addr, uint32 *data) { * and alignment restrictions. Return 1 if failure, 0 if * success. */ -int WriteFull(uint32 addr, uint32 data) { +int +WriteFull(uint32 addr, uint32 data) +{ int offset; uint32 pa; uint32 pa2; @@ -877,7 +906,9 @@ int WriteFull(uint32 addr, uint32 data) { * and alignment restrictions. Return 1 if failure, 0 if * success. */ -int WriteByte(uint32 addr, uint32 data) { +int +WriteByte(uint32 addr, uint32 data) +{ uint32 mask; uint32 pa; int offset; @@ -934,7 +965,9 @@ int WriteByte(uint32 addr, uint32 data) { * and alignment restrictions. Return 1 if failure, 0 if * success. */ -int WriteHalf(uint32 addr, uint32 data) { +int +WriteHalf(uint32 addr, uint32 data) +{ uint32 mask; uint32 pa; uint32 pa2; @@ -1492,6 +1525,9 @@ opr: storepsw(OPPSW, IRC_OPR); goto supress; } else if (flags & PROBLEM) { + /* Try to do quick SSK */ + if (QVMA && vma_stssk(src1, addr1)) + break; storepsw(OPPSW, IRC_PRIV); goto supress; } else if ((addr1 & 0xF) != 0) { @@ -1513,6 +1549,9 @@ opr: if ((cpu_unit[0].flags & FEAT_PROT) == 0) { storepsw(OPPSW, IRC_PROT); } if (flags & PROBLEM) { + /* Try to do quick ISK */ + if (QVMA && vma_stisk(reg1, addr1)) + break; storepsw(OPPSW, IRC_PRIV); } else if ((addr1 & 0xF) != 0) { storepsw(OPPSW, IRC_SPEC); @@ -1530,11 +1569,19 @@ opr: break; case OP_SVC: + /* Try to do quick SVC */ + if ((flags & PROBLEM) != 0 && \ + (cpu_unit[0].flags & (FEAT_370|FEAT_VMA)) == (FEAT_370|FEAT_VMA) && \ + (cregs[6] & 0x88000000) == MSIGN && vma_stsvc(reg)) + break; storepsw(OSPSW, reg); break; case OP_SSM: - if (flags & PROBLEM) { + if ((flags & PROBLEM)) { + sim_debug(DEBUG_VMA, &cpu_dev, "SSM CR6 %08x\n", cregs[6]); + if (QVMA && vma_ssm(addr1)) + break; storepsw(OPPSW, IRC_PRIV); goto supress; } else { @@ -1580,6 +1627,8 @@ opr: case OP_LPSW: if (flags & PROBLEM) { + if (QVMA && vma_lpsw(addr1)) + break; storepsw(OPPSW, IRC_PRIV); goto supress; } else if ((addr1 & 0x7) != 0) { @@ -2343,6 +2392,9 @@ save_dbl: if ((cpu_unit[0].flags & FEAT_DAT) == 0) { storepsw(OPPSW, IRC_OPR); } else if (flags & PROBLEM) { + /* Try to do quick LRA */ + if (QVMA && vma_lra(reg, addr1)) + break; storepsw(OPPSW, IRC_PRIV); } else { uint32 seg; @@ -2383,7 +2435,7 @@ save_dbl: /* Check if over end of table */ if ((page >> pte_len_shift) >= addr2) { cc = 3; - regs[reg1] = addr1; + regs[reg1] = addr2; per_mod |= 1 << reg1; break; } @@ -2982,6 +3034,9 @@ save_dbl: goto supress; } if (reg != 5 && flags & PROBLEM) { + /* Try to do quick IPK */ + if (QVMA && vma_370(reg, addr1)) + break; storepsw(OPPSW, IRC_PRIV); goto supress; } @@ -3104,7 +3159,7 @@ save_dbl: storepsw(OPPSW, IRC_OPR); goto supress; } - regs[2] = (regs[2] & 0xffffff00) | st_key; + regs[2] = (regs[2] & 0xffffff00) | (st_key & 0xf0); break; case 0xd: /* PTLB */ if ((cpu_unit[0].flags & FEAT_DAT) == 0) { @@ -3145,6 +3200,9 @@ save_dbl: case OP_STNSM: if (Q370) { if (flags & PROBLEM) { + /* Try to do quick STNSM */ + if (QVMA && vma_stnsm(reg, addr1)) + break; storepsw(OPPSW, IRC_PRIV); goto supress; } @@ -3190,6 +3248,9 @@ save_dbl: case OP_STOSM: if (Q370) { if (flags & PROBLEM) { + /* Try to do quick STOSM */ + if (QVMA && vma_stosm(reg, addr1)) + break; storepsw(OPPSW, IRC_PRIV); goto supress; } @@ -3343,6 +3404,9 @@ save_dbl: sysmsk = irq_en ? (dest >> 16) : 0; irq_pend = 1; break; + case 0x6: /* Assist function */ + sim_debug(DEBUG_VMA, &cpu_dev, "set CR6 %08x\n", dest); + break; case 0x3: /* Unassigned */ case 0x4: /* Unassigned */ case 0x5: /* Unassigned */ @@ -3372,6 +3436,9 @@ save_dbl: } else if ((cpu_unit[0].flags & FEAT_DAT) == 0) { storepsw(OPPSW, IRC_OPR); } else if (flags & PROBLEM) { + /* Try to do quick STCLT */ + if (QVMA && vma_stctl(reg, addr1)) + break; storepsw(OPPSW, IRC_PRIV); } else { reg = R2(reg); @@ -5434,8 +5501,8 @@ lpsw: dat_en = 0; irq_en = (sysmsk != 0); per_en = 0; - pmsk = (src2 >> 24) & 0xf; cc = (src2 >> 28) & 0x3; + pmsk = (src2 >> 24) & 0xf; } irq_pend = 1; st_key = (src1 >> 16) & 0xf0; @@ -5827,10 +5894,11 @@ dec_div(int op, uint32 addr1, uint8 len1, uint32 addr2, uint8 len2) dec_store(a, addr1, len, sa); } - + /* Reset */ -t_stat cpu_reset (DEVICE *dptr) +t_stat +cpu_reset (DEVICE *dptr) { int i; @@ -5941,7 +6009,8 @@ check_tod_irq() /* Memory examine */ -t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) +t_stat +cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) { uint32 addr = (uint32) exta; uint32 byte; @@ -6016,7 +6085,8 @@ t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) /* Memory deposit */ -t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) +t_stat +cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) { uint32 addr = (uint32) exta; uint32 offset = 8 * (3 - (addr & 0x3)); @@ -6092,7 +6162,8 @@ t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) /* Memory allocation */ -t_stat cpu_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +t_stat +cpu_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int32 mc = 0; int32 i, clim; @@ -6228,7 +6299,8 @@ cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc) } -t_stat cpu_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +t_stat +cpu_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { fprintf(st, "IBM360 CPU\n\n"); fprint_set_help(st, dptr); diff --git a/IBM360/ibm360_defs.h b/IBM360/ibm360_defs.h index 77373ce..3e19561 100644 --- a/IBM360/ibm360_defs.h +++ b/IBM360/ibm360_defs.h @@ -105,7 +105,8 @@ typedef struct dib { #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 */ +#define FEAT_VMA (1 << (UNIT_V_UF + 8)) /* Enable VM assists */ +#define EXT_IRQ (1 << (UNIT_V_UF + 9)) /* External interrupt */ /* low addresses */ #define IPSW 0x00 /* IPSW */ @@ -367,8 +368,10 @@ extern const uint8 ebcdic_to_ascii[256]; #define DEBUG_IRQ 0x0000100 /* Show IRQ requests */ #define DEBUG_CDATA 0x0000200 /* Show channel data */ #define DEBUG_TRACE 0x0000400 /* Show instruction trace */ +#define DEBUG_VMA 0x0000800 /* Show VM Assist functions */ extern DEBTAB dev_debug[]; +extern DEBTAB cpu_debug[]; extern DEBTAB crd_debug[]; extern DEVICE cpu_dev; diff --git a/IBM360/ibm360_sys.c b/IBM360/ibm360_sys.c index 9d45606..0516039 100644 --- a/IBM360/ibm360_sys.c +++ b/IBM360/ibm360_sys.c @@ -96,9 +96,19 @@ DEBTAB dev_debug[] = { {"DETAIL", DEBUG_DETAIL, "Show details about device"}, {"EXP", DEBUG_EXP, "Show exception information"}, {"POS", DEBUG_POS, "Dasd positioning information"}, + {0, 0} +}; + +/* Simulator debug controls */ +DEBTAB cpu_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"}, {"CDATA", DEBUG_CDATA, "Show channel data"}, {"TRACE", DEBUG_TRACE, "Show instruction history"}, + {"VMA", DEBUG_VMA, "Show assist history"}, {0, 0} }; diff --git a/IBM360/ibm360_vma.c b/IBM360/ibm360_vma.c new file mode 100644 index 0000000..9357fee --- /dev/null +++ b/IBM360/ibm360_vma.c @@ -0,0 +1,731 @@ +/* ibm360_vma.c: ibm 360 Virtual Memory Assists for VM/370. + + Copyright (c) 2021, 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. + +*/ + +#include "ibm360_defs.h" /* simulator defns */ + +extern uint32 *M; +extern uint8 key[MAXMEMSIZE / 2048]; +extern uint32 PC; /* Program counter */ +extern uint32 regs[16]; /* CPU Registers */ +extern uint32 cregs[16]; /* Control registers /67 or 370 only */ +extern uint8 cc; /* CC */ +extern uint8 pmsk; /* Program mask */ +extern uint8 st_key; /* Storage key */ +extern uint8 per_en; /* PER mode enable */ + +#define AMASK 0x00ffffff /* Mask address bits */ +#define MSIGN 0x80000000 /* Minus sign */ + +#define R1(x) (((x)>>4) & 0xf) +#define R2(x) ((x) & 0xf) +#define B1(x) (((x) >> 12) & 0xf) +#define D1(x) ((x) & 0xfff) +#define X2(x) R2(x) + +extern int ReadFull(uint32 addr, uint32 *data); +extern int ReadByte(uint32 addr, uint32 *data); +extern int ReadHalf(uint32 addr, uint32 *data); +extern int WriteFull(uint32 addr, uint32 data); +extern int WriteByte(uint32 addr, uint32 data); +extern int WriteHalf(uint32 addr, uint32 data); + +/* Handle VM Assists for RRB instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_rrb(uint32 addr1) +{ + uint32 micblok; + uint32 micrseg; + uint32 page; + uint32 seg; + uint32 segpage; + uint32 pagswp; + uint32 swpflg; + uint32 pagcore; + uint32 micvpsw; + uint32 vpsw; + uint8 stk; + + sim_debug(DEBUG_VMA, &cpu_dev, "RRB check %08x\n", addr1); + /* Check if enabled */ + if ((cregs[6] & 0xe0000000) != MSIGN) + return 0; + micblok = (cregs[6] & 0xfffff8) >> 2; + /* Fetch SEGPAGE */ + micrseg = M[micblok]; + sim_debug(DEBUG_VMA, &cpu_dev, "Micrseg %08x\n", micrseg); + if (micrseg & 0x2) + return 0; + /* Compute address to operate on */ + page = addr1 >> 12; + if (micrseg & 0x1) { + seg = page >> 7; + page &= 0x7f; + } else { + seg = page >> 4; + page &= 0xf; + } + segpage = M[((micrseg & AMASK) >> 2) + seg]; + sim_debug(DEBUG_VMA, &cpu_dev, "Segpage %08x s=%x p=%x\n", segpage, seg, page); + if ((segpage >> 24) <= (addr1 >> 20)) + return 0; + pagswp = M[((segpage & AMASK) >> 2) - 1]; + sim_debug(DEBUG_VMA, &cpu_dev, "pagswp %08x\n", pagswp); + swpflg = M[((pagswp + (8 * page)) & AMASK) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "swpflg %08x\n", swpflg); + pagcore = M[((segpage + (2 * page)) & AMASK) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "pagcore %08x\n", pagcore); + /* Get key value */ + if (addr1 & 0x800) { + stk = swpflg & 0xfe; + } else { + stk = (swpflg >> 8) & 0xfe; + } + sim_debug(DEBUG_VMA, &cpu_dev, "stk %02x\n", stk); + /* Check if page is valid */ + if ((page & 0x1) == 0) + pagcore >>= 16; + if ((pagcore & 0xe) == 0) { + pagcore &= 0xfff0; + pagcore <<= 8; + pagcore |= addr1 & 0x800; + stk |= key[pagcore>>11] & 0x6; + key[pagcore>>11] &= 0xfb; /* Clear reference bit */ + sim_debug(DEBUG_VMA, &cpu_dev, "real addr %08x %02x\n", pagcore, stk); + } + /* Clear virtual reference bits */ + if (addr1 & 0x800) { + swpflg &= 0xfcfffffb; + } else { + swpflg & 0xf3fffbff; + } + M[((pagswp + (8 * page)) & AMASK) >> 2] = swpflg; + /* Update the CC */ + cc = (stk >> 1) & 03; + return 1; +} + +/* Handle VM Assists for B2 instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_370(int reg, uint32 addr1) +{ + uint32 micvpsw; + uint32 micseg; + uint32 vpsw; + uint32 page; + uint32 seg; + + sim_debug(DEBUG_VMA, &cpu_dev, "B2%02x %08x check\n", reg, addr1); + switch(reg) { + default: + case 0x2: /* STIDP */ + case 0x3: /* STIDC */ + case 0x4: /* SCK */ + case 0x5: /* STCK */ + case 0x6: /* SCKC */ + case 0x7: /* STCKC */ + break; + case 0x8: /* SPT */ + break; + case 0x9: /* STPT */ + break; + case 0xd: /* PTLB */ + break; + case 0xa: /* SPKA */ + if ((cpu_unit[0].flags & FEAT_PROT) == 0) { + break; + } + if (cregs[6] & 0x10000000) + break; + micvpsw = M[((cregs[6] & 0xfffff8) >> 2) + 2]; + vpsw = M[(micvpsw & AMASK) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "VPSW %08x\n", vpsw); + vpsw &= 0xff0fffff; + vpsw |= (0xf0 & addr1) << 16; + M[micvpsw & AMASK] = vpsw; + st_key = 0xf0 & addr1; + sim_debug(DEBUG_VMA, &cpu_dev, "New VPSW %08x New key %02x \n", vpsw, st_key); + return 1; + + case 0xb: /* IPK */ + if ((cpu_unit[0].flags & FEAT_PROT) == 0) { + break; + } + if (cregs[6] & 0x10000000) + break; + micvpsw = M[((cregs[6] & 0xfffff8) >> 2) + 2]; + vpsw = M[(micvpsw & AMASK) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "VPSW %08x\n", vpsw); + regs[2] = (regs[2] & 0xffffff00) | ((vpsw >> 16) & 0xf0); + sim_debug(DEBUG_VMA, &cpu_dev, "Reg2 %08x\n", regs[2]); + return 1; + + case 0x13: /* RRB */ + return vma_rrb(addr1); + } + return 0; +} + +/* Handle VM Assists for SSM instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_ssm(uint32 addr1) +{ + uint32 micblok; + uint32 miccreg; + uint32 micvpsw; + uint32 vpsw; + uint32 temp; + int flags; + + sim_debug(DEBUG_VMA, &cpu_dev, "SSM check %08x\n", addr1); + micblok = (cregs[6] & 0xfffff8) >> 2; + /* Check if function enabled */ + if ((cregs[6] & 0x01000000) != 0) { + miccreg = M[micblok + 5]; + sim_debug(DEBUG_VMA, &cpu_dev, "SSM micacf %08x\n", miccreg); + if ((miccreg & 0x00800000) == 0) + return 0; + } + /* Fetch Virtual Cr 0 */ + miccreg = M[micblok + 1]; + sim_debug(DEBUG_VMA, &cpu_dev, "SSM miccreg %08x\n", miccreg); + temp = M[(miccreg & AMASK) >> 2]; + if ((temp & 0x40000000) != 0) + return 0; + /* Fetch the virtual PSW */ + micvpsw = M[micblok + 2]; + vpsw = M[(micvpsw & AMASK) >> 2]; + /* Fetch new mask */ + if (ReadByte(addr1, &temp)) + return 0; + sim_debug(DEBUG_VMA, &cpu_dev, "VPSW %08x d=%08x\n", vpsw, temp); + flags = vpsw >> 24; + flags ^= temp; + if (vpsw & 0x80000) { + /* If bits are not zero, exit */ + if (temp & 0xb8) + return 0; + /* Check if DAT or PER changed */ + if (flags & 0x44) + return 0; + /* Check if IRQ pending and enable interrupt */ + if ((micvpsw & MSIGN) && (flags & temp & 0x3) != 0) + return 0; + } else { + /* Check if IRQ pending and enable interrupt */ + if ((micvpsw & MSIGN) && (flags & temp) != 0) + return 0; + } + vpsw &= 0xffffff; + vpsw |= temp << 24; + M[(micvpsw & AMASK) >> 2] = vpsw; + sim_debug(DEBUG_VMA, &cpu_dev, "new VPSW %08x\n", vpsw); + return 1; +} + +/* Handle VM Assists for LPSW instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_lpsw(uint32 addr1) +{ + uint32 micblok; + uint32 miccreg; + uint32 micvpsw; + uint32 vpsw; + uint32 vpsw2; + uint32 npsw1; + uint32 npsw2; + + sim_debug(DEBUG_VMA, &cpu_dev, "LPSW check %08x\n", addr1); + /* Quick check to exit */ + if (per_en || (addr1 & 0x7) != 0) + return 0; + /* Check if function enabled */ + micblok = (cregs[6] & 0xfffff8) >> 2; + /* Fetch new PSW */ + if (ReadFull(addr1, &npsw1)) + return 0; + if (ReadFull(addr1 + 4, &npsw2)) + return 0; + sim_debug(DEBUG_VMA, &cpu_dev, "new %08x %08x\n", npsw1, npsw2); + /* New PSW has WAIT or invalid ECmode bits */ + if ((npsw1 & 0x20000) != 0) + return 0; + if ((npsw1 & 0x80000) != 0 && + ((npsw1 & 0xf800c0ff) != 0 || (npsw2 & 0xff000000) != 0)) + return 0; + /* Fetch the virtual PSW */ + micvpsw = (M[micblok + 2] & AMASK) >> 2; + vpsw = M[micvpsw]; + sim_debug(DEBUG_VMA, &cpu_dev, "VPSW %08x %08x\n", vpsw, M[micvpsw + 1]); + /* Check if old PSW has PER set */ + if ((vpsw & 0x40080000) == 0x40080000) + return 0; + /* Check if PSW changing BC/EC mode */ + if (((vpsw ^ npsw1) & 0x80000) != 0) + return 0; + /* Check for interrupt */ + if (npsw1 & 0x80000) { /* EC Mode */ + /* Check if DAT changed */ + if (((npsw1 ^ vpsw) & 0x04000000) != 0) + return 0; + /* Check if IRQ pending and enable interrupt */ + if ((M[micblok + 2] & MSIGN) && (npsw1 & 0x3000000) != 0 + && ((vpsw ^ npsw1) & npsw1 & 0x3000000) != 0) + return 0; + pmsk = (npsw1 >> 8) & 0xf; + cc = (npsw1 >> 12) & 3; + } else { + /* Check if IRQ pending and enable interrupt */ + if ((M[micblok + 2] & MSIGN) && (((vpsw ^ npsw1) & npsw1) & 0xff000000) != 0) + return 0; + pmsk = (npsw2 >> 24) & 0xf; + cc = (npsw2 >> 28) & 0x3; + } + M[micvpsw] = npsw1; + M[micvpsw + 1] = npsw2; + st_key = (npsw1 >> 16) & 0xf0; + /* Set CR6 to new problem state */ + if (npsw1 & 0x10000) + cregs[6] |= 0x40000000; + else + cregs[6] &= 0xbfffffff; + PC = npsw2 & AMASK; + sim_debug(DEBUG_VMA, &cpu_dev, "new VPSW %08x %08x\n", npsw1, cregs[6]); + return 1; +} + +/* Handle VM Assists for SSK instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_stssk(uint32 src1, uint32 addr1) +{ + uint32 micblok; + uint32 micrseg; + uint32 page; + uint32 seg; + uint32 segpage; + uint32 pagswp; + uint32 swpflg; + uint32 pagcore; + uint8 stk; + + sim_debug(DEBUG_VMA, &cpu_dev, "SSK check %08x %08x\n", src1, addr1); + /* Check if enabled */ + if ((cregs[6] & 0xe0000000) != MSIGN || (src1 & 0xf) != 0) + return 0; + micblok = (cregs[6] & 0xfffff8) >> 2; + /* Fetch SEGPAGE */ + micrseg = M[micblok]; + sim_debug(DEBUG_VMA, &cpu_dev, "Micrseg %08x\n", micrseg); + if (micrseg & 0x2) + return 0; + /* Compute address to operate on */ + page = addr1 >> 12; + if (micrseg & 0x1) { + seg = page >> 7; + page &= 0x7f; + } else { + seg = page >> 4; + page &= 0xf; + } + segpage = M[((micrseg & AMASK) >> 2) + seg]; + sim_debug(DEBUG_VMA, &cpu_dev, "Segpage %08x s=%x p=%x\n", segpage, seg, page); + if ((segpage >> 24) <= (addr1 >> 20)) + return 0; + pagswp = M[((segpage & AMASK) >> 2) - 1]; + sim_debug(DEBUG_VMA, &cpu_dev, "pagswp %08x\n", pagswp); + swpflg = M[((pagswp + (8 * page)) & AMASK) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "swpflg %08x\n", swpflg); + pagcore = M[((segpage + (2 * page)) & AMASK) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "pagcore %08x\n", pagcore); + /* Check if page is valid */ + if ((page & 0x1) == 0) + pagcore >>= 16; + if (pagcore & 0xe) + return 0; + pagcore &= 0xfff0; + pagcore <<= 8; + pagcore |= addr1 & 0x800; + stk = key[pagcore>>11]; + sim_debug(DEBUG_VMA, &cpu_dev, "real addr %08x %02x\n", pagcore, stk); + key[pagcore>>11] = (stk & 0xf) | (src1 & 0xf0); + if (addr1 & 0x800) { + swpflg = (swpflg & 0xfcffff00) | (((uint32)stk & 0x6) << 25) | (src1 & 0xff); + } else { + swpflg = (swpflg & 0xf3ff00ff) | (((uint32)stk & 0x6) << 23) | ((src1 & 0xff) << 8); + } + sim_debug(DEBUG_VMA, &cpu_dev, "swpflg %08x\n", swpflg); + M[((pagswp + (8 * page)) & AMASK) >> 2] = swpflg; + return 1; +} + +/* Handle VM Assists for ISK instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_stisk(uint8 reg1, uint32 addr1) +{ + uint32 micblok; + uint32 micrseg; + uint32 page; + uint32 seg; + uint32 segpage; + uint32 pagswp; + uint32 swpflg; + uint32 pagcore; + uint32 micvpsw; + uint32 vpsw; + uint8 stk; + + sim_debug(DEBUG_VMA, &cpu_dev, "ISK check %02x %08x\n", reg1, addr1); + /* Check if enabled */ + if ((cregs[6] & 0xe0000000) != MSIGN) + return 0; + micblok = (cregs[6] & 0xfffff8) >> 2; + /* Fetch SEGPAGE */ + micrseg = M[micblok]; + sim_debug(DEBUG_VMA, &cpu_dev, "Micrseg %08x\n", micrseg); + if (micrseg & 0x2) + return 0; + /* Compute address to operate on */ + page = addr1 >> 12; + if (micrseg & 0x1) { + seg = page >> 7; + page &= 0x7f; + } else { + seg = page >> 4; + page &= 0xf; + } + segpage = M[((micrseg & AMASK) >> 2) + seg]; + sim_debug(DEBUG_VMA, &cpu_dev, "Segpage %08x s=%x p=%x\n", segpage, seg, page); + if ((segpage >> 24) <= (addr1 >> 20)) + return 0; + pagswp = M[((segpage & AMASK) >> 2) - 1]; + sim_debug(DEBUG_VMA, &cpu_dev, "pagswp %08x\n", pagswp); + swpflg = M[((pagswp + (8 * page)) & AMASK) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "swpflg %08x\n", swpflg); + pagcore = M[((segpage + (2 * page)) & AMASK) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "pagcore %08x\n", pagcore); + /* Get key value */ + if (addr1 & 0x800) { + stk = swpflg & 0xfe; + } else { + stk = (swpflg >> 8) & 0xfe; + } + sim_debug(DEBUG_VMA, &cpu_dev, "stk %02x\n", stk); + /* Check if page is valid */ + if ((page & 0x1) == 0) + pagcore >>= 16; + if ((pagcore & 0xe) == 0) { + pagcore &= 0xfff0; + pagcore <<= 8; + pagcore |= addr1 & 0x800; + stk |= key[pagcore>>11] & 0x6; + sim_debug(DEBUG_VMA, &cpu_dev, "real addr %08x %02x\n", pagcore, stk); + } + /* Fetch the virtual PSW */ + micvpsw = (M[micblok + 2] & AMASK) >> 2; + vpsw = M[micvpsw]; + sim_debug(DEBUG_VMA, &cpu_dev, "VPSW %08x %08x\n", vpsw, M[micvpsw + 1]); + if ((vpsw & 0x80000) == 0) { /* BC Mode */ + stk &= 0xf0; + } + regs[reg1] = (regs[reg1] & 0xffffff00) | (uint32)stk; + return 1; +} + +/* Handle VM Assists for SVC instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_stsvc(uint8 reg) +{ + uint32 micblok; + uint32 micrseg; + uint32 micvpsw; + uint32 segpage; + uint32 pagcore; + uint32 psa; + uint32 vpsw; + uint32 npsw1; + uint32 npsw2; + + sim_debug(DEBUG_VMA, &cpu_dev, "SVC check %02x\n", reg); + if (per_en || reg == 76) + return 0; + micblok = (cregs[6] & 0xfffff8) >> 2; + /* Fetch the virtual PSW */ + micvpsw = (M[micblok + 2] & AMASK) >> 2; + vpsw = M[micvpsw]; + sim_debug(DEBUG_VMA, &cpu_dev, "VPSW %08x %08x\n", vpsw, M[micvpsw + 1]); + /* Check if old PSW has PER set */ + if ((vpsw & 0x40080000) == 0x40080000) + return 0; + /* Fetch SEGPAGE */ + micrseg = M[micblok]; + segpage = M[(micrseg & AMASK) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "Segpage %08x\n", segpage); + pagcore = M[(segpage & AMASK) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "pagcore %08x\n", pagcore); + psa = pagcore >> 16; + sim_debug(DEBUG_VMA, &cpu_dev, "psa %08x\n", psa); + /* determine if page is valid */ + /* Check if 4k or 2k paging */ + if ((micrseg & 02) != 0) { + /* 2K paging */ + if (psa & 0x6) + return 0; + psa &= 0xfff8; + psa <<= 7; + } else { + /* 4K paging */ + if (psa & 0xe) + return 0; + psa &= 0xfff0; + psa <<= 8; + } + /* PSA now points correctly */ + npsw1 = M[(psa + 0x60) >> 2]; + npsw2 = M[(psa + 0x64) >> 2]; + sim_debug(DEBUG_VMA, &cpu_dev, "new PSW %08x %08x\n", npsw1, npsw2); + /* New PSW has WAIT or invalid ECmode bits */ + if ((npsw1 & 0x20000) != 0) + return 0; + if ((npsw1 & 0x80000) != 0 && + ((npsw1 & 0xf800c0ff) != 0 || (npsw2 & 0xff000000) != 0)) + return 0; + /* Check if PSW changing BC/EC mode */ + if (((vpsw ^ npsw1) & 0x80000) != 0) + return 0; + /* Check for interrupt */ + if (npsw1 & 0x80000) { + /* Check if DAT changed */ + if (((npsw1 ^ vpsw) & 0x04000000) != 0) + return 0; + /* Check if IRQ pending and enable interrupt */ + if ((M[micblok + 2] & MSIGN) && (npsw1 & 0x3000000) != 0 + && ((vpsw ^ npsw1) & npsw1 & 0x3000000) != 0) + return 0; + } else { + /* Check if IRQ pending and enable interrupt */ + if ((M[micblok + 2] & MSIGN) && (((vpsw ^ npsw1) & npsw1) & 0xff000000) != 0) + return 0; + } + /* Construct old PSW */ + if (vpsw & 0x80000) { + uint32 temp1; + /* Generate first word */ + temp1 = (vpsw & 0xff0f0f00) | + (((uint32)st_key) << 16) | + (((uint32)cc) << 12) | + (((uint32)pmsk) << 8); + /* Save old PSW */ + M[(psa + 0x20) >> 2] = temp1; + M[(psa + 0x24) >> 2] = PC & AMASK; + M[(psa + 0x88) >> 2] = (1 << 17) | reg; + sim_debug(DEBUG_VMA, &cpu_dev, "Old PSW %08x %08x\n", temp1, PC); + } else { + uint32 temp1; + uint32 temp2; + /* Generate first word */ + temp1 = (vpsw & 0xff0f0000) | + (((uint32)st_key) << 16) | + ((uint32)reg); + /* Generate second word. */ + temp2 = (((uint32)1) << 30) | + (((uint32)cc) << 28) | + (((uint32)pmsk) << 24) | + (PC & AMASK); + /* Save old PSW */ + M[(psa + 0x20) >> 2] = temp1; + M[(psa + 0x24) >> 2] = temp2; + sim_debug(DEBUG_VMA, &cpu_dev, "Old PSW %08x %08x\n", temp1, temp2); + } + /* Set machine for new PSW */ + M[micvpsw] = npsw1; + M[micvpsw + 1] = npsw2; + if (npsw1 & 0x80000) { + pmsk = (npsw1 >> 8) & 0xf; + cc = (npsw1 >> 12) & 3; + } else { + pmsk = (npsw2 >> 24) & 0xf; + cc = (npsw2 >> 28) & 0x3; + } + st_key = (npsw1 >> 16) & 0xf0; + /* Set CR6 to new problem state */ + if (npsw1 & 0x10000) + cregs[6] |= 0x40000000; + else + cregs[6] &= 0xbfffffff; + PC = npsw2 & AMASK; + key[psa >> 11] |= 0x6; + sim_debug(DEBUG_VMA, &cpu_dev, "new VPSW %08x %08x %08x\n", npsw1, npsw2, cregs[6]); + return 1; +} + +/* Handle VM Assists for LRA instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_lra(uint8 reg, uint32 addr1) +{ + sim_debug(DEBUG_VMA, &cpu_dev, "LRA check %02x %08x\n", reg, addr1); + return 0; +} + + +/* Handle VM Assists for STNSM instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_stnsm(uint8 reg, uint32 addr1) +{ + uint32 micblok; + uint32 miccreg; + uint32 micvpsw; + uint32 vpsw; + uint32 temp; + int flags; + + sim_debug(DEBUG_VMA, &cpu_dev, "STNSM check %02x %08x\n", reg, addr1); + micblok = (cregs[6] & 0xfffff8) >> 2; + /* Check if function enabled */ + if ((cregs[6] & 0x01000000) != 0) { + miccreg = M[micblok + 5]; + sim_debug(DEBUG_VMA, &cpu_dev, "SSM micacf %08x\n", miccreg); + if ((miccreg & 0x00800000) == 0) + return 0; + } + /* Fetch Virtual Cr 0 */ + miccreg = M[micblok + 1]; + sim_debug(DEBUG_VMA, &cpu_dev, "SSM miccreg %08x\n", miccreg); + temp = M[(miccreg & AMASK) >> 2]; + /* Fetch the virtual PSW */ + micvpsw = M[micblok + 2]; + vpsw = M[(micvpsw & AMASK) >> 2]; + /* Don't allow change of PER or DAT */ + if (vpsw & 0x80000 && (reg & 0x44) != 0x44) + return 0; + /* Update Mask */ + temp = (vpsw >> 24) & 0xff; + vpsw &= ((uint32)reg << 24) | 0xffffff; + sim_debug(DEBUG_VMA, &cpu_dev, "VPSW %08x d=%08x\n", vpsw, temp); + /* Save old mask in addr1 */ + if (WriteByte(addr1, temp)) + return 0; + M[(micvpsw & AMASK) >> 2] = vpsw; + sim_debug(DEBUG_VMA, &cpu_dev, "new VPSW %08x\n", vpsw); + return 1; +} + +/* Handle VM Assists for STOSM instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_stosm(uint8 reg, uint32 addr1) +{ + uint32 micblok; + uint32 miccreg; + uint32 micvpsw; + uint32 vpsw; + uint32 temp; + int flags; + + sim_debug(DEBUG_VMA, &cpu_dev, "STOSM check %02x %08x\n", reg, addr1); + micblok = (cregs[6] & 0xfffff8) >> 2; + /* Check if function enabled */ + if ((cregs[6] & 0x01000000) != 0) { + miccreg = M[micblok + 5]; + sim_debug(DEBUG_VMA, &cpu_dev, "SSM micacf %08x\n", miccreg); + if ((miccreg & 0x00800000) == 0) + return 0; + } + /* Fetch Virtual Cr 0 */ + miccreg = M[micblok + 1]; + sim_debug(DEBUG_VMA, &cpu_dev, "SSM miccreg %08x\n", miccreg); + temp = M[(miccreg & AMASK) >> 2]; + if ((temp & 0x40000000) != 0) + return 0; + /* Fetch the virtual PSW */ + micvpsw = M[micblok + 2]; + vpsw = M[(micvpsw & AMASK) >> 2]; + flags = (vpsw >> 24) ^ reg; + if (vpsw & 0x80000) { + /* Don't allow change of PER or DAT */ + if ((flags & 0xfc) != 0x0) + return 0; + /* If enabling an interrupt and one pending, abort */ + if ((micvpsw & MSIGN) && (flags & reg & 0x3) != 0) + return 0; + } else { + /* Check if IRQ pending and enable interrupt */ + if ((vpsw & MSIGN) && ((flags & reg) & 0xff) != 0) + return 0; + } + /* Save old mask */ + temp = (vpsw >> 24) & 0xff; + /* Update Mask */ + vpsw |= ((uint32)reg << 24); + sim_debug(DEBUG_VMA, &cpu_dev, "VPSW %08x d=%08x\n", vpsw, temp); + if (WriteByte(addr1, temp)) + return 0; + M[(micvpsw & AMASK) >> 2] = vpsw; + sim_debug(DEBUG_VMA, &cpu_dev, "new VPSW %08x\n", vpsw); + return 1; +} + +/* Handle VM Assists for STCTL instructions + * return 0 if assist could not be completed. Return 1 if successful */ +int +vma_stctl(uint8 reg, uint32 addr1) +{ + int reg1 = R1(reg); + uint32 miccreg; + uint32 micblok; + + sim_debug(DEBUG_VMA, &cpu_dev, "STCL check %02x %08x\n", reg, addr1); + if ((addr1 & 0x3) != 0) + return 0; + micblok = (cregs[6] & 0xfffff8) >> 2; + /* Check if function enabled */ + if ((cregs[6] & 0x01000000) != 0) { + miccreg = M[micblok + 5]; + sim_debug(DEBUG_VMA, &cpu_dev, "STCL micacf %08x\n", miccreg); + if ((miccreg & 0x00800000) == 0) + return 0; + } + /* Point to CR0 */ + miccreg = M[micblok + 1]; + reg = R2(reg); + for (;;) { + uint32 temp; + temp = M[miccreg + reg1]; + if (WriteFull(addr1, temp)) + return 0; + if (reg1 == reg) + break; + reg1++; + reg1 &= 0xf; + addr1 += 4; + } ; + return 1; +} + diff --git a/doc/ibm360.doc b/doc/ibm360.doc index c101a0dd5e1c9cd9b5d98d39937b7e266695e425..a9d359b9a4bed2c888e174cc272f39377929c4c6 100644 GIT binary patch delta 13711 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 KTyA9c*Z%^V)6NV4 delta 13125 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 Hw*CDt>%0_f diff --git a/makefile b/makefile index ec871c9..3f4de00 100644 --- a/makefile +++ b/makefile @@ -2064,7 +2064,7 @@ IBM360D = ${SIMHD}/IBM360 IBM360 = ${IBM360D}/ibm360_cpu.c ${IBM360D}/ibm360_sys.c ${IBM360D}/ibm360_con.c \ ${IBM360D}/ibm360_chan.c ${IBM360D}/ibm360_cdr.c ${IBM360D}/ibm360_cdp.c \ ${IBM360D}/ibm360_mt.c ${IBM360D}/ibm360_lpr.c ${IBM360D}/ibm360_dasd.c \ - ${IBM360D}/ibm360_com.c ${IBM360D}/ibm360_scom.c + ${IBM360D}/ibm360_com.c ${IBM360D}/ibm360_scom.c ${IBM360D}/ibm360_vma.c IBM360_OPT = -I $(IBM360D) -DIBM360 -DUSE_64BIT -DUSE_SIM_CARD IBM360_OPT32 = -I $(IBM360D) -DIBM360 -DUSE_SIM_CARD