From 4bd2eb72de438c4202f6cf6b76d1357a3a668636 Mon Sep 17 00:00:00 2001 From: Mark Emmer Date: Mon, 2 Feb 2015 21:00:05 -0600 Subject: [PATCH] SDS: Corrections to memory trap logic 1. In sim_instr, if an Unauthorized Memory Access trap occurs, the code was enforcing the 940 Reference Manual's admonition that: "The instruction in the trap location must be a MARK PLACE AND BRANCH (BRM) instruction." Normally there is a BRM TRAPM in location 041, but when exploring a memory trap, the TSS monitor code at CEX (SMEM) temporarily puts a BRU CEX2+1 in location 041. Clearly the hardware allows BRU in the trap transfer vector, because the system uses that feature. Change simulator to allow BRM or BRU in Unauthorized Memory Access Trap vector word in location 041. 2. Page 17 of the 940 reference manual specifies special actions when the target address of a BRU, BRX, BRM or BRR instruction cannot be accessed because it's not in the memory map. The simulator was not doing this, causing TRAPM to operate with the address of the BR? instruction instead of its target address. The result was to allocate a page of zeros, which then trapped when the branch completed and transferred to a HLT instruction. By modifying the code in sds_cpu.c to provide the correct trap address, monitor code TRAPM does not allocate a page, and instead allows any user-defined trap to fire off. This fixes the problem with DDT, which relies on this trap to then map in the DDT SBREK page to 34000 and then complete the transfer to it for command processing. --- SDS/sds_cpu.c | 45 +++++++++++++++++++++++++++++++++++++-------- SDS/sds_defs.h | 4 ++-- SDS/sds_sys.c | 2 +- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/SDS/sds_cpu.c b/SDS/sds_cpu.c index 7537cfc8..798a534a 100644 --- a/SDS/sds_cpu.c +++ b/SDS/sds_cpu.c @@ -216,7 +216,7 @@ void Mul48 (uint32 mplc, uint32 mplr); void Div48 (uint32 dvdh, uint32 dvdl, uint32 dvr); void RotR48 (uint32 sc); void ShfR48 (uint32 sc, uint32 sgn); -t_stat one_inst (uint32 inst, uint32 pc, uint32 mode); +t_stat one_inst (uint32 inst, uint32 pc, uint32 mode, uint32 *trappc); void inst_hist (uint32 inst, uint32 pc, uint32 typ); t_stat rtc_inst (uint32 inst); t_stat rtc_svc (UNIT *uptr); @@ -357,7 +357,7 @@ static const uint32 int_vec[32] = { t_stat sim_instr (void) { -uint32 inst, tinst, pa, save_P, save_mode; +uint32 inst, tinst, pa, save_P, save_mode, trap_P, tmp; t_stat reason, tr; /* Restore register state */ @@ -410,7 +410,7 @@ while (reason == 0) { /* loop until halted */ if (hst_lnt) /* record inst */ inst_hist (tinst, P, HIST_INT); if (pa != VEC_RTCP) { /* normal intr? */ - tr = one_inst (tinst, P, save_mode); /* exec intr inst */ + tr = one_inst (tinst, P, save_mode, &tmp); /* exec intr inst */ if (tr) { /* stop code? */ cpu_mode = save_mode; /* restore mode */ reason = (tr > 0)? tr: STOP_MMINT; @@ -463,7 +463,7 @@ while (reason == 0) { /* loop until halted */ ion_defer = 0; /* clear ion */ if (hst_lnt) inst_hist (inst, save_P, HIST_XCT); - reason = one_inst (inst, save_P, cpu_mode); /* exec inst */ + reason = one_inst (inst, save_P, cpu_mode, &trap_P); /* exec inst */ if (reason > 0) { /* stop code? */ if (reason != STOP_HALT) P = save_P; @@ -472,12 +472,13 @@ while (reason == 0) { /* loop until halted */ } } /* end if r == 0 */ if (reason < 0) { /* mm (fet or ex)? */ + int8 op; pa = -reason; /* get vector */ if (reason == MM_MONUSR) /* record P of user-mode */ save_P = P; /* transition point */ - reason = 0; /* defang */ tinst = ReadP (pa); /* get inst */ - if (I_GETOP (tinst) != BRM) { /* not BRM? */ + op = I_GETOP (tinst); + if (op != BRM && op != BRU) { /* not BRM or BRU? */ reason = STOP_TRPINS; /* fatal err */ break; } @@ -486,13 +487,20 @@ while (reason == 0) { /* loop until halted */ mon_usr_trap = 0; if (hst_lnt) inst_hist (tinst, save_P, HIST_TRP); - tr = one_inst (tinst, save_P, save_mode); /* trap inst */ + + /* Use previously recorded trap address if memory acccess trap. + Will differ from save_P if trapped instruction was a branch. + See page 17 of 940 reference manual for additional info. + */ + tr = one_inst (tinst, (reason == MM_NOACC)? + trap_P: save_P, save_mode, &tmp); /* trap address */ if (tr) { /* stop code? */ cpu_mode = save_mode; /* restore mode */ P = save_P; /* restore PC */ reason = (tr > 0)? tr: STOP_MMTRP; break; } + reason = 0; /* defang */ } /* end if reason */ } /* end else int */ } /* end while */ @@ -505,13 +513,14 @@ return reason; /* Simulate one instruction */ -t_stat one_inst (uint32 inst, uint32 pc, uint32 mode) +t_stat one_inst (uint32 inst, uint32 pc, uint32 mode, uint32 *trappc) { uint32 op, shf_op, va, dat; uint32 old_A, old_B, old_X; int32 i, exu_cnt, sc; t_stat r; +*trappc = pc; /* default trap pc to pc */ exu_cnt = 0; /* init EXU count */ EXU_LOOP: op = I_GETOP (inst); /* get opcode */ @@ -813,7 +822,11 @@ switch (op) { /* case on opcode */ if ((r = Ea (inst, &va))) /* decode eff addr */ return r; if ((r = Read (va, &dat))) /* get operand */ + { + if (r == MM_NOACC) + *trappc = va & VA_MASK; /* use target as trap adr */ return r; + } PCQ_ENTRY; P = va & VA_MASK; /* branch */ if ((va & VA_USR) && (cpu_mode == MON_MODE)) { /* user ref from mon. mode? */ @@ -829,7 +842,11 @@ switch (op) { /* case on opcode */ X = (X + 1) & DMASK; /* incr X */ if (X & I_IND) { /* bit 9 set? */ if ((r = Read (va, &dat))) /* test dest access */ + { + if (r == MM_NOACC) + *trappc = va & VA_MASK; /* use target as trap adr */ return r; + } PCQ_ENTRY; P = va & VA_MASK; /* branch */ if ((va & VA_USR) && (cpu_mode == MON_MODE)) { /* user ref from mon. mode? */ @@ -848,7 +865,11 @@ switch (op) { /* case on opcode */ dat = dat | ((mode == USR_MODE) << 23) | (OV << 21); else dat = dat | (OV << 23); /* normal or user */ if ((r = Write (va, dat))) /* write ret word */ + { + if (r == MM_NOACC) + *trappc = va & VA_MASK; /* use target as trap adr */ return r; + } PCQ_ENTRY; P = (va + 1) & VA_MASK; /* branch */ if ((va & VA_USR) && (cpu_mode == MON_MODE)) { /* user ref from mon. mode? */ @@ -862,7 +883,11 @@ switch (op) { /* case on opcode */ if ((r = Ea (inst, &va))) /* decode eff addr */ return r; if ((r = Read (va, &dat))) /* get operand */ + { + if (r == MM_NOACC) + *trappc = va & VA_MASK; /* use target as trap adr */ return r; + } PCQ_ENTRY; P = (dat + 1) & VA_MASK; /* branch */ if (cpu_mode == MON_MODE) { /* monitor mode? */ @@ -882,7 +907,11 @@ switch (op) { /* case on opcode */ if ((r = Ea (inst, &va))) /* decode eff addr */ return r; if ((r = Read (va, &dat))) /* get operand */ + { + if (r == MM_NOACC) + *trappc = va & VA_MASK; /* use target as trap adr */ return r; + } api_dismiss (); /* dismiss hi api */ PCQ_ENTRY; P = dat & VA_MASK; /* branch */ diff --git a/SDS/sds_defs.h b/SDS/sds_defs.h index 00795efa..6654a73b 100644 --- a/SDS/sds_defs.h +++ b/SDS/sds_defs.h @@ -48,8 +48,8 @@ #define STOP_EXULIM 8 /* EXU limit */ #define STOP_MMINT 9 /* mm in intr */ #define STOP_MMTRP 10 /* mm in trap */ -#define STOP_TRPINS 11 /* trap inst not BRM */ -#define STOP_RTCINS 12 /* rtc inst not MIN/SKR */ +#define STOP_TRPINS 11 /* trap inst not BRM or BRU */ +#define STOP_RTCINS 12 /* rtc inst not MIN or SKR */ #define STOP_ILLVEC 13 /* zero vector */ #define STOP_CCT 14 /* runaway CCT */ #define STOP_MBKPT 15 /* monitor-mode breakpoint */ diff --git a/SDS/sds_sys.c b/SDS/sds_sys.c index 4cc33e34..8d216a80 100644 --- a/SDS/sds_sys.c +++ b/SDS/sds_sys.c @@ -94,7 +94,7 @@ const char *sim_stop_messages[] = { "Nested EXU's exceed limit", "Memory management trap during interrupt", "Memory management trap during trap", - "Trap instruction not BRM", + "Trap instruction not BRM or BRU", "RTC instruction not MIN or SKR", "Interrupt vector zero", "Runaway carriage control tape",