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