mirror of
https://github.com/simh/simh.git
synced 2026-02-06 16:35:43 +00:00
PDP11: CPU MMR1 and FP changes
There are a lot of niggling fixes, mostly for incompatibility issues found by Walter Mueller. Working out the 11/70 behavior is still not fully done, but it's a lot better than it was, and it passes more of the 11/70 MMU diagnostic. - Floating point. Now model sensitive in treating MMR1, for 2.11 BSD. - MMR1 now tracks PC changes on 11/44, 11/45, 11/70, and J11 -(PC) and @-(PC). - MMR1 is cleared at start of trap sequence on 11/45, 11/70. - Red stack abort occurs before memory writes on 11/45, 11/70 (no other model has them).
This commit is contained in:
committed by
Mark Pizzolato
parent
7fcaa7cf02
commit
72f75ec1b5
@@ -1,6 +1,6 @@
|
||||
/* pdp11_cpu.c: PDP-11 CPU simulator
|
||||
|
||||
Copyright (c) 1993-2016, Robert M Supnik
|
||||
Copyright (c) 1993-2022, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,14 @@
|
||||
|
||||
cpu PDP-11 CPU
|
||||
|
||||
25-Aug-22 RMS 11/45,70 clear MMR1 in trap sequence (Walter Mueller)
|
||||
23-Aug-22 RMS 11/45,70 detect red stack abort before memory write
|
||||
in JSR, MFPx (Walter Mueller)
|
||||
20-Aug-22 RMS MMR1 reads as 0 on subset memory mmgt systems
|
||||
11/44, 45, 70 track PC changes (Walter Mueller)
|
||||
J11 tracks PC changes on -(PC) and @-(PC)
|
||||
25-Jul-22 RMS Removed deprecated CPU models (Q22, UHR11, URH70)
|
||||
04-Jun-18 RMS Removed CPU model entries for UC15 (Mark Pizzolato)
|
||||
04-Dec-16 RMS Removed duplicate IDLE entries in MTAB
|
||||
30-Aug-16 RMS Fixed overloading of -d in ex/mod
|
||||
14-Mar-16 RMS Added UC15 support
|
||||
@@ -338,6 +346,7 @@ int32 relocR (int32 addr);
|
||||
int32 relocW (int32 addr);
|
||||
void relocR_test (int32 va, int32 apridx);
|
||||
void relocW_test (int32 va, int32 apridx);
|
||||
int32 clean_MMR1 (int32 mmr1);
|
||||
t_bool PLF_test (int32 va, int32 apr);
|
||||
void reloc_abort (int32 err, int32 apridx);
|
||||
int32 ReadE (int32 addr);
|
||||
@@ -609,9 +618,9 @@ MTAB cpu_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "11/84", &cpu_set_model, NULL, NULL, "Set CPU type to 11/84" },
|
||||
{ MTAB_XTD|MTAB_VDV, MOD_1193, NULL, "11/93", &cpu_set_model, NULL, NULL, "Set CPU type to 11/93" },
|
||||
{ MTAB_XTD|MTAB_VDV, MOD_1194, NULL, "11/94", &cpu_set_model, NULL, NULL, "Set CPU type to 11/94" },
|
||||
{ MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "Q22", &cpu_set_model, NULL, NULL, "deprecated: same as 11/73" },
|
||||
{ MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "URH11", &cpu_set_model, NULL, NULL, "deprecated: same as 11/84" },
|
||||
{ MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "URH70", &cpu_set_model, NULL, NULL, "deprecated: same as 11/70" },
|
||||
// { MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "Q22", &cpu_set_model, NULL, NULL, "deprecated: same as 11/73" },
|
||||
// { MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "URH11", &cpu_set_model, NULL, NULL, "deprecated: same as 11/84" },
|
||||
// { MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "URH70", &cpu_set_model, NULL, NULL, "deprecated: same as 11/70" },
|
||||
{ MTAB_XTD|MTAB_VDV, MOD_1145, NULL, "U18", &cpu_set_model, NULL, NULL, "deprecated: same as 11/45" },
|
||||
{ MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "EIS", &cpu_set_opt, NULL, NULL, "enable EIS instructions" },
|
||||
{ MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "NOEIS", &cpu_clr_opt, NULL, NULL, "disable EIS instructions" },
|
||||
@@ -888,8 +897,10 @@ while (reason == 0) {
|
||||
PSW = get_PSW (); /* assemble PSW */
|
||||
oldrs = rs;
|
||||
if (CPUT (HAS_MMTR)) { /* 45,70? */
|
||||
if (update_MM) /* save vector */
|
||||
MMR2 = trapea;
|
||||
if (update_MM) { /* if not frozen */
|
||||
MMR1 = 0; /* clear MMR1 */
|
||||
MMR2 = trapea; /* save vector */
|
||||
}
|
||||
MMR0 = MMR0 & ~MMR0_IC; /* clear IC */
|
||||
}
|
||||
src = ReadCW (trapea | calc_ds (MD_KER)); /* new PC */
|
||||
@@ -1222,9 +1233,9 @@ while (reason == 0) {
|
||||
reg_mods = calc_MMR1 (0366);
|
||||
if (update_MM)
|
||||
MMR1 = reg_mods;
|
||||
WriteW (R[srcspec], SP | dsenable);
|
||||
if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (SP);
|
||||
WriteW (R[srcspec], SP | dsenable);
|
||||
R[srcspec] = PC;
|
||||
if (hst_ent)
|
||||
hst_ent->dst = dst;
|
||||
@@ -1424,9 +1435,9 @@ while (reason == 0) {
|
||||
MMR1 = reg_mods;
|
||||
if (hst_ent)
|
||||
hst_ent->dst = dst;
|
||||
WriteW (dst, SP | dsenable);
|
||||
if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (SP);
|
||||
WriteW (dst, SP | dsenable);
|
||||
}
|
||||
else setTRAP (TRAP_ILL);
|
||||
break;
|
||||
@@ -1715,7 +1726,7 @@ while (reason == 0) {
|
||||
break;
|
||||
}
|
||||
if ((((uint32)src) == 020000000000) && (src2 == 0177777)) {
|
||||
V = 1; /* J11,11/70 compat */
|
||||
V = 1; /* V = 1 */
|
||||
N = Z = C = 0; /* N = Z = 0 */
|
||||
break;
|
||||
}
|
||||
@@ -1730,7 +1741,7 @@ while (reason == 0) {
|
||||
}
|
||||
N = (dst < 0); /* N set on 32b result */
|
||||
if ((dst > 077777) || (dst < -0100000)) {
|
||||
V = 1; /* J11,11/70 compat */
|
||||
V = 1; /* V = 1 */
|
||||
Z = C = 0; /* Z = C = 0 */
|
||||
break;
|
||||
}
|
||||
@@ -2215,9 +2226,9 @@ while (reason == 0) {
|
||||
MMR1 = reg_mods;
|
||||
if (hst_ent)
|
||||
hst_ent->dst = dst;
|
||||
WriteW (dst, SP | dsenable);
|
||||
if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (SP);
|
||||
WriteW (dst, SP | dsenable);
|
||||
}
|
||||
else setTRAP (TRAP_ILL);
|
||||
break;
|
||||
@@ -2414,6 +2425,7 @@ for (i = 0; i < 6; i++)
|
||||
REGFILE[i][rs] = R[i];
|
||||
STACKFILE[cm] = SP;
|
||||
saved_PC = PC & 0177777;
|
||||
MMR1 = clean_MMR1 (MMR1); /* clean up MMR1 */
|
||||
pcq_r->qptr = pcq_p; /* update pc q ptr */
|
||||
set_r_display (rs, cm);
|
||||
return reason;
|
||||
@@ -2454,7 +2466,7 @@ return reason;
|
||||
explicitly reference the PC. For the J-11, this is only true for
|
||||
autodecrement operands, autodecrement deferred operands, and
|
||||
autoincrement destination operands that involve a write to memory.
|
||||
The simulator follows the Handbook, for simplicity.
|
||||
This is cleaned up at simulator exit or MMR1 read.
|
||||
|
||||
Notes:
|
||||
|
||||
@@ -2482,14 +2494,14 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
||||
case 2: /* (R)+ */
|
||||
R[reg] = ((adr = R[reg]) + 2) & 0177777;
|
||||
reg_mods = calc_MMR1 (020 | reg);
|
||||
if (update_MM && (reg != 7))
|
||||
if (update_MM)
|
||||
MMR1 = reg_mods;
|
||||
return (adr | ds);
|
||||
|
||||
case 3: /* @(R)+ */
|
||||
R[reg] = ((adr = R[reg]) + 2) & 0177777;
|
||||
reg_mods = calc_MMR1 (020 | reg);
|
||||
if (update_MM && (reg != 7))
|
||||
if (update_MM)
|
||||
MMR1 = reg_mods;
|
||||
adr = ReadW (adr | ds);
|
||||
return (adr | dsenable);
|
||||
@@ -2497,7 +2509,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
||||
case 4: /* -(R) */
|
||||
adr = R[reg] = (R[reg] - 2) & 0177777;
|
||||
reg_mods = calc_MMR1 (0360 | reg);
|
||||
if (update_MM && (reg != 7))
|
||||
if (update_MM)
|
||||
MMR1 = reg_mods;
|
||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (adr);
|
||||
@@ -2506,7 +2518,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
||||
case 5: /* @-(R) */
|
||||
adr = R[reg] = (R[reg] - 2) & 0177777;
|
||||
reg_mods = calc_MMR1 (0360 | reg);
|
||||
if (update_MM && (reg != 7))
|
||||
if (update_MM)
|
||||
MMR1 = reg_mods;
|
||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (adr);
|
||||
@@ -2551,7 +2563,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
||||
case 3: /* @(R)+ */
|
||||
R[reg] = ((adr = R[reg]) + 2) & 0177777;
|
||||
reg_mods = calc_MMR1 (020 | reg);
|
||||
if (update_MM && (reg != 7))
|
||||
if (update_MM)
|
||||
MMR1 = reg_mods;
|
||||
adr = ReadW (adr | ds);
|
||||
return (adr | dsenable);
|
||||
@@ -2560,7 +2572,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
||||
delta = 1 + (reg >= 6); /* 2 if R6, PC */
|
||||
adr = R[reg] = (R[reg] - delta) & 0177777;
|
||||
reg_mods = calc_MMR1 ((((-delta) & 037) << 3) | reg);
|
||||
if (update_MM && (reg != 7))
|
||||
if (update_MM)
|
||||
MMR1 = reg_mods;
|
||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (adr);
|
||||
@@ -2569,7 +2581,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
||||
case 5: /* @-(R) */
|
||||
adr = R[reg] = (R[reg] - 2) & 0177777;
|
||||
reg_mods = calc_MMR1 (0360 | reg);
|
||||
if (update_MM && (reg != 7))
|
||||
if (update_MM)
|
||||
MMR1 = reg_mods;
|
||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (adr);
|
||||
@@ -3087,7 +3099,8 @@ switch ((pa >> 1) & 3) { /* decode pa<2:1> */
|
||||
break;
|
||||
|
||||
case 2: /* MMR1 */
|
||||
*data = MMR1;
|
||||
MMR1 = clean_MMR1 (MMR1); /* clean up MMR1 */
|
||||
*data = MMR1; /* return data */
|
||||
break;
|
||||
|
||||
case 3: /* MMR2 */
|
||||
@@ -3133,6 +3146,29 @@ dsenable = calc_ds (cm);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Clean up MMR1 for presentation
|
||||
|
||||
!HAS_SID MMR1 is 0
|
||||
HAS_SID && J11 MMR1 values corresponding to # and @# are cleared
|
||||
HAS_SID && !J11 MMR1 is unchanged
|
||||
|
||||
Note that # and @# always generate reg = 7 and change = 2;
|
||||
no other specifier combination can do that.
|
||||
*/
|
||||
|
||||
int32 clean_MMR1 (int32 mmr1)
|
||||
{
|
||||
if (!CPUT (HAS_SID)) /* not full mmgt? */
|
||||
return 0; /* always 0 */
|
||||
if (CPUT (CPUT_J)) { /* J11? */
|
||||
if ((mmr1 >> 8) == 027) /* high byte # or @#? */
|
||||
mmr1 = mmr1 & 0377; /* erase high byte */
|
||||
if ((mmr1 & 0377) == 027) /* low byte # or @#? */
|
||||
mmr1 = mmr1 >> 8; /* erase low byte */
|
||||
}
|
||||
return mmr1;
|
||||
}
|
||||
|
||||
/* PARs and PDRs. These are grouped in I/O space as follows:
|
||||
|
||||
17772200 - 17772276 supervisor block
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_fp.c: PDP-11 floating point simulator (32b version)
|
||||
|
||||
Copyright (c) 1993-2015, Robert M Supnik
|
||||
Copyright (c) 1993-2018, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -23,6 +23,7 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
21-Aug-22 RMS Restored MMR1 operation for 11/44, 11/45-70 (Walter Mueller)
|
||||
24-Mar-15 RMS MMR1 does not track register changes (Johnny Billquist)
|
||||
20-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist)
|
||||
22-Sep-05 RMS Fixed declarations (Sterling Garwood)
|
||||
@@ -248,9 +249,10 @@ static const uint32 and_mask[33] = { 0,
|
||||
int32 backup_PC;
|
||||
int32 fp_change;
|
||||
|
||||
int32 fpnotrap (int32 code);
|
||||
t_bool fpnotrap (int32 code);
|
||||
int32 GeteaFW (int32 spec);
|
||||
int32 GeteaFP (int32 spec, int32 len);
|
||||
void fp_reg_change (int32 len, int32 reg);
|
||||
uint32 ReadI (int32 addr, int32 spec, int32 len);
|
||||
t_bool ReadFP (fpac_t *fac, int32 addr, int32 spec, int32 len);
|
||||
void WriteI (int32 data, int32 addr, int32 spec, int32 len);
|
||||
@@ -606,33 +608,25 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
||||
|
||||
case 2: /* (R)+ */
|
||||
adr = R[reg]; /* post increment */
|
||||
if (reg == 7) /* commit PC chg now */
|
||||
R[reg] = (R[reg] + 2) & 0177777;
|
||||
else fp_change = FPCHG (2, reg); /* others, update later */
|
||||
fp_reg_change (2, reg); /* update */
|
||||
return (adr | ds);
|
||||
|
||||
case 3: /* @(R)+ */
|
||||
adr = R[reg]; /* post increment */
|
||||
if (reg == 7) /* commit PC chg now */
|
||||
R[reg] = (R[reg] + 2) & 0177777;
|
||||
else fp_change = FPCHG (2, reg); /* others, update later */
|
||||
fp_reg_change (2, reg); /* update */
|
||||
adr = ReadW (adr | ds);
|
||||
return (adr | dsenable);
|
||||
|
||||
case 4: /* -(R) */
|
||||
adr = (R[reg] - 2) & 0177777; /* predecrement */
|
||||
if (reg == 7) /* commit PC chg now */
|
||||
R[reg] = adr;
|
||||
else fp_change = FPCHG (-2, reg); /* others, update later */
|
||||
fp_reg_change (-2, reg); /* update */
|
||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (adr);
|
||||
return (adr | ds);
|
||||
|
||||
case 5: /* @-(R) */
|
||||
adr = (R[reg] - 2) & 0177777; /* predecrement */
|
||||
if (reg == 7) /* commit PC chg now */
|
||||
R[reg] = adr;
|
||||
else fp_change = FPCHG (-2, reg); /* others, update later */
|
||||
fp_reg_change (-2, reg); /* update */
|
||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (adr);
|
||||
adr = ReadW (adr | ds);
|
||||
@@ -687,33 +681,27 @@ switch (spec >> 3) { /* case on spec */
|
||||
|
||||
case 2: /* (R)+ */
|
||||
adr = R[reg]; /* post increment */
|
||||
if (reg == 7) /* commit PC chg now */
|
||||
R[reg] = (R[reg] + 2) & 0177777;
|
||||
else fp_change = FPCHG (len, reg); /* others, update later */
|
||||
if (reg == 7) /* # is always length 2 */
|
||||
len = 2;
|
||||
fp_reg_change (len, reg); /* update */
|
||||
return (adr | ds);
|
||||
|
||||
case 3: /* @(R)+ */
|
||||
adr = R[reg]; /* post increment */
|
||||
if (reg == 7) /* commit PC chg now */
|
||||
R[reg] = (R[reg] + 2) & 0177777;
|
||||
else fp_change = FPCHG (2, reg); /* others, update later */
|
||||
fp_reg_change (2, reg); /* update */
|
||||
adr = ReadW (adr | ds);
|
||||
return (adr | dsenable);
|
||||
|
||||
case 4: /* -(R) */
|
||||
adr = (R[reg] - len) & 0177777; /* predecrement */
|
||||
if (reg == 7) /* commit PC chg now */
|
||||
R[reg] = adr;
|
||||
else fp_change = FPCHG (-len, reg); /* others, udpate later */
|
||||
fp_reg_change (-len, reg); /* update */
|
||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (adr);
|
||||
return (adr | ds);
|
||||
|
||||
case 5: /* @-(R) */
|
||||
adr = (R[reg] - 2) & 0177777; /* predecrement */
|
||||
if (reg == 7) /* commit PC chg now */
|
||||
R[reg] = adr;
|
||||
else fp_change = FPCHG (-2, reg); /* others, update later */
|
||||
fp_reg_change (-2, reg); /* update */
|
||||
if ((reg == 6) && (cm == MD_KER) && ((adr - 2) < (STKLIM + STKL_Y)))
|
||||
set_stack_trap (adr);
|
||||
adr = ReadW (adr | ds);
|
||||
@@ -734,6 +722,35 @@ switch (spec >> 3) { /* case on spec */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Specifier register change
|
||||
|
||||
On systems with full memory management, the 11/44, 11/45, and 11/70
|
||||
operate differently than J11. The former do normal register modification
|
||||
and track changes in MMR1; on an abort, the register modifications
|
||||
are visible. The J11 does not perform normal register modification
|
||||
and tracking. Instead, it tracks changes internally and only updates
|
||||
the general registers upon successful completion of the instruction.
|
||||
On an abort, the general registers are unchanged.
|
||||
|
||||
This routine performs the appropriate bookkeeping for the different
|
||||
models.
|
||||
*/
|
||||
|
||||
void fp_reg_change (int32 len, int32 reg)
|
||||
{
|
||||
if (CPUT (CPUT_J)) { /* J11? */
|
||||
if (reg == 7)
|
||||
R[reg] = (R[reg] + len) & 0177777; /* commit PC changes now */
|
||||
else fp_change = FPCHG (len, reg); /* track other changes */
|
||||
}
|
||||
else { /* all others */
|
||||
R[reg] = (R[reg] + len) & 0177777; /* commit reg changes */
|
||||
if (update_MM) /* if not frozen */
|
||||
MMR1 = ((len & 037) << 3) | reg; /* update MMR1 */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read integer operand
|
||||
|
||||
Inputs:
|
||||
@@ -785,10 +802,12 @@ else {
|
||||
(ReadW (exta | ((VA + 6) & 0177777)) << FP_V_F3);
|
||||
else fptr->l = 0;
|
||||
}
|
||||
if ((GET_SIGN (fptr->h) != 0) &&
|
||||
if ((GET_SIGN (fptr->h) != 0) && /* undef variable? */
|
||||
(GET_EXP (fptr->h) == 0) &&
|
||||
(fpnotrap (FEC_UNDFV) == 0))
|
||||
return FALSE;
|
||||
!fpnotrap (FEC_UNDFV)) { /* trap enabled? */
|
||||
fp_change = 0; /* J11, no reg changes */
|
||||
return FALSE; /* NOP instruction */
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1393,7 +1412,7 @@ return 0;
|
||||
int = FALSE if interrupt enabled, TRUE if disabled
|
||||
*/
|
||||
|
||||
int32 fpnotrap (int32 code)
|
||||
t_bool fpnotrap (int32 code)
|
||||
{
|
||||
static const int32 test_code[] = { 0, 0, 0, FPS_IC, FPS_IV, FPS_IU, FPS_IUV };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user