From 5270c4411796cd64ebbcf2b848a1b5a7f3806f82 Mon Sep 17 00:00:00 2001 From: Mark Emmer Date: Sun, 2 Mar 2014 22:21:13 -0600 Subject: [PATCH] SDS: Fix bugs in Monitor-to-User Transition 1. When transitioning from monitor to user mode with the trap enabled, the trap was latching the monitor address of the transferring branch rather than the user-mode address of the branch target. 2. When executing a BRU, BRX or BRM in monitor mode, if the effective address was in user mode, the code neglected to transition the machine to user mode. And after doing so, it is necessary to check for an armed monitor-to-user trap. Also removed superfluous trailing blanks from lines in file. --- SDS/sds_cpu.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/SDS/sds_cpu.c b/SDS/sds_cpu.c index c80ce356..78fe8ede 100644 --- a/SDS/sds_cpu.c +++ b/SDS/sds_cpu.c @@ -448,6 +448,8 @@ while (reason == 0) { /* loop until halted */ } /* end if r == 0 */ if (reason < 0) { /* mm (fet or ex)? */ 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? */ @@ -505,7 +507,7 @@ if (inst & I_POP) { /* POP? */ if ((r = Write (0, dat))) return r; } - } + } else { /* mon mode */ dat = (OV << 21) | dat; /* ov in <2> */ WriteP (0, dat); /* store return */ @@ -776,7 +778,7 @@ switch (op) { /* case on opcode */ return r; inst = dat; goto EXU_LOOP; - + case BRU: if (nml_mode && (inst & I_IND)) api_dismiss (); /* normal BRU*, dism */ if ((r = Ea (inst, &va))) /* decode eff addr */ @@ -785,6 +787,11 @@ switch (op) { /* case on opcode */ return r; PCQ_ENTRY; P = va & VA_MASK; /* branch */ + if ((va & VA_USR) && !nml_mode && !usr_mode) { /* user ref from mon. mode? */ + usr_mode = 1; /* transition to user mode */ + if (mon_usr_trap) + return MM_MONUSR; + } break; case BRX: @@ -796,6 +803,11 @@ switch (op) { /* case on opcode */ return r; PCQ_ENTRY; P = va & VA_MASK; /* branch */ + if ((va & VA_USR) && !nml_mode && !usr_mode) { /* user ref from mon. mode? */ + usr_mode = 1; /* transition to user mode */ + if (mon_usr_trap) + return MM_MONUSR; + } } break; @@ -810,6 +822,11 @@ switch (op) { /* case on opcode */ return r; PCQ_ENTRY; P = (va + 1) & VA_MASK; /* branch */ + if ((va & VA_USR) && !nml_mode && !usr_mode) { /* user ref from mon. mode? */ + usr_mode = 1; /* transition to user mode */ + if (mon_usr_trap) + return MM_MONUSR; + } break; case BRR: @@ -1191,7 +1208,7 @@ uint32 nml = nml_mode, usr = usr_mode; uint32 pa, pgn, map; if (sw & SWMASK ('N')) /* -n: normal */ - nml = 1; + nml = 1; else if (sw & SWMASK ('X')) /* -x: mon */ nml = usr = 0; else if (sw & SWMASK ('U')) { /* -u: user */ @@ -1269,7 +1286,7 @@ return; /* Divide - the SDS 940 uses a non-restoring divide. The algorithm runs even for overflow cases. Hence it must be emulated precisely - to give the right answers for diagnostics. If the dividend is + to give the right answers for diagnostics. If the dividend is negative, AB are 2's complemented starting at B<22>, and B<23> is unchanged. */