1 /* pdp10_xtnd.c: PDP-10 extended instruction simulator
2
3 Copyright (c) 1993-2008, Robert M Supnik
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
25
26 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
xtend(int32 ac,int32 ea,int32 pflgs)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))
198 return XT_MUUO;
199 rlog = 0; /* clear log */
200 switch (xop) { /* case on opcode */
201
202 /* String compares - checked against KS10 ucode
203 If both strings are zero length, they are considered equal.
204 Both source and destination lengths are MBZ checked.
205
206 AC = source1 length
207 AC + 1 = source1 byte pointer
208 AC + 3 = source2 length
209 AC + 4 = source2 byte pointer
210 */
211
212 case XT_CMPSL: /* CMPSL */
213 case XT_CMPSE: /* CMPSE */
214 case XT_CMPSLE: /* CMPSLE */
215 case XT_CMPSGE: /* CMPSGE */
216 case XT_CMPSN: /* CMPSN */
217 case XT_CMPSG: /* CMPSG */
218 if ((AC(ac) | AC(p3)) & XT_MBZ) /* check length MBZ */
219 return XT_MUUO;
220 f1 = Read (ADDA (ea, 1), MM_OPND) & bytemask[GET_S (AC(p1))];
221 f2 = Read (ADDA (ea, 2), MM_OPND) & bytemask[GET_S (AC(p4))];
222 b1 = b2 = 0;
223 for (flg = 0; (AC(ac) | AC(p3)) && (b1 == b2); flg++) {
224 if (flg && (t = test_int ()))
225 ABORT (t);
226 rlog = 0; /* clear log */
227 if (AC(ac)) /* src1 */
228 b1 = incloadbp (p1, pflgs);
229 else b1 = f1;
230 if (AC(p3)) /* src2 */
231 b2 = incloadbp (p4, pflgs);
232 else b2 = f2;
233 if (AC(ac))
234 AC(ac) = (AC(ac) - 1) & XLNTMASK;
235 if (AC(p3))
236 AC(p3) = (AC(p3) - 1) & XLNTMASK;
237 }
238 switch (xop) {
239 case XT_CMPSL:
240 return (b1 < b2)? XT_SKIP: XT_NOSK;
241 case XT_CMPSE:
242 return (b1 == b2)? XT_SKIP: XT_NOSK;
243 case XT_CMPSLE:
244 return (b1 <= b2)? XT_SKIP: XT_NOSK;
245 case XT_CMPSGE:
246 return (b1 >= b2)? XT_SKIP: XT_NOSK;
247 case XT_CMPSN:
248 return (b1 != b2)? XT_SKIP: XT_NOSK;
249 case XT_CMPSG:
250 return (b1 > b2)? XT_SKIP: XT_NOSK;
251 }
252
253 return XT_MUUO;
254
255 /* Convert binary to decimal instructions - checked against KS10 ucode
256 There are no MBZ tests.
257
258 AC'AC + 1 = double precision integer source
259 AC + 3 = flags and destination length
260 AC + 4 = destination byte pointer
261 */
262
263 case XT_CVTBDO: /* CVTBDO */
264 case XT_CVTBDT: /* CVTBDT */
265 e1 = calc_ea (xinst, MM_EA); /* get ext inst addr */
266 if (xop == XT_CVTBDO) /* offset? */
267 xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */
268 rs[0] = AC(ac); /* get src opnd */
269 rs[1] = CLRS (AC(p1));
270 if (!TSTF (F_FPD)) { /* set up done yet? */
271 if (TSTS (AC(ac))) { /* get abs value */
272 DMOVN (rs);
273 }
274 for (i = 22; i > 1; i--) { /* find field width */
275 if (DCMPGE (rs, pwrs10[i]))
276 break;
277 }
278 if (i > (AC(p3) & XLNTMASK))
279 return XT_NOSK;
280 if ((i < (AC(p3) & XLNTMASK)) && (AC(p3) & XT_LFLG)) {
281 f1 = Read (ADDA (ea, 1), MM_OPND);
282 filldst (f1, p3, (AC(p3) & XLNTMASK) - i, pflgs);
283 }
284 else AC(p3) = (AC(p3) & XFLGMASK) | i;
285 if (TSTS (AC(ac)))
286 AC(p3) = AC(p3) | XT_MFLG;
287 if (AC(ac) | AC(p1))
288 AC(p3) = AC(p3) | XT_NFLG;
289 AC(ac) = rs[0]; /* update state */
290 AC(p1) = rs[1];
291 SETF (F_FPD); /* mark set up done */
292 }
293
294 /* Now do actual binary to decimal conversion */
295
296 for (flg = 0; AC(p3) & XLNTMASK; flg++) {
297 if (flg && (t = test_int ()))
298 ABORT (t);
299 rlog = 0; /* clear log */
300 i = (int32) AC(p3) & XLNTMASK; /* get length */
301 if (i > 22) /* put in range */
302 i = 22;
303 for (digit = 0; (digit < 10) && DCMPGE (rs, pwrs10[i]); digit++) {
304 rs[0] = rs[0] - pwrs10[i][0] - (rs[1] < pwrs10[i][1]);
305 rs[1] = (rs[1] - pwrs10[i][1]) & MMASK;
306 }
307 if (xop == XT_CVTBDO)
308 digit = (digit + xoff) & DMASK;
309 else {
310 f1 = Read (e1 + (int32) digit, MM_OPND);
311 if ((i == 1) && (AC(p3) & XT_LFLG))
312 f1 = f1 >> 18;
313 digit = f1 & RMASK;
314 }
315 incstorebp (digit, p4, pflgs); /* store digit */
316 AC(ac) = rs[0]; /* mem access ok */
317 AC(p1) = rs[1]; /* update state */
318 AC(p3) = (AC(p3) & XFLGMASK) | ((AC(p3) - 1) & XLNTMASK);
319 }
320 CLRF (F_FPD); /* clear FPD */
321 return XT_SKIP;
322
323 /* Convert decimal to binary instructions - checked against KS10 ucode
324 There are no MBZ tests.
325
326 AC = flags and source length
327 AC + 1 = source byte pointer
328 AC + 3'AC + 4 = double precision integer result
329 */
330
331 case XT_CVTDBT: /* CVTDBT */
332 case XT_CVTDBO: /* CVTDBO */
333 e1 = calc_ea (xinst, MM_EA); /* get ext inst addr */
334 if ((AC(ac) & XT_SFLG) == 0) /* !S? clr res */
335 AC(p3) = AC(p4) = 0;
336 else AC(p4) = CLRS (AC(p4)); /* clear low sign */
337 if (xop == XT_CVTDBO) { /* offset? */
338 xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */
339 AC(ac) = AC(ac) | XT_SFLG; /* set S flag */
340 }
341 xflgs = AC(ac) & XFLGMASK; /* get xlation flags */
342 for (flg = 0; AC(ac) & XLNTMASK; flg++) {
343 if (flg && (t = test_int ()))
344 ABORT (t);
345 rlog = 0; /* clear log */
346 b1 = incloadbp (p1, pflgs); /* get byte */
347 if (xop == XT_CVTDBO)
348 b1 = (b1 + xoff) & DMASK;
349 else {
350 b1 = xlate (b1, e1, &xflgs, MM_OPND);
351 if (b1 < 0) { /* terminated? */
352 AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
353 if (TSTS (AC(p3)))
354 AC(p4) = SETS (AC(p4));
355 return XT_NOSK;
356 }
357 if (xflgs & XT_SFLG)
358 b1 = b1 & XT_DGMASK;
359 else b1 = 0;
360 }
361 AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
362 if ((b1 < 0) || (b1 > 9)) { /* bad digit? done */
363 if (TSTS (AC(p3)))
364 AC(p4) = SETS (AC(p4));
365 return XT_NOSK;
366 }
367 AC(p4) = (AC(p4) * 10) + b1; /* base * 10 + digit */
368 AC(p3) = ((AC(p3) * 10) + (AC(p4) >> 35)) & DMASK;
369 AC(p4) = AC(p4) & MMASK;
370 }
371 if (AC(ac) & XT_MFLG) {
372 AC(p4) = -AC(p4) & MMASK;
373 AC(p3) = (~AC(p3) + (AC(p4) == 0)) & DMASK;
374 }
375 if (TSTS (AC(p3)))
376 AC(p4) = SETS (AC(p4));
377 return XT_SKIP;
378
379 /* String move instructions - checked against KS10 ucode
380 Only the destination length is MBZ checked.
381
382 AC = flags (MOVST only) and source length
383 AC + 1 = source byte pointer
384 AC + 3 = destination length
385 AC + 4 = destination byte pointer
386 */
387
388 case XT_MOVSO: /* MOVSO */
389 case XT_MOVST: /* MOVST */
390 case XT_MOVSRJ: /* MOVSRJ */
391 case XT_MOVSLJ: /* MOVSLJ */
392 if (AC(p3) & XT_MBZ) /* test dst lnt MBZ */
393 return XT_MUUO;
394 f1 = Read (ADDA (ea, 1), MM_OPND); /* get fill */
395 switch (xop) { /* case on instr */
396
397 case XT_MOVSO: /* MOVSO */
398 AC(ac) = AC(ac) & XLNTMASK; /* trim src length */
399 xoff = calc_ea (xinst, MM_EA); /* get offset */
400 if (xoff & RSIGN) /* sign extend 18b */
401 xoff = xoff | LMASK;
402 s2 = GET_S (AC(p4)); /* get dst byte size */
403 break;
404
405 case XT_MOVST: /* MOVST */
406 e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */
407 break;
408
409 case XT_MOVSRJ: /* MOVSRJ */
410 AC(ac) = AC(ac) & XLNTMASK; /* trim src length */
411 if (AC(p3) == 0)
412 return (AC(ac)? XT_NOSK: XT_SKIP);
413 if (AC(ac) > AC(p3)) { /* adv src ptr */
414 for (flg = 0; AC(ac) > AC(p3); flg++) {
415 if (flg && (t = test_int ()))
416 ABORT (t);
417 AC(p1) = incbp (AC(p1));
418 AC(ac) = (AC(ac) - 1) & XLNTMASK;
419 }
420 }
421 else if (AC(ac) < AC(p3))
422 filldst (f1, p3, AC(p3) - AC(ac), pflgs);
423 break;
424
425 case XT_MOVSLJ: /* MOVSLJ */
426 AC(ac) = AC(ac) & XLNTMASK; /* trim src length */
427 break;
428 } /* end case xop */
429
430 xflgs = AC(ac) & XFLGMASK; /* get xlation flags */
431 if (AC(p3) == 0)
432 return (AC(ac)? XT_NOSK: XT_SKIP);
433 for (flg = 0; AC(p3) & XLNTMASK; flg++) {
434 if (flg && (t = test_int ()))
435 ABORT (t);
436 rlog = 0; /* clear log */
437 if (AC(ac) & XLNTMASK) { /* any source? */
438 b1 = incloadbp (p1, pflgs); /* src byte */
439 if (xop == XT_MOVSO) { /* offset? */
440 b1 = (b1 + xoff) & DMASK; /* test fit */
441 if (b1 & ~bytemask[s2]) {
442 AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
443 return XT_NOSK;
444 }
445 }
446 else if (xop == XT_MOVST) { /* translate? */
447 b1 = xlate (b1, e1, &xflgs, MM_OPND);
448 if (b1 < 0) { /* upd flags in AC */
449 AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
450 return XT_NOSK;
451 }
452 if (xflgs & XT_SFLG)
453 b1 = b1 & XT_BYMASK;
454 else b1 = -1;
455 }
456 }
457 else b1 = f1;
458 if (b1 >= 0) { /* valid byte? */
459 incstorebp (b1, p4, pflgs); /* store byte */
460 AC(p3) = (AC(p3) - 1) & XLNTMASK; /* update state */
461 }
462 if (AC(ac) & XLNTMASK)
463 AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
464 }
465 return (AC(ac) & XLNTMASK)? XT_NOSK: XT_SKIP;
466
467 /* Edit - checked against KS10 ucode
468 Only the flags/pattern pointer word is MBZ checked.
469
470 AC = flags, pattern pointer
471 AC + 1 = source byte pointer
472 AC + 3 = mark address
473 AC + 4 = destination byte pointer
474 */
475
476 case XT_EDIT: /* EDIT */
477 if (AC(ac) & XT_MBZE) /* check pattern MBZ */
478 return XT_MUUO;
479 xflgs = AC(ac) & XFLGMASK; /* get xlation flags */
480 e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */
481 for (ppi = 1, ret = -1, flg = 0; ret < 0; flg++, ppi = 1) {
482 if (flg && (t = test_int ()))
483 ABORT (t);
484 rlog = 0; /* clear log */
485 pp = (int32) AC(ac) & AMASK; /* get pattern ptr */
486 b1 = Read (pp, MM_OPND); /* get pattern word */
487 pat = ED_PBYTE (b1, AC(ac)); /* get pattern byte */
488 switch ((pat < 0100)? pat: ((pat >> ED_V_POPC) + 0100)) {
489
490 case ED_STOP: /* stop */
491 ret = XT_SKIP; /* exit loop */
492 break;
493
494 case ED_SELECT: /* select source */
495 b1 = incloadbp (p1, pflgs); /* get src */
496 entad = (e1 + ((int32) b1 >> 1)) & AMASK;
497 f1 = ((Read (entad, MM_OPND) >> ((b1 & 1)? 0: 18)) & RMASK);
498 i = XT_GETCODE (f1);
499 if (i & 2)
500 xflgs = (i & 1)? xflgs | XT_MFLG: xflgs & ~XT_MFLG;
501 switch (i) {
502
503 case 00: case 02: case 03:
504 if (xflgs & XT_SFLG)
505 f1 = f1 & XT_BYMASK;
506 else {
507 f1 = Read (INCA (ea), MM_OPND);
508 if (f1 == 0)
509 break;
510 }
511 incstorebp (f1, p4, pflgs);
512 break;
513
514 case 01:
515 ret = XT_NOSK; /* exit loop */
516 break;
517
518 case 04: case 06: case 07:
519 xflgs = xflgs | XT_NFLG;
520 f1 = f1 & XT_BYMASK;
521 if ((xflgs & XT_SFLG) == 0) {
522 f2 = Read (ADDA (ea, 2), MM_OPND);
523 Write ((a10) AC(p3), AC(p4), MM_OPND);
524 if (f2)
525 incstorebp (f2, p4, pflgs);
526 xflgs = xflgs | XT_SFLG;
527 }
528 incstorebp (f1, p4, pflgs);
529 break;
530
531 case 05:
532 xflgs = xflgs | XT_NFLG;
533 ret = XT_NOSK; /* exit loop */
534 break;
535 } /* end case xlate op */
536 break;
537
538 case ED_SIGST: /* start significance */
539 if ((xflgs & XT_SFLG) == 0) {
540 f2 = Read (ADDA (ea, 2), MM_OPND);
541 Write ((a10) AC(p3), AC(p4), MM_OPND);
542 if (f2)
543 incstorebp (f2, p4, pflgs);
544 xflgs = xflgs | XT_SFLG;
545 }
546 break;
547
548 case ED_FLDSEP: /* separate fields */
549 xflgs = 0;
550 break;
551
552 case ED_EXCHMD: /* exchange */
553 f2 = Read ((int32) (AC(p3) & AMASK), MM_OPND);
554 Write ((int32) (AC(p3) & AMASK), AC(p4), MM_OPND);
555 AC(p4) = f2;
556 break;
557
558 case (0100 + (ED_MESSAG >> ED_V_POPC)): /* message */
559 if (xflgs & XT_SFLG)
560 f1 = Read (ea + (pat & ED_M_NUM) + 1, MM_OPND);
561 else {
562 f1 = Read (ea + 1, MM_OPND);
563 if (f1 == 0)
564 break;
565 }
566 incstorebp (f1, p4, pflgs);
567 break;
568
569 case (0100 + (ED_SKPM >> ED_V_POPC)): /* skip on M */
570 if (xflgs & XT_MFLG)
571 ppi = (pat & ED_M_NUM) + 2;
572 break;
573
574 case (0100 + (ED_SKPN >> ED_V_POPC)): /* skip on N */
575 if (xflgs & XT_NFLG)
576 ppi = (pat & ED_M_NUM) + 2;
577 break;
578
579 case (0100 + (ED_SKPA >> ED_V_POPC)): /* skip always */
580 ppi = (pat & ED_M_NUM) + 2;
581 break;
582
583 default: /* NOP or undefined */
584 break;
585 } /* end case pttrn op */
586 AC(ac) = AC(ac) + ((ppi & ED_M_PBYN) << ED_V_PBYN);
587 AC(ac) = AC(ac) + (ppi >> 2) + ((AC(ac) & ED_PBYNO)? 1: 0);
588 AC(ac) = xflgs | (AC(ac) & ~(XT_MBZE | XFLGMASK));
589 }
590 return ret;
591 } /* end case xop */
592 return XT_MUUO;
593 }
594
595 /* Supporting subroutines */
596
597 /* Increment byte pointer, register version */
598
incbp(d10 bp)599 d10 incbp (d10 bp)
600 {
601 int32 p, s;
602
603 p = GET_P (bp); /* get P and S */
604 s = GET_S (bp);
605 p = p - s; /* adv P */
606 if (p < 0) { /* end of word? */
607 bp = (bp & LMASK) | (INCR (bp)); /* increment addr */
608 p = (36 - s) & 077; /* reset P */
609 }
610 bp = PUT_P (bp, p); /* store new P */
611 return bp;
612 }
613
614 /* Increment and load byte, extended version - uses register log */
615
incloadbp(int32 ac,int32 pflgs)616 d10 incloadbp (int32 ac, int32 pflgs)
617 {
618 a10 ba;
619 d10 bp, wd;
620 int32 p, s;
621
622 bp = AC(ac) = incbp (AC(ac)); /* increment bp */
623 XT_INSRLOG (ac, rlog); /* log change */
624 p = GET_P (bp); /* get P and S */
625 s = GET_S (bp);
626 ba = calc_ea (bp, MM_EA_XSRC); /* calc bp eff addr */
627 wd = Read (ba, MM_XSRC); /* read word */
628 wd = (wd >> p) & bytemask[s]; /* get byte */
629 return wd;
630 }
631
632 /* Increment and deposit byte, extended version - uses register log */
633
incstorebp(d10 val,int32 ac,int32 pflgs)634 void incstorebp (d10 val, int32 ac, int32 pflgs)
635 {
636 a10 ba;
637 d10 bp, wd, mask;
638 int32 p, s;
639
640 bp = AC(ac) = incbp (AC(ac)); /* increment bp */
641 XT_INSRLOG (ac, rlog); /* log change */
642 p = GET_P (bp); /* get P and S */
643 s = GET_S (bp);
644 ba = calc_ea (bp, MM_EA_XDST); /* calc bp eff addr */
645 wd = Read (ba, MM_XDST); /* read, write test */
646 mask = bytemask[s] << p; /* shift mask, val */
647 val = val << p;
648 wd = (wd & ~mask) | (val & mask); /* insert byte */
649 Write (ba, wd & DMASK, MM_XDST);
650 return;
651 }
652
653 /* Translate byte
654
655 Arguments
656 by = byte to translate
657 tblad = virtual address of translation table
658 *xflgs = pointer to word containing translation flags
659 prv = previous mode flag for table lookup
660 Returns
661 xby = >= 0, translated byte
662 < 0, terminate translation
663 */
664
xlate(d10 by,a10 tblad,d10 * xflgs,int32 prv)665 d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 prv)
666 {
667 a10 ea;
668 int32 tcode;
669 d10 tblent;
670
671 ea = (tblad + ((int32) by >> 1)) & AMASK;
672 tblent = ((Read (ea, prv) >> ((by & 1)? 0: 18)) & RMASK);
673 tcode = XT_GETCODE (tblent); /* get xlate code */
674 switch (tcode) {
675
676 case 00:
677 return (*xflgs & XT_SFLG)? tblent: by;
678
679 case 01:
680 break;
681
682 case 02:
683 *xflgs = *xflgs & ~XT_MFLG;
684 return (*xflgs & XT_SFLG)? tblent: by;
685
686 case 03:
687 *xflgs = *xflgs | XT_MFLG;
688 return (*xflgs & XT_SFLG)? tblent: by;
689
690 case 04:
691 *xflgs = *xflgs | XT_SFLG | XT_NFLG;
692 return tblent;
693
694 case 05:
695 *xflgs = *xflgs | XT_NFLG;
696 break;
697
698 case 06:
699 *xflgs = (*xflgs | XT_SFLG | XT_NFLG) & ~XT_MFLG;
700 return tblent;
701
702 case 07:
703 *xflgs = *xflgs | XT_SFLG | XT_NFLG | XT_MFLG;
704 return tblent;
705 } /* end case */
706
707 return -1;
708 }
709
710 /* Fill out the destination string
711
712 Arguments:
713 fill = fill
714 ac = 2 word AC block (length, byte pointer)
715 cnt = fill count
716 pflgs = PXCT flags
717 */
718
filldst(d10 fill,int32 ac,d10 cnt,int32 pflgs)719 void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs)
720 {
721 int32 i, t;
722 int32 p1 = ADDA (ac, 1);
723
724 for (i = 0; i < cnt; i++) {
725 if (i && (t = test_int ()))
726 ABORT (t);
727 rlog = 0; /* clear log */
728 incstorebp (fill, p1, pflgs);
729 AC(ac) = (AC(ac) & XFLGMASK) | ((AC(ac) - 1) & XLNTMASK);
730 }
731 rlog = 0;
732 return;
733 }
734
735 /* Clean up after page fault
736
737 Arguments:
738 logv = register change log
739
740 For each register in logv, decrement the register's contents as
741 though it were a byte pointer. Note that the KS10 does <not>
742 do a full decrement calculation but merely adds S to P.
743 */
744
xtcln(int32 logv)745 void xtcln (int32 logv)
746 {
747 int32 p, reg;
748
749 while (logv) {
750 XT_REMRLOG (reg, logv); /* get next reg */
751 if ((reg >= 0) && (reg < AC_NUM)) {
752 p = GET_P (AC(reg)) + GET_S (AC(reg)); /* get p + s */
753 AC(reg) = PUT_P (AC(reg), p); /* p <- p + s */
754 }
755 }
756 return;
757 }
758