First Commit of my working state
[simh.git] / PDP10 / pdp10_xtnd.c
CommitLineData
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
141extern d10 *ac_cur; /* current AC block */\r
142extern const d10 bytemask[64];\r
143extern int32 flags;\r
144extern int32 rlog;\r
145extern jmp_buf save_env;\r
146\r
147extern d10 Read (int32 ea, int32 prv);\r
148extern void Write (int32 ea, d10 val, int32 prv);\r
149extern a10 calc_ea (d10 inst, int32 prv);\r
150extern int32 test_int (void);\r
151d10 incbp (d10 bp);\r
152d10 incloadbp (int32 ac, int32 pflgs);\r
153void incstorebp (d10 val, int32 ac, int32 pflgs);\r
154d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 pflgs);\r
155void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs);\r
156\r
157static 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
183int xtend (int32 ac, int32 ea, int32 pflgs)\r
184{\r
185d10 b1, b2, ppi; \r
186d10 xinst, xoff, digit, f1, f2, rs[2];\r
187d10 xflgs = 0;\r
188a10 e1, entad;\r
189int32 p1 = ADDAC (ac, 1);\r
190int32 p3 = ADDAC (ac, 3);\r
191int32 p4 = ADDAC (ac, 4);\r
192int32 flg, i, s2, t, pp, pat, xop, xac, ret;\r
193\r
194xinst = Read (ea, MM_OPND); /* get extended instr */\r
195xop = GET_OP (xinst); /* get opcode */\r
196xac = GET_AC (xinst); /* get AC */\r
197if (xac || (xop == 0) || (xop > XT_MOVSRJ)) return XT_MUUO;\r
198rlog = 0; /* clear log */\r
199switch (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
551return XT_MUUO;\r
552}\r
553\r
554/* Supporting subroutines */\r
555\r
556/* Increment byte pointer, register version */\r
557\r
558d10 incbp (d10 bp)\r
559{\r
560int32 p, s;\r
561\r
562p = GET_P (bp); /* get P and S */\r
563s = GET_S (bp);\r
564p = p - s; /* adv P */\r
565if (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
569bp = PUT_P (bp, p); /* store new P */\r
570return bp;\r
571}\r
572\r
573/* Increment and load byte, extended version - uses register log */\r
574\r
575d10 incloadbp (int32 ac, int32 pflgs)\r
576{\r
577a10 ba;\r
578d10 bp, wd;\r
579int32 p, s;\r
580\r
581bp = AC(ac) = incbp (AC(ac)); /* increment bp */\r
582XT_INSRLOG (ac, rlog); /* log change */\r
583p = GET_P (bp); /* get P and S */\r
584s = GET_S (bp);\r
585ba = calc_ea (bp, MM_EA_XSRC); /* calc bp eff addr */\r
586wd = Read (ba, MM_XSRC); /* read word */\r
587wd = (wd >> p) & bytemask[s]; /* get byte */\r
588return wd;\r
589}\r
590\r
591/* Increment and deposit byte, extended version - uses register log */\r
592\r
593void incstorebp (d10 val, int32 ac, int32 pflgs)\r
594{\r
595a10 ba;\r
596d10 bp, wd, mask;\r
597int32 p, s;\r
598\r
599bp = AC(ac) = incbp (AC(ac)); /* increment bp */\r
600XT_INSRLOG (ac, rlog); /* log change */\r
601p = GET_P (bp); /* get P and S */\r
602s = GET_S (bp);\r
603ba = calc_ea (bp, MM_EA_XDST); /* calc bp eff addr */\r
604wd = Read (ba, MM_XDST); /* read, write test */\r
605mask = bytemask[s] << p; /* shift mask, val */\r
606val = val << p;\r
607wd = (wd & ~mask) | (val & mask); /* insert byte */\r
608Write (ba, wd & DMASK, MM_XDST);\r
609return;\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
624d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 prv)\r
625{\r
626a10 ea;\r
627int32 tcode;\r
628d10 tblent;\r
629\r
630ea = (tblad + ((int32) by >> 1)) & AMASK;\r
631tblent = ((Read (ea, prv) >> ((by & 1)? 0: 18)) & RMASK);\r
632tcode = XT_GETCODE (tblent); /* get xlate code */\r
633switch (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
666return -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
678void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs)\r
679{\r
680int32 i, t;\r
681int32 p1 = ADDA (ac, 1);\r
682\r
683for (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
689rlog = 0;\r
690return;\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
703void xtcln (int32 logv)\r
704{\r
705int32 p, reg;\r
706\r
707while (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
714return;\r
715}\r