First Commit of my working state
[simh.git] / VAX / vax_cpu1.c
CommitLineData
196ba1fc
PH
1/* vax_cpu1.c: VAX complex instructions\r
2\r
3 Copyright (c) 1998-2008, Robert M Supnik\r
4\r
5 Permission is hereby granted, free of charge, to any person obtaining a\r
6 copy of this software and associated documentation files (the "Software"),\r
7 to deal in the Software without restriction, including without limitation\r
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
9 and/or sell copies of the Software, and to permit persons to whom the\r
10 Software is furnished to do so, subject to the following conditions:\r
11\r
12 The above copyright notice and this permission notice shall be included in\r
13 all copies or substantial portions of the Software.\r
14\r
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21\r
22 Except as contained in this notice, the name of Robert M Supnik shall not be\r
23 used in advertising or otherwise to promote the sale, use or other dealings\r
24 in this Software without prior written authorization from Robert M Supnik.\r
25\r
26 28-May-08 RMS Inlined physical memory routines\r
27 29-Apr-07 RMS Separated base register access checks for 11/780\r
28 10-May-06 RMS Added access check on system PTE for 11/780\r
29 Added mbz check in LDPCTX for 11/780\r
30 22-Sep-06 RMS Fixed declarations (from Sterling Garwood)\r
31 30-Sep-04 RMS Added conditionals for full VAX\r
32 Moved emulation to vax_cis.c\r
33 Moved model-specific IPRs to system module\r
34 27-Jan-04 RMS Added device logging support\r
35 Fixed EXTxV, INSV double register PC reference fault\r
36 30-Apr-02 RMS Fixed interrupt/exception handler to clear traps\r
37 17-Apr-02 RMS Fixed pos > 31 test in bit fields (should be unsigned)\r
38 14-Apr-02 RMS Fixed prv_mode handling for interrupts (found by Tim Stark)\r
39 Fixed PROBEx to mask mode to 2b (found by Kevin Handy)\r
40\r
41 This module contains the instruction simulators for\r
42\r
43 Field instructions:\r
44 - BBS, BBC, BBSSI, BBCCI\r
45 - BBSC, BBCC, BBCS, BBSS\r
46 - EXTV, EXTZV, CMPV, CMPZV\r
47 - FFS, FFC, INSV\r
48\r
49 Call/return and push/pop instructions:\r
50 - CALLS, CALLG, RET\r
51 - PUSHR, POPR\r
52\r
53 Queue instructions:\r
54 - INSQUE, REMQUE\r
55 - INSQHI, INSQTI, REMQHI, REMQTI\r
56\r
57 String instructions:\r
58 - MOVC3, MOVC5, CMPC3, CMPC5\r
59 - LOCC, SKPC, SCANC, SPANC\r
60\r
61 Operating system interface instructions:\r
62 - CHMK, CHME, CHMS, CHMU\r
63 - PROBER, PROBEW, REI\r
64 - MTPR, MFPR\r
65 - LDPCTX, SVPCTX\r
66 - (interrupt and exception routine) \r
67*/\r
68\r
69#include "vax_defs.h"\r
70\r
71static const uint8 rcnt[128] = {\r
72 0, 4, 4, 8, 4, 8, 8,12, 4, 8, 8,12, 8,12,12,16, /* 00 - 0F */\r
73 4, 8, 8,12, 8,12,12,16, 8,12,12,16,12,16,16,20, /* 10 - 1F */\r
74 4, 8, 8,12, 8,12,12,16, 8,12,12,16,12,16,16,20, /* 20 - 2F */\r
75 8,12,12,16,12,16,16,20,12,16,16,20,16,20,20,24, /* 30 - 3F */\r
76 4, 8, 8,12, 8,12,12,16, 8,12,12,16,12,16,16,20, /* 40 - 4F */\r
77 8,12,12,16,12,16,16,20,12,16,16,20,16,20,20,24, /* 50 - 5F */\r
78 8,12,12,16,12,16,16,20,12,16,16,20,16,20,20,24, /* 60 - 6F */\r
7912,16,16,20,16,20,20,24,16,20,20,24,20,24,24,28 /* 70 - 7F */\r
80};\r
81\r
82int32 last_chm = 0;\r
83\r
84extern uint32 *M;\r
85extern const uint32 byte_mask[33];\r
86extern int32 R[16];\r
87extern int32 STK[5];\r
88extern int32 PSL;\r
89extern int32 SCBB, PCBB, SBR, SLR;\r
90extern int32 P0BR, P0LR, P1BR, P1LR;\r
91extern int32 ASTLVL, SISR, mapen;\r
92extern int32 pme;\r
93extern int32 trpirq;\r
94extern int32 p1, p2;\r
95extern int32 fault_PC;\r
96extern int32 pcq[PCQ_SIZE];\r
97extern int32 pcq_p;\r
98extern int32 in_ie;\r
99extern int32 sim_interval;\r
100extern int32 ibcnt, ppc;\r
101extern FILE *sim_deb;\r
102extern DEVICE cpu_dev;\r
103\r
104extern int32 Test (uint32 va, int32 acc, int32 *status);\r
105extern void set_map_reg (void);\r
106extern void zap_tb (int stb);\r
107extern void zap_tb_ent (uint32 va);\r
108extern t_bool chk_tb_ent (uint32 va);\r
109extern int32 ReadIPR (int32 rg);\r
110extern void WriteIPR (int32 rg, int32 val);\r
111extern t_bool BadCmPSL (int32 newpsl);\r
112extern int32 cpu_psl_ipl_idle (int32 newpsl);\r
113\r
114extern jmp_buf save_env;\r
115\r
116/* Branch on bit and no modify\r
117 Branch on bit and modify\r
118\r
119 opnd[0] = position (pos.rl)\r
120 opnd[1] = register number/memory flag\r
121 opnd[2] = memory address, if memory\r
122 Returns bit to be tested\r
123*/\r
124\r
125int32 op_bb_n (int32 *opnd, int32 acc)\r
126{\r
127int32 pos = opnd[0];\r
128int32 rn = opnd[1];\r
129int32 ea, by;\r
130\r
131if (rn >= 0) { /* register? */\r
132 if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */\r
133 return (R[rn] >> pos) & 1; /* get bit */\r
134 }\r
135ea = opnd[2] + (pos >> 3); /* base byte addr */\r
136pos = pos & 07; /* pos in byte */\r
137by = Read (ea, L_BYTE, RA); /* read byte */\r
138return ((by >> pos) & 1); /* get bit */\r
139}\r
140\r
141int32 op_bb_x (int32 *opnd, int32 newb, int32 acc)\r
142{\r
143int32 pos = opnd[0];\r
144int32 rn = opnd[1];\r
145int32 ea, by, bit;\r
146\r
147if (rn >= 0) { /* register? */\r
148 if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */\r
149 bit = (R[rn] >> pos) & 1; /* get bit */\r
150 R[rn] = newb? (R[rn] | (1u << pos)): (R[rn] & ~(1u << pos));\r
151 return bit;\r
152 }\r
153ea = opnd[2] + (pos >> 3); /* base byte addr */\r
154pos = pos & 07; /* pos in byte */\r
155by = Read (ea, L_BYTE, WA); /* read byte */\r
156bit = (by >> pos) & 1; /* get bit */\r
157by = newb? (by | (1u << pos)): (by & ~(1u << pos)); /* change bit */\r
158Write (ea, by, L_BYTE, WA); /* rewrite byte */\r
159return bit;\r
160}\r
161\r
162/* Extract field\r
163\r
164 opnd[0] = position (pos.rl)\r
165 opnd[1] = size (size.rb)\r
166 opnd[2] = register number/memory flag\r
167 opnd[3] = register content/memory address\r
168\r
169 If the field is in a register, rn + 1 is in vfldrp1\r
170*/\r
171\r
172int32 op_extv (int32 *opnd, int32 vfldrp1, int32 acc)\r
173{\r
174int32 pos = opnd[0];\r
175int32 size = opnd[1];\r
176int32 rn = opnd[2];\r
177uint32 wd = opnd[3];\r
178int32 ba, wd1 = 0;\r
179\r
180if (size == 0) return 0; /* size 0? field = 0 */\r
181if (size > 32) RSVD_OPND_FAULT; /* size > 32? fault */\r
182if (rn >= 0) { /* register? */\r
183 if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */\r
184 if (((pos + size) > 32) && (rn >= nSP)) /* span 2 reg, PC? */\r
185 RSVD_ADDR_FAULT; /* fault */\r
186 if (pos) wd = (wd >> pos) | (((uint32) vfldrp1) << (32 - pos));\r
187 }\r
188else {\r
189 ba = wd + (pos >> 3); /* base byte addr */\r
190 pos = (pos & 07) | ((ba & 03) << 3); /* bit offset */\r
191 ba = ba & ~03; /* lw align base */\r
192 wd = Read (ba, L_LONG, RA); /* read field */\r
193 if ((size + pos) > 32) wd1 = Read (ba + 4, L_LONG, RA);\r
194 if (pos) wd = (wd >> pos) | (((uint32) wd1) << (32 - pos));\r
195 }\r
196return wd & byte_mask[size];\r
197}\r
198\r
199/* Insert field\r
200\r
201 opnd[0] = field (src.rl)\r
202 opnd[1] = position (pos.rl)\r
203 opnd[2] = size (size.rb)\r
204 opnd[3] = register number/memory flag\r
205 opnd[4] = register content/memory address\r
206\r
207 If the field is in a register, rn + 1 is in vfldrp1\r
208*/\r
209\r
210void op_insv (int32 *opnd, int32 vfldrp1, int32 acc)\r
211{\r
212uint32 ins = opnd[0];\r
213int32 pos = opnd[1];\r
214int32 size = opnd[2];\r
215int32 rn = opnd[3];\r
216int32 val, mask, ba, wd, wd1;\r
217\r
218if (size == 0) return; /* size = 0? done */\r
219if (size > 32) RSVD_OPND_FAULT; /* size > 32? fault */\r
220if (rn >= 0) { /* in registers? */\r
221 if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */\r
222 if ((pos + size) > 32) { /* span two reg? */\r
223 if (rn >= nSP) RSVD_ADDR_FAULT; /* if PC, fault */\r
224 mask = byte_mask[pos + size - 32]; /* insert fragment */\r
225 val = ins >> (32 - pos);\r
226 R[rn + 1] = (vfldrp1 & ~mask) | (val & mask);\r
227 }\r
228 mask = byte_mask[size] << pos; /* insert field */\r
229 val = ins << pos;\r
230 R[rn] = (R[rn] & ~mask) | (val & mask);\r
231 }\r
232else {\r
233 ba = opnd[4] + (pos >> 3); /* base byte addr */\r
234 pos = (pos & 07) | ((ba & 03) << 3); /* bit offset */\r
235 ba = ba & ~03; /* lw align base */\r
236 wd = Read (ba, L_LONG, WA); /* read field */\r
237 if ((size + pos) > 32) { /* field span lw? */\r
238 wd1 = Read (ba + 4, L_LONG, WA); /* read 2nd lw */\r
239 mask = byte_mask[pos + size - 32]; /* insert fragment */\r
240 val = ins >> (32 - pos);\r
241 Write (ba + 4, (wd1 & ~mask) | (val & mask), L_LONG, WA);\r
242 }\r
243 mask = byte_mask[size] << pos; /* insert field */\r
244 val = ins << pos;\r
245 Write (ba, (wd & ~mask) | (val & mask), L_LONG, WA);\r
246 }\r
247return;\r
248}\r
249\r
250/* Find first */\r
251\r
252int32 op_ffs (uint32 wd, int32 size)\r
253{\r
254int32 i;\r
255\r
256for (i = 0; wd; i++, wd = wd >> 1) if (wd & 1) return i;\r
257return size;\r
258}\r
259\r
260#define CALL_DV 0x8000 /* DV set */\r
261#define CALL_IV 0x4000 /* IV set */\r
262#define CALL_MBZ 0x3000 /* MBZ */\r
263#define CALL_MASK 0x0FFF /* mask */\r
264#define CALL_V_SPA 30 /* SPA */\r
265#define CALL_M_SPA 03\r
266#define CALL_V_S 29 /* S flag */\r
267#define CALL_S (1 << CALL_V_S)\r
268#define CALL_V_MASK 16\r
269#define CALL_PUSH(n) if ((mask >> (n)) & 1) { \\r
270 tsp = tsp - 4; \\r
271 Write (tsp, R[n], L_LONG, WA); \\r
272 }\r
273#define CALL_GETSPA(x) (((x) >> CALL_V_SPA) & CALL_M_SPA)\r
274#define RET_POP(n) if ((spamask >> (n + CALL_V_MASK)) & 1) { \\r
275 R[n] = Read (tsp, L_LONG, RA); \\r
276 tsp = tsp + 4; \\r
277 }\r
278#define PUSHR_PUSH(n) CALL_PUSH(n)\r
279#define POPR_POP(n) if ((mask >> (n)) & 1) { \\r
280 R[n] = Read (SP, L_LONG, RA); \\r
281 SP = SP + 4; \\r
282 }\r
283\r
284/* CALLG, CALLS\r
285\r
286 opnd[0] = argument (arg.rx)\r
287 opnd[1] = procedure address (adr.ab)\r
288 flg = CALLG (0), CALLS (1) \r
289 acc = access mask\r
290\r
291 These instructions implement a generalized procedure call and return facility.\r
292 The principal data structure involved is the stack frame.\r
293 CALLS and CALLG build a stack frame in the following format:\r
294\r
295\r
296 +---------------------------------------------------------------+\r
297 | condition handler (initially 0) |\r
298 +---+-+-+-----------------------+--------------------+----------+ \r
299 |SPA|S|0| entry mask<11:0> | saved PSW<15:5> | 0 0 0 0 0|\r
300 +---+-+-+-----------------------+--------------------+----------+\r
301 | saved AP |\r
302 +---------------------------------------------------------------+\r
303 | saved FP |\r
304 +---------------------------------------------------------------+\r
305 | saved PC |\r
306 +---------------------------------------------------------------+\r
307 | saved R0 (...) |\r
308 +---------------------------------------------------------------+\r
309 . . \r
310 . (according to entry mask<11:0>) . \r
311 . . \r
312 +---------------------------------------------------------------+\r
313 | saved R11 (...) |\r
314 +---------------+-----------------------------------------------+\r
315 | #args (CALLS) | (0-3 bytes needed to align stack) |\r
316 +---------------+-----------------------------------------------+\r
317 | | 0 0 0 (CALLS) |\r
318 +---------------+-----------------------------------------------+\r
319\r
320 RET expects to find this structure based at the frame pointer (FP).\r
321\r
322 For CALLG and CALLS, the entry mask specifies the new settings of\r
323 DV and IV, and also which registers are to be saved on entry:\r
324\r
325 15 14 13 12 11 0\r
326 +--+--+-----+----------------------------------+\r
327 |DV|IV| MBZ | register mask |\r
328 +--+--+-----+----------------------------------+\r
329\r
330 CALLG/CALLS operation:\r
331\r
332 read the procedure entry mask\r
333 make sure that the stack frame will be accessible\r
334 if CALLS, push the number of arguments onto the stack\r
335 align the stack to the next lower longword boundary\r
336 push the registers specified by the procedure entry mask\r
337 push PC, AP, FP, saved SPA/S0/mask/PSW, condition handler\r
338 update PC, SP, FP, AP\r
339 update PSW traps, clear condition codes\r
340*/\r
341\r
342int32 op_call (int32 *opnd, t_bool gs, int32 acc)\r
343{\r
344int32 addr = opnd[1];\r
345int32 mask, stklen, tsp, wd;\r
346\r
347mask = Read (addr, L_WORD, RA); /* get proc mask */\r
348if (mask & CALL_MBZ) RSVD_OPND_FAULT; /* test mbz */\r
349stklen = rcnt[mask & 077] + rcnt[(mask >> 6) & 077] + (gs? 24: 20);\r
350Read (SP - stklen, L_BYTE, WA); /* wchk stk */\r
351if (gs) {\r
352 Write (SP - 4, opnd[0], L_LONG, WA); /* if S, push #arg */\r
353 SP = SP - 4; /* stack is valid */\r
354 }\r
355tsp = SP & ~CALL_M_SPA; /* lw align stack */\r
356CALL_PUSH (11); /* check mask bits, */\r
357CALL_PUSH (10); /* push sel reg */\r
358CALL_PUSH (9);\r
359CALL_PUSH (8);\r
360CALL_PUSH (7);\r
361CALL_PUSH (6);\r
362CALL_PUSH (5);\r
363CALL_PUSH (4);\r
364CALL_PUSH (3);\r
365CALL_PUSH (2);\r
366CALL_PUSH (1);\r
367CALL_PUSH (0);\r
368Write (tsp - 4, PC, L_LONG, WA); /* push PC */\r
369Write (tsp - 8, FP, L_LONG, WA); /* push AP */\r
370Write (tsp - 12, AP, L_LONG, WA); /* push FP */\r
371wd = ((SP & CALL_M_SPA) << CALL_V_SPA) | (gs << CALL_V_S) |\r
372 ((mask & CALL_MASK) << CALL_V_MASK) | (PSL & 0xFFE0);\r
373Write (tsp - 16, wd, L_LONG, WA); /* push spa/s/mask/psw */\r
374Write (tsp - 20, 0, L_LONG, WA); /* push cond hdlr */\r
375if (gs) AP = SP; /* update AP */\r
376else AP = opnd[0];\r
377SP = FP = tsp - 20; /* update FP, SP */\r
378PSL = (PSL & ~(PSW_DV | PSW_FU | PSW_IV)) | /* update PSW */\r
379 ((mask & CALL_DV)? PSW_DV: 0) |\r
380 ((mask & CALL_IV)? PSW_IV: 0);\r
381JUMP (addr + 2); /* new PC */\r
382return 0; /* new cc's */\r
383}\r
384\r
385int32 op_ret (int32 acc)\r
386{\r
387int32 spamask, stklen, newpc, nargs;\r
388int32 tsp = FP;\r
389\r
390spamask = Read (tsp + 4, L_LONG, RA); /* spa/s/mask/psw */\r
391if (spamask & PSW_MBZ) RSVD_OPND_FAULT; /* test mbz */\r
392stklen = rcnt[(spamask >> CALL_V_MASK) & 077] +\r
393 rcnt[(spamask >> (CALL_V_MASK + 6)) & 077] + ((spamask & CALL_S)? 23: 19);\r
394Read (tsp + stklen, L_BYTE, RA); /* rchk stk end */\r
395AP = Read (tsp + 8, L_LONG, RA); /* restore AP */\r
396FP = Read (tsp + 12, L_LONG, RA); /* restore FP */\r
397newpc = Read (tsp + 16, L_LONG, RA); /* get new PC */\r
398tsp = tsp + 20; /* update stk ptr */\r
399RET_POP (0); /* chk mask bits, */\r
400RET_POP (1); /* pop sel regs */\r
401RET_POP (2);\r
402RET_POP (3);\r
403RET_POP (4);\r
404RET_POP (5);\r
405RET_POP (6);\r
406RET_POP (7);\r
407RET_POP (8);\r
408RET_POP (9);\r
409RET_POP (10);\r
410RET_POP (11);\r
411SP = tsp + CALL_GETSPA (spamask); /* dealign stack */\r
412if (spamask & CALL_S) { /* CALLS? */\r
413 nargs = Read (SP, L_LONG, RA); /* read #args */\r
414 SP = SP + 4 + ((nargs & BMASK) << 2); /* pop arg list */\r
415 }\r
416PSL = (PSL & ~(PSW_DV | PSW_FU | PSW_IV | PSW_T)) | /* reset PSW */\r
417 (spamask & (PSW_DV | PSW_FU | PSW_IV | PSW_T));\r
418JUMP (newpc); /* set new PC */\r
419return spamask & (CC_MASK); /* return cc's */\r
420}\r
421\r
422/* PUSHR and POPR */\r
423\r
424void op_pushr (int32 *opnd, int32 acc)\r
425{\r
426int32 mask = opnd[0] & 0x7FFF;\r
427int32 stklen, tsp;\r
428\r
429if (mask == 0) return;\r
430stklen = rcnt[(mask >> 7) & 0177] + rcnt[mask & 0177] +\r
431 ((mask & 0x4000)? 4: 0);\r
432Read (SP - stklen, L_BYTE, WA); /* wchk stk end */\r
433tsp = SP; /* temp stk ptr */\r
434PUSHR_PUSH (14); /* check mask bits, */\r
435PUSHR_PUSH (13); /* push sel reg */\r
436PUSHR_PUSH (12);\r
437PUSHR_PUSH (11);\r
438PUSHR_PUSH (10);\r
439PUSHR_PUSH (9);\r
440PUSHR_PUSH (8);\r
441PUSHR_PUSH (7);\r
442PUSHR_PUSH (6);\r
443PUSHR_PUSH (5);\r
444PUSHR_PUSH (4);\r
445PUSHR_PUSH (3);\r
446PUSHR_PUSH (2);\r
447PUSHR_PUSH (1);\r
448PUSHR_PUSH (0);\r
449SP = tsp; /* update stk ptr */\r
450return;\r
451}\r
452\r
453void op_popr (int32 *opnd, int32 acc)\r
454{\r
455int32 mask = opnd[0] & 0x7FFF;\r
456int32 stklen;\r
457\r
458if (mask == 0) return;\r
459stklen = rcnt[(mask >> 7) & 0177] + rcnt[mask & 0177] +\r
460 ((mask & 0x4000)? 4: 0);\r
461Read (SP + stklen - 1, L_BYTE, RA); /* rchk stk end */\r
462POPR_POP (0); /* check mask bits, */\r
463POPR_POP (1); /* pop sel regs */\r
464POPR_POP (2);\r
465POPR_POP (3);\r
466POPR_POP (4);\r
467POPR_POP (5);\r
468POPR_POP (6);\r
469POPR_POP (7);\r
470POPR_POP (8);\r
471POPR_POP (9);\r
472POPR_POP (10);\r
473POPR_POP (11);\r
474POPR_POP (12);\r
475POPR_POP (13);\r
476if (mask & 0x4000) SP = Read (SP, L_LONG, RA); /* if pop SP, no inc */\r
477return;\r
478}\r
479\r
480/* INSQUE\r
481\r
482 opnd[0] = entry address (ent.ab)\r
483 opnd[1] = predecessor address (pred.ab)\r
484\r
485 Condition codes returned to caller on comparison of (ent):(ent+4).\r
486 All writes must be checked before any writes are done.\r
487\r
488 Pictorially:\r
489\r
490 BEFORE AFTER\r
491\r
492 P: S P: E W\r
493 P+4: (n/a) P+4: (n/a)\r
494\r
495 E: --- E: S W\r
496 E+4: --- E+4: P W\r
497\r
498 S: (n/a) S: (n/a)\r
499 S+4: P S+4: E W\r
500\r
501 s+4 must be tested with a read modify rather than a probe, as it\r
502 might be misaligned.\r
503*/\r
504\r
505int32 op_insque (int32 *opnd, int32 acc)\r
506{\r
507int32 p = opnd[1];\r
508int32 e = opnd[0];\r
509int32 s, cc;\r
510\r
511s = Read (p, L_LONG, WA); /* s <- (p), wchk */\r
512Read (s + 4, L_LONG, WA); /* wchk s+4 */\r
513Read (e + 4, L_LONG, WA); /* wchk e+4 */\r
514Write (e, s, L_LONG, WA); /* (e) <- s */\r
515Write (e + 4, p, L_LONG, WA); /* (e+4) <- p */\r
516Write (s + 4, e, L_LONG, WA); /* (s+4) <- ent */\r
517Write (p, e, L_LONG, WA); /* (p) <- e */\r
518CC_CMP_L (s, p); /* set cc's */\r
519return cc;\r
520}\r
521\r
522/* REMQUE\r
523\r
524 opnd[0] = entry address (ent.ab)\r
525 opnd[1:2] = destination address (dst.wl)\r
526\r
527 Condition codes returned to caller based on (ent):(ent+4).\r
528 All writes must be checked before any writes are done.\r
529\r
530 Pictorially:\r
531\r
532 BEFORE AFTER\r
533\r
534 P: E P: S W\r
535 P+4: (n/a) P+4: (n/a)\r
536\r
537 E: S W E: S\r
538 E+4: P W E+4: P\r
539\r
540 S: (n/a) S: (n/a)\r
541 S+4: E W S+4: P\r
542\r
543*/\r
544\r
545int32 op_remque (int32 *opnd, int32 acc)\r
546{\r
547int32 e = opnd[0];\r
548int32 s, p, cc;\r
549\r
550s = Read (e, L_LONG, RA); /* s <- (e) */\r
551p = Read (e + 4, L_LONG, RA); /* p <- (e+4) */\r
552CC_CMP_L (s, p); /* set cc's */\r
553if (e != p) { /* queue !empty? */\r
554 Read (s + 4, L_LONG, WA); /* wchk (s+4) */\r
555 if (opnd[1] < 0) Read (opnd[2], L_LONG, WA); /* wchk dest */\r
556 Write (p, s, L_LONG, WA); /* (p) <- s */\r
557 Write (s + 4, p, L_LONG, WA); /* (s+4) <- p */\r
558 }\r
559else cc = cc | CC_V; /* else set v */\r
560if (opnd[1] >= 0) R[opnd[1]] = e; /* store result */\r
561else Write (opnd[2], e, L_LONG, WA);\r
562return cc;\r
563}\r
564\r
565/* Interlocked insert instructions\r
566\r
567 opnd[0] = entry (ent.ab)\r
568 opnd[1] = header (hdr.aq)\r
569\r
570 Pictorially:\r
571\r
572 BEFORE AFTER INSQHI AFTER INSQTI\r
573\r
574 H: A-H H: D-H W H: A-H W for interlock\r
575 H+4: C-H H+4: C-H H+4: D-H W\r
576\r
577 A: B-A A: B-A A: B-A\r
578 A+4: H-A A+4: D-A W A+4: H-A\r
579\r
580 B: C-B B: C-B B: C-B\r
581 B+4: A-B B+4: A-B B+4: A-B\r
582\r
583 C: H-C C: H-C C: D-C W\r
584 C+4: B-C C+4: B-C C+4: B-C\r
585\r
586 D: --- D: A-D W D: H-D W\r
587 D+4: --- D+4: H-D W D+4: C-D W\r
588\r
589 Note that the queue header, the entry to be inserted, and all\r
590 the intermediate entries that are "touched" in any way must be\r
591 QUADWORD aligned. In addition, the header and the entry must\r
592 not be equal.\r
593*/\r
594\r
595int32 op_insqhi (int32 *opnd, int32 acc)\r
596{\r
597int32 h = opnd[1];\r
598int32 d = opnd[0];\r
599int32 a, t;\r
600\r
601if ((h == d) || ((h | d) & 07)) RSVD_OPND_FAULT; /* h, d quad align? */\r
602Read (d, L_BYTE, WA); /* wchk ent */\r
603a = Read (h, L_LONG, WA); /* a <- (h), wchk */\r
604if (a & 06) RSVD_OPND_FAULT; /* chk quad align */\r
605if (a & 01) return CC_C; /* busy, cc = 0001 */\r
606Write (h, a | 1, L_LONG, WA); /* get interlock */\r
607a = a + h; /* abs addr of a */\r
608if (Test (a, WA, &t) < 0) Write (h, a - h, L_LONG, WA); /* wtst a, rls if err */\r
609Write (a + 4, d - a, L_LONG, WA); /* (a+4) <- d-a, flt ok */\r
610Write (d, a - d, L_LONG, WA); /* (d) <- a-d */\r
611Write (d + 4, h - d, L_LONG, WA); /* (d+4) <- h-d */\r
612Write (h, d - h, L_LONG, WA); /* (h) <- d-h, rls int */\r
613return (a == h)? CC_Z: 0; /* Z = 1 if a = h */\r
614}\r
615\r
616int32 op_insqti (int32 *opnd, int32 acc)\r
617{\r
618int32 h = opnd[1];\r
619int32 d = opnd[0];\r
620int32 a, c, t;\r
621\r
622if ((h == d) || ((h | d) & 07)) RSVD_OPND_FAULT; /* h, d quad align? */\r
623Read (d, L_BYTE, WA); /* wchk ent */\r
624a = Read (h, L_LONG, WA); /* a <- (h), wchk */\r
625if (a == 0) return op_insqhi (opnd, acc); /* if empty, ins hd */\r
626if (a & 06) RSVD_OPND_FAULT; /* chk quad align */\r
627if (a & 01) return CC_C; /* busy, cc = 0001 */\r
628Write (h, a | 1, L_LONG, WA); /* acquire interlock */\r
629c = Read (h + 4, L_LONG, RA) + h; /* c <- (h+4) + h */\r
630if (c & 07) { /* c quad aligned? */\r
631 Write (h, a, L_LONG, WA); /* release interlock */\r
632 RSVD_OPND_FAULT; /* fault */\r
633 }\r
634if (Test (c, WA, &t) < 0) Write (h, a, L_LONG, WA); /* wtst c, rls if err */\r
635Write (c, d - c, L_LONG, WA); /* (c) <- d-c, flt ok */\r
636Write (d, h - d, L_LONG, WA); /* (d) <- h-d */\r
637Write (d + 4, c - d, L_LONG, WA); /* (d+4) <- c-d */\r
638Write (h + 4, d - h, L_LONG, WA); /* (h+4) <- d-h */\r
639Write (h, a, L_LONG, WA); /* release interlock */\r
640return 0; /* q >= 2 entries */\r
641}\r
642\r
643/* Interlocked remove instructions\r
644\r
645 opnd[0] = header (hdr.aq)\r
646 opnd[1:2] = destination address (dst.al)\r
647\r
648 Pictorially:\r
649\r
650 BEFORE AFTER REMQHI AFTER REMQTI\r
651\r
652 H: A-H H: B-H W H: A-H W for interlock\r
653 H+4: C-H H+4: C-H H+4: B-H W\r
654\r
655 A: B-A A: B-A R A: B-A\r
656 A+4: H-A A+4: H-A A+4: H-A\r
657\r
658 B: C-B B: C-B B: H-B W\r
659 B+4: A-B B+4: H-B W B+4: A-B\r
660\r
661 C: H-C C: H-C C: H-C\r
662 C+4: B-C C+4: B-C C+4: B-C R\r
663\r
664 Note that the queue header and all the entries that are\r
665 "touched" in any way must be QUADWORD aligned. In addition,\r
666 the header and the destination must not be equal.\r
667*/\r
668\r
669int32 op_remqhi (int32 *opnd, int32 acc)\r
670{\r
671int32 h = opnd[0];\r
672int32 ar, a, b, t;\r
673\r
674if (h & 07) RSVD_OPND_FAULT; /* h quad aligned? */\r
675if (opnd[1] < 0) { /* mem destination? */\r
676 if (h == opnd[2]) RSVD_OPND_FAULT; /* hdr = dst? */\r
677 Read (opnd[2], L_LONG, WA); /* wchk dst */\r
678 }\r
679ar = Read (h, L_LONG, WA); /* ar <- (h) */\r
680if (ar & 06) RSVD_OPND_FAULT; /* a quad aligned? */\r
681if (ar & 01) return CC_V | CC_C; /* busy, cc = 0011 */\r
682a = ar + h; /* abs addr of a */\r
683if (ar) { /* queue not empty? */\r
684 Write (h, ar | 1, L_LONG, WA); /* acquire interlock */\r
685 if (Test (a, RA, &t) < 0) /* read tst a */\r
686 Write (h, ar, L_LONG, WA); /* release if error */\r
687 b = Read (a, L_LONG, RA) + a; /* b <- (a)+a, flt ok */\r
688 if (b & 07) { /* b quad aligned? */\r
689 Write (h, ar, L_LONG, WA); /* release interlock */\r
690 RSVD_OPND_FAULT; /* fault */\r
691 }\r
692 if (Test (b, WA, &t) < 0) /* write test b */\r
693 Write (h, ar, L_LONG, WA); /* release if err */\r
694 Write (b + 4, h - b, L_LONG, WA); /* (b+4) <- h-b, flt ok */\r
695 Write (h, b - h, L_LONG, WA); /* (h) <- b-h, rls int */\r
696 }\r
697if (opnd[1] >= 0) R[opnd[1]] = a; /* store result */\r
698else Write (opnd[2], a, L_LONG, WA);\r
699if (ar == 0) return CC_Z | CC_V; /* empty, cc = 0110 */\r
700return (b == h)? CC_Z: 0; /* if b = h, q empty */\r
701}\r
702\r
703int32 op_remqti (int32 *opnd, int32 acc)\r
704{\r
705int32 h = opnd[0];\r
706int32 ar, b, c, t;\r
707\r
708if (h & 07) RSVD_OPND_FAULT; /* h quad aligned? */\r
709if (opnd[1] < 0) { /* mem destination? */\r
710 if (h == opnd[2]) RSVD_OPND_FAULT; /* hdr = dst? */\r
711 Read (opnd[2], L_LONG, WA); /* wchk dst */\r
712 }\r
713ar = Read (h, L_LONG, WA); /* a <- (h) */\r
714if (ar & 06) RSVD_OPND_FAULT; /* a quad aligned? */\r
715if (ar & 01) return CC_V | CC_C; /* busy, cc = 0011 */\r
716if (ar) { /* queue not empty */\r
717 Write (h, ar | 1, L_LONG, WA); /* acquire interlock */\r
718 c = Read (h + 4, L_LONG, RA); /* c <- (h+4) */\r
719 if (ar == c) { /* single entry? */\r
720 Write (h, ar, L_LONG, WA); /* release interlock */\r
721 return op_remqhi (opnd, acc); /* treat as remqhi */\r
722 }\r
723 if (c & 07) { /* c quad aligned? */\r
724 Write (h, ar, L_LONG, WA); /* release interlock */\r
725 RSVD_OPND_FAULT; /* fault */\r
726 }\r
727 c = c + h; /* abs addr of c */\r
728 if (Test (c + 4, RA, &t) < 0) /* read test c+4 */\r
729 Write (h, ar, L_LONG, WA); /* release if error */\r
730 b = Read (c + 4, L_LONG, RA) + c; /* b <- (c+4)+c, flt ok */\r
731 if (b & 07) { /* b quad aligned? */\r
732 Write (h, ar, L_LONG, WA); /* release interlock */\r
733 RSVD_OPND_FAULT; /* fault */\r
734 }\r
735 if (Test (b, WA, &t) < 0) /* write test b */\r
736 Write (h, ar, L_LONG, WA); /* release if error */\r
737 Write (b, h - b, L_LONG, WA); /* (b) <- h-b */\r
738 Write (h + 4, b - h, L_LONG, WA); /* (h+4) <- b-h */\r
739 Write (h, ar, L_LONG, WA); /* release interlock */\r
740 }\r
741else c = h; /* empty, result = h */\r
742if (opnd[1] >= 0) R[opnd[1]] = c; /* store result */\r
743else Write (opnd[2], c, L_LONG, WA);\r
744if (ar == 0) return CC_Z | CC_V; /* empty, cc = 0110 */\r
745return 0; /* q can't be empty */\r
746}\r
747\r
748/* String instructions */\r
749\r
750#define MVC_FRWD 0 /* movc state codes */\r
751#define MVC_BACK 1\r
752#define MVC_FILL 3 /* must be 3 */\r
753#define MVC_M_STATE 3\r
754#define MVC_V_CC 2\r
755\r
756/* MOVC3, MOVC5\r
757\r
758 if PSL<fpd> = 0 and MOVC3,\r
759 opnd[0] = length\r
760 opnd[1] = source address\r
761 opnd[2] = dest address\r
762\r
763 if PSL<fpd> = 0 and MOVC5,\r
764 opnd[0] = source length\r
765 opnd[1] = source address\r
766 opnd[2] = fill\r
767 opnd[3] = dest length\r
768 opnd[4] = dest address\r
769\r
770 if PSL<fpd> = 1,\r
771 R0 = delta-PC/fill/initial move length\r
772 R1 = current source address\r
773 R2 = current move length\r
774 R3 = current dest address\r
775 R4 = dstlen - srclen (loop count if fill state)\r
776 R5 = cc/state\r
777*/\r
778\r
779int32 op_movc (int32 *opnd, int32 movc5, int32 acc)\r
780{\r
781int32 i, cc, fill, wd;\r
782int32 j, lnt, mlnt[3];\r
783static const int32 looplnt[3] = { L_BYTE, L_LONG, L_BYTE };\r
784\r
785if (PSL & PSL_FPD) { /* FPD set? */\r
786 SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */\r
787 fill = STR_GETCHR (R[0]); /* get fill */\r
788 R[2] = R[2] & STR_LNMASK; /* mask lengths */\r
789 if (R[4] > 0) R[4] = R[4] & STR_LNMASK;\r
790 }\r
791else {\r
792 R[1] = opnd[1]; /* src addr */\r
793 if (movc5) { /* MOVC5? */\r
794 R[2] = (opnd[0] < opnd[3])? opnd[0]: opnd[3];\r
795 R[3] = opnd[4]; /* dst addr */\r
796 R[4] = opnd[3] - opnd[0]; /* dstlen - srclen */\r
797 fill = opnd[2]; /* set fill */\r
798 CC_CMP_W (opnd[0], opnd[3]); /* set cc's */\r
799 }\r
800 else {\r
801 R[2] = opnd[0]; /* mvlen = srclen */\r
802 R[3] = opnd[2]; /* dst addr */\r
803 R[4] = fill = 0; /* no fill */\r
804 cc = CC_Z; /* set cc's */\r
805 }\r
806 R[0] = STR_PACK (fill, R[2]); /* initial mvlen */\r
807 if (R[2]) { /* any move? */\r
808 if (((uint32) R[1]) < ((uint32) R[3])) {\r
809 R[1] = R[1] + R[2]; /* backward, adjust */\r
810 R[3] = R[3] + R[2]; /* addr to end */\r
811 R[5] = MVC_BACK; /* set state */\r
812 }\r
813 else R[5] = MVC_FRWD; /* fwd, set state */\r
814 }\r
815 else R[5] = MVC_FILL; /* fill, set state */\r
816 R[5] = R[5] | (cc << MVC_V_CC); /* pack with state */\r
817 PSL = PSL | PSL_FPD; /* set FPD */\r
818 }\r
819\r
820/* At this point,\r
821\r
822 R0 = delta PC'fill'initial move length\r
823 R1 = current src addr\r
824 R2 = current move length\r
825 R3 = current dst addr\r
826 R4 = dst length - src length\r
827 R5 = cc'state\r
828*/\r
829\r
830switch (R[5] & MVC_M_STATE) { /* case on state */\r
831\r
832 case MVC_FRWD: /* move forward */\r
833 mlnt[0] = (4 - R[3]) & 3; /* length to align */\r
834 if (mlnt[0] > R[2]) mlnt[0] = R[2]; /* cant exceed total */\r
835 mlnt[1] = (R[2] - mlnt[0]) & ~03; /* aligned length */\r
836 mlnt[2] = R[2] - mlnt[0] - mlnt[1]; /* tail */\r
837 for (i = 0; i < 3; i++) { /* head, align, tail */\r
838 lnt = looplnt[i]; /* length for loop */\r
839 for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) {\r
840 wd = Read (R[1], lnt, RA); /* read src */\r
841 Write (R[3], wd, lnt, WA); /* write dst */\r
842 R[1] = R[1] + lnt; /* inc src addr */\r
843 R[3] = R[3] + lnt; /* inc dst addr */\r
844 R[2] = R[2] - lnt; /* dec move lnt */\r
845 }\r
846 }\r
847 goto FILL; /* check for fill */\r
848\r
849 case MVC_BACK: /* move backward */\r
850 mlnt[0] = R[3] & 03; /* length to align */\r
851 if (mlnt[0] > R[2]) mlnt[0] = R[2]; /* cant exceed total */\r
852 mlnt[1] = (R[2] - mlnt[0]) & ~03; /* aligned length */\r
853 mlnt[2] = R[2] - mlnt[0] - mlnt[1]; /* tail */\r
854 for (i = 0; i < 3; i++) { /* head, align, tail */\r
855 lnt = looplnt[i]; /* length for loop */\r
856 for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) {\r
857 wd = Read (R[1] - lnt, lnt, RA); /* read src */\r
858 Write (R[3] - lnt, wd, lnt, WA); /* write dst */\r
859 R[1] = R[1] - lnt; /* dec src addr */\r
860 R[3] = R[3] - lnt; /* dec dst addr */\r
861 R[2] = R[2] - lnt; /* dec move lnt */\r
862 }\r
863 }\r
864 R[1] = R[1] + (R[0] & STR_LNMASK); /* final src addr */\r
865 R[3] = R[3] + (R[0] & STR_LNMASK); /* final dst addr */\r
866\r
867 case MVC_FILL: /* fill */\r
868 FILL:\r
869 if (R[4] <= 0) break; /* any fill? */\r
870 R[5] = R[5] | MVC_FILL; /* set state */\r
871 mlnt[0] = (4 - R[3]) & 3; /* length to align */\r
872 if (mlnt[0] > R[4]) mlnt[0] = R[4]; /* cant exceed total */\r
873 mlnt[1] = (R[4] - mlnt[0]) & ~03; /* aligned length */\r
874 mlnt[2] = R[4] - mlnt[0] - mlnt[1]; /* tail */\r
875 for (i = 0; i < 3; i++) { /* head, align, tail */\r
876 lnt = looplnt[i]; /* length for loop */\r
877 fill = fill & BMASK; /* fill for loop */\r
878 if (lnt == L_LONG) fill = \r
879 (((uint32) fill) << 24) | (fill << 16) | (fill << 8) | fill;\r
880 for (j = 0; j < mlnt[i]; j = j + lnt, sim_interval--) {\r
881 Write (R[3], fill, lnt, WA); /* write fill */\r
882 R[3] = R[3] + lnt; /* inc dst addr */\r
883 R[4] = R[4] - lnt; /* dec fill lnt */\r
884 }\r
885 }\r
886 break;\r
887\r
888 default: /* bad state */\r
889 RSVD_OPND_FAULT; /* you lose */\r
890 }\r
891\r
892PSL = PSL & ~PSL_FPD; /* clear FPD */\r
893cc = (R[5] >> MVC_V_CC) & CC_MASK; /* get cc's */\r
894R[0] = NEG (R[4]); /* set R0 */\r
895R[2] = R[4] = R[5] = 0; /* clear reg */\r
896return cc;\r
897}\r
898\r
899/* CMPC3, CMPC5\r
900\r
901 if PSL<fpd> = 0 and CMPC3,\r
902 opnd[0] = length\r
903 opnd[1] = source1 address\r
904 opnd[2] = source2 address\r
905\r
906 if PSL<fpd> = 0 and CMPC5,\r
907 opnd[0] = source1 length\r
908 opnd[1] = source1 address\r
909 opnd[2] = fill\r
910 opnd[3] = source2 length\r
911 opnd[4] = source2 address\r
912\r
913 if PSL<fpd> = 1,\r
914 R0 = delta-PC/fill/source1 length\r
915 R1 = source1 address\r
916 R2 = source2 length\r
917 R3 = source2 address\r
918*/\r
919\r
920int32 op_cmpc (int32 *opnd, int32 cmpc5, int32 acc)\r
921{\r
922int32 cc, s1, s2, fill;\r
923\r
924if (PSL & PSL_FPD) { /* FPD set? */\r
925 SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */\r
926 fill = STR_GETCHR (R[0]); /* get fill */\r
927 }\r
928else {\r
929 R[1] = opnd[1]; /* src1len */\r
930 if (cmpc5) { /* CMPC5? */\r
931 R[2] = opnd[3]; /* get src2 opnds */\r
932 R[3] = opnd[4];\r
933 fill = opnd[2];\r
934 }\r
935 else {\r
936 R[2] = opnd[0]; /* src2len = src1len */\r
937 R[3] = opnd[2];\r
938 fill = 0;\r
939 }\r
940 R[0] = STR_PACK (fill, opnd[0]); /* src1len + FPD data */\r
941 PSL = PSL | PSL_FPD;\r
942 }\r
943R[2] = R[2] & STR_LNMASK; /* mask src2len */\r
944for (s1 = s2 = 0; ((R[0] | R[2]) & STR_LNMASK) != 0; sim_interval--) {\r
945 if (R[0] & STR_LNMASK) s1 = Read (R[1], L_BYTE, RA); /* src1? read */\r
946 else s1 = fill; /* no, use fill */\r
947 if (R[2]) s2 = Read (R[3], L_BYTE, RA); /* src2? read */\r
948 else s2 = fill; /* no, use fill */\r
949 if (s1 != s2) break; /* src1 = src2? */\r
950 if (R[0] & STR_LNMASK) { /* if src1, decr */\r
951 R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK);\r
952 R[1] = R[1] + 1;\r
953 }\r
954 if (R[2]) { /* if src2, decr */\r
955 R[2] = (R[2] - 1) & STR_LNMASK;\r
956 R[3] = R[3] + 1;\r
957 }\r
958 }\r
959PSL = PSL & ~PSL_FPD; /* clear FPD */\r
960CC_CMP_B (s1, s2); /* set cc's */\r
961R[0] = R[0] & STR_LNMASK; /* clear packup */\r
962return cc;\r
963}\r
964\r
965/* LOCC, SKPC\r
966\r
967 if PSL<fpd> = 0,\r
968 opnd[0] = match character\r
969 opnd[1] = source length\r
970 opnd[2] = source address\r
971\r
972 if PSL<fpd> = 1,\r
973 R0 = delta-PC/match/source length\r
974 R1 = source address\r
975*/\r
976\r
977int32 op_locskp (int32 *opnd, int32 skpc, int32 acc)\r
978{\r
979int32 c, match;\r
980\r
981if (PSL & PSL_FPD) { /* FPD set? */\r
982 SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */\r
983 match = STR_GETCHR (R[0]); /* get match char */\r
984 }\r
985else {\r
986 match = opnd[0]; /* get operands */\r
987 R[0] = STR_PACK (match, opnd[1]); /* src len + FPD data */\r
988 R[1] = opnd[2]; /* src addr */\r
989 PSL = PSL | PSL_FPD;\r
990 }\r
991for ( ; (R[0] & STR_LNMASK) != 0; sim_interval-- ) { /* loop thru string */\r
992 c = Read (R[1], L_BYTE, RA); /* get src byte */\r
993 if ((c == match) ^ skpc) break; /* match & locc? */\r
994 R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK);\r
995 R[1] = R[1] + 1; /* incr src1adr */\r
996 }\r
997PSL = PSL & ~PSL_FPD; /* clear FPD */\r
998R[0] = R[0] & STR_LNMASK; /* clear packup */\r
999return (R[0]? 0: CC_Z); /* set cc's */\r
1000}\r
1001\r
1002/* SCANC, SPANC\r
1003\r
1004 if PSL<fpd> = 0,\r
1005 opnd[0] = source length\r
1006 opnd[1] = source address\r
1007 opnd[2] = table address\r
1008 opnd[3] = mask\r
1009\r
1010 if PSL<fpd> = 1,\r
1011 R0 = delta-PC/char/source length\r
1012 R1 = source address\r
1013 R3 = table address\r
1014*/\r
1015\r
1016int32 op_scnspn (int32 *opnd, int32 spanc, int32 acc)\r
1017{\r
1018int32 c, t, mask;\r
1019\r
1020if (PSL & PSL_FPD) { /* FPD set? */\r
1021 SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */\r
1022 mask = STR_GETCHR (R[0]); /* get mask */\r
1023 }\r
1024else {\r
1025 R[1] = opnd[1]; /* src addr */\r
1026 R[3] = opnd[2]; /* tblad */\r
1027 mask = opnd[3]; /* mask */\r
1028 R[0] = STR_PACK (mask, opnd[0]); /* srclen + FPD data */\r
1029 PSL = PSL | PSL_FPD;\r
1030 }\r
1031for ( ; (R[0] & STR_LNMASK) != 0; sim_interval-- ) { /* loop thru string */\r
1032 c = Read (R[1], L_BYTE, RA); /* get byte */\r
1033 t = Read (R[3] + c, L_BYTE, RA); /* get table ent */\r
1034 if (((t & mask) != 0) ^ spanc) break; /* test vs instr */\r
1035 R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK);\r
1036 R[1] = R[1] + 1;\r
1037 }\r
1038PSL = PSL & ~PSL_FPD;\r
1039R[0] = R[0] & STR_LNMASK; /* clear packup */\r
1040R[2] = 0;\r
1041return (R[0]? 0: CC_Z);\r
1042}\r
1043\r
1044/* Operating system interfaces */\r
1045\r
1046/* Interrupt or exception\r
1047\r
1048 vec = SCB vector\r
1049 cc = condition codes\r
1050 ipl = new IPL if interrupt\r
1051 ei = -1: severe exception\r
1052 0: normal exception\r
1053 1: interrupt\r
1054*/\r
1055\r
1056int32 intexc (int32 vec, int32 cc, int32 ipl, int ei)\r
1057{\r
1058int32 oldpsl = PSL | cc;\r
1059int32 oldcur = PSL_GETCUR (oldpsl);\r
1060int32 oldsp = SP;\r
1061int32 newpsl;\r
1062int32 newpc;\r
1063int32 acc;\r
1064\r
1065in_ie = 1; /* flag int/exc */\r
1066CLR_TRAPS; /* clear traps */\r
1067newpc = ReadLP ((SCBB + vec) & PAMASK); /* read new PC */\r
1068if (ei < 0) newpc = newpc | 1; /* severe? on istk */\r
1069if (newpc & 2) ABORT (STOP_ILLVEC); /* bad flags? */\r
1070if (oldpsl & PSL_IS) newpsl = PSL_IS; /* on int stk? */\r
1071else {\r
1072 STK[oldcur] = SP; /* no, save cur stk */\r
1073 if (newpc & 1) { /* to int stk? */\r
1074 newpsl = PSL_IS; /* flag */\r
1075 SP = IS; /* new stack */\r
1076 }\r
1077 else {\r
1078 newpsl = 0; /* to ker stk */\r
1079 SP = KSP; /* new stack */\r
1080 }\r
1081 }\r
1082if (ei > 0) /* if int, new IPL */\r
1083 PSL = cpu_psl_ipl_idle (newpsl | (ipl << PSL_V_IPL));\r
1084else PSL = cpu_psl_ipl_idle (newpsl | /* exc, old IPL/1F */\r
1085 ((newpc & 1)? PSL_IPL1F: (oldpsl & PSL_IPL)) | (oldcur << PSL_V_PRV));\r
1086if (DEBUG_PRI (cpu_dev, LOG_CPU_I)) fprintf (sim_deb,\r
1087 ">>IEX: PC=%08x, PSL=%08x, SP=%08x, VEC=%08x, nPSL=%08x, nSP=%08x\n",\r
1088 PC, oldpsl, oldsp, vec, PSL, SP);\r
1089acc = ACC_MASK (KERN); /* new mode is kernel */\r
1090Write (SP - 4, oldpsl, L_LONG, WA); /* push old PSL */\r
1091Write (SP - 8, PC, L_LONG, WA); /* push old PC */\r
1092SP = SP - 8; /* update stk ptr */\r
1093JUMP (newpc & ~3); /* change PC */\r
1094in_ie = 0; /* out of flows */\r
1095return 0;\r
1096}\r
1097\r
1098/* CHMK, CHME, CHMS, CHMU\r
1099\r
1100 opnd[0] = operand\r
1101*/\r
1102\r
1103int32 op_chm (int32 *opnd, int32 cc, int32 opc)\r
1104{\r
1105int32 mode = opc & PSL_M_MODE;\r
1106int32 cur = PSL_GETCUR (PSL);\r
1107int32 tsp, newpc, acc, sta;\r
1108\r
1109if (PSL & PSL_IS) ABORT (STOP_CHMFI);\r
1110newpc = ReadLP ((SCBB + SCB_CHMK + (mode << 2)) & PAMASK);\r
1111if (cur < mode) mode = cur; /* only inward */\r
1112STK[cur] = SP; /* save stack */\r
1113tsp = STK[mode]; /* get new stk */\r
1114acc = ACC_MASK (mode); /* set new mode */\r
1115if (Test (p2 = tsp - 1, WA, &sta) < 0) { /* probe stk */\r
1116 p1 = MM_WRITE | (sta & MM_EMASK);\r
1117 ABORT ((sta & 4)? ABORT_TNV: ABORT_ACV);\r
1118 }\r
1119if (Test (p2 = tsp - 12, WA, &sta) < 0) {\r
1120 p1 = MM_WRITE | (sta & MM_EMASK);\r
1121 ABORT ((sta & 4)? ABORT_TNV: ABORT_ACV);\r
1122 }\r
1123Write (tsp - 12, SXTW (opnd[0]), L_LONG, WA); /* push argument */\r
1124Write (tsp - 8, PC, L_LONG, WA); /* push PC */\r
1125Write (tsp - 4, PSL | cc, L_LONG, WA); /* push PSL */\r
1126SP = tsp - 12; /* set new stk */\r
1127PSL = (mode << PSL_V_CUR) | (PSL & PSL_IPL) | /* set new PSL */\r
1128 (cur << PSL_V_PRV); /* IPL unchanged */\r
1129last_chm = fault_PC;\r
1130JUMP (newpc & ~03); /* set new PC */\r
1131return 0; /* cc = 0 */\r
1132}\r
1133\r
1134/* REI - return from exception or interrupt\r
1135\r
1136The lengthiest part of the REI instruction is the validity checking of the PSL\r
1137popped off the stack. The new PSL is checked against the following eight rules:\r
1138\r
1139let tmp = new PSL popped off the stack\r
1140let PSL = current PSL\r
1141\r
1142Rule SRM formulation Comment\r
1143---- --------------- -------\r
1144 1 tmp<25:24> GEQ PSL<25:24> tmp<cur_mode> GEQ PSL<cur_mode>\r
1145 2 tmp<26> LEQ PSL<26> tmp<is> LEQ PSL<is>\r
1146 3 tmp<26> = 1 => tmp<25:24> = 0 tmp<is> = 1 => tmp<cur_mode> = ker\r
1147 4 tmp<26> = 1 => tmp<20:16> > 0 tmp<is> = 1 => tmp<ipl> > 0\r
1148 5 tmp<20:16> > 0 => tmp<25:24> = 0 tmp<ipl> > 0 => tmp<cur_mode> = ker\r
1149 6 tmp<25:24> LEQ tmp<23:22> tmp<cur_mode> LEQ tmp<prv_mode>\r
1150 7 tmp<20:16> LEQ PSL<20:16> tmp<ipl> LEQ PSL<ipl>\r
1151 8 tmp<31,29:28,21,15:8> = 0 tmp<mbz> = 0\r
1152 9 tmp<31> = 1 => tmp<cur_mode> = 3, tmp<prv_mode> = 3>, tmp<fpd,is,ipl> = 0 \r
1153*/\r
1154\r
1155int32 op_rei (int32 acc)\r
1156{\r
1157int32 newpc = Read (SP, L_LONG, RA);\r
1158int32 newpsl = Read (SP + 4, L_LONG, RA);\r
1159int32 newcur = PSL_GETCUR (newpsl);\r
1160int32 oldcur = PSL_GETCUR (PSL);\r
1161int32 newipl, i;\r
1162\r
1163if ((newpsl & PSL_MBZ) || /* rule 8 */\r
1164 (newcur < oldcur)) RSVD_OPND_FAULT; /* rule 1 */\r
1165if (newcur) { /* to esu, skip 2,4,7 */\r
1166 if ((newpsl & (PSL_IS | PSL_IPL)) || /* rules 3,5 */\r
1167 (newcur > PSL_GETPRV (newpsl))) /* rule 6 */\r
1168 RSVD_OPND_FAULT; /* end rei to esu */\r
1169 }\r
1170else { /* to k, skip 3,5,6 */\r
1171 newipl = PSL_GETIPL (newpsl); /* get new ipl */\r
1172 if ((newpsl & PSL_IS) && /* setting IS? */\r
1173 (((PSL & PSL_IS) == 0) || (newipl == 0))) /* test rules 2,4 */\r
1174 RSVD_OPND_FAULT; /* else skip 2,4 */\r
1175 if (newipl > PSL_GETIPL (PSL)) RSVD_OPND_FAULT; /* test rule 7 */\r
1176 } /* end if kernel */\r
1177if (newpsl & PSL_CM) { /* setting cmode? */\r
1178 if (BadCmPSL (newpsl)) RSVD_OPND_FAULT; /* validate PSL */\r
1179 for (i = 0; i < 7; i++) R[i] = R[i] & WMASK; /* mask R0-R6, PC */\r
1180 newpc = newpc & WMASK;\r
1181 }\r
1182SP = SP + 8; /* pop stack */\r
1183if (PSL & PSL_IS) IS = SP; /* save stack */\r
1184else STK[oldcur] = SP;\r
1185if (DEBUG_PRI (cpu_dev, LOG_CPU_R)) fprintf (sim_deb,\r
1186 ">>REI: PC=%08x, PSL=%08x, SP=%08x, nPC=%08x, nPSL=%08x, nSP=%08x\n",\r
1187 PC, PSL, SP - 8, newpc, newpsl, ((newpsl & IS)? IS: STK[newcur]));\r
1188PSL = cpu_psl_ipl_idle ((PSL & PSL_TP) | (newpsl & ~CC_MASK)); /* set PSL */\r
1189if (PSL & PSL_IS) SP = IS; /* set new stack */\r
1190else {\r
1191 SP = STK[newcur]; /* if ~IS, chk AST */\r
1192 if (newcur >= ASTLVL) {\r
1193 if (DEBUG_PRI (cpu_dev, LOG_CPU_R)) fprintf (sim_deb,\r
1194 ">>REI: AST delivered\n");\r
1195 SISR = SISR | SISR_2;\r
1196 }\r
1197 }\r
1198JUMP (newpc); /* set new PC */\r
1199return newpsl & CC_MASK; /* set new cc */\r
1200}\r
1201\r
1202/* LDCPTX - load process context */\r
1203\r
1204void op_ldpctx (int32 acc)\r
1205{\r
1206int32 newpc, newpsl, pcbpa, t;\r
1207\r
1208if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */\r
1209pcbpa = PCBB & PAMASK; /* phys address */\r
1210KSP = ReadLP (pcbpa); /* restore stk ptrs */\r
1211ESP = ReadLP (pcbpa + 4);\r
1212SSP = ReadLP (pcbpa + 8);\r
1213USP = ReadLP (pcbpa + 12);\r
1214R[0] = ReadLP (pcbpa + 16); /* restore registers */\r
1215R[1] = ReadLP (pcbpa + 20);\r
1216R[2] = ReadLP (pcbpa + 24);\r
1217R[3] = ReadLP (pcbpa + 28);\r
1218R[4] = ReadLP (pcbpa + 32);\r
1219R[5] = ReadLP (pcbpa + 36);\r
1220R[6] = ReadLP (pcbpa + 40);\r
1221R[7] = ReadLP (pcbpa + 44);\r
1222R[8] = ReadLP (pcbpa + 48);\r
1223R[9] = ReadLP (pcbpa + 52);\r
1224R[10] = ReadLP (pcbpa + 56);\r
1225R[11] = ReadLP (pcbpa + 60);\r
1226R[12] = ReadLP (pcbpa + 64);\r
1227R[13] = ReadLP (pcbpa + 68);\r
1228newpc = ReadLP (pcbpa + 72); /* get PC, PSL */\r
1229newpsl = ReadLP (pcbpa + 76);\r
1230\r
1231t = ReadLP (pcbpa + 80);\r
1232ML_PXBR_TEST (t); /* validate P0BR */\r
1233P0BR = t & BR_MASK; /* restore P0BR */\r
1234t = ReadLP (pcbpa + 84);\r
1235LP_MBZ84_TEST (t); /* test mbz */\r
1236ML_LR_TEST (t & LR_MASK); /* validate P0LR */\r
1237P0LR = t & LR_MASK; /* restore P0LR */\r
1238t = (t >> 24) & AST_MASK;\r
1239LP_AST_TEST (t); /* validate AST */\r
1240ASTLVL = t; /* restore AST */\r
1241t = ReadLP (pcbpa + 88);\r
1242ML_PXBR_TEST (t + 0x800000); /* validate P1BR */\r
1243P1BR = t & BR_MASK; /* restore P1BR */\r
1244t = ReadLP (pcbpa + 92);\r
1245LP_MBZ92_TEST (t); /* test MBZ */\r
1246ML_LR_TEST (t & LR_MASK); /* validate P1LR */\r
1247P1LR = t & LR_MASK; /* restore P1LR */\r
1248pme = (t >> 31) & 1; /* restore PME */\r
1249\r
1250zap_tb (0); /* clear process TB */\r
1251set_map_reg ();\r
1252if (DEBUG_PRI (cpu_dev, LOG_CPU_P)) fprintf (sim_deb,\r
1253 ">>LDP: PC=%08x, PSL=%08x, SP=%08x, nPC=%08x, nPSL=%08x, nSP=%08x\n",\r
1254 PC, PSL, SP, newpc, newpsl, KSP);\r
1255if (PSL & PSL_IS) IS = SP; /* if istk, */\r
1256PSL = PSL & ~PSL_IS; /* switch to kstk */\r
1257SP = KSP - 8;\r
1258Write (SP, newpc, L_LONG, WA); /* push PC, PSL */\r
1259Write (SP + 4, newpsl, L_LONG, WA);\r
1260return;\r
1261}\r
1262\r
1263/* SVPCTX - save processor context */\r
1264\r
1265void op_svpctx (int32 acc)\r
1266{\r
1267int32 savpc, savpsl, pcbpa;\r
1268\r
1269if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */\r
1270savpc = Read (SP, L_LONG, RA); /* pop PC, PSL */\r
1271savpsl = Read (SP + 4, L_LONG, RA);\r
1272if (DEBUG_PRI (cpu_dev, LOG_CPU_P)) fprintf (sim_deb,\r
1273 ">>SVP: PC=%08x, PSL=%08x, SP=%08x, oPC=%08x, oPSL=%08x\n",\r
1274 PC, PSL, SP, savpc, savpsl);\r
1275if (PSL & PSL_IS) SP = SP + 8; /* int stack? */\r
1276else {\r
1277 KSP = SP + 8; /* pop kernel stack */\r
1278 SP = IS; /* switch to int stk */\r
1279 if ((PSL & PSL_IPL) == 0) /* make IPL > 0 */\r
1280 PSL = PSL | PSL_IPL1;\r
1281 PSL = PSL | PSL_IS; /* set PSL<is> */\r
1282 }\r
1283pcbpa = PCBB & PAMASK;\r
1284WriteLP (pcbpa, KSP); /* save stk ptrs */\r
1285WriteLP (pcbpa + 4, ESP);\r
1286WriteLP (pcbpa + 8, SSP);\r
1287WriteLP (pcbpa + 12, USP);\r
1288WriteLP (pcbpa + 16, R[0]); /* save registers */\r
1289WriteLP (pcbpa + 20, R[1]);\r
1290WriteLP (pcbpa + 24, R[2]);\r
1291WriteLP (pcbpa + 28, R[3]);\r
1292WriteLP (pcbpa + 32, R[4]);\r
1293WriteLP (pcbpa + 36, R[5]);\r
1294WriteLP (pcbpa + 40, R[6]);\r
1295WriteLP (pcbpa + 44, R[7]);\r
1296WriteLP (pcbpa + 48, R[8]);\r
1297WriteLP (pcbpa + 52, R[9]);\r
1298WriteLP (pcbpa + 56, R[10]);\r
1299WriteLP (pcbpa + 60, R[11]);\r
1300WriteLP (pcbpa + 64, R[12]);\r
1301WriteLP (pcbpa + 68, R[13]);\r
1302WriteLP (pcbpa + 72, savpc); /* save PC, PSL */\r
1303WriteLP (pcbpa + 76, savpsl);\r
1304return;\r
1305}\r
1306\r
1307/* PROBER and PROBEW\r
1308\r
1309 opnd[0] = mode\r
1310 opnd[1] = length\r
1311 opnd[2] = base address\r
1312*/\r
1313\r
1314int32 op_probe (int32 *opnd, int32 rw)\r
1315{\r
1316int32 mode = opnd[0] & PSL_M_MODE; /* mask mode */\r
1317int32 length = opnd[1];\r
1318int32 ba = opnd[2];\r
1319int32 prv = PSL_GETPRV (PSL);\r
1320int32 acc, sta, sta1;\r
1321\r
1322if (prv > mode) mode = prv; /* maximize mode */\r
1323acc = ACC_MASK (mode) << (rw? TLB_V_WACC: 0); /* set acc mask */\r
1324Test (ba, acc, &sta); /* probe */\r
1325switch (sta) { /* case on status */\r
1326\r
1327 case PR_PTNV: /* pte TNV */\r
1328 p1 = MM_PARAM (rw, PR_PTNV);\r
1329 p2 = ba;\r
1330 ABORT (ABORT_TNV); /* force TNV */\r
1331\r
1332 case PR_TNV: case PR_OK: /* TNV or ok */\r
1333 break; /* continue */\r
1334\r
1335 default: /* other */\r
1336 return CC_Z; /* lose */\r
1337 }\r
1338\r
1339Test (ba + length - 1, acc, &sta1); /* probe end addr */\r
1340switch (sta1) { /* case on status */\r
1341\r
1342 case PR_PTNV: /* pte TNV */\r
1343 p1 = MM_PARAM (rw, PR_PTNV);\r
1344 p2 = ba + length - 1;\r
1345 ABORT (ABORT_TNV); /* force TNV */\r
1346\r
1347 case PR_TNV: case PR_OK: /* TNV or ok */\r
1348 break; /* win */\r
1349\r
1350 default: /* other */\r
1351 return CC_Z; /* lose */\r
1352 }\r
1353\r
1354return 0;\r
1355}\r
1356\r
1357/* MTPR - move to processor register\r
1358\r
1359 opnd[0] = data\r
1360 opnd[1] = register number\r
1361*/\r
1362\r
1363int32 op_mtpr (int32 *opnd)\r
1364{\r
1365int32 val = opnd[0];\r
1366int32 prn = opnd[1];\r
1367int32 cc;\r
1368\r
1369if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */\r
1370if (prn > 63) RSVD_OPND_FAULT; /* reg# > 63? fault */\r
1371CC_IIZZ_L (val); /* set cc's */\r
1372switch (prn) { /* case on reg # */\r
1373\r
1374 case MT_KSP: /* KSP */\r
1375 if (PSL & PSL_IS) KSP = val; /* on IS? store KSP */\r
1376 else SP = val; /* else store SP */\r
1377 break;\r
1378\r
1379 case MT_ESP: case MT_SSP: case MT_USP: /* ESP, SSP, USP */\r
1380 STK[prn] = val; /* store stack */\r
1381 break;\r
1382\r
1383 case MT_IS: /* IS */\r
1384 if (PSL & PSL_IS) SP = val; /* on IS? store SP */\r
1385 else IS = val; /* else store IS */\r
1386 break;\r
1387\r
1388 case MT_P0BR: /* P0BR */\r
1389 ML_PXBR_TEST (val); /* validate */\r
1390 P0BR = val & BR_MASK; /* lw aligned */\r
1391 zap_tb (0); /* clr proc TLB */\r
1392 set_map_reg ();\r
1393 break;\r
1394\r
1395 case MT_P0LR: /* P0LR */\r
1396 ML_LR_TEST (val & LR_MASK); /* validate */\r
1397 P0LR = val & LR_MASK;\r
1398 zap_tb (0); /* clr proc TLB */\r
1399 set_map_reg ();\r
1400 break;\r
1401\r
1402 case MT_P1BR: /* P1BR */\r
1403 ML_PXBR_TEST (val + 0x800000); /* validate */\r
1404 P1BR = val & BR_MASK; /* lw aligned */\r
1405 zap_tb (0); /* clr proc TLB */\r
1406 set_map_reg ();\r
1407 break;\r
1408\r
1409 case MT_P1LR: /* P1LR */\r
1410 ML_LR_TEST (val & LR_MASK); /* validate */\r
1411 P1LR = val & LR_MASK;\r
1412 zap_tb (0); /* clr proc TLB */\r
1413 set_map_reg ();\r
1414 break;\r
1415\r
1416 case MT_SBR: /* SBR */\r
1417 ML_SBR_TEST (val); /* validate */\r
1418 SBR = val & BR_MASK; /* lw aligned */\r
1419 zap_tb (1); /* clr entire TLB */\r
1420 set_map_reg ();\r
1421 break;\r
1422\r
1423 case MT_SLR: /* SLR */\r
1424 ML_LR_TEST (val & LR_MASK); /* validate */\r
1425 SLR = val & LR_MASK;\r
1426 zap_tb (1); /* clr entire TLB */\r
1427 set_map_reg ();\r
1428 break;\r
1429\r
1430 case MT_SCBB: /* SCBB */\r
1431 ML_PA_TEST (val); /* validate */\r
1432 SCBB = val & BR_MASK; /* lw aligned */\r
1433 break;\r
1434\r
1435 case MT_PCBB: /* PCBB */\r
1436 ML_PA_TEST (val); /* validate */\r
1437 PCBB = val & BR_MASK; /* lw aligned */\r
1438 break;\r
1439\r
1440 case MT_IPL: /* IPL */\r
1441 PSL = (PSL & ~PSL_IPL) | ((val & PSL_M_IPL) << PSL_V_IPL);\r
1442 break;\r
1443\r
1444 case MT_ASTLVL: /* ASTLVL */\r
1445 if (val > AST_MAX) RSVD_OPND_FAULT; /* > 4? fault */\r
1446 ASTLVL = val;\r
1447 break;\r
1448\r
1449 case MT_SIRR: /* SIRR */\r
1450 if ((val > 0xF) || (val == 0)) RSVD_OPND_FAULT;\r
1451 SISR = SISR | (1 << val); /* set bit in SISR */\r
1452 break;\r
1453\r
1454 case MT_SISR: /* SISR */\r
1455 SISR = val & SISR_MASK;\r
1456 break;\r
1457\r
1458 case MT_MAPEN: /* MAPEN */\r
1459 mapen = val & 1;\r
1460 case MT_TBIA: /* TBIA */\r
1461 zap_tb (1); /* clr entire TLB */\r
1462 break;\r
1463\r
1464 case MT_TBIS: /* TBIS */\r
1465 zap_tb_ent (val);\r
1466 break;\r
1467\r
1468 case MT_TBCHK: /* TBCHK */\r
1469 if (chk_tb_ent (val)) cc = cc | CC_V;\r
1470 break;\r
1471\r
1472 case MT_PME: /* PME */\r
1473 pme = val & 1;\r
1474 break;\r
1475\r
1476 default:\r
1477 WriteIPR (prn, val); /* others */\r
1478 break;\r
1479 }\r
1480\r
1481return cc;\r
1482}\r
1483\r
1484int32 op_mfpr (int32 *opnd)\r
1485{\r
1486int32 prn = opnd[0];\r
1487int32 val;\r
1488\r
1489if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */\r
1490if (prn > 63) RSVD_OPND_FAULT; /* reg# > 63? fault */\r
1491switch (prn) { /* case on reg# */\r
1492\r
1493 case MT_KSP: /* KSP */\r
1494 val = (PSL & PSL_IS)? KSP: SP; /* return KSP or SP */\r
1495 break;\r
1496\r
1497 case MT_ESP: case MT_SSP: case MT_USP: /* ESP, SSP, USP */\r
1498 val = STK[prn]; /* return stk ptr */\r
1499 break;\r
1500\r
1501 case MT_IS: /* IS */\r
1502 val = (PSL & PSL_IS)? SP: IS; /* return SP or IS */\r
1503 break;\r
1504\r
1505 case MT_P0BR: /* P0BR */\r
1506 val = P0BR;\r
1507 break;\r
1508\r
1509 case MT_P0LR: /* P0LR */\r
1510 val = P0LR;\r
1511 break;\r
1512\r
1513 case MT_P1BR: /* P1BR */\r
1514 val = P1BR;\r
1515 break;\r
1516\r
1517 case MT_P1LR: /* P1LR */\r
1518 val = P1LR;\r
1519 break;\r
1520\r
1521 case MT_SBR: /* SBR */\r
1522 val = SBR;\r
1523 break;\r
1524\r
1525 case MT_SLR: /* SLR */\r
1526 val = SLR;\r
1527 break;\r
1528\r
1529 case MT_SCBB: /* SCBB */\r
1530 val = SCBB;\r
1531 break;\r
1532\r
1533 case MT_PCBB: /* PCBB */\r
1534 val = PCBB;\r
1535 break;\r
1536\r
1537 case MT_IPL: /* IPL */\r
1538 val = PSL_GETIPL (PSL);\r
1539 break;\r
1540\r
1541 case MT_ASTLVL: /* ASTLVL */\r
1542 val = ASTLVL;\r
1543 break;\r
1544\r
1545 case MT_SISR: /* SISR */\r
1546 val = SISR & SISR_MASK;\r
1547 break;\r
1548\r
1549 case MT_MAPEN: /* MAPEN */\r
1550 val = mapen & 1;\r
1551 break;\r
1552\r
1553 case MT_PME:\r
1554 val = pme & 1;\r
1555 break;\r
1556\r
1557 case MT_SIRR:\r
1558 case MT_TBIA:\r
1559 case MT_TBIS:\r
1560 case MT_TBCHK:\r
1561 RSVD_OPND_FAULT; /* write only */\r
1562\r
1563 default: /* others */\r
1564 val = ReadIPR (prn); /* read from SSC */\r
1565 break;\r
1566 }\r
1567\r
1568return val;\r
1569}\r