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",