mirror of
https://github.com/open-simh/simh.git
synced 2026-04-25 20:01:33 +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
e93d21ac79
commit
a847ee13a3
@@ -1,6 +1,6 @@
|
|||||||
/* pdp11_cpu.c: PDP-11 CPU simulator
|
/* pdp11_cpu.c: PDP-11 CPU simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2018, Robert M Supnik
|
Copyright (c) 1993-2022, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -25,6 +25,13 @@
|
|||||||
|
|
||||||
cpu PDP-11 CPU
|
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-Jun-18 RMS Removed CPU model entries for UC15 (Mark Pizzolato)
|
||||||
04-Dec-16 RMS Removed duplicate IDLE entries in MTAB
|
04-Dec-16 RMS Removed duplicate IDLE entries in MTAB
|
||||||
30-Aug-16 RMS Fixed overloading of -d in ex/mod
|
30-Aug-16 RMS Fixed overloading of -d in ex/mod
|
||||||
@@ -329,6 +336,7 @@ int32 relocR (int32 addr);
|
|||||||
int32 relocW (int32 addr);
|
int32 relocW (int32 addr);
|
||||||
void relocR_test (int32 va, int32 apridx);
|
void relocR_test (int32 va, int32 apridx);
|
||||||
void relocW_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);
|
t_bool PLF_test (int32 va, int32 apr);
|
||||||
void reloc_abort (int32 err, int32 apridx);
|
void reloc_abort (int32 err, int32 apridx);
|
||||||
int32 ReadE (int32 addr);
|
int32 ReadE (int32 addr);
|
||||||
@@ -582,10 +590,9 @@ MTAB cpu_mod[] = {
|
|||||||
{ MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "11/84", &cpu_set_model },
|
{ MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "11/84", &cpu_set_model },
|
||||||
{ MTAB_XTD|MTAB_VDV, MOD_1193, NULL, "11/93", &cpu_set_model },
|
{ MTAB_XTD|MTAB_VDV, MOD_1193, NULL, "11/93", &cpu_set_model },
|
||||||
{ MTAB_XTD|MTAB_VDV, MOD_1194, NULL, "11/94", &cpu_set_model },
|
{ MTAB_XTD|MTAB_VDV, MOD_1194, NULL, "11/94", &cpu_set_model },
|
||||||
{ MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "Q22", &cpu_set_model },
|
// { MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "Q22", &cpu_set_model },
|
||||||
{ MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "URH11", &cpu_set_model },
|
// { MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "URH11", &cpu_set_model },
|
||||||
{ MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "URH70", &cpu_set_model },
|
// { MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "URH70", &cpu_set_model },
|
||||||
{ MTAB_XTD|MTAB_VDV, MOD_1145, NULL, "U18", &cpu_set_model },
|
|
||||||
{ MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "EIS", &cpu_set_opt },
|
{ MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "EIS", &cpu_set_opt },
|
||||||
{ MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "NOEIS", &cpu_clr_opt },
|
{ MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "NOEIS", &cpu_clr_opt },
|
||||||
{ MTAB_XTD|MTAB_VDV, OPT_FIS, NULL, "FIS", &cpu_set_opt },
|
{ MTAB_XTD|MTAB_VDV, OPT_FIS, NULL, "FIS", &cpu_set_opt },
|
||||||
@@ -779,8 +786,10 @@ while (reason == 0) {
|
|||||||
PSW = get_PSW (); /* assemble PSW */
|
PSW = get_PSW (); /* assemble PSW */
|
||||||
oldrs = rs;
|
oldrs = rs;
|
||||||
if (CPUT (HAS_MMTR)) { /* 45,70? */
|
if (CPUT (HAS_MMTR)) { /* 45,70? */
|
||||||
if (update_MM) /* save vector */
|
if (update_MM) { /* if not frozen */
|
||||||
MMR2 = trapea;
|
MMR1 = 0; /* clear MMR1 */
|
||||||
|
MMR2 = trapea; /* save vector */
|
||||||
|
}
|
||||||
MMR0 = MMR0 & ~MMR0_IC; /* clear IC */
|
MMR0 = MMR0 & ~MMR0_IC; /* clear IC */
|
||||||
}
|
}
|
||||||
src = ReadW (trapea | calc_ds (MD_KER)); /* new PC */
|
src = ReadW (trapea | calc_ds (MD_KER)); /* new PC */
|
||||||
@@ -1095,9 +1104,9 @@ while (reason == 0) {
|
|||||||
SP = (SP - 2) & 0177777;
|
SP = (SP - 2) & 0177777;
|
||||||
if (update_MM)
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 (0366);
|
MMR1 = calc_MMR1 (0366);
|
||||||
WriteW (R[srcspec], SP | dsenable);
|
|
||||||
if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
|
if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (SP);
|
set_stack_trap (SP);
|
||||||
|
WriteW (R[srcspec], SP | dsenable);
|
||||||
R[srcspec] = PC;
|
R[srcspec] = PC;
|
||||||
JMP_PC (dst & 0177777);
|
JMP_PC (dst & 0177777);
|
||||||
}
|
}
|
||||||
@@ -1268,9 +1277,9 @@ while (reason == 0) {
|
|||||||
SP = (SP - 2) & 0177777;
|
SP = (SP - 2) & 0177777;
|
||||||
if (update_MM)
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 (0366);
|
MMR1 = calc_MMR1 (0366);
|
||||||
WriteW (dst, SP | dsenable);
|
|
||||||
if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
|
if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (SP);
|
set_stack_trap (SP);
|
||||||
|
WriteW (dst, SP | dsenable);
|
||||||
}
|
}
|
||||||
else setTRAP (TRAP_ILL);
|
else setTRAP (TRAP_ILL);
|
||||||
break;
|
break;
|
||||||
@@ -1522,7 +1531,7 @@ while (reason == 0) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((((uint32)src) == 020000000000) && (src2 == 0177777)) {
|
if ((((uint32)src) == 020000000000) && (src2 == 0177777)) {
|
||||||
V = 1; /* J11,11/70 compat */
|
V = 1; /* V = 1 */
|
||||||
N = Z = C = 0; /* N = Z = 0 */
|
N = Z = C = 0; /* N = Z = 0 */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1533,7 +1542,7 @@ while (reason == 0) {
|
|||||||
dst = src / src2;
|
dst = src / src2;
|
||||||
N = (dst < 0); /* N set on 32b result */
|
N = (dst < 0); /* N set on 32b result */
|
||||||
if ((dst > 077777) || (dst < -0100000)) {
|
if ((dst > 077777) || (dst < -0100000)) {
|
||||||
V = 1; /* J11,11/70 compat */
|
V = 1; /* V = 1 */
|
||||||
Z = C = 0; /* Z = C = 0 */
|
Z = C = 0; /* Z = C = 0 */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1944,9 +1953,9 @@ while (reason == 0) {
|
|||||||
SP = (SP - 2) & 0177777;
|
SP = (SP - 2) & 0177777;
|
||||||
if (update_MM)
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 (0366);
|
MMR1 = calc_MMR1 (0366);
|
||||||
WriteW (dst, SP | dsenable);
|
|
||||||
if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
|
if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (SP);
|
set_stack_trap (SP);
|
||||||
|
WriteW (dst, SP | dsenable);
|
||||||
}
|
}
|
||||||
else setTRAP (TRAP_ILL);
|
else setTRAP (TRAP_ILL);
|
||||||
break;
|
break;
|
||||||
@@ -2103,7 +2112,7 @@ while (reason == 0) {
|
|||||||
|
|
||||||
case 017:
|
case 017:
|
||||||
if (CPUO (OPT_FPP))
|
if (CPUO (OPT_FPP))
|
||||||
fp11 (IR); /* call fpp */
|
fp11 (IR); /* call fpp */
|
||||||
else setTRAP (TRAP_ILL);
|
else setTRAP (TRAP_ILL);
|
||||||
break; /* end case 017 */
|
break; /* end case 017 */
|
||||||
} /* end switch op */
|
} /* end switch op */
|
||||||
@@ -2116,6 +2125,7 @@ for (i = 0; i < 6; i++)
|
|||||||
REGFILE[i][rs] = R[i];
|
REGFILE[i][rs] = R[i];
|
||||||
STACKFILE[cm] = SP;
|
STACKFILE[cm] = SP;
|
||||||
saved_PC = PC & 0177777;
|
saved_PC = PC & 0177777;
|
||||||
|
MMR1 = clean_MMR1 (MMR1); /* clean up MMR1 */
|
||||||
pcq_r->qptr = pcq_p; /* update pc q ptr */
|
pcq_r->qptr = pcq_p; /* update pc q ptr */
|
||||||
set_r_display (rs, cm);
|
set_r_display (rs, cm);
|
||||||
return reason;
|
return reason;
|
||||||
@@ -2153,10 +2163,10 @@ return reason;
|
|||||||
|
|
||||||
According to the PDP-11 Architecture Handbook, MMR1 records all
|
According to the PDP-11 Architecture Handbook, MMR1 records all
|
||||||
autoincrement and autodecrement operations, including those which
|
autoincrement and autodecrement operations, including those which
|
||||||
explicitly reference the PC. For the J-11, this is only true for
|
explicitly reference the PC. For the J-11, this is only true for
|
||||||
autodecrement operands, autodecrement deferred operands, and
|
autodecrement operands, autodecrement deferred operands, and
|
||||||
autoincrement destination operands that involve a write to memory.
|
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:
|
Notes:
|
||||||
|
|
||||||
@@ -2183,20 +2193,20 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
|||||||
|
|
||||||
case 2: /* (R)+ */
|
case 2: /* (R)+ */
|
||||||
R[reg] = ((adr = R[reg]) + 2) & 0177777;
|
R[reg] = ((adr = R[reg]) + 2) & 0177777;
|
||||||
if (update_MM && (reg != 7))
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 (020 | reg);
|
MMR1 = calc_MMR1 (020 | reg);
|
||||||
return (adr | ds);
|
return (adr | ds);
|
||||||
|
|
||||||
case 3: /* @(R)+ */
|
case 3: /* @(R)+ */
|
||||||
R[reg] = ((adr = R[reg]) + 2) & 0177777;
|
R[reg] = ((adr = R[reg]) + 2) & 0177777;
|
||||||
if (update_MM && (reg != 7))
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 (020 | reg);
|
MMR1 = calc_MMR1 (020 | reg);
|
||||||
adr = ReadW (adr | ds);
|
adr = ReadW (adr | ds);
|
||||||
return (adr | dsenable);
|
return (adr | dsenable);
|
||||||
|
|
||||||
case 4: /* -(R) */
|
case 4: /* -(R) */
|
||||||
adr = R[reg] = (R[reg] - 2) & 0177777;
|
adr = R[reg] = (R[reg] - 2) & 0177777;
|
||||||
if (update_MM && (reg != 7))
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 (0360 | reg);
|
MMR1 = calc_MMR1 (0360 | reg);
|
||||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (adr);
|
set_stack_trap (adr);
|
||||||
@@ -2204,7 +2214,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
|||||||
|
|
||||||
case 5: /* @-(R) */
|
case 5: /* @-(R) */
|
||||||
adr = R[reg] = (R[reg] - 2) & 0177777;
|
adr = R[reg] = (R[reg] - 2) & 0177777;
|
||||||
if (update_MM && (reg != 7))
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 (0360 | reg);
|
MMR1 = calc_MMR1 (0360 | reg);
|
||||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (adr);
|
set_stack_trap (adr);
|
||||||
@@ -2238,16 +2248,16 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
|||||||
case 1: /* (R) */
|
case 1: /* (R) */
|
||||||
return (R[reg] | ds);
|
return (R[reg] | ds);
|
||||||
|
|
||||||
case 2: /* (R)+ */
|
case 2: /* (R)+ */
|
||||||
delta = 1 + (reg >= 6); /* 2 if R6, PC */
|
delta = 1 + (reg >= 6); /* 2 if R6, PC */
|
||||||
R[reg] = ((adr = R[reg]) + delta) & 0177777;
|
R[reg] = ((adr = R[reg]) + delta) & 0177777;
|
||||||
if (update_MM && (reg != 7))
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 ((delta << 3) | reg);
|
MMR1 = calc_MMR1 ((delta << 3) | reg);
|
||||||
return (adr | ds);
|
return (adr | ds);
|
||||||
|
|
||||||
case 3: /* @(R)+ */
|
case 3: /* @(R)+ */
|
||||||
R[reg] = ((adr = R[reg]) + 2) & 0177777;
|
R[reg] = ((adr = R[reg]) + 2) & 0177777;
|
||||||
if (update_MM && (reg != 7))
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 (020 | reg);
|
MMR1 = calc_MMR1 (020 | reg);
|
||||||
adr = ReadW (adr | ds);
|
adr = ReadW (adr | ds);
|
||||||
return (adr | dsenable);
|
return (adr | dsenable);
|
||||||
@@ -2255,7 +2265,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
|||||||
case 4: /* -(R) */
|
case 4: /* -(R) */
|
||||||
delta = 1 + (reg >= 6); /* 2 if R6, PC */
|
delta = 1 + (reg >= 6); /* 2 if R6, PC */
|
||||||
adr = R[reg] = (R[reg] - delta) & 0177777;
|
adr = R[reg] = (R[reg] - delta) & 0177777;
|
||||||
if (update_MM && (reg != 7))
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 ((((-delta) & 037) << 3) | reg);
|
MMR1 = calc_MMR1 ((((-delta) & 037) << 3) | reg);
|
||||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (adr);
|
set_stack_trap (adr);
|
||||||
@@ -2263,7 +2273,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
|||||||
|
|
||||||
case 5: /* @-(R) */
|
case 5: /* @-(R) */
|
||||||
adr = R[reg] = (R[reg] - 2) & 0177777;
|
adr = R[reg] = (R[reg] - 2) & 0177777;
|
||||||
if (update_MM && (reg != 7))
|
if (update_MM)
|
||||||
MMR1 = calc_MMR1 (0360 | reg);
|
MMR1 = calc_MMR1 (0360 | reg);
|
||||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (adr);
|
set_stack_trap (adr);
|
||||||
@@ -2749,7 +2759,8 @@ switch ((pa >> 1) & 3) { /* decode pa<2:1> */
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /* MMR1 */
|
case 2: /* MMR1 */
|
||||||
*data = MMR1;
|
MMR1 = clean_MMR1 (MMR1); /* clean up MMR1 */
|
||||||
|
*data = MMR1; /* return data */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /* MMR2 */
|
case 3: /* MMR2 */
|
||||||
@@ -2795,6 +2806,29 @@ dsenable = calc_ds (cm);
|
|||||||
return SCPE_OK;
|
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:
|
/* PARs and PDRs. These are grouped in I/O space as follows:
|
||||||
|
|
||||||
17772200 - 17772276 supervisor block
|
17772200 - 17772276 supervisor block
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
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)
|
||||||
28-May-18 RMS Fixed FPCHG macro to avoid undefined operation (Mark Pizzolato)
|
28-May-18 RMS Fixed FPCHG macro to avoid undefined operation (Mark Pizzolato)
|
||||||
24-Mar-15 RMS MMR1 does not track register changes (Johnny Billquist)
|
24-Mar-15 RMS MMR1 does not track register changes (Johnny Billquist)
|
||||||
20-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist)
|
20-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist)
|
||||||
@@ -248,9 +249,10 @@ static const uint32 and_mask[33] = { 0,
|
|||||||
int32 backup_PC;
|
int32 backup_PC;
|
||||||
int32 fp_change;
|
int32 fp_change;
|
||||||
|
|
||||||
int32 fpnotrap (int32 code);
|
t_bool fpnotrap (int32 code);
|
||||||
int32 GeteaFW (int32 spec);
|
int32 GeteaFW (int32 spec);
|
||||||
int32 GeteaFP (int32 spec, int32 len);
|
int32 GeteaFP (int32 spec, int32 len);
|
||||||
|
void fp_reg_change (int32 len, int32 reg);
|
||||||
uint32 ReadI (int32 addr, int32 spec, int32 len);
|
uint32 ReadI (int32 addr, int32 spec, int32 len);
|
||||||
t_bool ReadFP (fpac_t *fac, 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);
|
void WriteI (int32 data, int32 addr, int32 spec, int32 len);
|
||||||
@@ -603,33 +605,25 @@ switch (spec >> 3) { /* decode spec<5:3> */
|
|||||||
|
|
||||||
case 2: /* (R)+ */
|
case 2: /* (R)+ */
|
||||||
adr = R[reg]; /* post increment */
|
adr = R[reg]; /* post increment */
|
||||||
if (reg == 7) /* commit PC chg now */
|
fp_reg_change (2, reg); /* update */
|
||||||
R[reg] = (R[reg] + 2) & 0177777;
|
|
||||||
else fp_change = FPCHG (2, reg); /* others, update later */
|
|
||||||
return (adr | ds);
|
return (adr | ds);
|
||||||
|
|
||||||
case 3: /* @(R)+ */
|
case 3: /* @(R)+ */
|
||||||
adr = R[reg]; /* post increment */
|
adr = R[reg]; /* post increment */
|
||||||
if (reg == 7) /* commit PC chg now */
|
fp_reg_change (2, reg); /* update */
|
||||||
R[reg] = (R[reg] + 2) & 0177777;
|
|
||||||
else fp_change = FPCHG (2, reg); /* others, update later */
|
|
||||||
adr = ReadW (adr | ds);
|
adr = ReadW (adr | ds);
|
||||||
return (adr | dsenable);
|
return (adr | dsenable);
|
||||||
|
|
||||||
case 4: /* -(R) */
|
case 4: /* -(R) */
|
||||||
adr = (R[reg] - 2) & 0177777; /* predecrement */
|
adr = (R[reg] - 2) & 0177777; /* predecrement */
|
||||||
if (reg == 7) /* commit PC chg now */
|
fp_reg_change (-2, reg); /* update */
|
||||||
R[reg] = adr;
|
|
||||||
else fp_change = FPCHG (-2, reg); /* others, update later */
|
|
||||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (adr);
|
set_stack_trap (adr);
|
||||||
return (adr | ds);
|
return (adr | ds);
|
||||||
|
|
||||||
case 5: /* @-(R) */
|
case 5: /* @-(R) */
|
||||||
adr = (R[reg] - 2) & 0177777; /* predecrement */
|
adr = (R[reg] - 2) & 0177777; /* predecrement */
|
||||||
if (reg == 7) /* commit PC chg now */
|
fp_reg_change (-2, reg); /* update */
|
||||||
R[reg] = adr;
|
|
||||||
else fp_change = FPCHG (-2, reg); /* others, update later */
|
|
||||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (adr);
|
set_stack_trap (adr);
|
||||||
adr = ReadW (adr | ds);
|
adr = ReadW (adr | ds);
|
||||||
@@ -684,33 +678,27 @@ switch (spec >> 3) { /* case on spec */
|
|||||||
|
|
||||||
case 2: /* (R)+ */
|
case 2: /* (R)+ */
|
||||||
adr = R[reg]; /* post increment */
|
adr = R[reg]; /* post increment */
|
||||||
if (reg == 7) /* commit PC chg now */
|
if (reg == 7) /* # is always length 2 */
|
||||||
R[reg] = (R[reg] + 2) & 0177777;
|
len = 2;
|
||||||
else fp_change = FPCHG (len, reg); /* others, update later */
|
fp_reg_change (len, reg); /* update */
|
||||||
return (adr | ds);
|
return (adr | ds);
|
||||||
|
|
||||||
case 3: /* @(R)+ */
|
case 3: /* @(R)+ */
|
||||||
adr = R[reg]; /* post increment */
|
adr = R[reg]; /* post increment */
|
||||||
if (reg == 7) /* commit PC chg now */
|
fp_reg_change (2, reg); /* update */
|
||||||
R[reg] = (R[reg] + 2) & 0177777;
|
|
||||||
else fp_change = FPCHG (2, reg); /* others, update later */
|
|
||||||
adr = ReadW (adr | ds);
|
adr = ReadW (adr | ds);
|
||||||
return (adr | dsenable);
|
return (adr | dsenable);
|
||||||
|
|
||||||
case 4: /* -(R) */
|
case 4: /* -(R) */
|
||||||
adr = (R[reg] - len) & 0177777; /* predecrement */
|
adr = (R[reg] - len) & 0177777; /* predecrement */
|
||||||
if (reg == 7) /* commit PC chg now */
|
fp_reg_change (-len, reg); /* update */
|
||||||
R[reg] = adr;
|
|
||||||
else fp_change = FPCHG (-len, reg); /* others, udpate later */
|
|
||||||
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (adr);
|
set_stack_trap (adr);
|
||||||
return (adr | ds);
|
return (adr | ds);
|
||||||
|
|
||||||
case 5: /* @-(R) */
|
case 5: /* @-(R) */
|
||||||
adr = (R[reg] - 2) & 0177777; /* predecrement */
|
adr = (R[reg] - 2) & 0177777; /* predecrement */
|
||||||
if (reg == 7) /* commit PC chg now */
|
fp_reg_change (-2, reg); /* update */
|
||||||
R[reg] = adr;
|
|
||||||
else fp_change = FPCHG (-2, reg); /* others, update later */
|
|
||||||
if ((reg == 6) && (cm == MD_KER) && ((adr - 2) < (STKLIM + STKL_Y)))
|
if ((reg == 6) && (cm == MD_KER) && ((adr - 2) < (STKLIM + STKL_Y)))
|
||||||
set_stack_trap (adr);
|
set_stack_trap (adr);
|
||||||
adr = ReadW (adr | ds);
|
adr = ReadW (adr | ds);
|
||||||
@@ -731,6 +719,35 @@ switch (spec >> 3) { /* case on spec */
|
|||||||
return 0;
|
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
|
/* Read integer operand
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
@@ -782,10 +799,12 @@ else {
|
|||||||
(ReadW (exta | ((VA + 6) & 0177777)) << FP_V_F3);
|
(ReadW (exta | ((VA + 6) & 0177777)) << FP_V_F3);
|
||||||
else fptr->l = 0;
|
else fptr->l = 0;
|
||||||
}
|
}
|
||||||
if ((GET_SIGN (fptr->h) != 0) &&
|
if ((GET_SIGN (fptr->h) != 0) && /* undef variable? */
|
||||||
(GET_EXP (fptr->h) == 0) &&
|
(GET_EXP (fptr->h) == 0) &&
|
||||||
(fpnotrap (FEC_UNDFV) == 0))
|
!fpnotrap (FEC_UNDFV)) { /* trap enabled? */
|
||||||
return FALSE;
|
fp_change = 0; /* J11, no reg changes */
|
||||||
|
return FALSE; /* NOP instruction */
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1332,7 +1351,7 @@ return 0;
|
|||||||
int = FALSE if interrupt enabled, TRUE if disabled
|
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 };
|
static const int32 test_code[] = { 0, 0, 0, FPS_IC, FPS_IV, FPS_IU, FPS_IUV };
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user