/* * 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; }