Remove explicit redundant extern declarations in source files that are defined in processor include files.
754 lines
31 KiB
C
754 lines
31 KiB
C
/* pdp10_xtnd.c: PDP-10 extended instruction simulator
|
|
|
|
Copyright (c) 1993-2016, 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.
|
|
|
|
05-Nov-16 RMS Fixed last digit error in CVTBDT (Pascal Parent)
|
|
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 INT64_C(0400000000000) /* L flag */
|
|
#define XT_SFLG INT64_C(0400000000000) /* S flag */
|
|
#define XT_NFLG INT64_C(0200000000000) /* N flag */
|
|
#define XT_MFLG INT64_C(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 INT64_C(0000777777777) /* length */
|
|
#define XFLGMASK INT64_C(0700000000000) /* flags */
|
|
#define XT_MBZ INT64_C(0777000000000) /* must be zero */
|
|
#define XT_MBZE INT64_C(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 INT64_C(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 int32 rlog;
|
|
|
|
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] = {
|
|
{ INT64_C(0), INT64_C(0),},
|
|
{ INT64_C(0), INT64_C(1),},
|
|
{ INT64_C(0), INT64_C(10),},
|
|
{ INT64_C(0), INT64_C(100),},
|
|
{ INT64_C(0), INT64_C(1000),},
|
|
{ INT64_C(0), INT64_C(10000),},
|
|
{ INT64_C(0), INT64_C(100000),},
|
|
{ INT64_C(0), INT64_C(1000000),},
|
|
{ INT64_C(0), INT64_C(10000000),},
|
|
{ INT64_C(0), INT64_C(100000000),},
|
|
{ INT64_C(0), INT64_C(1000000000),},
|
|
{ INT64_C(0), INT64_C(10000000000),},
|
|
{ INT64_C(2), INT64_C(31280523264),},
|
|
{ INT64_C(29), INT64_C(3567587328),},
|
|
{ INT64_C(291), INT64_C(1316134912),},
|
|
{ INT64_C(2910), INT64_C(13161349120),},
|
|
{ INT64_C(29103), INT64_C(28534276096),},
|
|
{ INT64_C(291038), INT64_C(10464854016),},
|
|
{ INT64_C(2910383), INT64_C(1569325056),},
|
|
{ INT64_C(29103830), INT64_C(15693250560),},
|
|
{ INT64_C(291038304), INT64_C(19493552128),},
|
|
{ INT64_C(2910383045), INT64_C(23136829440),},
|
|
{ INT64_C(29103830456), INT64_C(25209864192),},
|
|
};
|
|
|
|
int xtend (int32 ac, int32 ea, int32 pflgs)
|
|
{
|
|
d10 b1, b2, ppi;
|
|
d10 xinst, xoff = 0, digit, f1, f2, rs[2];
|
|
d10 xflgs = 0;
|
|
a10 e1 = 0, entad;
|
|
int32 p1 = ADDAC (ac, 1);
|
|
int32 p3 = ADDAC (ac, 3);
|
|
int32 p4 = ADDAC (ac, 4);
|
|
int32 flg, i, s2 = 0, 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) /* check length MBZ */
|
|
return XT_MUUO;
|
|
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)) /* src1 */
|
|
b1 = incloadbp (p1, pflgs);
|
|
else b1 = f1;
|
|
if (AC(p3)) /* src2 */
|
|
b2 = incloadbp (p4, pflgs);
|
|
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))) { /* get abs value */
|
|
DMOVN (rs);
|
|
}
|
|
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) /* put in range */
|
|
i = 22;
|
|
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) /* offset? */
|
|
digit = (digit + xoff) & DMASK;
|
|
else { /* translate */
|
|
f1 = Read (e1 + (int32) digit, MM_OPND);/* get xlation */
|
|
if ((i == 1) && (AC(p3) & XT_MFLG)) /* last digit, minus? */
|
|
f1 = f1 >> 18; /* use left */
|
|
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) /* !S? clr res */
|
|
AC(p3) = AC(p4) = 0;
|
|
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) /* test dst lnt MBZ */
|
|
return XT_MUUO;
|
|
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) /* sign extend 18b */
|
|
xoff = xoff | LMASK;
|
|
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;
|
|
} /* end case xop */
|
|
|
|
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) /* check pattern MBZ */
|
|
return XT_MUUO;
|
|
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 */
|
|
|
|
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;
|
|
}
|