| 1 | /* pdp10_cpu.c: PDP-10 CPU simulator\r |
| 2 | \r |
| 3 | Copyright (c) 1993-2007, Robert M. Supnik\r |
| 4 | \r |
| 5 | Permission is hereby granted, free of charge, to any person obtaining a\r |
| 6 | copy of this software and associated documentation files (the "Software"),\r |
| 7 | to deal in the Software without restriction, including without limitation\r |
| 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense,\r |
| 9 | and/or sell copies of the Software, and to permit persons to whom the\r |
| 10 | Software is furnished to do so, subject to the following conditions:\r |
| 11 | \r |
| 12 | The above copyright notice and this permission notice shall be included in\r |
| 13 | all copies or substantial portions of the Software.\r |
| 14 | \r |
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r |
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r |
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r |
| 18 | ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r |
| 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r |
| 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r |
| 21 | \r |
| 22 | Except as contained in this notice, the name of Robert M Supnik shall not be\r |
| 23 | used in advertising or otherwise to promote the sale, use or other dealings\r |
| 24 | in this Software without prior written authorization from Robert M Supnik.\r |
| 25 | \r |
| 26 | cpu KS10 central processor\r |
| 27 | \r |
| 28 | 17-Jul-07 RMS Fixed non-portable usage in SHOW HISTORY\r |
| 29 | 28-Apr-07 RMS Removed clock initialization\r |
| 30 | 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)\r |
| 31 | Fixed warning in MOVNI\r |
| 32 | 16-Aug-05 RMS Fixed C++ declaration and cast problems\r |
| 33 | 10-Nov-04 RMS Added instruction history\r |
| 34 | 08-Oct-02 RMS Revised to build dib_tab dynamically\r |
| 35 | Added SHOW IOSPACE\r |
| 36 | 30-Dec-01 RMS Added old PC queue\r |
| 37 | 25-Dec-01 RMS Cleaned up sim_inst declarations\r |
| 38 | 07-Dec-01 RMS Revised to use new breakpoint package\r |
| 39 | 21-Nov-01 RMS Implemented ITS 1-proceed hack\r |
| 40 | 31-Aug-01 RMS Changed int64 to t_int64 for Windoze\r |
| 41 | 10-Aug-01 RMS Removed register in declarations\r |
| 42 | 17-Jul-01 RMS Moved function prototype\r |
| 43 | 19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug\r |
| 44 | 29-Apr-01 RMS Fixed modifier naming conflict\r |
| 45 | Fixed XCTR/XCTRI, UMOVE/UMOVEM, BLTUB/BLTBU for ITS\r |
| 46 | Added CLRCSH for ITS\r |
| 47 | \r |
| 48 | The 36b system family had six different implementions: PDP-6, KA10, KI10,\r |
| 49 | L10, KL10 extended, and KS10. This simulator implements the KS10.\r |
| 50 | \r |
| 51 | The register state for the KS10 is:\r |
| 52 | \r |
| 53 | AC[8][16] accumulators\r |
| 54 | PC program counter\r |
| 55 | flags<0:11> state flags\r |
| 56 | pi_enb<1:7> enabled PI levels\r |
| 57 | pi_act<1:7> active PI levels\r |
| 58 | pi_prq<1:7> program PI requests\r |
| 59 | apr_enb<0:7> enabled system flags\r |
| 60 | apr_flg<0:7> system flags\r |
| 61 | ebr executive base register\r |
| 62 | ubr user base register\r |
| 63 | hsb halt status block address\r |
| 64 | spt SPT base\r |
| 65 | cst CST base\r |
| 66 | pur process use register\r |
| 67 | cstm CST mask\r |
| 68 | \r |
| 69 | The PDP-10 had just two instruction formats: memory reference\r |
| 70 | and I/O.\r |
| 71 | \r |
| 72 | 000000000 0111 1 1111 112222222222333333\r |
| 73 | 012345678 9012 3 4567 890123456789012345\r |
| 74 | +---------+----+-+----+------------------+\r |
| 75 | | opcode | ac |i| idx| address | memory reference\r |
| 76 | +---------+----+-+----+------------------+\r |
| 77 | \r |
| 78 | 000 0000000 111 1 1111 112222222222333333\r |
| 79 | 012 3456789 012 3 4567 890123456789012345\r |
| 80 | +---+-------+---+-+----+------------------+\r |
| 81 | |111|device |iop|i| idx| address | I/O\r |
| 82 | +---+-------+---+-+----+------------------+\r |
| 83 | \r |
| 84 | This routine is the instruction decode routine for the PDP-10.\r |
| 85 | It is called from the simulator control program to execute\r |
| 86 | instructions in simulated memory, starting at the simulated PC.\r |
| 87 | It runs until an abort occurs.\r |
| 88 | \r |
| 89 | General notes:\r |
| 90 | \r |
| 91 | 1. Reasons to stop. The simulator can be stopped by:\r |
| 92 | \r |
| 93 | HALT instruction\r |
| 94 | MUUO instruction in executive mode\r |
| 95 | pager error in interrupt sequence\r |
| 96 | invalid vector table in interrupt sequence\r |
| 97 | illegal instruction in interrupt sequence\r |
| 98 | breakpoint encountered\r |
| 99 | nested indirects exceeding limit\r |
| 100 | nested XCT's exceeding limit\r |
| 101 | I/O error in I/O simulator\r |
| 102 | \r |
| 103 | 2. Interrupts. PDP-10's have a seven level priority interrupt\r |
| 104 | system. Interrupt requests can come from internal sources,\r |
| 105 | such as APR program requests, or external sources, such as\r |
| 106 | I/O devices. The requests are stored in pi_prq for program\r |
| 107 | requests, pi_apr for other internal flags, and pi_ioq for\r |
| 108 | I/O device flags. Internal and device (but not program)\r |
| 109 | interrupts must be enabled on a level by level basis. When\r |
| 110 | an interrupt is granted on a level, interrupts at that level\r |
| 111 | and below are masked until the interrupt is dismissed.\r |
| 112 | \r |
| 113 | The I/O device interrupt system is taken from the PDP-11.\r |
| 114 | int_req stores the interrupt requests for Unibus I/O devices.\r |
| 115 | Routines in the Unibus adapter map requests in int_req to\r |
| 116 | PDP-10 levels. The Unibus adapter also calculates which\r |
| 117 | device to get a vector from when a PDP-10 interrupt is granted.\r |
| 118 | \r |
| 119 | 3. Arithmetic. The PDP-10 is a 2's complement system.\r |
| 120 | \r |
| 121 | 4. Adding I/O devices. These modules must be modified:\r |
| 122 | \r |
| 123 | pdp10_defs.h add device address and interrupt definitions\r |
| 124 | pdp10_sys.c add sim_devices table entry\r |
| 125 | \r |
| 126 | A note on ITS 1-proceed. The simulator follows the implementation\r |
| 127 | on the KS10, keeping 1-proceed as a side flag (its_1pr) rather than\r |
| 128 | as flags<8>. This simplifies the flag saving instructions, which\r |
| 129 | don't have to clear flags<8> before saving it. Instead, the page\r |
| 130 | fail and interrupt code must restore flags<8> from its_1pr. Unlike\r |
| 131 | the KS10, the simulator will not lose the 1-proceed trap if the\r |
| 132 | 1-proceeded instructions clears 1-proceed.\r |
| 133 | */\r |
| 134 | \r |
| 135 | #include "pdp10_defs.h"\r |
| 136 | #include <setjmp.h>\r |
| 137 | \r |
| 138 | #define PCQ_SIZE 64 /* must be 2**n */\r |
| 139 | #define PCQ_MASK (PCQ_SIZE - 1)\r |
| 140 | #define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC\r |
| 141 | \r |
| 142 | #define HIST_PC 0x40000000\r |
| 143 | #define HIST_MIN 64\r |
| 144 | #define HIST_MAX 65536\r |
| 145 | \r |
| 146 | typedef struct {\r |
| 147 | a10 pc;\r |
| 148 | a10 ea;\r |
| 149 | d10 ir;\r |
| 150 | d10 ac;\r |
| 151 | } InstHistory;\r |
| 152 | \r |
| 153 | d10 *M = NULL; /* memory */\r |
| 154 | d10 acs[AC_NBLK * AC_NUM] = { 0 }; /* AC blocks */\r |
| 155 | d10 *ac_cur, *ac_prv; /* AC cur, prv (dyn) */\r |
| 156 | a10 epta, upta; /* proc tbl addr (dyn) */\r |
| 157 | a10 saved_PC = 0; /* scp: saved PC */\r |
| 158 | d10 pager_word = 0; /* pager: error word */\r |
| 159 | a10 pager_PC = 0; /* pager: saved PC */\r |
| 160 | int32 pager_flags = 0; /* pager: trap flags */\r |
| 161 | t_bool pager_pi = FALSE; /* pager: in pi seq */\r |
| 162 | t_bool pager_tc = FALSE; /* pager: trap cycle */\r |
| 163 | d10 ebr = 0; /* exec base reg */\r |
| 164 | d10 ubr = 0; /* user base reg */\r |
| 165 | d10 hsb = 0; /* halt status block */\r |
| 166 | d10 spt = 0; /* TOPS20 paging regs */\r |
| 167 | d10 cst = 0;\r |
| 168 | d10 pur = 0;\r |
| 169 | d10 cstm = 0;\r |
| 170 | a10 dbr1 = 0; /* ITS paging regs */\r |
| 171 | a10 dbr2 = 0;\r |
| 172 | a10 dbr3 = 0;\r |
| 173 | a10 dbr4 = 0;\r |
| 174 | d10 pcst = 0; /* ITS PC sampling */\r |
| 175 | int32 pi_on = 0; /* pi system enable */\r |
| 176 | int32 pi_enb = 0; /* pi enabled levels */\r |
| 177 | int32 pi_act = 0; /* pi active levels */\r |
| 178 | int32 pi_ioq = 0; /* pi io requests */\r |
| 179 | int32 pi_apr = 0; /* pi apr requests */\r |
| 180 | int32 pi_prq = 0; /* pi prog requests */\r |
| 181 | int32 apr_enb = 0; /* apr enables */\r |
| 182 | int32 apr_flg = 0; /* apr flags */\r |
| 183 | int32 apr_lvl = 0; /* apr level */\r |
| 184 | int32 qintr = 0; /* interrupt pending */\r |
| 185 | int32 flags = 0; /* flags */\r |
| 186 | int32 its_1pr = 0; /* ITS 1-proceed */\r |
| 187 | int32 stop_op0 = 0; /* stop on 0 */\r |
| 188 | int32 rlog = 0; /* extend fixup log */\r |
| 189 | int32 ind_max = 32; /* nested ind limit */\r |
| 190 | int32 xct_max = 32; /* nested XCT limit */\r |
| 191 | int32 t20_idlelock = 0; /* TOPS-20 idle lock */\r |
| 192 | a10 pcq[PCQ_SIZE] = { 0 }; /* PC queue */\r |
| 193 | int32 pcq_p = 0; /* PC queue ptr */\r |
| 194 | REG *pcq_r = NULL; /* PC queue reg ptr */\r |
| 195 | jmp_buf save_env;\r |
| 196 | int32 hst_p = 0; /* history pointer */\r |
| 197 | int32 hst_lnt = 0; /* history length */\r |
| 198 | InstHistory *hst = NULL; /* instruction history */\r |
| 199 | \r |
| 200 | extern int32 sim_int_char;\r |
| 201 | extern int32 sim_interval;\r |
| 202 | extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */\r |
| 203 | \r |
| 204 | /* Forward and external declarations */\r |
| 205 | \r |
| 206 | t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);\r |
| 207 | t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);\r |
| 208 | t_stat cpu_reset (DEVICE *dptr);\r |
| 209 | t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);\r |
| 210 | t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);\r |
| 211 | d10 adjsp (d10 val, a10 ea);\r |
| 212 | void ibp (a10 ea, int32 pflgs);\r |
| 213 | d10 ldb (a10 ea, int32 pflgs);\r |
| 214 | void dpb (d10 val, a10 ea, int32 pflgs);\r |
| 215 | void adjbp (int32 ac, a10 ea, int32 pflgs);\r |
| 216 | d10 add (d10 val, d10 mb);\r |
| 217 | d10 sub (d10 val, d10 mb);\r |
| 218 | void dadd (int32 ac, d10 *rs);\r |
| 219 | void dsub (int32 ac, d10 *rs);\r |
| 220 | int32 jffo (d10 val);\r |
| 221 | d10 lsh (d10 val, a10 ea);\r |
| 222 | d10 rot (d10 val, a10 ea);\r |
| 223 | d10 ash (d10 val, a10 ea);\r |
| 224 | void lshc (int32 ac, a10 ea);\r |
| 225 | void rotc (int32 ac, a10 ea);\r |
| 226 | void ashc (int32 ac, a10 ea);\r |
| 227 | void circ (int32 ac, a10 ea);\r |
| 228 | void blt (int32 ac, a10 ea, int32 pflgs);\r |
| 229 | void bltu (int32 ac, a10 ea, int32 pflgs, int dir);\r |
| 230 | a10 calc_ea (d10 inst, int32 prv);\r |
| 231 | a10 calc_ioea (d10 inst, int32 prv);\r |
| 232 | d10 calc_jrstfea (d10 inst, int32 pflgs);\r |
| 233 | void pi_dismiss (void);\r |
| 234 | void set_newflags (d10 fl, t_bool jrst);\r |
| 235 | extern t_bool aprid (a10 ea, int32 prv);\r |
| 236 | t_bool wrpi (a10 ea, int32 prv);\r |
| 237 | t_bool rdpi (a10 ea, int32 prv);\r |
| 238 | t_bool czpi (a10 ea, int32 prv);\r |
| 239 | t_bool copi (a10 ea, int32 prv);\r |
| 240 | t_bool wrapr (a10 ea, int32 prv);\r |
| 241 | t_bool rdapr (a10 ea, int32 prv);\r |
| 242 | t_bool czapr (a10 ea, int32 prv);\r |
| 243 | t_bool coapr (a10 ea, int32 prv);\r |
| 244 | int32 pi_eval (void);\r |
| 245 | int32 test_int (void);\r |
| 246 | void set_ac_display (d10 *acbase);\r |
| 247 | \r |
| 248 | extern t_stat build_dib_tab (void);\r |
| 249 | extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc);\r |
| 250 | extern d10 Read (a10 ea, int32 prv); /* read, read check */\r |
| 251 | extern d10 ReadM (a10 ea, int32 prv); /* read, write check */\r |
| 252 | extern d10 ReadE (a10 ea); /* read, exec */\r |
| 253 | extern d10 ReadP (a10 ea); /* read, physical */\r |
| 254 | extern void Write (a10 ea, d10 val, int32 prv); /* write */\r |
| 255 | extern void WriteE (a10 ea, d10 val); /* write, exec */\r |
| 256 | extern void WriteP (a10 ea, d10 val); /* write, physical */\r |
| 257 | extern t_bool AccViol (a10 ea, int32 prv, int32 mode); /* access check */\r |
| 258 | extern void set_dyn_ptrs (void);\r |
| 259 | extern a10 conmap (a10 ea, int32 mode, int32 sw);\r |
| 260 | extern void fe_intr ();\r |
| 261 | extern void dfad (int32 ac, d10 *rs, int32 inv);\r |
| 262 | extern void dfmp (int32 ac, d10 *rs);\r |
| 263 | extern void dfdv (int32 ac, d10 *rs);\r |
| 264 | extern void dmul (int32 ac, d10 *rs);\r |
| 265 | extern void ddiv (int32 ac, d10 *rs);\r |
| 266 | extern void fix (int32 ac, d10 mb, t_bool rnd);\r |
| 267 | extern d10 fad (d10 val, d10 mb, t_bool rnd, int32 inv);\r |
| 268 | extern d10 fmp (d10 val, d10 mb, t_bool rnd);\r |
| 269 | extern t_bool fdv (d10 val, d10 mb, d10 *rs, t_bool rnd);\r |
| 270 | extern d10 fsc (d10 val, a10 ea);\r |
| 271 | extern d10 fltr (d10 mb);\r |
| 272 | extern int xtend (int32 ac, a10 ea, int32 pflgs);\r |
| 273 | extern void xtcln (int32 rlog);\r |
| 274 | extern d10 map (a10 ea, int32 prv);\r |
| 275 | extern d10 imul (d10 val, d10 mb);\r |
| 276 | extern t_bool idiv (d10 val, d10 mb, d10 *rs);\r |
| 277 | extern void mul (d10 val, d10 mb, d10 *rs);\r |
| 278 | extern t_bool divi (int32 ac, d10 mb, d10 *rs);\r |
| 279 | extern t_bool io710 (int32 ac, a10 ea);\r |
| 280 | extern t_bool io711 (int32 ac, a10 ea);\r |
| 281 | extern d10 io712 (a10 ea);\r |
| 282 | extern void io713 (d10 val, a10 ea);\r |
| 283 | extern void io714 (d10 val, a10 ea);\r |
| 284 | extern void io715 (d10 val, a10 ea);\r |
| 285 | extern t_bool io720 (int32 ac, a10 ea);\r |
| 286 | extern t_bool io721 (int32 ac, a10 ea);\r |
| 287 | extern d10 io722 (a10 ea);\r |
| 288 | extern void io723 (d10 val, a10 ea);\r |
| 289 | extern void io724 (d10 val, a10 ea);\r |
| 290 | extern void io725 (d10 val, a10 ea);\r |
| 291 | extern t_bool clrcsh (a10 ea, int32 prv);\r |
| 292 | extern t_bool clrpt (a10 ea, int32 prv);\r |
| 293 | extern t_bool wrubr (a10 ea, int32 prv);\r |
| 294 | extern t_bool wrebr (a10 ea, int32 prv);\r |
| 295 | extern t_bool wrhsb (a10 ea, int32 prv);\r |
| 296 | extern t_bool wrspb (a10 ea, int32 prv);\r |
| 297 | extern t_bool wrcsb (a10 ea, int32 prv);\r |
| 298 | extern t_bool wrpur (a10 ea, int32 prv);\r |
| 299 | extern t_bool wrcstm (a10 ea, int32 prv);\r |
| 300 | extern t_bool ldbr1 (a10 ea, int32 prv);\r |
| 301 | extern t_bool ldbr2 (a10 ea, int32 prv);\r |
| 302 | extern t_bool ldbr3 (a10 ea, int32 prv);\r |
| 303 | extern t_bool ldbr4 (a10 ea, int32 prv);\r |
| 304 | extern t_bool rdubr (a10 ea, int32 prv);\r |
| 305 | extern t_bool rdebr (a10 ea, int32 prv);\r |
| 306 | extern t_bool rdhsb (a10 ea, int32 prv);\r |
| 307 | extern t_bool rdspb (a10 ea, int32 prv);\r |
| 308 | extern t_bool rdcsb (a10 ea, int32 prv);\r |
| 309 | extern t_bool rdpur (a10 ea, int32 prv);\r |
| 310 | extern t_bool rdcstm (a10 ea, int32 prv);\r |
| 311 | extern t_bool sdbr1 (a10 ea, int32 prv);\r |
| 312 | extern t_bool sdbr2 (a10 ea, int32 prv);\r |
| 313 | extern t_bool sdbr3 (a10 ea, int32 prv);\r |
| 314 | extern t_bool sdbr4 (a10 ea, int32 prv);\r |
| 315 | extern t_bool rdtim (a10 ea, int32 prv);\r |
| 316 | extern t_bool rdint (a10 ea, int32 prv);\r |
| 317 | extern t_bool wrtim (a10 ea, int32 prv);\r |
| 318 | extern t_bool wrint (a10 ea, int32 prv);\r |
| 319 | extern t_bool rdpcst (a10 ea, int32 prv);\r |
| 320 | extern t_bool wrpcst (a10 ea, int32 prv);\r |
| 321 | extern t_bool spm (a10 ea, int32 prv);\r |
| 322 | extern t_bool lpmr (a10 ea, int32 prv);\r |
| 323 | extern int32 pi_ub_vec (int32 lvl, int32 *uba);\r |
| 324 | extern t_stat tim_set_mod (UNIT *uptr, int32 val, char *cptr, void *desc);\r |
| 325 | \r |
| 326 | /* CPU data structures\r |
| 327 | \r |
| 328 | cpu_dev CPU device descriptor\r |
| 329 | cpu_unit CPU unit\r |
| 330 | cpu_reg CPU register list\r |
| 331 | cpu_mod CPU modifier list\r |
| 332 | */\r |
| 333 | \r |
| 334 | UNIT cpu_unit = { UDATA (NULL, UNIT_FIX, MAXMEMSIZE) };\r |
| 335 | \r |
| 336 | REG cpu_reg[] = {\r |
| 337 | { ORDATA (PC, saved_PC, VASIZE) },\r |
| 338 | { ORDATA (FLAGS, flags, 18) },\r |
| 339 | { ORDATA (AC0, acs[0], 36) }, /* addr in memory */\r |
| 340 | { ORDATA (AC1, acs[1], 36) }, /* modified at exit */\r |
| 341 | { ORDATA (AC2, acs[2], 36) }, /* to SCP */\r |
| 342 | { ORDATA (AC3, acs[3], 36) },\r |
| 343 | { ORDATA (AC4, acs[4], 36) },\r |
| 344 | { ORDATA (AC5, acs[5], 36) },\r |
| 345 | { ORDATA (AC6, acs[6], 36) },\r |
| 346 | { ORDATA (AC7, acs[7], 36) },\r |
| 347 | { ORDATA (AC10, acs[10], 36) },\r |
| 348 | { ORDATA (AC11, acs[11], 36) },\r |
| 349 | { ORDATA (AC12, acs[12], 36) },\r |
| 350 | { ORDATA (AC13, acs[13], 36) },\r |
| 351 | { ORDATA (AC14, acs[14], 36) },\r |
| 352 | { ORDATA (AC15, acs[15], 36) },\r |
| 353 | { ORDATA (AC16, acs[16], 36) },\r |
| 354 | { ORDATA (AC17, acs[17], 36) },\r |
| 355 | { ORDATA (PFW, pager_word, 36) },\r |
| 356 | { ORDATA (EBR, ebr, EBR_N_EBR) },\r |
| 357 | { FLDATA (PGON, ebr, EBR_V_PGON) },\r |
| 358 | { FLDATA (T20P, ebr, EBR_V_T20P) },\r |
| 359 | { ORDATA (UBR, ubr, 36) },\r |
| 360 | { GRDATA (CURAC, ubr, 8, 3, UBR_V_CURAC), REG_RO },\r |
| 361 | { GRDATA (PRVAC, ubr, 8, 3, UBR_V_PRVAC) },\r |
| 362 | { ORDATA (SPT, spt, 36) },\r |
| 363 | { ORDATA (CST, cst, 36) },\r |
| 364 | { ORDATA (PUR, pur, 36) },\r |
| 365 | { ORDATA (CSTM, cstm, 36) },\r |
| 366 | { ORDATA (HSB, hsb, 36) },\r |
| 367 | { ORDATA (DBR1, dbr1, PASIZE) },\r |
| 368 | { ORDATA (DBR2, dbr2, PASIZE) },\r |
| 369 | { ORDATA (DBR3, dbr3, PASIZE) },\r |
| 370 | { ORDATA (DBR4, dbr4, PASIZE) },\r |
| 371 | { ORDATA (PCST, pcst, 36) }, \r |
| 372 | { ORDATA (PIENB, pi_enb, 7) },\r |
| 373 | { FLDATA (PION, pi_on, 0) },\r |
| 374 | { ORDATA (PIACT, pi_act, 7) },\r |
| 375 | { ORDATA (PIPRQ, pi_prq, 7) },\r |
| 376 | { ORDATA (PIIOQ, pi_ioq, 7), REG_RO },\r |
| 377 | { ORDATA (PIAPR, pi_apr, 7), REG_RO },\r |
| 378 | { ORDATA (APRENB, apr_enb, 8) },\r |
| 379 | { ORDATA (APRFLG, apr_flg, 8) },\r |
| 380 | { ORDATA (APRLVL, apr_lvl, 3) },\r |
| 381 | { ORDATA (RLOG, rlog, 10) },\r |
| 382 | { FLDATA (F1PR, its_1pr, 0) },\r |
| 383 | { BRDATA (PCQ, pcq, 8, VASIZE, PCQ_SIZE), REG_RO+REG_CIRC },\r |
| 384 | { ORDATA (PCQP, pcq_p, 6), REG_HRO },\r |
| 385 | { DRDATA (INDMAX, ind_max, 8), PV_LEFT + REG_NZ },\r |
| 386 | { DRDATA (XCTMAX, xct_max, 8), PV_LEFT + REG_NZ },\r |
| 387 | { ORDATA (WRU, sim_int_char, 8) },\r |
| 388 | { FLDATA (STOP_ILL, stop_op0, 0) },\r |
| 389 | { BRDATA (REG, acs, 8, 36, AC_NUM * AC_NBLK) },\r |
| 390 | { NULL }\r |
| 391 | };\r |
| 392 | \r |
| 393 | MTAB cpu_mod[] = {\r |
| 394 | { UNIT_KLAD+UNIT_ITS+UNIT_T20, 0, "TOPS-10", "TOPS-10", &tim_set_mod },\r |
| 395 | { UNIT_KLAD+UNIT_ITS+UNIT_T20, 0, NULL , "TOPS10", &tim_set_mod },\r |
| 396 | { UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_T20, "TOPS-20", "TOPS-20", &tim_set_mod },\r |
| 397 | { UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_T20, NULL, "TOPS20", &tim_set_mod },\r |
| 398 | { UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_ITS, "ITS", "ITS", &tim_set_mod },\r |
| 399 | { UNIT_KLAD+UNIT_ITS+UNIT_T20, UNIT_KLAD, "diagnostic mode", "KLAD", &tim_set_mod },\r |
| 400 | { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },\r |
| 401 | { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },\r |
| 402 | { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,\r |
| 403 | NULL, &show_iospace },\r |
| 404 | { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",\r |
| 405 | &cpu_set_hist, &cpu_show_hist },\r |
| 406 | { 0 }\r |
| 407 | };\r |
| 408 | \r |
| 409 | DEVICE cpu_dev = {\r |
| 410 | "CPU", &cpu_unit, cpu_reg, cpu_mod,\r |
| 411 | 1, 8, PASIZE, 1, 8, 36,\r |
| 412 | &cpu_ex, &cpu_dep, &cpu_reset,\r |
| 413 | NULL, NULL, NULL\r |
| 414 | };\r |
| 415 | \r |
| 416 | /* Data arrays */\r |
| 417 | \r |
| 418 | const int32 pi_l2bit[8] = {\r |
| 419 | 0, 0100, 0040, 0020, 0010, 0004, 0002, 0001\r |
| 420 | };\r |
| 421 | \r |
| 422 | const int32 pi_m2lvl[128] = {\r |
| 423 | 0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,\r |
| 424 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\r |
| 425 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r |
| 426 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\r |
| 427 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r |
| 428 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r |
| 429 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r |
| 430 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r |
| 431 | };\r |
| 432 | \r |
| 433 | const d10 bytemask[64] = { 0,\r |
| 434 | 01, 03, 07, 017, 037, 077,\r |
| 435 | 0177, 0377, 0777, 01777, 03777, 07777,\r |
| 436 | 017777, 037777, 077777,\r |
| 437 | 0177777, 0377777, 0777777,\r |
| 438 | 01777777, 03777777, 07777777,\r |
| 439 | 017777777, 037777777, 077777777,\r |
| 440 | 0177777777, 0377777777, 0777777777,\r |
| 441 | 01777777777, 03777777777, 07777777777,\r |
| 442 | 017777777777, 037777777777, 077777777777,\r |
| 443 | 0177777777777, 0377777777777, 0777777777777,\r |
| 444 | ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES,\r |
| 445 | ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES,\r |
| 446 | ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES\r |
| 447 | };\r |
| 448 | \r |
| 449 | static t_bool (*io700d[16])() = {\r |
| 450 | &aprid, NULL, NULL, NULL, &wrapr, &rdapr, &czapr, &coapr,\r |
| 451 | NULL, NULL, NULL, NULL, &wrpi, &rdpi, &czpi, &copi\r |
| 452 | };\r |
| 453 | static t_bool (*io701d[16])() = {\r |
| 454 | NULL, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL,\r |
| 455 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL\r |
| 456 | };\r |
| 457 | static t_bool (*io702d[16])() = {\r |
| 458 | &rdspb, &rdcsb, &rdpur, &rdcstm, &rdtim, &rdint, &rdhsb, NULL,\r |
| 459 | &wrspb, &wrcsb, &wrpur, &wrcstm, &wrtim, &wrint, &wrhsb, NULL\r |
| 460 | };\r |
| 461 | #define io700i io700d\r |
| 462 | static t_bool (*io701i[16])() = {\r |
| 463 | &clrcsh, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL,\r |
| 464 | NULL, &rdpcst, NULL, &wrpcst, NULL, NULL, NULL, NULL\r |
| 465 | };\r |
| 466 | static t_bool (*io702i[16])() = {\r |
| 467 | &sdbr1, &sdbr2, &sdbr3, &sdbr4, &rdtim, &rdint, &rdhsb, &spm,\r |
| 468 | &ldbr1, &ldbr2, &ldbr3, &ldbr4, &wrtim, &wrint, &wrhsb, &lpmr\r |
| 469 | };\r |
| 470 | \r |
| 471 | /* JRST classes and validation table */\r |
| 472 | \r |
| 473 | #define JRST_U 1 /* ok anywhere */\r |
| 474 | #define JRST_E 2 /* ok exec mode */\r |
| 475 | #define JRST_UIO 3 /* ok user I/O mode */\r |
| 476 | \r |
| 477 | static t_stat jrst_tab[16] = {\r |
| 478 | JRST_U, JRST_U, JRST_U, 0, JRST_E, JRST_U, JRST_E, JRST_E,\r |
| 479 | JRST_UIO, 0, JRST_UIO, 0, JRST_E, JRST_U, 0, 0\r |
| 480 | };\r |
| 481 | \r |
| 482 | /* Address operations */\r |
| 483 | \r |
| 484 | #define IM ((d10) ea)\r |
| 485 | #define IMS (((d10) ea) << 18)\r |
| 486 | #define JUMP(x) PCQ_ENTRY, PC = ((a10) (x)) & AMASK\r |
| 487 | #define SUBJ(x) CLRF (F_AFI | F_FPD | F_TR); JUMP (x)\r |
| 488 | #define INCPC PC = INCA (PC)\r |
| 489 | \r |
| 490 | /* AC operations */\r |
| 491 | \r |
| 492 | #define AOBAC AC(ac) = AOB (AC(ac))\r |
| 493 | #define SOBAC AC(ac) = SOB (AC(ac))\r |
| 494 | #define G2AC rs[0] = AC(ac), rs[1] = AC(P1)\r |
| 495 | #define S1AC AC(ac) = rs[0]\r |
| 496 | #define S2AC S1AC, AC(P1) = rs[1]\r |
| 497 | #define LAC if (ac) AC(ac) = mb\r |
| 498 | \r |
| 499 | /* Memory operations */\r |
| 500 | \r |
| 501 | #define RD mb = Read (ea, MM_OPND)\r |
| 502 | #define RDAC AC(ac) = Read (ea, MM_OPND)\r |
| 503 | #define RM mb = ReadM (ea, MM_OPND)\r |
| 504 | #define RMAC AC(ac) = ReadM (ea, MM_OPND)\r |
| 505 | #define RDP mb = Read (((a10) AC(ac)) & AMASK, MM_BSTK)\r |
| 506 | #define RD2 rs[0] = Read (ea, MM_OPND); \\r |
| 507 | rs[1] = Read (INCA (ea), MM_OPND)\r |
| 508 | #define WR Write (ea, mb, MM_OPND)\r |
| 509 | #define WRAC Write (ea, AC(ac), MM_OPND)\r |
| 510 | #define WRP(x) Write (((a10) INCA (AC(ac))), (x), MM_BSTK)\r |
| 511 | #define WR1 Write (ea, rs[0], MM_OPND)\r |
| 512 | #define WR2 ReadM (INCA (ea), MM_OPND); \\r |
| 513 | Write (ea, rs[0], MM_OPND); \\r |
| 514 | Write (INCA (ea), rs[1], MM_OPND)\r |
| 515 | \r |
| 516 | /* Tests and compares */\r |
| 517 | \r |
| 518 | #define TL(a) (TSTS (a) != 0)\r |
| 519 | #define TE(a) ((a) == 0)\r |
| 520 | #define TLE(a) (TL (a) || TE (a))\r |
| 521 | #define TGE(a) (TSTS (a) == 0)\r |
| 522 | #define TN(a) ((a) != 0)\r |
| 523 | #define TG(a) (TGE (a) && TN (a))\r |
| 524 | #define CL(a) ((TSTS (AC(ac) ^ a))? (a < AC(ac)): (AC(ac) < a))\r |
| 525 | #define CE(a) (AC(ac) == a)\r |
| 526 | #define CLE(a) (CL (a) || CE (a))\r |
| 527 | #define CGE(a) (!CL (a))\r |
| 528 | #define CN(a) (AC(ac) != a)\r |
| 529 | #define CG(a) (CGE (a) && CN (a))\r |
| 530 | \r |
| 531 | /* Word assemblies */\r |
| 532 | \r |
| 533 | #define FLPC XWD (flags, PC)\r |
| 534 | #define UUOWORD (((d10) op) << INST_V_OP) | (((d10) ac) << INST_V_AC) | ea\r |
| 535 | #define APRHWORD ((apr_flg << APR_V_FLG) | (apr_lvl & APR_M_LVL) | \\r |
| 536 | ((apr_flg & apr_enb)? APR_IRQ: 0))\r |
| 537 | #define APRWORD ((apr_enb << (APR_V_FLG + 18)) | APRHWORD)\r |
| 538 | #define PIHWORD ((pi_act << PI_V_ACT) | (pi_on << PI_V_ON) | \\r |
| 539 | (pi_enb << PI_V_ENB))\r |
| 540 | #define PIWORD ((pi_prq << PI_V_PRQ) | PIHWORD)\r |
| 541 | \r |
| 542 | /* Instruction operations */\r |
| 543 | \r |
| 544 | #define CIBP if (!TSTF (F_FPD)) { ibp (ea, pflgs); SETF (F_FPD); }\r |
| 545 | #define LDB AC(ac) = ldb (ea, pflgs)\r |
| 546 | #define DPB dpb (AC(ac), ea, pflgs)\r |
| 547 | #define FAD(s) fad (AC(ac), s, FALSE, 0)\r |
| 548 | #define FADR(s) fad (AC(ac), s, TRUE, 0)\r |
| 549 | #define FSB(s) fad (AC(ac), s, FALSE, 1)\r |
| 550 | #define FSBR(s) fad (AC(ac), s, TRUE, 1)\r |
| 551 | #define FMP(s) fmp (AC(ac), s, FALSE)\r |
| 552 | #define FMPR(s) fmp (AC(ac), s, TRUE)\r |
| 553 | #define FDV(s) fdv (AC(ac), s, rs, FALSE)\r |
| 554 | #define FDVR(s) fdv (AC(ac), s, rs, TRUE)\r |
| 555 | #define MOVN(s) NEG (s); MOVNF(s)\r |
| 556 | #define MOVM(s) ABS (s); MOVMF(s)\r |
| 557 | #define ADD(s) add (AC(ac), s)\r |
| 558 | #define SUB(s) sub (AC(ac), s)\r |
| 559 | #define IMUL(s) imul (AC(ac), s)\r |
| 560 | #define IDIV(s) idiv (AC(ac), s, rs)\r |
| 561 | #define MUL(s) mul (AC(ac), s, rs)\r |
| 562 | #define DIV(s) divi (ac, s, rs)\r |
| 563 | #define AOJ AC(ac) = INC (AC(ac)); INCF (AC(ac))\r |
| 564 | #define AOS RM; mb = INC (mb); WR; INCF (mb); LAC\r |
| 565 | #define SOJ AC(ac) = DEC (AC(ac)); DECF (AC(ac))\r |
| 566 | #define SOS RM; mb = DEC (mb); WR; DECF (mb); LAC\r |
| 567 | #define SETCA(s) ~AC(ac) & DMASK\r |
| 568 | #define SETCM(s) ~(s) & DMASK;\r |
| 569 | #define AND(s) AC(ac) & (s)\r |
| 570 | #define ANDCA(s) ~AC(ac) & (s)\r |
| 571 | #define ANDCM(s) AC(ac) & ~(s)\r |
| 572 | #define ANDCB(s) (~AC(ac) & ~(s)) & DMASK\r |
| 573 | #define IOR(s) AC(ac) | (s)\r |
| 574 | #define ORCA(s) (~AC(ac) | (s)) & DMASK\r |
| 575 | #define ORCM(s) (AC(ac) | ~(s)) & DMASK\r |
| 576 | #define ORCB(s) (~AC(ac) | ~(s)) & DMASK\r |
| 577 | #define XOR(s) AC(ac) ^ (s)\r |
| 578 | #define EQV(s) (~(AC(ac) ^ (s))) & DMASK\r |
| 579 | #define LL(s,d) ((s) & LMASK) | ((d) & RMASK)\r |
| 580 | #define RL(s,d) (((s) << 18) & LMASK) | ((d) & RMASK)\r |
| 581 | #define RR(s,d) ((s) & RMASK) | ((d) & LMASK)\r |
| 582 | #define LR(s,d) (((s) >> 18) & RMASK) | ((d) & LMASK)\r |
| 583 | #define LLO(s) ((s) & LMASK) | RMASK\r |
| 584 | #define RLO(s) (((s) << 18) & LMASK) | RMASK\r |
| 585 | #define RRO(s) ((s) & RMASK) | LMASK\r |
| 586 | #define LRO(s) (((s) >> 18) & RMASK) | LMASK\r |
| 587 | #define LLE(s) ((s) & LMASK) | (((s) & LSIGN)? RMASK: 0)\r |
| 588 | #define RLE(s) (((s) << 18) & LMASK) | (((s) & RSIGN)? RMASK: 0)\r |
| 589 | #define RRE(s) ((s) & RMASK) | (((s) & RSIGN)? LMASK: 0)\r |
| 590 | #define LRE(s) (((s) >> 18) & RMASK) | (((s) & LSIGN)? LMASK: 0)\r |
| 591 | #define TD_ RD\r |
| 592 | #define TS_ RD; mb = SWP (mb)\r |
| 593 | #define TL_ mb = IMS\r |
| 594 | #define TR_ mb = IM\r |
| 595 | #define T_Z AC(ac) = AC(ac) & ~mb\r |
| 596 | #define T_O AC(ac) = AC(ac) | mb\r |
| 597 | #define T_C AC(ac) = AC(ac) ^ mb\r |
| 598 | #define T__E if ((AC(ac) & mb) == 0) INCPC\r |
| 599 | #define T__N if ((AC(ac) & mb) != 0) INCPC\r |
| 600 | #define T__A INCPC\r |
| 601 | #define IOC if (TSTF (F_USR) && !TSTF (F_UIO)) goto MUUO;\r |
| 602 | #define IO7(x,y) IOC; fptr = ((Q_ITS)? x[ac]: y[ac]); \\r |
| 603 | if (fptr == NULL) goto MUUO; \\r |
| 604 | if (fptr (ea, MM_OPND)) INCPC; break;\r |
| 605 | #define IOA IOC; if (!Q_ITS) ea = calc_ioea (inst, pflgs)\r |
| 606 | #define IOAM IOC; ea = ((Q_ITS)? ((a10) Read (ea, MM_OPND)): \\r |
| 607 | calc_ioea (inst, pflgs))\r |
| 608 | \r |
| 609 | /* Flag tests */\r |
| 610 | \r |
| 611 | #define MOVNF(x) if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1); \\r |
| 612 | else if ((x) == 0) SETF (F_C0 | F_C1)\r |
| 613 | #define MOVMF(x) if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1)\r |
| 614 | #define INCF(x) if ((x) == 0) SETF (F_C0 | F_C1); \\r |
| 615 | else if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1)\r |
| 616 | #define DECF(x) if ((x) == MAXPOS) SETF (F_C0 | F_AOV | F_T1); \\r |
| 617 | else if ((x) != ONES) SETF (F_C0 | F_C1)\r |
| 618 | #define PUSHF if (LRZ (AC(ac)) == 0) SETF (F_T2)\r |
| 619 | #define POPF if (LRZ (AC(ac)) == RMASK) SETF (F_T2)\r |
| 620 | #define DMOVNF if (rs[1] == 0) { MOVNF (rs[0]); }\r |
| 621 | \r |
| 622 | t_stat sim_instr (void)\r |
| 623 | {\r |
| 624 | a10 PC; /* set by setjmp */\r |
| 625 | int abortval = 0; /* abort value */\r |
| 626 | t_stat r;\r |
| 627 | \r |
| 628 | /* Restore register state */\r |
| 629 | \r |
| 630 | if ((r = build_dib_tab ()) != SCPE_OK) return r; /* build, chk dib_tab */\r |
| 631 | pager_PC = PC = saved_PC & AMASK; /* load local PC */\r |
| 632 | set_dyn_ptrs (); /* set up local ptrs */\r |
| 633 | pager_tc = FALSE; /* not in trap cycle */\r |
| 634 | pager_pi = FALSE; /* not in pi sequence */\r |
| 635 | rlog = 0; /* not in extend */\r |
| 636 | pi_eval (); /* eval pi system */\r |
| 637 | if (!Q_ITS) its_1pr = 0; /* ~ITS, clr 1-proc */\r |
| 638 | t20_idlelock = 0; /* clr T20 idle lock */\r |
| 639 | \r |
| 640 | /* Abort handling\r |
| 641 | \r |
| 642 | Aborts may come from within the simulator to stop simulation (values > 0),\r |
| 643 | for page fails (values < 0), or for an interrupt check (value = 0).\r |
| 644 | */\r |
| 645 | \r |
| 646 | abortval = setjmp (save_env); /* set abort hdlr */\r |
| 647 | if ((abortval > 0) || pager_pi) { /* stop or pi err? */\r |
| 648 | if (pager_pi && (abortval == PAGE_FAIL))\r |
| 649 | abortval = STOP_PAGINT; /* stop for pi err */\r |
| 650 | saved_PC = pager_PC & AMASK; /* failing instr PC */\r |
| 651 | set_ac_display (ac_cur); /* set up AC display */\r |
| 652 | pcq_r->qptr = pcq_p; /* update pc q ptr */\r |
| 653 | return abortval; /* return to SCP */\r |
| 654 | }\r |
| 655 | \r |
| 656 | /* Page fail - checked against KS10 ucode\r |
| 657 | All state variables MUST be declared global for GCC optimization to work\r |
| 658 | */\r |
| 659 | \r |
| 660 | else if (abortval == PAGE_FAIL) { /* page fail */\r |
| 661 | d10 mb;\r |
| 662 | if (rlog) xtcln (rlog); /* clean up extend */\r |
| 663 | rlog = 0; /* clear log */\r |
| 664 | if (pager_tc) flags = pager_flags; /* trap? get flags */\r |
| 665 | if (T20PAG) { /* TOPS-20 paging? */\r |
| 666 | WriteP (upta + UPT_T20_PFL, pager_word); /* write page fail wd */\r |
| 667 | WriteP (upta + UPT_T20_OFL, XWD (flags, 0));\r |
| 668 | WriteP (upta + UPT_T20_OPC, pager_PC);\r |
| 669 | mb = ReadP (upta + UPT_T20_NPC);\r |
| 670 | }\r |
| 671 | else {\r |
| 672 | a10 ea; /* TOPS-10 or ITS */\r |
| 673 | if (Q_ITS) { /* ITS? */\r |
| 674 | ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3);\r |
| 675 | if (its_1pr) flags = flags | F_1PR; /* store 1-proc */\r |
| 676 | its_1pr = 0; /* clear 1-proc */\r |
| 677 | }\r |
| 678 | else ea = upta + UPT_T10_PAG;\r |
| 679 | WriteP (ea, pager_word); /* write page fail wd */\r |
| 680 | WriteP (ADDA (ea, 1), XWD (flags, pager_PC));\r |
| 681 | mb = ReadP (ADDA (ea, 2));\r |
| 682 | }\r |
| 683 | JUMP (mb); /* set new PC */\r |
| 684 | set_newflags (mb, FALSE); /* set new flags */\r |
| 685 | pi_eval (); /* eval pi system */\r |
| 686 | }\r |
| 687 | else PC = pager_PC; /* intr, restore PC */\r |
| 688 | \r |
| 689 | /* Main instruction fetch/decode loop: check clock queue, intr, trap, bkpt */\r |
| 690 | \r |
| 691 | for ( ;; ) { /* loop until ABORT */\r |
| 692 | int32 op, ac, i, st, xr, xct_cnt, its_2pr, pflgs;\r |
| 693 | a10 ea;\r |
| 694 | d10 inst, mb, indrct, rs[2];\r |
| 695 | t_bool (*fptr)();\r |
| 696 | \r |
| 697 | pager_PC = PC; /* update pager PC */\r |
| 698 | pager_tc = FALSE; /* not in trap cycle */\r |
| 699 | pflgs = 0; /* not in PXCT */\r |
| 700 | xct_cnt = 0; /* count XCT's */\r |
| 701 | if (sim_interval <= 0) { /* check clock queue */\r |
| 702 | if (i = sim_process_event ()) ABORT (i); /* error? stop sim */\r |
| 703 | pi_eval (); /* eval pi system */\r |
| 704 | }\r |
| 705 | \r |
| 706 | /* PI interrupt (Unibus or system flags).\r |
| 707 | On the KS10, only JSR and XPCW are allowed as interrupt instructions.\r |
| 708 | Because of exec mode addressing, and unconditional processing of flags,\r |
| 709 | they are explicitly emulated here.\r |
| 710 | */\r |
| 711 | \r |
| 712 | if (qintr) {\r |
| 713 | int32 vec, uba;\r |
| 714 | pager_pi = TRUE; /* flag in pi seq */\r |
| 715 | if (vec = pi_ub_vec (qintr, &uba)) { /* Unibus interrupt? */\r |
| 716 | mb = ReadP (epta + EPT_UBIT + uba); /* get dispatch table */\r |
| 717 | if (mb == 0) ABORT (STOP_ZERINT); /* invalid? stop */\r |
| 718 | inst = ReadE ((((a10) mb) + (vec / 4)) & AMASK);\r |
| 719 | if (inst == 0) ABORT (STOP_ZERINT);\r |
| 720 | }\r |
| 721 | else inst = ReadP (epta + EPT_PIIT + (2 * qintr));\r |
| 722 | op = GET_OP (inst); /* get opcode */\r |
| 723 | ac = GET_AC (inst); /* get ac */\r |
| 724 | if (its_1pr && Q_ITS) { /* 1-proc set? */\r |
| 725 | flags = flags | F_1PR; /* store 1-proc */\r |
| 726 | its_1pr = 0; /* clear 1-proc */\r |
| 727 | }\r |
| 728 | if (op == OP_JSR) { /* JSR? */\r |
| 729 | ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */\r |
| 730 | WriteE (ea, FLPC); /* save flags+PC, exec */\r |
| 731 | JUMP (INCA (ea)); /* PC = ea + 1 */\r |
| 732 | set_newflags (0, FALSE); /* set new flags */\r |
| 733 | }\r |
| 734 | else if ((op == OP_JRST) && (ac == AC_XPCW)) { /* XPCW? */\r |
| 735 | ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */\r |
| 736 | WriteE (ea, XWD (flags, 0)); /* write flags, exec */\r |
| 737 | WriteE (ADDA (ea, 1), PC); /* write PC, exec */\r |
| 738 | rs[0] = ReadE (ADDA (ea, 2)); /* read new flags */\r |
| 739 | rs[1] = ReadE (ADDA (ea, 3)); /* read new PC */\r |
| 740 | JUMP (rs[1]); /* set new PC */\r |
| 741 | set_newflags (rs[0], FALSE); /* set new flags */\r |
| 742 | }\r |
| 743 | else ABORT (STOP_ILLINT); /* invalid instr */\r |
| 744 | pi_act = pi_act | pi_l2bit[qintr]; /* set level active */\r |
| 745 | pi_eval (); /* eval pi system */\r |
| 746 | pager_pi = FALSE; /* end of sequence */\r |
| 747 | if (sim_interval) sim_interval--; /* charge for instr */\r |
| 748 | continue;\r |
| 749 | } /* end if interrupt */\r |
| 750 | \r |
| 751 | /* Traps fetch and execute an instruction from the current mode process table.\r |
| 752 | On the KS10, the fetch of the next instruction has started, and a page fail\r |
| 753 | trap on the instruction fetch takes precedence over the trap. During a trap,\r |
| 754 | flags are cleared before the execute, but if the execute aborts, they must\r |
| 755 | be restored. Also, the MUUO processor needs to know whether we are in a\r |
| 756 | trap sequence. Hence, trap in progress is recorded in pflgs, and the\r |
| 757 | traps for pager restoration are recorded in pager_flags.\r |
| 758 | */\r |
| 759 | \r |
| 760 | if (TSTF (F_T1 | F_T2) && PAGING) {\r |
| 761 | Read (pager_PC = PC, MM_CUR); /* test fetch */\r |
| 762 | pager_tc = TRUE; /* in a trap sequence */\r |
| 763 | pager_flags = flags; /* save flags */\r |
| 764 | ea = (TSTF (F_USR)? upta + UPT_TRBASE: epta + EPT_TRBASE)\r |
| 765 | + GET_TRAPS (flags);\r |
| 766 | inst = ReadP (ea); /* get trap instr */\r |
| 767 | CLRF (F_T1 | F_T2); /* clear flags */\r |
| 768 | }\r |
| 769 | \r |
| 770 | /* Test for instruction breakpoint */\r |
| 771 | \r |
| 772 | else {\r |
| 773 | if (sim_brk_summ &&\r |
| 774 | sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */\r |
| 775 | ABORT (STOP_IBKPT); /* stop simulation */\r |
| 776 | }\r |
| 777 | \r |
| 778 | /* Ready (at last) to get an instruction */\r |
| 779 | \r |
| 780 | inst = Read (pager_PC = PC, MM_CUR); /* get instruction */\r |
| 781 | INCPC; \r |
| 782 | sim_interval = sim_interval - 1;\r |
| 783 | }\r |
| 784 | \r |
| 785 | its_2pr = its_1pr; /* save 1-proc flag */\r |
| 786 | \r |
| 787 | /* Execute instruction. XCT and PXCT also return here. */\r |
| 788 | \r |
| 789 | XCT:\r |
| 790 | op = GET_OP (inst); /* get opcode */\r |
| 791 | ac = GET_AC (inst); /* get AC */\r |
| 792 | for (indrct = inst, i = 0; i < ind_max; i++) { /* calc eff addr */\r |
| 793 | ea = GET_ADDR (indrct);\r |
| 794 | xr = GET_XR (indrct);\r |
| 795 | if (xr) ea = (ea + ((a10) XR (xr, MM_EA))) & AMASK;\r |
| 796 | if (TST_IND (indrct)) indrct = Read (ea, MM_EA);\r |
| 797 | else break;\r |
| 798 | }\r |
| 799 | if (i >= ind_max)\r |
| 800 | ABORT (STOP_IND); /* too many ind? stop */\r |
| 801 | if (hst_lnt) { /* history enabled? */\r |
| 802 | hst_p = (hst_p + 1); /* next entry */\r |
| 803 | if (hst_p >= hst_lnt) hst_p = 0;\r |
| 804 | hst[hst_p].pc = pager_PC | HIST_PC;\r |
| 805 | hst[hst_p].ea = ea;\r |
| 806 | hst[hst_p].ir = inst;\r |
| 807 | hst[hst_p].ac = AC(ac);\r |
| 808 | }\r |
| 809 | switch (op) { /* case on opcode */\r |
| 810 | \r |
| 811 | /* UUO's (0000 - 0077) - checked against KS10 ucode */\r |
| 812 | \r |
| 813 | case 0000: if (stop_op0) { ABORT (STOP_ILLEG); }\r |
| 814 | goto MUUO;\r |
| 815 | case 0001: /* local UUO's */\r |
| 816 | case 0002:\r |
| 817 | case 0003:\r |
| 818 | case 0004:\r |
| 819 | case 0005:\r |
| 820 | case 0006:\r |
| 821 | case 0007:\r |
| 822 | case 0010:\r |
| 823 | case 0011:\r |
| 824 | case 0012:\r |
| 825 | case 0013:\r |
| 826 | case 0014:\r |
| 827 | case 0015:\r |
| 828 | case 0016:\r |
| 829 | case 0017:\r |
| 830 | case 0020:\r |
| 831 | case 0021:\r |
| 832 | case 0022:\r |
| 833 | case 0023:\r |
| 834 | case 0024:\r |
| 835 | case 0025:\r |
| 836 | case 0026:\r |
| 837 | case 0027:\r |
| 838 | case 0030:\r |
| 839 | case 0031:\r |
| 840 | case 0032:\r |
| 841 | case 0033:\r |
| 842 | case 0034:\r |
| 843 | case 0035:\r |
| 844 | case 0036:\r |
| 845 | case 0037: Write (040, UUOWORD, MM_CUR); /* store op, ac, ea */\r |
| 846 | inst = Read (041, MM_CUR); /* get new instr */\r |
| 847 | goto XCT;\r |
| 848 | \r |
| 849 | /* case 0040 - 0077: MUUO's, handled by default at end of case */\r |
| 850 | \r |
| 851 | /* Floating point, bytes, multiple precision (0100 - 0177) */\r |
| 852 | \r |
| 853 | /* case 0100: MUUO /* UJEN */\r |
| 854 | /* case 0101: MUUO /* unassigned */\r |
| 855 | case 0102: if (Q_ITS && !TSTF (F_USR)) { /* GFAD (KL), XCTRI (ITS) */\r |
| 856 | inst = Read (ea, MM_OPND);\r |
| 857 | pflgs = pflgs | ac; goto XCT;\r |
| 858 | }\r |
| 859 | goto MUUO;\r |
| 860 | case 0103: if (Q_ITS && !TSTF (F_USR)) { /* GFSB (KL), XCTR (ITS) */\r |
| 861 | inst = Read (ea, MM_OPND);\r |
| 862 | pflgs = pflgs | ac; goto XCT;\r |
| 863 | }\r |
| 864 | goto MUUO;\r |
| 865 | /* case 0104: MUUO /* JSYS (T20) */\r |
| 866 | case 0105: AC(ac) = adjsp (AC(ac), ea); break; /* ADJSP */\r |
| 867 | /* case 0106: MUUO /* GFMP (KL)*/\r |
| 868 | /* case 0107: MUUO /* GFDV (KL) */\r |
| 869 | case 0110: RD2; dfad (ac, rs, 0); break; /* DFAD */\r |
| 870 | case 0111: RD2; dfad (ac, rs, 1); break; /* DFSB */\r |
| 871 | case 0112: RD2; dfmp (ac, rs); break; /* DFMP */\r |
| 872 | case 0113: RD2; dfdv (ac, rs); break; /* DFDV */\r |
| 873 | case 0114: RD2; dadd (ac, rs); break; /* DADD */\r |
| 874 | case 0115: RD2; dsub (ac, rs); break; /* DSUB */\r |
| 875 | case 0116: RD2; dmul (ac, rs); break; /* DMUL */\r |
| 876 | case 0117: RD2; ddiv (ac, rs); break; /* DDIV */\r |
| 877 | case 0120: RD2; S2AC; break; /* DMOVE */\r |
| 878 | case 0121: RD2; DMOVN (rs); S2AC; DMOVNF; break; /* DMOVN */\r |
| 879 | case 0122: RD; fix(ac, mb, 0); break; /* FIX */\r |
| 880 | case 0123: st = xtend (ac, ea, pflgs); /* EXTEND */\r |
| 881 | rlog = 0; /* clear log */\r |
| 882 | switch (st) {\r |
| 883 | case XT_SKIP:\r |
| 884 | INCPC;\r |
| 885 | case XT_NOSK:\r |
| 886 | break;\r |
| 887 | default:\r |
| 888 | goto MUUO;\r |
| 889 | }\r |
| 890 | break;\r |
| 891 | case 0124: G2AC; WR2; break; /* DMOVEM */\r |
| 892 | case 0125: G2AC; DMOVN (rs); WR2; DMOVNF; break; /* DMOVNM */\r |
| 893 | case 0126: RD; fix (ac, mb, 1); break; /* FIXR */\r |
| 894 | case 0127: RD; AC(ac) = fltr (mb); break; /* FLTR */\r |
| 895 | /* case 0130: MUUO /* UFA */\r |
| 896 | /* case 0131: MUUO /* DFN */\r |
| 897 | case 0132: AC(ac) = fsc (AC(ac), ea); break; /* FSC */\r |
| 898 | case 0133: if (!ac) ibp (ea, pflgs); /* IBP */\r |
| 899 | else adjbp (ac, ea, pflgs); break;\r |
| 900 | case 0134: CIBP; LDB; CLRF (F_FPD); break; /* ILBP */\r |
| 901 | case 0135: LDB; break; /* LDB */\r |
| 902 | case 0136: CIBP; DPB; CLRF (F_FPD); break; /* IDBP */\r |
| 903 | case 0137: DPB; break; /* DPB */\r |
| 904 | case 0140: RD; AC(ac) = FAD (mb); break; /* FAD */\r |
| 905 | /* case 0141: MUUO /* FADL */\r |
| 906 | case 0142: RM; mb = FAD (mb); WR; break; /* FADM */\r |
| 907 | case 0143: RM; AC(ac) = FAD (mb); WRAC; break; /* FADB */\r |
| 908 | case 0144: RD; AC(ac) = FADR (mb); break; /* FADR */\r |
| 909 | case 0145: AC(ac) = FADR (IMS); break; /* FADRI */\r |
| 910 | case 0146: RM; mb = FADR (mb); WR; break; /* FADRM */\r |
| 911 | case 0147: RM; AC(ac) = FADR (mb); WRAC; break; /* FADRB */\r |
| 912 | case 0150: RD; AC(ac) = FSB (mb); break; /* FSB */\r |
| 913 | /* case 0151: MUUO /* FSBL */\r |
| 914 | case 0152: RM; mb = FSB (mb); WR; break; /* FSBM */\r |
| 915 | case 0153: RM; AC(ac) = FSB (mb); WRAC; break; /* FSBB */\r |
| 916 | case 0154: RD; AC(ac) = FSBR (mb); break; /* FSBR */\r |
| 917 | case 0155: AC(ac) = FSBR (IMS); break; /* FSBRI */\r |
| 918 | case 0156: RM; mb = FSBR (mb); WR; break; /* FSBRM */\r |
| 919 | case 0157: RM; AC(ac) = FSBR (mb); WRAC; break; /* FSBRB */\r |
| 920 | case 0160: RD; AC(ac) = FMP (mb); break; /* FMP */\r |
| 921 | /* case 0161: MUUO /* FMPL */\r |
| 922 | case 0162: RM; mb = FMP (mb); WR; break; /* FMPM */\r |
| 923 | case 0163: RM; AC(ac) = FMP (mb); WRAC; break; /* FMPB */\r |
| 924 | case 0164: RD; AC(ac) = FMPR (mb); break; /* FMPR */\r |
| 925 | case 0165: AC(ac) = FMPR (IMS); break; /* FMPRI */\r |
| 926 | case 0166: RM; mb = FMPR (mb); WR; break; /* FMPRM */\r |
| 927 | case 0167: RM; AC(ac) = FMPR (mb); WRAC; break; /* FMPRB */\r |
| 928 | case 0170: RD; if (FDV (mb)) S1AC; break; /* FDV */\r |
| 929 | /* case 0171: MUUO /* FDVL */\r |
| 930 | case 0172: RM; if (FDV (mb)) WR1; break; /* FDVM */\r |
| 931 | case 0173: RM; if (FDV (mb)) { S1AC; WRAC; } break; /* FDVB */\r |
| 932 | case 0174: RD; if (FDVR (mb)) S1AC; break; /* FDVR */\r |
| 933 | case 0175: if (FDVR (IMS)) S1AC; break; /* FDVRI */\r |
| 934 | case 0176: RM; if (FDVR (mb)) WR1; break; /* FDVRM */\r |
| 935 | case 0177: RM; if (FDVR (mb)) { S1AC; WRAC; } break; /* FDVRB */\r |
| 936 | \r |
| 937 | /* Move, arithmetic, shift, and jump (0200 - 0277)\r |
| 938 | \r |
| 939 | Note that instructions which modify the flags and store a\r |
| 940 | result in memory must prove the writeability of the result\r |
| 941 | location before modifying the flags. Also, 0247 and 0257,\r |
| 942 | if not implemented, are nops, not MUUO's.\r |
| 943 | */\r |
| 944 | \r |
| 945 | case 0200: RDAC; break; /* MOVE */\r |
| 946 | case 0201: AC(ac) = ea; break; /* MOVEI */\r |
| 947 | case 0202: WRAC; break; /* MOVEM */\r |
| 948 | case 0203: RM; LAC; break; /* MOVES */\r |
| 949 | case 0204: RD; AC(ac) = SWP (mb); break; /* MOVS */\r |
| 950 | case 0205: AC(ac) = IMS; break; /* MOVSI */\r |
| 951 | case 0206: mb = SWP (AC(ac)); WR; break; /* MOVSM */\r |
| 952 | case 0207: RM; mb = SWP (mb); WR; LAC; break; /* MOVSS */\r |
| 953 | case 0210: RD; AC(ac) = MOVN (mb); break; /* MOVN */\r |
| 954 | case 0211: AC(ac) = NEG (IM); /* MOVNI */\r |
| 955 | if (AC(ac) == 0) SETF (F_C0 | F_C1); break;\r |
| 956 | case 0212: RM; mb = MOVN (AC(ac)); WR; break; /* MOVNM */\r |
| 957 | case 0213: RM; mb = MOVN (mb); WR; LAC; break; /* MOVNS */\r |
| 958 | case 0214: RD; AC(ac) = MOVM (mb); break; /* MOVM */\r |
| 959 | case 0215: AC(ac) = ea; break; /* MOVMI */\r |
| 960 | case 0216: RM; mb = MOVM (AC(ac)); WR; break; /* MOVMM */\r |
| 961 | case 0217: RM; mb = MOVM (mb); WR; LAC; break; /* MOVMS */\r |
| 962 | case 0220: RD; AC(ac) = IMUL (mb); break; /* IMUL */\r |
| 963 | case 0221: AC(ac) = IMUL (IM); break; /* IMULI */\r |
| 964 | case 0222: RM; mb = IMUL (mb); WR; break; /* IMULM */\r |
| 965 | case 0223: RM; AC(ac) = IMUL (mb); WRAC; break; /* IMULB */\r |
| 966 | case 0224: RD; MUL (mb); S2AC; break; /* MUL */\r |
| 967 | case 0225: MUL (IM); S2AC; break; /* MULI */\r |
| 968 | case 0226: RM; MUL (mb); WR1; break; /* MULM */\r |
| 969 | case 0227: RM; MUL (mb); WR1; S2AC; break; /* MULB */\r |
| 970 | case 0230: RD; if (IDIV (mb)) S2AC; break; /* IDIV */\r |
| 971 | case 0231: if (IDIV (IM)) S2AC; break; /* IDIVI */\r |
| 972 | case 0232: RM; if (IDIV (mb)) WR1; break; /* IDIVM */\r |
| 973 | case 0233: RM; if (IDIV (mb)) { WR1; S2AC; } break; /* IDIVB */\r |
| 974 | case 0234: RD; if (DIV (mb)) S2AC; break; /* DIV */\r |
| 975 | case 0235: if (DIV (IM)) S2AC; break; /* DIVI */\r |
| 976 | case 0236: RM; if (DIV (mb)) WR1; break; /* DIVM */\r |
| 977 | case 0237: RM; if (DIV (mb)) { WR1; S2AC; } break; /* DIVB */\r |
| 978 | case 0240: AC(ac) = ash (AC(ac), ea); break; /* ASH */\r |
| 979 | case 0241: AC(ac) = rot (AC(ac), ea); break; /* ROT */\r |
| 980 | case 0242: AC(ac) = lsh (AC(ac), ea); break; /* LSH */\r |
| 981 | case 0243: AC(P1) = jffo (AC(ac)); /* JFFO */\r |
| 982 | if (AC(ac)) JUMP (ea); break;\r |
| 983 | case 0244: ashc (ac, ea); break; /* ASHC */\r |
| 984 | case 0245: rotc (ac, ea); break; /* ROTC */\r |
| 985 | case 0246: lshc (ac, ea); break; /* LSHC */\r |
| 986 | case 0247: if (Q_ITS) circ (ac, ea); break; /* (ITS) CIRC */\r |
| 987 | case 0250: RM; WRAC; AC(ac) = mb; break; /* EXCH */\r |
| 988 | case 0251: blt (ac, ea, pflgs); break; /* BLT */\r |
| 989 | case 0252: AOBAC; if (TGE (AC(ac))) JUMP (ea); break; /* AOBJP */\r |
| 990 | case 0253: AOBAC; if (TL (AC(ac))) JUMP (ea); break; /* AOBJN */\r |
| 991 | /* case 0254: /* shown later /* JRST */\r |
| 992 | case 0255: if (flags & (ac << 14)) { /* JFCL */\r |
| 993 | JUMP (ea);\r |
| 994 | CLRF (ac << 14);\r |
| 995 | }\r |
| 996 | break;\r |
| 997 | case 0256: if (xct_cnt++ >= xct_max) /* XCT */\r |
| 998 | ABORT (STOP_XCT);\r |
| 999 | inst = Read (ea, MM_OPND);\r |
| 1000 | if (ac && !TSTF (F_USR) && !Q_ITS)\r |
| 1001 | pflgs = pflgs | ac;\r |
| 1002 | goto XCT;\r |
| 1003 | case 0257: if (Q_ITS) goto MUUO; /* MAP */\r |
| 1004 | AC(ac) = map (ea, MM_OPND); break;\r |
| 1005 | case 0260: WRP (FLPC); AOBAC; /* PUSHJ */\r |
| 1006 | SUBJ (ea); PUSHF; break;\r |
| 1007 | case 0261: RD; WRP (mb); AOBAC; PUSHF; break; /* PUSH */\r |
| 1008 | case 0262: RDP; WR; SOBAC; POPF; break; /* POP */\r |
| 1009 | case 0263: RDP; JUMP (mb); SOBAC; POPF; break; /* POPJ */\r |
| 1010 | case 0264: Write (ea, FLPC, MM_OPND); /* JSR */\r |
| 1011 | SUBJ (INCR (ea)); break;\r |
| 1012 | case 0265: AC(ac) = FLPC; SUBJ (ea); break; /* JSP */\r |
| 1013 | case 0266: WRAC; AC(ac) = XWD (ea, PC); /* JSA */\r |
| 1014 | JUMP (INCR (ea)); break;\r |
| 1015 | case 0267: AC(ac) = Read ((a10) LRZ (AC(ac)), MM_OPND);/* JRA */\r |
| 1016 | JUMP (ea); break;\r |
| 1017 | case 0270: RD; AC(ac) = ADD (mb); break; /* ADD */\r |
| 1018 | case 0271: AC(ac) = ADD (IM); break; /* ADDI */\r |
| 1019 | case 0272: RM; mb = ADD (mb); WR; break; /* ADDM */\r |
| 1020 | case 0273: RM; AC(ac) = ADD (mb); WRAC; break; /* ADDB */\r |
| 1021 | case 0274: RD; AC(ac) = SUB (mb); break; /* SUB */\r |
| 1022 | case 0275: AC(ac) = SUB (IM); break; /* SUBI */\r |
| 1023 | case 0276: RM; mb = SUB (mb); WR; break; /* SUBM */\r |
| 1024 | case 0277: RM; AC(ac) = SUB (mb); WRAC; break; /* SUBB */\r |
| 1025 | \r |
| 1026 | /* Compare, jump, skip instructions (0300 - 0377) - checked against KS10 ucode */\r |
| 1027 | \r |
| 1028 | case 0300: break; /* CAI */\r |
| 1029 | case 0301: if (CL (IM)) INCPC; break; /* CAIL */\r |
| 1030 | case 0302: if (CE (IM)) INCPC; break; /* CAIE */\r |
| 1031 | case 0303: if (CLE (IM)) INCPC; break; /* CAILE */\r |
| 1032 | case 0304: INCPC; break; /* CAIA */\r |
| 1033 | case 0305: if (CGE (IM)) INCPC; break; /* CAIGE */\r |
| 1034 | case 0306: if (CN (IM)) INCPC; break; /* CAIN */\r |
| 1035 | case 0307: if (CG (IM)) INCPC; break; /* CAIG */\r |
| 1036 | case 0310: RD; break; /* CAM */\r |
| 1037 | case 0311: RD; if (CL (mb)) INCPC; break; /* CAML */\r |
| 1038 | case 0312: RD; if (CE (mb)) INCPC; break; /* CAME */\r |
| 1039 | case 0313: RD; if (CLE (mb)) INCPC; break; /* CAMLE */\r |
| 1040 | case 0314: RD; INCPC; break; /* CAMA */\r |
| 1041 | case 0315: RD; if (CGE (mb)) INCPC; break; /* CAMGE */\r |
| 1042 | case 0316: RD; if (CN (mb)) INCPC; break; /* CAMN */\r |
| 1043 | case 0317: RD; if (CG (mb)) INCPC; break; /* CAMG */\r |
| 1044 | case 0320: break; /* JUMP */\r |
| 1045 | case 0321: if (TL (AC(ac))) JUMP (ea); break; /* JUMPL */\r |
| 1046 | case 0322: if (TE (AC(ac))) JUMP (ea); break; /* JUMPE */\r |
| 1047 | case 0323: if (TLE( AC(ac))) JUMP (ea); break; /* JUMPLE */\r |
| 1048 | case 0324: JUMP (ea); break; /* JUMPA */\r |
| 1049 | case 0325: if (TGE (AC(ac))) JUMP (ea); break; /* JUMPGE */\r |
| 1050 | case 0326: if (TN (AC(ac))) JUMP (ea); break; /* JUMPN */\r |
| 1051 | case 0327: if (TG (AC(ac))) JUMP (ea); break; /* JUMPG */\r |
| 1052 | case 0330: RD; LAC; break; /* SKIP */\r |
| 1053 | case 0331: RD; LAC; if (TL (mb)) INCPC; break; /* SKIPL */\r |
| 1054 | case 0332: RD; LAC; if (TE (mb)) INCPC; break; /* SKIPE */\r |
| 1055 | case 0333: RD; LAC; if (TLE (mb)) INCPC; break; /* SKIPLE */\r |
| 1056 | case 0334: RD; LAC; INCPC; break; /* SKIPA */\r |
| 1057 | case 0335: RD; LAC; if (TGE (mb)) INCPC; break; /* SKIPGE */\r |
| 1058 | case 0336: RD; LAC; if (TN (mb)) INCPC; break; /* SKIPN */\r |
| 1059 | case 0337: RD; LAC; if (TG (mb)) INCPC; break; /* SKIPG */\r |
| 1060 | case 0340: AOJ; break; /* AOJ */\r |
| 1061 | case 0341: AOJ; if (TL (AC(ac))) JUMP (ea); break; /* AOJL */\r |
| 1062 | case 0342: AOJ; if (TE (AC(ac))) JUMP (ea); break; /* AOJE */\r |
| 1063 | case 0343: AOJ; if (TLE (AC(ac))) JUMP (ea); break; /* AOJLE */\r |
| 1064 | case 0344: AOJ; JUMP(ea); /* AOJA */\r |
| 1065 | if (Q_ITS && Q_IDLE && /* ITS idle? */\r |
| 1066 | TSTF (F_USR) && (pager_PC == 017) && /* user mode, loc 17? */\r |
| 1067 | (ac == 0) && (ea == 017)) /* AOJA 0,17? */\r |
| 1068 | sim_idle (0, FALSE);\r |
| 1069 | break;\r |
| 1070 | case 0345: AOJ; if (TGE (AC(ac))) JUMP (ea); break; /* AOJGE */\r |
| 1071 | case 0346: AOJ; if (TN (AC(ac))) JUMP (ea); break; /* AOJN */\r |
| 1072 | case 0347: AOJ; if (TG (AC(ac))) JUMP (ea); break; /* AOJG */\r |
| 1073 | case 0350: AOS; break; /* AOS */\r |
| 1074 | case 0351: AOS; if (TL (mb)) INCPC; break; /* AOSL */\r |
| 1075 | case 0352: AOS; if (TE (mb)) INCPC; break; /* AOSE */\r |
| 1076 | case 0353: AOS; if (TLE (mb)) INCPC; break; /* AOSLE */\r |
| 1077 | case 0354: AOS; INCPC; break; /* AOSA */\r |
| 1078 | case 0355: AOS; if (TGE (mb)) INCPC; break; /* AOSGE */\r |
| 1079 | case 0356: AOS; if (TN (mb)) INCPC; break; /* AOSN */\r |
| 1080 | case 0357: AOS; if (TG (mb)) INCPC; break; /* AOSG */\r |
| 1081 | case 0360: SOJ; break; /* SOJ */\r |
| 1082 | case 0361: SOJ; if (TL (AC(ac))) JUMP (ea); break; /* SOJL */\r |
| 1083 | case 0362: SOJ; if (TE (AC(ac))) JUMP (ea); break; /* SOJE */\r |
| 1084 | case 0363: SOJ; if (TLE (AC(ac))) JUMP (ea); break; /* SOJLE */\r |
| 1085 | case 0364: SOJ; JUMP(ea); break; /* SOJA */\r |
| 1086 | case 0365: SOJ; if (TGE (AC(ac))) JUMP (ea); break; /* SOJGE */\r |
| 1087 | case 0366: SOJ; if (TN (AC(ac))) JUMP (ea); break; /* SOJN */\r |
| 1088 | case 0367: SOJ; if (TG (AC(ac))) JUMP (ea); /* SOJG */\r |
| 1089 | if ((ea == pager_PC) && Q_IDLE) { /* to self, idle enab? */\r |
| 1090 | extern int32 tmr_poll;\r |
| 1091 | if ((ac == 6) && (ea == 1) && /* SOJG 6,1? */\r |
| 1092 | TSTF (F_USR) && Q_T10) /* T10, user mode? */\r |
| 1093 | sim_idle (0, FALSE);\r |
| 1094 | else if (!t20_idlelock && /* interlock off? */\r |
| 1095 | (ac == 2) && (ea == 3) && /* SOJG 2,3? */\r |
| 1096 | !TSTF (F_USR) && Q_T20 && /* T20, mon mode? */\r |
| 1097 | (sim_interval > (tmr_poll >> 1))) { /* >= half clock? */\r |
| 1098 | t20_idlelock = 1; /* set interlock */\r |
| 1099 | if (sim_os_ms_sleep (1)) /* sleep 1ms */\r |
| 1100 | sim_interval = 0; /* if ok, sched event */\r |
| 1101 | }\r |
| 1102 | } \r |
| 1103 | break;\r |
| 1104 | case 0370: SOS; break; /* SOS */\r |
| 1105 | case 0371: SOS; if (TL (mb)) INCPC; break; /* SOSL */\r |
| 1106 | case 0372: SOS; if (TE (mb)) INCPC; break; /* SOSE */\r |
| 1107 | case 0373: SOS; if (TLE (mb)) INCPC; break; /* SOSLE */\r |
| 1108 | case 0374: SOS; INCPC; break; /* SOSA */\r |
| 1109 | case 0375: SOS; if (TGE (mb)) INCPC; break; /* SOSGE */\r |
| 1110 | case 0376: SOS; if (TN (mb)) INCPC; break; /* SOSN */\r |
| 1111 | case 0377: SOS; if (TG (mb)) INCPC; break; /* SOSG */\r |
| 1112 | \r |
| 1113 | /* Boolean instructions (0400 - 0477) - checked against KS10 ucode\r |
| 1114 | \r |
| 1115 | Note that for boolean B, the initial read checks writeability of\r |
| 1116 | the memory operand; hence, it is safe to modify the AC.\r |
| 1117 | */\r |
| 1118 | \r |
| 1119 | case 0400: AC(ac) = 0; break; /* SETZ */\r |
| 1120 | case 0401: AC(ac) = 0; break; /* SETZI */\r |
| 1121 | case 0402: mb = 0; WR; break; /* SETZM */\r |
| 1122 | case 0403: mb = 0; WR; AC(ac) = 0; break; /* SETZB */\r |
| 1123 | case 0404: RD; AC(ac) = AND (mb); break; /* AND */\r |
| 1124 | case 0405: AC(ac) = AND (IM); break; /* ANDI */\r |
| 1125 | case 0406: RM; mb = AND (mb); WR; break; /* ANDM */\r |
| 1126 | case 0407: RM; AC(ac) = AND (mb); WRAC; break; /* ANDB */\r |
| 1127 | case 0410: RD; AC(ac) = ANDCA (mb); break; /* ANDCA */\r |
| 1128 | case 0411: AC(ac) = ANDCA (IM); break; /* ANDCAI */\r |
| 1129 | case 0412: RM; mb = ANDCA (mb); WR; break; /* ANDCAM */\r |
| 1130 | case 0413: RM; AC(ac) = ANDCA (mb); WRAC; break; /* ANDCAB */\r |
| 1131 | case 0414: RDAC; break; /* SETM */\r |
| 1132 | case 0415: AC(ac) = ea; break; /* SETMI */\r |
| 1133 | case 0416: RM; WR; break; /* SETMM */\r |
| 1134 | case 0417: RMAC; WRAC; break; /* SETMB */\r |
| 1135 | case 0420: RD; AC(ac) = ANDCM (mb); break; /* ANDCM */\r |
| 1136 | case 0421: AC(ac) = ANDCM (IM); break; /* ANDCMI */\r |
| 1137 | case 0422: RM; mb = ANDCM (mb); WR; break; /* ANDCMM */\r |
| 1138 | case 0423: RM; AC(ac) = ANDCM (mb); WRAC; break; /* ANDCMB */\r |
| 1139 | case 0424: break; /* SETA */\r |
| 1140 | case 0425: break; /* SETAI */\r |
| 1141 | case 0426: WRAC; break; /* SETAM */\r |
| 1142 | case 0427: WRAC; break; /* SETAB */\r |
| 1143 | case 0430: RD; AC(ac) = XOR (mb); break; /* XOR */\r |
| 1144 | case 0431: AC(ac) = XOR (IM); break; /* XORI */\r |
| 1145 | case 0432: RM; mb = XOR (mb); WR; break; /* XORM */\r |
| 1146 | case 0433: RM; AC(ac) = XOR (mb); WRAC; break; /* XORB */\r |
| 1147 | case 0434: RD; AC(ac) = IOR (mb); break; /* IOR */\r |
| 1148 | case 0435: AC(ac) = IOR (IM); break; /* IORI */\r |
| 1149 | case 0436: RM; mb = IOR (mb); WR; break; /* IORM */\r |
| 1150 | case 0437: RM; AC(ac) = IOR (mb); WRAC; break; /* IORB */\r |
| 1151 | case 0440: RD; AC(ac) = ANDCB (mb); break; /* ANDCB */\r |
| 1152 | case 0441: AC(ac) = ANDCB (IM); break; /* ANDCBI */\r |
| 1153 | case 0442: RM; mb = ANDCB (mb); WR; break; /* ANDCBM */\r |
| 1154 | case 0443: RM; AC(ac) = ANDCB (mb); WRAC; break; /* ANDCBB */\r |
| 1155 | case 0444: RD; AC(ac) = EQV (mb); break; /* EQV */\r |
| 1156 | case 0445: AC(ac) = EQV (IM); break; /* EQVI */\r |
| 1157 | case 0446: RM; mb = EQV (mb); WR; break; /* EQVM */\r |
| 1158 | case 0447: RM; AC(ac) = EQV (mb); WRAC; break; /* EQVB */\r |
| 1159 | case 0450: RD; AC(ac) = SETCA (mb); break; /* SETCA */\r |
| 1160 | case 0451: AC(ac) = SETCA (IM); break; /* SETCAI */\r |
| 1161 | case 0452: RM; mb = SETCA (mb); WR; break; /* SETCAM */\r |
| 1162 | case 0453: RM; AC(ac) = SETCA (mb); WRAC; break; /* SETCAB */\r |
| 1163 | case 0454: RD; AC(ac) = ORCA (mb); break; /* ORCA */\r |
| 1164 | case 0455: AC(ac) = ORCA (IM); break; /* ORCAI */\r |
| 1165 | case 0456: RM; mb = ORCA (mb); WR; break; /* ORCAM */\r |
| 1166 | case 0457: RM; AC(ac) = ORCA (mb); WRAC; break; /* ORCAB */\r |
| 1167 | case 0460: RD; AC(ac) = SETCM (mb); break; /* SETCM */\r |
| 1168 | case 0461: AC(ac) = SETCM (IM); break; /* SETCMI */\r |
| 1169 | case 0462: RM; mb = SETCM (mb); WR; break; /* SETCMM */\r |
| 1170 | case 0463: RM; AC(ac) = SETCM (mb); WRAC; break; /* SETCMB */\r |
| 1171 | case 0464: RD; AC(ac) = ORCM (mb); break; /* ORCM */\r |
| 1172 | case 0465: AC(ac) = ORCM (IM); break; /* ORCMI */\r |
| 1173 | case 0466: RM; mb = ORCM (mb); WR; break; /* ORCMM */\r |
| 1174 | case 0467: RM; AC(ac) = ORCM (mb); WRAC; break; /* ORCMB */\r |
| 1175 | case 0470: RD; AC(ac) = ORCB (mb); break; /* ORCB */\r |
| 1176 | case 0471: AC(ac) = ORCB (IM); break; /* ORCBI */\r |
| 1177 | case 0472: RM; mb = ORCB (mb); WR; break; /* ORCBM */\r |
| 1178 | case 0473: RM; AC(ac) = ORCB (mb); WRAC; break; /* ORCBB */\r |
| 1179 | case 0474: AC(ac) = ONES; break; /* SETO */\r |
| 1180 | case 0475: AC(ac) = ONES; break; /* SETOI */\r |
| 1181 | case 0476: mb = ONES; WR; break; /* SETOM */\r |
| 1182 | case 0477: mb = ONES; WR; AC(ac) = ONES; break; /* SETOB */\r |
| 1183 | \r |
| 1184 | /* Halfword instructions (0500 - 0577) - checked against KS10 ucode */\r |
| 1185 | \r |
| 1186 | case 0500: RD; AC(ac) = LL (mb, AC(ac)); break; /* HLL */\r |
| 1187 | case 0501: AC(ac) = LL (IM, AC(ac)); break; /* HLLI */\r |
| 1188 | case 0502: RM; mb = LL (AC(ac), mb); WR; break; /* HLLM */\r |
| 1189 | case 0503: RM; mb = LL (mb, mb); WR; LAC; break; /* HLLS */\r |
| 1190 | case 0504: RD; AC(ac) = RL (mb, AC(ac)); break; /* HRL */\r |
| 1191 | case 0505: AC(ac) = RL (IM, AC(ac)); break; /* HRLI */\r |
| 1192 | case 0506: RM; mb = RL (AC(ac), mb); WR; break; /* HRLM */\r |
| 1193 | case 0507: RM; mb = RL (mb, mb); WR; LAC; break; /* HRLS */\r |
| 1194 | case 0510: RD; AC(ac) = LLZ (mb); break; /* HLLZ */\r |
| 1195 | case 0511: AC(ac) = LLZ (IM); break; /* HLLZI */\r |
| 1196 | case 0512: mb = LLZ (AC(ac)); WR; break; /* HLLZM */\r |
| 1197 | case 0513: RM; mb = LLZ (mb); WR; LAC; break; /* HLLZS */\r |
| 1198 | case 0514: RD; AC(ac) = RLZ (mb); break; /* HRLZ */\r |
| 1199 | case 0515: AC(ac) = RLZ (IM); break; /* HRLZI */\r |
| 1200 | case 0516: mb = RLZ (AC(ac)); WR; break; /* HRLZM */\r |
| 1201 | case 0517: RM; mb = RLZ (mb); WR; LAC; break; /* HRLZS */\r |
| 1202 | case 0520: RD; AC(ac) = LLO (mb); break; /* HLLO */\r |
| 1203 | case 0521: AC(ac) = LLO (IM); break; /* HLLOI */\r |
| 1204 | case 0522: mb = LLO (AC(ac)); WR; break; /* HLLOM */\r |
| 1205 | case 0523: RM; mb = LLO (mb); WR; LAC; break; /* HLLOS */\r |
| 1206 | case 0524: RD; AC(ac) = RLO (mb); break; /* HRLO */\r |
| 1207 | case 0525: AC(ac) = RLO (IM); break; /* HRLOI */\r |
| 1208 | case 0526: mb = RLO (AC(ac)); WR; break; /* HRLOM */\r |
| 1209 | case 0527: RM; mb = RLO (mb); WR; LAC; break; /* HRLOS */\r |
| 1210 | case 0530: RD; AC(ac) = LLE (mb); break; /* HLLE */\r |
| 1211 | case 0531: AC(ac) = LLE (IM); break; /* HLLEI */\r |
| 1212 | case 0532: mb = LLE (AC(ac)); WR; break; /* HLLEM */\r |
| 1213 | case 0533: RM; mb = LLE (mb); WR; LAC; break; /* HLLES */\r |
| 1214 | case 0534: RD; AC(ac) = RLE (mb); break; /* HRLE */\r |
| 1215 | case 0535: AC(ac) = RLE (IM); break; /* HRLEI */\r |
| 1216 | case 0536: mb = RLE (AC(ac)); WR; break; /* HRLEM */\r |
| 1217 | case 0537: RM; mb = RLE (mb); WR; LAC; break; /* HRLES */\r |
| 1218 | case 0540: RD; AC(ac) = RR (mb, AC(ac)); break; /* HRR */\r |
| 1219 | case 0541: AC(ac) = RR (IM, AC(ac)); break; /* HRRI */\r |
| 1220 | case 0542: RM; mb = RR (AC(ac), mb); WR; break; /* HRRM */\r |
| 1221 | case 0543: RM; mb = RR (mb, mb); WR; LAC; break; /* HRRS */\r |
| 1222 | case 0544: RD; AC(ac) = LR (mb, AC(ac)); break; /* HLR */\r |
| 1223 | case 0545: AC(ac) = LR (IM, AC(ac)); break; /* HLRI */\r |
| 1224 | case 0546: RM; mb = LR (AC(ac), mb); WR; break; /* HLRM */\r |
| 1225 | case 0547: RM; mb = LR (mb, mb); WR; LAC; break; /* HLRS */\r |
| 1226 | case 0550: RD; AC(ac) = RRZ (mb); break; /* HRRZ */\r |
| 1227 | case 0551: AC(ac) = RRZ (IM); break; /* HRRZI */\r |
| 1228 | case 0552: mb = RRZ (AC(ac)); WR; break; /* HRRZM */\r |
| 1229 | case 0553: RM; mb = RRZ(mb); WR; LAC; break; /* HRRZS */\r |
| 1230 | case 0554: RD; AC(ac) = LRZ (mb); break; /* HLRZ */\r |
| 1231 | case 0555: AC(ac) = LRZ (IM); break; /* HLRZI */\r |
| 1232 | case 0556: mb = LRZ (AC(ac)); WR; break; /* HLRZM */\r |
| 1233 | case 0557: RM; mb = LRZ (mb); WR; LAC; break; /* HLRZS */\r |
| 1234 | case 0560: RD; AC(ac) = RRO (mb); break; /* HRRO */\r |
| 1235 | case 0561: AC(ac) = RRO (IM); break; /* HRROI */\r |
| 1236 | case 0562: mb = RRO (AC(ac)); WR; break; /* HRROM */\r |
| 1237 | case 0563: RM; mb = RRO (mb); WR; LAC; break; /* HRROS */\r |
| 1238 | case 0564: RD; AC(ac) = LRO (mb); break; /* HLRO */\r |
| 1239 | case 0565: AC(ac) = LRO (IM); break; /* HLROI */\r |
| 1240 | case 0566: mb = LRO (AC(ac)); WR; break; /* HLROM */\r |
| 1241 | case 0567: RM; mb = LRO (mb); WR; LAC; break; /* HLROS */\r |
| 1242 | case 0570: RD; AC(ac) = RRE (mb); break; /* HRRE */\r |
| 1243 | case 0571: AC(ac) = RRE (IM); break; /* HRREI */\r |
| 1244 | case 0572: mb = RRE (AC(ac)); WR; break; /* HRREM */\r |
| 1245 | case 0573: RM; mb = RRE (mb); WR; LAC; break; /* HRRES */\r |
| 1246 | case 0574: RD; AC(ac) = LRE (mb); break; /* HLRE */\r |
| 1247 | case 0575: AC(ac) = LRE (IM); break; /* HLREI */\r |
| 1248 | case 0576: mb = LRE (AC(ac)); WR; break; /* HLREM */\r |
| 1249 | case 0577: RM; mb = LRE (mb); WR; LAC; break; /* HLRES */\r |
| 1250 | \r |
| 1251 | /* Test instructions (0600 - 0677) - checked against KS10 ucode\r |
| 1252 | In the KS10 ucode, TDN and TSN do not fetch an operand; the Processor\r |
| 1253 | Reference Manual describes them as NOPs that reference memory.\r |
| 1254 | */\r |
| 1255 | \r |
| 1256 | case 0600: break; /* TRN */\r |
| 1257 | case 0601: break; /* TLN */\r |
| 1258 | case 0602: TR_; T__E; break; /* TRNE */\r |
| 1259 | case 0603: TL_; T__E; break; /* TLNE */\r |
| 1260 | case 0604: T__A; break; /* TRNA */\r |
| 1261 | case 0605: T__A; break; /* TLNA */\r |
| 1262 | case 0606: TR_; T__N; break; /* TRNN */\r |
| 1263 | case 0607: TL_; T__N; break; /* TLNN */\r |
| 1264 | case 0610: TD_; break; /* TDN */\r |
| 1265 | case 0611: TS_; break; /* TSN */\r |
| 1266 | case 0612: TD_; T__E; break; /* TDNE */\r |
| 1267 | case 0613: TS_; T__E; break; /* TSNE */\r |
| 1268 | case 0614: TD_; T__A; break; /* TDNA */\r |
| 1269 | case 0615: TS_; T__A; break; /* TSNA */\r |
| 1270 | case 0616: TD_; T__N; break; /* TDNN */\r |
| 1271 | case 0617: TS_; T__N; break; /* TSNN */\r |
| 1272 | case 0620: TR_; T_Z; break; /* TRZ */\r |
| 1273 | case 0621: TL_; T_Z; break; /* TLZ */\r |
| 1274 | case 0622: TR_; T__E; T_Z; break; /* TRZE */\r |
| 1275 | case 0623: TL_; T__E; T_Z; break; /* TLZE */\r |
| 1276 | case 0624: TR_; T__A; T_Z; break; /* TRZA */\r |
| 1277 | case 0625: TL_; T__A; T_Z; break; /* TLZA */\r |
| 1278 | case 0626: TR_; T__N; T_Z; break; /* TRZN */\r |
| 1279 | case 0627: TL_; T__N; T_Z; break; /* TLZN */\r |
| 1280 | case 0630: TD_; T_Z; break; /* TDZ */\r |
| 1281 | case 0631: TS_; T_Z; break; /* TSZ */\r |
| 1282 | case 0632: TD_; T__E; T_Z; break; /* TDZE */\r |
| 1283 | case 0633: TS_; T__E; T_Z; break; /* TSZE */\r |
| 1284 | case 0634: TD_; T__A; T_Z; break; /* TDZA */\r |
| 1285 | case 0635: TS_; T__A; T_Z; break; /* TSZA */\r |
| 1286 | case 0636: TD_; T__N; T_Z; break; /* TDZN */\r |
| 1287 | case 0637: TS_; T__N; T_Z; break; /* TSZN */\r |
| 1288 | case 0640: TR_; T_C; break; /* TRC */\r |
| 1289 | case 0641: TL_; T_C; break; /* TLC */\r |
| 1290 | case 0642: TR_; T__E; T_C; break; /* TRCE */\r |
| 1291 | case 0643: TL_; T__E; T_C; break; /* TLCE */\r |
| 1292 | case 0644: TR_; T__A; T_C; break; /* TRCA */\r |
| 1293 | case 0645: TL_; T__A; T_C; break; /* TLCA */\r |
| 1294 | case 0646: TR_; T__N; T_C; break; /* TRCN */\r |
| 1295 | case 0647: TL_; T__N; T_C; break; /* TLCN */\r |
| 1296 | case 0650: TD_; T_C; break; /* TDC */\r |
| 1297 | case 0651: TS_; T_C; break; /* TSC */\r |
| 1298 | case 0652: TD_; T__E; T_C; break; /* TDCE */\r |
| 1299 | case 0653: TS_; T__E; T_C; break; /* TSCE */\r |
| 1300 | case 0654: TD_; T__A; T_C; break; /* TDCA */\r |
| 1301 | case 0655: TS_; T__A; T_C; break; /* TSCA */\r |
| 1302 | case 0656: TD_; T__N; T_C; break; /* TDCN */\r |
| 1303 | case 0657: TS_; T__N; T_C; break; /* TSCN */\r |
| 1304 | case 0660: TR_; T_O; break; /* TRO */\r |
| 1305 | case 0661: TL_; T_O; break; /* TLO */\r |
| 1306 | case 0662: TR_; T__E; T_O; break; /* TROE */\r |
| 1307 | case 0663: TL_; T__E; T_O; break; /* TLOE */\r |
| 1308 | case 0664: TR_; T__A; T_O; break; /* TROA */\r |
| 1309 | case 0665: TL_; T__A; T_O; break; /* TLOA */\r |
| 1310 | case 0666: TR_; T__N; T_O; break; /* TRON */\r |
| 1311 | case 0667: TL_; T__N; T_O; break; /* TLON */\r |
| 1312 | case 0670: TD_; T_O; break; /* TDO */\r |
| 1313 | case 0671: TS_; T_O; break; /* TSO */\r |
| 1314 | case 0672: TD_; T__E; T_O; break; /* TDOE */\r |
| 1315 | case 0673: TS_; T__E; T_O; break; /* TSOE */\r |
| 1316 | case 0674: TD_; T__A; T_O; break; /* TDOA */\r |
| 1317 | case 0675: TS_; T__A; T_O; break; /* TSOA */\r |
| 1318 | case 0676: TD_; T__N; T_O; break; /* TDON */\r |
| 1319 | case 0677: TS_; T__N; T_O; break; /* TSON */\r |
| 1320 | \r |
| 1321 | /* I/O instructions (0700 - 0777)\r |
| 1322 | \r |
| 1323 | Only the defined I/O instructions have explicit case labels;\r |
| 1324 | the rest default to unimplemented (monitor UUO). Note that \r |
| 1325 | 710-715 and 720-725 have different definitions under ITS and\r |
| 1326 | use normal effective addresses instead of the special address\r |
| 1327 | calculation required by TOPS-10 and TOPS-20.\r |
| 1328 | */\r |
| 1329 | \r |
| 1330 | case 0700: IO7 (io700i, io700d); break; /* I/O 0 */\r |
| 1331 | case 0701: IO7 (io701i, io701d); break; /* I/O 1 */\r |
| 1332 | case 0702: IO7 (io702i, io702d); break; /* I/O 2 */\r |
| 1333 | case 0704: IOC; AC(ac) = Read (ea, OPND_PXCT); break; /* UMOVE */\r |
| 1334 | case 0705: IOC; Write (ea, AC(ac), OPND_PXCT); break; /* UMOVEM */\r |
| 1335 | case 0710: IOA; if (io710 (ac, ea)) INCPC; break; /* TIOE, IORDI */\r |
| 1336 | case 0711: IOA; if (io711 (ac, ea)) INCPC; break; /* TION, IORDQ */\r |
| 1337 | case 0712: IOAM; AC(ac) = io712 (ea); break; /* RDIO, IORD */\r |
| 1338 | case 0713: IOAM; io713 (AC(ac), ea); break; /* WRIO, IOWR */\r |
| 1339 | case 0714: IOA; io714 (AC(ac), ea); break; /* BSIO, IOWRI */\r |
| 1340 | case 0715: IOA; io715 (AC(ac), ea); break; /* BCIO, IOWRQ */\r |
| 1341 | case 0716: IOC; bltu (ac, ea, pflgs, 0); break; /* BLTBU */\r |
| 1342 | case 0717: IOC; bltu (ac, ea, pflgs, 1); break; /* BLTUB */\r |
| 1343 | case 0720: IOA; if (io720 (ac, ea)) INCPC; break; /* TIOEB, IORDBI */\r |
| 1344 | case 0721: IOA; if (io721 (ac, ea)) INCPC; break; /* TIONB, IORDBQ */\r |
| 1345 | case 0722: IOAM; AC(ac) = io722 (ea); break; /* RDIOB, IORDB */\r |
| 1346 | case 0723: IOAM; io723 (AC(ac), ea); break; /* WRIOB, IOWRB */\r |
| 1347 | case 0724: IOA; io724 (AC(ac), ea); break; /* BSIOB, IOWRBI */\r |
| 1348 | case 0725: IOA; io725 (AC(ac), ea); break; /* BCIOB, IOWRBQ */\r |
| 1349 | \r |
| 1350 | /* If undefined, monitor UUO - checked against KS10 ucode\r |
| 1351 | The KS10 implements a much more limited version of MUUO flag handling.\r |
| 1352 | In the KS10, the trap ucode checks for opcodes 000-077. If the opcode\r |
| 1353 | is in that range, the trap flags are not cleared. Instead, the MUUO\r |
| 1354 | microcode stores the flags with traps cleared, and uses the trap flags\r |
| 1355 | to determine how to vector. Thus, MUUO's >= 100 will vector incorrectly.\r |
| 1356 | */\r |
| 1357 | \r |
| 1358 | default:\r |
| 1359 | MUUO:\r |
| 1360 | its_2pr = 0; /* clear trap */\r |
| 1361 | if (T20PAG) { /* TOPS20 paging? */\r |
| 1362 | int32 tf = (op << (INST_V_OP - 18)) | (ac << (INST_V_AC - 18));\r |
| 1363 | WriteP (upta + UPT_MUUO, XWD ( /* store flags,,op+ac */\r |
| 1364 | flags & ~(F_T2 | F_T1), tf)); /* traps clear */\r |
| 1365 | WriteP (upta + UPT_MUPC, PC); /* store PC */\r |
| 1366 | WriteP (upta + UPT_T20_UEA, ea); /* store eff addr */\r |
| 1367 | WriteP (upta + UPT_T20_CTX, UBRWORD); /* store context */\r |
| 1368 | }\r |
| 1369 | else { /* TOPS10/ITS */\r |
| 1370 | WriteP (upta + UPT_MUUO, UUOWORD); /* store instr word */\r |
| 1371 | WriteP (upta + UPT_MUPC, XWD ( /* store flags,,PC */\r |
| 1372 | flags & ~(F_T2 | F_T1), PC)); /* traps clear */\r |
| 1373 | WriteP (upta + UPT_T10_CTX, UBRWORD); /* store context */\r |
| 1374 | }\r |
| 1375 | ea = upta + (TSTF (F_USR)? UPT_UNPC: UPT_ENPC) +\r |
| 1376 | (pager_tc? UPT_NPCT: 0); /* calculate vector */\r |
| 1377 | mb = ReadP (ea); /* new flags, PC */\r |
| 1378 | JUMP (mb); /* set new PC */\r |
| 1379 | if (TSTF (F_USR)) mb = mb | XWD (F_UIO, 0); /* set PCU */\r |
| 1380 | set_newflags (mb, FALSE); /* set new flags */\r |
| 1381 | break;\r |
| 1382 | \r |
| 1383 | /* JRST - checked against KS10 ucode\r |
| 1384 | Differences from the KS10: the KS10\r |
| 1385 | - (JRSTF, JEN) refetches the base instruction from PC - 1\r |
| 1386 | - (XJEN) dismisses interrupt before reading the new flags and PC\r |
| 1387 | - (XPCW) writes the old flags and PC before reading the new\r |
| 1388 | ITS microcode includes extended JRST's, although they are not used\r |
| 1389 | */\r |
| 1390 | \r |
| 1391 | case 0254: /* JRST */\r |
| 1392 | i = jrst_tab[ac]; /* get subop flags */\r |
| 1393 | if ((i == 0) || ((i == JRST_E) && TSTF (F_USR)) ||\r |
| 1394 | ((i == JRST_UIO) && TSTF (F_USR) && !TSTF (F_UIO)))\r |
| 1395 | goto MUUO; /* not legal */\r |
| 1396 | switch (ac) { /* case on subopcode */\r |
| 1397 | \r |
| 1398 | case 000: /* JRST 0 = jump */\r |
| 1399 | case 001: /* JRST 1 = portal */\r |
| 1400 | JUMP (ea);\r |
| 1401 | break;\r |
| 1402 | \r |
| 1403 | case 002: /* JRST 2 = JRSTF */\r |
| 1404 | mb = calc_jrstfea (inst, pflgs); /* recalc addr w flgs */\r |
| 1405 | JUMP (ea); /* set new PC */\r |
| 1406 | set_newflags (mb, TRUE); /* set new flags */\r |
| 1407 | break;\r |
| 1408 | \r |
| 1409 | case 004: /* JRST 4 = halt */\r |
| 1410 | JUMP (ea); /* old_PC = halt + 1 */\r |
| 1411 | pager_PC = PC; /* force right PC */\r |
| 1412 | ABORT (STOP_HALT); /* known to be exec */\r |
| 1413 | break;\r |
| 1414 | \r |
| 1415 | case 005: /* JRST 5 = XJRSTF */\r |
| 1416 | RD2; /* read doubleword */\r |
| 1417 | JUMP (rs[1]); /* set new PC */\r |
| 1418 | set_newflags (rs[0], TRUE); /* set new flags */\r |
| 1419 | break;\r |
| 1420 | \r |
| 1421 | case 006: /* JRST 6 = XJEN */\r |
| 1422 | RD2; /* read doubleword */\r |
| 1423 | pi_dismiss (); /* page ok, dismiss */\r |
| 1424 | JUMP (rs[1]); /* set new PC */\r |
| 1425 | set_newflags (rs[0], FALSE); /* known to be exec */\r |
| 1426 | break;\r |
| 1427 | \r |
| 1428 | case 007: /* JRST 7 = XPCW */\r |
| 1429 | ea = ADDA (i = ea, 2); /* new flags, PC */\r |
| 1430 | RD2; /* read, test page fail */\r |
| 1431 | ReadM (INCA (i), MM_OPND); /* test PC write */\r |
| 1432 | Write (i, XWD (flags, 0), MM_OPND); /* write flags */\r |
| 1433 | Write (INCA (i), PC, MM_OPND); /* write PC */\r |
| 1434 | JUMP (rs[1]); /* set new PC */\r |
| 1435 | set_newflags (rs[0], FALSE); /* known to be exec */\r |
| 1436 | break;\r |
| 1437 | \r |
| 1438 | case 010: /* JRST 10 = dismiss */\r |
| 1439 | pi_dismiss (); /* dismiss int */\r |
| 1440 | JUMP (ea); /* set new PC */\r |
| 1441 | break;\r |
| 1442 | \r |
| 1443 | case 012: /* JRST 12 = JEN */\r |
| 1444 | mb = calc_jrstfea (inst, pflgs); /* recalc addr w flgs */\r |
| 1445 | JUMP (ea); /* set new PC */\r |
| 1446 | set_newflags (mb, TRUE); /* set new flags */\r |
| 1447 | pi_dismiss (); /* dismiss int */\r |
| 1448 | break;\r |
| 1449 | \r |
| 1450 | case 014: /* JRST 14 = SFM */\r |
| 1451 | Write (ea, XWD (flags, 0), MM_OPND);\r |
| 1452 | break; \r |
| 1453 | \r |
| 1454 | case 015: /* JRST 15 = XJRST */\r |
| 1455 | if (!T20PAG) goto MUUO; /* only in TOPS20 paging */\r |
| 1456 | JUMP (Read (ea, MM_OPND)); /* jump to M[ea] */\r |
| 1457 | break;\r |
| 1458 | } /* end case subop */\r |
| 1459 | break;\r |
| 1460 | } /* end case op */\r |
| 1461 | \r |
| 1462 | if (its_2pr) { /* 1-proc trap? */\r |
| 1463 | its_1pr = its_2pr = 0; /* clear trap */\r |
| 1464 | if (Q_ITS) { /* better be ITS */\r |
| 1465 | WriteP (upta + UPT_1PO, FLPC); /* wr old flgs, PC */\r |
| 1466 | mb = ReadP (upta + UPT_1PN); /* rd new flgs, PC */\r |
| 1467 | JUMP (mb); /* set PC */\r |
| 1468 | set_newflags (mb, TRUE); /* set new flags */\r |
| 1469 | }\r |
| 1470 | } /* end if 2-proc */\r |
| 1471 | } /* end for */\r |
| 1472 | \r |
| 1473 | /* Should never get here */\r |
| 1474 | \r |
| 1475 | ABORT (STOP_UNKNOWN);\r |
| 1476 | }\r |
| 1477 | \r |
| 1478 | /* Single word integer routines */\r |
| 1479 | \r |
| 1480 | /* Integer add\r |
| 1481 | \r |
| 1482 | Truth table for integer add\r |
| 1483 | \r |
| 1484 | case a b r flags\r |
| 1485 | 1 + + + none\r |
| 1486 | 2 + + - AOV + C1\r |
| 1487 | 3 + - + C0 + C1\r |
| 1488 | 4 + - - -\r |
| 1489 | 5 - + + C0 + C1\r |
| 1490 | 6 - + - -\r |
| 1491 | 7 - - + AOV + C0\r |
| 1492 | 8 - - - C0 + C1\r |
| 1493 | */\r |
| 1494 | \r |
| 1495 | d10 add (d10 a, d10 b)\r |
| 1496 | {\r |
| 1497 | d10 r;\r |
| 1498 | \r |
| 1499 | r = (a + b) & DMASK;\r |
| 1500 | if (TSTS (a & b)) { /* cases 7,8 */\r |
| 1501 | if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */\r |
| 1502 | else SETF (F_C0 | F_AOV | F_T1); /* case 7 */\r |
| 1503 | return r;\r |
| 1504 | }\r |
| 1505 | if (!TSTS (a | b)) { /* cases 1,2 */\r |
| 1506 | if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */\r |
| 1507 | return r; /* case 1 */\r |
| 1508 | }\r |
| 1509 | if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */\r |
| 1510 | return r;\r |
| 1511 | }\r |
| 1512 | \r |
| 1513 | /* Integer subtract - actually ac + ~op + 1 */\r |
| 1514 | \r |
| 1515 | d10 sub (d10 a, d10 b)\r |
| 1516 | {\r |
| 1517 | d10 r;\r |
| 1518 | \r |
| 1519 | r = (a - b) & DMASK;\r |
| 1520 | if (TSTS (a & ~b)) { /* cases 7,8 */\r |
| 1521 | if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */\r |
| 1522 | else SETF (F_C0 | F_AOV | F_T1); /* case 7 */\r |
| 1523 | return r;\r |
| 1524 | }\r |
| 1525 | if (!TSTS (a | ~b)) { /* cases 1,2 */\r |
| 1526 | if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */\r |
| 1527 | return r; /* case 1 */\r |
| 1528 | }\r |
| 1529 | if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */\r |
| 1530 | return r;\r |
| 1531 | }\r |
| 1532 | \r |
| 1533 | \r |
| 1534 | /* Logical shift */\r |
| 1535 | \r |
| 1536 | d10 lsh (d10 val, a10 ea)\r |
| 1537 | {\r |
| 1538 | int32 sc = LIT8 (ea);\r |
| 1539 | \r |
| 1540 | if (sc > 35) return 0;\r |
| 1541 | if (ea & RSIGN) return (val >> sc);\r |
| 1542 | return ((val << sc) & DMASK);\r |
| 1543 | }\r |
| 1544 | \r |
| 1545 | /* Rotate */\r |
| 1546 | \r |
| 1547 | d10 rot (d10 val, a10 ea)\r |
| 1548 | {\r |
| 1549 | int32 sc = LIT8 (ea) % 36;\r |
| 1550 | \r |
| 1551 | if (sc == 0) return val;\r |
| 1552 | if (ea & RSIGN) sc = 36 - sc;\r |
| 1553 | return (((val << sc) | (val >> (36 - sc))) & DMASK);\r |
| 1554 | }\r |
| 1555 | \r |
| 1556 | /* Double word integer instructions */\r |
| 1557 | \r |
| 1558 | /* Double add - see case table for single add */\r |
| 1559 | \r |
| 1560 | void dadd (int32 ac, d10 *rs)\r |
| 1561 | {\r |
| 1562 | d10 r;\r |
| 1563 | int32 p1 = ADDAC (ac, 1);\r |
| 1564 | \r |
| 1565 | AC(p1) = CLRS (AC(p1)) + CLRS (rs[1]); /* add lo */\r |
| 1566 | r = (AC(ac) + rs[0] + (TSTS (AC(p1))? 1: 0)) & DMASK; /* add hi+cry */\r |
| 1567 | if (TSTS (AC(ac) & rs[0])) { /* cases 7,8 */\r |
| 1568 | if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */\r |
| 1569 | else SETF (F_C0 | F_AOV | F_T1); /* case 7 */\r |
| 1570 | }\r |
| 1571 | else if (!TSTS (AC(ac) | rs[0])) { /* cases 1,2 */\r |
| 1572 | if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */\r |
| 1573 | }\r |
| 1574 | else if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */\r |
| 1575 | AC(ac) = r;\r |
| 1576 | AC(p1) = TSTS (r)? SETS (AC(p1)): CLRS (AC(p1));\r |
| 1577 | return;\r |
| 1578 | } \r |
| 1579 | \r |
| 1580 | /* Double subtract - see comments for single subtract */\r |
| 1581 | \r |
| 1582 | void dsub (int32 ac, d10 *rs)\r |
| 1583 | {\r |
| 1584 | d10 r;\r |
| 1585 | int32 p1 = ADDAC (ac, 1);\r |
| 1586 | \r |
| 1587 | AC(p1) = CLRS (AC(p1)) - CLRS (rs[1]); /* sub lo */\r |
| 1588 | r = (AC(ac) - rs[0] - (TSTS (AC(p1))? 1: 0)) & DMASK; /* sub hi,borrow */\r |
| 1589 | if (TSTS (AC(ac) & ~rs[0])) { /* cases 7,8 */\r |
| 1590 | if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */\r |
| 1591 | else SETF (F_C0 | F_AOV | F_T1); /* case 7 */\r |
| 1592 | }\r |
| 1593 | else if (!TSTS (AC(ac) | ~rs[0])) { /* cases 1,2 */\r |
| 1594 | if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */\r |
| 1595 | }\r |
| 1596 | else if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */\r |
| 1597 | AC(ac) = r;\r |
| 1598 | AC(p1) = (TSTS (r)? SETS (AC(p1)): CLRS (AC(p1))) & DMASK;\r |
| 1599 | return;\r |
| 1600 | } \r |
| 1601 | \r |
| 1602 | \r |
| 1603 | /* Logical shift combined */\r |
| 1604 | \r |
| 1605 | void lshc (int32 ac, a10 ea)\r |
| 1606 | {\r |
| 1607 | int32 p1 = ADDAC (ac, 1);\r |
| 1608 | int32 sc = LIT8 (ea);\r |
| 1609 | \r |
| 1610 | if (sc > 71) AC(ac) = AC(p1) = 0;\r |
| 1611 | else if (ea & RSIGN) {\r |
| 1612 | if (sc >= 36) {\r |
| 1613 | AC(p1) = AC(ac) >> (sc - 36);\r |
| 1614 | AC(ac) = 0;\r |
| 1615 | }\r |
| 1616 | else {\r |
| 1617 | AC(p1) = ((AC(p1) >> sc) | (AC(ac) << (36 - sc))) & DMASK;\r |
| 1618 | AC(ac) = AC(ac) >> sc;\r |
| 1619 | }\r |
| 1620 | }\r |
| 1621 | else {\r |
| 1622 | if (sc >= 36) {\r |
| 1623 | AC(ac) = (AC(p1) << (sc - 36)) & DMASK;\r |
| 1624 | AC(p1) = 0;\r |
| 1625 | }\r |
| 1626 | else {\r |
| 1627 | AC(ac) = ((AC(ac) << sc) | (AC(p1) >> (36 - sc))) & DMASK;\r |
| 1628 | AC(p1) = (AC(p1) << sc) & DMASK;\r |
| 1629 | }\r |
| 1630 | }\r |
| 1631 | return;\r |
| 1632 | }\r |
| 1633 | \r |
| 1634 | /* Rotate combined */\r |
| 1635 | \r |
| 1636 | void rotc (int32 ac, a10 ea)\r |
| 1637 | {\r |
| 1638 | int32 p1 = ADDAC (ac, 1);\r |
| 1639 | int32 sc = LIT8 (ea) % 72;\r |
| 1640 | d10 t = AC(ac);\r |
| 1641 | \r |
| 1642 | if (sc == 0) return;\r |
| 1643 | if (ea & RSIGN) sc = 72 - sc;\r |
| 1644 | if (sc >= 36) {\r |
| 1645 | AC(ac) = ((AC(p1) << (sc - 36)) | (t >> (72 - sc))) & DMASK;\r |
| 1646 | AC(p1) = ((t << (sc - 36)) | (AC(p1) >> (72 - sc))) & DMASK;\r |
| 1647 | }\r |
| 1648 | else {\r |
| 1649 | AC(ac) = ((t << sc) | (AC(p1) >> (36 - sc))) & DMASK;\r |
| 1650 | AC(p1) = ((AC(p1) << sc) | (t >> (36 - sc))) & DMASK;\r |
| 1651 | }\r |
| 1652 | return;\r |
| 1653 | }\r |
| 1654 | \r |
| 1655 | /* Arithmetic shifts */\r |
| 1656 | \r |
| 1657 | d10 ash (d10 val, a10 ea)\r |
| 1658 | {\r |
| 1659 | int32 sc = LIT8 (ea);\r |
| 1660 | d10 sign = TSTS (val);\r |
| 1661 | d10 fill = sign? ONES: 0;\r |
| 1662 | d10 so;\r |
| 1663 | \r |
| 1664 | if (sc == 0) return val;\r |
| 1665 | if (sc > 35) sc = 35; /* cap sc at 35 */\r |
| 1666 | if (ea & RSIGN)\r |
| 1667 | return (((val >> sc) | (fill << (36 - sc))) & DMASK);\r |
| 1668 | so = val >> (35 - sc); /* bits lost left + sign */\r |
| 1669 | if (so != (sign? bytemask[sc + 1]: 0)) SETF (F_AOV | F_T1);\r |
| 1670 | return (sign | ((val << sc) & MMASK));\r |
| 1671 | }\r |
| 1672 | \r |
| 1673 | void ashc (int32 ac, a10 ea)\r |
| 1674 | {\r |
| 1675 | int32 sc = LIT8 (ea);\r |
| 1676 | int32 p1 = ADDAC (ac, 1);\r |
| 1677 | d10 sign = TSTS (AC(ac));\r |
| 1678 | d10 fill = sign? ONES: 0;\r |
| 1679 | d10 so;\r |
| 1680 | \r |
| 1681 | if (sc == 0) return;\r |
| 1682 | if (sc > 70) sc = 70; /* cap sc at 70 */\r |
| 1683 | AC(ac) = CLRS (AC(ac)); /* clear signs */\r |
| 1684 | AC(p1) = CLRS (AC(p1));\r |
| 1685 | if (ea & RSIGN) {\r |
| 1686 | if (sc >= 35) { /* right 36..70 */\r |
| 1687 | AC(p1) = ((AC(ac) >> (sc - 35)) | (fill << (70 - sc))) & DMASK;\r |
| 1688 | AC(ac) = fill;\r |
| 1689 | }\r |
| 1690 | else {\r |
| 1691 | AC(p1) = sign | /* right 1..35 */\r |
| 1692 | (((AC(p1) >> sc) | (AC(ac) << (35 - sc))) & MMASK);\r |
| 1693 | AC(ac) = ((AC(ac) >> sc) | (fill << (35 - sc))) & DMASK;\r |
| 1694 | }\r |
| 1695 | }\r |
| 1696 | else {\r |
| 1697 | if (sc >= 35) { /* left 36..70 */\r |
| 1698 | so = AC(p1) >> (70 - sc); /* bits lost left */\r |
| 1699 | if ((AC(ac) != (sign? MMASK: 0)) ||\r |
| 1700 | (so != (sign? bytemask[sc - 35]: 0))) SETF (F_AOV | F_T1);\r |
| 1701 | AC(ac) = sign | ((AC(p1) << (sc - 35)) & MMASK);\r |
| 1702 | AC(p1) = sign;\r |
| 1703 | }\r |
| 1704 | else {\r |
| 1705 | so = AC(ac) >> (35 - sc); /* bits lost left */\r |
| 1706 | if (so != (sign? bytemask[sc]: 0)) SETF (F_AOV | F_T1);\r |
| 1707 | AC(ac) = sign |\r |
| 1708 | (((AC(ac) << sc) | (AC(p1) >> (35 - sc))) & MMASK);\r |
| 1709 | AC(p1) = sign | ((AC(p1) << sc) & MMASK);\r |
| 1710 | }\r |
| 1711 | }\r |
| 1712 | return;\r |
| 1713 | }\r |
| 1714 | \r |
| 1715 | /* Effective address routines */\r |
| 1716 | \r |
| 1717 | /* Calculate effective address - used by byte instructions, extended\r |
| 1718 | instructions, and interrupts to get a different mapping context from\r |
| 1719 | the main loop. prv is either EABP_PXCT or MM_CUR.\r |
| 1720 | */\r |
| 1721 | \r |
| 1722 | a10 calc_ea (d10 inst, int32 prv)\r |
| 1723 | {\r |
| 1724 | int32 i, ea, xr;\r |
| 1725 | d10 indrct;\r |
| 1726 | \r |
| 1727 | for (indrct = inst, i = 0; i < ind_max; i++) {\r |
| 1728 | ea = GET_ADDR (indrct);\r |
| 1729 | xr = GET_XR (indrct);\r |
| 1730 | if (xr) ea = (ea + ((a10) XR (xr, prv))) & AMASK;\r |
| 1731 | if (TST_IND (indrct)) indrct = Read (ea, prv);\r |
| 1732 | else break;\r |
| 1733 | }\r |
| 1734 | if (i >= ind_max) ABORT (STOP_IND);\r |
| 1735 | return ea;\r |
| 1736 | }\r |
| 1737 | \r |
| 1738 | /* Calculate I/O effective address. Cases:\r |
| 1739 | - No index or indirect, return addr from instruction\r |
| 1740 | - Index only, index >= 0, return 36b sum of addr + index\r |
| 1741 | - Index only, index <= 0, return 18b sum of addr + index\r |
| 1742 | - Indirect, calculate 18b sum of addr + index, return\r |
| 1743 | entire word fetch (single level)\r |
| 1744 | */\r |
| 1745 | \r |
| 1746 | a10 calc_ioea (d10 inst, int32 pflgs)\r |
| 1747 | {\r |
| 1748 | int32 xr;\r |
| 1749 | a10 ea;\r |
| 1750 | \r |
| 1751 | xr = GET_XR (inst);\r |
| 1752 | ea = GET_ADDR (inst);\r |
| 1753 | if (TST_IND (inst)) { /* indirect? */\r |
| 1754 | if (xr) ea = (ea + ((a10) XR (xr, MM_EA))) & AMASK;\r |
| 1755 | ea = (a10) Read (ea, MM_EA);\r |
| 1756 | }\r |
| 1757 | else if (xr) { /* direct + idx? */\r |
| 1758 | ea = ea + ((a10) XR (xr, MM_EA));\r |
| 1759 | if (TSTS (XR (xr, MM_EA))) ea = ea & AMASK;\r |
| 1760 | }\r |
| 1761 | return ea;\r |
| 1762 | }\r |
| 1763 | \r |
| 1764 | /* Calculate JRSTF effective address. This routine preserves\r |
| 1765 | the left half of the effective address, to be the new flags.\r |
| 1766 | */\r |
| 1767 | \r |
| 1768 | d10 calc_jrstfea (d10 inst, int32 pflgs)\r |
| 1769 | {\r |
| 1770 | int32 i, xr;\r |
| 1771 | d10 mb;\r |
| 1772 | \r |
| 1773 | for (i = 0; i < ind_max; i++) {\r |
| 1774 | mb = inst;\r |
| 1775 | xr = GET_XR (inst);\r |
| 1776 | if (xr) mb = (mb & AMASK) + XR (xr, MM_EA);\r |
| 1777 | if (TST_IND (inst)) inst = Read (((a10) mb) & AMASK, MM_EA);\r |
| 1778 | else break;\r |
| 1779 | }\r |
| 1780 | if (i >= ind_max) ABORT (STOP_IND);\r |
| 1781 | return (mb & DMASK);\r |
| 1782 | }\r |
| 1783 | \r |
| 1784 | /* Byte pointer routines */\r |
| 1785 | \r |
| 1786 | /* Increment byte pointer - checked against KS10 ucode */\r |
| 1787 | \r |
| 1788 | void ibp (a10 ea, int32 pflgs)\r |
| 1789 | {\r |
| 1790 | int32 p, s;\r |
| 1791 | d10 bp;\r |
| 1792 | \r |
| 1793 | bp = ReadM (ea, MM_OPND); /* get byte ptr */\r |
| 1794 | p = GET_P (bp); /* get P and S */\r |
| 1795 | s = GET_S (bp);\r |
| 1796 | p = p - s; /* adv P */\r |
| 1797 | if (p < 0) { /* end of word? */\r |
| 1798 | bp = (bp & LMASK) | (INCR (bp)); /* incr addr */\r |
| 1799 | p = (36 - s) & 077; /* reset P */\r |
| 1800 | }\r |
| 1801 | bp = PUT_P (bp, p); /* store new P */\r |
| 1802 | Write (ea, bp, MM_OPND); /* store byte ptr */\r |
| 1803 | return;\r |
| 1804 | }\r |
| 1805 | \r |
| 1806 | /* Load byte */\r |
| 1807 | \r |
| 1808 | d10 ldb (a10 ea, int32 pflgs)\r |
| 1809 | {\r |
| 1810 | a10 ba;\r |
| 1811 | int32 p, s;\r |
| 1812 | d10 bp, wd;\r |
| 1813 | \r |
| 1814 | bp = Read (ea, MM_OPND); /* get byte ptr */\r |
| 1815 | p = GET_P (bp); /* get P and S */\r |
| 1816 | s = GET_S (bp);\r |
| 1817 | ba = calc_ea (bp, MM_EABP); /* get addr of byte */\r |
| 1818 | wd = Read (ba, MM_BSTK); /* read word */\r |
| 1819 | wd = (wd >> p); /* align byte */\r |
| 1820 | wd = wd & bytemask[s]; /* mask to size */\r |
| 1821 | return wd;\r |
| 1822 | }\r |
| 1823 | \r |
| 1824 | /* Deposit byte - must use read and write to get page fail correct */\r |
| 1825 | \r |
| 1826 | void dpb (d10 val, a10 ea, int32 pflgs)\r |
| 1827 | {\r |
| 1828 | a10 ba;\r |
| 1829 | int32 p, s;\r |
| 1830 | d10 bp, wd, mask;\r |
| 1831 | \r |
| 1832 | bp = Read (ea, MM_OPND); /* get byte ptr */\r |
| 1833 | p = GET_P (bp); /* get P and S */\r |
| 1834 | s = GET_S (bp);\r |
| 1835 | ba = calc_ea (bp, MM_EABP); /* get addr of byte */\r |
| 1836 | wd = Read (ba, MM_BSTK); /* read word */\r |
| 1837 | mask = bytemask[s] << p; /* shift mask, val */\r |
| 1838 | val = val << p;\r |
| 1839 | wd = (wd & ~mask) | (val & mask); /* insert byte */\r |
| 1840 | Write (ba, wd & DMASK, MM_BSTK);\r |
| 1841 | return;\r |
| 1842 | }\r |
| 1843 | \r |
| 1844 | /* Adjust byte pointer - checked against KS10 ucode \r |
| 1845 | The KS10 divide checks if the bytes per word = 0, which is a simpler\r |
| 1846 | formulation of the processor reference manual check.\r |
| 1847 | */\r |
| 1848 | \r |
| 1849 | void adjbp (int32 ac, a10 ea, int32 pflgs)\r |
| 1850 | {\r |
| 1851 | int32 p, s;\r |
| 1852 | d10 bp, newby, left, byadj, bywrd, val, wdadj;\r |
| 1853 | \r |
| 1854 | val = AC(ac); /* get adjustment */\r |
| 1855 | bp = Read (ea, MM_OPND); /* get byte pointer */\r |
| 1856 | p = GET_P (bp); /* get p */\r |
| 1857 | s = GET_S (bp); /* get s */\r |
| 1858 | if (s) {\r |
| 1859 | left = (36 - p) / s; /* bytes to left of p */\r |
| 1860 | bywrd = left + (p / s); /* bytes per word */\r |
| 1861 | if (bywrd == 0) { /* zero bytes? */\r |
| 1862 | SETF (F_AOV | F_T1 | F_DCK); /* set flags */\r |
| 1863 | return; /* abort operation */\r |
| 1864 | }\r |
| 1865 | newby = left + SXT (val); /* adjusted byte # */\r |
| 1866 | wdadj = newby / bywrd; /* word adjustment */\r |
| 1867 | byadj = (newby >= 0)? newby % bywrd: -((-newby) % bywrd);\r |
| 1868 | if (byadj <= 0) {\r |
| 1869 | byadj = byadj + bywrd; /* make adj positive */\r |
| 1870 | wdadj = wdadj - 1;\r |
| 1871 | }\r |
| 1872 | p = (36 - ((int32) byadj) * s) - ((36 - p) % s); /* new p */\r |
| 1873 | bp = (PUT_P (bp, p) & LMASK) | ((bp + wdadj) & RMASK);\r |
| 1874 | }\r |
| 1875 | AC(ac) = bp; \r |
| 1876 | return;\r |
| 1877 | }\r |
| 1878 | \r |
| 1879 | /* Block transfer - checked against KS10 ucode\r |
| 1880 | The KS10 uses instruction specific recovery code in page fail\r |
| 1881 | to set the AC properly for restart. Lacking this mechanism,\r |
| 1882 | the simulator must test references in advance.\r |
| 1883 | The clocking test guarantees forward progress under single step.\r |
| 1884 | */\r |
| 1885 | \r |
| 1886 | void blt (int32 ac, a10 ea, int32 pflgs)\r |
| 1887 | {\r |
| 1888 | a10 srca = (a10) LRZ (AC(ac));\r |
| 1889 | a10 dsta = (a10) RRZ (AC(ac));\r |
| 1890 | a10 lnt = ea - dsta + 1;\r |
| 1891 | d10 srcv;\r |
| 1892 | int32 flg, t;\r |
| 1893 | \r |
| 1894 | AC(ac) = XWD (srca + lnt, dsta + lnt);\r |
| 1895 | for (flg = 0; dsta <= ea; flg++) { /* loop */\r |
| 1896 | if (flg && (t = test_int ())) { /* timer event? */\r |
| 1897 | AC(ac) = XWD (srca, dsta); /* AC for intr */\r |
| 1898 | ABORT (t);\r |
| 1899 | }\r |
| 1900 | if (AccViol (srca & AMASK, MM_BSTK, PTF_RD)) { /* src access viol? */\r |
| 1901 | AC(ac) = XWD (srca, dsta); /* AC for page fail */\r |
| 1902 | Read (srca & AMASK, MM_BSTK); /* force trap */\r |
| 1903 | }\r |
| 1904 | if (AccViol (dsta & AMASK, MM_OPND, PTF_WR)) { /* dst access viol? */\r |
| 1905 | AC(ac) = XWD (srca, dsta); /* AC for page fail */\r |
| 1906 | ReadM (dsta & AMASK, MM_OPND); /* force trap */\r |
| 1907 | }\r |
| 1908 | srcv = Read (srca & AMASK, MM_BSTK); /* read */\r |
| 1909 | Write (dsta & AMASK, srcv, MM_OPND); /* write */\r |
| 1910 | srca = srca + 1; /* incr addr */\r |
| 1911 | dsta = dsta + 1;\r |
| 1912 | }\r |
| 1913 | return;\r |
| 1914 | }\r |
| 1915 | \r |
| 1916 | /* I/O block transfers - byte to Unibus (0) and Unibus to byte (1) */\r |
| 1917 | \r |
| 1918 | #define BYTE1 0776000000000\r |
| 1919 | #define BYTE2 0001774000000\r |
| 1920 | #define BYTE3 0000003770000\r |
| 1921 | #define BYTE4 0000000007760\r |
| 1922 | /* unused 0000000000017 */\r |
| 1923 | \r |
| 1924 | void bltu (int32 ac, a10 ea, int32 pflgs, int dir)\r |
| 1925 | {\r |
| 1926 | a10 srca = (a10) LRZ (AC(ac));\r |
| 1927 | a10 dsta = (a10) RRZ (AC(ac));\r |
| 1928 | a10 lnt = ea - dsta + 1;\r |
| 1929 | d10 srcv, dstv;\r |
| 1930 | int32 flg, t;\r |
| 1931 | \r |
| 1932 | AC(ac) = XWD (srca + lnt, dsta + lnt);\r |
| 1933 | for (flg = 0; dsta <= ea; flg++) { /* loop */\r |
| 1934 | if (flg && (t = test_int ())) { /* timer event? */\r |
| 1935 | AC(ac) = XWD (srca, dsta); /* AC for intr */\r |
| 1936 | ABORT (t);\r |
| 1937 | }\r |
| 1938 | if (AccViol (srca & AMASK, MM_BSTK, PTF_RD)) { /* src access viol? */\r |
| 1939 | AC(ac) = XWD (srca, dsta); /* AC for page fail */\r |
| 1940 | Read (srca & AMASK, MM_BSTK); /* force trap */\r |
| 1941 | }\r |
| 1942 | if (AccViol (dsta & AMASK, MM_OPND, PTF_WR)) { /* dst access viol? */\r |
| 1943 | AC(ac) = XWD (srca, dsta); /* AC for page fail */\r |
| 1944 | ReadM (dsta & AMASK, MM_OPND); /* force trap */\r |
| 1945 | }\r |
| 1946 | srcv = Read (srca & AMASK, MM_BSTK); /* read */\r |
| 1947 | if (dir) dstv = ((srcv << 10) & BYTE1) | ((srcv >> 6) & BYTE2) |\r |
| 1948 | ((srcv << 12) & BYTE3) | ((srcv >> 4) & BYTE4);\r |
| 1949 | else dstv = ((srcv & BYTE1) >> 10) | ((srcv & BYTE2) << 6) |\r |
| 1950 | ((srcv & BYTE3) >> 12) | ((srcv & BYTE4) << 4);\r |
| 1951 | Write (dsta & AMASK, dstv, MM_OPND); /* write */\r |
| 1952 | srca = srca + 1; /* incr addr */\r |
| 1953 | dsta = dsta + 1;\r |
| 1954 | }\r |
| 1955 | return;\r |
| 1956 | }\r |
| 1957 | \r |
| 1958 | /* Utility routine to test for I/O event and interrupt */\r |
| 1959 | \r |
| 1960 | int32 test_int (void)\r |
| 1961 | {\r |
| 1962 | int32 t;\r |
| 1963 | \r |
| 1964 | if (sim_interval <= 0) { /* check queue */\r |
| 1965 | if (t = sim_process_event ()) return t; /* IO event? */\r |
| 1966 | if (pi_eval ()) return (INTERRUPT); /* interrupt? */\r |
| 1967 | }\r |
| 1968 | else sim_interval--; /* count clock */\r |
| 1969 | return 0;\r |
| 1970 | }\r |
| 1971 | \r |
| 1972 | /* Adjust stack pointer\r |
| 1973 | \r |
| 1974 | The reference manual says to trap on:\r |
| 1975 | 1) E < 0, left changes from + to -\r |
| 1976 | 2) E >= 0, left changes from - to +\r |
| 1977 | This is the same as trap on:\r |
| 1978 | 1) E and left result have same signs\r |
| 1979 | 2) initial value and left result have different signs\r |
| 1980 | */\r |
| 1981 | \r |
| 1982 | d10 adjsp (d10 val, a10 ea)\r |
| 1983 | {\r |
| 1984 | d10 imm = ea;\r |
| 1985 | d10 left, right;\r |
| 1986 | \r |
| 1987 | left = ADDL (val, imm);\r |
| 1988 | right = ADDR (val, imm);\r |
| 1989 | if (TSTS ((val ^ left) & (~left ^ RLZ (imm)))) SETF (F_T2);\r |
| 1990 | return (left | right);\r |
| 1991 | }\r |
| 1992 | \r |
| 1993 | /* Jump if find first ones\r |
| 1994 | Takes advantage of 7 bit find first table for priority interrupts.\r |
| 1995 | */\r |
| 1996 | \r |
| 1997 | int32 jffo (d10 val)\r |
| 1998 | {\r |
| 1999 | int32 i, by;\r |
| 2000 | \r |
| 2001 | if ((val & DMASK) == 0) return 0;\r |
| 2002 | for (i = 0; i <= 28; i = i + 7) { /* scan five bytes */\r |
| 2003 | by = (int32) ((val >> (29 - i)) & 0177);\r |
| 2004 | if (by) return (pi_m2lvl[by] + i - 1);\r |
| 2005 | }\r |
| 2006 | return 35; /* must be bit 35 */\r |
| 2007 | }\r |
| 2008 | \r |
| 2009 | /* Circulate - ITS only instruction\r |
| 2010 | \r |
| 2011 | Bits rotated out of AC are rotated into the opposite end of AC+1 - why?\r |
| 2012 | No attempt is made to optimize this instruction.\r |
| 2013 | */\r |
| 2014 | \r |
| 2015 | void circ (int32 ac, int32 ea)\r |
| 2016 | {\r |
| 2017 | int32 sc = LIT8 (ea) % 72;\r |
| 2018 | int32 p1 = ADDAC (ac,1);\r |
| 2019 | int32 i;\r |
| 2020 | d10 val;\r |
| 2021 | \r |
| 2022 | if (sc == 0) return; /* any shift? */\r |
| 2023 | if (ea & RSIGN) sc = 72 - sc; /* if right, make left */\r |
| 2024 | for (i = 0; i < sc; i++) { /* one bit at a time */\r |
| 2025 | val = TSTS (AC(ac)); /* shift out */\r |
| 2026 | AC(ac) = ((AC(ac) << 1) | (AC(p1) & 1)) & DMASK;\r |
| 2027 | AC(p1) = (AC(p1) >> 1) | val; /* shift in */\r |
| 2028 | }\r |
| 2029 | return;\r |
| 2030 | }\r |
| 2031 | \r |
| 2032 | /* Arithmetic processor (APR)\r |
| 2033 | \r |
| 2034 | The APR subsystem includes miscellaneous interrupts that are individually\r |
| 2035 | maskable but which interrupt on a single, selectable level\r |
| 2036 | \r |
| 2037 | Instructions for the arithmetic processor:\r |
| 2038 | APRID read system id \r |
| 2039 | WRAPR (CONO APR) write system flags\r |
| 2040 | RDAPR (CONI APR) read system flags\r |
| 2041 | (CONSO APR) test system flags\r |
| 2042 | (CONSZ APR) test system flags\r |
| 2043 | */\r |
| 2044 | \r |
| 2045 | t_bool aprid (a10 ea, int32 prv)\r |
| 2046 | {\r |
| 2047 | Write (ea, (Q_ITS)? UC_AIDITS: UC_AIDDEC, prv);\r |
| 2048 | return FALSE;\r |
| 2049 | }\r |
| 2050 | \r |
| 2051 | /* Checked against KS10 ucode */\r |
| 2052 | \r |
| 2053 | t_bool wrapr (a10 ea, int32 prv)\r |
| 2054 | {\r |
| 2055 | int32 bits = APR_GETF (ea);\r |
| 2056 | \r |
| 2057 | apr_lvl = ea & APR_M_LVL;\r |
| 2058 | if (ea & APR_SENB) apr_enb = apr_enb | bits; /* set enables? */\r |
| 2059 | if (ea & APR_CENB) apr_enb = apr_enb & ~bits; /* clear enables? */\r |
| 2060 | if (ea & APR_CFLG) apr_flg = apr_flg & ~bits; /* clear flags? */\r |
| 2061 | if (ea & APR_SFLG) apr_flg = apr_flg | bits; /* set flags? */\r |
| 2062 | if (apr_flg & APRF_ITC) { /* interrupt console? */\r |
| 2063 | fe_intr (); /* explicit callout */\r |
| 2064 | apr_flg = apr_flg & ~APRF_ITC; /* interrupt clears */\r |
| 2065 | }\r |
| 2066 | pi_eval (); /* eval pi system */\r |
| 2067 | return FALSE;\r |
| 2068 | }\r |
| 2069 | \r |
| 2070 | t_bool rdapr (a10 ea, int32 prv)\r |
| 2071 | {\r |
| 2072 | Write (ea, (d10) APRWORD, prv);\r |
| 2073 | return FALSE;\r |
| 2074 | }\r |
| 2075 | \r |
| 2076 | t_bool czapr (a10 ea, int32 prv)\r |
| 2077 | {\r |
| 2078 | return ((APRHWORD & ea)? FALSE: TRUE);\r |
| 2079 | }\r |
| 2080 | \r |
| 2081 | t_bool coapr (a10 ea, int32 prv)\r |
| 2082 | {\r |
| 2083 | return ((APRHWORD & ea)? TRUE: FALSE);\r |
| 2084 | }\r |
| 2085 | \r |
| 2086 | /* Routine to change the processor flags, called from JRST, MUUO, interrupt.\r |
| 2087 | If jrst is TRUE, must munge flags for executive security.\r |
| 2088 | Because the KS10 lacks the public flag, these checks are simplified.\r |
| 2089 | */\r |
| 2090 | \r |
| 2091 | void set_newflags (d10 newf, t_bool jrst)\r |
| 2092 | {\r |
| 2093 | int32 fl = (int32) LRZ (newf);\r |
| 2094 | \r |
| 2095 | if (jrst && TSTF (F_USR)) { /* if in user now */\r |
| 2096 | fl = fl | F_USR; /* can't clear user */\r |
| 2097 | if (!TSTF (F_UIO)) fl = fl & ~F_UIO; /* if !UIO, can't set */\r |
| 2098 | }\r |
| 2099 | if (Q_ITS && (fl & F_1PR)) { /* ITS 1-proceed? */\r |
| 2100 | its_1pr = 1; /* set flag */\r |
| 2101 | fl = fl & ~F_1PR; /* vanish bit */\r |
| 2102 | }\r |
| 2103 | flags = fl & F_MASK; /* set new flags */\r |
| 2104 | set_dyn_ptrs (); /* set new ptrs */\r |
| 2105 | return;\r |
| 2106 | }\r |
| 2107 | \r |
| 2108 | /* Priority interrupt system (PI)\r |
| 2109 | \r |
| 2110 | The priority interrupt system has three sources of requests\r |
| 2111 | (pi_apr) system flags - synthesized on the fly\r |
| 2112 | (pi_ioq) I/O interrupts - synthesized on the fly\r |
| 2113 | pi_prq program requests\r |
| 2114 | APR and I/O requests are masked with the PI enable mask; the program\r |
| 2115 | requests are not. If priority interrupts are enabled, and there is\r |
| 2116 | a request at a level exceeding the currently active level, then an\r |
| 2117 | interrupt occurs.\r |
| 2118 | \r |
| 2119 | Instructions for the priority interrupt system:\r |
| 2120 | WRPI (CONO PI) write pi system\r |
| 2121 | RDPI (CONI PI) read pi system\r |
| 2122 | (CONSO PI) test pi system\r |
| 2123 | (CONSZ PI) test pi system\r |
| 2124 | \r |
| 2125 | Routines for the priority interrupt system:\r |
| 2126 | pi_eval return level number of highest interrupt\r |
| 2127 | pi_dismiss dismiss highest outstanding interrupt\r |
| 2128 | \r |
| 2129 | Checked against KS10 ucode - KS10 UUO's if <18:21> are non-zero\r |
| 2130 | */\r |
| 2131 | \r |
| 2132 | t_bool wrpi (a10 ea, int32 prv)\r |
| 2133 | {\r |
| 2134 | int32 lvl = ea & PI_M_LVL;\r |
| 2135 | \r |
| 2136 | if (ea & PI_INIT) pi_on = pi_enb = pi_act = pi_prq = 0;\r |
| 2137 | if (ea & PI_CPRQ) pi_prq = pi_prq & ~lvl; /* clear prog reqs? */\r |
| 2138 | if (ea & PI_SPRQ) pi_prq = pi_prq | lvl; /* set prog reqs? */\r |
| 2139 | if (ea & PI_SENB) pi_enb = pi_enb | lvl; /* enable levels? */\r |
| 2140 | if (ea & PI_CENB) pi_enb = pi_enb & ~lvl; /* disable levels? */\r |
| 2141 | if (ea & PI_SON) pi_on = 1; /* enable pi? */\r |
| 2142 | if (ea & PI_CON) pi_on = 0; /* disable pi? */\r |
| 2143 | pi_eval (); /* eval pi system */\r |
| 2144 | return FALSE;\r |
| 2145 | }\r |
| 2146 | \r |
| 2147 | t_bool rdpi (a10 ea, int32 prv)\r |
| 2148 | {\r |
| 2149 | Write (ea, (d10) PIWORD, prv);\r |
| 2150 | return FALSE;\r |
| 2151 | }\r |
| 2152 | \r |
| 2153 | t_bool czpi (a10 ea, int32 prv)\r |
| 2154 | {\r |
| 2155 | return ((PIHWORD & ea)? FALSE: TRUE);\r |
| 2156 | }\r |
| 2157 | \r |
| 2158 | t_bool copi (a10 ea, int32 prv)\r |
| 2159 | {\r |
| 2160 | return ((PIHWORD & ea)? TRUE: FALSE);\r |
| 2161 | }\r |
| 2162 | \r |
| 2163 | /* Priority interrupt evaluation\r |
| 2164 | \r |
| 2165 | The Processor Reference Manuals says that program interrupt\r |
| 2166 | requests occur whether the corresponding level is enabled or\r |
| 2167 | not. However, the KS10, starting with microcode edit 47,\r |
| 2168 | masked program requests under the enable mask, just like APR\r |
| 2169 | and I/O requests. This is not formally documented but appears\r |
| 2170 | to be necessary for the TOPS20 console port to run correclty.\r |
| 2171 | */\r |
| 2172 | \r |
| 2173 | int32 pi_eval (void)\r |
| 2174 | {\r |
| 2175 | int32 reqlvl, actlvl;\r |
| 2176 | extern int32 pi_ub_eval ();\r |
| 2177 | \r |
| 2178 | qintr = 0;\r |
| 2179 | if (pi_on) {\r |
| 2180 | pi_apr = (apr_flg & apr_enb)? pi_l2bit[apr_lvl]: 0;\r |
| 2181 | pi_ioq = pi_ub_eval ();\r |
| 2182 | reqlvl = pi_m2lvl[((pi_apr | pi_ioq | pi_prq) & pi_enb)];\r |
| 2183 | actlvl = pi_m2lvl[pi_act];\r |
| 2184 | if ((actlvl == 0) || (reqlvl < actlvl)) qintr = reqlvl;\r |
| 2185 | }\r |
| 2186 | return qintr;\r |
| 2187 | }\r |
| 2188 | \r |
| 2189 | void pi_dismiss (void)\r |
| 2190 | {\r |
| 2191 | pi_act = pi_act & ~pi_l2bit[pi_m2lvl[pi_act]]; /* clr left most bit */\r |
| 2192 | pi_eval (); /* eval pi system */\r |
| 2193 | return;\r |
| 2194 | }\r |
| 2195 | \r |
| 2196 | /* Reset routine */\r |
| 2197 | \r |
| 2198 | t_stat cpu_reset (DEVICE *dptr)\r |
| 2199 | {\r |
| 2200 | flags = 0; /* clear flags */\r |
| 2201 | its_1pr = 0; /* clear 1-proceed */\r |
| 2202 | ebr = ubr = 0; /* clear paging */\r |
| 2203 | pi_enb = pi_act = pi_prq = 0; /* clear PI */\r |
| 2204 | apr_enb = apr_flg = apr_lvl = 0; /* clear APR */\r |
| 2205 | pcst = 0; /* clear PC samp */\r |
| 2206 | rlog = 0; /* clear reg log */\r |
| 2207 | hsb = (Q_ITS)? UC_HSBITS: UC_HSBDEC; /* set HSB */\r |
| 2208 | set_dyn_ptrs ();\r |
| 2209 | set_ac_display (ac_cur);\r |
| 2210 | pi_eval ();\r |
| 2211 | if (M == NULL) M = (d10 *) calloc (MAXMEMSIZE, sizeof (d10));\r |
| 2212 | if (M == NULL) return SCPE_MEM;\r |
| 2213 | pcq_r = find_reg ("PCQ", NULL, dptr);\r |
| 2214 | if (pcq_r) pcq_r->qptr = 0;\r |
| 2215 | else return SCPE_IERR;\r |
| 2216 | sim_brk_types = sim_brk_dflt = SWMASK ('E');\r |
| 2217 | return SCPE_OK;\r |
| 2218 | }\r |
| 2219 | \r |
| 2220 | /* Memory examine */\r |
| 2221 | \r |
| 2222 | t_stat cpu_ex (t_value *vptr, t_addr ea, UNIT *uptr, int32 sw)\r |
| 2223 | {\r |
| 2224 | if (vptr == NULL) return SCPE_ARG;\r |
| 2225 | if (ea < AC_NUM) *vptr = AC(ea) & DMASK;\r |
| 2226 | else {\r |
| 2227 | if (sw & SWMASK ('V')) {\r |
| 2228 | ea = conmap (ea, PTF_CON, sw);\r |
| 2229 | if (ea >= MAXMEMSIZE) return SCPE_REL;\r |
| 2230 | }\r |
| 2231 | if (ea >= MEMSIZE) return SCPE_NXM;\r |
| 2232 | *vptr = M[ea] & DMASK;\r |
| 2233 | }\r |
| 2234 | return SCPE_OK;\r |
| 2235 | }\r |
| 2236 | \r |
| 2237 | /* Memory deposit */\r |
| 2238 | \r |
| 2239 | t_stat cpu_dep (t_value val, t_addr ea, UNIT *uptr, int32 sw)\r |
| 2240 | {\r |
| 2241 | if (ea < AC_NUM) AC(ea) = val & DMASK;\r |
| 2242 | else {\r |
| 2243 | if (sw & SWMASK ('V')) {\r |
| 2244 | ea = conmap (ea, PTF_CON | PTF_WR, sw);\r |
| 2245 | if (ea >= MAXMEMSIZE) return SCPE_REL;\r |
| 2246 | }\r |
| 2247 | if (ea >= MEMSIZE) return SCPE_NXM;\r |
| 2248 | M[ea] = val & DMASK;\r |
| 2249 | }\r |
| 2250 | return SCPE_OK;\r |
| 2251 | }\r |
| 2252 | \r |
| 2253 | /* Set current AC pointers for SCP */\r |
| 2254 | \r |
| 2255 | void set_ac_display (d10 *acbase)\r |
| 2256 | {\r |
| 2257 | extern REG *find_reg (char *cptr, char **optr, DEVICE *dptr);\r |
| 2258 | REG *rptr;\r |
| 2259 | int i;\r |
| 2260 | \r |
| 2261 | rptr = find_reg ("AC0", NULL, &cpu_dev);\r |
| 2262 | if (rptr == NULL) return;\r |
| 2263 | for (i = 0; i < AC_NUM; i++, rptr++) rptr->loc = (void *) (acbase + i);\r |
| 2264 | return;\r |
| 2265 | }\r |
| 2266 | \r |
| 2267 | /* Set history */\r |
| 2268 | \r |
| 2269 | t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)\r |
| 2270 | {\r |
| 2271 | int32 i, lnt;\r |
| 2272 | t_stat r;\r |
| 2273 | \r |
| 2274 | if (cptr == NULL) {\r |
| 2275 | for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;\r |
| 2276 | hst_p = 0;\r |
| 2277 | return SCPE_OK;\r |
| 2278 | }\r |
| 2279 | lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);\r |
| 2280 | if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;\r |
| 2281 | hst_p = 0;\r |
| 2282 | if (hst_lnt) {\r |
| 2283 | free (hst);\r |
| 2284 | hst_lnt = 0;\r |
| 2285 | hst = NULL;\r |
| 2286 | }\r |
| 2287 | if (lnt) {\r |
| 2288 | hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));\r |
| 2289 | if (hst == NULL) return SCPE_MEM;\r |
| 2290 | hst_lnt = lnt;\r |
| 2291 | }\r |
| 2292 | return SCPE_OK;\r |
| 2293 | }\r |
| 2294 | \r |
| 2295 | /* Show history */\r |
| 2296 | \r |
| 2297 | t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)\r |
| 2298 | {\r |
| 2299 | int32 k, di, lnt;\r |
| 2300 | char *cptr = (char *) desc;\r |
| 2301 | t_stat r;\r |
| 2302 | t_value sim_eval;\r |
| 2303 | InstHistory *h;\r |
| 2304 | extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,\r |
| 2305 | UNIT *uptr, int32 sw);\r |
| 2306 | \r |
| 2307 | if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */\r |
| 2308 | if (cptr) {\r |
| 2309 | lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);\r |
| 2310 | if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG;\r |
| 2311 | }\r |
| 2312 | else lnt = hst_lnt;\r |
| 2313 | di = hst_p - lnt; /* work forward */\r |
| 2314 | if (di < 0) di = di + hst_lnt;\r |
| 2315 | fprintf (st, "PC AC EA IR\n\n");\r |
| 2316 | for (k = 0; k < lnt; k++) { /* print specified */\r |
| 2317 | h = &hst[(++di) % hst_lnt]; /* entry pointer */\r |
| 2318 | if (h->pc & HIST_PC) { /* instruction? */\r |
| 2319 | fprintf (st, "%06o ", h->pc & AMASK);\r |
| 2320 | fprint_val (st, h->ac, 8, 36, PV_RZRO);\r |
| 2321 | fputs (" ", st);\r |
| 2322 | fprintf (st, "%06o ", h->ea);\r |
| 2323 | sim_eval = h->ir;\r |
| 2324 | if ((fprint_sym (st, h->pc & AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) {\r |
| 2325 | fputs ("(undefined) ", st);\r |
| 2326 | fprint_val (st, h->ir, 8, 36, PV_RZRO);\r |
| 2327 | }\r |
| 2328 | fputc ('\n', st); /* end line */\r |
| 2329 | } /* end else instruction */\r |
| 2330 | } /* end for */\r |
| 2331 | return SCPE_OK;\r |
| 2332 | }\r |