mirror of
https://github.com/rcornwell/sims.git
synced 2026-04-03 12:22:52 +00:00
IBM360: Added VMAssist to speed up VM/370.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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}
|
||||
};
|
||||
|
||||
|
||||
731
IBM360/ibm360_vma.c
Normal file
731
IBM360/ibm360_vma.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
BIN
doc/ibm360.doc
BIN
doc/ibm360.doc
Binary file not shown.
2
makefile
2
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user