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