simh-testsetgenerator/ND100/nd100_sys.c
Anders Magnusson 5cda68abce ND100: MMS-1 support (Memory Management 1) + other fixes for Nord-100.
Can now boot the last test programs from floppy, and runs INSTRUCTION-C
and PAGING-C without errors.
2023-05-18 16:53:06 -04:00

358 lines
14 KiB
C

/*
* Copyright (c) 2023 Anders Magnusson.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "sim_defs.h"
#include "nd100_defs.h"
char sim_name[] = "ND100";
extern REG cpu_reg[];
REG *sim_PC = &cpu_reg[8];
int32 sim_emax = 1;
DEVICE *sim_devices[] = {
&cpu_dev,
&mm_dev,
&tti_dev,
&tto_dev,
&floppy_dev,
&clk_dev,
NULL
};
const char *sim_stop_messages[SCPE_BASE] = {
"Unknown error",
"Unhandled IOX address",
"Unknown instruction",
"Checksum error",
"Simulator breakpoint",
"Wait at level 0",
"manual end",
};
static int mlp;
static int
gb(FILE *f)
{
int w;
if (f == NULL)
return prdmem(mlp++, PM_CPU);
w = getc(f) & 0377;
return w;
}
static int
gw(FILE *f)
{
int c = gb(f);
return (c << 8) | gb(f);
}
/*
* Bootable (BPUN) tape format.
* Disks can use it as well with a max of 64 words data. In this case
* the bytes are stored in the LSB of the words from beginning of disk.
* 1kw block should be read at address 0 in memory.
*
* A bootable tape consists of nine segments, named A-I.
*
* A - Any chars not including '!'
* B - (optional) octal number terminated by CR (LF ignored).
* C - (optional) octal number terminated by '!'.
* D - A '!' delimeter
* E - Block start address (in memory), two byte, MSB first.
* F - Word count in G section, two byte, MSB first.
* G - Words as counted in F section.
* H - Checksum of G section, one word.
* I - Action code. If non-zero, start at address in B, otherwise nothing.
*/
t_stat
sim_load(FILE *f, CONST char *buf, CONST char *fnam, t_bool flag)
{
int B, C, E, F, H, I;
int w, i, rv;
uint16 s;
rv = SCPE_OK;
if (sim_switches & SWMASK('D')) { /* read file from disk */
mlp = 0;
for (i = 0; i < 1024; i++) {
/* images have MSB first */
s = (getc(f) & 0377) << 8;
s |= getc(f) & 0377;
pwrmem(i, s, PM_CPU);
}
f = NULL;
}
/* read B/C section */
for (B = C = 0;(w = gb(f) & 0177) != '!'; ) {
switch (w) {
case '\n':
continue;
case '\r':
B = C, C = 0;
break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
C = (C << 3) | (w - '0');
break;
default:
B = C = 0;
}
}
printf("B address %06o\n", B);
printf("C address %06o\n", C);
regP = B;
printf("Load address %06o\n", E = gw(f));
printf("Word count %06o\n", F = gw(f));
for (i = s = 0; i < F; i++) {
pwrmem(E+i, gw(f), PM_CPU);
s += prdmem(E+i, PM_CPU);
}
printf("Checksum %06o\n", H = gw(f));
if (H != s)
rv = STOP_CKSUM;
printf("Execute %06o\n", I = gw(f));
printf("Words read %06o\n", i);
ald = 0300; /* from tape reader */
return rv;
}
static char *nd_mem[] = {
"stz", "sta", "stt", "stx", "std", "ldd", "stf", "ldf",
"min", "lda", "ldt", "ldx", "add", "sub", "and", "ora",
"fad", "fsb", "fmu", "fdv", "mpy", "jmp", "cjp", "jpl",
"skp", "rop", "mis", "sht", "N/A", "iox", "arg", "bop"
};
static char *jptab[] =
{ "jap", "jan", "jaz", "jaf", "jpc", "jnc", "jxz", "jxn" };
static char *argtab[] =
{ "sab", "saa", "sat", "sax", "aab", "aaa", "aat", "aax" };
static char *boptab[] = {
"bset zro", "bset one", "bset bcm", "bset bac",
"bskp zro", "bskp one", "bskp bcm", "bskp bac",
"bstc", "bsta", "bldc", "blda", "banc", "band", "borc", "bora",
};
static char *dactab[] = { "", "d", "p", "b", "l", "a", "t", "x" };
static char *skptab[] = {
"eql", "geq", "gre", "mgre", "ueq", "lss", "lst", "mlst"
};
static char *tratab[] = {
"pans", "sts", "opr", "pgs", "pvl", "iic", "pid", "pie",
"csr", "actl", "ald", "pes", "pcs14", "pea", "err16", "err17"
};
static char *trrtab[] = {
"panc", "sts", "lmp", "pcr", "err04", "iie", "pid", "pie",
"cclr", "lcil", "ucil", "err13", "err14", "eccr", "err16", "err17"
};
static char *mitab[] = {
"ldatx", "ldxtx", "lddtx", "ldbtx", "statx", "stztx", "stdtx", "ERR"
};
t_stat
fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
{
int ins, op, off;
if (!(sw & SWMASK ('M')))
return SCPE_ARG;
op = val[0];
ins = op & ND_MEMMSK;
off = SEXT8(op);
#define R(x) ((x) & 0177777)
fprintf(of, "%06o\t", op);
if (ins < ND_CJP || ins == ND_JPL) {
/* MEMORY REFERENCE INSTRUCTIONS */
fprintf(of, "%s ", nd_mem[ins >> ND_MEMSH]);
switch ((op >> 8) & 07) {
case 0:
fprintf(of, "0%o", R(off + addr));
break;
case 1:
fprintf(of, "B+0%o", R(off));
break;
case 2:
fprintf(of, "(0%o)", R(off + addr));
break;
case 3:
fprintf(of, "(B+0%o)", R(off));
break;
case 4:
fprintf(of, "0%o+X", R(off));
break;
case 5:
fprintf(of, "B+0%o+X", R(off));
break;
case 6:
fprintf(of, "(0%o)+X", R(off + addr));
break;
case 7:
fprintf(of, "(B+0%o)+X", R(off));
break;
}
#undef R
} else if (ins == ND_CJP) {
fprintf(of, "%s 0%o", jptab[(op & ND_CJPMSK) >> ND_CJPSH],
off + addr);
} else if (ins == ND_IOX) {
fprintf(of, "iox 0%04o", op & ND_IOXMSK);
} else if (ins == ND_ARG) {
fprintf(of, "%s 0%o", argtab[(op & ND_CJPMSK) >> ND_CJPSH],
off & 0177777);
} else if (ins == ND_SHT) {
fprintf(of, "s%c%c ", (op & 0600) == 0600 ? 'a' : 'h',
(op & 0200) ? 'd' : (op & 0400) ? 'a' : 't');
if (op & 03000)
fprintf(of, "%s ", (op & 01000) == 01000 ? "rot " :
(op & 02000) == 02000 ? "zin" : "lin");
fprintf(of, "%d", op & 040 ? 32 - (op & 037) : (op & 037));
} else if (ins == ND_BOP) {
fprintf(of, "%s ", boptab[(op & ND_BOPMSK) >> ND_BOPSH]);
fprintf(of, "%d d%s", (op & 0170) >> 3, dactab[op & 7]);
} else if (ins == ND_MIS) {
if ((op & 0177400) == 0151000)
fprintf(of, "wait 0%o", op & 0377);
else if (op == ND_MIS_SEX)
fprintf(of, "sex");
else if (op == ND_MIS_REX)
fprintf(of, "rex");
else if (op == ND_MIS_IOF)
fprintf(of, "iof");
else if (op == ND_MIS_ION)
fprintf(of, "ion");
else if (op == ND_MIS_POF)
fprintf(of, "pof");
else if (op == ND_MIS_PON)
fprintf(of, "pon");
else if (op == ND_MIS_PIOF)
fprintf(of, "piof");
else if (op == ND_MIS_PION)
fprintf(of, "pion");
else if (op == ND_MIS_IOXT)
fprintf(of, "ioxt");
else if ((op & ND_MIS_TRMSK) == ND_MIS_TRA)
fprintf(of, "tra %s", tratab[op & 017]);
else if ((op & ND_MIS_TRMSK) == ND_MIS_TRR)
fprintf(of, "trr %s", trrtab[op & 017]);
else if ((op & ND_MIS_TRMSK) == ND_MIS_MCL)
fprintf(of, "mcl 0%o", op & 077);
else if ((op & ND_MIS_TRMSK) == ND_MIS_MST)
fprintf(of, "mst 0%o", op & 077);
else if ((op & 0177600) == 0153600)
fprintf(of, "irr 0%02o d%s",
(op >> 3) & 017, dactab[op & 07]);
else if ((op & 0177600) == 0153400)
fprintf(of, "irw 0%02o d%s",
(op >> 3) & 017, dactab[op & 07]);
else if ((op & ND_MONMSK) == ND_MON)
fprintf(of, "mon 0%o", op & 0377);
else if ((op & ND_MONMSK) == ND_MIS_NLZ)
fprintf(of, "nlz 0%o", op & 0377);
else if ((op & ND_MIS_RBMSK) == ND_MIS_LRB)
fprintf(of, "lrb");
else if ((op & ND_MIS_RBMSK) == ND_MIS_SRB)
fprintf(of, "srb");
else
fprintf(of, "MISSING2: 0%06o", op);
} else if (ins == ND_ROP) {
switch (op & ND_ROPMSK) {
case 0146000: fprintf(of, "radd"); break;
case 0146600: fprintf(of, "rsub"); break;
case 0144400: fprintf(of, "rand"); break;
case 0145400: fprintf(of, "rora"); break;
case 0145000: fprintf(of, "rexo"); break;
case 0144000: fprintf(of, "swap"); break;
case 0146100: fprintf(of, "copy"); break;
case 0146500: fprintf(of, "rinc"); break;
default:
if ((op & 0177770) == 0146400) {
fprintf(of, "rinc %s", dactab[op & 07]);
op = 0;
} else
fprintf(of, "%07o", op & ND_ROPMSK);
break;
}
if (op)
fprintf(of, " s%s to d%s",
dactab[(op & 070) >> 3], dactab[op & 07]);
} else if (ins == ND_SKP) {
if (op & 0300) {
if (op == ND_SKP_BFILL)
fprintf(of, "bfill");
else if (op == ND_SKP_MOVB)
fprintf(of, "movb");
else if (op == ND_SKP_MOVBF)
fprintf(of, "movbf");
else if (op == ND_SKP_IDENT10)
fprintf(of, "ident 10");
else if (op == ND_SKP_IDENT11)
fprintf(of, "ident 11");
else if (op == ND_SKP_IDENT12)
fprintf(of, "ident 12");
else if (op == ND_SKP_IDENT13)
fprintf(of, "ident 13");
else if (op == ND_SKP_LBYT)
fprintf(of, "lbyt");
else if (op == ND_SKP_SBYT)
fprintf(of, "sbyt");
else if ((op & 0177707) == ND_SKP_EXR)
fprintf(of, "exr %s", dactab[(op & 070) >> 3]);
else if ((op & 0177700) == ND_SKP_LDATX)
fprintf(of, "%s", mitab[op & 07]);
else if ((op & 0177700) == ND_SKP_RMPY)
fprintf(of, "rmpy %s %s",
dactab[(op & 070) >> 3], dactab[op & 07]);
else
fprintf(of, "MISSING4: 0%06o", op);
} else
fprintf(of, "skp d%s %s s%s", dactab[op & 07],
skptab[(op >> 8) & 07], dactab[(op & 070) >> 3]);
} else
fprintf(of, "MISSING: 0%06o", op);
return SCPE_OK;
}
t_stat
parse_sym(CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
{
return SCPE_ARG;
}