1 /* vax_cmode.c: VAX compatibility mode
3 Copyright (c) 2004-2008, Robert M Supnik
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
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>.
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
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.
42 #if defined (FULL_VAX)
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))
56 extern int32 fault_PC
;
57 extern int32 recq
[]; /* recovery queue */
58 extern int32 recqptr
; /* recq pointer */
61 extern int32 ibcnt
, ppc
;
62 extern int32 sim_interval
;
63 extern uint32 sim_brk_summ
;
64 extern jmp_buf save_env
;
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
);
76 /* Validate PSL for compatibility mode */
78 t_bool
BadCmPSL (int32 newpsl
)
80 if ((newpsl
& (PSL_FPD
|PSL_IS
|PSL_CUR
|PSL_PRV
|PSL_IPL
)) !=
81 ((USER
<< PSL_V_CUR
) | (USER
<< PSL_V_PRV
)))
86 /* Compatibility mode execution */
88 int32
op_cmode (int32 cc
)
90 int32 IR
, srcspec
, dstspec
, srcreg
, dstreg
, ea
;
91 int32 i
, t
, src
, src2
, dst
, sign
, oc
;
92 int32 acc
= ACC_MASK (USER
);
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 */
98 sim_interval
= sim_interval
- 1; /* count instr */
100 IR
= RdMemW (PC
); /* fetch instruction */
101 PC
= (PC
+ 2) & WMASK
; /* incr PC, mod 65k */
102 srcspec
= (IR
>> 6) & 077; /* src, dst specs */
104 srcreg
= (srcspec
<= 07); /* src, dst = rmode? */
105 dstreg
= (dstspec
<= 07);
106 switch ((IR
>> 12) & 017) { /* decode IR<15:12> */
108 /* Opcode 0: no operands, specials, branches, JSR, SOPs */
110 case 000: /* 00xxxx */
111 switch ((IR
>> 6) & 077) { /* decode IR<11:6> */
112 case 000: /* 0000xx */
113 switch (IR
) { /* decode IR<5:0> */
115 CMODE_FAULT (CMODE_BPT
);
119 CMODE_FAULT (CMODE_IOT
);
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 */
133 default: /* undefined */
134 CMODE_FAULT (CMODE_RSVI
);
136 } /* end switch IR */
137 break; /* end case 0000xx */
140 if (dstreg
) CMODE_FAULT (CMODE_ILLI
); /* mode 0 illegal */
141 else { CMODE_JUMP (GeteaW (dstspec
)); }
144 case 002: /* 0002xx */
145 if (IR
< 000210) { /* RTS */
146 dstspec
= dstspec
& 07;
147 if (dstspec
!= 7) { /* PC <- r */
148 CMODE_JUMP (RdRegW (dstspec
));
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 */
155 if (IR
< 000240) { /* [210:237] */
156 CMODE_FAULT (CMODE_RSVI
);
159 if (IR
< 000260) cc
= cc
& ~(IR
& CC_MASK
); /* clear CC */
160 else cc
= cc
| (IR
& CC_MASK
); /* set CC */
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
));
172 case 004: case 005: /* BR */
176 case 006: case 007: /* BR */
180 case 010: case 011: /* BNE */
181 if ((cc
& CC_Z
) == 0) { BRANCH_F (IR
); }
184 case 012: case 013: /* BNE */
185 if ((cc
& CC_Z
) == 0) { BRANCH_B (IR
); }
188 case 014: case 015: /* BEQ */
189 if (cc
& CC_Z
) { BRANCH_F (IR
); }
192 case 016: case 017: /* BEQ */
193 if (cc
& CC_Z
) { BRANCH_B (IR
); }
196 case 020: case 021: /* BGE */
197 if (CC_XOR_NV (cc
) == 0) { BRANCH_F (IR
); }
200 case 022: case 023: /* BGE */
201 if (CC_XOR_NV (cc
) == 0) { BRANCH_B (IR
); }
204 case 024: case 025: /* BLT */
205 if (CC_XOR_NV (cc
)) { BRANCH_F (IR
); }
208 case 026: case 027: /* BLT */
209 if (CC_XOR_NV (cc
)) { BRANCH_B (IR
); }
212 case 030: case 031: /* BGT */
213 if (((cc
& CC_Z
) || CC_XOR_NV (cc
)) == 0) { BRANCH_F (IR
); }
216 case 032: case 033: /* BGT */
217 if (((cc
& CC_Z
) || CC_XOR_NV (cc
)) == 0) { BRANCH_B (IR
); }
220 case 034: case 035: /* BLE */
221 if ((cc
& CC_Z
) || CC_XOR_NV (cc
)) { BRANCH_F (IR
); }
224 case 036: case 037: /* BLE */
225 if ((cc
& CC_Z
) || CC_XOR_NV (cc
)) { BRANCH_B (IR
); }
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 */
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 */
243 if (dstreg
) WrRegW (0, dstspec
);
244 else WrMemW (0, GeteaW (dstspec
));
249 if (dstreg
) src
= RdRegW (dstspec
);
250 else src
= RdMemMW (ea
= GeteaW (dstspec
));
252 if (dstreg
) WrRegW (dst
, dstspec
);
253 else WrMemW (dst
, ea
);
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
);
265 if (dst
== 0100000) cc
= cc
| CC_V
;
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
);
275 if (dst
== 077777) cc
= cc
| CC_V
;
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
);
285 if (dst
== 0100000) cc
= cc
| CC_V
;
286 if (dst
) cc
= cc
| CC_C
;
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
);
296 if ((src
== 077777) && (dst
== 0100000)) cc
= cc
| CC_V
;
297 if ((src
== 0177777) && (dst
== 0)) cc
= cc
| CC_C
;
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
);
307 if ((src
== 0100000) && (dst
== 077777)) cc
= cc
| CC_V
;
308 if ((src
== 0) && (dst
== 0177777)) cc
= cc
| CC_C
;
312 if (dstreg
) src
= RdRegW (dstspec
);
313 else src
= RdMemW (GeteaW (dstspec
));
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
);
324 if (src
& 1) cc
= cc
| CC_C
;
325 if (CC_XOR_NC (cc
)) cc
= cc
| CC_V
;
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
);
335 if (src
& WSIGN
) cc
= cc
| CC_C
;
336 if (CC_XOR_NC (cc
)) cc
= cc
| CC_V
;
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
);
346 if (src
& 1) cc
= cc
| CC_C
;
347 if (CC_XOR_NC (cc
)) cc
= cc
| CC_V
;
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
);
357 if (src
& WSIGN
) cc
= cc
| CC_C
;
358 if (CC_XOR_NC (cc
)) cc
= cc
| CC_V
;
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
;
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
));
379 dst
= (cc
& CC_N
)? 0177777: 0;
380 if (dstreg
) WrRegW (dst
, dstspec
);
381 else WrMemW (dst
, GeteaW (dstspec
));
385 default: /* undefined */
386 CMODE_FAULT (CMODE_RSVI
);
388 } /* end switch SOPs */
389 break; /* end case 000 */
391 /* Opcodes 01 - 06: double operand word instructions
393 Compatibility mode requires source address decode, source fetch,
394 dest address decode, dest fetch/store.
396 Add: v = [sign (src) = sign (src2)] and [sign (src) != sign (result)]
397 Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)]
401 if (srcreg
) src
= RdRegW (srcspec
);
402 else src
= RdMemW (GeteaW (srcspec
));
403 if (dstreg
) WrRegW (src
, dstspec
);
404 else WrMemW (src
, GeteaW (dstspec
));
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
;
415 if (((src
^ src2
) & (~src2
^ dst
)) & WSIGN
) cc
= cc
| CC_V
;
416 if (src
< src2
) cc
= cc
| CC_C
;
420 if (srcreg
) src
= RdRegW (srcspec
);
421 else src
= RdMemW (GeteaW (srcspec
));
422 if (dstreg
) src2
= RdRegW (dstspec
);
423 else src2
= RdMemW (GeteaW (dstspec
));
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
));
434 if (dstreg
) WrRegW (dst
, dstspec
);
435 else WrMemW (dst
, ea
);
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
));
445 if (dstreg
) WrRegW (dst
, dstspec
);
446 else WrMemW (dst
, ea
);
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
);
461 /* Opcode 07: EIS, FIS (not implemented), CIS
464 - MUL carry: C is set if the (signed) result doesn't fit in 16 bits.
465 - Divide has three error cases:
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.
478 srcspec
= srcspec
& 07; /* get src reg */
479 switch ((IR
>> 9) & 07) { /* decode IR<11:9> */
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
;
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 */
503 if ((src
== LSIGN
) && (src2
== WMASK
)) { /* -2^31 / -1? */
504 cc
= CC_V
; /* overflow */
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 */
514 CC_IIZZ_W (dst
& WMASK
); /* set cc's */
515 WrRegW (dst
& WMASK
, srcspec
); /* quotient */
516 WrRegW ((src
- (src2
* dst
)) & WMASK
, srcspec
| 1);
520 if (dstreg
) src2
= RdRegW (dstspec
); /* get src2 */
521 else src2
= RdMemW (GeteaW (dstspec
));
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 */
529 else if (src2
<= 15) { /* [1,15] */
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
;
535 else if (src2
<= 31) { /* [16,31] */
537 oc
= ((src
<< (src2
- 16)) & 1)? CC_C
: 0;
538 if (src
) oc
= oc
| CC_V
;
540 else if (src2
== 32) { /* [32] = -32 */
544 else { /* [33,63] = -31,-1 */
545 dst
= (src
>> (64 - src2
)) | (-sign
<< (src2
- 32));
546 oc
= ((src
>> (63 - src2
)) & 1)? CC_C
: 0;
548 WrRegW (dst
= dst
& WMASK
, srcspec
); /* result */
554 if (dstreg
) src2
= RdRegW (dstspec
); /* get src2 */
555 else src2
= RdMemW (GeteaW (dstspec
));
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 */
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
;
570 else if (src2
== 32) { /* [32] = -32 */
574 else { /* [33,63] = -31,-1 */
575 dst
= (src
>> (64 - src2
)) | (-sign
<< (src2
- 32));
576 oc
= ((src
>> (63 - src2
)) & 1)? CC_C
: 0;
578 WrRegW ((dst
>> 16) & WMASK
, srcspec
); /* high result */
579 WrRegW (dst
& WMASK
, srcspec
| 1); /* low result */
580 CC_IIZZ_L (dst
& LMASK
);
585 src
= RdRegW (srcspec
); /* get src */
586 if (dstreg
) src2
= RdRegW (dstspec
); /* get dst */
587 else src2
= RdMemMW (ea
= GeteaW (dstspec
));
589 if (dstreg
) WrRegW (dst
, dstspec
); /* result */
590 else WrMemW (dst
, ea
);
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
);
603 CMODE_FAULT (CMODE_RSVI
); /* end switch EIS */
605 break; /* end case 007 */
607 /* Opcode 10: branches, traps, SOPs */
610 switch ((IR
>> 6) & 077) { /* decode IR<11:6> */
611 case 000: case 001: /* BPL */
612 if ((cc
& CC_N
) == 0) { BRANCH_F (IR
); }
615 case 002: case 003: /* BPL */
616 if ((cc
& CC_N
) == 0) { BRANCH_B (IR
); }
619 case 004: case 005: /* BMI */
620 if (cc
& CC_N
) { BRANCH_F (IR
); }
623 case 006: case 007: /* BMI */
624 if (cc
& CC_N
) { BRANCH_B (IR
); }
627 case 010: case 011: /* BHI */
628 if ((cc
& (CC_C
| CC_Z
)) == 0) { BRANCH_F (IR
); }
631 case 012: case 013: /* BHI */
632 if ((cc
& (CC_C
| CC_Z
)) == 0) { BRANCH_B (IR
); }
635 case 014: case 015: /* BLOS */
636 if (cc
& (CC_C
| CC_Z
)) { BRANCH_F (IR
); }
639 case 016: case 017: /* BLOS */
640 if (cc
& (CC_C
| CC_Z
)) { BRANCH_B (IR
); }
643 case 020: case 021: /* BVC */
644 if ((cc
& CC_V
) == 0) { BRANCH_F (IR
); }
647 case 022: case 023: /* BVC */
648 if ((cc
& CC_V
) == 0) { BRANCH_B (IR
); }
651 case 024: case 025: /* BVS */
652 if (cc
& CC_V
) { BRANCH_F (IR
); }
655 case 026: case 027: /* BVS */
656 if (cc
& CC_V
) { BRANCH_B (IR
); }
659 case 030: case 031: /* BCC */
660 if ((cc
& CC_C
) == 0) { BRANCH_F (IR
); }
663 case 032: case 033: /* BCC */
664 if ((cc
& CC_C
) == 0) { BRANCH_B (IR
); }
667 case 034: case 035: /* BCS */
668 if (cc
& CC_C
) { BRANCH_F (IR
); }
671 case 036: case 037: /* BCS */
672 if (cc
& CC_C
) { BRANCH_B (IR
); }
675 case 040: case 041: case 042: case 043: /* EMT */
676 CMODE_FAULT (CMODE_EMT
);
679 case 044: case 045: case 046: case 047: /* TRAP */
680 CMODE_FAULT (CMODE_TRAP
);
684 if (dstreg
) WrRegB (0, dstspec
);
685 else WrMemB (0, GeteaB (dstspec
));
690 if (dstreg
) src
= RdRegB (dstspec
);
691 else src
= RdMemMB (ea
= GeteaB (dstspec
));
693 if (dstreg
) WrRegB (dst
, dstspec
);
694 else WrMemB (dst
, ea
);
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
);
706 if (dst
== 0200) cc
= cc
| CC_V
;
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
);
716 if (dst
== 0177) cc
= cc
| CC_V
;
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
);
726 if (dst
== 0200) cc
= cc
| CC_V
;
727 if (dst
) cc
= cc
| CC_C
;
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
);
737 if ((src
== 0177) && (dst
== 0200)) cc
= cc
| CC_V
;
738 if ((src
== 0377) && (dst
== 0)) cc
= cc
| CC_C
;
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
);
748 if ((src
== 0200) && (dst
== 0177)) cc
= cc
| CC_V
;
749 if ((src
== 0) && (dst
== 0377)) cc
= cc
| CC_C
;
753 if (dstreg
) src
= RdRegB (dstspec
);
754 else src
= RdMemB (GeteaB (dstspec
));
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
);
765 if (src
& 1) cc
= cc
| CC_C
;
766 if (CC_XOR_NC (cc
)) cc
= cc
| CC_V
;
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
);
776 if (src
& BSIGN
) cc
= cc
| CC_C
;
777 if (CC_XOR_NC (cc
)) cc
= cc
| CC_V
;
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
);
787 if (src
& 1) cc
= cc
| CC_C
;
788 if (CC_XOR_NC (cc
)) cc
= cc
| CC_V
;
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
);
798 if (src
& BSIGN
) cc
= cc
| CC_C
;
799 if (CC_XOR_NC (cc
)) cc
= cc
| CC_V
;
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
;
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
));
820 CMODE_FAULT (CMODE_RSVI
);
821 break; } /* end switch SOPs */
822 break; /* end case 010 */
824 /* Opcodes 11 - 16: double operand byte instructions
826 Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)]
827 Sub: v = [sign (src) != sign (src2)] and [sign (src) = sign (result)]
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
));
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
;
845 if (((src
^ src2
) & (~src2
^ dst
)) & BSIGN
) cc
= cc
| CC_V
;
846 if (src
< src2
) cc
= cc
| CC_C
;
850 if (srcreg
) src
= RdRegB (srcspec
);
851 else src
= RdMemB (GeteaB (srcspec
));
852 if (dstreg
) src2
= RdRegB (dstspec
);
853 else src2
= RdMemB (GeteaB (dstspec
));
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
));
864 if (dstreg
) WrRegB (dst
, dstspec
);
865 else WrMemB (dst
, ea
);
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
));
875 if (dstreg
) WrRegB (dst
, dstspec
);
876 else WrMemB (dst
, ea
);
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
);
889 if (((src
^ src2
) & (~src
^ dst
)) & WSIGN
) cc
= cc
| CC_V
;
890 if (src2
< src
) cc
= cc
| CC_C
;
894 CMODE_FAULT (CMODE_RSVI
);
896 } /* end switch op */
901 /* Effective address calculations
904 spec = specifier <5:0>
906 ea = effective address
909 int32
GeteaW (int32 spec
)
913 reg
= spec
& 07; /* register number */
914 switch (spec
>> 3) { /* decode spec<5:3> */
916 default: /* can't get here */
918 if (reg
== 7) return (PC
& WMASK
);
919 else return (R
[reg
] & WMASK
);
922 if (reg
== 7) PC
= ((adr
= PC
) + 2) & WMASK
;
924 R
[reg
] = ((adr
= R
[reg
]) + 2) & WMASK
;
925 recq
[recqptr
++] = RQ_REC (AIN
|RW
, reg
);
930 if (reg
== 7) PC
= ((adr
= PC
) + 2) & WMASK
;
932 R
[reg
] = ((adr
= R
[reg
]) + 2) & WMASK
;
933 recq
[recqptr
++] = RQ_REC (AIN
|RW
, reg
);
938 if (reg
== 7) adr
= PC
= (PC
- 2) & WMASK
;
940 adr
= R
[reg
] = (R
[reg
] - 2) & WMASK
;
941 recq
[recqptr
++] = RQ_REC (ADC
|RW
, reg
);
946 if (reg
== 7) adr
= PC
= (PC
- 2) & WMASK
;
948 adr
= R
[reg
] = (R
[reg
] - 2) & WMASK
;
949 recq
[recqptr
++] = RQ_REC (ADC
|RW
, reg
);
955 PC
= (PC
+ 2) & WMASK
;
956 if (reg
== 7) return ((PC
+ adr
) & WMASK
);
957 else return ((R
[reg
] + adr
) & WMASK
);
961 PC
= (PC
+ 2) & WMASK
;
962 if (reg
== 7) adr
= (PC
+ adr
) & WMASK
;
963 else adr
= (R
[reg
] + adr
) & WMASK
;
968 int32
GeteaB (int32 spec
)
972 reg
= spec
& 07; /* reg number */
973 switch (spec
>> 3) { /* decode spec<5:3> */
975 default: /* can't get here */
977 if (reg
== 7) return (PC
& WMASK
);
978 else return (R
[reg
] & WMASK
);
981 if (reg
== 7) PC
= ((adr
= PC
) + 2) & WMASK
;
983 R
[reg
] = ((adr
= R
[reg
]) + 2) & WMASK
;
984 recq
[recqptr
++] = RQ_REC (AIN
|RW
, reg
);
987 R
[reg
] = ((adr
= R
[reg
]) + 1) & WMASK
;
988 recq
[recqptr
++] = RQ_REC (AIN
|RB
, reg
);
993 if (reg
== 7) PC
= ((adr
= PC
) + 2) & WMASK
;
995 R
[reg
] = ((adr
= R
[reg
]) + 2) & WMASK
;
996 recq
[recqptr
++] = RQ_REC (AIN
|RW
, reg
);
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
);
1007 adr
= R
[reg
] = (R
[reg
] - 1) & WMASK
;
1008 recq
[recqptr
++] = RQ_REC (ADC
|RB
, reg
);
1013 if (reg
== 7) adr
= PC
= (PC
- 2) & WMASK
;
1015 adr
= R
[reg
] = (R
[reg
] - 2) & WMASK
;
1016 recq
[recqptr
++] = RQ_REC (ADC
|RW
, reg
);
1018 return RdMemW (adr
);
1022 PC
= (PC
+ 2) & WMASK
;
1023 if (reg
== 7) return ((PC
+ adr
) & WMASK
);
1024 else return ((R
[reg
] + adr
) & WMASK
);
1028 PC
= (PC
+ 2) & WMASK
;
1029 if (reg
== 7) adr
= (PC
+ adr
) & WMASK
;
1030 else adr
= (R
[reg
] + adr
) & WMASK
;
1031 return RdMemW (adr
);
1035 /* Memory and register access routines */
1037 int32
RdMemW (int32 a
)
1039 int32 acc
= ACC_MASK (USER
);
1041 if (a
& 1) CMODE_FAULT (CMODE_ODD
);
1042 return Read (a
, L_WORD
, RA
);
1045 int32
RdMemMW (int32 a
)
1047 int32 acc
= ACC_MASK (USER
);
1049 if (a
& 1) CMODE_FAULT (CMODE_ODD
);
1050 return Read (a
, L_WORD
, WA
);
1053 void WrMemW (int32 d
, int32 a
)
1055 int32 acc
= ACC_MASK (USER
);
1057 if (a
& 1) CMODE_FAULT (CMODE_ODD
);
1058 Write (a
, d
, L_WORD
, WA
);
1062 int32
RdRegB (int32 rn
)
1064 if (rn
== 7) return (PC
& BMASK
);
1065 else return (R
[rn
] & BMASK
);
1068 int32
RdRegW (int32 rn
)
1070 if (rn
== 7) return (PC
& WMASK
);
1071 else return (R
[rn
] & WMASK
);
1074 void WrRegB (int32 val
, int32 rn
)
1076 if (rn
== 7) { CMODE_JUMP ((PC
& ~BMASK
) | val
); }
1077 else R
[rn
] = (R
[rn
] & ~BMASK
) | val
;
1081 void WrRegW (int32 val
, int32 rn
)
1083 if (rn
== 7) { CMODE_JUMP (val
); }
1092 Never legal to set CM in PSL
1093 Should never get to instruction execution
1096 extern jmp_buf save_env
;
1098 t_bool
BadCmPSL (int32 newpsl
)
1100 return TRUE
; /* always bad */
1103 int32
op_cmode (int32 cc
)