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