RESTRICTION: The PDP-15 FPP is only partially debugged. Do NOT enable this feature for normal operations. WARNING: The core simulator files (scp.c, sim_*.c) have been reorganized. Unzip V3.2-0 to an empty directory before attempting to compile the source. IMPORTANT: If you are compiling for UNIX, please read the notes for Ethernet very carefully. You may need to download a new version of the pcap library, or make changes to the makefile, to get Ethernet support to work. 1. New Features in 3.2-0 1.1 SCP and libraries - Added SHOW <device> RADIX command. - Added SHOW <device> MODIFIERS command. - Added SHOW <device> NAMES command. - Added SET/SHOW <device> DEBUG command. - Added sim_vm_parse_addr and sim_vm_fprint_addr optional interfaces. - Added REG_VMAD flag. - Split SCP into separate libraries for easier modification. - Added more room to the device and unit flag fields. - Changed terminal multiplexor library to support unlimited. number of async lines. 1.2 All DECtapes - Added STOP_EOR flag to enable end-of-reel error stop - Added device debug support. 1.3 Nova and Eclipse - Added QTY and ALM multiplexors (Bruce Ray). 1.4 LGP-30 - Added LGP-30/LGP-21 simulator. 1.5 PDP-11 - Added format, address increment inhibit, transfer overrun detection to RK. - Added device debug support to HK, RP, TM, TQ, TS. - Added DEUNA/DELUA (XU) support (Dave Hittner). - Add DZ per-line logging. 1.6 18b PDP's - Added support for 1-4 (PDP-9)/1-16 (PDP-15) additional terminals. 1.7 PDP-10 - Added DEUNA/DELUA (XU) support (Dave Hittner). 1.8 VAX - Added extended memory to 512MB (Mark Pizzolato). - Added RXV21 support. 2. Bugs Fixed in 3.2-0 2.1 SCP - Fixed double logging of SHOW BREAK (found by Mark Pizzolato). - Fixed implementation of REG_VMIO. 2.2 Nova and Eclipse - Fixed device enable/disable support (found by Bruce Ray). 2.3 PDP-1 - Fixed bug in LOAD (found by Mark Crispin). 2.4 PDP-10 - Fixed bug in floating point unpack. - Fixed bug in FIXR (found by Phil Stone, fixed by Chris Smith). 2.6 PDP-11 - Fixed bug in RQ interrupt control (found by Tom Evans). 2.6 PDP-18B - Fixed bug in PDP-15 XVM g_mode implementation. - Fixed bug in PDP-15 indexed address calculation. - Fixed bug in PDP-15 autoindexed address calculation. - Fixed bugs in FPP-15 instruction decode. - Fixed clock response to CAF. - Fixed bug in hardware read-in mode bootstrap. - Fixed PDP-15 XVM instruction decoding errors. 2.7 VAX - Fixed PC read fault in EXTxV. - Fixed PC write fault in INSV.
642 lines
22 KiB
C
642 lines
22 KiB
C
/* pdp10_xtnd.c: PDP-10 extended instruction simulator
|
||
|
||
Copyright (c) 1993-2004, Robert M Supnik
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a
|
||
copy of this software and associated documentation files (the "Software"),
|
||
to deal in the Software without restriction, including without limitation
|
||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
and/or sell copies of the Software, and to permit persons to whom the
|
||
Software is furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||
in this Software without prior written authorization from Robert M Supnik.
|
||
|
||
12-May-01 RMS Fixed compiler warning in xlate
|
||
|
||
Instructions handled in this module:
|
||
MOVSLJ move string left justified
|
||
MOVSO move string offset
|
||
MOVST move string translated
|
||
MOVSRJ move string right justified
|
||
CMPSL compare string, skip on less
|
||
CMPSE compare string, skip on equal
|
||
CMPSLE compare string, skip on less or equal
|
||
CMPSGE compare string, skip on greater or equal
|
||
CMPSN compare string, skip on unequal
|
||
CMPSG compare string, skip on greater
|
||
CVTDBO convert decimal to binary offset
|
||
CVTDBT convert decimal to binary translated
|
||
CVTBDO convert binary to decimal offset
|
||
CVTBDT convert binary to decimal translated
|
||
EDIT edit
|
||
|
||
The PDP-10 extended instructions deal with non-binary data types,
|
||
particularly byte strings and decimal strings. (In the KL10, the
|
||
extended instructions include G floating support as well.) They
|
||
are very complicated microcoded subroutines that can potentially
|
||
run for a very long time. Accordingly, the instructions must test
|
||
for interrupts as well as page faults, and be prepared to restart
|
||
from either.
|
||
|
||
In general, the simulator attempts to keep the AC block up to date,
|
||
so that page fails and interrupts can be taken directly at any point.
|
||
If the AC block is not up to date, memory accessibility must be tested
|
||
before the actual read or write is done.
|
||
|
||
The extended instruction routine returns a status code as follows:
|
||
XT_NOSK no skip completion
|
||
XT_SKIP skip completion
|
||
XT_MUUO invalid extended instruction
|
||
*/
|
||
|
||
#include "pdp10_defs.h"
|
||
#include <setjmp.h>
|
||
|
||
#define MM_XSRC (pflgs & XSRC_PXCT)
|
||
#define MM_XDST (pflgs & XDST_PXCT)
|
||
#define MM_EA_XSRC ((pflgs & EA_PXCT) && MM_XSRC)
|
||
#define MM_EA_XDST ((pflgs & EA_PXCT) && MM_XDST)
|
||
|
||
#define XT_CMPSL 001 /* opcodes */
|
||
#define XT_CMPSE 002
|
||
#define XT_CMPSLE 003
|
||
#define XT_EDIT 004
|
||
#define XT_CMPSGE 005
|
||
#define XT_CMPSN 006
|
||
#define XT_CMPSG 007
|
||
#define XT_CVTDBO 010
|
||
#define XT_CVTDBT 011
|
||
#define XT_CVTBDO 012
|
||
#define XT_CVTBDT 013
|
||
#define XT_MOVSO 014
|
||
#define XT_MOVST 015
|
||
#define XT_MOVSLJ 016
|
||
#define XT_MOVSRJ 017
|
||
|
||
/* Translation control */
|
||
|
||
#define XT_LFLG 0400000000000 /* L flag */
|
||
#define XT_SFLG 0400000000000 /* S flag */
|
||
#define XT_NFLG 0200000000000 /* N flag */
|
||
#define XT_MFLG 0100000000000 /* M flag */
|
||
|
||
/* Translation table */
|
||
|
||
#define XT_V_CODE 15 /* translation op */
|
||
#define XT_M_CODE 07
|
||
#define XT_BYMASK 07777 /* byte mask */
|
||
#define XT_DGMASK 017 /* digit mask */
|
||
#define XT_GETCODE(x) ((int32) (((x) >> XT_V_CODE) & XT_M_CODE))
|
||
|
||
/* AC masks */
|
||
|
||
#define XLNTMASK 0000777777777 /* length */
|
||
#define XFLGMASK 0700000000000 /* flags */
|
||
#define XT_MBZ 0777000000000 /* must be zero */
|
||
#define XT_MBZE 0047777000000 /* must be zero, edit */
|
||
|
||
/* Register change log */
|
||
|
||
#define XT_N_RLOG 5 /* entry width */
|
||
#define XT_M_RLOG ((1 << XT_N_RLOG) - 1) /* entry mask */
|
||
#define XT_O_RLOG 1 /* entry offset */
|
||
#define XT_INSRLOG(x,v) v = ((v << XT_N_RLOG) | (((x) + XT_O_RLOG) & XT_M_RLOG))
|
||
#define XT_REMRLOG(x,v) x = (v & XT_M_RLOG) - XT_O_RLOG; \
|
||
v = v >> XT_N_RLOG
|
||
|
||
/* Edit */
|
||
|
||
#define ED_V_PBYN 30 /* pattern byte # */
|
||
#define ED_M_PBYN 03
|
||
#define ED_PBYNO 0040000000000 /* overflow bit */
|
||
#define ED_GETPBYN(x) ((int32) (((x) >> ED_V_PBYN) & ED_M_PBYN))
|
||
#define ED_V_POPC 6 /* pattern byte opcode */
|
||
#define ED_M_PAT 0777 /* pattern byte mask */
|
||
#define ED_M_NUM 0077 /* number for msg, etc */
|
||
#define ED_PBYTE(x,y) ((int32) (((x) >> (27 - (ED_GETPBYN (y) * 9))) & ED_M_PAT))
|
||
#define ED_STOP 0000 /* stop */
|
||
#define ED_SELECT 0001 /* select source */
|
||
#define ED_SIGST 0002 /* start significance */
|
||
#define ED_FLDSEP 0003 /* field separator */
|
||
#define ED_EXCHMD 0004 /* exchange mark, dst */
|
||
#define ED_MESSAG 0100 /* message */
|
||
#define ED_SKPM 0500 /* skip if M */
|
||
#define ED_SKPN 0600 /* skip if N */
|
||
#define ED_SKPA 0700 /* skip always */
|
||
|
||
extern d10 *ac_cur; /* current AC block */
|
||
extern d10 bytemask[64];
|
||
extern int32 flags;
|
||
extern int32 rlog;
|
||
extern jmp_buf save_env;
|
||
|
||
extern d10 Read (int32 ea, int32 prv);
|
||
extern void Write (int32 ea, d10 val, int32 prv);
|
||
extern a10 calc_ea (d10 inst, int32 prv);
|
||
extern int32 test_int (void);
|
||
d10 incbp (d10 bp);
|
||
d10 incloadbp (int32 ac, int32 pflgs);
|
||
void incstorebp (d10 val, int32 ac, int32 pflgs);
|
||
d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 pflgs);
|
||
void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs);
|
||
|
||
static const d10 pwrs10[23][2] = {
|
||
0, 0,
|
||
0, 1,
|
||
0, 10,
|
||
0, 100,
|
||
0, 1000,
|
||
0, 10000,
|
||
0, 100000,
|
||
0, 1000000,
|
||
0, 10000000,
|
||
0, 100000000,
|
||
0, 1000000000,
|
||
0, 10000000000,
|
||
2, 31280523264,
|
||
29, 3567587328,
|
||
291, 1316134912,
|
||
2910, 13161349120,
|
||
29103, 28534276096,
|
||
291038, 10464854016,
|
||
2910383, 1569325056,
|
||
29103830, 15693250560,
|
||
291038304, 19493552128,
|
||
2910383045, 23136829440,
|
||
29103830456, 25209864192 };
|
||
|
||
int xtend (int32 ac, int32 ea, int32 pflgs)
|
||
{
|
||
d10 b1, b2, ppi;
|
||
d10 xinst, xoff, digit, f1, f2, rs[2];
|
||
d10 xflgs = 0;
|
||
a10 e1, entad;
|
||
int32 p1 = ADDAC (ac, 1);
|
||
int32 p3 = ADDAC (ac, 3);
|
||
int32 p4 = ADDAC (ac, 4);
|
||
int32 flg, i, s2, t, pp, pat, xop, xac, ret;
|
||
|
||
xinst = Read (ea, MM_OPND); /* get extended instr */
|
||
xop = GET_OP (xinst); /* get opcode */
|
||
xac = GET_AC (xinst); /* get AC */
|
||
if (xac || (xop == 0) || (xop > XT_MOVSRJ)) return XT_MUUO;
|
||
rlog = 0; /* clear log */
|
||
switch (xop) { /* case on opcode */
|
||
|
||
/* String compares - checked against KS10 ucode
|
||
If both strings are zero length, they are considered equal.
|
||
Both source and destination lengths are MBZ checked.
|
||
|
||
AC = source1 length
|
||
AC + 1 = source1 byte pointer
|
||
AC + 3 = source2 length
|
||
AC + 4 = source2 byte pointer
|
||
*/
|
||
|
||
case XT_CMPSL: /* CMPSL */
|
||
case XT_CMPSE: /* CMPSE */
|
||
case XT_CMPSLE: /* CMPSLE */
|
||
case XT_CMPSGE: /* CMPSGE */
|
||
case XT_CMPSN: /* CMPSN */
|
||
case XT_CMPSG: /* CMPSG */
|
||
if ((AC(ac) | AC(p3)) & XT_MBZ) return XT_MUUO; /* check length MBZ */
|
||
f1 = Read (ADDA (ea, 1), MM_OPND) & bytemask[GET_S (AC(p1))];
|
||
f2 = Read (ADDA (ea, 2), MM_OPND) & bytemask[GET_S (AC(p4))];
|
||
b1 = b2 = 0;
|
||
for (flg = 0; (AC(ac) | AC(p3)) && (b1 == b2); flg++) {
|
||
if (flg && (t = test_int ())) ABORT (t);
|
||
rlog = 0; /* clear log */
|
||
if (AC(ac)) b1 = incloadbp (p1, pflgs); /* src1 */
|
||
else b1 = f1;
|
||
if (AC(p3)) b2 = incloadbp (p4, pflgs); /* src2 */
|
||
else b2 = f2;
|
||
if (AC(ac)) AC(ac) = (AC(ac) - 1) & XLNTMASK;
|
||
if (AC(p3)) AC(p3) = (AC(p3) - 1) & XLNTMASK; }
|
||
switch (xop) {
|
||
case XT_CMPSL: return (b1 < b2)? XT_SKIP: XT_NOSK;
|
||
case XT_CMPSE: return (b1 == b2)? XT_SKIP: XT_NOSK;
|
||
case XT_CMPSLE: return (b1 <= b2)? XT_SKIP: XT_NOSK;
|
||
case XT_CMPSGE: return (b1 >= b2)? XT_SKIP: XT_NOSK;
|
||
case XT_CMPSN: return (b1 != b2)? XT_SKIP: XT_NOSK;
|
||
case XT_CMPSG: return (b1 > b2)? XT_SKIP: XT_NOSK; }
|
||
return XT_MUUO;
|
||
|
||
/* Convert binary to decimal instructions - checked against KS10 ucode
|
||
There are no MBZ tests.
|
||
|
||
AC'AC + 1 = double precision integer source
|
||
AC + 3 = flags and destination length
|
||
AC + 4 = destination byte pointer
|
||
*/
|
||
|
||
case XT_CVTBDO: /* CVTBDO */
|
||
case XT_CVTBDT: /* CVTBDT */
|
||
e1 = calc_ea (xinst, MM_EA); /* get ext inst addr */
|
||
if (xop == XT_CVTBDO) /* offset? */
|
||
xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */
|
||
rs[0] = AC(ac); /* get src opnd */
|
||
rs[1] = CLRS (AC(p1));
|
||
if (!TSTF (F_FPD)) { /* set up done yet? */
|
||
if (TSTS (AC(ac))) { DMOVN (rs); } /* get abs value */
|
||
for (i = 22; i > 1; i--) { /* find field width */
|
||
if (DCMPGE (rs, pwrs10[i])) break; }
|
||
if (i > (AC(p3) & XLNTMASK)) return XT_NOSK;
|
||
if ((i < (AC(p3) & XLNTMASK)) && (AC(p3) & XT_LFLG)) {
|
||
f1 = Read (ADDA (ea, 1), MM_OPND);
|
||
filldst (f1, p3, (AC(p3) & XLNTMASK) - i, pflgs); }
|
||
else AC(p3) = (AC(p3) & XFLGMASK) | i;
|
||
if (TSTS (AC(ac))) AC(p3) = AC(p3) | XT_MFLG;
|
||
if (AC(ac) | AC(p1)) AC(p3) = AC(p3) | XT_NFLG;
|
||
AC(ac) = rs[0]; /* update state */
|
||
AC(p1) = rs[1];
|
||
SETF (F_FPD); } /* mark set up done */
|
||
|
||
/* Now do actual binary to decimal conversion */
|
||
|
||
for (flg = 0; AC(p3) & XLNTMASK; flg++) {
|
||
if (flg && (t = test_int ())) ABORT (t);
|
||
rlog = 0; /* clear log */
|
||
i = (int32) AC(p3) & XLNTMASK; /* get length */
|
||
if (i > 22) i = 22; /* put in range */
|
||
for (digit = 0; (digit < 10) && DCMPGE (rs, pwrs10[i]); digit++) {
|
||
rs[0] = rs[0] - pwrs10[i][0] - (rs[1] < pwrs10[i][1]);
|
||
rs[1] = (rs[1] - pwrs10[i][1]) & MMASK; }
|
||
if (xop == XT_CVTBDO) digit = (digit + xoff) & DMASK;
|
||
else {
|
||
f1 = Read (e1 + (int32) digit, MM_OPND);
|
||
if ((i == 1) && (AC(p3) & XT_LFLG)) f1 = f1 >> 18;
|
||
digit = f1 & RMASK; }
|
||
incstorebp (digit, p4, pflgs); /* store digit */
|
||
AC(ac) = rs[0]; /* mem access ok */
|
||
AC(p1) = rs[1]; /* update state */
|
||
AC(p3) = (AC(p3) & XFLGMASK) | ((AC(p3) - 1) & XLNTMASK); }
|
||
CLRF (F_FPD); /* clear FPD */
|
||
return XT_SKIP;
|
||
|
||
/* Convert decimal to binary instructions - checked against KS10 ucode
|
||
There are no MBZ tests.
|
||
|
||
AC = flags and source length
|
||
AC + 1 = source byte pointer
|
||
AC + 3'AC + 4 = double precision integer result
|
||
*/
|
||
|
||
case XT_CVTDBT: /* CVTDBT */
|
||
case XT_CVTDBO: /* CVTDBO */
|
||
e1 = calc_ea (xinst, MM_EA); /* get ext inst addr */
|
||
if ((AC(ac) & XT_SFLG) == 0) AC(p3) = AC(p4) = 0; /* !S? clr res */
|
||
else AC(p4) = CLRS (AC(p4)); /* clear low sign */
|
||
if (xop == XT_CVTDBO) { /* offset? */
|
||
xoff = (e1 & RSIGN)? (e1 | LMASK): e1; /* get offset */
|
||
AC(ac) = AC(ac) | XT_SFLG; } /* set S flag */
|
||
xflgs = AC(ac) & XFLGMASK; /* get xlation flags */
|
||
for (flg = 0; AC(ac) & XLNTMASK; flg++) {
|
||
if (flg && (t = test_int ())) ABORT (t);
|
||
rlog = 0; /* clear log */
|
||
b1 = incloadbp (p1, pflgs); /* get byte */
|
||
if (xop == XT_CVTDBO) b1 = (b1 + xoff) & DMASK;
|
||
else {
|
||
b1 = xlate (b1, e1, &xflgs, MM_OPND);
|
||
if (b1 < 0) { /* terminated? */
|
||
AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
|
||
if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4));
|
||
return XT_NOSK; }
|
||
if (xflgs & XT_SFLG) b1 = b1 & XT_DGMASK;
|
||
else b1 = 0; }
|
||
AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
|
||
if ((b1 < 0) || (b1 > 9)) { /* bad digit? done */
|
||
if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4));
|
||
return XT_NOSK; }
|
||
AC(p4) = (AC(p4) * 10) + b1; /* base * 10 + digit */
|
||
AC(p3) = ((AC(p3) * 10) + (AC(p4) >> 35)) & DMASK;
|
||
AC(p4) = AC(p4) & MMASK; }
|
||
if (AC(ac) & XT_MFLG) {
|
||
AC(p4) = -AC(p4) & MMASK;
|
||
AC(p3) = (~AC(p3) + (AC(p4) == 0)) & DMASK; }
|
||
if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4));
|
||
return XT_SKIP;
|
||
|
||
/* String move instructions - checked against KS10 ucode
|
||
Only the destination length is MBZ checked.
|
||
|
||
AC = flags (MOVST only) and source length
|
||
AC + 1 = source byte pointer
|
||
AC + 3 = destination length
|
||
AC + 4 = destination byte pointer
|
||
*/
|
||
|
||
case XT_MOVSO: /* MOVSO */
|
||
case XT_MOVST: /* MOVST */
|
||
case XT_MOVSRJ: /* MOVSRJ */
|
||
case XT_MOVSLJ: /* MOVSLJ */
|
||
if (AC(p3) & XT_MBZ) return XT_MUUO; /* test dst lnt MBZ */
|
||
f1 = Read (ADDA (ea, 1), MM_OPND); /* get fill */
|
||
switch (xop) { /* case on instr */
|
||
case XT_MOVSO: /* MOVSO */
|
||
AC(ac) = AC(ac) & XLNTMASK; /* trim src length */
|
||
xoff = calc_ea (xinst, MM_EA); /* get offset */
|
||
if (xoff & RSIGN) xoff = xoff | LMASK; /* sign extend 18b */
|
||
s2 = GET_S (AC(p4)); /* get dst byte size */
|
||
break;
|
||
case XT_MOVST: /* MOVST */
|
||
e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */
|
||
break;
|
||
case XT_MOVSRJ: /* MOVSRJ */
|
||
AC(ac) = AC(ac) & XLNTMASK; /* trim src length */
|
||
if (AC(p3) == 0) return (AC(ac)? XT_NOSK: XT_SKIP);
|
||
if (AC(ac) > AC(p3)) { /* adv src ptr */
|
||
for (flg = 0; AC(ac) > AC(p3); flg++) {
|
||
if (flg && (t = test_int ())) ABORT (t);
|
||
AC(p1) = incbp (AC(p1));
|
||
AC(ac) = (AC(ac) - 1) & XLNTMASK; } }
|
||
else if (AC(ac) < AC(p3))
|
||
filldst (f1, p3, AC(p3) - AC(ac), pflgs);
|
||
break;
|
||
case XT_MOVSLJ: /* MOVSLJ */
|
||
AC(ac) = AC(ac) & XLNTMASK; /* trim src length */
|
||
break; }
|
||
|
||
xflgs = AC(ac) & XFLGMASK; /* get xlation flags */
|
||
if (AC(p3) == 0) return (AC(ac)? XT_NOSK: XT_SKIP);
|
||
for (flg = 0; AC(p3) & XLNTMASK; flg++) {
|
||
if (flg && (t = test_int ())) ABORT (t);
|
||
rlog = 0; /* clear log */
|
||
if (AC(ac) & XLNTMASK) { /* any source? */
|
||
b1 = incloadbp (p1, pflgs); /* src byte */
|
||
if (xop == XT_MOVSO) { /* offset? */
|
||
b1 = (b1 + xoff) & DMASK; /* test fit */
|
||
if (b1 & ~bytemask[s2]) {
|
||
AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
|
||
return XT_NOSK; } }
|
||
else if (xop == XT_MOVST) { /* translate? */
|
||
b1 = xlate (b1, e1, &xflgs, MM_OPND);
|
||
if (b1 < 0) { /* upd flags in AC */
|
||
AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
|
||
return XT_NOSK; }
|
||
if (xflgs & XT_SFLG) b1 = b1 & XT_BYMASK;
|
||
else b1 = -1; } }
|
||
else b1 = f1;
|
||
if (b1 >= 0) { /* valid byte? */
|
||
incstorebp (b1, p4, pflgs); /* store byte */
|
||
AC(p3) = (AC(p3) - 1) & XLNTMASK; } /* update state */
|
||
if (AC(ac) & XLNTMASK) AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK); }
|
||
return (AC(ac) & XLNTMASK)? XT_NOSK: XT_SKIP;
|
||
|
||
/* Edit - checked against KS10 ucode
|
||
Only the flags/pattern pointer word is MBZ checked.
|
||
|
||
AC = flags, pattern pointer
|
||
AC + 1 = source byte pointer
|
||
AC + 3 = mark address
|
||
AC + 4 = destination byte pointer
|
||
*/
|
||
|
||
case XT_EDIT: /* EDIT */
|
||
if (AC(ac) & XT_MBZE) return XT_MUUO; /* check pattern MBZ */
|
||
xflgs = AC(ac) & XFLGMASK; /* get xlation flags */
|
||
e1 = calc_ea (xinst, MM_EA); /* get xlate tbl addr */
|
||
for (ppi = 1, ret = -1, flg = 0; ret < 0; flg++, ppi = 1) {
|
||
if (flg && (t = test_int ())) ABORT (t);
|
||
rlog = 0; /* clear log */
|
||
pp = (int32) AC(ac) & AMASK; /* get pattern ptr */
|
||
b1 = Read (pp, MM_OPND); /* get pattern word */
|
||
pat = ED_PBYTE (b1, AC(ac)); /* get pattern byte */
|
||
switch ((pat < 0100)? pat: ((pat >> ED_V_POPC) + 0100)) {
|
||
case ED_STOP: /* stop */
|
||
ret = XT_SKIP; /* exit loop */
|
||
break;
|
||
case ED_SELECT: /* select source */
|
||
b1 = incloadbp (p1, pflgs); /* get src */
|
||
entad = (e1 + ((int32) b1 >> 1)) & AMASK;
|
||
f1 = ((Read (entad, MM_OPND) >> ((b1 & 1)? 0: 18)) & RMASK);
|
||
i = XT_GETCODE (f1);
|
||
if (i & 2) xflgs =
|
||
(i & 1)? xflgs | XT_MFLG: xflgs & ~XT_MFLG;
|
||
switch (i) {
|
||
case 00: case 02: case 03:
|
||
if (xflgs & XT_SFLG) f1 = f1 & XT_BYMASK;
|
||
else {
|
||
f1 = Read (INCA (ea), MM_OPND);
|
||
if (f1 == 0) break; }
|
||
incstorebp (f1, p4, pflgs);
|
||
break;
|
||
case 01:
|
||
ret = XT_NOSK; /* exit loop */
|
||
break;
|
||
case 04: case 06: case 07:
|
||
xflgs = xflgs | XT_NFLG;
|
||
f1 = f1 & XT_BYMASK;
|
||
if ((xflgs & XT_SFLG) == 0) {
|
||
f2 = Read (ADDA (ea, 2), MM_OPND);
|
||
Write ((a10) AC(p3), AC(p4), MM_OPND);
|
||
if (f2) incstorebp (f2, p4, pflgs);
|
||
xflgs = xflgs | XT_SFLG; }
|
||
incstorebp (f1, p4, pflgs);
|
||
break;
|
||
case 05:
|
||
xflgs = xflgs | XT_NFLG;
|
||
ret = XT_NOSK; /* exit loop */
|
||
break; } /* end case xlate op */
|
||
break;
|
||
case ED_SIGST: /* start significance */
|
||
if ((xflgs & XT_SFLG) == 0) {
|
||
f2 = Read (ADDA (ea, 2), MM_OPND);
|
||
Write ((a10) AC(p3), AC(p4), MM_OPND);
|
||
if (f2) incstorebp (f2, p4, pflgs);
|
||
xflgs = xflgs | XT_SFLG; }
|
||
break;
|
||
case ED_FLDSEP: /* separate fields */
|
||
xflgs = 0;
|
||
break;
|
||
case ED_EXCHMD: /* exchange */
|
||
f2 = Read ((int32) (AC(p3) & AMASK), MM_OPND);
|
||
Write ((int32) (AC(p3) & AMASK), AC(p4), MM_OPND);
|
||
AC(p4) = f2;
|
||
break;
|
||
case (0100 + (ED_MESSAG >> ED_V_POPC)): /* message */
|
||
if (xflgs & XT_SFLG)
|
||
f1 = Read (ea + (pat & ED_M_NUM) + 1, MM_OPND);
|
||
else {
|
||
f1 = Read (ea + 1, MM_OPND);
|
||
if (f1 == 0) break; }
|
||
incstorebp (f1, p4, pflgs);
|
||
break;
|
||
case (0100 + (ED_SKPM >> ED_V_POPC)): /* skip on M */
|
||
if (xflgs & XT_MFLG) ppi = (pat & ED_M_NUM) + 2;
|
||
break;
|
||
case (0100 + (ED_SKPN >> ED_V_POPC)): /* skip on N */
|
||
if (xflgs & XT_NFLG) ppi = (pat & ED_M_NUM) + 2;
|
||
break;
|
||
case (0100 + (ED_SKPA >> ED_V_POPC)): /* skip always */
|
||
ppi = (pat & ED_M_NUM) + 2;
|
||
break;
|
||
default: /* NOP or undefined */
|
||
break; } /* end case pttrn op */
|
||
AC(ac) = AC(ac) + ((ppi & ED_M_PBYN) << ED_V_PBYN);
|
||
AC(ac) = AC(ac) + (ppi >> 2) + ((AC(ac) & ED_PBYNO)? 1: 0);
|
||
AC(ac) = xflgs | (AC(ac) & ~(XT_MBZE | XFLGMASK)); }
|
||
return ret; } /* end case xop */
|
||
return XT_MUUO;
|
||
}
|
||
|
||
/* Supporting subroutines */
|
||
|
||
/* Increment byte pointer, register version */
|
||
|
||
d10 incbp (d10 bp)
|
||
{
|
||
int32 p, s;
|
||
|
||
p = GET_P (bp); /* get P and S */
|
||
s = GET_S (bp);
|
||
p = p - s; /* adv P */
|
||
if (p < 0) { /* end of word? */
|
||
bp = (bp & LMASK) | (INCR (bp)); /* increment addr */
|
||
p = (36 - s) & 077; } /* reset P */
|
||
bp = PUT_P (bp, p); /* store new P */
|
||
return bp;
|
||
}
|
||
|
||
/* Increment and load byte, extended version - uses register log */
|
||
|
||
d10 incloadbp (int32 ac, int32 pflgs)
|
||
{
|
||
a10 ba;
|
||
d10 bp, wd;
|
||
int32 p, s;
|
||
|
||
bp = AC(ac) = incbp (AC(ac)); /* increment bp */
|
||
XT_INSRLOG (ac, rlog); /* log change */
|
||
p = GET_P (bp); /* get P and S */
|
||
s = GET_S (bp);
|
||
ba = calc_ea (bp, MM_EA_XSRC); /* calc bp eff addr */
|
||
wd = Read (ba, MM_XSRC); /* read word */
|
||
wd = (wd >> p) & bytemask[s]; /* get byte */
|
||
return wd;
|
||
}
|
||
|
||
/* Increment and deposit byte, extended version - uses register log */
|
||
|
||
void incstorebp (d10 val, int32 ac, int32 pflgs)
|
||
{
|
||
a10 ba;
|
||
d10 bp, wd, mask;
|
||
int32 p, s;
|
||
|
||
bp = AC(ac) = incbp (AC(ac)); /* increment bp */
|
||
XT_INSRLOG (ac, rlog); /* log change */
|
||
p = GET_P (bp); /* get P and S */
|
||
s = GET_S (bp);
|
||
ba = calc_ea (bp, MM_EA_XDST); /* calc bp eff addr */
|
||
wd = Read (ba, MM_XDST); /* read, write test */
|
||
mask = bytemask[s] << p; /* shift mask, val */
|
||
val = val << p;
|
||
wd = (wd & ~mask) | (val & mask); /* insert byte */
|
||
Write (ba, wd & DMASK, MM_XDST);
|
||
return;
|
||
}
|
||
|
||
/* Translate byte
|
||
|
||
Arguments
|
||
by = byte to translate
|
||
tblad = virtual address of translation table
|
||
*xflgs = pointer to word containing translation flags
|
||
prv = previous mode flag for table lookup
|
||
Returns
|
||
xby = >= 0, translated byte
|
||
< 0, terminate translation
|
||
*/
|
||
|
||
d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 prv)
|
||
{
|
||
a10 ea;
|
||
int32 tcode;
|
||
d10 tblent;
|
||
|
||
ea = (tblad + ((int32) by >> 1)) & AMASK;
|
||
tblent = ((Read (ea, prv) >> ((by & 1)? 0: 18)) & RMASK);
|
||
tcode = XT_GETCODE (tblent); /* get xlate code */
|
||
switch (tcode) {
|
||
case 00:
|
||
return (*xflgs & XT_SFLG)? tblent: by;
|
||
case 01:
|
||
break;
|
||
case 02:
|
||
*xflgs = *xflgs & ~XT_MFLG;
|
||
return (*xflgs & XT_SFLG)? tblent: by;
|
||
case 03:
|
||
*xflgs = *xflgs | XT_MFLG;
|
||
return (*xflgs & XT_SFLG)? tblent: by;
|
||
case 04:
|
||
*xflgs = *xflgs | XT_SFLG | XT_NFLG;
|
||
return tblent;
|
||
case 05:
|
||
*xflgs = *xflgs | XT_NFLG;
|
||
break;
|
||
case 06:
|
||
*xflgs = (*xflgs | XT_SFLG | XT_NFLG) & ~XT_MFLG;
|
||
return tblent;
|
||
case 07:
|
||
*xflgs = *xflgs | XT_SFLG | XT_NFLG | XT_MFLG;
|
||
return tblent; } /* end case xlate code */
|
||
return -1;
|
||
}
|
||
|
||
/* Fill out the destination string
|
||
|
||
Arguments:
|
||
fill = fill
|
||
ac = 2 word AC block (length, byte pointer)
|
||
cnt = fill count
|
||
pflgs = PXCT flags
|
||
*/
|
||
|
||
void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs)
|
||
{
|
||
int32 i, t;
|
||
int32 p1 = ADDA (ac, 1);
|
||
|
||
for (i = 0; i < cnt; i++) {
|
||
if (i && (t = test_int ())) ABORT (t);
|
||
rlog = 0; /* clear log */
|
||
incstorebp (fill, p1, pflgs);
|
||
AC(ac) = (AC(ac) & XFLGMASK) | ((AC(ac) - 1) & XLNTMASK); }
|
||
rlog = 0;
|
||
return;
|
||
}
|
||
|
||
/* Clean up after page fault
|
||
|
||
Arguments:
|
||
logv = register change log
|
||
|
||
For each register in logv, decrement the register's contents as
|
||
though it were a byte pointer. Note that the KS10 does <not>
|
||
do a full decrement calculation but merely adds S to P.
|
||
*/
|
||
|
||
void xtcln (int32 logv)
|
||
{
|
||
int32 p, reg;
|
||
|
||
while (logv) {
|
||
XT_REMRLOG (reg, logv); /* get next reg */
|
||
if ((reg >= 0) && (reg < AC_NUM)) {
|
||
p = GET_P (AC(reg)) + GET_S (AC(reg)); /* get p + s */
|
||
AC(reg) = PUT_P (AC(reg), p); } /* p <- p + s */
|
||
}
|
||
return;
|
||
}
|