First Commit of my working state
[simh.git] / PDP10 / pdp10_xtnd.c
1 /* pdp10_xtnd.c: PDP-10 extended instruction simulator
2
3 Copyright (c) 1993-2005, 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 12-May-01 RMS Fixed compiler warning in xlate
27
28 Instructions handled in this module:
29
30 MOVSLJ move string left justified
31 MOVSO move string offset
32 MOVST move string translated
33 MOVSRJ move string right justified
34 CMPSL compare string, skip on less
35 CMPSE compare string, skip on equal
36 CMPSLE compare string, skip on less or equal
37 CMPSGE compare string, skip on greater or equal
38 CMPSN compare string, skip on unequal
39 CMPSG compare string, skip on greater
40 CVTDBO convert decimal to binary offset
41 CVTDBT convert decimal to binary translated
42 CVTBDO convert binary to decimal offset
43 CVTBDT convert binary to decimal translated
44 EDIT edit
45
46 The PDP-10 extended instructions deal with non-binary data types,
47 particularly byte strings and decimal strings. (In the KL10, the
48 extended instructions include G floating support as well.) They
49 are very complicated microcoded subroutines that can potentially
50 run for a very long time. Accordingly, the instructions must test
51 for interrupts as well as page faults, and be prepared to restart
52 from either.
53
54 In general, the simulator attempts to keep the AC block up to date,
55 so that page fails and interrupts can be taken directly at any point.
56 If the AC block is not up to date, memory accessibility must be tested
57 before the actual read or write is done.
58
59 The extended instruction routine returns a status code as follows:
60
61 XT_NOSK no skip completion
62 XT_SKIP skip completion
63 XT_MUUO invalid extended instruction
64 */
65
66 #include "pdp10_defs.h"
67 #include <setjmp.h>
68
69 #define MM_XSRC (pflgs & XSRC_PXCT)
70 #define MM_XDST (pflgs & XDST_PXCT)
71 #define MM_EA_XSRC ((pflgs & EA_PXCT) && MM_XSRC)
72 #define MM_EA_XDST ((pflgs & EA_PXCT) && MM_XDST)
73
74 #define XT_CMPSL 001 /* opcodes */
75 #define XT_CMPSE 002
76 #define XT_CMPSLE 003
77 #define XT_EDIT 004
78 #define XT_CMPSGE 005
79 #define XT_CMPSN 006
80 #define XT_CMPSG 007
81 #define XT_CVTDBO 010
82 #define XT_CVTDBT 011
83 #define XT_CVTBDO 012
84 #define XT_CVTBDT 013
85 #define XT_MOVSO 014
86 #define XT_MOVST 015
87 #define XT_MOVSLJ 016
88 #define XT_MOVSRJ 017
89
90 /* Translation control */
91
92 #define XT_LFLG 0400000000000 /* L flag */
93 #define XT_SFLG 0400000000000 /* S flag */
94 #define XT_NFLG 0200000000000 /* N flag */
95 #define XT_MFLG 0100000000000 /* M flag */
96
97 /* Translation table */
98
99 #define XT_V_CODE 15 /* translation op */
100 #define XT_M_CODE 07
101 #define XT_BYMASK 07777 /* byte mask */
102 #define XT_DGMASK 017 /* digit mask */
103 #define XT_GETCODE(x) ((int32) (((x) >> XT_V_CODE) & XT_M_CODE))
104
105 /* AC masks */
106
107 #define XLNTMASK 0000777777777 /* length */
108 #define XFLGMASK 0700000000000 /* flags */
109 #define XT_MBZ 0777000000000 /* must be zero */
110 #define XT_MBZE 0047777000000 /* must be zero, edit */
111
112 /* Register change log */
113
114 #define XT_N_RLOG 5 /* entry width */
115 #define XT_M_RLOG ((1 << XT_N_RLOG) - 1) /* entry mask */
116 #define XT_O_RLOG 1 /* entry offset */
117 #define XT_INSRLOG(x,v) v = ((v << XT_N_RLOG) | (((x) + XT_O_RLOG) & XT_M_RLOG))
118 #define XT_REMRLOG(x,v) x = (v & XT_M_RLOG) - XT_O_RLOG; \
119 v = v >> XT_N_RLOG
120
121 /* Edit */
122
123 #define ED_V_PBYN 30 /* pattern byte # */
124 #define ED_M_PBYN 03
125 #define ED_PBYNO 0040000000000 /* overflow bit */
126 #define ED_GETPBYN(x) ((int32) (((x) >> ED_V_PBYN) & ED_M_PBYN))
127 #define ED_V_POPC 6 /* pattern byte opcode */
128 #define ED_M_PAT 0777 /* pattern byte mask */
129 #define ED_M_NUM 0077 /* number for msg, etc */
130 #define ED_PBYTE(x,y) ((int32) (((x) >> (27 - (ED_GETPBYN (y) * 9))) & ED_M_PAT))
131 #define ED_STOP 0000 /* stop */
132 #define ED_SELECT 0001 /* select source */
133 #define ED_SIGST 0002 /* start significance */
134 #define ED_FLDSEP 0003 /* field separator */
135 #define ED_EXCHMD 0004 /* exchange mark, dst */
136 #define ED_MESSAG 0100 /* message */
137 #define ED_SKPM 0500 /* skip if M */
138 #define ED_SKPN 0600 /* skip if N */
139 #define ED_SKPA 0700 /* skip always */
140
141 extern d10 *ac_cur; /* current AC block */
142 extern const d10 bytemask[64];
143 extern int32 flags;
144 extern int32 rlog;
145 extern jmp_buf save_env;
146
147 extern d10 Read (int32 ea, int32 prv);
148 extern void Write (int32 ea, d10 val, int32 prv);
149 extern a10 calc_ea (d10 inst, int32 prv);
150 extern int32 test_int (void);
151 d10 incbp (d10 bp);
152 d10 incloadbp (int32 ac, int32 pflgs);
153 void incstorebp (d10 val, int32 ac, int32 pflgs);
154 d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 pflgs);
155 void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs);
156
157 static const d10 pwrs10[23][2] = {
158 0, 0,
159 0, 1,
160 0, 10,
161 0, 100,
162 0, 1000,
163 0, 10000,
164 0, 100000,
165 0, 1000000,
166 0, 10000000,
167 0, 100000000,
168 0, 1000000000,
169 0, 10000000000,
170 2, 31280523264,
171 29, 3567587328,
172 291, 1316134912,
173 2910, 13161349120,
174 29103, 28534276096,
175 291038, 10464854016,
176 2910383, 1569325056,
177 29103830, 15693250560,
178 291038304, 19493552128,
179 2910383045, 23136829440,
180 29103830456, 25209864192
181 };
182
183 int xtend (int32 ac, int32 ea, int32 pflgs)
184 {
185 d10 b1, b2, ppi;
186 d10 xinst, xoff, digit, f1, f2, rs[2];
187 d10 xflgs = 0;
188 a10 e1, entad;
189 int32 p1 = ADDAC (ac, 1);
190 int32 p3 = ADDAC (ac, 3);
191 int32 p4 = ADDAC (ac, 4);
192 int32 flg, i, s2, t, pp, pat, xop, xac, ret;
193
194 xinst = Read (ea, MM_OPND); /* get extended instr */
195 xop = GET_OP (xinst); /* get opcode */
196 xac = GET_AC (xinst); /* get AC */
197 if (xac || (xop == 0) || (xop > XT_MOVSRJ)) return XT_MUUO;
198 rlog = 0; /* clear log */
199 switch (xop) { /* case on opcode */
200
201 /* String compares - checked against KS10 ucode
202 If both strings are zero length, they are considered equal.
203 Both source and destination lengths are MBZ checked.
204
205 AC = source1 length
206 AC + 1 = source1 byte pointer
207 AC + 3 = source2 length
208 AC + 4 = source2 byte pointer
209 */
210
211 case XT_CMPSL: /* CMPSL */
212 case XT_CMPSE: /* CMPSE */
213 case XT_CMPSLE: /* CMPSLE */
214 case XT_CMPSGE: /* CMPSGE */
215 case XT_CMPSN: /* CMPSN */
216 case XT_CMPSG: /* CMPSG */
217 if ((AC(ac) | AC(p3)) & XT_MBZ) return XT_MUUO; /* check length MBZ */
218 f1 = Read (ADDA (ea, 1), MM_OPND) & bytemask[GET_S (AC(p1))];
219 f2 = Read (ADDA (ea, 2), MM_OPND) & bytemask[GET_S (AC(p4))];
220 b1 = b2 = 0;
221 for (flg = 0; (AC(ac) | AC(p3)) && (b1 == b2); flg++) {
222 if (flg && (t = test_int ())) ABORT (t);
223 rlog = 0; /* clear log */
224 if (AC(ac)) b1 = incloadbp (p1, pflgs); /* src1 */
225 else b1 = f1;
226 if (AC(p3)) b2 = incloadbp (p4, pflgs); /* src2 */
227 else b2 = f2;
228 if (AC(ac)) AC(ac) = (AC(ac) - 1) & XLNTMASK;
229 if (AC(p3)) AC(p3) = (AC(p3) - 1) & XLNTMASK;
230 }
231 switch (xop) {
232 case XT_CMPSL:
233 return (b1 < b2)? XT_SKIP: XT_NOSK;
234 case XT_CMPSE:
235 return (b1 == b2)? XT_SKIP: XT_NOSK;
236 case XT_CMPSLE:
237 return (b1 <= b2)? XT_SKIP: XT_NOSK;
238 case XT_CMPSGE:
239 return (b1 >= b2)? XT_SKIP: XT_NOSK;
240 case XT_CMPSN:
241 return (b1 != b2)? XT_SKIP: XT_NOSK;
242 case XT_CMPSG:
243 return (b1 > b2)? XT_SKIP: XT_NOSK;
244 }
245
246 return XT_MUUO;
247
248 /* Convert binary to decimal instructions - checked against KS10 ucode
249 There are no MBZ tests.
250
251 AC'AC + 1 = double precision integer source
252 AC + 3 = flags and destination length
253 AC + 4 = destination byte pointer
254 */
255
256 case XT_CVTBDO: /* CVTBDO */
257 case XT_CVTBDT: /* CVTBDT */
258 e1 = calc_ea (xinst, MM_EA); /* get ext inst addr */
259 if (xop == XT_CVTBDO) /* offset? */
260 xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */
261 rs[0] = AC(ac); /* get src opnd */
262 rs[1] = CLRS (AC(p1));
263 if (!TSTF (F_FPD)) { /* set up done yet? */
264 if (TSTS (AC(ac))) { DMOVN (rs); } /* get abs value */
265 for (i = 22; i > 1; i--) { /* find field width */
266 if (DCMPGE (rs, pwrs10[i])) break;
267 }
268 if (i > (AC(p3) & XLNTMASK)) return XT_NOSK;
269 if ((i < (AC(p3) & XLNTMASK)) && (AC(p3) & XT_LFLG)) {
270 f1 = Read (ADDA (ea, 1), MM_OPND);
271 filldst (f1, p3, (AC(p3) & XLNTMASK) - i, pflgs);
272 }
273 else AC(p3) = (AC(p3) & XFLGMASK) | i;
274 if (TSTS (AC(ac))) AC(p3) = AC(p3) | XT_MFLG;
275 if (AC(ac) | AC(p1)) AC(p3) = AC(p3) | XT_NFLG;
276 AC(ac) = rs[0]; /* update state */
277 AC(p1) = rs[1];
278 SETF (F_FPD); /* mark set up done */
279 }
280
281 /* Now do actual binary to decimal conversion */
282
283 for (flg = 0; AC(p3) & XLNTMASK; flg++) {
284 if (flg && (t = test_int ())) ABORT (t);
285 rlog = 0; /* clear log */
286 i = (int32) AC(p3) & XLNTMASK; /* get length */
287 if (i > 22) i = 22; /* put in range */
288 for (digit = 0; (digit < 10) && DCMPGE (rs, pwrs10[i]); digit++) {
289 rs[0] = rs[0] - pwrs10[i][0] - (rs[1] < pwrs10[i][1]);
290 rs[1] = (rs[1] - pwrs10[i][1]) & MMASK;
291 }
292 if (xop == XT_CVTBDO) digit = (digit + xoff) & DMASK;
293 else {
294 f1 = Read (e1 + (int32) digit, MM_OPND);
295 if ((i == 1) && (AC(p3) & XT_LFLG)) f1 = f1 >> 18;
296 digit = f1 & RMASK;
297 }
298 incstorebp (digit, p4, pflgs); /* store digit */
299 AC(ac) = rs[0]; /* mem access ok */
300 AC(p1) = rs[1]; /* update state */
301 AC(p3) = (AC(p3) & XFLGMASK) | ((AC(p3) - 1) & XLNTMASK);
302 }
303 CLRF (F_FPD); /* clear FPD */
304 return XT_SKIP;
305
306 /* Convert decimal to binary instructions - checked against KS10 ucode
307 There are no MBZ tests.
308
309 AC = flags and source length
310 AC + 1 = source byte pointer
311 AC + 3'AC + 4 = double precision integer result
312 */
313
314 case XT_CVTDBT: /* CVTDBT */
315 case XT_CVTDBO: /* CVTDBO */
316 e1 = calc_ea (xinst, MM_EA); /* get ext inst addr */
317 if ((AC(ac) & XT_SFLG) == 0) AC(p3) = AC(p4) = 0; /* !S? clr res */
318 else AC(p4) = CLRS (AC(p4)); /* clear low sign */
319 if (xop == XT_CVTDBO) { /* offset? */
320 xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */
321 AC(ac) = AC(ac) | XT_SFLG; /* set S flag */
322 }
323 xflgs = AC(ac) & XFLGMASK; /* get xlation flags */
324 for (flg = 0; AC(ac) & XLNTMASK; flg++) {
325 if (flg && (t = test_int ())) ABORT (t);
326 rlog = 0; /* clear log */
327 b1 = incloadbp (p1, pflgs); /* get byte */
328 if (xop == XT_CVTDBO) b1 = (b1 + xoff) & DMASK;
329 else {
330 b1 = xlate (b1, e1, &xflgs, MM_OPND);
331 if (b1 < 0) { /* terminated? */
332 AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
333 if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4));
334 return XT_NOSK;
335 }
336 if (xflgs & XT_SFLG) b1 = b1 & XT_DGMASK;
337 else b1 = 0;
338 }
339 AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
340 if ((b1 < 0) || (b1 > 9)) { /* bad digit? done */
341 if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4));
342 return XT_NOSK;
343 }
344 AC(p4) = (AC(p4) * 10) + b1; /* base * 10 + digit */
345 AC(p3) = ((AC(p3) * 10) + (AC(p4) >> 35)) & DMASK;
346 AC(p4) = AC(p4) & MMASK;
347 }
348 if (AC(ac) & XT_MFLG) {
349 AC(p4) = -AC(p4) & MMASK;
350 AC(p3) = (~AC(p3) + (AC(p4) == 0)) & DMASK;
351 }
352 if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4));
353 return XT_SKIP;
354
355 /* String move instructions - checked against KS10 ucode
356 Only the destination length is MBZ checked.
357
358 AC = flags (MOVST only) and source length
359 AC + 1 = source byte pointer
360 AC + 3 = destination length
361 AC + 4 = destination byte pointer
362 */
363
364 case XT_MOVSO: /* MOVSO */
365 case XT_MOVST: /* MOVST */
366 case XT_MOVSRJ: /* MOVSRJ */
367 case XT_MOVSLJ: /* MOVSLJ */
368 if (AC(p3) & XT_MBZ) return XT_MUUO; /* test dst lnt MBZ */
369 f1 = Read (ADDA (ea, 1), MM_OPND); /* get fill */
370 switch (xop) { /* case on instr */
371
372 case XT_MOVSO: /* MOVSO */
373 AC(ac) = AC(ac) & XLNTMASK; /* trim src length */
374 xoff = calc_ea (xinst, MM_EA); /* get offset */
375 if (xoff & RSIGN) xoff = xoff | LMASK; /* sign extend 18b */
376 s2 = GET_S (AC(p4)); /* get dst byte size */
377 break;
378
379 case XT_MOVST: /* MOVST */
380 e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */
381 break;
382
383 case XT_MOVSRJ: /* MOVSRJ */
384 AC(ac) = AC(ac) & XLNTMASK; /* trim src length */
385 if (AC(p3) == 0) return (AC(ac)? XT_NOSK: XT_SKIP);
386 if (AC(ac) > AC(p3)) { /* adv src ptr */
387 for (flg = 0; AC(ac) > AC(p3); flg++) {
388 if (flg && (t = test_int ())) ABORT (t);
389 AC(p1) = incbp (AC(p1));
390 AC(ac) = (AC(ac) - 1) & XLNTMASK;
391 }
392 }
393 else if (AC(ac) < AC(p3))
394 filldst (f1, p3, AC(p3) - AC(ac), pflgs);
395 break;
396
397 case XT_MOVSLJ: /* MOVSLJ */
398 AC(ac) = AC(ac) & XLNTMASK; /* trim src length */
399 break;
400 } /* end case xop */
401
402 xflgs = AC(ac) & XFLGMASK; /* get xlation flags */
403 if (AC(p3) == 0) return (AC(ac)? XT_NOSK: XT_SKIP);
404 for (flg = 0; AC(p3) & XLNTMASK; flg++) {
405 if (flg && (t = test_int ())) ABORT (t);
406 rlog = 0; /* clear log */
407 if (AC(ac) & XLNTMASK) { /* any source? */
408 b1 = incloadbp (p1, pflgs); /* src byte */
409 if (xop == XT_MOVSO) { /* offset? */
410 b1 = (b1 + xoff) & DMASK; /* test fit */
411 if (b1 & ~bytemask[s2]) {
412 AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
413 return XT_NOSK;
414 }
415 }
416 else if (xop == XT_MOVST) { /* translate? */
417 b1 = xlate (b1, e1, &xflgs, MM_OPND);
418 if (b1 < 0) { /* upd flags in AC */
419 AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
420 return XT_NOSK;
421 }
422 if (xflgs & XT_SFLG) b1 = b1 & XT_BYMASK;
423 else b1 = -1;
424 }
425 }
426 else b1 = f1;
427 if (b1 >= 0) { /* valid byte? */
428 incstorebp (b1, p4, pflgs); /* store byte */
429 AC(p3) = (AC(p3) - 1) & XLNTMASK; /* update state */
430 }
431 if (AC(ac) & XLNTMASK) AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
432 }
433 return (AC(ac) & XLNTMASK)? XT_NOSK: XT_SKIP;
434
435 /* Edit - checked against KS10 ucode
436 Only the flags/pattern pointer word is MBZ checked.
437
438 AC = flags, pattern pointer
439 AC + 1 = source byte pointer
440 AC + 3 = mark address
441 AC + 4 = destination byte pointer
442 */
443
444 case XT_EDIT: /* EDIT */
445 if (AC(ac) & XT_MBZE) return XT_MUUO; /* check pattern MBZ */
446 xflgs = AC(ac) & XFLGMASK; /* get xlation flags */
447 e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */
448 for (ppi = 1, ret = -1, flg = 0; ret < 0; flg++, ppi = 1) {
449 if (flg && (t = test_int ())) ABORT (t);
450 rlog = 0; /* clear log */
451 pp = (int32) AC(ac) & AMASK; /* get pattern ptr */
452 b1 = Read (pp, MM_OPND); /* get pattern word */
453 pat = ED_PBYTE (b1, AC(ac)); /* get pattern byte */
454 switch ((pat < 0100)? pat: ((pat >> ED_V_POPC) + 0100)) {
455
456 case ED_STOP: /* stop */
457 ret = XT_SKIP; /* exit loop */
458 break;
459
460 case ED_SELECT: /* select source */
461 b1 = incloadbp (p1, pflgs); /* get src */
462 entad = (e1 + ((int32) b1 >> 1)) & AMASK;
463 f1 = ((Read (entad, MM_OPND) >> ((b1 & 1)? 0: 18)) & RMASK);
464 i = XT_GETCODE (f1);
465 if (i & 2) xflgs =
466 (i & 1)? xflgs | XT_MFLG: xflgs & ~XT_MFLG;
467 switch (i) {
468
469 case 00: case 02: case 03:
470 if (xflgs & XT_SFLG) f1 = f1 & XT_BYMASK;
471 else {
472 f1 = Read (INCA (ea), MM_OPND);
473 if (f1 == 0) break;
474 }
475 incstorebp (f1, p4, pflgs);
476 break;
477
478 case 01:
479 ret = XT_NOSK; /* exit loop */
480 break;
481
482 case 04: case 06: case 07:
483 xflgs = xflgs | XT_NFLG;
484 f1 = f1 & XT_BYMASK;
485 if ((xflgs & XT_SFLG) == 0) {
486 f2 = Read (ADDA (ea, 2), MM_OPND);
487 Write ((a10) AC(p3), AC(p4), MM_OPND);
488 if (f2) incstorebp (f2, p4, pflgs);
489 xflgs = xflgs | XT_SFLG;
490 }
491 incstorebp (f1, p4, pflgs);
492 break;
493
494 case 05:
495 xflgs = xflgs | XT_NFLG;
496 ret = XT_NOSK; /* exit loop */
497 break;
498 } /* end case xlate op */
499 break;
500
501 case ED_SIGST: /* start significance */
502 if ((xflgs & XT_SFLG) == 0) {
503 f2 = Read (ADDA (ea, 2), MM_OPND);
504 Write ((a10) AC(p3), AC(p4), MM_OPND);
505 if (f2) incstorebp (f2, p4, pflgs);
506 xflgs = xflgs | XT_SFLG;
507 }
508 break;
509
510 case ED_FLDSEP: /* separate fields */
511 xflgs = 0;
512 break;
513
514 case ED_EXCHMD: /* exchange */
515 f2 = Read ((int32) (AC(p3) & AMASK), MM_OPND);
516 Write ((int32) (AC(p3) & AMASK), AC(p4), MM_OPND);
517 AC(p4) = f2;
518 break;
519
520 case (0100 + (ED_MESSAG >> ED_V_POPC)): /* message */
521 if (xflgs & XT_SFLG)
522 f1 = Read (ea + (pat & ED_M_NUM) + 1, MM_OPND);
523 else {
524 f1 = Read (ea + 1, MM_OPND);
525 if (f1 == 0) break;
526 }
527 incstorebp (f1, p4, pflgs);
528 break;
529
530 case (0100 + (ED_SKPM >> ED_V_POPC)): /* skip on M */
531 if (xflgs & XT_MFLG) ppi = (pat & ED_M_NUM) + 2;
532 break;
533
534 case (0100 + (ED_SKPN >> ED_V_POPC)): /* skip on N */
535 if (xflgs & XT_NFLG) ppi = (pat & ED_M_NUM) + 2;
536 break;
537
538 case (0100 + (ED_SKPA >> ED_V_POPC)): /* skip always */
539 ppi = (pat & ED_M_NUM) + 2;
540 break;
541
542 default: /* NOP or undefined */
543 break;
544 } /* end case pttrn op */
545 AC(ac) = AC(ac) + ((ppi & ED_M_PBYN) << ED_V_PBYN);
546 AC(ac) = AC(ac) + (ppi >> 2) + ((AC(ac) & ED_PBYNO)? 1: 0);
547 AC(ac) = xflgs | (AC(ac) & ~(XT_MBZE | XFLGMASK));
548 }
549 return ret;
550 } /* end case xop */
551 return XT_MUUO;
552 }
553
554 /* Supporting subroutines */
555
556 /* Increment byte pointer, register version */
557
558 d10 incbp (d10 bp)
559 {
560 int32 p, s;
561
562 p = GET_P (bp); /* get P and S */
563 s = GET_S (bp);
564 p = p - s; /* adv P */
565 if (p < 0) { /* end of word? */
566 bp = (bp & LMASK) | (INCR (bp)); /* increment addr */
567 p = (36 - s) & 077; /* reset P */
568 }
569 bp = PUT_P (bp, p); /* store new P */
570 return bp;
571 }
572
573 /* Increment and load byte, extended version - uses register log */
574
575 d10 incloadbp (int32 ac, int32 pflgs)
576 {
577 a10 ba;
578 d10 bp, wd;
579 int32 p, s;
580
581 bp = AC(ac) = incbp (AC(ac)); /* increment bp */
582 XT_INSRLOG (ac, rlog); /* log change */
583 p = GET_P (bp); /* get P and S */
584 s = GET_S (bp);
585 ba = calc_ea (bp, MM_EA_XSRC); /* calc bp eff addr */
586 wd = Read (ba, MM_XSRC); /* read word */
587 wd = (wd >> p) & bytemask[s]; /* get byte */
588 return wd;
589 }
590
591 /* Increment and deposit byte, extended version - uses register log */
592
593 void incstorebp (d10 val, int32 ac, int32 pflgs)
594 {
595 a10 ba;
596 d10 bp, wd, mask;
597 int32 p, s;
598
599 bp = AC(ac) = incbp (AC(ac)); /* increment bp */
600 XT_INSRLOG (ac, rlog); /* log change */
601 p = GET_P (bp); /* get P and S */
602 s = GET_S (bp);
603 ba = calc_ea (bp, MM_EA_XDST); /* calc bp eff addr */
604 wd = Read (ba, MM_XDST); /* read, write test */
605 mask = bytemask[s] << p; /* shift mask, val */
606 val = val << p;
607 wd = (wd & ~mask) | (val & mask); /* insert byte */
608 Write (ba, wd & DMASK, MM_XDST);
609 return;
610 }
611
612 /* Translate byte
613
614 Arguments
615 by = byte to translate
616 tblad = virtual address of translation table
617 *xflgs = pointer to word containing translation flags
618 prv = previous mode flag for table lookup
619 Returns
620 xby = >= 0, translated byte
621 < 0, terminate translation
622 */
623
624 d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 prv)
625 {
626 a10 ea;
627 int32 tcode;
628 d10 tblent;
629
630 ea = (tblad + ((int32) by >> 1)) & AMASK;
631 tblent = ((Read (ea, prv) >> ((by & 1)? 0: 18)) & RMASK);
632 tcode = XT_GETCODE (tblent); /* get xlate code */
633 switch (tcode) {
634
635 case 00:
636 return (*xflgs & XT_SFLG)? tblent: by;
637
638 case 01:
639 break;
640
641 case 02:
642 *xflgs = *xflgs & ~XT_MFLG;
643 return (*xflgs & XT_SFLG)? tblent: by;
644
645 case 03:
646 *xflgs = *xflgs | XT_MFLG;
647 return (*xflgs & XT_SFLG)? tblent: by;
648
649 case 04:
650 *xflgs = *xflgs | XT_SFLG | XT_NFLG;
651 return tblent;
652
653 case 05:
654 *xflgs = *xflgs | XT_NFLG;
655 break;
656
657 case 06:
658 *xflgs = (*xflgs | XT_SFLG | XT_NFLG) & ~XT_MFLG;
659 return tblent;
660
661 case 07:
662 *xflgs = *xflgs | XT_SFLG | XT_NFLG | XT_MFLG;
663 return tblent;
664 } /* end case */
665
666 return -1;
667 }
668
669 /* Fill out the destination string
670
671 Arguments:
672 fill = fill
673 ac = 2 word AC block (length, byte pointer)
674 cnt = fill count
675 pflgs = PXCT flags
676 */
677
678 void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs)
679 {
680 int32 i, t;
681 int32 p1 = ADDA (ac, 1);
682
683 for (i = 0; i < cnt; i++) {
684 if (i && (t = test_int ())) ABORT (t);
685 rlog = 0; /* clear log */
686 incstorebp (fill, p1, pflgs);
687 AC(ac) = (AC(ac) & XFLGMASK) | ((AC(ac) - 1) & XLNTMASK);
688 }
689 rlog = 0;
690 return;
691 }
692
693 /* Clean up after page fault
694
695 Arguments:
696 logv = register change log
697
698 For each register in logv, decrement the register's contents as
699 though it were a byte pointer. Note that the KS10 does <not>
700 do a full decrement calculation but merely adds S to P.
701 */
702
703 void xtcln (int32 logv)
704 {
705 int32 p, reg;
706
707 while (logv) {
708 XT_REMRLOG (reg, logv); /* get next reg */
709 if ((reg >= 0) && (reg < AC_NUM)) {
710 p = GET_P (AC(reg)) + GET_S (AC(reg)); /* get p + s */
711 AC(reg) = PUT_P (AC(reg), p); /* p <- p + s */
712 }
713 }
714 return;
715 }