1 /*
2 * vim: filetype=c:tabstop=4:ai:expandtab
3 * SPDX-License-Identifier: ICU
4 * SPDX-License-Identifier: Multics
5 * scspell-id: 7f512181-f62e-11ec-ad25-80ee73e9b8e7
6 *
7 * ---------------------------------------------------------------------------
8 *
9 * Copyright (c) 2007-2013 Michael Mondy
10 * Copyright (c) 2012-2016 Harry Reed
11 * Copyright (c) 2013-2016 Charles Anthony
12 * Copyright (c) 2016 Michal Tomek
13 * Copyright (c) 2021-2023 Jeffrey H. Johnson
14 * Copyright (c) 2021-2025 The DPS8M Development Team
15 *
16 * This software is made available under the terms of the ICU License.
17 * See the LICENSE.md file at the top-level directory of this distribution.
18 *
19 * ---------------------------------------------------------------------------
20 *
21 * This source file may contain code comments that adapt, include, and/or
22 * incorporate Multics program code and/or documentation distributed under
23 * the Multics License. In the event of any discrepancy between code
24 * comments herein and the original Multics materials, the original Multics
25 * materials should be considered authoritative unless otherwise noted.
26 * For more details and historical background, see the LICENSE.md file at
27 * the top-level directory of this distribution.
28 *
29 * ---------------------------------------------------------------------------
30 */
31
32 #include <stdio.h>
33
34 #include "dps8.h"
35 #include "dps8_sys.h"
36 #include "dps8_iom.h"
37 #include "dps8_cable.h"
38 #include "dps8_cpu.h"
39 #include "dps8_addrmods.h"
40 #include "dps8_faults.h"
41 #include "dps8_scu.h"
42 #include "dps8_append.h"
43 #include "dps8_eis.h"
44 #include "dps8_ins.h"
45 #include "dps8_math.h"
46 #include "dps8_opcodetable.h"
47 #include "dps8_decimal.h"
48 #include "dps8_iefp.h"
49 #include "dps8_utils.h"
50
51 #if defined(THREADZ) || defined(LOCKLESS)
52 # include "threadz.h"
53 #endif
54
55 #include "ver.h"
56
57 #define DBG_CTR cpu.cycleCnt
58
59 // Forward declarations
60
61 static int doABSA (cpu_state_t * cpup, word36 * result);
62 static bool scr_port_from_final_address (cpu_state_t * cpup, uint * portp);
63 HOT static t_stat doInstruction (cpu_state_t * cpup);
64 static int emCall (cpu_state_t * cpup);
65
66 #if BARREL_SHIFTER
67 static word36 barrelLeftMaskTable[37] = {
68 0000000000000ull,
69 0400000000000ull, 0600000000000ull, 0700000000000ull,
70 0740000000000ull, 0760000000000ull, 0770000000000ull,
71 0774000000000ull, 0776000000000ull, 0777000000000ull,
72 0777400000000ull, 0777600000000ull, 0777700000000ull,
73 0777740000000ull, 0777760000000ull, 0777770000000ull,
74 0777774000000ull, 0777776000000ull, 0777777000000ull,
75 0777777400000ull, 0777777600000ull, 0777777700000ull,
76 0777777740000ull, 0777777760000ull, 0777777770000ull,
77 0777777774000ull, 0777777776000ull, 0777777777000ull,
78 0777777777400ull, 0777777777600ull, 0777777777700ull,
79 0777777777740ull, 0777777777760ull, 0777777777770ull,
80 0777777777774ull, 0777777777776ull, 0777777777777ull
81 };
82 static word36 barrelRightMaskTable[37] = {
83 0000000000000ull,
84 0000000000001ull, 0000000000003ull, 0000000000007ull,
85 0000000000017ull, 0000000000037ull, 0000000000077ull,
86 0000000000177ull, 0000000000377ull, 0000000000777ull,
87 0000000001777ull, 0000000003777ull, 0000000007777ull,
88 0000000017777ull, 0000000037777ull, 0000000077777ull,
89 0000000177777ull, 0000000377777ull, 0000000777777ull,
90 0000001777777ull, 0000003777777ull, 0000007777777ull,
91 0000017777777ull, 0000037777777ull, 0000077777777ull,
92 0000177777777ull, 0000377777777ull, 0000777777777ull,
93 0001777777777ull, 0003777777777ull, 0007777777777ull,
94 0017777777777ull, 0037777777777ull, 0077777777777ull,
95 0177777777777ull, 0377777777777ull, 0777777777777ull,
96 };
97 # define BS_COMPL(HI) ((~(HI)) & MASK36)
98 #endif // BARREL_SHIFTER
99
100 #if defined(LOOPTRC)
101 void elapsedtime (void)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
102 {
103 static bool init = false;
104 static struct timespec t0;
105 struct timespec now, delta;
106
107 if (! init)
108 {
109 init = true;
110 clock_gettime (CLOCK_REALTIME, & t0);
111 }
112 clock_gettime (CLOCK_REALTIME, & now);
113 timespec_diff (& t0, & now, & delta);
114 sim_printf ("%5ld.%03ld", delta.tv_sec, delta.tv_nsec/1000000);
115 }
116 #endif
117
118 // CANFAULT
119 static void writeOperands (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
120 {
121 char buf [256];
122 CPT (cpt2U, 0); // write operands
123 DCDstruct * i = & cpu.currentInstruction;
124
125 sim_debug (DBG_ADDRMOD, & cpu_dev,
126 "%s (%s):mne=%s flags=%x\r\n",
127 __func__, disassemble (buf, IWB_IRODD), i->info->mne, i->info->flags);
128
129 PNL (cpu.prepare_state |= ps_RAW);
130
131 word6 rTAG = 0;
132 if (! (i->info->flags & NO_TAG))
133 rTAG = GET_TAG (cpu.cu.IWB);
134 word6 Td = GET_TD (rTAG);
135 word6 Tm = GET_TM (rTAG);
136
137 //
138 // IT CI/SC/SCR
139 //
140
141 if (Tm == TM_IT && (Td == IT_CI || Td == IT_SC || Td == IT_SCR))
142 {
143 //
144 // Put the character into the data word
145 //
146
147 #if defined(LOCKLESS)
148 word36 tmpdata;
149 core_read(cpup, cpu.char_word_address, &tmpdata, __func__);
150 if (tmpdata != cpu.ou.character_data)
151 sim_warn("write char: data changed from %llo to %llo at %o\r\n",
152 (long long unsigned int)cpu.ou.character_data,
153 (long long unsigned int)tmpdata, cpu.char_word_address);
154 #endif
155
156 switch (cpu.ou.characterOperandSize)
157 {
158 case TB6:
159 putChar (& cpu.ou.character_data, cpu.CY & 077, cpu.ou.characterOperandOffset);
160 break;
161
162 case TB9:
163 putByte (& cpu.ou.character_data, cpu.CY & 0777, cpu.ou.characterOperandOffset);
164 break;
165 }
166
167 //
168 // Write it
169 //
170
171 PNL (cpu.prepare_state |= ps_SAW);
172
173 #if defined(LOCKLESSXXX)
174 // gives warnings as another lock is acquired in between
175 core_write_unlock (cpup, cpu.char_word_address, cpu.ou.character_data, __func__);
176 #else
177 WriteOperandStore (cpup, cpu.ou.character_address, cpu.ou.character_data);
178 #endif
179
180 sim_debug (DBG_ADDRMOD, & cpu_dev,
181 "%s IT wrote char/byte %012"PRIo64" to %06o "
182 "tTB=%o tCF=%o\r\n",
183 __func__, cpu.ou.character_data, cpu.ou.character_address,
184 cpu.ou.characterOperandSize, cpu.ou.characterOperandOffset);
185
186 // Restore the CA; Read/Write() updates it.
187 //cpu.TPR.CA = indwordAddress;
188 cpu.TPR.CA = cpu.ou.character_address;
189 return;
190 } // IT
191
192 write_operand (cpup, cpu.TPR.CA, OPERAND_STORE);
193
194 return;
195 }
196
197 // CANFAULT
198 static void readOperands (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
199 {
200 char buf [256];
201 CPT (cpt2U, 3); // read operands
202 DCDstruct * i = & cpu.currentInstruction;
203
204 sim_debug (DBG_ADDRMOD, &cpu_dev,
205 "%s (%s):mne=%s flags=%x\r\n",
206 __func__, disassemble (buf, IWB_IRODD), i->info->mne, i->info->flags);
207 sim_debug (DBG_ADDRMOD, &cpu_dev,
208 "%s a %d address %08o\r\n", __func__, i->b29, cpu.TPR.CA);
209
210 PNL (cpu.prepare_state |= ps_POA);
211
212 word6 rTAG = 0;
213 if (! (i->info->flags & NO_TAG))
214 rTAG = GET_TAG (cpu.cu.IWB);
215 word6 Td = GET_TD (rTAG);
216 word6 Tm = GET_TM (rTAG);
217
218 //
219 // DU
220 //
221
222 if (Tm == TM_R && Td == TD_DU)
223 {
224 cpu.CY = 0;
225 SETHI (cpu.CY, cpu.TPR.CA);
226 sim_debug (DBG_ADDRMOD, & cpu_dev,
227 "%s DU CY=%012"PRIo64"\r\n", __func__, cpu.CY);
228 return;
229 }
230
231 //
232 // DL
233 //
234
235 if (Tm == TM_R && Td == TD_DL)
236 {
237 cpu.CY = 0;
238 SETLO (cpu.CY, cpu.TPR.CA);
239 sim_debug (DBG_ADDRMOD, & cpu_dev,
240 "%s DL CY=%012"PRIo64"\r\n", __func__, cpu.CY);
241 return;
242 }
243
244 //
245 // IT CI/SC/SCR
246 //
247
248 if (Tm == TM_IT && (Td == IT_CI || Td == IT_SC || Td == IT_SCR))
249 {
250 //
251 // Get the character from the data word
252 //
253
254 switch (cpu.ou.characterOperandSize)
255 {
256 case TB6:
257 cpu.CY = GETCHAR (cpu.ou.character_data, cpu.ou.characterOperandOffset);
258 break;
259
260 case TB9:
261 cpu.CY = GETBYTE (cpu.ou.character_data, cpu.ou.characterOperandOffset);
262 break;
263 }
264
265 sim_debug (DBG_ADDRMOD, & cpu_dev,
266 "%s IT read operand %012"PRIo64" from"
267 " %06o char/byte=%"PRIo64"\r\n",
268 __func__, cpu.ou.character_data, cpu.ou.character_address, cpu.CY);
269
270 // Restore the CA; Read/Write() updates it.
271 cpu.TPR.CA = cpu.ou.character_address;
272 return;
273 } // IT
274
275 #if defined(LOCKLESS)
276 if ((i->info->flags & RMW) == RMW)
277 readOperandRMW (cpup, cpu.TPR.CA);
278 else
279 readOperandRead (cpup, cpu.TPR.CA);
280 #else
281 readOperandRead (cpup, cpu.TPR.CA);
282 #endif
283
284 return;
285 }
286
287 static void read_tra_op (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
288 {
289 if (cpu.TPR.CA & 1)
290 ReadOperandRead (cpup, cpu.TPR.CA, &cpu.CY);
291 else
292 Read2OperandRead (cpup, cpu.TPR.CA, cpu.Ypair);
293 cpu.l68PairAddr = cpu.iefpFinalAddress & ~1u;
294 cpu.l68PairValid = true;
295 // The read of the target pair is the transfer's instruction fetch
296 // cycle (PM701 02C)
297 if (cpu.tweaks.l68_mode)
298 add_l68_CU_fetch_history (cpup);
299 if (! (get_addr_mode (cpup) == APPEND_mode || cpu.cu.TSN_VALID [0] ||
300 cpu.cu.XSF || cpu.currentInstruction.b29 /*get_went_appending ()*/))
301 {
302 if (cpu.currentInstruction.info->flags & TSPN_INS)
303 {
304 word3 n;
305 if (cpu.currentInstruction.opcode <= 0273) //-V536
306 n = (cpu.currentInstruction.opcode & 3);
307 else
308 n = (cpu.currentInstruction.opcode & 3) + 4;
309
310 // C(PPR.PRR) -> C(PRn.RNR)
311 // C(PPR.PSR) -> C(PRn.SNR)
312 // C(PPR.IC) -> C(PRn.WORDNO)
313 // 000000 -> C(PRn.BITNO)
314 cpu.PR[n].RNR = cpu.PPR.PRR;
315 // According the AL39, the PSR is 'undefined' in absolute mode.
316 // ISOLTS thinks it means "don't change the operand"
317 if (get_addr_mode (cpup) == APPEND_mode)
318 cpu.PR[n].SNR = cpu.PPR.PSR;
319 cpu.PR[n].WORDNO = (cpu.PPR.IC + 1) & MASK18;
320 SET_PR_BITNO (n, 0);
321 #if defined(TESTING)
322 HDBGRegPRW (n, "read_tra_op tsp");
323 #endif
324 }
325 cpu.PPR.IC = cpu.TPR.CA;
326 // ISOLTS 870-02f
327 //cpu.PPR.PSR = 0;
328 }
329 sim_debug (DBG_TRACE, & cpu_dev, "%s %05o:%06o\r\n",
330 __func__, cpu.PPR.PSR, cpu.PPR.IC);
331 if (cpu.PPR.IC & 1)
332 {
333 cpu.cu.IWB = cpu.CY;
334 cpu.cu.IRODD = cpu.CY;
335 }
336 else
337 {
338 cpu.cu.IWB = cpu.Ypair[0];
339 cpu.cu.IRODD = cpu.Ypair[1];
340 }
341 }
342
343 static void dump_words (cpu_state_t * cpup, word36 * words)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
344 {
345 sim_debug (DBG_FAULT, & cpu_dev,
346 "CU: P %d IR %#o PSR %0#o IC %0#o TSR %0#o\r\n",
347 getbits36_1 (words[0], 18), getbits36_18 (words[4], 18),
348 getbits36_15 (words[0], 3), getbits36_18 (words[4], 0), getbits36_15 (words[2], 3));
349 sim_debug (DBG_FAULT, & cpu_dev,
350 "CU: xsf %d rf %d rpt %d rd %d rl %d pot %d xde %d xdo %d itp %d rfi %d its %d fif %d hold %0#o\r\n",
351 getbits36_1 (words[0], 19),
352 getbits36_1 (words[5], 18), getbits36_1 (words[5], 19), getbits36_1 (words[5], 20), getbits36_1 (words[5], 21),
353 getbits36_1 (words[5], 22), getbits36_1 (words[5], 24), getbits36_1 (words[5], 25), getbits36_1 (words[5], 26),
354 getbits36_1 (words[5], 27), getbits36_1 (words[5], 28), getbits36_1 (words[5], 29), getbits36_6 (words[5], 30));
355 sim_debug (DBG_FAULT, & cpu_dev,
356 "CU: iwb %012"PRIo64" irodd %012"PRIo64"\r\n",
357 words[6], words[7]);
358 }
359
360 static void scu2words (cpu_state_t * cpup, word36 *words)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
361 {
362 CPT (cpt2U, 6); // scu2words
363 (void)memset (words, 0, 8 * sizeof (* words));
364
365 // words[0]
366
367 putbits36_3 (& words[0], 0, cpu.PPR.PRR);
368 putbits36_15 (& words[0], 3, cpu.PPR.PSR);
369 putbits36_1 (& words[0], 18, cpu.PPR.P);
370 // XSF, external segment flag: set by an append cycle that loaded
371 // TPR.TSR (indirect word, ITS/ITP, bit 29, rtcd), not by a plain
372 // operand access or the instruction fetch; cu.XSF means "went
373 // appending" in dps8m (PA885 10B, 01A; PA870 01A). Fetch faults keep
374 // cu.XSF, and so does absolute mode, where XSF is what keeps appending
375 // (RCU restores it; PA878 01A).
376 putbits36_1 (& words[0], 19, (cpu.cu.FIF || TST_I_ABS) ? cpu.cu.XSF : cpu.xsfScu);
377 putbits36_1 (& words[0], 20, cpu.cu.SDWAMM); // Match on SDWAM (PA866 02B)
378 putbits36_1 (& words[0], 21, cpu.cu.SD_ON);
379 putbits36_1 (& words[0], 22, cpu.cu.PTWAMM); // Match on PTWAM
380 putbits36_1 (& words[0], 23, cpu.cu.PT_ON);
381
382
383
384
385
386
387
388
389
390
391
392 // XXX Only the top 9 bits are used in APUCycleBits, so this is
393 // zeroing the 3 FTC bits at the end of the word; on the
394 // other hand this keeps the values in apuStatusBits clearer.
395 // If FTC is ever used, be sure to put its save code after this
396 // line.
397 putbits36_12 (& words[0], 24, cpu.cu.APUCycleBits);
398
399
400 // words[1]
401
402 putbits36_1 (& words[1], 0, cpu.cu.IRO_ISN);
403 putbits36_1 (& words[1], 1, cpu.cu.OEB_IOC);
404 putbits36_1 (& words[1], 2, cpu.cu.EOFF_IAIM);
405 putbits36_1 (& words[1], 3, cpu.cu.ORB_ISP);
406 putbits36_1 (& words[1], 4, cpu.cu.ROFF_IPR);
407 putbits36_1 (& words[1], 5, cpu.cu.OWB_NEA);
408 putbits36_1 (& words[1], 6, cpu.cu.WOFF_OOB);
409 putbits36_1 (& words[1], 7, cpu.cu.NO_GA);
410 putbits36_1 (& words[1], 8, cpu.cu.OCB);
411 putbits36_1 (& words[1], 9, cpu.cu.OCALL);
412 putbits36_1 (& words[1], 10, cpu.cu.BOC);
413 putbits36_1 (& words[1], 11, cpu.cu.PTWAM_ER);
414 putbits36_1 (& words[1], 12, cpu.cu.CRT);
415 putbits36_1 (& words[1], 13, cpu.cu.RALR);
416 putbits36_1 (& words[1], 14, cpu.cu.SDWAM_ER);
417 putbits36_1 (& words[1], 15, cpu.cu.OOSB);
418 putbits36_1 (& words[1], 16, cpu.cu.PARU);
419 putbits36_1 (& words[1], 17, cpu.cu.PARL);
420 putbits36_1 (& words[1], 18, cpu.cu.ONC1);
421 putbits36_1 (& words[1], 19, cpu.cu.ONC2);
422 putbits36_4 (& words[1], 20, cpu.cu.IA);
423 putbits36_3 (& words[1], 24, cpu.cu.IACHN);
424 putbits36_3 (& words[1], 27, cpu.cu.CNCHN);
425 putbits36_5 (& words[1], 30, cpu.cu.FI_ADDR);
426 putbits36_1 (& words[1], 35, cpu.cycle == INTERRUPT_cycle ? 0 : 1);
427
428 // words[2]
429
430 putbits36_3 (& words[2], 0, cpu.TPR.TRR);
431 putbits36_15 (& words[2], 3, cpu.TPR.TSR);
432 // 18, 4 PTWAM levels enabled
433 // 22, 4 SDWAM levels enabled
434 // 26, 1 0
435 putbits36_3 (& words[2], 27, (word3) cpu.switches.cpu_num);
436 putbits36_6 (& words[2], 30, cpu.cu.delta);
437
438 // words[3]
439
440 putbits36_3 (& words[3], 18, cpu.cu.TSN_VALID[0] ? cpu.cu.TSN_PRNO[0] : 0);
441 putbits36_1 (& words[3], 21, cpu.cu.TSN_VALID[0]);
442 putbits36_3 (& words[3], 22, cpu.cu.TSN_VALID[1] ? cpu.cu.TSN_PRNO[1] : 0);
443 putbits36_1 (& words[3], 25, cpu.cu.TSN_VALID[1]);
444 putbits36_3 (& words[3], 26, cpu.cu.TSN_VALID[2] ? cpu.cu.TSN_PRNO[2] : 0);
445 putbits36_1 (& words[3], 29, cpu.cu.TSN_VALID[2]);
446 putbits36_6 (& words[3], 30, cpu.TPR.TBR);
447
448 // words[4]
449
450 putbits36_18 (& words[4], 0, cpu.PPR.IC);
451
452 // According the AL39, the Hex Mode bit should be 0, but ISOLTS pas2 exec checks it;
453 // this code does not set it to zero and indicated by AL39.
454
455 putbits36_18 (& words[4], 18, cpu.cu.IR);
456
457 // ISOLTS 887 test-03a
458 // Adding this makes test03 hang instead of erroring;
459 // presumably it's stuck on some later test.
460 // An 'Add Delta' addressing mode will alter the TALLY bit;
461 // restore it.
462
463 // Breaks ISOLTS 768
464 //putbits36_1 (& words[4], 25, cpu.currentInstruction.stiTally);
465
466 //#if defined(ISOLTS)
467 //testing for ipr fault by attempting execution of
468 //the illegal opcode 000 and bit 27 not set
469 //in privileged-append-bar mode.
470 //
471 //expects ABS to be clear....
472 //
473 //testing for ipr fault by attempting execution of
474 //the illegal opcode 000 and bit 27 not set
475 //in absolute-bar mode.
476 //
477 //expects ABS to be set
478
479 //if (cpu.PPR.P && TST_I_NBAR == 0) fails 101007 absolute-bar mode; s/b set
480 //if (cpu.PPR.P == 0 && TST_I_NBAR == 0)
481 //if (TST_I_NBAR == 0 && TST_I_ABS == 1) // If ABS BAR
482 //{
483 //putbits36 (& words[4], 31, 1, 0);
484 // putbits36 (& words[4], 31, 1, cpu.PPR.P ? 0 : 1);
485 //if (current_running_cpu_idx)
486 //sim_printf ("cleared ABS\r\n");
487 //}
488 //#endif
489
490 // words[5]
491
492 putbits36 (& words[5], 0, 18, cpu.TPR.CA);
493 putbits36 (& words[5], 18, 1, cpu.cu.repeat_first);
494 putbits36 (& words[5], 19, 1, cpu.cu.rpt);
495 putbits36 (& words[5], 20, 1, cpu.cu.rd);
496 putbits36 (& words[5], 21, 1, cpu.cu.rl);
497 putbits36 (& words[5], 22, 1, cpu.cu.pot);
498 // 23, 1 PON Prepare operand no tally
499 putbits36_1 (& words[5], 24, cpu.cu.xde);
500 // While the even instruction of an xed pair executes, xdo is on
501 // internally; the SCU data has XDO only if the xed itself is at an
502 // odd address (PA885 05C: XDE; 05D: XDE+XDO)
503 putbits36_1 (& words[5], 25, cpu.cu.xdo && (! cpu.cu.xde || (cpu.PPR.IC & 1)));
504 putbits36_1 (& words[5], 26, cpu.cu.itp);
505 putbits36_1 (& words[5], 27, cpu.cu.rfi);
506 putbits36_1 (& words[5], 28, cpu.cu.its);
507 putbits36_1 (& words[5], 29, cpu.cu.FIF);
508 // In a repeat, CT-HOLD shows the tag of the last instruction completed
509 // (first time through, the rpx's own tag) (PA885 06B-06D)
510 if ((cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl) && ! cpu.cu.CT_HOLD)
511 putbits36_6 (& words[5], 30, cpu.lastTag);
512 else
513 putbits36_6 (& words[5], 30, cpu.cu.CT_HOLD);
514
515 // words[6]
516
517 words[6] = cpu.cu.IWB;
518
519 // words[7]
520
521 words[7] = cpu.cu.IRODD;
522 //sim_printf ("scu2words %lld %012llo\r\n", cpu.cycleCnt, words [6]);
523
524 if_sim_debug (DBG_FAULT, & cpu_dev)
525 dump_words (cpup, words);
526
527 if (cpu.tweaks.isolts_mode)
528 {
529 struct
530 {
531 word36 should_be[8];
532 word36 was[8];
533 char *name;
534 }
535 rewrite_table[] =
536 {
537 { { 0000001400021, 0000000000011, 0000001000100, 0000000000000,
538 0000016400000, 0110015000500, 0110015011000, 0110015011000 },
539 { 0000001400011, 0000000000011, 0000001000100, 0000000000000,
540 0000016400000, 0110015000100, 0110015011000, 0110015011000 },
541 "pa865 test-03a inhibit", // rfi
542 },
543 { { 0000000401001, 0000000000041, 0000001000100, 0000000000000,
544 0101175000220, 0000006000000, 0100006235100, 0100006235100 },
545 { 0000000601001, 0000000000041, 0000001000100, 0000000000000,
546 0101175000220, 0000006000000, 0100006235100, 0100006235100 },
547 "pa870 test-01a dir. fault",
548 },
549 { { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
550 0000000200200, 0000003000000, 0200003716100, 0000005755000 },
551 { 0000000651001, 0000000000041, 0000001000100, 0000000000000,
552 0000000200200, 0000003000000, 0200003716100, 0000005755000 },
553 "pa885 test-05a xec inst",
554 },
555 { { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
556 0000000200200, 0000002000000, 0200002717100, 0110002001000 },
557 { 0000000651001, 0000000000041, 0000001000100, 0000000000000,
558 0000000200200, 0000002000000, 0200002717100, 0110002001000 },
559 "pa885 test-05b xed inst",
560 },
561 { { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
562 0000000200200, 0000004004000, 0200004235100, 0000005755000 },
563 { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
564 0000000200200, 0000004002000, 0200004235100, 0000005755000 },
565 "pa885 test-05c xed inst", // xde/xdo
566 },
567 { { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
568 0000001200200, 0000004006000, 0200004235100, 0000005755000 },
569 { 0000000451001, 0000000000041, 0000001000100, 0000000000000,
570 0000001200200, 0000004002000, 0200004235100, 0000005755000 },
571 "pa885 test-05d xed inst", // xde/xdo
572 },
573 { { 0000000454201, 0000000000041, 0000000000100, 0000000000000,
574 0001777200200, 0002000000500, 0005600560201, 0005600560201 },
575 { 0000000450201, 0000000000041, 0000000000100, 0000000000000,
576 0001777200200, 0002000000000, 0005600560201, 0005600560201 },
577 "pa885 test-06a rpd inst", // rfi/fif
578 },
579 { { 0000000451001, 0000000000041, 0000001000101, 0000000000000,
580 0002000200200, 0000003500001, 0200003235111, 0002005755012 },
581 { 0000000651001, 0000000000041, 0000001000101, 0000000000000,
582 0002000202200, 0000003500000, 0200003235111, 0002005755012 },
583 "pa885 test-06b rpd inst", // tro ct-hold
584 },
585 { { 0000000450201, 0000000000041, 0000000000101, 0000000000000,
586 0001776200200, 0002015500001, 0002015235031, 0002017755032 },
587 { 0000000450201, 0000000000041, 0000000000101, 0000000000000,
588 0001776202200, 0002015500000, 0002015235031, 0002017755032 },
589 "pa885 test-06c rpd inst", // tro ct-hold
590 },
591 { { 0000000450201, 0000000000041, 0000000000101, 0000000000000,
592 0001776000200, 0002000100012, 0001775235011, 0001775755012 },
593 { 0000000450201, 0000000000041, 0000000000101, 0000000000000,
594 0001776000200, 0002000100000, 0001775235011, 0001775755012 },
595 "pa885 test-06d rpd inst", // ct-hold
596 },
597 { { 0000000404202, 0000000000041, 0000000000100, 0000000000000,
598 0002000202200, 0002000000500, 0001773755000, 0001773755000 },
599 { 0000000400202, 0000000000041, 0000000000100, 0000000000000,
600 0002000202200, 0002000000100, 0001773755000, 0001773755000 },
601 "pa885 test-10a scu snap (acv fault)", // rfi
602 }
603 };
604 int i;
605 for (i=0; i < 11; i++)
606 {
607 if (memcmp (words, rewrite_table[i].was, 8*sizeof (word36)) == 0)
608 {
609 memcpy (words, rewrite_table[i].should_be, 8*sizeof (word36));
610 sim_warn("%s: scu rewrite %d: %s\r\n", __func__, i, rewrite_table[i].name);
611 break;
612 }
613 }
614 }
615 }
616
617 void cu_safe_store (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
618 {
619 // Save current Control Unit Data in hidden temporary so a later SCU
620 // instruction running in FAULT mode can save the state as it existed at
621 // the time of the fault rather than as it exists at the time the SCU
622 // instruction is executed.
623 scu2words (cpup, cpu.scu_data);
624
625 cpu.cu_data.PSR = cpu.PPR.PSR;
626 cpu.cu_data.PRR = cpu.PPR.PRR;
627 cpu.cu_data.IC = cpu.PPR.IC;
628
629 tidy_cu (cpup);
630 }
631
632 void tidy_cu (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
633 {
634 // The only places this is called is in fault and interrupt processing;
635 // once the CU is saved, it needs to be set to a usable state. Refactoring
636 // that code here so that there is only a single copy to maintain.
637
638 cpu.cu.delta = 0;
639 cpu.cu.repeat_first = false;
640 cpu.cu.rpt = false;
641 cpu.cu.rd = false;
642 cpu.cu.rl = false;
643 cpu.cu.pot = false;
644 cpu.cu.itp = false;
645 cpu.cu.its = false;
646 cpu.cu.xde = false;
647 cpu.cu.xdo = false;
648 }
649
650 static void words2scu (cpu_state_t * cpup, word36 * words)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
651 {
652 CPT (cpt2U, 7); // words2scu
653 // BUG: We don't track much of the data that should be tracked
654
655 // words[0]
656
657 cpu.PPR.PRR = getbits36_3 (words[0], 0);
658 cpu.PPR.PSR = getbits36_15 (words[0], 3);
659 cpu.PPR.P = getbits36_1 (words[0], 18);
660 cpu.cu.XSF = getbits36_1 (words[0], 19);
661 sim_debug (DBG_TRACEEXT, & cpu_dev, "%s sets XSF to %o\r\n", __func__, cpu.cu.XSF);
662 //cpu.cu.SDWAMM = getbits36_1 (words[0], 20);
663 //cpu.cu.SD_ON = getbits36_1 (words[0], 21);
664 //cpu.cu.PTWAMM = getbits36_1 (words[0], 22);
665 //cpu.cu.PT_ON = getbits36_1 (words[0], 23);
666
667
668
669
670
671
672
673
674
675
676
677 //cpu.cu.APUCycleBits = getbits36_12 (words[0], 24);
678
679 // The FCT is stored in APUCycleBits
680 cpu.cu.APUCycleBits = (word12) ((cpu.cu.APUCycleBits & 07770) | (word12) getbits36_3 (words[0], 33));
681
682 // words[1]
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712 // words[2]
713
714 cpu.TPR.TRR = getbits36_3 (words[2], 0);
715 cpu.TPR.TSR = getbits36_15 (words[2], 3);
716 // 18-21 PTW
717 // 22-25 SDW
718 // 26 0
719 // 27-29 CPU number
720 cpu.cu.delta = getbits36_6 (words[2], 30);
721
722 // words[3]
723
724 // 0-17 0
725
726 cpu.cu.TSN_PRNO[0] = getbits36_3 (words[3], 18);
727 cpu.cu.TSN_VALID[0] = getbits36_1 (words[3], 21);
728 cpu.cu.TSN_PRNO[1] = getbits36_3 (words[3], 22);
729 cpu.cu.TSN_VALID[1] = getbits36_1 (words[3], 25);
730 cpu.cu.TSN_PRNO[2] = getbits36_3 (words[3], 26);
731 cpu.cu.TSN_VALID[2] = getbits36_1 (words[3], 29);
732 cpu.TPR.TBR = getbits36_6 (words[3], 30);
733
734 // words[4]
735
736 cpu.cu.IR = getbits36_18 (words[4], 18); // HWR
737 cpu.PPR.IC = getbits36_18 (words[4], 0);
738
739 // words[5]
740
741 // AL39 pg 75, RCU does not restore CA
742 //cpu.TPR.CA = getbits36_18 (words[5], 0);
743 cpu.cu.repeat_first = getbits36_1 (words[5], 18);
744 cpu.cu.rpt = getbits36_1 (words[5], 19);
745 cpu.cu.rd = getbits36_1 (words[5], 20);
746 cpu.cu.rl = getbits36_1 (words[5], 21);
747 cpu.cu.pot = getbits36_1 (words[5], 22);
748 // 23 PON
749 cpu.cu.xde = getbits36_1 (words[5], 24);
750 // XDE (even instruction of an xed pair) implies the odd one follows
751 cpu.cu.xdo = getbits36_1 (words[5], 25) | cpu.cu.xde;
752 cpu.cu.itp = getbits36_1 (words[5], 26);
753 cpu.cu.rfi = getbits36_1 (words[5], 27);
754 cpu.cu.its = getbits36_1 (words[5], 28);
755 cpu.cu.FIF = getbits36_1 (words[5], 29);
756 cpu.cu.CT_HOLD = getbits36_6 (words[5], 30);
757 // the repeated instructions take no IT/IR modifiers, so there is no
758 // modifier to restart; CT-HOLD here is the last tag (scu2words)
759 if (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)
760 cpu.cu.CT_HOLD = 0;
761
762 // words[6]
763
764 cpu.cu.IWB = words[6];
765
766 // words[7]
767
768 cpu.cu.IRODD = words[7];
769 }
770
771 void cu_safe_restore (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
772 {
773 words2scu (cpup, cpu.scu_data);
774 decode_instruction (cpup, IWB_IRODD, & cpu.currentInstruction);
775 }
776
777 static void du2words (cpu_state_t * cpup, word36 * words)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
778 {
779 CPT (cpt2U, 7); // du2words
780
781 if (cpu.tweaks.isolts_mode || cpu.tweaks.tandd_mode)
782 {
783 for (int i = 0; i < 8; i ++)
784 {
785 words[i] = cpu.du.image[i];
786 }
787 }
788 else
789 {
790 (void)memset (words, 0, 8 * sizeof (* words));
791 }
792
793 // Word 0
794
795 putbits36_1 (& words[0], 9, cpu.du.Z);
796 putbits36_1 (& words[0], 10, cpu.du.NOP);
797 putbits36_24 (& words[0], 12, cpu.du.CHTALLY);
798
799 // Word 1
800
801 if (cpu.tweaks.isolts_mode || cpu.tweaks.tandd_mode)
802 words[1] = words[0];
803
804 // Word 2
805
806 putbits36_18 (& words[2], 0, cpu.du.D1_PTR_W);
807 putbits36_6 (& words[2], 18, cpu.du.D1_PTR_B);
808 putbits36_2 (& words[2], 25, cpu.du.TAk[0]);
809 putbits36_1 (& words[2], 31, cpu.du.F1);
810 putbits36_1 (& words[2], 32, cpu.du.Ak[0]);
811
812 // Word 3
813
814 putbits36_10 (& words[3], 0, cpu.du.LEVEL1);
815 putbits36_24 (& words[3], 12, cpu.du.D1_RES);
816
817 // Word 4
818
819 putbits36_18 (& words[4], 0, cpu.du.D2_PTR_W);
820 putbits36_6 (& words[4], 18, cpu.du.D2_PTR_B);
821 putbits36_2 (& words[4], 25, cpu.du.TAk[1]);
822 putbits36_1 (& words[4], 30, cpu.du.R);
823 putbits36_1 (& words[4], 31, cpu.du.F2);
824 putbits36_1 (& words[4], 32, cpu.du.Ak[1]);
825
826 // Word 5
827
828 putbits36_10 (& words[5], 0, cpu.du.LEVEL2);
829 putbits36_24 (& words[5], 12, cpu.du.D2_RES);
830
831 // Word 6
832
833 putbits36_18 (& words[6], 0, cpu.du.D3_PTR_W);
834 putbits36_6 (& words[6], 18, cpu.du.D3_PTR_B);
835 putbits36_2 (& words[6], 25, cpu.du.TAk[2]);
836 putbits36_1 (& words[6], 31, cpu.du.F3);
837 putbits36_1 (& words[6], 32, cpu.du.Ak[2]);
838 putbits36_3 (& words[6], 33, cpu.du.JMP);
839
840 // Word 7
841
842 putbits36_24 (& words[7], 12, cpu.du.D3_RES);
843
844 }
845
846 static void words2du (cpu_state_t * cpup, word36 * words)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
847 {
848 CPT (cpt2U, 8); // words2du
849 // Word 0
850
851 cpu.du.Z = getbits36_1 (words[0], 9);
852 cpu.du.NOP = getbits36_1 (words[0], 10);
853 cpu.du.CHTALLY = getbits36_24 (words[0], 12);
854 // Word 1
855
856 // Word 2
857
858 cpu.du.D1_PTR_W = getbits36_18 (words[2], 0);
859 cpu.du.D1_PTR_B = getbits36_6 (words[2], 18);
860 cpu.du.TAk[0] = getbits36_2 (words[2], 25);
861 cpu.du.F1 = getbits36_1 (words[2], 31);
862 cpu.du.Ak[0] = getbits36_1 (words[2], 32);
863
864 // Word 3
865
866 cpu.du.LEVEL1 = getbits36_10 (words[3], 0);
867 cpu.du.D1_RES = getbits36_24 (words[3], 12);
868
869 // Word 4
870
871 cpu.du.D2_PTR_W = getbits36_18 (words[4], 0);
872 cpu.du.D2_PTR_B = getbits36_6 (words[4], 18);
873 cpu.du.TAk[1] = getbits36_2 (words[4], 25);
874 cpu.du.F2 = getbits36_1 (words[4], 31);
875 cpu.du.Ak[1] = getbits36_1 (words[4], 32);
876
877 // Word 5
878
879 cpu.du.LEVEL2 = getbits36_10 (words[5], 0);
880 cpu.du.D2_RES = getbits36_24 (words[5], 12);
881
882 // Word 6
883
884 cpu.du.D3_PTR_W = getbits36_18 (words[6], 0);
885 cpu.du.D3_PTR_B = getbits36_6 (words[6], 18);
886 cpu.du.TAk[2] = getbits36_2 (words[6], 25);
887 cpu.du.F3 = getbits36_1 (words[6], 31);
888 cpu.du.Ak[2] = getbits36_1 (words[6], 32);
889 cpu.du.JMP = getbits36_3 (words[6], 33);
890
891 // Word 7
892
893 cpu.du.D3_RES = getbits36_24 (words[7], 12);
894
895 if (cpu.tweaks.isolts_mode || cpu.tweaks.tandd_mode)
896 {
897 for (int i = 0; i < 8; i ++)
898 {
899 cpu.du.image[i] = words[i];
900 }
901 }
902 }
903
904 static char *PRalias[] = {"ap", "ab", "bp", "bb", "lp", "lb", "sp", "sb" };
905
906 //=============================================================================
907
908 // illegal modifications for various instructions
909
910 /*
911
912 00 01 02 03 04 05 06 07
913
914 00 -- au qu du ic al ql dl R
915 10 0 1 2 3 4 5 6 7
916
917 20 n* au* qu* -- ic* al* al* -- RI
918 30 0* 1* 2* 3* 4* 5* 6* 7*
919
920 40 f1 itp -- its sd scr f2 f3 IT
921 50 ci i sc ad di dic id idc
922
923 60 *n *au *qu -- *ic *al *al -- IR
924 70 *0 *1 *2 *3 *4 *5 *6 *7
925
926 bool _allowed[] = {
927 // Tm = 0 (register) R
928 // -- au qu du ic al ql dl
929 true, false, false, false, false, false, false, false,
930 // 0 1 2 3 4 5 6 7
931 false, false, false, false, false, false, false, false,
932 // Tm = 1 (register then indirect) RI
933 // n* au* qu* -- ic* al* al* --
934 false, false, false, true, false, false, false, true,
935 // 0* 1* 2* 3* 4* 5* 6* 7*
936 false, false, false, false, false, false, false, false,
937 // Tm = 2 (indirect then tally) IT
938 // f1 itp -- its sd scr f2 f3
939 false, false, true, false, false, false, false, false,
940 // ci i sc ad di dic id idc
941 false, false, false, false, false, false, false, false,
942 // Tm = 3 (indirect then register) IR
943 // *n *au *qu -- *ic *al *al --
944 false, false, false, true, false, false, false, true,
945 // *0 *1 *2 *3 *4 *5 *6 *7
946 false, false, false, false, false, false, false, false,
947 };
948
949 */
950 // No DUDL
951
952 static bool _nodudl[] = {
953 // Tm = 0 (register) R
954 // -- au qu du ic al ql dl
955 false, false, false, true, false, false, false, true,
956 // 0 1 2 3 4 5 6 7
957 false, false, false, false, false, false, false, false,
958 // Tm = 1 (register then indirect) RI
959 // n* au* qu* -- ic* al* al* --
960 false, false, false, true, false, false, false, true,
961 // 0* 1* 2* 3* 4* 5* 6* 7*
962 false, false, false, false, false, false, false, false,
963 // Tm = 2 (indirect then tally) IT
964 // f1 itp -- its sd scr f2 f3
965 false, false, true, false, false, false, false, false,
966 // ci i sc ad di dic id idc
967 false, false, false, false, false, false, false, false,
968 // Tm = 3 (indirect then register) IR
969 // *n *au *qu -- *ic *al *al --
970 false, false, false, true, false, false, false, true,
971 // *0 *1 *2 *3 *4 *5 *6 *7
972 false, false, false, false, false, false, false, false,
973 };
974
975 // No DU
976 // No DL
977
978 // (NO_CI | NO_SC | NO_SCR)
979 static bool _nocss[] = {
980 // Tm = 0 (register) R
981 // * au qu du ic al ql dl
982 false, false, false, false, false, false, false, false,
983 // 0 1 2 3 4 5 6 7
984 false, false, false, false, false, false, false, false,
985 // Tm = 1 (register then indirect) RI
986 // n* au* qu* -- ic* al* al* --
987 false, false, false, true, false, false, false, true,
988 // 0* 1* 2* 3* 4* 5* 6* 7*
989 false, false, false, false, false, false, false, false,
990 // Tm = 2 (indirect then tally) IT
991 // f1 itp -- its sd scr f2 f3
992 false, false, true, false, false, true, false, false,
993 // ci i sc ad di dic id idc
994 true, false, true, false, false, false, false, false,
995 // Tm = 3 (indirect then register) IR
996 // *r may be any register modifier but null (AL39), so *du and *dl
997 // are legal here (PS945: bcd y,*dl)
998 // *n *au *qu *du *ic *al *al *dl
999 false, false, false, false, false, false, false, false,
1000 // *0 *1 *2 *3 *4 *5 *6 *7
1001 false, false, false, false, false, false, false, false,
1002 };
1003
1004 // (NO_DUDL | NO_CISCSCR)
1005 static bool _noddcss[] = {
1006 // Tm = 0 (register) R
1007 // * au qu du ic al ql dl
1008 false, false, false, true, false, false, false, true,
1009 // 0 1 2 3 4 5 6 7
1010 false, false, false, false, false, false, false, false,
1011 // Tm = 1 (register then indirect) RI
1012 // n* au* qu* -- ic* al* al* --
1013 false, false, false, true, false, false, false, true,
1014 // 0* 1* 2* 3* 4* 5* 6* 7*
1015 false, false, false, false, false, false, false, false,
1016 // Tm = 2 (indirect then tally) IT
1017 // f1 itp -- its sd scr f2 f3
1018 false, false, true, false, false, true, false, false,
1019 // ci i sc ad di dic id idc
1020 true, false, true, false, false, false, false, false,
1021 // Tm = 3 (indirect then register) IR
1022 // *n *au *qu -- *ic *al *al --
1023 false, false, false, true, false, false, false, true,
1024 // *0 *1 *2 *3 *4 *5 *6 *7
1025 false, false, false, false, false, false, false, false,
1026 };
1027
1028 // (NO_DUDL | NO_CISCSCR)
1029 static bool _nodlcss[] = {
1030 // Tm = 0 (register) R
1031 // * au qu du ic al ql dl
1032 false, false, false, false, false, false, false, true,
1033 // 0 1 2 3 4 5 6 7
1034 false, false, false, false, false, false, false, false,
1035 // Tm = 1 (register then indirect) RI
1036 // n* au* qu* -- ic* al* al* --
1037 false, false, false, true, false, false, false, true,
1038 // 0* 1* 2* 3* 4* 5* 6* 7*
1039 false, false, false, false, false, false, false, false,
1040 // Tm = 2 (indirect then tally) IT
1041 // f1 itp -- its sd scr f2 f3
1042 false, false, true, false, false, true, false, false,
1043 // ci i sc ad di dic id idc
1044 true, false, true, false, false, false, false, false,
1045 // Tm = 3 (indirect then register) IR
1046 // *du is legal (DU is allowed); *dl is not
1047 // *n *au *qu *du *ic *al *al --
1048 false, false, false, false, false, false, false, true,
1049 // *0 *1 *2 *3 *4 *5 *6 *7
1050 false, false, false, false, false, false, false, false,
1051 };
1052
1053 static bool _onlyaqxn[] = {
1054 // Tm = 0 (register) R
1055 // -- au qu du ic al ql dl
1056 false, false, false, true, true, false, false, true,
1057 // 0 1 2 3 4 5 6 7
1058 false, false, false, false, false, false, false, false,
1059 // Tm = 1 (register then indirect) RI
1060 // n* au* qu* -- ic* al* al* --
1061 false, false, false, true, false, false, false, true,
1062 // 0* 1* 2* 3* 4* 5* 6* 7*
1063 false, false, false, false, false, false, false, false,
1064 // Tm = 2 (indirect then tally) IT
1065 // f1 itp -- its sd scr f2 f3
1066 false, false, true, false, false, false, false, false,
1067 // ci i sc ad di dic id idc
1068 false, false, false, false, false, false, false, false,
1069 // Tm = 3 (indirect then register) IR
1070 // *n *au *qu -- *ic *al *al --
1071 false, false, false, true, false, false, false, true,
1072 // *0 *1 *2 *3 *4 *5 *6 *7
1073 false, false, false, false, false, false, false, false,
1074 };
1075
1076 #if !defined(QUIET_UNUSED)
1077 static bool _illmod[] = {
1078 // Tm = 0 (register) R
1079 // * au qu du ic al ql dl
1080 false, false, false, false, false, false, false, false,
1081 // 0 1 2 3 4 5 6 7
1082 false, false, false, false, false, false, false, false,
1083 // Tm = 1 (register then indirect) RI
1084 // n* au* qu* -- ic* al* al* --
1085 false, false, false, true, false, false, false, true,
1086 // 0* 1* 2* 3* 4* 5* 6* 7*
1087 false, false, false, false, false, false, false, false,
1088 // Tm = 2 (indirect then tally) IT
1089 // f1 itp -- its sd scr f2 f3
1090 false, false, true, false, false, false, false, false,
1091 // ci i sc ad di dic id idc
1092 false, false, false, false, false, false, false, false,
1093 // Tm = 3 (indirect then register) IR
1094 // *n *au *qu -- *ic *al *al --
1095 // *0 *1 *2 *3 *4 *5 *6 *7
1096 false, false, false, true, false, false, false, true,
1097 false, false, false, false, false, false, false, false,
1098 };
1099 #endif
1100
1101 //=============================================================================
1102
1103 #if defined(MATRIX)
1104
1105 static long long theMatrix[1024] // 1024 opcodes (2^10)
1106 [2] // opcode extension
1107 [2] // bit 29
1108 [64]; // Tag
1109
1110 void initializeTheMatrix (void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1111 {
1112 (void)memset (theMatrix, 0, sizeof (theMatrix));
1113 }
1114
1115 void addToTheMatrix (uint32 opcode, bool opcodeX, bool a, word6 tag)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1116 {
1117 // safety
1118 uint _opcode = opcode & 01777;
1119 int _opcodeX = opcodeX ? 1 : 0;
1120 int _a = a ? 1 : 0;
1121 int _tag = tag & 077;
1122 theMatrix[_opcode][_opcodeX][_a][_tag] ++;
1123 }
1124
1125 t_stat display_the_matrix (UNUSED int32 arg, UNUSED const char * buf)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1126 {
1127 long long count;
1128
1129 for (int opcode = 0; opcode < 01000; opcode ++)
1130 for (int opcodeX = 0; opcodeX < 2; opcodeX ++)
1131 {
1132 long long total = 0;
1133 for (int a = 0; a < 2; a ++)
1134 for (int tag = 0; tag < 64; tag ++)
1135 if ((count = theMatrix[opcode][opcodeX][a][tag]))
1136 {
1137 // disassemble doesn't quite do what we want so copy the good bits
1138 static char result[132] = "???";
1139 strcpy (result, "???");
1140 // get mnemonic ...
1141 if (opcodes10 [opcode | (opcodeX ? 01000 : 0)].mne)
1142 strcpy (result, opcodes10[opcode | (opcodeX ? 01000 : 0)].mne);
1143 if (a)
1144 strcat (result, " prn|nnnn");
1145 else
1146 strcat (result, " nnnn");
1147
1148 // get mod
1149 if (extMods[tag].mod)
1150 {
1151 strcat (result, ",");
1152 strcat (result, extMods[tag].mod);
1153 }
1154 if (result[0] == '?')
1155 sim_printf ("%20"PRId64": ? opcode 0%04o X %d a %d tag 0%02do\r\n",
1156 count, opcode, opcodeX, a, tag);
1157 else
1158 sim_printf ("%20"PRId64": %s\r\n", count, result);
1159 total += count;
1160 }
1161 static char result[132] = "???";
1162 strcpy (result, "???");
1163 if (total) {
1164 // get mnemonic ...
1165 if (opcodes10 [opcode | (opcodeX ? 01000 : 0)].mne)
1166 strcpy (result, opcodes10[opcode | (opcodeX ? 01000 : 0)].mne);
1167 sim_printf ("%20"PRId64": %s\r\n", total, result);
1168 }
1169 }
1170 return SCPE_OK;
1171 }
1172 #endif
1173
1174 // fetch instruction at address
1175 // CANFAULT
1176 void fetchInstruction (cpu_state_t * cpup, word18 addr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1177 {
1178 CPT (cpt2U, 9); // fetchInstruction
1179
1180 if (get_addr_mode (cpup) == ABSOLUTE_mode)
1181 {
1182 cpu.TPR.TRR = 0;
1183 cpu.RSDWH_R1 = 0;
1184 //cpu.PPR.P = 1; // XXX this should be already set by set_addr_mode, so no worry here
1185 }
1186
1187 if (cpu.cu.rd && ((cpu.PPR.IC & 1) != 0))
1188 {
1189 if (cpu.cu.repeat_first)
1190 {
1191 CPT (cpt2U, 10); // fetch rpt odd
1192 //Read (addr, & cpu.cu.IRODD, INSTRUCTION_FETCH);
1193 }
1194 }
1195 else if (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)
1196 {
1197 if (cpu.cu.repeat_first)
1198 {
1199 CPT (cpt2U, 11); // fetch rpt even
1200 if (addr & 1)
1201 ReadInstructionFetch (cpup, addr, & cpu.cu.IWB);
1202 else
1203 {
1204 word36 tmp[2];
1205 /* Read2 (addr, tmp, INSTRUCTION_FETCH); */
1206 /* cpu.cu.IWB = tmp[0]; */
1207 Read2InstructionFetch (cpup, addr, tmp);
1208 cpu.cu.IWB = tmp[0];
1209 cpu.cu.IRODD = tmp[1];
1210 }
1211 }
1212 }
1213 else
1214 {
1215 CPT (cpt2U, 12); // fetch
1216
1217 // ISOLTS test pa870 expects IRODD to be set up.
1218 // If we are fetching an even instruction, also fetch the odd.
1219 // If we are fetching an odd instruction, copy it to IRODD as
1220 // if that was where we got it from.
1221
1222 //Read (addr, & cpu.cu.IWB, INSTRUCTION_FETCH);
1223 if ((cpu.PPR.IC & 1) == 0) // Even
1224 {
1225 word36 tmp[2];
1226 /* Read2 (addr, tmp, INSTRUCTION_FETCH); */
1227 /* cpu.cu.IWB = tmp[0]; */
1228 Read2InstructionFetch (cpup, addr, tmp);
1229 cpu.cu.IWB = tmp[0];
1230 cpu.cu.IRODD = tmp[1];
1231 }
1232 else // Odd
1233 {
1234 ReadInstructionFetch (cpup, addr, & cpu.cu.IWB);
1235 cpu.cu.IRODD = cpu.cu.IWB;
1236 }
1237 cpu.l68PairAddr = cpu.iefpFinalAddress & ~1u;
1238 cpu.l68PairValid = true;
1239 // The instruction fetch is a CU cycle of its own (PM701 02C)
1240 if (cpu.tweaks.l68_mode)
1241 add_l68_CU_fetch_history (cpup);
1242 // L68: PI-AP stays on after an instruction fetch, absolute and BAR
1243 // fetches too (PA870 01A: MME in absolute mode, SCU word 0 404011)
1244 if (cpu.tweaks.l68_mode)
1245 cpu.cu.APUCycleBits |= 04000;
1246 }
1247 }
1248
1249 #if defined(TESTING)
1250 void traceInstruction (uint flag)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1251 {
1252 cpu_state_t * cpup = _cpup;
1253 char buf [256];
1254 if (! flag) goto force;
1255 if_sim_debug (flag, &cpu_dev)
1256 {
1257 force:;
1258 char * compname;
1259 word18 compoffset;
1260 char * where = lookup_address (cpu.PPR.PSR, cpu.PPR.IC, & compname,
1261 & compoffset);
1262 bool isBAR = TST_I_NBAR ? false : true;
1263 if (where)
1264 {
1265 if (get_addr_mode (cpup) == ABSOLUTE_mode)
1266 {
1267 if (isBAR)
1268 {
1269 sim_debug (flag, &cpu_dev, "%06o|%06o %s\r\n",
1270 cpu.BAR.BASE, cpu.PPR.IC, where);
1271 }
1272 else
1273 {
1274 sim_debug (flag, &cpu_dev, "%06o %s\r\n", cpu.PPR.IC, where);
1275 }
1276 }
1277 else if (get_addr_mode (cpup) == APPEND_mode)
1278 {
1279 if (isBAR)
1280 {
1281 sim_debug (flag, &cpu_dev, "%05o:%06o|%06o %s\r\n",
1282 cpu.PPR.PSR,
1283 cpu.BAR.BASE, cpu.PPR.IC, where);
1284 }
1285 else
1286 {
1287 sim_debug (flag, &cpu_dev, "%05o:%06o %s\r\n",
1288 cpu.PPR.PSR, cpu.PPR.IC, where);
1289 }
1290 }
1291 list_source (compname, compoffset, flag);
1292 }
1293 if (get_addr_mode (cpup) == ABSOLUTE_mode)
1294 {
1295 if (isBAR)
1296 {
1297 sim_debug (flag, &cpu_dev,
1298 "%d: "
1299 "%05o|%06o %012"PRIo64" (%s) %06o %03o(%d) %o %o %o %02o\r\n",
1300 current_running_cpu_idx,
1301 cpu.BAR.BASE,
1302 cpu.PPR.IC,
1303 IWB_IRODD,
1304 disassemble (buf, IWB_IRODD),
1305 cpu.currentInstruction.address,
1306 cpu.currentInstruction.opcode,
1307 cpu.currentInstruction.opcodeX,
1308 cpu.currentInstruction.b29,
1309 cpu.currentInstruction.i,
1310 GET_TM (cpu.currentInstruction.tag) >> 4,
1311 GET_TD (cpu.currentInstruction.tag) & 017);
1312 }
1313 else
1314 {
1315 sim_debug (flag, &cpu_dev,
1316 "%d: "
1317 "%06o %012"PRIo64" (%s) %06o %03o(%d) %o %o %o %02o\r\n",
1318 current_running_cpu_idx,
1319 cpu.PPR.IC,
1320 IWB_IRODD,
1321 disassemble (buf, IWB_IRODD),
1322 cpu.currentInstruction.address,
1323 cpu.currentInstruction.opcode,
1324 cpu.currentInstruction.opcodeX,
1325 cpu.currentInstruction.b29,
1326 cpu.currentInstruction.i,
1327 GET_TM (cpu.currentInstruction.tag) >> 4,
1328 GET_TD (cpu.currentInstruction.tag) & 017);
1329 }
1330 }
1331 else if (get_addr_mode (cpup) == APPEND_mode)
1332 {
1333 if (isBAR)
1334 {
1335 sim_debug (flag, &cpu_dev,
1336 "%d: "
1337 "%05o:%06o|%06o %o %012"PRIo64" (%s) %06o %03o(%d) %o %o %o %02o\r\n",
1338 current_running_cpu_idx,
1339 cpu.PPR.PSR,
1340 cpu.BAR.BASE,
1341 cpu.PPR.IC,
1342 cpu.PPR.PRR,
1343 IWB_IRODD,
1344 disassemble (buf, IWB_IRODD),
1345 cpu.currentInstruction.address,
1346 cpu.currentInstruction.opcode,
1347 cpu.currentInstruction.opcodeX,
1348 cpu.currentInstruction.b29, cpu.currentInstruction.i,
1349 GET_TM (cpu.currentInstruction.tag) >> 4,
1350 GET_TD (cpu.currentInstruction.tag) & 017);
1351 }
1352 else
1353 {
1354 sim_debug (flag, &cpu_dev,
1355 "%d: "
1356 "%05o:%06o %o %012"PRIo64" (%s) %06o %03o(%d) %o %o %o %02o\r\n",
1357 current_running_cpu_idx,
1358 cpu.PPR.PSR,
1359 cpu.PPR.IC,
1360 cpu.PPR.PRR,
1361 IWB_IRODD,
1362 disassemble (buf, IWB_IRODD),
1363 cpu.currentInstruction.address,
1364 cpu.currentInstruction.opcode,
1365 cpu.currentInstruction.opcodeX,
1366 cpu.currentInstruction.b29,
1367 cpu.currentInstruction.i,
1368 GET_TM (cpu.currentInstruction.tag) >> 4,
1369 GET_TD (cpu.currentInstruction.tag) & 017);
1370 }
1371 }
1372 }
1373
1374 }
1375 #endif
1376
1377 bool chkOVF (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1378 {
1379 if (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)
1380 {
1381 // a:AL39/rpd2
1382 // Did the repeat instruction inhibit overflow faults?
1383 if ((cpu.rX[0] & 00001) == 0)
1384 return false;
1385 }
1386 return true;
1387 }
1388
1389 bool tstOVFfault (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1390 {
1391 // Masked?
1392 if (TST_I_OMASK)
1393 return false;
1394 // Doing a RPT/RPD?
1395 if (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)
1396 {
1397 // a:AL39/rpd2
1398 // Did the repeat instruction inhibit overflow faults?
1399 if ((cpu.rX[0] & 00001) == 0)
1400 return false;
1401 }
1402 return true;
1403 }
1404
1405 #if defined(TESTING)
1406 # include "tracker.h"
1407 #endif
1408
1409 t_stat executeInstruction (cpu_state_t * cpup) {
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
1410 #if defined(TESTING)
1411 trk (cpu.cycleCnt, cpu.PPR.PSR, cpu.PPR.IC, IWB_IRODD);
1412 #endif
1413 CPT (cpt2U, 13); // execute instruction
1414
1415 //
1416 // Decode the instruction
1417 //
1418 // If not restart
1419 // if xec/xed
1420 // check for illegal execute
1421 // if rpt/rpd
1422 // check for illegal rpt/rpd modifiers
1423 // check for illegal modifiers
1424 // check for privilege
1425 // initialize CA
1426 //
1427 // Save tally
1428 // Debug trace instruction
1429 // If not restart
1430 // Initialize TPR
1431 //
1432 // Initialize DU.JMP
1433 // If rpt/rpd
1434 // If first repeat
1435 // Initialize Xn
1436 //
1437 // If EIS instruction
1438 // If not restart
1439 // Initialize DU.CHTALLY, DU.Z
1440 // Read operands
1441 // Parse operands
1442 // Else not EIS instruction
1443 // If not restart
1444 // If B29
1445 // Set TPR from pointer register
1446 // Else
1447 // Setup up TPR
1448 // Initialize CU.CT_HOLD
1449 // If restart and CU.POT
1450 // Restore CA from IWB
1451 // Do CAF if needed
1452 // Read operand if needed
1453 //
1454 // Execute the instruction
1455 //
1456 // Write operand if needed
1457 // Update IT tally if needed
1458 // If XEC/XED, move instructions into IWB/IRODD
1459 // If instruction was repeated
1460 // Update Xn
1461 // Check for repeat termination
1462 // Post-instruction debug
1463
1464 ///
1465 /// executeInstruction: Decode the instruction
1466 ///
1467
1468 DCDstruct * ci = & cpu.currentInstruction;
1469 decode_instruction (cpup, IWB_IRODD, ci);
1470 const struct opcode_s *info = ci->info;
1471
1472 // Local caches of frequently accessed data
1473
1474 const uint ndes = info->ndes;
1475 const bool restart = cpu.cu.rfi; // instruction is to be restarted
1476 cpu.xsfScu = false;
1477 cpu.cu.rfi = 0;
1478 const opc_flag flags = info->flags;
1479 const enum opc_mod mods = info->mods;
1480 const uint32 opcode = ci->opcode; // opcode
1481 const bool opcodeX = ci->opcodeX; // opcode extension
1482 const word6 tag = ci->tag; // instruction tag
1483
1484 #if defined(MATRIX)
1485 {
1486 const uint32 opcode = ci->opcode; // opcode
1487 const bool opcodeX = ci->opcodeX; // opcode extension
1488 // XXX replace with rY
1489 const bool b29 = ci->b29; // bit-29 - addressing via pointer
1490 // register
1491 const word6 tag = ci->tag; // instruction tag
1492 // XXX replace withrTAG
1493 addToTheMatrix (opcode, opcodeX, b29, tag);
1494 }
1495 #endif
1496
1497 if (ci->b29)
1498 ci->address = SIGNEXT15_18 (ci->address & MASK15);
1499
1500 L68_ (
1501 CPTUR (cptUseMR);
1502 if (UNLIKELY (cpu.MR.emr && cpu.MR.OC_TRAP)) {
1503 if (cpu.MR.OPCODE == opcode && cpu.MR.OPCODEX == opcodeX) {
1504 // The trapping instruction is strobed into the CU history register
1505 // before the trap and the HR reset (PM700 02V)
1506 memcpy (& cpu.MR_cache, & cpu.MR, sizeof (cpu.MR_cache));
1507 cpu.skip_cu_hist = false;
1508 add_l68_CU_history (cpup);
1509 if (cpu.MR.ihrrs) {
1510 cpu.MR.ihr = 0;
1511 }
1512 CPT (cpt2U, 14); // opcode trap
1513 //set_FFV_fault (2); // XXX According to AL39
1514 do_FFV_fault (cpup, 1, "OC TRAP");
1515 }
1516 }
1517 )
1518
1519 ///
1520 /// executeInstruction: Non-restart processing
1521 ///
1522
1523 if (LIKELY (!restart) || UNLIKELY (ndes > 0)) { // until we implement EIS restart
1524 cpu.cu.TSN_VALID[0] = 0;
1525 cpu.cu.TSN_VALID[1] = 0;
1526 cpu.cu.TSN_VALID[2] = 0;
1527 cpu.cu.TSN_PRNO[0] = 0;
1528 cpu.cu.TSN_PRNO[1] = 0;
1529 cpu.cu.TSN_PRNO[2] = 0;
1530 }
1531
1532 if (UNLIKELY (restart))
1533 goto restart_1;
1534
1535 //
1536 // not restart
1537 //
1538
1539 cpu.cu.XSF = 0;
1540
1541 cpu.cu.pot = 0;
1542 cpu.cu.its = 0;
1543 cpu.cu.itp = 0;
1544
1545 CPT (cpt2U, 14); // non-restart processing
1546 // Set Address register empty
1547 PNL (L68_ (cpu.AR_F_E = false;))
1548
1549 // Reset the fault counter
1550 cpu.cu.APUCycleBits &= 07770;
1551
1552 //cpu.cu.TSN_VALID[0] = 0;
1553 //cpu.cu.TSN_VALID[1] = 0;
1554 //cpu.cu.TSN_VALID[2] = 0;
1555
1556 // If executing the target of XEC/XED, check the instruction is allowed
1557 if (UNLIKELY (cpu.isXED)) {
1558 if (flags & NO_XED)
1559 doFault (FAULT_IPR, fst_ill_proc,
1560 "Instruction not allowed in XEC/XED");
1561 // The even instruction from C(Y-pair) must not alter
1562 // C(Y-pair)36,71, and must not be another xed instruction.
1563 if (opcode == 0717 && !opcodeX && cpu.cu.xde && cpu.cu.xdo /* even instruction being executed */)
1564 doFault (FAULT_IPR, fst_ill_proc,
1565 "XED of XED on even word");
1566 // ISOLTS 791 03k, 792 03k
1567 if (opcode == 0560 && !opcodeX) {
1568 // To Execute Double (XED) the RPD instruction, the RPD must be the second
1569 // instruction at an odd-numbered address.
1570 if (cpu.cu.xde && cpu.cu.xdo /* even instr being executed */)
1571 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_PROC},
1572 "XED of RPD on even word");
1573 // To execute an instruction pair having an rpd instruction as the odd
1574 // instruction, the xed instruction must be located at an odd address.
1575 if (!cpu.cu.xde && cpu.cu.xdo /* odd instr being executed */ && !(cpu.PPR.IC & 1))
1576 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_PROC},
1577 "XED of RPD on odd word, even IC");
1578 }
1579 } else if (UNLIKELY (cpu.isExec)) {
1580 // To execute a rpd instruction, the xec instruction must be in an odd location.
1581 // ISOLTS 768 01w
1582 if (opcode == 0560 && !opcodeX && cpu.cu.xde && !(cpu.PPR.IC & 1))
1583 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_PROC},
1584 "XEC of RPx on even word");
1585 }
1586
1587 // ISOLTS wants both the not allowed in RPx and RPx illegal modifier
1588 // tested.
1589 fault_ipr_subtype_ RPx_fault = 0;
1590
1591 // RPT/RPD illegal modifiers
1592 // a:AL39/rpd3
1593 if (UNLIKELY (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)) {
1594 if (! (flags & NO_TAG)) {
1595 // check for illegal modifiers:
1596 // only R & RI are allowed
1597 // only X1..X7
1598 switch (GET_TM (tag)) {
1599 case TM_RI:
1600 if (cpu.cu.rl)
1601 RPx_fault |= FR_ILL_MOD;
1602 break;
1603 case TM_R:
1604 break;
1605 default:
1606 // generate fault. Only R & RI allowed
1607 RPx_fault |= FR_ILL_MOD;
1608 }
1609
1610 word6 Td = GET_TD (tag);
1611 if (Td == TD_X0)
1612 RPx_fault |= FR_ILL_MOD;
1613 if (Td < TD_X0)
1614 RPx_fault |= FR_ILL_MOD;
1615 }
1616
1617 DPS8M_ (
1618 // ISOLTS 792 03e
1619 // this is really strange. possibly a bug in DPS8M HW (L68 handles it the same as all other instructions)
1620 if (RPx_fault && !opcodeX && opcode==0413) // rscr
1621 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=RPx_fault},
1622 "DPS8M rscr early raise");
1623 )
1624
1625 // Instruction not allowed in RPx?
1626
1627 if (UNLIKELY (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)) {
1628 if (flags & NO_RPT)
1629 RPx_fault |= FR_ILL_PROC;
1630 }
1631
1632 if (UNLIKELY (cpu.cu.rl)) {
1633 if (flags & NO_RPL)
1634 RPx_fault |= FR_ILL_PROC;
1635 }
1636
1637 L68_ (
1638 // ISOLTS 791 03d, 792 03d
1639 // L68 wants ILL_MOD here - stca,stcq,stba,stbq,scpr,lcpr
1640 // all these instructions have a nonstandard TAG field interpretation. probably a HW bug in decoder
1641 if (RPx_fault && !opcodeX && (opcode==0751 || opcode==0752 || opcode==0551 || opcode==0552 || opcode==0452 || opcode==0674))
1642 RPx_fault |= FR_ILL_MOD;
1643 )
1644 }
1645
1646 // PVS-Studio says: Expression 'RPx_fault != 0' is always false.
1647 if (UNLIKELY (RPx_fault != 0)) //-V547
1648 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=RPx_fault},
1649 "RPx test fail");
1650
1651 /// check for illegal addressing mode(s) ...
1652 ///
1653 // ISOLTS wants both the IPR and illegal modifier tested.
1654 fault_ipr_subtype_ mod_fault = 0;
1655
1656 // No CI/SC/SCR allowed
1657 if (mods == NO_CSS) {
1658 if (_nocss[tag])
1659 mod_fault |= FR_ILL_MOD; // "Illegal CI/SC/SCR modification"
1660 }
1661 // No DU/DL/CI/SC/SCR allowed
1662 else if (mods == NO_DDCSS) {
1663 if (_noddcss[tag])
1664 mod_fault |= FR_ILL_MOD; // "Illegal DU/DL/CI/SC/SCR modification"
1665 }
1666 // No DL/CI/SC/SCR allowed
1667 else if (mods == NO_DLCSS) {
1668 if (_nodlcss[tag])
1669 mod_fault |= FR_ILL_MOD; // "Illegal DL/CI/SC/SCR modification"
1670 }
1671 // No DU/DL allowed
1672 else if (mods == NO_DUDL) {
1673 if (_nodudl[tag])
1674 mod_fault |= FR_ILL_MOD; // "Illegal DU/DL modification"
1675 }
1676 else if ((unsigned long long)mods == (unsigned long long)ONLY_AU_QU_AL_QL_XN) {
1677 if (_onlyaqxn[tag])
1678 mod_fault |= FR_ILL_MOD; // "Illegal DU/DL/IC modification"
1679 }
1680
1681 L68_ (
1682 // L68 raises it immediately
1683 if (mod_fault)
1684 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=mod_fault},
1685 "Illegal modifier");
1686 )
1687
1688 // check for priv ins - Attempted execution in normal or BAR modes causes a
1689 // illegal procedure fault.
1690 if (UNLIKELY (flags & PRIV_INS)) {
1691 DPS8M_ (
1692 // DPS8M illegal instructions lptp,lptr,lsdp,lsdr
1693 // ISOLTS 890 05abc
1694 if (((opcode == 0232 || opcode == 0173) && opcodeX ) || (opcode == 0257))
1695 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_OP|mod_fault},
1696 "Attempted execution of multics privileged instruction.");
1697 )
1698
1699 if (!is_priv_mode (cpup)) {
1700 // Multics privileged instructions: absa,ldbr,lra,rcu,scu,sdbr,ssdp,ssdr,sptp,sptr
1701 // ISOLTS 890 05abc,06abc
1702 bool prv;
1703 DPS8M_ (
1704 prv =((opcode == 0212 || opcode == 0232 || opcode == 0613 || opcode == 0657) && !opcodeX ) ||
1705 ((opcode == 0254 || opcode == 0774) && opcodeX ) ||
1706 (opcode == 0557 || opcode == 0154);
1707 )
1708 L68_ (
1709 // on L68, lptp,lptr,lsdp,lsdr instructions are not illegal, so handle them here
1710 prv = ((opcode == 0212 || opcode == 0232 || opcode == 0613 || opcode == 0657) && !opcodeX ) ||
1711 ((opcode == 0254 || opcode == 0774 || opcode == 0232 || opcode == 0173) && opcodeX ) ||
1712 (opcode == 0557 || opcode == 0154 || opcode == 0257);
1713 )
1714 if (prv) {
1715 if (!get_bar_mode (cpup)) {
1716 // ISOLTS-890 05ab
1717 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_SLV|mod_fault},
1718 "Attempted execution of multics privileged instruction.");
1719 } else {
1720 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_OP|mod_fault},
1721 "Attempted execution of multics privileged instruction.");
1722 }
1723 }
1724 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_SLV|mod_fault},
1725 "Attempted execution of privileged instruction.");
1726 }
1727 }
1728
1729 if (UNLIKELY (flags & NO_BAR)) {
1730 if (get_bar_mode(cpup)) {
1731 // lbar
1732 // ISOLTS 890 06a
1733 // ISOLTS says that L68 handles this in the same way
1734 if (opcode == 0230 && !opcodeX)
1735 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_SLV|mod_fault},
1736 "Attempted BAR execution of nonprivileged instruction.");
1737 else
1738 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=FR_ILL_OP|mod_fault},
1739 "Attempted BAR execution of nonprivileged instruction.");
1740 }
1741 }
1742
1743 DPS8M_ (
1744 // DPS8M raises it delayed
1745 if (UNLIKELY (mod_fault != 0))
1746 doFault (FAULT_IPR, (_fault_subtype) {.fault_ipr_subtype=mod_fault},
1747 "Illegal modifier");
1748 )
1749
1750 ///
1751 /// executeInstruction: Restart or Non-restart processing
1752 /// Initialize address registers
1753 ///
1754
1755 restart_1:
1756 CPT (cpt2U, 15); // instruction processing
1757
1758 ///
1759 /// executeInstruction: Initialize state saving registers
1760 ///
1761
1762 // XXX this may be wrong; make sure that the right value is used
1763 // if a page fault occurs. (i.e. this may belong above restart_1.
1764 // This is also used by the SCU instruction. ISOLTS tst887 does
1765 // a 'SCU n,ad' with a tally of 1; the tally is decremented, setting
1766 // the IR tally bit as part of the CA calculation; this is not
1767 // the machine conditions that the SCU instruction is saving.
1768
1769 ci->stiTally = TST_I_TALLY; // for sti instruction
1770
1771 ///
1772 /// executeInstruction: scp hooks
1773 ///
1774
1775 #if !defined(SPEED)
1776 // Don't trace Multics idle loop
1777 //if (cpu.PPR.PSR != 061 || cpu.PPR.IC != 0307)
1778
1779 {
1780 traceInstruction (DBG_TRACE);
1781 # if defined(DBGEVENT)
1782 int dbgevt;
1783 if (n_dbgevents && (dbgevt = (dbgevent_lookup (cpu.PPR.PSR, cpu.PPR.IC))) >= 0) {
1784 if (dbgevents[dbgevt].t0)
1785 clock_gettime (CLOCK_REALTIME, & dbgevent_t0);
1786 struct timespec now, delta;
1787 clock_gettime (CLOCK_REALTIME, & now);
1788 timespec_diff (& dbgevent_t0, & now, & delta);
1789 sim_printf ("[%d] %5ld.%03ld %s\r\n", dbgevt, delta.tv_sec, delta.tv_nsec/1000000, dbgevents[dbgevt].tag);
1790 }
1791 # endif
1792 # if defined(TESTING)
1793 HDBGTrace ("");
1794 # endif
1795 }
1796 #else // !SPEED
1797 // Don't trace Multics idle loop
1798 //if (cpu.PPR.PSR != 061 || cpu.PPR.IC != 0307)
1799 # if defined(TESTING)
1800 HDBGTrace ("");
1801 # endif
1802 #endif // !SPEED
1803
1804 ///
1805 /// executeInstruction: Initialize misc.
1806 ///
1807
1808 cpu.du.JMP = (word3) ndes;
1809 cpu.dlyFlt = false;
1810
1811 ///
1812 /// executeInstruction: RPT/RPD/RPL special processing for 'first time'
1813 ///
1814
1815 if (UNLIKELY (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)) {
1816 CPT (cpt2U, 15); // RPx processing
1817
1818 //
1819 // RPT:
1820 //
1821 // The computed address, y, of the operand (in the case of R modification) or
1822 // indirect word (in the case of RI modification) is determined as follows:
1823 //
1824 // For the first execution of the repeated instruction:
1825 // C(C(PPR.IC)+1)0,17 + C(Xn) -> y, y -> C(Xn)
1826 //
1827 // For all successive executions of the repeated instruction:
1828 // C(Xn) + Delta -> y, y -> C(Xn);
1829 //
1830 //
1831 // RPD:
1832 //
1833 // The computed addresses, y-even and y-odd, of the operands (in the case of
1834 // R modification) or indirect words (in the case of RI modification) are
1835 // determined as follows:
1836 //
1837 // For the first execution of the repeated instruction pair:
1838 // C(C(PPR.IC)+1)0,17 + C(X-even) -> y-even, y-even -> C(X-even)
1839 // C(C(PPR.IC)+2)0,17 + C(X-odd) -> y-odd, y-odd -> C(X-odd)
1840 //
1841 // For all successive executions of the repeated instruction pair:
1842 // if C(X0)8 = 1, then C(X-even) + Delta -> y-even,
1843 // y-even -> C(X-even);
1844 // otherwise, C(X-even) -> y-even
1845 // if C(X0)9 = 1, then C(X-odd) + Delta -> y-odd,
1846 // y-odd -> C(X-odd);
1847 // otherwise, C(X-odd) -> y-odd
1848 //
1849 // C(X0)8,9 correspond to control bits A and B, respectively, of the rpd
1850 // instruction word.
1851 //
1852 //
1853 // RL:
1854 //
1855 // The computed address, y, of the operand is determined as follows:
1856 //
1857 // For the first execution of the repeated instruction:
1858 //
1859 // C(C(PPR.IC)+1)0,17 + C(Xn) -> y, y -> C(Xn)
1860 //
1861 // For all successive executions of the repeated instruction:
1862 //
1863 // C(Xn) -> y
1864 //
1865 // if C(Y)0,17 != 0, then C (y)0,17 -> C(Xn);
1866 //
1867 // otherwise, no change to C(Xn)
1868 //
1869 // C(Y)0,17 is known as the link address and is the computed address of the
1870 // next entry in a threaded list of operands to be referenced by the repeated
1871 // instruction.
1872 //
1873
1874 sim_debug (DBG_TRACEEXT, & cpu_dev,
1875 "RPT/RPD first %d rpt %d rd %d e/o %d X0 %06o a %d b %d\r\n",
1876 cpu.cu.repeat_first, cpu.cu.rpt, cpu.cu.rd, cpu.PPR.IC & 1, cpu.rX[0],
1877 !! (cpu.rX[0] & 01000), !! (cpu.rX[0] & 0400));
1878 sim_debug (DBG_TRACEEXT, & cpu_dev,
1879 "RPT/RPD CA %06o\r\n", cpu.TPR.CA);
1880
1881 // Handle first time of a RPT or RPD
1882
1883 if (cpu.cu.repeat_first) {
1884 CPT (cpt2U, 16); // RPx first processing
1885 // The semantics of these are that even is the first instruction of
1886 // and RPD, and odd the second.
1887
1888 bool icOdd = !! (cpu.PPR.IC & 1);
1889 bool icEven = ! icOdd;
1890
1891 // If RPT or (RPD and the odd instruction)
1892 if (cpu.cu.rpt || (cpu.cu.rd && icOdd) || cpu.cu.rl)
1893 cpu.cu.repeat_first = false;
1894
1895 // a:RJ78/rpd6
1896 // For the first execution of the repeated instruction:
1897 // C(C(PPR.IC)+1)0,17 + C(Xn) -> y, y -> C(Xn)
1898 if (cpu.cu.rpt || // rpt
1899 (cpu.cu.rd && icEven) || // rpd & even
1900 (cpu.cu.rd && icOdd) || // rpd & odd
1901 cpu.cu.rl) { // rl
1902 word18 offset = ci->address;
1903 offset &= AMASK;
1904
1905 sim_debug (DBG_TRACEEXT, & cpu_dev, "rpt/rd/rl repeat first; offset is %06o\r\n", offset);
1906
1907 word6 Td = GET_TD (tag);
1908 uint Xn = X (Td); // Get Xn of next instruction
1909 sim_debug (DBG_TRACEEXT, & cpu_dev, "rpt/rd/rl repeat first; X%d was %06o\r\n", Xn, cpu.rX[Xn]);
1910 // a:RJ78/rpd5
1911 cpu.TPR.CA = (cpu.rX[Xn] + offset) & AMASK;
1912 // Xn is changed only if the instruction completes: a fault
1913 // before then leaves it as it was, and the restart (RF still
1914 // on) does this again (PA885 06B)
1915 cpu.rptXnSaved = true;
1916 cpu.rptXn = Xn;
1917 cpu.rptXnOld = cpu.rX[Xn];
1918 cpu.rX[Xn] = cpu.TPR.CA;
1919 #if defined(TESTING)
1920 HDBGRegXW (Xn, "rpt 1st");
1921 #endif
1922 sim_debug (DBG_TRACEEXT, & cpu_dev, "rpt/rd/rl repeat first; X%d now %06o\r\n", Xn, cpu.rX[Xn]);
1923 } // rpt or rd or rl
1924
1925 } // repeat first
1926 } // cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl
1927
1928 ///
1929 /// Restart or Non-restart
1930 ///
1931
1932 ///
1933 /// executeInstruction: EIS operand processing
1934 ///
1935
1936 if (UNLIKELY (ndes > 0)) {
1937 CPT (cpt2U, 27); // EIS operand processing
1938 sim_debug (DBG_APPENDING, &cpu_dev, "initialize EIS descriptors\r\n");
1939 // This must not happen on instruction restart
1940 // T&D: an interruptible EIS instruction started with MIF on resumes
1941 // from the decimal unit (AL39 "not initialized from the operand
1942 // descriptors if ... MIF is set ON"; PM842).
1943 if (!restart && ! (cpu.tweaks.tandd_mode && TST_I_MIF &&
1944 tandd_eis_interruptible (cpup))) {
1945 CPT (cpt2U, 28); // EIS not restart
1946 cpu.du.CHTALLY = 0;
1947 cpu.du.Z = 1;
1948 }
1949 cpu.tanddEISstart = cpu.du.CHTALLY;
1950 for (uint n = 0; n < ndes; n += 1) {
1951 CPT (cpt2U, 29 + n); // EIS operand fetch (29, 30, 31)
1952 // XXX This is a bit of a hack; In general the code is good about
1953 // setting up for bit29 or PR operations by setting up TPR, but
1954 // assumes that the 'else' case can be ignored when it should set
1955 // TPR to the canonical values. Here, in the case of a EIS instruction
1956 // restart after page fault, the TPR is in an unknown state. Ultimately,
1957 // this should not be an issue, as this folderol would be in the DU, and
1958 // we would not be re-executing that code, but until then, set the TPR
1959 // to the condition we know it should be in.
1960 cpu.TPR.TRR = cpu.PPR.PRR;
1961 cpu.TPR.TSR = cpu.PPR.PSR;
1962
1963
1964
1965
1966
1967
1968
1969 // append cycles updates cpu.PPR.IC to TPR.CA
1970 word18 saveIC = cpu.PPR.IC;
1971 //Read (cpu.PPR.IC + 1 + n, & cpu.currentEISinstruction.op[n], INSTRUCTION_FETCH);
1972 ReadInstructionFetch (cpup, cpu.PPR.IC + 1 + n, & cpu.currentEISinstruction.op[n]);
1973 cpu.PPR.IC = saveIC;
1974 //Read (cpu.PPR.IC + 1 + n, & cpu.currentEISinstruction.op[n], APU_DATA_READ);
1975
1976 }
1977 PNL (cpu.IWRAddr = cpu.currentEISinstruction.op[0]);
1978 setupEISoperands (cpup);
1979 }
1980
1981 ///
1982 /// Restart or Non-restart
1983 ///
1984
1985 ///
1986 /// executeInstruction: non-EIS operand processing
1987 ///
1988
1989 else {
1990 CPT (cpt2U, 32); // non-EIS operand processing
1991 CPT (cpt2U, 33); // not restart non-EIS operand processing
1992 if (ci->b29) { // if A bit set set-up TPR stuff ...
1993 CPT (cpt2U, 34); // B29
1994
1995 // AL39 says that RCU does not restore CA, so words to SCU does not.
1996 // So we do it here, even if restart
1997 word3 n = GET_PRN(IWB_IRODD); // get PRn
1998 word15 offset = GET_OFFSET(IWB_IRODD);
1999 CPTUR (cptUsePRn + n);
2000
2001 sim_debug (DBG_APPENDING, &cpu_dev,
2002 "doPtrReg: PR[%o] SNR=%05o RNR=%o WORDNO=%06o " "BITNO=%02o\r\n",
2003 n, cpu.PAR[n].SNR, cpu.PAR[n].RNR, cpu.PAR[n].WORDNO, GET_PR_BITNO (n));
2004
2005 // Fix tst880: 'call6 pr1|0'. The instruction does a DF1; the fault handler
2006 // updates PRR in the CU save data. On restart, TRR is not updated.
2007 // Removing the 'if' appears to resolve the problem without regressions.
2008 //if (!restart) {
2009 // Not EIS, bit 29 set, !restart
2010 cpu.TPR.TBR = GET_PR_BITNO (n);
2011
2012 cpu.TPR.TSR = cpu.PAR[n].SNR;
2013 if (ci->info->flags & TRANSFER_INS)
2014 cpu.TPR.TRR = max (cpu.PAR[n].RNR, cpu.PPR.PRR);
2015 else
2016 cpu.TPR.TRR = max3 (cpu.PAR[n].RNR, cpu.TPR.TRR, cpu.PPR.PRR);
2017
2018 sim_debug (DBG_APPENDING, &cpu_dev,
2019 "doPtrReg: n=%o offset=%05o TPR.CA=%06o " "TPR.TBR=%o TPR.TSR=%05o TPR.TRR=%o\r\n",
2020 n, offset, cpu.TPR.CA, cpu.TPR.TBR, cpu.TPR.TSR, cpu.TPR.TRR);
2021 //}
2022
2023 // Putting the a29 clear here makes sense, but breaks the emulator for unclear
2024 // reasons (possibly ABSA?). Do it in updateIWB instead
2025 // ci->a = false;
2026 // // Don't clear a; it is needed to detect change to appending
2027 // // mode
2028 // //a = false;
2029 // putbits36_1 (& cpu.cu.IWB, 29, 0);
2030 } else {
2031 // not eis, not bit b29
2032 if (!restart) {
2033 CPT (cpt2U, 35); // not B29
2034 cpu.cu.TSN_VALID [0] = 0;
2035 cpu.TPR.TBR = 0;
2036 if (get_addr_mode (cpup) == ABSOLUTE_mode) {
2037 cpu.TPR.TSR = cpu.PPR.PSR;
2038 cpu.TPR.TRR = 0;
2039 cpu.RSDWH_R1 = 0;
2040 }
2041 }
2042 }
2043
2044 // This must not happen on instruction restart
2045 if (!restart)
2046 cpu.cu.CT_HOLD = 0; // Clear interrupted IR mode flag
2047
2048 // These are set by do_caf
2049 cpu.ou.directOperandFlag = false;
2050 cpu.ou.directOperand = 0;
2051 cpu.ou.characterOperandSize = 0;
2052 cpu.ou.characterOperandOffset = 0;
2053 cpu.ou.crflag = false;
2054
2055 if ((flags & PREPARE_CA) || WRITEOP (ci) || READOP (ci)) {
2056 CPT (cpt2L, 1); // CAF
2057 do_caf (cpup);
2058 PNL (L68_ (cpu.AR_F_E = true;))
2059 cpu.iefpFinalAddress = cpu.TPR.CA;
2060 }
2061
2062 if (READOP (ci)) {
2063 CPT (cpt2L, 2); // Read operands
2064 readOperands (cpup);
2065 #if defined(LOCKLESS)
2066 cpu.rmw_address = cpu.iefpFinalAddress;
2067 #endif
2068 if (cpu.cu.rl) {
2069 switch (operand_size (cpup)) {
2070 case 1:
2071 cpu.lnk = GETHI36 (cpu.CY);
2072 cpu.CY &= MASK18;
2073 break;
2074
2075 case 2:
2076 cpu.lnk = GETHI36 (cpu.Ypair[0]);
2077 cpu.Ypair[0] &= MASK18;
2078 break;
2079
2080 default:
2081 break;
2082 }
2083 }
2084 }
2085 PNL (cpu.IWRAddr = 0);
2086 }
2087
2088 // Initialize zone to 'entire word'
2089
2090 cpu.useZone = false;
2091 cpu.zone = MASK36;
2092
2093 ///
2094 /// executeInstruction: Execute the instruction
2095 ///
2096
2097 t_stat ret = doInstruction (cpup);
2098
2099 ///
2100 /// executeInstruction: Write operand
2101 ///
2102
2103 cpu.last_write = 0;
2104 if (WRITEOP (ci)) {
2105 CPT (cpt2L, 3); // Write operands
2106 cpu.last_write = cpu.TPR.CA;
2107 #if defined(LOCKLESS)
2108 if ((ci->info->flags & RMW) == RMW) {
2109 if (operand_size(cpup) != 1)
2110 sim_warn("executeInstruction: operand_size!= 1\r\n");
2111 if (cpu.iefpFinalAddress != cpu.rmw_address)
2112 sim_warn("executeInstruction: write addr changed %o %d\r\n", cpu.iefpFinalAddress, cpu.rmw_address);
2113 core_write_unlock (cpup, cpu.iefpFinalAddress, cpu.CY, __func__);
2114 # if defined(TESTING)
2115 HDBGMWrite (cpu.iefpFinalAddress, cpu.CY, "Write RMW");
2116 # endif
2117 } else
2118 writeOperands (cpup);
2119 #else
2120 writeOperands (cpup);
2121 #endif
2122 }
2123
2124 else if (flags & PREPARE_CA) {
2125 // 'EPP ITS; TRA' confuses the APU by leaving last_cycle
2126 // at INDIRECT_WORD_FETCH; defoobarize the APU:
2127 fauxDoAppendCycle (cpup, OPERAND_READ);
2128 cpu.TPR.TRR = cpu.PPR.PRR;
2129 cpu.TPR.TSR = cpu.PPR.PSR;
2130 cpu.TPR.TBR = 0;
2131 }
2132
2133 ///
2134 /// executeInstruction: RPT/RPD/RPL processing
2135 ///
2136
2137 // The semantics of these are that even is the first instruction of
2138 // and RPD, and odd the second.
2139
2140 bool icOdd = !! (cpu.PPR.IC & 1);
2141 bool icEven = ! icOdd;
2142
2143 // Here, repeat_first means that the instruction just executed was the
2144 // RPT or RPD; but when the even instruction of a RPD is executed,
2145 // repeat_first is still set, since repeat_first cannot be cleared
2146 // until the odd instruction gets its first execution. Put some
2147 // ugly logic in to detect that condition.
2148
2149 bool rf = cpu.cu.repeat_first;
2150 if (rf && cpu.cu.rd && icEven)
2151 rf = false;
2152
2153 if (UNLIKELY ((! rf) && (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl))) {
2154 CPT (cpt2L, 7); // Post execution RPx
2155 // If we get here, the instruction just executed was a
2156 // RPT, RPD or RPL target instruction, and not the RPT or RPD
2157 // instruction itself
2158
2159 if (cpu.cu.rpt || cpu.cu.rd) {
2160 // Add delta to index register.
2161
2162 bool rptA = !! (cpu.rX[0] & 01000);
2163 bool rptB = !! (cpu.rX[0] & 00400);
2164
2165 // The delta added below is for the next execution; on the hardware
2166 // Xn changes when that instruction completes, so until then a fault
2167 // undoes it (doFault; PA885 06D). This instruction completed.
2168 if (cpu.cu.rpt || ! icOdd)
2169 cpu.rptUndo[0] = 0;
2170 else
2171 cpu.rptUndo[1] = 0;
2172
2173 sim_debug (DBG_TRACEEXT, & cpu_dev,
2174 "RPT/RPD delta first %d rf %d rpt %d rd %d " "e/o %d X0 %06o a %d b %d\r\n",
2175 cpu.cu.repeat_first, rf, cpu.cu.rpt, cpu.cu.rd, icOdd, cpu.rX[0], rptA, rptB);
2176
2177 if (cpu.cu.rpt) { // rpt
2178 CPT (cpt2L, 8); // RPT delta
2179 uint Xn = (uint) getbits36_3 (cpu.cu.IWB, 36 - 3);
2180 cpu.TPR.CA = (cpu.rX[Xn] + cpu.cu.delta) & AMASK;
2181 cpu.rX[Xn] = cpu.TPR.CA;
2182 cpu.rptUndo[0] = Xn + 1;
2183 #if defined(TESTING)
2184 HDBGRegXW (Xn, "rpt delta");
2185 #endif
2186 sim_debug (DBG_TRACEEXT, & cpu_dev, "RPT/RPD delta; X%d now %06o\r\n", Xn, cpu.rX[Xn]);
2187 }
2188
2189 // a:RJ78/rpd6
2190 // We know that the X register is not to be incremented until
2191 // after both instructions have executed, so the following
2192 // if uses icOdd instead of the more sensical icEven.
2193 if (cpu.cu.rd && icOdd && rptA) { // rpd, even instruction
2194 CPT (cpt2L, 9); // RD even
2195 // a:RJ78/rpd7
2196 uint Xn = (uint) getbits36_3 (cpu.cu.IWB, 36 - 3);
2197 cpu.TPR.CA = (cpu.rX[Xn] + cpu.cu.delta) & AMASK;
2198 cpu.rX[Xn] = cpu.TPR.CA;
2199 cpu.rptUndo[0] = Xn + 1;
2200 #if defined(TESTING)
2201 HDBGRegXW (Xn, "rpd delta even");
2202 #endif
2203 sim_debug (DBG_TRACEEXT, & cpu_dev, "RPT/RPD delta; X%d now %06o\r\n", Xn, cpu.rX[Xn]);
2204 }
2205
2206 if (cpu.cu.rd && icOdd && rptB) { // rpdb, odd instruction
2207 CPT (cpt2L, 10); // RD odd
2208 // a:RJ78/rpd8
2209 uint Xn = (uint) getbits36_3 (cpu.cu.IRODD, 36 - 3);
2210 cpu.TPR.CA = (cpu.rX[Xn] + cpu.cu.delta) & AMASK;
2211 cpu.rX[Xn] = cpu.TPR.CA;
2212 cpu.rptUndo[1] = Xn + 1;
2213 #if defined(TESTING)
2214 HDBGRegXW (Xn, "rpd delta odd");
2215 #endif
2216 sim_debug (DBG_TRACEEXT, & cpu_dev, "RPT/RPD delta; X%d now %06o\r\n", Xn, cpu.rX[Xn]);
2217 }
2218 } // rpt || rd
2219
2220 // Check for termination conditions.
2221
2222 ///////
2223 //
2224 // ISOLTS test 769 claims in test-02a that 'rpt;div' with a divide
2225 // fault should delay the divide fault until after the termination
2226 // check (it checks that the tally should be decremented) and in test-02b
2227 // that 'rpl;div' with a divide fault should not due the termination
2228 // check (the tally should not be decremented).
2229 //
2230 // This implies that rpt and rpl are handled differently; as a test
2231 // trying:
2232
2233 bool flt;
2234 if (cpu.tweaks.l68_mode)
2235 flt = (cpu.cu.rl || cpu.cu.rpt || cpu.cu.rd) && cpu.dlyFlt; // L68
2236 else
2237 flt = cpu.cu.rl && cpu.dlyFlt;
2238 if (flt) {
2239 CPT (cpt2L, 14); // Delayed fault
2240 doFault (cpu.dlyFltNum, cpu.dlySubFltNum, cpu.dlyCtx);
2241 }
2242
2243 // Sadly, it fixes ISOLTS 769 test 02a and 02b.
2244 //
2245 ///////
2246
2247 if (cpu.cu.rpt || (cpu.cu.rd && icOdd) || cpu.cu.rl) {
2248 CPT (cpt2L, 12); // RPx termination check
2249 bool exit = false;
2250 // The repetition cycle consists of the following steps:
2251 // a. Execute the repeated instruction
2252 // b. C(X0)0,7 - 1 -> C(X0)0,7
2253 // a:AL39/rpd9
2254 uint x = (uint) getbits18 (cpu.rX[0], 0, 8);
2255 //x -= 1;
2256 // ubsan
2257 x = (uint) (((int) x) - 1);
2258 x &= MASK8;
2259 putbits18 (& cpu.rX[0], 0, 8, x);
2260 #if defined(TESTING)
2261 HDBGRegXW (0, "rpt term");
2262 #endif
2263
2264 // a:AL39/rpd10
2265 // c. If C(X0)0,7 = 0, then set the tally runout indicator ON
2266 // and terminate
2267
2268 sim_debug (DBG_TRACEEXT, & cpu_dev, "tally %d\r\n", x);
2269 if (x == 0) {
2270 sim_debug (DBG_TRACEEXT, & cpu_dev, "tally runout\r\n");
2271 SET_I_TALLY;
2272 exit = true;
2273 } else {
2274 sim_debug (DBG_TRACEEXT, & cpu_dev, "not tally runout\r\n");
2275 CLR_I_TALLY;
2276 }
2277
2278 // d. If a terminate condition has been met, then set
2279 // the tally runout indicator OFF and terminate
2280
2281 if (TST_I_ZERO && (cpu.rX[0] & 0100)) {
2282 sim_debug (DBG_TRACEEXT, & cpu_dev, "is zero terminate\r\n");
2283 CLR_I_TALLY;
2284 exit = true;
2285 }
2286 if (!TST_I_ZERO && (cpu.rX[0] & 040)) {
2287 sim_debug (DBG_TRACEEXT, & cpu_dev, "is not zero terminate\r\n");
2288 CLR_I_TALLY;
2289 exit = true;
2290 }
2291 if (TST_I_NEG && (cpu.rX[0] & 020)) {
2292 sim_debug (DBG_TRACEEXT, & cpu_dev, "is neg terminate\r\n");
2293 CLR_I_TALLY;
2294 exit = true;
2295 }
2296 if (!TST_I_NEG && (cpu.rX[0] & 010)) {
2297 sim_debug (DBG_TRACEEXT, & cpu_dev, "is not neg terminate\r\n");
2298 CLR_I_TALLY;
2299 exit = true;
2300 }
2301 if (TST_I_CARRY && (cpu.rX[0] & 04)) {
2302 sim_debug (DBG_TRACEEXT, & cpu_dev, "is carry terminate\r\n");
2303 CLR_I_TALLY;
2304 exit = true;
2305 }
2306 if (!TST_I_CARRY && (cpu.rX[0] & 02)) {
2307 sim_debug (DBG_TRACEEXT, & cpu_dev, "is not carry terminate\r\n");
2308 CLR_I_TALLY;
2309 exit = true;
2310 }
2311 if (TST_I_OFLOW && (cpu.rX[0] & 01)) {
2312 sim_debug (DBG_TRACEEXT, & cpu_dev, "is overflow terminate\r\n");
2313 // ISOLTS test ps805 says that on overflow the tally should be set.
2314 //CLR_I_TALLY;
2315 SET_I_TALLY;
2316 exit = true;
2317 }
2318
2319 if (exit) {
2320 CPT (cpt2L, 13); // RPx terminated
2321 cpu.cu.rpt = false;
2322 cpu.cu.rd = false;
2323 cpu.cu.rl = false;
2324 // The delta matters only while the repeat runs. Kept, it showed up
2325 // in the SCU data of the next unrelated fault, so ISOLTS PS955's
2326 // isolated and sequential runs of a case saved different deltas
2327 // (01 vs 02, from PS955's own last RPT/RPD).
2328 cpu.cu.delta = 0;
2329 } else {
2330 sim_debug (DBG_TRACEEXT, & cpu_dev, "not terminate\r\n");
2331 }
2332 } // if (cpu.cu.rpt || cpu.cu.rd & (cpu.PPR.IC & 1))
2333
2334 if (cpu.cu.rl) {
2335 CPT (cpt2L, 11); // RL
2336 if (cpu.lnk == 0) {
2337 CPT (cpt2L, 13); // RPx terminated
2338 cpu.cu.rpt = false;
2339 cpu.cu.rd = false;
2340 cpu.cu.rl = false;
2341 SET_I_TALLY;
2342 cpu.cu.delta = 0; // as for RPT/RPD termination above
2343 } else {
2344 // C(Xn) -> y
2345 uint Xn = (uint) getbits36_3 (cpu.cu.IWB, 36 - 3);
2346 //word18 lnk = GETHI36 (cpu.CY);
2347 //cpu.CY &= MASK18;
2348 cpu.rX[Xn] = cpu.lnk;
2349 #if defined(TESTING)
2350 HDBGRegXW (Xn, "rl");
2351 #endif
2352 }
2353 } // rl
2354 } // (! rf) && (cpu.cu.rpt || cpu.cu.rd)
2355
2356 if (UNLIKELY (cpu.dlyFlt)) {
2357 CPT (cpt2L, 14); // Delayed fault
2358 doFault (cpu.dlyFltNum, cpu.dlySubFltNum, cpu.dlyCtx);
2359 }
2360
2361 ///
2362 /// executeInstruction: scp hooks
2363 ///
2364
2365 cpu.instrCnt ++;
2366
2367 if_sim_debug (DBG_REGDUMP, & cpu_dev) {
2368 char buf [256];
2369 sim_debug (DBG_REGDUMPAQI, &cpu_dev, "A=%012"PRIo64" Q=%012"PRIo64" IR:%s\r\n",
2370 cpu.rA, cpu.rQ, dump_flags (buf, cpu.cu.IR));
2371 #if !defined(__MINGW64__) || !defined(__MINGW32__)
2372 sim_debug (DBG_REGDUMPFLT, &cpu_dev, "E=%03o A=%012"PRIo64" Q=%012"PRIo64" %.10Lg\r\n",
2373 cpu.rE, cpu.rA, cpu.rQ, EAQToIEEElongdouble (cpup));
2374 #else
2375 sim_debug (DBG_REGDUMPFLT, &cpu_dev, "E=%03o A=%012"PRIo64" Q=%012"PRIo64" %.10g\r\n",
2376 cpu.rE, cpu.rA, cpu.rQ, EAQToIEEEdouble (cpup));
2377 #endif
2378 sim_debug (DBG_REGDUMPIDX, &cpu_dev, "X[0]=%06o X[1]=%06o X[2]=%06o X[3]=%06o\r\n",
2379 cpu.rX[0], cpu.rX[1], cpu.rX[2], cpu.rX[3]);
2380 sim_debug (DBG_REGDUMPIDX, &cpu_dev, "X[4]=%06o X[5]=%06o X[6]=%06o X[7]=%06o\r\n",
2381 cpu.rX[4], cpu.rX[5], cpu.rX[6], cpu.rX[7]);
2382 for (int n = 0 ; n < 8 ; n++) {
2383 sim_debug (DBG_REGDUMPPR, &cpu_dev, "PR%d/%s: SNR=%05o RNR=%o WORDNO=%06o BITNO:%02o ARCHAR:%o ARBITNO:%02o\r\n",
2384 n, PRalias[n], cpu.PR[n].SNR, cpu.PR[n].RNR, cpu.PR[n].WORDNO,
2385 GET_PR_BITNO (n), GET_AR_CHAR (n), GET_AR_BITNO (n));
2386 }
2387 sim_debug (DBG_REGDUMPPPR, &cpu_dev, "PRR:%o PSR:%05o P:%o IC:%06o\r\n",
2388 cpu.PPR.PRR, cpu.PPR.PSR, cpu.PPR.P, cpu.PPR.IC);
2389 sim_debug (DBG_REGDUMPDSBR, &cpu_dev, "ADDR:%08o BND:%05o U:%o STACK:%04o\r\n",
2390 cpu.DSBR.ADDR, cpu.DSBR.BND, cpu.DSBR.U, cpu.DSBR.STACK);
2391 }
2392
2393 ///
2394 /// executeInstruction: done. (Whew!)
2395 ///
2396
2397 return ret;
2398 }
2399
2400 //static t_stat DoBasicInstruction (void);
2401 //static t_stat DoEISInstruction (void);
2402
2403 static inline void overflow (cpu_state_t * cpup, bool ovf, bool dly, const char * msg)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
2404 {
2405 CPT (cpt2L, 15); // overflow check
2406 // If an overflow occurred and the repeat instruction is not inhibiting
2407 // overflow checking.
2408 if (ovf && chkOVF (cpup))
2409 {
2410 SET_I_OFLOW;
2411 // If overflows are not masked
2412 if (tstOVFfault (cpup))
2413 {
2414 CPT (cpt2L, 16); // overflow
2415 // ISOLTS test ps768: Overflows set TRO.
2416 if (cpu.cu.rpt || cpu.cu.rd || cpu.cu.rl)
2417 {
2418 SET_I_TALLY;
2419 }
2420 if (dly)
2421 dlyDoFault (FAULT_OFL, fst_zero, msg);
2422 else
2423 doFault (FAULT_OFL, fst_zero, msg);
2424 }
2425 }
2426 }
2427
2428 // Return values
2429 // CONT_TRA
2430 // STOP_UNIMP
2431 // STOP_ILLOP
2432 // emCall()
2433 // STOP_HALT
2434 // scu_sscr()
2435 // STOP_BUG
2436 // STOP_WARN
2437 // scu_rmcm()
2438 // STOP_BUG
2439 // scu_smcm()
2440 // STOP_DIS
2441 // simh_hooks()
2442 // hard to document what this can return....
2443 // 0
2444 //
2445
2446 // CANFAULT
2447 HOT static t_stat doInstruction (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
2448 {
2449 DCDstruct * i = & cpu.currentInstruction;
2450 // AL39 says it is always cleared, but that makes no sense (what good
2451 // is an indicator bit if it is always 0 when you check it?). Clear it if
2452 // an multiword EIS is at bat.
2453 // NB: Never clearing it renders Multics unbootable.
2454 if (i->info->ndes > 0)
2455 CLR_I_MIF;
2456
2457 L68_ (
2458 cpu.ou.eac = 0;
2459 cpu.ou.RB1_FULL = 0;
2460 cpu.ou.RP_FULL = 0;
2461 cpu.ou.RS_FULL = 0;
2462 cpu.ou.STR_OP = 0;
2463 cpu.ou.cycle = 0;
2464 )
2465 // The L68 OU history register records RS (PM700 01M), so keep it in
2466 // every build, not only PANEL68
2467 L68_ (cpu.ou.RS = (word9) i->opcode;)
2468 PNL (L68_ (DU_CYCLE_FDUD;)) // set DU idle
2469 cpu.skip_cu_hist = false;
2470
2471 //memcpy (& cpu.MR_cache, & cpu.MR, sizeof (cpu.MR_cache));
2472 // Only these MR fields are actually used by the history logic.
2473 // Snapshot them now without copying the entire register. The L68 CU
2474 // history reads O.C$ (bit 29) and the OPCODE field (18-27) from r
2475 // (PM700 02Y); without this r was stale from the last OC trap.
2476 cpu.MR_cache.r = cpu.MR.r;
2477 cpu.MR_cache.emr = cpu.MR.emr;
2478 cpu.MR_cache.ihr = cpu.MR.ihr;
2479 cpu.MR_cache.hrxfr = cpu.MR.hrxfr;
2480
2481 // This mapping keeps nonEIS/EIS ordering, making various tables cleaner
2482 #define x0(n) (n)
2483 #define x1(n) (n|01000)
2484
2485 //t_stat ret = i->opcodeX ? DoEISInstruction () : DoBasicInstruction ();
2486 uint32 opcode10 = i->opcode10;
2487
2488 #if defined(PANEL68)
2489 if (insGrp [opcode10])
2490 {
2491 word8 grp = insGrp [opcode10] - 1;
2492 uint row = grp / 36;
2493 uint col = grp % 36;
2494 CPT (cpt3U + row, col); // 3U 0-35, 3L 0-17
2495 }
2496 #endif
2497 bool is_ou = false;
2498 bool is_du = false;
2499 if (cpu.tweaks.l68_mode) { // L68
2500 if (opcodes10[opcode10].reg_use & is_OU) {
2501 is_ou = true;
2502 // XXX Punt on RP FULL, RS FULL
2503 cpu.ou.RB1_FULL = cpu.ou.RP_FULL = cpu.ou.RS_FULL = 1;
2504 cpu.ou.cycle |= ou_GIN;
2505 #if defined(PANEL68)
2506 cpu.ou.opsz = (opcodes10[i->opcode10].reg_use >> 12) & 037;
2507 word10 reguse = (opcodes10[i->opcode10].reg_use) & MASK10;
2508 cpu.ou.reguse = reguse;
2509 if (reguse & ru_A) CPT (cpt5U, 4);
2510 if (reguse & ru_Q) CPT (cpt5U, 5);
2511 if (reguse & ru_X0) CPT (cpt5U, 6);
2512 if (reguse & ru_X1) CPT (cpt5U, 7);
2513 if (reguse & ru_X2) CPT (cpt5U, 8);
2514 if (reguse & ru_X3) CPT (cpt5U, 9);
2515 if (reguse & ru_X4) CPT (cpt5U, 10);
2516 if (reguse & ru_X5) CPT (cpt5U, 11);
2517 if (reguse & ru_X6) CPT (cpt5U, 12);
2518 if (reguse & ru_X7) CPT (cpt5U, 13);
2519 #endif // PANEL68
2520 }
2521 if (opcodes10[opcode10].reg_use & is_DU) {
2522 is_du = true;
2523 PNL (DU_CYCLE_nDUD;) // set not idle
2524 }
2525 }
2526
2527 switch (opcode10)
2528 {
2529 // Operations sorted by frequency of use; should help with caching issues
2530
2531 // Operations counts from booting and build a boot tape from source:
2532 // 1605873148: eppn
2533 // 845109778: sprin
2534 // 702257337: lda
2535 // 637613648: tra
2536 // 555520875: ldq
2537 // 462569862: tze
2538 // 322979813: tnz
2539 // 288200618: stq
2540 // 260400300: cmpq
2541 // 192454329: anaq
2542 // 187283749: sta
2543 // 170691055: lprpn
2544 // 167568868: eaxn
2545 // 166842812: tsxn
2546 // 161542573: stz
2547 // 155129792: epbpn
2548 // 153639462: cmpa
2549 // 144804232: aos
2550 // 133559646: cana
2551 // 127230192: ldaq
2552 // 119988496: tpnz
2553 // 113295654: lxln
2554 // 109645303: staq
2555 // 109417021: tspn
2556 // 108352453: als
2557 // 96267840: rtcd
2558 // 93570029: tmi
2559 // 93161815: stxn
2560 // 90485871: ldi
2561 // 87421892: eraq
2562 // 76632891: ora
2563 // 75372023: adq
2564 // 75036448: tmoz
2565 // 64921645: spbpn
2566 // 63595794: ana
2567 // 62621406: fld
2568 // 57281513: epaq
2569 // 56066122: qls
2570 // 55861962: sti
2571 // 55186331: mlr
2572 // 54388393: call6
2573 // 50000721: lrl
2574 // 49736026: sbq
2575 // 49552594: tpl
2576 // 46097756: cmpb
2577 // 44484993: szn
2578 // 41295856: arl
2579 // 40019677: lrs
2580 // 39386119: sprpn
2581 // 36130580: ldxn
2582 // 32168708: ersa
2583 // 31817270: cmpxn
2584 // 31280696: a9bd
2585 // 29383886: era
2586 // 29282465: lls
2587 // 28714658: mpy
2588 // 28508378: sba
2589 // 24067324: anq
2590 // 23963178: asq
2591 // 23953122: nop
2592 // 23643534: orsa
2593 // 23083282: csl
2594 // 20970795: sbxn
2595 // 20109045: tct
2596 // 18504719: stba
2597 // 18297461: eaq
2598 // 17130040: eaa
2599 // 16035441: cmpc
2600 // 15762874: sxln
2601 // 15109836: lca
2602 // 15013924: adxn
2603 // 14159104: lcq
2604 // 14049597: div
2605 // 14043543: cmpaq
2606 // 13528591: ada
2607 // 12778888: ansa
2608 // 12534711: trc
2609 // 11710149: sbaq
2610 // 11584853: neg
2611 // 11456885: ttn
2612 // 11356918: canq
2613 // 10797383: rccl
2614 // 10743245: asa
2615 // 10100949: ttf
2616 // 9691628: orq
2617 // 9332512: adwp0-3
2618 // 9251904: anxn
2619 // 8076030: ldac
2620 // 8061536: scd
2621 // 7779639: adaq
2622 // 7586713: xec
2623 // 7506406: qrl
2624 // 7442522: adl
2625 // 6535658: stca
2626 // 6359531: adlxn
2627 // 6255134: sbla
2628 // 5936484: stacq
2629 // 5673345: eawp2
2630 // 4671545: tnc
2631 // 4230412: scm
2632 // 4040255: sarn
2633 // 4006015: oraq
2634 // 3918690: adlq
2635 // 3912600: stbq
2636 // 3449053: lcxn
2637 // 3368670: adla
2638 // 3290057: qrs
2639 // 3252438: ars
2640 // 3143543: qlr
2641 // 3098158: stac
2642 // 2838451: mvne
2643 // 2739787: lde
2644 // 2680484: btd
2645 // 2573170: erq
2646 // 2279433: fno
2647 // 2273692: smcm
2648 // 2240713: ersq
2649 // 2173455: sreg
2650 // 2173196: lreg
2651 // 2112784: mrl
2652 // 2030237: mvt
2653 // 2010819: stc2
2654 // 2008675: fmp
2655 // 1981148: llr
2656 // 1915081: mvn
2657 // 1846728: sblxn
2658 // 1820604: fcmp
2659 // 1765253: lcpr
2660 // 1447485: stc1
2661 // 1373184: ansxn
2662 // 1337744: negl
2663 // 1264062: rscr
2664 // 1201563: adwp4-7
2665 // 1198321: rmcm
2666 // 1182814: sznc
2667 // 1171307: sblq
2668 // 1140227: spri
2669 // 1139968: lpri
2670 // 1133946: dvf
2671 // 1059600: scpr
2672 // 958321: stcq
2673 // 837695: tctr
2674 // 820615: s9bd
2675 // 812523: rsw
2676 // 769275: fad
2677 // 729737: orsq
2678 // 651623: scu
2679 // 651612: rcu
2680 // 606518: abd
2681 // 603591: eawp1
2682 // 555935: orsxn
2683 // 525680: scmr
2684 // 467605: spl
2685 // 467405: lpl
2686 // 463927: lra
2687 // 416700: awd
2688 // 384090: dtb
2689 // 383544: cmk
2690 // 382254: fst
2691 // 378820: ssa
2692 // 370308: sra
2693 // 326432: alr
2694 // 321319: ldt
2695 // 319911: ldbr
2696 // 319908: sbar
2697 // 319907: lbar
2698 // 310379: cams
2699 // 303041: eawp7
2700 // 299122: xed
2701 // 294724: easp2
2702 // 270712: sztl
2703 // 252001: dfst
2704 // 241844: ste
2705 // 226970: absa
2706 // 218891: cioc
2707 // 184535: dfld
2708 // 182347: camp
2709 // 174567: ansq
2710 // 169317: rpt
2711 // 124972: erx2
2712 // 121933: fneg
2713 // 114697: cnaaq
2714 // 111728: rpd
2715 // 106892: dis
2716 // 96801: tov
2717 // 92283: fsb
2718 // 86209: erx4
2719 // 80564: eawp3
2720 // 76911: canaq
2721 // 65706: ufa
2722 // 65700: dfcmp
2723 // 64530: fdv
2724 // 48215: ldqc
2725 // 45994: dfad
2726 // 37790: awca
2727 // 27218: asxn
2728 // 23203: eawp5
2729 // 16947: gtb
2730 // 11431: ersxn
2731 // 9527: erx3
2732 // 8888: ssdr
2733 // 8888: ssdp
2734 // 8888: sptr
2735 // 8888: sptp
2736 // 8170: ssq
2737 // 7116: mp3d
2738 // 6969: cmg
2739 // 6878: dv3d
2740 // 5615: eawp6
2741 // 4859: easp1
2742 // 4726: easp3
2743 // 3157: ad2d
2744 // 2807: eawp4
2745 // 2807: easp4
2746 // 2411: cwl
2747 // 1912: teu
2748 // 1912: teo
2749 // 1798: cmpn
2750 // 1625: easp6
2751 // 931: adlaq
2752 // 659: erx1
2753 // 500: ???
2754 // 388: csr
2755 // 215: sb3d
2756 // 176: dfdv
2757 // 93: stcd
2758 // 92: mp2d
2759 // 41: sscr
2760 // 26: dfmp
2761 // 14: ad3d
2762 // 12: mve
2763 // 11: dfsb
2764 // 5: sdbr
2765 // 4: trtf
2766 // 4: orxn
2767 // 3: sb2d
2768 // 2: scdr
2769 // 1: stt
2770 // 1: ret
2771 // 1: drl
2772
2773 case x0 (0350): // epp0
2774 case x1 (0351): // epp1
2775 case x0 (0352): // epp2
2776 case x1 (0353): // epp3
2777 case x0 (0370): // epp4
2778 case x1 (0371): // epp5
2779 case x0 (0372): // epp6
2780 case x1 (0373): // epp7
2781 // For n = 0, 1, ..., or 7 as determined by operation code
2782 // C(TPR.TRR) -> C(PRn.RNR)
2783 // C(TPR.TSR) -> C(PRn.SNR)
2784 // C(TPR.CA) -> C(PRn.WORDNO)
2785 // C(TPR.TBR) -> C(PRn.BITNO)
2786 {
2787 // epp0 0350 101 000
2788 // epp1 1351 101 001
2789 // epp2 0352 101 010
2790 // epp3 1353 101 011
2791 // epp4 0370 111 000
2792 // epp5 1371 111 001
2793 // epp6 0372 111 010
2794 // epp7 1373 111 011
2795 //n = ((opcode10 & 020) ? 4 : 0) + (opcode10 & 03);
2796 uint n = ((opcode10 & 020) >> 2) | (opcode10 & 03);
2797 CPTUR (cptUsePRn + n);
2798 cpu.PR[n].RNR = cpu.TPR.TRR;
2799 cpu.PR[n].SNR = cpu.TPR.TSR;
2800 cpu.PR[n].WORDNO = cpu.TPR.CA;
2801 SET_PR_BITNO (n, cpu.TPR.TBR);
2802 #if defined(TESTING)
2803 HDBGRegPRW (n, "epp");
2804 #endif
2805 }
2806 break;
2807
2808 case x0 (0250): // spri0
2809 case x1 (0251): // spri1
2810 case x0 (0252): // spri2
2811 case x1 (0253): // spri3
2812 case x0 (0650): // spri4
2813 case x1 (0651): // spri5
2814 case x0 (0652): // spri6
2815 case x1 (0653): // spri7
2816
2817 // For n = 0, 1, ..., or 7 as determined by operation code
2818 // 000 -> C(Y-pair)0,2
2819 // C(PRn.SNR) -> C(Y-pair)3,17
2820 // C(PRn.RNR) -> C(Y-pair)18,20
2821 // 00...0 -> C(Y-pair)21,29
2822 // (43)8 -> C(Y-pair)30,35
2823 // C(PRn.WORDNO) -> C(Y-pair)36,53
2824 // 000 -> C(Y-pair)54,56
2825 // C(PRn.BITNO) -> C(Y-pair)57,62
2826 // 00...0 -> C(Y-pair)63,71
2827 {
2828 // spri0 0250 0 010 101 000
2829 // spri1 1251 1 010 101 001
2830 // spri2 0252 0 010 101 010
2831 // spri3 1253 1 010 101 011
2832 // spri4 0650 0 110 101 000
2833 // spri5 1651 1 110 101 001
2834 // spri6 0652 0 110 101 010
2835 // spri7 1653 1 110 101 011
2836 //uint n = ((opcode10 & 0400) ? 4 : 0) + (opcode10 & 03);
2837 uint n = ((opcode10 & 0400) >> 6) | (opcode10 & 03);
2838 CPTUR (cptUsePRn + n);
2839 #if defined(TESTING)
2840 HDBGRegPRR (n, "spri");
2841 #endif
2842 cpu.Ypair[0] = 043;
2843 cpu.Ypair[0] |= ((word36) cpu.PR[n].SNR) << 18;
2844 cpu.Ypair[0] |= ((word36) cpu.PR[n].RNR) << 15;
2845
2846 cpu.Ypair[1] = (word36) cpu.PR[n].WORDNO << 18;
2847 cpu.Ypair[1] |= (word36) GET_PR_BITNO (n) << 9;
2848 }
2849 break;
2850
2851 case x0 (0235): // lda
2852 cpu.rA = cpu.CY;
2853 #if defined(TESTING)
2854 HDBGRegAW ("lda");
2855 #endif
2856 SC_I_ZERO (cpu.rA == 0);
2857 SC_I_NEG (cpu.rA & SIGN36);
2858 break;
2859
2860 case x0 (0710): // tra
2861 // C(TPR.CA) -> C(PPR.IC)
2862 // C(TPR.TSR) -> C(PPR.PSR)
2863 do_caf (cpup);
2864 read_tra_op (cpup);
2865 return CONT_TRA;
2866
2867 case x0 (0236): // ldq
2868 cpu.rQ = cpu.CY;
2869 #if defined(TESTING)
2870 HDBGRegQW ("ldq");
2871 #endif
2872 SC_I_ZERO (cpu.rQ == 0);
2873 SC_I_NEG (cpu.rQ & SIGN36);
2874 break;
2875
2876 case x0 (0600): // tze
2877 // If zero indicator ON then
2878 // C(TPR.CA) -> C(PPR.IC)
2879 // C(TPR.TSR) -> C(PPR.PSR)
2880 // otherwise, no change to C(PPR)
2881 if (TST_I_ZERO)
2882 {
2883 do_caf (cpup);
2884 read_tra_op (cpup);
2885 return CONT_TRA;
2886 }
2887 break;
2888
2889 case x0 (0601): // tnz
2890 // If zero indicator OFF then
2891 // C(TPR.CA) -> C(PPR.IC)
2892 // C(TPR.TSR) -> C(PPR.PSR)
2893 if (!TST_I_ZERO)
2894 {
2895 do_caf (cpup);
2896 read_tra_op (cpup);
2897 return CONT_TRA;
2898 }
2899 break;
2900
2901 case x0 (0756): // stq
2902 cpu.CY = cpu.rQ;
2903 #if defined(TESTING)
2904 HDBGRegQR ("stq");
2905 #endif
2906 break;
2907
2908 case x0 (0116): // cmpq
2909 // C(Q) :: C(Y)
2910 cmp36 (cpup, cpu.rQ, cpu.CY, &cpu.cu.IR);
2911 #if defined(TESTING)
2912 HDBGRegQR ("cmpq");
2913 #endif
2914 break;
2915
2916 case x0 (0377): //< anaq
2917 // C(AQ)i & C(Y-pair)i -> C(AQ)i for i = (0, 1, ..., 71)
2918 {
2919 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
2920 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
2921 #if defined(TESTING)
2922 HDBGRegAR ("anaq");
2923 HDBGRegQR ("anaq");
2924 #endif
2925 #if defined(NEED_128)
2926 trAQ = and_128 (trAQ, tmp72);
2927 trAQ = and_128 (trAQ, MASK72);
2928
2929 SC_I_ZERO (iszero_128 (trAQ));
2930 SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
2931 #else
2932 trAQ = trAQ & tmp72;
2933 trAQ &= MASK72;
2934
2935 SC_I_ZERO (trAQ == 0);
2936 SC_I_NEG (trAQ & SIGN72);
2937 #endif
2938 convert_to_word36 (trAQ, &cpu.rA, &cpu.rQ);
2939 #if defined(TESTING)
2940 HDBGRegAW ("anaq");
2941 HDBGRegQW ("anaq");
2942 #endif
2943 }
2944 break;
2945
2946 case x0 (0755): // sta
2947 cpu.CY = cpu.rA;
2948 #if defined(TESTING)
2949 HDBGRegAR ("sta");
2950 #endif
2951 break;
2952
2953 // lprpn
2954 case x0 (0760): // lprp0
2955 case x0 (0761): // lprp1
2956 case x0 (0762): // lprp2
2957 case x0 (0763): // lprp3
2958 case x0 (0764): // lprp4
2959 case x0 (0765): // lprp5
2960 case x0 (0766): // lprp6
2961 case x0 (0767): // lprp7
2962 // For n = 0, 1, ..., or 7 as determined by operation code
2963 // C(TPR.TRR) -> C(PRn.RNR)
2964 // If C(Y)0,1 != 11, then
2965 // C(Y)0,5 -> C(PRn.BITNO);
2966 // otherwise,
2967 // generate command fault
2968 // If C(Y)6,17 = 11...1, then 111 -> C(PRn.SNR)0,2
2969 // otherwise,
2970 // 000 -> C(PRn.SNR)0,2
2971 // C(Y)6,17 -> C(PRn.SNR)3,14
2972 // C(Y)18,35 -> C(PRn.WORDNO)
2973 {
2974 uint32 n = opcode10 & 07; // get n
2975 CPTUR (cptUsePRn + n);
2976 cpu.PR[n].RNR = cpu.TPR.TRR;
2977
2978 // [CAC] sprpn says: If C(PRn.SNR) 0,2 are nonzero, and C(PRn.SNR) != 11...1,
2979 // then a store fault (illegal pointer) will occur and C(Y) will not be changed.
2980 // I interpret this has meaning that only the high bits should be set here
2981
2982 if (((cpu.CY >> 34) & 3) != 3)
2983 {
2984 word6 bitno = (cpu.CY >> 30) & 077;
2985 SET_PR_BITNO (n, bitno);
2986 }
2987 else
2988 {
2989 // fim.alm
2990 // command_fault:
2991 // eax7 com assume normal command fault
2992 // ldq bp|mc.scu.port_stat_word check illegal action
2993 // canq scu.ial_mask,dl
2994 // tnz fixindex nonzero, treat as normal case
2995 // ldq bp|scu.even_inst_word check for LPRPxx instruction
2996 // anq =o770400,dl
2997 // cmpq lprp_insts,dl
2998 // tnz fixindex isn't LPRPxx, treat as normal
2999
3000 // ial_mask is checking SCU word 1, field IA: 0 means "no illegal action"
3001
3002 // Therefore the subfault well no illegal action, and
3003 // Multics will peek it the instruction to deduce that it
3004 // is a lprpn fault.
3005 doFault (FAULT_CMD, fst_cmd_lprpn, "lprpn");
3006 }
3007 // The SPRPn instruction stores only the low 12 bits of the 15 bit SNR.
3008 // A special case is made for an SNR of all ones; it is stored as 12 1's.
3009 // The pcode in AL39 handles this awkwardly; I believe this is
3010 // the same, but in a more straightforward manner
3011
3012 // Get the 12 bit operand SNR
3013 word12 oSNR = getbits36_12 (cpu.CY, 6);
3014 // Test for special case
3015 if (oSNR == 07777)
3016 cpu.PR[n].SNR = 077777;
3017 else
3018 cpu.PR[n].SNR = oSNR; // unsigned word will 0-extend.
3019 //C(Y)18,35 -> C(PRn.WORDNO)
3020 cpu.PR[n].WORDNO = GETLO (cpu.CY);
3021
3022 sim_debug (DBG_APPENDING, & cpu_dev,
3023 "lprp%d CY 0%012"PRIo64", PR[n].RNR 0%o, "
3024 "PR[n].BITNO 0%o, PR[n].SNR 0%o, PR[n].WORDNO %o\r\n",
3025 n, cpu.CY, cpu.PR[n].RNR, GET_PR_BITNO (n),
3026 cpu.PR[n].SNR, cpu.PR[n].WORDNO);
3027 #if defined(TESTING)
3028 HDBGRegPRW (n, "lprp");
3029 #endif
3030 }
3031 break;
3032
3033 // eaxn
3034 case x0 (0620): // eax0
3035 case x0 (0621): // eax1
3036 case x0 (0622): // eax2
3037 case x0 (0623): // eax3
3038 case x0 (0624): // eax4
3039 case x0 (0625): // eax5
3040 case x0 (0626): // eax6
3041 case x0 (0627): // eax7
3042 {
3043 uint32 n = opcode10 & 07; // get n
3044 cpu.rX[n] = cpu.TPR.CA;
3045 #if defined(TESTING)
3046 HDBGRegXW (n, "eaxn");
3047 #endif
3048
3049 SC_I_ZERO (cpu.TPR.CA == 0);
3050 SC_I_NEG (cpu.TPR.CA & SIGN18);
3051
3052 }
3053 break;
3054
3055 // tsxn
3056 case x0 (0700): // tsx0
3057 case x0 (0701): // tsx1
3058 case x0 (0702): // tsx2
3059 case x0 (0703): // tsx3
3060 case x0 (0704): // tsx4
3061 case x0 (0705): // tsx5
3062 case x0 (0706): // tsx6
3063 case x0 (0707): // tsx7
3064 // For n = 0, 1, ..., or 7 as determined by operation code
3065 // C(PPR.IC) + 1 -> C(Xn)
3066 // C(TPR.CA) -> C(PPR.IC)
3067 // C(TPR.TSR) -> C(PPR.PSR)
3068 {
3069 // We can't set Xn yet as the CAF may refer to Xn
3070 word18 ret = (cpu.PPR.IC + 1) & MASK18;
3071 do_caf (cpup);
3072 read_tra_op (cpup);
3073 cpu.rX[opcode10 & 07] = ret;
3074 #if defined(TESTING)
3075 HDBGRegXW (opcode10 & 07, "tsxn");
3076 #endif
3077 }
3078 return CONT_TRA;
3079
3080 case x0 (0450): // stz
3081 cpu.CY = 0;
3082 break;
3083
3084 // epbpn
3085 case x1 (0350): // epbp0
3086 case x0 (0351): // epbp1
3087 case x1 (0352): // epbp2
3088 case x0 (0353): // epbp3
3089 case x1 (0370): // epbp4
3090 case x0 (0371): // epbp5
3091 case x1 (0372): // epbp6
3092 case x0 (0373): // epbp7
3093 // For n = 0, 1, ..., or 7 as determined by operation code
3094 // C(TPR.TRR) -> C(PRn.RNR)
3095 // C(TPR.TSR) -> C(PRn.SNR)
3096 // 00...0 -> C(PRn.WORDNO)
3097 // 0000 -> C(PRn.BITNO)
3098 {
3099 // epbp0 1350 101 000
3100 // epbp1 0351 101 000
3101 // epbp2 1352 101 000
3102 // epbp3 0353 101 000
3103 // epbp4 1370 111 000
3104 // epbp4 0371 111 000
3105 // epbp6 1372 111 000
3106 // epbp7 0373 111 000
3107 //n = ((opcode10 & 020) ? 4 : 0) + (opcode10 & 03);
3108 uint n = ((opcode10 & 020) >> 2) | (opcode10 & 03);
3109 CPTUR (cptUsePRn + n);
3110 cpu.PR[n].RNR = cpu.TPR.TRR;
3111 cpu.PR[n].SNR = cpu.TPR.TSR;
3112 cpu.PR[n].WORDNO = 0;
3113 SET_PR_BITNO (n, 0);
3114 #if defined(TESTING)
3115 HDBGRegPRW (n, "epbp");
3116 #endif
3117 }
3118 break;
3119
3120 case x0 (0115): // cmpa
3121 // C(A) :: C(Y)
3122 cmp36 (cpup, cpu.rA, cpu.CY, &cpu.cu.IR);
3123 #if defined(TESTING)
3124 HDBGRegAR ("cmpa");
3125 #endif
3126 break;
3127
3128 case x0 (0054): // aos
3129 {
3130 // C(Y)+1->C(Y)
3131
3132 L68_ (cpu.ou.cycle |= ou_GOS;)
3133 bool ovf;
3134 cpu.CY = Add36b (cpup, cpu.CY, 1, 0, I_ZNOC,
3135 & cpu.cu.IR, & ovf);
3136 overflow (cpup, ovf, true, "aos overflow fault");
3137 }
3138 break;
3139
3140 case x0 (0315): // cana
3141 // C(Z)i = C(A)i & C(Y)i for i = (0, 1, ..., 35)
3142 {
3143 #if defined(TESTING)
3144 HDBGRegAR ("cana");
3145 #endif
3146 word36 trZ = cpu.rA & cpu.CY;
3147 trZ &= MASK36;
3148
3149 SC_I_ZERO (trZ == 0);
3150 SC_I_NEG (trZ & SIGN36);
3151 }
3152 break;
3153
3154 case x0 (0237): // ldaq
3155 cpu.rA = cpu.Ypair[0];
3156 #if defined(TESTING)
3157 HDBGRegAW ("ldaq");
3158 #endif
3159 cpu.rQ = cpu.Ypair[1];
3160 #if defined(TESTING)
3161 HDBGRegQW ("ldaq");
3162 #endif
3163 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0)
3164 SC_I_NEG (cpu.rA & SIGN36);
3165 break;
3166
3167 case x1 (0605): // tpnz
3168 // If negative and zero indicators are OFF then
3169 // C(TPR.CA) -> C(PPR.IC)
3170 // C(TPR.TSR) -> C(PPR.PSR)
3171 if (! (cpu.cu.IR & I_NEG) && ! (cpu.cu.IR & I_ZERO))
3172 {
3173 do_caf (cpup);
3174 read_tra_op (cpup);
3175 return CONT_TRA;
3176 }
3177 break;
3178
3179 // lxln
3180 case x0 (0720): // lxl0
3181 case x0 (0721): // lxl1
3182 case x0 (0722): // lxl2
3183 case x0 (0723): // lxl3
3184 case x0 (0724): // lxl4
3185 case x0 (0725): // lxl5
3186 case x0 (0726): // lxl6
3187 case x0 (0727): // lxl7
3188 {
3189 uint32 n = opcode10 & 07; // get n
3190 cpu.rX[n] = GETLO (cpu.CY);
3191 #if defined(TESTING)
3192 HDBGRegXW (n, "lxln");
3193 #endif
3194 SC_I_ZERO (cpu.rX[n] == 0);
3195 SC_I_NEG (cpu.rX[n] & SIGN18);
3196 }
3197 break;
3198
3199 case x0 (0757): // staq
3200 cpu.Ypair[0] = cpu.rA;
3201 cpu.Ypair[1] = cpu.rQ;
3202 break;
3203
3204 // tspn
3205 case x0 (0270): // tsp0
3206 case x0 (0271): // tsp1
3207 case x0 (0272): // tsp2
3208 case x0 (0273): // tsp3
3209 case x0 (0670): // tsp4
3210 case x0 (0671): // tsp5
3211 case x0 (0672): // tsp6
3212 case x0 (0673): // tsp7
3213 // For n = 0, 1, ..., or 7 as determined by operation code
3214 // C(PPR.PRR) -> C(PRn.RNR)
3215 // C(PPR.PSR) -> C(PRn.SNR)
3216 // C(PPR.IC) + 1 -> C(PRn.WORDNO)
3217 // 00...0 -> C(PRn.BITNO)
3218 // C(TPR.CA) -> C(PPR.IC)
3219 // C(TPR.TSR) -> C(PPR.PSR)
3220 {
3221 #if defined(PANEL68)
3222 uint32 n;
3223 if (opcode10 <= 0273)
3224 n = (opcode10 & 3);
3225 else
3226 n = (opcode10 & 3) + 4;
3227 CPTUR (cptUsePRn + n);
3228 #endif
3229
3230 do_caf (cpup);
3231 // PR[n] is set in read_tra_op().
3232 read_tra_op (cpup);
3233 }
3234 return CONT_TRA;
3235
3236 case x0 (0735): // als
3237 {
3238 #if defined(TESTING)
3239 HDBGRegAR ("als");
3240 #endif
3241 #if BARREL_SHIFTER
3242 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
3243
3244 // Capture the bits shifted through A0
3245 word36 capture;
3246 // If count is > 36, than all of the bits will rotate through A
3247 if (cnt < 36) {
3248 // +1 is A0 plus the bits that will get shifted into A0
3249 capture = cpu.rA & barrelLeftMaskTable[cnt + 1];
3250
3251 // Do the shift
3252 cpu.rA <<= cnt;
3253 cpu.rA &= DMASK; // keep to 36-bits
3254
3255 // If the captured bits are all 0 or all 1, then
3256 // A0 will not have changed during the rotate
3257
3258 } else {
3259 capture = cpu.rA;
3260 cpu.rA = 0;
3261 cnt = 35;
3262 }
3263
3264 if (capture == 0 || capture == (MASK36 & barrelLeftMaskTable[cnt + 1]))
3265 CLR_I_CARRY;
3266 else
3267 SET_I_CARRY;
3268 #else // !BARREL_SHIFTER
3269 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
3270
3271 word36 tmpSign = cpu.rA & SIGN36;
3272 CLR_I_CARRY;
3273
3274 for (uint j = 0; j < tmp36; j ++)
3275 {
3276 cpu.rA <<= 1;
3277 if (tmpSign != (cpu.rA & SIGN36))
3278 SET_I_CARRY;
3279 }
3280 cpu.rA &= DMASK; // keep to 36-bits
3281 #endif // BARREL_SHIFTER
3282 #if defined(TESTING)
3283 HDBGRegAW ("als");
3284 #endif
3285
3286 SC_I_ZERO (cpu.rA == 0);
3287 SC_I_NEG (cpu.rA & SIGN36);
3288 }
3289 break;
3290
3291 case x0 (0610): // rtcd
3292 // If an access violation fault occurs when fetching the SDW for
3293 // the Y-pair, the C(PPR.PSR) and C(PPR.PRR) are not altered.
3294
3295 do_caf (cpup);
3296 Read2RTCDOperandFetch (cpup, cpu.TPR.CA, cpu.Ypair);
3297 // RTCD always ends up in append mode.
3298 set_addr_mode (cpup, APPEND_mode);
3299
3300 return CONT_RET;
3301
3302 case x0 (0604): // tmi
3303 // If negative indicator ON then
3304 // C(TPR.CA) -> C(PPR.IC)
3305 // C(TPR.TSR) -> C(PPR.PSR)
3306 if (TST_I_NEG)
3307 {
3308 do_caf (cpup);
3309 read_tra_op (cpup);
3310 return CONT_TRA;
3311 }
3312 break;
3313
3314 // stxn
3315 case x0 (0740): // stx0
3316 case x0 (0741): // stx1
3317 case x0 (0742): // stx2
3318 case x0 (0743): // stx3
3319 case x0 (0744): // stx4
3320 case x0 (0745): // stx5
3321 case x0 (0746): // stx6
3322 case x0 (0747): // stx7
3323 {
3324 uint32 n = opcode10 & 07; // get n
3325 //SETHI (cpu.CY, cpu.rX[n]);
3326 cpu.CY = ((word36) cpu.rX[n]) << 18;
3327 cpu.zone = 0777777000000;
3328 cpu.useZone = true;
3329 }
3330 break;
3331
3332 case x0 (0634): // ldi
3333 {
3334 CPTUR (cptUseIR);
3335 // C(Y)18,31 -> C(IR)
3336
3337 // Indicators:
3338 // Parity Mask:
3339 // If C(Y)27 = 1, and the processor is in absolute or
3340 // instruction privileged mode, then ON; otherwise OFF.
3341 // This indicator is not affected in the normal or BAR modes.
3342 // Not BAR mode:
3343 // Cannot be changed by the ldi instruction
3344 // MIF:
3345 // If C(Y)30 = 1, and the processor is in absolute or
3346 // instruction privileged mode, then ON; otherwise OFF.
3347 // This indicator is not affected in normal or BAR modes.
3348 // Absolute mode:
3349 // Cannot be changed by the ldi instruction
3350 // All others: If corresponding bit in C(Y) is 1, then ON;
3351 // otherwise, OFF
3352
3353 // upper 14-bits of lower 18-bits
3354
3355 // AL39 ldi says that HEX is ignored, but the mode register
3356 // description says that it isn't
3357 word18 tmp18;
3358 if (cpu.tweaks.l68_mode)
3359 tmp18 = GETLO (cpu.CY) & 0777760; // L68
3360 else
3361 tmp18 = GETLO (cpu.CY) & 0777770; // DPS8M
3362
3363 bool bAbsPriv = is_priv_mode (cpup);
3364
3365 SC_I_ZERO (tmp18 & I_ZERO);
3366 SC_I_NEG (tmp18 & I_NEG);
3367 SC_I_CARRY (tmp18 & I_CARRY);
3368 SC_I_OFLOW (tmp18 & I_OFLOW);
3369 SC_I_EOFL (tmp18 & I_EOFL);
3370 SC_I_EUFL (tmp18 & I_EUFL);
3371 SC_I_OMASK (tmp18 & I_OMASK);
3372 SC_I_TALLY (tmp18 & I_TALLY);
3373 SC_I_PERR (tmp18 & I_PERR);
3374 // I_PMASK handled below
3375 // LDI cannot change I_NBAR
3376 SC_I_TRUNC (tmp18 & I_TRUNC);
3377 // I_MIF handled below
3378 // LDI cannot change I_ABS
3379 DPS8M_ (SC_I_HEX (tmp18 & I_HEX);)
3380
3381 if (bAbsPriv)
3382 {
3383 SC_I_PMASK (tmp18 & I_PMASK);
3384 SC_I_MIF (tmp18 & I_MIF);
3385 }
3386 else
3387 {
3388 CLR_I_PMASK;
3389 CLR_I_MIF;
3390 }
3391 }
3392 break;
3393
3394 case x0 (0677): // eraq
3395 // C(AQ)i XOR C(Y-pair)i -> C(AQ)i for i = (0, 1, ..., 71)
3396 {
3397 #if defined(TESTING)
3398 HDBGRegAR ("eraq");
3399 HDBGRegQR ("eraq");
3400 #endif
3401 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
3402 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
3403 #if defined(NEED_128)
3404 trAQ = xor_128 (trAQ, tmp72);
3405 trAQ = and_128 (trAQ, MASK72);
3406
3407 SC_I_ZERO (iszero_128 (trAQ));
3408 SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
3409 #else
3410 trAQ = trAQ ^ tmp72;
3411 trAQ &= MASK72;
3412
3413 SC_I_ZERO (trAQ == 0);
3414 SC_I_NEG (trAQ & SIGN72);
3415 #endif
3416
3417 convert_to_word36 (trAQ, &cpu.rA, &cpu.rQ);
3418 #if defined(TESTING)
3419 HDBGRegAW ("eraq");
3420 HDBGRegQW ("eraq");
3421 #endif
3422 }
3423 break;
3424
3425 case x0 (0275): // ora
3426 // C(A)i | C(Y)i -> C(A)i for i = (0, 1, ..., 35)
3427 #if defined(TESTING)
3428 HDBGRegAR ("ora");
3429 #endif
3430 cpu.rA = cpu.rA | cpu.CY;
3431 cpu.rA &= DMASK;
3432 #if defined(TESTING)
3433 HDBGRegAW ("ora");
3434 #endif
3435
3436 SC_I_ZERO (cpu.rA == 0);
3437 SC_I_NEG (cpu.rA & SIGN36);
3438 break;
3439
3440 case x0 (0076): // adq
3441 {
3442 L68_ (cpu.ou.cycle |= ou_GOS;)
3443 bool ovf;
3444 #if defined(TESTING)
3445 HDBGRegQR ("adq");
3446 #endif
3447 cpu.rQ = Add36b (cpup, cpu.rQ, cpu.CY, 0, I_ZNOC,
3448 & cpu.cu.IR, & ovf);
3449 #if defined(TESTING)
3450 HDBGRegQW ("adq");
3451 #endif
3452 overflow (cpup, ovf, false, "adq overflow fault");
3453 }
3454 break;
3455
3456 case x1 (0604): // tmoz
3457 // If negative or zero indicator ON then
3458 // C(TPR.CA) -> C(PPR.IC)
3459 // C(TPR.TSR) -> C(PPR.PSR)
3460 if (cpu.cu.IR & (I_NEG | I_ZERO))
3461 {
3462 do_caf (cpup);
3463 read_tra_op (cpup);
3464 return CONT_TRA;
3465 }
3466 break;
3467
3468 case x1 (0250): // spbp0
3469 case x0 (0251): // spbp1
3470 case x1 (0252): // spbp2
3471 case x0 (0253): // spbp3
3472 case x1 (0650): // spbp4
3473 case x0 (0651): // spbp5
3474 case x1 (0652): // spbp6
3475 case x0 (0653): // spbp7
3476 // For n = 0, 1, ..., or 7 as determined by operation code
3477 // C(PRn.SNR) -> C(Y-pair)3,17
3478 // C(PRn.RNR) -> C(Y-pair)18,20
3479 // 000 -> C(Y-pair)0,2
3480 // 00...0 -> C(Y-pair)21,29
3481 // (43)8 -> C(Y-pair)30,35
3482 // 00...0 -> C(Y-pair)36,71
3483 {
3484 // spbp0 1250 010 101 000
3485 // spbp1 0251 010 101 001
3486 // spbp2 1252 010 101 010
3487 // spbp3 0253 010 101 011
3488 // spbp4 1650 110 101 000
3489 // spbp5 0651 110 101 001
3490 // spbp6 1652 110 101 010
3491 // spbp8 0653 110 101 011
3492 uint n = ((opcode10 & 0400) >> 6) | (opcode10 & 03);
3493 CPTUR (cptUsePRn + n);
3494 cpu.Ypair[0] = 043;
3495 cpu.Ypair[0] |= ((word36) cpu.PR[n].SNR) << 18;
3496 cpu.Ypair[0] |= ((word36) cpu.PR[n].RNR) << 15;
3497 cpu.Ypair[1] = 0;
3498 }
3499 break;
3500
3501 case x0 (0375): // ana
3502 // C(A)i & C(Y)i -> C(A)i for i = (0, 1, ..., 35)
3503 #if defined(TESTING)
3504 HDBGRegAR ("ana");
3505 #endif
3506 cpu.rA = cpu.rA & cpu.CY;
3507 cpu.rA &= DMASK;
3508 #if defined(TESTING)
3509 HDBGRegAW ("ana");
3510 #endif
3511 SC_I_ZERO (cpu.rA == 0);
3512 SC_I_NEG (cpu.rA & SIGN36);
3513 break;
3514
3515 case x0 (0431): // fld
3516 // C(Y)0,7 -> C(E)
3517 // C(Y)8,35 -> C(AQ)0,27
3518 // 00...0 -> C(AQ)30,71
3519 // Zero: If C(AQ) = 0, then ON; otherwise OFF
3520 // Neg: If C(AQ)0 = 1, then ON; otherwise OFF
3521
3522 CPTUR (cptUseE);
3523 cpu.CY &= DMASK;
3524 cpu.rE = (cpu.CY >> 28) & 0377;
3525 cpu.rA = (cpu.CY & FLOAT36MASK) << 8;
3526 #if defined(TESTING)
3527 HDBGRegAW ("fld");
3528 #endif
3529 cpu.rQ = 0;
3530 #if defined(TESTING)
3531 HDBGRegQW ("fld");
3532 #endif
3533
3534 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
3535 SC_I_NEG (cpu.rA & SIGN36);
3536 break;
3537
3538 case x0 (0213): // epaq
3539 // 000 -> C(AQ)0,2
3540 // C(TPR.TSR) -> C(AQ)3,17
3541 // 00...0 -> C(AQ)18,32
3542 // C(TPR.TRR) -> C(AQ)33,35
3543
3544 // C(TPR.CA) -> C(AQ)36,53
3545 // 00...0 -> C(AQ)54,65
3546 // C(TPR.TBR) -> C(AQ)66,71
3547
3548 cpu.rA = cpu.TPR.TRR & MASK3;
3549 cpu.rA |= (word36) (cpu.TPR.TSR & MASK15) << 18;
3550 #if defined(TESTING)
3551 HDBGRegAW ("epaq");
3552 #endif
3553
3554 cpu.rQ = cpu.TPR.TBR & MASK6;
3555 cpu.rQ |= (word36) (cpu.TPR.CA & MASK18) << 18;
3556 #if defined(TESTING)
3557 HDBGRegQW ("epaq");
3558 #endif
3559
3560 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
3561
3562 break;
3563
3564 case x0 (0736): // qls
3565 // Shift C(Q) left the number of positions given in
3566 // C(TPR.CA)11,17; fill vacated positions with zeros.
3567 {
3568 #if defined(TESTING)
3569 HDBGRegQR ("qls");
3570 #endif
3571 #if BARREL_SHIFTER
3572 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
3573
3574 // Capture the bits shifted through Q0
3575 word36 capture;
3576 // If count is > 36, than all of the bits will rotate through Q
3577 if (cnt < 36) {
3578 // +1 is Q0 plus the bits that will get shifted into Q0
3579 capture = cpu.rQ & barrelLeftMaskTable[cnt + 1];
3580
3581 // Do the shift
3582 cpu.rQ <<= cnt;
3583 cpu.rQ &= DMASK; // keep to 36-bits
3584
3585 // If the captured bits are all 0 or all 1, then
3586 // Q0 will not have changed during the rotate
3587
3588 } else {
3589 capture = cpu.rQ;
3590 cpu.rQ = 0;
3591 }
3592
3593 if (capture == 0 || capture == (MASK36 & barrelLeftMaskTable[cnt + 1]))
3594 CLR_I_CARRY;
3595 else
3596 SET_I_CARRY;
3597 #else // !BARREL_SHIFTER
3598 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
3599 word36 tmpSign = cpu.rQ & SIGN36;
3600 CLR_I_CARRY;
3601
3602 for (uint j = 0; j < tmp36; j ++)
3603 {
3604 cpu.rQ <<= 1;
3605 if (tmpSign != (cpu.rQ & SIGN36))
3606 SET_I_CARRY;
3607 }
3608 cpu.rQ &= DMASK; // keep to 36-bits
3609 #endif // BARREL_SHIFTER
3610 #if defined(TESTING)
3611 HDBGRegQW ("qls");
3612 #endif
3613
3614 SC_I_ZERO (cpu.rQ == 0);
3615 SC_I_NEG (cpu.rQ & SIGN36);
3616 }
3617 break;
3618
3619 case x0 (0754): // sti
3620
3621 // C(IR) -> C(Y)18,31
3622 // 00...0 -> C(Y)32,35
3623
3624 // The contents of the indicator register after address
3625 // preparation are stored in C(Y)18,31 C(Y)18,31 reflects the
3626 // state of the tally runout indicator prior to address
3627 // preparation. The relation between C(Y)18,31 and the indicators
3628 // is given in Table 4-5.
3629
3630 CPTUR (cptUseIR);
3631 // AL39 sti says that HEX is ignored, but the mode register
3632 // description says that it isn't
3633
3634 //SETLO (cpu.CY, (cpu.cu.IR & 0000000777770LL));
3635 DPS8M_ (cpu.CY = cpu.cu.IR & 0000000777770LL; )
3636 //SETLO (cpu.CY, (cpu.cu.IR & 0000000777760LL));
3637 L68_ (cpu.CY = cpu.cu.IR & 0000000777760LL;)
3638
3639 if (cpu.switches.procMode == procModeGCOS)
3640 cpu.CY = cpu.cu.IR & 0000000777600LL;
3641 cpu.zone = 0000000777777;
3642 cpu.useZone = true;
3643 SCF (i->stiTally, cpu.CY, I_TALLY);
3644 break;
3645
3646 /// FIXED-POINT ARITHMETIC INSTRUCTIONS
3647
3648 /// Fixed-Point Data Movement Load
3649
3650 case x0 (0635): // eaa
3651 cpu.rA = 0;
3652 SETHI (cpu.rA, cpu.TPR.CA);
3653 #if defined(TESTING)
3654 HDBGRegAW ("eea");
3655 #endif
3656 SC_I_ZERO (cpu.TPR.CA == 0);
3657 SC_I_NEG (cpu.TPR.CA & SIGN18);
3658
3659 break;
3660
3661 case x0 (0636): // eaq
3662 cpu.rQ = 0;
3663 SETHI (cpu.rQ, cpu.TPR.CA);
3664 #if defined(TESTING)
3665 HDBGRegQW ("eaq");
3666 #endif
3667
3668 SC_I_ZERO (cpu.TPR.CA == 0);
3669 SC_I_NEG (cpu.TPR.CA & SIGN18);
3670
3671 break;
3672
3673 // Optimized to the top of the loop
3674 // case x0 (0620): // eax0
3675 // case x0 (0621): // eax1
3676 // case x0 (0622): // eax2
3677 // case x0 (0623): // eax3
3678 // case x0 (0624): // eax4
3679 // case x0 (0625): // eax5
3680 // case x0 (0626): // eax6
3681 // case x0 (0627): // eax7
3682
3683 case x0 (0335): // lca
3684 {
3685 bool ovf;
3686 cpu.rA = compl36 (cpup, cpu.CY, & cpu.cu.IR, & ovf);
3687 #if defined(TESTING)
3688 HDBGRegAW ("lca");
3689 #endif
3690 overflow (cpup, ovf, false, "lca overflow fault");
3691 }
3692 break;
3693
3694 case x0 (0336): // lcq
3695 {
3696 bool ovf;
3697 cpu.rQ = compl36 (cpup, cpu.CY, & cpu.cu.IR, & ovf);
3698 #if defined(TESTING)
3699 HDBGRegQW ("lcq");
3700 #endif
3701 overflow (cpup, ovf, false, "lcq overflow fault");
3702 }
3703 break;
3704
3705 // lcxn
3706 case x0 (0320): // lcx0
3707 case x0 (0321): // lcx1
3708 case x0 (0322): // lcx2
3709 case x0 (0323): // lcx3
3710 case x0 (0324): // lcx4
3711 case x0 (0325): // lcx5
3712 case x0 (0326): // lcx6
3713 case x0 (0327): // lcx7
3714 {
3715 bool ovf;
3716 uint32 n = opcode10 & 07; // get n
3717 cpu.rX[n] = compl18 (cpup, GETHI (cpu.CY), & cpu.cu.IR, & ovf);
3718 #if defined(TESTING)
3719 HDBGRegXW (n, "lcxn");
3720 #endif
3721 overflow (cpup, ovf, false, "lcxn overflow fault");
3722 }
3723 break;
3724
3725 case x0 (0337): // lcaq
3726 {
3727 // The lcaq instruction changes the number to its negative while
3728 // moving it from Y-pair to AQ. The operation is executed by
3729 // forming the twos complement of the string of 72 bits. In twos
3730 // complement arithmetic, the value 0 is its own negative. An
3731 // overflow condition exists if C(Y-pair) = -2**71.
3732
3733 if (cpu.Ypair[0] == 0400000000000LL && cpu.Ypair[1] == 0)
3734 {
3735 cpu.rA = cpu.Ypair[0];
3736 #if defined(TESTING)
3737 HDBGRegAW ("lcaq");
3738 #endif
3739 cpu.rQ = cpu.Ypair[1];
3740 #if defined(TESTING)
3741 HDBGRegQW ("lcaq");
3742 #endif
3743 SET_I_NEG;
3744 CLR_I_ZERO;
3745 overflow (cpup, true, false, "lcaq overflow fault");
3746 }
3747 else if (cpu.Ypair[0] == 0 && cpu.Ypair[1] == 0)
3748 {
3749 cpu.rA = 0;
3750 #if defined(TESTING)
3751 HDBGRegAW ("lcaq");
3752 #endif
3753 cpu.rQ = 0;
3754 #if defined(TESTING)
3755 HDBGRegQW ("lcaq");
3756 #endif
3757
3758 SET_I_ZERO;
3759 CLR_I_NEG;
3760 }
3761 else
3762 {
3763 word72 tmp72 = convert_to_word72 (cpu.Ypair[0], cpu.Ypair[1]);
3764 #if defined(NEED_128)
3765 tmp72 = negate_128 (tmp72);
3766 #else
3767 tmp72 = ~tmp72 + 1;
3768 #endif
3769 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
3770 #if defined(TESTING)
3771 HDBGRegAW ("lcaq");
3772 HDBGRegQW ("lcaq");
3773 #endif
3774
3775 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
3776 SC_I_NEG (cpu.rA & SIGN36);
3777 }
3778 }
3779 break;
3780
3781 // Optimized to the top of the loop
3782 // case x0 (0235): // lda
3783
3784 case x0 (0034): // ldac
3785 cpu.rA = cpu.CY;
3786 #if defined(TESTING)
3787 HDBGRegAW ("ldac");
3788 #endif
3789 SC_I_ZERO (cpu.rA == 0);
3790 SC_I_NEG (cpu.rA & SIGN36);
3791 cpu.CY = 0;
3792 break;
3793
3794 // Optimized to the top of the loop
3795 // case x0 (0237): // ldaq
3796
3797 // Optimized to the top of the loop
3798 // case x0 (0634): // ldi
3799
3800 // Optimized to the top of the loop
3801 // case x0 (0236): // ldq
3802
3803 case x0 (0032): // ldqc
3804 cpu.rQ = cpu.CY;
3805 #if defined(TESTING)
3806 HDBGRegQW ("ldqc");
3807 #endif
3808 SC_I_ZERO (cpu.rQ == 0);
3809 SC_I_NEG (cpu.rQ & SIGN36);
3810 cpu.CY = 0;
3811 break;
3812
3813 // ldxn
3814 case x0 (0220): // ldx0
3815 case x0 (0221): // ldx1
3816 case x0 (0222): // ldx2
3817 case x0 (0223): // ldx3
3818 case x0 (0224): // ldx4
3819 case x0 (0225): // ldx5
3820 case x0 (0226): // ldx6
3821 case x0 (0227): // ldx7
3822 {
3823 uint32 n = opcode10 & 07; // get n
3824 cpu.rX[n] = GETHI (cpu.CY);
3825 #if defined(TESTING)
3826 HDBGRegXW (n, "ldxn");
3827 #endif
3828 SC_I_ZERO (cpu.rX[n] == 0);
3829 SC_I_NEG (cpu.rX[n] & SIGN18);
3830 }
3831 break;
3832
3833 case x0 (0073): // lreg
3834 CPTUR (cptUseE);
3835 L68_ (cpu.ou.cycle |= ou_GOS;)
3836 L68_ (cpu.ou.eac = 0;)
3837 cpu.rX[0] = GETHI (cpu.Yblock8[0]);
3838 #if defined(TESTING)
3839 HDBGRegXW (0, "lreg");
3840 #endif
3841 cpu.rX[1] = GETLO (cpu.Yblock8[0]);
3842 #if defined(TESTING)
3843 HDBGRegXW (1, "lreg");
3844 #endif
3845 L68_ (cpu.ou.eac ++;)
3846 cpu.rX[2] = GETHI (cpu.Yblock8[1]);
3847 #if defined(TESTING)
3848 HDBGRegXW (2, "lreg");
3849 #endif
3850 cpu.rX[3] = GETLO (cpu.Yblock8[1]);
3851 #if defined(TESTING)
3852 HDBGRegXW (3, "lreg");
3853 #endif
3854 L68_ (cpu.ou.eac ++;)
3855 cpu.rX[4] = GETHI (cpu.Yblock8[2]);
3856 #if defined(TESTING)
3857 HDBGRegXW (4, "lreg");
3858 #endif
3859 cpu.rX[5] = GETLO (cpu.Yblock8[2]);
3860 #if defined(TESTING)
3861 HDBGRegXW (5, "lreg");
3862 #endif
3863 L68_ (cpu.ou.eac ++;)
3864 cpu.rX[6] = GETHI (cpu.Yblock8[3]);
3865 #if defined(TESTING)
3866 HDBGRegXW (6, "lreg");
3867 #endif
3868 cpu.rX[7] = GETLO (cpu.Yblock8[3]);
3869 #if defined(TESTING)
3870 HDBGRegXW (7, "lreg");
3871 #endif
3872 L68_ (cpu.ou.eac ++;)
3873 cpu.rA = cpu.Yblock8[4];
3874 #if defined(TESTING)
3875 HDBGRegAW ("lreg");
3876 #endif
3877 cpu.rQ = cpu.Yblock8[5];
3878 #if defined(TESTING)
3879 HDBGRegQW ("lreg");
3880 #endif
3881 cpu.rE = (GETHI (cpu.Yblock8[6]) >> 10) & 0377; // need checking
3882 break;
3883
3884 // Optimized to the top of the loop
3885 // // lxln
3886 // case x0 (0720): // lxl0
3887 // case x0 (0721): // lxl1
3888 // case x0 (0722): // lxl2
3889 // case x0 (0723): // lxl3
3890 // case x0 (0724): // lxl4
3891 // case x0 (0725): // lxl5
3892 // case x0 (0726): // lxl6
3893 // case x0 (0727): // lxl7
3894
3895 /// Fixed-Point Data Movement Store
3896
3897 case x0 (0753): // sreg
3898 CPTUR (cptUseE);
3899 CPTUR (cptUseRALR);
3900 // clear block (changed to memset() per DJ request)
3901 //(void)memset (cpu.Yblock8, 0, sizeof (cpu.Yblock8));
3902 L68_ (cpu.ou.cycle |= ou_GOS;)
3903 L68_ (cpu.ou.eac = 0;)
3904 SETHI (cpu.Yblock8[0], cpu.rX[0]);
3905 SETLO (cpu.Yblock8[0], cpu.rX[1]);
3906 L68_ (cpu.ou.eac ++;)
3907 SETHI (cpu.Yblock8[1], cpu.rX[2]);
3908 SETLO (cpu.Yblock8[1], cpu.rX[3]);
3909 L68_ (cpu.ou.eac ++;)
3910 SETHI (cpu.Yblock8[2], cpu.rX[4]);
3911 SETLO (cpu.Yblock8[2], cpu.rX[5]);
3912 L68_ (cpu.ou.eac ++;)
3913 SETHI (cpu.Yblock8[3], cpu.rX[6]);
3914 SETLO (cpu.Yblock8[3], cpu.rX[7]);
3915 L68_ (cpu.ou.eac ++;)
3916 cpu.Yblock8[4] = cpu.rA;
3917 cpu.Yblock8[5] = cpu.rQ;
3918 cpu.Yblock8[6] = ((word36)(cpu.rE & MASK8)) << 28;
3919 if (cpu.tweaks.isolts_mode && ! cpu.tweaks.tandd_mode) // as stt
3920 cpu.Yblock8[7] = (((-- cpu.shadowTR) & MASK27) << 9) | (cpu.rRALR & 07);
3921 else
3922 cpu.Yblock8[7] = ((cpu.rTR & MASK27) << 9) | (cpu.rRALR & 07);
3923 #if defined(TESTING)
3924 HDBGRegXR (0, "sreg");
3925 HDBGRegXR (1, "sreg");
3926 HDBGRegXR (2, "sreg");
3927 HDBGRegXR (3, "sreg");
3928 HDBGRegXR (4, "sreg");
3929 HDBGRegXR (5, "sreg");
3930 HDBGRegXR (6, "sreg");
3931 HDBGRegXR (7, "sreg");
3932 HDBGRegAR ("sreg");
3933 HDBGRegQR ("sreg");
3934 #endif
3935 break;
3936
3937 // Optimized to the top of the loop
3938 // case x0 (0755): // sta
3939
3940 case x0 (0354): // stac
3941 if (cpu.CY == 0)
3942 {
3943 #if defined(TESTING)
3944 HDBGRegAR ("stac");
3945 #endif
3946 SET_I_ZERO;
3947 cpu.CY = cpu.rA;
3948 }
3949 else
3950 CLR_I_ZERO;
3951 break;
3952
3953 case x0 (0654): // stacq
3954 #if defined(TESTING)
3955 HDBGRegQR ("stacq");
3956 #endif
3957 if (cpu.CY == cpu.rQ)
3958 {
3959 #if defined(TESTING)
3960 HDBGRegAR ("stacq");
3961 #endif
3962 cpu.CY = cpu.rA;
3963 SET_I_ZERO;
3964 }
3965 else
3966 CLR_I_ZERO;
3967 break;
3968
3969 // Optimized to the top of the loop
3970 // case x0 (0757): // staq
3971
3972 case x0 (0551): // stba
3973 // 9-bit bytes of C(A) -> corresponding bytes of C(Y), the byte
3974 // positions affected being specified in the TAG field.
3975 // copyBytes ((i->tag >> 2) & 0xf, cpu.rA, &cpu.CY);
3976 #if defined(TESTING)
3977 HDBGRegAR ("stba");
3978 #endif
3979 cpu.CY = cpu.rA;
3980 cpu.zone =
3981 /*LINTED E_CONST_PROMOTED_UNSIGNED_LONG*/
3982 ((i->tag & 040) ? 0777000000000u : 0) |
3983 ((i->tag & 020) ? 0000777000000u : 0) |
3984 ((i->tag & 010) ? 0000000777000u : 0) |
3985 ((i->tag & 004) ? 0000000000777u : 0);
3986 cpu.useZone = true;
3987 cpu.ou.crflag = true;
3988 break;
3989
3990 case x0 (0552): // stbq
3991 // 9-bit bytes of C(Q) -> corresponding bytes of C(Y), the byte
3992 // positions affected being specified in the TAG field.
3993 // copyBytes ((i->tag >> 2) & 0xf, cpu.rQ, &cpu.CY);
3994 #if defined(TESTING)
3995 HDBGRegQR ("stbq");
3996 #endif
3997 cpu.CY = cpu.rQ;
3998 cpu.zone =
3999 /*LINTED E_CONST_PROMOTED_UNSIGNED_LONG*/
4000 ((i->tag & 040) ? 0777000000000u : 0) |
4001 ((i->tag & 020) ? 0000777000000u : 0) |
4002 ((i->tag & 010) ? 0000000777000u : 0) |
4003 ((i->tag & 004) ? 0000000000777u : 0);
4004 cpu.useZone = true;
4005 cpu.ou.crflag = true;
4006 break;
4007
4008 case x0 (0554): // stc1
4009 // "C(Y)25 reflects the state of the tally runout indicator
4010 // prior to modification.
4011 SETHI (cpu.CY, (cpu.PPR.IC + 1) & MASK18);
4012 // AL39 stc1 says that HEX is ignored, but the mode register
4013 // description says that it isn't
4014 DPS8M_ (SETLO (cpu.CY, cpu.cu.IR & 0777770);)
4015 L68_ (SETLO (cpu.CY, cpu.cu.IR & 0777760);)
4016 SCF (i->stiTally, cpu.CY, I_TALLY);
4017 break;
4018
4019 case x0 (0750): // stc2
4020 // AL-39 doesn't specify if the low half is set to zero,
4021 // set to IR, or left unchanged
4022 // RJ78 specifies unchanged
4023 // SETHI (cpu.CY, (cpu.PPR.IC + 2) & MASK18);
4024 cpu.CY = ((word36) ((cpu.PPR.IC + 2) & MASK18)) << 18;
4025 cpu.zone = 0777777000000;
4026 cpu.useZone = true;
4027 break;
4028
4029 case x0 (0751): // stca
4030 // Characters of C(A) -> corresponding characters of C(Y),
4031 // the character positions affected being specified in the TAG
4032 // field.
4033 // copyChars (i->tag, cpu.rA, &cpu.CY);
4034 #if defined(TESTING)
4035 HDBGRegAR ("stca");
4036 #endif
4037 cpu.CY = cpu.rA;
4038 cpu.zone =
4039 /*LINTED E_CONST_PROMOTED_UNSIGNED_LONG*/
4040 ((i->tag & 040) ? 0770000000000u : 0) |
4041 ((i->tag & 020) ? 0007700000000u : 0) |
4042 ((i->tag & 010) ? 0000077000000u : 0) |
4043 ((i->tag & 004) ? 0000000770000u : 0) |
4044 ((i->tag & 002) ? 0000000007700u : 0) |
4045 ((i->tag & 001) ? 0000000000077u : 0);
4046 cpu.useZone = true;
4047 cpu.ou.crflag = true;
4048 break;
4049
4050 case x0 (0752): // stcq
4051 // Characters of C(Q) -> corresponding characters of C(Y), the
4052 // character positions affected being specified in the TAG field.
4053 // copyChars (i->tag, cpu.rQ, &cpu.CY);
4054 #if defined(TESTING)
4055 HDBGRegQR ("stcq");
4056 #endif
4057 cpu.CY = cpu.rQ;
4058 cpu.zone =
4059 /*LINTED E_CONST_PROMOTED_UNSIGNED_LONG*/
4060 ((i->tag & 040) ? 0770000000000u : 0) |
4061 ((i->tag & 020) ? 0007700000000u : 0) |
4062 ((i->tag & 010) ? 0000077000000u : 0) |
4063 ((i->tag & 004) ? 0000000770000u : 0) |
4064 ((i->tag & 002) ? 0000000007700u : 0) |
4065 ((i->tag & 001) ? 0000000000077u : 0);
4066 cpu.useZone = true;
4067 cpu.ou.crflag = true;
4068 break;
4069
4070 case x0 (0357): //< stcd
4071 // C(PPR) -> C(Y-pair) as follows:
4072
4073 // 000 -> C(Y-pair)0,2
4074 // C(PPR.PSR) -> C(Y-pair)3,17
4075 // C(PPR.PRR) -> C(Y-pair)18,20
4076 // 00...0 -> C(Y-pair)21,29
4077 // (43)8 -> C(Y-pair)30,35
4078
4079 // C(PPR.IC)+2 -> C(Y-pair)36,53
4080 // 00...0 -> C(Y-pair)54,71
4081
4082 // ISOLTS 880 5a has an STCD in an XED in a fault pair;
4083 // it reports the wrong ring number. This was fixed by
4084 // emulating the SCU instruction (different behavior in fault
4085 // pair).
4086
4087 if (cpu.cycle == EXEC_cycle)
4088 {
4089 cpu.Ypair[0] = 0;
4090 putbits36_15 (& cpu.Ypair[0], 3, cpu.PPR.PSR);
4091 putbits36_3 (& cpu.Ypair[0], 18, cpu.PPR.PRR);
4092 putbits36_6 (& cpu.Ypair[0], 30, 043);
4093
4094 cpu.Ypair[1] = 0;
4095 putbits36_18 (& cpu.Ypair[1], 0, cpu.PPR.IC + 2);
4096 }
4097 else
4098 {
4099 cpu.Ypair[0] = 0;
4100 putbits36_15 (& cpu.Ypair[0], 3, cpu.cu_data.PSR);
4101 putbits36_3 (& cpu.Ypair[0], 18, cpu.cu_data.PRR);
4102 //putbits36_6 (& cpu.Ypair[0], 30, 043);
4103
4104 cpu.Ypair[1] = 0;
4105 putbits36_18 (& cpu.Ypair[1], 0, cpu.cu_data.IC + 2);
4106 }
4107 break;
4108
4109 // Optimized to the top of the loop
4110 // case x0 (0754): // sti
4111
4112 // Optimized to the top of the loop
4113 // case x0 (0756): // stq
4114
4115 case x0 (0454): // stt
4116 CPTUR (cptUseTR);
4117 // ISOLTS reads the shadow TR, except in T&D mode, where the TR
4118 // itself counts with execution (see do_LUF_fault)
4119 if (cpu.tweaks.isolts_mode && ! cpu.tweaks.tandd_mode)
4120 //cpu.CY = ((-- cpu.shadowTR) & MASK27) << 9;
4121 // ubsan
4122 cpu.CY = (((uint) (((int) cpu.shadowTR) - 1)) & MASK27) << 9;
4123 else
4124 cpu.CY = (cpu.rTR & MASK27) << 9;
4125 break;
4126
4127 // Optimized to the top of the loop
4128 // // stxn
4129 // case x0 (0740): // stx0
4130 // case x0 (0741): // stx1
4131 // case x0 (0742): // stx2
4132 // case x0 (0743): // stx3
4133 // case x0 (0744): // stx4
4134 // case x0 (0745): // stx5
4135 // case x0 (0746): // stx6
4136 // case x0 (0747): // stx7
4137
4138 // Optimized to the top of the loop
4139 // case x0 (0450): // stz
4140
4141 // sxln
4142 case x0 (0440): // sxl0
4143 case x0 (0441): // sxl1
4144 case x0 (0442): // sxl2
4145 case x0 (0443): // sxl3
4146 case x0 (0444): // sxl4
4147 case x0 (0445): // sxl5
4148 case x0 (0446): // sxl6
4149 case x0 (0447): // sxl7
4150 //SETLO (cpu.CY, cpu.rX[opcode10 & 07]);
4151 cpu.CY = cpu.rX[opcode10 & 07];
4152 cpu.zone = 0000000777777;
4153 cpu.useZone = true;
4154 break;
4155
4156 /// Fixed-Point Data Movement Shift
4157
4158 case x0 (0775): // alr
4159 {
4160 #if defined(TESTING)
4161 HDBGRegAR ("alr");
4162 #endif
4163 #if BARREL_SHIFTER
4164 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4165 cnt %= 36;
4166
4167 word36 highA = cpu.rA & barrelLeftMaskTable[cnt];
4168 cpu.rA <<= cnt;
4169 highA >>= (36 - cnt);
4170 highA &= barrelRightMaskTable[cnt];
4171 cpu.rA |= highA;
4172 cpu.rA &= DMASK; // keep to 36-bits
4173 #else // !BARREL_SHIFTER
4174 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4175 for (uint j = 0 ; j < tmp36 ; j++)
4176 {
4177 bool a0 = cpu.rA & SIGN36; // A0
4178 cpu.rA <<= 1; // shift left 1
4179 if (a0) // rotate A0 -> A35
4180 cpu.rA |= 1;
4181 }
4182 cpu.rA &= DMASK; // keep to 36-bits
4183 #endif // BARREL_SHIFTER
4184 #if defined(TESTING)
4185 HDBGRegAW ("alr");
4186 #endif
4187
4188 SC_I_ZERO (cpu.rA == 0);
4189 SC_I_NEG (cpu.rA & SIGN36);
4190 }
4191 break;
4192
4193 // Optimized to the top of the loop
4194 // case x0 (0735): // als
4195
4196 case x0 (0771): // arl
4197 // Shift C(A) right the number of positions given in
4198 // C(TPR.CA)11,17; filling vacated positions with zeros.
4199 {
4200 #if defined(TESTING)
4201 HDBGRegAR ("arl");
4202 #endif
4203 cpu.rA &= DMASK; // Make sure the shifted in bits are 0
4204 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4205
4206 cpu.rA >>= tmp36;
4207 cpu.rA &= DMASK; // keep to 36-bits
4208 #if defined(TESTING)
4209 HDBGRegAW ("arl");
4210 #endif
4211
4212 SC_I_ZERO (cpu.rA == 0);
4213 SC_I_NEG (cpu.rA & SIGN36);
4214 }
4215 break;
4216
4217 case x0 (0731): // ars
4218 {
4219 // Shift C(A) right the number of positions given in
4220 // C(TPR.CA)11,17; filling vacated positions with initial C(A)0.
4221
4222 #if defined(TESTING)
4223 HDBGRegAR ("ars");
4224 #endif
4225 #if BARREL_SHIFTER
4226 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4227 bool A0 = (cpu.rA & SIGN36) != 0;
4228
4229 if (cnt >= 36) {
4230 cpu.rA = A0 ? MASK36 : 0;
4231 } else {
4232 // Shift rA
4233 cpu.rA >>= cnt;
4234 // Mask out the high bits
4235 if (A0) {
4236 cpu.rA |= barrelLeftMaskTable[cnt];
4237 } else {
4238 cpu.rA &= BS_COMPL (barrelLeftMaskTable[cnt]);
4239 }
4240 }
4241 cpu.rA &= DMASK; // keep to 36-bits
4242 #else // !BARREL_SHIFTER
4243 cpu.rA &= DMASK; // Make sure the shifted in bits are 0
4244 word18 tmp18 = cpu.TPR.CA & 0177; // CY bits 11-17
4245
4246 bool a0 = cpu.rA & SIGN36; // A0
4247 for (uint j = 0 ; j < tmp18 ; j ++)
4248 {
4249 cpu.rA >>= 1; // shift right 1
4250 if (a0) // propagate sign bit
4251 cpu.rA |= SIGN36;
4252 }
4253 cpu.rA &= DMASK; // keep to 36-bits
4254 #endif // BARREL_SHIFTER
4255 #if defined(TESTING)
4256 HDBGRegAW ("ars");
4257 #endif
4258
4259 SC_I_ZERO (cpu.rA == 0);
4260 SC_I_NEG (cpu.rA & SIGN36);
4261 }
4262 break;
4263
4264 case x0 (0777): // llr
4265 // Shift C(AQ) left by the number of positions given in
4266 // C(TPR.CA)11,17; entering each bit leaving AQ0 into AQ71.
4267
4268 {
4269 #if defined(TESTING)
4270 HDBGRegAR ("llr");
4271 HDBGRegQR ("llr");
4272 #endif
4273 #if BARREL_SHIFTER
4274 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4275 cnt = cnt % 72; // 0-71
4276 if (cnt > 35) {
4277 cnt = cnt - 36;
4278 word36 tmp = cpu.rA;
4279 cpu.rA = cpu.rQ;
4280 cpu.rQ = tmp;
4281 }
4282 word36 highA = cpu.rA & barrelLeftMaskTable[cnt];
4283 word36 lowA = cpu.rA & BS_COMPL(barrelLeftMaskTable[cnt]);
4284 word36 highQ = cpu.rQ & barrelLeftMaskTable[cnt];
4285 word36 lowQ = cpu.rQ & BS_COMPL(barrelLeftMaskTable[cnt]);
4286 cpu.rA = (lowA << cnt) | (highQ >> (36 - cnt));
4287 cpu.rQ = (lowQ << cnt) | (highA >> (36 - cnt));
4288 #else // !BARREL_SHIFTER
4289 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4290 for (uint j = 0 ; j < tmp36 ; j++)
4291 {
4292 bool a0 = cpu.rA & SIGN36; // A0
4293
4294 cpu.rA <<= 1; // shift left 1
4295
4296 bool b0 = cpu.rQ & SIGN36; // Q0
4297 if (b0)
4298 cpu.rA |= 1; // Q0 => A35
4299
4300 cpu.rQ <<= 1; // shift left 1
4301
4302 if (a0) // propagate A sign bit
4303 cpu.rQ |= 1;
4304 }
4305
4306 #endif // BARREL_SHIFTER
4307 cpu.rA &= DMASK; // keep to 36-bits
4308 cpu.rQ &= DMASK;
4309 #if defined(TESTING)
4310 HDBGRegAW ("llr");
4311 HDBGRegQW ("llr");
4312 #endif
4313
4314 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4315 SC_I_NEG (cpu.rA & SIGN36);
4316 }
4317 break;
4318
4319 case x0 (0737): // lls
4320 {
4321 // lls Long Left Shift
4322 // Shift C(AQ) left the number of positions given in
4323 // C(TPR.CA)11,17; filling vacated positions with zeros.
4324 // Zero if C(AQ) == 0 then ON; otherwise OFF:
4325 // Negative if C(AQ)0 == 1 then On; otherwise OFF;
4326 // Carry if C(AQ)0 changes during the shift; then ON; otherwise OFF:
4327 #if BARREL_SHIFTER
4328 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4329
4330
4331 // Sanitize
4332 cpu.rA &= MASK36;
4333 cpu.rQ &= MASK36;
4334
4335 if (cnt >= 72) {
4336 // If the shift is 72 or greater, AQ will be set to zero and
4337 // the carry will be cleared if the initial value of AQ is 0 or
4338 // all ones
4339 bool allz = cpu.rA == 0 && cpu.rQ == 0;
4340 bool all1 = cpu.rA == MASK36 && cpu.rQ == MASK36;
4341 if (allz || all1)
4342 CLR_I_CARRY;
4343 else
4344 SET_I_CARRY;
4345 cpu.rA = 0;
4346 cpu.rQ = 0;
4347
4348 } else if (cnt >= 36) {
4349 // If the shift count is 36 to 71, all of A and some of Q will determine
4350 // the carry; all of A will become Q << (cnt - 36), and Q will become 0.
4351 uint cnt36 = cnt - 36;
4352 // The carry depends on the sign bit changing on the shift;
4353 // add 1 so that the mask includes the sign bit and all of
4354 // the bits that will be shifted in.
4355 word36 lmask = barrelLeftMaskTable[cnt36 + 1];
4356 // Capture all of the bits that will be shifted
4357 word36 captureA = cpu.rA;
4358 word36 captureQ = lmask & cpu.rQ;
4359 bool az = captureA == 0;
4360 bool a1 = captureA == MASK36;
4361 bool qz = captureQ == 0;
4362 bool q1 = captureQ == (MASK36 & lmask);
4363 bool allz = az && qz;
4364 bool all1 = a1 && q1;
4365 if (allz || all1)
4366 CLR_I_CARRY;
4367 else
4368 SET_I_CARRY;
4369
4370 // Shift the bits
4371 cpu.rA = (cpu.rQ << cnt36) & MASK36;
4372 cpu.rQ = 0;
4373 } else { // cnt < 36
4374 // If the count is < 36, carry is determined by the high part of A;
4375 // A is shifted left, and bits shifted out of Q are shifted into A.
4376 // The carry depends on the sign bit changing on the shift;
4377 // add 1 so that the mask includes the sign bit and all of
4378 // the bits that will be shifted in.
4379 word36 lmask = barrelLeftMaskTable[cnt + 1];
4380 word36 captureA = lmask & cpu.rA;
4381 bool allz = captureA == 0;
4382 bool all1 = captureA == (MASK36 & lmask);
4383
4384 if (allz || all1)
4385 CLR_I_CARRY;
4386 else
4387 SET_I_CARRY;
4388
4389 // Shift the bits
4390 cpu.rA = ((cpu.rA << cnt) & MASK36) | (cpu.rQ >> (36 - cnt));
4391 cpu.rQ = (cpu.rQ << cnt) & MASK36;
4392 }
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430 #else // !BARREL_SHIFTER
4431
4432 CLR_I_CARRY;
4433
4434 # if defined(TESTING)
4435 HDBGRegAR ("lls");
4436 HDBGRegQR ("lls");
4437 # endif
4438 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4439 word36 tmpSign = cpu.rA & SIGN36;
4440 for (uint j = 0 ; j < tmp36 ; j ++)
4441 {
4442 cpu.rA <<= 1; // shift left 1
4443
4444 if (tmpSign != (cpu.rA & SIGN36))
4445 SET_I_CARRY;
4446
4447 bool b0 = cpu.rQ & SIGN36; // Q0
4448 if (b0)
4449 cpu.rA |= 1; // Q0 => A35
4450
4451 cpu.rQ <<= 1; // shift left 1
4452 }
4453
4454 cpu.rA &= DMASK; // keep to 36-bits
4455 cpu.rQ &= DMASK;
4456 #endif // BARREL_SHIFTER
4457 #if defined(TESTING)
4458 HDBGRegAW ("lls");
4459 HDBGRegQW ("lls");
4460 #endif
4461
4462 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4463 SC_I_NEG (cpu.rA & SIGN36);
4464 }
4465 break;
4466
4467 case x0 (0773): // lrl
4468 // Shift C(AQ) right the number of positions given in
4469 // C(TPR.CA)11,17; filling vacated positions with zeros.
4470 {
4471 #if defined(TESTING)
4472 HDBGRegAR ("lrl");
4473 HDBGRegQR ("lrl");
4474 #endif
4475 #if BARREL_SHIFTER
4476 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4477 if (cnt >= 72) {
4478 cpu.rA = 0;
4479 cpu.rQ = 0;
4480 } else if (cnt < 36) {
4481 // Shift rQ
4482 cpu.rQ >>= cnt;
4483 // Mask out the high bits
4484 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt]);
4485 // Capture the low bits in A
4486 word36 lowA = cpu.rA & barrelRightMaskTable[cnt];
4487 // Shift A
4488 cpu.rA >>= cnt;
4489 // Mask out the high bits
4490 cpu.rA &= BS_COMPL (barrelLeftMaskTable[cnt]);
4491 // Move the low A bits left
4492 lowA <<= (36 - cnt);
4493 // Put them in high Q
4494 cpu.rQ |= lowA;
4495 } else { // 36-71
4496 // Shift rQ
4497 cpu.rQ = cpu.rA >> (cnt - 36);
4498 // Mask out the high bits
4499 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt - 36]);
4500 cpu.rA = 0;
4501 }
4502 cpu.rA &= DMASK; // keep to 36-bits
4503 cpu.rQ &= DMASK;
4504 #else // !BARREL_SHIFTER
4505 cpu.rA &= DMASK; // Make sure the shifted in bits are 0
4506 cpu.rQ &= DMASK; // Make sure the shifted in bits are 0
4507 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4508 for (uint j = 0 ; j < tmp36 ; j++)
4509 {
4510 bool a35 = cpu.rA & 1; // A35
4511 cpu.rA >>= 1; // shift right 1
4512
4513 cpu.rQ >>= 1; // shift right 1
4514
4515 if (a35) // propagate sign bit
4516 cpu.rQ |= SIGN36;
4517 }
4518 cpu.rA &= DMASK; // keep to 36-bits
4519 cpu.rQ &= DMASK;
4520 #endif // BARREL_SHIFTER
4521 #if defined(TESTING)
4522 HDBGRegAW ("lrl");
4523 HDBGRegQW ("lrl");
4524 #endif
4525
4526 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4527 SC_I_NEG (cpu.rA & SIGN36);
4528 }
4529 break;
4530
4531 case x0 (0733): // lrs
4532 {
4533 // Shift C(AQ) right the number of positions given in
4534 // C(TPR.CA)11,17; filling vacated positions with initial C(AQ)0.
4535
4536 #if defined(TESTING)
4537 HDBGRegAR ("lrs");
4538 HDBGRegQR ("lrs");
4539 #endif
4540 #if BARREL_SHIFTER
4541 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4542 bool AQ0 = (cpu.rA & SIGN36) != 0;
4543 if (cnt >= 72) {
4544 cpu.rA = cpu.rQ = AQ0 ? MASK36 : 0;
4545 } else if (cnt < 36) {
4546 // Shift rQ
4547 cpu.rQ >>= cnt;
4548 // Mask out the high bits
4549 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt]);
4550 // Capture the low bits in A
4551 word36 lowA = cpu.rA & barrelRightMaskTable[cnt];
4552 // Shift A
4553 cpu.rA >>= cnt;
4554 // Set the high bits to AQ0
4555 if (AQ0)
4556 cpu.rA |= barrelLeftMaskTable[cnt];
4557 else
4558 cpu.rA &= BS_COMPL (barrelLeftMaskTable[cnt]);
4559 // Move the low A bits left
4560 lowA <<= (36 - cnt);
4561 // Put them in high Q
4562 cpu.rQ |= lowA;
4563 } else { // 36-71
4564 // Shift rQ
4565 cpu.rQ = cpu.rA >> (cnt - 36);
4566 // Mask out the high bits
4567 if (AQ0) {
4568 cpu.rQ |= barrelLeftMaskTable[cnt - 36];
4569 cpu.rA = MASK36;
4570 } else {
4571 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt - 36]);
4572 cpu.rA = 0;
4573 }
4574 }
4575 cpu.rA &= DMASK; // keep to 36-bits
4576 cpu.rQ &= DMASK;
4577 #else // !BARREL_SHIFTER
4578 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4579 cpu.rA &= DMASK; // Make sure the shifted in bits are 0
4580 cpu.rQ &= DMASK; // Make sure the shifted in bits are 0
4581 bool a0 = cpu.rA & SIGN36; // A0
4582
4583 for (uint j = 0 ; j < tmp36 ; j ++)
4584 {
4585 bool a35 = cpu.rA & 1; // A35
4586
4587 cpu.rA >>= 1; // shift right 1
4588 if (a0)
4589 cpu.rA |= SIGN36;
4590
4591 cpu.rQ >>= 1; // shift right 1
4592 if (a35) // propagate sign bit1
4593 cpu.rQ |= SIGN36;
4594 }
4595 cpu.rA &= DMASK; // keep to 36-bits (probably ain't necessary)
4596 cpu.rQ &= DMASK;
4597 #endif // BARREL_SHIFTER
4598 #if defined(TESTING)
4599 HDBGRegAW ("lrs");
4600 HDBGRegQW ("lrs");
4601 #endif
4602
4603 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
4604 SC_I_NEG (cpu.rA & SIGN36);
4605 }
4606 break;
4607
4608 case x0 (0776): // qlr
4609 // Shift C(Q) left the number of positions given in
4610 // C(TPR.CA)11,17; entering each bit leaving Q0 into Q35.
4611 {
4612 #if defined(TESTING)
4613 HDBGRegQR ("qlr");
4614 #endif
4615 #if BARREL_SHIFTER
4616 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4617 cnt %= 36;
4618
4619 word36 highQ = cpu.rQ & barrelLeftMaskTable[cnt];
4620 cpu.rQ <<= cnt;
4621 highQ >>= (36 - cnt);
4622 highQ &= barrelRightMaskTable[cnt];
4623 cpu.rQ |= highQ;
4624 cpu.rQ &= DMASK; // keep to 36-bits
4625 #else // !BARREL_SHIFTER
4626 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4627 for (uint j = 0 ; j < tmp36 ; j++)
4628 {
4629 bool q0 = cpu.rQ & SIGN36; // Q0
4630 cpu.rQ <<= 1; // shift left 1
4631 if (q0) // rotate A0 -> A35
4632 cpu.rQ |= 1;
4633 }
4634 cpu.rQ &= DMASK; // keep to 36-bits
4635 #endif // BARREL_SHIFTER
4636 #if defined(TESTING)
4637 HDBGRegQW ("qlr");
4638 #endif
4639
4640 SC_I_ZERO (cpu.rQ == 0);
4641 SC_I_NEG (cpu.rQ & SIGN36);
4642 }
4643 break;
4644
4645 // Optimized to the top of the loop
4646 // case x0 (0736): // qls
4647
4648 case x0 (0772): // qrl
4649 // Shift C(Q) right the number of positions specified by
4650 // Y11,17; fill vacated positions with zeros.
4651 {
4652 #if defined(TESTING)
4653 HDBGRegQR ("qrl");
4654 #endif
4655 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4656
4657 cpu.rQ &= DMASK; // Make sure the shifted in bits are 0
4658 cpu.rQ >>= tmp36;
4659 cpu.rQ &= DMASK; // keep to 36-bits
4660 #if defined(TESTING)
4661 HDBGRegQW ("qrl");
4662 #endif
4663
4664 SC_I_ZERO (cpu.rQ == 0);
4665 SC_I_NEG (cpu.rQ & SIGN36);
4666
4667 }
4668 break;
4669
4670 case x0 (0732): // qrs
4671 {
4672 // Shift C(Q) right the number of positions given in
4673 // C(TPR.CA)11,17; filling vacated positions with initial C(Q)0.
4674
4675 #if defined(TESTING)
4676 HDBGRegQR ("qrs");
4677 #endif
4678 #if BARREL_SHIFTER
4679 uint cnt = (uint) cpu.TPR.CA & 0177; // 0-127
4680 bool Q0 = (cpu.rQ & SIGN36) != 0;
4681
4682 if (cnt >= 36) {
4683 cpu.rQ = Q0 ? MASK36 : 0;
4684 } else {
4685 // Shift rQ
4686 cpu.rQ >>= cnt;
4687 // Mask out the high bits
4688 if (Q0) {
4689 cpu.rQ |= barrelLeftMaskTable[cnt];
4690 } else {
4691 cpu.rQ &= BS_COMPL (barrelLeftMaskTable[cnt]);
4692 }
4693 }
4694 cpu.rQ &= DMASK; // keep to 36-bits
4695 #else // !BARREL_SHIFTER
4696 cpu.rQ &= DMASK; // Make sure the shifted in bits are 0
4697 word36 tmp36 = cpu.TPR.CA & 0177; // CY bits 11-17
4698 bool q0 = cpu.rQ & SIGN36; // Q0
4699 for (uint j = 0 ; j < tmp36 ; j++)
4700 {
4701 cpu.rQ >>= 1; // shift right 1
4702 if (q0) // propagate sign bit
4703 cpu.rQ |= SIGN36;
4704 }
4705 cpu.rQ &= DMASK; // keep to 36-bits
4706 #endif // BARREL_SHIFTER
4707 #if defined(TESTING)
4708 HDBGRegQW ("qrs");
4709 #endif
4710
4711 SC_I_ZERO (cpu.rQ == 0);
4712 SC_I_NEG (cpu.rQ & SIGN36);
4713 }
4714 break;
4715
4716 /// Fixed-Point Addition
4717
4718 case x0 (0075): // ada
4719 {
4720 // C(A) + C(Y) -> C(A)
4721 // Modifications: All
4722 //
4723 // (Indicators not listed are not affected)
4724 // ZERO: If C(A) = 0, then ON; otherwise OFF
4725 // NEG: If C(A)0 = 1, then ON; otherwise OFF
4726 // OVR: If range of A is exceeded, then ON
4727 // CARRY: If a carry out of A0 is generated, then ON; otherwise OFF
4728
4729 L68_ (cpu.ou.cycle |= ou_GOS;)
4730 #if defined(TESTING)
4731 HDBGRegAR ("ada");
4732 #endif
4733 bool ovf;
4734 cpu.rA = Add36b (cpup, cpu.rA, cpu.CY, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4735 #if defined(TESTING)
4736 HDBGRegAW ("ada");
4737 #endif
4738 overflow (cpup, ovf, false, "ada overflow fault");
4739 }
4740 break;
4741
4742 case x0 (0077): // adaq
4743 {
4744 // C(AQ) + C(Y-pair) -> C(AQ)
4745 L68_ (cpu.ou.cycle |= ou_GOS;)
4746 #if defined(TESTING)
4747 HDBGRegAR ("adaq");
4748 HDBGRegQR ("adaq");
4749 #endif
4750 bool ovf;
4751 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
4752 tmp72 = Add72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ),
4753 tmp72, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4754 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4755 #if defined(TESTING)
4756 HDBGRegAW ("adaq");
4757 HDBGRegQW ("adaq");
4758 #endif
4759 overflow (cpup, ovf, false, "adaq overflow fault");
4760 }
4761 break;
4762
4763 case x0 (0033): // adl
4764 {
4765 // C(AQ) + C(Y) sign extended -> C(AQ)
4766 L68_ (cpu.ou.cycle |= ou_GOS;)
4767 #if defined(TESTING)
4768 HDBGRegAR ("adl");
4769 HDBGRegQR ("adl");
4770 #endif
4771 bool ovf;
4772 word72 tmp72 = SIGNEXT36_72 (cpu.CY); // sign extend Cy
4773 tmp72 = Add72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ),
4774 tmp72, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4775 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4776 #if defined(TESTING)
4777 HDBGRegAW ("adl");
4778 HDBGRegQW ("adl");
4779 #endif
4780 overflow (cpup, ovf, false, "adl overflow fault");
4781 }
4782 break;
4783
4784 case x0 (0037): // adlaq
4785 {
4786 // The adlaq instruction is identical to the adaq instruction with
4787 // the exception that the overflow indicator is not affected by the
4788 // adlaq instruction, nor does an overflow fault occur. Operands
4789 // and results are treated as unsigned, positive binary integers.
4790 L68_ (cpu.ou.cycle |= ou_GOS;)
4791 #if defined(TESTING)
4792 HDBGRegAR ("adlaq");
4793 HDBGRegQR ("adlaq");
4794 #endif
4795 bool ovf;
4796 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
4797
4798 tmp72 = Add72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ),
4799 tmp72, 0, I_ZNC, & cpu.cu.IR, & ovf);
4800 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
4801 #if defined(TESTING)
4802 HDBGRegAW ("adlaq");
4803 HDBGRegQW ("adlaq");
4804 #endif
4805 }
4806 break;
4807
4808 case x0 (0035): // adla
4809 {
4810 L68_ (cpu.ou.cycle |= ou_GOS;)
4811 // The adla instruction is identical to the ada instruction with
4812 // the exception that the overflow indicator is not affected by the
4813 // adla instruction, nor does an overflow fault occur. Operands and
4814 // results are treated as unsigned, positive binary integers. */
4815
4816 #if defined(TESTING)
4817 HDBGRegAR ("adla");
4818 #endif
4819 bool ovf;
4820 cpu.rA = Add36b (cpup, cpu.rA, cpu.CY, 0, I_ZNC, & cpu.cu.IR, & ovf);
4821 #if defined(TESTING)
4822 HDBGRegAW ("adla");
4823 #endif
4824 }
4825 break;
4826
4827 case x0 (0036): // adlq
4828 {
4829 // The adlq instruction is identical to the adq instruction with
4830 // the exception that the overflow indicator is not affected by the
4831 // adlq instruction, nor does an overflow fault occur. Operands and
4832 // results are treated as unsigned, positive binary integers. */
4833
4834 L68_ (cpu.ou.cycle |= ou_GOS;)
4835 #if defined(TESTING)
4836 HDBGRegQR ("adlq");
4837 #endif
4838 bool ovf;
4839 cpu.rQ = Add36b (cpup, cpu.rQ, cpu.CY, 0, I_ZNC, & cpu.cu.IR, & ovf);
4840 #if defined(TESTING)
4841 HDBGRegQW ("adlq");
4842 #endif
4843 }
4844 break;
4845
4846 // adlxn
4847 case x0 (0020): // adlx0
4848 case x0 (0021): // adlx1
4849 case x0 (0022): // adlx2
4850 case x0 (0023): // adlx3
4851 case x0 (0024): // adlx4
4852 case x0 (0025): // adlx5
4853 case x0 (0026): // adlx6
4854 case x0 (0027): // adlx7
4855 {
4856 L68_ (cpu.ou.cycle |= ou_GOS;)
4857 uint32 n = opcode10 & 07; // get n
4858 #if defined(TESTING)
4859 HDBGRegXR (n, "adlxn");
4860 #endif
4861 bool ovf;
4862 cpu.rX[n] = Add18b (cpup, cpu.rX[n], GETHI (cpu.CY), 0, I_ZNC,
4863 & cpu.cu.IR, & ovf);
4864 #if defined(TESTING)
4865 HDBGRegXW (n, "adlxn");
4866 #endif
4867 }
4868 break;
4869
4870 // Optimized to the top of the loop
4871 // case x0 (0076): // adq
4872
4873 // adxn
4874 case x0 (0060): // adx0
4875 case x0 (0061): // adx1
4876 case x0 (0062): // adx2
4877 case x0 (0063): // adx3
4878 case x0 (0064): // adx4
4879 case x0 (0065): // adx5
4880 case x0 (0066): // adx6
4881 case x0 (0067): // adx7
4882 {
4883 L68_ (cpu.ou.cycle |= ou_GOS;)
4884 uint32 n = opcode10 & 07; // get n
4885 #if defined(TESTING)
4886 HDBGRegXR (n, "adxn");
4887 #endif
4888 bool ovf;
4889 cpu.rX[n] = Add18b (cpup, cpu.rX[n], GETHI (cpu.CY), 0,
4890 I_ZNOC,
4891 & cpu.cu.IR, & ovf);
4892 #if defined(TESTING)
4893 HDBGRegXW (n, "adxn");
4894 #endif
4895 overflow (cpup, ovf, false, "adxn overflow fault");
4896 }
4897 break;
4898
4899 // Optimized to the top of the loop
4900 // case x0 (0054): // aos
4901
4902 case x0 (0055): // asa
4903 {
4904 // C(A) + C(Y) -> C(Y)
4905
4906 L68_ (cpu.ou.cycle |= ou_GOS;)
4907 #if defined(TESTING)
4908 HDBGRegAR ("asa");
4909 #endif
4910 bool ovf;
4911 cpu.CY = Add36b (cpup, cpu.rA, cpu.CY, 0, I_ZNOC,
4912 & cpu.cu.IR, & ovf);
4913 overflow (cpup, ovf, true, "asa overflow fault");
4914 }
4915 break;
4916
4917 case x0 (0056): // asq
4918 {
4919 // C(Q) + C(Y) -> C(Y)
4920 L68_ (cpu.ou.cycle |= ou_GOS;)
4921 #if defined(TESTING)
4922 HDBGRegQR ("asa");
4923 #endif
4924 bool ovf;
4925 cpu.CY = Add36b (cpup, cpu.rQ, cpu.CY, 0, I_ZNOC, & cpu.cu.IR, & ovf);
4926 overflow (cpup, ovf, true, "asq overflow fault");
4927 }
4928 break;
4929
4930 // asxn
4931 case x0 (0040): // asx0
4932 case x0 (0041): // asx1
4933 case x0 (0042): // asx2
4934 case x0 (0043): // asx3
4935 case x0 (0044): // asx4
4936 case x0 (0045): // asx5
4937 case x0 (0046): // asx6
4938 case x0 (0047): // asx7
4939 {
4940 // For n = 0, 1, ..., or 7 as determined by operation code
4941 // C(Xn) + C(Y)0,17 -> C(Y)0,17
4942 L68_ (cpu.ou.cycle |= ou_GOS;)
4943 uint32 n = opcode10 & 07; // get n
4944 #if defined(TESTING)
4945 HDBGRegXR (n, "asxn");
4946 #endif
4947 bool ovf;
4948 word18 tmp18 = Add18b (cpup, cpu.rX[n], GETHI (cpu.CY), 0,
4949 I_ZNOC, & cpu.cu.IR, & ovf);
4950 SETHI (cpu.CY, tmp18);
4951 overflow (cpup, ovf, true, "asxn overflow fault");
4952 }
4953 break;
4954
4955 case x0 (0071): // awca
4956 {
4957 // If carry indicator OFF, then C(A) + C(Y) -> C(A)
4958 // If carry indicator ON, then C(A) + C(Y) + 1 -> C(A)
4959
4960 L68_ (cpu.ou.cycle |= ou_GOS;)
4961 #if defined(TESTING)
4962 HDBGRegAR ("awca");
4963 #endif
4964 bool ovf;
4965 cpu.rA = Add36b (cpup, cpu.rA, cpu.CY, TST_I_CARRY ? 1 : 0,
4966 I_ZNOC, & cpu.cu.IR, & ovf);
4967 #if defined(TESTING)
4968 HDBGRegAW ("awca");
4969 #endif
4970 overflow (cpup, ovf, false, "awca overflow fault");
4971 }
4972 break;
4973
4974 case x0 (0072): // awcq
4975 {
4976 // If carry indicator OFF, then C(Q) + C(Y) -> C(Q)
4977 // If carry indicator ON, then C(Q) + C(Y) + 1 -> C(Q)
4978
4979 L68_ (cpu.ou.cycle |= ou_GOS;)
4980 #if defined(TESTING)
4981 HDBGRegQR ("awcq");
4982 #endif
4983 bool ovf;
4984 cpu.rQ = Add36b (cpup, cpu.rQ, cpu.CY, TST_I_CARRY ? 1 : 0,
4985 I_ZNOC, & cpu.cu.IR, & ovf);
4986 #if defined(TESTING)
4987 HDBGRegQW ("awcq");
4988 #endif
4989 overflow (cpup, ovf, false, "awcq overflow fault");
4990 }
4991 break;
4992
4993 /// Fixed-Point Subtraction
4994
4995 case x0 (0175): // sba
4996 {
4997 // C(A) - C(Y) -> C(A)
4998
4999 L68_ (cpu.ou.cycle |= ou_GOS;)
5000 #if defined(TESTING)
5001 HDBGRegAR ("sba");
5002 #endif
5003 bool ovf;
5004 cpu.rA = Sub36b (cpup, cpu.rA, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
5005 #if defined(TESTING)
5006 HDBGRegAW ("sba");
5007 #endif
5008 overflow (cpup, ovf, false, "sba overflow fault");
5009 }
5010 break;
5011
5012 case x0 (0177): // sbaq
5013 {
5014 // C(AQ) - C(Y-pair) -> C(AQ)
5015 L68_ (cpu.ou.cycle |= ou_GOS;)
5016 #if defined(TESTING)
5017 HDBGRegAR ("sbaq");
5018 HDBGRegQR ("sbaq");
5019 #endif
5020 bool ovf;
5021 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
5022 tmp72 = Sub72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ), tmp72, 1,
5023 I_ZNOC, & cpu.cu.IR,
5024 & ovf);
5025 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
5026 #if defined(TESTING)
5027 HDBGRegAW ("sbaq");
5028 HDBGRegQW ("sbaq");
5029 #endif
5030 overflow (cpup, ovf, false, "sbaq overflow fault");
5031 }
5032 break;
5033
5034 case x0 (0135): // sbla
5035 {
5036 // C(A) - C(Y) -> C(A) logical
5037
5038 L68_ (cpu.ou.cycle |= ou_GOS;)
5039 #if defined(TESTING)
5040 HDBGRegAR ("sbla");
5041 #endif
5042 bool ovf;
5043 cpu.rA = Sub36b (cpup, cpu.rA, cpu.CY, 1, I_ZNC, & cpu.cu.IR, & ovf);
5044 #if defined(TESTING)
5045 HDBGRegAW ("sbla");
5046 #endif
5047 }
5048 break;
5049
5050 case x0 (0137): // sblaq
5051 {
5052 // The sblaq instruction is identical to the sbaq instruction with
5053 // the exception that the overflow indicator is not affected by the
5054 // sblaq instruction, nor does an overflow fault occur. Operands
5055 // and results are treated as unsigned, positive binary integers.
5056 // C(AQ) - C(Y-pair) -> C(AQ)
5057
5058 L68_ (cpu.ou.cycle |= ou_GOS;)
5059 #if defined(TESTING)
5060 HDBGRegAR ("sblaq");
5061 HDBGRegQR ("sblaq");
5062 #endif
5063 bool ovf;
5064 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
5065
5066 tmp72 = Sub72b (cpup, convert_to_word72 (cpu.rA, cpu.rQ), tmp72, 1,
5067 I_ZNC, & cpu.cu.IR, & ovf);
5068 convert_to_word36 (tmp72, & cpu.rA, & cpu.rQ);
5069 #if defined(TESTING)
5070 HDBGRegAW ("sblaq");
5071 HDBGRegQW ("sblaq");
5072 #endif
5073 }
5074 break;
5075
5076 case x0 (0136): // sblq
5077 {
5078 // C(Q) - C(Y) -> C(Q)
5079 L68_ (cpu.ou.cycle |= ou_GOS;)
5080 #if defined(TESTING)
5081 HDBGRegQR ("sblq");
5082 #endif
5083 bool ovf;
5084 cpu.rQ = Sub36b (cpup, cpu.rQ, cpu.CY, 1, I_ZNC, & cpu.cu.IR, & ovf);
5085 #if defined(TESTING)
5086 HDBGRegQW ("sblq");
5087 #endif
5088 }
5089 break;
5090
5091 // sblxn
5092 case x0 (0120): // sblx0
5093 case x0 (0121): // sblx1
5094 case x0 (0122): // sblx2
5095 case x0 (0123): // sblx3
5096 case x0 (0124): // sblx4
5097 case x0 (0125): // sblx5
5098 case x0 (0126): // sblx6
5099 case x0 (0127): // sblx7
5100 {
5101 // For n = 0, 1, ..., or 7 as determined by operation code
5102 // C(Xn) - C(Y)0,17 -> C(Xn)
5103
5104 L68_ (cpu.ou.cycle |= ou_GOS;)
5105 uint32 n = opcode10 & 07; // get n
5106 #if defined(TESTING)
5107 HDBGRegXR (n, "sblxn");
5108 #endif
5109 bool ovf;
5110 cpu.rX[n] = Sub18b (cpup, cpu.rX[n], GETHI (cpu.CY), 1,
5111 I_ZNC, & cpu.cu.IR, & ovf);
5112 #if defined(TESTING)
5113 HDBGRegXW (n, "sblxn");
5114 #endif
5115 }
5116 break;
5117
5118 case x0 (0176): // sbq
5119 {
5120 // C(Q) - C(Y) -> C(Q)
5121 L68_ (cpu.ou.cycle |= ou_GOS;)
5122 #if defined(TESTING)
5123 HDBGRegQR ("sbq");
5124 #endif
5125 bool ovf;
5126 cpu.rQ = Sub36b (cpup, cpu.rQ, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
5127 #if defined(TESTING)
5128 HDBGRegQW ("sbq");
5129 #endif
5130 overflow (cpup, ovf, false, "sbq overflow fault");
5131 }
5132 break;
5133
5134 // sbxn
5135 case x0 (0160): // sbx0
5136 case x0 (0161): // sbx1
5137 case x0 (0162): // sbx2
5138 case x0 (0163): // sbx3
5139 case x0 (0164): // sbx4
5140 case x0 (0165): // sbx5
5141 case x0 (0166): // sbx6
5142 case x0 (0167): // sbx7
5143 {
5144 // For n = 0, 1, ..., or 7 as determined by operation code
5145 // C(Xn) - C(Y)0,17 -> C(Xn)
5146
5147 L68_ (cpu.ou.cycle |= ou_GOS;)
5148 uint32 n = opcode10 & 07; // get n
5149 #if defined(TESTING)
5150 HDBGRegXR (n, "sbxn");
5151 #endif
5152 bool ovf;
5153 cpu.rX[n] = Sub18b (cpup, cpu.rX[n], GETHI (cpu.CY), 1,
5154 I_ZNOC, & cpu.cu.IR, & ovf);
5155 #if defined(TESTING)
5156 HDBGRegXW (n, "sbxn");
5157 #endif
5158 overflow (cpup, ovf, false, "sbxn overflow fault");
5159 }
5160 break;
5161
5162 case x0 (0155): // ssa
5163 {
5164 // C(A) - C(Y) -> C(Y)
5165
5166 L68_ (cpu.ou.cycle |= ou_GOS;)
5167 #if defined(TESTING)
5168 HDBGRegAR ("ssa");
5169 #endif
5170 bool ovf;
5171 cpu.CY = Sub36b (cpup, cpu.rA, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
5172 overflow (cpup, ovf, true, "ssa overflow fault");
5173 }
5174 break;
5175
5176 case x0 (0156): // ssq
5177 {
5178 // C(Q) - C(Y) -> C(Y)
5179
5180 L68_ (cpu.ou.cycle |= ou_GOS;)
5181 #if defined(TESTING)
5182 HDBGRegQR ("ssq");
5183 #endif
5184 bool ovf;
5185 cpu.CY = Sub36b (cpup, cpu.rQ, cpu.CY, 1, I_ZNOC, & cpu.cu.IR, & ovf);
5186 overflow (cpup, ovf, true, "ssq overflow fault");
5187 }
5188 break;
5189
5190 // ssxn
5191 case x0 (0140): // ssx0
5192 case x0 (0141): // ssx1
5193 case x0 (0142): // ssx2
5194 case x0 (0143): // ssx3
5195 case x0 (0144): // ssx4
5196 case x0 (0145): // ssx5
5197 case x0 (0146): // ssx6
5198 case x0 (0147): // ssx7
5199 {
5200 // For uint32 n = 0, 1, ..., or 7 as determined by operation code
5201 // C(Xn) - C(Y)0,17 -> C(Y)0,17
5202
5203 L68_ (cpu.ou.cycle |= ou_GOS;)
5204 uint32 n = opcode10 & 07; // get n
5205 #if defined(TESTING)
5206 HDBGRegXR (n, "ssxn");
5207 #endif
5208 bool ovf;
5209 word18 tmp18 = Sub18b (cpup, cpu.rX[n], GETHI (cpu.CY), 1,
5210 I_ZNOC, & cpu.cu.IR, & ovf);
5211 SETHI (cpu.CY, tmp18);
5212 overflow (cpup, ovf, true, "ssxn overflow fault");
5213 }
5214 break;
5215
5216 case x0 (0171): // swca
5217 {
5218 // If carry indicator ON, then C(A)- C(Y) -> C(A)
5219 // If carry indicator OFF, then C(A) - C(Y) - 1 -> C(A)
5220
5221 L68_ (cpu.ou.cycle |= ou_GOS;)
5222 #if defined(TESTING)
5223 HDBGRegAR ("swca");
5224 #endif
5225 bool ovf;
5226 cpu.rA = Sub36b (cpup, cpu.rA, cpu.CY, TST_I_CARRY ? 1 : 0,
5227 I_ZNOC, & cpu.cu.IR, & ovf);
5228 #if defined(TESTING)
5229 HDBGRegAW ("swca");
5230 #endif
5231 overflow (cpup, ovf, false, "swca overflow fault");
5232 }
5233 break;
5234
5235 case x0 (0172): // swcq
5236 {
5237 // If carry indicator ON, then C(Q) - C(Y) -> C(Q)
5238 // If carry indicator OFF, then C(Q) - C(Y) - 1 -> C(Q)
5239
5240 L68_ (cpu.ou.cycle |= ou_GOS;)
5241 #if defined(TESTING)
5242 HDBGRegQR ("swcq");
5243 #endif
5244 bool ovf;
5245 cpu.rQ = Sub36b (cpup, cpu.rQ, cpu.CY, TST_I_CARRY ? 1 : 0,
5246 I_ZNOC, & cpu.cu.IR, & ovf);
5247 #if defined(TESTING)
5248 HDBGRegQW ("swcq");
5249 #endif
5250 overflow (cpup, ovf, false, "swcq overflow fault");
5251 }
5252 break;
5253
5254 /// Fixed-Point Multiplication
5255
5256 case x0 (0401): // mpf
5257 {
5258 // C(A) * C(Y) -> C(AQ), left adjusted
5259 //
5260 // Two 36-bit fractional factors (including sign) are multiplied
5261 // to form a 71- bit fractional product (including sign), which
5262 // is stored left-adjusted in the AQ register. AQ71 contains a
5263 // zero. Overflow can occur only in the case of A and Y
5264 // containing negative 1 and the result exceeding the range of
5265 // the AQ register.
5266
5267 L68_ (cpu.ou.cycle |= ou_GD1;)
5268 #if defined(NEED_128)
5269 # if defined(TESTING)
5270 HDBGRegAR ("mpf");
5271 HDBGRegQR ("mpf");
5272 # endif
5273 word72 tmp72 = multiply_128 (SIGNEXT36_72 (cpu.rA), SIGNEXT36_72 (cpu.CY));
5274 tmp72 = and_128 (tmp72, MASK72);
5275 tmp72 = lshift_128 (tmp72, 1);
5276 #else
5277 // word72 tmp72 = SIGNEXT36_72 (cpu.rA) * SIGNEXT36_72 (cpu.CY);
5278 // ubsan
5279 word72 tmp72 = (word72) (((word72s) SIGNEXT36_72 (cpu.rA)) * ((word72s) SIGNEXT36_72 (cpu.CY)));
5280 tmp72 &= MASK72;
5281 tmp72 <<= 1; // left adjust so AQ71 contains 0
5282 #endif
5283 L68_ (cpu.ou.cycle |= ou_GD2;)
5284 // Overflow can occur only in the case of A and Y containing
5285 // negative 1
5286 if (cpu.rA == MAXNEG && cpu.CY == MAXNEG)
5287 {
5288 SET_I_NEG;
5289 CLR_I_ZERO;
5290 overflow (cpup, true, false, "mpf overflow fault");
5291 }
5292
5293 convert_to_word36 (tmp72, &cpu.rA, &cpu.rQ);
5294 #if defined(TESTING)
5295 HDBGRegAW ("mpf");
5296 HDBGRegQW ("mpf");
5297 #endif
5298 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
5299 SC_I_NEG (cpu.rA & SIGN36);
5300 }
5301 break;
5302
5303 case x0 (0402): // mpy
5304 // C(Q) * C(Y) -> C(AQ), right adjusted
5305
5306 {
5307 L68_ (cpu.ou.cycle |= ou_GOS;)
5308 #if defined(NEED_128)
5309 # if defined(TESTING)
5310 HDBGRegQR ("mpy");
5311 # endif
5312 int128 prod = multiply_s128 (
5313 SIGNEXT36_128 (cpu.rQ & DMASK),
5314 SIGNEXT36_128 (cpu.CY & DMASK));
5315 convert_to_word36 (cast_128 (prod), &cpu.rA, &cpu.rQ);
5316 #else
5317 int64_t t0 = SIGNEXT36_64 (cpu.rQ & DMASK);
5318 int64_t t1 = SIGNEXT36_64 (cpu.CY & DMASK);
5319
5320 __int128_t prod = (__int128_t) t0 * (__int128_t) t1;
5321
5322 convert_to_word36 ((word72)prod, &cpu.rA, &cpu.rQ);
5323 #endif
5324 #if defined(TESTING)
5325 HDBGRegAW ("mpy");
5326 HDBGRegQW ("mpy");
5327 #endif
5328
5329 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
5330 SC_I_NEG (cpu.rA & SIGN36);
5331 }
5332 break;
5333
5334 //#define DIV_TRACE
5335
5336 /// Fixed-Point Division
5337
5338 case x0 (0506): // div
5339 // C(Q) / (Y) integer quotient -> C(Q), integer remainder -> C(A)
5340 //
5341 // A 36-bit integer dividend (including sign) is divided by a
5342 // 36-bit integer divisor (including sign) to form a 36-bit integer
5343 // * quotient (including sign) and a 36-bit integer remainder
5344 // * (including sign). The remainder sign is equal to the dividend
5345 // * sign unless the remainder is zero.
5346 // *
5347 // * If the dividend = -2**35 and the divisor = -1 or if the divisor
5348 // * = 0, then division does not take place. Instead, a divide check
5349 // * fault occurs, C(Q) contains the dividend magnitude, and the
5350 // * negative indicator reflects the dividend sign.
5351
5352 L68_ (cpu.ou.cycle |= ou_GD1;)
5353 // RJ78: If the dividend = -2**35 and the divisor = +/-1, or if
5354 // the divisor is 0
5355
5356 #if defined(TESTING)
5357 HDBGRegQR ("div");
5358 #endif
5359 if ((cpu.rQ == MAXNEG && (cpu.CY == 1 || cpu.CY == NEG136)) ||
5360 (cpu.CY == 0))
5361 {
5362 //sim_printf ("DIV Q %012"PRIo64" Y %012"PRIo64"\r\n", cpu.rQ, cpu.CY);
5363 // case 1 400000000000 000000000000 --> 000000000000
5364 // case 2 000000000000 000000000000 --> 400000000000
5365 //cpu.rA = 0; // works for case 1
5366 cpu.rA = (cpu.rQ & SIGN36) ? 0 : SIGN36; // works for case 1,2
5367 #if defined(TESTING)
5368 HDBGRegAW ("div");
5369 #endif
5370
5371 // no division takes place
5372 SC_I_ZERO (cpu.CY == 0);
5373 SC_I_NEG (cpu.rQ & SIGN36);
5374
5375 if (cpu.rQ & SIGN36)
5376 {
5377 // cpu.rQ = (- cpu.rQ) & MASK36;
5378 // ubsan
5379 cpu.rQ = ((word36) (- (word36s) cpu.rQ)) & MASK36;
5380 #if defined(TESTING)
5381 HDBGRegQW ("div");
5382 #endif
5383 }
5384
5385 dlyDoFault (FAULT_DIV,
5386 fst_ill_op,
5387 "div divide check");
5388 }
5389 else
5390 {
5391 t_int64 dividend = (t_int64) (SIGNEXT36_64 (cpu.rQ));
5392 t_int64 divisor = (t_int64) (SIGNEXT36_64 (cpu.CY));
5393 #if defined(TESTING)
5394 # if defined(DIV_TRACE)
5395 sim_debug (DBG_CAC, & cpu_dev, "\r\n");
5396 sim_debug (DBG_CAC, & cpu_dev,
5397 ">>> dividend cpu.rQ %"PRId64" (%012"PRIo64")\r\n",
5398 dividend, cpu.rQ);
5399 sim_debug (DBG_CAC, & cpu_dev,
5400 ">>> divisor CY %"PRId64" (%012"PRIo64")\r\n",
5401 divisor, cpu.CY);
5402 # endif
5403 #endif
5404
5405 t_int64 quotient = dividend / divisor;
5406 L68_ (cpu.ou.cycle |= ou_GD2;)
5407 t_int64 remainder = dividend % divisor;
5408 #if defined(TESTING)
5409 # if defined(DIV_TRACE)
5410 sim_debug (DBG_CAC, & cpu_dev, ">>> quot 1 %"PRId64"\r\n", quotient);
5411 sim_debug (DBG_CAC, & cpu_dev, ">>> rem 1 %"PRId64"\r\n", remainder);
5412 # endif
5413 #endif
5414
5415 // Evidence is that DPS8M rounds toward zero; if it turns out that it
5416 // rounds toward -inf, try this code:
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434 #if defined(TESTING)
5435 # if defined(DIV_TRACE)
5436 // (a/b)*b + a%b is equal to a.
5437 sim_debug (DBG_CAC, & cpu_dev,
5438 "dividend was = %"PRId64"\r\n", dividend);
5439 sim_debug (DBG_CAC, & cpu_dev,
5440 "quotient * divisor + remainder = %"PRId64"\r\n",
5441 quotient * divisor + remainder);
5442 if (dividend != quotient * divisor + remainder)
5443 {
5444 sim_debug (DBG_CAC, & cpu_dev,
5445 "---------------------------------^^^^^^^^^^^^^^^\r\n");
5446 }
5447 # endif
5448 #endif
5449
5450 if (dividend != quotient * divisor + remainder)
5451 {
5452 sim_debug (DBG_ERR, & cpu_dev,
5453 "Internal division error;"
5454 " rQ %012"PRIo64" CY %012"PRIo64"\r\n", cpu.rQ, cpu.CY);
5455 }
5456
5457 cpu.rA = (word36) remainder & DMASK;
5458 cpu.rQ = (word36) quotient & DMASK;
5459 #if defined(TESTING)
5460 HDBGRegAW ("div");
5461 HDBGRegQW ("div");
5462
5463 # if defined(DIV_TRACE)
5464 sim_debug (DBG_CAC, & cpu_dev, "rA (rem) %012"PRIo64"\r\n", cpu.rA);
5465 sim_debug (DBG_CAC, & cpu_dev, "rQ (quot) %012"PRIo64"\r\n", cpu.rQ);
5466 # endif
5467 #endif
5468
5469 SC_I_ZERO (cpu.rQ == 0);
5470 SC_I_NEG (cpu.rQ & SIGN36);
5471 }
5472
5473 break;
5474
5475 case x0 (0507): // dvf
5476 // C(AQ) / (Y)
5477 // fractional quotient -> C(A)
5478 // fractional remainder -> C(Q)
5479
5480 // A 71-bit fractional dividend (including sign) is divided by a
5481 // 36-bit fractional divisor yielding a 36-bit fractional quotient
5482 // (including sign) and a 36-bit fractional remainder (including
5483 // sign). C(AQ)71 is ignored; bit position 35 of the remainder
5484 // corresponds to bit position 70 of the dividend. The remainder
5485 // sign is equal to the dividend sign unless the remainder is zero.
5486
5487 // If | dividend | >= | divisor | or if the divisor = 0, division
5488 // does not take place. Instead, a divide check fault occurs, C(AQ)
5489 // contains the dividend magnitude in absolute, and the negative
5490 // indicator reflects the dividend sign.
5491
5492 dvf (cpup);
5493
5494 break;
5495
5496 /// Fixed-Point Negate
5497
5498 case x0 (0531): // neg
5499 // -C(A) -> C(A) if C(A) != 0
5500
5501 #if defined(TESTING)
5502 HDBGRegAR ("neg");
5503 #endif
5504 cpu.rA &= DMASK;
5505 if (cpu.rA == 0400000000000ULL)
5506 {
5507 CLR_I_ZERO;
5508 SET_I_NEG;
5509 overflow (cpup, true, false, "neg overflow fault");
5510 }
5511
5512 //cpu.rA = -cpu.rA;
5513 // ubsan
5514 cpu.rA = (word36) (- (word36s) cpu.rA);
5515
5516 cpu.rA &= DMASK; // keep to 36-bits
5517 #if defined(TESTING)
5518 HDBGRegAW ("neg");
5519 #endif
5520
5521 SC_I_ZERO (cpu.rA == 0);
5522 SC_I_NEG (cpu.rA & SIGN36);
5523
5524 break;
5525
5526 case x0 (0533): // negl
5527 // -C(AQ) -> C(AQ) if C(AQ) != 0
5528 {
5529 #if defined(TESTING)
5530 HDBGRegAR ("negl");
5531 HDBGRegQR ("negl");
5532 #endif
5533 cpu.rA &= DMASK;
5534 cpu.rQ &= DMASK;
5535
5536 if (cpu.rA == 0400000000000ULL && cpu.rQ == 0)
5537 {
5538 CLR_I_ZERO;
5539 SET_I_NEG;
5540 overflow (cpup, true, false, "negl overflow fault");
5541 }
5542
5543 word72 tmp72 = convert_to_word72 (cpu.rA, cpu.rQ);
5544 #if defined(NEED_128)
5545 tmp72 = negate_128 (tmp72);
5546
5547 SC_I_ZERO (iszero_128 (tmp72));
5548 SC_I_NEG (isnonzero_128 (and_128 (tmp72, SIGN72)));
5549 #else
5550 //tmp72 = -tmp72;
5551 // ubsan
5552 tmp72 = (word72) (-(word72s) tmp72);
5553
5554 SC_I_ZERO (tmp72 == 0);
5555 SC_I_NEG (tmp72 & SIGN72);
5556 #endif
5557
5558 convert_to_word36 (tmp72, &cpu.rA, &cpu.rQ);
5559 #if defined(TESTING)
5560 HDBGRegAW ("negl");
5561 HDBGRegQW ("negl");
5562 #endif
5563 }
5564 break;
5565
5566 /// Fixed-Point Comparison
5567
5568 case x0 (0405): // cmg
5569 // | C(A) | :: | C(Y) |
5570 // Zero: If | C(A) | = | C(Y) | , then ON; otherwise OFF
5571 // Negative: If | C(A) | < | C(Y) | , then ON; otherwise OFF
5572 {
5573 // This is wrong for MAXNEG
5574 //word36 a = cpu.rA & SIGN36 ? -cpu.rA : cpu.rA;
5575 //word36 y = cpu.CY & SIGN36 ? -cpu.CY : cpu.CY;
5576
5577 // If we do the 64 math, the MAXNEG case works
5578 #if defined(TESTING)
5579 HDBGRegAR ("cmg");
5580 #endif
5581 t_int64 a = SIGNEXT36_64 (cpu.rA);
5582 if (a < 0)
5583 a = -a;
5584 t_int64 y = SIGNEXT36_64 (cpu.CY);
5585 if (y < 0)
5586 y = -y;
5587
5588 SC_I_ZERO (a == y);
5589 SC_I_NEG (a < y);
5590 }
5591 break;
5592
5593 case x0 (0211): // cmk
5594 // For i = 0, 1, ..., 35
5595 // C(Z)i = ~C(Q)i & ( C(A)i XOR C(Y)i )
5596
5597 /*
5598 * The cmk instruction compares the contents of bit positions of A
5599 * and Y for identity that are not masked by a 1 in the
5600 * corresponding bit position of Q.
5601 *
5602 * The zero indicator is set ON if the comparison is successful for
5603 * all bit positions; i.e., if for all i = 0, 1, ..., 35 there is
5604 * either: C(A)i = C(Y)i (the identical case) or C(Q)i = 1 (the
5605 * masked case); otherwise, the zero indicator is set OFF.
5606 *
5607 * The negative indicator is set ON if the comparison is
5608 * unsuccessful for bit position 0; i.e., if C(A)0 XOR C(Y)0 (they
5609 * are nonidentical) as well as C(Q)0 = 0 (they are unmasked);
5610 * otherwise, the negative indicator is set OFF.
5611 */
5612 {
5613 #if defined(TESTING)
5614 HDBGRegAR ("cmk");
5615 HDBGRegQR ("cmk");
5616 HDBGRegYR ("cmk");
5617 #endif
5618 word36 Z = ~cpu.rQ & (cpu.rA ^ cpu.CY);
5619 Z &= DMASK;
5620 #if defined(TESTING)
5621 HDBGRegZW (Z, "cmk");
5622 HDBGRegIR ("cmk");
5623 #endif
5624
5625 // Q A Y ~Q A^Y Z
5626 // 0 0 0 1 0 0
5627 // 0 0 1 1 1 1
5628 // 0 1 0 1 1 1
5629 // 0 1 1 1 0 0
5630 // 1 0 0 0 0 0
5631 // 1 0 1 0 1 0
5632 // 1 1 0 0 1 0
5633 // 1 1 1 0 0 0
5634
5635 SC_I_ZERO (Z == 0);
5636 SC_I_NEG (Z & SIGN36);
5637 }
5638 break;
5639
5640 // Optimized to the top of the loop
5641 // case x0 (0115): // cmpa
5642
5643 case x0 (0117): // cmpaq
5644 // C(AQ) :: C(Y-pair)
5645 {
5646 #if defined(TESTING)
5647 HDBGRegAR ("cmpaq");
5648 HDBGRegQR ("cmpaq");
5649 #endif
5650 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
5651 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
5652 #if defined(NEED_128)
5653 trAQ = and_128 (trAQ, MASK72);
5654 #else
5655 trAQ &= MASK72;
5656 #endif
5657 cmp72 (cpup, trAQ, tmp72, &cpu.cu.IR);
5658 }
5659 break;
5660
5661 // Optimized to the top of the loop
5662 // case x0 (0116): // cmpq
5663
5664 // cmpxn
5665 case x0 (0100): // cmpx0
5666 case x0 (0101): // cmpx1
5667 case x0 (0102): // cmpx2
5668 case x0 (0103): // cmpx3
5669 case x0 (0104): // cmpx4
5670 case x0 (0105): // cmpx5
5671 case x0 (0106): // cmpx6
5672 case x0 (0107): // cmpx7
5673 // For n = 0, 1, ..., or 7 as determined by operation code
5674 // C(Xn) :: C(Y)0,17
5675 {
5676 uint32 n = opcode10 & 07; // get n
5677 #if defined(TESTING)
5678 HDBGRegXR (n, "cmpxn");
5679 #endif
5680 cmp18 (cpup, cpu.rX[n], GETHI (cpu.CY), &cpu.cu.IR);
5681 }
5682 break;
5683
5684 case x0 (0111): // cwl
5685 // C(Y) :: closed interval [C(A);C(Q)]
5686 /*
5687 * The cwl instruction tests the value of C(Y) to determine if it
5688 * is within the range of values set by C(A) and C(Q). The
5689 * comparison of C(Y) with C(Q) locates C(Y) with respect to the
5690 * interval if C(Y) is not contained within the interval.
5691 */
5692 #if defined(TESTING)
5693 HDBGRegAR ("cwl");
5694 HDBGRegQR ("cwl");
5695 #endif
5696 cmp36wl (cpup, cpu.rA, cpu.CY, cpu.rQ, &cpu.cu.IR);
5697 break;
5698
5699 /// Fixed-Point Miscellaneous
5700
5701 case x0 (0234): // szn
5702 // Set indicators according to C(Y)
5703 cpu.CY &= DMASK;
5704 SC_I_ZERO (cpu.CY == 0);
5705 SC_I_NEG (cpu.CY & SIGN36);
5706 break;
5707
5708 case x0 (0214): // sznc
5709 // Set indicators according to C(Y)
5710 cpu.CY &= DMASK;
5711 SC_I_ZERO (cpu.CY == 0);
5712 SC_I_NEG (cpu.CY & SIGN36);
5713 // ... and clear
5714 cpu.CY = 0;
5715 break;
5716
5717 /// BOOLEAN OPERATION INSTRUCTIONS
5718
5719 /// Boolean And
5720
5721 // Optimized to the top of the loop
5722 // case x0 (0375): // ana
5723
5724 // Optimized to the top of the loop
5725 // case x0 (0377): //< anaq
5726
5727 case x0 (0376): // anq
5728 // C(Q)i & C(Y)i -> C(Q)i for i = (0, 1, ..., 35)
5729 #if defined(TESTING)
5730 HDBGRegQR ("anq");
5731 #endif
5732 cpu.rQ = cpu.rQ & cpu.CY;
5733 cpu.rQ &= DMASK;
5734 #if defined(TESTING)
5735 HDBGRegQW ("anq");
5736 #endif
5737
5738 SC_I_ZERO (cpu.rQ == 0);
5739 SC_I_NEG (cpu.rQ & SIGN36);
5740 break;
5741
5742 case x0 (0355): // ansa
5743 // C(A)i & C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5744 {
5745 #if defined(TESTING)
5746 HDBGRegAR ("ansa");
5747 #endif
5748 cpu.CY = cpu.rA & cpu.CY;
5749 cpu.CY &= DMASK;
5750
5751 SC_I_ZERO (cpu.CY == 0);
5752 SC_I_NEG (cpu.CY & SIGN36);
5753 }
5754 break;
5755
5756 case x0 (0356): // ansq
5757 // C(Q)i & C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5758 {
5759 #if defined(TESTING)
5760 HDBGRegQR ("ansq");
5761 #endif
5762 cpu.CY = cpu.rQ & cpu.CY;
5763 cpu.CY &= DMASK;
5764
5765 SC_I_ZERO (cpu.CY == 0);
5766 SC_I_NEG (cpu.CY & SIGN36);
5767 }
5768 break;
5769
5770 // ansxn
5771 case x0 (0340): // ansx0
5772 case x0 (0341): // ansx1
5773 case x0 (0342): // ansx2
5774 case x0 (0343): // ansx3
5775 case x0 (0344): // ansx4
5776 case x0 (0345): // ansx5
5777 case x0 (0346): // ansx6
5778 case x0 (0347): // ansx7
5779 // For n = 0, 1, ..., or 7 as determined by operation code
5780 // C(Xn)i & C(Y)i -> C(Y)i for i = (0, 1, ..., 17)
5781 {
5782 uint32 n = opcode10 & 07; // get n
5783 #if defined(TESTING)
5784 HDBGRegXR (n, "ansxn");
5785 #endif
5786 word18 tmp18 = cpu.rX[n] & GETHI (cpu.CY);
5787 tmp18 &= MASK18;
5788
5789 SC_I_ZERO (tmp18 == 0);
5790 SC_I_NEG (tmp18 & SIGN18);
5791
5792 SETHI (cpu.CY, tmp18);
5793 }
5794
5795 break;
5796
5797 // anxn
5798 case x0 (0360): // anx0
5799 case x0 (0361): // anx1
5800 case x0 (0362): // anx2
5801 case x0 (0363): // anx3
5802 case x0 (0364): // anx4
5803 case x0 (0365): // anx5
5804 case x0 (0366): // anx6
5805 case x0 (0367): // anx7
5806 // For n = 0, 1, ..., or 7 as determined by operation code
5807 // C(Xn)i & C(Y)i -> C(Xn)i for i = (0, 1, ..., 17)
5808 {
5809 uint32 n = opcode10 & 07; // get n
5810 #if defined(TESTING)
5811 HDBGRegXR (n, "anxn");
5812 #endif
5813 cpu.rX[n] &= GETHI (cpu.CY);
5814 cpu.rX[n] &= MASK18;
5815 #if defined(TESTING)
5816 HDBGRegXW (n, "anxn");
5817 #endif
5818
5819 SC_I_ZERO (cpu.rX[n] == 0);
5820 SC_I_NEG (cpu.rX[n] & SIGN18);
5821 }
5822 break;
5823
5824 /// Boolean Or
5825
5826 // Optimized to the top of the loop
5827 // case x0 (0275): // ora
5828
5829 case x0 (0277): // oraq
5830 // C(AQ)i | C(Y-pair)i -> C(AQ)i for i = (0, 1, ..., 71)
5831 {
5832 #if defined(TESTING)
5833 HDBGRegAR ("oraq");
5834 HDBGRegQR ("oraq");
5835 #endif
5836 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
5837 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
5838 #if defined(NEED_128)
5839 trAQ = or_128 (trAQ, tmp72);
5840 trAQ = and_128 (trAQ, MASK72);
5841
5842 SC_I_ZERO (iszero_128 (trAQ));
5843 SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
5844 #else
5845 trAQ = trAQ | tmp72;
5846 trAQ &= MASK72;
5847
5848 SC_I_ZERO (trAQ == 0);
5849 SC_I_NEG (trAQ & SIGN72);
5850 #endif
5851 convert_to_word36 (trAQ, &cpu.rA, &cpu.rQ);
5852 #if defined(TESTING)
5853 HDBGRegAW ("oraq");
5854 HDBGRegQW ("oraq");
5855 #endif
5856 }
5857 break;
5858
5859 case x0 (0276): // orq
5860 // C(Q)i | C(Y)i -> C(Q)i for i = (0, 1, ..., 35)
5861 #if defined(TESTING)
5862 HDBGRegQR ("orq");
5863 #endif
5864 cpu.rQ = cpu.rQ | cpu.CY;
5865 cpu.rQ &= DMASK;
5866 #if defined(TESTING)
5867 HDBGRegQW ("orq");
5868 #endif
5869
5870 SC_I_ZERO (cpu.rQ == 0);
5871 SC_I_NEG (cpu.rQ & SIGN36);
5872
5873 break;
5874
5875 case x0 (0255): // orsa
5876 // C(A)i | C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5877 #if defined(TESTING)
5878 HDBGRegAR ("orsa");
5879 #endif
5880 cpu.CY = cpu.rA | cpu.CY;
5881 cpu.CY &= DMASK;
5882
5883 SC_I_ZERO (cpu.CY == 0);
5884 SC_I_NEG (cpu.CY & SIGN36);
5885 break;
5886
5887 case x0 (0256): // orsq
5888 // C(Q)i | C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5889 #if defined(TESTING)
5890 HDBGRegQR ("orsq");
5891 #endif
5892 cpu.CY = cpu.rQ | cpu.CY;
5893 cpu.CY &= DMASK;
5894
5895 SC_I_ZERO (cpu.CY == 0);
5896 SC_I_NEG (cpu.CY & SIGN36);
5897 break;
5898
5899 // orsxn
5900 case x0 (0240): // orsx0
5901 case x0 (0241): // orsx1
5902 case x0 (0242): // orsx2
5903 case x0 (0243): // orsx3
5904 case x0 (0244): // orsx4
5905 case x0 (0245): // orsx5
5906 case x0 (0246): // orsx6
5907 case x0 (0247): // orsx7
5908 // For n = 0, 1, ..., or 7 as determined by operation code
5909 // C(Xn)i | C(Y)i -> C(Y)i for i = (0, 1, ..., 17)
5910 {
5911 uint32 n = opcode10 & 07; // get n
5912
5913 word18 tmp18 = cpu.rX[n] | GETHI (cpu.CY);
5914 tmp18 &= MASK18;
5915
5916 SC_I_ZERO (tmp18 == 0);
5917 SC_I_NEG (tmp18 & SIGN18);
5918
5919 SETHI (cpu.CY, tmp18);
5920 }
5921 break;
5922
5923 // orxn
5924 case x0 (0260): // orx0
5925 case x0 (0261): // orx1
5926 case x0 (0262): // orx2
5927 case x0 (0263): // orx3
5928 case x0 (0264): // orx4
5929 case x0 (0265): // orx5
5930 case x0 (0266): // orx6
5931 case x0 (0267): // orx7
5932 // For n = 0, 1, ..., or 7 as determined by operation code
5933 // C(Xn)i | C(Y)i -> C(Xn)i for i = (0, 1, ..., 17)
5934 {
5935 uint32 n = opcode10 & 07; // get n
5936 #if defined(TESTING)
5937 HDBGRegXR (n, "orxn");
5938 #endif
5939 cpu.rX[n] |= GETHI (cpu.CY);
5940 cpu.rX[n] &= MASK18;
5941 #if defined(TESTING)
5942 HDBGRegXW (n, "orxn");
5943 #endif
5944
5945 SC_I_ZERO (cpu.rX[n] == 0);
5946 SC_I_NEG (cpu.rX[n] & SIGN18);
5947 }
5948 break;
5949
5950 /// Boolean Exclusive Or
5951
5952 case x0 (0675): // era
5953 // C(A)i XOR C(Y)i -> C(A)i for i = (0, 1, ..., 35)
5954 #if defined(TESTING)
5955 HDBGRegAR ("era");
5956 #endif
5957 cpu.rA = cpu.rA ^ cpu.CY;
5958 cpu.rA &= DMASK;
5959 #if defined(TESTING)
5960 HDBGRegAW ("era");
5961 #endif
5962
5963 SC_I_ZERO (cpu.rA == 0);
5964 SC_I_NEG (cpu.rA & SIGN36);
5965
5966 break;
5967
5968 // Optimized to the top of the loop
5969 // case x0 (0677): // eraq
5970
5971 case x0 (0676): // erq
5972 // C(Q)i XOR C(Y)i -> C(Q)i for i = (0, 1, ..., 35)
5973 #if defined(TESTING)
5974 HDBGRegQR ("eraq");
5975 #endif
5976 cpu.rQ = cpu.rQ ^ cpu.CY;
5977 cpu.rQ &= DMASK;
5978 #if defined(TESTING)
5979 HDBGRegQW ("eraq");
5980 #endif
5981 SC_I_ZERO (cpu.rQ == 0);
5982 SC_I_NEG (cpu.rQ & SIGN36);
5983 break;
5984
5985 case x0 (0655): // ersa
5986 // C(A)i XOR C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5987 #if defined(TESTING)
5988 HDBGRegAR ("ersa");
5989 #endif
5990 cpu.CY = cpu.rA ^ cpu.CY;
5991 cpu.CY &= DMASK;
5992
5993 SC_I_ZERO (cpu.CY == 0);
5994 SC_I_NEG (cpu.CY & SIGN36);
5995 break;
5996
5997 case x0 (0656): // ersq
5998 // C(Q)i XOR C(Y)i -> C(Y)i for i = (0, 1, ..., 35)
5999 #if defined(TESTING)
6000 HDBGRegQR ("ersq");
6001 #endif
6002 cpu.CY = cpu.rQ ^ cpu.CY;
6003 cpu.CY &= DMASK;
6004
6005 SC_I_ZERO (cpu.CY == 0);
6006 SC_I_NEG (cpu.CY & SIGN36);
6007
6008 break;
6009
6010 // ersxn
6011 case x0 (0640): // ersx0
6012 case x0 (0641): // ersx1
6013 case x0 (0642): // ersx2
6014 case x0 (0643): // ersx3
6015 case x0 (0644): // ersx4
6016 case x0 (0645): // ersx5
6017 case x0 (0646): // ersx6
6018 case x0 (0647): // ersx7
6019 // For n = 0, 1, ..., or 7 as determined by operation code
6020 // C(Xn)i XOR C(Y)i -> C(Y)i for i = (0, 1, ..., 17)
6021 {
6022 uint32 n = opcode10 & 07; // get n
6023 #if defined(TESTING)
6024 HDBGRegXR (n, "ersxn");
6025 #endif
6026
6027 word18 tmp18 = cpu.rX[n] ^ GETHI (cpu.CY);
6028 tmp18 &= MASK18;
6029
6030 SC_I_ZERO (tmp18 == 0);
6031 SC_I_NEG (tmp18 & SIGN18);
6032
6033 SETHI (cpu.CY, tmp18);
6034 }
6035 break;
6036
6037 // erxn
6038 case x0 (0660): // erx0
6039 case x0 (0661): // erx1
6040 case x0 (0662): // erx2
6041 case x0 (0663): // erx3
6042 case x0 (0664): // erx4
6043 case x0 (0665): // erx5
6044 case x0 (0666): // erx6 !!!! Beware !!!!
6045 case x0 (0667): // erx7
6046 // For n = 0, 1, ..., or 7 as determined by operation code
6047 // C(Xn)i XOR C(Y)i -> C(Xn)i for i = (0, 1, ..., 17)
6048 {
6049 uint32 n = opcode10 & 07; // get n
6050 #if defined(TESTING)
6051 HDBGRegXR (n, "erxn");
6052 #endif
6053 cpu.rX[n] ^= GETHI (cpu.CY);
6054 cpu.rX[n] &= MASK18;
6055 #if defined(TESTING)
6056 HDBGRegXW (n, "erxn");
6057 #endif
6058
6059 SC_I_ZERO (cpu.rX[n] == 0);
6060 SC_I_NEG (cpu.rX[n] & SIGN18);
6061 }
6062 break;
6063
6064 /// Boolean Comparative And
6065
6066 // Optimized to the top of the loop
6067 // case x0 (0315): // cana
6068
6069 case x0 (0317): // canaq
6070 // C(Z)i = C(AQ)i & C(Y-pair)i for i = (0, 1, ..., 71)
6071 {
6072 #if defined(TESTING)
6073 HDBGRegAR ("canaq");
6074 HDBGRegQR ("canaq");
6075 #endif
6076 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
6077 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
6078 #if defined(NEED_128)
6079 trAQ = and_128 (trAQ, tmp72);
6080 trAQ = and_128 (trAQ, MASK72);
6081
6082 SC_I_ZERO (iszero_128 (trAQ));
6083 SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
6084 #else
6085 trAQ = trAQ & tmp72;
6086 trAQ &= MASK72;
6087
6088 SC_I_ZERO (trAQ == 0);
6089 SC_I_NEG (trAQ & SIGN72);
6090 #endif
6091 }
6092 break;
6093
6094 case x0 (0316): // canq
6095 // C(Z)i = C(Q)i & C(Y)i for i = (0, 1, ..., 35)
6096 {
6097 #if defined(TESTING)
6098 HDBGRegQR ("canq");
6099 #endif
6100 word36 trZ = cpu.rQ & cpu.CY;
6101 trZ &= DMASK;
6102
6103 SC_I_ZERO (trZ == 0);
6104 SC_I_NEG (trZ & SIGN36);
6105 }
6106 break;
6107
6108 // canxn
6109 case x0 (0300): // canx0
6110 case x0 (0301): // canx1
6111 case x0 (0302): // canx2
6112 case x0 (0303): // canx3
6113 case x0 (0304): // canx4
6114 case x0 (0305): // canx5
6115 case x0 (0306): // canx6
6116 case x0 (0307): // canx7
6117 // For n = 0, 1, ..., or 7 as determined by operation code
6118 // C(Z)i = C(Xn)i & C(Y)i for i = (0, 1, ..., 17)
6119 {
6120 uint32 n = opcode10 & 07; // get n
6121 #if defined(TESTING)
6122 HDBGRegXR (n, "canxn");
6123 #endif
6124 word18 tmp18 = cpu.rX[n] & GETHI (cpu.CY);
6125 tmp18 &= MASK18;
6126 sim_debug (DBG_TRACEEXT, & cpu_dev,
6127 "n %o rX %06o HI %06o tmp %06o\r\n",
6128 n, cpu.rX[n], (word18) (GETHI (cpu.CY) & MASK18),
6129 tmp18);
6130
6131 SC_I_ZERO (tmp18 == 0);
6132 SC_I_NEG (tmp18 & SIGN18);
6133 }
6134 break;
6135
6136 /// Boolean Comparative Not
6137
6138 case x0 (0215): // cnaa
6139 // C(Z)i = C(A)i & ~C(Y)i for i = (0, 1, ..., 35)
6140 {
6141 #if defined(TESTING)
6142 HDBGRegAR ("cnaa");
6143 #endif
6144 word36 trZ = cpu.rA & ~cpu.CY;
6145 trZ &= DMASK;
6146
6147 SC_I_ZERO (trZ == 0);
6148 SC_I_NEG (trZ & SIGN36);
6149 }
6150 break;
6151
6152 case x0 (0217): // cnaaq
6153 // C(Z)i = C (AQ)i & ~C(Y-pair)i for i = (0, 1, ..., 71)
6154 {
6155 #if defined(TESTING)
6156 HDBGRegAR ("cnaaq");
6157 HDBGRegQR ("cnaaq");
6158 #endif
6159 word72 tmp72 = YPAIRTO72 (cpu.Ypair);
6160
6161 word72 trAQ = convert_to_word72 (cpu.rA, cpu.rQ);
6162 #if defined(NEED_128)
6163 trAQ = and_128 (trAQ, complement_128 (tmp72));
6164 trAQ = and_128 (trAQ, MASK72);
6165
6166 SC_I_ZERO (iszero_128 (trAQ));
6167 SC_I_NEG (isnonzero_128 (and_128 (trAQ, SIGN72)));
6168 #else
6169 trAQ = trAQ & ~tmp72;
6170 trAQ &= MASK72;
6171
6172 SC_I_ZERO (trAQ == 0);
6173 SC_I_NEG (trAQ & SIGN72);
6174 #endif
6175 }
6176 break;
6177
6178 case x0 (0216): // cnaq
6179 // C(Z)i = C(Q)i & ~C(Y)i for i = (0, 1, ..., 35)
6180 {
6181 #if defined(TESTING)
6182 HDBGRegQR ("cnaq");
6183 #endif
6184 word36 trZ = cpu.rQ & ~cpu.CY;
6185 trZ &= DMASK;
6186 SC_I_ZERO (trZ == 0);
6187 SC_I_NEG (trZ & SIGN36);
6188 }
6189 break;
6190
6191 // cnaxn
6192 case x0 (0200): // cnax0
6193 case x0 (0201): // cnax1
6194 case x0 (0202): // cnax2
6195 case x0 (0203): // cnax3
6196 case x0 (0204): // cnax4
6197 case x0 (0205): // cnax5
6198 case x0 (0206): // cnax6
6199 case x0 (0207): // cnax7
6200 // C(Z)i = C(Xn)i & ~C(Y)i for i = (0, 1, ..., 17)
6201 {
6202 uint32 n = opcode10 & 07; // get n
6203 #if defined(TESTING)
6204 HDBGRegXR (n, "cnaxn");
6205 #endif
6206 word18 tmp18 = cpu.rX[n] & ~GETHI (cpu.CY);
6207 tmp18 &= MASK18;
6208
6209 SC_I_ZERO (tmp18 == 0);
6210 SC_I_NEG (tmp18 & SIGN18);
6211 }
6212 break;
6213
6214 /// FLOATING-POINT ARITHMETIC INSTRUCTIONS
6215
6216 /// Floating-Point Data Movement Load
6217
6218 case x0 (0433): // dfld
6219 // C(Y-pair)0,7 -> C(E)
6220 // C(Y-pair)8,71 -> C(AQ)0,63
6221 // 00...0 -> C(AQ)64,71
6222 // Zero: If C(AQ) = 0, then ON; otherwise OFF
6223 // Neg: If C(AQ)0 = 1, then ON; otherwise OFF
6224
6225 CPTUR (cptUseE);
6226 cpu.rE = (cpu.Ypair[0] >> 28) & MASK8;
6227
6228 cpu.rA = (cpu.Ypair[0] & FLOAT36MASK) << 8;
6229 cpu.rA |= (cpu.Ypair[1] >> 28) & MASK8;
6230
6231 cpu.rQ = (cpu.Ypair[1] & FLOAT36MASK) << 8;
6232
6233 #if defined(TESTING)
6234 HDBGRegAW ("dfld");
6235 HDBGRegQW ("dfld");
6236 #endif
6237
6238 SC_I_ZERO (cpu.rA == 0 && cpu.rQ == 0);
6239 SC_I_NEG (cpu.rA & SIGN36);
6240 break;
6241
6242 // Optimized to the top of the loop
6243 // case x0 (0431): // fld
6244
6245 /// Floating-Point Data Movement Store
6246
6247 case x0 (0457): // dfst
6248 // C(E) -> C(Y-pair)0,7
6249 // C(AQ)0,63 -> C(Y-pair)8,71
6250
6251 CPTUR (cptUseE);
6252 #if defined(TESTING)
6253 HDBGRegAR ("dfst");
6254 HDBGRegQR ("dfst");
6255 #endif
6256 cpu.Ypair[0] = ((word36)cpu.rE << 28) |
6257 ((cpu.rA & 0777777777400LLU) >> 8);
6258 cpu.Ypair[1] = ((cpu.rA & 0377) << 28) |
6259 ((cpu.rQ & 0777777777400LLU) >> 8);
6260
6261 break;
6262
6263 case x0 (0472): // dfstr
6264
6265 dfstr (cpup, cpu.Ypair);
6266 break;
6267
6268 case x0 (0455): // fst
6269 // C(E) -> C(Y)0,7
6270 // C(A)0,27 -> C(Y)8,35
6271 CPTUR (cptUseE);
6272 #if defined(TESTING)
6273 HDBGRegAR ("fst");
6274 #endif
6275 cpu.rE &= MASK8;
6276 cpu.rA &= DMASK;
6277 cpu.CY = ((word36)cpu.rE << 28) | (((cpu.rA >> 8) & 01777777777LL));
6278 break;
6279
6280 case x0 (0470): // fstr
6281 // The fstr instruction performs a true round and normalization on
6282 // C(EAQ) as it is stored.
6283
6284 // frd ();
6285 //
6286 // // C(E) -> C(Y)0,7
6287 // // C(A)0,27 -> C(Y)8,35
6288 // cpu.CY = ((word36)cpu.rE << 28) |
6289 // (((cpu.rA >> 8) & 01777777777LL));
6290 //
6291 // // Zero: If C(Y) = floating point 0, then ON; otherwise OFF
6292 // //SC_I_ZERO ((cpu.CY & 01777777777LL) == 0);
6293 // bool isZero = cpu.rE == -128 && cpu.rA == 0;
6294 // SC_I_ZERO (isZero);
6295 //
6296 // // Neg: If C(Y)8 = 1, then ON; otherwise OFF
6297 // //SC_I_NEG (cpu.CY & 01000000000LL);
6298 // SC_I_NEG (cpu.rA & SIGN36);
6299 //
6300 // // Exp Ovr: If exponent is greater than +127, then ON
6301 // // Exp Undr: If exponent is less than -128, then ON
6302 // // XXX: not certain how these can occur here ....
6303
6304 fstr (cpup, &cpu.CY);
6305
6306 break;
6307
6308 /// Floating-Point Addition
6309
6310 case x0 (0477): // dfad
6311 // The dfad instruction may be thought of as a dufa instruction
6312 // followed by a fno instruction.
6313
6314 CPTUR (cptUseE);
6315 #if defined(TESTING)
6316 HDBGRegAR ("dfad");
6317 HDBGRegQR ("dfad");
6318 #endif
6319 dufa (cpup, false, true);
6320 #if defined(TESTING)
6321 HDBGRegAW ("dfad");
6322 HDBGRegQW ("dfad");
6323 #endif
6324 break;
6325
6326 case x0 (0437): // dufa
6327 dufa (cpup, false, false);
6328 break;
6329
6330 case x0 (0475): // fad
6331 // The fad instruction may be thought of a an ufa instruction
6332 // followed by a fno instruction.
6333 // (Heh, heh. We'll see....)
6334
6335 CPTUR (cptUseE);
6336 #if defined(TESTING)
6337 HDBGRegAR ("fad");
6338 HDBGRegQR ("fad");
6339 #endif
6340 ufa (cpup, false, true);
6341 #if defined(TESTING)
6342 HDBGRegAW ("fad");
6343 HDBGRegQW ("fad");
6344 #endif
6345
6346 break;
6347
6348 case x0 (0435): // ufa
6349 // C(EAQ) + C(Y) -> C(EAQ)
6350
6351 ufa (cpup, false, false);
6352 break;
6353
6354 /// Floating-Point Subtraction
6355
6356 case x0 (0577): // dfsb
6357 // The dfsb instruction is identical to the dfad instruction with
6358 // the exception that the twos complement of the mantissa of the
6359 // operand from main memory is used.
6360
6361 CPTUR (cptUseE);
6362 #if defined(TESTING)
6363 HDBGRegAR ("dfsb");
6364 HDBGRegQR ("dfsb");
6365 #endif
6366 dufa (cpup, true, true);
6367 #if defined(TESTING)
6368 HDBGRegAW ("dfsb");
6369 HDBGRegQW ("dfsb");
6370 #endif
6371 break;
6372
6373 case x0 (0537): // dufs
6374 dufa (cpup, true, false);
6375 break;
6376
6377 case x0 (0575): // fsb
6378 // The fsb instruction may be thought of as an ufs instruction
6379 // followed by a fno instruction.
6380 #if defined(TESTING)
6381 HDBGRegAR ("fsb");
6382 HDBGRegQR ("fsb");
6383 #endif
6384 CPTUR (cptUseE);
6385 ufa (cpup, true, true);
6386 #if defined(TESTING)
6387 HDBGRegAW ("fsb");
6388 HDBGRegQW ("fsb");
6389 #endif
6390 break;
6391
6392 case x0 (0535): // ufs
6393 // C(EAQ) - C(Y) -> C(EAQ)
6394 ufa (cpup, true, false);
6395 break;
6396
6397 /// Floating-Point Multiplication
6398
6399 case x0 (0463): // dfmp
6400 // The dfmp instruction may be thought of as a dufm instruction
6401 // followed by a fno instruction.
6402
6403 CPTUR (cptUseE);
6404 #if defined(TESTING)
6405 HDBGRegAR ("dfmp");
6406 HDBGRegQR ("dfmp");
6407 #endif
6408 dufm (cpup, true);
6409 #if defined(TESTING)
6410 HDBGRegAW ("dfmp");
6411 HDBGRegQW ("dfmp");
6412 #endif
6413 break;
6414
6415 case x0 (0423): // dufm
6416
6417 dufm (cpup, false);
6418 break;
6419
6420 case x0 (0461): // fmp
6421 // The fmp instruction may be thought of as a ufm instruction
6422 // followed by a fno instruction.
6423
6424 CPTUR (cptUseE);
6425 ufm (cpup, true);
6426 #if defined(TESTING)
6427 HDBGRegAW ("fmp");
6428 HDBGRegQW ("fmp");
6429 #endif
6430 break;
6431
6432 case x0 (0421): // ufm
6433 // C(EAQ)* C(Y) -> C(EAQ)
6434 ufm (cpup, false);
6435 break;
6436
6437 /// Floating-Point Division
6438
6439 case x0 (0527): // dfdi
6440
6441 dfdi (cpup);
6442 break;
6443
6444 case x0 (0567): // dfdv
6445
6446 dfdv (cpup);
6447 break;
6448
6449 case x0 (0525): // fdi
6450 // C(Y) / C(EAQ) -> C(EA)
6451
6452 fdi (cpup);
6453 break;
6454
6455 case x0 (0565): // fdv
6456 // C(EAQ) /C(Y) -> C(EA)
6457 // 00...0 -> C(Q)
6458 fdv (cpup);
6459 break;
6460
6461 /// Floating-Point Negation
6462
6463 case x0 (0513): // fneg
6464 // -C(EAQ) normalized -> C(EAQ)
6465 fneg (cpup);
6466 break;
6467
6468 /// Floating-Point Normalize
6469
6470 case x0 (0573): // fno
6471 // The fno instruction normalizes the number in C(EAQ) if C(AQ)
6472 // != 0 and the overflow indicator is OFF.
6473 //
6474 // A normalized floating number is defined as one whose mantissa
6475 // lies in the interval [0.5,1.0) such that 0.5<= |C(AQ)| <1.0
6476 // which, in turn, requires that C(AQ)0 != C(AQ)1.list
6477 //
6478 // !!!! For personal reasons the following 3 lines of comment must
6479 // never be removed from this program or any code derived
6480 // there from. HWR 25 Aug 2014
6481 ///Charles Is the coolest
6482 ///true story y'all
6483 //you should get me darksisers 2 for christmas
6484
6485 CPTUR (cptUseE);
6486 fno (cpup, & cpu.rE, & cpu.rA, & cpu.rQ);
6487 #if defined(TESTING)
6488 HDBGRegAW ("fno");
6489 HDBGRegQW ("fno");
6490 #endif
6491 break;
6492
6493 /// Floating-Point Round
6494
6495 case x0 (0473): // dfrd
6496 // C(EAQ) rounded to 64 bits -> C(EAQ)
6497 // 0 -> C(AQ)64,71 (See notes in dps8_math.c on dfrd())
6498
6499 dfrd (cpup);
6500 break;
6501
6502 case x0 (0471): // frd
6503 // C(EAQ) rounded to 28 bits -> C(EAQ)
6504 // 0 -> C(AQ)28,71 (See notes in dps8_math.c on frd())
6505
6506 frd (cpup);
6507 break;
6508
6509 /// Floating-Point Compare
6510
6511 case x0 (0427): // dfcmg
6512 // C(E) :: C(Y-pair)0,7
6513 // | C(AQ)0,63 | :: | C(Y-pair)8,71 |
6514
6515 dfcmg (cpup);
6516 break;
6517
6518 case x0 (0517): // dfcmp
6519 // C(E) :: C(Y-pair)0,7
6520 // C(AQ)0,63 :: C(Y-pair)8,71
6521
6522 dfcmp (cpup);
6523 break;
6524
6525 case x0 (0425): // fcmg
6526 // C(E) :: C(Y)0,7
6527 // | C(AQ)0,27 | :: | C(Y)8,35 |
6528
6529 fcmg (cpup);
6530 break;
6531
6532 case x0 (0515): // fcmp
6533 // C(E) :: C(Y)0,7
6534 // C(AQ)0,27 :: C(Y)8,35
6535
6536 fcmp (cpup);
6537 break;
6538
6539 /// Floating-Point Miscellaneous
6540
6541 case x0 (0415): // ade
6542 // C(E) + C(Y)0,7 -> C(E)
6543 {
6544 CPTUR (cptUseE);
6545 int y = SIGNEXT8_int ((cpu.CY >> 28) & 0377);
6546 int e = SIGNEXT8_int (cpu.rE);
6547 e = e + y;
6548
6549 cpu.rE = e & 0377;
6550 CLR_I_ZERO;
6551 CLR_I_NEG;
6552
6553 if (e > 127)
6554 {
6555 SET_I_EOFL;
6556 if (tstOVFfault (cpup))
6557 doFault (FAULT_OFL, fst_zero, "ade exp overflow fault");
6558 }
6559
6560 if (e < -128)
6561 {
6562 SET_I_EUFL;
6563 if (tstOVFfault (cpup))
6564 doFault (FAULT_OFL, fst_zero, "ade exp underflow fault");
6565 }
6566 }
6567 break;
6568
6569 case x0 (0430): // fszn
6570
6571 // Zero: If C(Y)8,35 = 0, then ON; otherwise OFF
6572 // Negative: If C(Y)8 = 1, then ON; otherwise OFF
6573
6574 SC_I_ZERO ((cpu.CY & 001777777777LL) == 0);
6575 SC_I_NEG (cpu.CY & 001000000000LL);
6576
6577 break;
6578
6579 case x0 (0411): // lde
6580 // C(Y)0,7 -> C(E)
6581
6582 CPTUR (cptUseE);
6583 cpu.rE = (cpu.CY >> 28) & 0377;
6584 CLR_I_ZERO;
6585 CLR_I_NEG;
6586
6587 break;
6588
6589 case x0 (0456): // ste
6590 // C(E) -> C(Y)0,7
6591 // 00...0 -> C(Y)8,17
6592
6593 CPTUR (cptUseE);
6594 //putbits36_18 (& cpu.CY, 0, ((word18) (cpu.rE & 0377) << 10));
6595 cpu.CY = ((word36) (cpu.rE & 0377)) << 28;
6596 cpu.zone = 0777777000000;
6597 cpu.useZone = true;
6598 break;
6599
6600 /// TRANSFER INSTRUCTIONS
6601
6602 case x0 (0713): // call6
6603
6604 CPTUR (cptUsePRn + 7);
6605
6606 do_caf (cpup);
6607 read_tra_op (cpup);
6608 sim_debug (DBG_TRACEEXT, & cpu_dev,
6609 "call6 PRR %o PSR %o\r\n", cpu.PPR.PRR, cpu.PPR.PSR);
6610
6611 return CONT_TRA;
6612
6613 case x0 (0630): // ret
6614 {
6615 // Parity mask: If C(Y)27 = 1, and the processor is in absolute or
6616 // mask privileged mode, then ON; otherwise OFF. This indicator is
6617 // not affected in the normal or BAR modes.
6618 // Not BAR mode: Can be set OFF but not ON by the ret instruction
6619 // Absolute mode: Can be set OFF but not ON by the ret instruction
6620 // All other indicators: If corresponding bit in C(Y) is 1, then ON;
6621 // otherwise, OFF
6622
6623 // C(Y)0,17 -> C(PPR.IC)
6624 // C(Y)18,31 -> C(IR)
6625 do_caf (cpup);
6626 ReadOperandRead (cpup, cpu.TPR.CA, & cpu.CY);
6627
6628 cpu.PPR.IC = GETHI (cpu.CY);
6629 word18 tempIR = GETLO (cpu.CY) & 0777770;
6630 // Assuming 'mask privileged mode' is 'temporary absolute mode'
6631 if (is_priv_mode (cpup)) // abs. or temp. abs. or priv.
6632 {
6633 // if abs, copy existing parity mask to tempIR
6634 // According to ISOLTS pm785, not the case.
6635 //SCF (TST_I_PMASK, tempIR, I_PMASK);
6636 // MIF comes from C(Y)30 like the other indicators (AL39
6637 // "All other indicators"); it used to be kept from the
6638 // current IR. PM842 16A/17A: the TRO handler returns with
6639 // RET to an interrupted SCD, which must resume from the
6640 // decimal unit (MIF on), not start over.
6641 }
6642 else
6643 {
6644 CLRF (tempIR, I_MIF);
6645 }
6646 // can be set OFF but not on
6647 // IR ret result
6648 // off off off
6649 // off on off
6650 // on on on
6651 // on off off
6652 // "If it was on, set it to on"
6653 //SCF (TST_I_NBAR, tempIR, I_NBAR);
6654 if (! (TST_I_NBAR && TSTF (tempIR, I_NBAR)))
6655 {
6656 CLRF (tempIR, I_NBAR);
6657 }
6658 if (! (TST_I_ABS && TSTF (tempIR, I_ABS)))
6659 {
6660 CLRF (tempIR, I_ABS);
6661 }
6662
6663 //sim_debug (DBG_TRACEEXT, & cpu_dev,
6664 // "RET NBAR was %d now %d\r\n",
6665 // TST_NBAR ? 1 : 0,
6666 // TSTF (tempIR, I_NBAR) ? 1 : 0);
6667 //sim_debug (DBG_TRACEEXT, & cpu_dev,
6668 // "RET ABS was %d now %d\r\n",
6669 // TST_I_ABS ? 1 : 0,
6670 // TSTF (tempIR, I_ABS) ? 1 : 0);
6671 CPTUR (cptUseIR);
6672 cpu.cu.IR = tempIR;
6673 return CONT_RET;
6674 }
6675
6676 // Optimized to the top of the loop
6677 // case x0 (0610): // rtcd
6678
6679 case x0 (0614): // teo
6680 // If exponent overflow indicator ON then
6681 // C(TPR.CA) -> C(PPR.IC)
6682 // C(TPR.TSR) -> C(PPR.PSR)
6683 // otherwise, no change to C(PPR)
6684 if (TST_I_EOFL)
6685 {
6686 CLR_I_EOFL;
6687 do_caf (cpup);
6688 read_tra_op (cpup);
6689 return CONT_TRA;
6690 }
6691 break;
6692
6693 case x0 (0615): // teu
6694 // If exponent underflow indicator ON then
6695 // C(TPR.CA) -> C(PPR.IC)
6696 // C(TPR.TSR) -> C(PPR.PSR)
6697 if (TST_I_EUFL)
6698 {
6699 CLR_I_EUFL;
6700 do_caf (cpup);
6701 read_tra_op (cpup);
6702 return CONT_TRA;
6703 }
6704 break;
6705
6706 // Optimized to the top of the loop
6707 // case x0 (0604): // tmi
6708
6709 // Optimized to the top of the loop
6710 // case x1 (0604): // tmoz
6711
6712 case x0 (0602): // tnc
6713 // If carry indicator OFF then
6714 // C(TPR.CA) -> C(PPR.IC)
6715 // C(TPR.TSR) -> C(PPR.PSR)
6716 if (!TST_I_CARRY)
6717 {
6718 do_caf (cpup);
6719 read_tra_op (cpup);
6720 return CONT_TRA;
6721 }
6722 break;
6723
6724 // Optimized to the top of the loop
6725 // case x0 (0601): // tnz
6726
6727 case x0 (0617): // tov
6728 // If overflow indicator ON then
6729 // C(TPR.CA) -> C(PPR.IC)
6730 // C(TPR.TSR) -> C(PPR.PSR)
6731 if (TST_I_OFLOW)
6732 {
6733 CLR_I_OFLOW;
6734 do_caf (cpup);
6735 read_tra_op (cpup);
6736 return CONT_TRA;
6737 }
6738 break;
6739
6740 case x0 (0605): // tpl
6741 // If negative indicator OFF, then
6742 // C(TPR.CA) -> C(PPR.IC)
6743 // C(TPR.TSR) -> C(PPR.PSR)
6744 if (! (TST_I_NEG))
6745 {
6746 do_caf (cpup);
6747 read_tra_op (cpup);
6748 return CONT_TRA;
6749 }
6750 break;
6751
6752 // Optimized to the top of the loop
6753 // case x1 (0605): // tpnz
6754
6755 // Optimized to the top of the loop
6756 // case x0 (0710): // tra
6757
6758 case x0 (0603): // trc
6759 // If carry indicator ON then
6760 // C(TPR.CA) -> C(PPR.IC)
6761 // C(TPR.TSR) -> C(PPR.PSR)
6762 if (TST_I_CARRY)
6763 {
6764 do_caf (cpup);
6765 read_tra_op (cpup);
6766 return CONT_TRA;
6767 }
6768 break;
6769
6770 case x1 (0601): // trtf
6771 // If truncation indicator OFF then
6772 // C(TPR.CA) -> C(PPR.IC)
6773 // C(TPR.TSR) -> C(PPR.PSR)
6774 if (!TST_I_TRUNC)
6775 {
6776 do_caf (cpup);
6777 read_tra_op (cpup);
6778 return CONT_TRA;
6779 }
6780 break;
6781
6782 case x1 (0600): // trtn
6783 // If truncation indicator ON then
6784 // C(TPR.CA) -> C(PPR.IC)
6785 // C(TPR.TSR) -> C(PPR.PSR)
6786 if (TST_I_TRUNC)
6787 {
6788 CLR_I_TRUNC;
6789 do_caf (cpup);
6790 read_tra_op (cpup);
6791 return CONT_TRA;
6792 }
6793 break;
6794
6795 // Optimized to the top of the loop
6796 // // tspn
6797 // case x0 (0270): // tsp0
6798 // case x0 (0271): // tsp1
6799 // case x0 (0272): // tsp2
6800 // case x0 (0273): // tsp3
6801 // case x0 (0670): // tsp4
6802 // case x0 (0671): // tsp5
6803 // case x0 (0672): // tsp6
6804 // case x0 (0673): // tsp7
6805
6806 case x0 (0715): // tss
6807 CPTUR (cptUseBAR);
6808 do_caf (cpup);
6809 if (get_bar_mode (cpup))
6810 read_tra_op (cpup);
6811 else
6812 {
6813 cpu.TPR.CA = get_BAR_address (cpup, cpu.TPR.CA);
6814 read_tra_op (cpup);
6815 CLR_I_NBAR;
6816 }
6817 return CONT_TRA;
6818
6819 // Optimized to the top of the loop
6820 // // tsxn
6821 // case x0 (0700): // tsx0
6822 // case x0 (0701): // tsx1
6823 // case x0 (0702): // tsx2
6824 // case x0 (0703): // tsx3
6825 // case x0 (0704): // tsx4
6826 // case x0 (0705): // tsx5
6827 // case x0 (0706): // tsx6
6828 // case x0 (0707): // tsx7
6829
6830 case x0 (0607): // ttf
6831 // If tally runout indicator OFF then
6832 // C(TPR.CA) -> C(PPR.IC)
6833 // C(TPR.TSR) -> C(PPR.PSR)
6834 // otherwise, no change to C(PPR)
6835 if (TST_I_TALLY == 0)
6836 {
6837 do_caf (cpup);
6838 read_tra_op (cpup);
6839 return CONT_TRA;
6840 }
6841 break;
6842
6843 case x1 (0606): // ttn
6844 // If tally runout indicator ON then
6845 // C(TPR.CA) -> C(PPR.IC)
6846 // C(TPR.TSR) -> C(PPR.PSR)
6847 // otherwise, no change to C(PPR)
6848 if (TST_I_TALLY)
6849 {
6850 do_caf (cpup);
6851 read_tra_op (cpup);
6852 return CONT_TRA;
6853 }
6854 break;
6855
6856 // Optimized to the top of the loop
6857 // case x0 (0600): // tze
6858
6859 /// POINTER REGISTER INSTRUCTIONS
6860
6861 /// Pointer Register Data Movement Load
6862
6863 // easpn
6864
6865 case x0 (0311): // easp0
6866 // C(TPR.CA) -> C(PRn.SNR)
6867 CPTUR (cptUsePRn + 0);
6868 cpu.PR[0].SNR = cpu.TPR.CA & MASK15;
6869 #if defined(TESTING)
6870 HDBGRegPRW (0, "easp0");
6871 #endif
6872 break;
6873
6874 case x1 (0310): // easp1
6875 // C(TPR.CA) -> C(PRn.SNR)
6876 CPTUR (cptUsePRn + 1);
6877 cpu.PR[1].SNR = cpu.TPR.CA & MASK15;
6878 #if defined(TESTING)
6879 HDBGRegPRW (1, "easp1");
6880 #endif
6881 break;
6882
6883 case x0 (0313): // easp2
6884 // C(TPR.CA) -> C(PRn.SNR)
6885 CPTUR (cptUsePRn + 2);
6886 cpu.PR[2].SNR = cpu.TPR.CA & MASK15;
6887 #if defined(TESTING)
6888 HDBGRegPRW (2, "easp2");
6889 #endif
6890 break;
6891
6892 case x1 (0312): // easp3
6893 // C(TPR.CA) -> C(PRn.SNR)
6894 CPTUR (cptUsePRn + 3);
6895 cpu.PR[3].SNR = cpu.TPR.CA & MASK15;
6896 #if defined(TESTING)
6897 HDBGRegPRW (3, "easp3");
6898 #endif
6899 break;
6900
6901 case x0 (0331): // easp4
6902 // C(TPR.CA) -> C(PRn.SNR)
6903 CPTUR (cptUsePRn + 4);
6904 cpu.PR[4].SNR = cpu.TPR.CA & MASK15;
6905 #if defined(TESTING)
6906 HDBGRegPRW (4, "easp4");
6907 #endif
6908 break;
6909
6910 case x1 (0330): // easp5
6911 // C(TPR.CA) -> C(PRn.SNR)
6912 CPTUR (cptUsePRn + 5);
6913 cpu.PR[5].SNR = cpu.TPR.CA & MASK15;
6914 #if defined(TESTING)
6915 HDBGRegPRW (5, "easp5");
6916 #endif
6917 break;
6918
6919 case x0 (0333): // easp6
6920 // C(TPR.CA) -> C(PRn.SNR)
6921 CPTUR (cptUsePRn + 6);
6922 cpu.PR[6].SNR = cpu.TPR.CA & MASK15;
6923 #if defined(TESTING)
6924 HDBGRegPRW (6, "easp6");
6925 #endif
6926 break;
6927
6928 case x1 (0332): // easp7
6929 // C(TPR.CA) -> C(PRn.SNR)
6930 CPTUR (cptUsePRn + 7);
6931 cpu.PR[7].SNR = cpu.TPR.CA & MASK15;
6932 #if defined(TESTING)
6933 HDBGRegPRW (7, "easp7");
6934 #endif
6935 break;
6936
6937 // eawpn
6938
6939 case x0 (0310): // eawp0
6940 // For n = 0, 1, ..., or 7 as determined by operation code
6941 // C(TPR.CA) -> C(PRn.WORDNO)
6942 // C(TPR.TBR) -> C(PRn.BITNO)
6943 CPTUR (cptUsePRn + 0);
6944 cpu.PR[0].WORDNO = cpu.TPR.CA;
6945 SET_PR_BITNO (0, cpu.TPR.TBR);
6946 #if defined(TESTING)
6947 HDBGRegPRW (0, "eawp0");
6948 #endif
6949 break;
6950
6951 case x1 (0311): // eawp1
6952 // For n = 0, 1, ..., or 7 as determined by operation code
6953 // C(TPR.CA) -> C(PRn.WORDNO)
6954 // C(TPR.TBR) -> C(PRn.BITNO)
6955 CPTUR (cptUsePRn + 1);
6956 cpu.PR[1].WORDNO = cpu.TPR.CA;
6957 SET_PR_BITNO (1, cpu.TPR.TBR);
6958 #if defined(TESTING)
6959 HDBGRegPRW (1, "eawp1");
6960 #endif
6961 break;
6962
6963 case x0 (0312): // eawp2
6964 // For n = 0, 1, ..., or 7 as determined by operation code
6965 // C(TPR.CA) -> C(PRn.WORDNO)
6966 // C(TPR.TBR) -> C(PRn.BITNO)
6967 CPTUR (cptUsePRn + 2);
6968 cpu.PR[2].WORDNO = cpu.TPR.CA;
6969 SET_PR_BITNO (2, cpu.TPR.TBR);
6970 #if defined(TESTING)
6971 HDBGRegPRW (2, "eawp2");
6972 #endif
6973 break;
6974
6975 case x1 (0313): // eawp3
6976 // For n = 0, 1, ..., or 7 as determined by operation code
6977 // C(TPR.CA) -> C(PRn.WORDNO)
6978 // C(TPR.TBR) -> C(PRn.BITNO)
6979 CPTUR (cptUsePRn + 3);
6980 cpu.PR[3].WORDNO = cpu.TPR.CA;
6981 SET_PR_BITNO (3, cpu.TPR.TBR);
6982 #if defined(TESTING)
6983 HDBGRegPRW (3, "eawp3");
6984 #endif
6985 break;
6986
6987 case x0 (0330): // eawp4
6988 // For n = 0, 1, ..., or 7 as determined by operation code
6989 // C(TPR.CA) -> C(PRn.WORDNO)
6990 // C(TPR.TBR) -> C(PRn.BITNO)
6991 CPTUR (cptUsePRn + 4);
6992 cpu.PR[4].WORDNO = cpu.TPR.CA;
6993 SET_PR_BITNO (4, cpu.TPR.TBR);
6994 #if defined(TESTING)
6995 HDBGRegPRW (4, "eawp4");
6996 #endif
6997 break;
6998
6999 case x1 (0331): // eawp5
7000 // For n = 0, 1, ..., or 7 as determined by operation code
7001 // C(TPR.CA) -> C(PRn.WORDNO)
7002 // C(TPR.TBR) -> C(PRn.BITNO)
7003 CPTUR (cptUsePRn + 5);
7004 cpu.PR[5].WORDNO = cpu.TPR.CA;
7005 SET_PR_BITNO (5, cpu.TPR.TBR);
7006 #if defined(TESTING)
7007 HDBGRegPRW (5, "eawp5");
7008 #endif
7009 break;
7010
7011 case x0 (0332): // eawp6
7012 // For n = 0, 1, ..., or 7 as determined by operation code
7013 // C(TPR.CA) -> C(PRn.WORDNO)
7014 // C(TPR.TBR) -> C(PRn.BITNO)
7015 CPTUR (cptUsePRn + 6);
7016 cpu.PR[6].WORDNO = cpu.TPR.CA;
7017 SET_PR_BITNO (6, cpu.TPR.TBR);
7018 #if defined(TESTING)
7019 HDBGRegPRW (6, "eawp6");
7020 #endif
7021 break;
7022
7023 case x1 (0333): // eawp7
7024 // For n = 0, 1, ..., or 7 as determined by operation code
7025 // C(TPR.CA) -> C(PRn.WORDNO)
7026 // C(TPR.TBR) -> C(PRn.BITNO)
7027 CPTUR (cptUsePRn + 7);
7028 cpu.PR[7].WORDNO = cpu.TPR.CA;
7029 SET_PR_BITNO (7, cpu.TPR.TBR);
7030 #if defined(TESTING)
7031 HDBGRegPRW (7, "eawp7");
7032 #endif
7033 break;
7034
7035 // Optimized to the top of the loop
7036 // case x1 (0350): // epbp0
7037 // case x0 (0351): // epbp1
7038 // case x1 (0352): // epbp2
7039 // case x0 (0353): // epbp3
7040 // case x1 (0370): // epbp4
7041 // case x0 (0371): // epbp5
7042 // case x1 (0372): // epbp6
7043 // case x0 (0373): // epbp7
7044
7045 // Optimized to the top of the switch
7046 // case x0 (0350): // epp0
7047 // case x1 (0351): // epp1
7048 // case x0 (0352): // epp2
7049 // case x1 (0353): // epp3
7050 // case x0 (0374): // epp4
7051 // case x1 (0371): // epp5
7052 // case x0 (0376): // epp6
7053 // case x1 (0373): // epp7
7054
7055 case x0 (0173): // lpri
7056 // For n = 0, 1, ..., 7
7057 // Y-pair = Y-block16 + 2n
7058 // Maximum of C(Y-pair)18,20; C(SDW.R1); C(TPR.TRR) -> C(PRn.RNR)
7059 // C(Y-pair) 3,17 -> C(PRn.SNR)
7060 // C(Y-pair)36,53 -> C(PRn.WORDNO)
7061 // C(Y-pair)57,62 -> C(PRn.BITNO)
7062
7063 for (uint32 n = 0 ; n < 8 ; n ++)
7064 {
7065 CPTUR (cptUsePRn + n);
7066 // Even word of ITS pointer pair
7067 cpu.Ypair[0] = cpu.Yblock16[n * 2 + 0];
7068 // Odd word of ITS pointer pair
7069 cpu.Ypair[1] = cpu.Yblock16[n * 2 + 1];
7070
7071 // RNR from ITS pair
7072 word3 Crr = (GETLO (cpu.Ypair[0]) >> 15) & 07;
7073 if (get_addr_mode (cpup) == APPEND_mode)
7074 cpu.PR[n].RNR = max3 (Crr, cpu.SDW->R1, cpu.TPR.TRR);
7075 else
7076 cpu.PR[n].RNR = Crr;
7077 cpu.PR[n].SNR = (cpu.Ypair[0] >> 18) & MASK15;
7078 cpu.PR[n].WORDNO = GETHI (cpu.Ypair[1]);
7079 word6 bitno = (GETLO (cpu.Ypair[1]) >> 9) & 077;
7080 // According to ISOLTS, loading a 077 into bitno results in 037
7081 // pa851 test-04b lpri test bar-100176
7082 // test start 105321 patch 105461 subtest loop point 105442
7083 // s/b 77777737
7084 // was 77777733
7085 if (bitno == 077)
7086 bitno = 037;
7087 SET_PR_BITNO (n, bitno);
7088 #if defined(TESTING)
7089 HDBGRegPRW (n, "lpri");
7090 #endif
7091 }
7092
7093 break;
7094
7095 // Optimized to the top of the loop
7096 // // lprpn
7097 // case x0 (0760): // lprp0
7098 // case x0 (0761): // lprp1
7099 // case x0 (0762): // lprp2
7100 // case x0 (0763): // lprp3
7101 // case x0 (0764): // lprp4
7102 // case x0 (0765): // lprp5
7103 // case x0 (0766): // lprp6
7104 // case x0 (0767): // lprp7
7105
7106 /// Pointer Register Data Movement Store
7107
7108 // Optimized to the top of the loop
7109 // case x1 (0250): // spbp0
7110 // case x0 (0251): // spbp1
7111 // case x1 (0252): // spbp2
7112 // case x0 (0253): // spbp3
7113 // case x1 (0650): // spbp4
7114 // case x0 (0651): // spbp5
7115 // case x1 (0652): // spbp6
7116 // case x0 (0653): // spbp7
7117
7118 case x0 (0254): // spri
7119 // For n = 0, 1, ..., 7
7120 // Y-pair = Y-block16 + 2n
7121
7122 // 000 -> C(Y-pair)0,2
7123 // C(PRn.SNR) -> C(Y-pair)3,17
7124 // C(PRn.RNR) -> C(Y-pair)18,20
7125 // 00...0 -> C(Y-pair)21,29
7126 // (43)8 -> C(Y-pair)30,35
7127
7128 // C(PRn.WORDNO) -> C(Y-pair)36,53
7129 // 000 -> C(Y-pair)54,56
7130 // C(PRn.BITNO) -> C(Y-pair)57,62
7131 // 00...0 -> C(Y-pair)63,71
7132
7133 for (uint32 n = 0 ; n < 8 ; n++)
7134 {
7135 CPTUR (cptUsePRn + n);
7136 cpu.Yblock16[2 * n] = 043;
7137 cpu.Yblock16[2 * n] |= ((word36) cpu.PR[n].SNR) << 18;
7138 cpu.Yblock16[2 * n] |= ((word36) cpu.PR[n].RNR) << 15;
7139
7140 cpu.Yblock16[2 * n + 1] = (word36) cpu.PR[n].WORDNO << 18;
7141 cpu.Yblock16[2 * n + 1] |= (word36) GET_PR_BITNO(n) << 9;
7142 }
7143
7144 break;
7145
7146 // Optimized to the top of the loop
7147 // case x0 (0250): // spri0
7148 // case x1 (0251): // spri1
7149 // case x0 (0252): // spri2
7150 // case x1 (0253): // spri3
7151 // case x0 (0650): // spri4
7152 // case x1 (0255): // spri5
7153 // case x0 (0652): // spri6
7154 // case x1 (0257): // spri7
7155
7156 // sprpn
7157 case x0 (0540): // sprp0
7158 case x0 (0541): // sprp1
7159 case x0 (0542): // sprp2
7160 case x0 (0543): // sprp3
7161 case x0 (0544): // sprp4
7162 case x0 (0545): // sprp5
7163 case x0 (0546): // sprp6
7164 case x0 (0547): // sprp7
7165 // For n = 0, 1, ..., or 7 as determined by operation code
7166 // C(PRn.BITNO) -> C(Y)0,5
7167 // C(PRn.SNR)3,14 -> C(Y)6,17
7168 // C(PRn.WORDNO) -> C(Y)18,35
7169 {
7170 uint32 n = opcode10 & 07; // get n
7171 CPTUR (cptUsePRn + n);
7172
7173 // If C(PRn.SNR)0,2 are nonzero, and C(PRn.SNR) != 11...1, then
7174 // a store fault (illegal pointer) will occur and C(Y) will not
7175 // be changed.
7176
7177 if ((cpu.PR[n].SNR & 070000) != 0 && cpu.PR[n].SNR != MASK15)
7178 doFault (FAULT_STR, fst_str_ptr, "sprpn");
7179
7180 cpu.CY = ((word36) (GET_PR_BITNO(n) & 077)) << 30;
7181 // lower 12- of 15-bits
7182 cpu.CY |= ((word36) (cpu.PR[n].SNR & 07777)) << 18;
7183 cpu.CY |= cpu.PR[n].WORDNO & PAMASK;
7184 cpu.CY &= DMASK; // keep to 36-bits
7185 }
7186 break;
7187
7188 /// Pointer Register Address Arithmetic
7189
7190 // adwpn
7191 case x0 (0050): // adwp0
7192 case x0 (0051): // adwp1
7193 case x0 (0052): // adwp2
7194 case x0 (0053): // adwp3
7195 // For n = 0, 1, ..., or 7 as determined by operation code
7196 // C(Y)0,17 + C(PRn.WORDNO) -> C(PRn.WORDNO)
7197 // 00...0 -> C(PRn.BITNO)
7198 {
7199 uint32 n = opcode10 & 03; // get n
7200 CPTUR (cptUsePRn + n);
7201 cpu.PR[n].WORDNO += GETHI (cpu.CY);
7202 cpu.PR[n].WORDNO &= MASK18;
7203 SET_PR_BITNO (n, 0);
7204 #if defined(TESTING)
7205 HDBGRegPRW (n, "adwpn");
7206 #endif
7207 }
7208 break;
7209
7210 case x0 (0150): // adwp4
7211 case x0 (0151): // adwp5
7212 case x0 (0152): // adwp6
7213 case x0 (0153): // adwp7
7214 // For n = 0, 1, ..., or 7 as determined by operation code
7215 // C(Y)0,17 + C(PRn.WORDNO) -> C(PRn.WORDNO)
7216 // 00...0 -> C(PRn.BITNO)
7217 {
7218 uint32 n = (opcode10 & MASK3) + 4U; // get n
7219 CPTUR (cptUsePRn + n);
7220 cpu.PR[n].WORDNO += GETHI (cpu.CY);
7221 cpu.PR[n].WORDNO &= MASK18;
7222 SET_PR_BITNO (n, 0);
7223 #if defined(TESTING)
7224 HDBGRegPRW (n, "adwpn");
7225 #endif
7226 }
7227 break;
7228
7229 /// Pointer Register Miscellaneous
7230
7231 // Optimized to the top of the loop
7232 // case x0 (0213): // epaq
7233
7234 /// MISCELLANEOUS INSTRUCTIONS
7235
7236 case x0 (0633): // rccl
7237 // 00...0 -> C(AQ)0,19
7238 // C(calendar clock) -> C(AQ)20,71
7239 {
7240 // For the rccl instruction, the first 2 or 3 bits of the addr
7241 // field of the instruction are used to specify which SCU.
7242 // init_processor.alm systematically steps through the SCUs,
7243 // using addresses 000000 100000 200000 300000.
7244 uint cpu_port_num;
7245 if (cpu.tweaks.l68_mode)
7246 cpu_port_num = (cpu.TPR.CA >> 15) & 07;
7247 else
7248 cpu_port_num = (cpu.TPR.CA >> 15) & 03;
7249 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
7250 {
7251 sim_warn ("rccl on CPU %u port %d has no SCU; faulting\r\n",
7252 current_running_cpu_idx, cpu_port_num);
7253 doFault (FAULT_ONC, fst_onc_nem, "(rccl)");
7254 }
7255 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
7256
7257 t_stat rc = scu_rscr (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
7258 040, & cpu.rA, & cpu.rQ);
7259 #if defined(TESTING)
7260 HDBGRegAW ("rccl");
7261 HDBGRegQW ("rccl");
7262 #endif
7263 if (rc > 0)
7264 return rc;
7265 #if !defined(SPEED)
7266 if_sim_debug (DBG_TRACEEXT, & cpu_dev)
7267 {
7268 // Clock at initialization
7269 // date -d "Tue Jul 22 16:39:38 PDT 1999" +%s
7270 // 932686778
7271 uint64 UnixSecs = 932686778;
7272 uint64 UnixuSecs = UnixSecs * 1000000LL;
7273 // now determine uSecs since Jan 1, 1901 ...
7274 uint64 MulticsuSecs = 2177452800000000LL + UnixuSecs;
7275
7276 // Back into 72 bits
7277 word72 big = convert_to_word72 (cpu.rA, cpu.rQ);
7278 # if defined(NEED_128)
7279 // Convert to time since boot
7280 big = subtract_128 (big, construct_128 (0, MulticsuSecs));
7281 uint32_t remainder;
7282 uint128 bigsecs = divide_128_32 (big, 1000000u, & remainder);
7283 uint64_t uSecs = remainder;
7284 uint64_t secs = bigsecs.l;
7285 sim_debug (DBG_TRACEEXT, & cpu_dev,
7286 "Clock time since boot %4llu.%06llu seconds\r\n",
7287 secs, uSecs);
7288 # else
7289 // Convert to time since boot
7290 big -= MulticsuSecs;
7291 unsigned long uSecs = big % 1000000u;
7292 unsigned long secs = (unsigned long) (big / 1000000u);
7293 sim_debug (DBG_TRACEEXT, & cpu_dev,
7294 "Clock time since boot %4lu.%06lu seconds\r\n",
7295 secs, uSecs);
7296 # endif
7297 }
7298 #endif
7299 }
7300 break;
7301
7302 case x0 (0002): // drl
7303 // Causes a fault which fetches and executes, in absolute mode, the
7304 // instruction pair at main memory location C+(14)8. The value of C
7305 // is obtained from the FAULT VECTOR switches on the processor
7306 // configuration panel.
7307
7308 if (cpu.tweaks.drl_fatal)
7309 {
7310 return STOP_STOP;
7311 }
7312 doFault (FAULT_DRL, fst_zero, "drl");
7313
7314 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7315 case x0 (0716): // xec
7316 cpu.cu.xde = 1;
7317 cpu.cu.xdo = 0;
7318 // XXX NB. This used to be done in executeInstruction post-execution
7319 // processing; moving it here means that post-execution code cannot inspect IWB
7320 // to determine what the instruction or it flags were.
7321 cpu.cu.IWB = cpu.CY;
7322 return CONT_XEC;
7323
7324 case x0 (0717): // xed
7325 // The xed instruction itself does not affect any indicator.
7326 // However, the execution of the instruction pair from C(Y-pair)
7327 // may affect indicators.
7328 //
7329 // The even instruction from C(Y-pair) must not alter
7330 // C(Y-pair)36,71, and must not be another xed instruction.
7331 //
7332 // If the execution of the instruction pair from C(Y-pair) alters
7333 // C(PPR.IC), then a transfer of control occurs; otherwise, the
7334 // next instruction to be executed is fetched from C(PPR.IC)+1. If
7335 // the even instruction from C(Y-pair) alters C(PPR.IC), then the
7336 // transfer of control is effective immediately and the odd
7337 // instruction is not executed.
7338 //
7339 // To execute an instruction pair having an rpd instruction as the
7340 // odd instruction, the xed instruction must be located at an odd
7341 // address. The instruction pair repeated is that instruction pair
7342 // at C PPR.IC)+1, that is, the instruction pair immediately
7343 // following the xed instruction. C(PPR.IC) is adjusted during the
7344 // execution of the repeated instruction pair so the next
7345 // instruction fetched for execution is from the first word
7346 // following the repeated instruction pair.
7347 //
7348 // The instruction pair at C(Y-pair) may cause any of the processor
7349 // defined fault conditions, but only the directed faults (0,1,2,3)
7350 // and the access violation fault may be restarted successfully by
7351 // the hardware. Note that the software induced fault tag (1,2,3)
7352 // faults cannot be properly restarted.
7353 //
7354 // An attempt to execute an EIS multiword instruction causes an
7355 // illegal procedure fault.
7356 //
7357 // Attempted repetition with the rpt, rpd, or rpl instructions
7358 // causes an illegal procedure fault.
7359
7360 cpu.cu.xde = 1;
7361 cpu.cu.xdo = 1;
7362 // XXX NB. This used to be done in executeInstruction post-execution
7363 // processing; moving it here means that post-execution code cannot inspect IWB
7364 // to determine what the instruction or it flags were.
7365 cpu.cu.IWB = cpu.Ypair[0];
7366 cpu.cu.IRODD = cpu.Ypair[1];
7367 return CONT_XEC;
7368
7369 case x0 (0001): // mme
7370 #if defined(TESTING)
7371 if (sim_deb_mme_cntdwn > 0)
7372 sim_deb_mme_cntdwn --;
7373 #endif
7374 // Causes a fault that fetches and executes, in absolute mode, the
7375 // instruction pair at main memory location C+4. The value of C is
7376 // obtained from the FAULT VECTOR switches on the processor
7377 // configuration panel.
7378 doFault (FAULT_MME, fst_zero, "Master Mode Entry (mme)");
7379
7380 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7381 case x0 (0004): // mme2
7382 // Causes a fault that fetches and executes, in absolute mode, the
7383 // instruction pair at main memory location C+(52)8. The value of C
7384 // is obtained from the FAULT VECTOR switches on the processor
7385 // configuration panel.
7386 doFault (FAULT_MME2, fst_zero, "Master Mode Entry 2 (mme2)");
7387
7388 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7389 case x0 (0005): // mme3
7390 // Causes a fault that fetches and executes, in absolute mode, the
7391 // instruction pair at main memory location C+(54)8. The value of C
7392 // is obtained from the FAULT VECTOR switches on the processor
7393 // configuration panel.
7394 doFault (FAULT_MME3, fst_zero, "Master Mode Entry 3 (mme3)");
7395
7396 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7397 case x0 (0007): // mme4
7398 // Causes a fault that fetches and executes, in absolute mode, the
7399 // instruction pair at main memory location C+(56)8. The value of C
7400 // is obtained from the FAULT VECTOR switches on the processor
7401 // configuration panel.
7402 doFault (FAULT_MME4, fst_zero, "Master Mode Entry 4 (mme4)");
7403
7404 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7405 case x0 (0011): // nop
7406 break;
7407
7408 case x0 (0012): // puls1
7409 break;
7410
7411 case x0 (0013): // puls2
7412 break;
7413
7414 /// Repeat
7415
7416 case x0 (0560): // rpd
7417 {
7418 if ((cpu.PPR.IC & 1) == 0)
7419 doFault (FAULT_IPR, fst_ill_proc, "rpd odd");
7420 cpu.cu.delta = i->tag;
7421 // a:AL39/rpd1
7422 word1 c = (i->address >> 7) & 1;
7423 if (c)
7424 {
7425 cpu.rX[0] = i->address; // Entire 18 bits
7426 #if defined(TESTING)
7427 HDBGRegXW (0, "rpd");
7428 #endif
7429 }
7430 cpu.cu.rd = 1;
7431 cpu.cu.repeat_first = 1;
7432 // the tally runout indicator is off until the repeat ends
7433 // (PA885 06B: fault in the first repetition)
7434 CLR_I_TALLY;
7435 cpu.rptUndo[0] = cpu.rptUndo[1] = 0;
7436 }
7437 break;
7438
7439 case x0 (0500): // rpl
7440 {
7441 uint c = (i->address >> 7) & 1;
7442 cpu.cu.delta = i->tag;
7443 if (c)
7444 {
7445 cpu.rX[0] = i->address; // Entire 18 bits
7446 #if defined(TESTING)
7447 HDBGRegXW (0, "rpl");
7448 #endif
7449 }
7450 cpu.cu.rl = 1;
7451 cpu.cu.repeat_first = 1;
7452 // the tally runout indicator is off until the repeat ends
7453 // (PA885 06B: fault in the first repetition)
7454 CLR_I_TALLY;
7455 cpu.rptUndo[0] = cpu.rptUndo[1] = 0;
7456 }
7457 break;
7458
7459 case x0 (0520): // rpt
7460 {
7461 uint c = (i->address >> 7) & 1;
7462 cpu.cu.delta = i->tag;
7463 if (c)
7464 {
7465 cpu.rX[0] = i->address; // Entire 18 bits
7466 #if defined(TESTING)
7467 HDBGRegXW (0, "rpt");
7468 #endif
7469 }
7470 cpu.cu.rpt = 1;
7471 cpu.cu.repeat_first = 1;
7472 // the tally runout indicator is off until the repeat ends
7473 // (PA885 06B: fault in the first repetition)
7474 CLR_I_TALLY;
7475 cpu.rptUndo[0] = cpu.rptUndo[1] = 0;
7476 }
7477 break;
7478
7479 /// Ring Alarm Register
7480
7481 case x1 (0754): // sra
7482 // 00...0 -> C(Y)0,32
7483 // C(RALR) -> C(Y)33,35
7484
7485 CPTUR (cptUseRALR);
7486 cpu.CY = (word36)cpu.rRALR;
7487
7488 break;
7489
7490 /// Store Base Address Register
7491
7492 case x0 (0550): // sbar
7493 // C(BAR) -> C(Y) 0,17
7494 CPTUR (cptUseBAR);
7495 //SETHI (cpu.CY, (cpu.BAR.BASE << 9) | cpu.BAR.BOUND);
7496 cpu.CY = ((((word36) cpu.BAR.BASE) << 9) | cpu.BAR.BOUND) << 18;
7497 cpu.zone = 0777777000000;
7498 cpu.useZone = true;
7499 break;
7500
7501 /// Translation
7502
7503 case x0 (0505): // bcd
7504 // Shift C(A) left three positions
7505 // | C(A) | / C(Y) -> 4-bit quotient
7506 // C(A) - C(Y) * quotient -> remainder
7507 // Shift C(Q) left six positions
7508 // 4-bit quotient -> C(Q)32,35
7509 // remainder -> C(A)
7510
7511 {
7512 word36 tmp1 = cpu.rA & SIGN36; // A0
7513 word36 tmp36 = (cpu.rA << 3) & DMASK;
7514 word36 tmp36q = tmp36 / cpu.CY; // this may be more than 4 bits, keep it for remainder calculation
7515 word36 tmp36r = 0;
7516 if (!tmp1) {
7517 tmp36r = tmp36 - tmp36q * cpu.CY;
7518 } else {
7519 // ISOLTS-745 05i: bcd when rA is negative.
7520 // Note that this only gets called in the first round of the bcd
7521 // conversion; the rA sign bit will get shifted out.
7522 // Looking at the expected results, it appears that a 'borrow'
7523 // is represented in a residue style notation -- an unborrow
7524 // result is 0-9 (000 - 011), a borrowed digit as 6-15 (006-017)
7525 tmp36q += 6;
7526 tmp36r = tmp36 + tmp36q * cpu.CY;
7527 }
7528
7529 cpu.rQ <<= 6; // Shift C(Q) left six positions
7530 cpu.rQ &= DMASK;
7531
7532 //cpu.rQ &= (word36) ~017; // 4-bit quotient -> C(Q)32,35 lo6 bits already zeroed out
7533 cpu.rQ |= (tmp36q & 017);
7534 #if defined(TESTING)
7535 HDBGRegQW ("bcd");
7536 #endif
7537
7538 cpu.rA = tmp36r & DMASK; // remainder -> C(A)
7539 #if defined(TESTING)
7540 HDBGRegAW ("bcd");
7541 #endif
7542
7543 SC_I_ZERO (cpu.rA == 0); // If C(A) = 0, then ON;
7544 // otherwise OFF
7545 SC_I_NEG (tmp1); // If C(A)0 = 1 before execution,
7546 // then ON; otherwise OFF
7547 }
7548 break;
7549
7550 case x0 (0774): // gtb
7551 // C(A)0 -> C(A)0
7552 // C(A)i XOR C(A)i-1 -> C(A)i for i = 1, 2, ..., 35
7553 {
7554 word36 tmp = cpu.rA & MASK36;
7555 word36 mask = SIGN36;
7556
7557 for (int n=1;n<=35;n++) {
7558 tmp ^= (tmp & mask) >> 1;
7559 mask >>= 1;
7560 }
7561
7562 cpu.rA = tmp;
7563 #if defined(TESTING)
7564 HDBGRegAW ("gtb");
7565 #endif
7566
7567 SC_I_ZERO (cpu.rA == 0); // If C(A) = 0, then ON;
7568 // otherwise OFF
7569 SC_I_NEG (cpu.rA & SIGN36); // If C(A)0 = 1, then ON;
7570 // otherwise OFF
7571 }
7572 break;
7573
7574 /// REGISTER LOAD
7575
7576 case x0 (0230): // lbar
7577 // C(Y)0,17 -> C(BAR)
7578 CPTUR (cptUseBAR);
7579 // BAR.BASE is upper 9-bits (0-8)
7580 cpu.BAR.BASE = (GETHI (cpu.CY) >> 9) & 0777;
7581 // BAR.BOUND is next lower 9-bits (9-17)
7582 cpu.BAR.BOUND = GETHI (cpu.CY) & 0777;
7583 break;
7584
7585 /// PRIVILEGED INSTRUCTIONS
7586
7587 /// Privileged - Register Load
7588
7589 case x0 (0674): // lcpr
7590 // DPS8M interpretation
7591 switch (i->tag)
7592 {
7593 // Extract bits from 'from' under 'mask' shifted to where (where
7594 // is dps8 '0 is the msbit.
7595
7596 case 02: // cache mode register
7597 {
7598 //cpu.CMR = cpu.CY;
7599 // cpu.CMR.cache_dir_address = <ignored for lcpr>
7600 // cpu.CMR.par_bit = <ignored for lcpr>
7601 // cpu.CMR.lev_ful = <ignored for lcpr>
7602
7603 CPTUR (cptUseCMR);
7604 // a:AL39/cmr2 If either cache enable bit c or d changes
7605 // from disable state to enable state, the entire cache is
7606 // cleared.
7607 uint csh1_on = getbits36_1 (cpu.CY, 54 - 36);
7608 uint csh2_on = getbits36_1 (cpu.CY, 55 - 36);
7609 //bool clear = (cpu.CMR.csh1_on == 0 && csh1_on != 0) ||
7610 //(cpu.CMR.csh1_on == 0 && csh1_on != 0);
7611 cpu.CMR.csh1_on = (word1) csh1_on;
7612 cpu.CMR.csh2_on = (word1) csh2_on;
7613 //if (clear) // a:AL39/cmr2
7614 //{
7615 //}
7616 L68_ (cpu.CMR.opnd_on = getbits36_1 (cpu.CY, 56 - 36);)
7617 cpu.CMR.inst_on = getbits36_1 (cpu.CY, 57 - 36);
7618 cpu.CMR.csh_reg = getbits36_1 (cpu.CY, 59 - 36);
7619 if (cpu.CMR.csh_reg)
7620 sim_warn ("LCPR set csh_reg\r\n");
7621 // cpu.CMR.str_asd = <ignored for lcpr>
7622 // cpu.CMR.col_ful = <ignored for lcpr>
7623 // cpu.CMR.rro_AB = getbits36_1 (cpu.CY, 18);
7624 DPS8M_ (cpu.CMR.bypass_cache = getbits36_1 (cpu.CY, 68 - 36);)
7625 cpu.CMR.luf = getbits36_2 (cpu.CY, 70 - 36);
7626 }
7627 break;
7628
7629 case 04: // mode register
7630 {
7631 CPTUR (cptUseMR);
7632 cpu.MR.r = cpu.CY;
7633 // XXX TEST/NORMAL switch is set to NORMAL
7634 putbits36_1 (& cpu.MR.r, 32, 0);
7635 // SBZ
7636 putbits36_2 (& cpu.MR.r, 33, 0);
7637 L68_ (
7638 cpu.MR.FFV = getbits36_15 (cpu.CY, 0);
7639 cpu.MR.OC_TRAP = getbits36_1 (cpu.CY, 16);
7640 cpu.MR.ADR_TRAP = getbits36_1 (cpu.CY, 17);
7641 cpu.MR.OPCODE = getbits36_9 (cpu.CY, 18);
7642 cpu.MR.OPCODEX = getbits36_1 (cpu.CY, 27);
7643 )
7644 cpu.MR.sdpap = getbits36_1 (cpu.CY, 20);
7645 cpu.MR.separ = getbits36_1 (cpu.CY, 21);
7646 // DPS/L68: bits 18-27 are the trap OPCODE; bits 18-25
7647 // are controls (store incorrect parity: 20, 21) only with
7648 // OC TRAP (16) and O.C$ (29) off (PM700 02V: opcode 755
7649 // would set both). TEST mode (32, the TEST/NORMAL switch)
7650 // gates only the margin controls (22-25), which dps8m
7651 // ignores: SM782 tests store parity with the switch in
7652 // NORMAL, and no page asks for TEST
7653 L68_ (
7654 if (getbits36_1 (cpu.CY, 16) || getbits36_1 (cpu.CY, 29))
7655 cpu.MR.sdpap = cpu.MR.separ = 0;
7656 )
7657 cpu.MR.hrhlt = getbits36_1 (cpu.CY, 28);
7658 DPS8M_ (cpu.MR.hrxfr = getbits36_1 (cpu.CY, 29);)
7659 cpu.MR.ihr = getbits36_1 (cpu.CY, 30);
7660 cpu.MR.ihrrs = getbits36_1 (cpu.CY, 31);
7661 cpu.MR.emr = getbits36_1 (cpu.CY, 35);
7662 if (! cpu.tweaks.l68_mode) // DPS8M
7663 cpu.MR.hexfp = getbits36_1 (cpu.CY, 33);
7664 else // L68
7665 cpu.MR.hexfp = 0;
7666
7667 // Stop HR Strobe on HR Counter Overflow. (Setting bit 28
7668 // shall cause the HR counter to be reset to zero.)
7669 // CAC: It is unclear if bit 28 is edge or level
7670 // triggered; assuming level for simplicity.
7671 if (cpu.MR.hrhlt)
7672 {
7673 for (uint hset = 0; hset < N_HIST_SETS; hset ++)
7674 cpu.history_cyclic[hset] = 0;
7675 }
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688 }
7689 break;
7690
7691 case 03: // 0's -> history
7692 {
7693 for (uint i = 0; i < N_HIST_SETS; i ++)
7694 add_history_force (cpup, i, 0, 0);
7695 // XXX ISOLTS pm700 test-01n
7696 // The test clears the history registers but with ihr & emr set, causing
7697 // the registers to fill with alternating 0's and lcpr instructions.
7698 // Set flag to prevent the LCPR from being recorded.
7699 //cpu.MR.ihr = 0;
7700 cpu.skip_cu_hist = true;
7701
7702 }
7703 break;
7704
7705 case 07: // 1's -> history
7706 {
7707 for (uint i = 0; i < N_HIST_SETS; i ++)
7708 add_history_force (cpup, i, MASK36, MASK36);
7709 // XXX ISOLTS pm700 test-01n
7710 // The test clears the history registers but with ihr & emr set, causing
7711 // the registers to fill with alternating 0's and lcpr instructions.
7712 // Set flag to prevent the LCPR from being recorded.
7713 //cpu.MR.ihr = 0;
7714 cpu.skip_cu_hist = true;
7715 }
7716 break;
7717
7718 default:
7719 doFault (FAULT_IPR,
7720 fst_ill_mod,
7721 "lcpr tag invalid");
7722
7723 }
7724 break;
7725
7726 case x0 (0232): // ldbr
7727 do_ldbr (cpup, cpu.Ypair);
7728 ucInvalidate (cpup);
7729 break;
7730
7731 case x0 (0637): // ldt
7732 CPTUR (cptUseTR);
7733 cpu.rTR = (cpu.CY >> 9) & MASK27;
7734 cpu.rTRticks = 0;
7735 if (cpu.tweaks.isolts_mode)
7736 {
7737 cpu.shadowTR = cpu.TR0 = cpu.rTR;
7738 cpu.rTRlsb = 0;
7739 }
7740 // L68, T&D: a TR loaded with 0 runs out at once; the runout is
7741 // taken at the first slave-mode sampling point (PM776 04C,
7742 // "immediate timer runout fault in slave mode", L68 only: the
7743 // page skips it on a DPS8). The T&D TR counts one per four
7744 // cycles, so otherwise it would wrap only a few instructions
7745 // later, after the page has left slave mode. Continue from the
7746 // wrapped value so the runout isn't signalled twice.
7747 if (cpu.tweaks.l68_mode && cpu.tweaks.tandd_mode && cpu.rTR == 0)
7748 {
7749 cpu.rTR = MASK27;
7750 if (cpu.tweaks.tro_enable)
7751 setG7fault (current_running_cpu_idx, FAULT_TRO);
7752 }
7753 sim_debug (DBG_TRACEEXT, & cpu_dev, "ldt TR %d (%o)\r\n",
7754 cpu.rTR, cpu.rTR);
7755 #if defined(LOOPTRC)
7756 elapsedtime ();
7757 sim_printf (" ldt %d PSR:IC %05o:%06o\r\n", cpu.rTR, cpu.PPR.PSR, cpu.PPR.IC);
7758 #endif
7759 // Undocumented feature. return to bce has been observed to
7760 // experience TRO while masked, setting the TR to -1, and
7761 // experiencing an unexpected TRo interrupt when unmasking.
7762 // Reset any pending TRO fault when the TR is loaded.
7763 clearTROFault (cpup);
7764 break;
7765
7766 case x1 (0257): // lptp
7767
7768 if (cpu.tweaks.l68_mode) {
7769 // For i = 0, 1, ..., 15
7770 // m = C(PTWAM(i).USE)
7771 // C(Y-block16+m)0,14 -> C(PTWAM(m).POINTER)
7772 // C(Y-block16+m)15,26 -> C(PTWAM(m).PAGE)
7773 // C(Y-block16+m)27 -> C(PTWAM(m).F)
7774
7775 for (uint i = 0; i < 16; i ++)
7776 {
7777 word4 m = cpu.PTWAM[i].USE;
7778 cpu.PTWAM[m].POINTER = getbits36_15 (cpu.Yblock16[i], 0);
7779 cpu.PTWAM[m].PAGENO = getbits36_12 (cpu.Yblock16[i], 15);
7780 cpu.PTWAM[m].FE = getbits36_1 (cpu.Yblock16[i], 27);
7781 }
7782 }
7783 break;
7784
7785 case x1 (0173): // lptr
7786 if (cpu.tweaks.l68_mode) {
7787 // For i = 0, 1, ..., 15
7788 // m = C(PTWAM(i).USE)
7789 // C(Y-block16+m)0,17 -> C(PTWAM(m).ADDR)
7790 // C(Y-block16+m)29 -> C(PTWAM(m).M)
7791 for (uint i = 0; i < 16; i ++)
7792 {
7793 word4 m = cpu.PTWAM[i].USE;
7794 cpu.PTWAM[m].ADDR = getbits36_18 (cpu.Yblock16[i], 0);
7795 cpu.PTWAM[m].M = getbits36_1 (cpu.Yblock16[i], 29);
7796 }
7797 }
7798 break;
7799
7800 case x1 (0774): // lra
7801 CPTUR (cptUseRALR);
7802 cpu.rRALR = cpu.CY & MASK3;
7803 sim_debug (DBG_TRACEEXT, & cpu_dev, "RALR set to %o\r\n", cpu.rRALR);
7804 #if defined(LOOPTRC)
7805 {
7806 void elapsedtime (void);
7807 elapsedtime ();
7808 sim_printf (" RALR set to %o PSR:IC %05o:%06o\r\n", cpu.rRALR, cpu.PPR.PSR, cpu.PPR.IC);
7809 }
7810 #endif
7811 break;
7812
7813 case x0 (0257): // lsdp
7814 if (cpu.tweaks.l68_mode) {
7815 // For i = 0, 1, ..., 15
7816 // m = C(SDWAM(i).USE)
7817 // C(Y-block16+m)0,14 -> C(SDWAM(m).POINTER)
7818 // C(Y-block16+m)27 -> C(SDWAM(m).F) Note: typo in AL39, P(17) should be F(27)
7819 for (uint i = 0; i < 16; i ++)
7820 {
7821 word4 m = cpu.SDWAM[i].USE;
7822 cpu.SDWAM[m].POINTER = getbits36_15 (cpu.Yblock16[i], 0);
7823 cpu.SDWAM[m].FE = getbits36_1 (cpu.Yblock16[i], 27);
7824 }
7825 }
7826 break;
7827
7828 case x1 (0232): // lsdr
7829 if (cpu.tweaks.l68_mode) {
7830 // For i = 0, 1, ..., 15
7831 // m = C(SDWAM(i).USE)
7832 // C(Y-block32+2m)0,23 -> C(SDWAM(m).ADDR)
7833 // C(Y-block32+2m)24,32 -> C(SDWAM(m).R1, R2, R3)
7834 // C(Y-block32+2m)37,50 -> C(SDWAM(m).BOUND)
7835 // C(Y-block32+2m)51,57 -> C(SDWAM(m).R, E, W, P, U, G, C) Note: typo in AL39, 52 should be 51
7836 // C(Y-block32+2m)58,71 -> C(SDWAM(m).CL)
7837 for (uint i = 0; i < 16; i ++)
7838 {
7839 word4 m = cpu.SDWAM[i].USE;
7840 uint j = (uint)m * 2;
7841 cpu.SDWAM[m].ADDR = getbits36_24 (cpu.Yblock32[j], 0);
7842 cpu.SDWAM[m].R1 = getbits36_3 (cpu.Yblock32[j], 24);
7843 cpu.SDWAM[m].R2 = getbits36_3 (cpu.Yblock32[j], 27);
7844 cpu.SDWAM[m].R3 = getbits36_3 (cpu.Yblock32[j], 30);
7845
7846 cpu.SDWAM[m].BOUND = getbits36_14 (cpu.Yblock32[j + 1], 37 - 36);
7847 cpu.SDWAM[m].R = getbits36_1 (cpu.Yblock32[j + 1], 51 - 36);
7848 cpu.SDWAM[m].E = getbits36_1 (cpu.Yblock32[j + 1], 52 - 36);
7849 cpu.SDWAM[m].W = getbits36_1 (cpu.Yblock32[j + 1], 53 - 36);
7850 cpu.SDWAM[m].P = getbits36_1 (cpu.Yblock32[j + 1], 54 - 36);
7851 cpu.SDWAM[m].U = getbits36_1 (cpu.Yblock32[j + 1], 55 - 36);
7852 cpu.SDWAM[m].G = getbits36_1 (cpu.Yblock32[j + 1], 56 - 36);
7853 cpu.SDWAM[m].C = getbits36_1 (cpu.Yblock32[j + 1], 57 - 36);
7854 cpu.SDWAM[m].EB = getbits36_14 (cpu.Yblock32[j + 1], 58 - 36);
7855 }
7856 }
7857 break;
7858
7859 case x0 (0613): // rcu
7860 doRCU (cpup); // never returns!
7861
7862 /// Privileged - Register Store
7863
7864 /*FALLTHRU*/ /* fall through */ /* fallthrough */
7865 case x0 (0452): // scpr
7866 {
7867 uint tag = (i->tag) & MASK6;
7868 switch (tag)
7869 {
7870 case 000: // C(APU history register#1) -> C(Y-pair)
7871 {
7872 uint reg = cpu.tweaks.l68_mode ? L68_APU_HIST_REG : DPS8M_APU_HIST_REG;
7873 cpu.Ypair[0] = cpu.history[reg] [cpu.history_cyclic[reg]][0];
7874 cpu.Ypair[1] = cpu.history[reg] [cpu.history_cyclic[reg]][1];
7875 cpu.history_cyclic[reg] = (cpu.history_cyclic[reg] + 1) % N_MODEL_HIST_SIZE;
7876 }
7877 break;
7878
7879 case 001: // C(fault register) -> C(Y-pair)0,35
7880 // 00...0 -> C(Y-pair)36,71
7881 {
7882 CPTUR (cptUseFR);
7883 cpu.Ypair[0] = cpu.faultRegister[0];
7884 cpu.Ypair[1] = cpu.faultRegister[1];
7885 cpu.faultRegister[0] = 0;
7886 cpu.faultRegister[1] = 0;
7887 }
7888 break;
7889
7890 case 006: // C(mode register) -> C(Y-pair)0,35
7891 // C(cache mode register) -> C(Y-pair)36,72
7892 {
7893 CPTUR (cptUseMR);
7894 cpu.Ypair[0] = cpu.MR.r;
7895 // DPS/L68: bits 20-21 are part of the trap OPCODE when
7896 // OC TRAP (16) or O.C$ (29) is on (PM700 02V)
7897 if (! cpu.tweaks.l68_mode ||
7898 ! (getbits36_1 (cpu.MR.r, 16) || getbits36_1 (cpu.MR.r, 29)))
7899 {
7900 putbits36_1 (& cpu.Ypair[0], 20, cpu.MR.sdpap);
7901 putbits36_1 (& cpu.Ypair[0], 21, cpu.MR.separ);
7902 }
7903 putbits36_1 (& cpu.Ypair[0], 30, cpu.MR.ihr);
7904 DPS8M_ (putbits36_1 (& cpu.Ypair[0], 33, cpu.MR.hexfp);)
7905 CPTUR (cptUseCMR);
7906 cpu.Ypair[1] = 0;
7907 putbits36_15 (& cpu.Ypair[1], 36 - 36,
7908 cpu.CMR.cache_dir_address);
7909 putbits36_1 (& cpu.Ypair[1], 51 - 36, cpu.CMR.par_bit);
7910 putbits36_1 (& cpu.Ypair[1], 52 - 36, cpu.CMR.lev_ful);
7911 putbits36_1 (& cpu.Ypair[1], 54 - 36, cpu.CMR.csh1_on);
7912 putbits36_1 (& cpu.Ypair[1], 55 - 36, cpu.CMR.csh2_on);
7913 L68_ (putbits36_1 (& cpu.Ypair[1], 56 - 36, cpu.CMR.opnd_on);)
7914 putbits36_1 (& cpu.Ypair[1], 57 - 36, cpu.CMR.inst_on);
7915 putbits36_1 (& cpu.Ypair[1], 59 - 36, cpu.CMR.csh_reg);
7916 putbits36_1 (& cpu.Ypair[1], 60 - 36, cpu.CMR.str_asd);
7917 putbits36_1 (& cpu.Ypair[1], 61 - 36, cpu.CMR.col_ful);
7918 putbits36_2 (& cpu.Ypair[1], 62 - 36, cpu.CMR.rro_AB);
7919 DPS8M_ (putbits36_1 (& cpu.Ypair[1], 68 - 36, cpu.CMR.bypass_cache);)
7920 putbits36_2 (& cpu.Ypair[1], 70 - 36, cpu.CMR.luf);
7921 }
7922 break;
7923
7924 case 010: // C(APU history register#2) -> C(Y-pair)
7925 {
7926 uint reg = cpu.tweaks.l68_mode ? L68_DU_HIST_REG : DPS8M_EAPU_HIST_REG;
7927 cpu.Ypair[0] = cpu.history[reg] [cpu.history_cyclic[reg]][0];
7928 cpu.Ypair[1] = cpu.history[reg] [cpu.history_cyclic[reg]][1];
7929 cpu.history_cyclic[reg] = (cpu.history_cyclic[reg] + 1) % N_MODEL_HIST_SIZE;
7930 }
7931 break;
7932
7933 case 020: // C(CU history register) -> C(Y-pair)
7934 {
7935 cpu.Ypair[0] =
7936 cpu.history[CU_HIST_REG]
7937 [cpu.history_cyclic[CU_HIST_REG]][0];
7938 cpu.Ypair[1] =
7939 cpu.history[CU_HIST_REG]
7940 [cpu.history_cyclic[CU_HIST_REG]][1];
7941 cpu.history_cyclic[CU_HIST_REG] =
7942 (cpu.history_cyclic[CU_HIST_REG] + 1) % N_MODEL_HIST_SIZE;
7943 }
7944 break;
7945
7946 case 040: // C(OU/DU history register) -> C(Y-pair)
7947 {
7948 uint reg = cpu.tweaks.l68_mode ? L68_OU_HIST_REG : DPS8M_DU_OU_HIST_REG;
7949 cpu.Ypair[0] = cpu.history[reg] [cpu.history_cyclic[reg]][0];
7950 cpu.Ypair[1] = cpu.history[reg] [cpu.history_cyclic[reg]][1];
7951 cpu.history_cyclic[reg] = (cpu.history_cyclic[reg] + 1) % N_MODEL_HIST_SIZE;
7952 }
7953 break;
7954
7955 default:
7956 {
7957 doFault (FAULT_IPR,
7958 fst_ill_mod,
7959 "SCPR Illegal register select value");
7960 }
7961 }
7962 }
7963 break;
7964
7965 case x0 (0657): // scu
7966 // AL-39 defines the behavior of SCU during fault/interrupt
7967 // processing, but not otherwise.
7968 // The T&D tape uses SCU during normal processing, and apparently
7969 // expects the current CU state to be saved.
7970
7971 if (cpu.cycle == EXEC_cycle)
7972 {
7973 // T&D behavior
7974
7975 // An 'Add Delta' addressing mode will alter the TALLY bit;
7976 // restore it (PA887 03A: unchanged by the scu).
7977 SC_I_TALLY (cpu.currentInstruction.stiTally);
7978
7979 scu2words (cpup, cpu.Yblock8);
7980 }
7981 else
7982 {
7983 // AL-39 behavior
7984 for (int j = 0; j < 8; j ++)
7985 cpu.Yblock8[j] = cpu.scu_data[j];
7986 }
7987 break;
7988
7989 case x0 (0154): // sdbr
7990 {
7991 CPTUR (cptUseDSBR);
7992 // C(DSBR.ADDR) -> C(Y-pair) 0,23
7993 // 00...0 -> C(Y-pair) 24,36
7994 cpu.Ypair[0] = ((word36) (cpu.DSBR.ADDR & PAMASK)) << (35 - 23);
7995
7996 // C(DSBR.BOUND) -> C(Y-pair) 37,50
7997 // 0000 -> C(Y-pair) 51,54
7998 // C(DSBR.U) -> C(Y-pair) 55
7999 // 000 -> C(Y-pair) 56,59
8000 // C(DSBR.STACK) -> C(Y-pair) 60,71
8001 cpu.Ypair[1] = ((word36) (cpu.DSBR.BND & 037777)) << (71 - 50) |
8002 ((word36) (cpu.DSBR.U & 1)) << (71 - 55) |
8003 ((word36) (cpu.DSBR.STACK & 07777)) << (71 - 71);
8004 }
8005 break;
8006
8007 case x1 (0557): // sptp
8008 {
8009 // XXX AL39 The associative memory is ignored (forced to "no match") during address
8010 // preparation.
8011 // Level j is selected by C(TPR.CA)12,13
8012 uint level;
8013 L68_ (level = 0;)
8014 DPS8M_ (level = (cpu.TPR.CA >> 4) & 03;)
8015 uint toffset = level * 16;
8016 for (uint j = 0; j < 16; j ++)
8017 {
8018 cpu.Yblock16[j] = 0;
8019 putbits36_15 (& cpu.Yblock16[j], 0,
8020 cpu.PTWAM[toffset + j].POINTER);
8021 DPS8M_ (
8022 putbits36_12 (& cpu.Yblock16[j], 15, cpu.PTWAM[toffset + j].PAGENO & 07760);
8023
8024 uint parity = 0;
8025 // the parity bit was written with the register (PA866)
8026 if (cpu.PTWAM[toffset + j].loaded) {
8027 // calculate parity
8028 // 58009997-040 p.101,111
8029 parity = ((uint) cpu.PTWAM[toffset + j].POINTER << 4) | (cpu.PTWAM[toffset + j].PAGENO >> 8);
8030 parity = parity ^ (parity >>16);
8031 parity = parity ^ (parity >> 8);
8032 parity = parity ^ (parity >> 4);
8033 parity = ~ (0x6996u >> (parity & 0xf));
8034 }
8035 putbits36_1 (& cpu.Yblock16[j], 23, (word1) (parity & 1));
8036 )
8037 L68_ (putbits36_12 (& cpu.Yblock16[j], 15, cpu.PTWAM[toffset + j].PAGENO); )
8038 putbits36_1 (& cpu.Yblock16[j], 27,
8039 cpu.PTWAM[toffset + j].FE);
8040 DPS8M_ (putbits36_6 (& cpu.Yblock16[j], 30, cpu.PTWAM[toffset + j].USE);)
8041 L68_ (putbits36_4 (& cpu.Yblock16[j], 32, cpu.PTWAM[toffset + j].USE);)
8042 }
8043 }
8044 break;
8045
8046 case x1 (0154): // sptr
8047 {
8048 // XXX The associative memory is ignored (forced to "no match") during address
8049 // preparation.
8050
8051 // Level j is selected by C(TPR.CA)12,13
8052 uint level;
8053 DPS8M_ (level = (cpu.TPR.CA >> 4) & 03;)
8054 L68_ (level = 0;)
8055 uint toffset = level * 16;
8056 for (uint j = 0; j < 16; j ++)
8057 {
8058 cpu.Yblock16[j] = 0;
8059 DPS8M_ (putbits36_18 (& cpu.Yblock16[j], 0, cpu.PTWAM[toffset + j].ADDR & 0777760);)
8060 L68_ (putbits36_18 (& cpu.Yblock16[j], 0, cpu.PTWAM[toffset + j].ADDR);)
8061 putbits36_1 (& cpu.Yblock16[j], 29,
8062 cpu.PTWAM[toffset + j].M);
8063 }
8064 }
8065 break;
8066
8067 case x0 (0557): // ssdp
8068 {
8069 // XXX AL39: The associative memory is ignored (forced to "no match")
8070 // during address preparation.
8071 // Level j is selected by C(TPR.CA)12,13
8072 uint level;
8073 DPS8M_ (level = (cpu.TPR.CA >> 4) & 03;)
8074 L68_ (level = 0;)
8075 uint toffset = level * 16;
8076 for (uint j = 0; j < 16; j ++)
8077 {
8078 cpu.Yblock16[j] = 0;
8079 putbits36_15 (& cpu.Yblock16[j], 0,
8080 cpu.SDWAM[toffset + j].POINTER);
8081 putbits36_1 (& cpu.Yblock16[j], 27,
8082 cpu.SDWAM[toffset + j].FE);
8083 DPS8M_ (
8084 uint parity = 0;
8085 // the parity bit was written with the register (PA866)
8086 if (cpu.SDWAM[toffset + j].loaded) {
8087 // calculate parity
8088 // 58009997-040 p.112
8089 parity = cpu.SDWAM[toffset + j].POINTER >> 4;
8090 //parity = parity ^ (parity >>16);
8091 parity = parity ^ (parity >> 8);
8092 parity = parity ^ (parity >> 4);
8093 parity = ~ (0x6996u >> (parity & 0xf));
8094 }
8095 putbits36_1 (& cpu.Yblock16[j], 15, (word1) (parity & 1));
8096
8097 putbits36_6 (& cpu.Yblock16[j], 30, cpu.SDWAM[toffset + j].USE);
8098 )
8099 L68_ (putbits36_4 (& cpu.Yblock16[j], 32, cpu.SDWAM[toffset + j].USE);)
8100 }
8101 }
8102 break;
8103
8104 case x1 (0254): // ssdr
8105 {
8106 // XXX AL39: The associative memory is ignored (forced to "no match") during
8107 // address preparation.
8108
8109 // Level j is selected by C(TPR.CA)11,12
8110 // Note: not bits 12,13. This is due to operand being Yblock32
8111 uint level = 0;
8112 DPS8M_ (level = (cpu.TPR.CA >> 5) & 03;)
8113 L68_ (level = 0;)
8114 uint toffset = level * 16;
8115 for (uint j = 0; j < 16; j ++)
8116 {
8117 cpu.Yblock32[j * 2] = 0;
8118 putbits36_24 (& cpu.Yblock32[j * 2], 0,
8119 cpu.SDWAM[toffset + j].ADDR);
8120 putbits36_3 (& cpu.Yblock32[j * 2], 24,
8121 cpu.SDWAM[toffset + j].R1);
8122 putbits36_3 (& cpu.Yblock32[j * 2], 27,
8123 cpu.SDWAM[toffset + j].R2);
8124 putbits36_3 (& cpu.Yblock32[j * 2], 30,
8125 cpu.SDWAM[toffset + j].R3);
8126 cpu.Yblock32[j * 2 + 1] = 0;
8127
8128 putbits36_14 (& cpu.Yblock32[j * 2 + 1], 37 - 36,
8129 cpu.SDWAM[toffset + j].BOUND);
8130 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 51 - 36,
8131 cpu.SDWAM[toffset + j].R);
8132 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 52 - 36,
8133 cpu.SDWAM[toffset + j].E);
8134 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 53 - 36,
8135 cpu.SDWAM[toffset + j].W);
8136 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 54 - 36,
8137 cpu.SDWAM[toffset + j].P);
8138 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 55 - 36,
8139 cpu.SDWAM[toffset + j].U);
8140 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 56 - 36,
8141 cpu.SDWAM[toffset + j].G);
8142 putbits36_1 (& cpu.Yblock32[j * 2 + 1], 57 - 36,
8143 cpu.SDWAM[toffset + j].C);
8144 putbits36_14 (& cpu.Yblock32[j * 2 + 1], 58 - 36,
8145 cpu.SDWAM[toffset + j].EB);
8146 }
8147 }
8148 break;
8149
8150 /// Privileged - Clear Associative Memory
8151
8152 case x1 (0532): // camp
8153 {
8154 // C(TPR.CA) 16,17 control disabling or enabling the associative
8155 // memory.
8156 // This may be done to either or both halves.
8157 // The full/empty bit of cache PTWAM register is set to zero and
8158 // the LRU counters are initialized.
8159 if (cpu.tweaks.enable_wam)
8160 { // disabled, do nothing
8161 if (cpu.tweaks.l68_mode || cpu.cu.PT_ON) // only clear when enabled
8162 for (uint i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
8163 {
8164 cpu.PTWAM[i].FE = 0;
8165 L68_ (cpu.PTWAM[i].USE = (word4) i;)
8166 DPS8M_ (cpu.PTWAM[i].USE = 0;)
8167 }
8168
8169 // 58009997-040 A level of the associative memory is disabled if
8170 // C(TPR.CA) 16,17 = 01
8171 // 58009997-040 A level of the associative memory is enabled if
8172 // C(TPR.CA) 16,17 = 10
8173 // Level j is selected to be enabled/disable if
8174 // C(TPR.CA) 10+j = 1; j=1,2,3,4
8175 // All levels are selected to be enabled/disabled if
8176 // C(TPR.CA) 11,14 = 0
8177 // This is contrary to what AL39 says, so I'm not going to implement it.
8178 // In fact, I'm not even going to implement the halves.
8179
8180 DPS8M_ (if (cpu.TPR.CA != 0000002 && (cpu.TPR.CA & 3) != 0)
8181 { static bool warned = false; // once: T&D pages issue thousands
8182 if (! warned) { warned = true; sim_warn ("CAMP ignores enable/disable %06o\r\n", cpu.TPR.CA); } })
8183 if ((cpu.TPR.CA & 3) == 02)
8184 cpu.cu.PT_ON = 1;
8185 else if ((cpu.TPR.CA & 3) == 01)
8186 cpu.cu.PT_ON = 0;
8187 }
8188 else
8189 {
8190 cpu.PTW0.FE = 0;
8191 cpu.PTW0.USE = 0;
8192 }
8193 }
8194 ucInvalidate (cpup);
8195 break;
8196
8197 case x0 (0532): // cams
8198 {
8199 // The full/empty bit of each SDWAM register is set to zero and the
8200 // LRU counters are initialized. The remainder of the contents of
8201 // the registers are unchanged. If the associative memory is
8202 // disabled, F and LRU are unchanged.
8203 // C(TPR.CA) 16,17 control disabling or enabling the associative
8204 // memory.
8205 // This may be done to either or both halves.
8206 if (cpu.tweaks.enable_wam)
8207 {
8208 if (cpu.tweaks.l68_mode || cpu.cu.SD_ON) // only clear when enabled
8209 for (uint i = 0; i < N_MODEL_WAM_ENTRIES; i ++)
8210 {
8211 cpu.SDWAM[i].FE = 0;
8212 L68_ (cpu.SDWAM[i].USE = (word4) i;)
8213 DPS8M_ (cpu.SDWAM[i].USE = 0;)
8214 }
8215 // 58009997-040 A level of the associative memory is disabled if
8216 // C(TPR.CA) 16,17 = 01
8217 // 58009997-040 A level of the associative memory is enabled if
8218 // C(TPR.CA) 16,17 = 10
8219 // Level j is selected to be enabled/disable if
8220 // C(TPR.CA) 10+j = 1; j=1,2,3,4
8221 // All levels are selected to be enabled/disabled if
8222 // C(TPR.CA) 11,14 = 0
8223 // This is contrary to what AL39 says, so I'm not going to implement it. In
8224 // fact, I'm not even going to implement the halves.
8225
8226 DPS8M_ (if (cpu.TPR.CA != 0000006 && (cpu.TPR.CA & 3) != 0)
8227 { static bool warned = false; // once: T&D pages issue thousands
8228 if (! warned) { warned = true; sim_warn ("CAMS ignores enable/disable %06o\r\n", cpu.TPR.CA); } })
8229 if ((cpu.TPR.CA & 3) == 02)
8230 cpu.cu.SD_ON = 1;
8231 else if ((cpu.TPR.CA & 3) == 01)
8232 cpu.cu.SD_ON = 0;
8233 }
8234 else
8235 {
8236 cpu.SDW0.FE = 0;
8237 cpu.SDW0.USE = 0;
8238 }
8239 }
8240 ucInvalidate (cpup);
8241 break;
8242
8243 /// Privileged - Configuration and Status
8244
8245 case x0 (0233): // rmcm
8246 {
8247 // C(TPR.CA)0,2 (C(TPR.CA)1,2 for the DPS 8M processor)
8248 // specify which processor port (i.e., which system
8249 // controller) is used.
8250 uint cpu_port_num;
8251 DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 15) & 03;)
8252 L68_ (cpu_port_num = (cpu.TPR.CA >> 15) & 07;)
8253 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8254 {
8255 sim_warn ("rmcm to non-existent controller on "
8256 "cpu %d port %d\r\n",
8257 current_running_cpu_idx, cpu_port_num);
8258 break;
8259 }
8260 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8261 t_stat rc = scu_rmcm ((uint) scuUnitIdx,
8262 current_running_cpu_idx,
8263 & cpu.rA, & cpu.rQ);
8264 #if defined(TESTING)
8265 HDBGRegAW ("rmcm");
8266 HDBGRegQW ("rmcm");
8267 #endif
8268 if (rc)
8269 return rc;
8270 SC_I_ZERO (cpu.rA == 0);
8271 SC_I_NEG (cpu.rA & SIGN36);
8272 }
8273 break;
8274
8275 case x0 (0413): // rscr
8276 {
8277 // For the rscr instruction, the first 2 (DPS8M) or 3 (L68) bits of
8278 // the addr field of the instruction are used to specify which SCU.
8279 // (2 bits for the DPS8M. (Expect for x6x and x7x below, where
8280 // the selected SCU is the one holding the addressed memory).
8281
8282 // According to DH02:
8283 // XXXXXX0X SCU Mode Register (Level 66 only)
8284 // XXXXXX1X Configuration switches
8285 // XXXXXn2X Interrupt mask port n
8286 // XXXXXX3X Interrupt cells
8287 // XXXXXX4X Elapsed time clock
8288 // XXXXXX5X Elapsed time clock
8289 // XXXXXX6X Mode register
8290 // XXXXXX7X Mode register
8291
8292 // According to privileged_mode_ut,
8293 // port*1024 + scr_input*8
8294
8295 // privileged_mode_ut makes no reference to the special case
8296 // of x6x and x7x.
8297
8298 // According to DH02, RSCR in Slave Mode does the CAF
8299 // without BAR correction, and then forces the CA to 040,
8300 // resulting in a Clock Read from the SCU on port 0.
8301
8302 // According to AL93, RSCR in BAR mode is IPR.
8303
8304 //
8305 // Implementing privileged_mode_ut.alm algorithm
8306 //
8307
8308 // Extract port number
8309 uint cpu_port_num;
8310 // T&D: SM781 addresses sscr/rscr through the appending unit
8311 // (pr0|0,x7 in absolute mode): the controller is the one holding
8312 // the final absolute address (as with Multics' SCAS); otherwise
8313 // C(TPR.CA)1,2 (AL39). Multics (privileged_mode_ut) uses
8314 // port*1024, i.e. >> 10.
8315 if (! (cpu.tweaks.tandd_mode && scr_port_from_final_address (cpup, & cpu_port_num)))
8316 {
8317 uint shift = cpu.tweaks.tandd_mode ? 15 : 10;
8318 DPS8M_ (cpu_port_num = (cpu.TPR.CA >> shift) & 03;)
8319 L68_ (cpu_port_num = (cpu.TPR.CA >> shift) & 07;)
8320 }
8321
8322 // Trace the cable from the port to find the SCU number
8323 // connected to that port
8324 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8325 {
8326 // CPTUR (cptUseFR) -- will be set by doFault
8327
8328 // Set IAn in Fault register
8329 if (cpu_port_num == 0)
8330 putbits36 (& cpu.faultRegister[0], 16, 4, 010);
8331 else if (cpu_port_num == 1)
8332 putbits36 (& cpu.faultRegister[0], 20, 4, 010);
8333 else if (cpu_port_num == 2)
8334 putbits36 (& cpu.faultRegister[0], 24, 4, 010);
8335 else
8336 putbits36 (& cpu.faultRegister[0], 28, 4, 010);
8337
8338 doFault (FAULT_CMD, fst_cmd_ctl, "(rscr)");
8339 }
8340 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8341 #if defined(PANEL68)
8342 {
8343 uint function = (cpu.iefpFinalAddress >> 3) & 07;
8344 CPT (cpt13L, function);
8345 }
8346 #endif
8347 t_stat rc = scu_rscr (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
8348 cpu.iefpFinalAddress & MASK15,
8349 & cpu.rA, & cpu.rQ);
8350 #if defined(TESTING)
8351 HDBGRegAW ("rscr");
8352 HDBGRegQW ("rscr");
8353 #endif
8354 if (rc)
8355 return rc;
8356 }
8357 break;
8358
8359 case x0 (0231): // rsw
8360 {
8361 if (! cpu.tweaks.l68_mode) {
8362 word6 rTAG = GET_TAG (IWB_IRODD);
8363 word6 Td = GET_TD (rTAG);
8364 word6 Tm = GET_TM (rTAG);
8365 if (Tm == TM_R && Td == TD_DL)
8366 {
8367 unsigned char PROM[1024];
8368 setupPROM (current_running_cpu_idx, PROM);
8369 cpu.rA = PROM[cpu.TPR.CA & 1023];
8370 break;
8371 }
8372 } // DPS8M
8373 uint select = cpu.TPR.CA & 0x7;
8374 switch (select)
8375 {
8376 case 0: // data switches
8377 cpu.rA = cpu.switches.data_switches;
8378 break;
8379
8380 case 1: // configuration switches for ports A, B, C, D
8381 // y = 1:
8382 //
8383 // 0 0 0 1 1 2 2 3
8384 // 0 8 9 7 8 6 7 5
8385 // -------------------------------------------------------------------------
8386 // | PORT A | PORT B | PORT C | PORT D |
8387 // -------------------------------------------------------------------------
8388 // | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM |
8389 // -------------------------------------------------------------------------
8390 //
8391 //
8392 // ADR: Address assignment switch setting for port
8393 // This defines the base address for the SCU
8394 // j: port enabled flag
8395 // k: system initialize enabled flag
8396 // l: interface enabled flag
8397 // MEM coded memory size
8398 // 000 32K 2^15
8399 // 001 64K 2^16
8400 // 010 128K 2^17
8401 // 011 256K 2^18
8402 // 100 512K 2^19
8403 // 101 1024K 2^20
8404 // 110 2048K 2^21
8405 // 111 4096K 2^22
8406
8407 cpu.rA = 0;
8408 cpu.rA |= (word36) (cpu.switches.assignment [0] & 07LL)
8409 << (35 - (2 + 0));
8410 cpu.rA |= (word36) (cpu.switches.enable [0] & 01LL)
8411 << (35 - (3 + 0));
8412 cpu.rA |= (word36) (cpu.switches.init_enable [0] & 01LL)
8413 << (35 - (4 + 0));
8414 cpu.rA |= (word36) (cpu.switches.interlace [0] ? 1LL:0LL)
8415 << (35 - (5 + 0));
8416 cpu.rA |= (word36) (cpu.switches.store_size [0] & 07LL)
8417 << (35 - (8 + 0));
8418
8419 cpu.rA |= (word36) (cpu.switches.assignment [1] & 07LL)
8420 << (35 - (2 + 9));
8421 cpu.rA |= (word36) (cpu.switches.enable [1] & 01LL)
8422 << (35 - (3 + 9));
8423 cpu.rA |= (word36) (cpu.switches.init_enable [1] & 01LL)
8424 << (35 - (4 + 9));
8425 cpu.rA |= (word36) (cpu.switches.interlace [1] ? 1LL:0LL)
8426 << (35 - (5 + 9));
8427 cpu.rA |= (word36) (cpu.switches.store_size [1] & 07LL)
8428 << (35 - (8 + 9));
8429
8430 cpu.rA |= (word36) (cpu.switches.assignment [2] & 07LL)
8431 << (35 - (2 + 18));
8432 cpu.rA |= (word36) (cpu.switches.enable [2] & 01LL)
8433 << (35 - (3 + 18));
8434 cpu.rA |= (word36) (cpu.switches.init_enable [2] & 01LL)
8435 << (35 - (4 + 18));
8436 cpu.rA |= (word36) (cpu.switches.interlace [2] ? 1LL:0LL)
8437 << (35 - (5 + 18));
8438 cpu.rA |= (word36) (cpu.switches.store_size [2] & 07LL)
8439 << (35 - (8 + 18));
8440
8441 cpu.rA |= (word36) (cpu.switches.assignment [3] & 07LL)
8442 << (35 - (2 + 27));
8443 cpu.rA |= (word36) (cpu.switches.enable [3] & 01LL)
8444 << (35 - (3 + 27));
8445 cpu.rA |= (word36) (cpu.switches.init_enable [3] & 01LL)
8446 << (35 - (4 + 27));
8447 cpu.rA |= (word36) (cpu.switches.interlace [3] ? 1LL:0LL)
8448 << (35 - (5 + 27));
8449 cpu.rA |= (word36) (cpu.switches.store_size [3] & 07LL)
8450 << (35 - (8 + 27));
8451 break;
8452
8453 case 2: // fault base and processor number switches
8454 // y = 2:
8455 //
8456 // 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 3 3 3
8457 // 0 3 4 5 6 2 3 4 7 8 9 0 1 2 3 4 5 6 8 9 2 3 5
8458 // --------------------------------------------------------------------------
8459 // |A|B|C|D| | | | | | | | | | | | | | |
8460 // --------- b | FLT BASE |c|0 0 0 0|d|e|f|0 0|g|h|i|0 0 0| SPEED | CPU |
8461 // |a|a|a|a| | | | | | | | | | | | | | |
8462 // --------------------------------------------------------------------------
8463 //
8464
8465 // a: port A-D is 0: 4 word or 1: 2 word
8466 // b: processor type 0:L68 or DPS, 1: DPS8M, 2,3: reserved for future use
8467 // c: id prom 0: not installed, 1: installed
8468 // d: 1: bcd option installed (marketing designation)
8469 // e: 1: dps option installed (marketing designation)
8470 // f: 1: 8k cache installed
8471 // g: processor type designation: 0: dps8/xx, 1: dps8m/xx
8472 // h: gcos/vms switch position: 0:GCOS mode 1: virtual mode
8473 // i: current or new product line peripheral type: 0:CPL, 1:NPL
8474 // SPEED: 0000 = 8/70, 0100 = 8/52
8475 // CPU: Processor number
8476 // DPS 8M processors:
8477 // C(Port interlace, Ports A-D) -> C(A) 0,3
8478 // 01 -> C(A) 4,5
8479 // C(Fault base switches) -> C(A) 6,12
8480 // 1 -> C(A) 13
8481 // 0000 -> C(A) 14,17
8482 // 111 -> C(A) 18,20
8483 // 00 -> C(A) 21,22
8484 // 1 -> C(A) 23
8485 // C(Processor mode sw) -> C(A) 24
8486 // 1 -> C(A) 25
8487 // 000 -> C(A) 26,28
8488 // C(Processor speed) -> C (A) 29,32
8489
8490 // C(Processor number switches) -> C(A) 33,35
8491
8492 // According to bound_gcos_.1.s.archive/gcos_fault_processor_.pl1 (L68/DPS):
8493 //
8494 // /* Set the A register to reflect switch info. */
8495 // mc.regs.a =
8496 //
8497 // /* (A-reg bits) */
8498 // /* (0-3) Port address expansion option: */ (4)"0"b
8499 // /* (4-5) Reserved for future use: */ || (2)"0"b
8500 // /* (6-12) Processor fault base address switches: */ || (7)"0"b
8501 // /* (13-16) L66 peripheral connectability: */ || (4)"0"b
8502 // /* (17) Future use (must be zero): */ || (1)"1"b
8503 // /* (18) BCD option installed: */ || (1)"1"b
8504 // /* (19) DPS type processor: */ || (1)"0"b
8505 // /* (20) 8K cache option installed: */ || (1)"0"b
8506 // /* (21) Gear shift model processor: */ || (1)"0"b
8507 // /* (22) Power patch option installed: */ || (1)"0"b
8508 // /* (23) VMS-CU option installed - 66B' proc: */ || (1)"0"b
8509 // /* (24) VMS-VU option installed - 66B proc: */ || (1)"0"b
8510 // /* (25) Type processor (0) CPL, (1) DPSE-NPL: */ || (1)"0"b
8511 // /* (26) 6025, 6605 or 6610 type processor: */ || (1)"0"b
8512 // /* (27) 2K cache option installed: */ || (1)"0"b
8513 // /* (28) Extended memory option installed: */ || (1)"0"b
8514 // /* (29-30) cabinet (00) 8/70, (01) 8/52, (10) 862, (11) 846: */ || (2)"0"b
8515 // /* (31) EIS option installed: */ || (1)"1"b
8516 // /* (32) (1) slow memory access, (0) fast memory: */ || (1)"0"b
8517 // /* (33) (1) no instruction overlap, (0) overlap: */ || (1)"0"b
8518 // /* (34-35) Processor number: */ ||unspec (mc.cpu_type);
8519
8520 cpu.rA = 0;
8521 DPS8M_ (
8522 cpu.rA |= (word36) ((cpu.switches.interlace[0] == 2 ?
8523 1LL : 0LL) << (35- 0));
8524 cpu.rA |= (word36) ((cpu.switches.interlace[1] == 2 ?
8525 1LL : 0LL) << (35- 1));
8526 cpu.rA |= (word36) ((cpu.switches.interlace[2] == 2 ?
8527 1LL : 0LL) << (35- 2));
8528 cpu.rA |= (word36) ((cpu.switches.interlace[3] == 2 ?
8529 1LL : 0LL) << (35- 3));
8530 )
8531
8532 if (cpu.tweaks.l68_mode)
8533 // NO-OP
8534 // cpu.rA |= (word36) ((00L) /* 0b00 L68/DPS */
8535 // << (35- 5));
8536 ;
8537 else
8538 cpu.rA |= (word36) ((01L) /* 0b01 DPS8M */
8539 << (35- 5));
8540 cpu.rA |= (word36) ((cpu.switches.FLT_BASE & 0177LL)
8541 << (35-12));
8542 DPS8M_ (cpu.rA |= (word36) ((01L) /* 0b1 ID_PROM installed */
8543 << (35-13));)
8544 // NO-OP
8545 // cpu.rA |= (word36) ((00L) // 0b0000
8546 // << (35-17));
8547 //cpu.rA |= (word36) ((0b111L)
8548 //<< (35-20));
8549 // According to rsw.incl.pl1, Multics ignores this bit.
8550 // NO-OP
8551 // cpu.rA |= (word36) ((00L) // 0b0 BCD option off
8552 // << (35-18));
8553 if (cpu.tweaks.l68_mode)
8554 // NO-OP
8555 // cpu.rA |= (word36) ((00L) // 0b0 L68/DPS option: L68
8556 // << (35-19));
8557 ;
8558 else
8559 cpu.rA |= (word36) ((01L) // 0b1 L68/DPS option: DPS
8560 << (35-19));
8561 DPS8M_ (
8562 // 8K cache
8563 // 0b0: not installed
8564 // 0b1: installed
8565 cpu.rA |= (word36) ((cpu.switches.enable_cache ? 1 : 0)
8566 << (35-20));
8567 // NO-OP
8568 // cpu.rA |= (word36) ((00L) // 0b00
8569 // << (35-22));
8570 // g: 1 = DPS8M processor type designation. h: GCOS/VMS
8571 // switch, 1 = virtual mode; rsw.incl.pl1 calls it
8572 // multics_cpu, "always 1 for Multics cpu" (procModeMultics
8573 // is 0, so the old procMode bits were 0 in Multics mode).
8574 // The T&D PAS executive halts unless h is 1.
8575 cpu.rA |= (word36) (1LL << (35-23));
8576 cpu.rA |= (word36) ((cpu.switches.procMode == procModeMultics ? 1LL : 0LL)
8577 << (35-24));
8578 // NO-OP
8579 // cpu.rA |= (word36) ((00L) // 0b0 new product line (CPL/NPL)
8580 // << (35-25));
8581 // NO-OP
8582 // cpu.rA |= (word36) ((00L) // 0b000
8583 // << (35-28));
8584 cpu.rA |= (word36) ((cpu.options.proc_speed & 017LL)
8585 << (35-32));
8586 )
8587
8588 L68_ (
8589 // NO-OP
8590 // cpu.rA |= (word36) ((00L) // 0b0 2K cache disabled
8591 // << (35-27));
8592 // NO-OP
8593 // cpu.rA |= (word36) ((00L) // 0b0 GCOS mode extended memory disabled
8594 // << (35-28));
8595 cpu.rA |= (word36) ((016L) // 0b1110 CPU ID
8596 << (35-32));
8597 )
8598 cpu.rA |= (word36) ((cpu.switches.cpu_num & 07LL)
8599 << (35-35));
8600 break;
8601
8602 case 3: // configuration switches for ports E, F, G, H
8603 if (!cpu.tweaks.l68_mode) { // DPS8M
8604 cpu.rA = 0;
8605 break;
8606 }
8607 // L68
8608 // y = 3:
8609 //
8610 // 0 0 0 1 1 2 2 3
8611 // 0 8 9 7 8 6 7 5
8612 // -------------------------------------------------------------------------
8613 // | PORT E | PORT F | PORT G | PORT H |
8614 // -------------------------------------------------------------------------
8615 // | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM | ADR |j|k|l| MEM |
8616 // -------------------------------------------------------------------------
8617 //
8618 //
8619 // ADR: Address assignment switch setting for port
8620 // This defines the base address for the SCU
8621 // j: port enabled flag
8622 // k: system initialize enabled flag
8623 // l: interface enabled flag
8624 // MEM coded memory size
8625 // 000 32K 2^15
8626 // 001 64K 2^16
8627 // 010 128K 2^17
8628 // 011 256K 2^18
8629 // 100 512K 2^19
8630 // 101 1024K 2^20
8631 // 110 2048K 2^21
8632 // 111 4096K 2^22
8633
8634 cpu.rA = 0;
8635 cpu.rA |= (word36) (cpu.switches.assignment [4] & 07LL)
8636 << (35 - (2 + 0));
8637 cpu.rA |= (word36) (cpu.switches.enable [4] & 01LL)
8638 << (35 - (3 + 0));
8639 cpu.rA |= (word36) (cpu.switches.init_enable [4] & 01LL)
8640 << (35 - (4 + 0));
8641 cpu.rA |= (word36) (cpu.switches.interlace [4] ? 1LL:0LL)
8642 << (35 - (5 + 0));
8643 cpu.rA |= (word36) (cpu.switches.store_size [4] & 07LL)
8644 << (35 - (8 + 0));
8645
8646 cpu.rA |= (word36) (cpu.switches.assignment [5] & 07LL)
8647 << (35 - (2 + 9));
8648 cpu.rA |= (word36) (cpu.switches.enable [5] & 01LL)
8649 << (35 - (3 + 9));
8650 cpu.rA |= (word36) (cpu.switches.init_enable [5] & 01LL)
8651 << (35 - (4 + 9));
8652 cpu.rA |= (word36) (cpu.switches.interlace [5] ? 1LL:0LL)
8653 << (35 - (5 + 9));
8654 cpu.rA |= (word36) (cpu.switches.store_size [5] & 07LL)
8655 << (35 - (8 + 9));
8656
8657 cpu.rA |= (word36) (cpu.switches.assignment [6] & 07LL)
8658 << (35 - (2 + 18));
8659 cpu.rA |= (word36) (cpu.switches.enable [6] & 01LL)
8660 << (35 - (3 + 18));
8661 cpu.rA |= (word36) (cpu.switches.init_enable [6] & 01LL)
8662 << (35 - (4 + 18));
8663 cpu.rA |= (word36) (cpu.switches.interlace [6] ? 1LL:0LL)
8664 << (35 - (5 + 18));
8665 cpu.rA |= (word36) (cpu.switches.store_size [6] & 07LL)
8666 << (35 - (8 + 18));
8667
8668 cpu.rA |= (word36) (cpu.switches.assignment [7] & 07LL)
8669 << (35 - (2 + 27));
8670 cpu.rA |= (word36) (cpu.switches.enable [7] & 01LL)
8671 << (35 - (3 + 27));
8672 cpu.rA |= (word36) (cpu.switches.init_enable [7] & 01LL)
8673 << (35 - (4 + 27));
8674 cpu.rA |= (word36) (cpu.switches.interlace [7] ? 1LL:0LL)
8675 << (35 - (5 + 27));
8676 cpu.rA |= (word36) (cpu.switches.store_size [7] & 07LL)
8677 << (35 - (8 + 27));
8678 break;
8679
8680 case 4:
8681 // I suspect the this is a L68 only, but AL39 says both
8682 // port interlace and half/full size
8683 // The DPS doesn't seem to have the half/full size switches
8684 // so we'll always report full, and the interlace bits were
8685 // squeezed into RSW 2
8686
8687 // 0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3
8688 // 0 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 5
8689 // -------------------------------------------------------------------------
8690 // | | A | B | C | D | E | F | G | H | |
8691 // |0 0 0 0 0 0 0 0 0 0 0 0 0---------------------------------0 0 0 0 0 0 0|
8692 // | |f|g|f|g|f|g|f|g|f|g|f|g|f|g|f|g| |
8693 // -------------------------------------------------------------------------
8694 // 13 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 7
8695
8696 cpu.rA = 0;
8697 cpu.rA |= (word36) (cpu.switches.interlace [0] == 2 ?
8698 1LL : 0LL) << (35-13);
8699 cpu.rA |= (word36) (cpu.switches.interlace [1] == 2 ?
8700 1LL : 0LL) << (35-15);
8701 cpu.rA |= (word36) (cpu.switches.interlace [2] == 2 ?
8702 1LL : 0LL) << (35-17);
8703 cpu.rA |= (word36) (cpu.switches.interlace [3] == 2 ?
8704 1LL : 0LL) << (35-19);
8705 L68_ (
8706 cpu.rA |= (word36) (cpu.switches.interlace [4] == 2 ?
8707 1LL : 0LL) << (35-21);
8708 cpu.rA |= (word36) (cpu.switches.interlace [5] == 2 ?
8709 1LL : 0LL) << (35-23);
8710 cpu.rA |= (word36) (cpu.switches.interlace [6] == 2 ?
8711 1LL : 0LL) << (35-25);
8712 cpu.rA |= (word36) (cpu.switches.interlace [7] == 2 ?
8713 1LL : 0LL) << (35-27);
8714 )
8715 break;
8716
8717 default:
8718 // XXX Guessing values; also we don't know if this is actually a fault
8719 doFault (FAULT_IPR,
8720 fst_ill_mod,
8721 "Illegal register select value");
8722 }
8723 #if defined(TESTING)
8724 HDBGRegAW ("rsw");
8725 #endif
8726 SC_I_ZERO (cpu.rA == 0);
8727 SC_I_NEG (cpu.rA & SIGN36);
8728 }
8729 break;
8730
8731 /// Privileged - System Control
8732
8733 case x0 (0015): // cioc
8734 {
8735
8736 #if defined(THREADZ) || defined(LOCKLESS)
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748 #endif
8749
8750 // cioc The system controller addressed by Y (i.e., contains
8751 // the word at Y) sends a connect signal to the port specified
8752 // by C(Y) 33,35.
8753 int cpu_port_num = lookup_cpu_mem_map (cpup, cpu.iefpFinalAddress);
8754 // If there is no port to that memory location, fault
8755 if (cpu_port_num < 0)
8756 {
8757 doFault (FAULT_ONC, fst_onc_nem, "(cioc)");
8758 }
8759 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8760 {
8761 doFault (FAULT_ONC, fst_onc_nem, "(cioc)");
8762 }
8763 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8764
8765 // expander word
8766 // dcl 1 scs$reconfig_general_cow aligned external, /* Used during reconfig
8767 // ops. */
8768 // 2 pad bit (36) aligned,
8769 // 2 cow, /* Connect operand word, in odd location. */
8770 // 3 sub_mask bit (8) unaligned, /* Expander sub-port mask */
8771 // 3 mbz1 bit (13) unaligned,
8772 // 3 expander_command bit (3) unaligned, /* Expander command. */
8773 // 3 mbz2 bit (9) unaligned,
8774 // 3 controller_port fixed bin (3) unaligned unsigned;/* controller port for
8775 // this CPU */
8776
8777 word8 sub_mask = getbits36_8 (cpu.CY, 0);
8778 word3 expander_command = getbits36_3 (cpu.CY, 21);
8779 uint scu_port_num = (uint) getbits36_3 (cpu.CY, 33);
8780 scu_cioc (current_running_cpu_idx, (uint) scuUnitIdx, scu_port_num,
8781 expander_command, sub_mask);
8782 }
8783 break;
8784
8785 case x0 (0553): // smcm
8786 {
8787 // C(TPR.CA)0,2 (C(TPR.CA)1,2 for the DPS 8M processor)
8788 // specify which processor port (i.e., which system
8789 // controller) is used.
8790 uint cpu_port_num;
8791 DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 15) & 03;)
8792 L68_ (cpu_port_num = (cpu.TPR.CA >> 15) & 07;)
8793 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8794 {
8795 sim_warn ("smcm to non-existent controller on "
8796 "cpu %d port %d\r\n",
8797 current_running_cpu_idx, cpu_port_num);
8798 break;
8799 }
8800 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8801 // T&D: sent with incorrect ZAC/data parity
8802 if (sc_command_parity (cpup, (uint) scuUnitIdx, cpu_port_num))
8803 break;
8804 t_stat rc = scu_smcm ((uint) scuUnitIdx,
8805 current_running_cpu_idx, cpu.rA, cpu.rQ);
8806 if (rc)
8807 return rc;
8808 }
8809 break;
8810
8811 case x0 (0451): // smic
8812 {
8813 // For the smic instruction, the first 2 or 3 bits of the addr
8814 // field of the instruction are used to specify which SCU.
8815 // 2 bits for the DPS8M.
8816 //int scuUnitIdx = getbits36_2 (TPR.CA, 0);
8817
8818 // C(TPR.CA)0,2 (C(TPR.CA)1,2 for the DPS 8M processor)
8819 // specify which processor port (i.e., which system
8820 // controller) is used.
8821 uint cpu_port_num;
8822 DPS8M_ (cpu_port_num = (cpu.TPR.CA >> 15) & 03;)
8823 L68_ (cpu_port_num = (cpu.TPR.CA >> 15) & 07;)
8824 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8825 {
8826 DPS8M_ (return SCPE_OK;)
8827 // L68
8828 // CPTUR (cptUseFR) -- will be set by doFault
8829 if (cpu_port_num == 0)
8830 putbits36_4 (& cpu.faultRegister[0], 16, 010);
8831 else if (cpu_port_num == 1)
8832 putbits36_4 (& cpu.faultRegister[0], 20, 010);
8833 else if (cpu_port_num == 2)
8834 putbits36_4 (& cpu.faultRegister[0], 24, 010);
8835 else if (cpu_port_num == 3)
8836 putbits36 (& cpu.faultRegister[0], 28, 4, 010);
8837 // XXX What if the port is > 3?
8838 doFault (FAULT_CMD, fst_cmd_ctl, "(smic)");
8839 }
8840 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8841 // T&D: sent with incorrect ZAC/data parity
8842 if (sc_command_parity (cpup, (uint) scuUnitIdx, cpu_port_num))
8843 break;
8844 t_stat rc = scu_smic (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
8845 cpu_port_num, cpu.rA);
8846 if (rc)
8847 return rc;
8848 }
8849 break;
8850
8851 case x0 (0057): // sscr
8852 {
8853 //uint cpu_port_num = (cpu.TPR.CA >> 15) & 03;
8854 // Looking at privileged_mode_ut.alm, shift 10 bits...
8855 uint cpu_port_num;
8856 // T&D: SM781 addresses sscr/rscr through the appending unit
8857 // (pr0|0,x7 in absolute mode): the controller is the one holding
8858 // the final absolute address (as with Multics' SCAS); otherwise
8859 // C(TPR.CA)1,2 (AL39). Multics (privileged_mode_ut) uses
8860 // port*1024, i.e. >> 10.
8861 if (! (cpu.tweaks.tandd_mode && scr_port_from_final_address (cpup, & cpu_port_num)))
8862 {
8863 uint shift = cpu.tweaks.tandd_mode ? 15 : 10;
8864 DPS8M_ (cpu_port_num = (cpu.TPR.CA >> shift) & 03;)
8865 L68_ (cpu_port_num = (cpu.TPR.CA >> shift) & 07;)
8866 }
8867 if (! get_scu_in_use (current_running_cpu_idx, cpu_port_num))
8868 {
8869 // CPTUR (cptUseFR) -- will be set by doFault
8870 if (cpu_port_num == 0)
8871 putbits36_4 (& cpu.faultRegister[0], 16, 010);
8872 else if (cpu_port_num == 1)
8873 putbits36_4 (& cpu.faultRegister[0], 20, 010);
8874 else if (cpu_port_num == 2)
8875 putbits36_4 (& cpu.faultRegister[0], 24, 010);
8876 else
8877 putbits36 (& cpu.faultRegister[0], 28, 4, 010);
8878 doFault (FAULT_CMD, fst_cmd_ctl, "(sscr)");
8879 }
8880 uint scuUnitIdx = get_scu_idx (current_running_cpu_idx, cpu_port_num);
8881 // T&D: sent with incorrect ZAC/data parity
8882 if (sc_command_parity (cpup, (uint) scuUnitIdx, cpu_port_num))
8883 break;
8884 t_stat rc = scu_sscr (cpup, (uint) scuUnitIdx, current_running_cpu_idx,
8885 cpu_port_num, cpu.iefpFinalAddress & MASK15,
8886 cpu.rA, cpu.rQ);
8887
8888 if (rc)
8889 return rc;
8890 }
8891 break;
8892
8893 // Privileged - Miscellaneous
8894
8895 case x0 (0212): // absa
8896 {
8897 word36 result;
8898 int rc = doABSA (cpup, & result);
8899 if (rc)
8900 return rc;
8901 cpu.rA = result;
8902 #if defined(TESTING)
8903 HDBGRegAW ("absa");
8904 #endif
8905 SC_I_ZERO (cpu.rA == 0);
8906 SC_I_NEG (cpu.rA & SIGN36);
8907 }
8908 break;
8909
8910 case x0 (0616): // dis
8911
8912 #ifdef SYNCTEST
8913 // Trap the call to sys$trouble
8914 if (cpu.PPR.PSR == 034 && cpu.PPR.IC == 03535) {
8915 # ifdef HDBG
8916 hdbgPrint ();
8917 # endif
8918 sim_printf ("sys$trouble\r\n");
8919 exit (1);
8920 }
8921 #endif
8922
8923 #if defined(THREADZ) || defined(LOCKLESS)
8924 if (cpu.forceRestart) {
8925 cpu.forceRestart = 0;
8926 longjmp (cpu.jmpMain, JMP_FORCE_RESTART);
8927 }
8928 #endif
8929
8930 if (! cpu.tweaks.dis_enable)
8931 {
8932 return STOP_STOP;
8933 }
8934
8935 // XXX This is subtle; g7Pending below won't see the queued
8936 // g7Fault. I don't understand how the real hardware dealt
8937 // with this, but this seems to work. (I would hazard a guess
8938 // that DIS was doing a continuous FETCH/EXECUTE cycle
8939 // ('if !interrupt goto .'))
8940 advanceG7Faults (cpup);
8941
8942 if ((! cpu.tweaks.tro_enable) &&
8943 (! sample_interrupts (cpup)) &&
8944 (sim_qcount () == 0)) // XXX If clk_svc is implemented it will
8945 // break this logic
8946 {
8947 sim_printf ("DIS@0%06o with no interrupts pending and"
8948 " no events in queue\r\n", cpu.PPR.IC);
8949 #if defined(WIN_STDIO)
8950 sim_printf ("\r\nCycles = %llu\r\n",
8951 #else
8952 sim_printf ("\r\nCycles = %'llu\r\n",
8953 #endif /* if defined(WIN_STDIO) */
8954 (unsigned long long)cpu.cycleCnt);
8955 #if defined(WIN_STDIO)
8956 sim_printf ("\r\nInstructions = %llu\r\n",
8957 #else
8958 sim_printf ("\r\nInstructions = %'llu\r\n",
8959 #endif /* if defined(WIN_STDIO) */
8960 (unsigned long long)cpu.cycleCnt);
8961 longjmp (cpu.jmpMain, JMP_STOP);
8962 }
8963
8964 // Multics/BCE halt
8965 if (cpu.PPR.PSR == 0430 && cpu.PPR.IC == 012)
8966 {
8967 sim_printf ("BCE DIS causes CPU halt\r\n");
8968 sim_debug (DBG_MSG, & cpu_dev, "BCE DIS causes CPU halt\r\n");
8969 #if defined(LOCKLESS)
8970 bce_dis_called = true;
8971 #endif // LOCKLESS
8972 longjmp (cpu.jmpMain, JMP_STOP);
8973 }
8974
8975 #if defined(THREADZ) || defined(LOCKLESS)
8976 // RCF halt
8977 // XXX pxss uses a distinctive DIS operation
8978 // for RCF DELETE. If we see it, remember that
8979 // we did.
8980 if (IWB_IRODD == 0000777616207) {
8981 //HDBGNote (cpup, "DIS", "DIS clears inMultics%s", "");
8982 cpu.inMultics = false;
8983 }
8984
8985 // ISOLTS start:
8986 // CPU B thread created.
8987 // DBG(1)> CPU 1 TRACE: 000000 0 000000616000 (DIS 000000)
8988 // DBG(3)> CPU 1 INTR: Interrupt pair address 0
8989 // DBG(3)> CPU 1 FINAL: intr even read 00000000 000000755200
8990 // DBG(3)> CPU 1 FINAL: intr odd read 00000001 000000616200
8991 // DBG(4)> CPU 1 TRACE: 000001 0 000000755200 (STA 000000)
8992 // DBG(4)> CPU 1 REG: sta read A 000000000000
8993 // DBG(4)> CPU 1 IEFP ABS WRITE: :000000
8994 // DBG(4)> CPU 1 FINAL: WriteOperandStore AB write 00000000 000000000000
8995 // DBG(5)> CPU 1 TRACE: 000001 0 000000616200 (DIS 000000)
8996 // There are different behaviors for various configuration errors.
8997 // If ISOLTS mode is not set, we see an IWB_IRODD of 0000000616200
8998 // If set, 0000001616200
8999
9000 // If we do a DIS while sync clock master, and are inMultics,
9001 // cancel sync clock... But not the processor startup DIS
9002
9003 if (UNLIKELY (cpu.syncClockModeMaster) &&
9004 cpu.inMultics &&
9005 (cpu.PPR.PSR !=0 || cpu.PPR.IC != 0)) {
9006 # ifdef SYNCTEST
9007 sim_printf ("CPU%c DIS %o:%o gives up master\r\n", cpu.cpuIdx + 'A', cpu.PPR.PSR, cpu.PPR.IC);
9008 # endif
9009 //HDBGNote (cpup, "DIS", "DIS give up clock master%s", "");
9010 giveupClockMaster (cpup);
9011 }
9012 #endif
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033 sim_debug (DBG_TRACEEXT, & cpu_dev, "entered DIS_cycle\r\n");
9034
9035 // No operation takes place, and the processor does not
9036 // continue with the next instruction; it waits for a
9037 // external interrupt signal.
9038 // AND, according to pxss.alm, TRO
9039
9040 // Bless NovaScale...
9041 // DIS
9042 //
9043 // NOTES:
9044 //
9045 // 1. The inhibit bit in this instruction only affects the recognition
9046 // of a Timer Runout (TROF) fault.
9047 //
9048 // Inhibit ON delays the recognition of a TROF until the processor
9049 // enters Slave mode.
9050 //
9051 // Inhibit OFF allows the TROF to interrupt the DIS state.
9052 //
9053 // 2. For all other faults and interrupts, the inhibit bit is ignored.
9054 //
9055 // 3. The use of this instruction in the Slave or Master mode causes a
9056 // Command fault.
9057
9058 disDiagEnter (cpup);
9059 if (sample_interrupts (cpup))
9060 {
9061 disDiagWake (cpup);
9062 sim_debug (DBG_TRACEEXT, & cpu_dev, "DIS sees an interrupt\r\n");
9063 cpu.interrupt_flag = true;
9064 break;
9065 }
9066 // EXECUTE DATA SWITCHES: see FETCH_cycle
9067 if (cpu.execSwitchesReq)
9068 break;
9069 // Implementing TRO according to AL39 for the DIS cause the idle systems to
9070 // hang in the DIS instruction. Revert back to the old behavior.
9071
9072 if (GET_I (cpu.cu.IWB) ? bG7PendingNoTRO (cpup) : bG7Pending (cpup))
9073
9074
9075
9076
9077
9078
9079
9080
9081 {
9082 sim_debug (DBG_TRACEEXT, & cpu_dev, "DIS sees a TRO\r\n");
9083 cpu.g7_flag = true;
9084 break;
9085 }
9086 else
9087 {
9088 sim_debug (DBG_TRACEEXT, & cpu_dev, "DIS refetches\r\n");
9089 return CONT_DIS;
9090 }
9091
9092 /// POINTER REGISTER INSTRUCTIONS
9093
9094 /// PRIVILEGED INSTRUCTIONS
9095
9096 /// Privileged - Register Load
9097
9098 /// Privileged - Clear Associative Memory
9099
9100 /// EIS - Address Register Load
9101
9102 // aarn
9103 case x1 (0560): // aar0
9104 case x1 (0561): // aar1
9105 case x1 (0562): // aar2
9106 case x1 (0563): // aar3
9107 case x1 (0564): // aar4
9108 case x1 (0565): // aar5
9109 case x1 (0566): // aar6
9110 case x1 (0567): // aar7
9111 {
9112 // For n = 0, 1, ..., or 7 as determined by operation code
9113 PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9114
9115 if (getbits36_1 (cpu.CY, 23) != 0)
9116 doFault (FAULT_IPR,
9117 fst_ill_proc,
9118 "aarn C(Y)23 != 0");
9119
9120 uint32 n = opcode10 & 07; // get
9121 CPTUR (cptUsePRn + n);
9122
9123 // C(Y)0,17 -> C(ARn.WORDNO)
9124 cpu.AR[n].WORDNO = GETHI (cpu.CY);
9125
9126 uint TA = getbits36_2 (cpu.CY, 21);
9127 uint CN = getbits36_3 (cpu.CY, 18);
9128
9129 switch (TA)
9130 {
9131 case CTA4: // 2
9132 // If C(Y)21,22 = 10 (TA code = 2), then
9133 // C(Y)18,20 / 2 -> C(ARn.CHAR)
9134 // 4 * (C(Y)18,20)mod2 + 1 -> C(ARn.BITNO)
9135
9136 // According to AL39, CN is translated:
9137 // CN CHAR BIT
9138 // 0 0 1
9139 // 1 0 5
9140 // 2 1 1
9141 // 3 1 5
9142 // 4 2 1
9143 // 5 2 5
9144 // 6 3 1
9145 // 7 3 5
9146 //SET_AR_CHAR_BITNO (n, CN/2, 4 * (CN % 2) + 1);
9147
9148 // According to ISOLTS ps805
9149 // CN CHAR BIT
9150 // 0 0 0
9151 // 1 0 5
9152 // 2 1 0
9153 // 3 1 5
9154 // 4 2 0
9155 // 5 2 5
9156 // 6 3 0
9157 // 7 3 5
9158 SET_AR_CHAR_BITNO (n, (word2) (CN/2), (CN % 2) ? 5 : 0);
9159
9160 break;
9161
9162 case CTA6: // 1
9163 // If C(Y)21,22 = 01 (TA code = 1) and C(Y)18,20 = 110
9164 // or 111 an illegal procedure fault occurs.
9165 if (CN > 5)
9166 {
9167 cpu.AR[n].WORDNO = 0;
9168 SET_AR_CHAR_BITNO (n, 0, 0);
9169 doFault (FAULT_IPR, fst_ill_proc, "aarn TN > 5");
9170 }
9171
9172 // If C(Y)21,22 = 01 (TA code = 1), then
9173 // (6 * C(Y)18,20) / 9 -> C(ARn.CHAR)
9174 // (6 * C(Y)18,20)mod9 -> C(ARn.BITNO)
9175 SET_AR_CHAR_BITNO (n, (word2) ((6 * CN) / 9),
9176 (6 * CN) % 9);
9177 break;
9178
9179 case CTA9: // 0
9180 // If C(Y)21,22 = 00 (TA code = 0), then
9181 // C(Y)18,19 -> C(ARn.CHAR)
9182 // 0000 -> C(ARn.BITNO)
9183 // remember, 9-bit CN's are funky
9184 SET_AR_CHAR_BITNO (n, (word2) (CN >> 1), 0);
9185 break;
9186
9187 case CTAILL: // 3
9188 // If C(Y)21,22 = 11 (TA code = 3) an illegal procedure
9189 // fault occurs.
9190 cpu.AR[n].WORDNO = 0;
9191 SET_AR_CHAR_BITNO (n, 0, 0);
9192 #if defined(TESTING)
9193 HDBGRegARW (n, "aarn");
9194 #endif
9195 doFault (FAULT_IPR, fst_ill_proc, "aarn TA = 3");
9196 }
9197 #if defined(TESTING)
9198 HDBGRegARW (n, "aarn");
9199 #endif
9200 }
9201 break;
9202
9203 // Load Address Register n
9204 // larn
9205 case x1 (0760): // lar0
9206 case x1 (0761): // lar1
9207 case x1 (0762): // lar2
9208 case x1 (0763): // lar3
9209 case x1 (0764): // lar4
9210 case x1 (0765): // lar5
9211 case x1 (0766): // lar6
9212 case x1 (0767): // lar7
9213 {
9214 // For n = 0, 1, ..., or 7 as determined by operation code
9215 // C(Y)0,23 -> C(ARn)
9216 PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9217
9218 uint32 n = opcode10 & 07; // get n
9219 CPTUR (cptUsePRn + n);
9220 cpu.AR[n].WORDNO = GETHI (cpu.CY);
9221 // AL-38 implies CHAR/BITNO, but ISOLTS requires PR.BITNO.
9222 SET_AR_CHAR_BITNO (n, getbits36_2 (cpu.CY, 18),
9223 getbits36_4 (cpu.CY, 20));
9224 #if defined(TESTING)
9225 HDBGRegARW (n, "larn");
9226 #endif
9227 }
9228 break;
9229
9230 // lareg - Load Address Registers
9231
9232 case x1 (0463): // lareg
9233 PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9234
9235 for (uint32 n = 0 ; n < 8 ; n += 1)
9236 {
9237 CPTUR (cptUsePRn + n);
9238 word36 tmp36 = cpu.Yblock8[n];
9239 cpu.AR[n].WORDNO = getbits36_18 (tmp36, 0);
9240 SET_AR_CHAR_BITNO (n, getbits36_2 (tmp36, 18),
9241 getbits36_4 (tmp36, 20));
9242 #if defined(TESTING)
9243 HDBGRegARW (n, "lareg");
9244 #endif
9245 }
9246 break;
9247
9248 // lpl - Load Pointers and Lengths
9249
9250 case x1 (0467): // lpl
9251 PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9252 words2du (cpup, cpu.Yblock8);
9253 break;
9254
9255 // narn - (G'Kar?) Numeric Descriptor to Address Register n
9256 // narn
9257 case x1 (0660): // nar0
9258 case x1 (0661): // nar1
9259 case x1 (0662): // nar2
9260 case x1 (0663): // nar3
9261 case x1 (0664): // nar4
9262 case x1 (0665): // nar5
9263 case x1 (0666): // nar6 beware!!!! :-)
9264 case x1 (0667): // nar7
9265 {
9266 // For n = 0, 1, ..., or 7 as determined by operation code
9267 PNL (L68_ (DU_CYCLE_DDU_LDEA;))
9268
9269 uint32 n = opcode10 & 07; // get
9270 CPTUR (cptUsePRn + n);
9271
9272 // C(Y)0,17 -> C(ARn.WORDNO)
9273 cpu.AR[n].WORDNO = GETHI (cpu.CY);
9274
9275 uint TN = getbits36_1 (cpu.CY, 21); // C(Y) 21
9276 uint CN = getbits36_3 (cpu.CY, 18); // C(Y) 18-20
9277
9278 switch(TN)
9279 {
9280 case CTN4: // 1
9281 // If C(Y)21 = 1 (TN code = 1), then
9282 // (C(Y)18,20) / 2 -> C(ARn.CHAR)
9283 // 4 * (C(Y)18,20)mod2 + 1 -> C(ARn.BITNO)
9284
9285 // According to AL39, CN is translated:
9286 // CN CHAR BIT
9287 // 0 0 1
9288 // 1 0 5
9289 // 2 1 1
9290 // 3 1 5
9291 // 4 2 1
9292 // 5 2 5
9293 // 6 3 1
9294 // 7 3 5
9295 //SET_AR_CHAR_BITNO (n, CN/2, 4 * (CN % 2) + 1);
9296
9297 // According to ISOLTS ps805
9298 // CN CHAR BIT
9299 // 0 0 0
9300 // 1 0 5
9301 // 2 1 0
9302 // 3 1 5
9303 // 4 2 0
9304 // 5 2 5
9305 // 6 3 0
9306 // 7 3 5
9307 SET_AR_CHAR_BITNO (n, (word2) (CN/2), (CN % 2) ? 5 : 0);
9308
9309 break;
9310
9311 case CTN9: // 0
9312 // If C(Y)21 = 0 (TN code = 0) and C(Y)20 = 1 an
9313 // illegal procedure fault occurs.
9314 if ((CN & 1) != 0)
9315 doFault (FAULT_IPR, fst_ill_proc, "narn N9 and CN odd");
9316 // The character number is in bits 18-19; recover it
9317 CN >>= 1;
9318 // If C(Y)21 = 0 (TN code = 0), then
9319 // C(Y)18,20 -> C(ARn.CHAR)
9320 // 0000 -> C(ARn.BITNO)
9321 SET_AR_CHAR_BITNO (n, (word2) CN, 0);
9322 break;
9323 }
9324 #if defined(TESTING)
9325 HDBGRegARW (n, "narn");
9326 #endif
9327 }
9328 break;
9329
9330 /// EIS - Address Register Store
9331
9332 // aran Address Register n to Alphanumeric Descriptor
9333
9334 // aran
9335 case x1 (0540): // ara0
9336 case x1 (0541): // ara1
9337 case x1 (0542): // ara2
9338 case x1 (0543): // ara3
9339 case x1 (0544): // ara4
9340 case x1 (0545): // ara5
9341 case x1 (0546): // ara6
9342 case x1 (0547): // ara7
9343 {
9344 // The alphanumeric descriptor is fetched from Y and C(Y)21,22
9345 // (TA field) is examined to determine the data type described.
9346 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9347
9348 uint TA = getbits36_2 (cpu.CY, 21);
9349
9350 // If C(Y)21,22 = 11 (TA code = 3) or C(Y)23 = 1 (unused bit),
9351 // an illegal procedure fault occurs.
9352 if (TA == 03) {
9353 dlyDoFault (FAULT_IPR, fst_ill_proc, "ARAn tag == 3");
9354 break;
9355 }
9356 if (getbits36_1 (cpu.CY, 23) != 0) {
9357 dlyDoFault (FAULT_IPR, fst_ill_proc, "ARAn b23 == 1");
9358 break;
9359 }
9360
9361 uint32 n = opcode10 & 07; // get
9362 CPTUR (cptUsePRn + n);
9363 // For n = 0, 1, ..., or 7 as determined by operation code
9364
9365 // C(ARn.WORDNO) -> C(Y)0,17
9366 putbits36_18 (& cpu.CY, 0, cpu.AR[n].WORDNO & MASK18);
9367
9368 // If TA = 1 (6-bit data) or TA = 2 (4-bit data), C(ARn.CHAR)
9369 // and C(ARn.BITNO) are translated to an equivalent character
9370 // position that goes to C(Y)18,20.
9371
9372 int CN = 0;
9373
9374 switch (TA)
9375 {
9376 case CTA4: // 2
9377 // If C(Y)21,22 = 10 (TA code = 2), then
9378 // (9 * C(ARn.CHAR) + C(ARn.BITNO) - 1) / 4 -> C(Y)18,20
9379 // As for arnn: the digit holding the bit (see there).
9380 CN = (int) (2 * GET_AR_CHAR (n) +
9381 (GET_AR_BITNO (n) >= 5 ? 1 : 0));
9382 putbits36_3 (& cpu.CY, 18, (word3) CN & MASK3);
9383 break;
9384
9385 case CTA6: // 1
9386 // If C(Y)21,22 = 01 (TA code = 1), then
9387 // (9 * C(ARn.CHAR) + C(ARn.BITNO)) / 6 -> C(Y)18,20
9388 // An AR BITNO of 9-15 (LAREG) counts as 8 (ISOLTS
9389 // PS905 ara0: CHAR 2 BITNO 016 s/b CN 4, not 5; as
9390 // for EIS operands, pas.905 L34325)
9391 CN = (9 * GET_AR_CHAR (n) +
9392 min (GET_AR_BITNO (n), 8)) / 6;
9393 putbits36_3 (& cpu.CY, 18, (word3) CN & MASK3);
9394 break;
9395
9396 case CTA9: // 0
9397 // If C(Y)21,22 = 00 (TA code = 0), then
9398 // C(ARn.CHAR) -> C(Y)18,19
9399 // 0 -> C(Y)20
9400 putbits36_3 (& cpu.CY, 18,
9401 (word3) ((GET_AR_CHAR (n) & MASK2) << 1));
9402 break;
9403 }
9404 cpu.zone = 0777777700000;
9405 cpu.useZone = true;
9406 }
9407 break;
9408
9409 // arnn Address Register n to Numeric Descriptor
9410
9411 // arnn
9412 case x1 (0640): // arn0
9413 case x1 (0641): // arn1
9414 case x1 (0642): // arn2
9415 case x1 (0643): // arn3
9416 case x1 (0644): // arn4
9417 case x1 (0645): // arn5
9418 case x1 (0646): // arn6
9419 case x1 (0647): // arn7
9420 {
9421 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9422 uint32 n = opcode10 & 07; // get register #
9423 CPTUR (cptUsePRn + n);
9424
9425 // The Numeric descriptor is fetched from Y and C(Y)21,22 (TA
9426 // field) is examined to determine the data type described.
9427
9428 uint TN = getbits36_1 (cpu.CY, 21); // C(Y) 21
9429
9430 // For n = 0, 1, ..., or 7 as determined by operation code
9431 // C(ARn.WORDNO) -> C(Y)0,17
9432 putbits36_18 (& cpu.CY, 0, cpu.AR[n].WORDNO & MASK18);
9433
9434 switch (TN)
9435 {
9436 case CTN4: // 1
9437 {
9438 // AL39: If C(Y)21 = 1 (TN code = 1) then
9439 // (9 * C(ARn.CHAR) + C(ARn.BITNO) - 1) / 4 ->
9440 // C(Y)18,20
9441 // That treats the word as a linear bit string, but
9442 // a 9-bit character holds a pad bit and two 4-bit
9443 // digits (bits 1-4 and 5-8), so CN is the digit
9444 // holding the addressed bit: 2 * CHAR, plus 1 for
9445 // BITNO 5-8. ISOLTS PS905 (ARN0, CHAR 2, BITNO 4)
9446 // expects 4, where the AL39 formula gives 5.
9447 word3 CN = (word3) (2 * GET_AR_CHAR (n) +
9448 (GET_AR_BITNO (n) >= 5 ? 1 : 0));
9449 putbits36_3 (& cpu.CY, 18, CN & MASK3);
9450 break;
9451 }
9452 case CTN9: // 0
9453 // If C(Y)21 = 0 (TN code = 0), then
9454 // C(ARn.CHAR) -> C(Y)18,19
9455 // 0 -> C(Y)20
9456 putbits36_3 (& cpu.CY, 18,
9457 (word3) ((GET_AR_CHAR (n) & MASK2) << 1));
9458 break;
9459 }
9460 cpu.zone = 0777777700000;
9461 cpu.useZone = true;
9462 }
9463 break;
9464
9465 // sarn Store Address Register n
9466
9467 // sarn
9468 case x1 (0740): // sar0
9469 case x1 (0741): // sar1
9470 case x1 (0742): // sar2
9471 case x1 (0743): // sar3
9472 case x1 (0744): // sar4
9473 case x1 (0745): // sar5
9474 case x1 (0746): // sar6
9475 case x1 (0747): // sar7
9476 //For n = 0, 1, ..., or 7 as determined by operation code
9477 // C(ARn) -> C(Y)0,23
9478 // C(Y)24,35 -> unchanged
9479 {
9480 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9481 uint32 n = opcode10 & 07; // get n
9482 CPTUR (cptUsePRn + n);
9483 putbits36 (& cpu.CY, 0, 18, cpu.PR[n].WORDNO);
9484 // AL-39 implies CHAR/BITNO, but ISOLTS test 805 requires BITNO
9485 putbits36 (& cpu.CY, 18, 2, GET_AR_CHAR (n));
9486 putbits36 (& cpu.CY, 20, 4, GET_AR_BITNO (n));
9487 //putbits36 (& cpu.CY, 18, 6, GET_PR_BITNO (n));
9488 cpu.zone = 0777777770000;
9489 cpu.useZone = true;
9490 }
9491 break;
9492
9493 // sareg Store Address Registers
9494
9495 case x1 (0443): // sareg
9496 // a:AL39/ar1 According to ISOLTS ps805, the BITNO data is stored
9497 // in BITNO format, not CHAR/BITNO.
9498 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9499 (void)memset (cpu.Yblock8, 0, sizeof (cpu.Yblock8));
9500 for (uint32 n = 0 ; n < 8 ; n += 1)
9501 {
9502 CPTUR (cptUsePRn + n);
9503 word36 arx = 0;
9504 putbits36 (& arx, 0, 18, cpu.PR[n].WORDNO);
9505 putbits36 (& arx, 18, 2, GET_AR_CHAR (n));
9506 putbits36 (& arx, 20, 4, GET_AR_BITNO (n));
9507 cpu.Yblock8[n] = arx;
9508 }
9509 break;
9510
9511 // spl Store Pointers and Lengths
9512
9513 case x1 (0447): // spl
9514 PNL (L68_ (DU_CYCLE_DDU_STEA;))
9515 du2words (cpup, cpu.Yblock8);
9516 break;
9517
9518 /// EIS - Address Register Special Arithmetic
9519
9520 // a4bd Add 4-bit Displacement to Address Register 5
9521
9522 case x1 (0502): // a4bd
9523 asxbd (cpup, 4, false);
9524 break;
9525
9526 // a6bd Add 6-bit Displacement to Address Register
9527
9528 case x1 (0501): // a6bd
9529 asxbd (cpup, 6, false);
9530 break;
9531
9532 // a9bd Add 9-bit Displacement to Address Register
9533
9534 case x1 (0500): // a9bd
9535 asxbd (cpup, 9, false);
9536 break;
9537
9538 // abd Add Bit Displacement to Address Register
9539
9540 case x1 (0503): // abd
9541 asxbd (cpup, 1, false);
9542 break;
9543
9544 // awd Add Word Displacement to Address Register
9545
9546 case x1 (0507): // awd
9547 asxbd (cpup, 36, false);
9548 break;
9549
9550 // s4bd Subtract 4-bit Displacement from Address Register
9551
9552 case x1 (0522): // s4bd
9553 asxbd (cpup, 4, true);
9554 break;
9555
9556 // s6bd Subtract 6-bit Displacement from Address Register
9557
9558 case x1 (0521): // s6bd
9559 asxbd (cpup, 6, true);
9560 break;
9561
9562 // s9bd Subtract 9-bit Displacement from Address Register
9563
9564 case x1 (0520): // s9bd
9565 asxbd (cpup, 9, true);
9566 break;
9567
9568 // sbd Subtract Bit Displacement from Address Register
9569
9570 case x1 (0523): // sbd
9571 asxbd (cpup, 1, true);
9572 break;
9573
9574 // swd Subtract Word Displacement from Address Register
9575
9576 case x1 (0527): // swd
9577 asxbd (cpup, 36, true);
9578 break;
9579
9580 /// EIS = Alphanumeric Compare
9581
9582 case x1 (0106): // cmpc
9583 cmpc (cpup);
9584 break;
9585
9586 case x1 (0120): // scd
9587 scd (cpup);
9588 break;
9589
9590 case x1 (0121): // scdr
9591 scdr (cpup);
9592 break;
9593
9594 case x1 (0124): // scm
9595 scm (cpup);
9596 break;
9597
9598 case x1 (0125): // scmr
9599 scmr (cpup);
9600 break;
9601
9602 case x1 (0164): // tct
9603 tct (cpup);
9604 break;
9605
9606 case x1 (0165): // tctr
9607 tctr (cpup);
9608 break;
9609
9610 /// EIS - Alphanumeric Move
9611
9612 case x1 (0100): // mlr
9613 mlr (cpup);
9614 break;
9615
9616 case x1 (0101): // mrl
9617 mrl (cpup);
9618 break;
9619
9620 case x1 (0020): // mve
9621 mve (cpup);
9622 break;
9623
9624 case x1 (0160): // mvt
9625 mvt (cpup);
9626 break;
9627
9628 /// EIS - Numeric Compare
9629
9630 case x1 (0303): // cmpn
9631 cmpn (cpup);
9632 break;
9633
9634 /// EIS - Numeric Move
9635
9636 case x1 (0300): // mvn
9637 mvn (cpup);
9638 break;
9639
9640 case x1 (0024): // mvne
9641 mvne (cpup);
9642 break;
9643
9644 /// EIS - Bit String Combine
9645
9646 case x1 (0060): // csl
9647 csl (cpup);
9648 break;
9649
9650 case x1 (0061): // csr
9651 csr (cpup);
9652 break;
9653
9654 /// EIS - Bit String Compare
9655
9656 case x1 (0066): // cmpb
9657 cmpb (cpup);
9658 break;
9659
9660 /// EIS - Bit String Set Indicators
9661
9662 case x1 (0064): // sztl
9663 // The execution of this instruction is identical to the Combine
9664 // Bit Strings Left (csl) instruction except that C(BOLR)m is
9665 // not placed into C(Y-bit2)i-1.
9666 sztl (cpup);
9667 break;
9668
9669 case x1 (0065): // sztr
9670 // The execution of this instruction is identical to the Combine
9671 // Bit Strings Left (csr) instruction except that C(BOLR)m is
9672 // not placed into C(Y-bit2)i-1.
9673 sztr (cpup);
9674 break;
9675
9676 /// EIS -- Data Conversion
9677
9678 case x1 (0301): // btd
9679 btd (cpup);
9680 break;
9681
9682 case x1 (0305): // dtb
9683 dtb (cpup);
9684 break;
9685
9686 /// EIS - Decimal Addition
9687
9688 case x1 (0202): // ad2d
9689 ad2d (cpup);
9690 break;
9691
9692 case x1 (0222): // ad3d
9693 ad3d (cpup);
9694 break;
9695
9696 /// EIS - Decimal Subtraction
9697
9698 case x1 (0203): // sb2d
9699 sb2d (cpup);
9700 break;
9701
9702 case x1 (0223): // sb3d
9703 sb3d (cpup);
9704 break;
9705
9706 /// EIS - Decimal Multiplication
9707
9708 case x1 (0206): // mp2d
9709 mp2d (cpup);
9710 break;
9711
9712 case x1 (0226): // mp3d
9713 mp3d (cpup);
9714 break;
9715
9716 /// EIS - Decimal Division
9717
9718 case x1 (0207): // dv2d
9719 dv2d (cpup);
9720 break;
9721
9722 case x1 (0227): // dv3d
9723 dv3d (cpup);
9724 break;
9725
9726 case x1 (0420): // emcall instruction Custom, for an emulator call for scp
9727 {
9728 if (cpu.tweaks.enable_emcall) {
9729 int ret = emCall (cpup);
9730 if (ret)
9731 return ret;
9732 break;
9733 }
9734 goto unimp;
9735 }
9736
9737 default:
9738 unimp:
9739 if (cpu.tweaks.halt_on_unimp)
9740 return STOP_STOP;
9741 doFault (FAULT_IPR,
9742 fst_ill_op,
9743 "Illegal instruction");
9744 }
9745 L68_ (
9746 cpu.ou.STR_OP = (is_ou && (i->info->flags & (STORE_OPERAND | STORE_YPAIR))) ? 1 : 0;
9747 cpu.ou.cycle |= ou_GOF;
9748 if (cpu.MR_cache.emr && cpu.MR_cache.ihr && is_ou)
9749 add_l68_OU_history (cpup);
9750 if (cpu.MR_cache.emr && cpu.MR_cache.ihr && is_du)
9751 add_l68_DU_history (cpup);
9752 )
9753 return SCPE_OK;
9754 }
9755
9756 #include <ctype.h>
9757 #include <time.h>
9758
9759 /*
9760 * emulator call instruction. Do whatever address field sez' ....
9761 */
9762
9763 //static clockid_t clockID;
9764 //static struct timespec startTime;
9765 static uv_rusage_t startTime;
9766 static unsigned long long startInstrCnt;
9767
9768 static int emCall (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
9769 {
9770 #if defined(THREADZ) || defined(LOCKLESS)
9771 atomic_thread_fence (memory_order_seq_cst);
9772 #endif /* defined(THREADZ) || defined(LOCKLESS) */
9773
9774 DCDstruct * i = & cpu.currentInstruction;
9775
9776 // The address is absolute address of a structure consisting of a
9777 // operation code word and optional following words containing
9778 // data for the operation.
9779
9780 word36 op = M[i->address];
9781 switch (op)
9782 {
9783 // OP 1: Print the unsigned decimal representation of the first data
9784 // word.
9785 case 1:
9786 sim_printf ("%lld\r\n", (long long int) M[i->address+1]);
9787 break;
9788
9789 // OP 2: Halt the simulation
9790 case 2:
9791 #if defined(LOCKLESS)
9792 bce_dis_called = true;
9793 #endif
9794 return STOP_STOP;
9795
9796 #define UV_VERSION(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
9797
9798 // OP 3: Start CPU clock
9799 case 3:
9800 startInstrCnt = cpu.instrCnt;
9801 uv_getrusage (& startTime);
9802 #if UV_VERSION_HEX >= UV_VERSION(1, 50, 0)
9803 if (uv_getrusage_thread(& startTime) == UV_ENOTSUP) {
9804 uv_getrusage (& startTime);
9805 }
9806 #else
9807 uv_getrusage (& startTime);
9808 #endif
9809 break;
9810
9811 // OP 4: Report CPU clock
9812 case 4:
9813 {
9814 #define ns_sec (1000000000L)
9815 #define ns_msec (1000000000L / 1000L)
9816 #define ns_usec (1000000000L / 1000L / 1000L)
9817 uv_rusage_t now;
9818 #if UV_VERSION_HEX >= UV_VERSION(1, 50, 0)
9819 if (uv_getrusage_thread(& now) == UV_ENOTSUP) {
9820 uv_getrusage (& now);
9821 }
9822 #else
9823 uv_getrusage (& now);
9824 #endif
9825 uint64_t u_start = (uint64_t)((uint64_t)(startTime.ru_utime.tv_usec * 1000ULL) +
9826 (uint64_t)(startTime.ru_utime.tv_sec * (uint64_t)ns_sec));
9827 uint64_t s_start = (uint64_t)((uint64_t)(startTime.ru_stime.tv_usec * 1000ULL) +
9828 (uint64_t)(startTime.ru_stime.tv_sec * (uint64_t)ns_sec));
9829 uint64_t u_stop = (uint64_t)((uint64_t)(now.ru_utime.tv_usec * 1000ULL) +
9830 (uint64_t)(now.ru_utime.tv_sec * (uint64_t)ns_sec));
9831 uint64_t s_stop = (uint64_t)((uint64_t)(now.ru_stime.tv_usec * 1000ULL) +
9832 (uint64_t)(now.ru_stime.tv_sec * (uint64_t)ns_sec));
9833 uint64_t u_delta = u_stop - u_start;
9834 uint64_t s_delta = s_stop - s_start;
9835 uint64_t u_seconds = u_delta / ns_sec;
9836 uint64_t s_seconds = s_delta / ns_sec;
9837 uint64_t u_milliseconds = (u_delta / ns_msec) % 1000ULL;
9838 uint64_t s_milliseconds = (s_delta / ns_msec) % 1000ULL;
9839 uint64_t u_microseconds = (u_delta / ns_usec) % 1000ULL;
9840 uint64_t s_microseconds = (s_delta / ns_usec) % 1000ULL;
9841 unsigned long long nInsts = (unsigned long long)((unsigned long long)cpu.instrCnt -
9842 (unsigned long long)startInstrCnt);
9843 double u_secs = (double)(((long double) u_delta) / ((long double) ns_sec));
9844 double s_secs = (double)(((long double) s_delta) / ((long double) ns_sec));
9845 long double ips = (long double)(((long double) nInsts) /
9846 (((long double) u_secs) + ((long double) s_secs)));
9847 long double mips = (long double)(ips / 1000000.0L);
9848
9849 struct tm tm = {0};
9850 char elapsed_time[64];
9851
9852 tm.tm_hour = u_seconds / 3600;
9853 tm.tm_min = (u_seconds % 3600) / 60;
9854 tm.tm_sec = u_seconds % 60;
9855 strftime(elapsed_time, sizeof(elapsed_time), "%H:%M:%S", &tm);
9856
9857 sim_printf ("\rUser time elapsed : %s.%03llu%03llu\r\n",
9858 elapsed_time, (unsigned long long)u_milliseconds, (unsigned long long)u_microseconds);
9859
9860 tm.tm_hour = s_seconds / 3600;
9861 tm.tm_min = (s_seconds % 3600) / 60;
9862 tm.tm_sec = s_seconds % 60;
9863 strftime(elapsed_time, sizeof(elapsed_time), "%H:%M:%S", &tm);
9864
9865 sim_printf ("\rSystem time elapsed: %s.%03llu%03llu\r\n",
9866 elapsed_time, (unsigned long long)s_milliseconds, (unsigned long long)s_microseconds);
9867 #if defined(WIN_STDIO)
9868 sim_printf ("\rInstructions : %llu\r\n", (unsigned long long) nInsts);
9869 sim_printf ("\rPerformance : %f MIPS\r\n\r\n", (double) mips);
9870 #else
9871 sim_printf ("\rInstructions : %'llu\r\n", (unsigned long long) nInsts);
9872 sim_printf ("\rPerformance : %'f MIPS\r\n", (double) mips);
9873 #endif /* if defined(WIN_STDIO) */
9874 break;
9875 }
9876 default:
9877 sim_printf ("emcall unknown op %llo\r\n", (unsigned long long)op);
9878 }
9879 return 0;
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
9891
9892
9893
9894
9895
9896
9897
9898
9899
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916
9917
9918
9919
9920
9921
9922
9923
9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
9934
9935
9936
9937
9938
9939
9940
9941
9942
9943
9944
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954
9955
9956
9957
9958
9959
9960
9961
9962
9963
9964
9965
9966
9967
9968
9969
9970
9971
9972
9973
9974
9975
9976
9977
9978
9979
9980
9981
9982
9983
9984
9985
9986
9987
9988
9989
9990
9991
9992
9993
9994
9995
9996
9997
9998
9999
10000
10001
10002
10003
10004
10005
10006
10007
10008
10009
10010
10011
10012
10013
10014
10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065
10066
10067
10068
10069
10070
10071 }
10072
10073 // CANFAULT
10074 // T&D: for sscr/rscr addressed through the appending unit, the CPU port
10075 // whose window (port assignment and store size switches) holds the final
10076 // absolute address. False if not appended or on no port.
10077 static bool scr_port_from_final_address (cpu_state_t * cpup, uint * portp)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
10078 {
10079 if (get_addr_mode (cpup) == ABSOLUTE_mode && ! (cpu.cu.XSF || cpu.currentInstruction.b29))
10080 return false;
10081 word24 final_address = doAppendCycleABSA (cpup, NULL, 0);
10082 uint dps8m_store_table [8] =
10083 { 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304 };
10084 uint l68_store_table [8] =
10085 { 32768, 65536, 4194304, 131072, 524288, 1048576, 2097152, 262144 };
10086 int n_ports = cpu.tweaks.l68_mode ? N_L68_CPU_PORTS : N_DPS8M_CPU_PORTS;
10087 for (int port_num = 0; port_num < n_ports; port_num ++)
10088 {
10089 if (! cpu.switches.enable [port_num] ||
10090 ! cables->cpu_to_scu[current_running_cpu_idx][port_num].in_use)
10091 continue;
10092 uint store_size = cpu.switches.store_size [port_num];
10093 uint sz_wds = cpu.tweaks.l68_mode ? l68_store_table [store_size] :
10094 dps8m_store_table [store_size];
10095 uint base = sz_wds * cpu.switches.assignment[port_num];
10096 if (final_address >= base && final_address - base < sz_wds)
10097 {
10098 * portp = (uint) port_num;
10099 return true;
10100 }
10101 }
10102 return false;
10103 }
10104
10105 static int doABSA (cpu_state_t * cpup, word36 * result)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
10106 {
10107 word36 res;
10108 sim_debug (DBG_APPENDING, & cpu_dev, "absa CA:%08o\r\n", cpu.TPR.CA);
10109
10110 //if (get_addr_mode (cpup) == ABSOLUTE_mode && ! cpu.isb29)
10111 //if (get_addr_mode (cpup) == ABSOLUTE_mode && ! cpu.went_appending) // ISOLTS-860
10112 if (get_addr_mode (cpup) == ABSOLUTE_mode && ! (cpu.cu.XSF || cpu.currentInstruction.b29)) // ISOLTS-860
10113 {
10114 * result = ((word36) (cpu.TPR.CA & MASK18)) << 12; // 24:12 format
10115 return SCPE_OK;
10116 }
10117
10118 // ABSA handles directed faults differently, so a special append cycle is
10119 // needed.
10120 // do_append_cycle also provides WAM support, which is required by
10121 // ISOLTS-860 02
10122 // res = (word36) do_append_cycle (cpu.TPR.CA & MASK18, ABSA_CYCLE, NULL,
10123 // 0) << 12;
10124 //res = (word36) do_append_cycle (ABSA_CYCLE, NULL, 0) << 12;
10125 res = (word36) doAppendCycleABSA (cpup, NULL, 0) << 12;
10126
10127 * result = res;
10128
10129 return SCPE_OK;
10130 }
10131
10132 void doRCU (cpu_state_t * cpup)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
10133 {
10134 #if defined(LOOPTRC)
10135 elapsedtime ();
10136 sim_printf (" rcu to %05o:%06o PSR:IC %05o:%06o\r\n",
10137 (cpu.Yblock8[0]>>18)&MASK15, (cpu.Yblock8[4]>>18)&MASK18, cpu.PPR.PSR, cpu.PPR.IC);
10138 #endif
10139
10140 if_sim_debug (DBG_FAULT, & cpu_dev)
10141 {
10142 dump_words(cpup, cpu.Yblock8);
10143 //for (int i = 0; i < 8; i ++)
10144 // {
10145 // sim_debug (DBG_FAULT, & cpu_dev, "RCU %d %012"PRIo64"\r\n", i,
10146 // cpu.Yblock8[i]);
10147 // }
10148 }
10149
10150 words2scu (cpup, cpu.Yblock8);
10151 decode_instruction (cpup, IWB_IRODD, & cpu.currentInstruction);
10152
10153 // Resuming a repeat after its first repetition: a fault left the Xn
10154 // of the instructions not yet completed as the hardware has them
10155 // (doFault); dps8m's repetition uses Xn already advanced by delta
10156 // (PA885 06D)
10157 if ((cpu.cu.rpt || cpu.cu.rd) && ! cpu.cu.repeat_first)
10158 {
10159 bool icOdd = getbits36_1 (cpu.Yblock8[4], 17);
10160 if (cpu.cu.rpt)
10161 {
10162 uint Xn = (uint) getbits36_3 (cpu.cu.IWB, 36 - 3);
10163 cpu.rX[Xn] = (cpu.rX[Xn] + cpu.cu.delta) & AMASK;
10164 }
10165 else
10166 {
10167 if (! icOdd && (cpu.rX[0] & 01000))
10168 {
10169 uint Xn = (uint) getbits36_3 (cpu.cu.IWB, 36 - 3);
10170 cpu.rX[Xn] = (cpu.rX[Xn] + cpu.cu.delta) & AMASK;
10171 }
10172 if (cpu.rX[0] & 00400)
10173 {
10174 uint Xn = (uint) getbits36_3 (cpu.cu.IRODD, 36 - 3);
10175 cpu.rX[Xn] = (cpu.rX[Xn] + cpu.cu.delta) & AMASK;
10176 }
10177 }
10178 }
10179
10180 // Restore addressing mode
10181
10182 word1 saveP = cpu.PPR.P; // ISOLTS-870 02m
10183 if (TST_I_ABS == 0)
10184 set_addr_mode (cpup, APPEND_mode);
10185 else
10186 set_addr_mode (cpup, ABSOLUTE_mode);
10187 cpu.PPR.P = saveP;
10188
10189 if (getbits36_1 (cpu.Yblock8[1], 35) == 0) // cpu.cu.FLT_INT is interrupt, not fault
10190 {
10191 sim_debug (DBG_FAULT, & cpu_dev, "RCU interrupt return\r\n");
10192 longjmp (cpu.jmpMain, JMP_REFETCH);
10193 }
10194
10195 // Resync the append unit
10196 fauxDoAppendCycle (cpup, INSTRUCTION_FETCH);
10197
10198 // All of the faults list as having handlers have actually
10199 // been encountered in Multics operation and are believed
10200 // to be being handled correctly. The handlers in
10201 // parenthesis are speculative and untested.
10202 //
10203 // Unhandled:
10204 //
10205 // SDF Shutdown: Why would you RCU from a shutdown fault?
10206 // STR Store:
10207 // AL39 is contradictory or vague about store fault subfaults and store
10208 // faults in general. They are mentioned:
10209 // SPRPn: store fault (illegal pointer) (assuming STR:ISN)
10210 // SMCM: store fault (not control) -
10211 // SMIC: store fault (not control) > I believe that these should be
10212 // SSCR: store fault (not control) - command fault
10213 // TSS: STR:OOB
10214 // Bar mode out-of-bounds: STR:OOB
10215 // The SCU register doesn't define which bit is "store fault (not control)"
10216 // STR:ISN - illegal segment number
10217 // STR:NEA - nonexistent address
10218 // STR:OOB - bar mode out-of-bounds
10219 //
10220 // decimal octal
10221 // fault fault mnemonic name priority group handler
10222 // number address
10223 // 0 0 sdf Shutdown 27 7
10224 // 1 2 str Store 10 4 get_BAR_address, instruction execution
10225 // 2 4 mme Master mode entry 1 11 5 JMP_SYNC_FAULT_RETURN instruction execution
10226 // 3 6 f1 Fault tag 1 17 5 (JMP_REFETCH/JMP_RESTART) do_caf
10227 // 4 10 tro Timer runout 26 7 JMP_REFETCH FETCH_cycle
10228 // 5 12 cmd Command 9 4 JMP_REFETCH/JMP_RESTART instruction execution
10229 // 6 14 drl Derail 15 5 JMP_REFETCH/JMP_RESTART instruction execution
10230 // 7 16 luf Lockup 5 4 JMP_REFETCH do_caf, FETCH_cycle
10231 // 8 20 con Connect 25 7 JMP_REFETCH FETCH_cycle
10232 // 9 22 par Parity 8 4
10233 // 10 24 ipr Illegal procedure 16 5 doITSITP, do_caf, instruction execution
10234 // 11 26 onc Operation not complete 4 2 nem_check, instruction execution
10235 // 12 30 suf Startup 1 1
10236 // 13 32 ofl Overflow 7 3 JMP_REFETCH/JMP_RESTART instruction execution
10237 // 14 34 div Divide check 6 3 instruction execution
10238 // 15 36 exf Execute 2 1 JMP_REFETCH/JMP_RESTART FETCH_cycle
10239 // 16 40 df0 Directed fault 0 20 6 JMP_REFETCH/JMP_RESTART getSDW, do_append_cycle
10240 // 17 42 df1 Directed fault 1 21 6 JMP_REFETCH/JMP_RESTART getSDW, do_append_cycle
10241 // 18 44 df2 Directed fault 2 22 6 (JMP_REFETCH/JMP_RESTART) getSDW, do_append_cycle
10242 // 19 46 df3 Directed fault 3 23 6 JMP_REFETCH/JMP_RESTART getSDW, do_append_cycle
10243 // 20 50 acv Access violation 24 6 JMP_REFETCH/JMP_RESTART fetchDSPTW, modifyDSPTW, fetchNSDW,
10244 // do_append_cycle, EXEC_cycle (ring alarm)
10245 // 21 52 mme2 Master mode entry 2 12 5 JMP_SYNC_FAULT_RETURN instruction execution
10246 // 22 54 mme3 Master mode entry 3 13 5 (JMP_SYNC_FAULT_RETURN) instruction execution
10247 // 23 56 mme4 Master mode entry 4 14 5 (JMP_SYNC_FAULT_RETURN) instruction execution
10248 // 24 60 f2 Fault tag 2 18 5 JMP_REFETCH/JMP_RESTART do_caf
10249 // 25 62 f3 Fault tag 3 19 5 JMP_REFETCH/JMP_RESTART do_caf
10250 // 26 64 Unassigned
10251 // 27 66 Unassigned
10252 // 28 70 Unassigned
10253 // 29 72 Unassigned
10254 // 30 74 Unassigned
10255 // 31 76 trb Trouble 3 2 FETCH_cycle, doRCU
10256
10257 // Reworking logic
10258
10259 #define rework
10260 #if defined(rework)
10261 if (cpu.cu.FIF) // fault occurred during instruction fetch
10262 {
10263 //if (cpu.cu.rfi) sim_printf ( "RCU FIF refetch return caught rfi\r\n");
10264 // I am misusing this bit; on restart I want a way to tell the
10265 // CPU state machine to restart the instruction, which is not
10266 // how Multics uses it. I need to pick a different way to
10267 // communicate; for now, turn it off on refetch so the state
10268 // machine doesn't become confused.
10269 cpu.cu.rfi = 0;
10270 sim_debug (DBG_FAULT, & cpu_dev, "RCU FIF REFETCH return\r\n");
10271 longjmp (cpu.jmpMain, JMP_REFETCH);
10272 }
10273
10274 // RFI means 'refetch this instruction'
10275 if (cpu.cu.rfi)
10276 {
10277 //sim_printf ( "RCU rfi refetch return\r\n");
10278 sim_debug (DBG_FAULT, & cpu_dev, "RCU rfi refetch return\r\n");
10279 // Setting the to RESTART causes ISOLTS 776 to report unexpected
10280 // trouble faults.
10281 // Without clearing rfi, ISOLTS pm776-08i LUFs.
10282 cpu.cu.rfi = 0;
10283 longjmp (cpu.jmpMain, JMP_REFETCH);
10284 }
10285
10286 // The debug command uses MME2 to implement breakpoints, but it is not
10287 // clear what it does to the MC data to signal RFI behavior.
10288
10289 word5 fi_addr = getbits36_5 (cpu.Yblock8[1], 30);
10290 if (fi_addr == FAULT_MME ||
10291 fi_addr == FAULT_MME2 ||
10292 fi_addr == FAULT_MME3 ||
10293 fi_addr == FAULT_MME4 ||
10294 fi_addr == FAULT_DRL)
10295 //if (fi_addr == FAULT_MME2)
10296 {
10297 //sim_printf ("MME2 restart\r\n");
10298 sim_debug (DBG_FAULT, & cpu_dev, "RCU MME2 restart return\r\n");
10299 cpu.cu.rfi = 0;
10300 longjmp (cpu.jmpMain, JMP_RESTART);
10301 }
10302 #else
10303 if (cpu.cu.rfi || // S/W asked for the instruction to be started
10304 cpu.cu.FIF) // fault occurred during instruction fetch
10305 {
10306 // I am misusing this bit; on restart I want a way to tell the
10307 // CPU state machine to restart the instruction, which is not
10308 // how Multics uses it. I need to pick a different way to
10309 // communicate; for now, turn it off on refetch so the state
10310 // machine doesn't become confused.
10311
10312 cpu.cu.rfi = 0;
10313 sim_debug (DBG_FAULT, & cpu_dev, "RCU rfi/FIF REFETCH return\r\n");
10314 longjmp (cpu.jmpMain, JMP_REFETCH);
10315 }
10316
10317 // It seems obvious that MMEx should do a JMP_SYNC_FAULT_RETURN, but doing
10318 // a JMP_RESTART makes 'debug' work. (The same change to DRL does not make
10319 // 'gtss' work, tho.
10320
10321 if (fi_addr == FAULT_MME2)
10322 {
10323 //sim_printf ("MME2 restart\r\n");
10324 sim_debug (DBG_FAULT, & cpu_dev, "RCU MME2 restart return\r\n");
10325 cpu.cu.rfi = 1;
10326 longjmp (cpu.jmpMain, JMP_RESTART);
10327 }
10328 #endif
10329
10330
10331
10332
10333
10334
10335
10336
10337
10338
10339
10340
10341
10342
10343
10344
10345
10346
10347
10348 // MME faults resume with the next instruction
10349
10350 #if defined(rework)
10351 // Overflow and divide check: RCU resumes at the saved IC; software
10352 // that wants to go past the instruction adjusts the IC first (PA887:
10353 // the handler adds the dv3d's length). Multics's fim sets rfi+if on
10354 // every overflow, so it takes the FIF refetch above.
10355 if (fi_addr == FAULT_DIV ||
10356 fi_addr == FAULT_OFL)
10357 {
10358 cpu.cu.rfi = 0;
10359 sim_debug (DBG_FAULT, & cpu_dev, "RCU OFL/DIV refetch return\r\n");
10360 longjmp (cpu.jmpMain, JMP_REFETCH);
10361 }
10362 if (fi_addr == FAULT_IPR)
10363 {
10364 sim_debug (DBG_FAULT, & cpu_dev, "RCU sync fault return\r\n");
10365 cpu.cu.rfi = 0;
10366 longjmp (cpu.jmpMain, JMP_SYNC_FAULT_RETURN);
10367 }
10368 #else
10369 if (fi_addr == FAULT_MME ||
10370 /* fi_addr == FAULT_MME2 || */
10371 fi_addr == FAULT_MME3 ||
10372 fi_addr == FAULT_MME4 ||
10373 fi_addr == FAULT_DRL ||
10374 fi_addr == FAULT_DIV ||
10375 fi_addr == FAULT_OFL ||
10376 fi_addr == FAULT_IPR)
10377 {
10378 sim_debug (DBG_FAULT, & cpu_dev, "RCU MMEx sync fault return\r\n");
10379 cpu.cu.rfi = 0;
10380 longjmp (cpu.jmpMain, JMP_SYNC_FAULT_RETURN);
10381 }
10382 #endif
10383
10384 // LUF can happen during fetch or CAF. If fetch, handled above
10385 if (fi_addr == FAULT_LUF)
10386 {
10387 cpu.cu.rfi = 1;
10388 sim_debug (DBG_FAULT, & cpu_dev, "RCU LUF RESTART return\r\n");
10389 longjmp (cpu.jmpMain, JMP_RESTART);
10390 }
10391
10392 if (fi_addr == FAULT_DF0 ||
10393 fi_addr == FAULT_DF1 ||
10394 fi_addr == FAULT_DF2 ||
10395 fi_addr == FAULT_DF3 ||
10396 fi_addr == FAULT_ACV ||
10397 fi_addr == FAULT_F1 ||
10398 fi_addr == FAULT_F2 ||
10399 fi_addr == FAULT_F3 ||
10400 fi_addr == FAULT_CMD ||
10401 fi_addr == FAULT_EXF ||
10402 fi_addr == FAULT_STR || // restartable once the cause is fixed (PA885 10B)
10403 // a timer runout or connect taken part way through an
10404 // interruptible EIS instruction (T&D model, PM842); at a fetch
10405 // they are refetches, above (PA887 01B)
10406 fi_addr == FAULT_TRO ||
10407 fi_addr == FAULT_CON)
10408 {
10409 // If the fault occurred during fetch, handled above.
10410 cpu.cu.rfi = 1;
10411 sim_debug (DBG_FAULT, & cpu_dev, "RCU ACV RESTART return\r\n");
10412 longjmp (cpu.jmpMain, JMP_RESTART);
10413 }
10414 sim_printf ("doRCU dies with unhandled fault number %d\r\n", fi_addr);
10415 doFault (FAULT_TRB,
10416 (_fault_subtype) {.bits=fi_addr},
10417 "doRCU dies with unhandled fault number");
10418 }