First Commit of my working state
[simh.git] / VAX / vax_cmode.c
1 /* vax_cmode.c: VAX compatibility mode
2
3 Copyright (c) 2004-2008, Robert M Supnik
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
25
26 On a full VAX, this module implements PDP-11 compatibility mode.
27 On a subset VAX, this module forces a fault if REI attempts to set PSL<cm>.
28
29 28-May-08 RMS Inlined physical memory routines
30 25-Jan-08 RMS Fixed declaration (from Mark Pizzolato)
31 03-May-06 RMS Fixed omission of SXT
32 Fixed order of operand fetching in XOR
33 24-Aug-04 RMS Cloned from PDP-11 CPU
34
35 In compatibility mode, the Istream prefetch mechanism is not used. The
36 prefetcher will be explicitly resynchronized through intexc on any exit
37 from compatibility mode.
38 */
39
40 #include "vax_defs.h"
41
42 #if defined (FULL_VAX)
43
44 #define RdMemB(a) Read (a, L_BYTE, RA)
45 #define RdMemMB(a) Read (a, L_BYTE, WA)
46 #define WrMemB(d,a) Write (a, d, L_BYTE, WA)
47 #define BRANCH_F(x) CMODE_JUMP ((PC + (((x) + (x)) & BMASK)) & WMASK)
48 #define BRANCH_B(x) CMODE_JUMP ((PC + (((x) + (x)) | 0177400)) & WMASK)
49 #define CC_XOR_NV(x) ((((x) & CC_N) != 0) ^ (((x) & CC_V) != 0))
50 #define CC_XOR_NC(x) ((((x) & CC_N) != 0) ^ (((x) & CC_C) != 0))
51
52 extern int32 R[16];
53 extern int32 PSL;
54 extern int32 trpirq;
55 extern int32 p1;
56 extern int32 fault_PC;
57 extern int32 recq[]; /* recovery queue */
58 extern int32 recqptr; /* recq pointer */
59 extern int32 pcq[];
60 extern int32 pcq_p;
61 extern int32 ibcnt, ppc;
62 extern int32 sim_interval;
63 extern uint32 sim_brk_summ;
64 extern jmp_buf save_env;
65
66 int32 GeteaB (int32 spec);
67 int32 GeteaW (int32 spec);
68 int32 RdMemW (int32 a);
69 int32 RdMemMW (int32 a);
70 void WrMemW (int32 d, int32 a);
71 int32 RdRegB (int32 rn);
72 int32 RdRegW (int32 rn);
73 void WrRegB (int32 val, int32 rn);
74 void WrRegW (int32 val, int32 rn);
75
76 /* Validate PSL for compatibility mode */
77
78 t_bool BadCmPSL (int32 newpsl)
79 {
80 if ((newpsl & (PSL_FPD|PSL_IS|PSL_CUR|PSL_PRV|PSL_IPL)) !=
81 ((USER << PSL_V_CUR) | (USER << PSL_V_PRV)))
82 return TRUE;
83 else return FALSE;
84 }
85
86 /* Compatibility mode execution */
87
88 int32 op_cmode (int32 cc)
89 {
90 int32 IR, srcspec, dstspec, srcreg, dstreg, ea;
91 int32 i, t, src, src2, dst, sign, oc;
92 int32 acc = ACC_MASK (USER);
93
94 PC = PC & WMASK; /* PC must be 16b */
95 if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
96 ABORT (STOP_IBKPT); /* stop simulation */
97 }
98 sim_interval = sim_interval - 1; /* count instr */
99
100 IR = RdMemW (PC); /* fetch instruction */
101 PC = (PC + 2) & WMASK; /* incr PC, mod 65k */
102 srcspec = (IR >> 6) & 077; /* src, dst specs */
103 dstspec = IR & 077;
104 srcreg = (srcspec <= 07); /* src, dst = rmode? */
105 dstreg = (dstspec <= 07);
106 switch ((IR >> 12) & 017) { /* decode IR<15:12> */
107
108 /* Opcode 0: no operands, specials, branches, JSR, SOPs */
109
110 case 000: /* 00xxxx */
111 switch ((IR >> 6) & 077) { /* decode IR<11:6> */
112 case 000: /* 0000xx */
113 switch (IR) { /* decode IR<5:0> */
114 case 3: /* BPT */
115 CMODE_FAULT (CMODE_BPT);
116 break;
117
118 case 4: /* IOT */
119 CMODE_FAULT (CMODE_IOT);
120 break;
121
122 case 2: /* RTI */
123 case 6: /* RTT */
124 src = RdMemW (R[6] & WMASK); /* new PC */
125 src2 = RdMemW ((R[6] + 2) & WMASK); /* new PSW */
126 R[6] = (R[6] + 4) & WMASK;
127 cc = src2 & CC_MASK; /* update cc, T */
128 if (src2 & PSW_T) PSL = PSL | PSW_T;
129 else PSL = PSL & ~PSW_T;
130 CMODE_JUMP (src); /* update PC */
131 break;
132
133 default: /* undefined */
134 CMODE_FAULT (CMODE_RSVI);
135 break;
136 } /* end switch IR */
137 break; /* end case 0000xx */
138
139 case 001: /* JMP */
140 if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */
141 else { CMODE_JUMP (GeteaW (dstspec)); }
142 break;
143
144 case 002: /* 0002xx */
145 if (IR < 000210) { /* RTS */
146 dstspec = dstspec & 07;
147 if (dstspec != 7) { /* PC <- r */
148 CMODE_JUMP (RdRegW (dstspec));
149 }
150 dst = RdMemW (R[6]); /* t <- (sp)+ */
151 R[6] = (R[6] + 2) & WMASK;
152 WrRegW (dst, dstspec); /* r <- t */
153 break; /* end if RTS */
154 }
155 if (IR < 000240) { /* [210:237] */
156 CMODE_FAULT (CMODE_RSVI);
157 break;
158 }
159 if (IR < 000260) cc = cc & ~(IR & CC_MASK); /* clear CC */
160 else cc = cc | (IR & CC_MASK); /* set CC */
161 break;
162
163 case 003: /* SWAB */
164 if (dstreg) src = RdRegW (dstspec);
165 else src = RdMemMW (ea = GeteaW (dstspec));
166 dst = ((src & BMASK) << 8) | ((src >> 8) & BMASK);
167 if (dstreg) WrRegW (dst, dstspec);
168 else WrMemW (dst, ea);
169 CC_IIZZ_B ((dst & BMASK));
170 break;
171
172 case 004: case 005: /* BR */
173 BRANCH_F (IR);
174 break;
175
176 case 006: case 007: /* BR */
177 BRANCH_B (IR);
178 break;
179
180 case 010: case 011: /* BNE */
181 if ((cc & CC_Z) == 0) { BRANCH_F (IR); }
182 break;
183
184 case 012: case 013: /* BNE */
185 if ((cc & CC_Z) == 0) { BRANCH_B (IR); }
186 break;
187
188 case 014: case 015: /* BEQ */
189 if (cc & CC_Z) { BRANCH_F (IR); }
190 break;
191
192 case 016: case 017: /* BEQ */
193 if (cc & CC_Z) { BRANCH_B (IR); }
194 break;
195
196 case 020: case 021: /* BGE */
197 if (CC_XOR_NV (cc) == 0) { BRANCH_F (IR); }
198 break;
199
200 case 022: case 023: /* BGE */
201 if (CC_XOR_NV (cc) == 0) { BRANCH_B (IR); }
202 break;
203
204 case 024: case 025: /* BLT */
205 if (CC_XOR_NV (cc)) { BRANCH_F (IR); }
206 break;
207
208 case 026: case 027: /* BLT */
209 if (CC_XOR_NV (cc)) { BRANCH_B (IR); }
210 break;
211
212 case 030: case 031: /* BGT */
213 if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_F (IR); }
214 break;
215
216 case 032: case 033: /* BGT */
217 if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_B (IR); }
218 break;
219
220 case 034: case 035: /* BLE */
221 if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_F (IR); }
222 break;
223
224 case 036: case 037: /* BLE */
225 if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_B (IR); }
226 break;
227
228 case 040: case 041: case 042: case 043: /* JSR */
229 case 044: case 045: case 046: case 047:
230 if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */
231 else {
232 srcspec = srcspec & 07; /* get reg num */
233 dst = GeteaW (dstspec); /* get dst addr */
234 src = RdRegW (srcspec); /* get src reg */
235 WrMemW (src, (R[6] - 2) & WMASK); /* -(sp) <- r */
236 R[6] = (R[6] - 2) & WMASK;
237 if (srcspec != 7) WrRegW (PC, srcspec); /* r <- PC */
238 CMODE_JUMP (dst); /* PC <- dst */
239 }
240 break; /* end JSR */
241
242 case 050: /* CLR */
243 if (dstreg) WrRegW (0, dstspec);
244 else WrMemW (0, GeteaW (dstspec));
245 cc = CC_Z;
246 break;
247
248 case 051: /* COM */
249 if (dstreg) src = RdRegW (dstspec);
250 else src = RdMemMW (ea = GeteaW (dstspec));
251 dst = src ^ WMASK;
252 if (dstreg) WrRegW (dst, dstspec);
253 else WrMemW (dst, ea);
254 CC_IIZZ_W (dst);
255 cc = cc | CC_C;
256 break;
257
258 case 052: /* INC */
259 if (dstreg) src = RdRegW (dstspec);
260 else src = RdMemMW (ea = GeteaW (dstspec));
261 dst = (src + 1) & WMASK;
262 if (dstreg) WrRegW (dst, dstspec);
263 else WrMemW (dst, ea);
264 CC_IIZP_W (dst);
265 if (dst == 0100000) cc = cc | CC_V;
266 break;
267
268 case 053: /* DEC */
269 if (dstreg) src = RdRegW (dstspec);
270 else src = RdMemMW (ea = GeteaW (dstspec));
271 dst = (src - 1) & WMASK;
272 if (dstreg) WrRegW (dst, dstspec);
273 else WrMemW (dst, ea);
274 CC_IIZP_W (dst);
275 if (dst == 077777) cc = cc | CC_V;
276 break;
277
278 case 054: /* NEG */
279 if (dstreg) src = RdRegW (dstspec);
280 else src = RdMemMW (ea = GeteaW (dstspec));
281 dst = (-src) & WMASK;
282 if (dstreg) WrRegW (dst, dstspec);
283 else WrMemW (dst, ea);
284 CC_IIZZ_W (dst);
285 if (dst == 0100000) cc = cc | CC_V;
286 if (dst) cc = cc | CC_C;
287 break;
288
289 case 055: /* ADC */
290 if (dstreg) src = RdRegW (dstspec);
291 else src = RdMemMW (ea = GeteaW (dstspec));
292 dst = (src + (cc & CC_C)) & WMASK;
293 if (dstreg) WrRegW (dst, dstspec);
294 else WrMemW (dst, ea);
295 CC_IIZZ_W (dst);
296 if ((src == 077777) && (dst == 0100000)) cc = cc | CC_V;
297 if ((src == 0177777) && (dst == 0)) cc = cc | CC_C;
298 break;
299
300 case 056: /* SBC */
301 if (dstreg) src = RdRegW (dstspec);
302 else src = RdMemMW (ea = GeteaW (dstspec));
303 dst = (src - (cc & CC_C)) & WMASK;
304 if (dstreg) WrRegW (dst, dstspec);
305 else WrMemW (dst, ea);
306 CC_IIZZ_W (dst);
307 if ((src == 0100000) && (dst == 077777)) cc = cc | CC_V;
308 if ((src == 0) && (dst == 0177777)) cc = cc | CC_C;
309 break;
310
311 case 057: /* TST */
312 if (dstreg) src = RdRegW (dstspec);
313 else src = RdMemW (GeteaW (dstspec));
314 CC_IIZZ_W (src);
315 break;
316
317 case 060: /* ROR */
318 if (dstreg) src = RdRegW (dstspec);
319 else src = RdMemMW (ea = GeteaW (dstspec));
320 dst = (src >> 1) | ((cc & CC_C)? WSIGN: 0);
321 if (dstreg) WrRegW (dst, dstspec);
322 else WrMemW (dst, ea);
323 CC_IIZZ_W (dst);
324 if (src & 1) cc = cc | CC_C;
325 if (CC_XOR_NC (cc)) cc = cc | CC_V;
326 break;
327
328 case 061: /* ROL */
329 if (dstreg) src = RdRegW (dstspec);
330 else src = RdMemMW (ea = GeteaW (dstspec));
331 dst = ((src << 1) | ((cc & CC_C)? 1: 0)) & WMASK;
332 if (dstreg) WrRegW (dst, dstspec);
333 else WrMemW (dst, ea);
334 CC_IIZZ_W (dst);
335 if (src & WSIGN) cc = cc | CC_C;
336 if (CC_XOR_NC (cc)) cc = cc | CC_V;
337 break;
338
339 case 062: /* ASR */
340 if (dstreg) src = RdRegW (dstspec);
341 else src = RdMemMW (ea = GeteaW (dstspec));
342 dst = (src & WSIGN) | (src >> 1);
343 if (dstreg) WrRegW (dst, dstspec);
344 else WrMemW (dst, ea);
345 CC_IIZZ_W (dst);
346 if (src & 1) cc = cc | CC_C;
347 if (CC_XOR_NC (cc)) cc = cc | CC_V;
348 break;
349
350 case 063: /* ASL */
351 if (dstreg) src = RdRegW (dstspec);
352 else src = RdMemMW (ea = GeteaW (dstspec));
353 dst = (src << 1) & WMASK;
354 if (dstreg) WrRegW (dst, dstspec);
355 else WrMemW (dst, ea);
356 CC_IIZZ_W (dst);
357 if (src & WSIGN) cc = cc | CC_C;
358 if (CC_XOR_NC (cc)) cc = cc | CC_V;
359 break;
360
361 case 065: /* MFPI */
362 if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */
363 else dst = RdMemW (GeteaW (dstspec));
364 WrMemW (dst, (R[6] - 2) & WMASK);
365 R[6] = (R[6] - 2) & WMASK;
366 CC_IIZP_W (dst);
367 break;
368
369 case 066: /* MTPI */
370 dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */
371 R[6] = (R[6] + 2) & WMASK;
372 recq[recqptr++] = RQ_REC (AIN|RW, 6);
373 if (dstreg) WrRegW (dst, dstspec);
374 else WrMemW (dst, (GeteaW (dstspec) & WMASK));
375 CC_IIZP_W (dst);
376 break;
377
378 case 067: /* SXT */
379 dst = (cc & CC_N)? 0177777: 0;
380 if (dstreg) WrRegW (dst, dstspec);
381 else WrMemW (dst, GeteaW (dstspec));
382 CC_IIZP_W (dst);
383 break;
384
385 default: /* undefined */
386 CMODE_FAULT (CMODE_RSVI);
387 break;
388 } /* end switch SOPs */
389 break; /* end case 000 */
390
391 /* Opcodes 01 - 06: double operand word instructions
392
393 Compatibility mode requires source address decode, source fetch,
394 dest address decode, dest fetch/store.
395
396 Add: v = [sign (src) = sign (src2)] and [sign (src) != sign (result)]
397 Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)]
398 */
399
400 case 001: /* MOV */
401 if (srcreg) src = RdRegW (srcspec);
402 else src = RdMemW (GeteaW (srcspec));
403 if (dstreg) WrRegW (src, dstspec);
404 else WrMemW (src, GeteaW (dstspec));
405 CC_IIZP_W (src);
406 break;
407
408 case 002: /* CMP */
409 if (srcreg) src = RdRegW (srcspec);
410 else src = RdMemW (GeteaW (srcspec));
411 if (dstreg) src2 = RdRegW (dstspec);
412 else src2 = RdMemW (GeteaW (dstspec));
413 dst = (src - src2) & WMASK;
414 CC_IIZZ_W (dst);
415 if (((src ^ src2) & (~src2 ^ dst)) & WSIGN) cc = cc | CC_V;
416 if (src < src2) cc = cc | CC_C;
417 break;
418
419 case 003: /* BIT */
420 if (srcreg) src = RdRegW (srcspec);
421 else src = RdMemW (GeteaW (srcspec));
422 if (dstreg) src2 = RdRegW (dstspec);
423 else src2 = RdMemW (GeteaW (dstspec));
424 dst = src2 & src;
425 CC_IIZP_W (dst);
426 break;
427
428 case 004: /* BIC */
429 if (srcreg) src = RdRegW (srcspec);
430 else src = RdMemW (GeteaW (srcspec));
431 if (dstreg) src2 = RdRegW (dstspec);
432 else src2 = RdMemMW (ea = GeteaW (dstspec));
433 dst = src2 & ~src;
434 if (dstreg) WrRegW (dst, dstspec);
435 else WrMemW (dst, ea);
436 CC_IIZP_W (dst);
437 break;
438
439 case 005: /* BIS */
440 if (srcreg) src = RdRegW (srcspec);
441 else src = RdMemW (GeteaW (srcspec));
442 if (dstreg) src2 = RdRegW (dstspec);
443 else src2 = RdMemMW (ea = GeteaW (dstspec));
444 dst = src2 | src;
445 if (dstreg) WrRegW (dst, dstspec);
446 else WrMemW (dst, ea);
447 CC_IIZP_W (dst);
448 break;
449
450 case 006: /* ADD */
451 if (srcreg) src = RdRegW (srcspec);
452 else src = RdMemW (GeteaW (srcspec));
453 if (dstreg) src2 = RdRegW (dstspec);
454 else src2 = RdMemMW (ea = GeteaW (dstspec));
455 dst = (src2 + src) & WMASK;
456 if (dstreg) WrRegW (dst, dstspec);
457 else WrMemW (dst, ea);
458 CC_ADD_W (dst, src, src2);
459 break;
460
461 /* Opcode 07: EIS, FIS (not implemented), CIS
462
463 Notes:
464 - MUL carry: C is set if the (signed) result doesn't fit in 16 bits.
465 - Divide has three error cases:
466 1. Divide by zero.
467 2. Divide largest negative number by -1.
468 3. (Signed) quotient doesn't fit in 16 bits.
469 Cases 1 and 2 must be tested in advance, to avoid C runtime errors.
470 - ASHx left: overflow if the bits shifted out do not equal the sign
471 of the result (convert shift out to 1/0, xor against sign).
472 - ASHx right: if right shift sign extends, then the shift and
473 conditional or of shifted -1 is redundant. If right shift zero
474 extends, then the shift and conditional or does sign extension.
475 */
476
477 case 007: /* EIS */
478 srcspec = srcspec & 07; /* get src reg */
479 switch ((IR >> 9) & 07) { /* decode IR<11:9> */
480
481 case 0: /* MUL */
482 if (dstreg) src2 = RdRegW (dstspec); /* get src2 */
483 else src2 = RdMemW (GeteaW (dstspec));
484 src = RdRegW (srcspec); /* get src */
485 if (src2 & WSIGN) src2 = src2 | ~WMASK; /* sext src, src2 */
486 if (src & WSIGN) src = src | ~WMASK;
487 dst = src * src2; /* multiply */
488 WrRegW ((dst >> 16) & WMASK, srcspec); /* high 16b */
489 WrRegW (dst & WMASK, srcspec | 1); /* low 16b */
490 CC_IIZZ_L (dst & LMASK);
491 if ((dst > 077777) || (dst < -0100000)) cc = cc | CC_C;
492 break;
493
494 case 1: /* DIV */
495 if (dstreg) src2 = RdRegW (dstspec); /* get src2 */
496 else src2 = RdMemW (GeteaW (dstspec));
497 t = RdRegW (srcspec);
498 src = (((uint32) t) << 16) | RdRegW (srcspec | 1);
499 if (src2 == 0) { /* div by 0? */
500 cc = CC_V | CC_C; /* set cc's */
501 break; /* done */
502 }
503 if ((src == LSIGN) && (src2 == WMASK)) { /* -2^31 / -1? */
504 cc = CC_V; /* overflow */
505 break; /* done */
506 }
507 if (src2 & WSIGN) src2 = src2 | ~WMASK; /* sext src, src2 */
508 if (t & WSIGN) src = src | ~LMASK;
509 dst = src / src2; /* divide */
510 if ((dst > 077777) || (dst < -0100000)) { /* out of range? */
511 cc = CC_V; /* overflow */
512 break;
513 }
514 CC_IIZZ_W (dst & WMASK); /* set cc's */
515 WrRegW (dst & WMASK, srcspec); /* quotient */
516 WrRegW ((src - (src2 * dst)) & WMASK, srcspec | 1);
517 break;
518
519 case 2: /* ASH */
520 if (dstreg) src2 = RdRegW (dstspec); /* get src2 */
521 else src2 = RdMemW (GeteaW (dstspec));
522 src2 = src2 & 077;
523 src = RdRegW (srcspec); /* get src */
524 if (sign = ((src & WSIGN)? 1: 0)) src = src | ~WMASK;
525 if (src2 == 0) { /* [0] */
526 dst = src; /* result */
527 oc = 0; /* last bit out */
528 }
529 else if (src2 <= 15) { /* [1,15] */
530 dst = src << src2;
531 i = (src >> (16 - src2)) & WMASK;
532 oc = (i & 1)? CC_C: 0;
533 if ((dst & WSIGN)? (i != WMASK): (i != 0)) oc = oc | CC_V;
534 }
535 else if (src2 <= 31) { /* [16,31] */
536 dst = 0;
537 oc = ((src << (src2 - 16)) & 1)? CC_C: 0;
538 if (src) oc = oc | CC_V;
539 }
540 else if (src2 == 32) { /* [32] = -32 */
541 dst = -sign;
542 oc = sign? CC_C: 0;
543 }
544 else { /* [33,63] = -31,-1 */
545 dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
546 oc = ((src >> (63 - src2)) & 1)? CC_C: 0;
547 }
548 WrRegW (dst = dst & WMASK, srcspec); /* result */
549 CC_IIZZ_W (dst);
550 cc = cc | oc;
551 break;
552
553 case 3: /* ASHC */
554 if (dstreg) src2 = RdRegW (dstspec); /* get src2 */
555 else src2 = RdMemW (GeteaW (dstspec));
556 src2 = src2 & 077;
557 t = RdRegW (srcspec);
558 src = (((uint32) t) << 16) | RdRegW (srcspec | 1);
559 sign = (t & WSIGN)? 1: 0; /* get src sign */
560 if (src2 == 0) { /* [0] */
561 dst = src; /* result */
562 oc = 0; /* last bit out */
563 }
564 else if (src2 <= 31) { /* [1,31] */
565 dst = ((uint32) src) << src2;
566 i = ((src >> (32 - src2)) | (-sign << src2)) & LMASK;
567 oc = (i & 1)? CC_C: 0;
568 if ((dst & LSIGN)? (i != LMASK): (i != 0)) oc = oc | CC_V;
569 }
570 else if (src2 == 32) { /* [32] = -32 */
571 dst = -sign;
572 oc = sign? CC_C: 0;
573 }
574 else { /* [33,63] = -31,-1 */
575 dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
576 oc = ((src >> (63 - src2)) & 1)? CC_C: 0;
577 }
578 WrRegW ((dst >> 16) & WMASK, srcspec); /* high result */
579 WrRegW (dst & WMASK, srcspec | 1); /* low result */
580 CC_IIZZ_L (dst & LMASK);
581 cc = cc | oc;
582 break;
583
584 case 4: /* XOR */
585 src = RdRegW (srcspec); /* get src */
586 if (dstreg) src2 = RdRegW (dstspec); /* get dst */
587 else src2 = RdMemMW (ea = GeteaW (dstspec));
588 dst = src2 ^ src;
589 if (dstreg) WrRegW (dst, dstspec); /* result */
590 else WrMemW (dst, ea);
591 CC_IIZP_W (dst);
592 break;
593
594 case 7: /* SOB */
595 dst = (RdRegW (srcspec) - 1) & WMASK; /* decr reg */
596 WrRegW (dst, srcspec); /* result */
597 if (dst != 0) { /* br if zero */
598 CMODE_JUMP ((PC - dstspec - dstspec) & WMASK);
599 }
600 break;
601
602 default:
603 CMODE_FAULT (CMODE_RSVI); /* end switch EIS */
604 }
605 break; /* end case 007 */
606
607 /* Opcode 10: branches, traps, SOPs */
608
609 case 010:
610 switch ((IR >> 6) & 077) { /* decode IR<11:6> */
611 case 000: case 001: /* BPL */
612 if ((cc & CC_N) == 0) { BRANCH_F (IR); }
613 break;
614
615 case 002: case 003: /* BPL */
616 if ((cc & CC_N) == 0) { BRANCH_B (IR); }
617 break;
618
619 case 004: case 005: /* BMI */
620 if (cc & CC_N) { BRANCH_F (IR); }
621 break;
622
623 case 006: case 007: /* BMI */
624 if (cc & CC_N) { BRANCH_B (IR); }
625 break;
626
627 case 010: case 011: /* BHI */
628 if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_F (IR); }
629 break;
630
631 case 012: case 013: /* BHI */
632 if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_B (IR); }
633 break;
634
635 case 014: case 015: /* BLOS */
636 if (cc & (CC_C | CC_Z)) { BRANCH_F (IR); }
637 break;
638
639 case 016: case 017: /* BLOS */
640 if (cc & (CC_C | CC_Z)) { BRANCH_B (IR); }
641 break;
642
643 case 020: case 021: /* BVC */
644 if ((cc & CC_V) == 0) { BRANCH_F (IR); }
645 break;
646
647 case 022: case 023: /* BVC */
648 if ((cc & CC_V) == 0) { BRANCH_B (IR); }
649 break;
650
651 case 024: case 025: /* BVS */
652 if (cc & CC_V) { BRANCH_F (IR); }
653 break;
654
655 case 026: case 027: /* BVS */
656 if (cc & CC_V) { BRANCH_B (IR); }
657 break;
658
659 case 030: case 031: /* BCC */
660 if ((cc & CC_C) == 0) { BRANCH_F (IR); }
661 break;
662
663 case 032: case 033: /* BCC */
664 if ((cc & CC_C) == 0) { BRANCH_B (IR); }
665 break;
666
667 case 034: case 035: /* BCS */
668 if (cc & CC_C) { BRANCH_F (IR); }
669 break;
670
671 case 036: case 037: /* BCS */
672 if (cc & CC_C) { BRANCH_B (IR); }
673 break;
674
675 case 040: case 041: case 042: case 043: /* EMT */
676 CMODE_FAULT (CMODE_EMT);
677 break;
678
679 case 044: case 045: case 046: case 047: /* TRAP */
680 CMODE_FAULT (CMODE_TRAP);
681 break;
682
683 case 050: /* CLRB */
684 if (dstreg) WrRegB (0, dstspec);
685 else WrMemB (0, GeteaB (dstspec));
686 cc = CC_Z;
687 break;
688
689 case 051: /* COMB */
690 if (dstreg) src = RdRegB (dstspec);
691 else src = RdMemMB (ea = GeteaB (dstspec));
692 dst = src ^ BMASK;
693 if (dstreg) WrRegB (dst, dstspec);
694 else WrMemB (dst, ea);
695 CC_IIZZ_B (dst);
696 cc = cc | CC_C;
697 break;
698
699 case 052: /* INCB */
700 if (dstreg) src = RdRegB (dstspec);
701 else src = RdMemMB (ea = GeteaB (dstspec));
702 dst = (src + 1) & BMASK;
703 if (dstreg) WrRegB (dst, dstspec);
704 else WrMemB (dst, ea);
705 CC_IIZP_B (dst);
706 if (dst == 0200) cc = cc | CC_V;
707 break;
708
709 case 053: /* DECB */
710 if (dstreg) src = RdRegB (dstspec);
711 else src = RdMemMB (ea = GeteaB (dstspec));
712 dst = (src - 1) & BMASK;
713 if (dstreg) WrRegB (dst, dstspec);
714 else WrMemB (dst, ea);
715 CC_IIZP_B (dst);
716 if (dst == 0177) cc = cc | CC_V;
717 break;
718
719 case 054: /* NEGB */
720 if (dstreg) src = RdRegB (dstspec);
721 else src = RdMemMB (ea = GeteaB (dstspec));
722 dst = (-src) & BMASK;
723 if (dstreg) WrRegB (dst, dstspec);
724 else WrMemB (dst, ea);
725 CC_IIZZ_B (dst);
726 if (dst == 0200) cc = cc | CC_V;
727 if (dst) cc = cc | CC_C;
728 break;
729
730 case 055: /* ADCB */
731 if (dstreg) src = RdRegB (dstspec);
732 else src = RdMemMB (ea = GeteaB (dstspec));
733 dst = (src + (cc & CC_C)) & BMASK;
734 if (dstreg) WrRegB (dst, dstspec);
735 else WrMemB (dst, ea);
736 CC_IIZZ_B (dst);
737 if ((src == 0177) && (dst == 0200)) cc = cc | CC_V;
738 if ((src == 0377) && (dst == 0)) cc = cc | CC_C;
739 break;
740
741 case 056: /* SBCB */
742 if (dstreg) src = RdRegB (dstspec);
743 else src = RdMemMB (ea = GeteaB (dstspec));
744 dst = (src - (cc & CC_C)) & BMASK;
745 if (dstreg) WrRegB (dst, dstspec);
746 else WrMemB (dst, ea);
747 CC_IIZZ_B (dst);
748 if ((src == 0200) && (dst == 0177)) cc = cc | CC_V;
749 if ((src == 0) && (dst == 0377)) cc = cc | CC_C;
750 break;
751
752 case 057: /* TSTB */
753 if (dstreg) src = RdRegB (dstspec);
754 else src = RdMemB (GeteaB (dstspec));
755 CC_IIZZ_B (src);
756 break;
757
758 case 060: /* RORB */
759 if (dstreg) src = RdRegB (dstspec);
760 else src = RdMemMB (ea = GeteaB (dstspec));
761 dst = (src >> 1) | ((cc & CC_C)? BSIGN: 0);
762 if (dstreg) WrRegB (dst, dstspec);
763 else WrMemB (dst, ea);
764 CC_IIZZ_B (dst);
765 if (src & 1) cc = cc | CC_C;
766 if (CC_XOR_NC (cc)) cc = cc | CC_V;
767 break;
768
769 case 061: /* ROLB */
770 if (dstreg) src = RdRegB (dstspec);
771 else src = RdMemMB (ea = GeteaB (dstspec));
772 dst = ((src << 1) | ((cc & CC_C)? 1: 0)) & BMASK;
773 if (dstreg) WrRegB (dst, dstspec);
774 else WrMemB (dst, ea);
775 CC_IIZZ_B (dst);
776 if (src & BSIGN) cc = cc | CC_C;
777 if (CC_XOR_NC (cc)) cc = cc | CC_V;
778 break;
779
780 case 062: /* ASRB */
781 if (dstreg) src = RdRegB (dstspec);
782 else src = RdMemMB (ea = GeteaB (dstspec));
783 dst = (src >> 1) | (src & BSIGN);
784 if (dstreg) WrRegB (dst, dstspec);
785 else WrMemB (dst, ea);
786 CC_IIZZ_B (dst);
787 if (src & 1) cc = cc | CC_C;
788 if (CC_XOR_NC (cc)) cc = cc | CC_V;
789 break;
790
791 case 063: /* ASLB */
792 if (dstreg) src = RdRegB (dstspec);
793 else src = RdMemMB (ea = GeteaB (dstspec));
794 dst = (src << 1) & BMASK;
795 if (dstreg) WrRegB (dst, dstspec);
796 else WrMemB (dst, ea);
797 CC_IIZZ_B (dst);
798 if (src & BSIGN) cc = cc | CC_C;
799 if (CC_XOR_NC (cc)) cc = cc | CC_V;
800 break;
801
802 case 065: /* MFPD */
803 if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */
804 else dst = RdMemW (GeteaW (dstspec));
805 WrMemW (dst, (R[6] - 2) & WMASK);
806 R[6] = (R[6] - 2) & WMASK;
807 CC_IIZP_W (dst);
808 break;
809
810 case 066: /* MTPD */
811 dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */
812 R[6] = (R[6] + 2) & WMASK;
813 recq[recqptr++] = RQ_REC (AIN|RW, 6);
814 if (dstreg) WrRegW (dst, dstspec);
815 else WrMemW (dst, (GeteaW (dstspec) & WMASK));
816 CC_IIZP_W (dst);
817 break;
818
819 default:
820 CMODE_FAULT (CMODE_RSVI);
821 break; } /* end switch SOPs */
822 break; /* end case 010 */
823
824 /* Opcodes 11 - 16: double operand byte instructions
825
826 Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)]
827 Sub: v = [sign (src) != sign (src2)] and [sign (src) = sign (result)]
828 */
829
830 case 011: /* MOVB */
831 if (srcreg) src = RdRegB (srcspec);
832 else src = RdMemB (GeteaB (srcspec));
833 if (dstreg) WrRegW ((src & BSIGN)? (0xFF00 | src): src, dstspec);
834 else WrMemB (src, GeteaB (dstspec));
835 CC_IIZP_B (src);
836 break;
837
838 case 012: /* CMPB */
839 if (srcreg) src = RdRegB (srcspec);
840 else src = RdMemB (GeteaB (srcspec));
841 if (dstreg) src2 = RdRegB (dstspec);
842 else src2 = RdMemB (GeteaB (dstspec));
843 dst = (src - src2) & BMASK;
844 CC_IIZZ_B (dst);
845 if (((src ^ src2) & (~src2 ^ dst)) & BSIGN) cc = cc | CC_V;
846 if (src < src2) cc = cc | CC_C;
847 break;
848
849 case 013: /* BITB */
850 if (srcreg) src = RdRegB (srcspec);
851 else src = RdMemB (GeteaB (srcspec));
852 if (dstreg) src2 = RdRegB (dstspec);
853 else src2 = RdMemB (GeteaB (dstspec));
854 dst = src2 & src;
855 CC_IIZP_B (dst);
856 break;
857
858 case 014: /* BICB */
859 if (srcreg) src = RdRegB (srcspec);
860 else src = RdMemB (GeteaB (srcspec));
861 if (dstreg) src2 = RdRegB (dstspec);
862 else src2 = RdMemMB (ea = GeteaB (dstspec));
863 dst = src2 & ~src;
864 if (dstreg) WrRegB (dst, dstspec);
865 else WrMemB (dst, ea);
866 CC_IIZP_B (dst);
867 break;
868
869 case 015: /* BISB */
870 if (srcreg) src = RdRegB (srcspec);
871 else src = RdMemB (GeteaB (srcspec));
872 if (dstreg) src2 = RdRegB (dstspec);
873 else src2 = RdMemMB (ea = GeteaB (dstspec));
874 dst = src2 | src;
875 if (dstreg) WrRegB (dst, dstspec);
876 else WrMemB (dst, ea);
877 CC_IIZP_B (dst);
878 break;
879
880 case 016: /* SUB */
881 if (srcreg) src = RdRegW (srcspec);
882 else src = RdMemW (GeteaW (srcspec));
883 if (dstreg) src2 = RdRegW (dstspec);
884 else src2 = RdMemMW (ea = GeteaW (dstspec));
885 dst = (src2 - src) & WMASK;
886 if (dstreg) WrRegW (dst, dstspec);
887 else WrMemW (dst, ea);
888 CC_IIZZ_W (dst);
889 if (((src ^ src2) & (~src ^ dst)) & WSIGN) cc = cc | CC_V;
890 if (src2 < src) cc = cc | CC_C;
891 break;
892
893 default:
894 CMODE_FAULT (CMODE_RSVI);
895 break;
896 } /* end switch op */
897
898 return cc;
899 }
900
901 /* Effective address calculations
902
903 Inputs:
904 spec = specifier <5:0>
905 Outputs:
906 ea = effective address
907 */
908
909 int32 GeteaW (int32 spec)
910 {
911 int32 adr, reg;
912
913 reg = spec & 07; /* register number */
914 switch (spec >> 3) { /* decode spec<5:3> */
915
916 default: /* can't get here */
917 case 1: /* (R) */
918 if (reg == 7) return (PC & WMASK);
919 else return (R[reg] & WMASK);
920
921 case 2: /* (R)+ */
922 if (reg == 7) PC = ((adr = PC) + 2) & WMASK;
923 else {
924 R[reg] = ((adr = R[reg]) + 2) & WMASK;
925 recq[recqptr++] = RQ_REC (AIN|RW, reg);
926 }
927 return adr;
928
929 case 3: /* @(R)+ */
930 if (reg == 7) PC = ((adr = PC) + 2) & WMASK;
931 else {
932 R[reg] = ((adr = R[reg]) + 2) & WMASK;
933 recq[recqptr++] = RQ_REC (AIN|RW, reg);
934 }
935 return RdMemW (adr);
936
937 case 4: /* -(R) */
938 if (reg == 7) adr = PC = (PC - 2) & WMASK;
939 else {
940 adr = R[reg] = (R[reg] - 2) & WMASK;
941 recq[recqptr++] = RQ_REC (ADC|RW, reg);
942 }
943 return adr;
944
945 case 5: /* @-(R) */
946 if (reg == 7) adr = PC = (PC - 2) & WMASK;
947 else {
948 adr = R[reg] = (R[reg] - 2) & WMASK;
949 recq[recqptr++] = RQ_REC (ADC|RW, reg);
950 }
951 return RdMemW (adr);
952
953 case 6: /* d(r) */
954 adr = RdMemW (PC);
955 PC = (PC + 2) & WMASK;
956 if (reg == 7) return ((PC + adr) & WMASK);
957 else return ((R[reg] + adr) & WMASK);
958
959 case 7: /* @d(R) */
960 adr = RdMemW (PC);
961 PC = (PC + 2) & WMASK;
962 if (reg == 7) adr = (PC + adr) & WMASK;
963 else adr = (R[reg] + adr) & WMASK;
964 return RdMemW (adr);
965 } /* end switch */
966 }
967
968 int32 GeteaB (int32 spec)
969 {
970 int32 adr, reg;
971
972 reg = spec & 07; /* reg number */
973 switch (spec >> 3) { /* decode spec<5:3> */
974
975 default: /* can't get here */
976 case 1: /* (R) */
977 if (reg == 7) return (PC & WMASK);
978 else return (R[reg] & WMASK);
979
980 case 2: /* (R)+ */
981 if (reg == 7) PC = ((adr = PC) + 2) & WMASK;
982 else if (reg == 6) {
983 R[reg] = ((adr = R[reg]) + 2) & WMASK;
984 recq[recqptr++] = RQ_REC (AIN|RW, reg);
985 }
986 else {
987 R[reg] = ((adr = R[reg]) + 1) & WMASK;
988 recq[recqptr++] = RQ_REC (AIN|RB, reg);
989 }
990 return adr;
991
992 case 3: /* @(R)+ */
993 if (reg == 7) PC = ((adr = PC) + 2) & WMASK;
994 else {
995 R[reg] = ((adr = R[reg]) + 2) & WMASK;
996 recq[recqptr++] = RQ_REC (AIN|RW, reg);
997 }
998 return RdMemW (adr);
999
1000 case 4: /* -(R) */
1001 if (reg == 7) adr = PC = (PC - 2) & WMASK;
1002 else if (reg == 6) {
1003 adr = R[reg] = (R[reg] - 2) & WMASK;
1004 recq[recqptr++] = RQ_REC (ADC|RW, reg);
1005 }
1006 else {
1007 adr = R[reg] = (R[reg] - 1) & WMASK;
1008 recq[recqptr++] = RQ_REC (ADC|RB, reg);
1009 }
1010 return adr;
1011
1012 case 5: /* @-(R) */
1013 if (reg == 7) adr = PC = (PC - 2) & WMASK;
1014 else {
1015 adr = R[reg] = (R[reg] - 2) & WMASK;
1016 recq[recqptr++] = RQ_REC (ADC|RW, reg);
1017 }
1018 return RdMemW (adr);
1019
1020 case 6: /* d(r) */
1021 adr = RdMemW (PC);
1022 PC = (PC + 2) & WMASK;
1023 if (reg == 7) return ((PC + adr) & WMASK);
1024 else return ((R[reg] + adr) & WMASK);
1025
1026 case 7: /* @d(R) */
1027 adr = RdMemW (PC);
1028 PC = (PC + 2) & WMASK;
1029 if (reg == 7) adr = (PC + adr) & WMASK;
1030 else adr = (R[reg] + adr) & WMASK;
1031 return RdMemW (adr);
1032 } /* end switch */
1033 }
1034
1035 /* Memory and register access routines */
1036
1037 int32 RdMemW (int32 a)
1038 {
1039 int32 acc = ACC_MASK (USER);
1040
1041 if (a & 1) CMODE_FAULT (CMODE_ODD);
1042 return Read (a, L_WORD, RA);
1043 }
1044
1045 int32 RdMemMW (int32 a)
1046 {
1047 int32 acc = ACC_MASK (USER);
1048
1049 if (a & 1) CMODE_FAULT (CMODE_ODD);
1050 return Read (a, L_WORD, WA);
1051 }
1052
1053 void WrMemW (int32 d, int32 a)
1054 {
1055 int32 acc = ACC_MASK (USER);
1056
1057 if (a & 1) CMODE_FAULT (CMODE_ODD);
1058 Write (a, d, L_WORD, WA);
1059 return;
1060 }
1061
1062 int32 RdRegB (int32 rn)
1063 {
1064 if (rn == 7) return (PC & BMASK);
1065 else return (R[rn] & BMASK);
1066 }
1067
1068 int32 RdRegW (int32 rn)
1069 {
1070 if (rn == 7) return (PC & WMASK);
1071 else return (R[rn] & WMASK);
1072 }
1073
1074 void WrRegB (int32 val, int32 rn)
1075 {
1076 if (rn == 7) { CMODE_JUMP ((PC & ~BMASK) | val); }
1077 else R[rn] = (R[rn] & ~BMASK) | val;
1078 return;
1079 }
1080
1081 void WrRegW (int32 val, int32 rn)
1082 {
1083 if (rn == 7) { CMODE_JUMP (val); }
1084 else R[rn] = val;
1085 return;
1086 }
1087
1088 #else
1089
1090 /* Subset VAX
1091
1092 Never legal to set CM in PSL
1093 Should never get to instruction execution
1094 */
1095
1096 extern jmp_buf save_env;
1097
1098 t_bool BadCmPSL (int32 newpsl)
1099 {
1100 return TRUE; /* always bad */
1101 }
1102
1103 int32 op_cmode (int32 cc)
1104 {
1105 RSVD_INST_FAULT;
1106 return cc;
1107 }
1108
1109 #endif